get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

GET /api/patches/77496/?format=api
HTTP 200 OK
Allow: GET, PUT, PATCH, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

{
    "id": 77496,
    "url": "http://patches.dpdk.org/api/patches/77496/?format=api",
    "web_url": "http://patches.dpdk.org/project/dpdk/patch/1599851920-16802-13-git-send-email-timothy.mcdaniel@intel.com/",
    "project": {
        "id": 1,
        "url": "http://patches.dpdk.org/api/projects/1/?format=api",
        "name": "DPDK",
        "link_name": "dpdk",
        "list_id": "dev.dpdk.org",
        "list_email": "dev@dpdk.org",
        "web_url": "http://core.dpdk.org",
        "scm_url": "git://dpdk.org/dpdk",
        "webscm_url": "http://git.dpdk.org/dpdk",
        "list_archive_url": "https://inbox.dpdk.org/dev",
        "list_archive_url_format": "https://inbox.dpdk.org/dev/{}",
        "commit_url_format": ""
    },
    "msgid": "<1599851920-16802-13-git-send-email-timothy.mcdaniel@intel.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/1599851920-16802-13-git-send-email-timothy.mcdaniel@intel.com",
    "date": "2020-09-11T19:18:30",
    "name": "[v4,12/22] event/dlb: add port link",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": true,
    "hash": "defcf2fae484556d323f3f5c474a49227901c9d2",
    "submitter": {
        "id": 826,
        "url": "http://patches.dpdk.org/api/people/826/?format=api",
        "name": "Timothy McDaniel",
        "email": "timothy.mcdaniel@intel.com"
    },
    "delegate": {
        "id": 310,
        "url": "http://patches.dpdk.org/api/users/310/?format=api",
        "username": "jerin",
        "first_name": "Jerin",
        "last_name": "Jacob",
        "email": "jerinj@marvell.com"
    },
    "mbox": "http://patches.dpdk.org/project/dpdk/patch/1599851920-16802-13-git-send-email-timothy.mcdaniel@intel.com/mbox/",
    "series": [
        {
            "id": 12163,
            "url": "http://patches.dpdk.org/api/series/12163/?format=api",
            "web_url": "http://patches.dpdk.org/project/dpdk/list/?series=12163",
            "date": "2020-09-11T19:18:18",
            "name": "Add DLB PMD",
            "version": 4,
            "mbox": "http://patches.dpdk.org/series/12163/mbox/"
        }
    ],
    "comments": "http://patches.dpdk.org/api/patches/77496/comments/",
    "check": "warning",
    "checks": "http://patches.dpdk.org/api/patches/77496/checks/",
    "tags": {},
    "related": [],
    "headers": {
        "Return-Path": "<dev-bounces@dpdk.org>",
        "X-Original-To": "patchwork@inbox.dpdk.org",
        "Delivered-To": "patchwork@inbox.dpdk.org",
        "Received": [
            "from dpdk.org (dpdk.org [92.243.14.124])\n\tby inbox.dpdk.org (Postfix) with ESMTP id F1052A04C1;\n\tFri, 11 Sep 2020 21:24:17 +0200 (CEST)",
            "from [92.243.14.124] (localhost [127.0.0.1])\n\tby dpdk.org (Postfix) with ESMTP id D47901C1F8;\n\tFri, 11 Sep 2020 21:22:25 +0200 (CEST)",
            "from mga12.intel.com (mga12.intel.com [192.55.52.136])\n by dpdk.org (Postfix) with ESMTP id B11471C1AB\n for <dev@dpdk.org>; Fri, 11 Sep 2020 21:22:12 +0200 (CEST)",
            "from fmsmga005.fm.intel.com ([10.253.24.32])\n by fmsmga106.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384;\n 11 Sep 2020 12:22:11 -0700",
            "from txasoft-yocto.an.intel.com ([10.123.72.192])\n by fmsmga005.fm.intel.com with ESMTP; 11 Sep 2020 12:22:10 -0700"
        ],
        "IronPort-SDR": [
            "\n yYSy8LNUSA6EP9BbudNoX0USoeJNDa+tB3EWA4QVwrmT1Qa3c6ElbuB5Y099DQAfbUaHTDYTp5\n VkHJrnvfTU9A==",
            "\n XoKXW5dWr8gcuu3p8M74nFI4Ezu1qfUzG+idr7CJSMCIqUh7TspPay3nG/UUuKtahidM07YOuH\n VKJseeGCXLeA=="
        ],
        "X-IronPort-AV": [
            "E=McAfee;i=\"6000,8403,9741\"; a=\"138352274\"",
            "E=Sophos;i=\"5.76,416,1592895600\"; d=\"scan'208\";a=\"138352274\"",
            "E=Sophos;i=\"5.76,416,1592895600\"; d=\"scan'208\";a=\"506375679\""
        ],
        "X-Amp-Result": "SKIPPED(no attachment in message)",
        "X-Amp-File-Uploaded": "False",
        "X-ExtLoop1": "1",
        "From": "Timothy McDaniel <timothy.mcdaniel@intel.com>",
        "To": "",
        "Cc": "dev@dpdk.org, erik.g.carrillo@intel.com, gage.eads@intel.com,\n harry.van.haaren@intel.com, jerinj@marvell.com",
        "Date": "Fri, 11 Sep 2020 14:18:30 -0500",
        "Message-Id": "<1599851920-16802-13-git-send-email-timothy.mcdaniel@intel.com>",
        "X-Mailer": "git-send-email 1.7.10",
        "In-Reply-To": "<1599851920-16802-1-git-send-email-timothy.mcdaniel@intel.com>",
        "References": "<1599851920-16802-1-git-send-email-timothy.mcdaniel@intel.com>",
        "Subject": "[dpdk-dev] [PATCH v4 12/22] event/dlb: add port link",
        "X-BeenThere": "dev@dpdk.org",
        "X-Mailman-Version": "2.1.15",
        "Precedence": "list",
        "List-Id": "DPDK patches and discussions <dev.dpdk.org>",
        "List-Unsubscribe": "<https://mails.dpdk.org/options/dev>,\n <mailto:dev-request@dpdk.org?subject=unsubscribe>",
        "List-Archive": "<http://mails.dpdk.org/archives/dev/>",
        "List-Post": "<mailto:dev@dpdk.org>",
        "List-Help": "<mailto:dev-request@dpdk.org?subject=help>",
        "List-Subscribe": "<https://mails.dpdk.org/listinfo/dev>,\n <mailto:dev-request@dpdk.org?subject=subscribe>",
        "Errors-To": "dev-bounces@dpdk.org",
        "Sender": "\"dev\" <dev-bounces@dpdk.org>"
    },
    "content": "Add port link entry point. Directed queues are identified and created\nat this stage. Their setup defered until link-time, at which\npoint we know the directed port ID. Directed queue setup\nwill only fail if this queue is already setup or there are\nno directed queues left to configure.\n\nSigned-off-by: Timothy McDaniel <timothy.mcdaniel@intel.com>\n---\n drivers/event/dlb/dlb.c                  | 306 +++++++++++++++\n drivers/event/dlb/dlb_iface.c            |   9 +\n drivers/event/dlb/dlb_iface.h            |   9 +\n drivers/event/dlb/pf/base/dlb_resource.c | 641 +++++++++++++++++++++++++++++++\n drivers/event/dlb/pf/dlb_pf.c            |  69 ++++\n 5 files changed, 1034 insertions(+)",
    "diff": "diff --git a/drivers/event/dlb/dlb.c b/drivers/event/dlb/dlb.c\nindex e90a088..c3ad2ee 100644\n--- a/drivers/event/dlb/dlb.c\n+++ b/drivers/event/dlb/dlb.c\n@@ -1563,6 +1563,311 @@ set_num_atm_inflights(const char *key __rte_unused,\n \treturn 0;\n }\n \n+static int\n+dlb_validate_port_link(struct dlb_eventdev_port *ev_port,\n+\t\t       uint8_t queue_id,\n+\t\t       bool link_exists,\n+\t\t       int index)\n+{\n+\tstruct dlb_eventdev *dlb = ev_port->dlb;\n+\tstruct dlb_eventdev_queue *ev_queue;\n+\tbool port_is_dir, queue_is_dir;\n+\n+\tif (queue_id > dlb->num_queues) {\n+\t\tDLB_LOG_ERR(\"queue_id %d > num queues %d\\n\",\n+\t\t\t    queue_id, dlb->num_queues);\n+\t\trte_errno = -EINVAL;\n+\t\treturn -1;\n+\t}\n+\n+\tev_queue = &dlb->ev_queues[queue_id];\n+\n+\tif (!ev_queue->setup_done &&\n+\t    ev_queue->qm_queue.config_state != DLB_PREV_CONFIGURED) {\n+\t\tDLB_LOG_ERR(\"setup not done and not previously configured\\n\");\n+\t\trte_errno = -EINVAL;\n+\t\treturn -1;\n+\t}\n+\n+\tport_is_dir = ev_port->qm_port.is_directed;\n+\tqueue_is_dir = ev_queue->qm_queue.is_directed;\n+\n+\tif (port_is_dir != queue_is_dir) {\n+\t\tDLB_LOG_ERR(\"%s queue %u can't link to %s port %u\\n\",\n+\t\t\t    queue_is_dir ? \"DIR\" : \"LDB\", ev_queue->id,\n+\t\t\t    port_is_dir ? \"DIR\" : \"LDB\", ev_port->id);\n+\n+\t\trte_errno = -EINVAL;\n+\t\treturn -1;\n+\t}\n+\n+\t/* Check if there is space for the requested link */\n+\tif (!link_exists && index == -1) {\n+\t\tDLB_LOG_ERR(\"no space for new link\\n\");\n+\t\trte_errno = -ENOSPC;\n+\t\treturn -1;\n+\t}\n+\n+\t/* Check if the directed port is already linked */\n+\tif (ev_port->qm_port.is_directed && ev_port->num_links > 0 &&\n+\t    !link_exists) {\n+\t\tDLB_LOG_ERR(\"Can't link DIR port %d to >1 queues\\n\",\n+\t\t\t    ev_port->id);\n+\t\trte_errno = -EINVAL;\n+\t\treturn -1;\n+\t}\n+\n+\t/* Check if the directed queue is already linked */\n+\tif (ev_queue->qm_queue.is_directed && ev_queue->num_links > 0 &&\n+\t    !link_exists) {\n+\t\tDLB_LOG_ERR(\"Can't link DIR queue %d to >1 ports\\n\",\n+\t\t\t    ev_queue->id);\n+\t\trte_errno = -EINVAL;\n+\t\treturn -1;\n+\t}\n+\n+\treturn 0;\n+}\n+\n+static int16_t\n+dlb_hw_map_ldb_qid_to_port(struct dlb_hw_dev *handle,\n+\t\t\t   uint32_t qm_port_id,\n+\t\t\t   uint16_t qm_qid,\n+\t\t\t   uint8_t priority)\n+{\n+\tstruct dlb_map_qid_args cfg;\n+\tstruct dlb_cmd_response response;\n+\tint32_t ret;\n+\n+\tif (handle == NULL)\n+\t\treturn -EINVAL;\n+\n+\t/* Build message */\n+\tcfg.response = (uintptr_t)&response;\n+\tcfg.port_id = qm_port_id;\n+\tcfg.qid = qm_qid;\n+\tcfg.priority = EV_TO_DLB_PRIO(priority);\n+\n+\tret = dlb_iface_map_qid(handle, &cfg);\n+\tif (ret < 0) {\n+\t\tDLB_LOG_ERR(\"dlb: map qid error, ret=%d (driver status: %s)\\n\",\n+\t\t\t    ret, dlb_error_strings[response.status]);\n+\t\tDLB_LOG_ERR(\"dlb: device_id=%d grp=%d, qm_port=%d, qm_qid=%d prio=%d\\n\",\n+\t\t\t    handle->device_id,\n+\t\t\t    handle->domain_id, cfg.port_id,\n+\t\t\t    cfg.qid,\n+\t\t\t    cfg.priority);\n+\t} else {\n+\t\tDLB_LOG_DBG(\"dlb: mapped queue %d to qm_port %d\\n\",\n+\t\t\t    qm_qid, qm_port_id);\n+\t}\n+\n+\treturn ret;\n+}\n+\n+static int\n+dlb_event_queue_join_ldb(struct dlb_eventdev *dlb,\n+\t\t\t struct dlb_eventdev_port *ev_port,\n+\t\t\t struct dlb_eventdev_queue *ev_queue,\n+\t\t\t uint8_t priority)\n+{\n+\tint first_avail = -1;\n+\tint ret, i;\n+\n+\tfor (i = 0; i < DLB_MAX_NUM_QIDS_PER_LDB_CQ; i++) {\n+\t\tif (ev_port->link[i].valid) {\n+\t\t\tif (ev_port->link[i].queue_id == ev_queue->id &&\n+\t\t\t    ev_port->link[i].priority == priority) {\n+\t\t\t\tif (ev_port->link[i].mapped)\n+\t\t\t\t\treturn 0; /* already mapped */\n+\t\t\t\tfirst_avail = i;\n+\t\t\t}\n+\t\t} else {\n+\t\t\tif (first_avail == -1)\n+\t\t\t\tfirst_avail = i;\n+\t\t}\n+\t}\n+\tif (first_avail == -1) {\n+\t\tDLB_LOG_ERR(\"dlb: qm_port %d has no available QID slots.\\n\",\n+\t\t\t    ev_port->qm_port.id);\n+\t\treturn -EINVAL;\n+\t}\n+\n+\tret = dlb_hw_map_ldb_qid_to_port(&dlb->qm_instance,\n+\t\t\t\t\t ev_port->qm_port.id,\n+\t\t\t\t\t ev_queue->qm_queue.id,\n+\t\t\t\t\t priority);\n+\n+\tif (!ret)\n+\t\tev_port->link[first_avail].mapped = true;\n+\n+\treturn ret;\n+}\n+\n+static int32_t\n+dlb_hw_create_dir_queue(struct dlb_eventdev *dlb, int32_t qm_port_id)\n+{\n+\tstruct dlb_hw_dev *handle = &dlb->qm_instance;\n+\tstruct dlb_create_dir_queue_args cfg;\n+\tstruct dlb_cmd_response response;\n+\tint32_t ret;\n+\n+\tcfg.response = (uintptr_t)&response;\n+\n+\t/* The directed port is always configured before its queue */\n+\tcfg.port_id = qm_port_id;\n+\n+\tret = dlb_iface_dir_queue_create(handle, &cfg);\n+\tif (ret < 0) {\n+\t\tDLB_LOG_ERR(\"dlb: create DIR event queue error, ret=%d (driver status: %s)\\n\",\n+\t\t\t    ret, dlb_error_strings[response.status]);\n+\t\treturn -EINVAL;\n+\t}\n+\n+\treturn response.id;\n+}\n+\n+static int\n+dlb_eventdev_dir_queue_setup(struct dlb_eventdev *dlb,\n+\t\t\t     struct dlb_eventdev_queue *ev_queue,\n+\t\t\t     struct dlb_eventdev_port *ev_port)\n+{\n+\tint32_t qm_qid;\n+\n+\tqm_qid = dlb_hw_create_dir_queue(dlb, ev_port->qm_port.id);\n+\n+\tif (qm_qid < 0) {\n+\t\tDLB_LOG_ERR(\"Failed to create the DIR queue\\n\");\n+\t\treturn qm_qid;\n+\t}\n+\n+\tdlb->qm_dir_to_ev_queue_id[qm_qid] = ev_queue->id;\n+\n+\tev_queue->qm_queue.id = qm_qid;\n+\n+\treturn 0;\n+}\n+\n+static int\n+dlb_do_port_link(struct rte_eventdev *dev,\n+\t\t struct dlb_eventdev_queue *ev_queue,\n+\t\t struct dlb_eventdev_port *ev_port,\n+\t\t uint8_t prio)\n+{\n+\tstruct dlb_eventdev *dlb = dlb_pmd_priv(dev);\n+\tint err;\n+\n+\t/* Don't link until start time. */\n+\tif (dlb->run_state == DLB_RUN_STATE_STOPPED)\n+\t\treturn 0;\n+\n+\tif (ev_queue->qm_queue.is_directed)\n+\t\terr = dlb_eventdev_dir_queue_setup(dlb, ev_queue, ev_port);\n+\telse\n+\t\terr = dlb_event_queue_join_ldb(dlb, ev_port, ev_queue, prio);\n+\n+\tif (err) {\n+\t\tDLB_LOG_ERR(\"port link failure for %s ev_q %d, ev_port %d\\n\",\n+\t\t\t    ev_queue->qm_queue.is_directed ? \"DIR\" : \"LDB\",\n+\t\t\t    ev_queue->id, ev_port->id);\n+\n+\t\trte_errno = err;\n+\t\treturn -1;\n+\t}\n+\n+\treturn 0;\n+}\n+\n+static int\n+dlb_eventdev_port_link(struct rte_eventdev *dev, void *event_port,\n+\t\t       const uint8_t queues[], const uint8_t priorities[],\n+\t\t       uint16_t nb_links)\n+\n+{\n+\tstruct dlb_eventdev_port *ev_port = event_port;\n+\tstruct dlb_eventdev *dlb;\n+\tint i, j;\n+\n+\tRTE_SET_USED(dev);\n+\n+\tif (!ev_port) {\n+\t\tDLB_LOG_ERR(\"dlb: evport not setup\\n\");\n+\t\trte_errno = -EINVAL;\n+\t\treturn 0;\n+\t}\n+\n+\tif (!ev_port->setup_done &&\n+\t    ev_port->qm_port.config_state != DLB_PREV_CONFIGURED) {\n+\t\tDLB_LOG_ERR(\"dlb: evport not setup\\n\");\n+\t\trte_errno = -EINVAL;\n+\t\treturn 0;\n+\t}\n+\n+\t/* Note: rte_event_port_link() ensures the PMD won't receive a NULL\n+\t * queues pointer.\n+\t */\n+\tif (nb_links == 0) {\n+\t\tDLB_LOG_DBG(\"dlb: nb_links is 0\\n\");\n+\t\treturn 0; /* Ignore and return success */\n+\t}\n+\n+\tdlb = ev_port->dlb;\n+\n+\tDLB_LOG_DBG(\"Linking %u queues to %s port %d\\n\",\n+\t\t    nb_links,\n+\t\t    ev_port->qm_port.is_directed ? \"DIR\" : \"LDB\",\n+\t\t    ev_port->id);\n+\n+\tfor (i = 0; i < nb_links; i++) {\n+\t\tstruct dlb_eventdev_queue *ev_queue;\n+\t\tuint8_t queue_id, prio;\n+\t\tbool found = false;\n+\t\tint index = -1;\n+\n+\t\tqueue_id = queues[i];\n+\t\tprio = priorities[i];\n+\n+\t\t/* Check if the link already exists. */\n+\t\tfor (j = 0; j < DLB_MAX_NUM_QIDS_PER_LDB_CQ; j++)\n+\t\t\tif (ev_port->link[j].valid) {\n+\t\t\t\tif (ev_port->link[j].queue_id == queue_id) {\n+\t\t\t\t\tfound = true;\n+\t\t\t\t\tindex = j;\n+\t\t\t\t\tbreak;\n+\t\t\t\t}\n+\t\t\t} else {\n+\t\t\t\tif (index == -1)\n+\t\t\t\t\tindex = j;\n+\t\t\t}\n+\n+\t\t/* could not link */\n+\t\tif (index == -1)\n+\t\t\tbreak;\n+\n+\t\t/* Check if already linked at the requested priority */\n+\t\tif (found && ev_port->link[j].priority == prio)\n+\t\t\tcontinue;\n+\n+\t\tif (dlb_validate_port_link(ev_port, queue_id, found, index))\n+\t\t\tbreak; /* return index of offending queue */\n+\n+\t\tev_queue = &dlb->ev_queues[queue_id];\n+\n+\t\tif (dlb_do_port_link(dev, ev_queue, ev_port, prio))\n+\t\t\tbreak; /* return index of offending queue */\n+\n+\t\tev_queue->num_links++;\n+\n+\t\tev_port->link[index].queue_id = queue_id;\n+\t\tev_port->link[index].priority = prio;\n+\t\tev_port->link[index].valid = true;\n+\t\t/* Entry already exists?  If so, then must be prio change */\n+\t\tif (!found)\n+\t\t\tev_port->num_links++;\n+\t}\n+\treturn i;\n+}\n+\n void\n dlb_entry_points_init(struct rte_eventdev *dev)\n {\n@@ -1573,6 +1878,7 @@ dlb_entry_points_init(struct rte_eventdev *dev)\n \t\t.port_def_conf    = dlb_eventdev_port_default_conf_get,\n \t\t.queue_setup      = dlb_eventdev_queue_setup,\n \t\t.port_setup       = dlb_eventdev_port_setup,\n+\t\t.port_link        = dlb_eventdev_port_link,\n \t\t.dump             = dlb_eventdev_dump,\n \t\t.xstats_get       = dlb_eventdev_xstats_get,\n \t\t.xstats_get_names = dlb_eventdev_xstats_get_names,\ndiff --git a/drivers/event/dlb/dlb_iface.c b/drivers/event/dlb/dlb_iface.c\nindex 0302be4..3d34c89 100644\n--- a/drivers/event/dlb/dlb_iface.c\n+++ b/drivers/event/dlb/dlb_iface.c\n@@ -61,6 +61,15 @@ int (*dlb_iface_dir_port_create)(struct dlb_hw_dev *handle,\n \t\t\t\t struct dlb_create_dir_port_args *cfg,\n \t\t\t\t enum dlb_cq_poll_modes poll_mode);\n \n+int (*dlb_iface_map_qid)(struct dlb_hw_dev *handle,\n+\t\t\t struct dlb_map_qid_args *cfg);\n+\n+int (*dlb_iface_unmap_qid)(struct dlb_hw_dev *handle,\n+\t\t\t   struct dlb_unmap_qid_args *cfg);\n+\n+int (*dlb_iface_pending_port_unmaps)(struct dlb_hw_dev *handle,\n+\t\t\t\t     struct dlb_pending_port_unmaps_args *args);\n+\n int (*dlb_iface_get_cq_poll_mode)(struct dlb_hw_dev *handle,\n \t\t\t\t  enum dlb_cq_poll_modes *mode);\n \ndiff --git a/drivers/event/dlb/dlb_iface.h b/drivers/event/dlb/dlb_iface.h\nindex d578185..c0f5f2e 100644\n--- a/drivers/event/dlb/dlb_iface.h\n+++ b/drivers/event/dlb/dlb_iface.h\n@@ -49,6 +49,15 @@ extern int (*dlb_iface_dir_port_create)(struct dlb_hw_dev *handle,\n extern int (*dlb_iface_ldb_queue_create)(struct dlb_hw_dev *handle,\n \t\t\t\t  struct dlb_create_ldb_queue_args *cfg);\n \n+extern int (*dlb_iface_map_qid)(struct dlb_hw_dev *handle,\n+\t\t\t struct dlb_map_qid_args *cfg);\n+\n+extern int (*dlb_iface_unmap_qid)(struct dlb_hw_dev *handle,\n+\t\t\t\t  struct dlb_unmap_qid_args *cfg);\n+\n+extern int (*dlb_iface_pending_port_unmaps)(struct dlb_hw_dev *handle,\n+\t\t\t\tstruct dlb_pending_port_unmaps_args *args);\n+\n extern int (*dlb_iface_get_cq_poll_mode)(struct dlb_hw_dev *handle,\n \t\t\t\t\t enum dlb_cq_poll_modes *mode);\n \ndiff --git a/drivers/event/dlb/pf/base/dlb_resource.c b/drivers/event/dlb/pf/base/dlb_resource.c\nindex a4d9e4a..34207ff 100644\n--- a/drivers/event/dlb/pf/base/dlb_resource.c\n+++ b/drivers/event/dlb/pf/base/dlb_resource.c\n@@ -6028,3 +6028,644 @@ int dlb_hw_create_dir_port(struct dlb_hw *hw,\n \treturn 0;\n }\n \n+static struct dlb_ldb_port *\n+dlb_get_domain_used_ldb_port(u32 id, struct dlb_domain *domain)\n+{\n+\tstruct dlb_list_entry *iter;\n+\tstruct dlb_ldb_port *port;\n+\tRTE_SET_USED(iter);\n+\n+\tif (id >= DLB_MAX_NUM_LDB_PORTS)\n+\t\treturn NULL;\n+\n+\tDLB_DOM_LIST_FOR(domain->used_ldb_ports, port, iter)\n+\t\tif (port->id == id)\n+\t\t\treturn port;\n+\n+\tDLB_DOM_LIST_FOR(domain->avail_ldb_ports, port, iter)\n+\t\tif (port->id == id)\n+\t\t\treturn port;\n+\n+\treturn NULL;\n+}\n+\n+static void\n+dlb_log_pending_port_unmaps_args(struct dlb_hw *hw,\n+\t\t\t\t struct dlb_pending_port_unmaps_args *args)\n+{\n+\tDLB_HW_INFO(hw, \"DLB pending port unmaps arguments:\\n\");\n+\tDLB_HW_INFO(hw, \"\\tPort ID: %d\\n\", args->port_id);\n+}\n+\n+int dlb_hw_pending_port_unmaps(struct dlb_hw *hw,\n+\t\t\t       u32 domain_id,\n+\t\t\t       struct dlb_pending_port_unmaps_args *args,\n+\t\t\t       struct dlb_cmd_response *resp)\n+{\n+\tstruct dlb_domain *domain;\n+\tstruct dlb_ldb_port *port;\n+\n+\tdlb_log_pending_port_unmaps_args(hw, args);\n+\n+\tdomain = dlb_get_domain_from_id(hw, domain_id);\n+\n+\tif (!domain) {\n+\t\tresp->status = DLB_ST_INVALID_DOMAIN_ID;\n+\t\treturn -EINVAL;\n+\t}\n+\n+\tport = dlb_get_domain_used_ldb_port(args->port_id, domain);\n+\tif (!port || !port->configured) {\n+\t\tresp->status = DLB_ST_INVALID_PORT_ID;\n+\t\treturn -EINVAL;\n+\t}\n+\n+\tresp->id = port->num_pending_removals;\n+\n+\treturn 0;\n+}\n+\n+static void dlb_log_unmap_qid(struct dlb_hw *hw,\n+\t\t\t      u32 domain_id,\n+\t\t\t      struct dlb_unmap_qid_args *args)\n+{\n+\tDLB_HW_INFO(hw, \"DLB unmap QID arguments:\\n\");\n+\tDLB_HW_INFO(hw, \"\\tDomain ID: %d\\n\",\n+\t\t    domain_id);\n+\tDLB_HW_INFO(hw, \"\\tPort ID:   %d\\n\",\n+\t\t    args->port_id);\n+\tDLB_HW_INFO(hw, \"\\tQueue ID:  %d\\n\",\n+\t\t    args->qid);\n+\tif (args->qid < DLB_MAX_NUM_LDB_QUEUES)\n+\t\tDLB_HW_INFO(hw, \"\\tQueue's num mappings:  %d\\n\",\n+\t\t\t    hw->rsrcs.ldb_queues[args->qid].num_mappings);\n+}\n+\n+static struct dlb_ldb_queue *dlb_get_domain_ldb_queue(u32 id,\n+\t\t\t\t\t\t      struct dlb_domain *domain)\n+{\n+\tstruct dlb_list_entry *iter;\n+\tstruct dlb_ldb_queue *queue;\n+\tRTE_SET_USED(iter);\n+\n+\tif (id >= DLB_MAX_NUM_LDB_QUEUES)\n+\t\treturn NULL;\n+\n+\tDLB_DOM_LIST_FOR(domain->used_ldb_queues, queue, iter)\n+\t\tif (queue->id == id)\n+\t\t\treturn queue;\n+\n+\treturn NULL;\n+}\n+\n+static bool\n+dlb_port_find_slot_with_pending_map_queue(struct dlb_ldb_port *port,\n+\t\t\t\t\t  struct dlb_ldb_queue *queue,\n+\t\t\t\t\t  int *slot)\n+{\n+\tint i;\n+\n+\tfor (i = 0; i < DLB_MAX_NUM_QIDS_PER_LDB_CQ; i++) {\n+\t\tstruct dlb_ldb_port_qid_map *map = &port->qid_map[i];\n+\n+\t\tif (map->state == DLB_QUEUE_UNMAP_IN_PROGRESS_PENDING_MAP &&\n+\t\t    map->pending_qid == queue->id)\n+\t\t\tbreak;\n+\t}\n+\n+\t*slot = i;\n+\n+\treturn (i < DLB_MAX_NUM_QIDS_PER_LDB_CQ);\n+}\n+\n+static int dlb_verify_unmap_qid_args(struct dlb_hw *hw,\n+\t\t\t\t     u32 domain_id,\n+\t\t\t\t     struct dlb_unmap_qid_args *args,\n+\t\t\t\t     struct dlb_cmd_response *resp)\n+{\n+\tenum dlb_qid_map_state state;\n+\tstruct dlb_domain *domain;\n+\tstruct dlb_ldb_port *port;\n+\tstruct dlb_ldb_queue *queue;\n+\tint slot;\n+\tint id;\n+\n+\tdomain = dlb_get_domain_from_id(hw, domain_id);\n+\n+\tif (!domain) {\n+\t\tresp->status = DLB_ST_INVALID_DOMAIN_ID;\n+\t\treturn -1;\n+\t}\n+\n+\tif (!domain->configured) {\n+\t\tresp->status = DLB_ST_DOMAIN_NOT_CONFIGURED;\n+\t\treturn -1;\n+\t}\n+\n+\tid = args->port_id;\n+\n+\tport = dlb_get_domain_used_ldb_port(id, domain);\n+\n+\tif (!port || !port->configured) {\n+\t\tresp->status = DLB_ST_INVALID_PORT_ID;\n+\t\treturn -1;\n+\t}\n+\n+\tif (port->domain_id != domain->id) {\n+\t\tresp->status = DLB_ST_INVALID_PORT_ID;\n+\t\treturn -1;\n+\t}\n+\n+\tqueue = dlb_get_domain_ldb_queue(args->qid, domain);\n+\n+\tif (!queue || !queue->configured) {\n+\t\tDLB_HW_ERR(hw, \"[%s()] Can't unmap unconfigured queue %d\\n\",\n+\t\t\t   __func__, args->qid);\n+\t\tresp->status = DLB_ST_INVALID_QID;\n+\t\treturn -1;\n+\t}\n+\n+\t/* Verify that the port has the queue mapped. From the application's\n+\t * perspective a queue is mapped if it is actually mapped, the map is\n+\t * in progress, or the map is blocked pending an unmap.\n+\t */\n+\tstate = DLB_QUEUE_MAPPED;\n+\tif (dlb_port_find_slot_queue(port, state, queue, &slot))\n+\t\treturn 0;\n+\n+\tstate = DLB_QUEUE_MAP_IN_PROGRESS;\n+\tif (dlb_port_find_slot_queue(port, state, queue, &slot))\n+\t\treturn 0;\n+\n+\tif (dlb_port_find_slot_with_pending_map_queue(port, queue, &slot))\n+\t\treturn 0;\n+\n+\tresp->status = DLB_ST_INVALID_QID;\n+\treturn -1;\n+}\n+\n+int dlb_hw_unmap_qid(struct dlb_hw *hw,\n+\t\t     u32 domain_id,\n+\t\t     struct dlb_unmap_qid_args *args,\n+\t\t     struct dlb_cmd_response *resp)\n+{\n+\tenum dlb_qid_map_state state;\n+\tstruct dlb_ldb_queue *queue;\n+\tstruct dlb_ldb_port *port;\n+\tstruct dlb_domain *domain;\n+\tbool unmap_complete;\n+\tint i, ret, id;\n+\n+\tdlb_log_unmap_qid(hw, domain_id, args);\n+\n+\t/* Verify that hardware resources are available before attempting to\n+\t * satisfy the request. This simplifies the error unwinding code.\n+\t */\n+\tif (dlb_verify_unmap_qid_args(hw, domain_id, args, resp))\n+\t\treturn -EINVAL;\n+\n+\tdomain = dlb_get_domain_from_id(hw, domain_id);\n+\tif (!domain) {\n+\t\tDLB_HW_ERR(hw,\n+\t\t\t   \"[%s():%d] Internal error: domain not found\\n\",\n+\t\t\t   __func__, __LINE__);\n+\t\treturn -EFAULT;\n+\t}\n+\n+\tid = args->port_id;\n+\n+\tport = dlb_get_domain_used_ldb_port(id, domain);\n+\tif (!port) {\n+\t\tDLB_HW_ERR(hw,\n+\t\t\t   \"[%s():%d] Internal error: port not found\\n\",\n+\t\t\t   __func__, __LINE__);\n+\t\treturn -EFAULT;\n+\t}\n+\n+\tqueue = dlb_get_domain_ldb_queue(args->qid, domain);\n+\tif (!queue) {\n+\t\tDLB_HW_ERR(hw,\n+\t\t\t   \"[%s():%d] Internal error: queue not found\\n\",\n+\t\t\t   __func__, __LINE__);\n+\t\treturn -EFAULT;\n+\t}\n+\n+\t/* If the queue hasn't been mapped yet, we need to update the slot's\n+\t * state and re-enable the queue's inflights.\n+\t */\n+\tstate = DLB_QUEUE_MAP_IN_PROGRESS;\n+\tif (dlb_port_find_slot_queue(port, state, queue, &i)) {\n+\t\tif (i >= DLB_MAX_NUM_QIDS_PER_LDB_CQ) {\n+\t\t\tDLB_HW_ERR(hw,\n+\t\t\t\t   \"[%s():%d] Internal error: port slot tracking failed\\n\",\n+\t\t\t\t   __func__, __LINE__);\n+\t\t\treturn -EFAULT;\n+\t\t}\n+\n+\t\t/* Since the in-progress map was aborted, re-enable the QID's\n+\t\t * inflights.\n+\t\t */\n+\t\tif (queue->num_pending_additions == 0)\n+\t\t\tdlb_ldb_queue_set_inflight_limit(hw, queue);\n+\n+\t\tstate = DLB_QUEUE_UNMAPPED;\n+\t\tret = dlb_port_slot_state_transition(hw, port, queue, i, state);\n+\t\tif (ret)\n+\t\t\treturn ret;\n+\n+\t\tgoto unmap_qid_done;\n+\t}\n+\n+\t/* If the queue mapping is on hold pending an unmap, we simply need to\n+\t * update the slot's state.\n+\t */\n+\tif (dlb_port_find_slot_with_pending_map_queue(port, queue, &i)) {\n+\t\tif (i >= DLB_MAX_NUM_QIDS_PER_LDB_CQ) {\n+\t\t\tDLB_HW_ERR(hw,\n+\t\t\t\t   \"[%s():%d] Internal error: port slot tracking failed\\n\",\n+\t\t\t\t   __func__, __LINE__);\n+\t\t\treturn -EFAULT;\n+\t\t}\n+\n+\t\tstate = DLB_QUEUE_UNMAP_IN_PROGRESS;\n+\t\tret = dlb_port_slot_state_transition(hw, port, queue, i, state);\n+\t\tif (ret)\n+\t\t\treturn ret;\n+\n+\t\tgoto unmap_qid_done;\n+\t}\n+\n+\tstate = DLB_QUEUE_MAPPED;\n+\tif (!dlb_port_find_slot_queue(port, state, queue, &i)) {\n+\t\tDLB_HW_ERR(hw,\n+\t\t\t   \"[%s():%d] Internal error: no available CQ slots\\n\",\n+\t\t\t   __func__, __LINE__);\n+\t\treturn -EFAULT;\n+\t}\n+\n+\tif (i >= DLB_MAX_NUM_QIDS_PER_LDB_CQ) {\n+\t\tDLB_HW_ERR(hw,\n+\t\t\t   \"[%s():%d] Internal error: port slot tracking failed\\n\",\n+\t\t\t   __func__, __LINE__);\n+\t\treturn -EFAULT;\n+\t}\n+\n+\t/* QID->CQ mapping removal is an asynchronous procedure. It requires\n+\t * stopping the DLB from scheduling this CQ, draining all inflights\n+\t * from the CQ, then unmapping the queue from the CQ. This function\n+\t * simply marks the port as needing the queue unmapped, and (if\n+\t * necessary) starts the unmapping worker thread.\n+\t */\n+\tdlb_ldb_port_cq_disable(hw, port);\n+\n+\tstate = DLB_QUEUE_UNMAP_IN_PROGRESS;\n+\tret = dlb_port_slot_state_transition(hw, port, queue, i, state);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\t/* Attempt to finish the unmapping now, in case the port has no\n+\t * outstanding inflights. If that's not the case, this will fail and\n+\t * the unmapping will be completed at a later time.\n+\t */\n+\tunmap_complete = dlb_domain_finish_unmap_port(hw, domain, port);\n+\n+\t/* If the unmapping couldn't complete immediately, launch the worker\n+\t * thread (if it isn't already launched) to finish it later.\n+\t */\n+\tif (!unmap_complete && !os_worker_active(hw))\n+\t\tos_schedule_work(hw);\n+\n+unmap_qid_done:\n+\tresp->status = 0;\n+\n+\treturn 0;\n+}\n+\n+static void dlb_log_map_qid(struct dlb_hw *hw,\n+\t\t\t    u32 domain_id,\n+\t\t\t    struct dlb_map_qid_args *args)\n+{\n+\tDLB_HW_INFO(hw, \"DLB map QID arguments:\\n\");\n+\tDLB_HW_INFO(hw, \"\\tDomain ID: %d\\n\", domain_id);\n+\tDLB_HW_INFO(hw, \"\\tPort ID:   %d\\n\", args->port_id);\n+\tDLB_HW_INFO(hw, \"\\tQueue ID:  %d\\n\", args->qid);\n+\tDLB_HW_INFO(hw, \"\\tPriority:  %d\\n\", args->priority);\n+}\n+\n+static int dlb_verify_map_qid_args(struct dlb_hw *hw,\n+\t\t\t\t   u32 domain_id,\n+\t\t\t\t   struct dlb_map_qid_args *args,\n+\t\t\t\t   struct dlb_cmd_response *resp)\n+{\n+\tstruct dlb_domain *domain;\n+\tstruct dlb_ldb_port *port;\n+\tstruct dlb_ldb_queue *queue;\n+\tint id;\n+\n+\tdomain = dlb_get_domain_from_id(hw, domain_id);\n+\n+\tif (!domain) {\n+\t\tresp->status = DLB_ST_INVALID_DOMAIN_ID;\n+\t\treturn -1;\n+\t}\n+\n+\tif (!domain->configured) {\n+\t\tresp->status = DLB_ST_DOMAIN_NOT_CONFIGURED;\n+\t\treturn -1;\n+\t}\n+\n+\tid = args->port_id;\n+\n+\tport = dlb_get_domain_used_ldb_port(id, domain);\n+\n+\tif (!port || !port->configured) {\n+\t\tresp->status = DLB_ST_INVALID_PORT_ID;\n+\t\treturn -1;\n+\t}\n+\n+\tif (args->priority >= DLB_QID_PRIORITIES) {\n+\t\tresp->status = DLB_ST_INVALID_PRIORITY;\n+\t\treturn -1;\n+\t}\n+\n+\tqueue = dlb_get_domain_ldb_queue(args->qid, domain);\n+\n+\tif (!queue || !queue->configured) {\n+\t\tresp->status = DLB_ST_INVALID_QID;\n+\t\treturn -1;\n+\t}\n+\n+\tif (queue->domain_id != domain->id) {\n+\t\tresp->status = DLB_ST_INVALID_QID;\n+\t\treturn -1;\n+\t}\n+\n+\tif (port->domain_id != domain->id) {\n+\t\tresp->status = DLB_ST_INVALID_PORT_ID;\n+\t\treturn -1;\n+\t}\n+\n+\treturn 0;\n+}\n+\n+static int dlb_verify_map_qid_slot_available(struct dlb_ldb_port *port,\n+\t\t\t\t\t     struct dlb_ldb_queue *queue,\n+\t\t\t\t\t     struct dlb_cmd_response *resp)\n+{\n+\tenum dlb_qid_map_state state;\n+\tint i;\n+\n+\t/* Unused slot available? */\n+\tif (port->num_mappings < DLB_MAX_NUM_QIDS_PER_LDB_CQ)\n+\t\treturn 0;\n+\n+\t/* If the queue is already mapped (from the application's perspective),\n+\t * this is simply a priority update.\n+\t */\n+\tstate = DLB_QUEUE_MAPPED;\n+\tif (dlb_port_find_slot_queue(port, state, queue, &i))\n+\t\treturn 0;\n+\n+\tstate = DLB_QUEUE_MAP_IN_PROGRESS;\n+\tif (dlb_port_find_slot_queue(port, state, queue, &i))\n+\t\treturn 0;\n+\n+\tif (dlb_port_find_slot_with_pending_map_queue(port, queue, &i))\n+\t\treturn 0;\n+\n+\t/* If the slot contains an unmap in progress, it's considered\n+\t * available.\n+\t */\n+\tstate = DLB_QUEUE_UNMAP_IN_PROGRESS;\n+\tif (dlb_port_find_slot(port, state, &i))\n+\t\treturn 0;\n+\n+\tstate = DLB_QUEUE_UNMAPPED;\n+\tif (dlb_port_find_slot(port, state, &i))\n+\t\treturn 0;\n+\n+\tresp->status = DLB_ST_NO_QID_SLOTS_AVAILABLE;\n+\treturn -EINVAL;\n+}\n+\n+static void dlb_ldb_port_change_qid_priority(struct dlb_hw *hw,\n+\t\t\t\t\t     struct dlb_ldb_port *port,\n+\t\t\t\t\t     int slot,\n+\t\t\t\t\t     struct dlb_map_qid_args *args)\n+{\n+\tunion dlb_lsp_cq2priov r0;\n+\n+\t/* Read-modify-write the priority and valid bit register */\n+\tr0.val = DLB_CSR_RD(hw, DLB_LSP_CQ2PRIOV(port->id));\n+\n+\tr0.field.v |= 1 << slot;\n+\tr0.field.prio |= (args->priority & 0x7) << slot * 3;\n+\n+\tDLB_CSR_WR(hw, DLB_LSP_CQ2PRIOV(port->id), r0.val);\n+\n+\tdlb_flush_csr(hw);\n+\n+\tport->qid_map[slot].priority = args->priority;\n+}\n+\n+int dlb_hw_map_qid(struct dlb_hw *hw,\n+\t\t   u32 domain_id,\n+\t\t   struct dlb_map_qid_args *args,\n+\t\t   struct dlb_cmd_response *resp)\n+{\n+\tenum dlb_qid_map_state state;\n+\tstruct dlb_ldb_queue *queue;\n+\tstruct dlb_ldb_port *port;\n+\tstruct dlb_domain *domain;\n+\tint ret, i, id;\n+\tu8 prio;\n+\n+\tdlb_log_map_qid(hw, domain_id, args);\n+\n+\t/* Verify that hardware resources are available before attempting to\n+\t * satisfy the request. This simplifies the error unwinding code.\n+\t */\n+\tif (dlb_verify_map_qid_args(hw, domain_id, args, resp))\n+\t\treturn -EINVAL;\n+\n+\tprio = args->priority;\n+\n+\tdomain = dlb_get_domain_from_id(hw, domain_id);\n+\tif (!domain) {\n+\t\tDLB_HW_ERR(hw,\n+\t\t\t   \"[%s():%d] Internal error: domain not found\\n\",\n+\t\t\t   __func__, __LINE__);\n+\t\treturn -EFAULT;\n+\t}\n+\n+\tid = args->port_id;\n+\n+\tport = dlb_get_domain_used_ldb_port(id, domain);\n+\tif (!port) {\n+\t\tDLB_HW_ERR(hw,\n+\t\t\t   \"[%s():%d] Internal error: port not found\\n\",\n+\t\t\t   __func__, __LINE__);\n+\t\treturn -EFAULT;\n+\t}\n+\n+\tqueue = dlb_get_domain_ldb_queue(args->qid, domain);\n+\tif (!queue) {\n+\t\tDLB_HW_ERR(hw,\n+\t\t\t   \"[%s():%d] Internal error: queue not found\\n\",\n+\t\t\t   __func__, __LINE__);\n+\t\treturn -EFAULT;\n+\t}\n+\n+\t/* If there are any outstanding detach operations for this port,\n+\t * attempt to complete them. This may be necessary to free up a QID\n+\t * slot for this requested mapping.\n+\t */\n+\tif (port->num_pending_removals)\n+\t\tdlb_domain_finish_unmap_port(hw, domain, port);\n+\n+\tret = dlb_verify_map_qid_slot_available(port, queue, resp);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\t/* Hardware requires disabling the CQ before mapping QIDs. */\n+\tif (port->enabled)\n+\t\tdlb_ldb_port_cq_disable(hw, port);\n+\n+\t/* If this is only a priority change, don't perform the full QID->CQ\n+\t * mapping procedure\n+\t */\n+\tstate = DLB_QUEUE_MAPPED;\n+\tif (dlb_port_find_slot_queue(port, state, queue, &i)) {\n+\t\tif (i >= DLB_MAX_NUM_QIDS_PER_LDB_CQ) {\n+\t\t\tDLB_HW_ERR(hw,\n+\t\t\t\t   \"[%s():%d] Internal error: port slot tracking failed\\n\",\n+\t\t\t\t   __func__, __LINE__);\n+\t\t\treturn -EFAULT;\n+\t\t}\n+\n+\t\tif (prio != port->qid_map[i].priority) {\n+\t\t\tdlb_ldb_port_change_qid_priority(hw, port, i, args);\n+\t\t\tDLB_HW_INFO(hw, \"DLB map: priority change only\\n\");\n+\t\t}\n+\n+\t\tstate = DLB_QUEUE_MAPPED;\n+\t\tret = dlb_port_slot_state_transition(hw, port, queue, i, state);\n+\t\tif (ret)\n+\t\t\treturn ret;\n+\n+\t\tgoto map_qid_done;\n+\t}\n+\n+\tstate = DLB_QUEUE_UNMAP_IN_PROGRESS;\n+\tif (dlb_port_find_slot_queue(port, state, queue, &i)) {\n+\t\tif (i >= DLB_MAX_NUM_QIDS_PER_LDB_CQ) {\n+\t\t\tDLB_HW_ERR(hw,\n+\t\t\t\t   \"[%s():%d] Internal error: port slot tracking failed\\n\",\n+\t\t\t\t   __func__, __LINE__);\n+\t\t\treturn -EFAULT;\n+\t\t}\n+\n+\t\tif (prio != port->qid_map[i].priority) {\n+\t\t\tdlb_ldb_port_change_qid_priority(hw, port, i, args);\n+\t\t\tDLB_HW_INFO(hw, \"DLB map: priority change only\\n\");\n+\t\t}\n+\n+\t\tstate = DLB_QUEUE_MAPPED;\n+\t\tret = dlb_port_slot_state_transition(hw, port, queue, i, state);\n+\t\tif (ret)\n+\t\t\treturn ret;\n+\n+\t\tgoto map_qid_done;\n+\t}\n+\n+\t/* If this is a priority change on an in-progress mapping, don't\n+\t * perform the full QID->CQ mapping procedure.\n+\t */\n+\tstate = DLB_QUEUE_MAP_IN_PROGRESS;\n+\tif (dlb_port_find_slot_queue(port, state, queue, &i)) {\n+\t\tif (i >= DLB_MAX_NUM_QIDS_PER_LDB_CQ) {\n+\t\t\tDLB_HW_ERR(hw,\n+\t\t\t\t   \"[%s():%d] Internal error: port slot tracking failed\\n\",\n+\t\t\t\t   __func__, __LINE__);\n+\t\t\treturn -EFAULT;\n+\t\t}\n+\n+\t\tport->qid_map[i].priority = prio;\n+\n+\t\tDLB_HW_INFO(hw, \"DLB map: priority change only\\n\");\n+\n+\t\tgoto map_qid_done;\n+\t}\n+\n+\t/* If this is a priority change on a pending mapping, update the\n+\t * pending priority\n+\t */\n+\tif (dlb_port_find_slot_with_pending_map_queue(port, queue, &i)) {\n+\t\tif (i >= DLB_MAX_NUM_QIDS_PER_LDB_CQ) {\n+\t\t\tDLB_HW_ERR(hw,\n+\t\t\t\t   \"[%s():%d] Internal error: port slot tracking failed\\n\",\n+\t\t\t\t   __func__, __LINE__);\n+\t\t\treturn -EFAULT;\n+\t\t}\n+\n+\t\tport->qid_map[i].pending_priority = prio;\n+\n+\t\tDLB_HW_INFO(hw, \"DLB map: priority change only\\n\");\n+\n+\t\tgoto map_qid_done;\n+\t}\n+\n+\t/* If all the CQ's slots are in use, then there's an unmap in progress\n+\t * (guaranteed by dlb_verify_map_qid_slot_available()), so add this\n+\t * mapping to pending_map and return. When the removal is completed for\n+\t * the slot's current occupant, this mapping will be performed.\n+\t */\n+\tif (!dlb_port_find_slot(port, DLB_QUEUE_UNMAPPED, &i)) {\n+\t\tif (dlb_port_find_slot(port, DLB_QUEUE_UNMAP_IN_PROGRESS, &i)) {\n+\t\t\tenum dlb_qid_map_state state;\n+\n+\t\t\tif (i >= DLB_MAX_NUM_QIDS_PER_LDB_CQ) {\n+\t\t\t\tDLB_HW_ERR(hw,\n+\t\t\t\t\t   \"[%s():%d] Internal error: port slot tracking failed\\n\",\n+\t\t\t\t\t   __func__, __LINE__);\n+\t\t\t\treturn -EFAULT;\n+\t\t\t}\n+\n+\t\t\tport->qid_map[i].pending_qid = queue->id;\n+\t\t\tport->qid_map[i].pending_priority = prio;\n+\n+\t\t\tstate = DLB_QUEUE_UNMAP_IN_PROGRESS_PENDING_MAP;\n+\n+\t\t\tret = dlb_port_slot_state_transition(hw, port, queue,\n+\t\t\t\t\t\t\t     i, state);\n+\t\t\tif (ret)\n+\t\t\t\treturn ret;\n+\n+\t\t\tDLB_HW_INFO(hw, \"DLB map: map pending removal\\n\");\n+\n+\t\t\tgoto map_qid_done;\n+\t\t}\n+\t}\n+\n+\t/* If the domain has started, a special \"dynamic\" CQ->queue mapping\n+\t * procedure is required in order to safely update the CQ<->QID tables.\n+\t * The \"static\" procedure cannot be used when traffic is flowing,\n+\t * because the CQ<->QID tables cannot be updated atomically and the\n+\t * scheduler won't see the new mapping unless the queue's if_status\n+\t * changes, which isn't guaranteed.\n+\t */\n+\tret = dlb_ldb_port_map_qid(hw, domain, port, queue, prio);\n+\n+\t/* If ret is less than zero, it's due to an internal error */\n+\tif (ret < 0)\n+\t\treturn ret;\n+\n+map_qid_done:\n+\tif (port->enabled)\n+\t\tdlb_ldb_port_cq_enable(hw, port);\n+\n+\tresp->status = 0;\n+\n+\treturn 0;\n+}\n+\ndiff --git a/drivers/event/dlb/pf/dlb_pf.c b/drivers/event/dlb/pf/dlb_pf.c\nindex cd766d3..a6a5adb 100644\n--- a/drivers/event/dlb/pf/dlb_pf.c\n+++ b/drivers/event/dlb/pf/dlb_pf.c\n@@ -476,6 +476,72 @@ dlb_pf_get_sn_occupancy(struct dlb_hw_dev *handle,\n \treturn ret;\n }\n \n+static int\n+dlb_pf_pending_port_unmaps(struct dlb_hw_dev *handle,\n+\t\t\t   struct dlb_pending_port_unmaps_args *args)\n+{\n+\tstruct dlb_dev *dlb_dev = (struct dlb_dev *)handle->pf_dev;\n+\tstruct dlb_cmd_response response = {0};\n+\tint ret;\n+\n+\tDLB_INFO(dev->dlb_device, \"Entering %s()\\n\", __func__);\n+\n+\tret = dlb_hw_pending_port_unmaps(&dlb_dev->hw,\n+\t\t\t\t\t handle->domain_id,\n+\t\t\t\t\t args,\n+\t\t\t\t\t &response);\n+\n+\t*(struct dlb_cmd_response *)args->response = response;\n+\n+\tDLB_INFO(dev->dlb_device, \"Exiting %s() with ret=%d\\n\", __func__, ret);\n+\n+\treturn ret;\n+}\n+\n+static int\n+dlb_pf_map_qid(struct dlb_hw_dev *handle,\n+\t       struct dlb_map_qid_args *cfg)\n+{\n+\tstruct dlb_dev *dlb_dev = (struct dlb_dev *)handle->pf_dev;\n+\tstruct dlb_cmd_response response = {0};\n+\tint ret;\n+\n+\tDLB_INFO(dev->dlb_device, \"Entering %s()\\n\", __func__);\n+\n+\tret = dlb_hw_map_qid(&dlb_dev->hw,\n+\t\t\t     handle->domain_id,\n+\t\t\t     cfg,\n+\t\t\t     &response);\n+\n+\t*(struct dlb_cmd_response *)cfg->response = response;\n+\n+\tDLB_INFO(dev->dlb_device, \"Exiting %s() with ret=%d\\n\", __func__, ret);\n+\n+\treturn ret;\n+}\n+\n+static int\n+dlb_pf_unmap_qid(struct dlb_hw_dev *handle,\n+\t\t struct dlb_unmap_qid_args *cfg)\n+{\n+\tstruct dlb_dev *dlb_dev = (struct dlb_dev *)handle->pf_dev;\n+\tstruct dlb_cmd_response response = {0};\n+\tint ret;\n+\n+\tDLB_INFO(dev->dlb_device, \"Entering %s()\\n\", __func__);\n+\n+\tret = dlb_hw_unmap_qid(&dlb_dev->hw,\n+\t\t\t       handle->domain_id,\n+\t\t\t       cfg,\n+\t\t\t       &response);\n+\n+\t*(struct dlb_cmd_response *)cfg->response = response;\n+\n+\tDLB_INFO(dev->dlb_device, \"Exiting %s() with ret=%d\\n\", __func__, ret);\n+\n+\treturn ret;\n+}\n+\n static void\n dlb_pf_iface_fn_ptrs_init(void)\n {\n@@ -491,6 +557,9 @@ dlb_pf_iface_fn_ptrs_init(void)\n \tdlb_iface_dir_queue_create = dlb_pf_dir_queue_create;\n \tdlb_iface_ldb_port_create = dlb_pf_ldb_port_create;\n \tdlb_iface_dir_port_create = dlb_pf_dir_port_create;\n+\tdlb_iface_map_qid = dlb_pf_map_qid;\n+\tdlb_iface_unmap_qid = dlb_pf_unmap_qid;\n+\tdlb_iface_pending_port_unmaps = dlb_pf_pending_port_unmaps;\n \tdlb_iface_get_cq_poll_mode = dlb_pf_get_cq_poll_mode;\n \tdlb_iface_get_sn_allocation = dlb_pf_get_sn_allocation;\n \tdlb_iface_set_sn_allocation = dlb_pf_set_sn_allocation;\n",
    "prefixes": [
        "v4",
        "12/22"
    ]
}