i40evf_client.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579
  1. // SPDX-License-Identifier: GPL-2.0
  2. #include <linux/list.h>
  3. #include <linux/errno.h>
  4. #include "i40evf.h"
  5. #include "i40e_prototype.h"
  6. #include "i40evf_client.h"
  7. static
  8. const char i40evf_client_interface_version_str[] = I40EVF_CLIENT_VERSION_STR;
  9. static struct i40e_client *vf_registered_client;
  10. static LIST_HEAD(i40evf_devices);
  11. static DEFINE_MUTEX(i40evf_device_mutex);
  12. static u32 i40evf_client_virtchnl_send(struct i40e_info *ldev,
  13. struct i40e_client *client,
  14. u8 *msg, u16 len);
  15. static int i40evf_client_setup_qvlist(struct i40e_info *ldev,
  16. struct i40e_client *client,
  17. struct i40e_qvlist_info *qvlist_info);
  18. static struct i40e_ops i40evf_lan_ops = {
  19. .virtchnl_send = i40evf_client_virtchnl_send,
  20. .setup_qvlist = i40evf_client_setup_qvlist,
  21. };
  22. /**
  23. * i40evf_client_get_params - retrieve relevant client parameters
  24. * @vsi: VSI with parameters
  25. * @params: client param struct
  26. **/
  27. static
  28. void i40evf_client_get_params(struct i40e_vsi *vsi, struct i40e_params *params)
  29. {
  30. int i;
  31. memset(params, 0, sizeof(struct i40e_params));
  32. params->mtu = vsi->netdev->mtu;
  33. params->link_up = vsi->back->link_up;
  34. for (i = 0; i < I40E_MAX_USER_PRIORITY; i++) {
  35. params->qos.prio_qos[i].tc = 0;
  36. params->qos.prio_qos[i].qs_handle = vsi->qs_handle;
  37. }
  38. }
  39. /**
  40. * i40evf_notify_client_message - call the client message receive callback
  41. * @vsi: the VSI associated with this client
  42. * @msg: message buffer
  43. * @len: length of message
  44. *
  45. * If there is a client to this VSI, call the client
  46. **/
  47. void i40evf_notify_client_message(struct i40e_vsi *vsi, u8 *msg, u16 len)
  48. {
  49. struct i40e_client_instance *cinst;
  50. if (!vsi)
  51. return;
  52. cinst = vsi->back->cinst;
  53. if (!cinst || !cinst->client || !cinst->client->ops ||
  54. !cinst->client->ops->virtchnl_receive) {
  55. dev_dbg(&vsi->back->pdev->dev,
  56. "Cannot locate client instance virtchnl_receive function\n");
  57. return;
  58. }
  59. cinst->client->ops->virtchnl_receive(&cinst->lan_info, cinst->client,
  60. msg, len);
  61. }
  62. /**
  63. * i40evf_notify_client_l2_params - call the client notify callback
  64. * @vsi: the VSI with l2 param changes
  65. *
  66. * If there is a client to this VSI, call the client
  67. **/
  68. void i40evf_notify_client_l2_params(struct i40e_vsi *vsi)
  69. {
  70. struct i40e_client_instance *cinst;
  71. struct i40e_params params;
  72. if (!vsi)
  73. return;
  74. cinst = vsi->back->cinst;
  75. if (!cinst || !cinst->client || !cinst->client->ops ||
  76. !cinst->client->ops->l2_param_change) {
  77. dev_dbg(&vsi->back->pdev->dev,
  78. "Cannot locate client instance l2_param_change function\n");
  79. return;
  80. }
  81. i40evf_client_get_params(vsi, &params);
  82. cinst->lan_info.params = params;
  83. cinst->client->ops->l2_param_change(&cinst->lan_info, cinst->client,
  84. &params);
  85. }
  86. /**
  87. * i40evf_notify_client_open - call the client open callback
  88. * @vsi: the VSI with netdev opened
  89. *
  90. * If there is a client to this netdev, call the client with open
  91. **/
  92. void i40evf_notify_client_open(struct i40e_vsi *vsi)
  93. {
  94. struct i40evf_adapter *adapter = vsi->back;
  95. struct i40e_client_instance *cinst = adapter->cinst;
  96. int ret;
  97. if (!cinst || !cinst->client || !cinst->client->ops ||
  98. !cinst->client->ops->open) {
  99. dev_dbg(&vsi->back->pdev->dev,
  100. "Cannot locate client instance open function\n");
  101. return;
  102. }
  103. if (!(test_bit(__I40E_CLIENT_INSTANCE_OPENED, &cinst->state))) {
  104. ret = cinst->client->ops->open(&cinst->lan_info, cinst->client);
  105. if (!ret)
  106. set_bit(__I40E_CLIENT_INSTANCE_OPENED, &cinst->state);
  107. }
  108. }
  109. /**
  110. * i40evf_client_release_qvlist - send a message to the PF to release iwarp qv map
  111. * @ldev: pointer to L2 context.
  112. *
  113. * Return 0 on success or < 0 on error
  114. **/
  115. static int i40evf_client_release_qvlist(struct i40e_info *ldev)
  116. {
  117. struct i40evf_adapter *adapter = ldev->vf;
  118. i40e_status err;
  119. if (adapter->aq_required)
  120. return -EAGAIN;
  121. err = i40e_aq_send_msg_to_pf(&adapter->hw,
  122. VIRTCHNL_OP_RELEASE_IWARP_IRQ_MAP,
  123. I40E_SUCCESS, NULL, 0, NULL);
  124. if (err)
  125. dev_err(&adapter->pdev->dev,
  126. "Unable to send iWarp vector release message to PF, error %d, aq status %d\n",
  127. err, adapter->hw.aq.asq_last_status);
  128. return err;
  129. }
  130. /**
  131. * i40evf_notify_client_close - call the client close callback
  132. * @vsi: the VSI with netdev closed
  133. * @reset: true when close called due to reset pending
  134. *
  135. * If there is a client to this netdev, call the client with close
  136. **/
  137. void i40evf_notify_client_close(struct i40e_vsi *vsi, bool reset)
  138. {
  139. struct i40evf_adapter *adapter = vsi->back;
  140. struct i40e_client_instance *cinst = adapter->cinst;
  141. if (!cinst || !cinst->client || !cinst->client->ops ||
  142. !cinst->client->ops->close) {
  143. dev_dbg(&vsi->back->pdev->dev,
  144. "Cannot locate client instance close function\n");
  145. return;
  146. }
  147. cinst->client->ops->close(&cinst->lan_info, cinst->client, reset);
  148. i40evf_client_release_qvlist(&cinst->lan_info);
  149. clear_bit(__I40E_CLIENT_INSTANCE_OPENED, &cinst->state);
  150. }
  151. /**
  152. * i40evf_client_add_instance - add a client instance to the instance list
  153. * @adapter: pointer to the board struct
  154. * @client: pointer to a client struct in the client list.
  155. *
  156. * Returns cinst ptr on success, NULL on failure
  157. **/
  158. static struct i40e_client_instance *
  159. i40evf_client_add_instance(struct i40evf_adapter *adapter)
  160. {
  161. struct i40e_client_instance *cinst = NULL;
  162. struct i40e_vsi *vsi = &adapter->vsi;
  163. struct netdev_hw_addr *mac = NULL;
  164. struct i40e_params params;
  165. if (!vf_registered_client)
  166. goto out;
  167. if (adapter->cinst) {
  168. cinst = adapter->cinst;
  169. goto out;
  170. }
  171. cinst = kzalloc(sizeof(*cinst), GFP_KERNEL);
  172. if (!cinst)
  173. goto out;
  174. cinst->lan_info.vf = (void *)adapter;
  175. cinst->lan_info.netdev = vsi->netdev;
  176. cinst->lan_info.pcidev = adapter->pdev;
  177. cinst->lan_info.fid = 0;
  178. cinst->lan_info.ftype = I40E_CLIENT_FTYPE_VF;
  179. cinst->lan_info.hw_addr = adapter->hw.hw_addr;
  180. cinst->lan_info.ops = &i40evf_lan_ops;
  181. cinst->lan_info.version.major = I40EVF_CLIENT_VERSION_MAJOR;
  182. cinst->lan_info.version.minor = I40EVF_CLIENT_VERSION_MINOR;
  183. cinst->lan_info.version.build = I40EVF_CLIENT_VERSION_BUILD;
  184. i40evf_client_get_params(vsi, &params);
  185. cinst->lan_info.params = params;
  186. set_bit(__I40E_CLIENT_INSTANCE_NONE, &cinst->state);
  187. cinst->lan_info.msix_count = adapter->num_iwarp_msix;
  188. cinst->lan_info.msix_entries =
  189. &adapter->msix_entries[adapter->iwarp_base_vector];
  190. mac = list_first_entry(&cinst->lan_info.netdev->dev_addrs.list,
  191. struct netdev_hw_addr, list);
  192. if (mac)
  193. ether_addr_copy(cinst->lan_info.lanmac, mac->addr);
  194. else
  195. dev_err(&adapter->pdev->dev, "MAC address list is empty!\n");
  196. cinst->client = vf_registered_client;
  197. adapter->cinst = cinst;
  198. out:
  199. return cinst;
  200. }
  201. /**
  202. * i40evf_client_del_instance - removes a client instance from the list
  203. * @adapter: pointer to the board struct
  204. * @client: pointer to the client struct
  205. *
  206. **/
  207. static
  208. void i40evf_client_del_instance(struct i40evf_adapter *adapter)
  209. {
  210. kfree(adapter->cinst);
  211. adapter->cinst = NULL;
  212. }
  213. /**
  214. * i40evf_client_subtask - client maintenance work
  215. * @adapter: board private structure
  216. **/
  217. void i40evf_client_subtask(struct i40evf_adapter *adapter)
  218. {
  219. struct i40e_client *client = vf_registered_client;
  220. struct i40e_client_instance *cinst;
  221. int ret = 0;
  222. if (adapter->state < __I40EVF_DOWN)
  223. return;
  224. /* first check client is registered */
  225. if (!client)
  226. return;
  227. /* Add the client instance to the instance list */
  228. cinst = i40evf_client_add_instance(adapter);
  229. if (!cinst)
  230. return;
  231. dev_info(&adapter->pdev->dev, "Added instance of Client %s\n",
  232. client->name);
  233. if (!test_bit(__I40E_CLIENT_INSTANCE_OPENED, &cinst->state)) {
  234. /* Send an Open request to the client */
  235. if (client->ops && client->ops->open)
  236. ret = client->ops->open(&cinst->lan_info, client);
  237. if (!ret)
  238. set_bit(__I40E_CLIENT_INSTANCE_OPENED,
  239. &cinst->state);
  240. else
  241. /* remove client instance */
  242. i40evf_client_del_instance(adapter);
  243. }
  244. }
  245. /**
  246. * i40evf_lan_add_device - add a lan device struct to the list of lan devices
  247. * @adapter: pointer to the board struct
  248. *
  249. * Returns 0 on success or none 0 on error
  250. **/
  251. int i40evf_lan_add_device(struct i40evf_adapter *adapter)
  252. {
  253. struct i40e_device *ldev;
  254. int ret = 0;
  255. mutex_lock(&i40evf_device_mutex);
  256. list_for_each_entry(ldev, &i40evf_devices, list) {
  257. if (ldev->vf == adapter) {
  258. ret = -EEXIST;
  259. goto out;
  260. }
  261. }
  262. ldev = kzalloc(sizeof(*ldev), GFP_KERNEL);
  263. if (!ldev) {
  264. ret = -ENOMEM;
  265. goto out;
  266. }
  267. ldev->vf = adapter;
  268. INIT_LIST_HEAD(&ldev->list);
  269. list_add(&ldev->list, &i40evf_devices);
  270. dev_info(&adapter->pdev->dev, "Added LAN device bus=0x%02x dev=0x%02x func=0x%02x\n",
  271. adapter->hw.bus.bus_id, adapter->hw.bus.device,
  272. adapter->hw.bus.func);
  273. /* Since in some cases register may have happened before a device gets
  274. * added, we can schedule a subtask to go initiate the clients.
  275. */
  276. adapter->flags |= I40EVF_FLAG_SERVICE_CLIENT_REQUESTED;
  277. out:
  278. mutex_unlock(&i40evf_device_mutex);
  279. return ret;
  280. }
  281. /**
  282. * i40evf_lan_del_device - removes a lan device from the device list
  283. * @adapter: pointer to the board struct
  284. *
  285. * Returns 0 on success or non-0 on error
  286. **/
  287. int i40evf_lan_del_device(struct i40evf_adapter *adapter)
  288. {
  289. struct i40e_device *ldev, *tmp;
  290. int ret = -ENODEV;
  291. mutex_lock(&i40evf_device_mutex);
  292. list_for_each_entry_safe(ldev, tmp, &i40evf_devices, list) {
  293. if (ldev->vf == adapter) {
  294. dev_info(&adapter->pdev->dev,
  295. "Deleted LAN device bus=0x%02x dev=0x%02x func=0x%02x\n",
  296. adapter->hw.bus.bus_id, adapter->hw.bus.device,
  297. adapter->hw.bus.func);
  298. list_del(&ldev->list);
  299. kfree(ldev);
  300. ret = 0;
  301. break;
  302. }
  303. }
  304. mutex_unlock(&i40evf_device_mutex);
  305. return ret;
  306. }
  307. /**
  308. * i40evf_client_release - release client specific resources
  309. * @client: pointer to the registered client
  310. *
  311. **/
  312. static void i40evf_client_release(struct i40e_client *client)
  313. {
  314. struct i40e_client_instance *cinst;
  315. struct i40e_device *ldev;
  316. struct i40evf_adapter *adapter;
  317. mutex_lock(&i40evf_device_mutex);
  318. list_for_each_entry(ldev, &i40evf_devices, list) {
  319. adapter = ldev->vf;
  320. cinst = adapter->cinst;
  321. if (!cinst)
  322. continue;
  323. if (test_bit(__I40E_CLIENT_INSTANCE_OPENED, &cinst->state)) {
  324. if (client->ops && client->ops->close)
  325. client->ops->close(&cinst->lan_info, client,
  326. false);
  327. i40evf_client_release_qvlist(&cinst->lan_info);
  328. clear_bit(__I40E_CLIENT_INSTANCE_OPENED, &cinst->state);
  329. dev_warn(&adapter->pdev->dev,
  330. "Client %s instance closed\n", client->name);
  331. }
  332. /* delete the client instance */
  333. i40evf_client_del_instance(adapter);
  334. dev_info(&adapter->pdev->dev, "Deleted client instance of Client %s\n",
  335. client->name);
  336. }
  337. mutex_unlock(&i40evf_device_mutex);
  338. }
  339. /**
  340. * i40evf_client_prepare - prepare client specific resources
  341. * @client: pointer to the registered client
  342. *
  343. **/
  344. static void i40evf_client_prepare(struct i40e_client *client)
  345. {
  346. struct i40e_device *ldev;
  347. struct i40evf_adapter *adapter;
  348. mutex_lock(&i40evf_device_mutex);
  349. list_for_each_entry(ldev, &i40evf_devices, list) {
  350. adapter = ldev->vf;
  351. /* Signal the watchdog to service the client */
  352. adapter->flags |= I40EVF_FLAG_SERVICE_CLIENT_REQUESTED;
  353. }
  354. mutex_unlock(&i40evf_device_mutex);
  355. }
  356. /**
  357. * i40evf_client_virtchnl_send - send a message to the PF instance
  358. * @ldev: pointer to L2 context.
  359. * @client: Client pointer.
  360. * @msg: pointer to message buffer
  361. * @len: message length
  362. *
  363. * Return 0 on success or < 0 on error
  364. **/
  365. static u32 i40evf_client_virtchnl_send(struct i40e_info *ldev,
  366. struct i40e_client *client,
  367. u8 *msg, u16 len)
  368. {
  369. struct i40evf_adapter *adapter = ldev->vf;
  370. i40e_status err;
  371. if (adapter->aq_required)
  372. return -EAGAIN;
  373. err = i40e_aq_send_msg_to_pf(&adapter->hw, VIRTCHNL_OP_IWARP,
  374. I40E_SUCCESS, msg, len, NULL);
  375. if (err)
  376. dev_err(&adapter->pdev->dev, "Unable to send iWarp message to PF, error %d, aq status %d\n",
  377. err, adapter->hw.aq.asq_last_status);
  378. return err;
  379. }
  380. /**
  381. * i40evf_client_setup_qvlist - send a message to the PF to setup iwarp qv map
  382. * @ldev: pointer to L2 context.
  383. * @client: Client pointer.
  384. * @qv_info: queue and vector list
  385. *
  386. * Return 0 on success or < 0 on error
  387. **/
  388. static int i40evf_client_setup_qvlist(struct i40e_info *ldev,
  389. struct i40e_client *client,
  390. struct i40e_qvlist_info *qvlist_info)
  391. {
  392. struct virtchnl_iwarp_qvlist_info *v_qvlist_info;
  393. struct i40evf_adapter *adapter = ldev->vf;
  394. struct i40e_qv_info *qv_info;
  395. i40e_status err;
  396. u32 v_idx, i;
  397. u32 msg_size;
  398. if (adapter->aq_required)
  399. return -EAGAIN;
  400. /* A quick check on whether the vectors belong to the client */
  401. for (i = 0; i < qvlist_info->num_vectors; i++) {
  402. qv_info = &qvlist_info->qv_info[i];
  403. if (!qv_info)
  404. continue;
  405. v_idx = qv_info->v_idx;
  406. if ((v_idx >=
  407. (adapter->iwarp_base_vector + adapter->num_iwarp_msix)) ||
  408. (v_idx < adapter->iwarp_base_vector))
  409. return -EINVAL;
  410. }
  411. v_qvlist_info = (struct virtchnl_iwarp_qvlist_info *)qvlist_info;
  412. msg_size = sizeof(struct virtchnl_iwarp_qvlist_info) +
  413. (sizeof(struct virtchnl_iwarp_qv_info) *
  414. (v_qvlist_info->num_vectors - 1));
  415. adapter->client_pending |= BIT(VIRTCHNL_OP_CONFIG_IWARP_IRQ_MAP);
  416. err = i40e_aq_send_msg_to_pf(&adapter->hw,
  417. VIRTCHNL_OP_CONFIG_IWARP_IRQ_MAP,
  418. I40E_SUCCESS, (u8 *)v_qvlist_info, msg_size, NULL);
  419. if (err) {
  420. dev_err(&adapter->pdev->dev,
  421. "Unable to send iWarp vector config message to PF, error %d, aq status %d\n",
  422. err, adapter->hw.aq.asq_last_status);
  423. goto out;
  424. }
  425. err = -EBUSY;
  426. for (i = 0; i < 5; i++) {
  427. msleep(100);
  428. if (!(adapter->client_pending &
  429. BIT(VIRTCHNL_OP_CONFIG_IWARP_IRQ_MAP))) {
  430. err = 0;
  431. break;
  432. }
  433. }
  434. out:
  435. return err;
  436. }
  437. /**
  438. * i40evf_register_client - Register a i40e client driver with the L2 driver
  439. * @client: pointer to the i40e_client struct
  440. *
  441. * Returns 0 on success or non-0 on error
  442. **/
  443. int i40evf_register_client(struct i40e_client *client)
  444. {
  445. int ret = 0;
  446. if (!client) {
  447. ret = -EIO;
  448. goto out;
  449. }
  450. if (strlen(client->name) == 0) {
  451. pr_info("i40evf: Failed to register client with no name\n");
  452. ret = -EIO;
  453. goto out;
  454. }
  455. if (vf_registered_client) {
  456. pr_info("i40evf: Client %s has already been registered!\n",
  457. client->name);
  458. ret = -EEXIST;
  459. goto out;
  460. }
  461. if ((client->version.major != I40EVF_CLIENT_VERSION_MAJOR) ||
  462. (client->version.minor != I40EVF_CLIENT_VERSION_MINOR)) {
  463. pr_info("i40evf: Failed to register client %s due to mismatched client interface version\n",
  464. client->name);
  465. pr_info("Client is using version: %02d.%02d.%02d while LAN driver supports %s\n",
  466. client->version.major, client->version.minor,
  467. client->version.build,
  468. i40evf_client_interface_version_str);
  469. ret = -EIO;
  470. goto out;
  471. }
  472. vf_registered_client = client;
  473. i40evf_client_prepare(client);
  474. pr_info("i40evf: Registered client %s with return code %d\n",
  475. client->name, ret);
  476. out:
  477. return ret;
  478. }
  479. EXPORT_SYMBOL(i40evf_register_client);
  480. /**
  481. * i40evf_unregister_client - Unregister a i40e client driver with the L2 driver
  482. * @client: pointer to the i40e_client struct
  483. *
  484. * Returns 0 on success or non-0 on error
  485. **/
  486. int i40evf_unregister_client(struct i40e_client *client)
  487. {
  488. int ret = 0;
  489. /* When a unregister request comes through we would have to send
  490. * a close for each of the client instances that were opened.
  491. * client_release function is called to handle this.
  492. */
  493. i40evf_client_release(client);
  494. if (vf_registered_client != client) {
  495. pr_info("i40evf: Client %s has not been registered\n",
  496. client->name);
  497. ret = -ENODEV;
  498. goto out;
  499. }
  500. vf_registered_client = NULL;
  501. pr_info("i40evf: Unregistered client %s\n", client->name);
  502. out:
  503. return ret;
  504. }
  505. EXPORT_SYMBOL(i40evf_unregister_client);