diff --git a/drivers/net/ethernet/netronome/nfp/abm/ctrl.c b/drivers/net/ethernet/netronome/nfp/abm/ctrl.c index 10a571b5b565..ef10a2e730bc 100644 --- a/drivers/net/ethernet/netronome/nfp/abm/ctrl.c +++ b/drivers/net/ethernet/netronome/nfp/abm/ctrl.c @@ -33,6 +33,12 @@ #define NFP_Q_STAT_PKTS 0 #define NFP_Q_STAT_BYTES 8 +#define NFP_NET_ABM_MBOX_CMD NFP_NET_CFG_MBOX_SIMPLE_CMD +#define NFP_NET_ABM_MBOX_RET NFP_NET_CFG_MBOX_SIMPLE_RET +#define NFP_NET_ABM_MBOX_DATALEN NFP_NET_CFG_MBOX_SIMPLE_VAL +#define NFP_NET_ABM_MBOX_RESERVED (NFP_NET_CFG_MBOX_SIMPLE_VAL + 4) +#define NFP_NET_ABM_MBOX_DATA (NFP_NET_CFG_MBOX_SIMPLE_VAL + 8) + static int nfp_abm_ctrl_stat(struct nfp_abm_link *alink, const struct nfp_rtsym *sym, unsigned int stride, unsigned int offset, unsigned int band, @@ -215,10 +221,42 @@ int nfp_abm_ctrl_qm_disable(struct nfp_abm *abm) NULL, 0, NULL, 0); } -void nfp_abm_ctrl_read_params(struct nfp_abm_link *alink) +static int nfp_abm_ctrl_prio_check_params(struct nfp_abm_link *alink) +{ + struct nfp_abm *abm = alink->abm; + struct nfp_net *nn = alink->vnic; + unsigned int min_mbox_sz; + + if (!nfp_abm_has_prio(alink->abm)) + return 0; + + min_mbox_sz = NFP_NET_ABM_MBOX_DATA + alink->abm->prio_map_len; + if (nn->tlv_caps.mbox_len < min_mbox_sz) { + nfp_err(abm->app->pf->cpp, "vNIC mailbox too small for prio offload: %u, need: %u\n", + nn->tlv_caps.mbox_len, min_mbox_sz); + return -EINVAL; + } + + return 0; +} + +int nfp_abm_ctrl_read_params(struct nfp_abm_link *alink) { alink->queue_base = nn_readl(alink->vnic, NFP_NET_CFG_START_RXQ); alink->queue_base /= alink->vnic->stride_rx; + + return nfp_abm_ctrl_prio_check_params(alink); +} + +static unsigned int nfp_abm_ctrl_prio_map_size(struct nfp_abm *abm) +{ + unsigned int size; + + size = roundup_pow_of_two(order_base_2(abm->num_bands)); + size = DIV_ROUND_UP(size * abm->num_prios, BITS_PER_BYTE); + size = round_up(size, sizeof(u32)); + + return size; } static const struct nfp_rtsym * @@ -273,6 +311,8 @@ int nfp_abm_ctrl_find_addrs(struct nfp_abm *abm) return res; abm->num_prios = res; + abm->prio_map_len = nfp_abm_ctrl_prio_map_size(abm); + /* Check values are sane, U16_MAX is arbitrarily chosen as max */ if (!is_power_of_2(abm->num_bands) || !is_power_of_2(abm->num_prios) || abm->num_bands > U16_MAX || abm->num_prios > U16_MAX || diff --git a/drivers/net/ethernet/netronome/nfp/abm/main.c b/drivers/net/ethernet/netronome/nfp/abm/main.c index 4f95f7b4430b..aeb0c9a1f260 100644 --- a/drivers/net/ethernet/netronome/nfp/abm/main.c +++ b/drivers/net/ethernet/netronome/nfp/abm/main.c @@ -315,6 +315,10 @@ nfp_abm_vnic_alloc(struct nfp_app *app, struct nfp_net *nn, unsigned int id) alink->id = id; alink->total_queues = alink->vnic->max_rx_rings; + err = nfp_abm_ctrl_read_params(alink); + if (err) + goto err_free_alink; + /* This is a multi-host app, make sure MAC/PHY is up, but don't * make the MAC/PHY state follow the state of any of the ports. */ @@ -325,7 +329,6 @@ nfp_abm_vnic_alloc(struct nfp_app *app, struct nfp_net *nn, unsigned int id) netif_keep_dst(nn->dp.netdev); nfp_abm_vnic_set_mac(app->pf, abm, nn, id); - nfp_abm_ctrl_read_params(alink); INIT_RADIX_TREE(&alink->qdiscs, GFP_KERNEL); return 0; diff --git a/drivers/net/ethernet/netronome/nfp/abm/main.h b/drivers/net/ethernet/netronome/nfp/abm/main.h index 6bb4e60c1ad8..1ca2768cd5a2 100644 --- a/drivers/net/ethernet/netronome/nfp/abm/main.h +++ b/drivers/net/ethernet/netronome/nfp/abm/main.h @@ -34,9 +34,11 @@ struct nfp_net; * @thresholds: current threshold configuration * @threshold_undef: bitmap of thresholds which have not been set * @num_thresholds: number of @thresholds and bits in @threshold_undef + * @prio_map_len: computed length of FW priority map (in bytes) * * @eswitch_mode: devlink eswitch mode, advanced functions only visible * in switchdev mode + * * @q_lvls: queue level control area * @qm_stats: queue statistics symbol * @q_stats: basic queue statistics (only in per-band case) @@ -51,8 +53,10 @@ struct nfp_abm { u32 *thresholds; unsigned long *threshold_undef; size_t num_thresholds; + unsigned int prio_map_len; enum devlink_eswitch_mode eswitch_mode; + const struct nfp_rtsym *q_lvls; const struct nfp_rtsym *qm_stats; const struct nfp_rtsym *q_stats; @@ -201,7 +205,7 @@ int nfp_abm_setup_tc_mq(struct net_device *netdev, struct nfp_abm_link *alink, int nfp_abm_setup_tc_gred(struct net_device *netdev, struct nfp_abm_link *alink, struct tc_gred_qopt_offload *opt); -void nfp_abm_ctrl_read_params(struct nfp_abm_link *alink); +int nfp_abm_ctrl_read_params(struct nfp_abm_link *alink); int nfp_abm_ctrl_find_addrs(struct nfp_abm *abm); int __nfp_abm_ctrl_set_q_lvl(struct nfp_abm *abm, unsigned int id, u32 val); int nfp_abm_ctrl_set_q_lvl(struct nfp_abm_link *alink, unsigned int band,