get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 131417,
    "url": "https://patches.dpdk.org/api/patches/131417/?format=api",
    "web_url": "https://patches.dpdk.org/project/dpdk/patch/20230914123615.1705654-5-david.marchand@redhat.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": "<20230914123615.1705654-5-david.marchand@redhat.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/20230914123615.1705654-5-david.marchand@redhat.com",
    "date": "2023-09-14T12:36:03",
    "name": "[v3,04/15] bus/pci: find PCI capability",
    "commit_ref": null,
    "pull_url": null,
    "state": "accepted",
    "archived": true,
    "hash": "79666856bbb11182c5526c561590aa88da747e3d",
    "submitter": {
        "id": 1173,
        "url": "https://patches.dpdk.org/api/people/1173/?format=api",
        "name": "David Marchand",
        "email": "david.marchand@redhat.com"
    },
    "delegate": {
        "id": 1,
        "url": "https://patches.dpdk.org/api/users/1/?format=api",
        "username": "tmonjalo",
        "first_name": "Thomas",
        "last_name": "Monjalon",
        "email": "thomas@monjalon.net"
    },
    "mbox": "https://patches.dpdk.org/project/dpdk/patch/20230914123615.1705654-5-david.marchand@redhat.com/mbox/",
    "series": [
        {
            "id": 29507,
            "url": "https://patches.dpdk.org/api/series/29507/?format=api",
            "web_url": "https://patches.dpdk.org/project/dpdk/list/?series=29507",
            "date": "2023-09-14T12:35:59",
            "name": "Cleanup PCI(e) drivers",
            "version": 3,
            "mbox": "https://patches.dpdk.org/series/29507/mbox/"
        }
    ],
    "comments": "https://patches.dpdk.org/api/patches/131417/comments/",
    "check": "warning",
    "checks": "https://patches.dpdk.org/api/patches/131417/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 0C2D542597;\n\tThu, 14 Sep 2023 14:36:56 +0200 (CEST)",
            "from mails.dpdk.org (localhost [127.0.0.1])\n\tby mails.dpdk.org (Postfix) with ESMTP id 6A49A409FA;\n\tThu, 14 Sep 2023 14:36:45 +0200 (CEST)",
            "from us-smtp-delivery-124.mimecast.com\n (us-smtp-delivery-124.mimecast.com [170.10.133.124])\n by mails.dpdk.org (Postfix) with ESMTP id 9CD984064A\n for <dev@dpdk.org>; Thu, 14 Sep 2023 14:36:43 +0200 (CEST)",
            "from mimecast-mx02.redhat.com (mimecast-mx02.redhat.com\n [66.187.233.88]) by relay.mimecast.com with ESMTP with STARTTLS\n (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id\n us-mta-572-mQ6Zc-EzPme5Wu7ZsTi8YA-1; Thu, 14 Sep 2023 08:36:37 -0400",
            "from smtp.corp.redhat.com (int-mx06.intmail.prod.int.rdu2.redhat.com\n [10.11.54.6])\n (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits))\n (No client certificate requested)\n by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 870EA81DBE9;\n Thu, 14 Sep 2023 12:36:36 +0000 (UTC)",
            "from dmarchan.redhat.com (unknown [10.45.225.25])\n by smtp.corp.redhat.com (Postfix) with ESMTP id 0D19421B2413;\n Thu, 14 Sep 2023 12:36:32 +0000 (UTC)"
        ],
        "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com;\n s=mimecast20190719; t=1694695003;\n h=from:from:reply-to:subject:subject:date:date:message-id:message-id:\n to:to:cc:cc:mime-version:mime-version:content-type:content-type:\n content-transfer-encoding:content-transfer-encoding:\n in-reply-to:in-reply-to:references:references;\n bh=jreyN14XJsZpLJJj1z2GEcOfTW9gINiVJ0ihMRDQgfQ=;\n b=E16lt8VXsscY6UA0ZiS7ZdW+wWfxhpcw8+7pfrH5+L932I1HrloWoA73t5FLiwSrTix/ob\n rtfYpgZuJreqfP1fGpoD9dNOc8/8xjSoAEBif+zDnFedwYrtNTCSGFQ6evtmYqctT0Nmvj\n y+dadImWUDDn302QO3g7HCCUKRyxnlE=",
        "X-MC-Unique": "mQ6Zc-EzPme5Wu7ZsTi8YA-1",
        "From": "David Marchand <david.marchand@redhat.com>",
        "To": "dev@dpdk.org",
        "Cc": "thomas@monjalon.net, ferruh.yigit@amd.com, chenbo.xia@intel.com,\n nipun.gupta@amd.com, bruce.richardson@intel.com,\n Anatoly Burakov <anatoly.burakov@intel.com>,\n Jay Zhou <jianjay.zhou@huawei.com>,\n Abdullah Sevincer <abdullah.sevincer@intel.com>,\n Julien Aube <julien_dpdk@jaube.fr>,\n Rahul Lakkireddy <rahul.lakkireddy@chelsio.com>,\n Junfeng Guo <junfeng.guo@intel.com>, Jeroen de Borst <jeroendb@google.com>,\n Rushil Gupta <rushilg@google.com>, Joshua Washington <joshwash@google.com>,\n Dongdong Liu <liudongdong3@huawei.com>,\n Yisen Zhuang <yisen.zhuang@huawei.com>,\n Maxime Coquelin <maxime.coquelin@redhat.com>, Gaetan Rivet <grive@u256.net>",
        "Subject": "[PATCH v3 04/15] bus/pci: find PCI capability",
        "Date": "Thu, 14 Sep 2023 14:36:03 +0200",
        "Message-ID": "<20230914123615.1705654-5-david.marchand@redhat.com>",
        "In-Reply-To": "<20230914123615.1705654-1-david.marchand@redhat.com>",
        "References": "<20230803075038.307012-1-david.marchand@redhat.com>\n <20230914123615.1705654-1-david.marchand@redhat.com>",
        "MIME-Version": "1.0",
        "X-Scanned-By": "MIMEDefang 3.1 on 10.11.54.6",
        "X-Mimecast-Spam-Score": "0",
        "X-Mimecast-Originator": "redhat.com",
        "Content-Transfer-Encoding": "8bit",
        "Content-Type": "text/plain; charset=\"US-ASCII\"; x-default=true",
        "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"
    },
    "content": "Introduce two helpers so that drivers stop reinventing the wheel when it\ncomes to finding capabilities in a device PCI configuration space.\nUse it in existing drivers.\n\nNote:\n- base/ drivers code is left untouched, only some wrappers in cxgbe\n  are touched,\n- bnx2x maintained a per device cache of capabilities, this code has been\n  reworked to only cache the capabilities used in this driver,\n\nAcked-by: Bruce Richardson <bruce.richardson@intel.com>\nSigned-off-by: David Marchand <david.marchand@redhat.com>\n---\nChanges since v2:\n- added rte_pci_find_next_capability for vendor capa used with virtio,\n\nChanges since v1:\n- updated commitlog,\n- separated VFIO changes for using standard PCI helper in a separate\n  patch,\n- marked new experimental symbols with current version,\n- reordered defines in rte_pci.h,\n\n---\n drivers/bus/pci/linux/pci_vfio.c   |  74 ++++--------------\n drivers/bus/pci/pci_common.c       |  54 +++++++++++++\n drivers/bus/pci/rte_bus_pci.h      |  53 +++++++++++++\n drivers/bus/pci/version.map        |   5 ++\n drivers/crypto/virtio/virtio_pci.c |  57 +++++---------\n drivers/event/dlb2/pf/dlb2_main.c  |  42 +---------\n drivers/net/bnx2x/bnx2x.c          |  41 +++++-----\n drivers/net/cxgbe/base/adapter.h   |  28 +------\n drivers/net/gve/gve_ethdev.c       |  46 ++---------\n drivers/net/gve/gve_ethdev.h       |   4 -\n drivers/net/hns3/hns3_ethdev_vf.c  |  79 +++----------------\n drivers/net/virtio/virtio_pci.c    | 121 ++++++-----------------------\n lib/pci/rte_pci.h                  |  12 +++\n 13 files changed, 223 insertions(+), 393 deletions(-)",
    "diff": "diff --git a/drivers/bus/pci/linux/pci_vfio.c b/drivers/bus/pci/linux/pci_vfio.c\nindex 958f8b3b52..614ed5d696 100644\n--- a/drivers/bus/pci/linux/pci_vfio.c\n+++ b/drivers/bus/pci/linux/pci_vfio.c\n@@ -110,74 +110,34 @@ static int\n pci_vfio_get_msix_bar(const struct rte_pci_device *dev,\n \tstruct pci_msix_table *msix_table)\n {\n-\tint ret;\n-\tuint32_t reg;\n-\tuint16_t flags;\n-\tuint8_t cap_id, cap_offset;\n+\toff_t cap_offset;\n \n-\t/* read PCI capability pointer from config space */\n-\tret = rte_pci_read_config(dev, &reg, sizeof(reg), PCI_CAPABILITY_LIST);\n-\tif (ret != sizeof(reg)) {\n-\t\tRTE_LOG(ERR, EAL,\n-\t\t\t\"Cannot read capability pointer from PCI config space!\\n\");\n+\tcap_offset = rte_pci_find_capability(dev, PCI_CAP_ID_MSIX);\n+\tif (cap_offset < 0)\n \t\treturn -1;\n-\t}\n \n-\t/* we need first byte */\n-\tcap_offset = reg & 0xFF;\n+\tif (cap_offset != 0) {\n+\t\tuint16_t flags;\n+\t\tuint32_t reg;\n \n-\twhile (cap_offset) {\n-\n-\t\t/* read PCI capability ID */\n-\t\tret = rte_pci_read_config(dev, &reg, sizeof(reg), cap_offset);\n-\t\tif (ret != sizeof(reg)) {\n+\t\t/* table offset resides in the next 4 bytes */\n+\t\tif (rte_pci_read_config(dev, &reg, sizeof(reg), cap_offset + 4) < 0) {\n \t\t\tRTE_LOG(ERR, EAL,\n-\t\t\t\t\"Cannot read capability ID from PCI config space!\\n\");\n+\t\t\t\t\"Cannot read MSIX table from PCI config space!\\n\");\n \t\t\treturn -1;\n \t\t}\n \n-\t\t/* we need first byte */\n-\t\tcap_id = reg & 0xFF;\n-\n-\t\t/* if we haven't reached MSI-X, check next capability */\n-\t\tif (cap_id != PCI_CAP_ID_MSIX) {\n-\t\t\tret = rte_pci_read_config(dev, &reg, sizeof(reg), cap_offset);\n-\t\t\tif (ret != sizeof(reg)) {\n-\t\t\t\tRTE_LOG(ERR, EAL,\n-\t\t\t\t\t\"Cannot read capability pointer from PCI config space!\\n\");\n-\t\t\t\treturn -1;\n-\t\t\t}\n-\n-\t\t\t/* we need second byte */\n-\t\t\tcap_offset = (reg & 0xFF00) >> 8;\n-\n-\t\t\tcontinue;\n+\t\tif (rte_pci_read_config(dev, &flags, sizeof(flags), cap_offset + 2) < 0) {\n+\t\t\tRTE_LOG(ERR, EAL,\n+\t\t\t\t\"Cannot read MSIX flags from PCI config space!\\n\");\n+\t\t\treturn -1;\n \t\t}\n-\t\t/* else, read table offset */\n-\t\telse {\n-\t\t\t/* table offset resides in the next 4 bytes */\n-\t\t\tret = rte_pci_read_config(dev, &reg, sizeof(reg), cap_offset + 4);\n-\t\t\tif (ret != sizeof(reg)) {\n-\t\t\t\tRTE_LOG(ERR, EAL,\n-\t\t\t\t\t\"Cannot read table offset from PCI config space!\\n\");\n-\t\t\t\treturn -1;\n-\t\t\t}\n-\n-\t\t\tret = rte_pci_read_config(dev, &flags, sizeof(flags), cap_offset + 2);\n-\t\t\tif (ret != sizeof(flags)) {\n-\t\t\t\tRTE_LOG(ERR, EAL,\n-\t\t\t\t\t\"Cannot read table flags from PCI config space!\\n\");\n-\t\t\t\treturn -1;\n-\t\t\t}\n-\n-\t\t\tmsix_table->bar_index = reg & RTE_PCI_MSIX_TABLE_BIR;\n-\t\t\tmsix_table->offset = reg & RTE_PCI_MSIX_TABLE_OFFSET;\n-\t\t\tmsix_table->size =\n-\t\t\t\t16 * (1 + (flags & RTE_PCI_MSIX_FLAGS_QSIZE));\n \n-\t\t\treturn 0;\n-\t\t}\n+\t\tmsix_table->bar_index = reg & RTE_PCI_MSIX_TABLE_BIR;\n+\t\tmsix_table->offset = reg & RTE_PCI_MSIX_TABLE_OFFSET;\n+\t\tmsix_table->size = 16 * (1 + (flags & RTE_PCI_MSIX_FLAGS_QSIZE));\n \t}\n+\n \treturn 0;\n }\n \ndiff --git a/drivers/bus/pci/pci_common.c b/drivers/bus/pci/pci_common.c\nindex 382b0b8946..f149963364 100644\n--- a/drivers/bus/pci/pci_common.c\n+++ b/drivers/bus/pci/pci_common.c\n@@ -813,6 +813,60 @@ rte_pci_get_iommu_class(void)\n \treturn iova_mode;\n }\n \n+bool\n+rte_pci_has_capability_list(const struct rte_pci_device *dev)\n+{\n+\tuint16_t status;\n+\n+\tif (rte_pci_read_config(dev, &status, sizeof(status), RTE_PCI_STATUS) != sizeof(status))\n+\t\treturn false;\n+\n+\treturn (status & RTE_PCI_STATUS_CAP_LIST) != 0;\n+}\n+\n+off_t\n+rte_pci_find_capability(const struct rte_pci_device *dev, uint8_t cap)\n+{\n+\treturn rte_pci_find_next_capability(dev, cap, 0);\n+}\n+\n+off_t\n+rte_pci_find_next_capability(const struct rte_pci_device *dev, uint8_t cap,\n+\toff_t offset)\n+{\n+\tuint8_t pos;\n+\tint ttl;\n+\n+\tif (offset == 0)\n+\t\toffset = RTE_PCI_CAPABILITY_LIST;\n+\telse\n+\t\toffset += RTE_PCI_CAP_NEXT;\n+\tttl = (RTE_PCI_CFG_SPACE_SIZE - RTE_PCI_STD_HEADER_SIZEOF) / RTE_PCI_CAP_SIZEOF;\n+\n+\tif (rte_pci_read_config(dev, &pos, sizeof(pos), offset) < 0)\n+\t\treturn -1;\n+\n+\twhile (pos && ttl--) {\n+\t\tuint16_t ent;\n+\t\tuint8_t id;\n+\n+\t\toffset = pos;\n+\t\tif (rte_pci_read_config(dev, &ent, sizeof(ent), offset) < 0)\n+\t\t\treturn -1;\n+\n+\t\tid = ent & 0xff;\n+\t\tif (id == 0xff)\n+\t\t\tbreak;\n+\n+\t\tif (id == cap)\n+\t\t\treturn offset;\n+\n+\t\tpos = (ent >> 8);\n+\t}\n+\n+\treturn 0;\n+}\n+\n off_t\n rte_pci_find_ext_capability(const struct rte_pci_device *dev, uint32_t cap)\n {\ndiff --git a/drivers/bus/pci/rte_bus_pci.h b/drivers/bus/pci/rte_bus_pci.h\nindex 75d0030eae..e97b7eae5c 100644\n--- a/drivers/bus/pci/rte_bus_pci.h\n+++ b/drivers/bus/pci/rte_bus_pci.h\n@@ -68,6 +68,59 @@ void rte_pci_unmap_device(struct rte_pci_device *dev);\n  */\n void rte_pci_dump(FILE *f);\n \n+/**\n+ * Check whether this device has a PCI capability list.\n+ *\n+ *  @param dev\n+ *    A pointer to rte_pci_device structure.\n+ *\n+ *  @return\n+ *    true/false\n+ */\n+__rte_experimental\n+bool rte_pci_has_capability_list(const struct rte_pci_device *dev);\n+\n+/**\n+ * Find device's PCI capability.\n+ *\n+ *  @param dev\n+ *    A pointer to rte_pci_device structure.\n+ *\n+ *  @param cap\n+ *    Capability to be found, which can be any from\n+ *    RTE_PCI_CAP_ID_*, defined in librte_pci.\n+ *\n+ *  @return\n+ *  > 0: The offset of the next matching capability structure\n+ *       within the device's PCI configuration space.\n+ *  < 0: An error in PCI config space read.\n+ *  = 0: Device does not support it.\n+ */\n+__rte_experimental\n+off_t rte_pci_find_capability(const struct rte_pci_device *dev, uint8_t cap);\n+\n+/**\n+ * Find device's PCI capability starting from a previous offset in PCI\n+ * configuration space.\n+ *\n+ *  @param dev\n+ *    A pointer to rte_pci_device structure.\n+ *\n+ *  @param cap\n+ *    Capability to be found, which can be any from\n+ *    RTE_PCI_CAP_ID_*, defined in librte_pci.\n+ *  @param offset\n+ *    offset from which the capability is looked for.\n+ *\n+ *  @return\n+ *  > 0: The offset of the next matching capability structure\n+ *       within the device's PCI configuration space.\n+ *  < 0: An error in PCI config space read.\n+ *  = 0: Device does not support it.\n+ */\n+__rte_experimental\n+off_t rte_pci_find_next_capability(const struct rte_pci_device *dev, uint8_t cap, off_t offset);\n+\n /**\n  * Find device's extended PCI capability.\n  *\ndiff --git a/drivers/bus/pci/version.map b/drivers/bus/pci/version.map\nindex a0000f7938..74c5b075d5 100644\n--- a/drivers/bus/pci/version.map\n+++ b/drivers/bus/pci/version.map\n@@ -25,6 +25,11 @@ EXPERIMENTAL {\n \t# added in 23.07\n \trte_pci_mmio_read;\n \trte_pci_mmio_write;\n+\n+\t# added in 23.11\n+\trte_pci_find_capability;\n+\trte_pci_find_next_capability;\n+\trte_pci_has_capability_list;\n };\n \n INTERNAL {\ndiff --git a/drivers/crypto/virtio/virtio_pci.c b/drivers/crypto/virtio/virtio_pci.c\nindex 95a43c8801..19afebdcad 100644\n--- a/drivers/crypto/virtio/virtio_pci.c\n+++ b/drivers/crypto/virtio/virtio_pci.c\n@@ -19,7 +19,6 @@\n  * we can't simply include that header here, as there is no such\n  * file for non-Linux platform.\n  */\n-#define PCI_CAPABILITY_LIST\t0x34\n #define PCI_CAP_ID_VNDR\t\t0x09\n #define PCI_CAP_ID_MSIX\t\t0x11\n \n@@ -343,8 +342,9 @@ get_cfg_addr(struct rte_pci_device *dev, struct virtio_pci_cap *cap)\n static int\n virtio_read_caps(struct rte_pci_device *dev, struct virtio_crypto_hw *hw)\n {\n-\tuint8_t pos;\n \tstruct virtio_pci_cap cap;\n+\tuint16_t flags;\n+\toff_t pos;\n \tint ret;\n \n \tif (rte_pci_map_device(dev)) {\n@@ -352,44 +352,28 @@ virtio_read_caps(struct rte_pci_device *dev, struct virtio_crypto_hw *hw)\n \t\treturn -1;\n \t}\n \n-\tret = rte_pci_read_config(dev, &pos, 1, PCI_CAPABILITY_LIST);\n-\tif (ret < 0) {\n-\t\tVIRTIO_CRYPTO_INIT_LOG_DBG(\"failed to read pci capability list\");\n-\t\treturn -1;\n+\t/*\n+\t * Transitional devices would also have this capability,\n+\t * that's why we also check if msix is enabled.\n+\t */\n+\tpos = rte_pci_find_capability(dev, PCI_CAP_ID_MSIX);\n+\tif (pos > 0 && rte_pci_read_config(dev, &flags, sizeof(flags),\n+\t\t\tpos + 2) == sizeof(flags)) {\n+\t\tif (flags & PCI_MSIX_ENABLE)\n+\t\t\thw->use_msix = VIRTIO_MSIX_ENABLED;\n+\t\telse\n+\t\t\thw->use_msix = VIRTIO_MSIX_DISABLED;\n+\t} else {\n+\t\thw->use_msix = VIRTIO_MSIX_NONE;\n \t}\n \n-\twhile (pos) {\n-\t\tret = rte_pci_read_config(dev, &cap, sizeof(cap), pos);\n-\t\tif (ret < 0) {\n-\t\t\tVIRTIO_CRYPTO_INIT_LOG_ERR(\n-\t\t\t\t\"failed to read pci cap at pos: %x\", pos);\n+\tpos = rte_pci_find_capability(dev, PCI_CAP_ID_VNDR);\n+\twhile (pos > 0) {\n+\t\tif (rte_pci_read_config(dev, &cap, sizeof(cap), pos) != sizeof(cap))\n \t\t\tbreak;\n-\t\t}\n-\n-\t\tif (cap.cap_vndr == PCI_CAP_ID_MSIX) {\n-\t\t\t/* Transitional devices would also have this capability,\n-\t\t\t * that's why we also check if msix is enabled.\n-\t\t\t * 1st byte is cap ID; 2nd byte is the position of next\n-\t\t\t * cap; next two bytes are the flags.\n-\t\t\t */\n-\t\t\tuint16_t flags = ((uint16_t *)&cap)[1];\n-\n-\t\t\tif (flags & PCI_MSIX_ENABLE)\n-\t\t\t\thw->use_msix = VIRTIO_MSIX_ENABLED;\n-\t\t\telse\n-\t\t\t\thw->use_msix = VIRTIO_MSIX_DISABLED;\n-\t\t}\n-\n-\t\tif (cap.cap_vndr != PCI_CAP_ID_VNDR) {\n-\t\t\tVIRTIO_CRYPTO_INIT_LOG_DBG(\n-\t\t\t\t\"[%2x] skipping non VNDR cap id: %02x\",\n-\t\t\t\tpos, cap.cap_vndr);\n-\t\t\tgoto next;\n-\t\t}\n-\n \t\tVIRTIO_CRYPTO_INIT_LOG_DBG(\n \t\t\t\"[%2x] cfg type: %u, bar: %u, offset: %04x, len: %u\",\n-\t\t\tpos, cap.cfg_type, cap.bar, cap.offset, cap.length);\n+\t\t\t(unsigned int)pos, cap.cfg_type, cap.bar, cap.offset, cap.length);\n \n \t\tswitch (cap.cfg_type) {\n \t\tcase VIRTIO_PCI_CAP_COMMON_CFG:\n@@ -412,8 +396,7 @@ virtio_read_caps(struct rte_pci_device *dev, struct virtio_crypto_hw *hw)\n \t\t\tbreak;\n \t\t}\n \n-next:\n-\t\tpos = cap.cap_next;\n+\t\tpos = rte_pci_find_next_capability(dev, PCI_CAP_ID_VNDR, pos);\n \t}\n \n \tif (hw->common_cfg == NULL || hw->notify_base == NULL ||\ndiff --git a/drivers/event/dlb2/pf/dlb2_main.c b/drivers/event/dlb2/pf/dlb2_main.c\nindex 717aa4fc08..40e5cb594f 100644\n--- a/drivers/event/dlb2/pf/dlb2_main.c\n+++ b/drivers/event/dlb2/pf/dlb2_main.c\n@@ -27,10 +27,6 @@\n #define NO_OWNER_VF 0\t/* PF ONLY! */\n #define NOT_VF_REQ false /* PF ONLY! */\n \n-#define DLB2_PCI_CAP_POINTER 0x34\n-#define DLB2_PCI_CAP_NEXT(hdr) (((hdr) >> 8) & 0xFC)\n-#define DLB2_PCI_CAP_ID(hdr) ((hdr) & 0xFF)\n-\n #define DLB2_PCI_LNKCTL 16\n #define DLB2_PCI_SLTCTL 24\n #define DLB2_PCI_RTCTL 28\n@@ -65,35 +61,6 @@\n #define DLB2_PCI_ACS_UF                  0x10\n #define DLB2_PCI_ACS_EC                  0x20\n \n-static int dlb2_pci_find_capability(struct rte_pci_device *pdev, uint32_t id)\n-{\n-\tuint8_t pos;\n-\tint ret;\n-\tuint16_t hdr;\n-\n-\tret = rte_pci_read_config(pdev, &pos, 1, DLB2_PCI_CAP_POINTER);\n-\tpos &= 0xFC;\n-\n-\tif (ret != 1)\n-\t\treturn -1;\n-\n-\twhile (pos > 0x3F) {\n-\t\tret = rte_pci_read_config(pdev, &hdr, 2, pos);\n-\t\tif (ret != 2)\n-\t\t\treturn -1;\n-\n-\t\tif (DLB2_PCI_CAP_ID(hdr) == id)\n-\t\t\treturn pos;\n-\n-\t\tif (DLB2_PCI_CAP_ID(hdr) == 0xFF)\n-\t\t\treturn -1;\n-\n-\t\tpos = DLB2_PCI_CAP_NEXT(hdr);\n-\t}\n-\n-\treturn -1;\n-}\n-\n static int\n dlb2_pf_init_driver_state(struct dlb2_dev *dlb2_dev)\n {\n@@ -258,9 +225,9 @@ dlb2_pf_reset(struct dlb2_dev *dlb2_dev)\n \tuint32_t pri_reqs_dword;\n \tuint16_t pri_ctrl_word;\n \n-\tint pcie_cap_offset;\n+\toff_t pcie_cap_offset;\n \tint pri_cap_offset;\n-\tint msix_cap_offset;\n+\toff_t msix_cap_offset;\n \tint err_cap_offset;\n \tint acs_cap_offset;\n \tint wait_count;\n@@ -277,7 +244,7 @@ dlb2_pf_reset(struct dlb2_dev *dlb2_dev)\n \t\t\treturn ret;\n \t}\n \n-\tpcie_cap_offset = dlb2_pci_find_capability(pdev, DLB2_PCI_CAP_ID_EXP);\n+\tpcie_cap_offset = rte_pci_find_capability(pdev, DLB2_PCI_CAP_ID_EXP);\n \n \tif (pcie_cap_offset < 0) {\n \t\tDLB2_LOG_ERR(\"[%s()] failed to find the pcie capability\\n\",\n@@ -516,8 +483,7 @@ dlb2_pf_reset(struct dlb2_dev *dlb2_dev)\n \t\t}\n \t}\n \n-\tmsix_cap_offset = dlb2_pci_find_capability(pdev,\n-\t\t\t\t\t\t   DLB2_PCI_CAP_ID_MSIX);\n+\tmsix_cap_offset = rte_pci_find_capability(pdev, DLB2_PCI_CAP_ID_MSIX);\n \tif (msix_cap_offset >= 0) {\n \t\toff = msix_cap_offset + DLB2_PCI_MSIX_FLAGS;\n \t\tif (rte_pci_read_config(pdev, &cmd, 2, off) == 2) {\ndiff --git a/drivers/net/bnx2x/bnx2x.c b/drivers/net/bnx2x/bnx2x.c\nindex 29c16bb207..06f2949885 100644\n--- a/drivers/net/bnx2x/bnx2x.c\n+++ b/drivers/net/bnx2x/bnx2x.c\n@@ -9586,14 +9586,17 @@ static void bnx2x_init_multi_cos(struct bnx2x_softc *sc)\n \t}\n }\n \n+static uint8_t bnx2x_pci_capabilities[] = {\n+\tPCIY_EXPRESS,\n+\tPCIY_PMG,\n+\tPCIY_MSI,\n+\tPCIY_MSIX,\n+};\n+\n static int bnx2x_pci_get_caps(struct bnx2x_softc *sc)\n {\n-\tstruct {\n-\t\tuint8_t id;\n-\t\tuint8_t next;\n-\t} pci_cap;\n-\tuint16_t status;\n \tstruct bnx2x_pci_cap *cap;\n+\tunsigned int i;\n \n \tcap = sc->pci_caps = rte_zmalloc(\"caps\", sizeof(struct bnx2x_pci_cap),\n \t\t\t\t\t RTE_CACHE_LINE_SIZE);\n@@ -9602,29 +9605,21 @@ static int bnx2x_pci_get_caps(struct bnx2x_softc *sc)\n \t\treturn -ENOMEM;\n \t}\n \n-#ifndef RTE_EXEC_ENV_FREEBSD\n-\tpci_read(sc, PCI_STATUS, &status, 2);\n-\tif (!(status & PCI_STATUS_CAP_LIST)) {\n-#else\n-\tpci_read(sc, PCIR_STATUS, &status, 2);\n-\tif (!(status & PCIM_STATUS_CAPPRESENT)) {\n-#endif\n+\tif (!rte_pci_has_capability_list(sc->pci_dev)) {\n \t\tPMD_DRV_LOG(NOTICE, sc, \"PCIe capability reading failed\");\n \t\treturn -1;\n \t}\n \n-#ifndef RTE_EXEC_ENV_FREEBSD\n-\tpci_read(sc, PCI_CAPABILITY_LIST, &pci_cap.next, 1);\n-#else\n-\tpci_read(sc, PCIR_CAP_PTR, &pci_cap.next, 1);\n-#endif\n-\twhile (pci_cap.next) {\n-\t\tcap->addr = pci_cap.next & ~3;\n-\t\tpci_read(sc, pci_cap.next & ~3, &pci_cap, 2);\n-\t\tif (pci_cap.id == 0xff)\n-\t\t\tbreak;\n-\t\tcap->id = pci_cap.id;\n+\tfor (i = 0; i < RTE_DIM(bnx2x_pci_capabilities); i++) {\n+\t\toff_t pos = rte_pci_find_capability(sc->pci_dev,\n+\t\t\tbnx2x_pci_capabilities[i]);\n+\n+\t\tif (pos <= 0)\n+\t\t\tcontinue;\n+\n+\t\tcap->id = bnx2x_pci_capabilities[i];\n \t\tcap->type = BNX2X_PCI_CAP;\n+\t\tcap->addr = pos;\n \t\tcap->next = rte_zmalloc(\"pci_cap\",\n \t\t\t\t\tsizeof(struct bnx2x_pci_cap),\n \t\t\t\t\tRTE_CACHE_LINE_SIZE);\ndiff --git a/drivers/net/cxgbe/base/adapter.h b/drivers/net/cxgbe/base/adapter.h\nindex 8f2ffa0eeb..00d7591ea4 100644\n--- a/drivers/net/cxgbe/base/adapter.h\n+++ b/drivers/net/cxgbe/base/adapter.h\n@@ -511,13 +511,8 @@ static inline void t4_write_reg64(struct adapter *adapter, u32 reg_addr,\n \tCXGBE_WRITE_REG64(adapter, reg_addr, val);\n }\n \n-#define PCI_STATUS              0x06    /* 16 bits */\n-#define PCI_STATUS_CAP_LIST     0x10    /* Support Capability List */\n-#define PCI_CAPABILITY_LIST     0x34\n /* Offset of first capability list entry */\n #define PCI_CAP_ID_EXP          0x10    /* PCI Express */\n-#define PCI_CAP_LIST_ID         0       /* Capability ID */\n-#define PCI_CAP_LIST_NEXT       1       /* Next capability in the list */\n #define PCI_EXP_DEVCTL          0x0008  /* Device control */\n #define PCI_EXP_DEVCTL2         40      /* Device Control 2 */\n #define PCI_EXP_DEVCTL_EXT_TAG  0x0100  /* Extended Tag Field Enable */\n@@ -620,31 +615,12 @@ static inline void t4_os_pci_read_cfg(struct adapter *adapter, size_t addr,\n  */\n static inline int t4_os_find_pci_capability(struct adapter *adapter, int cap)\n {\n-\tu16 status;\n-\tint ttl = 48;\n-\tu8 pos = 0;\n-\tu8 id = 0;\n-\n-\tt4_os_pci_read_cfg2(adapter, PCI_STATUS, &status);\n-\tif (!(status & PCI_STATUS_CAP_LIST)) {\n+\tif (!rte_pci_has_capability_list(adapter->pdev)) {\n \t\tdev_err(adapter, \"PCIe capability reading failed\\n\");\n \t\treturn -1;\n \t}\n \n-\tt4_os_pci_read_cfg(adapter, PCI_CAPABILITY_LIST, &pos);\n-\twhile (ttl-- && pos >= 0x40) {\n-\t\tpos &= ~3;\n-\t\tt4_os_pci_read_cfg(adapter, (pos + PCI_CAP_LIST_ID), &id);\n-\n-\t\tif (id == 0xff)\n-\t\t\tbreak;\n-\n-\t\tif (id == cap)\n-\t\t\treturn (int)pos;\n-\n-\t\tt4_os_pci_read_cfg(adapter, (pos + PCI_CAP_LIST_NEXT), &pos);\n-\t}\n-\treturn 0;\n+\treturn rte_pci_find_capability(adapter->pdev, cap);\n }\n \n /**\ndiff --git a/drivers/net/gve/gve_ethdev.c b/drivers/net/gve/gve_ethdev.c\nindex aa75abe102..c276b9e68e 100644\n--- a/drivers/net/gve/gve_ethdev.c\n+++ b/drivers/net/gve/gve_ethdev.c\n@@ -606,53 +606,17 @@ gve_teardown_device_resources(struct gve_priv *priv)\n \tgve_clear_device_resources_ok(priv);\n }\n \n-static uint8_t\n-pci_dev_find_capability(struct rte_pci_device *pdev, int cap)\n-{\n-\tuint8_t pos, id;\n-\tuint16_t ent;\n-\tint loops;\n-\tint ret;\n-\n-\tret = rte_pci_read_config(pdev, &pos, sizeof(pos), PCI_CAPABILITY_LIST);\n-\tif (ret != sizeof(pos))\n-\t\treturn 0;\n-\n-\tloops = (PCI_CFG_SPACE_SIZE - PCI_STD_HEADER_SIZEOF) / PCI_CAP_SIZEOF;\n-\n-\twhile (pos && loops--) {\n-\t\tret = rte_pci_read_config(pdev, &ent, sizeof(ent), pos);\n-\t\tif (ret != sizeof(ent))\n-\t\t\treturn 0;\n-\n-\t\tid = ent & 0xff;\n-\t\tif (id == 0xff)\n-\t\t\tbreak;\n-\n-\t\tif (id == cap)\n-\t\t\treturn pos;\n-\n-\t\tpos = (ent >> 8);\n-\t}\n-\n-\treturn 0;\n-}\n-\n static int\n pci_dev_msix_vec_count(struct rte_pci_device *pdev)\n {\n-\tuint8_t msix_cap = pci_dev_find_capability(pdev, PCI_CAP_ID_MSIX);\n+\toff_t msix_pos = rte_pci_find_capability(pdev, PCI_CAP_ID_MSIX);\n \tuint16_t control;\n-\tint ret;\n \n-\tif (!msix_cap)\n-\t\treturn 0;\n-\n-\tret = rte_pci_read_config(pdev, &control, sizeof(control), msix_cap + PCI_MSIX_FLAGS);\n-\tif (ret != sizeof(control))\n-\t\treturn 0;\n+\tif (msix_pos > 0 && rte_pci_read_config(pdev, &control, sizeof(control),\n+\t\t\tmsix_pos + PCI_MSIX_FLAGS) == sizeof(control))\n+\t\treturn (control & PCI_MSIX_FLAGS_QSIZE) + 1;\n \n-\treturn (control & PCI_MSIX_FLAGS_QSIZE) + 1;\n+\treturn 0;\n }\n \n static int\ndiff --git a/drivers/net/gve/gve_ethdev.h b/drivers/net/gve/gve_ethdev.h\nindex c9bcfa553c..8759b1c76e 100644\n--- a/drivers/net/gve/gve_ethdev.h\n+++ b/drivers/net/gve/gve_ethdev.h\n@@ -19,10 +19,6 @@\n  * we can't simply include that header here, as there is no such\n  * file for non-Linux platform.\n  */\n-#define PCI_CFG_SPACE_SIZE\t256\n-#define PCI_CAPABILITY_LIST\t0x34\t/* Offset of first capability list entry */\n-#define PCI_STD_HEADER_SIZEOF\t64\n-#define PCI_CAP_SIZEOF\t\t4\n #define PCI_CAP_ID_MSIX\t\t0x11\t/* MSI-X */\n #define PCI_MSIX_FLAGS\t\t2\t/* Message Control */\n #define PCI_MSIX_FLAGS_QSIZE\t0x07FF\t/* Table size */\ndiff --git a/drivers/net/hns3/hns3_ethdev_vf.c b/drivers/net/hns3/hns3_ethdev_vf.c\nindex 7b3c5dc168..b731850b01 100644\n--- a/drivers/net/hns3/hns3_ethdev_vf.c\n+++ b/drivers/net/hns3/hns3_ethdev_vf.c\n@@ -49,80 +49,24 @@ static int hns3vf_remove_mc_mac_addr(struct hns3_hw *hw,\n static int hns3vf_dev_link_update(struct rte_eth_dev *eth_dev,\n \t\t\t\t   __rte_unused int wait_to_complete);\n \n-/**\n- * hns3vf_find_pci_capability - lookup a capability in the PCI capability list\n- * @cap: the capability\n- *\n- * Return the address of the given capability within the PCI capability list.\n- */\n static int\n-hns3vf_find_pci_capability(const struct rte_pci_device *device, int cap)\n+hns3vf_enable_msix(const struct rte_pci_device *device, bool op)\n {\n-#define MAX_PCIE_CAPABILITY 48\n-\tuint16_t status;\n-\tuint8_t pos;\n-\tuint8_t id;\n-\tint ttl;\n+\tuint16_t control;\n+\toff_t pos;\n \tint ret;\n \n-\tret = rte_pci_read_config(device, &status, sizeof(status), PCI_STATUS);\n-\tif (ret < 0) {\n-\t\tPMD_INIT_LOG(ERR, \"Failed to read PCI offset 0x%x\", PCI_STATUS);\n-\t\treturn 0;\n-\t}\n-\n-\tif (!(status & PCI_STATUS_CAP_LIST))\n-\t\treturn 0;\n-\n-\tttl = MAX_PCIE_CAPABILITY;\n-\tret = rte_pci_read_config(device, &pos, sizeof(pos),\n-\t\t\t\t  PCI_CAPABILITY_LIST);\n-\tif (ret < 0) {\n-\t\tPMD_INIT_LOG(ERR, \"Failed to read PCI offset 0x%x\",\n-\t\t\t     PCI_CAPABILITY_LIST);\n+\tif (!rte_pci_has_capability_list(device)) {\n+\t\tPMD_INIT_LOG(ERR, \"Failed to read PCI capability list\");\n \t\treturn 0;\n \t}\n \n-\twhile (ttl-- && pos >= PCI_STD_HEADER_SIZEOF) {\n-\t\tret = rte_pci_read_config(device, &id, sizeof(id),\n-\t\t\t\t\t  (pos + PCI_CAP_LIST_ID));\n-\t\tif (ret < 0) {\n-\t\t\tPMD_INIT_LOG(ERR, \"Failed to read PCI offset 0x%x\",\n-\t\t\t\t     (pos + PCI_CAP_LIST_ID));\n-\t\t\tbreak;\n-\t\t}\n-\n-\t\tif (id == 0xFF)\n-\t\t\tbreak;\n-\n-\t\tif (id == cap)\n-\t\t\treturn (int)pos;\n-\n-\t\tret = rte_pci_read_config(device, &pos, sizeof(pos),\n-\t\t\t\t\t  (pos + PCI_CAP_LIST_NEXT));\n-\t\tif (ret < 0) {\n-\t\t\tPMD_INIT_LOG(ERR, \"Failed to read PCI offset 0x%x\",\n-\t\t\t\t     (pos + PCI_CAP_LIST_NEXT));\n-\t\t\tbreak;\n-\t\t}\n-\t}\n-\treturn 0;\n-}\n-\n-static int\n-hns3vf_enable_msix(const struct rte_pci_device *device, bool op)\n-{\n-\tuint16_t control;\n-\tint pos;\n-\tint ret;\n-\n-\tpos = hns3vf_find_pci_capability(device, PCI_CAP_ID_MSIX);\n-\tif (pos) {\n+\tpos = rte_pci_find_capability(device, PCI_CAP_ID_MSIX);\n+\tif (pos > 0) {\n \t\tret = rte_pci_read_config(device, &control, sizeof(control),\n-\t\t\t\t\t  (pos + PCI_MSIX_FLAGS));\n+\t\t\tpos + PCI_MSIX_FLAGS);\n \t\tif (ret < 0) {\n-\t\t\tPMD_INIT_LOG(ERR, \"Failed to read PCI offset 0x%x\",\n-\t\t\t\t     (pos + PCI_MSIX_FLAGS));\n+\t\t\tPMD_INIT_LOG(ERR, \"Failed to read MSIX flags\");\n \t\t\treturn -ENXIO;\n \t\t}\n \n@@ -131,10 +75,9 @@ hns3vf_enable_msix(const struct rte_pci_device *device, bool op)\n \t\telse\n \t\t\tcontrol &= ~PCI_MSIX_FLAGS_ENABLE;\n \t\tret = rte_pci_write_config(device, &control, sizeof(control),\n-\t\t\t\t\t   (pos + PCI_MSIX_FLAGS));\n+\t\t\tpos + PCI_MSIX_FLAGS);\n \t\tif (ret < 0) {\n-\t\t\tPMD_INIT_LOG(ERR, \"failed to write PCI offset 0x%x\",\n-\t\t\t\t     (pos + PCI_MSIX_FLAGS));\n+\t\t\tPMD_INIT_LOG(ERR, \"failed to write MSIX flags\");\n \t\t\treturn -ENXIO;\n \t\t}\n \ndiff --git a/drivers/net/virtio/virtio_pci.c b/drivers/net/virtio/virtio_pci.c\nindex 29eb739b04..4c2a1911d1 100644\n--- a/drivers/net/virtio/virtio_pci.c\n+++ b/drivers/net/virtio/virtio_pci.c\n@@ -20,7 +20,6 @@\n  * we can't simply include that header here, as there is no such\n  * file for non-Linux platform.\n  */\n-#define PCI_CAPABILITY_LIST\t0x34\n #define PCI_CAP_ID_VNDR\t\t0x09\n #define PCI_CAP_ID_MSIX\t\t0x11\n \n@@ -38,46 +37,16 @@ struct virtio_pci_internal virtio_pci_internal[RTE_MAX_ETHPORTS];\n static enum virtio_msix_status\n vtpci_msix_detect(struct rte_pci_device *dev)\n {\n-\tuint8_t pos;\n-\tint ret;\n-\n-\tret = rte_pci_read_config(dev, &pos, 1, PCI_CAPABILITY_LIST);\n-\tif (ret != 1) {\n-\t\tPMD_INIT_LOG(DEBUG,\n-\t\t\t     \"failed to read pci capability list, ret %d\", ret);\n-\t\treturn VIRTIO_MSIX_NONE;\n-\t}\n-\n-\twhile (pos) {\n-\t\tuint8_t cap[2];\n-\n-\t\tret = rte_pci_read_config(dev, cap, sizeof(cap), pos);\n-\t\tif (ret != sizeof(cap)) {\n-\t\t\tPMD_INIT_LOG(DEBUG,\n-\t\t\t\t     \"failed to read pci cap at pos: %x ret %d\",\n-\t\t\t\t     pos, ret);\n-\t\t\tbreak;\n-\t\t}\n+\tuint16_t flags;\n+\toff_t pos;\n \n-\t\tif (cap[0] == PCI_CAP_ID_MSIX) {\n-\t\t\tuint16_t flags;\n-\n-\t\t\tret = rte_pci_read_config(dev, &flags, sizeof(flags),\n-\t\t\t\t\tpos + sizeof(cap));\n-\t\t\tif (ret != sizeof(flags)) {\n-\t\t\t\tPMD_INIT_LOG(DEBUG,\n-\t\t\t\t\t     \"failed to read pci cap at pos:\"\n-\t\t\t\t\t     \" %x ret %d\", pos + 2, ret);\n-\t\t\t\tbreak;\n-\t\t\t}\n-\n-\t\t\tif (flags & PCI_MSIX_ENABLE)\n-\t\t\t\treturn VIRTIO_MSIX_ENABLED;\n-\t\t\telse\n-\t\t\t\treturn VIRTIO_MSIX_DISABLED;\n-\t\t}\n-\n-\t\tpos = cap[1];\n+\tpos = rte_pci_find_capability(dev, PCI_CAP_ID_MSIX);\n+\tif (pos > 0 && rte_pci_read_config(dev, &flags, sizeof(flags),\n+\t\t\tpos + 2) == sizeof(flags)) {\n+\t\tif (flags & PCI_MSIX_ENABLE)\n+\t\t\treturn VIRTIO_MSIX_ENABLED;\n+\t\telse\n+\t\t\treturn VIRTIO_MSIX_DISABLED;\n \t}\n \n \treturn VIRTIO_MSIX_NONE;\n@@ -623,8 +592,8 @@ static int\n virtio_read_caps(struct rte_pci_device *pci_dev, struct virtio_hw *hw)\n {\n \tstruct virtio_pci_dev *dev = virtio_pci_get_dev(hw);\n-\tuint8_t pos;\n \tstruct virtio_pci_cap cap;\n+\toff_t pos;\n \tint ret;\n \n \tif (rte_pci_map_device(pci_dev)) {\n@@ -632,72 +601,27 @@ virtio_read_caps(struct rte_pci_device *pci_dev, struct virtio_hw *hw)\n \t\treturn -1;\n \t}\n \n-\tret = rte_pci_read_config(pci_dev, &pos, 1, PCI_CAPABILITY_LIST);\n-\tif (ret != 1) {\n-\t\tPMD_INIT_LOG(DEBUG,\n-\t\t\t     \"failed to read pci capability list, ret %d\", ret);\n-\t\treturn -1;\n-\t}\n-\n-\twhile (pos) {\n-\t\tret = rte_pci_read_config(pci_dev, &cap, 2, pos);\n-\t\tif (ret != 2) {\n-\t\t\tPMD_INIT_LOG(DEBUG,\n-\t\t\t\t     \"failed to read pci cap at pos: %x ret %d\",\n-\t\t\t\t     pos, ret);\n-\t\t\tbreak;\n-\t\t}\n-\n-\t\tif (cap.cap_vndr == PCI_CAP_ID_MSIX) {\n-\t\t\t/* Transitional devices would also have this capability,\n-\t\t\t * that's why we also check if msix is enabled.\n-\t\t\t * 1st byte is cap ID; 2nd byte is the position of next\n-\t\t\t * cap; next two bytes are the flags.\n-\t\t\t */\n-\t\t\tuint16_t flags;\n-\n-\t\t\tret = rte_pci_read_config(pci_dev, &flags, sizeof(flags),\n-\t\t\t\t\tpos + 2);\n-\t\t\tif (ret != sizeof(flags)) {\n-\t\t\t\tPMD_INIT_LOG(DEBUG,\n-\t\t\t\t\t     \"failed to read pci cap at pos:\"\n-\t\t\t\t\t     \" %x ret %d\", pos + 2, ret);\n-\t\t\t\tbreak;\n-\t\t\t}\n-\n-\t\t\tif (flags & PCI_MSIX_ENABLE)\n-\t\t\t\tdev->msix_status = VIRTIO_MSIX_ENABLED;\n-\t\t\telse\n-\t\t\t\tdev->msix_status = VIRTIO_MSIX_DISABLED;\n-\t\t}\n-\n-\t\tif (cap.cap_vndr != PCI_CAP_ID_VNDR) {\n-\t\t\tPMD_INIT_LOG(DEBUG,\n-\t\t\t\t\"[%2x] skipping non VNDR cap id: %02x\",\n-\t\t\t\tpos, cap.cap_vndr);\n-\t\t\tgoto next;\n-\t\t}\n+\t/*\n+\t * Transitional devices would also have this capability,\n+\t * that's why we also check if msix is enabled.\n+\t */\n+\tdev->msix_status = vtpci_msix_detect(pci_dev);\n \n-\t\tret = rte_pci_read_config(pci_dev, &cap, sizeof(cap), pos);\n-\t\tif (ret != sizeof(cap)) {\n-\t\t\tPMD_INIT_LOG(DEBUG,\n-\t\t\t\t     \"failed to read pci cap at pos: %x ret %d\",\n-\t\t\t\t     pos, ret);\n+\tpos = rte_pci_find_capability(pci_dev, PCI_CAP_ID_VNDR);\n+\twhile (pos > 0) {\n+\t\tif (rte_pci_read_config(pci_dev, &cap, sizeof(cap), pos) != sizeof(cap))\n \t\t\tbreak;\n-\t\t}\n-\n \t\tPMD_INIT_LOG(DEBUG,\n \t\t\t\"[%2x] cfg type: %u, bar: %u, offset: %04x, len: %u\",\n-\t\t\tpos, cap.cfg_type, cap.bar, cap.offset, cap.length);\n+\t\t\t(unsigned int)pos, cap.cfg_type, cap.bar, cap.offset, cap.length);\n \n \t\tswitch (cap.cfg_type) {\n \t\tcase VIRTIO_PCI_CAP_COMMON_CFG:\n \t\t\tdev->common_cfg = get_cfg_addr(pci_dev, &cap);\n \t\t\tbreak;\n \t\tcase VIRTIO_PCI_CAP_NOTIFY_CFG:\n-\t\t\tret = rte_pci_read_config(pci_dev,\n-\t\t\t\t\t&dev->notify_off_multiplier,\n-\t\t\t\t\t4, pos + sizeof(cap));\n+\t\t\tret = rte_pci_read_config(pci_dev, &dev->notify_off_multiplier,\n+\t\t\t\t4, pos + sizeof(cap));\n \t\t\tif (ret != 4)\n \t\t\t\tPMD_INIT_LOG(DEBUG,\n \t\t\t\t\t\"failed to read notify_off_multiplier, ret %d\",\n@@ -713,8 +637,7 @@ virtio_read_caps(struct rte_pci_device *pci_dev, struct virtio_hw *hw)\n \t\t\tbreak;\n \t\t}\n \n-next:\n-\t\tpos = cap.cap_next;\n+\t\tpos = rte_pci_find_next_capability(pci_dev, PCI_CAP_ID_VNDR, pos);\n \t}\n \n \tif (dev->common_cfg == NULL || dev->notify_base == NULL ||\ndiff --git a/lib/pci/rte_pci.h b/lib/pci/rte_pci.h\nindex aab761b918..a6a38462cb 100644\n--- a/lib/pci/rte_pci.h\n+++ b/lib/pci/rte_pci.h\n@@ -28,13 +28,25 @@ extern \"C\" {\n #define RTE_PCI_CFG_SPACE_SIZE\t\t256\n #define RTE_PCI_CFG_SPACE_EXP_SIZE\t4096\n \n+#define RTE_PCI_STD_HEADER_SIZEOF\t64\n+\n+/* Standard register offsets in the PCI configuration space */\n #define RTE_PCI_VENDOR_ID\t0x00\t/* 16 bits */\n #define RTE_PCI_DEVICE_ID\t0x02\t/* 16 bits */\n #define RTE_PCI_COMMAND\t\t0x04\t/* 16 bits */\n+#define RTE_PCI_STATUS\t\t0x06\t/* 16 bits */\n+#define RTE_PCI_CAPABILITY_LIST\t0x34\t/* 32 bits */\n \n /* PCI Command Register */\n #define RTE_PCI_COMMAND_MASTER\t0x4\t/* Bus Master Enable */\n \n+/* PCI Status Register (RTE_PCI_STATUS) */\n+#define RTE_PCI_STATUS_CAP_LIST\t\t0x10\t/* Support Capability List */\n+\n+/* Capability registers (RTE_PCI_CAPABILITY_LIST) */\n+#define RTE_PCI_CAP_SIZEOF\t\t4\n+#define RTE_PCI_CAP_NEXT\t\t1\n+\n /* PCI Express capability registers */\n #define RTE_PCI_EXP_DEVCTL\t8\t/* Device Control */\n \n",
    "prefixes": [
        "v3",
        "04/15"
    ]
}