get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 91496,
    "url": "https://patches.dpdk.org/api/patches/91496/?format=api",
    "web_url": "https://patches.dpdk.org/project/dpdk/patch/1618451359-20693-13-git-send-email-timothy.mcdaniel@intel.com/",
    "project": {
        "id": 1,
        "url": "https://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": "<1618451359-20693-13-git-send-email-timothy.mcdaniel@intel.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/1618451359-20693-13-git-send-email-timothy.mcdaniel@intel.com",
    "date": "2021-04-15T01:49:04",
    "name": "[v4,12/27] event/dlb2: add v2.5 map qid",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": true,
    "hash": "528bc926fec1d333256febb8360c96c3a5710fef",
    "submitter": {
        "id": 826,
        "url": "https://patches.dpdk.org/api/people/826/?format=api",
        "name": "Timothy McDaniel",
        "email": "timothy.mcdaniel@intel.com"
    },
    "delegate": {
        "id": 310,
        "url": "https://patches.dpdk.org/api/users/310/?format=api",
        "username": "jerin",
        "first_name": "Jerin",
        "last_name": "Jacob",
        "email": "jerinj@marvell.com"
    },
    "mbox": "https://patches.dpdk.org/project/dpdk/patch/1618451359-20693-13-git-send-email-timothy.mcdaniel@intel.com/mbox/",
    "series": [
        {
            "id": 16383,
            "url": "https://patches.dpdk.org/api/series/16383/?format=api",
            "web_url": "https://patches.dpdk.org/project/dpdk/list/?series=16383",
            "date": "2021-04-15T01:48:52",
            "name": "Add DLB v2.5",
            "version": 4,
            "mbox": "https://patches.dpdk.org/series/16383/mbox/"
        }
    ],
    "comments": "https://patches.dpdk.org/api/patches/91496/comments/",
    "check": "success",
    "checks": "https://patches.dpdk.org/api/patches/91496/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 mails.dpdk.org (mails.dpdk.org [217.70.189.124])\n\tby inbox.dpdk.org (Postfix) with ESMTP id 77B1BA0562;\n\tThu, 15 Apr 2021 03:52:08 +0200 (CEST)",
            "from [217.70.189.124] (localhost [127.0.0.1])\n\tby mails.dpdk.org (Postfix) with ESMTP id 99AD5161E59;\n\tThu, 15 Apr 2021 03:50:49 +0200 (CEST)",
            "from mga01.intel.com (mga01.intel.com [192.55.52.88])\n by mails.dpdk.org (Postfix) with ESMTP id 73258161E1E\n for <dev@dpdk.org>; Thu, 15 Apr 2021 03:50:38 +0200 (CEST)",
            "from orsmga003.jf.intel.com ([10.7.209.27])\n by fmsmga101.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384;\n 14 Apr 2021 18:50:37 -0700",
            "from txasoft-yocto.an.intel.com ([10.123.72.192])\n by orsmga003.jf.intel.com with ESMTP; 14 Apr 2021 18:50:37 -0700"
        ],
        "IronPort-SDR": [
            "\n hesmVimtt7gn4U+C0oltSXEoYU3JH8r+OR4+B0AWs05RlXuY+PFbOqpOxj6MVTPYNtGXqq4EDa\n g23RUf+uLCiw==",
            "\n UUyQCnOTc63yozUusJD3g+/qJ8vhawILRKUs5n5bITfjsNDcCAtLG1xyGNc2TtP45Y+4CexGna\n SPE4p+iQeyNg=="
        ],
        "X-IronPort-AV": [
            "E=McAfee;i=\"6200,9189,9954\"; a=\"215272807\"",
            "E=Sophos;i=\"5.82,223,1613462400\"; d=\"scan'208\";a=\"215272807\"",
            "E=Sophos;i=\"5.82,223,1613462400\"; d=\"scan'208\";a=\"382569856\""
        ],
        "X-ExtLoop1": "1",
        "From": "Timothy McDaniel <timothy.mcdaniel@intel.com>",
        "To": "",
        "Cc": "dev@dpdk.org, erik.g.carrillo@intel.com, harry.van.haaren@intel.com,\n jerinj@marvell.com, thomas@monjalon.net",
        "Date": "Wed, 14 Apr 2021 20:49:04 -0500",
        "Message-Id": "<1618451359-20693-13-git-send-email-timothy.mcdaniel@intel.com>",
        "X-Mailer": "git-send-email 1.7.10",
        "In-Reply-To": "<1618451359-20693-1-git-send-email-timothy.mcdaniel@intel.com>",
        "References": "<20210316221857.2254-2-timothy.mcdaniel@intel.com>\n <1618451359-20693-1-git-send-email-timothy.mcdaniel@intel.com>",
        "Subject": "[dpdk-dev] [PATCH v4 12/27] event/dlb2: add v2.5 map qid",
        "X-BeenThere": "dev@dpdk.org",
        "X-Mailman-Version": "2.1.29",
        "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": "Update the low level HW functions responsible for\nmapping queues to ports. These functions also validate\nthe map arguments and verify that the maximum number\nof queues linked to a load balanced port does not\nexceed the capabilities of the hardware.\n\nThe logic is very similar to what was done for v2.0,\nbut the new combined register map for v2.0 and v2.5\nuses new register names and bit names.  Additionally,\nnew register access macros are used so that the code\ncan perform the correct action, based on the hardware\nversion, v2.0 or v2.5.\n\nSigned-off-by: Timothy McDaniel <timothy.mcdaniel@intel.com>\n---\n drivers/event/dlb2/pf/base/dlb2_resource.c    | 355 ---------------\n .../event/dlb2/pf/base/dlb2_resource_new.c    | 418 ++++++++++++++++++\n 2 files changed, 418 insertions(+), 355 deletions(-)",
    "diff": "diff --git a/drivers/event/dlb2/pf/base/dlb2_resource.c b/drivers/event/dlb2/pf/base/dlb2_resource.c\nindex 362deadfe..d59df5e39 100644\n--- a/drivers/event/dlb2/pf/base/dlb2_resource.c\n+++ b/drivers/event/dlb2/pf/base/dlb2_resource.c\n@@ -1245,68 +1245,6 @@ dlb2_port_find_slot_with_pending_map_queue(struct dlb2_ldb_port *port,\n \treturn (i < DLB2_MAX_NUM_QIDS_PER_LDB_CQ);\n }\n \n-static void dlb2_ldb_port_change_qid_priority(struct dlb2_hw *hw,\n-\t\t\t\t\t      struct dlb2_ldb_port *port,\n-\t\t\t\t\t      int slot,\n-\t\t\t\t\t      struct dlb2_map_qid_args *args)\n-{\n-\tunion dlb2_lsp_cq2priov r0;\n-\n-\t/* Read-modify-write the priority and valid bit register */\n-\tr0.val = DLB2_CSR_RD(hw, DLB2_LSP_CQ2PRIOV(port->id.phys_id));\n-\n-\tr0.field.v |= 1 << slot;\n-\tr0.field.prio |= (args->priority & 0x7) << slot * 3;\n-\n-\tDLB2_CSR_WR(hw, DLB2_LSP_CQ2PRIOV(port->id.phys_id), r0.val);\n-\n-\tdlb2_flush_csr(hw);\n-\n-\tport->qid_map[slot].priority = args->priority;\n-}\n-\n-static int dlb2_verify_map_qid_slot_available(struct dlb2_ldb_port *port,\n-\t\t\t\t\t      struct dlb2_ldb_queue *queue,\n-\t\t\t\t\t      struct dlb2_cmd_response *resp)\n-{\n-\tenum dlb2_qid_map_state state;\n-\tint i;\n-\n-\t/* Unused slot available? */\n-\tif (port->num_mappings < DLB2_MAX_NUM_QIDS_PER_LDB_CQ)\n-\t\treturn 0;\n-\n-\t/*\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 = DLB2_QUEUE_MAPPED;\n-\tif (dlb2_port_find_slot_queue(port, state, queue, &i))\n-\t\treturn 0;\n-\n-\tstate = DLB2_QUEUE_MAP_IN_PROG;\n-\tif (dlb2_port_find_slot_queue(port, state, queue, &i))\n-\t\treturn 0;\n-\n-\tif (dlb2_port_find_slot_with_pending_map_queue(port, queue, &i))\n-\t\treturn 0;\n-\n-\t/*\n-\t * If the slot contains an unmap in progress, it's considered\n-\t * available.\n-\t */\n-\tstate = DLB2_QUEUE_UNMAP_IN_PROG;\n-\tif (dlb2_port_find_slot(port, state, &i))\n-\t\treturn 0;\n-\n-\tstate = DLB2_QUEUE_UNMAPPED;\n-\tif (dlb2_port_find_slot(port, state, &i))\n-\t\treturn 0;\n-\n-\tresp->status = DLB2_ST_NO_QID_SLOTS_AVAILABLE;\n-\treturn -EINVAL;\n-}\n-\n static struct dlb2_ldb_queue *\n dlb2_get_domain_ldb_queue(u32 id,\n \t\t\t  bool vdev_req,\n@@ -1355,299 +1293,6 @@ dlb2_get_domain_used_ldb_port(u32 id,\n \treturn NULL;\n }\n \n-static int dlb2_verify_map_qid_args(struct dlb2_hw *hw,\n-\t\t\t\t    u32 domain_id,\n-\t\t\t\t    struct dlb2_map_qid_args *args,\n-\t\t\t\t    struct dlb2_cmd_response *resp,\n-\t\t\t\t    bool vdev_req,\n-\t\t\t\t    unsigned int vdev_id)\n-{\n-\tstruct dlb2_hw_domain *domain;\n-\tstruct dlb2_ldb_port *port;\n-\tstruct dlb2_ldb_queue *queue;\n-\tint id;\n-\n-\tdomain = dlb2_get_domain_from_id(hw, domain_id, vdev_req, vdev_id);\n-\n-\tif (domain == NULL) {\n-\t\tresp->status = DLB2_ST_INVALID_DOMAIN_ID;\n-\t\treturn -EINVAL;\n-\t}\n-\n-\tif (!domain->configured) {\n-\t\tresp->status = DLB2_ST_DOMAIN_NOT_CONFIGURED;\n-\t\treturn -EINVAL;\n-\t}\n-\n-\tid = args->port_id;\n-\n-\tport = dlb2_get_domain_used_ldb_port(id, vdev_req, domain);\n-\n-\tif (port == NULL || !port->configured) {\n-\t\tresp->status = DLB2_ST_INVALID_PORT_ID;\n-\t\treturn -EINVAL;\n-\t}\n-\n-\tif (args->priority >= DLB2_QID_PRIORITIES) {\n-\t\tresp->status = DLB2_ST_INVALID_PRIORITY;\n-\t\treturn -EINVAL;\n-\t}\n-\n-\tqueue = dlb2_get_domain_ldb_queue(args->qid, vdev_req, domain);\n-\n-\tif (queue == NULL || !queue->configured) {\n-\t\tresp->status = DLB2_ST_INVALID_QID;\n-\t\treturn -EINVAL;\n-\t}\n-\n-\tif (queue->domain_id.phys_id != domain->id.phys_id) {\n-\t\tresp->status = DLB2_ST_INVALID_QID;\n-\t\treturn -EINVAL;\n-\t}\n-\n-\tif (port->domain_id.phys_id != domain->id.phys_id) {\n-\t\tresp->status = DLB2_ST_INVALID_PORT_ID;\n-\t\treturn -EINVAL;\n-\t}\n-\n-\treturn 0;\n-}\n-\n-static void dlb2_log_map_qid(struct dlb2_hw *hw,\n-\t\t\t     u32 domain_id,\n-\t\t\t     struct dlb2_map_qid_args *args,\n-\t\t\t     bool vdev_req,\n-\t\t\t     unsigned int vdev_id)\n-{\n-\tDLB2_HW_DBG(hw, \"DLB2 map QID arguments:\\n\");\n-\tif (vdev_req)\n-\t\tDLB2_HW_DBG(hw, \"(Request from vdev %d)\\n\", vdev_id);\n-\tDLB2_HW_DBG(hw, \"\\tDomain ID: %d\\n\",\n-\t\t    domain_id);\n-\tDLB2_HW_DBG(hw, \"\\tPort ID:   %d\\n\",\n-\t\t    args->port_id);\n-\tDLB2_HW_DBG(hw, \"\\tQueue ID:  %d\\n\",\n-\t\t    args->qid);\n-\tDLB2_HW_DBG(hw, \"\\tPriority:  %d\\n\",\n-\t\t    args->priority);\n-}\n-\n-int dlb2_hw_map_qid(struct dlb2_hw *hw,\n-\t\t    u32 domain_id,\n-\t\t    struct dlb2_map_qid_args *args,\n-\t\t    struct dlb2_cmd_response *resp,\n-\t\t    bool vdev_req,\n-\t\t    unsigned int vdev_id)\n-{\n-\tstruct dlb2_hw_domain *domain;\n-\tstruct dlb2_ldb_queue *queue;\n-\tenum dlb2_qid_map_state st;\n-\tstruct dlb2_ldb_port *port;\n-\tint ret, i, id;\n-\tu8 prio;\n-\n-\tdlb2_log_map_qid(hw, domain_id, args, vdev_req, vdev_id);\n-\n-\t/*\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-\tret = dlb2_verify_map_qid_args(hw,\n-\t\t\t\t       domain_id,\n-\t\t\t\t       args,\n-\t\t\t\t       resp,\n-\t\t\t\t       vdev_req,\n-\t\t\t\t       vdev_id);\n-\tif (ret)\n-\t\treturn ret;\n-\n-\tprio = args->priority;\n-\n-\tdomain = dlb2_get_domain_from_id(hw, domain_id, vdev_req, vdev_id);\n-\tif (domain == NULL) {\n-\t\tDLB2_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 = dlb2_get_domain_used_ldb_port(id, vdev_req, domain);\n-\tif (port == NULL) {\n-\t\tDLB2_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 = dlb2_get_domain_ldb_queue(args->qid, vdev_req, domain);\n-\tif (queue == NULL) {\n-\t\tDLB2_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/*\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\tdlb2_domain_finish_unmap_port(hw, domain, port);\n-\n-\tret = dlb2_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\tdlb2_ldb_port_cq_disable(hw, port);\n-\n-\t/*\n-\t * If this is only a priority change, don't perform the full QID->CQ\n-\t * mapping procedure\n-\t */\n-\tst = DLB2_QUEUE_MAPPED;\n-\tif (dlb2_port_find_slot_queue(port, st, queue, &i)) {\n-\t\tif (i >= DLB2_MAX_NUM_QIDS_PER_LDB_CQ) {\n-\t\t\tDLB2_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\tdlb2_ldb_port_change_qid_priority(hw, port, i, args);\n-\t\t\tDLB2_HW_DBG(hw, \"DLB2 map: priority change\\n\");\n-\t\t}\n-\n-\t\tst = DLB2_QUEUE_MAPPED;\n-\t\tret = dlb2_port_slot_state_transition(hw, port, queue, i, st);\n-\t\tif (ret)\n-\t\t\treturn ret;\n-\n-\t\tgoto map_qid_done;\n-\t}\n-\n-\tst = DLB2_QUEUE_UNMAP_IN_PROG;\n-\tif (dlb2_port_find_slot_queue(port, st, queue, &i)) {\n-\t\tif (i >= DLB2_MAX_NUM_QIDS_PER_LDB_CQ) {\n-\t\t\tDLB2_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\tdlb2_ldb_port_change_qid_priority(hw, port, i, args);\n-\t\t\tDLB2_HW_DBG(hw, \"DLB2 map: priority change\\n\");\n-\t\t}\n-\n-\t\tst = DLB2_QUEUE_MAPPED;\n-\t\tret = dlb2_port_slot_state_transition(hw, port, queue, i, st);\n-\t\tif (ret)\n-\t\t\treturn ret;\n-\n-\t\tgoto map_qid_done;\n-\t}\n-\n-\t/*\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-\tst = DLB2_QUEUE_MAP_IN_PROG;\n-\tif (dlb2_port_find_slot_queue(port, st, queue, &i)) {\n-\t\tif (i >= DLB2_MAX_NUM_QIDS_PER_LDB_CQ) {\n-\t\t\tDLB2_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\tDLB2_HW_DBG(hw, \"DLB2 map: priority change only\\n\");\n-\n-\t\tgoto map_qid_done;\n-\t}\n-\n-\t/*\n-\t * If this is a priority change on a pending mapping, update the\n-\t * pending priority\n-\t */\n-\tif (dlb2_port_find_slot_with_pending_map_queue(port, queue, &i)) {\n-\t\tif (i >= DLB2_MAX_NUM_QIDS_PER_LDB_CQ) {\n-\t\t\tDLB2_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\tDLB2_HW_DBG(hw, \"DLB2 map: priority change only\\n\");\n-\n-\t\tgoto map_qid_done;\n-\t}\n-\n-\t/*\n-\t * If all the CQ's slots are in use, then there's an unmap in progress\n-\t * (guaranteed by dlb2_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 (!dlb2_port_find_slot(port, DLB2_QUEUE_UNMAPPED, &i)) {\n-\t\tif (dlb2_port_find_slot(port, DLB2_QUEUE_UNMAP_IN_PROG, &i)) {\n-\t\t\tenum dlb2_qid_map_state st;\n-\n-\t\t\tif (i >= DLB2_MAX_NUM_QIDS_PER_LDB_CQ) {\n-\t\t\t\tDLB2_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.phys_id;\n-\t\t\tport->qid_map[i].pending_priority = prio;\n-\n-\t\t\tst = DLB2_QUEUE_UNMAP_IN_PROG_PENDING_MAP;\n-\n-\t\t\tret = dlb2_port_slot_state_transition(hw, port, queue,\n-\t\t\t\t\t\t\t      i, st);\n-\t\t\tif (ret)\n-\t\t\t\treturn ret;\n-\n-\t\t\tDLB2_HW_DBG(hw, \"DLB2 map: map pending removal\\n\");\n-\n-\t\t\tgoto map_qid_done;\n-\t\t}\n-\t}\n-\n-\t/*\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 = dlb2_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\tdlb2_ldb_port_cq_enable(hw, port);\n-\n-\tresp->status = 0;\n-\n-\treturn 0;\n-}\n-\n static void dlb2_log_unmap_qid(struct dlb2_hw *hw,\n \t\t\t       u32 domain_id,\n \t\t\t       struct dlb2_unmap_qid_args *args,\ndiff --git a/drivers/event/dlb2/pf/base/dlb2_resource_new.c b/drivers/event/dlb2/pf/base/dlb2_resource_new.c\nindex d4b401250..5277a2643 100644\n--- a/drivers/event/dlb2/pf/base/dlb2_resource_new.c\n+++ b/drivers/event/dlb2/pf/base/dlb2_resource_new.c\n@@ -5058,3 +5058,421 @@ int dlb2_hw_create_dir_queue(struct dlb2_hw *hw,\n \treturn 0;\n }\n \n+static bool\n+dlb2_port_find_slot_with_pending_map_queue(struct dlb2_ldb_port *port,\n+\t\t\t\t\t   struct dlb2_ldb_queue *queue,\n+\t\t\t\t\t   int *slot)\n+{\n+\tint i;\n+\n+\tfor (i = 0; i < DLB2_MAX_NUM_QIDS_PER_LDB_CQ; i++) {\n+\t\tstruct dlb2_ldb_port_qid_map *map = &port->qid_map[i];\n+\n+\t\tif (map->state == DLB2_QUEUE_UNMAP_IN_PROG_PENDING_MAP &&\n+\t\t    map->pending_qid == queue->id.phys_id)\n+\t\t\tbreak;\n+\t}\n+\n+\t*slot = i;\n+\n+\treturn (i < DLB2_MAX_NUM_QIDS_PER_LDB_CQ);\n+}\n+\n+static int dlb2_verify_map_qid_slot_available(struct dlb2_ldb_port *port,\n+\t\t\t\t\t      struct dlb2_ldb_queue *queue,\n+\t\t\t\t\t      struct dlb2_cmd_response *resp)\n+{\n+\tenum dlb2_qid_map_state state;\n+\tint i;\n+\n+\t/* Unused slot available? */\n+\tif (port->num_mappings < DLB2_MAX_NUM_QIDS_PER_LDB_CQ)\n+\t\treturn 0;\n+\n+\t/*\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 = DLB2_QUEUE_MAPPED;\n+\tif (dlb2_port_find_slot_queue(port, state, queue, &i))\n+\t\treturn 0;\n+\n+\tstate = DLB2_QUEUE_MAP_IN_PROG;\n+\tif (dlb2_port_find_slot_queue(port, state, queue, &i))\n+\t\treturn 0;\n+\n+\tif (dlb2_port_find_slot_with_pending_map_queue(port, queue, &i))\n+\t\treturn 0;\n+\n+\t/*\n+\t * If the slot contains an unmap in progress, it's considered\n+\t * available.\n+\t */\n+\tstate = DLB2_QUEUE_UNMAP_IN_PROG;\n+\tif (dlb2_port_find_slot(port, state, &i))\n+\t\treturn 0;\n+\n+\tstate = DLB2_QUEUE_UNMAPPED;\n+\tif (dlb2_port_find_slot(port, state, &i))\n+\t\treturn 0;\n+\n+\tresp->status = DLB2_ST_NO_QID_SLOTS_AVAILABLE;\n+\treturn -EINVAL;\n+}\n+\n+static struct dlb2_ldb_queue *\n+dlb2_get_domain_ldb_queue(u32 id,\n+\t\t\t  bool vdev_req,\n+\t\t\t  struct dlb2_hw_domain *domain)\n+{\n+\tstruct dlb2_list_entry *iter;\n+\tstruct dlb2_ldb_queue *queue;\n+\tRTE_SET_USED(iter);\n+\n+\tif (id >= DLB2_MAX_NUM_LDB_QUEUES)\n+\t\treturn NULL;\n+\n+\tDLB2_DOM_LIST_FOR(domain->used_ldb_queues, queue, iter) {\n+\t\tif ((!vdev_req && queue->id.phys_id == id) ||\n+\t\t    (vdev_req && queue->id.virt_id == id))\n+\t\t\treturn queue;\n+\t}\n+\n+\treturn NULL;\n+}\n+\n+static struct dlb2_ldb_port *\n+dlb2_get_domain_used_ldb_port(u32 id,\n+\t\t\t      bool vdev_req,\n+\t\t\t      struct dlb2_hw_domain *domain)\n+{\n+\tstruct dlb2_list_entry *iter;\n+\tstruct dlb2_ldb_port *port;\n+\tint i;\n+\tRTE_SET_USED(iter);\n+\n+\tif (id >= DLB2_MAX_NUM_LDB_PORTS)\n+\t\treturn NULL;\n+\n+\tfor (i = 0; i < DLB2_NUM_COS_DOMAINS; i++) {\n+\t\tDLB2_DOM_LIST_FOR(domain->used_ldb_ports[i], port, iter) {\n+\t\t\tif ((!vdev_req && port->id.phys_id == id) ||\n+\t\t\t    (vdev_req && port->id.virt_id == id))\n+\t\t\t\treturn port;\n+\t\t}\n+\n+\t\tDLB2_DOM_LIST_FOR(domain->avail_ldb_ports[i], port, iter) {\n+\t\t\tif ((!vdev_req && port->id.phys_id == id) ||\n+\t\t\t    (vdev_req && port->id.virt_id == id))\n+\t\t\t\treturn port;\n+\t\t}\n+\t}\n+\n+\treturn NULL;\n+}\n+\n+static void dlb2_ldb_port_change_qid_priority(struct dlb2_hw *hw,\n+\t\t\t\t\t      struct dlb2_ldb_port *port,\n+\t\t\t\t\t      int slot,\n+\t\t\t\t\t      struct dlb2_map_qid_args *args)\n+{\n+\tu32 cq2priov;\n+\n+\t/* Read-modify-write the priority and valid bit register */\n+\tcq2priov = DLB2_CSR_RD(hw,\n+\t\t\t       DLB2_LSP_CQ2PRIOV(hw->ver, port->id.phys_id));\n+\n+\tcq2priov |= (1 << (slot + DLB2_LSP_CQ2PRIOV_V_LOC)) &\n+\t\t    DLB2_LSP_CQ2PRIOV_V;\n+\tcq2priov |= ((args->priority & 0x7) << slot * 3) &\n+\t\t    DLB2_LSP_CQ2PRIOV_PRIO;\n+\n+\tDLB2_CSR_WR(hw, DLB2_LSP_CQ2PRIOV(hw->ver, port->id.phys_id), cq2priov);\n+\n+\tdlb2_flush_csr(hw);\n+\n+\tport->qid_map[slot].priority = args->priority;\n+}\n+\n+static int dlb2_verify_map_qid_args(struct dlb2_hw *hw,\n+\t\t\t\t    u32 domain_id,\n+\t\t\t\t    struct dlb2_map_qid_args *args,\n+\t\t\t\t    struct dlb2_cmd_response *resp,\n+\t\t\t\t    bool vdev_req,\n+\t\t\t\t    unsigned int vdev_id,\n+\t\t\t\t    struct dlb2_hw_domain **out_domain,\n+\t\t\t\t    struct dlb2_ldb_port **out_port,\n+\t\t\t\t    struct dlb2_ldb_queue **out_queue)\n+{\n+\tstruct dlb2_hw_domain *domain;\n+\tstruct dlb2_ldb_queue *queue;\n+\tstruct dlb2_ldb_port *port;\n+\tint id;\n+\n+\tdomain = dlb2_get_domain_from_id(hw, domain_id, vdev_req, vdev_id);\n+\n+\tif (!domain) {\n+\t\tresp->status = DLB2_ST_INVALID_DOMAIN_ID;\n+\t\treturn -EINVAL;\n+\t}\n+\n+\tif (!domain->configured) {\n+\t\tresp->status = DLB2_ST_DOMAIN_NOT_CONFIGURED;\n+\t\treturn -EINVAL;\n+\t}\n+\n+\tid = args->port_id;\n+\n+\tport = dlb2_get_domain_used_ldb_port(id, vdev_req, domain);\n+\n+\tif (!port || !port->configured) {\n+\t\tresp->status = DLB2_ST_INVALID_PORT_ID;\n+\t\treturn -EINVAL;\n+\t}\n+\n+\tif (args->priority >= DLB2_QID_PRIORITIES) {\n+\t\tresp->status = DLB2_ST_INVALID_PRIORITY;\n+\t\treturn -EINVAL;\n+\t}\n+\n+\tqueue = dlb2_get_domain_ldb_queue(args->qid, vdev_req, domain);\n+\n+\tif (!queue || !queue->configured) {\n+\t\tresp->status = DLB2_ST_INVALID_QID;\n+\t\treturn -EINVAL;\n+\t}\n+\n+\tif (queue->domain_id.phys_id != domain->id.phys_id) {\n+\t\tresp->status = DLB2_ST_INVALID_QID;\n+\t\treturn -EINVAL;\n+\t}\n+\n+\tif (port->domain_id.phys_id != domain->id.phys_id) {\n+\t\tresp->status = DLB2_ST_INVALID_PORT_ID;\n+\t\treturn -EINVAL;\n+\t}\n+\n+\t*out_domain = domain;\n+\t*out_queue = queue;\n+\t*out_port = port;\n+\n+\treturn 0;\n+}\n+\n+static void dlb2_log_map_qid(struct dlb2_hw *hw,\n+\t\t\t     u32 domain_id,\n+\t\t\t     struct dlb2_map_qid_args *args,\n+\t\t\t     bool vdev_req,\n+\t\t\t     unsigned int vdev_id)\n+{\n+\tDLB2_HW_DBG(hw, \"DLB2 map QID arguments:\\n\");\n+\tif (vdev_req)\n+\t\tDLB2_HW_DBG(hw, \"(Request from vdev %d)\\n\", vdev_id);\n+\tDLB2_HW_DBG(hw, \"\\tDomain ID: %d\\n\",\n+\t\t    domain_id);\n+\tDLB2_HW_DBG(hw, \"\\tPort ID:   %d\\n\",\n+\t\t    args->port_id);\n+\tDLB2_HW_DBG(hw, \"\\tQueue ID:  %d\\n\",\n+\t\t    args->qid);\n+\tDLB2_HW_DBG(hw, \"\\tPriority:  %d\\n\",\n+\t\t    args->priority);\n+}\n+\n+/**\n+ * dlb2_hw_map_qid() - map a load-balanced queue to a load-balanced port\n+ * @hw: dlb2_hw handle for a particular device.\n+ * @domain_id: domain ID.\n+ * @args: map QID arguments.\n+ * @resp: response structure.\n+ * @vdev_req: indicates whether this request came from a vdev.\n+ * @vdev_id: If vdev_req is true, this contains the vdev's ID.\n+ *\n+ * This function configures the DLB to schedule QEs from the specified queue\n+ * to the specified port. Each load-balanced port can be mapped to up to 8\n+ * queues; each load-balanced queue can potentially map to all the\n+ * load-balanced ports.\n+ *\n+ * A successful return does not necessarily mean the mapping was configured. If\n+ * this function is unable to immediately map the queue to the port, it will\n+ * add the requested operation to a per-port list of pending map/unmap\n+ * operations, and (if it's not already running) launch a kernel thread that\n+ * periodically attempts to process all pending operations. In a sense, this is\n+ * an asynchronous function.\n+ *\n+ * This asynchronicity creates two views of the state of hardware: the actual\n+ * hardware state and the requested state (as if every request completed\n+ * immediately). If there are any pending map/unmap operations, the requested\n+ * state will differ from the actual state. All validation is performed with\n+ * respect to the pending state; for instance, if there are 8 pending map\n+ * operations for port X, a request for a 9th will fail because a load-balanced\n+ * port can only map up to 8 queues.\n+ *\n+ * A vdev can be either an SR-IOV virtual function or a Scalable IOV virtual\n+ * device.\n+ *\n+ * Return:\n+ * Returns 0 upon success, < 0 otherwise. If an error occurs, resp->status is\n+ * assigned a detailed error code from enum dlb2_error.\n+ *\n+ * Errors:\n+ * EINVAL - A requested resource is unavailable, invalid port or queue ID, or\n+ *\t    the domain is not configured.\n+ * EFAULT - Internal error (resp->status not set).\n+ */\n+int dlb2_hw_map_qid(struct dlb2_hw *hw,\n+\t\t    u32 domain_id,\n+\t\t    struct dlb2_map_qid_args *args,\n+\t\t    struct dlb2_cmd_response *resp,\n+\t\t    bool vdev_req,\n+\t\t    unsigned int vdev_id)\n+{\n+\tstruct dlb2_hw_domain *domain;\n+\tstruct dlb2_ldb_queue *queue;\n+\tenum dlb2_qid_map_state st;\n+\tstruct dlb2_ldb_port *port;\n+\tint ret, i;\n+\tu8 prio;\n+\n+\tdlb2_log_map_qid(hw, domain_id, args, vdev_req, vdev_id);\n+\n+\t/*\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+\tret = dlb2_verify_map_qid_args(hw,\n+\t\t\t\t       domain_id,\n+\t\t\t\t       args,\n+\t\t\t\t       resp,\n+\t\t\t\t       vdev_req,\n+\t\t\t\t       vdev_id,\n+\t\t\t\t       &domain,\n+\t\t\t\t       &port,\n+\t\t\t\t       &queue);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\tprio = args->priority;\n+\n+\t/*\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\tdlb2_domain_finish_unmap_port(hw, domain, port);\n+\n+\tret = dlb2_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\tdlb2_ldb_port_cq_disable(hw, port);\n+\n+\t/*\n+\t * If this is only a priority change, don't perform the full QID->CQ\n+\t * mapping procedure\n+\t */\n+\tst = DLB2_QUEUE_MAPPED;\n+\tif (dlb2_port_find_slot_queue(port, st, queue, &i)) {\n+\t\tif (prio != port->qid_map[i].priority) {\n+\t\t\tdlb2_ldb_port_change_qid_priority(hw, port, i, args);\n+\t\t\tDLB2_HW_DBG(hw, \"DLB2 map: priority change\\n\");\n+\t\t}\n+\n+\t\tst = DLB2_QUEUE_MAPPED;\n+\t\tret = dlb2_port_slot_state_transition(hw, port, queue, i, st);\n+\t\tif (ret)\n+\t\t\treturn ret;\n+\n+\t\tgoto map_qid_done;\n+\t}\n+\n+\tst = DLB2_QUEUE_UNMAP_IN_PROG;\n+\tif (dlb2_port_find_slot_queue(port, st, queue, &i)) {\n+\t\tif (prio != port->qid_map[i].priority) {\n+\t\t\tdlb2_ldb_port_change_qid_priority(hw, port, i, args);\n+\t\t\tDLB2_HW_DBG(hw, \"DLB2 map: priority change\\n\");\n+\t\t}\n+\n+\t\tst = DLB2_QUEUE_MAPPED;\n+\t\tret = dlb2_port_slot_state_transition(hw, port, queue, i, st);\n+\t\tif (ret)\n+\t\t\treturn ret;\n+\n+\t\tgoto map_qid_done;\n+\t}\n+\n+\t/*\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+\tst = DLB2_QUEUE_MAP_IN_PROG;\n+\tif (dlb2_port_find_slot_queue(port, st, queue, &i)) {\n+\t\tport->qid_map[i].priority = prio;\n+\n+\t\tDLB2_HW_DBG(hw, \"DLB2 map: priority change only\\n\");\n+\n+\t\tgoto map_qid_done;\n+\t}\n+\n+\t/*\n+\t * If this is a priority change on a pending mapping, update the\n+\t * pending priority\n+\t */\n+\tif (dlb2_port_find_slot_with_pending_map_queue(port, queue, &i)) {\n+\t\tport->qid_map[i].pending_priority = prio;\n+\n+\t\tDLB2_HW_DBG(hw, \"DLB2 map: priority change only\\n\");\n+\n+\t\tgoto map_qid_done;\n+\t}\n+\n+\t/*\n+\t * If all the CQ's slots are in use, then there's an unmap in progress\n+\t * (guaranteed by dlb2_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 (!dlb2_port_find_slot(port, DLB2_QUEUE_UNMAPPED, &i)) {\n+\t\tif (dlb2_port_find_slot(port, DLB2_QUEUE_UNMAP_IN_PROG, &i)) {\n+\t\t\tenum dlb2_qid_map_state new_st;\n+\n+\t\t\tport->qid_map[i].pending_qid = queue->id.phys_id;\n+\t\t\tport->qid_map[i].pending_priority = prio;\n+\n+\t\t\tnew_st = DLB2_QUEUE_UNMAP_IN_PROG_PENDING_MAP;\n+\n+\t\t\tret = dlb2_port_slot_state_transition(hw, port, queue,\n+\t\t\t\t\t\t\t      i, new_st);\n+\t\t\tif (ret)\n+\t\t\t\treturn ret;\n+\n+\t\t\tDLB2_HW_DBG(hw, \"DLB2 map: map pending removal\\n\");\n+\n+\t\t\tgoto map_qid_done;\n+\t\t}\n+\t}\n+\n+\t/*\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 = dlb2_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\tdlb2_ldb_port_cq_enable(hw, port);\n+\n+\tresp->status = 0;\n+\n+\treturn 0;\n+}\n",
    "prefixes": [
        "v4",
        "12/27"
    ]
}