From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from dpdk.org (dpdk.org [92.243.14.124]) by inbox.dpdk.org (Postfix) with ESMTP id D1C32A00BE; Fri, 12 Jun 2020 23:30:03 +0200 (CEST) Received: from [92.243.14.124] (localhost [127.0.0.1]) by dpdk.org (Postfix) with ESMTP id BC5731C23C; Fri, 12 Jun 2020 23:26:53 +0200 (CEST) Received: from mga07.intel.com (mga07.intel.com [134.134.136.100]) by dpdk.org (Postfix) with ESMTP id 47F771BFE8 for ; Fri, 12 Jun 2020 23:26:33 +0200 (CEST) IronPort-SDR: SKVnuVMV/OJiInDxMuj9EOmIEGK2o/IfGCFFj6mVLjV8vicD8MZ7qG54U38SbFCTsQhyP0Iuwf 49vawZD2xUmg== X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from orsmga003.jf.intel.com ([10.7.209.27]) by orsmga105.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 12 Jun 2020 14:26:33 -0700 IronPort-SDR: HvsbTvn9E7hOvNQDuugQ4izYJe9Isenq79ht8zXOESUAiLlQ9GsXtnLTOpHZUuBejng10UDpJI bFeI3WlcSwpQ== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.73,504,1583222400"; d="scan'208";a="272035868" Received: from txasoft-yocto.an.intel.com ([10.123.72.192]) by orsmga003.jf.intel.com with ESMTP; 12 Jun 2020 14:26:32 -0700 From: "McDaniel, Timothy" To: jerinj@marvell.com Cc: dev@dpdk.org, gage.eads@intel.com, harry.van.haaren@intel.com Date: Fri, 12 Jun 2020 16:24:27 -0500 Message-Id: <20200612212434.6852-21-timothy.mcdaniel@intel.com> X-Mailer: git-send-email 2.13.6 In-Reply-To: <20200612212434.6852-1-timothy.mcdaniel@intel.com> References: <20200612212434.6852-1-timothy.mcdaniel@intel.com> Subject: [dpdk-dev] [PATCH 20/27] event/dlb: add port_link X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Sender: "dev" Change-Id: Id86dbdd1070e8102bf602765654fe5afde0e0d6c Signed-off-by: McDaniel, Timothy --- drivers/event/dlb/dlb.c | 303 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 303 insertions(+) diff --git a/drivers/event/dlb/dlb.c b/drivers/event/dlb/dlb.c index deea474bf..7acf8b33d 100644 --- a/drivers/event/dlb/dlb.c +++ b/drivers/event/dlb/dlb.c @@ -794,6 +794,29 @@ dlb_hw_create_ldb_queue(struct dlb_eventdev *dlb, return qm_qid; } +static int32_t +dlb_hw_create_dir_queue(struct dlb_eventdev *dlb, int32_t qm_port_id) +{ + struct dlb_hw_dev *handle = &dlb->qm_instance; + struct dlb_create_dir_queue_args cfg; + struct dlb_cmd_response response; + int32_t ret; + + cfg.response = (uintptr_t)&response; + + /* The directed port is always configured before its queue */ + cfg.port_id = qm_port_id; + + ret = dlb_iface_dir_queue_create(handle, &cfg); + if (ret < 0) { + DLB_LOG_ERR("dlb: create DIR event queue error, ret=%d (driver status: %s)\n", + ret, dlb_error_strings[response.status]); + return -EINVAL; + } + + return response.id; +} + static inline void dlb_hw_do_enqueue(struct dlb_port *qm_port, struct process_local_port_data *port_data) @@ -803,6 +826,42 @@ dlb_hw_do_enqueue(struct dlb_port *qm_port, dlb_pp_write(qm_port->qe4, port_data); } +static int16_t +dlb_hw_map_ldb_qid_to_port(struct dlb_hw_dev *handle, + uint32_t qm_port_id, + uint16_t qm_qid, + uint8_t priority) +{ + struct dlb_map_qid_args cfg; + struct dlb_cmd_response response; + int32_t ret; + + if (handle == NULL) + return -EINVAL; + + /* Build message */ + cfg.response = (uintptr_t)&response; + cfg.port_id = qm_port_id; + cfg.qid = qm_qid; + cfg.priority = EV_TO_DLB_PRIO(priority); + + ret = dlb_iface_map_qid(handle, &cfg); + if (ret < 0) { + DLB_LOG_ERR("dlb: map qid error, ret=%d (driver status: %s)\n", + ret, dlb_error_strings[response.status]); + DLB_LOG_ERR("dlb: device_id=%d grp=%d, qm_port=%d, qm_qid=%d prio=%d\n", + handle->device_id, + handle->domain_id, cfg.port_id, + cfg.qid, + cfg.priority); + } else { + DLB_LOG_DBG("dlb: mapped queue %d to qm_port %d\n", + qm_qid, qm_port_id); + } + + return ret; +} + /* VDEV-only notes: * This function first unmaps all memory mappings and closes the * domain's file descriptor, which causes the driver to reset the @@ -1785,6 +1844,249 @@ dlb_eventdev_configure(const struct rte_eventdev *dev) return 0; } +static int +dlb_event_queue_join_ldb(struct dlb_eventdev *dlb, + struct dlb_eventdev_port *ev_port, + struct dlb_eventdev_queue *ev_queue, + uint8_t priority) +{ + int first_avail = -1; + int ret, i; + + for (i = 0; i < DLB_MAX_NUM_QIDS_PER_LDB_CQ; i++) { + if (ev_port->link[i].valid) { + if (ev_port->link[i].queue_id == ev_queue->id && + ev_port->link[i].priority == priority) { + if (ev_port->link[i].mapped) + return 0; /* already mapped */ + first_avail = i; + } + } else { + if (first_avail == -1) + first_avail = i; + } + } + if (first_avail == -1) { + DLB_LOG_ERR("dlb: qm_port %d has no available QID slots.\n", + ev_port->qm_port.id); + return -EINVAL; + } + + ret = dlb_hw_map_ldb_qid_to_port(&dlb->qm_instance, + ev_port->qm_port.id, + ev_queue->qm_queue.id, + priority); + + if (!ret) + ev_port->link[first_avail].mapped = true; + + return ret; +} + +static int +dlb_eventdev_dir_queue_setup(struct dlb_eventdev *dlb, + struct dlb_eventdev_queue *ev_queue, + struct dlb_eventdev_port *ev_port) +{ + int32_t qm_qid; + + qm_qid = dlb_hw_create_dir_queue(dlb, ev_port->qm_port.id); + + if (qm_qid < 0) { + DLB_LOG_ERR("Failed to create the DIR queue\n"); + return qm_qid; + } + + dlb->qm_dir_to_ev_queue_id[qm_qid] = ev_queue->id; + + ev_queue->qm_queue.id = qm_qid; + + return 0; +} + +static int +dlb_do_port_link(struct rte_eventdev *dev, + struct dlb_eventdev_queue *ev_queue, + struct dlb_eventdev_port *ev_port, + uint8_t prio) +{ + struct dlb_eventdev *dlb = dlb_pmd_priv(dev); + int err; + + /* Don't link until start time. */ + if (dlb->run_state == DLB_RUN_STATE_STOPPED) + return 0; + + if (ev_queue->qm_queue.is_directed) + err = dlb_eventdev_dir_queue_setup(dlb, ev_queue, ev_port); + else + err = dlb_event_queue_join_ldb(dlb, ev_port, ev_queue, prio); + + if (err) { + DLB_LOG_ERR("port link failure for %s ev_q %d, ev_port %d\n", + ev_queue->qm_queue.is_directed ? "DIR" : "LDB", + ev_queue->id, ev_port->id); + + rte_errno = err; + return -1; + } + + return 0; +} + +static int +dlb_validate_port_link(struct dlb_eventdev_port *ev_port, + uint8_t queue_id, + bool link_exists, + int index) +{ + struct dlb_eventdev *dlb = ev_port->dlb; + struct dlb_eventdev_queue *ev_queue; + bool port_is_dir, queue_is_dir; + + if (queue_id > dlb->num_queues) { + rte_errno = -EINVAL; + return -1; + } + + ev_queue = &dlb->ev_queues[queue_id]; + + if (!ev_queue->setup_done && + ev_queue->qm_queue.config_state != DLB_PREV_CONFIGURED) { + rte_errno = -EINVAL; + return -1; + } + + port_is_dir = ev_port->qm_port.is_directed; + queue_is_dir = ev_queue->qm_queue.is_directed; + + if (port_is_dir != queue_is_dir) { + DLB_LOG_ERR("%s queue %u can't link to %s port %u\n", + queue_is_dir ? "DIR" : "LDB", ev_queue->id, + port_is_dir ? "DIR" : "LDB", ev_port->id); + + rte_errno = -EINVAL; + return -1; + } + + /* Check if there is space for the requested link */ + if (!link_exists && index == -1) { + DLB_LOG_ERR("no space for new link\n"); + rte_errno = -ENOSPC; + return -1; + } + + /* Check if the directed port is already linked */ + if (ev_port->qm_port.is_directed && ev_port->num_links > 0 && + !link_exists) { + DLB_LOG_ERR("Can't link DIR port %d to >1 queues\n", + ev_port->id); + rte_errno = -EINVAL; + return -1; + } + + /* Check if the directed queue is already linked */ + if (ev_queue->qm_queue.is_directed && ev_queue->num_links > 0 && + !link_exists) { + DLB_LOG_ERR("Can't link DIR queue %d to >1 ports\n", + ev_queue->id); + rte_errno = -EINVAL; + return -1; + } + + return 0; +} + +static int +dlb_eventdev_port_link(struct rte_eventdev *dev, void *event_port, + const uint8_t queues[], const uint8_t priorities[], + uint16_t nb_links) + +{ + struct dlb_eventdev_port *ev_port = event_port; + struct dlb_eventdev *dlb; + int i, j; + + RTE_SET_USED(dev); + + if (!ev_port) { + DLB_LOG_ERR("dlb: evport not setup\n"); + rte_errno = -EINVAL; + return 0; + } + + if (!ev_port->setup_done && + ev_port->qm_port.config_state != DLB_PREV_CONFIGURED) { + DLB_LOG_ERR("dlb: evport not setup\n"); + rte_errno = -EINVAL; + return 0; + } + + /* Note: rte_event_port_link() ensures the PMD won't receive a NULL + * queues pointer. + */ + if (nb_links == 0) { + DLB_LOG_DBG("dlb: nb_links is 0\n"); + return 0; /* Ignore and return success */ + } + + dlb = ev_port->dlb; + + DLB_LOG_DBG("Linking %u queues to %s port %d\n", + nb_links, + ev_port->qm_port.is_directed ? "DIR" : "LDB", + ev_port->id); + + for (i = 0; i < nb_links; i++) { + struct dlb_eventdev_queue *ev_queue; + uint8_t queue_id, prio; + bool found = false; + int index = -1; + + queue_id = queues[i]; + prio = priorities[i]; + + /* Check if the link already exists. */ + for (j = 0; j < DLB_MAX_NUM_QIDS_PER_LDB_CQ; j++) + if (ev_port->link[j].valid) { + if (ev_port->link[j].queue_id == queue_id) { + found = true; + index = j; + break; + } + } else { + if (index == -1) + index = j; + } + + /* could not link */ + if (index == -1) + break; + + /* Check if already linked at the requested priority */ + if (found && ev_port->link[j].priority == prio) + continue; + + if (dlb_validate_port_link(ev_port, queue_id, found, index)) + break; /* return index of offending queue */ + + ev_queue = &dlb->ev_queues[queue_id]; + + if (dlb_do_port_link(dev, ev_queue, ev_port, prio)) + break; /* return index of offending queue */ + + ev_queue->num_links++; + + ev_port->link[index].queue_id = queue_id; + ev_port->link[index].priority = prio; + ev_port->link[index].valid = true; + /* Entry already exists? If so, then must be prio change */ + if (!found) + ev_port->num_links++; + } + return i; +} + static void dlb_eventdev_port_default_conf_get(struct rte_eventdev *dev, uint8_t port_id, @@ -2255,6 +2557,7 @@ dlb_entry_points_init(struct rte_eventdev *dev) .queue_setup = dlb_eventdev_queue_setup, .port_def_conf = dlb_eventdev_port_default_conf_get, .port_setup = dlb_eventdev_port_setup, + .port_link = dlb_eventdev_port_link, }; /* Expose PMD's eventdev interface */ -- 2.13.6