diff mbox series

[v3,10/26] event/dlb2: add v2.5 create dir queue

Message ID 1618344896-2090-11-git-send-email-timothy.mcdaniel@intel.com (mailing list archive)
State Superseded
Delegated to: Jerin Jacob
Headers show
Series Add DLB V2.5 | expand

Checks

Context Check Description
ci/checkpatch success coding style OK

Commit Message

McDaniel, Timothy April 13, 2021, 8:14 p.m. UTC
Updated low level hardware functions to account for new
register map and hardware access macros.

Signed-off-by: Timothy McDaniel <timothy.mcdaniel@intel.com>
---
 drivers/event/dlb2/pf/base/dlb2_resource.c    | 213 ------------------
 .../event/dlb2/pf/base/dlb2_resource_new.c    | 201 +++++++++++++++++
 2 files changed, 201 insertions(+), 213 deletions(-)
diff mbox series

Patch

diff --git a/drivers/event/dlb2/pf/base/dlb2_resource.c b/drivers/event/dlb2/pf/base/dlb2_resource.c
index 70c52e908..362deadfe 100644
--- a/drivers/event/dlb2/pf/base/dlb2_resource.c
+++ b/drivers/event/dlb2/pf/base/dlb2_resource.c
@@ -1225,219 +1225,6 @@  dlb2_get_domain_used_dir_pq(struct dlb2_hw *hw,
 	return NULL;
 }
 
