]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c
i40e: reset all VFs in parallel when rebuilding PF
[karo-tx-linux.git] / drivers / net / ethernet / intel / i40e / i40e_virtchnl_pf.c
index 78460c52b7c445112cd777385f0e81058f26e918..350cba70490c3ba32c2113f303651314da4a97b6 100644 (file)
@@ -702,10 +702,8 @@ static int i40e_alloc_vsi_res(struct i40e_vf *vf, enum i40e_vsi_type type)
                        dev_info(&pf->pdev->dev,
                                 "Could not allocate VF broadcast filter\n");
                spin_unlock_bh(&vsi->mac_filter_hash_lock);
-               i40e_write_rx_ctl(&pf->hw, I40E_VFQF_HENA1(0, vf->vf_id),
-                                 (u32)hena);
-               i40e_write_rx_ctl(&pf->hw, I40E_VFQF_HENA1(1, vf->vf_id),
-                                 (u32)(hena >> 32));
+               wr32(&pf->hw, I40E_VFQF_HENA1(0, vf->vf_id), (u32)hena);
+               wr32(&pf->hw, I40E_VFQF_HENA1(1, vf->vf_id), (u32)(hena >> 32));
        }
 
        /* program mac filter */
@@ -811,6 +809,11 @@ static void i40e_free_vf_res(struct i40e_vf *vf)
        u32 reg_idx, reg;
        int i, msix_vf;
 
+       /* Start by disabling VF's configuration API to prevent the OS from
+        * accessing the VF's VSI after it's freed / invalidated.
+        */
+       clear_bit(I40E_VF_STAT_INIT, &vf->vf_states);
+
        /* free vsi & disconnect it from the parent uplink */
        if (vf->lan_vsi_idx) {
                i40e_vsi_release(pf->vsi[vf->lan_vsi_idx]);
@@ -850,7 +853,6 @@ static void i40e_free_vf_res(struct i40e_vf *vf)
        /* reset some of the state variables keeping track of the resources */
        vf->num_queue_pairs = 0;
        vf->vf_states = 0;
-       clear_bit(I40E_VF_STAT_INIT, &vf->vf_states);
 }
 
 /**
@@ -921,26 +923,31 @@ static int i40e_quiesce_vf_pci(struct i40e_vf *vf)
 }
 
 /**
- * i40e_reset_vf
+ * i40e_trigger_vf_reset
  * @vf: pointer to the VF structure
  * @flr: VFLR was issued or not
  *
- * reset the VF
+ * Trigger hardware to start a reset for a particular VF. Expects the caller
+ * to wait the proper amount of time to allow hardware to reset the VF before
+ * it cleans up and restores VF functionality.
  **/
