nfp: abm: calculate PRIO map len and check mailbox size

In preparation for PRIO offload calculate how long the prio map
for FW will be and make sure the configuration can be performed
via the vNIC mailbox.

Signed-off-by: Jakub Kicinski <jakub.kicinski@netronome.com>
Reviewed-by: John Hurley <john.hurley@netronome.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
Jakub Kicinski 2018-11-19 15:21:47 -08:00 committed by David S. Miller
parent 068ceb3555
commit 14780c3429
3 changed files with 50 additions and 3 deletions

View File

@ -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 ||

View File

@ -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;

View File

@ -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,