-static void dlb2_configure_dir_queue(struct dlb2_hw *hw,
-				     struct dlb2_hw_domain *domain,
-				     struct dlb2_dir_pq_pair *queue,
-				     struct dlb2_create_dir_queue_args *args,
-				     bool vdev_req,
-				     unsigned int vdev_id)
-{
-	union dlb2_sys_dir_vasqid_v r0 = { {0} };
-	union dlb2_sys_dir_qid_its r1 = { {0} };
-	union dlb2_lsp_qid_dir_depth_thrsh r2 = { {0} };
-	union dlb2_sys_dir_qid_v r5 = { {0} };
-
-	unsigned int offs;
-
-	/* QID write permissions are turned on when the domain is started */
-	r0.field.vasqid_v = 0;
-
-	offs = domain->id.phys_id * DLB2_MAX_NUM_DIR_QUEUES(hw->ver) +
-		queue->id.phys_id;
-
-	DLB2_CSR_WR(hw, DLB2_SYS_DIR_VASQID_V(offs), r0.val);
-
-	/* Don't timestamp QEs that pass through this queue */
-	r1.field.qid_its = 0;
-
-	DLB2_CSR_WR(hw,
-		    DLB2_SYS_DIR_QID_ITS(queue->id.phys_id),
-		    r1.val);
-
-	r2.field.thresh = args->depth_threshold;
-
-	DLB2_CSR_WR(hw,
-		    DLB2_LSP_QID_DIR_DEPTH_THRSH(queue->id.phys_id),
-		    r2.val);
-
-	if (vdev_req) {
-		union dlb2_sys_vf_dir_vqid_v r3 = { {0} };
-		union dlb2_sys_vf_dir_vqid2qid r4 = { {0} };
-
-		offs = vdev_id * DLB2_MAX_NUM_DIR_QUEUES(hw->ver)
-			+ queue->id.virt_id;
-
-		r3.field.vqid_v = 1;
-
-		DLB2_CSR_WR(hw, DLB2_SYS_VF_DIR_VQID_V(offs), r3.val);
-
-		r4.field.qid = queue->id.phys_id;
-
-		DLB2_CSR_WR(hw, DLB2_SYS_VF_DIR_VQID2QID(offs), r4.val);
-	}
-
-	r5.field.qid_v = 1;
-
-	DLB2_CSR_WR(hw, DLB2_SYS_DIR_QID_V(queue->id.phys_id), r5.val);
-
-	queue->queue_configured = true;
-}
-
-static void
-dlb2_log_create_dir_queue_args(struct dlb2_hw *hw,
-			       u32 domain_id,
-			       struct dlb2_create_dir_queue_args *args,
-			       bool vdev_req,
-			       unsigned int vdev_id)
-{
-	DLB2_HW_DBG(hw, "DLB2 create directed queue arguments:\n");
-	if (vdev_req)
-		DLB2_HW_DBG(hw, "(Request from vdev %d)\n", vdev_id);
-	DLB2_HW_DBG(hw, "\tDomain ID: %d\n", domain_id);
-	DLB2_HW_DBG(hw, "\tPort ID:   %d\n", args->port_id);
-}
-
-static int
-dlb2_verify_create_dir_queue_args(struct dlb2_hw *hw,
-				  u32 domain_id,
-				  struct dlb2_create_dir_queue_args *args,
-				  struct dlb2_cmd_response *resp,
-				  bool vdev_req,
-				  unsigned int vdev_id)
-{
-	struct dlb2_hw_domain *domain;
-
-	domain = dlb2_get_domain_from_id(hw, domain_id, vdev_req, vdev_id);
-
-	if (domain == NULL) {
-		resp->status = DLB2_ST_INVALID_DOMAIN_ID;
-		return -EINVAL;
-	}
-
-	if (!domain->configured) {
-		resp->status = DLB2_ST_DOMAIN_NOT_CONFIGURED;
-		return -EINVAL;
-	}
-
-	if (domain->started) {
-		resp->status = DLB2_ST_DOMAIN_STARTED;
-		return -EINVAL;
-	}
-
-	/*
-	 * If the user claims the port is already configured, validate the port
-	 * ID, its domain, and whether the port is configured.
-	 */
-	if (args->port_id != -1) {
-		struct dlb2_dir_pq_pair *port;
-
-		port = dlb2_get_domain_used_dir_pq(hw,
-						   args->port_id,
-						   vdev_req,
-						   domain);
-
-		if (port == NULL || port->domain_id.phys_id !=
-				domain->id.phys_id || !port->port_configured) {
-			resp->status = DLB2_ST_INVALID_PORT_ID;
-			return -EINVAL;
-		}
-	}
-
-	/*
-	 * If the queue's port is not configured, validate that a free
-	 * port-queue pair is available.
-	 */
-	if (args->port_id == -1 &&
-	    dlb2_list_empty(&domain->avail_dir_pq_pairs)) {
-		resp->status = DLB2_ST_DIR_QUEUES_UNAVAILABLE;
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-/**
- * dlb2_hw_create_dir_queue() - Allocate and initialize a DLB DIR queue.
- * @hw:	Contains the current state of the DLB2 hardware.
- * @domain_id: Domain ID
- * @args: User-provided arguments.
- * @resp: Response to user.
- * @vdev_req: Request came from a virtual device.
- * @vdev_id: If vdev_req is true, this contains the virtual device's ID.
- *
- * Return: returns < 0 on error, 0 otherwise. If the driver is unable to
- * satisfy a request, resp->status will be set accordingly.
- */
-int dlb2_hw_create_dir_queue(struct dlb2_hw *hw,
-			     u32 domain_id,
-			     struct dlb2_create_dir_queue_args *args,
-			     struct dlb2_cmd_response *resp,
-			     bool vdev_req,
-			     unsigned int vdev_id)
-{
-	struct dlb2_dir_pq_pair *queue;
-	struct dlb2_hw_domain *domain;
-	int ret;
-
-	dlb2_log_create_dir_queue_args(hw, domain_id, args, vdev_req, vdev_id);
-
-	/*
-	 * Verify that hardware resources are available before attempting to
-	 * satisfy the request. This simplifies the error unwinding code.
-	 */
-	ret = dlb2_verify_create_dir_queue_args(hw,
-						domain_id,
-						args,
-						resp,
-						vdev_req,
-						vdev_id);
-	if (ret)
-		return ret;
-
-	domain = dlb2_get_domain_from_id(hw, domain_id, vdev_req, vdev_id);
-	if (domain == NULL) {
-		DLB2_HW_ERR(hw,
-			    "[%s():%d] Internal error: domain not found\n",
-			    __func__, __LINE__);
-		return -EFAULT;
-	}
-
-	if (args->port_id != -1)
-		queue = dlb2_get_domain_used_dir_pq(hw,
-						    args->port_id,
-						    vdev_req,
-						    domain);
-	else
-		queue = DLB2_DOM_LIST_HEAD(domain->avail_dir_pq_pairs,
-					   typeof(*queue));
-	if (queue == NULL) {
-		DLB2_HW_ERR(hw,
-			    "[%s():%d] Internal error: no available dir queues\n",
-			    __func__, __LINE__);
-		return -EFAULT;
-	}
-
-	dlb2_configure_dir_queue(hw, domain, queue, args, vdev_req, vdev_id);
-
-	/*
-	 * Configuration succeeded, so move the resource from the 'avail' to
-	 * the 'used' list (if it's not already there).
-	 */
-	if (args->port_id == -1) {
-		dlb2_list_del(&domain->avail_dir_pq_pairs,
-			      &queue->domain_list);
-
-		dlb2_list_add(&domain->used_dir_pq_pairs,
-			      &queue->domain_list);
-	}
-
-	resp->status = 0;
-
-	resp->id = (vdev_req) ? queue->id.virt_id : queue->id.phys_id;
-
-	return 0;
-}
-
 static bool
 dlb2_port_find_slot_with_pending_map_queue(struct dlb2_ldb_port *port,
 					   struct dlb2_ldb_queue *queue,
diff --git a/drivers/event/dlb2/pf/base/dlb2_resource_new.c b/drivers/event/dlb2/pf/base/dlb2_resource_new.c
index 4e4b390dd..d4b401250 100644
--- a/drivers/event/dlb2/pf/base/dlb2_resource_new.c
+++ b/drivers/event/dlb2/pf/base/dlb2_resource_new.c
@@ -4857,3 +4857,204 @@  int dlb2_hw_create_dir_port(struct dlb2_hw *hw,
 
 	return 0;
 }
+
+static void dlb2_configure_dir_queue(struct dlb2_hw *hw,
+				     struct dlb2_hw_domain *domain,
+				     struct dlb2_dir_pq_pair *queue,
+				     struct dlb2_create_dir_queue_args *args,
+				     bool vdev_req,
+				     unsigned int vdev_id)
+{
+	unsigned int offs;
+	u32 reg = 0;
+
+	/* QID write permissions are turned on when the domain is started */
+	offs = domain->id.phys_id * DLB2_MAX_NUM_DIR_QUEUES(hw->ver) +
+		queue->id.phys_id;
+
+	DLB2_CSR_WR(hw, DLB2_SYS_DIR_VASQID_V(offs), reg);
+
+	/* Don't timestamp QEs that pass through this queue */
+	DLB2_CSR_WR(hw, DLB2_SYS_DIR_QID_ITS(queue->id.phys_id), reg);
+
+	reg = 0;
+	DLB2_BITS_SET(reg, args->depth_threshold,
+		      DLB2_LSP_QID_DIR_DEPTH_THRSH_THRESH);
+	DLB2_CSR_WR(hw,
+		    DLB2_LSP_QID_DIR_DEPTH_THRSH(hw->ver, queue->id.phys_id),
+		    reg);
+
+	if (vdev_req) {
+		offs = vdev_id * DLB2_MAX_NUM_DIR_QUEUES(hw->ver) +
+			queue->id.virt_id;
+
+		reg = 0;
+		DLB2_BIT_SET(reg, DLB2_SYS_VF_DIR_VQID_V_VQID_V);
+		DLB2_CSR_WR(hw, DLB2_SYS_VF_DIR_VQID_V(offs), reg);
+
+		reg = 0;
+		DLB2_BITS_SET(reg, queue->id.phys_id,
+			      DLB2_SYS_VF_DIR_VQID2QID_QID);
+		DLB2_CSR_WR(hw, DLB2_SYS_VF_DIR_VQID2QID(offs), reg);
+	}
+
+	reg = 0;
+	DLB2_BIT_SET(reg, DLB2_SYS_DIR_QID_V_QID_V);
+	DLB2_CSR_WR(hw, DLB2_SYS_DIR_QID_V(queue->id.phys_id), reg);
+
+	queue->queue_configured = true;
+}
+
+static void
+dlb2_log_create_dir_queue_args(struct dlb2_hw *hw,
+			       u32 domain_id,
+			       struct dlb2_create_dir_queue_args *args,
+			       bool vdev_req,
+			       unsigned int vdev_id)
+{
+	DLB2_HW_DBG(hw, "DLB2 create directed queue arguments:\n");
+	if (vdev_req)
+		DLB2_HW_DBG(hw, "(Request from vdev %d)\n", vdev_id);
+	DLB2_HW_DBG(hw, "\tDomain ID: %d\n", domain_id);
+	DLB2_HW_DBG(hw, "\tPort ID:   %d\n", args->port_id);
+}
+
+static int
+dlb2_verify_create_dir_queue_args(struct dlb2_hw *hw,
+				  u32 domain_id,
+				  struct dlb2_create_dir_queue_args *args,
+				  struct dlb2_cmd_response *resp,
+				  bool vdev_req,
+				  unsigned int vdev_id,
+				  struct dlb2_hw_domain **out_domain,
+				  struct dlb2_dir_pq_pair **out_queue)
+{
+	struct dlb2_hw_domain *domain;
+	struct dlb2_dir_pq_pair *pq;
+
+	domain = dlb2_get_domain_from_id(hw, domain_id, vdev_req, vdev_id);
+
+	if (!domain) {
+		resp->status = DLB2_ST_INVALID_DOMAIN_ID;
+		return -EINVAL;
+	}
+
+	if (!domain->configured) {
+		resp->status = DLB2_ST_DOMAIN_NOT_CONFIGURED;
+		return -EINVAL;
+	}
+
+	if (domain->started) {
+		resp->status = DLB2_ST_DOMAIN_STARTED;
+		return -EINVAL;
+	}
+
+	/*
+	 * If the user claims the port is already configured, validate the port
+	 * ID, its domain, and whether the port is configured.
+	 */
+	if (args->port_id != -1) {
+		pq = dlb2_get_domain_used_dir_pq(hw,
+						 args->port_id,
+						 vdev_req,
+						 domain);
+
+		if (!pq || pq->domain_id.phys_id != domain->id.phys_id ||
+		    !pq->port_configured) {
+			resp->status = DLB2_ST_INVALID_PORT_ID;
+			return -EINVAL;
+		}
+	} else {
+		/*
+		 * If the queue's port is not configured, validate that a free
+		 * port-queue pair is available.
+		 */
+		pq = DLB2_DOM_LIST_HEAD(domain->avail_dir_pq_pairs,
+					typeof(*pq));
+		if (!pq) {
+			resp->status = DLB2_ST_DIR_QUEUES_UNAVAILABLE;
+			return -EINVAL;
+		}
+	}
+
+	*out_domain = domain;
+	*out_queue = pq;
+
+	return 0;
+}
+
+/**
+ * dlb2_hw_create_dir_queue() - create a directed queue
+ * @hw: dlb2_hw handle for a particular device.
+ * @domain_id: domain ID.
+ * @args: queue creation arguments.
+ * @resp: response structure.
+ * @vdev_req: indicates whether this request came from a vdev.
+ * @vdev_id: If vdev_req is true, this contains the vdev's ID.
+ *
+ * This function creates a directed queue.
+ *
+ * A vdev can be either an SR-IOV virtual function or a Scalable IOV virtual
+ * device.
+ *
+ * Return:
+ * Returns 0 upon success, < 0 otherwise. If an error occurs, resp->status is
+ * assigned a detailed error code from enum dlb2_error. If successful, resp->id
+ * contains the queue ID.
+ *
+ * resp->id contains a virtual ID if vdev_req is true.
+ *
+ * Errors:
+ * EINVAL - A requested resource is unavailable, the domain is not configured,
+ *	    or the domain has already been started.
+ * EFAULT - Internal error (resp->status not set).
+ */
+int dlb2_hw_create_dir_queue(struct dlb2_hw *hw,
+			     u32 domain_id,
+			     struct dlb2_create_dir_queue_args *args,
+			     struct dlb2_cmd_response *resp,
+			     bool vdev_req,
+			     unsigned int vdev_id)
+{
+	struct dlb2_dir_pq_pair *queue;
+	struct dlb2_hw_domain *domain;
+	int ret;
+
+	dlb2_log_create_dir_queue_args(hw, domain_id, args, vdev_req, vdev_id);
+
+	/*
+	 * Verify that hardware resources are available before attempting to
+	 * satisfy the request. This simplifies the error unwinding code.
+	 */
+	ret = dlb2_verify_create_dir_queue_args(hw,
+						domain_id,
+						args,
+						resp,
+						vdev_req,
+						vdev_id,
+						&domain,
+						&queue);
+	if (ret)
+		return ret;
+
+	dlb2_configure_dir_queue(hw, domain, queue, args, vdev_req, vdev_id);
+
+	/*
+	 * Configuration succeeded, so move the resource from the 'avail' to
+	 * the 'used' list (if it's not already there).
+	 */
+	if (args->port_id == -1) {
+		dlb2_list_del(&domain->avail_dir_pq_pairs,
+			      &queue->domain_list);
+
+		dlb2_list_add(&domain->used_dir_pq_pairs,
+			      &queue->domain_list);
+	}
+
+	resp->status = 0;
+
+	resp->id = (vdev_req) ? queue->id.virt_id : queue->id.phys_id;
+
+	return 0;
+}
+