|
|
@@ -101,130 +101,6 @@ static u16 i40e_vc_get_pf_queue_id(struct i40e_vf *vf, u8 vsi_idx,
|
|
|
return pf_queue_id;
|
|
|
}
|
|
|
|
|
|
-/**
|
|
|
- * i40e_ctrl_vsi_tx_queue
|
|
|
- * @vf: pointer to the vf info
|
|
|
- * @vsi_idx: index of VSI in PF struct
|
|
|
- * @vsi_queue_id: vsi relative queue index
|
|
|
- * @ctrl: control flags
|
|
|
- *
|
|
|
- * enable/disable/enable check/disable check
|
|
|
- **/
|
|
|
-static int i40e_ctrl_vsi_tx_queue(struct i40e_vf *vf, u16 vsi_idx,
|
|
|
- u16 vsi_queue_id,
|
|
|
- enum i40e_queue_ctrl ctrl)
|
|
|
-{
|
|
|
- struct i40e_pf *pf = vf->pf;
|
|
|
- struct i40e_hw *hw = &pf->hw;
|
|
|
- bool writeback = false;
|
|
|
- u16 pf_queue_id;
|
|
|
- int ret = 0;
|
|
|
- u32 reg;
|
|
|
-
|
|
|
- pf_queue_id = i40e_vc_get_pf_queue_id(vf, vsi_idx, vsi_queue_id);
|
|
|
- reg = rd32(hw, I40E_QTX_ENA(pf_queue_id));
|
|
|
-
|
|
|
- switch (ctrl) {
|
|
|
- case I40E_QUEUE_CTRL_ENABLE:
|
|
|
- reg |= I40E_QTX_ENA_QENA_REQ_MASK;
|
|
|
- writeback = true;
|
|
|
- break;
|
|
|
- case I40E_QUEUE_CTRL_ENABLECHECK:
|
|
|
- ret = (reg & I40E_QTX_ENA_QENA_STAT_MASK) ? 0 : -EPERM;
|
|
|
- break;
|
|
|
- case I40E_QUEUE_CTRL_DISABLE:
|
|
|
- reg &= ~I40E_QTX_ENA_QENA_REQ_MASK;
|
|
|
- writeback = true;
|
|
|
- break;
|
|
|
- case I40E_QUEUE_CTRL_DISABLECHECK:
|
|
|
- ret = (reg & I40E_QTX_ENA_QENA_STAT_MASK) ? -EPERM : 0;
|
|
|
- break;
|
|
|
- case I40E_QUEUE_CTRL_FASTDISABLE:
|
|
|
- reg |= I40E_QTX_ENA_FAST_QDIS_MASK;
|
|
|
- writeback = true;
|
|
|
- break;
|
|
|
- case I40E_QUEUE_CTRL_FASTDISABLECHECK:
|
|
|
- ret = (reg & I40E_QTX_ENA_QENA_STAT_MASK) ? -EPERM : 0;
|
|
|
- if (!ret) {
|
|
|
- reg &= ~I40E_QTX_ENA_FAST_QDIS_MASK;
|
|
|
- writeback = true;
|
|
|
- }
|
|
|
- break;
|
|
|
- default:
|
|
|
- ret = -EINVAL;
|
|
|
- break;
|
|
|
- }
|
|
|
-
|
|
|
- if (writeback) {
|
|
|
- wr32(hw, I40E_QTX_ENA(pf_queue_id), reg);
|
|
|
- i40e_flush(hw);
|
|
|
- }
|
|
|
-
|
|
|
- return ret;
|
|
|
-}
|
|
|
-
|
|
|
-/**
|
|
|
- * i40e_ctrl_vsi_rx_queue
|
|
|
- * @vf: pointer to the vf info
|
|
|
- * @vsi_idx: index of VSI in PF struct
|
|
|
- * @vsi_queue_id: vsi relative queue index
|
|
|
- * @ctrl: control flags
|
|
|
- *
|
|
|
- * enable/disable/enable check/disable check
|
|
|
- **/
|
|
|
-static int i40e_ctrl_vsi_rx_queue(struct i40e_vf *vf, u16 vsi_idx,
|
|
|
- u16 vsi_queue_id,
|
|
|
- enum i40e_queue_ctrl ctrl)
|
|
|
-{
|
|
|
- struct i40e_pf *pf = vf->pf;
|
|
|
- struct i40e_hw *hw = &pf->hw;
|
|
|
- bool writeback = false;
|
|
|
- u16 pf_queue_id;
|
|
|
- int ret = 0;
|
|
|
- u32 reg;
|
|
|
-
|
|
|
- pf_queue_id = i40e_vc_get_pf_queue_id(vf, vsi_idx, vsi_queue_id);
|
|
|
- reg = rd32(hw, I40E_QRX_ENA(pf_queue_id));
|
|
|
-
|
|
|
- switch (ctrl) {
|
|
|
- case I40E_QUEUE_CTRL_ENABLE:
|
|
|
- reg |= I40E_QRX_ENA_QENA_REQ_MASK;
|
|
|
- writeback = true;
|
|
|
- break;
|
|
|
- case I40E_QUEUE_CTRL_ENABLECHECK:
|
|
|
- ret = (reg & I40E_QRX_ENA_QENA_STAT_MASK) ? 0 : -EPERM;
|
|
|
- break;
|
|
|
- case I40E_QUEUE_CTRL_DISABLE:
|
|
|
- reg &= ~I40E_QRX_ENA_QENA_REQ_MASK;
|
|
|
- writeback = true;
|
|
|
- break;
|
|
|
- case I40E_QUEUE_CTRL_DISABLECHECK:
|
|
|
- ret = (reg & I40E_QRX_ENA_QENA_STAT_MASK) ? -EPERM : 0;
|
|
|
- break;
|
|
|
- case I40E_QUEUE_CTRL_FASTDISABLE:
|
|
|
- reg |= I40E_QRX_ENA_FAST_QDIS_MASK;
|
|
|
- writeback = true;
|
|
|
- break;
|
|
|
- case I40E_QUEUE_CTRL_FASTDISABLECHECK:
|
|
|
- ret = (reg & I40E_QRX_ENA_QENA_STAT_MASK) ? -EPERM : 0;
|
|
|
- if (!ret) {
|
|
|
- reg &= ~I40E_QRX_ENA_FAST_QDIS_MASK;
|
|
|
- writeback = true;
|
|
|
- }
|
|
|
- break;
|
|
|
- default:
|
|
|
- ret = -EINVAL;
|
|
|
- break;
|
|
|
- }
|
|
|
-
|
|
|
- if (writeback) {
|
|
|
- wr32(hw, I40E_QRX_ENA(pf_queue_id), reg);
|
|
|
- i40e_flush(hw);
|
|
|
- }
|
|
|
-
|
|
|
- return ret;
|
|
|
-}
|
|
|
-
|
|
|
/**
|
|
|
* i40e_config_irq_link_list
|
|
|
* @vf: pointer to the vf info
|
|
|
@@ -260,23 +136,17 @@ static void i40e_config_irq_link_list(struct i40e_vf *vf, u16 vsi_idx,
|
|
|
goto irq_list_done;
|
|
|
}
|
|
|
tempmap = vecmap->rxq_map;
|
|
|
- vsi_queue_id = find_first_bit(&tempmap, I40E_MAX_VSI_QP);
|
|
|
- while (vsi_queue_id < I40E_MAX_VSI_QP) {
|
|
|
+ for_each_set_bit(vsi_queue_id, &tempmap, I40E_MAX_VSI_QP) {
|
|
|
linklistmap |= (1 <<
|
|
|
(I40E_VIRTCHNL_SUPPORTED_QTYPES *
|
|
|
vsi_queue_id));
|
|
|
- vsi_queue_id =
|
|
|
- find_next_bit(&tempmap, I40E_MAX_VSI_QP, vsi_queue_id + 1);
|
|
|
}
|
|
|
|
|
|
tempmap = vecmap->txq_map;
|
|
|
- vsi_queue_id = find_first_bit(&tempmap, I40E_MAX_VSI_QP);
|
|
|
- while (vsi_queue_id < I40E_MAX_VSI_QP) {
|
|
|
+ for_each_set_bit(vsi_queue_id, &tempmap, I40E_MAX_VSI_QP) {
|
|
|
linklistmap |= (1 <<
|
|
|
(I40E_VIRTCHNL_SUPPORTED_QTYPES * vsi_queue_id
|
|
|
+ 1));
|
|
|
- vsi_queue_id = find_next_bit(&tempmap, I40E_MAX_VSI_QP,
|
|
|
- vsi_queue_id + 1);
|
|
|
}
|
|
|
|
|
|
next_q = find_first_bit(&linklistmap,
|
|
|
@@ -548,136 +418,6 @@ static int i40e_alloc_vsi_res(struct i40e_vf *vf, enum i40e_vsi_type type)
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
|
-/**
|
|
|
- * i40e_reset_vf
|
|
|
- * @vf: pointer to the vf structure
|
|
|
- * @flr: VFLR was issued or not
|
|
|
- *
|
|
|
- * reset the vf
|
|
|
- **/
|
|
|
-int i40e_reset_vf(struct i40e_vf *vf, bool flr)
|
|
|
-{
|
|
|
- int ret = -ENOENT;
|
|
|
- struct i40e_pf *pf = vf->pf;
|
|
|
- struct i40e_hw *hw = &pf->hw;
|
|
|
- u32 reg, reg_idx, msix_vf;
|
|
|
- bool rsd = false;
|
|
|
- u16 pf_queue_id;
|
|
|
- int i, j;
|
|
|
-
|
|
|
- /* warn the VF */
|
|
|
- wr32(hw, I40E_VFGEN_RSTAT1(vf->vf_id), I40E_VFR_INPROGRESS);
|
|
|
-
|
|
|
- clear_bit(I40E_VF_STAT_ACTIVE, &vf->vf_states);
|
|
|
-
|
|
|
- /* PF triggers VFR only when VF requests, in case of
|
|
|
- * VFLR, HW triggers VFR
|
|
|
- */
|
|
|
- if (!flr) {
|
|
|
- /* reset vf using VPGEN_VFRTRIG reg */
|
|
|
- reg = I40E_VPGEN_VFRTRIG_VFSWR_MASK;
|
|
|
- wr32(hw, I40E_VPGEN_VFRTRIG(vf->vf_id), reg);
|
|
|
- i40e_flush(hw);
|
|
|
- }
|
|
|
-
|
|
|
- /* poll VPGEN_VFRSTAT reg to make sure
|
|
|
- * that reset is complete
|
|
|
- */
|
|
|
- for (i = 0; i < 4; i++) {
|
|
|
- /* vf reset requires driver to first reset the
|
|
|
- * vf & than poll the status register to make sure
|
|
|
- * that the requested op was completed
|
|
|
- * successfully
|
|
|
- */
|
|
|
- udelay(10);
|
|
|
- reg = rd32(hw, I40E_VPGEN_VFRSTAT(vf->vf_id));
|
|
|
- if (reg & I40E_VPGEN_VFRSTAT_VFRD_MASK) {
|
|
|
- rsd = true;
|
|
|
- break;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- if (!rsd)
|
|
|
- dev_err(&pf->pdev->dev, "VF reset check timeout %d\n",
|
|
|
- vf->vf_id);
|
|
|
-
|
|
|
- /* fast disable qps */
|
|
|
- for (j = 0; j < pf->vsi[vf->lan_vsi_index]->num_queue_pairs; j++) {
|
|
|
- ret = i40e_ctrl_vsi_tx_queue(vf, vf->lan_vsi_index, j,
|
|
|
- I40E_QUEUE_CTRL_FASTDISABLE);
|
|
|
- ret = i40e_ctrl_vsi_rx_queue(vf, vf->lan_vsi_index, j,
|
|
|
- I40E_QUEUE_CTRL_FASTDISABLE);
|
|
|
- }
|
|
|
-
|
|
|
- /* Queue enable/disable requires driver to
|
|
|
- * first reset the vf & than poll the status register
|
|
|
- * to make sure that the requested op was completed
|
|
|
- * successfully
|
|
|
- */
|
|
|
- udelay(10);
|
|
|
- for (j = 0; j < pf->vsi[vf->lan_vsi_index]->num_queue_pairs; j++) {
|
|
|
- ret = i40e_ctrl_vsi_tx_queue(vf, vf->lan_vsi_index, j,
|
|
|
- I40E_QUEUE_CTRL_FASTDISABLECHECK);
|
|
|
- if (ret)
|
|
|
- dev_info(&pf->pdev->dev,
|
|
|
- "Queue control check failed on Tx queue %d of VSI %d VF %d\n",
|
|
|
- j, vf->lan_vsi_index, vf->vf_id);
|
|
|
- ret = i40e_ctrl_vsi_rx_queue(vf, vf->lan_vsi_index, j,
|
|
|
- I40E_QUEUE_CTRL_FASTDISABLECHECK);
|
|
|
- if (ret)
|
|
|
- dev_info(&pf->pdev->dev,
|
|
|
- "Queue control check failed on Rx queue %d of VSI %d VF %d\n",
|
|
|
- j, vf->lan_vsi_index, vf->vf_id);
|
|
|
- }
|
|
|
-
|
|
|
- /* clear the irq settings */
|
|
|
- msix_vf = pf->hw.func_caps.num_msix_vectors_vf;
|
|
|
- for (i = 0; i < msix_vf; i++) {
|
|
|
- /* format is same for both registers */
|
|
|
- if (0 == i)
|
|
|
- reg_idx = I40E_VPINT_LNKLST0(vf->vf_id);
|
|
|
- else
|
|
|
- reg_idx = I40E_VPINT_LNKLSTN(((msix_vf - 1) *
|
|
|
- (vf->vf_id))
|
|
|
- + (i - 1));
|
|
|
- reg = (I40E_VPINT_LNKLSTN_FIRSTQ_TYPE_MASK |
|
|
|
- I40E_VPINT_LNKLSTN_FIRSTQ_INDX_MASK);
|
|
|
- wr32(hw, reg_idx, reg);
|
|
|
- i40e_flush(hw);
|
|
|
- }
|
|
|
- /* disable interrupts so the VF starts in a known state */
|
|
|
- for (i = 0; i < msix_vf; i++) {
|
|
|
- /* format is same for both registers */
|
|
|
- if (0 == i)
|
|
|
- reg_idx = I40E_VFINT_DYN_CTL0(vf->vf_id);
|
|
|
- else
|
|
|
- reg_idx = I40E_VFINT_DYN_CTLN(((msix_vf - 1) *
|
|
|
- (vf->vf_id))
|
|
|
- + (i - 1));
|
|
|
- wr32(hw, reg_idx, I40E_VFINT_DYN_CTLN_CLEARPBA_MASK);
|
|
|
- i40e_flush(hw);
|
|
|
- }
|
|
|
-
|
|
|
- /* set the defaults for the rqctl & tqctl registers */
|
|
|
- reg = (I40E_QINT_RQCTL_NEXTQ_INDX_MASK | I40E_QINT_RQCTL_ITR_INDX_MASK |
|
|
|
- I40E_QINT_RQCTL_NEXTQ_TYPE_MASK);
|
|
|
- for (j = 0; j < pf->vsi[vf->lan_vsi_index]->num_queue_pairs; j++) {
|
|
|
- pf_queue_id = i40e_vc_get_pf_queue_id(vf, vf->lan_vsi_index, j);
|
|
|
- wr32(hw, I40E_QINT_RQCTL(pf_queue_id), reg);
|
|
|
- wr32(hw, I40E_QINT_TQCTL(pf_queue_id), reg);
|
|
|
- }
|
|
|
-
|
|
|
- /* 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);
|
|
|
- /* tell the VF the reset is done */
|
|
|
- wr32(hw, I40E_VFGEN_RSTAT1(vf->vf_id), I40E_VFR_COMPLETED);
|
|
|
- i40e_flush(hw);
|
|
|
-
|
|
|
- return ret;
|
|
|
-}
|
|
|
-
|
|
|
/**
|
|
|
* i40e_enable_vf_mappings
|
|
|
* @vf: pointer to the vf info
|
|
|
@@ -757,6 +497,9 @@ static void i40e_disable_vf_mappings(struct i40e_vf *vf)
|
|
|
static void i40e_free_vf_res(struct i40e_vf *vf)
|
|
|
{
|
|
|
struct i40e_pf *pf = vf->pf;
|
|
|
+ struct i40e_hw *hw = &pf->hw;
|
|
|
+ u32 reg_idx, reg;
|
|
|
+ int i, msix_vf;
|
|
|
|
|
|
/* free vsi & disconnect it from the parent uplink */
|
|
|
if (vf->lan_vsi_index) {
|
|
|
@@ -764,7 +507,34 @@ static void i40e_free_vf_res(struct i40e_vf *vf)
|
|
|
vf->lan_vsi_index = 0;
|
|
|
vf->lan_vsi_id = 0;
|
|
|
}
|
|
|
+ msix_vf = pf->hw.func_caps.num_msix_vectors_vf + 1;
|
|
|
+ /* disable interrupts so the VF starts in a known state */
|
|
|
+ for (i = 0; i < msix_vf; i++) {
|
|
|
+ /* format is same for both registers */
|
|
|
+ if (0 == i)
|
|
|
+ reg_idx = I40E_VFINT_DYN_CTL0(vf->vf_id);
|
|
|
+ else
|
|
|
+ reg_idx = I40E_VFINT_DYN_CTLN(((msix_vf - 1) *
|
|
|
+ (vf->vf_id))
|
|
|
+ + (i - 1));
|
|
|
+ wr32(hw, reg_idx, I40E_VFINT_DYN_CTLN_CLEARPBA_MASK);
|
|
|
+ i40e_flush(hw);
|
|
|
+ }
|
|
|
|
|
|
+ /* clear the irq settings */
|
|
|
+ for (i = 0; i < msix_vf; i++) {
|
|
|
+ /* format is same for both registers */
|
|
|
+ if (0 == i)
|
|
|
+ reg_idx = I40E_VPINT_LNKLST0(vf->vf_id);
|
|
|
+ else
|
|
|
+ reg_idx = I40E_VPINT_LNKLSTN(((msix_vf - 1) *
|
|
|
+ (vf->vf_id))
|
|
|
+ + (i - 1));
|
|
|
+ reg = (I40E_VPINT_LNKLSTN_FIRSTQ_TYPE_MASK |
|
|
|
+ I40E_VPINT_LNKLSTN_FIRSTQ_INDX_MASK);
|
|
|
+ wr32(hw, reg_idx, reg);
|
|
|
+ i40e_flush(hw);
|
|
|
+ }
|
|
|
/* reset some of the state varibles keeping
|
|
|
* track of the resources
|
|
|
*/
|
|
|
@@ -806,6 +576,112 @@ static int i40e_alloc_vf_res(struct i40e_vf *vf)
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
|
+#define VF_DEVICE_STATUS 0xAA
|
|
|
+#define VF_TRANS_PENDING_MASK 0x20
|
|
|
+/**
|
|
|
+ * i40e_quiesce_vf_pci
|
|
|
+ * @vf: pointer to the vf structure
|
|
|
+ *
|
|
|
+ * Wait for VF PCI transactions to be cleared after reset. Returns -EIO
|
|
|
+ * if the transactions never clear.
|
|
|
+ **/
|
|
|
+static int i40e_quiesce_vf_pci(struct i40e_vf *vf)
|
|
|
+{
|
|
|
+ struct i40e_pf *pf = vf->pf;
|
|
|
+ struct i40e_hw *hw = &pf->hw;
|
|
|
+ int vf_abs_id, i;
|
|
|
+ u32 reg;
|
|
|
+
|
|
|
+ reg = rd32(hw, I40E_PF_VT_PFALLOC);
|
|
|
+ vf_abs_id = vf->vf_id + (reg & I40E_PF_VT_PFALLOC_FIRSTVF_MASK);
|
|
|
+
|
|
|
+ wr32(hw, I40E_PF_PCI_CIAA,
|
|
|
+ VF_DEVICE_STATUS | (vf_abs_id << I40E_PF_PCI_CIAA_VF_NUM_SHIFT));
|
|
|
+ for (i = 0; i < 100; i++) {
|
|
|
+ reg = rd32(hw, I40E_PF_PCI_CIAD);
|
|
|
+ if ((reg & VF_TRANS_PENDING_MASK) == 0)
|
|
|
+ return 0;
|
|
|
+ udelay(1);
|
|
|
+ }
|
|
|
+ return -EIO;
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * 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;
|
|
|
+ int i;
|
|
|
+ u32 reg;
|
|
|
+
|
|
|
+ /* warn the VF */
|
|
|
+ clear_bit(I40E_VF_STAT_ACTIVE, &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.
|
|
|
+ */
|
|
|
+ if (!flr) {
|
|
|
+ /* reset vf using 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);
|
|
|
+ i40e_flush(hw);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (i40e_quiesce_vf_pci(vf))
|
|
|
+ dev_err(&pf->pdev->dev, "VF %d PCI transactions stuck\n",
|
|
|
+ vf->vf_id);
|
|
|
+
|
|
|
+ /* poll VPGEN_VFRSTAT reg to make sure
|
|
|
+ * that reset is complete
|
|
|
+ */
|
|
|
+ for (i = 0; i < 100; i++) {
|
|
|
+ /* vf reset requires driver to first reset the
|
|
|
+ * vf & than poll the status register to make sure
|
|
|
+ * that the requested op was completed
|
|
|
+ * successfully
|
|
|
+ */
|
|
|
+ udelay(10);
|
|
|
+ reg = rd32(hw, I40E_VPGEN_VFRSTAT(vf->vf_id));
|
|
|
+ if (reg & I40E_VPGEN_VFRSTAT_VFRD_MASK) {
|
|
|
+ rsd = true;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ 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);
|
|
|
+
|
|
|
+ /* On initial reset, we won't have any queues */
|
|
|
+ if (vf->lan_vsi_index == 0)
|
|
|
+ goto complete_reset;
|
|
|
+
|
|
|
+ i40e_vsi_control_rings(pf->vsi[vf->lan_vsi_index], false);
|
|
|
+complete_reset:
|
|
|
+ /* reallocate vf resources to reset the VSI state */
|
|
|
+ i40e_free_vf_res(vf);
|
|
|
+ mdelay(10);
|
|
|
+ i40e_alloc_vf_res(vf);
|
|
|
+ i40e_enable_vf_mappings(vf);
|
|
|
+
|
|
|
+ /* tell the VF the reset is done */
|
|
|
+ wr32(hw, I40E_VFGEN_RSTAT1(vf->vf_id), I40E_VFR_VFACTIVE);
|
|
|
+ i40e_flush(hw);
|
|
|
+}
|
|
|
+
|
|
|
/**
|
|
|
* i40e_vfs_are_assigned
|
|
|
* @pf: pointer to the pf structure
|
|
|
@@ -915,11 +791,8 @@ static int i40e_alloc_vfs(struct i40e_pf *pf, u16 num_alloc_vfs)
|
|
|
|
|
|
/* assign default capabilities */
|
|
|
set_bit(I40E_VIRTCHNL_VF_CAP_L2, &vfs[i].vf_caps);
|
|
|
-
|
|
|
- ret = i40e_alloc_vf_res(&vfs[i]);
|
|
|
- i40e_reset_vf(&vfs[i], true);
|
|
|
- if (ret)
|
|
|
- break;
|
|
|
+ /* vf resources get allocated during reset */
|
|
|
+ i40e_reset_vf(&vfs[i], false);
|
|
|
|
|
|
/* enable vf vplan_qtable mappings */
|
|
|
i40e_enable_vf_mappings(&vfs[i]);
|
|
|
@@ -1146,12 +1019,10 @@ static int i40e_vc_get_vf_resources_msg(struct i40e_vf *vf)
|
|
|
* unlike other virtchnl messages, pf driver
|
|
|
* doesn't send the response back to the vf
|
|
|
**/
|
|
|
-static int i40e_vc_reset_vf_msg(struct i40e_vf *vf)
|
|
|
+static void i40e_vc_reset_vf_msg(struct i40e_vf *vf)
|
|
|
{
|
|
|
- if (!test_bit(I40E_VF_STAT_ACTIVE, &vf->vf_states))
|
|
|
- return -ENOENT;
|
|
|
-
|
|
|
- return i40e_reset_vf(vf, false);
|
|
|
+ if (test_bit(I40E_VF_STAT_ACTIVE, &vf->vf_states))
|
|
|
+ i40e_reset_vf(vf, false);
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
@@ -1293,27 +1164,21 @@ static int i40e_vc_config_irq_map_msg(struct i40e_vf *vf, u8 *msg, u16 msglen)
|
|
|
|
|
|
/* lookout for the invalid queue index */
|
|
|
tempmap = map->rxq_map;
|
|
|
- vsi_queue_id = find_first_bit(&tempmap, I40E_MAX_VSI_QP);
|
|
|
- while (vsi_queue_id < I40E_MAX_VSI_QP) {
|
|
|
+ for_each_set_bit(vsi_queue_id, &tempmap, I40E_MAX_VSI_QP) {
|
|
|
if (!i40e_vc_isvalid_queue_id(vf, vsi_id,
|
|
|
vsi_queue_id)) {
|
|
|
aq_ret = I40E_ERR_PARAM;
|
|
|
goto error_param;
|
|
|
}
|
|
|
- vsi_queue_id = find_next_bit(&tempmap, I40E_MAX_VSI_QP,
|
|
|
- vsi_queue_id + 1);
|
|
|
}
|
|
|
|
|
|
tempmap = map->txq_map;
|
|
|
- vsi_queue_id = find_first_bit(&tempmap, I40E_MAX_VSI_QP);
|
|
|
- while (vsi_queue_id < I40E_MAX_VSI_QP) {
|
|
|
+ for_each_set_bit(vsi_queue_id, &tempmap, I40E_MAX_VSI_QP) {
|
|
|
if (!i40e_vc_isvalid_queue_id(vf, vsi_id,
|
|
|
vsi_queue_id)) {
|
|
|
aq_ret = I40E_ERR_PARAM;
|
|
|
goto error_param;
|
|
|
}
|
|
|
- vsi_queue_id = find_next_bit(&tempmap, I40E_MAX_VSI_QP,
|
|
|
- vsi_queue_id + 1);
|
|
|
}
|
|
|
|
|
|
i40e_config_irq_link_list(vf, vsi_id, map);
|
|
|
@@ -1339,8 +1204,6 @@ static int i40e_vc_enable_queues_msg(struct i40e_vf *vf, u8 *msg, u16 msglen)
|
|
|
struct i40e_pf *pf = vf->pf;
|
|
|
u16 vsi_id = vqs->vsi_id;
|
|
|
i40e_status aq_ret = 0;
|
|
|
- unsigned long tempmap;
|
|
|
- u16 queue_id;
|
|
|
|
|
|
if (!test_bit(I40E_VF_STAT_ACTIVE, &vf->vf_states)) {
|
|
|
aq_ret = I40E_ERR_PARAM;
|
|
|
@@ -1356,66 +1219,8 @@ static int i40e_vc_enable_queues_msg(struct i40e_vf *vf, u8 *msg, u16 msglen)
|
|
|
aq_ret = I40E_ERR_PARAM;
|
|
|
goto error_param;
|
|
|
}
|
|
|
-
|
|
|
- tempmap = vqs->rx_queues;
|
|
|
- queue_id = find_first_bit(&tempmap, I40E_MAX_VSI_QP);
|
|
|
- while (queue_id < I40E_MAX_VSI_QP) {
|
|
|
- if (!i40e_vc_isvalid_queue_id(vf, vsi_id, queue_id)) {
|
|
|
- aq_ret = I40E_ERR_PARAM;
|
|
|
- goto error_param;
|
|
|
- }
|
|
|
- i40e_ctrl_vsi_rx_queue(vf, vsi_id, queue_id,
|
|
|
- I40E_QUEUE_CTRL_ENABLE);
|
|
|
-
|
|
|
- queue_id = find_next_bit(&tempmap, I40E_MAX_VSI_QP,
|
|
|
- queue_id + 1);
|
|
|
- }
|
|
|
-
|
|
|
- tempmap = vqs->tx_queues;
|
|
|
- queue_id = find_first_bit(&tempmap, I40E_MAX_VSI_QP);
|
|
|
- while (queue_id < I40E_MAX_VSI_QP) {
|
|
|
- if (!i40e_vc_isvalid_queue_id(vf, vsi_id, queue_id)) {
|
|
|
- aq_ret = I40E_ERR_PARAM;
|
|
|
- goto error_param;
|
|
|
- }
|
|
|
- i40e_ctrl_vsi_tx_queue(vf, vsi_id, queue_id,
|
|
|
- I40E_QUEUE_CTRL_ENABLE);
|
|
|
-
|
|
|
- queue_id = find_next_bit(&tempmap, I40E_MAX_VSI_QP,
|
|
|
- queue_id + 1);
|
|
|
- }
|
|
|
-
|
|
|
- /* Poll the status register to make sure that the
|
|
|
- * requested op was completed successfully
|
|
|
- */
|
|
|
- udelay(10);
|
|
|
-
|
|
|
- tempmap = vqs->rx_queues;
|
|
|
- queue_id = find_first_bit(&tempmap, I40E_MAX_VSI_QP);
|
|
|
- while (queue_id < I40E_MAX_VSI_QP) {
|
|
|
- if (i40e_ctrl_vsi_rx_queue(vf, vsi_id, queue_id,
|
|
|
- I40E_QUEUE_CTRL_ENABLECHECK)) {
|
|
|
- dev_err(&pf->pdev->dev,
|
|
|
- "Queue control check failed on RX queue %d of VSI %d VF %d\n",
|
|
|
- queue_id, vsi_id, vf->vf_id);
|
|
|
- }
|
|
|
- queue_id = find_next_bit(&tempmap, I40E_MAX_VSI_QP,
|
|
|
- queue_id + 1);
|
|
|
- }
|
|
|
-
|
|
|
- tempmap = vqs->tx_queues;
|
|
|
- queue_id = find_first_bit(&tempmap, I40E_MAX_VSI_QP);
|
|
|
- while (queue_id < I40E_MAX_VSI_QP) {
|
|
|
- if (i40e_ctrl_vsi_tx_queue(vf, vsi_id, queue_id,
|
|
|
- I40E_QUEUE_CTRL_ENABLECHECK)) {
|
|
|
- dev_err(&pf->pdev->dev,
|
|
|
- "Queue control check failed on TX queue %d of VSI %d VF %d\n",
|
|
|
- queue_id, vsi_id, vf->vf_id);
|
|
|
- }
|
|
|
- queue_id = find_next_bit(&tempmap, I40E_MAX_VSI_QP,
|
|
|
- queue_id + 1);
|
|
|
- }
|
|
|
-
|
|
|
+ if (i40e_vsi_control_rings(pf->vsi[vsi_id], true))
|
|
|
+ aq_ret = I40E_ERR_TIMEOUT;
|
|
|
error_param:
|
|
|
/* send the response to the vf */
|
|
|
return i40e_vc_send_resp_to_vf(vf, I40E_VIRTCHNL_OP_ENABLE_QUEUES,
|
|
|
@@ -1438,8 +1243,6 @@ static int i40e_vc_disable_queues_msg(struct i40e_vf *vf, u8 *msg, u16 msglen)
|
|
|
struct i40e_pf *pf = vf->pf;
|
|
|
u16 vsi_id = vqs->vsi_id;
|
|
|
i40e_status aq_ret = 0;
|
|
|
- unsigned long tempmap;
|
|
|
- u16 queue_id;
|
|
|
|
|
|
if (!test_bit(I40E_VF_STAT_ACTIVE, &vf->vf_states)) {
|
|
|
aq_ret = I40E_ERR_PARAM;
|
|
|
@@ -1455,65 +1258,8 @@ static int i40e_vc_disable_queues_msg(struct i40e_vf *vf, u8 *msg, u16 msglen)
|
|
|
aq_ret = I40E_ERR_PARAM;
|
|
|
goto error_param;
|
|
|
}
|
|
|
-
|
|
|
- tempmap = vqs->rx_queues;
|
|
|
- queue_id = find_first_bit(&tempmap, I40E_MAX_VSI_QP);
|
|
|
- while (queue_id < I40E_MAX_VSI_QP) {
|
|
|
- if (!i40e_vc_isvalid_queue_id(vf, vsi_id, queue_id)) {
|
|
|
- aq_ret = I40E_ERR_PARAM;
|
|
|
- goto error_param;
|
|
|
- }
|
|
|
- i40e_ctrl_vsi_rx_queue(vf, vsi_id, queue_id,
|
|
|
- I40E_QUEUE_CTRL_DISABLE);
|
|
|
-
|
|
|
- queue_id = find_next_bit(&tempmap, I40E_MAX_VSI_QP,
|
|
|
- queue_id + 1);
|
|
|
- }
|
|
|
-
|
|
|
- tempmap = vqs->tx_queues;
|
|
|
- queue_id = find_first_bit(&tempmap, I40E_MAX_VSI_QP);
|
|
|
- while (queue_id < I40E_MAX_VSI_QP) {
|
|
|
- if (!i40e_vc_isvalid_queue_id(vf, vsi_id, queue_id)) {
|
|
|
- aq_ret = I40E_ERR_PARAM;
|
|
|
- goto error_param;
|
|
|
- }
|
|
|
- i40e_ctrl_vsi_tx_queue(vf, vsi_id, queue_id,
|
|
|
- I40E_QUEUE_CTRL_DISABLE);
|
|
|
-
|
|
|
- queue_id = find_next_bit(&tempmap, I40E_MAX_VSI_QP,
|
|
|
- queue_id + 1);
|
|
|
- }
|
|
|
-
|
|
|
- /* Poll the status register to make sure that the
|
|
|
- * requested op was completed successfully
|
|
|
- */
|
|
|
- udelay(10);
|
|
|
-
|
|
|
- tempmap = vqs->rx_queues;
|
|
|
- queue_id = find_first_bit(&tempmap, I40E_MAX_VSI_QP);
|
|
|
- while (queue_id < I40E_MAX_VSI_QP) {
|
|
|
- if (i40e_ctrl_vsi_rx_queue(vf, vsi_id, queue_id,
|
|
|
- I40E_QUEUE_CTRL_DISABLECHECK)) {
|
|
|
- dev_err(&pf->pdev->dev,
|
|
|
- "Queue control check failed on RX queue %d of VSI %d VF %d\n",
|
|
|
- queue_id, vsi_id, vf->vf_id);
|
|
|
- }
|
|
|
- queue_id = find_next_bit(&tempmap, I40E_MAX_VSI_QP,
|
|
|
- queue_id + 1);
|
|
|
- }
|
|
|
-
|
|
|
- tempmap = vqs->tx_queues;
|
|
|
- queue_id = find_first_bit(&tempmap, I40E_MAX_VSI_QP);
|
|
|
- while (queue_id < I40E_MAX_VSI_QP) {
|
|
|
- if (i40e_ctrl_vsi_tx_queue(vf, vsi_id, queue_id,
|
|
|
- I40E_QUEUE_CTRL_DISABLECHECK)) {
|
|
|
- dev_err(&pf->pdev->dev,
|
|
|
- "Queue control check failed on TX queue %d of VSI %d VF %d\n",
|
|
|
- queue_id, vsi_id, vf->vf_id);
|
|
|
- }
|
|
|
- queue_id = find_next_bit(&tempmap, I40E_MAX_VSI_QP,
|
|
|
- queue_id + 1);
|
|
|
- }
|
|
|
+ if (i40e_vsi_control_rings(pf->vsi[vsi_id], false))
|
|
|
+ aq_ret = I40E_ERR_TIMEOUT;
|
|
|
|
|
|
error_param:
|
|
|
/* send the response to the vf */
|
|
|
@@ -1594,7 +1340,7 @@ static int i40e_vc_add_mac_addr_msg(struct i40e_vf *vf, u8 *msg, u16 msglen)
|
|
|
is_zero_ether_addr(al->list[i].addr)) {
|
|
|
dev_err(&pf->pdev->dev, "invalid VF MAC addr %pMAC\n",
|
|
|
al->list[i].addr);
|
|
|
- aq_ret = I40E_ERR_PARAM;
|
|
|
+ aq_ret = I40E_ERR_INVALID_MAC_ADDR;
|
|
|
goto error_param;
|
|
|
}
|
|
|
}
|
|
|
@@ -1907,7 +1653,8 @@ int i40e_vc_process_vf_msg(struct i40e_pf *pf, u16 vf_id, u32 v_opcode,
|
|
|
ret = i40e_vc_validate_vf_msg(vf, v_opcode, v_retval, msg, msglen);
|
|
|
|
|
|
if (ret) {
|
|
|
- dev_err(&pf->pdev->dev, "invalid message from vf %d\n", vf_id);
|
|
|
+ dev_err(&pf->pdev->dev, "Invalid message from vf %d, opcode %d, len %d\n",
|
|
|
+ vf_id, v_opcode, msglen);
|
|
|
return ret;
|
|
|
}
|
|
|
wr32(hw, I40E_VFGEN_RSTAT1(vf_id), I40E_VFR_VFACTIVE);
|
|
|
@@ -1919,7 +1666,8 @@ int i40e_vc_process_vf_msg(struct i40e_pf *pf, u16 vf_id, u32 v_opcode,
|
|
|
ret = i40e_vc_get_vf_resources_msg(vf);
|
|
|
break;
|
|
|
case I40E_VIRTCHNL_OP_RESET_VF:
|
|
|
- ret = i40e_vc_reset_vf_msg(vf);
|
|
|
+ i40e_vc_reset_vf_msg(vf);
|
|
|
+ ret = 0;
|
|
|
break;
|
|
|
case I40E_VIRTCHNL_OP_CONFIG_PROMISCUOUS_MODE:
|
|
|
ret = i40e_vc_config_promiscuous_mode_msg(vf, msg, msglen);
|
|
|
@@ -1990,19 +1738,7 @@ int i40e_vc_process_vflr_event(struct i40e_pf *pf)
|
|
|
/* clear the bit in GLGEN_VFLRSTAT */
|
|
|
wr32(hw, I40E_GLGEN_VFLRSTAT(reg_idx), (1 << bit_idx));
|
|
|
|
|
|
- if (i40e_reset_vf(vf, true))
|
|
|
- dev_err(&pf->pdev->dev,
|
|
|
- "Unable to reset the VF %d\n", vf_id);
|
|
|
- /* free up vf resources to destroy vsi state */
|
|
|
- i40e_free_vf_res(vf);
|
|
|
-
|
|
|
- /* allocate new vf resources with the default state */
|
|
|
- if (i40e_alloc_vf_res(vf))
|
|
|
- dev_err(&pf->pdev->dev,
|
|
|
- "Unable to allocate VF resources %d\n",
|
|
|
- vf_id);
|
|
|
-
|
|
|
- i40e_enable_vf_mappings(vf);
|
|
|
+ i40e_reset_vf(vf, true);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
@@ -2269,7 +2005,6 @@ int i40e_ndo_get_vf_config(struct net_device *netdev,
|
|
|
int vf_id, struct ifla_vf_info *ivi)
|
|
|
{
|
|
|
struct i40e_netdev_priv *np = netdev_priv(netdev);
|
|
|
- struct i40e_mac_filter *f, *ftmp;
|
|
|
struct i40e_vsi *vsi = np->vsi;
|
|
|
struct i40e_pf *pf = vsi->back;
|
|
|
struct i40e_vf *vf;
|
|
|
@@ -2293,11 +2028,7 @@ int i40e_ndo_get_vf_config(struct net_device *netdev,
|
|
|
|
|
|
ivi->vf = vf_id;
|
|
|
|
|
|
- /* first entry of the list is the default ethernet address */
|
|
|
- list_for_each_entry_safe(f, ftmp, &vsi->mac_filter_list, list) {
|
|
|
- memcpy(&ivi->mac, f->macaddr, I40E_ETH_LENGTH_OF_ADDRESS);
|
|
|
- break;
|
|
|
- }
|
|
|
+ memcpy(&ivi->mac, vf->default_lan_addr.addr, ETH_ALEN);
|
|
|
|
|
|
ivi->tx_rate = 0;
|
|
|
ivi->vlan = le16_to_cpu(vsi->info.pvid) & I40E_VLAN_MASK;
|