return;
 
        /* Clear the __I40E_HANG_CHECK_ARMED bit for all Tx rings */
-       for (v = 0; v < pf->hw.func_caps.num_vsis; v++) {
+       for (v = 0; v < pf->num_alloc_vsi; v++) {
                struct i40e_vsi *vsi = pf->vsi[v];
 
                if (!vsi || !vsi->tx_rings[0])
        }
 
        /* Clear the __I40E_HANG_CHECK_ARMED bit for Tx rings */
-       for (v = 0; v < pf->hw.func_caps.num_vsis; v++) {
+       for (v = 0; v < pf->num_alloc_vsi; v++) {
                struct i40e_vsi *vsi = pf->vsi[v];
 
                if (!vsi || !vsi->tx_rings[0])
                return;
        pf->flags &= ~I40E_FLAG_FILTER_SYNC;
 
-       for (v = 0; v < pf->hw.func_caps.num_vsis; v++) {
+       for (v = 0; v < pf->num_alloc_vsi; v++) {
                if (pf->vsi[v] &&
                    (pf->vsi[v]->flags & I40E_VSI_FLAG_FILTER_CHANGED))
                        i40e_sync_vsi_filters(pf->vsi[v]);
        int i;
 
        i40e_put_lump(pf->irq_pile, 0, I40E_PILE_VALID_BIT-1);
-       for (i = 0; i < pf->hw.func_caps.num_vsis; i++)
+       for (i = 0; i < pf->num_alloc_vsi; i++)
                if (pf->vsi[i])
                        i40e_vsi_free_q_vectors(pf->vsi[i]);
        i40e_reset_interrupt_capability(pf);
 {
        int v;
 
-       for (v = 0; v < pf->hw.func_caps.num_vsis; v++) {
+       for (v = 0; v < pf->num_alloc_vsi; v++) {
                if (pf->vsi[v])
                        i40e_quiesce_vsi(pf->vsi[v]);
        }
 {
        int v;
 
-       for (v = 0; v < pf->hw.func_caps.num_vsis; v++) {
+       for (v = 0; v < pf->num_alloc_vsi; v++) {
                if (pf->vsi[v])
                        i40e_unquiesce_vsi(pf->vsi[v]);
        }
        }
 
        /* Update each VSI */
-       for (v = 0; v < pf->hw.func_caps.num_vsis; v++) {
+       for (v = 0; v < pf->num_alloc_vsi; v++) {
                if (!pf->vsi[v])
                        continue;
 
                /* Find the VSI(s) that requested a re-init */
                dev_info(&pf->pdev->dev,
                         "VSI reinit requested\n");
-               for (v = 0; v < pf->hw.func_caps.num_vsis; v++) {
+               for (v = 0; v < pf->num_alloc_vsi; v++) {
                        struct i40e_vsi *vsi = pf->vsi[v];
                        if (vsi != NULL &&
                            test_bit(__I40E_REINIT_REQUESTED, &vsi->state)) {
                        i40e_veb_link_event(pf->veb[i], link_up);
 
        /* ... now the local VSIs */
-       for (i = 0; i < pf->hw.func_caps.num_vsis; i++)
+       for (i = 0; i < pf->num_alloc_vsi; i++)
                if (pf->vsi[i] && (pf->vsi[i]->uplink_seid == veb->seid))
                        i40e_vsi_link_event(pf->vsi[i], link_up);
 }
         *     for each q_vector
         *         force an interrupt
         */
-       for (v = 0; v < pf->hw.func_caps.num_vsis; v++) {
+       for (v = 0; v < pf->num_alloc_vsi; v++) {
                struct i40e_vsi *vsi = pf->vsi[v];
                int armed = 0;
 
        /* Update the stats for active netdevs so the network stack
         * can look at updated numbers whenever it cares to
         */
-       for (i = 0; i < pf->hw.func_caps.num_vsis; i++)
+       for (i = 0; i < pf->num_alloc_vsi; i++)
                if (pf->vsi[i] && pf->vsi[i]->netdev)
                        i40e_update_stats(pf->vsi[i]);
 
        int ret;
 
        /* build VSI that owns this VEB, temporarily attached to base VEB */
-       for (v = 0; v < pf->hw.func_caps.num_vsis && !ctl_vsi; v++) {
+       for (v = 0; v < pf->num_alloc_vsi && !ctl_vsi; v++) {
                if (pf->vsi[v] &&
                    pf->vsi[v]->veb_idx == veb->idx &&
                    pf->vsi[v]->flags & I40E_VSI_FLAG_VEB_OWNER) {
                goto end_reconstitute;
 
        /* create the remaining VSIs attached to this VEB */
-       for (v = 0; v < pf->hw.func_caps.num_vsis; v++) {
+       for (v = 0; v < pf->num_alloc_vsi; v++) {
                if (!pf->vsi[v] || pf->vsi[v] == ctl_vsi)
                        continue;
 
 
        /* find existing VSI and see if it needs configuring */
        vsi = NULL;
-       for (i = 0; i < pf->hw.func_caps.num_vsis; i++) {
+       for (i = 0; i < pf->num_alloc_vsi; i++) {
                if (pf->vsi[i] && pf->vsi[i]->type == I40E_VSI_FDIR) {
                        vsi = pf->vsi[i];
                        break;
        int i;
 
        i40e_fdir_filter_exit(pf);
-       for (i = 0; i < pf->hw.func_caps.num_vsis; i++) {
+       for (i = 0; i < pf->num_alloc_vsi; i++) {
                if (pf->vsi[i] && pf->vsi[i]->type == I40E_VSI_FDIR) {
                        i40e_vsi_release(pf->vsi[i]);
                        break;
        /* quiesce the VSIs and their queues that are not already DOWN */
        i40e_pf_quiesce_all_vsi(pf);
 
-       for (v = 0; v < pf->hw.func_caps.num_vsis; v++) {
+       for (v = 0; v < pf->num_alloc_vsi; v++) {
                if (pf->vsi[v])
                        pf->vsi[v]->seid = 0;
        }
         * find next empty vsi slot, looping back around if necessary
         */
        i = pf->next_vsi;
-       while (i < pf->hw.func_caps.num_vsis && pf->vsi[i])
+       while (i < pf->num_alloc_vsi && pf->vsi[i])
                i++;
-       if (i >= pf->hw.func_caps.num_vsis) {
+       if (i >= pf->num_alloc_vsi) {
                i = 0;
                while (i < pf->next_vsi && pf->vsi[i])
                        i++;
        }
 
-       if (i < pf->hw.func_caps.num_vsis && !pf->vsi[i]) {
+       if (i < pf->num_alloc_vsi && !pf->vsi[i]) {
                vsi_idx = i;             /* Found one! */
        } else {
                ret = -ENODEV;
         * the orphan VEBs yet.  We'll wait for an explicit remove request
         * from up the network stack.
         */
-       for (n = 0, i = 0; i < pf->hw.func_caps.num_vsis; i++) {
+       for (n = 0, i = 0; i < pf->num_alloc_vsi; i++) {
                if (pf->vsi[i] &&
                    pf->vsi[i]->uplink_seid == uplink_seid &&
                    (pf->vsi[i]->flags & I40E_VSI_FLAG_VEB_OWNER) == 0) {
 
        if (!veb && uplink_seid != pf->mac_seid) {
 
-               for (i = 0; i < pf->hw.func_caps.num_vsis; i++) {
+               for (i = 0; i < pf->num_alloc_vsi; i++) {
                        if (pf->vsi[i] && pf->vsi[i]->seid == uplink_seid) {
                                vsi = pf->vsi[i];
                                break;
         * NOTE: Removing the last VSI on a VEB has the SIDE EFFECT of removing
         *       the VEB itself, so don't use (*branch) after this loop.
         */
-       for (i = 0; i < pf->hw.func_caps.num_vsis; i++) {
+       for (i = 0; i < pf->num_alloc_vsi; i++) {
                if (!pf->vsi[i])
                        continue;
                if (pf->vsi[i]->uplink_seid == branch_seid &&
        pf = veb->pf;
 
        /* find the remaining VSI and check for extras */
-       for (i = 0; i < pf->hw.func_caps.num_vsis; i++) {
+       for (i = 0; i < pf->num_alloc_vsi; i++) {
                if (pf->vsi[i] && pf->vsi[i]->uplink_seid == veb->seid) {
                        n++;
                        vsi = pf->vsi[i];
        }
 
        /* make sure there is such a vsi and uplink */
-       for (vsi_idx = 0; vsi_idx < pf->hw.func_caps.num_vsis; vsi_idx++)
+       for (vsi_idx = 0; vsi_idx < pf->num_alloc_vsi; vsi_idx++)
                if (pf->vsi[vsi_idx] && pf->vsi[vsi_idx]->seid == vsi_seid)
                        break;
-       if (vsi_idx >= pf->hw.func_caps.num_vsis && vsi_seid != 0) {
+       if (vsi_idx >= pf->num_alloc_vsi && vsi_seid != 0) {
                dev_info(&pf->pdev->dev, "vsi seid %d not found\n",
                         vsi_seid);
                return NULL;
        i40e_determine_queue_usage(pf);
        i40e_init_interrupt_scheme(pf);
 
-       /* Set up the *vsi struct based on the number of VSIs in the HW,
-        * and set up our local tracking of the MAIN PF vsi.
+       /* The number of VSIs reported by the FW is the minimum guaranteed
+        * to us; HW supports far more and we share the remaining pool with
+        * the other PFs. We allocate space for more than the guarantee with
+        * the understanding that we might not get them all later.
         */
-       len = sizeof(struct i40e_vsi *) * pf->hw.func_caps.num_vsis;
+       if (pf->hw.func_caps.num_vsis < I40E_MIN_VSI_ALLOC)
+               pf->num_alloc_vsi = I40E_MIN_VSI_ALLOC;
+       else
+               pf->num_alloc_vsi = pf->hw.func_caps.num_vsis;
+
+       /* Set up the *vsi struct and our local tracking of the MAIN PF vsi. */
+       len = sizeof(struct i40e_vsi *) * pf->num_alloc_vsi;
        pf->vsi = kzalloc(len, GFP_KERNEL);
        if (!pf->vsi) {
                err = -ENOMEM;
                goto err_vsis;
        }
        /* if FDIR VSI was set up, start it now */
-       for (i = 0; i < pf->hw.func_caps.num_vsis; i++) {
+       for (i = 0; i < pf->num_alloc_vsi; i++) {
                if (pf->vsi[i] && pf->vsi[i]->type == I40E_VSI_FDIR) {
                        i40e_vsi_open(pf->vsi[i]);
                        break;
 
        /* Clear all dynamic memory lists of rings, q_vectors, and VSIs */
        i40e_clear_interrupt_scheme(pf);
-       for (i = 0; i < pf->hw.func_caps.num_vsis; i++) {
+       for (i = 0; i < pf->num_alloc_vsi; i++) {
                if (pf->vsi[i]) {
                        i40e_vsi_clear_rings(pf->vsi[i]);
                        i40e_vsi_clear(pf->vsi[i]);