[Intel-wired-lan] [PATCH net-next v1] i40e: Add check for queue allocation for the VF and refactor VF queue requesting

Karen Sornek karen.sornek at intel.com
Mon Jun 14 09:46:14 UTC 2021


The change implements the search for free space in PF
queue pair piles and refactors VF queue requesting.
i40e_set_num_queues and i40e_request_queues_msg
used similar logic to change number of queues for VF's.

Signed-off-by: Slawomir Laba <slawomirx.laba at intel.com>
Signed-off-by: Jan Sokolowski <jan.sokolowski at intel.com>
Signed-off-by: Karen Sornek <karen.sornek at intel.com>
---
 drivers/net/ethernet/intel/i40e/i40e.h        |   1 +
 drivers/net/ethernet/intel/i40e/i40e_main.c   |  33 +++++
 .../ethernet/intel/i40e/i40e_virtchnl_pf.c    | 135 ++++++++++++++----
 3 files changed, 145 insertions(+), 24 deletions(-)

diff --git a/drivers/net/ethernet/intel/i40e/i40e.h b/drivers/net/ethernet/intel/i40e/i40e.h
index ea9e301c6..0f2e0e5e0 100644
--- a/drivers/net/ethernet/intel/i40e/i40e.h
+++ b/drivers/net/ethernet/intel/i40e/i40e.h
@@ -1154,6 +1154,7 @@ int i40e_reconfig_rss_queues(struct i40e_pf *pf, int queue_count);
 struct i40e_veb *i40e_veb_setup(struct i40e_pf *pf, u16 flags, u16 uplink_seid,
 				u16 downlink_seid, u8 enabled_tc);
 void i40e_veb_release(struct i40e_veb *veb);
+int i40e_max_lump_qp(struct i40e_pf *pf);
 
 int i40e_veb_config_tc(struct i40e_veb *veb, u8 enabled_tc);
 int i40e_vsi_add_pvid(struct i40e_vsi *vsi, u16 vid);
diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c
index fce05ad24..5d4d323c9 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_main.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_main.c
@@ -257,6 +257,39 @@ static int i40e_put_lump(struct i40e_lump_tracking *pile, u16 index, u16 id)
 	return count;
 }
 
