xref: /openbmc/linux/drivers/net/ethernet/huawei/hinic/hinic_port.c (revision 4f727ecefefbd180de10e25b3e74c03dce3f1e75)
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Huawei HiNIC PCI Express Linux driver
4  * Copyright(c) 2017 Huawei Technologies Co., Ltd
5  */
6 
7 #include <linux/types.h>
8 #include <linux/netdevice.h>
9 #include <linux/etherdevice.h>
10 #include <linux/if_vlan.h>
11 #include <linux/pci.h>
12 #include <linux/device.h>
13 #include <linux/errno.h>
14 
15 #include "hinic_hw_if.h"
16 #include "hinic_hw_dev.h"
17 #include "hinic_port.h"
18 #include "hinic_dev.h"
19 
20 #define HINIC_MIN_MTU_SIZE              256
21 #define HINIC_MAX_JUMBO_FRAME_SIZE      15872
22 
23 enum mac_op {
24 	MAC_DEL,
25 	MAC_SET,
26 };
27 
28 /**
29  * change_mac - change(add or delete) mac address
30  * @nic_dev: nic device
31  * @addr: mac address
32  * @vlan_id: vlan number to set with the mac
33  * @op: add or delete the mac
34  *
35  * Return 0 - Success, negative - Failure
36  **/
37 static int change_mac(struct hinic_dev *nic_dev, const u8 *addr,
38 		      u16 vlan_id, enum mac_op op)
39 {
40 	struct net_device *netdev = nic_dev->netdev;
41 	struct hinic_hwdev *hwdev = nic_dev->hwdev;
42 	struct hinic_port_mac_cmd port_mac_cmd;
43 	struct hinic_hwif *hwif = hwdev->hwif;
44 	struct pci_dev *pdev = hwif->pdev;
45 	enum hinic_port_cmd cmd;
46 	u16 out_size;
47 	int err;
48 
49 	if (vlan_id >= VLAN_N_VID) {
50 		netif_err(nic_dev, drv, netdev, "Invalid VLAN number\n");
51 		return -EINVAL;
52 	}
53 
54 	if (op == MAC_SET)
55 		cmd = HINIC_PORT_CMD_SET_MAC;
56 	else
57 		cmd = HINIC_PORT_CMD_DEL_MAC;
58 
59 	port_mac_cmd.func_idx = HINIC_HWIF_FUNC_IDX(hwif);
60 	port_mac_cmd.vlan_id = vlan_id;
61 	memcpy(port_mac_cmd.mac, addr, ETH_ALEN);
62 
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 
72 	return 0;
73 }
74 
75 /**
76  * hinic_port_add_mac - add mac address
77  * @nic_dev: nic device
78  * @addr: mac address
79  * @vlan_id: vlan number to set with the mac
80  *
81  * Return 0 - Success, negative - Failure
82  **/
83 int hinic_port_add_mac(struct hinic_dev *nic_dev,
84 		       const u8 *addr, u16 vlan_id)
85 {
86 	return change_mac(nic_dev, addr, vlan_id, MAC_SET);
87 }
88 
89 /**
90  * hinic_port_del_mac - remove mac address
91  * @nic_dev: nic device
92  * @addr: mac address
93  * @vlan_id: vlan number that is connected to the mac
94  *
95  * Return 0 - Success, negative - Failure
96  **/
97 int hinic_port_del_mac(struct hinic_dev *nic_dev, const u8 *addr,
98 		       u16 vlan_id)
99 {
100 	return change_mac(nic_dev, addr, vlan_id, MAC_DEL);
101 }
102 
103 /**
104  * hinic_port_get_mac - get the mac address of the nic device
105  * @nic_dev: nic device
106  * @addr: returned mac address
107  *
108  * Return 0 - Success, negative - Failure
109  **/
110 int hinic_port_get_mac(struct hinic_dev *nic_dev, u8 *addr)
111 {
112 	struct hinic_hwdev *hwdev = nic_dev->hwdev;
113 	struct hinic_port_mac_cmd port_mac_cmd;
114 	struct hinic_hwif *hwif = hwdev->hwif;
115 	struct pci_dev *pdev = hwif->pdev;
116 	u16 out_size;
117 	int err;
118 
119 	port_mac_cmd.func_idx = HINIC_HWIF_FUNC_IDX(hwif);
120 
121 	err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_GET_MAC,
122 				 &port_mac_cmd, sizeof(port_mac_cmd),
123 				 &port_mac_cmd, &out_size);
124 	if (err || (out_size != sizeof(port_mac_cmd)) || port_mac_cmd.status) {
125 		dev_err(&pdev->dev, "Failed to get mac, ret = %d\n",
126 			port_mac_cmd.status);
127 		return -EFAULT;
128 	}
129 
130 	memcpy(addr, port_mac_cmd.mac, ETH_ALEN);
131 	return 0;
132 }
133 
134 /**
135  * hinic_port_set_mtu - set mtu
136  * @nic_dev: nic device
137  * @new_mtu: new mtu
138  *
139  * Return 0 - Success, negative - Failure
140  **/
141 int hinic_port_set_mtu(struct hinic_dev *nic_dev, int new_mtu)
142 {
143 	struct net_device *netdev = nic_dev->netdev;
144 	struct hinic_hwdev *hwdev = nic_dev->hwdev;
145 	struct hinic_port_mtu_cmd port_mtu_cmd;
146 	struct hinic_hwif *hwif = hwdev->hwif;
147 	struct pci_dev *pdev = hwif->pdev;
148 	int err, max_frame;
149 	u16 out_size;
150 
151 	if (new_mtu < HINIC_MIN_MTU_SIZE) {
152 		netif_err(nic_dev, drv, netdev, "mtu < MIN MTU size");
153 		return -EINVAL;
154 	}
155 
156 	max_frame = new_mtu + ETH_HLEN + ETH_FCS_LEN;
157 	if (max_frame > HINIC_MAX_JUMBO_FRAME_SIZE) {
158 		netif_err(nic_dev, drv, netdev, "mtu > MAX MTU size");
159 		return -EINVAL;
160 	}
161 
162 	port_mtu_cmd.func_idx = HINIC_HWIF_FUNC_IDX(hwif);
163 	port_mtu_cmd.mtu = new_mtu;
164 
165 	err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_CHANGE_MTU,
166 				 &port_mtu_cmd, sizeof(port_mtu_cmd),
167 				 &port_mtu_cmd, &out_size);
168 	if (err || (out_size != sizeof(port_mtu_cmd)) || port_mtu_cmd.status) {
169 		dev_err(&pdev->dev, "Failed to set mtu, ret = %d\n",
170 			port_mtu_cmd.status);
171 		return -EFAULT;
172 	}
173 
174 	return 0;
175 }
176 
177 /**
178  * hinic_port_add_vlan - add vlan to the nic device
179  * @nic_dev: nic device
180  * @vlan_id: the vlan number to add
181  *
182  * Return 0 - Success, negative - Failure
183  **/
184 int hinic_port_add_vlan(struct hinic_dev *nic_dev, u16 vlan_id)
185 {
186 	struct hinic_hwdev *hwdev = nic_dev->hwdev;
187 	struct hinic_port_vlan_cmd port_vlan_cmd;
188 
189 	port_vlan_cmd.func_idx = HINIC_HWIF_FUNC_IDX(hwdev->hwif);
190 	port_vlan_cmd.vlan_id = vlan_id;
191 
192 	return hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_ADD_VLAN,
193 				  &port_vlan_cmd, sizeof(port_vlan_cmd),
194 				  NULL, NULL);
195 }
196 
197 /**
198  * hinic_port_del_vlan - delete vlan from the nic device
199  * @nic_dev: nic device
200  * @vlan_id: the vlan number to delete
201  *
202  * Return 0 - Success, negative - Failure
203  **/
204 int hinic_port_del_vlan(struct hinic_dev *nic_dev, u16 vlan_id)
205 {
206 	struct hinic_hwdev *hwdev = nic_dev->hwdev;
207 	struct hinic_port_vlan_cmd port_vlan_cmd;
208 
209 	port_vlan_cmd.func_idx = HINIC_HWIF_FUNC_IDX(hwdev->hwif);
210 	port_vlan_cmd.vlan_id = vlan_id;
211 
212 	return hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_DEL_VLAN,
213 				 &port_vlan_cmd, sizeof(port_vlan_cmd),
214 				 NULL, NULL);
215 }
216 
217 /**
218  * hinic_port_set_rx_mode - set rx mode in the nic device
219  * @nic_dev: nic device
220  * @rx_mode: the rx mode to set
221  *
222  * Return 0 - Success, negative - Failure
223  **/
224 int hinic_port_set_rx_mode(struct hinic_dev *nic_dev, u32 rx_mode)
225 {
226 	struct hinic_hwdev *hwdev = nic_dev->hwdev;
227 	struct hinic_port_rx_mode_cmd rx_mode_cmd;
228 
229 	rx_mode_cmd.func_idx = HINIC_HWIF_FUNC_IDX(hwdev->hwif);
230 	rx_mode_cmd.rx_mode = rx_mode;
231 
232 	return hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_SET_RX_MODE,
233 				  &rx_mode_cmd, sizeof(rx_mode_cmd),
234 				  NULL, NULL);
235 }
236 
237 /**
238  * hinic_port_link_state - get the link state
239  * @nic_dev: nic device
240  * @link_state: the returned link state
241  *
242  * Return 0 - Success, negative - Failure
243  **/
244 int hinic_port_link_state(struct hinic_dev *nic_dev,
245 			  enum hinic_port_link_state *link_state)
246 {
247 	struct hinic_hwdev *hwdev = nic_dev->hwdev;
248 	struct hinic_hwif *hwif = hwdev->hwif;
249 	struct hinic_port_link_cmd link_cmd;
250 	struct pci_dev *pdev = hwif->pdev;
251 	u16 out_size;
252 	int err;
253 
254 	if (!HINIC_IS_PF(hwif) && !HINIC_IS_PPF(hwif)) {
255 		dev_err(&pdev->dev, "unsupported PCI Function type\n");
256 		return -EINVAL;
257 	}
258 
259 	link_cmd.func_idx = HINIC_HWIF_FUNC_IDX(hwif);
260 
261 	err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_GET_LINK_STATE,
262 				 &link_cmd, sizeof(link_cmd),
263 				 &link_cmd, &out_size);
264 	if (err || (out_size != sizeof(link_cmd)) || link_cmd.status) {
265 		dev_err(&pdev->dev, "Failed to get link state, ret = %d\n",
266 			link_cmd.status);
267 		return -EINVAL;
268 	}
269 
270 	*link_state = link_cmd.state;
271 	return 0;
272 }
273 
274 /**
275  * hinic_port_set_state - set port state
276  * @nic_dev: nic device
277  * @state: the state to set
278  *
279  * Return 0 - Success, negative - Failure
280  **/
281 int hinic_port_set_state(struct hinic_dev *nic_dev, enum hinic_port_state state)
282 {
283 	struct hinic_hwdev *hwdev = nic_dev->hwdev;
284 	struct hinic_port_state_cmd port_state;
285 	struct hinic_hwif *hwif = hwdev->hwif;
286 	struct pci_dev *pdev = hwif->pdev;
287 	u16 out_size;
288 	int err;
289 
290 	if (!HINIC_IS_PF(hwif) && !HINIC_IS_PPF(hwif)) {
291 		dev_err(&pdev->dev, "unsupported PCI Function type\n");
292 		return -EINVAL;
293 	}
294 
295 	port_state.state = state;
296 
297 	err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_SET_PORT_STATE,
298 				 &port_state, sizeof(port_state),
299 				 &port_state, &out_size);
300 	if (err || (out_size != sizeof(port_state)) || port_state.status) {
301 		dev_err(&pdev->dev, "Failed to set port state, ret = %d\n",
302 			port_state.status);
303 		return -EFAULT;
304 	}
305 
306 	return 0;
307 }
308 
309 /**
310  * hinic_port_set_func_state- set func device state
311  * @nic_dev: nic device
312  * @state: the state to set
313  *
314  * Return 0 - Success, negative - Failure
315  **/
316 int hinic_port_set_func_state(struct hinic_dev *nic_dev,
317 			      enum hinic_func_port_state state)
318 {
319 	struct hinic_port_func_state_cmd func_state;
320 	struct hinic_hwdev *hwdev = nic_dev->hwdev;
321 	struct hinic_hwif *hwif = hwdev->hwif;
322 	struct pci_dev *pdev = hwif->pdev;
323 	u16 out_size;
324 	int err;
325 
326 	func_state.func_idx = HINIC_HWIF_FUNC_IDX(hwif);
327 	func_state.state = state;
328 
329 	err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_SET_FUNC_STATE,
330 				 &func_state, sizeof(func_state),
331 				 &func_state, &out_size);
332 	if (err || (out_size != sizeof(func_state)) || func_state.status) {
333 		dev_err(&pdev->dev, "Failed to set port func state, ret = %d\n",
334 			func_state.status);
335 		return -EFAULT;
336 	}
337 
338 	return 0;
339 }
340 
341 /**
342  * hinic_port_get_cap - get port capabilities
343  * @nic_dev: nic device
344  * @port_cap: returned port capabilities
345  *
346  * Return 0 - Success, negative - Failure
347  **/
348 int hinic_port_get_cap(struct hinic_dev *nic_dev,
349 		       struct hinic_port_cap *port_cap)
350 {
351 	struct hinic_hwdev *hwdev = nic_dev->hwdev;
352 	struct hinic_hwif *hwif = hwdev->hwif;
353 	struct pci_dev *pdev = hwif->pdev;
354 	u16 out_size;
355 	int err;
356 
357 	port_cap->func_idx = HINIC_HWIF_FUNC_IDX(hwif);
358 
359 	err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_GET_CAP,
360 				 port_cap, sizeof(*port_cap),
361 				 port_cap, &out_size);
362 	if (err || (out_size != sizeof(*port_cap)) || port_cap->status) {
363 		dev_err(&pdev->dev,
364 			"Failed to get port capabilities, ret = %d\n",
365 			port_cap->status);
366 		return -EINVAL;
367 	}
368 
369 	return 0;
370 }
371 
372 /**
373  * hinic_port_set_tso - set port tso configuration
374  * @nic_dev: nic device
375  * @state: the tso state to set
376  *
377  * Return 0 - Success, negative - Failure
378  **/
379 int hinic_port_set_tso(struct hinic_dev *nic_dev, enum hinic_tso_state state)
380 {
381 	struct hinic_hwdev *hwdev = nic_dev->hwdev;
382 	struct hinic_hwif *hwif = hwdev->hwif;
383 	struct hinic_tso_config tso_cfg = {0};
384 	struct pci_dev *pdev = hwif->pdev;
385 	u16 out_size;
386 	int err;
387 
388 	tso_cfg.func_id = HINIC_HWIF_FUNC_IDX(hwif);
389 	tso_cfg.tso_en = state;
390 
391 	err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_SET_TSO,
392 				 &tso_cfg, sizeof(tso_cfg),
393 				 &tso_cfg, &out_size);
394 	if (err || out_size != sizeof(tso_cfg) || tso_cfg.status) {
395 		dev_err(&pdev->dev,
396 			"Failed to set port tso, ret = %d\n",
397 			tso_cfg.status);
398 		return -EINVAL;
399 	}
400 
401 	return 0;
402 }
403 
404 int hinic_set_rx_csum_offload(struct hinic_dev *nic_dev, u32 en)
405 {
406 	struct hinic_checksum_offload rx_csum_cfg = {0};
407 	struct hinic_hwdev *hwdev = nic_dev->hwdev;
408 	struct hinic_hwif *hwif;
409 	struct pci_dev *pdev;
410 	u16 out_size;
411 	int err;
412 
413 	if (!hwdev)
414 		return -EINVAL;
415 
416 	hwif = hwdev->hwif;
417 	pdev = hwif->pdev;
418 	rx_csum_cfg.func_id = HINIC_HWIF_FUNC_IDX(hwif);
419 	rx_csum_cfg.rx_csum_offload = en;
420 
421 	err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_SET_RX_CSUM,
422 				 &rx_csum_cfg, sizeof(rx_csum_cfg),
423 				 &rx_csum_cfg, &out_size);
424 	if (err || !out_size || rx_csum_cfg.status) {
425 		dev_err(&pdev->dev,
426 			"Failed to set rx csum offload, ret = %d\n",
427 			rx_csum_cfg.status);
428 		return -EINVAL;
429 	}
430 
431 	return 0;
432 }
433