From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124]) by inbox.dpdk.org (Postfix) with ESMTP id 0C2D542597; Thu, 14 Sep 2023 14:36:56 +0200 (CEST) Received: from mails.dpdk.org (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 6A49A409FA; Thu, 14 Sep 2023 14:36:45 +0200 (CEST) Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by mails.dpdk.org (Postfix) with ESMTP id 9CD984064A for ; Thu, 14 Sep 2023 14:36:43 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1694695003; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=jreyN14XJsZpLJJj1z2GEcOfTW9gINiVJ0ihMRDQgfQ=; b=E16lt8VXsscY6UA0ZiS7ZdW+wWfxhpcw8+7pfrH5+L932I1HrloWoA73t5FLiwSrTix/ob rtfYpgZuJreqfP1fGpoD9dNOc8/8xjSoAEBif+zDnFedwYrtNTCSGFQ6evtmYqctT0Nmvj y+dadImWUDDn302QO3g7HCCUKRyxnlE= Received: from mimecast-mx02.redhat.com (mimecast-mx02.redhat.com [66.187.233.88]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-572-mQ6Zc-EzPme5Wu7ZsTi8YA-1; Thu, 14 Sep 2023 08:36:37 -0400 X-MC-Unique: mQ6Zc-EzPme5Wu7ZsTi8YA-1 Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.rdu2.redhat.com [10.11.54.6]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 870EA81DBE9; Thu, 14 Sep 2023 12:36:36 +0000 (UTC) Received: from dmarchan.redhat.com (unknown [10.45.225.25]) by smtp.corp.redhat.com (Postfix) with ESMTP id 0D19421B2413; Thu, 14 Sep 2023 12:36:32 +0000 (UTC) From: David Marchand To: dev@dpdk.org Cc: thomas@monjalon.net, ferruh.yigit@amd.com, chenbo.xia@intel.com, nipun.gupta@amd.com, bruce.richardson@intel.com, Anatoly Burakov , Jay Zhou , Abdullah Sevincer , Julien Aube , Rahul Lakkireddy , Junfeng Guo , Jeroen de Borst , Rushil Gupta , Joshua Washington , Dongdong Liu , Yisen Zhuang , Maxime Coquelin , Gaetan Rivet 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> <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 List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Introduce two helpers so that drivers stop reinventing the wheel when it comes to finding capabilities in a device PCI configuration space. Use it in existing drivers. Note: - base/ drivers code is left untouched, only some wrappers in cxgbe are touched, - bnx2x maintained a per device cache of capabilities, this code has been reworked to only cache the capabilities used in this driver, Acked-by: Bruce Richardson Signed-off-by: David Marchand --- Changes since v2: - added rte_pci_find_next_capability for vendor capa used with virtio, Changes since v1: - updated commitlog, - separated VFIO changes for using standard PCI helper in a separate patch, - marked new experimental symbols with current version, - reordered defines in rte_pci.h, --- drivers/bus/pci/linux/pci_vfio.c | 74 ++++-------------- drivers/bus/pci/pci_common.c | 54 +++++++++++++ drivers/bus/pci/rte_bus_pci.h | 53 +++++++++++++ drivers/bus/pci/version.map | 5 ++ drivers/crypto/virtio/virtio_pci.c | 57 +++++--------- drivers/event/dlb2/pf/dlb2_main.c | 42 +--------- drivers/net/bnx2x/bnx2x.c | 41 +++++----- drivers/net/cxgbe/base/adapter.h | 28 +------ drivers/net/gve/gve_ethdev.c | 46 ++--------- drivers/net/gve/gve_ethdev.h | 4 - drivers/net/hns3/hns3_ethdev_vf.c | 79 +++---------------- drivers/net/virtio/virtio_pci.c | 121 ++++++----------------------- lib/pci/rte_pci.h | 12 +++ 13 files changed, 223 insertions(+), 393 deletions(-) diff --git a/drivers/bus/pci/linux/pci_vfio.c b/drivers/bus/pci/linux/pci_vfio.c index 958f8b3b52..614ed5d696 100644 --- a/drivers/bus/pci/linux/pci_vfio.c +++ b/drivers/bus/pci/linux/pci_vfio.c @@ -110,74 +110,34 @@ static int pci_vfio_get_msix_bar(const struct rte_pci_device *dev, struct pci_msix_table *msix_table) { - int ret; - uint32_t reg; - uint16_t flags; - uint8_t cap_id, cap_offset; + off_t cap_offset; - /* read PCI capability pointer from config space */ - ret = rte_pci_read_config(dev, ®, sizeof(reg), PCI_CAPABILITY_LIST); - if (ret != sizeof(reg)) { - RTE_LOG(ERR, EAL, - "Cannot read capability pointer from PCI config space!\n"); + cap_offset = rte_pci_find_capability(dev, PCI_CAP_ID_MSIX); + if (cap_offset < 0) return -1; - } - /* we need first byte */ - cap_offset = reg & 0xFF; + if (cap_offset != 0) { + uint16_t flags; + uint32_t reg; - while (cap_offset) { - - /* read PCI capability ID */ - ret = rte_pci_read_config(dev, ®, sizeof(reg), cap_offset); - if (ret != sizeof(reg)) { + /* table offset resides in the next 4 bytes */ + if (rte_pci_read_config(dev, ®, sizeof(reg), cap_offset + 4) < 0) { RTE_LOG(ERR, EAL, - "Cannot read capability ID from PCI config space!\n"); + "Cannot read MSIX table from PCI config space!\n"); return -1; } - /* we need first byte */ - cap_id = reg & 0xFF; - - /* if we haven't reached MSI-X, check next capability */ - if (cap_id != PCI_CAP_ID_MSIX) { - ret = rte_pci_read_config(dev, ®, sizeof(reg), cap_offset); - if (ret != sizeof(reg)) { - RTE_LOG(ERR, EAL, - "Cannot read capability pointer from PCI config space!\n"); - return -1; - } - - /* we need second byte */ - cap_offset = (reg & 0xFF00) >> 8; - - continue; + if (rte_pci_read_config(dev, &flags, sizeof(flags), cap_offset + 2) < 0) { + RTE_LOG(ERR, EAL, + "Cannot read MSIX flags from PCI config space!\n"); + return -1; } - /* else, read table offset */ - else { - /* table offset resides in the next 4 bytes */ - ret = rte_pci_read_config(dev, ®, sizeof(reg), cap_offset + 4); - if (ret != sizeof(reg)) { - RTE_LOG(ERR, EAL, - "Cannot read table offset from PCI config space!\n"); - return -1; - } - - ret = rte_pci_read_config(dev, &flags, sizeof(flags), cap_offset + 2); - if (ret != sizeof(flags)) { - RTE_LOG(ERR, EAL, - "Cannot read table flags from PCI config space!\n"); - return -1; - } - - msix_table->bar_index = reg & RTE_PCI_MSIX_TABLE_BIR; - msix_table->offset = reg & RTE_PCI_MSIX_TABLE_OFFSET; - msix_table->size = - 16 * (1 + (flags & RTE_PCI_MSIX_FLAGS_QSIZE)); - return 0; - } + msix_table->bar_index = reg & RTE_PCI_MSIX_TABLE_BIR; + msix_table->offset = reg & RTE_PCI_MSIX_TABLE_OFFSET; + msix_table->size = 16 * (1 + (flags & RTE_PCI_MSIX_FLAGS_QSIZE)); } + return 0; } diff --git a/drivers/bus/pci/pci_common.c b/drivers/bus/pci/pci_common.c index 382b0b8946..f149963364 100644 --- a/drivers/bus/pci/pci_common.c +++ b/drivers/bus/pci/pci_common.c @@ -813,6 +813,60 @@ rte_pci_get_iommu_class(void) return iova_mode; } +bool +rte_pci_has_capability_list(const struct rte_pci_device *dev) +{ + uint16_t status; + + if (rte_pci_read_config(dev, &status, sizeof(status), RTE_PCI_STATUS) != sizeof(status)) + return false; + + return (status & RTE_PCI_STATUS_CAP_LIST) != 0; +} + +off_t +rte_pci_find_capability(const struct rte_pci_device *dev, uint8_t cap) +{ + return rte_pci_find_next_capability(dev, cap, 0); +} + +off_t +rte_pci_find_next_capability(const struct rte_pci_device *dev, uint8_t cap, + off_t offset) +{ + uint8_t pos; + int ttl; + + if (offset == 0) + offset = RTE_PCI_CAPABILITY_LIST; + else + offset += RTE_PCI_CAP_NEXT; + ttl = (RTE_PCI_CFG_SPACE_SIZE - RTE_PCI_STD_HEADER_SIZEOF) / RTE_PCI_CAP_SIZEOF; + + if (rte_pci_read_config(dev, &pos, sizeof(pos), offset) < 0) + return -1; + + while (pos && ttl--) { + uint16_t ent; + uint8_t id; + + offset = pos; + if (rte_pci_read_config(dev, &ent, sizeof(ent), offset) < 0) + return -1; + + id = ent & 0xff; + if (id == 0xff) + break; + + if (id == cap) + return offset; + + pos = (ent >> 8); + } + + return 0; +} + off_t rte_pci_find_ext_capability(const struct rte_pci_device *dev, uint32_t cap) { diff --git a/drivers/bus/pci/rte_bus_pci.h b/drivers/bus/pci/rte_bus_pci.h index 75d0030eae..e97b7eae5c 100644 --- a/drivers/bus/pci/rte_bus_pci.h +++ b/drivers/bus/pci/rte_bus_pci.h @@ -68,6 +68,59 @@ void rte_pci_unmap_device(struct rte_pci_device *dev); */ void rte_pci_dump(FILE *f); +/** + * Check whether this device has a PCI capability list. + * + * @param dev + * A pointer to rte_pci_device structure. + * + * @return + * true/false + */ +__rte_experimental +bool rte_pci_has_capability_list(const struct rte_pci_device *dev); + +/** + * Find device's PCI capability. + * + * @param dev + * A pointer to rte_pci_device structure. + * + * @param cap + * Capability to be found, which can be any from + * RTE_PCI_CAP_ID_*, defined in librte_pci. + * + * @return + * > 0: The offset of the next matching capability structure + * within the device's PCI configuration space. + * < 0: An error in PCI config space read. + * = 0: Device does not support it. + */ +__rte_experimental +off_t rte_pci_find_capability(const struct rte_pci_device *dev, uint8_t cap); + +/** + * Find device's PCI capability starting from a previous offset in PCI + * configuration space. + * + * @param dev + * A pointer to rte_pci_device structure. + * + * @param cap + * Capability to be found, which can be any from + * RTE_PCI_CAP_ID_*, defined in librte_pci. + * @param offset + * offset from which the capability is looked for. + * + * @return + * > 0: The offset of the next matching capability structure + * within the device's PCI configuration space. + * < 0: An error in PCI config space read. + * = 0: Device does not support it. + */ +__rte_experimental +off_t rte_pci_find_next_capability(const struct rte_pci_device *dev, uint8_t cap, off_t offset); + /** * Find device's extended PCI capability. * diff --git a/drivers/bus/pci/version.map b/drivers/bus/pci/version.map index a0000f7938..74c5b075d5 100644 --- a/drivers/bus/pci/version.map +++ b/drivers/bus/pci/version.map @@ -25,6 +25,11 @@ EXPERIMENTAL { # added in 23.07 rte_pci_mmio_read; rte_pci_mmio_write; + + # added in 23.11 + rte_pci_find_capability; + rte_pci_find_next_capability; + rte_pci_has_capability_list; }; INTERNAL { diff --git a/drivers/crypto/virtio/virtio_pci.c b/drivers/crypto/virtio/virtio_pci.c index 95a43c8801..19afebdcad 100644 --- a/drivers/crypto/virtio/virtio_pci.c +++ b/drivers/crypto/virtio/virtio_pci.c @@ -19,7 +19,6 @@ * we can't simply include that header here, as there is no such * file for non-Linux platform. */ -#define PCI_CAPABILITY_LIST 0x34 #define PCI_CAP_ID_VNDR 0x09 #define PCI_CAP_ID_MSIX 0x11 @@ -343,8 +342,9 @@ get_cfg_addr(struct rte_pci_device *dev, struct virtio_pci_cap *cap) static int virtio_read_caps(struct rte_pci_device *dev, struct virtio_crypto_hw *hw) { - uint8_t pos; struct virtio_pci_cap cap; + uint16_t flags; + off_t pos; int ret; if (rte_pci_map_device(dev)) { @@ -352,44 +352,28 @@ virtio_read_caps(struct rte_pci_device *dev, struct virtio_crypto_hw *hw) return -1; } - ret = rte_pci_read_config(dev, &pos, 1, PCI_CAPABILITY_LIST); - if (ret < 0) { - VIRTIO_CRYPTO_INIT_LOG_DBG("failed to read pci capability list"); - return -1; + /* + * Transitional devices would also have this capability, + * that's why we also check if msix is enabled. + */ + pos = rte_pci_find_capability(dev, PCI_CAP_ID_MSIX); + if (pos > 0 && rte_pci_read_config(dev, &flags, sizeof(flags), + pos + 2) == sizeof(flags)) { + if (flags & PCI_MSIX_ENABLE) + hw->use_msix = VIRTIO_MSIX_ENABLED; + else + hw->use_msix = VIRTIO_MSIX_DISABLED; + } else { + hw->use_msix = VIRTIO_MSIX_NONE; } - while (pos) { - ret = rte_pci_read_config(dev, &cap, sizeof(cap), pos); - if (ret < 0) { - VIRTIO_CRYPTO_INIT_LOG_ERR( - "failed to read pci cap at pos: %x", pos); + pos = rte_pci_find_capability(dev, PCI_CAP_ID_VNDR); + while (pos > 0) { + if (rte_pci_read_config(dev, &cap, sizeof(cap), pos) != sizeof(cap)) break; - } - - if (cap.cap_vndr == PCI_CAP_ID_MSIX) { - /* Transitional devices would also have this capability, - * that's why we also check if msix is enabled. - * 1st byte is cap ID; 2nd byte is the position of next - * cap; next two bytes are the flags. - */ - uint16_t flags = ((uint16_t *)&cap)[1]; - - if (flags & PCI_MSIX_ENABLE) - hw->use_msix = VIRTIO_MSIX_ENABLED; - else - hw->use_msix = VIRTIO_MSIX_DISABLED; - } - - if (cap.cap_vndr != PCI_CAP_ID_VNDR) { - VIRTIO_CRYPTO_INIT_LOG_DBG( - "[%2x] skipping non VNDR cap id: %02x", - pos, cap.cap_vndr); - goto next; - } - VIRTIO_CRYPTO_INIT_LOG_DBG( "[%2x] cfg type: %u, bar: %u, offset: %04x, len: %u", - pos, cap.cfg_type, cap.bar, cap.offset, cap.length); + (unsigned int)pos, cap.cfg_type, cap.bar, cap.offset, cap.length); switch (cap.cfg_type) { case VIRTIO_PCI_CAP_COMMON_CFG: @@ -412,8 +396,7 @@ virtio_read_caps(struct rte_pci_device *dev, struct virtio_crypto_hw *hw) break; } -next: - pos = cap.cap_next; + pos = rte_pci_find_next_capability(dev, PCI_CAP_ID_VNDR, pos); } if (hw->common_cfg == NULL || hw->notify_base == NULL || diff --git a/drivers/event/dlb2/pf/dlb2_main.c b/drivers/event/dlb2/pf/dlb2_main.c index 717aa4fc08..40e5cb594f 100644 --- a/drivers/event/dlb2/pf/dlb2_main.c +++ b/drivers/event/dlb2/pf/dlb2_main.c @@ -27,10 +27,6 @@ #define NO_OWNER_VF 0 /* PF ONLY! */ #define NOT_VF_REQ false /* PF ONLY! */ -#define DLB2_PCI_CAP_POINTER 0x34 -#define DLB2_PCI_CAP_NEXT(hdr) (((hdr) >> 8) & 0xFC) -#define DLB2_PCI_CAP_ID(hdr) ((hdr) & 0xFF) - #define DLB2_PCI_LNKCTL 16 #define DLB2_PCI_SLTCTL 24 #define DLB2_PCI_RTCTL 28 @@ -65,35 +61,6 @@ #define DLB2_PCI_ACS_UF 0x10 #define DLB2_PCI_ACS_EC 0x20 -static int dlb2_pci_find_capability(struct rte_pci_device *pdev, uint32_t id) -{ - uint8_t pos; - int ret; - uint16_t hdr; - - ret = rte_pci_read_config(pdev, &pos, 1, DLB2_PCI_CAP_POINTER); - pos &= 0xFC; - - if (ret != 1) - return -1; - - while (pos > 0x3F) { - ret = rte_pci_read_config(pdev, &hdr, 2, pos); - if (ret != 2) - return -1; - - if (DLB2_PCI_CAP_ID(hdr) == id) - return pos; - - if (DLB2_PCI_CAP_ID(hdr) == 0xFF) - return -1; - - pos = DLB2_PCI_CAP_NEXT(hdr); - } - - return -1; -} - static int dlb2_pf_init_driver_state(struct dlb2_dev *dlb2_dev) { @@ -258,9 +225,9 @@ dlb2_pf_reset(struct dlb2_dev *dlb2_dev) uint32_t pri_reqs_dword; uint16_t pri_ctrl_word; - int pcie_cap_offset; + off_t pcie_cap_offset; int pri_cap_offset; - int msix_cap_offset; + off_t msix_cap_offset; int err_cap_offset; int acs_cap_offset; int wait_count; @@ -277,7 +244,7 @@ dlb2_pf_reset(struct dlb2_dev *dlb2_dev) return ret; } - pcie_cap_offset = dlb2_pci_find_capability(pdev, DLB2_PCI_CAP_ID_EXP); + pcie_cap_offset = rte_pci_find_capability(pdev, DLB2_PCI_CAP_ID_EXP); if (pcie_cap_offset < 0) { DLB2_LOG_ERR("[%s()] failed to find the pcie capability\n", @@ -516,8 +483,7 @@ dlb2_pf_reset(struct dlb2_dev *dlb2_dev) } } - msix_cap_offset = dlb2_pci_find_capability(pdev, - DLB2_PCI_CAP_ID_MSIX); + msix_cap_offset = rte_pci_find_capability(pdev, DLB2_PCI_CAP_ID_MSIX); if (msix_cap_offset >= 0) { off = msix_cap_offset + DLB2_PCI_MSIX_FLAGS; if (rte_pci_read_config(pdev, &cmd, 2, off) == 2) { diff --git a/drivers/net/bnx2x/bnx2x.c b/drivers/net/bnx2x/bnx2x.c index 29c16bb207..06f2949885 100644 --- a/drivers/net/bnx2x/bnx2x.c +++ b/drivers/net/bnx2x/bnx2x.c @@ -9586,14 +9586,17 @@ static void bnx2x_init_multi_cos(struct bnx2x_softc *sc) } } +static uint8_t bnx2x_pci_capabilities[] = { + PCIY_EXPRESS, + PCIY_PMG, + PCIY_MSI, + PCIY_MSIX, +}; + static int bnx2x_pci_get_caps(struct bnx2x_softc *sc) { - struct { - uint8_t id; - uint8_t next; - } pci_cap; - uint16_t status; struct bnx2x_pci_cap *cap; + unsigned int i; cap = sc->pci_caps = rte_zmalloc("caps", sizeof(struct bnx2x_pci_cap), RTE_CACHE_LINE_SIZE); @@ -9602,29 +9605,21 @@ static int bnx2x_pci_get_caps(struct bnx2x_softc *sc) return -ENOMEM; } -#ifndef RTE_EXEC_ENV_FREEBSD - pci_read(sc, PCI_STATUS, &status, 2); - if (!(status & PCI_STATUS_CAP_LIST)) { -#else - pci_read(sc, PCIR_STATUS, &status, 2); - if (!(status & PCIM_STATUS_CAPPRESENT)) { -#endif + if (!rte_pci_has_capability_list(sc->pci_dev)) { PMD_DRV_LOG(NOTICE, sc, "PCIe capability reading failed"); return -1; } -#ifndef RTE_EXEC_ENV_FREEBSD - pci_read(sc, PCI_CAPABILITY_LIST, &pci_cap.next, 1); -#else - pci_read(sc, PCIR_CAP_PTR, &pci_cap.next, 1); -#endif - while (pci_cap.next) { - cap->addr = pci_cap.next & ~3; - pci_read(sc, pci_cap.next & ~3, &pci_cap, 2); - if (pci_cap.id == 0xff) - break; - cap->id = pci_cap.id; + for (i = 0; i < RTE_DIM(bnx2x_pci_capabilities); i++) { + off_t pos = rte_pci_find_capability(sc->pci_dev, + bnx2x_pci_capabilities[i]); + + if (pos <= 0) + continue; + + cap->id = bnx2x_pci_capabilities[i]; cap->type = BNX2X_PCI_CAP; + cap->addr = pos; cap->next = rte_zmalloc("pci_cap", sizeof(struct bnx2x_pci_cap), RTE_CACHE_LINE_SIZE); diff --git a/drivers/net/cxgbe/base/adapter.h b/drivers/net/cxgbe/base/adapter.h index 8f2ffa0eeb..00d7591ea4 100644 --- a/drivers/net/cxgbe/base/adapter.h +++ b/drivers/net/cxgbe/base/adapter.h @@ -511,13 +511,8 @@ static inline void t4_write_reg64(struct adapter *adapter, u32 reg_addr, CXGBE_WRITE_REG64(adapter, reg_addr, val); } -#define PCI_STATUS 0x06 /* 16 bits */ -#define PCI_STATUS_CAP_LIST 0x10 /* Support Capability List */ -#define PCI_CAPABILITY_LIST 0x34 /* Offset of first capability list entry */ #define PCI_CAP_ID_EXP 0x10 /* PCI Express */ -#define PCI_CAP_LIST_ID 0 /* Capability ID */ -#define PCI_CAP_LIST_NEXT 1 /* Next capability in the list */ #define PCI_EXP_DEVCTL 0x0008 /* Device control */ #define PCI_EXP_DEVCTL2 40 /* Device Control 2 */ #define PCI_EXP_DEVCTL_EXT_TAG 0x0100 /* Extended Tag Field Enable */ @@ -620,31 +615,12 @@ static inline void t4_os_pci_read_cfg(struct adapter *adapter, size_t addr, */ static inline int t4_os_find_pci_capability(struct adapter *adapter, int cap) { - u16 status; - int ttl = 48; - u8 pos = 0; - u8 id = 0; - - t4_os_pci_read_cfg2(adapter, PCI_STATUS, &status); - if (!(status & PCI_STATUS_CAP_LIST)) { + if (!rte_pci_has_capability_list(adapter->pdev)) { dev_err(adapter, "PCIe capability reading failed\n"); return -1; } - t4_os_pci_read_cfg(adapter, PCI_CAPABILITY_LIST, &pos); - while (ttl-- && pos >= 0x40) { - pos &= ~3; - t4_os_pci_read_cfg(adapter, (pos + PCI_CAP_LIST_ID), &id); - - if (id == 0xff) - break; - - if (id == cap) - return (int)pos; - - t4_os_pci_read_cfg(adapter, (pos + PCI_CAP_LIST_NEXT), &pos); - } - return 0; + return rte_pci_find_capability(adapter->pdev, cap); } /** diff --git a/drivers/net/gve/gve_ethdev.c b/drivers/net/gve/gve_ethdev.c index aa75abe102..c276b9e68e 100644 --- a/drivers/net/gve/gve_ethdev.c +++ b/drivers/net/gve/gve_ethdev.c @@ -606,53 +606,17 @@ gve_teardown_device_resources(struct gve_priv *priv) gve_clear_device_resources_ok(priv); } -static uint8_t -pci_dev_find_capability(struct rte_pci_device *pdev, int cap) -{ - uint8_t pos, id; - uint16_t ent; - int loops; - int ret; - - ret = rte_pci_read_config(pdev, &pos, sizeof(pos), PCI_CAPABILITY_LIST); - if (ret != sizeof(pos)) - return 0; - - loops = (PCI_CFG_SPACE_SIZE - PCI_STD_HEADER_SIZEOF) / PCI_CAP_SIZEOF; - - while (pos && loops--) { - ret = rte_pci_read_config(pdev, &ent, sizeof(ent), pos); - if (ret != sizeof(ent)) - return 0; - - id = ent & 0xff; - if (id == 0xff) - break; - - if (id == cap) - return pos; - - pos = (ent >> 8); - } - - return 0; -} - static int pci_dev_msix_vec_count(struct rte_pci_device *pdev) { - uint8_t msix_cap = pci_dev_find_capability(pdev, PCI_CAP_ID_MSIX); + off_t msix_pos = rte_pci_find_capability(pdev, PCI_CAP_ID_MSIX); uint16_t control; - int ret; - if (!msix_cap) - return 0; - - ret = rte_pci_read_config(pdev, &control, sizeof(control), msix_cap + PCI_MSIX_FLAGS); - if (ret != sizeof(control)) - return 0; + if (msix_pos > 0 && rte_pci_read_config(pdev, &control, sizeof(control), + msix_pos + PCI_MSIX_FLAGS) == sizeof(control)) + return (control & PCI_MSIX_FLAGS_QSIZE) + 1; - return (control & PCI_MSIX_FLAGS_QSIZE) + 1; + return 0; } static int diff --git a/drivers/net/gve/gve_ethdev.h b/drivers/net/gve/gve_ethdev.h index c9bcfa553c..8759b1c76e 100644 --- a/drivers/net/gve/gve_ethdev.h +++ b/drivers/net/gve/gve_ethdev.h @@ -19,10 +19,6 @@ * we can't simply include that header here, as there is no such * file for non-Linux platform. */ -#define PCI_CFG_SPACE_SIZE 256 -#define PCI_CAPABILITY_LIST 0x34 /* Offset of first capability list entry */ -#define PCI_STD_HEADER_SIZEOF 64 -#define PCI_CAP_SIZEOF 4 #define PCI_CAP_ID_MSIX 0x11 /* MSI-X */ #define PCI_MSIX_FLAGS 2 /* Message Control */ #define PCI_MSIX_FLAGS_QSIZE 0x07FF /* Table size */ diff --git a/drivers/net/hns3/hns3_ethdev_vf.c b/drivers/net/hns3/hns3_ethdev_vf.c index 7b3c5dc168..b731850b01 100644 --- a/drivers/net/hns3/hns3_ethdev_vf.c +++ b/drivers/net/hns3/hns3_ethdev_vf.c @@ -49,80 +49,24 @@ static int hns3vf_remove_mc_mac_addr(struct hns3_hw *hw, static int hns3vf_dev_link_update(struct rte_eth_dev *eth_dev, __rte_unused int wait_to_complete); -/** - * hns3vf_find_pci_capability - lookup a capability in the PCI capability list - * @cap: the capability - * - * Return the address of the given capability within the PCI capability list. - */ static int -hns3vf_find_pci_capability(const struct rte_pci_device *device, int cap) +hns3vf_enable_msix(const struct rte_pci_device *device, bool op) { -#define MAX_PCIE_CAPABILITY 48 - uint16_t status; - uint8_t pos; - uint8_t id; - int ttl; + uint16_t control; + off_t pos; int ret; - ret = rte_pci_read_config(device, &status, sizeof(status), PCI_STATUS); - if (ret < 0) { - PMD_INIT_LOG(ERR, "Failed to read PCI offset 0x%x", PCI_STATUS); - return 0; - } - - if (!(status & PCI_STATUS_CAP_LIST)) - return 0; - - ttl = MAX_PCIE_CAPABILITY; - ret = rte_pci_read_config(device, &pos, sizeof(pos), - PCI_CAPABILITY_LIST); - if (ret < 0) { - PMD_INIT_LOG(ERR, "Failed to read PCI offset 0x%x", - PCI_CAPABILITY_LIST); + if (!rte_pci_has_capability_list(device)) { + PMD_INIT_LOG(ERR, "Failed to read PCI capability list"); return 0; } - while (ttl-- && pos >= PCI_STD_HEADER_SIZEOF) { - ret = rte_pci_read_config(device, &id, sizeof(id), - (pos + PCI_CAP_LIST_ID)); - if (ret < 0) { - PMD_INIT_LOG(ERR, "Failed to read PCI offset 0x%x", - (pos + PCI_CAP_LIST_ID)); - break; - } - - if (id == 0xFF) - break; - - if (id == cap) - return (int)pos; - - ret = rte_pci_read_config(device, &pos, sizeof(pos), - (pos + PCI_CAP_LIST_NEXT)); - if (ret < 0) { - PMD_INIT_LOG(ERR, "Failed to read PCI offset 0x%x", - (pos + PCI_CAP_LIST_NEXT)); - break; - } - } - return 0; -} - -static int -hns3vf_enable_msix(const struct rte_pci_device *device, bool op) -{ - uint16_t control; - int pos; - int ret; - - pos = hns3vf_find_pci_capability(device, PCI_CAP_ID_MSIX); - if (pos) { + pos = rte_pci_find_capability(device, PCI_CAP_ID_MSIX); + if (pos > 0) { ret = rte_pci_read_config(device, &control, sizeof(control), - (pos + PCI_MSIX_FLAGS)); + pos + PCI_MSIX_FLAGS); if (ret < 0) { - PMD_INIT_LOG(ERR, "Failed to read PCI offset 0x%x", - (pos + PCI_MSIX_FLAGS)); + PMD_INIT_LOG(ERR, "Failed to read MSIX flags"); return -ENXIO; } @@ -131,10 +75,9 @@ hns3vf_enable_msix(const struct rte_pci_device *device, bool op) else control &= ~PCI_MSIX_FLAGS_ENABLE; ret = rte_pci_write_config(device, &control, sizeof(control), - (pos + PCI_MSIX_FLAGS)); + pos + PCI_MSIX_FLAGS); if (ret < 0) { - PMD_INIT_LOG(ERR, "failed to write PCI offset 0x%x", - (pos + PCI_MSIX_FLAGS)); + PMD_INIT_LOG(ERR, "failed to write MSIX flags"); return -ENXIO; } diff --git a/drivers/net/virtio/virtio_pci.c b/drivers/net/virtio/virtio_pci.c index 29eb739b04..4c2a1911d1 100644 --- a/drivers/net/virtio/virtio_pci.c +++ b/drivers/net/virtio/virtio_pci.c @@ -20,7 +20,6 @@ * we can't simply include that header here, as there is no such * file for non-Linux platform. */ -#define PCI_CAPABILITY_LIST 0x34 #define PCI_CAP_ID_VNDR 0x09 #define PCI_CAP_ID_MSIX 0x11 @@ -38,46 +37,16 @@ struct virtio_pci_internal virtio_pci_internal[RTE_MAX_ETHPORTS]; static enum virtio_msix_status vtpci_msix_detect(struct rte_pci_device *dev) { - uint8_t pos; - int ret; - - ret = rte_pci_read_config(dev, &pos, 1, PCI_CAPABILITY_LIST); - if (ret != 1) { - PMD_INIT_LOG(DEBUG, - "failed to read pci capability list, ret %d", ret); - return VIRTIO_MSIX_NONE; - } - - while (pos) { - uint8_t cap[2]; - - ret = rte_pci_read_config(dev, cap, sizeof(cap), pos); - if (ret != sizeof(cap)) { - PMD_INIT_LOG(DEBUG, - "failed to read pci cap at pos: %x ret %d", - pos, ret); - break; - } + uint16_t flags; + off_t pos; - if (cap[0] == PCI_CAP_ID_MSIX) { - uint16_t flags; - - ret = rte_pci_read_config(dev, &flags, sizeof(flags), - pos + sizeof(cap)); - if (ret != sizeof(flags)) { - PMD_INIT_LOG(DEBUG, - "failed to read pci cap at pos:" - " %x ret %d", pos + 2, ret); - break; - } - - if (flags & PCI_MSIX_ENABLE) - return VIRTIO_MSIX_ENABLED; - else - return VIRTIO_MSIX_DISABLED; - } - - pos = cap[1]; + pos = rte_pci_find_capability(dev, PCI_CAP_ID_MSIX); + if (pos > 0 && rte_pci_read_config(dev, &flags, sizeof(flags), + pos + 2) == sizeof(flags)) { + if (flags & PCI_MSIX_ENABLE) + return VIRTIO_MSIX_ENABLED; + else + return VIRTIO_MSIX_DISABLED; } return VIRTIO_MSIX_NONE; @@ -623,8 +592,8 @@ static int virtio_read_caps(struct rte_pci_device *pci_dev, struct virtio_hw *hw) { struct virtio_pci_dev *dev = virtio_pci_get_dev(hw); - uint8_t pos; struct virtio_pci_cap cap; + off_t pos; int ret; if (rte_pci_map_device(pci_dev)) { @@ -632,72 +601,27 @@ virtio_read_caps(struct rte_pci_device *pci_dev, struct virtio_hw *hw) return -1; } - ret = rte_pci_read_config(pci_dev, &pos, 1, PCI_CAPABILITY_LIST); - if (ret != 1) { - PMD_INIT_LOG(DEBUG, - "failed to read pci capability list, ret %d", ret); - return -1; - } - - while (pos) { - ret = rte_pci_read_config(pci_dev, &cap, 2, pos); - if (ret != 2) { - PMD_INIT_LOG(DEBUG, - "failed to read pci cap at pos: %x ret %d", - pos, ret); - break; - } - - if (cap.cap_vndr == PCI_CAP_ID_MSIX) { - /* Transitional devices would also have this capability, - * that's why we also check if msix is enabled. - * 1st byte is cap ID; 2nd byte is the position of next - * cap; next two bytes are the flags. - */ - uint16_t flags; - - ret = rte_pci_read_config(pci_dev, &flags, sizeof(flags), - pos + 2); - if (ret != sizeof(flags)) { - PMD_INIT_LOG(DEBUG, - "failed to read pci cap at pos:" - " %x ret %d", pos + 2, ret); - break; - } - - if (flags & PCI_MSIX_ENABLE) - dev->msix_status = VIRTIO_MSIX_ENABLED; - else - dev->msix_status = VIRTIO_MSIX_DISABLED; - } - - if (cap.cap_vndr != PCI_CAP_ID_VNDR) { - PMD_INIT_LOG(DEBUG, - "[%2x] skipping non VNDR cap id: %02x", - pos, cap.cap_vndr); - goto next; - } + /* + * Transitional devices would also have this capability, + * that's why we also check if msix is enabled. + */ + dev->msix_status = vtpci_msix_detect(pci_dev); - ret = rte_pci_read_config(pci_dev, &cap, sizeof(cap), pos); - if (ret != sizeof(cap)) { - PMD_INIT_LOG(DEBUG, - "failed to read pci cap at pos: %x ret %d", - pos, ret); + pos = rte_pci_find_capability(pci_dev, PCI_CAP_ID_VNDR); + while (pos > 0) { + if (rte_pci_read_config(pci_dev, &cap, sizeof(cap), pos) != sizeof(cap)) break; - } - PMD_INIT_LOG(DEBUG, "[%2x] cfg type: %u, bar: %u, offset: %04x, len: %u", - pos, cap.cfg_type, cap.bar, cap.offset, cap.length); + (unsigned int)pos, cap.cfg_type, cap.bar, cap.offset, cap.length); switch (cap.cfg_type) { case VIRTIO_PCI_CAP_COMMON_CFG: dev->common_cfg = get_cfg_addr(pci_dev, &cap); break; case VIRTIO_PCI_CAP_NOTIFY_CFG: - ret = rte_pci_read_config(pci_dev, - &dev->notify_off_multiplier, - 4, pos + sizeof(cap)); + ret = rte_pci_read_config(pci_dev, &dev->notify_off_multiplier, + 4, pos + sizeof(cap)); if (ret != 4) PMD_INIT_LOG(DEBUG, "failed to read notify_off_multiplier, ret %d", @@ -713,8 +637,7 @@ virtio_read_caps(struct rte_pci_device *pci_dev, struct virtio_hw *hw) break; } -next: - pos = cap.cap_next; + pos = rte_pci_find_next_capability(pci_dev, PCI_CAP_ID_VNDR, pos); } if (dev->common_cfg == NULL || dev->notify_base == NULL || diff --git a/lib/pci/rte_pci.h b/lib/pci/rte_pci.h index aab761b918..a6a38462cb 100644 --- a/lib/pci/rte_pci.h +++ b/lib/pci/rte_pci.h @@ -28,13 +28,25 @@ extern "C" { #define RTE_PCI_CFG_SPACE_SIZE 256 #define RTE_PCI_CFG_SPACE_EXP_SIZE 4096 +#define RTE_PCI_STD_HEADER_SIZEOF 64 + +/* Standard register offsets in the PCI configuration space */ #define RTE_PCI_VENDOR_ID 0x00 /* 16 bits */ #define RTE_PCI_DEVICE_ID 0x02 /* 16 bits */ #define RTE_PCI_COMMAND 0x04 /* 16 bits */ +#define RTE_PCI_STATUS 0x06 /* 16 bits */ +#define RTE_PCI_CAPABILITY_LIST 0x34 /* 32 bits */ /* PCI Command Register */ #define RTE_PCI_COMMAND_MASTER 0x4 /* Bus Master Enable */ +/* PCI Status Register (RTE_PCI_STATUS) */ +#define RTE_PCI_STATUS_CAP_LIST 0x10 /* Support Capability List */ + +/* Capability registers (RTE_PCI_CAPABILITY_LIST) */ +#define RTE_PCI_CAP_SIZEOF 4 +#define RTE_PCI_CAP_NEXT 1 + /* PCI Express capability registers */ #define RTE_PCI_EXP_DEVCTL 8 /* Device Control */ -- 2.41.0