nfp: abm: calculate PRIO map len and check mailbox size
authorJakub Kicinski <jakub.kicinski@netronome.com>
Mon, 19 Nov 2018 23:21:47 +0000 (15:21 -0800)
committerDavid S. Miller <davem@davemloft.net>
Tue, 20 Nov 2018 02:53:46 +0000 (18:53 -0800)
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>
drivers/net/ethernet/netronome/nfp/abm/ctrl.c
drivers/net/ethernet/netronome/nfp/abm/main.c
drivers/net/ethernet/netronome/nfp/abm/main.h

index 10a571b5b565953259f2c8e16b94e3c583e52ab0..ef10a2e730bcf97a836e40b0ef4f9bc9704e2914 100644 (file)
 #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 ||
index 4f95f7b4430bc4cd036f827651eb02dc2c7c243e..aeb0c9a1f2602032b2a293fab3186c3dcf946b3b 100644 (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;
index 6bb4e60c1ad8eabf1411a0c8a415d982355dc74e..1ca2768cd5a220d50be83e8a7f115bc822f65803 100644 (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,