2 * Huawei HiNIC PCI Express Linux driver
3 * Copyright(c) 2017 Huawei Technologies Co., Ltd
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.
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
16 #include <linux/types.h>
17 #include <linux/netdevice.h>
18 #include <linux/etherdevice.h>
19 #include <linux/if_vlan.h>
20 #include <linux/pci.h>
21 #include <linux/device.h>
22 #include <linux/errno.h>
24 #include "hinic_hw_if.h"
25 #include "hinic_hw_dev.h"
26 #include "hinic_port.h"
27 #include "hinic_dev.h"
29 #define HINIC_MIN_MTU_SIZE 256
30 #define HINIC_MAX_JUMBO_FRAME_SIZE 15872
38 * change_mac - change(add or delete) mac address
39 * @nic_dev: nic device
41 * @vlan_id: vlan number to set with the mac
42 * @op: add or delete the mac
44 * Return 0 - Success, negative - Failure
46 static int change_mac(struct hinic_dev *nic_dev, const u8 *addr,
47 u16 vlan_id, enum mac_op op)
49 struct net_device *netdev = nic_dev->netdev;
50 struct hinic_hwdev *hwdev = nic_dev->hwdev;
51 struct hinic_port_mac_cmd port_mac_cmd;
52 struct hinic_hwif *hwif = hwdev->hwif;
53 struct pci_dev *pdev = hwif->pdev;
54 enum hinic_port_cmd cmd;
58 if (vlan_id >= VLAN_N_VID) {
59 netif_err(nic_dev, drv, netdev, "Invalid VLAN number\n");
64 cmd = HINIC_PORT_CMD_SET_MAC;
66 cmd = HINIC_PORT_CMD_DEL_MAC;
68 port_mac_cmd.func_idx = HINIC_HWIF_FUNC_IDX(hwif);
69 port_mac_cmd.vlan_id = vlan_id;
70 memcpy(port_mac_cmd.mac, addr, ETH_ALEN);
72 err = hinic_port_msg_cmd(hwdev, cmd, &port_mac_cmd,
74 &port_mac_cmd, &out_size);
75 if (err || (out_size != sizeof(port_mac_cmd)) || port_mac_cmd.status) {
76 dev_err(&pdev->dev, "Failed to change MAC, ret = %d\n",
85 * hinic_port_add_mac - add mac address
86 * @nic_dev: nic device
88 * @vlan_id: vlan number to set with the mac
90 * Return 0 - Success, negative - Failure
92 int hinic_port_add_mac(struct hinic_dev *nic_dev,
93 const u8 *addr, u16 vlan_id)
95 return change_mac(nic_dev, addr, vlan_id, MAC_SET);
99 * hinic_port_del_mac - remove mac address
100 * @nic_dev: nic device
102 * @vlan_id: vlan number that is connected to the mac
104 * Return 0 - Success, negative - Failure
106 int hinic_port_del_mac(struct hinic_dev *nic_dev, const u8 *addr,
109 return change_mac(nic_dev, addr, vlan_id, MAC_DEL);
113 * hinic_port_get_mac - get the mac address of the nic device
114 * @nic_dev: nic device
115 * @addr: returned mac address
117 * Return 0 - Success, negative - Failure
119 int hinic_port_get_mac(struct hinic_dev *nic_dev, u8 *addr)
121 struct hinic_hwdev *hwdev = nic_dev->hwdev;
122 struct hinic_port_mac_cmd port_mac_cmd;
123 struct hinic_hwif *hwif = hwdev->hwif;
124 struct pci_dev *pdev = hwif->pdev;
128 port_mac_cmd.func_idx = HINIC_HWIF_FUNC_IDX(hwif);
130 err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_GET_MAC,
131 &port_mac_cmd, sizeof(port_mac_cmd),
132 &port_mac_cmd, &out_size);
133 if (err || (out_size != sizeof(port_mac_cmd)) || port_mac_cmd.status) {
134 dev_err(&pdev->dev, "Failed to get mac, ret = %d\n",
135 port_mac_cmd.status);
139 memcpy(addr, port_mac_cmd.mac, ETH_ALEN);
144 * hinic_port_set_mtu - set mtu
145 * @nic_dev: nic device
148 * Return 0 - Success, negative - Failure
150 int hinic_port_set_mtu(struct hinic_dev *nic_dev, int new_mtu)
152 struct net_device *netdev = nic_dev->netdev;
153 struct hinic_hwdev *hwdev = nic_dev->hwdev;
154 struct hinic_port_mtu_cmd port_mtu_cmd;
155 struct hinic_hwif *hwif = hwdev->hwif;
156 struct pci_dev *pdev = hwif->pdev;
160 if (new_mtu < HINIC_MIN_MTU_SIZE) {
161 netif_err(nic_dev, drv, netdev, "mtu < MIN MTU size");
165 max_frame = new_mtu + ETH_HLEN + ETH_FCS_LEN;
166 if (max_frame > HINIC_MAX_JUMBO_FRAME_SIZE) {
167 netif_err(nic_dev, drv, netdev, "mtu > MAX MTU size");
171 port_mtu_cmd.func_idx = HINIC_HWIF_FUNC_IDX(hwif);
172 port_mtu_cmd.mtu = new_mtu;
174 err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_CHANGE_MTU,
175 &port_mtu_cmd, sizeof(port_mtu_cmd),
176 &port_mtu_cmd, &out_size);
177 if (err || (out_size != sizeof(port_mtu_cmd)) || port_mtu_cmd.status) {
178 dev_err(&pdev->dev, "Failed to set mtu, ret = %d\n",
179 port_mtu_cmd.status);
187 * hinic_port_add_vlan - add vlan to the nic device
188 * @nic_dev: nic device
189 * @vlan_id: the vlan number to add
191 * Return 0 - Success, negative - Failure
193 int hinic_port_add_vlan(struct hinic_dev *nic_dev, u16 vlan_id)
195 struct hinic_hwdev *hwdev = nic_dev->hwdev;
196 struct hinic_port_vlan_cmd port_vlan_cmd;
198 port_vlan_cmd.func_idx = HINIC_HWIF_FUNC_IDX(hwdev->hwif);
199 port_vlan_cmd.vlan_id = vlan_id;
201 return hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_ADD_VLAN,
202 &port_vlan_cmd, sizeof(port_vlan_cmd),
207 * hinic_port_del_vlan - delete vlan from the nic device
208 * @nic_dev: nic device
209 * @vlan_id: the vlan number to delete
211 * Return 0 - Success, negative - Failure
213 int hinic_port_del_vlan(struct hinic_dev *nic_dev, u16 vlan_id)
215 struct hinic_hwdev *hwdev = nic_dev->hwdev;
216 struct hinic_port_vlan_cmd port_vlan_cmd;
218 port_vlan_cmd.func_idx = HINIC_HWIF_FUNC_IDX(hwdev->hwif);
219 port_vlan_cmd.vlan_id = vlan_id;
221 return hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_DEL_VLAN,
222 &port_vlan_cmd, sizeof(port_vlan_cmd),
227 * hinic_port_set_rx_mode - set rx mode in the nic device
228 * @nic_dev: nic device
229 * @rx_mode: the rx mode to set
231 * Return 0 - Success, negative - Failure
233 int hinic_port_set_rx_mode(struct hinic_dev *nic_dev, u32 rx_mode)
235 struct hinic_hwdev *hwdev = nic_dev->hwdev;
236 struct hinic_port_rx_mode_cmd rx_mode_cmd;
238 rx_mode_cmd.func_idx = HINIC_HWIF_FUNC_IDX(hwdev->hwif);
239 rx_mode_cmd.rx_mode = rx_mode;
241 return hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_SET_RX_MODE,
242 &rx_mode_cmd, sizeof(rx_mode_cmd),
247 * hinic_port_link_state - get the link state
248 * @nic_dev: nic device
249 * @link_state: the returned link state
251 * Return 0 - Success, negative - Failure
253 int hinic_port_link_state(struct hinic_dev *nic_dev,
254 enum hinic_port_link_state *link_state)
256 struct hinic_hwdev *hwdev = nic_dev->hwdev;
257 struct hinic_hwif *hwif = hwdev->hwif;
258 struct hinic_port_link_cmd link_cmd;
259 struct pci_dev *pdev = hwif->pdev;
263 if (!HINIC_IS_PF(hwif) && !HINIC_IS_PPF(hwif)) {
264 dev_err(&pdev->dev, "unsupported PCI Function type\n");
268 link_cmd.func_idx = HINIC_HWIF_FUNC_IDX(hwif);
270 err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_GET_LINK_STATE,
271 &link_cmd, sizeof(link_cmd),
272 &link_cmd, &out_size);
273 if (err || (out_size != sizeof(link_cmd)) || link_cmd.status) {
274 dev_err(&pdev->dev, "Failed to get link state, ret = %d\n",
279 *link_state = link_cmd.state;
284 * hinic_port_set_state - set port state
285 * @nic_dev: nic device
286 * @state: the state to set
288 * Return 0 - Success, negative - Failure
290 int hinic_port_set_state(struct hinic_dev *nic_dev, enum hinic_port_state state)
292 struct hinic_hwdev *hwdev = nic_dev->hwdev;
293 struct hinic_port_state_cmd port_state;
294 struct hinic_hwif *hwif = hwdev->hwif;
295 struct pci_dev *pdev = hwif->pdev;
299 if (!HINIC_IS_PF(hwif) && !HINIC_IS_PPF(hwif)) {
300 dev_err(&pdev->dev, "unsupported PCI Function type\n");
304 port_state.state = state;
306 err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_SET_PORT_STATE,
307 &port_state, sizeof(port_state),
308 &port_state, &out_size);
309 if (err || (out_size != sizeof(port_state)) || port_state.status) {
310 dev_err(&pdev->dev, "Failed to set port state, ret = %d\n",
319 * hinic_port_set_func_state- set func device state
320 * @nic_dev: nic device
321 * @state: the state to set
323 * Return 0 - Success, negative - Failure
325 int hinic_port_set_func_state(struct hinic_dev *nic_dev,
326 enum hinic_func_port_state state)
328 struct hinic_port_func_state_cmd func_state;
329 struct hinic_hwdev *hwdev = nic_dev->hwdev;
330 struct hinic_hwif *hwif = hwdev->hwif;
331 struct pci_dev *pdev = hwif->pdev;
335 func_state.func_idx = HINIC_HWIF_FUNC_IDX(hwif);
336 func_state.state = state;
338 err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_SET_FUNC_STATE,
339 &func_state, sizeof(func_state),
340 &func_state, &out_size);
341 if (err || (out_size != sizeof(func_state)) || func_state.status) {
342 dev_err(&pdev->dev, "Failed to set port func state, ret = %d\n",
351 * hinic_port_get_cap - get port capabilities
352 * @nic_dev: nic device
353 * @port_cap: returned port capabilities
355 * Return 0 - Success, negative - Failure
357 int hinic_port_get_cap(struct hinic_dev *nic_dev,
358 struct hinic_port_cap *port_cap)
360 struct hinic_hwdev *hwdev = nic_dev->hwdev;
361 struct hinic_hwif *hwif = hwdev->hwif;
362 struct pci_dev *pdev = hwif->pdev;
366 port_cap->func_idx = HINIC_HWIF_FUNC_IDX(hwif);
368 err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_GET_CAP,
369 port_cap, sizeof(*port_cap),
370 port_cap, &out_size);
371 if (err || (out_size != sizeof(*port_cap)) || port_cap->status) {
373 "Failed to get port capabilities, ret = %d\n",