qlcnic_sriov_pf.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455
  1. /*
  2. * QLogic qlcnic NIC Driver
  3. * Copyright (c) 2009-2013 QLogic Corporation
  4. *
  5. * See LICENSE.qlcnic for copyright and licensing details.
  6. */
  7. #include "qlcnic_sriov.h"
  8. #include "qlcnic.h"
  9. #include <linux/types.h>
  10. #define QLCNIC_SRIOV_VF_MAX_MAC 1
  11. static int qlcnic_sriov_pf_get_vport_handle(struct qlcnic_adapter *, u8);
  12. static int qlcnic_sriov_pf_set_vport_info(struct qlcnic_adapter *adapter,
  13. struct qlcnic_info *npar_info,
  14. u16 vport_id)
  15. {
  16. struct qlcnic_cmd_args cmd;
  17. int err;
  18. if (qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_SET_NIC_INFO))
  19. return -ENOMEM;
  20. cmd.req.arg[1] = (vport_id << 16) | 0x1;
  21. cmd.req.arg[2] = npar_info->bit_offsets;
  22. cmd.req.arg[2] |= npar_info->min_tx_bw << 16;
  23. cmd.req.arg[3] = npar_info->max_tx_bw | (npar_info->max_tx_ques << 16);
  24. cmd.req.arg[4] = npar_info->max_tx_mac_filters;
  25. cmd.req.arg[4] |= npar_info->max_rx_mcast_mac_filters << 16;
  26. cmd.req.arg[5] = npar_info->max_rx_ucast_mac_filters |
  27. (npar_info->max_rx_ip_addr << 16);
  28. cmd.req.arg[6] = npar_info->max_rx_lro_flow |
  29. (npar_info->max_rx_status_rings << 16);
  30. cmd.req.arg[7] = npar_info->max_rx_buf_rings |
  31. (npar_info->max_rx_ques << 16);
  32. cmd.req.arg[8] = npar_info->max_tx_vlan_keys;
  33. cmd.req.arg[8] |= npar_info->max_local_ipv6_addrs << 16;
  34. cmd.req.arg[9] = npar_info->max_remote_ipv6_addrs;
  35. err = qlcnic_issue_cmd(adapter, &cmd);
  36. if (err)
  37. dev_err(&adapter->pdev->dev,
  38. "Failed to set vport info, err=%d\n", err);
  39. qlcnic_free_mbx_args(&cmd);
  40. return err;
  41. }
  42. static int qlcnic_sriov_pf_cal_res_limit(struct qlcnic_adapter *adapter,
  43. struct qlcnic_info *info, u16 func)
  44. {
  45. struct qlcnic_sriov *sriov = adapter->ahw->sriov;
  46. struct qlcnic_resources *res = &sriov->ff_max;
  47. int ret = -EIO, vpid;
  48. u32 temp, num_vf_macs, num_vfs, max;
  49. vpid = qlcnic_sriov_pf_get_vport_handle(adapter, func);
  50. if (vpid < 0)
  51. return -EINVAL;
  52. num_vfs = sriov->num_vfs;
  53. max = num_vfs + 1;
  54. info->bit_offsets = 0xffff;
  55. info->min_tx_bw = 0;
  56. info->max_tx_bw = MAX_BW;
  57. info->max_tx_ques = res->num_tx_queues / max;
  58. info->max_rx_mcast_mac_filters = res->num_rx_mcast_mac_filters;
  59. num_vf_macs = QLCNIC_SRIOV_VF_MAX_MAC;
  60. if (adapter->ahw->pci_func == func) {
  61. temp = res->num_rx_mcast_mac_filters - (num_vfs * num_vf_macs);
  62. info->max_rx_ucast_mac_filters = temp;
  63. temp = res->num_tx_mac_filters - (num_vfs * num_vf_macs);
  64. info->max_tx_mac_filters = temp;
  65. } else {
  66. info->max_rx_ucast_mac_filters = num_vf_macs;
  67. info->max_tx_mac_filters = num_vf_macs;
  68. }
  69. info->max_rx_ip_addr = res->num_destip / max;
  70. info->max_rx_status_rings = res->num_rx_status_rings / max;
  71. info->max_rx_buf_rings = res->num_rx_buf_rings / max;
  72. info->max_rx_ques = res->num_rx_queues / max;
  73. info->max_rx_lro_flow = res->num_lro_flows_supported / max;
  74. info->max_tx_vlan_keys = res->num_txvlan_keys;
  75. info->max_local_ipv6_addrs = res->max_local_ipv6_addrs;
  76. info->max_remote_ipv6_addrs = res->max_remote_ipv6_addrs;
  77. ret = qlcnic_sriov_pf_set_vport_info(adapter, info, vpid);
  78. if (ret)
  79. return ret;
  80. return 0;
  81. }
  82. static void qlcnic_sriov_pf_set_ff_max_res(struct qlcnic_adapter *adapter,
  83. struct qlcnic_info *info)
  84. {
  85. struct qlcnic_resources *ff_max = &adapter->ahw->sriov->ff_max;
  86. ff_max->num_tx_mac_filters = info->max_tx_mac_filters;
  87. ff_max->num_rx_ucast_mac_filters = info->max_rx_ucast_mac_filters;
  88. ff_max->num_rx_mcast_mac_filters = info->max_rx_mcast_mac_filters;
  89. ff_max->num_txvlan_keys = info->max_tx_vlan_keys;
  90. ff_max->num_rx_queues = info->max_rx_ques;
  91. ff_max->num_tx_queues = info->max_tx_ques;
  92. ff_max->num_lro_flows_supported = info->max_rx_lro_flow;
  93. ff_max->num_destip = info->max_rx_ip_addr;
  94. ff_max->num_rx_buf_rings = info->max_rx_buf_rings;
  95. ff_max->num_rx_status_rings = info->max_rx_status_rings;
  96. ff_max->max_remote_ipv6_addrs = info->max_remote_ipv6_addrs;
  97. ff_max->max_local_ipv6_addrs = info->max_local_ipv6_addrs;
  98. }
  99. static int qlcnic_sriov_get_pf_info(struct qlcnic_adapter *adapter,
  100. struct qlcnic_info *npar_info)
  101. {
  102. int err;
  103. struct qlcnic_cmd_args cmd;
  104. if (qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_GET_NIC_INFO))
  105. return -ENOMEM;
  106. cmd.req.arg[1] = 0x2;
  107. err = qlcnic_issue_cmd(adapter, &cmd);
  108. if (err) {
  109. dev_err(&adapter->pdev->dev,
  110. "Failed to get PF info, err=%d\n", err);
  111. goto out;
  112. }
  113. npar_info->total_pf = cmd.rsp.arg[2] & 0xff;
  114. npar_info->total_rss_engines = (cmd.rsp.arg[2] >> 8) & 0xff;
  115. npar_info->max_vports = MSW(cmd.rsp.arg[2]);
  116. npar_info->max_tx_ques = LSW(cmd.rsp.arg[3]);
  117. npar_info->max_tx_mac_filters = MSW(cmd.rsp.arg[3]);
  118. npar_info->max_rx_mcast_mac_filters = LSW(cmd.rsp.arg[4]);
  119. npar_info->max_rx_ucast_mac_filters = MSW(cmd.rsp.arg[4]);
  120. npar_info->max_rx_ip_addr = LSW(cmd.rsp.arg[5]);
  121. npar_info->max_rx_lro_flow = MSW(cmd.rsp.arg[5]);
  122. npar_info->max_rx_status_rings = LSW(cmd.rsp.arg[6]);
  123. npar_info->max_rx_buf_rings = MSW(cmd.rsp.arg[6]);
  124. npar_info->max_rx_ques = LSW(cmd.rsp.arg[7]);
  125. npar_info->max_tx_vlan_keys = MSW(cmd.rsp.arg[7]);
  126. npar_info->max_local_ipv6_addrs = LSW(cmd.rsp.arg[8]);
  127. npar_info->max_remote_ipv6_addrs = MSW(cmd.rsp.arg[8]);
  128. dev_info(&adapter->pdev->dev,
  129. "\n\ttotal_pf: %d,\n"
  130. "\n\ttotal_rss_engines: %d max_vports: %d max_tx_ques %d,\n"
  131. "\tmax_tx_mac_filters: %d max_rx_mcast_mac_filters: %d,\n"
  132. "\tmax_rx_ucast_mac_filters: 0x%x, max_rx_ip_addr: %d,\n"
  133. "\tmax_rx_lro_flow: %d max_rx_status_rings: %d,\n"
  134. "\tmax_rx_buf_rings: %d, max_rx_ques: %d, max_tx_vlan_keys %d\n"
  135. "\tmax_local_ipv6_addrs: %d, max_remote_ipv6_addrs: %d\n",
  136. npar_info->total_pf, npar_info->total_rss_engines,
  137. npar_info->max_vports, npar_info->max_tx_ques,
  138. npar_info->max_tx_mac_filters,
  139. npar_info->max_rx_mcast_mac_filters,
  140. npar_info->max_rx_ucast_mac_filters, npar_info->max_rx_ip_addr,
  141. npar_info->max_rx_lro_flow, npar_info->max_rx_status_rings,
  142. npar_info->max_rx_buf_rings, npar_info->max_rx_ques,
  143. npar_info->max_tx_vlan_keys, npar_info->max_local_ipv6_addrs,
  144. npar_info->max_remote_ipv6_addrs);
  145. out:
  146. qlcnic_free_mbx_args(&cmd);
  147. return err;
  148. }
  149. static void qlcnic_sriov_pf_reset_vport_handle(struct qlcnic_adapter *adapter,
  150. u8 func)
  151. {
  152. struct qlcnic_sriov *sriov = adapter->ahw->sriov;
  153. if (adapter->ahw->pci_func == func)
  154. sriov->vp_handle = 0;
  155. }
  156. static void qlcnic_sriov_pf_set_vport_handle(struct qlcnic_adapter *adapter,
  157. u16 vport_handle, u8 func)
  158. {
  159. struct qlcnic_sriov *sriov = adapter->ahw->sriov;
  160. if (adapter->ahw->pci_func == func)
  161. sriov->vp_handle = vport_handle;
  162. }
  163. static int qlcnic_sriov_pf_get_vport_handle(struct qlcnic_adapter *adapter,
  164. u8 func)
  165. {
  166. struct qlcnic_sriov *sriov = adapter->ahw->sriov;
  167. if (adapter->ahw->pci_func == func)
  168. return sriov->vp_handle;
  169. return -EINVAL;
  170. }
  171. static int qlcnic_sriov_pf_config_vport(struct qlcnic_adapter *adapter,
  172. u8 flag, u16 func)
  173. {
  174. struct qlcnic_cmd_args cmd;
  175. int ret;
  176. int vpid;
  177. if (qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_CONFIG_VPORT))
  178. return -ENOMEM;
  179. if (flag) {
  180. cmd.req.arg[3] = func << 8;
  181. } else {
  182. vpid = qlcnic_sriov_pf_get_vport_handle(adapter, func);
  183. if (vpid < 0) {
  184. ret = -EINVAL;
  185. goto out;
  186. }
  187. cmd.req.arg[3] = ((vpid & 0xffff) << 8) | 1;
  188. }
  189. ret = qlcnic_issue_cmd(adapter, &cmd);
  190. if (ret) {
  191. dev_err(&adapter->pdev->dev,
  192. "Failed %s vport, err %d for func 0x%x\n",
  193. (flag ? "enable" : "disable"), ret, func);
  194. goto out;
  195. }
  196. if (flag) {
  197. vpid = cmd.rsp.arg[2] & 0xffff;
  198. qlcnic_sriov_pf_set_vport_handle(adapter, vpid, func);
  199. } else {
  200. qlcnic_sriov_pf_reset_vport_handle(adapter, func);
  201. }
  202. out:
  203. qlcnic_free_mbx_args(&cmd);
  204. return ret;
  205. }
  206. static int qlcnic_sriov_pf_cfg_eswitch(struct qlcnic_adapter *adapter,
  207. u8 func, u8 enable)
  208. {
  209. struct qlcnic_cmd_args cmd;
  210. int err = -EIO;
  211. if (qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_TOGGLE_ESWITCH))
  212. return -ENOMEM;
  213. cmd.req.arg[0] |= (3 << 29);
  214. cmd.req.arg[1] = ((func & 0xf) << 2) | BIT_6 | BIT_1;
  215. if (enable)
  216. cmd.req.arg[1] |= BIT_0;
  217. err = qlcnic_issue_cmd(adapter, &cmd);
  218. if (err != QLCNIC_RCODE_SUCCESS) {
  219. dev_err(&adapter->pdev->dev,
  220. "Failed to enable sriov eswitch%d\n", err);
  221. err = -EIO;
  222. }
  223. qlcnic_free_mbx_args(&cmd);
  224. return err;
  225. }
  226. void qlcnic_sriov_pf_cleanup(struct qlcnic_adapter *adapter)
  227. {
  228. u8 func = adapter->ahw->pci_func;
  229. if (!qlcnic_sriov_enable_check(adapter))
  230. return;
  231. qlcnic_sriov_pf_config_vport(adapter, 0, func);
  232. qlcnic_sriov_pf_cfg_eswitch(adapter, func, 0);
  233. __qlcnic_sriov_cleanup(adapter);
  234. adapter->ahw->op_mode = QLCNIC_MGMT_FUNC;
  235. clear_bit(__QLCNIC_SRIOV_ENABLE, &adapter->state);
  236. }
  237. void qlcnic_sriov_pf_disable(struct qlcnic_adapter *adapter)
  238. {
  239. if (!qlcnic_sriov_pf_check(adapter))
  240. return;
  241. if (!qlcnic_sriov_enable_check(adapter))
  242. return;
  243. pci_disable_sriov(adapter->pdev);
  244. netdev_info(adapter->netdev,
  245. "SR-IOV is disabled successfully on port %d\n",
  246. adapter->portnum);
  247. }
  248. static int qlcnic_pci_sriov_disable(struct qlcnic_adapter *adapter)
  249. {
  250. struct net_device *netdev = adapter->netdev;
  251. if (netif_running(netdev))
  252. __qlcnic_down(adapter, netdev);
  253. qlcnic_sriov_pf_disable(adapter);
  254. qlcnic_sriov_pf_cleanup(adapter);
  255. /* After disabling SRIOV re-init the driver in default mode
  256. configure opmode based on op_mode of function
  257. */
  258. if (qlcnic_83xx_configure_opmode(adapter))
  259. return -EIO;
  260. if (netif_running(netdev))
  261. __qlcnic_up(adapter, netdev);
  262. return 0;
  263. }
  264. static int qlcnic_sriov_pf_init(struct qlcnic_adapter *adapter)
  265. {
  266. struct qlcnic_hardware_context *ahw = adapter->ahw;
  267. struct qlcnic_info nic_info, pf_info, vp_info;
  268. int err;
  269. u8 func = ahw->pci_func;
  270. if (!qlcnic_sriov_enable_check(adapter))
  271. return 0;
  272. err = qlcnic_sriov_pf_cfg_eswitch(adapter, func, 1);
  273. if (err)
  274. goto clear_sriov_enable;
  275. err = qlcnic_sriov_pf_config_vport(adapter, 1, func);
  276. if (err)
  277. goto disable_eswitch;
  278. err = qlcnic_sriov_get_pf_info(adapter, &pf_info);
  279. if (err)
  280. goto delete_vport;
  281. qlcnic_sriov_pf_set_ff_max_res(adapter, &pf_info);
  282. err = qlcnic_get_nic_info(adapter, &nic_info, func);
  283. if (err)
  284. goto delete_vport;
  285. err = qlcnic_sriov_pf_cal_res_limit(adapter, &vp_info, func);
  286. if (err)
  287. goto delete_vport;
  288. ahw->physical_port = (u8) nic_info.phys_port;
  289. ahw->switch_mode = nic_info.switch_mode;
  290. ahw->max_mtu = nic_info.max_mtu;
  291. ahw->capabilities = nic_info.capabilities;
  292. ahw->nic_mode = QLC_83XX_SRIOV_MODE;
  293. return err;
  294. delete_vport:
  295. qlcnic_sriov_pf_config_vport(adapter, 0, func);
  296. disable_eswitch:
  297. qlcnic_sriov_pf_cfg_eswitch(adapter, func, 0);
  298. clear_sriov_enable:
  299. __qlcnic_sriov_cleanup(adapter);
  300. adapter->ahw->op_mode = QLCNIC_MGMT_FUNC;
  301. clear_bit(__QLCNIC_SRIOV_ENABLE, &adapter->state);
  302. return err;
  303. }
  304. static int qlcnic_sriov_pf_enable(struct qlcnic_adapter *adapter, int num_vfs)
  305. {
  306. int err;
  307. if (!qlcnic_sriov_enable_check(adapter))
  308. return 0;
  309. err = pci_enable_sriov(adapter->pdev, num_vfs);
  310. if (err)
  311. qlcnic_sriov_pf_cleanup(adapter);
  312. return err;
  313. }
  314. static int __qlcnic_pci_sriov_enable(struct qlcnic_adapter *adapter,
  315. int num_vfs)
  316. {
  317. int err = 0;
  318. set_bit(__QLCNIC_SRIOV_ENABLE, &adapter->state);
  319. adapter->ahw->op_mode = QLCNIC_SRIOV_PF_FUNC;
  320. if (qlcnic_sriov_init(adapter, num_vfs)) {
  321. clear_bit(__QLCNIC_SRIOV_ENABLE, &adapter->state);
  322. adapter->ahw->op_mode = QLCNIC_MGMT_FUNC;
  323. return -EIO;
  324. }
  325. if (qlcnic_sriov_pf_init(adapter))
  326. return -EIO;
  327. err = qlcnic_sriov_pf_enable(adapter, num_vfs);
  328. return err;
  329. }
  330. static int qlcnic_pci_sriov_enable(struct qlcnic_adapter *adapter, int num_vfs)
  331. {
  332. struct net_device *netdev = adapter->netdev;
  333. int err;
  334. if (!(adapter->flags & QLCNIC_MSIX_ENABLED)) {
  335. netdev_err(netdev,
  336. "SR-IOV cannot be enabled, when legacy interrupts are enabled\n");
  337. return -EIO;
  338. }
  339. if (netif_running(netdev))
  340. __qlcnic_down(adapter, netdev);
  341. err = __qlcnic_pci_sriov_enable(adapter, num_vfs);
  342. if (err) {
  343. netdev_info(netdev, "Failed to enable SR-IOV on port %d\n",
  344. adapter->portnum);
  345. if (qlcnic_83xx_configure_opmode(adapter))
  346. goto error;
  347. } else {
  348. netdev_info(adapter->netdev,
  349. "SR-IOV is enabled successfully on port %d\n",
  350. adapter->portnum);
  351. }
  352. if (netif_running(netdev))
  353. __qlcnic_up(adapter, netdev);
  354. error:
  355. return err;
  356. }
  357. int qlcnic_pci_sriov_configure(struct pci_dev *dev, int num_vfs)
  358. {
  359. struct qlcnic_adapter *adapter = pci_get_drvdata(dev);
  360. int err;
  361. if (test_and_set_bit(__QLCNIC_RESETTING, &adapter->state))
  362. return -EBUSY;
  363. if (num_vfs == 0)
  364. err = qlcnic_pci_sriov_disable(adapter);
  365. else
  366. err = qlcnic_pci_sriov_enable(adapter, num_vfs);
  367. clear_bit(__QLCNIC_RESETTING, &adapter->state);
  368. return err;
  369. }