[14/22] event/dlb2: add eventdev start

Message ID 1599855987-25976-15-git-send-email-timothy.mcdaniel@intel.com (mailing list archive)
State Superseded, archived
Delegated to: Jerin Jacob
Headers
Series Add DLB2 PMD |

Checks

Context Check Description
ci/checkpatch success coding style OK

Commit Message

Timothy McDaniel Sept. 11, 2020, 8:26 p.m. UTC
  Add support for the eventdev start entry point.

Signed-off-by: Timothy McDaniel <timothy.mcdaniel@intel.com>
---
 drivers/event/dlb2/dlb2.c                  | 133 +++++++++++++++++++++++++++++
 drivers/event/dlb2/dlb2_iface.c            |   3 +
 drivers/event/dlb2/dlb2_iface.h            |   3 +
 drivers/event/dlb2/pf/base/dlb2_resource.c | 123 ++++++++++++++++++++++++++
 drivers/event/dlb2/pf/dlb2_main.c          |  10 +++
 drivers/event/dlb2/pf/dlb2_pf.c            |  25 ++++++
 6 files changed, 297 insertions(+)
  

Comments

Eads, Gage Oct. 7, 2020, 8:51 p.m. UTC | #1
> -----Original Message-----
> From: McDaniel, Timothy <timothy.mcdaniel@intel.com>
> Sent: Friday, September 11, 2020 3:26 PM
> Cc: dev@dpdk.org; Carrillo, Erik G <erik.g.carrillo@intel.com>; Eads, Gage
> <gage.eads@intel.com>; Van Haaren, Harry <harry.van.haaren@intel.com>;
> jerinj@marvell.com
> Subject: [PATCH 14/22] event/dlb2: add eventdev start
> 
> Add support for the eventdev start entry point.
> 

Code looks fine (one whitespace nit below), but it could use a more detailed
commit message -- e.g. describing how the PMD delays port links until
eventdev start time, how the configuration will be reapplied at this time if
this is a reconfiguration scenario, etc.

[...]

