1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | /* Huawei HiNIC PCI Express Linux driver |
3 | * Copyright(c) 2017 Huawei Technologies Co., Ltd |
4 | */ |
5 | |
6 | #include <linux/pci.h> |
7 | #include <linux/if_vlan.h> |
8 | #include <linux/interrupt.h> |
9 | #include <linux/etherdevice.h> |
10 | #include <linux/netdevice.h> |
11 | #include <linux/module.h> |
12 | |
13 | #include "hinic_hw_dev.h" |
14 | #include "hinic_dev.h" |
15 | #include "hinic_hw_mbox.h" |
16 | #include "hinic_hw_cmdq.h" |
17 | #include "hinic_port.h" |
18 | #include "hinic_sriov.h" |
19 | |
20 | static unsigned char set_vf_link_state; |
21 | module_param(set_vf_link_state, byte, 0444); |
22 | MODULE_PARM_DESC(set_vf_link_state, "Set vf link state, 0 represents link auto, 1 represents link always up, 2 represents link always down. - default is 0." ); |
23 | |
24 | #define HINIC_VLAN_PRIORITY_SHIFT 13 |
25 | #define HINIC_ADD_VLAN_IN_MAC 0x8000 |
26 | #define HINIC_TX_RATE_TABLE_FULL 12 |
27 | #define HINIC_MAX_QOS 7 |
28 | |
29 | static int hinic_set_mac(struct hinic_hwdev *hwdev, const u8 *mac_addr, |
30 | u16 vlan_id, u16 func_id) |
31 | { |
32 | struct hinic_port_mac_cmd mac_info = {0}; |
33 | u16 out_size = sizeof(mac_info); |
34 | int err; |
35 | |
36 | mac_info.func_idx = func_id; |
37 | mac_info.vlan_id = vlan_id; |
38 | memcpy(mac_info.mac, mac_addr, ETH_ALEN); |
39 | |
40 | err = hinic_port_msg_cmd(hwdev, cmd: HINIC_PORT_CMD_SET_MAC, buf_in: &mac_info, |
41 | in_size: sizeof(mac_info), buf_out: &mac_info, out_size: &out_size); |
42 | if (err || out_size != sizeof(mac_info) || |
43 | (mac_info.status && mac_info.status != HINIC_MGMT_STATUS_EXIST)) { |
44 | dev_err(&hwdev->func_to_io.hwif->pdev->dev, "Failed to set MAC, err: %d, status: 0x%x, out size: 0x%x\n" , |
45 | err, mac_info.status, out_size); |
46 | return -EIO; |
47 | } |
48 | |
49 | return 0; |
50 | } |
51 | |
52 | static void hinic_notify_vf_link_status(struct hinic_hwdev *hwdev, u16 vf_id, |
53 | u8 link_status) |
54 | { |
55 | struct vf_data_storage *vf_infos = hwdev->func_to_io.vf_infos; |
56 | struct hinic_port_link_status link = {0}; |
57 | u16 out_size = sizeof(link); |
58 | int err; |
59 | |
60 | if (vf_infos[HW_VF_ID_TO_OS(vf_id)].registered) { |
61 | link.link = link_status; |
62 | link.func_id = hinic_glb_pf_vf_offset(hwif: hwdev->hwif) + vf_id; |
63 | err = hinic_mbox_to_vf(hwdev, mod: HINIC_MOD_L2NIC, |
64 | vf_id, cmd: HINIC_PORT_CMD_LINK_STATUS_REPORT, |
65 | buf_in: &link, in_size: sizeof(link), |
66 | buf_out: &link, out_size: &out_size, timeout: 0); |
67 | if (err || !out_size || link.status) |
68 | dev_err(&hwdev->hwif->pdev->dev, |
69 | "Send link change event to VF %d failed, err: %d, status: 0x%x, out_size: 0x%x\n" , |
70 | HW_VF_ID_TO_OS(vf_id), err, |
71 | link.status, out_size); |
72 | } |
73 | } |
74 | |
75 | /* send link change event mbox msg to active vfs under the pf */ |
76 | void hinic_notify_all_vfs_link_changed(struct hinic_hwdev *hwdev, |
77 | u8 link_status) |
78 | { |
79 | struct hinic_func_to_io *nic_io = &hwdev->func_to_io; |
80 | u16 i; |
81 | |
82 | nic_io->link_status = link_status; |
83 | for (i = 1; i <= nic_io->max_vfs; i++) { |
84 | if (!nic_io->vf_infos[HW_VF_ID_TO_OS(i)].link_forced) |
85 | hinic_notify_vf_link_status(hwdev, vf_id: i, link_status); |
86 | } |
87 | } |
88 | |
89 | static u16 hinic_vf_info_vlanprio(struct hinic_hwdev *hwdev, int vf_id) |
90 | { |
91 | struct hinic_func_to_io *nic_io = &hwdev->func_to_io; |
92 | u16 pf_vlan, vlanprio; |
93 | u8 pf_qos; |
94 | |
95 | pf_vlan = nic_io->vf_infos[HW_VF_ID_TO_OS(vf_id)].pf_vlan; |
96 | pf_qos = nic_io->vf_infos[HW_VF_ID_TO_OS(vf_id)].pf_qos; |
97 | vlanprio = pf_vlan | pf_qos << HINIC_VLAN_PRIORITY_SHIFT; |
98 | |
99 | return vlanprio; |
100 | } |
101 | |
102 | static int hinic_set_vf_vlan(struct hinic_hwdev *hwdev, bool add, u16 vid, |
103 | u8 qos, int vf_id) |
104 | { |
105 | struct hinic_vf_vlan_config vf_vlan = {0}; |
106 | u16 out_size = sizeof(vf_vlan); |
107 | int err; |
108 | u8 cmd; |
109 | |
110 | /* VLAN 0 is a special case, don't allow it to be removed */ |
111 | if (!vid && !add) |
112 | return 0; |
113 | |
114 | vf_vlan.func_id = hinic_glb_pf_vf_offset(hwif: hwdev->hwif) + vf_id; |
115 | vf_vlan.vlan_id = vid; |
116 | vf_vlan.qos = qos; |
117 | |
118 | if (add) |
119 | cmd = HINIC_PORT_CMD_SET_VF_VLAN; |
120 | else |
121 | cmd = HINIC_PORT_CMD_CLR_VF_VLAN; |
122 | |
123 | err = hinic_port_msg_cmd(hwdev, cmd, buf_in: &vf_vlan, |
124 | in_size: sizeof(vf_vlan), buf_out: &vf_vlan, out_size: &out_size); |
125 | if (err || !out_size || vf_vlan.status) { |
126 | dev_err(&hwdev->hwif->pdev->dev, "Failed to set VF %d vlan, err: %d, status: 0x%x, out size: 0x%x\n" , |
127 | HW_VF_ID_TO_OS(vf_id), err, vf_vlan.status, out_size); |
128 | return -EFAULT; |
129 | } |
130 | |
131 | return 0; |
132 | } |
133 | |
134 | static int hinic_set_vf_tx_rate_max_min(struct hinic_hwdev *hwdev, u16 vf_id, |
135 | u32 max_rate, u32 min_rate) |
136 | { |
137 | struct hinic_func_to_io *nic_io = &hwdev->func_to_io; |
138 | struct hinic_tx_rate_cfg_max_min rate_cfg = {0}; |
139 | u16 out_size = sizeof(rate_cfg); |
140 | int err; |
141 | |
142 | rate_cfg.func_id = hinic_glb_pf_vf_offset(hwif: hwdev->hwif) + vf_id; |
143 | rate_cfg.max_rate = max_rate; |
144 | rate_cfg.min_rate = min_rate; |
145 | err = hinic_port_msg_cmd(hwdev, cmd: HINIC_PORT_CMD_SET_VF_MAX_MIN_RATE, |
146 | buf_in: &rate_cfg, in_size: sizeof(rate_cfg), buf_out: &rate_cfg, |
147 | out_size: &out_size); |
148 | if ((rate_cfg.status != HINIC_MGMT_CMD_UNSUPPORTED && |
149 | rate_cfg.status) || err || !out_size) { |
150 | dev_err(&hwdev->hwif->pdev->dev, "Failed to set VF(%d) max rate(%d), min rate(%d), err: %d, status: 0x%x, out size: 0x%x\n" , |
151 | HW_VF_ID_TO_OS(vf_id), max_rate, min_rate, err, |
152 | rate_cfg.status, out_size); |
153 | return -EIO; |
154 | } |
155 | |
156 | if (!rate_cfg.status) { |
157 | nic_io->vf_infos[HW_VF_ID_TO_OS(vf_id)].max_rate = max_rate; |
158 | nic_io->vf_infos[HW_VF_ID_TO_OS(vf_id)].min_rate = min_rate; |
159 | } |
160 | |
161 | return rate_cfg.status; |
162 | } |
163 | |
164 | static int hinic_set_vf_rate_limit(struct hinic_hwdev *hwdev, u16 vf_id, |
165 | u32 tx_rate) |
166 | { |
167 | struct hinic_func_to_io *nic_io = &hwdev->func_to_io; |
168 | struct hinic_tx_rate_cfg rate_cfg = {0}; |
169 | u16 out_size = sizeof(rate_cfg); |
170 | int err; |
171 | |
172 | rate_cfg.func_id = hinic_glb_pf_vf_offset(hwif: hwdev->hwif) + vf_id; |
173 | rate_cfg.tx_rate = tx_rate; |
174 | err = hinic_port_msg_cmd(hwdev, cmd: HINIC_PORT_CMD_SET_VF_RATE, |
175 | buf_in: &rate_cfg, in_size: sizeof(rate_cfg), buf_out: &rate_cfg, |
176 | out_size: &out_size); |
177 | if (err || !out_size || rate_cfg.status) { |
178 | dev_err(&hwdev->hwif->pdev->dev, "Failed to set VF(%d) rate(%d), err: %d, status: 0x%x, out size: 0x%x\n" , |
179 | HW_VF_ID_TO_OS(vf_id), tx_rate, err, rate_cfg.status, |
180 | out_size); |
181 | if (rate_cfg.status) |
182 | return rate_cfg.status; |
183 | |
184 | return -EIO; |
185 | } |
186 | |
187 | nic_io->vf_infos[HW_VF_ID_TO_OS(vf_id)].max_rate = tx_rate; |
188 | nic_io->vf_infos[HW_VF_ID_TO_OS(vf_id)].min_rate = 0; |
189 | |
190 | return 0; |
191 | } |
192 | |
193 | static int hinic_set_vf_tx_rate(struct hinic_hwdev *hwdev, u16 vf_id, |
194 | u32 max_rate, u32 min_rate) |
195 | { |
196 | int err; |
197 | |
198 | err = hinic_set_vf_tx_rate_max_min(hwdev, vf_id, max_rate, min_rate); |
199 | if (err != HINIC_MGMT_CMD_UNSUPPORTED) |
200 | return err; |
201 | |
202 | if (min_rate) { |
203 | dev_err(&hwdev->hwif->pdev->dev, "Current firmware doesn't support to set min tx rate\n" ); |
204 | return -EOPNOTSUPP; |
205 | } |
206 | |
207 | dev_info(&hwdev->hwif->pdev->dev, "Current firmware doesn't support to set min tx rate, force min_tx_rate = max_tx_rate\n" ); |
208 | |
209 | return hinic_set_vf_rate_limit(hwdev, vf_id, tx_rate: max_rate); |
210 | } |
211 | |
212 | static int hinic_init_vf_config(struct hinic_hwdev *hwdev, u16 vf_id) |
213 | { |
214 | struct vf_data_storage *vf_info; |
215 | u16 func_id, vlan_id; |
216 | int err = 0; |
217 | |
218 | vf_info = hwdev->func_to_io.vf_infos + HW_VF_ID_TO_OS(vf_id); |
219 | if (vf_info->pf_set_mac) { |
220 | func_id = hinic_glb_pf_vf_offset(hwif: hwdev->hwif) + vf_id; |
221 | |
222 | vlan_id = 0; |
223 | |
224 | err = hinic_set_mac(hwdev, mac_addr: vf_info->vf_mac_addr, vlan_id, |
225 | func_id); |
226 | if (err) { |
227 | dev_err(&hwdev->func_to_io.hwif->pdev->dev, "Failed to set VF %d MAC\n" , |
228 | HW_VF_ID_TO_OS(vf_id)); |
229 | return err; |
230 | } |
231 | } |
232 | |
233 | if (hinic_vf_info_vlanprio(hwdev, vf_id)) { |
234 | err = hinic_set_vf_vlan(hwdev, add: true, vid: vf_info->pf_vlan, |
235 | qos: vf_info->pf_qos, vf_id); |
236 | if (err) { |
237 | dev_err(&hwdev->hwif->pdev->dev, "Failed to add VF %d VLAN_QOS\n" , |
238 | HW_VF_ID_TO_OS(vf_id)); |
239 | return err; |
240 | } |
241 | } |
242 | |
243 | if (vf_info->max_rate) { |
244 | err = hinic_set_vf_tx_rate(hwdev, vf_id, max_rate: vf_info->max_rate, |
245 | min_rate: vf_info->min_rate); |
246 | if (err) { |
247 | dev_err(&hwdev->hwif->pdev->dev, "Failed to set VF %d max rate: %d, min rate: %d\n" , |
248 | HW_VF_ID_TO_OS(vf_id), vf_info->max_rate, |
249 | vf_info->min_rate); |
250 | return err; |
251 | } |
252 | } |
253 | |
254 | return 0; |
255 | } |
256 | |
257 | static int hinic_register_vf_msg_handler(void *hwdev, u16 vf_id, |
258 | void *buf_in, u16 in_size, |
259 | void *buf_out, u16 *out_size) |
260 | { |
261 | struct hinic_register_vf *register_info = buf_out; |
262 | struct hinic_hwdev *hw_dev = hwdev; |
263 | struct hinic_func_to_io *nic_io; |
264 | int err; |
265 | |
266 | nic_io = &hw_dev->func_to_io; |
267 | if (vf_id > nic_io->max_vfs) { |
268 | dev_err(&hw_dev->hwif->pdev->dev, "Register VF id %d exceed limit[0-%d]\n" , |
269 | HW_VF_ID_TO_OS(vf_id), HW_VF_ID_TO_OS(nic_io->max_vfs)); |
270 | register_info->status = EFAULT; |
271 | return -EFAULT; |
272 | } |
273 | |
274 | *out_size = sizeof(*register_info); |
275 | err = hinic_init_vf_config(hwdev: hw_dev, vf_id); |
276 | if (err) { |
277 | register_info->status = EFAULT; |
278 | return err; |
279 | } |
280 | |
281 | nic_io->vf_infos[HW_VF_ID_TO_OS(vf_id)].registered = true; |
282 | |
283 | return 0; |
284 | } |
285 | |
286 | static int hinic_unregister_vf_msg_handler(void *hwdev, u16 vf_id, |
287 | void *buf_in, u16 in_size, |
288 | void *buf_out, u16 *out_size) |
289 | { |
290 | struct hinic_hwdev *hw_dev = hwdev; |
291 | struct hinic_func_to_io *nic_io; |
292 | |
293 | nic_io = &hw_dev->func_to_io; |
294 | *out_size = 0; |
295 | if (vf_id > nic_io->max_vfs) |
296 | return 0; |
297 | |
298 | nic_io->vf_infos[HW_VF_ID_TO_OS(vf_id)].registered = false; |
299 | |
300 | return 0; |
301 | } |
302 | |
303 | static int hinic_change_vf_mtu_msg_handler(void *hwdev, u16 vf_id, |
304 | void *buf_in, u16 in_size, |
305 | void *buf_out, u16 *out_size) |
306 | { |
307 | struct hinic_hwdev *hw_dev = hwdev; |
308 | int err; |
309 | |
310 | err = hinic_port_msg_cmd(hwdev, cmd: HINIC_PORT_CMD_CHANGE_MTU, buf_in, |
311 | in_size, buf_out, out_size); |
312 | if (err) { |
313 | dev_err(&hw_dev->hwif->pdev->dev, "Failed to set VF %u mtu\n" , |
314 | vf_id); |
315 | return err; |
316 | } |
317 | |
318 | return 0; |
319 | } |
320 | |
321 | static int hinic_get_vf_mac_msg_handler(void *hwdev, u16 vf_id, |
322 | void *buf_in, u16 in_size, |
323 | void *buf_out, u16 *out_size) |
324 | { |
325 | struct hinic_port_mac_cmd *mac_info = buf_out; |
326 | struct hinic_hwdev *dev = hwdev; |
327 | struct hinic_func_to_io *nic_io; |
328 | struct vf_data_storage *vf_info; |
329 | |
330 | nic_io = &dev->func_to_io; |
331 | vf_info = nic_io->vf_infos + HW_VF_ID_TO_OS(vf_id); |
332 | |
333 | memcpy(mac_info->mac, vf_info->vf_mac_addr, ETH_ALEN); |
334 | mac_info->status = 0; |
335 | *out_size = sizeof(*mac_info); |
336 | |
337 | return 0; |
338 | } |
339 | |
340 | static int hinic_set_vf_mac_msg_handler(void *hwdev, u16 vf_id, |
341 | void *buf_in, u16 in_size, |
342 | void *buf_out, u16 *out_size) |
343 | { |
344 | struct hinic_port_mac_cmd *mac_out = buf_out; |
345 | struct hinic_port_mac_cmd *mac_in = buf_in; |
346 | struct hinic_hwdev *hw_dev = hwdev; |
347 | struct hinic_func_to_io *nic_io; |
348 | struct vf_data_storage *vf_info; |
349 | int err; |
350 | |
351 | nic_io = &hw_dev->func_to_io; |
352 | vf_info = nic_io->vf_infos + HW_VF_ID_TO_OS(vf_id); |
353 | if (vf_info->pf_set_mac && !(vf_info->trust) && |
354 | is_valid_ether_addr(addr: mac_in->mac)) { |
355 | dev_warn(&hw_dev->hwif->pdev->dev, "PF has already set VF %d MAC address\n" , |
356 | HW_VF_ID_TO_OS(vf_id)); |
357 | mac_out->status = HINIC_PF_SET_VF_ALREADY; |
358 | *out_size = sizeof(*mac_out); |
359 | return 0; |
360 | } |
361 | |
362 | err = hinic_port_msg_cmd(hwdev: hw_dev, cmd: HINIC_PORT_CMD_SET_MAC, buf_in, |
363 | in_size, buf_out, out_size); |
364 | if ((err && err != HINIC_MBOX_PF_BUSY_ACTIVE_FW) || !(*out_size)) { |
365 | dev_err(&hw_dev->hwif->pdev->dev, |
366 | "Failed to set VF %d MAC address, err: %d, status: 0x%x, out size: 0x%x\n" , |
367 | HW_VF_ID_TO_OS(vf_id), err, mac_out->status, *out_size); |
368 | return -EFAULT; |
369 | } |
370 | |
371 | return err; |
372 | } |
373 | |
374 | static int hinic_del_vf_mac_msg_handler(void *hwdev, u16 vf_id, |
375 | void *buf_in, u16 in_size, |
376 | void *buf_out, u16 *out_size) |
377 | { |
378 | struct hinic_port_mac_cmd *mac_out = buf_out; |
379 | struct hinic_port_mac_cmd *mac_in = buf_in; |
380 | struct hinic_hwdev *hw_dev = hwdev; |
381 | struct hinic_func_to_io *nic_io; |
382 | struct vf_data_storage *vf_info; |
383 | int err; |
384 | |
385 | nic_io = &hw_dev->func_to_io; |
386 | vf_info = nic_io->vf_infos + HW_VF_ID_TO_OS(vf_id); |
387 | if (vf_info->pf_set_mac && is_valid_ether_addr(addr: mac_in->mac) && |
388 | !memcmp(p: vf_info->vf_mac_addr, q: mac_in->mac, ETH_ALEN)) { |
389 | dev_warn(&hw_dev->hwif->pdev->dev, "PF has already set VF mac.\n" ); |
390 | mac_out->status = HINIC_PF_SET_VF_ALREADY; |
391 | *out_size = sizeof(*mac_out); |
392 | return 0; |
393 | } |
394 | |
395 | err = hinic_port_msg_cmd(hwdev: hw_dev, cmd: HINIC_PORT_CMD_DEL_MAC, buf_in, |
396 | in_size, buf_out, out_size); |
397 | if ((err && err != HINIC_MBOX_PF_BUSY_ACTIVE_FW) || !(*out_size)) { |
398 | dev_err(&hw_dev->hwif->pdev->dev, "Failed to delete VF %d MAC, err: %d, status: 0x%x, out size: 0x%x\n" , |
399 | HW_VF_ID_TO_OS(vf_id), err, mac_out->status, *out_size); |
400 | return -EFAULT; |
401 | } |
402 | |
403 | return err; |
404 | } |
405 | |
406 | static int hinic_get_vf_link_status_msg_handler(void *hwdev, u16 vf_id, |
407 | void *buf_in, u16 in_size, |
408 | void *buf_out, u16 *out_size) |
409 | { |
410 | struct hinic_port_link_cmd *get_link = buf_out; |
411 | struct hinic_hwdev *hw_dev = hwdev; |
412 | struct vf_data_storage *vf_infos; |
413 | struct hinic_func_to_io *nic_io; |
414 | bool link_forced, link_up; |
415 | |
416 | nic_io = &hw_dev->func_to_io; |
417 | vf_infos = nic_io->vf_infos; |
418 | link_forced = vf_infos[HW_VF_ID_TO_OS(vf_id)].link_forced; |
419 | link_up = vf_infos[HW_VF_ID_TO_OS(vf_id)].link_up; |
420 | |
421 | if (link_forced) |
422 | get_link->state = link_up ? |
423 | HINIC_LINK_STATE_UP : HINIC_LINK_STATE_DOWN; |
424 | else |
425 | get_link->state = nic_io->link_status; |
426 | |
427 | get_link->status = 0; |
428 | *out_size = sizeof(*get_link); |
429 | |
430 | return 0; |
431 | } |
432 | |
433 | static bool check_func_table(struct hinic_hwdev *hwdev, u16 func_idx, |
434 | void *buf_in, u16 in_size) |
435 | { |
436 | struct hinic_cmd_fw_ctxt *function_table = buf_in; |
437 | |
438 | if (!hinic_mbox_check_func_id_8B(hwdev, func_idx, buf_in, in_size) || |
439 | !function_table->rx_buf_sz) |
440 | return false; |
441 | |
442 | return true; |
443 | } |
444 | |
445 | static struct vf_cmd_msg_handle nic_vf_cmd_msg_handler[] = { |
446 | {HINIC_PORT_CMD_VF_REGISTER, hinic_register_vf_msg_handler}, |
447 | {HINIC_PORT_CMD_VF_UNREGISTER, hinic_unregister_vf_msg_handler}, |
448 | {HINIC_PORT_CMD_CHANGE_MTU, hinic_change_vf_mtu_msg_handler}, |
449 | {HINIC_PORT_CMD_GET_MAC, hinic_get_vf_mac_msg_handler}, |
450 | {HINIC_PORT_CMD_SET_MAC, hinic_set_vf_mac_msg_handler}, |
451 | {HINIC_PORT_CMD_DEL_MAC, hinic_del_vf_mac_msg_handler}, |
452 | {HINIC_PORT_CMD_GET_LINK_STATE, hinic_get_vf_link_status_msg_handler}, |
453 | }; |
454 | |
455 | static struct vf_cmd_check_handle nic_cmd_support_vf[] = { |
456 | {HINIC_PORT_CMD_VF_REGISTER, NULL}, |
457 | {HINIC_PORT_CMD_VF_UNREGISTER, NULL}, |
458 | {HINIC_PORT_CMD_CHANGE_MTU, hinic_mbox_check_func_id_8B}, |
459 | {HINIC_PORT_CMD_ADD_VLAN, hinic_mbox_check_func_id_8B}, |
460 | {HINIC_PORT_CMD_DEL_VLAN, hinic_mbox_check_func_id_8B}, |
461 | {HINIC_PORT_CMD_SET_MAC, hinic_mbox_check_func_id_8B}, |
462 | {HINIC_PORT_CMD_GET_MAC, hinic_mbox_check_func_id_8B}, |
463 | {HINIC_PORT_CMD_DEL_MAC, hinic_mbox_check_func_id_8B}, |
464 | {HINIC_PORT_CMD_SET_RX_MODE, hinic_mbox_check_func_id_8B}, |
465 | {HINIC_PORT_CMD_GET_PAUSE_INFO, hinic_mbox_check_func_id_8B}, |
466 | {HINIC_PORT_CMD_GET_LINK_STATE, hinic_mbox_check_func_id_8B}, |
467 | {HINIC_PORT_CMD_SET_LRO, hinic_mbox_check_func_id_8B}, |
468 | {HINIC_PORT_CMD_SET_RX_CSUM, hinic_mbox_check_func_id_8B}, |
469 | {HINIC_PORT_CMD_SET_RX_VLAN_OFFLOAD, hinic_mbox_check_func_id_8B}, |
470 | {HINIC_PORT_CMD_GET_VPORT_STAT, hinic_mbox_check_func_id_8B}, |
471 | {HINIC_PORT_CMD_CLEAN_VPORT_STAT, hinic_mbox_check_func_id_8B}, |
472 | {HINIC_PORT_CMD_GET_RSS_TEMPLATE_INDIR_TBL, |
473 | hinic_mbox_check_func_id_8B}, |
474 | {HINIC_PORT_CMD_SET_RSS_TEMPLATE_TBL, hinic_mbox_check_func_id_8B}, |
475 | {HINIC_PORT_CMD_GET_RSS_TEMPLATE_TBL, hinic_mbox_check_func_id_8B}, |
476 | {HINIC_PORT_CMD_SET_RSS_HASH_ENGINE, hinic_mbox_check_func_id_8B}, |
477 | {HINIC_PORT_CMD_GET_RSS_HASH_ENGINE, hinic_mbox_check_func_id_8B}, |
478 | {HINIC_PORT_CMD_GET_RSS_CTX_TBL, hinic_mbox_check_func_id_8B}, |
479 | {HINIC_PORT_CMD_SET_RSS_CTX_TBL, hinic_mbox_check_func_id_8B}, |
480 | {HINIC_PORT_CMD_RSS_TEMP_MGR, hinic_mbox_check_func_id_8B}, |
481 | {HINIC_PORT_CMD_RSS_CFG, hinic_mbox_check_func_id_8B}, |
482 | {HINIC_PORT_CMD_FWCTXT_INIT, check_func_table}, |
483 | {HINIC_PORT_CMD_GET_MGMT_VERSION, NULL}, |
484 | {HINIC_PORT_CMD_SET_FUNC_STATE, hinic_mbox_check_func_id_8B}, |
485 | {HINIC_PORT_CMD_GET_GLOBAL_QPN, hinic_mbox_check_func_id_8B}, |
486 | {HINIC_PORT_CMD_SET_TSO, hinic_mbox_check_func_id_8B}, |
487 | {HINIC_PORT_CMD_SET_RQ_IQ_MAP, hinic_mbox_check_func_id_8B}, |
488 | {HINIC_PORT_CMD_LINK_STATUS_REPORT, hinic_mbox_check_func_id_8B}, |
489 | {HINIC_PORT_CMD_UPDATE_MAC, hinic_mbox_check_func_id_8B}, |
490 | {HINIC_PORT_CMD_GET_CAP, hinic_mbox_check_func_id_8B}, |
491 | {HINIC_PORT_CMD_GET_LINK_MODE, hinic_mbox_check_func_id_8B}, |
492 | {HINIC_PORT_CMD_GET_VF_COS, NULL}, |
493 | {HINIC_PORT_CMD_SET_VHD_CFG, hinic_mbox_check_func_id_8B}, |
494 | {HINIC_PORT_CMD_SET_VLAN_FILTER, hinic_mbox_check_func_id_8B}, |
495 | {HINIC_PORT_CMD_Q_FILTER, hinic_mbox_check_func_id_8B}, |
496 | {HINIC_PORT_CMD_TCAM_FILTER, NULL}, |
497 | {HINIC_PORT_CMD_UP_TC_ADD_FLOW, NULL}, |
498 | {HINIC_PORT_CMD_UP_TC_DEL_FLOW, NULL}, |
499 | {HINIC_PORT_CMD_UP_TC_FLUSH_TCAM, hinic_mbox_check_func_id_8B}, |
500 | {HINIC_PORT_CMD_UP_TC_CTRL_TCAM_BLOCK, hinic_mbox_check_func_id_8B}, |
501 | {HINIC_PORT_CMD_UP_TC_ENABLE, hinic_mbox_check_func_id_8B}, |
502 | {HINIC_PORT_CMD_CABLE_PLUG_EVENT, NULL}, |
503 | {HINIC_PORT_CMD_LINK_ERR_EVENT, NULL}, |
504 | {HINIC_PORT_CMD_SET_PORT_STATE, hinic_mbox_check_func_id_8B}, |
505 | {HINIC_PORT_CMD_SET_ETS, NULL}, |
506 | {HINIC_PORT_CMD_SET_ANTI_ATTACK_RATE, NULL}, |
507 | {HINIC_PORT_CMD_RESET_LINK_CFG, hinic_mbox_check_func_id_8B}, |
508 | {HINIC_PORT_CMD_SET_LINK_FOLLOW, NULL}, |
509 | {HINIC_PORT_CMD_CLEAR_QP_RES, NULL}, |
510 | }; |
511 | |
512 | #define CHECK_IPSU_15BIT 0X8000 |
513 | |
514 | static |
515 | struct hinic_sriov_info *hinic_get_sriov_info_by_pcidev(struct pci_dev *pdev) |
516 | { |
517 | struct net_device *netdev = pci_get_drvdata(pdev); |
518 | struct hinic_dev *nic_dev = netdev_priv(dev: netdev); |
519 | |
520 | return &nic_dev->sriov_info; |
521 | } |
522 | |
523 | static int hinic_check_mac_info(u8 status, u16 vlan_id) |
524 | { |
525 | if ((status && status != HINIC_MGMT_STATUS_EXIST) || |
526 | (vlan_id & CHECK_IPSU_15BIT && |
527 | status == HINIC_MGMT_STATUS_EXIST)) |
528 | return -EINVAL; |
529 | |
530 | return 0; |
531 | } |
532 | |
533 | #define HINIC_VLAN_ID_MASK 0x7FFF |
534 | |
535 | static int hinic_update_mac(struct hinic_hwdev *hwdev, u8 *old_mac, |
536 | u8 *new_mac, u16 vlan_id, u16 func_id) |
537 | { |
538 | struct hinic_port_mac_update mac_info = {0}; |
539 | u16 out_size = sizeof(mac_info); |
540 | int err; |
541 | |
542 | if (!hwdev || !old_mac || !new_mac) |
543 | return -EINVAL; |
544 | |
545 | if ((vlan_id & HINIC_VLAN_ID_MASK) >= VLAN_N_VID) { |
546 | dev_err(&hwdev->hwif->pdev->dev, "Invalid VLAN number: %d\n" , |
547 | (vlan_id & HINIC_VLAN_ID_MASK)); |
548 | return -EINVAL; |
549 | } |
550 | |
551 | mac_info.func_id = func_id; |
552 | mac_info.vlan_id = vlan_id; |
553 | memcpy(mac_info.old_mac, old_mac, ETH_ALEN); |
554 | memcpy(mac_info.new_mac, new_mac, ETH_ALEN); |
555 | |
556 | err = hinic_port_msg_cmd(hwdev, cmd: HINIC_PORT_CMD_UPDATE_MAC, buf_in: &mac_info, |
557 | in_size: sizeof(mac_info), buf_out: &mac_info, out_size: &out_size); |
558 | |
559 | if (err || !out_size || |
560 | hinic_check_mac_info(status: mac_info.status, vlan_id: mac_info.vlan_id)) { |
561 | dev_err(&hwdev->hwif->pdev->dev, |
562 | "Failed to update MAC, err: %d, status: 0x%x, out size: 0x%x\n" , |
563 | err, mac_info.status, out_size); |
564 | return -EINVAL; |
565 | } |
566 | |
567 | if (mac_info.status == HINIC_MGMT_STATUS_EXIST) |
568 | dev_warn(&hwdev->hwif->pdev->dev, "MAC is repeated. Ignore update operation\n" ); |
569 | |
570 | return 0; |
571 | } |
572 | |
573 | static void hinic_get_vf_config(struct hinic_hwdev *hwdev, u16 vf_id, |
574 | struct ifla_vf_info *ivi) |
575 | { |
576 | struct vf_data_storage *vfinfo; |
577 | |
578 | vfinfo = hwdev->func_to_io.vf_infos + HW_VF_ID_TO_OS(vf_id); |
579 | |
580 | ivi->vf = HW_VF_ID_TO_OS(vf_id); |
581 | memcpy(ivi->mac, vfinfo->vf_mac_addr, ETH_ALEN); |
582 | ivi->vlan = vfinfo->pf_vlan; |
583 | ivi->qos = vfinfo->pf_qos; |
584 | ivi->spoofchk = vfinfo->spoofchk; |
585 | ivi->trusted = vfinfo->trust; |
586 | ivi->max_tx_rate = vfinfo->max_rate; |
587 | ivi->min_tx_rate = vfinfo->min_rate; |
588 | |
589 | if (!vfinfo->link_forced) |
590 | ivi->linkstate = IFLA_VF_LINK_STATE_AUTO; |
591 | else if (vfinfo->link_up) |
592 | ivi->linkstate = IFLA_VF_LINK_STATE_ENABLE; |
593 | else |
594 | ivi->linkstate = IFLA_VF_LINK_STATE_DISABLE; |
595 | } |
596 | |
597 | int hinic_ndo_get_vf_config(struct net_device *netdev, |
598 | int vf, struct ifla_vf_info *ivi) |
599 | { |
600 | struct hinic_dev *nic_dev = netdev_priv(dev: netdev); |
601 | struct hinic_sriov_info *sriov_info; |
602 | |
603 | sriov_info = &nic_dev->sriov_info; |
604 | if (vf >= sriov_info->num_vfs) |
605 | return -EINVAL; |
606 | |
607 | hinic_get_vf_config(hwdev: sriov_info->hwdev, OS_VF_ID_TO_HW(vf), ivi); |
608 | |
609 | return 0; |
610 | } |
611 | |
612 | static int hinic_set_vf_mac(struct hinic_hwdev *hwdev, int vf, |
613 | unsigned char *mac_addr) |
614 | { |
615 | struct hinic_func_to_io *nic_io = &hwdev->func_to_io; |
616 | struct vf_data_storage *vf_info; |
617 | u16 func_id; |
618 | int err; |
619 | |
620 | vf_info = nic_io->vf_infos + HW_VF_ID_TO_OS(vf); |
621 | |
622 | /* duplicate request, so just return success */ |
623 | if (vf_info->pf_set_mac && |
624 | !memcmp(p: vf_info->vf_mac_addr, q: mac_addr, ETH_ALEN)) |
625 | return 0; |
626 | |
627 | vf_info->pf_set_mac = true; |
628 | |
629 | func_id = hinic_glb_pf_vf_offset(hwif: hwdev->hwif) + vf; |
630 | err = hinic_update_mac(hwdev, old_mac: vf_info->vf_mac_addr, |
631 | new_mac: mac_addr, vlan_id: 0, func_id); |
632 | if (err) { |
633 | vf_info->pf_set_mac = false; |
634 | return err; |
635 | } |
636 | |
637 | memcpy(vf_info->vf_mac_addr, mac_addr, ETH_ALEN); |
638 | |
639 | return 0; |
640 | } |
641 | |
642 | int hinic_ndo_set_vf_mac(struct net_device *netdev, int vf, u8 *mac) |
643 | { |
644 | struct hinic_dev *nic_dev = netdev_priv(dev: netdev); |
645 | struct hinic_sriov_info *sriov_info; |
646 | int err; |
647 | |
648 | sriov_info = &nic_dev->sriov_info; |
649 | if (!is_valid_ether_addr(addr: mac) || vf >= sriov_info->num_vfs) |
650 | return -EINVAL; |
651 | |
652 | err = hinic_set_vf_mac(hwdev: sriov_info->hwdev, OS_VF_ID_TO_HW(vf), mac_addr: mac); |
653 | if (err) |
654 | return err; |
655 | |
656 | netif_info(nic_dev, drv, netdev, "Setting MAC %pM on VF %d\n" , mac, vf); |
657 | netif_info(nic_dev, drv, netdev, "Reload the VF driver to make this change effective." ); |
658 | |
659 | return 0; |
660 | } |
661 | |
662 | static int hinic_add_vf_vlan(struct hinic_hwdev *hwdev, int vf_id, |
663 | u16 vlan, u8 qos) |
664 | { |
665 | struct hinic_func_to_io *nic_io = &hwdev->func_to_io; |
666 | int err; |
667 | |
668 | err = hinic_set_vf_vlan(hwdev, add: true, vid: vlan, qos, vf_id); |
669 | if (err) |
670 | return err; |
671 | |
672 | nic_io->vf_infos[HW_VF_ID_TO_OS(vf_id)].pf_vlan = vlan; |
673 | nic_io->vf_infos[HW_VF_ID_TO_OS(vf_id)].pf_qos = qos; |
674 | |
675 | dev_info(&hwdev->hwif->pdev->dev, "Setting VLAN %d, QOS 0x%x on VF %d\n" , |
676 | vlan, qos, HW_VF_ID_TO_OS(vf_id)); |
677 | return 0; |
678 | } |
679 | |
680 | static int hinic_kill_vf_vlan(struct hinic_hwdev *hwdev, int vf_id) |
681 | { |
682 | struct hinic_func_to_io *nic_io = &hwdev->func_to_io; |
683 | int err; |
684 | |
685 | err = hinic_set_vf_vlan(hwdev, add: false, |
686 | vid: nic_io->vf_infos[HW_VF_ID_TO_OS(vf_id)].pf_vlan, |
687 | qos: nic_io->vf_infos[HW_VF_ID_TO_OS(vf_id)].pf_qos, |
688 | vf_id); |
689 | if (err) |
690 | return err; |
691 | |
692 | dev_info(&hwdev->hwif->pdev->dev, "Remove VLAN %d on VF %d\n" , |
693 | nic_io->vf_infos[HW_VF_ID_TO_OS(vf_id)].pf_vlan, |
694 | HW_VF_ID_TO_OS(vf_id)); |
695 | |
696 | nic_io->vf_infos[HW_VF_ID_TO_OS(vf_id)].pf_vlan = 0; |
697 | nic_io->vf_infos[HW_VF_ID_TO_OS(vf_id)].pf_qos = 0; |
698 | |
699 | return 0; |
700 | } |
701 | |
702 | static int hinic_update_mac_vlan(struct hinic_dev *nic_dev, u16 old_vlan, |
703 | u16 new_vlan, int vf_id) |
704 | { |
705 | struct vf_data_storage *vf_info; |
706 | u16 vlan_id; |
707 | int err; |
708 | |
709 | if (!nic_dev || old_vlan >= VLAN_N_VID || new_vlan >= VLAN_N_VID) |
710 | return -EINVAL; |
711 | |
712 | vf_info = nic_dev->hwdev->func_to_io.vf_infos + HW_VF_ID_TO_OS(vf_id); |
713 | if (!vf_info->pf_set_mac) |
714 | return 0; |
715 | |
716 | vlan_id = old_vlan; |
717 | if (vlan_id) |
718 | vlan_id |= HINIC_ADD_VLAN_IN_MAC; |
719 | |
720 | err = hinic_port_del_mac(nic_dev, addr: vf_info->vf_mac_addr, vlan_id); |
721 | if (err) { |
722 | dev_err(&nic_dev->hwdev->hwif->pdev->dev, "Failed to delete VF %d MAC %pM vlan %d\n" , |
723 | HW_VF_ID_TO_OS(vf_id), vf_info->vf_mac_addr, old_vlan); |
724 | return err; |
725 | } |
726 | |
727 | vlan_id = new_vlan; |
728 | if (vlan_id) |
729 | vlan_id |= HINIC_ADD_VLAN_IN_MAC; |
730 | |
731 | err = hinic_port_add_mac(nic_dev, addr: vf_info->vf_mac_addr, vlan_id); |
732 | if (err) { |
733 | dev_err(&nic_dev->hwdev->hwif->pdev->dev, "Failed to add VF %d MAC %pM vlan %d\n" , |
734 | HW_VF_ID_TO_OS(vf_id), vf_info->vf_mac_addr, new_vlan); |
735 | goto out; |
736 | } |
737 | |
738 | return 0; |
739 | |
740 | out: |
741 | vlan_id = old_vlan; |
742 | if (vlan_id) |
743 | vlan_id |= HINIC_ADD_VLAN_IN_MAC; |
744 | hinic_port_add_mac(nic_dev, addr: vf_info->vf_mac_addr, vlan_id); |
745 | |
746 | return err; |
747 | } |
748 | |
749 | static int set_hw_vf_vlan(struct hinic_dev *nic_dev, |
750 | u16 cur_vlanprio, int vf, u16 vlan, u8 qos) |
751 | { |
752 | u16 old_vlan = cur_vlanprio & VLAN_VID_MASK; |
753 | int err = 0; |
754 | |
755 | if (vlan || qos) { |
756 | if (cur_vlanprio) { |
757 | err = hinic_kill_vf_vlan(hwdev: nic_dev->hwdev, |
758 | OS_VF_ID_TO_HW(vf)); |
759 | if (err) { |
760 | dev_err(&nic_dev->sriov_info.pdev->dev, "Failed to delete vf %d old vlan %d\n" , |
761 | vf, old_vlan); |
762 | goto out; |
763 | } |
764 | } |
765 | err = hinic_add_vf_vlan(hwdev: nic_dev->hwdev, |
766 | OS_VF_ID_TO_HW(vf), vlan, qos); |
767 | if (err) { |
768 | dev_err(&nic_dev->sriov_info.pdev->dev, "Failed to add vf %d new vlan %d\n" , |
769 | vf, vlan); |
770 | goto out; |
771 | } |
772 | } else { |
773 | err = hinic_kill_vf_vlan(hwdev: nic_dev->hwdev, OS_VF_ID_TO_HW(vf)); |
774 | if (err) { |
775 | dev_err(&nic_dev->sriov_info.pdev->dev, "Failed to delete vf %d vlan %d\n" , |
776 | vf, old_vlan); |
777 | goto out; |
778 | } |
779 | } |
780 | |
781 | err = hinic_update_mac_vlan(nic_dev, old_vlan, new_vlan: vlan, |
782 | OS_VF_ID_TO_HW(vf)); |
783 | |
784 | out: |
785 | return err; |
786 | } |
787 | |
788 | int hinic_ndo_set_vf_vlan(struct net_device *netdev, int vf, u16 vlan, u8 qos, |
789 | __be16 vlan_proto) |
790 | { |
791 | struct hinic_dev *nic_dev = netdev_priv(dev: netdev); |
792 | struct hinic_sriov_info *sriov_info; |
793 | u16 vlanprio, cur_vlanprio; |
794 | |
795 | sriov_info = &nic_dev->sriov_info; |
796 | if (vf >= sriov_info->num_vfs || vlan >= VLAN_N_VID || qos > HINIC_MAX_QOS) |
797 | return -EINVAL; |
798 | if (vlan_proto != htons(ETH_P_8021Q)) |
799 | return -EPROTONOSUPPORT; |
800 | vlanprio = vlan | qos << HINIC_VLAN_PRIORITY_SHIFT; |
801 | cur_vlanprio = hinic_vf_info_vlanprio(hwdev: nic_dev->hwdev, |
802 | OS_VF_ID_TO_HW(vf)); |
803 | /* duplicate request, so just return success */ |
804 | if (vlanprio == cur_vlanprio) |
805 | return 0; |
806 | |
807 | return set_hw_vf_vlan(nic_dev, cur_vlanprio, vf, vlan, qos); |
808 | } |
809 | |
810 | static int hinic_set_vf_trust(struct hinic_hwdev *hwdev, u16 vf_id, |
811 | bool trust) |
812 | { |
813 | struct vf_data_storage *vf_infos; |
814 | struct hinic_func_to_io *nic_io; |
815 | |
816 | if (!hwdev) |
817 | return -EINVAL; |
818 | |
819 | nic_io = &hwdev->func_to_io; |
820 | vf_infos = nic_io->vf_infos; |
821 | vf_infos[vf_id].trust = trust; |
822 | |
823 | return 0; |
824 | } |
825 | |
826 | int hinic_ndo_set_vf_trust(struct net_device *netdev, int vf, bool setting) |
827 | { |
828 | struct hinic_dev *adapter = netdev_priv(dev: netdev); |
829 | struct hinic_sriov_info *sriov_info; |
830 | struct hinic_func_to_io *nic_io; |
831 | bool cur_trust; |
832 | int err; |
833 | |
834 | sriov_info = &adapter->sriov_info; |
835 | nic_io = &adapter->hwdev->func_to_io; |
836 | |
837 | if (vf >= sriov_info->num_vfs) |
838 | return -EINVAL; |
839 | |
840 | cur_trust = nic_io->vf_infos[vf].trust; |
841 | /* same request, so just return success */ |
842 | if (setting == cur_trust) |
843 | return 0; |
844 | |
845 | err = hinic_set_vf_trust(hwdev: adapter->hwdev, vf_id: vf, trust: setting); |
846 | if (!err) |
847 | dev_info(&sriov_info->pdev->dev, "Set VF %d trusted %s succeed\n" , |
848 | vf, setting ? "on" : "off" ); |
849 | else |
850 | dev_err(&sriov_info->pdev->dev, "Failed set VF %d trusted %s\n" , |
851 | vf, setting ? "on" : "off" ); |
852 | |
853 | return err; |
854 | } |
855 | |
856 | int hinic_ndo_set_vf_bw(struct net_device *netdev, |
857 | int vf, int min_tx_rate, int max_tx_rate) |
858 | { |
859 | static const u32 speeds[] = { |
860 | SPEED_10, SPEED_100, SPEED_1000, SPEED_10000, |
861 | SPEED_25000, SPEED_40000, SPEED_100000 |
862 | }; |
863 | struct hinic_dev *nic_dev = netdev_priv(dev: netdev); |
864 | struct hinic_port_cap port_cap = { 0 }; |
865 | enum hinic_port_link_state link_state; |
866 | int err; |
867 | |
868 | if (vf >= nic_dev->sriov_info.num_vfs) { |
869 | netif_err(nic_dev, drv, netdev, "VF number must be less than %d\n" , |
870 | nic_dev->sriov_info.num_vfs); |
871 | return -EINVAL; |
872 | } |
873 | |
874 | err = hinic_port_link_state(nic_dev, link_state: &link_state); |
875 | if (err) { |
876 | netif_err(nic_dev, drv, netdev, |
877 | "Get link status failed when setting vf tx rate\n" ); |
878 | return -EIO; |
879 | } |
880 | |
881 | if (link_state == HINIC_LINK_STATE_DOWN) { |
882 | netif_err(nic_dev, drv, netdev, |
883 | "Link status must be up when setting vf tx rate\n" ); |
884 | return -EPERM; |
885 | } |
886 | |
887 | err = hinic_port_get_cap(nic_dev, port_cap: &port_cap); |
888 | if (err || port_cap.speed > LINK_SPEED_100GB) |
889 | return -EIO; |
890 | |
891 | /* rate limit cannot be less than 0 and greater than link speed */ |
892 | if (max_tx_rate < 0 || max_tx_rate > speeds[port_cap.speed]) { |
893 | netif_err(nic_dev, drv, netdev, "Max tx rate must be in [0 - %d]\n" , |
894 | speeds[port_cap.speed]); |
895 | return -EINVAL; |
896 | } |
897 | |
898 | err = hinic_set_vf_tx_rate(hwdev: nic_dev->hwdev, OS_VF_ID_TO_HW(vf), |
899 | max_rate: max_tx_rate, min_rate: min_tx_rate); |
900 | if (err) { |
901 | netif_err(nic_dev, drv, netdev, |
902 | "Unable to set VF %d max rate %d min rate %d%s\n" , |
903 | vf, max_tx_rate, min_tx_rate, |
904 | err == HINIC_TX_RATE_TABLE_FULL ? |
905 | ", tx rate profile is full" : "" ); |
906 | return -EIO; |
907 | } |
908 | |
909 | netif_info(nic_dev, drv, netdev, |
910 | "Set VF %d max tx rate %d min tx rate %d successfully\n" , |
911 | vf, max_tx_rate, min_tx_rate); |
912 | |
913 | return 0; |
914 | } |
915 | |
916 | static int hinic_set_vf_spoofchk(struct hinic_hwdev *hwdev, u16 vf_id, |
917 | bool spoofchk) |
918 | { |
919 | struct hinic_spoofchk_set spoofchk_cfg = {0}; |
920 | struct vf_data_storage *vf_infos = NULL; |
921 | u16 out_size = sizeof(spoofchk_cfg); |
922 | int err; |
923 | |
924 | if (!hwdev) |
925 | return -EINVAL; |
926 | |
927 | vf_infos = hwdev->func_to_io.vf_infos; |
928 | |
929 | spoofchk_cfg.func_id = hinic_glb_pf_vf_offset(hwif: hwdev->hwif) + vf_id; |
930 | spoofchk_cfg.state = spoofchk ? 1 : 0; |
931 | err = hinic_port_msg_cmd(hwdev, cmd: HINIC_PORT_CMD_ENABLE_SPOOFCHK, |
932 | buf_in: &spoofchk_cfg, in_size: sizeof(spoofchk_cfg), |
933 | buf_out: &spoofchk_cfg, out_size: &out_size); |
934 | if (spoofchk_cfg.status == HINIC_MGMT_CMD_UNSUPPORTED) { |
935 | err = HINIC_MGMT_CMD_UNSUPPORTED; |
936 | } else if (err || !out_size || spoofchk_cfg.status) { |
937 | dev_err(&hwdev->hwif->pdev->dev, "Failed to set VF(%d) spoofchk, err: %d, status: 0x%x, out size: 0x%x\n" , |
938 | HW_VF_ID_TO_OS(vf_id), err, spoofchk_cfg.status, |
939 | out_size); |
940 | err = -EIO; |
941 | } |
942 | |
943 | vf_infos[HW_VF_ID_TO_OS(vf_id)].spoofchk = spoofchk; |
944 | |
945 | return err; |
946 | } |
947 | |
948 | int hinic_ndo_set_vf_spoofchk(struct net_device *netdev, int vf, bool setting) |
949 | { |
950 | struct hinic_dev *nic_dev = netdev_priv(dev: netdev); |
951 | struct hinic_sriov_info *sriov_info; |
952 | bool cur_spoofchk; |
953 | int err; |
954 | |
955 | sriov_info = &nic_dev->sriov_info; |
956 | if (vf >= sriov_info->num_vfs) |
957 | return -EINVAL; |
958 | |
959 | cur_spoofchk = nic_dev->hwdev->func_to_io.vf_infos[vf].spoofchk; |
960 | |
961 | /* same request, so just return success */ |
962 | if (setting == cur_spoofchk) |
963 | return 0; |
964 | |
965 | err = hinic_set_vf_spoofchk(hwdev: sriov_info->hwdev, |
966 | OS_VF_ID_TO_HW(vf), spoofchk: setting); |
967 | if (!err) { |
968 | netif_info(nic_dev, drv, netdev, "Set VF %d spoofchk %s successfully\n" , |
969 | vf, setting ? "on" : "off" ); |
970 | } else if (err == HINIC_MGMT_CMD_UNSUPPORTED) { |
971 | netif_err(nic_dev, drv, netdev, |
972 | "Current firmware doesn't support to set vf spoofchk, need to upgrade latest firmware version\n" ); |
973 | err = -EOPNOTSUPP; |
974 | } |
975 | |
976 | return err; |
977 | } |
978 | |
979 | static int hinic_set_vf_link_state(struct hinic_hwdev *hwdev, u16 vf_id, |
980 | int link) |
981 | { |
982 | struct hinic_func_to_io *nic_io = &hwdev->func_to_io; |
983 | struct vf_data_storage *vf_infos = nic_io->vf_infos; |
984 | u8 link_status = 0; |
985 | |
986 | switch (link) { |
987 | case HINIC_IFLA_VF_LINK_STATE_AUTO: |
988 | vf_infos[HW_VF_ID_TO_OS(vf_id)].link_forced = false; |
989 | vf_infos[HW_VF_ID_TO_OS(vf_id)].link_up = nic_io->link_status ? |
990 | true : false; |
991 | link_status = nic_io->link_status; |
992 | break; |
993 | case HINIC_IFLA_VF_LINK_STATE_ENABLE: |
994 | vf_infos[HW_VF_ID_TO_OS(vf_id)].link_forced = true; |
995 | vf_infos[HW_VF_ID_TO_OS(vf_id)].link_up = true; |
996 | link_status = HINIC_LINK_UP; |
997 | break; |
998 | case HINIC_IFLA_VF_LINK_STATE_DISABLE: |
999 | vf_infos[HW_VF_ID_TO_OS(vf_id)].link_forced = true; |
1000 | vf_infos[HW_VF_ID_TO_OS(vf_id)].link_up = false; |
1001 | link_status = HINIC_LINK_DOWN; |
1002 | break; |
1003 | default: |
1004 | return -EINVAL; |
1005 | } |
1006 | |
1007 | /* Notify the VF of its new link state */ |
1008 | hinic_notify_vf_link_status(hwdev, vf_id, link_status); |
1009 | |
1010 | return 0; |
1011 | } |
1012 | |
1013 | int hinic_ndo_set_vf_link_state(struct net_device *netdev, int vf_id, int link) |
1014 | { |
1015 | struct hinic_dev *nic_dev = netdev_priv(dev: netdev); |
1016 | struct hinic_sriov_info *sriov_info; |
1017 | |
1018 | sriov_info = &nic_dev->sriov_info; |
1019 | |
1020 | if (vf_id >= sriov_info->num_vfs) { |
1021 | netif_err(nic_dev, drv, netdev, |
1022 | "Invalid VF Identifier %d\n" , vf_id); |
1023 | return -EINVAL; |
1024 | } |
1025 | |
1026 | return hinic_set_vf_link_state(hwdev: sriov_info->hwdev, |
1027 | OS_VF_ID_TO_HW(vf_id), link); |
1028 | } |
1029 | |
1030 | /* pf receive message from vf */ |
1031 | static int nic_pf_mbox_handler(void *hwdev, u16 vf_id, u8 cmd, void *buf_in, |
1032 | u16 in_size, void *buf_out, u16 *out_size) |
1033 | { |
1034 | u8 size = ARRAY_SIZE(nic_cmd_support_vf); |
1035 | struct vf_cmd_msg_handle *vf_msg_handle; |
1036 | struct hinic_hwdev *dev = hwdev; |
1037 | struct hinic_func_to_io *nic_io; |
1038 | struct hinic_pfhwdev *pfhwdev; |
1039 | int err = 0; |
1040 | u32 i; |
1041 | |
1042 | if (!hwdev) |
1043 | return -EINVAL; |
1044 | |
1045 | if (!hinic_mbox_check_cmd_valid(hwdev, cmd_handle: nic_cmd_support_vf, vf_id, cmd, |
1046 | buf_in, in_size, size)) { |
1047 | dev_err(&dev->hwif->pdev->dev, |
1048 | "PF Receive VF nic cmd: 0x%x, mbox len: 0x%x is invalid\n" , |
1049 | cmd, in_size); |
1050 | return HINIC_MBOX_VF_CMD_ERROR; |
1051 | } |
1052 | |
1053 | pfhwdev = container_of(dev, struct hinic_pfhwdev, hwdev); |
1054 | nic_io = &dev->func_to_io; |
1055 | for (i = 0; i < ARRAY_SIZE(nic_vf_cmd_msg_handler); i++) { |
1056 | vf_msg_handle = &nic_vf_cmd_msg_handler[i]; |
1057 | if (cmd == vf_msg_handle->cmd && |
1058 | vf_msg_handle->cmd_msg_handler) { |
1059 | err = vf_msg_handle->cmd_msg_handler(hwdev, vf_id, |
1060 | buf_in, in_size, |
1061 | buf_out, |
1062 | out_size); |
1063 | break; |
1064 | } |
1065 | } |
1066 | if (i == ARRAY_SIZE(nic_vf_cmd_msg_handler)) |
1067 | err = hinic_msg_to_mgmt(pf_to_mgmt: &pfhwdev->pf_to_mgmt, mod: HINIC_MOD_L2NIC, |
1068 | cmd, buf_in, in_size, buf_out, |
1069 | out_size, sync: HINIC_MGMT_MSG_SYNC); |
1070 | |
1071 | if (err && err != HINIC_MBOX_PF_BUSY_ACTIVE_FW) |
1072 | dev_err(&nic_io->hwif->pdev->dev, "PF receive VF L2NIC cmd: %d process error, err:%d\n" , |
1073 | cmd, err); |
1074 | return err; |
1075 | } |
1076 | |
1077 | static int cfg_mbx_pf_proc_vf_msg(void *hwdev, u16 vf_id, u8 cmd, void *buf_in, |
1078 | u16 in_size, void *buf_out, u16 *out_size) |
1079 | { |
1080 | struct hinic_dev_cap *dev_cap = buf_out; |
1081 | struct hinic_hwdev *dev = hwdev; |
1082 | struct hinic_cap *cap; |
1083 | |
1084 | cap = &dev->nic_cap; |
1085 | memset(dev_cap, 0, sizeof(*dev_cap)); |
1086 | |
1087 | dev_cap->max_vf = cap->max_vf; |
1088 | dev_cap->max_sqs = cap->max_vf_qps; |
1089 | dev_cap->max_rqs = cap->max_vf_qps; |
1090 | dev_cap->port_id = dev->port_id; |
1091 | |
1092 | *out_size = sizeof(*dev_cap); |
1093 | |
1094 | return 0; |
1095 | } |
1096 | |
1097 | static int hinic_init_vf_infos(struct hinic_func_to_io *nic_io, u16 vf_id) |
1098 | { |
1099 | struct vf_data_storage *vf_infos = nic_io->vf_infos; |
1100 | |
1101 | if (set_vf_link_state > HINIC_IFLA_VF_LINK_STATE_DISABLE) { |
1102 | dev_warn(&nic_io->hwif->pdev->dev, "Module Parameter set_vf_link_state value %d is out of range, resetting to %d\n" , |
1103 | set_vf_link_state, HINIC_IFLA_VF_LINK_STATE_AUTO); |
1104 | set_vf_link_state = HINIC_IFLA_VF_LINK_STATE_AUTO; |
1105 | } |
1106 | |
1107 | switch (set_vf_link_state) { |
1108 | case HINIC_IFLA_VF_LINK_STATE_AUTO: |
1109 | vf_infos[vf_id].link_forced = false; |
1110 | break; |
1111 | case HINIC_IFLA_VF_LINK_STATE_ENABLE: |
1112 | vf_infos[vf_id].link_forced = true; |
1113 | vf_infos[vf_id].link_up = true; |
1114 | break; |
1115 | case HINIC_IFLA_VF_LINK_STATE_DISABLE: |
1116 | vf_infos[vf_id].link_forced = true; |
1117 | vf_infos[vf_id].link_up = false; |
1118 | break; |
1119 | default: |
1120 | dev_err(&nic_io->hwif->pdev->dev, "Invalid input parameter set_vf_link_state: %d\n" , |
1121 | set_vf_link_state); |
1122 | return -EINVAL; |
1123 | } |
1124 | |
1125 | return 0; |
1126 | } |
1127 | |
1128 | static void hinic_clear_vf_infos(struct hinic_dev *nic_dev, u16 vf_id) |
1129 | { |
1130 | struct vf_data_storage *vf_infos; |
1131 | |
1132 | vf_infos = nic_dev->hwdev->func_to_io.vf_infos + HW_VF_ID_TO_OS(vf_id); |
1133 | if (vf_infos->pf_set_mac) |
1134 | hinic_port_del_mac(nic_dev, addr: vf_infos->vf_mac_addr, vlan_id: 0); |
1135 | |
1136 | if (hinic_vf_info_vlanprio(hwdev: nic_dev->hwdev, vf_id)) |
1137 | hinic_kill_vf_vlan(hwdev: nic_dev->hwdev, vf_id); |
1138 | |
1139 | if (vf_infos->max_rate) |
1140 | hinic_set_vf_tx_rate(hwdev: nic_dev->hwdev, vf_id, max_rate: 0, min_rate: 0); |
1141 | |
1142 | if (vf_infos->spoofchk) |
1143 | hinic_set_vf_spoofchk(hwdev: nic_dev->hwdev, vf_id, spoofchk: false); |
1144 | |
1145 | if (vf_infos->trust) |
1146 | hinic_set_vf_trust(hwdev: nic_dev->hwdev, vf_id, trust: false); |
1147 | |
1148 | memset(vf_infos, 0, sizeof(*vf_infos)); |
1149 | /* set vf_infos to default */ |
1150 | hinic_init_vf_infos(nic_io: &nic_dev->hwdev->func_to_io, HW_VF_ID_TO_OS(vf_id)); |
1151 | } |
1152 | |
1153 | static void hinic_deinit_vf_hw(struct hinic_sriov_info *sriov_info, |
1154 | u16 start_vf_id, u16 end_vf_id) |
1155 | { |
1156 | struct hinic_dev *nic_dev; |
1157 | u16 func_idx, idx; |
1158 | |
1159 | nic_dev = container_of(sriov_info, struct hinic_dev, sriov_info); |
1160 | |
1161 | for (idx = start_vf_id; idx <= end_vf_id; idx++) { |
1162 | func_idx = hinic_glb_pf_vf_offset(hwif: nic_dev->hwdev->hwif) + idx; |
1163 | hinic_set_wq_page_size(hwdev: nic_dev->hwdev, func_idx, |
1164 | HINIC_HW_WQ_PAGE_SIZE); |
1165 | hinic_clear_vf_infos(nic_dev, vf_id: idx); |
1166 | } |
1167 | } |
1168 | |
1169 | int hinic_vf_func_init(struct hinic_hwdev *hwdev) |
1170 | { |
1171 | struct hinic_register_vf register_info = {0}; |
1172 | u16 out_size = sizeof(register_info); |
1173 | struct hinic_func_to_io *nic_io; |
1174 | int err = 0; |
1175 | u32 size, i; |
1176 | |
1177 | err = hinic_vf_mbox_random_id_init(hwdev); |
1178 | if (err) { |
1179 | dev_err(&hwdev->hwif->pdev->dev, "Failed to init vf mbox random id, err: %d\n" , |
1180 | err); |
1181 | return err; |
1182 | } |
1183 | |
1184 | nic_io = &hwdev->func_to_io; |
1185 | |
1186 | if (HINIC_IS_VF(hwdev->hwif)) { |
1187 | err = hinic_mbox_to_pf(hwdev, mod: HINIC_MOD_L2NIC, |
1188 | cmd: HINIC_PORT_CMD_VF_REGISTER, |
1189 | buf_in: ®ister_info, in_size: sizeof(register_info), |
1190 | buf_out: ®ister_info, out_size: &out_size, timeout: 0); |
1191 | if (err || register_info.status || !out_size) { |
1192 | dev_err(&hwdev->hwif->pdev->dev, |
1193 | "Failed to register VF, err: %d, status: 0x%x, out size: 0x%x\n" , |
1194 | err, register_info.status, out_size); |
1195 | return -EIO; |
1196 | } |
1197 | } else { |
1198 | err = hinic_register_pf_mbox_cb(hwdev, mod: HINIC_MOD_CFGM, |
1199 | callback: cfg_mbx_pf_proc_vf_msg); |
1200 | if (err) { |
1201 | dev_err(&hwdev->hwif->pdev->dev, |
1202 | "Register PF mailbox callback failed\n" ); |
1203 | return err; |
1204 | } |
1205 | nic_io->max_vfs = hwdev->nic_cap.max_vf; |
1206 | size = sizeof(*nic_io->vf_infos) * nic_io->max_vfs; |
1207 | if (size != 0) { |
1208 | nic_io->vf_infos = kzalloc(size, GFP_KERNEL); |
1209 | if (!nic_io->vf_infos) { |
1210 | err = -ENOMEM; |
1211 | goto out_free_nic_io; |
1212 | } |
1213 | |
1214 | for (i = 0; i < nic_io->max_vfs; i++) { |
1215 | err = hinic_init_vf_infos(nic_io, vf_id: i); |
1216 | if (err) |
1217 | goto err_init_vf_infos; |
1218 | } |
1219 | |
1220 | err = hinic_register_pf_mbox_cb(hwdev, mod: HINIC_MOD_L2NIC, |
1221 | callback: nic_pf_mbox_handler); |
1222 | if (err) |
1223 | goto err_register_pf_mbox_cb; |
1224 | } |
1225 | } |
1226 | |
1227 | return 0; |
1228 | |
1229 | err_register_pf_mbox_cb: |
1230 | err_init_vf_infos: |
1231 | kfree(objp: nic_io->vf_infos); |
1232 | out_free_nic_io: |
1233 | return err; |
1234 | } |
1235 | |
1236 | void hinic_vf_func_free(struct hinic_hwdev *hwdev) |
1237 | { |
1238 | struct hinic_register_vf unregister = {0}; |
1239 | u16 out_size = sizeof(unregister); |
1240 | int err; |
1241 | |
1242 | if (HINIC_IS_VF(hwdev->hwif)) { |
1243 | err = hinic_mbox_to_pf(hwdev, mod: HINIC_MOD_L2NIC, |
1244 | cmd: HINIC_PORT_CMD_VF_UNREGISTER, |
1245 | buf_in: &unregister, in_size: sizeof(unregister), |
1246 | buf_out: &unregister, out_size: &out_size, timeout: 0); |
1247 | if (err || !out_size || unregister.status) |
1248 | dev_err(&hwdev->hwif->pdev->dev, "Failed to unregister VF, err: %d, status: 0x%x, out_size: 0x%x\n" , |
1249 | err, unregister.status, out_size); |
1250 | } else { |
1251 | if (hwdev->func_to_io.vf_infos) { |
1252 | hinic_unregister_pf_mbox_cb(hwdev, mod: HINIC_MOD_L2NIC); |
1253 | kfree(objp: hwdev->func_to_io.vf_infos); |
1254 | } |
1255 | } |
1256 | } |
1257 | |
1258 | static int hinic_init_vf_hw(struct hinic_hwdev *hwdev, u16 start_vf_id, |
1259 | u16 end_vf_id) |
1260 | { |
1261 | u16 i, func_idx; |
1262 | int err; |
1263 | |
1264 | /* vf use 256K as default wq page size, and can't change it */ |
1265 | for (i = start_vf_id; i <= end_vf_id; i++) { |
1266 | func_idx = hinic_glb_pf_vf_offset(hwif: hwdev->hwif) + i; |
1267 | err = hinic_set_wq_page_size(hwdev, func_idx, |
1268 | HINIC_DEFAULT_WQ_PAGE_SIZE); |
1269 | if (err) |
1270 | return err; |
1271 | } |
1272 | |
1273 | return 0; |
1274 | } |
1275 | |
1276 | int hinic_pci_sriov_disable(struct pci_dev *pdev) |
1277 | { |
1278 | struct hinic_sriov_info *sriov_info; |
1279 | u16 tmp_vfs; |
1280 | |
1281 | sriov_info = hinic_get_sriov_info_by_pcidev(pdev); |
1282 | /* if SR-IOV is already disabled then nothing will be done */ |
1283 | if (!sriov_info->sriov_enabled) |
1284 | return 0; |
1285 | |
1286 | set_bit(nr: HINIC_SRIOV_DISABLE, addr: &sriov_info->state); |
1287 | |
1288 | /* If our VFs are assigned we cannot shut down SR-IOV |
1289 | * without causing issues, so just leave the hardware |
1290 | * available but disabled |
1291 | */ |
1292 | if (pci_vfs_assigned(dev: sriov_info->pdev)) { |
1293 | clear_bit(nr: HINIC_SRIOV_DISABLE, addr: &sriov_info->state); |
1294 | dev_warn(&pdev->dev, "Unloading driver while VFs are assigned - VFs will not be deallocated\n" ); |
1295 | return -EPERM; |
1296 | } |
1297 | sriov_info->sriov_enabled = false; |
1298 | |
1299 | /* disable iov and allow time for transactions to clear */ |
1300 | pci_disable_sriov(dev: sriov_info->pdev); |
1301 | |
1302 | tmp_vfs = (u16)sriov_info->num_vfs; |
1303 | sriov_info->num_vfs = 0; |
1304 | hinic_deinit_vf_hw(sriov_info, OS_VF_ID_TO_HW(0), |
1305 | OS_VF_ID_TO_HW(tmp_vfs - 1)); |
1306 | |
1307 | clear_bit(nr: HINIC_SRIOV_DISABLE, addr: &sriov_info->state); |
1308 | |
1309 | return 0; |
1310 | } |
1311 | |
1312 | static int hinic_pci_sriov_enable(struct pci_dev *pdev, int num_vfs) |
1313 | { |
1314 | struct hinic_sriov_info *sriov_info; |
1315 | int err; |
1316 | |
1317 | sriov_info = hinic_get_sriov_info_by_pcidev(pdev); |
1318 | |
1319 | if (test_and_set_bit(nr: HINIC_SRIOV_ENABLE, addr: &sriov_info->state)) { |
1320 | dev_err(&pdev->dev, |
1321 | "SR-IOV enable in process, please wait, num_vfs %d\n" , |
1322 | num_vfs); |
1323 | return -EPERM; |
1324 | } |
1325 | |
1326 | err = hinic_init_vf_hw(hwdev: sriov_info->hwdev, OS_VF_ID_TO_HW(0), |
1327 | OS_VF_ID_TO_HW((u16)num_vfs - 1)); |
1328 | if (err) { |
1329 | dev_err(&sriov_info->pdev->dev, |
1330 | "Failed to init vf in hardware before enable sriov, error %d\n" , |
1331 | err); |
1332 | clear_bit(nr: HINIC_SRIOV_ENABLE, addr: &sriov_info->state); |
1333 | return err; |
1334 | } |
1335 | |
1336 | err = pci_enable_sriov(dev: sriov_info->pdev, nr_virtfn: num_vfs); |
1337 | if (err) { |
1338 | dev_err(&pdev->dev, |
1339 | "Failed to enable SR-IOV, error %d\n" , err); |
1340 | clear_bit(nr: HINIC_SRIOV_ENABLE, addr: &sriov_info->state); |
1341 | return err; |
1342 | } |
1343 | |
1344 | sriov_info->sriov_enabled = true; |
1345 | sriov_info->num_vfs = num_vfs; |
1346 | clear_bit(nr: HINIC_SRIOV_ENABLE, addr: &sriov_info->state); |
1347 | |
1348 | return num_vfs; |
1349 | } |
1350 | |
1351 | int hinic_pci_sriov_configure(struct pci_dev *dev, int num_vfs) |
1352 | { |
1353 | struct hinic_sriov_info *sriov_info; |
1354 | |
1355 | sriov_info = hinic_get_sriov_info_by_pcidev(pdev: dev); |
1356 | |
1357 | if (test_bit(HINIC_FUNC_REMOVE, &sriov_info->state)) |
1358 | return -EBUSY; |
1359 | |
1360 | if (!num_vfs) |
1361 | return hinic_pci_sriov_disable(pdev: dev); |
1362 | else |
1363 | return hinic_pci_sriov_enable(pdev: dev, num_vfs); |
1364 | } |
1365 | |