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
);
289 err
= nfp_nsp_hwinfo_lookup(nsp
, hwinfo
, sizeof(hwinfo
));
292 nfp_warn(pf
->cpp
, "Reading persistent MAC address failed: %d\n",
294 eth_hw_addr_random(nn
->dp
.netdev
);
298 if (sscanf(hwinfo
, "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
299 &mac_addr
[0], &mac_addr
[1], &mac_addr
[2],
300 &mac_addr
[3], &mac_addr
[4], &mac_addr
[5]) != 6) {
301 nfp_warn(pf
->cpp
, "Can't parse persistent MAC address (%s)\n",
303 eth_hw_addr_random(nn
->dp
.netdev
);
307 ether_addr_copy(nn
->dp
.netdev
->dev_addr
, mac_addr
);
308 ether_addr_copy(nn
->dp
.netdev
->perm_addr
, mac_addr
);
312 nfp_abm_vnic_alloc(struct nfp_app
*app
, struct nfp_net
*nn
, unsigned int id
)
314 struct nfp_eth_table_port
*eth_port
= &app
->pf
->eth_tbl
->ports
[id
];
315 struct nfp_abm
*abm
= app
->priv
;
316 struct nfp_abm_link
*alink
;
319 alink
= kzalloc(sizeof(*alink
), GFP_KERNEL
);
322 nn
->app_priv
= alink
;
326 alink
->total_queues
= alink
->vnic
->max_rx_rings
;
328 INIT_LIST_HEAD(&alink
->dscp_map
);
330 err
= nfp_abm_ctrl_read_params(alink
);
334 alink
->prio_map
= kzalloc(abm
->prio_map_len
, GFP_KERNEL
);
335 if (!alink
->prio_map
)
338 /* This is a multi-host app, make sure MAC/PHY is up, but don't
339 * make the MAC/PHY state follow the state of any of the ports.
341 err
= nfp_eth_set_configured(app
->cpp
, eth_port
->index
, true);
343 goto err_free_priomap
;
345 netif_keep_dst(nn
->dp
.netdev
);
347 nfp_abm_vnic_set_mac(app
->pf
, abm
, nn
, id
);
348 INIT_RADIX_TREE(&alink
->qdiscs
, GFP_KERNEL
);
353 kfree(alink
->prio_map
);
359 static void nfp_abm_vnic_free(struct nfp_app
*app
, struct nfp_net
*nn
)
361 struct nfp_abm_link
*alink
= nn
->app_priv
;
363 nfp_abm_kill_reprs(alink
->abm
, alink
);
364 WARN(!radix_tree_empty(&alink
->qdiscs
), "left over qdiscs\n");
365 kfree(alink
->prio_map
);
369 static int nfp_abm_vnic_init(struct nfp_app
*app
, struct nfp_net
*nn
)
371 struct nfp_abm_link
*alink
= nn
->app_priv
;
373 if (nfp_abm_has_prio(alink
->abm
))
374 return nfp_abm_ctrl_prio_map_update(alink
, alink
->prio_map
);
379 nfp_abm_port_get_stats(struct nfp_app
*app
, struct nfp_port
*port
, u64
*data
)
381 struct nfp_repr
*repr
= netdev_priv(port
->netdev
);
382 struct nfp_abm_link
*alink
;
385 if (port
->type
!= NFP_PORT_PF_PORT
)
387 alink
= repr
->app_priv
;
388 for (i
= 0; i
< alink
->vnic
->dp
.num_r_vecs
; i
++) {
389 *data
++ = nfp_abm_ctrl_stat_non_sto(alink
, i
);
390 *data
++ = nfp_abm_ctrl_stat_sto(alink
, i
);
396 nfp_abm_port_get_stats_count(struct nfp_app
*app
, struct nfp_port
*port
)
398 struct nfp_repr
*repr
= netdev_priv(port
->netdev
);
399 struct nfp_abm_link
*alink
;
401 if (port
->type
!= NFP_PORT_PF_PORT
)
403 alink
= repr
->app_priv
;
404 return alink
->vnic
->dp
.num_r_vecs
* 2;
408 nfp_abm_port_get_stats_strings(struct nfp_app
*app
, struct nfp_port
*port
,
411 struct nfp_repr
*repr
= netdev_priv(port
->netdev
);
412 struct nfp_abm_link
*alink
;
415 if (port
->type
!= NFP_PORT_PF_PORT
)
417 alink
= repr
->app_priv
;
418 for (i
= 0; i
< alink
->vnic
->dp
.num_r_vecs
; i
++) {
419 data
= nfp_pr_et(data
, "q%u_no_wait", i
);
420 data
= nfp_pr_et(data
, "q%u_delayed", i
);
425 static int nfp_abm_fw_init_reset(struct nfp_abm
*abm
)
429 if (!abm
->red_support
)
432 for (i
= 0; i
< abm
->num_bands
* NFP_NET_MAX_RX_RINGS
; i
++) {
433 __nfp_abm_ctrl_set_q_lvl(abm
, i
, NFP_ABM_LVL_INFINITY
);
434 __nfp_abm_ctrl_set_q_act(abm
, i
, NFP_ABM_ACT_DROP
);
437 return nfp_abm_ctrl_qm_disable(abm
);
440 static int nfp_abm_init(struct nfp_app
*app
)
442 struct nfp_pf
*pf
= app
->pf
;
443 struct nfp_reprs
*reprs
;
448 nfp_err(pf
->cpp
, "ABM NIC requires ETH table\n");
451 if (pf
->max_data_vnics
!= pf
->eth_tbl
->count
) {
452 nfp_err(pf
->cpp
, "ETH entries don't match vNICs (%d vs %d)\n",
453 pf
->max_data_vnics
, pf
->eth_tbl
->count
);
456 if (!pf
->mac_stats_bar
) {
457 nfp_warn(app
->cpp
, "ABM NIC requires mac_stats symbol\n");
461 abm
= kzalloc(sizeof(*abm
), GFP_KERNEL
);
467 err
= nfp_abm_ctrl_find_addrs(abm
);
472 abm
->num_thresholds
= array_size(abm
->num_bands
, NFP_NET_MAX_RX_RINGS
);
473 abm
->threshold_undef
= bitmap_zalloc(abm
->num_thresholds
, GFP_KERNEL
);
474 if (!abm
->threshold_undef
)
477 abm
->thresholds
= kvcalloc(abm
->num_thresholds
,
478 sizeof(*abm
->thresholds
), GFP_KERNEL
);
479 if (!abm
->thresholds
)
480 goto err_free_thresh_umap
;
482 abm
->actions
= kvcalloc(abm
->num_thresholds
, sizeof(*abm
->actions
),
485 goto err_free_thresh
;
487 /* We start in legacy mode, make sure advanced queuing is disabled */
488 err
= nfp_abm_fw_init_reset(abm
);
493 reprs
= nfp_reprs_alloc(pf
->max_data_vnics
);
496 RCU_INIT_POINTER(app
->reprs
[NFP_REPR_TYPE_PHYS_PORT
], reprs
);
498 reprs
= nfp_reprs_alloc(pf
->max_data_vnics
);
501 RCU_INIT_POINTER(app
->reprs
[NFP_REPR_TYPE_PF
], reprs
);
506 nfp_reprs_clean_and_free_by_type(app
, NFP_REPR_TYPE_PHYS_PORT
);
508 kvfree(abm
->actions
);
510 kvfree(abm
->thresholds
);
511 err_free_thresh_umap
:
512 bitmap_free(abm
->threshold_undef
);
519 static void nfp_abm_clean(struct nfp_app
*app
)
521 struct nfp_abm
*abm
= app
->priv
;
523 nfp_abm_eswitch_clean_up(abm
);
524 nfp_reprs_clean_and_free_by_type(app
, NFP_REPR_TYPE_PF
);
525 nfp_reprs_clean_and_free_by_type(app
, NFP_REPR_TYPE_PHYS_PORT
);
526 bitmap_free(abm
->threshold_undef
);
527 kvfree(abm
->actions
);
528 kvfree(abm
->thresholds
);
533 const struct nfp_app_type app_abm
= {
534 .id
= NFP_APP_ACTIVE_BUFFER_MGMT_NIC
,
537 .init
= nfp_abm_init
,
538 .clean
= nfp_abm_clean
,
540 .vnic_alloc
= nfp_abm_vnic_alloc
,
541 .vnic_free
= nfp_abm_vnic_free
,
542 .vnic_init
= nfp_abm_vnic_init
,
544 .port_get_stats
= nfp_abm_port_get_stats
,
545 .port_get_stats_count
= nfp_abm_port_get_stats_count
,
546 .port_get_stats_strings
= nfp_abm_port_get_stats_strings
,
548 .setup_tc
= nfp_abm_setup_tc
,
550 .eswitch_mode_get
= nfp_abm_eswitch_mode_get
,
551 .eswitch_mode_set
= nfp_abm_eswitch_mode_set
,
553 .dev_get
= nfp_abm_repr_get
,