hinic_port.c 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380
  1. /*
  2. * Huawei HiNIC PCI Express Linux driver
  3. * Copyright(c) 2017 Huawei Technologies Co., Ltd
  4. *
  5. * This program is free software; you can redistribute it and/or modify it
  6. * under the terms and conditions of the GNU General Public License,
  7. * version 2, as published by the Free Software Foundation.
  8. *
  9. * This program is distributed in the hope it will be useful, but WITHOUT
  10. * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11. * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
  12. * for more details.
  13. *
  14. */
  15. #include <linux/types.h>
  16. #include <linux/netdevice.h>
  17. #include <linux/etherdevice.h>
  18. #include <linux/if_vlan.h>
  19. #include <linux/pci.h>
  20. #include <linux/device.h>
  21. #include <linux/errno.h>
  22. #include "hinic_hw_if.h"
  23. #include "hinic_hw_dev.h"
  24. #include "hinic_port.h"
  25. #include "hinic_dev.h"
  26. #define HINIC_MIN_MTU_SIZE 256
  27. #define HINIC_MAX_JUMBO_FRAME_SIZE 15872
  28. enum mac_op {
  29. MAC_DEL,
  30. MAC_SET,
  31. };
  32. /**
  33. * change_mac - change(add or delete) mac address
  34. * @nic_dev: nic device
  35. * @addr: mac address
  36. * @vlan_id: vlan number to set with the mac
  37. * @op: add or delete the mac
  38. *
  39. * Return 0 - Success, negative - Failure
  40. **/
  41. static int change_mac(struct hinic_dev *nic_dev, const u8 *addr,
  42. u16 vlan_id, enum mac_op op)
  43. {
  44. struct net_device *netdev = nic_dev->netdev;
  45. struct hinic_hwdev *hwdev = nic_dev->hwdev;
  46. struct hinic_port_mac_cmd port_mac_cmd;
  47. struct hinic_hwif *hwif = hwdev->hwif;
  48. struct pci_dev *pdev = hwif->pdev;
  49. enum hinic_port_cmd cmd;
  50. u16 out_size;
  51. int err;
  52. if (vlan_id >= VLAN_N_VID) {
  53. netif_err(nic_dev, drv, netdev, "Invalid VLAN number\n");
  54. return -EINVAL;
  55. }
  56. if (op == MAC_SET)
  57. cmd = HINIC_PORT_CMD_SET_MAC;
  58. else
  59. cmd = HINIC_PORT_CMD_DEL_MAC;
  60. port_mac_cmd.func_idx = HINIC_HWIF_FUNC_IDX(hwif);
  61. port_mac_cmd.vlan_id = vlan_id;
  62. memcpy(port_mac_cmd.mac, addr, ETH_ALEN);
  63. err = hinic_port_msg_cmd(hwdev, cmd, &port_mac_cmd,
  64. sizeof(port_mac_cmd),
  65. &port_mac_cmd, &out_size);
  66. if (err || (out_size != sizeof(port_mac_cmd)) || port_mac_cmd.status) {
  67. dev_err(&pdev->dev, "Failed to change MAC, ret = %d\n",
  68. port_mac_cmd.status);
  69. return -EFAULT;
  70. }
  71. return 0;
  72. }
  73. /**
  74. * hinic_port_add_mac - add mac address
  75. * @nic_dev: nic device
  76. * @addr: mac address
  77. * @vlan_id: vlan number to set with the mac
  78. *
  79. * Return 0 - Success, negative - Failure
  80. **/
  81. int hinic_port_add_mac(struct hinic_dev *nic_dev,
  82. const u8 *addr, u16 vlan_id)
  83. {
  84. return change_mac(nic_dev, addr, vlan_id, MAC_SET);
  85. }
  86. /**
  87. * hinic_port_del_mac - remove mac address
  88. * @nic_dev: nic device
  89. * @addr: mac address
  90. * @vlan_id: vlan number that is connected to the mac
  91. *
  92. * Return 0 - Success, negative - Failure
  93. **/
  94. int hinic_port_del_mac(struct hinic_dev *nic_dev, const u8 *addr,
  95. u16 vlan_id)
  96. {
  97. return change_mac(nic_dev, addr, vlan_id, MAC_DEL);
  98. }
  99. /**
  100. * hinic_port_get_mac - get the mac address of the nic device
  101. * @nic_dev: nic device
  102. * @addr: returned mac address
  103. *
  104. * Return 0 - Success, negative - Failure
  105. **/
  106. int hinic_port_get_mac(struct hinic_dev *nic_dev, u8 *addr)
  107. {
  108. struct hinic_hwdev *hwdev = nic_dev->hwdev;
  109. struct hinic_port_mac_cmd port_mac_cmd;
  110. struct hinic_hwif *hwif = hwdev->hwif;
  111. struct pci_dev *pdev = hwif->pdev;
  112. u16 out_size;
  113. int err;
  114. port_mac_cmd.func_idx = HINIC_HWIF_FUNC_IDX(hwif);
  115. err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_GET_MAC,
  116. &port_mac_cmd, sizeof(port_mac_cmd),
  117. &port_mac_cmd, &out_size);
  118. if (err || (out_size != sizeof(port_mac_cmd)) || port_mac_cmd.status) {
  119. dev_err(&pdev->dev, "Failed to get mac, ret = %d\n",
  120. port_mac_cmd.status);
  121. return -EFAULT;
  122. }
  123. memcpy(addr, port_mac_cmd.mac, ETH_ALEN);
  124. return 0;
  125. }
  126. /**
  127. * hinic_port_set_mtu - set mtu
  128. * @nic_dev: nic device
  129. * @new_mtu: new mtu
  130. *
  131. * Return 0 - Success, negative - Failure
  132. **/
  133. int hinic_port_set_mtu(struct hinic_dev *nic_dev, int new_mtu)
  134. {
  135. struct net_device *netdev = nic_dev->netdev;
  136. struct hinic_hwdev *hwdev = nic_dev->hwdev;
  137. struct hinic_port_mtu_cmd port_mtu_cmd;
  138. struct hinic_hwif *hwif = hwdev->hwif;
  139. struct pci_dev *pdev = hwif->pdev;
  140. int err, max_frame;
  141. u16 out_size;
  142. if (new_mtu < HINIC_MIN_MTU_SIZE) {
  143. netif_err(nic_dev, drv, netdev, "mtu < MIN MTU size");
  144. return -EINVAL;
  145. }
  146. max_frame = new_mtu + ETH_HLEN + ETH_FCS_LEN;
  147. if (max_frame > HINIC_MAX_JUMBO_FRAME_SIZE) {
  148. netif_err(nic_dev, drv, netdev, "mtu > MAX MTU size");
  149. return -EINVAL;
  150. }
  151. port_mtu_cmd.func_idx = HINIC_HWIF_FUNC_IDX(hwif);
  152. port_mtu_cmd.mtu = new_mtu;
  153. err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_CHANGE_MTU,
  154. &port_mtu_cmd, sizeof(port_mtu_cmd),
  155. &port_mtu_cmd, &out_size);
  156. if (err || (out_size != sizeof(port_mtu_cmd)) || port_mtu_cmd.status) {
  157. dev_err(&pdev->dev, "Failed to set mtu, ret = %d\n",
  158. port_mtu_cmd.status);
  159. return -EFAULT;
  160. }
  161. return 0;
  162. }
  163. /**
  164. * hinic_port_add_vlan - add vlan to the nic device
  165. * @nic_dev: nic device
  166. * @vlan_id: the vlan number to add
  167. *
  168. * Return 0 - Success, negative - Failure
  169. **/
  170. int hinic_port_add_vlan(struct hinic_dev *nic_dev, u16 vlan_id)
  171. {
  172. struct hinic_hwdev *hwdev = nic_dev->hwdev;
  173. struct hinic_port_vlan_cmd port_vlan_cmd;
  174. port_vlan_cmd.func_idx = HINIC_HWIF_FUNC_IDX(hwdev->hwif);
  175. port_vlan_cmd.vlan_id = vlan_id;
  176. return hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_ADD_VLAN,
  177. &port_vlan_cmd, sizeof(port_vlan_cmd),
  178. NULL, NULL);
  179. }
  180. /**
  181. * hinic_port_del_vlan - delete vlan from the nic device
  182. * @nic_dev: nic device
  183. * @vlan_id: the vlan number to delete
  184. *
  185. * Return 0 - Success, negative - Failure
  186. **/
  187. int hinic_port_del_vlan(struct hinic_dev *nic_dev, u16 vlan_id)
  188. {
  189. struct hinic_hwdev *hwdev = nic_dev->hwdev;
  190. struct hinic_port_vlan_cmd port_vlan_cmd;
  191. port_vlan_cmd.func_idx = HINIC_HWIF_FUNC_IDX(hwdev->hwif);
  192. port_vlan_cmd.vlan_id = vlan_id;
  193. return hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_DEL_VLAN,
  194. &port_vlan_cmd, sizeof(port_vlan_cmd),
  195. NULL, NULL);
  196. }
  197. /**
  198. * hinic_port_set_rx_mode - set rx mode in the nic device
  199. * @nic_dev: nic device
  200. * @rx_mode: the rx mode to set
  201. *
  202. * Return 0 - Success, negative - Failure
  203. **/
  204. int hinic_port_set_rx_mode(struct hinic_dev *nic_dev, u32 rx_mode)
  205. {
  206. struct hinic_hwdev *hwdev = nic_dev->hwdev;
  207. struct hinic_port_rx_mode_cmd rx_mode_cmd;
  208. rx_mode_cmd.func_idx = HINIC_HWIF_FUNC_IDX(hwdev->hwif);
  209. rx_mode_cmd.rx_mode = rx_mode;
  210. return hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_SET_RX_MODE,
  211. &rx_mode_cmd, sizeof(rx_mode_cmd),
  212. NULL, NULL);
  213. }
  214. /**
  215. * hinic_port_link_state - get the link state
  216. * @nic_dev: nic device
  217. * @link_state: the returned link state
  218. *
  219. * Return 0 - Success, negative - Failure
  220. **/
  221. int hinic_port_link_state(struct hinic_dev *nic_dev,
  222. enum hinic_port_link_state *link_state)
  223. {
  224. struct hinic_hwdev *hwdev = nic_dev->hwdev;
  225. struct hinic_hwif *hwif = hwdev->hwif;
  226. struct hinic_port_link_cmd link_cmd;
  227. struct pci_dev *pdev = hwif->pdev;
  228. u16 out_size;
  229. int err;
  230. if (!HINIC_IS_PF(hwif) && !HINIC_IS_PPF(hwif)) {
  231. dev_err(&pdev->dev, "unsupported PCI Function type\n");
  232. return -EINVAL;
  233. }
  234. link_cmd.func_idx = HINIC_HWIF_FUNC_IDX(hwif);
  235. err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_GET_LINK_STATE,
  236. &link_cmd, sizeof(link_cmd),
  237. &link_cmd, &out_size);
  238. if (err || (out_size != sizeof(link_cmd)) || link_cmd.status) {
  239. dev_err(&pdev->dev, "Failed to get link state, ret = %d\n",
  240. link_cmd.status);
  241. return -EINVAL;
  242. }
  243. *link_state = link_cmd.state;
  244. return 0;
  245. }
  246. /**
  247. * hinic_port_set_state - set port state
  248. * @nic_dev: nic device
  249. * @state: the state to set
  250. *
  251. * Return 0 - Success, negative - Failure
  252. **/
  253. int hinic_port_set_state(struct hinic_dev *nic_dev, enum hinic_port_state state)
  254. {
  255. struct hinic_hwdev *hwdev = nic_dev->hwdev;
  256. struct hinic_port_state_cmd port_state;
  257. struct hinic_hwif *hwif = hwdev->hwif;
  258. struct pci_dev *pdev = hwif->pdev;
  259. u16 out_size;
  260. int err;
  261. if (!HINIC_IS_PF(hwif) && !HINIC_IS_PPF(hwif)) {
  262. dev_err(&pdev->dev, "unsupported PCI Function type\n");
  263. return -EINVAL;
  264. }
  265. port_state.state = state;
  266. err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_SET_PORT_STATE,
  267. &port_state, sizeof(port_state),
  268. &port_state, &out_size);
  269. if (err || (out_size != sizeof(port_state)) || port_state.status) {
  270. dev_err(&pdev->dev, "Failed to set port state, ret = %d\n",
  271. port_state.status);
  272. return -EFAULT;
  273. }
  274. return 0;
  275. }
  276. /**
  277. * hinic_port_set_func_state- set func device state
  278. * @nic_dev: nic device
  279. * @state: the state to set
  280. *
  281. * Return 0 - Success, negative - Failure
  282. **/
  283. int hinic_port_set_func_state(struct hinic_dev *nic_dev,
  284. enum hinic_func_port_state state)
  285. {
  286. struct hinic_port_func_state_cmd func_state;
  287. struct hinic_hwdev *hwdev = nic_dev->hwdev;
  288. struct hinic_hwif *hwif = hwdev->hwif;
  289. struct pci_dev *pdev = hwif->pdev;
  290. u16 out_size;
  291. int err;
  292. func_state.func_idx = HINIC_HWIF_FUNC_IDX(hwif);
  293. func_state.state = state;
  294. err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_SET_FUNC_STATE,
  295. &func_state, sizeof(func_state),
  296. &func_state, &out_size);
  297. if (err || (out_size != sizeof(func_state)) || func_state.status) {
  298. dev_err(&pdev->dev, "Failed to set port func state, ret = %d\n",
  299. func_state.status);
  300. return -EFAULT;
  301. }
  302. return 0;
  303. }
  304. /**
  305. * hinic_port_get_cap - get port capabilities
  306. * @nic_dev: nic device
  307. * @port_cap: returned port capabilities
  308. *
  309. * Return 0 - Success, negative - Failure
  310. **/
  311. int hinic_port_get_cap(struct hinic_dev *nic_dev,
  312. struct hinic_port_cap *port_cap)
  313. {
  314. struct hinic_hwdev *hwdev = nic_dev->hwdev;
  315. struct hinic_hwif *hwif = hwdev->hwif;
  316. struct pci_dev *pdev = hwif->pdev;
  317. u16 out_size;
  318. int err;
  319. port_cap->func_idx = HINIC_HWIF_FUNC_IDX(hwif);
  320. err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_GET_CAP,
  321. port_cap, sizeof(*port_cap),
  322. port_cap, &out_size);
  323. if (err || (out_size != sizeof(*port_cap)) || port_cap->status) {
  324. dev_err(&pdev->dev,
  325. "Failed to get port capabilities, ret = %d\n",
  326. port_cap->status);
  327. return -EINVAL;
  328. }
  329. return 0;
  330. }