i40evf_client.c 15 KB

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