sfc: Avoid generating over-length MC_CMD_FLUSH_RX_QUEUES request
authorBen Hutchings <bhutchings@solarflare.com>
Wed, 19 Sep 2012 01:53:34 +0000 (02:53 +0100)
committerBen Hutchings <bhutchings@solarflare.com>
Wed, 19 Sep 2012 01:56:25 +0000 (02:56 +0100)
MCDI supports requests up to 252 bytes long, which is only enough to
pass 63 RX queue IDs to MC_CMD_FLUSH_RX_QUEUES.  However a VF may have
up to 64 RX queues, and if we try to flush them all we will generate
an over-length request and BUG() in efx_mcdi_copyin().  Currently
all VF drivers limit themselves to 32 RX queues, so reducing the
limit to 63 does no harm.

Also add a BUILD_BUG_ON in efx_mcdi_flush_rxqs() so we remember to
deal with the same problem there if EFX_MAX_CHANNELS is increased.

Signed-off-by: Ben Hutchings <bhutchings@solarflare.com>
drivers/net/ethernet/sfc/mcdi.c
drivers/net/ethernet/sfc/siena_sriov.c

index e855f4cddb4ebcb30261fe53abe0b65070d0d4f8..aea43cbd05200acc1f19cd21e9f96d9e26782ca2 100644 (file)
@@ -1195,6 +1195,9 @@ int efx_mcdi_flush_rxqs(struct efx_nic *efx)
        __le32 *qid;
        int rc, count;
 
+       BUILD_BUG_ON(EFX_MAX_CHANNELS >
+                    MC_CMD_FLUSH_RX_QUEUES_IN_QID_OFST_MAXNUM);
+
        qid = kmalloc(EFX_MAX_CHANNELS * sizeof(*qid), GFP_KERNEL);
        if (qid == NULL)
                return -ENOMEM;
index 9cb3b84ecae99a24553f0bd039d5a5fdbaafbd8e..a8f48a455849ec26619c392bda0ce504ffabca2b 100644 (file)
@@ -21,6 +21,9 @@
 /* Number of longs required to track all the VIs in a VF */
 #define VI_MASK_LENGTH BITS_TO_LONGS(1 << EFX_VI_SCALE_MAX)
 
+/* Maximum number of RX queues supported */
+#define VF_MAX_RX_QUEUES 63
+
 /**
  * enum efx_vf_tx_filter_mode - TX MAC filtering behaviour
  * @VF_TX_FILTER_OFF: Disabled
@@ -578,6 +581,7 @@ static int efx_vfdi_init_rxq(struct efx_vf *vf)
        efx_oword_t reg;
 
        if (bad_vf_index(efx, vf_evq) || bad_vf_index(efx, vf_rxq) ||
+           vf_rxq >= VF_MAX_RX_QUEUES ||
            bad_buf_count(buf_count, EFX_MAX_DMAQ_SIZE)) {
                if (net_ratelimit())
                        netif_err(efx, hw, efx->net_dev,
@@ -683,6 +687,9 @@ static int efx_vfdi_fini_all_queues(struct efx_vf *vf)
        __le32 *rxqs;
        int rc;
 
+       BUILD_BUG_ON(VF_MAX_RX_QUEUES >
+                    MC_CMD_FLUSH_RX_QUEUES_IN_QID_OFST_MAXNUM);
+
        rxqs = kmalloc(count * sizeof(*rxqs), GFP_KERNEL);
        if (rxqs == NULL)
                return VFDI_RC_ENOMEM;