1 | /* Broadcom NetXtreme-C/E network driver. |
2 | * |
3 | * Copyright (c) 2014-2016 Broadcom Corporation |
4 | * Copyright (c) 2016-2018 Broadcom Limited |
5 | * |
6 | * This program is free software; you can redistribute it and/or modify |
7 | * it under the terms of the GNU General Public License as published by |
8 | * the Free Software Foundation. |
9 | */ |
10 | |
11 | #include <linux/ethtool.h> |
12 | #include <linux/module.h> |
13 | #include <linux/pci.h> |
14 | #include <linux/netdevice.h> |
15 | #include <linux/if_vlan.h> |
16 | #include <linux/interrupt.h> |
17 | #include <linux/etherdevice.h> |
18 | #include "bnxt_hsi.h" |
19 | #include "bnxt.h" |
20 | #include "bnxt_hwrm.h" |
21 | #include "bnxt_ulp.h" |
22 | #include "bnxt_sriov.h" |
23 | #include "bnxt_vfr.h" |
24 | #include "bnxt_ethtool.h" |
25 | |
26 | #ifdef CONFIG_BNXT_SRIOV |
27 | static int bnxt_hwrm_fwd_async_event_cmpl(struct bnxt *bp, |
28 | struct bnxt_vf_info *vf, u16 event_id) |
29 | { |
30 | struct hwrm_fwd_async_event_cmpl_input *req; |
31 | struct hwrm_async_event_cmpl *async_cmpl; |
32 | int rc = 0; |
33 | |
34 | rc = hwrm_req_init(bp, req, HWRM_FWD_ASYNC_EVENT_CMPL); |
35 | if (rc) |
36 | goto exit; |
37 | |
38 | if (vf) |
39 | req->encap_async_event_target_id = cpu_to_le16(vf->fw_fid); |
40 | else |
41 | /* broadcast this async event to all VFs */ |
42 | req->encap_async_event_target_id = cpu_to_le16(0xffff); |
43 | async_cmpl = |
44 | (struct hwrm_async_event_cmpl *)req->encap_async_event_cmpl; |
45 | async_cmpl->type = cpu_to_le16(ASYNC_EVENT_CMPL_TYPE_HWRM_ASYNC_EVENT); |
46 | async_cmpl->event_id = cpu_to_le16(event_id); |
47 | |
48 | rc = hwrm_req_send(bp, req); |
49 | exit: |
50 | if (rc) |
51 | netdev_err(dev: bp->dev, format: "hwrm_fwd_async_event_cmpl failed. rc:%d\n" , |
52 | rc); |
53 | return rc; |
54 | } |
55 | |
56 | static int bnxt_vf_ndo_prep(struct bnxt *bp, int vf_id) |
57 | { |
58 | if (!bp->pf.active_vfs) { |
59 | netdev_err(dev: bp->dev, format: "vf ndo called though sriov is disabled\n" ); |
60 | return -EINVAL; |
61 | } |
62 | if (vf_id >= bp->pf.active_vfs) { |
63 | netdev_err(dev: bp->dev, format: "Invalid VF id %d\n" , vf_id); |
64 | return -EINVAL; |
65 | } |
66 | return 0; |
67 | } |
68 | |
69 | int bnxt_set_vf_spoofchk(struct net_device *dev, int vf_id, bool setting) |
70 | { |
71 | struct bnxt *bp = netdev_priv(dev); |
72 | struct hwrm_func_cfg_input *req; |
73 | bool old_setting = false; |
74 | struct bnxt_vf_info *vf; |
75 | u32 func_flags; |
76 | int rc; |
77 | |
78 | if (bp->hwrm_spec_code < 0x10701) |
79 | return -ENOTSUPP; |
80 | |
81 | rc = bnxt_vf_ndo_prep(bp, vf_id); |
82 | if (rc) |
83 | return rc; |
84 | |
85 | vf = &bp->pf.vf[vf_id]; |
86 | if (vf->flags & BNXT_VF_SPOOFCHK) |
87 | old_setting = true; |
88 | if (old_setting == setting) |
89 | return 0; |
90 | |
91 | if (setting) |
92 | func_flags = FUNC_CFG_REQ_FLAGS_SRC_MAC_ADDR_CHECK_ENABLE; |
93 | else |
94 | func_flags = FUNC_CFG_REQ_FLAGS_SRC_MAC_ADDR_CHECK_DISABLE; |
95 | /*TODO: if the driver supports VLAN filter on guest VLAN, |
96 | * the spoof check should also include vlan anti-spoofing |
97 | */ |
98 | rc = bnxt_hwrm_func_cfg_short_req_init(bp, req: &req); |
99 | if (!rc) { |
100 | req->fid = cpu_to_le16(vf->fw_fid); |
101 | req->flags = cpu_to_le32(func_flags); |
102 | rc = hwrm_req_send(bp, req); |
103 | if (!rc) { |
104 | if (setting) |
105 | vf->flags |= BNXT_VF_SPOOFCHK; |
106 | else |
107 | vf->flags &= ~BNXT_VF_SPOOFCHK; |
108 | } |
109 | } |
110 | return rc; |
111 | } |
112 | |
113 | static int bnxt_hwrm_func_qcfg_flags(struct bnxt *bp, struct bnxt_vf_info *vf) |
114 | { |
115 | struct hwrm_func_qcfg_output *resp; |
116 | struct hwrm_func_qcfg_input *req; |
117 | int rc; |
118 | |
119 | rc = hwrm_req_init(bp, req, HWRM_FUNC_QCFG); |
120 | if (rc) |
121 | return rc; |
122 | |
123 | req->fid = cpu_to_le16(BNXT_PF(bp) ? vf->fw_fid : 0xffff); |
124 | resp = hwrm_req_hold(bp, req); |
125 | rc = hwrm_req_send(bp, req); |
126 | if (!rc) |
127 | vf->func_qcfg_flags = le16_to_cpu(resp->flags); |
128 | hwrm_req_drop(bp, req); |
129 | return rc; |
130 | } |
131 | |
132 | bool bnxt_is_trusted_vf(struct bnxt *bp, struct bnxt_vf_info *vf) |
133 | { |
134 | if (BNXT_PF(bp) && !(bp->fw_cap & BNXT_FW_CAP_TRUSTED_VF)) |
135 | return !!(vf->flags & BNXT_VF_TRUST); |
136 | |
137 | bnxt_hwrm_func_qcfg_flags(bp, vf); |
138 | return !!(vf->func_qcfg_flags & FUNC_QCFG_RESP_FLAGS_TRUSTED_VF); |
139 | } |
140 | |
141 | static int bnxt_hwrm_set_trusted_vf(struct bnxt *bp, struct bnxt_vf_info *vf) |
142 | { |
143 | struct hwrm_func_cfg_input *req; |
144 | int rc; |
145 | |
146 | if (!(bp->fw_cap & BNXT_FW_CAP_TRUSTED_VF)) |
147 | return 0; |
148 | |
149 | rc = bnxt_hwrm_func_cfg_short_req_init(bp, req: &req); |
150 | if (rc) |
151 | return rc; |
152 | |
153 | req->fid = cpu_to_le16(vf->fw_fid); |
154 | if (vf->flags & BNXT_VF_TRUST) |
155 | req->flags = cpu_to_le32(FUNC_CFG_REQ_FLAGS_TRUSTED_VF_ENABLE); |
156 | else |
157 | req->flags = cpu_to_le32(FUNC_CFG_REQ_FLAGS_TRUSTED_VF_DISABLE); |
158 | return hwrm_req_send(bp, req); |
159 | } |
160 | |
161 | int bnxt_set_vf_trust(struct net_device *dev, int vf_id, bool trusted) |
162 | { |
163 | struct bnxt *bp = netdev_priv(dev); |
164 | struct bnxt_vf_info *vf; |
165 | |
166 | if (bnxt_vf_ndo_prep(bp, vf_id)) |
167 | return -EINVAL; |
168 | |
169 | vf = &bp->pf.vf[vf_id]; |
170 | if (trusted) |
171 | vf->flags |= BNXT_VF_TRUST; |
172 | else |
173 | vf->flags &= ~BNXT_VF_TRUST; |
174 | |
175 | bnxt_hwrm_set_trusted_vf(bp, vf); |
176 | return 0; |
177 | } |
178 | |
179 | int bnxt_get_vf_config(struct net_device *dev, int vf_id, |
180 | struct ifla_vf_info *ivi) |
181 | { |
182 | struct bnxt *bp = netdev_priv(dev); |
183 | struct bnxt_vf_info *vf; |
184 | int rc; |
185 | |
186 | rc = bnxt_vf_ndo_prep(bp, vf_id); |
187 | if (rc) |
188 | return rc; |
189 | |
190 | ivi->vf = vf_id; |
191 | vf = &bp->pf.vf[vf_id]; |
192 | |
193 | if (is_valid_ether_addr(addr: vf->mac_addr)) |
194 | memcpy(&ivi->mac, vf->mac_addr, ETH_ALEN); |
195 | else |
196 | memcpy(&ivi->mac, vf->vf_mac_addr, ETH_ALEN); |
197 | ivi->max_tx_rate = vf->max_tx_rate; |
198 | ivi->min_tx_rate = vf->min_tx_rate; |
199 | ivi->vlan = vf->vlan; |
200 | if (vf->flags & BNXT_VF_QOS) |
201 | ivi->qos = vf->vlan >> VLAN_PRIO_SHIFT; |
202 | else |
203 | ivi->qos = 0; |
204 | ivi->spoofchk = !!(vf->flags & BNXT_VF_SPOOFCHK); |
205 | ivi->trusted = bnxt_is_trusted_vf(bp, vf); |
206 | if (!(vf->flags & BNXT_VF_LINK_FORCED)) |
207 | ivi->linkstate = IFLA_VF_LINK_STATE_AUTO; |
208 | else if (vf->flags & BNXT_VF_LINK_UP) |
209 | ivi->linkstate = IFLA_VF_LINK_STATE_ENABLE; |
210 | else |
211 | ivi->linkstate = IFLA_VF_LINK_STATE_DISABLE; |
212 | |
213 | return 0; |
214 | } |
215 | |
216 | int bnxt_set_vf_mac(struct net_device *dev, int vf_id, u8 *mac) |
217 | { |
218 | struct bnxt *bp = netdev_priv(dev); |
219 | struct hwrm_func_cfg_input *req; |
220 | struct bnxt_vf_info *vf; |
221 | int rc; |
222 | |
223 | rc = bnxt_vf_ndo_prep(bp, vf_id); |
224 | if (rc) |
225 | return rc; |
226 | /* reject bc or mc mac addr, zero mac addr means allow |
227 | * VF to use its own mac addr |
228 | */ |
229 | if (is_multicast_ether_addr(addr: mac)) { |
230 | netdev_err(dev, format: "Invalid VF ethernet address\n" ); |
231 | return -EINVAL; |
232 | } |
233 | vf = &bp->pf.vf[vf_id]; |
234 | |
235 | rc = bnxt_hwrm_func_cfg_short_req_init(bp, req: &req); |
236 | if (rc) |
237 | return rc; |
238 | |
239 | memcpy(vf->mac_addr, mac, ETH_ALEN); |
240 | |
241 | req->fid = cpu_to_le16(vf->fw_fid); |
242 | req->enables = cpu_to_le32(FUNC_CFG_REQ_ENABLES_DFLT_MAC_ADDR); |
243 | memcpy(req->dflt_mac_addr, mac, ETH_ALEN); |
244 | return hwrm_req_send(bp, req); |
245 | } |
246 | |
247 | int bnxt_set_vf_vlan(struct net_device *dev, int vf_id, u16 vlan_id, u8 qos, |
248 | __be16 vlan_proto) |
249 | { |
250 | struct bnxt *bp = netdev_priv(dev); |
251 | struct hwrm_func_cfg_input *req; |
252 | struct bnxt_vf_info *vf; |
253 | u16 vlan_tag; |
254 | int rc; |
255 | |
256 | if (bp->hwrm_spec_code < 0x10201) |
257 | return -ENOTSUPP; |
258 | |
259 | if (vlan_proto != htons(ETH_P_8021Q)) |
260 | return -EPROTONOSUPPORT; |
261 | |
262 | rc = bnxt_vf_ndo_prep(bp, vf_id); |
263 | if (rc) |
264 | return rc; |
265 | |
266 | /* TODO: needed to implement proper handling of user priority, |
267 | * currently fail the command if there is valid priority |
268 | */ |
269 | if (vlan_id > 4095 || qos) |
270 | return -EINVAL; |
271 | |
272 | vf = &bp->pf.vf[vf_id]; |
273 | vlan_tag = vlan_id; |
274 | if (vlan_tag == vf->vlan) |
275 | return 0; |
276 | |
277 | rc = bnxt_hwrm_func_cfg_short_req_init(bp, req: &req); |
278 | if (!rc) { |
279 | req->fid = cpu_to_le16(vf->fw_fid); |
280 | req->dflt_vlan = cpu_to_le16(vlan_tag); |
281 | req->enables = cpu_to_le32(FUNC_CFG_REQ_ENABLES_DFLT_VLAN); |
282 | rc = hwrm_req_send(bp, req); |
283 | if (!rc) |
284 | vf->vlan = vlan_tag; |
285 | } |
286 | return rc; |
287 | } |
288 | |
289 | int bnxt_set_vf_bw(struct net_device *dev, int vf_id, int min_tx_rate, |
290 | int max_tx_rate) |
291 | { |
292 | struct bnxt *bp = netdev_priv(dev); |
293 | struct hwrm_func_cfg_input *req; |
294 | struct bnxt_vf_info *vf; |
295 | u32 pf_link_speed; |
296 | int rc; |
297 | |
298 | rc = bnxt_vf_ndo_prep(bp, vf_id); |
299 | if (rc) |
300 | return rc; |
301 | |
302 | vf = &bp->pf.vf[vf_id]; |
303 | pf_link_speed = bnxt_fw_to_ethtool_speed(bp->link_info.link_speed); |
304 | if (max_tx_rate > pf_link_speed) { |
305 | netdev_info(dev: bp->dev, format: "max tx rate %d exceed PF link speed for VF %d\n" , |
306 | max_tx_rate, vf_id); |
307 | return -EINVAL; |
308 | } |
309 | |
310 | if (min_tx_rate > pf_link_speed) { |
311 | netdev_info(dev: bp->dev, format: "min tx rate %d is invalid for VF %d\n" , |
312 | min_tx_rate, vf_id); |
313 | return -EINVAL; |
314 | } |
315 | if (min_tx_rate == vf->min_tx_rate && max_tx_rate == vf->max_tx_rate) |
316 | return 0; |
317 | rc = bnxt_hwrm_func_cfg_short_req_init(bp, req: &req); |
318 | if (!rc) { |
319 | req->fid = cpu_to_le16(vf->fw_fid); |
320 | req->enables = cpu_to_le32(FUNC_CFG_REQ_ENABLES_MAX_BW | |
321 | FUNC_CFG_REQ_ENABLES_MIN_BW); |
322 | req->max_bw = cpu_to_le32(max_tx_rate); |
323 | req->min_bw = cpu_to_le32(min_tx_rate); |
324 | rc = hwrm_req_send(bp, req); |
325 | if (!rc) { |
326 | vf->min_tx_rate = min_tx_rate; |
327 | vf->max_tx_rate = max_tx_rate; |
328 | } |
329 | } |
330 | return rc; |
331 | } |
332 | |
333 | int bnxt_set_vf_link_state(struct net_device *dev, int vf_id, int link) |
334 | { |
335 | struct bnxt *bp = netdev_priv(dev); |
336 | struct bnxt_vf_info *vf; |
337 | int rc; |
338 | |
339 | rc = bnxt_vf_ndo_prep(bp, vf_id); |
340 | if (rc) |
341 | return rc; |
342 | |
343 | vf = &bp->pf.vf[vf_id]; |
344 | |
345 | vf->flags &= ~(BNXT_VF_LINK_UP | BNXT_VF_LINK_FORCED); |
346 | switch (link) { |
347 | case IFLA_VF_LINK_STATE_AUTO: |
348 | vf->flags |= BNXT_VF_LINK_UP; |
349 | break; |
350 | case IFLA_VF_LINK_STATE_DISABLE: |
351 | vf->flags |= BNXT_VF_LINK_FORCED; |
352 | break; |
353 | case IFLA_VF_LINK_STATE_ENABLE: |
354 | vf->flags |= BNXT_VF_LINK_UP | BNXT_VF_LINK_FORCED; |
355 | break; |
356 | default: |
357 | netdev_err(dev: bp->dev, format: "Invalid link option\n" ); |
358 | rc = -EINVAL; |
359 | break; |
360 | } |
361 | if (vf->flags & (BNXT_VF_LINK_UP | BNXT_VF_LINK_FORCED)) |
362 | rc = bnxt_hwrm_fwd_async_event_cmpl(bp, vf, |
363 | ASYNC_EVENT_CMPL_EVENT_ID_LINK_STATUS_CHANGE); |
364 | return rc; |
365 | } |
366 | |
367 | static int bnxt_set_vf_attr(struct bnxt *bp, int num_vfs) |
368 | { |
369 | int i; |
370 | struct bnxt_vf_info *vf; |
371 | |
372 | for (i = 0; i < num_vfs; i++) { |
373 | vf = &bp->pf.vf[i]; |
374 | memset(vf, 0, sizeof(*vf)); |
375 | } |
376 | return 0; |
377 | } |
378 | |
379 | static int bnxt_hwrm_func_vf_resource_free(struct bnxt *bp, int num_vfs) |
380 | { |
381 | struct hwrm_func_vf_resc_free_input *req; |
382 | struct bnxt_pf_info *pf = &bp->pf; |
383 | int i, rc; |
384 | |
385 | rc = hwrm_req_init(bp, req, HWRM_FUNC_VF_RESC_FREE); |
386 | if (rc) |
387 | return rc; |
388 | |
389 | hwrm_req_hold(bp, req); |
390 | for (i = pf->first_vf_id; i < pf->first_vf_id + num_vfs; i++) { |
391 | req->vf_id = cpu_to_le16(i); |
392 | rc = hwrm_req_send(bp, req); |
393 | if (rc) |
394 | break; |
395 | } |
396 | hwrm_req_drop(bp, req); |
397 | return rc; |
398 | } |
399 | |
400 | static void bnxt_free_vf_resources(struct bnxt *bp) |
401 | { |
402 | struct pci_dev *pdev = bp->pdev; |
403 | int i; |
404 | |
405 | kfree(objp: bp->pf.vf_event_bmap); |
406 | bp->pf.vf_event_bmap = NULL; |
407 | |
408 | for (i = 0; i < 4; i++) { |
409 | if (bp->pf.hwrm_cmd_req_addr[i]) { |
410 | dma_free_coherent(dev: &pdev->dev, BNXT_PAGE_SIZE, |
411 | cpu_addr: bp->pf.hwrm_cmd_req_addr[i], |
412 | dma_handle: bp->pf.hwrm_cmd_req_dma_addr[i]); |
413 | bp->pf.hwrm_cmd_req_addr[i] = NULL; |
414 | } |
415 | } |
416 | |
417 | bp->pf.active_vfs = 0; |
418 | kfree(objp: bp->pf.vf); |
419 | bp->pf.vf = NULL; |
420 | } |
421 | |
422 | static int bnxt_alloc_vf_resources(struct bnxt *bp, int num_vfs) |
423 | { |
424 | struct pci_dev *pdev = bp->pdev; |
425 | u32 nr_pages, size, i, j, k = 0; |
426 | |
427 | bp->pf.vf = kcalloc(n: num_vfs, size: sizeof(struct bnxt_vf_info), GFP_KERNEL); |
428 | if (!bp->pf.vf) |
429 | return -ENOMEM; |
430 | |
431 | bnxt_set_vf_attr(bp, num_vfs); |
432 | |
433 | size = num_vfs * BNXT_HWRM_REQ_MAX_SIZE; |
434 | nr_pages = size / BNXT_PAGE_SIZE; |
435 | if (size & (BNXT_PAGE_SIZE - 1)) |
436 | nr_pages++; |
437 | |
438 | for (i = 0; i < nr_pages; i++) { |
439 | bp->pf.hwrm_cmd_req_addr[i] = |
440 | dma_alloc_coherent(dev: &pdev->dev, BNXT_PAGE_SIZE, |
441 | dma_handle: &bp->pf.hwrm_cmd_req_dma_addr[i], |
442 | GFP_KERNEL); |
443 | |
444 | if (!bp->pf.hwrm_cmd_req_addr[i]) |
445 | return -ENOMEM; |
446 | |
447 | for (j = 0; j < BNXT_HWRM_REQS_PER_PAGE && k < num_vfs; j++) { |
448 | struct bnxt_vf_info *vf = &bp->pf.vf[k]; |
449 | |
450 | vf->hwrm_cmd_req_addr = bp->pf.hwrm_cmd_req_addr[i] + |
451 | j * BNXT_HWRM_REQ_MAX_SIZE; |
452 | vf->hwrm_cmd_req_dma_addr = |
453 | bp->pf.hwrm_cmd_req_dma_addr[i] + j * |
454 | BNXT_HWRM_REQ_MAX_SIZE; |
455 | k++; |
456 | } |
457 | } |
458 | |
459 | /* Max 128 VF's */ |
460 | bp->pf.vf_event_bmap = kzalloc(size: 16, GFP_KERNEL); |
461 | if (!bp->pf.vf_event_bmap) |
462 | return -ENOMEM; |
463 | |
464 | bp->pf.hwrm_cmd_req_pages = nr_pages; |
465 | return 0; |
466 | } |
467 | |
468 | static int bnxt_hwrm_func_buf_rgtr(struct bnxt *bp) |
469 | { |
470 | struct hwrm_func_buf_rgtr_input *req; |
471 | int rc; |
472 | |
473 | rc = hwrm_req_init(bp, req, HWRM_FUNC_BUF_RGTR); |
474 | if (rc) |
475 | return rc; |
476 | |
477 | req->req_buf_num_pages = cpu_to_le16(bp->pf.hwrm_cmd_req_pages); |
478 | req->req_buf_page_size = cpu_to_le16(BNXT_PAGE_SHIFT); |
479 | req->req_buf_len = cpu_to_le16(BNXT_HWRM_REQ_MAX_SIZE); |
480 | req->req_buf_page_addr0 = cpu_to_le64(bp->pf.hwrm_cmd_req_dma_addr[0]); |
481 | req->req_buf_page_addr1 = cpu_to_le64(bp->pf.hwrm_cmd_req_dma_addr[1]); |
482 | req->req_buf_page_addr2 = cpu_to_le64(bp->pf.hwrm_cmd_req_dma_addr[2]); |
483 | req->req_buf_page_addr3 = cpu_to_le64(bp->pf.hwrm_cmd_req_dma_addr[3]); |
484 | |
485 | return hwrm_req_send(bp, req); |
486 | } |
487 | |
488 | static int __bnxt_set_vf_params(struct bnxt *bp, int vf_id) |
489 | { |
490 | struct hwrm_func_cfg_input *req; |
491 | struct bnxt_vf_info *vf; |
492 | int rc; |
493 | |
494 | rc = bnxt_hwrm_func_cfg_short_req_init(bp, req: &req); |
495 | if (rc) |
496 | return rc; |
497 | |
498 | vf = &bp->pf.vf[vf_id]; |
499 | req->fid = cpu_to_le16(vf->fw_fid); |
500 | |
501 | if (is_valid_ether_addr(addr: vf->mac_addr)) { |
502 | req->enables |= cpu_to_le32(FUNC_CFG_REQ_ENABLES_DFLT_MAC_ADDR); |
503 | memcpy(req->dflt_mac_addr, vf->mac_addr, ETH_ALEN); |
504 | } |
505 | if (vf->vlan) { |
506 | req->enables |= cpu_to_le32(FUNC_CFG_REQ_ENABLES_DFLT_VLAN); |
507 | req->dflt_vlan = cpu_to_le16(vf->vlan); |
508 | } |
509 | if (vf->max_tx_rate) { |
510 | req->enables |= cpu_to_le32(FUNC_CFG_REQ_ENABLES_MAX_BW | |
511 | FUNC_CFG_REQ_ENABLES_MIN_BW); |
512 | req->max_bw = cpu_to_le32(vf->max_tx_rate); |
513 | req->min_bw = cpu_to_le32(vf->min_tx_rate); |
514 | } |
515 | if (vf->flags & BNXT_VF_TRUST) |
516 | req->flags |= cpu_to_le32(FUNC_CFG_REQ_FLAGS_TRUSTED_VF_ENABLE); |
517 | |
518 | return hwrm_req_send(bp, req); |
519 | } |
520 | |
521 | /* Only called by PF to reserve resources for VFs, returns actual number of |
522 | * VFs configured, or < 0 on error. |
523 | */ |
524 | static int bnxt_hwrm_func_vf_resc_cfg(struct bnxt *bp, int num_vfs, bool reset) |
525 | { |
526 | struct hwrm_func_vf_resource_cfg_input *req; |
527 | struct bnxt_hw_resc *hw_resc = &bp->hw_resc; |
528 | u16 vf_tx_rings, vf_rx_rings, vf_cp_rings; |
529 | u16 vf_stat_ctx, vf_vnics, vf_ring_grps; |
530 | struct bnxt_pf_info *pf = &bp->pf; |
531 | int i, rc = 0, min = 1; |
532 | u16 vf_msix = 0; |
533 | u16 ; |
534 | |
535 | rc = hwrm_req_init(bp, req, HWRM_FUNC_VF_RESOURCE_CFG); |
536 | if (rc) |
537 | return rc; |
538 | |
539 | if (bp->flags & BNXT_FLAG_CHIP_P5_PLUS) { |
540 | vf_msix = hw_resc->max_nqs - bnxt_nq_rings_in_use(bp); |
541 | vf_ring_grps = 0; |
542 | } else { |
543 | vf_ring_grps = hw_resc->max_hw_ring_grps - bp->rx_nr_rings; |
544 | } |
545 | vf_cp_rings = bnxt_get_avail_cp_rings_for_en(bp); |
546 | vf_stat_ctx = bnxt_get_avail_stat_ctxs_for_en(bp); |
547 | if (bp->flags & BNXT_FLAG_AGG_RINGS) |
548 | vf_rx_rings = hw_resc->max_rx_rings - bp->rx_nr_rings * 2; |
549 | else |
550 | vf_rx_rings = hw_resc->max_rx_rings - bp->rx_nr_rings; |
551 | vf_tx_rings = hw_resc->max_tx_rings - bp->tx_nr_rings; |
552 | vf_vnics = hw_resc->max_vnics - bp->nr_vnics; |
553 | vf_rss = hw_resc->max_rsscos_ctxs - bp->rsscos_nr_ctxs; |
554 | |
555 | req->min_rsscos_ctx = cpu_to_le16(BNXT_VF_MIN_RSS_CTX); |
556 | if (pf->vf_resv_strategy == BNXT_VF_RESV_STRATEGY_MINIMAL_STATIC) { |
557 | min = 0; |
558 | req->min_rsscos_ctx = cpu_to_le16(min); |
559 | } |
560 | if (pf->vf_resv_strategy == BNXT_VF_RESV_STRATEGY_MINIMAL || |
561 | pf->vf_resv_strategy == BNXT_VF_RESV_STRATEGY_MINIMAL_STATIC) { |
562 | req->min_cmpl_rings = cpu_to_le16(min); |
563 | req->min_tx_rings = cpu_to_le16(min); |
564 | req->min_rx_rings = cpu_to_le16(min); |
565 | req->min_l2_ctxs = cpu_to_le16(min); |
566 | req->min_vnics = cpu_to_le16(min); |
567 | req->min_stat_ctx = cpu_to_le16(min); |
568 | if (!(bp->flags & BNXT_FLAG_CHIP_P5_PLUS)) |
569 | req->min_hw_ring_grps = cpu_to_le16(min); |
570 | } else { |
571 | vf_cp_rings /= num_vfs; |
572 | vf_tx_rings /= num_vfs; |
573 | vf_rx_rings /= num_vfs; |
574 | if ((bp->fw_cap & BNXT_FW_CAP_PRE_RESV_VNICS) && |
575 | vf_vnics >= pf->max_vfs) { |
576 | /* Take into account that FW has pre-reserved 1 VNIC for |
577 | * each pf->max_vfs. |
578 | */ |
579 | vf_vnics = (vf_vnics - pf->max_vfs + num_vfs) / num_vfs; |
580 | } else { |
581 | vf_vnics /= num_vfs; |
582 | } |
583 | vf_stat_ctx /= num_vfs; |
584 | vf_ring_grps /= num_vfs; |
585 | vf_rss /= num_vfs; |
586 | |
587 | vf_vnics = min_t(u16, vf_vnics, vf_rx_rings); |
588 | req->min_cmpl_rings = cpu_to_le16(vf_cp_rings); |
589 | req->min_tx_rings = cpu_to_le16(vf_tx_rings); |
590 | req->min_rx_rings = cpu_to_le16(vf_rx_rings); |
591 | req->min_l2_ctxs = cpu_to_le16(BNXT_VF_MAX_L2_CTX); |
592 | req->min_vnics = cpu_to_le16(vf_vnics); |
593 | req->min_stat_ctx = cpu_to_le16(vf_stat_ctx); |
594 | req->min_hw_ring_grps = cpu_to_le16(vf_ring_grps); |
595 | req->min_rsscos_ctx = cpu_to_le16(vf_rss); |
596 | } |
597 | req->max_cmpl_rings = cpu_to_le16(vf_cp_rings); |
598 | req->max_tx_rings = cpu_to_le16(vf_tx_rings); |
599 | req->max_rx_rings = cpu_to_le16(vf_rx_rings); |
600 | req->max_l2_ctxs = cpu_to_le16(BNXT_VF_MAX_L2_CTX); |
601 | req->max_vnics = cpu_to_le16(vf_vnics); |
602 | req->max_stat_ctx = cpu_to_le16(vf_stat_ctx); |
603 | req->max_hw_ring_grps = cpu_to_le16(vf_ring_grps); |
604 | req->max_rsscos_ctx = cpu_to_le16(vf_rss); |
605 | if (bp->flags & BNXT_FLAG_CHIP_P5_PLUS) |
606 | req->max_msix = cpu_to_le16(vf_msix / num_vfs); |
607 | |
608 | hwrm_req_hold(bp, req); |
609 | for (i = 0; i < num_vfs; i++) { |
610 | if (reset) |
611 | __bnxt_set_vf_params(bp, vf_id: i); |
612 | |
613 | req->vf_id = cpu_to_le16(pf->first_vf_id + i); |
614 | rc = hwrm_req_send(bp, req); |
615 | if (rc) |
616 | break; |
617 | pf->active_vfs = i + 1; |
618 | pf->vf[i].fw_fid = pf->first_vf_id + i; |
619 | } |
620 | |
621 | if (pf->active_vfs) { |
622 | u16 n = pf->active_vfs; |
623 | |
624 | hw_resc->max_tx_rings -= le16_to_cpu(req->min_tx_rings) * n; |
625 | hw_resc->max_rx_rings -= le16_to_cpu(req->min_rx_rings) * n; |
626 | hw_resc->max_hw_ring_grps -= |
627 | le16_to_cpu(req->min_hw_ring_grps) * n; |
628 | hw_resc->max_cp_rings -= le16_to_cpu(req->min_cmpl_rings) * n; |
629 | hw_resc->max_rsscos_ctxs -= |
630 | le16_to_cpu(req->min_rsscos_ctx) * n; |
631 | hw_resc->max_stat_ctxs -= le16_to_cpu(req->min_stat_ctx) * n; |
632 | hw_resc->max_vnics -= le16_to_cpu(req->min_vnics) * n; |
633 | if (bp->flags & BNXT_FLAG_CHIP_P5_PLUS) |
634 | hw_resc->max_nqs -= vf_msix; |
635 | |
636 | rc = pf->active_vfs; |
637 | } |
638 | hwrm_req_drop(bp, req); |
639 | return rc; |
640 | } |
641 | |
642 | /* Only called by PF to reserve resources for VFs, returns actual number of |
643 | * VFs configured, or < 0 on error. |
644 | */ |
645 | static int bnxt_hwrm_func_cfg(struct bnxt *bp, int num_vfs) |
646 | { |
647 | u16 vf_tx_rings, vf_rx_rings, vf_cp_rings, vf_stat_ctx, vf_vnics; |
648 | struct bnxt_hw_resc *hw_resc = &bp->hw_resc; |
649 | struct bnxt_pf_info *pf = &bp->pf; |
650 | struct hwrm_func_cfg_input *req; |
651 | int total_vf_tx_rings = 0; |
652 | u16 vf_ring_grps; |
653 | u32 mtu, i; |
654 | int rc; |
655 | |
656 | rc = bnxt_hwrm_func_cfg_short_req_init(bp, req: &req); |
657 | if (rc) |
658 | return rc; |
659 | |
660 | /* Remaining rings are distributed equally amongs VF's for now */ |
661 | vf_cp_rings = bnxt_get_avail_cp_rings_for_en(bp) / num_vfs; |
662 | vf_stat_ctx = bnxt_get_avail_stat_ctxs_for_en(bp) / num_vfs; |
663 | if (bp->flags & BNXT_FLAG_AGG_RINGS) |
664 | vf_rx_rings = (hw_resc->max_rx_rings - bp->rx_nr_rings * 2) / |
665 | num_vfs; |
666 | else |
667 | vf_rx_rings = (hw_resc->max_rx_rings - bp->rx_nr_rings) / |
668 | num_vfs; |
669 | vf_ring_grps = (hw_resc->max_hw_ring_grps - bp->rx_nr_rings) / num_vfs; |
670 | vf_tx_rings = (hw_resc->max_tx_rings - bp->tx_nr_rings) / num_vfs; |
671 | vf_vnics = (hw_resc->max_vnics - bp->nr_vnics) / num_vfs; |
672 | vf_vnics = min_t(u16, vf_vnics, vf_rx_rings); |
673 | |
674 | req->enables = cpu_to_le32(FUNC_CFG_REQ_ENABLES_ADMIN_MTU | |
675 | FUNC_CFG_REQ_ENABLES_MRU | |
676 | FUNC_CFG_REQ_ENABLES_NUM_RSSCOS_CTXS | |
677 | FUNC_CFG_REQ_ENABLES_NUM_STAT_CTXS | |
678 | FUNC_CFG_REQ_ENABLES_NUM_CMPL_RINGS | |
679 | FUNC_CFG_REQ_ENABLES_NUM_TX_RINGS | |
680 | FUNC_CFG_REQ_ENABLES_NUM_RX_RINGS | |
681 | FUNC_CFG_REQ_ENABLES_NUM_L2_CTXS | |
682 | FUNC_CFG_REQ_ENABLES_NUM_VNICS | |
683 | FUNC_CFG_REQ_ENABLES_NUM_HW_RING_GRPS); |
684 | |
685 | mtu = bp->dev->mtu + ETH_HLEN + VLAN_HLEN; |
686 | req->mru = cpu_to_le16(mtu); |
687 | req->admin_mtu = cpu_to_le16(mtu); |
688 | |
689 | req->num_rsscos_ctxs = cpu_to_le16(1); |
690 | req->num_cmpl_rings = cpu_to_le16(vf_cp_rings); |
691 | req->num_tx_rings = cpu_to_le16(vf_tx_rings); |
692 | req->num_rx_rings = cpu_to_le16(vf_rx_rings); |
693 | req->num_hw_ring_grps = cpu_to_le16(vf_ring_grps); |
694 | req->num_l2_ctxs = cpu_to_le16(4); |
695 | |
696 | req->num_vnics = cpu_to_le16(vf_vnics); |
697 | /* FIXME spec currently uses 1 bit for stats ctx */ |
698 | req->num_stat_ctxs = cpu_to_le16(vf_stat_ctx); |
699 | |
700 | hwrm_req_hold(bp, req); |
701 | for (i = 0; i < num_vfs; i++) { |
702 | int vf_tx_rsvd = vf_tx_rings; |
703 | |
704 | req->fid = cpu_to_le16(pf->first_vf_id + i); |
705 | rc = hwrm_req_send(bp, req); |
706 | if (rc) |
707 | break; |
708 | pf->active_vfs = i + 1; |
709 | pf->vf[i].fw_fid = le16_to_cpu(req->fid); |
710 | rc = __bnxt_hwrm_get_tx_rings(bp, fid: pf->vf[i].fw_fid, |
711 | tx_rings: &vf_tx_rsvd); |
712 | if (rc) |
713 | break; |
714 | total_vf_tx_rings += vf_tx_rsvd; |
715 | } |
716 | hwrm_req_drop(bp, req); |
717 | if (pf->active_vfs) { |
718 | hw_resc->max_tx_rings -= total_vf_tx_rings; |
719 | hw_resc->max_rx_rings -= vf_rx_rings * num_vfs; |
720 | hw_resc->max_hw_ring_grps -= vf_ring_grps * num_vfs; |
721 | hw_resc->max_cp_rings -= vf_cp_rings * num_vfs; |
722 | hw_resc->max_rsscos_ctxs -= num_vfs; |
723 | hw_resc->max_stat_ctxs -= vf_stat_ctx * num_vfs; |
724 | hw_resc->max_vnics -= vf_vnics * num_vfs; |
725 | rc = pf->active_vfs; |
726 | } |
727 | return rc; |
728 | } |
729 | |
730 | static int bnxt_func_cfg(struct bnxt *bp, int num_vfs, bool reset) |
731 | { |
732 | if (BNXT_NEW_RM(bp)) |
733 | return bnxt_hwrm_func_vf_resc_cfg(bp, num_vfs, reset); |
734 | else |
735 | return bnxt_hwrm_func_cfg(bp, num_vfs); |
736 | } |
737 | |
738 | int bnxt_cfg_hw_sriov(struct bnxt *bp, int *num_vfs, bool reset) |
739 | { |
740 | int rc; |
741 | |
742 | /* Register buffers for VFs */ |
743 | rc = bnxt_hwrm_func_buf_rgtr(bp); |
744 | if (rc) |
745 | return rc; |
746 | |
747 | /* Reserve resources for VFs */ |
748 | rc = bnxt_func_cfg(bp, num_vfs: *num_vfs, reset); |
749 | if (rc != *num_vfs) { |
750 | if (rc <= 0) { |
751 | netdev_warn(dev: bp->dev, format: "Unable to reserve resources for SRIOV.\n" ); |
752 | *num_vfs = 0; |
753 | return rc; |
754 | } |
755 | netdev_warn(dev: bp->dev, format: "Only able to reserve resources for %d VFs.\n" , |
756 | rc); |
757 | *num_vfs = rc; |
758 | } |
759 | |
760 | return 0; |
761 | } |
762 | |
763 | static int bnxt_sriov_enable(struct bnxt *bp, int *num_vfs) |
764 | { |
765 | int rc = 0, vfs_supported; |
766 | int min_rx_rings, min_tx_rings, ; |
767 | struct bnxt_hw_resc *hw_resc = &bp->hw_resc; |
768 | int tx_ok = 0, rx_ok = 0, = 0; |
769 | int avail_cp, avail_stat; |
770 | |
771 | /* Check if we can enable requested num of vf's. At a mininum |
772 | * we require 1 RX 1 TX rings for each VF. In this minimum conf |
773 | * features like TPA will not be available. |
774 | */ |
775 | vfs_supported = *num_vfs; |
776 | |
777 | avail_cp = bnxt_get_avail_cp_rings_for_en(bp); |
778 | avail_stat = bnxt_get_avail_stat_ctxs_for_en(bp); |
779 | avail_cp = min_t(int, avail_cp, avail_stat); |
780 | |
781 | while (vfs_supported) { |
782 | min_rx_rings = vfs_supported; |
783 | min_tx_rings = vfs_supported; |
784 | min_rss_ctxs = vfs_supported; |
785 | |
786 | if (bp->flags & BNXT_FLAG_AGG_RINGS) { |
787 | if (hw_resc->max_rx_rings - bp->rx_nr_rings * 2 >= |
788 | min_rx_rings) |
789 | rx_ok = 1; |
790 | } else { |
791 | if (hw_resc->max_rx_rings - bp->rx_nr_rings >= |
792 | min_rx_rings) |
793 | rx_ok = 1; |
794 | } |
795 | if (hw_resc->max_vnics - bp->nr_vnics < min_rx_rings || |
796 | avail_cp < min_rx_rings) |
797 | rx_ok = 0; |
798 | |
799 | if (hw_resc->max_tx_rings - bp->tx_nr_rings >= min_tx_rings && |
800 | avail_cp >= min_tx_rings) |
801 | tx_ok = 1; |
802 | |
803 | if (hw_resc->max_rsscos_ctxs - bp->rsscos_nr_ctxs >= |
804 | min_rss_ctxs) |
805 | rss_ok = 1; |
806 | |
807 | if (tx_ok && rx_ok && rss_ok) |
808 | break; |
809 | |
810 | vfs_supported--; |
811 | } |
812 | |
813 | if (!vfs_supported) { |
814 | netdev_err(dev: bp->dev, format: "Cannot enable VF's as all resources are used by PF\n" ); |
815 | return -EINVAL; |
816 | } |
817 | |
818 | if (vfs_supported != *num_vfs) { |
819 | netdev_info(dev: bp->dev, format: "Requested VFs %d, can enable %d\n" , |
820 | *num_vfs, vfs_supported); |
821 | *num_vfs = vfs_supported; |
822 | } |
823 | |
824 | rc = bnxt_alloc_vf_resources(bp, num_vfs: *num_vfs); |
825 | if (rc) |
826 | goto err_out1; |
827 | |
828 | rc = bnxt_cfg_hw_sriov(bp, num_vfs, reset: false); |
829 | if (rc) |
830 | goto err_out2; |
831 | |
832 | rc = pci_enable_sriov(dev: bp->pdev, nr_virtfn: *num_vfs); |
833 | if (rc) |
834 | goto err_out2; |
835 | |
836 | if (bp->eswitch_mode != DEVLINK_ESWITCH_MODE_SWITCHDEV) |
837 | return 0; |
838 | |
839 | /* Create representors for VFs in switchdev mode */ |
840 | devl_lock(devlink: bp->dl); |
841 | rc = bnxt_vf_reps_create(bp); |
842 | devl_unlock(devlink: bp->dl); |
843 | if (rc) { |
844 | netdev_info(dev: bp->dev, format: "Cannot enable VFS as representors cannot be created\n" ); |
845 | goto err_out3; |
846 | } |
847 | |
848 | return 0; |
849 | |
850 | err_out3: |
851 | /* Disable SR-IOV */ |
852 | pci_disable_sriov(dev: bp->pdev); |
853 | |
854 | err_out2: |
855 | /* Free the resources reserved for various VF's */ |
856 | bnxt_hwrm_func_vf_resource_free(bp, num_vfs: *num_vfs); |
857 | |
858 | /* Restore the max resources */ |
859 | bnxt_hwrm_func_qcaps(bp); |
860 | |
861 | err_out1: |
862 | bnxt_free_vf_resources(bp); |
863 | |
864 | return rc; |
865 | } |
866 | |
867 | void bnxt_sriov_disable(struct bnxt *bp) |
868 | { |
869 | u16 num_vfs = pci_num_vf(dev: bp->pdev); |
870 | |
871 | if (!num_vfs) |
872 | return; |
873 | |
874 | /* synchronize VF and VF-rep create and destroy */ |
875 | devl_lock(devlink: bp->dl); |
876 | bnxt_vf_reps_destroy(bp); |
877 | |
878 | if (pci_vfs_assigned(dev: bp->pdev)) { |
879 | bnxt_hwrm_fwd_async_event_cmpl( |
880 | bp, NULL, ASYNC_EVENT_CMPL_EVENT_ID_PF_DRVR_UNLOAD); |
881 | netdev_warn(dev: bp->dev, format: "Unable to free %d VFs because some are assigned to VMs.\n" , |
882 | num_vfs); |
883 | } else { |
884 | pci_disable_sriov(dev: bp->pdev); |
885 | /* Free the HW resources reserved for various VF's */ |
886 | bnxt_hwrm_func_vf_resource_free(bp, num_vfs); |
887 | } |
888 | devl_unlock(devlink: bp->dl); |
889 | |
890 | bnxt_free_vf_resources(bp); |
891 | |
892 | /* Reclaim all resources for the PF. */ |
893 | rtnl_lock(); |
894 | bnxt_restore_pf_fw_resources(bp); |
895 | rtnl_unlock(); |
896 | } |
897 | |
898 | int bnxt_sriov_configure(struct pci_dev *pdev, int num_vfs) |
899 | { |
900 | struct net_device *dev = pci_get_drvdata(pdev); |
901 | struct bnxt *bp = netdev_priv(dev); |
902 | |
903 | if (!(bp->flags & BNXT_FLAG_USING_MSIX)) { |
904 | netdev_warn(dev, format: "Not allow SRIOV if the irq mode is not MSIX\n" ); |
905 | return 0; |
906 | } |
907 | |
908 | rtnl_lock(); |
909 | if (!netif_running(dev)) { |
910 | netdev_warn(dev, format: "Reject SRIOV config request since if is down!\n" ); |
911 | rtnl_unlock(); |
912 | return 0; |
913 | } |
914 | if (test_bit(BNXT_STATE_IN_FW_RESET, &bp->state)) { |
915 | netdev_warn(dev, format: "Reject SRIOV config request when FW reset is in progress\n" ); |
916 | rtnl_unlock(); |
917 | return 0; |
918 | } |
919 | bp->sriov_cfg = true; |
920 | rtnl_unlock(); |
921 | |
922 | if (pci_vfs_assigned(dev: bp->pdev)) { |
923 | netdev_warn(dev, format: "Unable to configure SRIOV since some VFs are assigned to VMs.\n" ); |
924 | num_vfs = 0; |
925 | goto sriov_cfg_exit; |
926 | } |
927 | |
928 | /* Check if enabled VFs is same as requested */ |
929 | if (num_vfs && num_vfs == bp->pf.active_vfs) |
930 | goto sriov_cfg_exit; |
931 | |
932 | /* if there are previous existing VFs, clean them up */ |
933 | bnxt_sriov_disable(bp); |
934 | if (!num_vfs) |
935 | goto sriov_cfg_exit; |
936 | |
937 | bnxt_sriov_enable(bp, num_vfs: &num_vfs); |
938 | |
939 | sriov_cfg_exit: |
940 | bp->sriov_cfg = false; |
941 | wake_up(&bp->sriov_cfg_wait); |
942 | |
943 | return num_vfs; |
944 | } |
945 | |
946 | static int bnxt_hwrm_fwd_resp(struct bnxt *bp, struct bnxt_vf_info *vf, |
947 | void *encap_resp, __le64 encap_resp_addr, |
948 | __le16 encap_resp_cpr, u32 msg_size) |
949 | { |
950 | struct hwrm_fwd_resp_input *req; |
951 | int rc; |
952 | |
953 | if (BNXT_FWD_RESP_SIZE_ERR(msg_size)) |
954 | return -EINVAL; |
955 | |
956 | rc = hwrm_req_init(bp, req, HWRM_FWD_RESP); |
957 | if (!rc) { |
958 | /* Set the new target id */ |
959 | req->target_id = cpu_to_le16(vf->fw_fid); |
960 | req->encap_resp_target_id = cpu_to_le16(vf->fw_fid); |
961 | req->encap_resp_len = cpu_to_le16(msg_size); |
962 | req->encap_resp_addr = encap_resp_addr; |
963 | req->encap_resp_cmpl_ring = encap_resp_cpr; |
964 | memcpy(req->encap_resp, encap_resp, msg_size); |
965 | |
966 | rc = hwrm_req_send(bp, req); |
967 | } |
968 | if (rc) |
969 | netdev_err(dev: bp->dev, format: "hwrm_fwd_resp failed. rc:%d\n" , rc); |
970 | return rc; |
971 | } |
972 | |
973 | static int bnxt_hwrm_fwd_err_resp(struct bnxt *bp, struct bnxt_vf_info *vf, |
974 | u32 msg_size) |
975 | { |
976 | struct hwrm_reject_fwd_resp_input *req; |
977 | int rc; |
978 | |
979 | if (BNXT_REJ_FWD_RESP_SIZE_ERR(msg_size)) |
980 | return -EINVAL; |
981 | |
982 | rc = hwrm_req_init(bp, req, HWRM_REJECT_FWD_RESP); |
983 | if (!rc) { |
984 | /* Set the new target id */ |
985 | req->target_id = cpu_to_le16(vf->fw_fid); |
986 | req->encap_resp_target_id = cpu_to_le16(vf->fw_fid); |
987 | memcpy(req->encap_request, vf->hwrm_cmd_req_addr, msg_size); |
988 | |
989 | rc = hwrm_req_send(bp, req); |
990 | } |
991 | if (rc) |
992 | netdev_err(dev: bp->dev, format: "hwrm_fwd_err_resp failed. rc:%d\n" , rc); |
993 | return rc; |
994 | } |
995 | |
996 | static int bnxt_hwrm_exec_fwd_resp(struct bnxt *bp, struct bnxt_vf_info *vf, |
997 | u32 msg_size) |
998 | { |
999 | struct hwrm_exec_fwd_resp_input *req; |
1000 | int rc; |
1001 | |
1002 | if (BNXT_EXEC_FWD_RESP_SIZE_ERR(msg_size)) |
1003 | return -EINVAL; |
1004 | |
1005 | rc = hwrm_req_init(bp, req, HWRM_EXEC_FWD_RESP); |
1006 | if (!rc) { |
1007 | /* Set the new target id */ |
1008 | req->target_id = cpu_to_le16(vf->fw_fid); |
1009 | req->encap_resp_target_id = cpu_to_le16(vf->fw_fid); |
1010 | memcpy(req->encap_request, vf->hwrm_cmd_req_addr, msg_size); |
1011 | |
1012 | rc = hwrm_req_send(bp, req); |
1013 | } |
1014 | if (rc) |
1015 | netdev_err(dev: bp->dev, format: "hwrm_exec_fw_resp failed. rc:%d\n" , rc); |
1016 | return rc; |
1017 | } |
1018 | |
1019 | static int bnxt_vf_configure_mac(struct bnxt *bp, struct bnxt_vf_info *vf) |
1020 | { |
1021 | u32 msg_size = sizeof(struct hwrm_func_vf_cfg_input); |
1022 | struct hwrm_func_vf_cfg_input *req = |
1023 | (struct hwrm_func_vf_cfg_input *)vf->hwrm_cmd_req_addr; |
1024 | |
1025 | /* Allow VF to set a valid MAC address, if trust is set to on or |
1026 | * if the PF assigned MAC address is zero |
1027 | */ |
1028 | if (req->enables & cpu_to_le32(FUNC_VF_CFG_REQ_ENABLES_DFLT_MAC_ADDR)) { |
1029 | bool trust = bnxt_is_trusted_vf(bp, vf); |
1030 | |
1031 | if (is_valid_ether_addr(addr: req->dflt_mac_addr) && |
1032 | (trust || !is_valid_ether_addr(addr: vf->mac_addr) || |
1033 | ether_addr_equal(addr1: req->dflt_mac_addr, addr2: vf->mac_addr))) { |
1034 | ether_addr_copy(dst: vf->vf_mac_addr, src: req->dflt_mac_addr); |
1035 | return bnxt_hwrm_exec_fwd_resp(bp, vf, msg_size); |
1036 | } |
1037 | return bnxt_hwrm_fwd_err_resp(bp, vf, msg_size); |
1038 | } |
1039 | return bnxt_hwrm_exec_fwd_resp(bp, vf, msg_size); |
1040 | } |
1041 | |
1042 | static int bnxt_vf_validate_set_mac(struct bnxt *bp, struct bnxt_vf_info *vf) |
1043 | { |
1044 | u32 msg_size = sizeof(struct hwrm_cfa_l2_filter_alloc_input); |
1045 | struct hwrm_cfa_l2_filter_alloc_input *req = |
1046 | (struct hwrm_cfa_l2_filter_alloc_input *)vf->hwrm_cmd_req_addr; |
1047 | bool mac_ok = false; |
1048 | |
1049 | if (!is_valid_ether_addr(addr: (const u8 *)req->l2_addr)) |
1050 | return bnxt_hwrm_fwd_err_resp(bp, vf, msg_size); |
1051 | |
1052 | /* Allow VF to set a valid MAC address, if trust is set to on. |
1053 | * Or VF MAC address must first match MAC address in PF's context. |
1054 | * Otherwise, it must match the VF MAC address if firmware spec >= |
1055 | * 1.2.2 |
1056 | */ |
1057 | if (bnxt_is_trusted_vf(bp, vf)) { |
1058 | mac_ok = true; |
1059 | } else if (is_valid_ether_addr(addr: vf->mac_addr)) { |
1060 | if (ether_addr_equal(addr1: (const u8 *)req->l2_addr, addr2: vf->mac_addr)) |
1061 | mac_ok = true; |
1062 | } else if (is_valid_ether_addr(addr: vf->vf_mac_addr)) { |
1063 | if (ether_addr_equal(addr1: (const u8 *)req->l2_addr, addr2: vf->vf_mac_addr)) |
1064 | mac_ok = true; |
1065 | } else { |
1066 | /* There are two cases: |
1067 | * 1.If firmware spec < 0x10202,VF MAC address is not forwarded |
1068 | * to the PF and so it doesn't have to match |
1069 | * 2.Allow VF to modify it's own MAC when PF has not assigned a |
1070 | * valid MAC address and firmware spec >= 0x10202 |
1071 | */ |
1072 | mac_ok = true; |
1073 | } |
1074 | if (mac_ok) |
1075 | return bnxt_hwrm_exec_fwd_resp(bp, vf, msg_size); |
1076 | return bnxt_hwrm_fwd_err_resp(bp, vf, msg_size); |
1077 | } |
1078 | |
1079 | static int bnxt_vf_set_link(struct bnxt *bp, struct bnxt_vf_info *vf) |
1080 | { |
1081 | int rc = 0; |
1082 | |
1083 | if (!(vf->flags & BNXT_VF_LINK_FORCED)) { |
1084 | /* real link */ |
1085 | rc = bnxt_hwrm_exec_fwd_resp( |
1086 | bp, vf, msg_size: sizeof(struct hwrm_port_phy_qcfg_input)); |
1087 | } else { |
1088 | struct hwrm_port_phy_qcfg_output phy_qcfg_resp = {0}; |
1089 | struct hwrm_port_phy_qcfg_input *phy_qcfg_req; |
1090 | |
1091 | phy_qcfg_req = |
1092 | (struct hwrm_port_phy_qcfg_input *)vf->hwrm_cmd_req_addr; |
1093 | mutex_lock(&bp->link_lock); |
1094 | memcpy(&phy_qcfg_resp, &bp->link_info.phy_qcfg_resp, |
1095 | sizeof(phy_qcfg_resp)); |
1096 | mutex_unlock(lock: &bp->link_lock); |
1097 | phy_qcfg_resp.resp_len = cpu_to_le16(sizeof(phy_qcfg_resp)); |
1098 | phy_qcfg_resp.seq_id = phy_qcfg_req->seq_id; |
1099 | phy_qcfg_resp.valid = 1; |
1100 | |
1101 | if (vf->flags & BNXT_VF_LINK_UP) { |
1102 | /* if physical link is down, force link up on VF */ |
1103 | if (phy_qcfg_resp.link != |
1104 | PORT_PHY_QCFG_RESP_LINK_LINK) { |
1105 | phy_qcfg_resp.link = |
1106 | PORT_PHY_QCFG_RESP_LINK_LINK; |
1107 | phy_qcfg_resp.link_speed = cpu_to_le16( |
1108 | PORT_PHY_QCFG_RESP_LINK_SPEED_10GB); |
1109 | phy_qcfg_resp.duplex_cfg = |
1110 | PORT_PHY_QCFG_RESP_DUPLEX_CFG_FULL; |
1111 | phy_qcfg_resp.duplex_state = |
1112 | PORT_PHY_QCFG_RESP_DUPLEX_STATE_FULL; |
1113 | phy_qcfg_resp.pause = |
1114 | (PORT_PHY_QCFG_RESP_PAUSE_TX | |
1115 | PORT_PHY_QCFG_RESP_PAUSE_RX); |
1116 | } |
1117 | } else { |
1118 | /* force link down */ |
1119 | phy_qcfg_resp.link = PORT_PHY_QCFG_RESP_LINK_NO_LINK; |
1120 | phy_qcfg_resp.link_speed = 0; |
1121 | phy_qcfg_resp.duplex_state = |
1122 | PORT_PHY_QCFG_RESP_DUPLEX_STATE_HALF; |
1123 | phy_qcfg_resp.pause = 0; |
1124 | } |
1125 | rc = bnxt_hwrm_fwd_resp(bp, vf, encap_resp: &phy_qcfg_resp, |
1126 | encap_resp_addr: phy_qcfg_req->resp_addr, |
1127 | encap_resp_cpr: phy_qcfg_req->cmpl_ring, |
1128 | msg_size: sizeof(phy_qcfg_resp)); |
1129 | } |
1130 | return rc; |
1131 | } |
1132 | |
1133 | static int bnxt_vf_req_validate_snd(struct bnxt *bp, struct bnxt_vf_info *vf) |
1134 | { |
1135 | int rc = 0; |
1136 | struct input *encap_req = vf->hwrm_cmd_req_addr; |
1137 | u32 req_type = le16_to_cpu(encap_req->req_type); |
1138 | |
1139 | switch (req_type) { |
1140 | case HWRM_FUNC_VF_CFG: |
1141 | rc = bnxt_vf_configure_mac(bp, vf); |
1142 | break; |
1143 | case HWRM_CFA_L2_FILTER_ALLOC: |
1144 | rc = bnxt_vf_validate_set_mac(bp, vf); |
1145 | break; |
1146 | case HWRM_FUNC_CFG: |
1147 | /* TODO Validate if VF is allowed to change mac address, |
1148 | * mtu, num of rings etc |
1149 | */ |
1150 | rc = bnxt_hwrm_exec_fwd_resp( |
1151 | bp, vf, msg_size: sizeof(struct hwrm_func_cfg_input)); |
1152 | break; |
1153 | case HWRM_PORT_PHY_QCFG: |
1154 | rc = bnxt_vf_set_link(bp, vf); |
1155 | break; |
1156 | default: |
1157 | break; |
1158 | } |
1159 | return rc; |
1160 | } |
1161 | |
1162 | void bnxt_hwrm_exec_fwd_req(struct bnxt *bp) |
1163 | { |
1164 | u32 i = 0, active_vfs = bp->pf.active_vfs, vf_id; |
1165 | |
1166 | /* Scan through VF's and process commands */ |
1167 | while (1) { |
1168 | vf_id = find_next_bit(addr: bp->pf.vf_event_bmap, size: active_vfs, offset: i); |
1169 | if (vf_id >= active_vfs) |
1170 | break; |
1171 | |
1172 | clear_bit(nr: vf_id, addr: bp->pf.vf_event_bmap); |
1173 | bnxt_vf_req_validate_snd(bp, vf: &bp->pf.vf[vf_id]); |
1174 | i = vf_id + 1; |
1175 | } |
1176 | } |
1177 | |
1178 | int bnxt_approve_mac(struct bnxt *bp, const u8 *mac, bool strict) |
1179 | { |
1180 | struct hwrm_func_vf_cfg_input *req; |
1181 | int rc = 0; |
1182 | |
1183 | if (!BNXT_VF(bp)) |
1184 | return 0; |
1185 | |
1186 | if (bp->hwrm_spec_code < 0x10202) { |
1187 | if (is_valid_ether_addr(addr: bp->vf.mac_addr)) |
1188 | rc = -EADDRNOTAVAIL; |
1189 | goto mac_done; |
1190 | } |
1191 | |
1192 | rc = hwrm_req_init(bp, req, HWRM_FUNC_VF_CFG); |
1193 | if (rc) |
1194 | goto mac_done; |
1195 | |
1196 | req->enables = cpu_to_le32(FUNC_VF_CFG_REQ_ENABLES_DFLT_MAC_ADDR); |
1197 | memcpy(req->dflt_mac_addr, mac, ETH_ALEN); |
1198 | if (!strict) |
1199 | hwrm_req_flags(bp, req, flags: BNXT_HWRM_CTX_SILENT); |
1200 | rc = hwrm_req_send(bp, req); |
1201 | mac_done: |
1202 | if (rc && strict) { |
1203 | rc = -EADDRNOTAVAIL; |
1204 | netdev_warn(dev: bp->dev, format: "VF MAC address %pM not approved by the PF\n" , |
1205 | mac); |
1206 | return rc; |
1207 | } |
1208 | return 0; |
1209 | } |
1210 | |
1211 | void bnxt_update_vf_mac(struct bnxt *bp) |
1212 | { |
1213 | struct hwrm_func_qcaps_output *resp; |
1214 | struct hwrm_func_qcaps_input *req; |
1215 | bool inform_pf = false; |
1216 | |
1217 | if (hwrm_req_init(bp, req, HWRM_FUNC_QCAPS)) |
1218 | return; |
1219 | |
1220 | req->fid = cpu_to_le16(0xffff); |
1221 | |
1222 | resp = hwrm_req_hold(bp, req); |
1223 | if (hwrm_req_send(bp, req)) |
1224 | goto update_vf_mac_exit; |
1225 | |
1226 | /* Store MAC address from the firmware. There are 2 cases: |
1227 | * 1. MAC address is valid. It is assigned from the PF and we |
1228 | * need to override the current VF MAC address with it. |
1229 | * 2. MAC address is zero. The VF will use a random MAC address by |
1230 | * default but the stored zero MAC will allow the VF user to change |
1231 | * the random MAC address using ndo_set_mac_address() if he wants. |
1232 | */ |
1233 | if (!ether_addr_equal(addr1: resp->mac_address, addr2: bp->vf.mac_addr)) { |
1234 | memcpy(bp->vf.mac_addr, resp->mac_address, ETH_ALEN); |
1235 | /* This means we are now using our own MAC address, let |
1236 | * the PF know about this MAC address. |
1237 | */ |
1238 | if (!is_valid_ether_addr(addr: bp->vf.mac_addr)) |
1239 | inform_pf = true; |
1240 | } |
1241 | |
1242 | /* overwrite netdev dev_addr with admin VF MAC */ |
1243 | if (is_valid_ether_addr(addr: bp->vf.mac_addr)) |
1244 | eth_hw_addr_set(dev: bp->dev, addr: bp->vf.mac_addr); |
1245 | update_vf_mac_exit: |
1246 | hwrm_req_drop(bp, req); |
1247 | if (inform_pf) |
1248 | bnxt_approve_mac(bp, mac: bp->dev->dev_addr, strict: false); |
1249 | } |
1250 | |
1251 | #else |
1252 | |
1253 | int bnxt_cfg_hw_sriov(struct bnxt *bp, int *num_vfs, bool reset) |
1254 | { |
1255 | if (*num_vfs) |
1256 | return -EOPNOTSUPP; |
1257 | return 0; |
1258 | } |
1259 | |
1260 | void bnxt_sriov_disable(struct bnxt *bp) |
1261 | { |
1262 | } |
1263 | |
1264 | void bnxt_hwrm_exec_fwd_req(struct bnxt *bp) |
1265 | { |
1266 | netdev_err(bp->dev, "Invalid VF message received when SRIOV is not enable\n" ); |
1267 | } |
1268 | |
1269 | void bnxt_update_vf_mac(struct bnxt *bp) |
1270 | { |
1271 | } |
1272 | |
1273 | int bnxt_approve_mac(struct bnxt *bp, const u8 *mac, bool strict) |
1274 | { |
1275 | return 0; |
1276 | } |
1277 | #endif |
1278 | |