From patchwork Sat Jun 27 04:37:44 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Timothy McDaniel X-Patchwork-Id: 72310 X-Patchwork-Delegate: jerinj@marvell.com Return-Path: X-Original-To: patchwork@inbox.dpdk.org Delivered-To: patchwork@inbox.dpdk.org Received: from dpdk.org (dpdk.org [92.243.14.124]) by inbox.dpdk.org (Postfix) with ESMTP id F3EF7A0520; Sat, 27 Jun 2020 06:43:53 +0200 (CEST) Received: from [92.243.14.124] (localhost [127.0.0.1]) by dpdk.org (Postfix) with ESMTP id B41D01C00F; Sat, 27 Jun 2020 06:40:29 +0200 (CEST) Received: from mga17.intel.com (mga17.intel.com [192.55.52.151]) by dpdk.org (Postfix) with ESMTP id 474A81BF5F for ; Sat, 27 Jun 2020 06:40:10 +0200 (CEST) IronPort-SDR: APlbI84ljwxhqcnZ+d6d6tGK8S1Nx+BfNEh7GBsJlT3/cyN8OEovhm6awgTVfzhYkJILBkxR2G I8ZtAWm/9glg== X-IronPort-AV: E=McAfee;i="6000,8403,9664"; a="125753091" X-IronPort-AV: E=Sophos;i="5.75,286,1589266800"; d="scan'208";a="125753091" X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from fmsmga006.fm.intel.com ([10.253.24.20]) by fmsmga107.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 26 Jun 2020 21:40:09 -0700 IronPort-SDR: pK0ZQf2T+1UNvhvUBO0BVEDmuKmOL8z9NTcBmKRP/HBD+W9NuHNJPZlzWSCQzlTpuPCR9mU6xz s4P39Y6UEFvA== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.75,286,1589266800"; d="scan'208";a="480023010" Received: from txasoft-yocto.an.intel.com ([10.123.72.192]) by fmsmga006.fm.intel.com with ESMTP; 26 Jun 2020 21:40:09 -0700 From: Tim McDaniel To: jerinj@marvell.com Cc: mattias.ronnblom@ericsson.com, dev@dpdk.org, gage.eads@intel.com, harry.van.haaren@intel.com, "McDaniel, Timothy" Date: Fri, 26 Jun 2020 23:37:44 -0500 Message-Id: <1593232671-5690-21-git-send-email-timothy.mcdaniel@intel.com> X-Mailer: git-send-email 1.7.10 In-Reply-To: <1593232671-5690-1-git-send-email-timothy.mcdaniel@intel.com> References: <1593232671-5690-1-git-send-email-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" From: "McDaniel, Timothy" 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 796b496..786c252 100644 --- a/drivers/event/dlb/dlb.c +++ b/drivers/event/dlb/dlb.c @@ -786,6 +786,29 @@ int dlb_string_to_int(int *result, const char *str) 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) @@ -795,6 +818,42 @@ int dlb_string_to_int(int *result, const char *str) 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 @@ -1778,6 +1837,249 @@ int dlb_string_to_int(int *result, const char *str) 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, @@ -2248,6 +2550,7 @@ static int dlb_num_dir_queues_setup(struct dlb_eventdev *dlb) .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 */