> +static int
> +dlb2_eventdev_start(struct rte_eventdev *dev)
> +{
> +	struct dlb2_eventdev *dlb2 = dlb2_pmd_priv(dev);
> +	struct dlb2_hw_dev *handle = &dlb2->qm_instance;
> +	struct dlb2_start_domain_args cfg;
> +	int ret, i;
> +
> +	rte_spinlock_lock(&dlb2->qm_instance.resource_lock);
> +	if (dlb2->run_state != DLB2_RUN_STATE_STOPPED) {
> +		DLB2_LOG_ERR("bad state %d for dev_start\n",
> +			     (int)dlb2->run_state);
> +		rte_spinlock_unlock(&dlb2->qm_instance.resource_lock);
> +		return -EINVAL;
> +	}
> +	dlb2->run_state	= DLB2_RUN_STATE_STARTING;

Looks like there's a tab between run_state and the equals sign.

Thanks,
Gage
  

Patch

diff --git a/drivers/event/dlb2/dlb2.c b/drivers/event/dlb2/dlb2.c
index 7ac47d9..ef23def 100644
--- a/drivers/event/dlb2/dlb2.c
+++ b/drivers/event/dlb2/dlb2.c
@@ -2033,6 +2033,138 @@  dlb2_eventdev_port_unlinks_in_progress(struct rte_eventdev *dev,
 	return cfg.response.id;
 }
 
+static int
+dlb2_eventdev_reapply_configuration(struct rte_eventdev *dev)
+{
+	struct dlb2_eventdev *dlb2 = dlb2_pmd_priv(dev);
+	int ret, i;
+
+	/* If an event queue or port was previously configured, but hasn't been
+	 * reconfigured, reapply its original configuration.
+	 */
+	for (i = 0; i < dlb2->num_queues; i++) {
+		struct dlb2_eventdev_queue *ev_queue;
+
+		ev_queue = &dlb2->ev_queues[i];
+
+		if (ev_queue->qm_queue.config_state != DLB2_PREV_CONFIGURED)
+			continue;
+
+		ret = dlb2_eventdev_queue_setup(dev, i, &ev_queue->conf);
+		if (ret < 0) {
+			DLB2_LOG_ERR("dlb2: failed to reconfigure queue %d", i);
+			return ret;
+		}
+	}
+
+	for (i = 0; i < dlb2->num_ports; i++) {
+		struct dlb2_eventdev_port *ev_port = &dlb2->ev_ports[i];
+
+		if (ev_port->qm_port.config_state != DLB2_PREV_CONFIGURED)
+			continue;
+
+		ret = dlb2_eventdev_port_setup(dev, i, &ev_port->conf);
+		if (ret < 0) {
+			DLB2_LOG_ERR("dlb2: failed to reconfigure ev_port %d",
+				     i);
+			return ret;
+		}
+	}
+
+	return 0;
+}
+
+static int
+dlb2_eventdev_apply_port_links(struct rte_eventdev *dev)
+{
+	struct dlb2_eventdev *dlb2 = dlb2_pmd_priv(dev);
+	int i;
+
+	/* Perform requested port->queue links */
+	for (i = 0; i < dlb2->num_ports; i++) {
+		struct dlb2_eventdev_port *ev_port = &dlb2->ev_ports[i];
+		int j;
+
+		for (j = 0; j < DLB2_MAX_NUM_QIDS_PER_LDB_CQ; j++) {
+			struct dlb2_eventdev_queue *ev_queue;
+			uint8_t prio, queue_id;
+
+			if (!ev_port->link[j].valid)
+				continue;
+
+			prio = ev_port->link[j].priority;
+			queue_id = ev_port->link[j].queue_id;
+
+			if (dlb2_validate_port_link(ev_port, queue_id, true, j))
+				return -EINVAL;
+
+			ev_queue = &dlb2->ev_queues[queue_id];
+
+			if (dlb2_do_port_link(dev, ev_queue, ev_port, prio))
+				return -EINVAL;
+		}
+	}
+
+	return 0;
+}
+
+static int
+dlb2_eventdev_start(struct rte_eventdev *dev)
+{
+	struct dlb2_eventdev *dlb2 = dlb2_pmd_priv(dev);
+	struct dlb2_hw_dev *handle = &dlb2->qm_instance;
+	struct dlb2_start_domain_args cfg;
+	int ret, i;
+
+	rte_spinlock_lock(&dlb2->qm_instance.resource_lock);
+	if (dlb2->run_state != DLB2_RUN_STATE_STOPPED) {
+		DLB2_LOG_ERR("bad state %d for dev_start\n",
+			     (int)dlb2->run_state);
+		rte_spinlock_unlock(&dlb2->qm_instance.resource_lock);
+		return -EINVAL;
+	}
+	dlb2->run_state	= DLB2_RUN_STATE_STARTING;
+	rte_spinlock_unlock(&dlb2->qm_instance.resource_lock);
+
+	/* If the device was configured more than once, some event ports and/or
+	 * queues may need to be reconfigured.
+	 */
+	ret = dlb2_eventdev_reapply_configuration(dev);
+	if (ret)
+		return ret;
+
+	/* The DLB PMD delays port links until the device is started. */
+	ret = dlb2_eventdev_apply_port_links(dev);
+	if (ret)
+		return ret;
+
+	for (i = 0; i < dlb2->num_ports; i++) {
+		if (!dlb2->ev_ports[i].setup_done) {
+			DLB2_LOG_ERR("dlb2: port %d not setup", i);
+			return -ESTALE;
+		}
+	}
+
+	for (i = 0; i < dlb2->num_queues; i++) {
+		if (dlb2->ev_queues[i].num_links == 0) {
+			DLB2_LOG_ERR("dlb2: queue %d is not linked", i);
+			return -ENOLINK;
+		}
+	}
+
+	ret = dlb2_iface_sched_domain_start(handle, &cfg);
+	if (ret < 0) {
+		DLB2_LOG_ERR("dlb2: sched_domain_start ret=%d (driver status: %s)\n",
+			     ret, dlb2_error_strings[cfg.response.status]);
+		return ret;
+	}
+
+	dlb2->run_state = DLB2_RUN_STATE_STARTED;
+	DLB2_LOG_DBG("dlb2: sched_domain_start completed OK\n");
+
+	return 0;
+}
+
 static void
 dlb2_entry_points_init(struct rte_eventdev *dev)
 {
@@ -2040,6 +2172,7 @@  dlb2_entry_points_init(struct rte_eventdev *dev)
 	static struct rte_eventdev_ops dlb2_eventdev_entry_ops = {
 		.dev_infos_get    = dlb2_eventdev_info_get,
 		.dev_configure    = dlb2_eventdev_configure,
+		.dev_start        = dlb2_eventdev_start,
 		.queue_def_conf   = dlb2_eventdev_queue_default_conf_get,
 		.queue_setup      = dlb2_eventdev_queue_setup,
 		.port_def_conf    = dlb2_eventdev_port_default_conf_get,
diff --git a/drivers/event/dlb2/dlb2_iface.c b/drivers/event/dlb2/dlb2_iface.c
index 8034165..8228bb3 100644
--- a/drivers/event/dlb2/dlb2_iface.c
+++ b/drivers/event/dlb2/dlb2_iface.c
@@ -77,3 +77,6 @@  int (*dlb2_iface_unmap_qid)(struct dlb2_hw_dev *handle,
 
 int (*dlb2_iface_pending_port_unmaps)(struct dlb2_hw_dev *handle,
 				struct dlb2_pending_port_unmaps_args *args);
+
+int (*dlb2_iface_sched_domain_start)(struct dlb2_hw_dev *handle,
+				     struct dlb2_start_domain_args *cfg);
diff --git a/drivers/event/dlb2/dlb2_iface.h b/drivers/event/dlb2/dlb2_iface.h
index 182a5bf..d5bb6be 100644
--- a/drivers/event/dlb2/dlb2_iface.h
+++ b/drivers/event/dlb2/dlb2_iface.h
@@ -63,4 +63,7 @@  extern int (*dlb2_iface_unmap_qid)(struct dlb2_hw_dev *handle,
 extern int (*dlb2_iface_pending_port_unmaps)(struct dlb2_hw_dev *handle,
 				struct dlb2_pending_port_unmaps_args *args);
 
+extern int (*dlb2_iface_sched_domain_start)(struct dlb2_hw_dev *handle,
+				struct dlb2_start_domain_args *cfg);
+
 #endif /* _DLB2_IFACE_H_ */
diff --git a/drivers/event/dlb2/pf/base/dlb2_resource.c b/drivers/event/dlb2/pf/base/dlb2_resource.c
index a5b2be1..4c4c0b4 100644
--- a/drivers/event/dlb2/pf/base/dlb2_resource.c
+++ b/drivers/event/dlb2/pf/base/dlb2_resource.c
@@ -5807,3 +5807,126 @@  int dlb2_hw_pending_port_unmaps(struct dlb2_hw *hw,
 
 	return 0;
 }
+
+static int dlb2_verify_start_domain_args(struct dlb2_hw *hw,
+					 u32 domain_id,
+					 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) {
+		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;
+	}
+
+	return 0;
+}
+
+static void dlb2_log_start_domain(struct dlb2_hw *hw,
+				  u32 domain_id,
+				  bool vdev_req,
+				  unsigned int vdev_id)
+{
+	DLB2_HW_DBG(hw, "DLB2 start domain 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_start_domain() - Lock the domain configuration
+ * @hw:	Contains the current state of the DLB2 hardware.
+ * @domain_id: Domain ID
+ * @arg: User-provided arguments (unused, here for ioctl callback template).
+ * @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_start_domain(struct dlb2_hw *hw,
+		     u32 domain_id,
+		     __attribute((unused)) struct dlb2_start_domain_args *arg,
+		     struct dlb2_cmd_response *resp,
+		     bool vdev_req,
+		     unsigned int vdev_id)
+{
+	struct dlb2_list_entry *iter;
+	struct dlb2_dir_pq_pair *dir_queue;
+	struct dlb2_ldb_queue *ldb_queue;
+	struct dlb2_hw_domain *domain;
+	int ret;
+	RTE_SET_USED(arg);
+	RTE_SET_USED(iter);
+
+	dlb2_log_start_domain(hw, domain_id, vdev_req, vdev_id);
+
+	ret = dlb2_verify_start_domain_args(hw,
+					    domain_id,
+					    resp,
+					    vdev_req,
+					    vdev_id);
+	if (ret)
+		return ret;
+
+	domain = dlb2_get_domain_from_id(hw, domain_id, vdev_req, vdev_id);
+	if (!domain) {
+		DLB2_HW_ERR(hw,
+			    "[%s():%d] Internal error: domain not found\n",
+			    __func__, __LINE__);
+		return -EFAULT;
+	}
+
+	/*
+	 * Enable load-balanced and directed queue write permissions for the
+	 * queues this domain owns. Without this, the DLB2 will drop all
+	 * incoming traffic to those queues.
+	 */
+	DLB2_DOM_LIST_FOR(domain->used_ldb_queues, ldb_queue, iter) {
+		union dlb2_sys_ldb_vasqid_v r0 = { {0} };
+		unsigned int offs;
+
+		r0.field.vasqid_v = 1;
+
+		offs = domain->id.phys_id * DLB2_MAX_NUM_LDB_QUEUES +
+			ldb_queue->id.phys_id;
+
+		DLB2_CSR_WR(hw, DLB2_SYS_LDB_VASQID_V(offs), r0.val);
+	}
+
+	DLB2_DOM_LIST_FOR(domain->used_dir_pq_pairs, dir_queue, iter) {
+		union dlb2_sys_dir_vasqid_v r0 = { {0} };
+		unsigned int offs;
+
+		r0.field.vasqid_v = 1;
+
+		offs = domain->id.phys_id * DLB2_MAX_NUM_DIR_PORTS +
+			dir_queue->id.phys_id;
+
+		DLB2_CSR_WR(hw, DLB2_SYS_DIR_VASQID_V(offs), r0.val);
+	}
+
+	dlb2_flush_csr(hw);
+
+	domain->started = true;
+
+	resp->status = 0;
+
+	return 0;
+}
diff --git a/drivers/event/dlb2/pf/dlb2_main.c b/drivers/event/dlb2/pf/dlb2_main.c
index efa7c1c..ba1c95c 100644
--- a/drivers/event/dlb2/pf/dlb2_main.c
+++ b/drivers/event/dlb2/pf/dlb2_main.c
@@ -680,3 +680,13 @@  dlb2_pf_create_dir_queue(struct dlb2_hw *hw,
 	return dlb2_hw_create_dir_queue(hw, id, args, resp, NOT_VF_REQ,
 					PF_ID_ZERO);
 }
+
+int
+dlb2_pf_start_domain(struct dlb2_hw *hw,
+		     u32 id,
+		     struct dlb2_start_domain_args *args,
+		     struct dlb2_cmd_response *resp)
+{
+	return dlb2_hw_start_domain(hw, id, args, resp, NOT_VF_REQ,
+				    PF_ID_ZERO);
+}
diff --git a/drivers/event/dlb2/pf/dlb2_pf.c b/drivers/event/dlb2/pf/dlb2_pf.c
index a3ee198..084ba64 100644
--- a/drivers/event/dlb2/pf/dlb2_pf.c
+++ b/drivers/event/dlb2/pf/dlb2_pf.c
@@ -508,6 +508,30 @@  dlb2_pf_pending_port_unmaps(struct dlb2_hw_dev *handle,
 
 	return ret;
 }
+
+static int
+dlb2_pf_sched_domain_start(struct dlb2_hw_dev *handle,
+			   struct dlb2_start_domain_args *cfg)
+{
+	struct dlb2_dev *dlb2_dev = (struct dlb2_dev *)handle->pf_dev;
+	struct dlb2_cmd_response response = {0};
+	int ret;
+
+	DLB2_INFO(dev->dlb2_device, "Entering %s()\n", __func__);
+
+	ret = dlb2_pf_start_domain(&dlb2_dev->hw,
+				   handle->domain_id,
+				   cfg,
+				   &response);
+
+	cfg->response = response;
+
+	DLB2_INFO(dev->dlb2_device, "Exiting %s() with ret=%d\n",
+		  __func__, ret);
+
+	return ret;
+}
+
 static void
 dlb2_pf_iface_fn_ptrs_init(void)
 {
@@ -526,6 +550,7 @@  dlb2_pf_iface_fn_ptrs_init(void)
 	dlb2_iface_dir_port_create = dlb2_pf_dir_port_create;
 	dlb2_iface_map_qid = dlb2_pf_map_qid;
 	dlb2_iface_unmap_qid = dlb2_pf_unmap_qid;
+	dlb2_iface_sched_domain_start = dlb2_pf_sched_domain_start;
 	dlb2_iface_pending_port_unmaps = dlb2_pf_pending_port_unmaps;
 	dlb2_iface_get_sn_allocation = dlb2_pf_get_sn_allocation;
 	dlb2_iface_set_sn_allocation = dlb2_pf_set_sn_allocation;