i40evf_client.c 15 KB

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