+/**
+ * i40e_max_lump_qp - find a biggest size of lump available in qp_pile
+ * @pf: pointer to private device data structure
+ *
+ * Returns the max size of lump in a qp_pile, or negative for error
+ */
+int i40e_max_lump_qp(struct i40e_pf *pf)
+{
+        struct i40e_lump_tracking *pile = pf->qp_pile;
+        int pool_size, max_size;
+        u16 i;
+
+        if (!pile) {
+                dev_info(&pf->pdev->dev,
+                         "param err: pile=%s\n",
+                         pile ? "<valid>" : "<null>");
+                return -EINVAL;
+        }
+
+        pool_size = 0;
+        max_size = 0;
+        for (i = 0; i < pile->num_entries; i++) {
+                if (pile->list[i] & I40E_PILE_VALID_BIT) {
+                        pool_size = 0;
+                        continue;
+                }
+                if (max_size < ++pool_size)
+                        max_size = pool_size;
+        }
+
+        return max_size;
+}
+
 /**
  * i40e_find_vsi_from_id - searches for the vsi with the given id
  * @pf: the pf structure to search for the vsi
diff --git a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c
index edfdce5f6..3d184a2ef 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c
@@ -2616,6 +2616,116 @@ error_param:
 				       aq_ret);
 }
 
+/**
+ * i40e_find_enough_vf_queues - find enough VF queues
+ * @vf: pointer to the VF info
+ * @needed: the number of items needed
+ *
+ * Returns the base item index of the queue, or negative for error
+ **/
+static int i40e_find_enough_vf_queues(struct i40e_vf *vf, u16 needed)
+{
+	struct i40e_pf *pf = vf->pf;
+	struct i40e_vsi *vsi = pf->vsi[vf->lan_vsi_idx];
+	struct i40e_lump_tracking *pile;
+	u16 cur_queues, more;
+	int i, j;
+
+	cur_queues = vsi->alloc_queue_pairs;
+
+	/* if current number of allocated queues is enough */
+	if (cur_queues >= needed)
+		return vsi->base_queue;
+
+	pile = pf->qp_pile;
+	if (cur_queues > 0) {
+		/*
+		 * if number of allocated queues is non-zero, just check if
+		 * there are enough queues behind the allocated queues
+		 * for more.
+		 */
+		more = needed - cur_queues;
+		for (i = vsi->base_queue + cur_queues;
+			i < pile->num_entries; i++) {
+			if (pile->list[i] & I40E_PILE_VALID_BIT)
+				break;
+
+			/* there are enough queues */
+			if (more-- == 1)
+				return vsi->base_queue;
+		}
+		/* start the linear search with that queue behind */
+		i++;
+	} else {
+		/* start the linear search with an imperfect hint */
+		i = pile->search_hint;
+	}
+
+	while (i < pile->num_entries) {
+		/* skip already allocated entries */
+		if (pile->list[i] & I40E_PILE_VALID_BIT) {
+			i++;
+			continue;
+		}
+
+		/* Are there enough in this lump? */
+		for (j = 1; j < needed && (i + j) < pile->num_entries; j++) {
+			if (pile->list[i + j] & I40E_PILE_VALID_BIT)
+				break;
+		}
+
+		if (j == needed)
+			/* there was enough */
+			return i;
+
+		/* not enough, so skip over it and continue looking */
+		i += j;
+	}
+
+	return -ENOMEM;
+}
+
+static int i40e_set_vf_num_queues(struct i40e_vf *vf, int num_queues)
+{
+	int cur_pairs = vf->num_queue_pairs;
+	struct i40e_pf *pf = vf->pf;
+	int max_size;
+
+	if (num_queues > I40E_MAX_VF_QUEUES) {
+		dev_err(&pf->pdev->dev, "Unable to configure %d VF queues, the maximum is %d\n",
+			num_queues,
+			I40E_MAX_VF_QUEUES);
+		return -EINVAL;
+	} else if (num_queues - cur_pairs > pf->queues_left) {
+		dev_warn(&pf->pdev->dev, "Unable to configure %d VF queues, only %d available\n",
+			 num_queues - cur_pairs,
+			 pf->queues_left);
+		return -EINVAL;
+	} else if (i40e_find_enough_vf_queues(vf, num_queues) < 0) {
+		dev_warn(&pf->pdev->dev, "VF requested %d more queues, but there is not enough for it.\n",
+			 num_queues - cur_pairs);
+		return -EINVAL;
+	}
+
+	max_size = i40e_max_lump_qp(pf);
+	if (max_size < 0) {
+		dev_err(&pf->pdev->dev, "Unable to configure %d VF queues, pile=<null>\n",
+			num_queues);
+		return -EINVAL;
+	}
+
+	if (num_queues > max_size) {
+		dev_err(&pf->pdev->dev, "Unable to configure %d VF queues, only %d available\n",
+			num_queues, max_size);
+		return -EINVAL;
+	}
+
+	/* successful request */
+	vf->num_req_queues = num_queues;
+	i40e_vc_reset_vf(vf, true);
+	return 0;
+}
+
 /**
  * i40e_vc_request_queues_msg
  * @vf: pointer to the VF info
@@ -2631,34 +2741,11 @@ static int i40e_vc_request_queues_msg(struct i40e_vf *vf, u8 *msg)
 	struct virtchnl_vf_res_request *vfres =
 		(struct virtchnl_vf_res_request *)msg;
 	u16 req_pairs = vfres->num_queue_pairs;
-	u8 cur_pairs = vf->num_queue_pairs;
-	struct i40e_pf *pf = vf->pf;
 
 	if (!i40e_sync_vf_state(vf, I40E_VF_STATE_ACTIVE))
 		return -EINVAL;
 
-	if (req_pairs > I40E_MAX_VF_QUEUES) {
-		dev_err(&pf->pdev->dev,
-			"VF %d tried to request more than %d queues.\n",
-			vf->vf_id,
-			I40E_MAX_VF_QUEUES);
-		vfres->num_queue_pairs = I40E_MAX_VF_QUEUES;
-	} else if (req_pairs - cur_pairs > pf->queues_left) {
-		dev_warn(&pf->pdev->dev,
-			 "VF %d requested %d more queues, but only %d left.\n",
-			 vf->vf_id,
-			 req_pairs - cur_pairs,
-			 pf->queues_left);
-		vfres->num_queue_pairs = pf->queues_left + cur_pairs;
-	} else {
-		/* successful request */
-		vf->num_req_queues = req_pairs;
-		i40e_vc_reset_vf(vf, true);
-		return 0;
-	}
-
-	return i40e_vc_send_msg_to_vf(vf, VIRTCHNL_OP_REQUEST_QUEUES, 0,
-				      (u8 *)vfres, sizeof(*vfres));
+	return i40e_set_vf_num_queues(vf, req_pairs);
 }
 
 /**
-- 
2.27.0



More information about the Intel-wired-lan mailing list