-void i40e_reset_vf(struct i40e_vf *vf, bool flr)
+static void i40e_trigger_vf_reset(struct i40e_vf *vf, bool flr)
 {
        struct i40e_pf *pf = vf->pf;
        struct i40e_hw *hw = &pf->hw;
        u32 reg, reg_idx, bit_idx;
-       bool rsd = false;
-       int i;
-
-       if (test_and_set_bit(__I40E_VF_DISABLE, &pf->state))
-               return;
 
        /* warn the VF */
        clear_bit(I40E_VF_STAT_ACTIVE, &vf->vf_states);
 
+       /* Disable VF's configuration API during reset. The flag is re-enabled
+        * in i40e_alloc_vf_res(), when it's safe again to access VF's VSI.
+        * It's normally disabled in i40e_free_vf_res(), but it's safer
+        * to do it earlier to give some time to finish to any VF config
+        * functions that may still be running at this point.
+        */
+       clear_bit(I40E_VF_STAT_INIT, &vf->vf_states);
+
        /* In the case of a VFLR, the HW has already reset the VF and we
         * just need to clean up, so don't hit the VFRTRIG register.
         */
@@ -960,6 +967,78 @@ void i40e_reset_vf(struct i40e_vf *vf, bool flr)
        if (i40e_quiesce_vf_pci(vf))
                dev_err(&pf->pdev->dev, "VF %d PCI transactions stuck\n",
                        vf->vf_id);
+}
+
+/**
+ * i40e_cleanup_reset_vf
+ * @vf: pointer to the VF structure
+ *
+ * Cleanup a VF after the hardware reset is finished. Expects the caller to
+ * have verified whether the reset is finished properly, and ensure the
+ * minimum amount of wait time has passed.
+ **/
+static void i40e_cleanup_reset_vf(struct i40e_vf *vf)
+{
+       struct i40e_pf *pf = vf->pf;
+       struct i40e_hw *hw = &pf->hw;
+       u32 reg;
+
+       /* free VF resources to begin resetting the VSI state */
+       i40e_free_vf_res(vf);
+
+       /* Enable hardware by clearing the reset bit in the VPGEN_VFRTRIG reg.
+        * By doing this we allow HW to access VF memory at any point. If we
+        * did it any sooner, HW could access memory while it was being freed
+        * in i40e_free_vf_res(), causing an IOMMU fault.
+        *
+        * On the other hand, this needs to be done ASAP, because the VF driver
+        * is waiting for this to happen and may report a timeout. It's
+        * harmless, but it gets logged into Guest OS kernel log, so best avoid
+        * it.
+        */
+       reg = rd32(hw, I40E_VPGEN_VFRTRIG(vf->vf_id));
+       reg &= ~I40E_VPGEN_VFRTRIG_VFSWR_MASK;
+       wr32(hw, I40E_VPGEN_VFRTRIG(vf->vf_id), reg);
+
+       /* reallocate VF resources to finish resetting the VSI state */
+       if (!i40e_alloc_vf_res(vf)) {
+               int abs_vf_id = vf->vf_id + hw->func_caps.vf_base_id;
+               i40e_enable_vf_mappings(vf);
+               set_bit(I40E_VF_STAT_ACTIVE, &vf->vf_states);
+               clear_bit(I40E_VF_STAT_DISABLED, &vf->vf_states);
+               /* Do not notify the client during VF init */
+               if (vf->pf->num_alloc_vfs)
+                       i40e_notify_client_of_vf_reset(pf, abs_vf_id);
+               vf->num_vlan = 0;
+       }
+
+       /* Tell the VF driver the reset is done. This needs to be done only
+        * after VF has been fully initialized, because the VF driver may
+        * request resources immediately after setting this flag.
+        */
+       wr32(hw, I40E_VFGEN_RSTAT1(vf->vf_id), I40E_VFR_VFACTIVE);
+}
+
+/**
+ * i40e_reset_vf
+ * @vf: pointer to the VF structure
+ * @flr: VFLR was issued or not
+ *
+ * reset the VF
+ **/
+void i40e_reset_vf(struct i40e_vf *vf, bool flr)
+{
+       struct i40e_pf *pf = vf->pf;
+       struct i40e_hw *hw = &pf->hw;
+       bool rsd = false;
+       u32 reg;
+       int i;
+
+       /* If VFs have been disabled, there is no need to reset */
+       if (test_and_set_bit(__I40E_VF_DISABLE, &pf->state))
+               return;
+
+       i40e_trigger_vf_reset(vf, flr);
 
        /* poll VPGEN_VFRSTAT reg to make sure
         * that reset is complete
@@ -984,32 +1063,113 @@ void i40e_reset_vf(struct i40e_vf *vf, bool flr)
        if (!rsd)
                dev_err(&pf->pdev->dev, "VF reset check timeout on VF %d\n",
                        vf->vf_id);
-       wr32(hw, I40E_VFGEN_RSTAT1(vf->vf_id), I40E_VFR_COMPLETED);
-       /* clear the reset bit in the VPGEN_VFRTRIG reg */
-       reg = rd32(hw, I40E_VPGEN_VFRTRIG(vf->vf_id));
-       reg &= ~I40E_VPGEN_VFRTRIG_VFSWR_MASK;
-       wr32(hw, I40E_VPGEN_VFRTRIG(vf->vf_id), reg);
+       usleep_range(10000, 20000);
 
-       /* On initial reset, we won't have any queues */
-       if (vf->lan_vsi_idx == 0)
-               goto complete_reset;
+       /* On initial reset, we don't have any queues to disable */
+       if (vf->lan_vsi_idx != 0)
+               i40e_vsi_stop_rings(pf->vsi[vf->lan_vsi_idx]);
 
-       i40e_vsi_stop_rings(pf->vsi[vf->lan_vsi_idx]);
-complete_reset:
-       /* reallocate VF resources to reset the VSI state */
-       i40e_free_vf_res(vf);
-       if (!i40e_alloc_vf_res(vf)) {
-               int abs_vf_id = vf->vf_id + hw->func_caps.vf_base_id;
-               i40e_enable_vf_mappings(vf);
-               set_bit(I40E_VF_STAT_ACTIVE, &vf->vf_states);
-               clear_bit(I40E_VF_STAT_DISABLED, &vf->vf_states);
-               /* Do not notify the client during VF init */
-               if (vf->pf->num_alloc_vfs)
-                       i40e_notify_client_of_vf_reset(pf, abs_vf_id);
-               vf->num_vlan = 0;
+       i40e_cleanup_reset_vf(vf);
+
+       i40e_flush(hw);
+       clear_bit(__I40E_VF_DISABLE, &pf->state);
+}
+
+/**
+ * i40e_reset_all_vfs
+ * @pf: pointer to the PF structure
+ * @flr: VFLR was issued or not
+ *
+ * Reset all allocated VFs in one go. First, tell the hardware to reset each
+ * VF, then do all the waiting in one chunk, and finally finish restoring each
+ * VF after the wait. This is useful during PF routines which need to reset
+ * all VFs, as otherwise it must perform these resets in a serialized fashion.
+ **/
+void i40e_reset_all_vfs(struct i40e_pf *pf, bool flr)
+{
+       struct i40e_hw *hw = &pf->hw;
+       struct i40e_vf *vf;
+       int i, v;
+       u32 reg;
+
+       /* If we don't have any VFs, then there is nothing to reset */
+       if (!pf->num_alloc_vfs)
+               return;
+
+       /* If VFs have been disabled, there is no need to reset */
+       if (test_and_set_bit(__I40E_VF_DISABLE, &pf->state))
+               return;
+
+       /* Begin reset on all VFs at once */
+       for (v = 0; v < pf->num_alloc_vfs; v++)
+               i40e_trigger_vf_reset(&pf->vf[v], flr);
+
+       /* HW requires some time to make sure it can flush the FIFO for a VF
+        * when it resets it. Poll the VPGEN_VFRSTAT register for each VF in
+        * sequence to make sure that it has completed. We'll keep track of
+        * the VFs using a simple iterator that increments once that VF has
+        * finished resetting.
+        */
+       for (i = 0, v = 0; i < 10 && v < pf->num_alloc_vfs; i++) {
+               usleep_range(10000, 20000);
+
+               /* Check each VF in sequence, beginning with the VF to fail
+                * the previous check.
+                */
+               while (v < pf->num_alloc_vfs) {
+                       vf = &pf->vf[v];
+                       reg = rd32(hw, I40E_VPGEN_VFRSTAT(vf->vf_id));
+                       if (!(reg & I40E_VPGEN_VFRSTAT_VFRD_MASK))
+                               break;
+
+                       /* If the current VF has finished resetting, move on
+                        * to the next VF in sequence.
+                        */
+                       v++;
+               }
        }
-       /* tell the VF the reset is done */
-       wr32(hw, I40E_VFGEN_RSTAT1(vf->vf_id), I40E_VFR_VFACTIVE);
+
+       if (flr)
+               usleep_range(10000, 20000);
+
+       /* Display a warning if at least one VF didn't manage to reset in
+        * time, but continue on with the operation.
+        */
+       if (v < pf->num_alloc_vfs)
+               dev_err(&pf->pdev->dev, "VF reset check timeout on VF %d\n",
+                       pf->vf[v].vf_id);
+       usleep_range(10000, 20000);
+
+       /* Begin disabling all the rings associated with VFs, but do not wait
+        * between each VF.
+        */
+       for (v = 0; v < pf->num_alloc_vfs; v++) {
+               /* On initial reset, we don't have any queues to disable */
+               if (pf->vf[v].lan_vsi_idx == 0)
+                       continue;
+
+               i40e_vsi_stop_rings_no_wait(pf->vsi[pf->vf[v].lan_vsi_idx]);
+       }
+
+       /* Now that we've notified HW to disable all of the VF rings, wait
+        * until they finish.
+        */
+       for (v = 0; v < pf->num_alloc_vfs; v++) {
+               /* On initial reset, we don't have any queues to disable */
+               if (pf->vf[v].lan_vsi_idx == 0)
+                       continue;
+
+               i40e_vsi_wait_queues_disabled(pf->vsi[pf->vf[v].lan_vsi_idx]);
+       }
+
+       /* Hw may need up to 50ms to finish disabling the RX queues. We
+        * minimize the wait by delaying only once for all VFs.
+        */
+       mdelay(50);
+
+       /* Finish the reset on each VF */
+       for (v = 0; v < pf->num_alloc_vfs; v++)
+               i40e_cleanup_reset_vf(&pf->vf[v]);
 
        i40e_flush(hw);
        clear_bit(__I40E_VF_DISABLE, &pf->state);
@@ -1359,7 +1519,7 @@ static int i40e_vc_get_vf_resources_msg(struct i40e_vf *vf, u8 *msg)
        if (!vsi->info.pvid)
                vfres->vf_offload_flags |= I40E_VIRTCHNL_VF_OFFLOAD_VLAN;
 
-       if (i40e_vf_client_capable(pf, vf->vf_id, I40E_CLIENT_IWARP) &&
+       if (i40e_vf_client_capable(pf, vf->vf_id) &&
            (vf->driver_caps & I40E_VIRTCHNL_VF_OFFLOAD_IWARP)) {
                vfres->vf_offload_flags |= I40E_VIRTCHNL_VF_OFFLOAD_IWARP;
                set_bit(I40E_VF_STAT_IWARPENA, &vf->vf_states);
@@ -1383,6 +1543,13 @@ static int i40e_vc_get_vf_resources_msg(struct i40e_vf *vf, u8 *msg)
                                I40E_VIRTCHNL_VF_OFFLOAD_RSS_PCTYPE_V2;
        }
 
+       if (vf->driver_caps & I40E_VIRTCHNL_VF_OFFLOAD_ENCAP)
+               vfres->vf_offload_flags |= I40E_VIRTCHNL_VF_OFFLOAD_ENCAP;
+
+       if ((pf->flags & I40E_FLAG_OUTER_UDP_CSUM_CAPABLE) &&
+           (vf->driver_caps & I40E_VIRTCHNL_VF_OFFLOAD_ENCAP_CSUM))
+               vfres->vf_offload_flags |= I40E_VIRTCHNL_VF_OFFLOAD_ENCAP_CSUM;
+
        if (vf->driver_caps & I40E_VIRTCHNL_VF_OFFLOAD_RX_POLLING) {
                if (pf->flags & I40E_FLAG_MFP_ENABLED) {
                        dev_err(&pf->pdev->dev,
@@ -1853,7 +2020,7 @@ error_param:
 }
 
 /* If the VF is not trusted restrict the number of MAC/VLAN it can program */
-#define I40E_VC_MAX_MAC_ADDR_PER_VF 8
+#define I40E_VC_MAX_MAC_ADDR_PER_VF 12
 #define I40E_VC_MAX_VLAN_PER_VF 8
 
 /**