1 // SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
2 /* Copyright (C) 2018 Netronome Systems, Inc. */
4 #include <linux/bitfield.h>
5 #include <linux/bitmap.h>
6 #include <linux/etherdevice.h>
7 #include <linux/lockdep.h>
8 #include <linux/netdevice.h>
9 #include <linux/rcupdate.h>
10 #include <linux/rtnetlink.h>
11 #include <linux/slab.h>
13 #include "../nfpcore/nfp.h"
14 #include "../nfpcore/nfp_cpp.h"
15 #include "../nfpcore/nfp_nsp.h"
16 #include "../nfp_app.h"
17 #include "../nfp_main.h"
18 #include "../nfp_net.h"
19 #include "../nfp_net_repr.h"
20 #include "../nfp_port.h"
23 static u32
nfp_abm_portid(enum nfp_repr_type rtype
, unsigned int id
)
25 return FIELD_PREP(NFP_ABM_PORTID_TYPE
, rtype
) |
26 FIELD_PREP(NFP_ABM_PORTID_ID
, id
);
30 nfp_abm_setup_tc(struct nfp_app
*app
, struct net_device
*netdev
,
31 enum tc_setup_type type
, void *type_data
)
33 struct nfp_repr
*repr
= netdev_priv(netdev
);
34 struct nfp_port
*port
;
36 port
= nfp_port_from_netdev(netdev
);
37 if (!port
|| port
->type
!= NFP_PORT_PF_PORT
)
41 case TC_SETUP_ROOT_QDISC
:
42 return nfp_abm_setup_root(netdev
, repr
->app_priv
, type_data
);
43 case TC_SETUP_QDISC_MQ
:
44 return nfp_abm_setup_tc_mq(netdev
, repr
->app_priv
, type_data
);
45 case TC_SETUP_QDISC_RED
:
46 return nfp_abm_setup_tc_red(netdev
, repr
->app_priv
, type_data
);
47 case TC_SETUP_QDISC_GRED
:
48 return nfp_abm_setup_tc_gred(netdev
, repr
->app_priv
, type_data
);
50 return nfp_abm_setup_cls_block(netdev
, repr
, type_data
);
56 static struct net_device
*
57 nfp_abm_repr_get(struct nfp_app
*app
, u32 port_id
, bool *redir_egress
)
59 enum nfp_repr_type rtype
;
60 struct nfp_reprs
*reprs
;
63 rtype
= FIELD_GET(NFP_ABM_PORTID_TYPE
, port_id
);
64 port
= FIELD_GET(NFP_ABM_PORTID_ID
, port_id
);
66 reprs
= rcu_dereference(app
->reprs
[rtype
]);
70 if (port
>= reprs
->num_reprs
)
73 return rcu_dereference(reprs
->reprs
[port
]);
77 nfp_abm_spawn_repr(struct nfp_app
*app
, struct nfp_abm_link
*alink
,
78 enum nfp_port_type ptype
)
80 struct net_device
*netdev
;
81 enum nfp_repr_type rtype
;
82 struct nfp_reprs
*reprs
;
83 struct nfp_repr
*repr
;
84 struct nfp_port
*port
;
88 if (ptype
== NFP_PORT_PHYS_PORT
) {
89 rtype
= NFP_REPR_TYPE_PHYS_PORT
;
92 rtype
= NFP_REPR_TYPE_PF
;
93 txqs
= alink
->vnic
->max_rx_rings
;
96 netdev
= nfp_repr_alloc_mqs(app
, txqs
, 1);
99 repr
= netdev_priv(netdev
);
100 repr
->app_priv
= alink
;
102 port
= nfp_port_alloc(app
, ptype
, netdev
);
108 if (ptype
== NFP_PORT_PHYS_PORT
) {
109 port
->eth_forced
= true;
110 err
= nfp_port_init_phy_port(app
->pf
, app
, port
, alink
->id
);
114 port
->pf_id
= alink
->abm
->pf_id
;
115 port
->pf_split
= app
->pf
->max_data_vnics
> 1;
116 port
->pf_split_id
= alink
->id
;
117 port
->vnic
= alink
->vnic
->dp
.ctrl_bar
;
120 SET_NETDEV_DEV(netdev
, &alink
->vnic
->pdev
->dev
);
121 eth_hw_addr_random(netdev
);
123 err
= nfp_repr_init(app
, netdev
, nfp_abm_portid(rtype
, alink
->id
),
124 port
, alink
->vnic
->dp
.netdev
);
128 reprs
= nfp_reprs_get_locked(app
, rtype
);
129 WARN(nfp_repr_get_locked(app
, reprs
, alink
->id
), "duplicate repr");
131 rcu_assign_pointer(reprs
->reprs
[alink
->id
], netdev
);
134 nfp_info(app
->cpp
, "%s Port %d Representor(%s) created\n",
135 ptype
== NFP_PORT_PF_PORT
? "PCIe" : "Phys",
136 alink
->id
, netdev
->name
);
143 nfp_repr_free(netdev
);
148 nfp_abm_kill_repr(struct nfp_app
*app
, struct nfp_abm_link
*alink
,
149 enum nfp_repr_type rtype
)
151 struct net_device
*netdev
;
152 struct nfp_reprs
*reprs
;
154 reprs
= nfp_reprs_get_locked(app
, rtype
);
155 netdev
= nfp_repr_get_locked(app
, reprs
, alink
->id
);
159 rcu_assign_pointer(reprs
->reprs
[alink
->id
], NULL
);
162 /* Cast to make sure nfp_repr_clean_and_free() takes a nfp_repr */
163 nfp_repr_clean_and_free((struct nfp_repr
*)netdev_priv(netdev
));
167 nfp_abm_kill_reprs(struct nfp_abm
*abm
, struct nfp_abm_link
*alink
)
169 nfp_abm_kill_repr(abm
->app
, alink
, NFP_REPR_TYPE_PF
);
170 nfp_abm_kill_repr(abm
->app
, alink
, NFP_REPR_TYPE_PHYS_PORT
);
173 static void nfp_abm_kill_reprs_all(struct nfp_abm
*abm
)
175 struct nfp_pf
*pf
= abm
->app
->pf
;
178 list_for_each_entry(nn
, &pf
->vnics
, vnic_list
)
179 nfp_abm_kill_reprs(abm
, (struct nfp_abm_link
*)nn
->app_priv
);
182 static enum devlink_eswitch_mode
nfp_abm_eswitch_mode_get(struct nfp_app
*app
)
184 struct nfp_abm
*abm
= app
->priv
;
186 return abm
->eswitch_mode
;
189 static int nfp_abm_eswitch_set_legacy(struct nfp_abm
*abm
)
191 nfp_abm_kill_reprs_all(abm
);
192 nfp_abm_ctrl_qm_disable(abm
);
194 abm
->eswitch_mode
= DEVLINK_ESWITCH_MODE_LEGACY
;
198 static void nfp_abm_eswitch_clean_up(struct nfp_abm
*abm
)
200 if (abm
->eswitch_mode
!= DEVLINK_ESWITCH_MODE_LEGACY
)
201 WARN_ON(nfp_abm_eswitch_set_legacy(abm
));
204 static int nfp_abm_eswitch_set_switchdev(struct nfp_abm
*abm
)
206 struct nfp_app
*app
= abm
->app
;
207 struct nfp_pf
*pf
= app
->pf
;
211 if (!abm
->red_support
)
214 err
= nfp_abm_ctrl_qm_enable(abm
);
218 list_for_each_entry(nn
, &pf
->vnics
, vnic_list
) {
219 struct nfp_abm_link
*alink
= nn
->app_priv
;
221 err
= nfp_abm_spawn_repr(app
, alink
, NFP_PORT_PHYS_PORT
);
223 goto err_kill_all_reprs
;
225 err
= nfp_abm_spawn_repr(app
, alink
, NFP_PORT_PF_PORT
);
227 goto err_kill_all_reprs
;
230 abm
->eswitch_mode
= DEVLINK_ESWITCH_MODE_SWITCHDEV
;
234 nfp_abm_kill_reprs_all(abm
);
235 nfp_abm_ctrl_qm_disable(abm
);
239 static int nfp_abm_eswitch_mode_set(struct nfp_app
*app
, u16 mode
)
241 struct nfp_abm
*abm
= app
->priv
;
243 if (abm
->eswitch_mode
== mode
)
247 case DEVLINK_ESWITCH_MODE_LEGACY
:
248 return nfp_abm_eswitch_set_legacy(abm
);
249 case DEVLINK_ESWITCH_MODE_SWITCHDEV
:
250 return nfp_abm_eswitch_set_switchdev(abm
);
257 nfp_abm_vnic_set_mac(struct nfp_pf
*pf
, struct nfp_abm
*abm
, struct nfp_net
*nn
,
260 struct nfp_eth_table_port
*eth_port
= &pf
->eth_tbl
->ports
[id
];
261 u8 mac_addr
[ETH_ALEN
];
266 if (id
> pf
->eth_tbl
->count
) {
267 nfp_warn(pf
->cpp
, "No entry for persistent MAC address\n");
268 eth_hw_addr_random(nn
->dp
.netdev
);
272 snprintf(hwinfo
, sizeof(hwinfo
), "eth%u.mac.pf%u",
273 eth_port
->eth_index
, abm
->pf_id
);
275 nsp
= nfp_nsp_open(pf
->cpp
);
277 nfp_warn(pf
->cpp
, "Failed to access the NSP for persistent MAC address: %ld\n",
279 eth_hw_addr_random(nn
->dp
.netdev
);
283 if (!nfp_nsp_has_hwinfo_lookup(nsp
)) {
284 nfp_warn(pf
->cpp
, "NSP doesn't support PF MAC generation\n");
285 eth_hw_addr_random(nn
->dp
.netdev
);
290 err
= nfp_nsp_hwinfo_lookup(nsp
, hwinfo
, sizeof(hwinfo
));
293 nfp_warn(pf
->cpp
, "Reading persistent MAC address failed: %d\n",
295 eth_hw_addr_random(nn
->dp
.netdev
);
299 if (sscanf(hwinfo
, "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
300 &mac_addr
[0], &mac_addr
[1], &mac_addr
[2],
301 &mac_addr
[3], &mac_addr
[4], &mac_addr
[5]) != 6) {
302 nfp_warn(pf
->cpp
, "Can't parse persistent MAC address (%s)\n",
304 eth_hw_addr_random(nn
->dp
.netdev
);
308 ether_addr_copy(nn
->dp
.netdev
->dev_addr
, mac_addr
);
309 ether_addr_copy(nn
->dp
.netdev
->perm_addr
, mac_addr
);
313 nfp_abm_vnic_alloc(struct nfp_app
*app
, struct nfp_net
*nn
, unsigned int id
)
315 struct nfp_eth_table_port
*eth_port
= &app
->pf
->eth_tbl
->ports
[id
];
316 struct nfp_abm
*abm
= app
->priv
;
317 struct nfp_abm_link
*alink
;
320 alink
= kzalloc(sizeof(*alink
), GFP_KERNEL
);
323 nn
->app_priv
= alink
;
327 alink
->total_queues
= alink
->vnic
->max_rx_rings
;
329 INIT_LIST_HEAD(&alink
->dscp_map
);
331 err
= nfp_abm_ctrl_read_params(alink
);
335 alink
->prio_map
= kzalloc(abm
->prio_map_len
, GFP_KERNEL
);
336 if (!alink
->prio_map
) {
341 /* This is a multi-host app, make sure MAC/PHY is up, but don't
342 * make the MAC/PHY state follow the state of any of the ports.
344 err
= nfp_eth_set_configured(app
->cpp
, eth_port
->index
, true);
346 goto err_free_priomap
;
348 netif_keep_dst(nn
->dp
.netdev
);
350 nfp_abm_vnic_set_mac(app
->pf
, abm
, nn
, id
);
351 INIT_RADIX_TREE(&alink
->qdiscs
, GFP_KERNEL
);
356 kfree(alink
->prio_map
);
362 static void nfp_abm_vnic_free(struct nfp_app
*app
, struct nfp_net
*nn
)
364 struct nfp_abm_link
*alink
= nn
->app_priv
;
366 nfp_abm_kill_reprs(alink
->abm
, alink
);
367 WARN(!radix_tree_empty(&alink
->qdiscs
), "left over qdiscs\n");
368 kfree(alink
->prio_map
);
372 static int nfp_abm_vnic_init(struct nfp_app
*app
, struct nfp_net
*nn
)
374 struct nfp_abm_link
*alink
= nn
->app_priv
;
376 if (nfp_abm_has_prio(alink
->abm
))
377 return nfp_abm_ctrl_prio_map_update(alink
, alink
->prio_map
);
382 nfp_abm_port_get_stats(struct nfp_app
*app
, struct nfp_port
*port
, u64
*data
)
384 struct nfp_repr
*repr
= netdev_priv(port
->netdev
);
385 struct nfp_abm_link
*alink
;
388 if (port
->type
!= NFP_PORT_PF_PORT
)
390 alink
= repr
->app_priv
;
391 for (i
= 0; i
< alink
->vnic
->dp
.num_r_vecs
; i
++) {
392 *data
++ = nfp_abm_ctrl_stat_non_sto(alink
, i
);
393 *data
++ = nfp_abm_ctrl_stat_sto(alink
, i
);
399 nfp_abm_port_get_stats_count(struct nfp_app
*app
, struct nfp_port
*port
)
401 struct nfp_repr
*repr
= netdev_priv(port
->netdev
);
402 struct nfp_abm_link
*alink
;
404 if (port
->type
!= NFP_PORT_PF_PORT
)
406 alink
= repr
->app_priv
;
407 return alink
->vnic
->dp
.num_r_vecs
* 2;
411 nfp_abm_port_get_stats_strings(struct nfp_app
*app
, struct nfp_port
*port
,
414 struct nfp_repr
*repr
= netdev_priv(port
->netdev
);
415 struct nfp_abm_link
*alink
;
418 if (port
->type
!= NFP_PORT_PF_PORT
)
420 alink
= repr
->app_priv
;
421 for (i
= 0; i
< alink
->vnic
->dp
.num_r_vecs
; i
++) {
422 data
= nfp_pr_et(data
, "q%u_no_wait", i
);
423 data
= nfp_pr_et(data
, "q%u_delayed", i
);
428 static int nfp_abm_fw_init_reset(struct nfp_abm
*abm
)
432 if (!abm
->red_support
)
435 for (i
= 0; i
< abm
->num_bands
* NFP_NET_MAX_RX_RINGS
; i
++) {
436 __nfp_abm_ctrl_set_q_lvl(abm
, i
, NFP_ABM_LVL_INFINITY
);
437 __nfp_abm_ctrl_set_q_act(abm
, i
, NFP_ABM_ACT_DROP
);
440 return nfp_abm_ctrl_qm_disable(abm
);
443 static int nfp_abm_init(struct nfp_app
*app
)
445 struct nfp_pf
*pf
= app
->pf
;
446 struct nfp_reprs
*reprs
;
451 nfp_err(pf
->cpp
, "ABM NIC requires ETH table\n");
454 if (pf
->max_data_vnics
!= pf
->eth_tbl
->count
) {
455 nfp_err(pf
->cpp
, "ETH entries don't match vNICs (%d vs %d)\n",
456 pf
->max_data_vnics
, pf
->eth_tbl
->count
);
459 if (!pf
->mac_stats_bar
) {
460 nfp_warn(app
->cpp
, "ABM NIC requires mac_stats symbol\n");
464 abm
= kzalloc(sizeof(*abm
), GFP_KERNEL
);
470 err
= nfp_abm_ctrl_find_addrs(abm
);
475 abm
->num_thresholds
= array_size(abm
->num_bands
, NFP_NET_MAX_RX_RINGS
);
476 abm
->threshold_undef
= bitmap_zalloc(abm
->num_thresholds
, GFP_KERNEL
);
477 if (!abm
->threshold_undef
)
480 abm
->thresholds
= kvcalloc(abm
->num_thresholds
,
481 sizeof(*abm
->thresholds
), GFP_KERNEL
);
482 if (!abm
->thresholds
)
483 goto err_free_thresh_umap
;
485 abm
->actions
= kvcalloc(abm
->num_thresholds
, sizeof(*abm
->actions
),
488 goto err_free_thresh
;
490 /* We start in legacy mode, make sure advanced queuing is disabled */
491 err
= nfp_abm_fw_init_reset(abm
);
496 reprs
= nfp_reprs_alloc(pf
->max_data_vnics
);
499 RCU_INIT_POINTER(app
->reprs
[NFP_REPR_TYPE_PHYS_PORT
], reprs
);
501 reprs
= nfp_reprs_alloc(pf
->max_data_vnics
);
504 RCU_INIT_POINTER(app
->reprs
[NFP_REPR_TYPE_PF
], reprs
);
509 nfp_reprs_clean_and_free_by_type(app
, NFP_REPR_TYPE_PHYS_PORT
);
511 kvfree(abm
->actions
);
513 kvfree(abm
->thresholds
);
514 err_free_thresh_umap
:
515 bitmap_free(abm
->threshold_undef
);
522 static void nfp_abm_clean(struct nfp_app
*app
)
524 struct nfp_abm
*abm
= app
->priv
;
526 nfp_abm_eswitch_clean_up(abm
);
527 nfp_reprs_clean_and_free_by_type(app
, NFP_REPR_TYPE_PF
);
528 nfp_reprs_clean_and_free_by_type(app
, NFP_REPR_TYPE_PHYS_PORT
);
529 bitmap_free(abm
->threshold_undef
);
530 kvfree(abm
->actions
);
531 kvfree(abm
->thresholds
);
536 const struct nfp_app_type app_abm
= {
537 .id
= NFP_APP_ACTIVE_BUFFER_MGMT_NIC
,
540 .init
= nfp_abm_init
,
541 .clean
= nfp_abm_clean
,
543 .vnic_alloc
= nfp_abm_vnic_alloc
,
544 .vnic_free
= nfp_abm_vnic_free
,
545 .vnic_init
= nfp_abm_vnic_init
,
547 .port_get_stats
= nfp_abm_port_get_stats
,
548 .port_get_stats_count
= nfp_abm_port_get_stats_count
,
549 .port_get_stats_strings
= nfp_abm_port_get_stats_strings
,
551 .setup_tc
= nfp_abm_setup_tc
,
553 .eswitch_mode_get
= nfp_abm_eswitch_mode_get
,
554 .eswitch_mode_set
= nfp_abm_eswitch_mode_set
,
556 .dev_get
= nfp_abm_repr_get
,