From: "Pali Rohár" <pali@kernel.org>
To: "Martin Mares" <mj@ucw.cz>, "Bjorn Helgaas" <helgaas@kernel.org>,
"Krzysztof Wilczyński" <kw@linux.com>,
"Matthew Wilcox" <willy@infradead.org>,
linux-pci@vger.kernel.org
Subject: [PATCH pciutils 3/4] libpci: Add support for filling bridge resources
Date: Mon, 20 Dec 2021 16:54:47 +0100 [thread overview]
Message-ID: <20211220155448.1233-3-pali@kernel.org> (raw)
In-Reply-To: <20211220155448.1233-1-pali@kernel.org>
Extend libpci API and ABI to fill bridge resources from sysfs.
---
lib/access.c | 20 +++++++++++---------
lib/caps.c | 2 +-
lib/filter.c | 2 +-
lib/internal.h | 1 +
lib/libpci.ver | 5 +++++
lib/pci.h | 4 ++++
lib/sysfs.c | 48 ++++++++++++++++++++++++++++++++++++++++++------
7 files changed, 65 insertions(+), 17 deletions(-)
diff --git a/lib/access.c b/lib/access.c
index b257849a685e..a33e067e2389 100644
--- a/lib/access.c
+++ b/lib/access.c
@@ -189,7 +189,7 @@ pci_reset_properties(struct pci_dev *d)
}
int
-pci_fill_info_v35(struct pci_dev *d, int flags)
+pci_fill_info_v38(struct pci_dev *d, int flags)
{
unsigned int uflags = flags;
if (uflags & PCI_FILL_RESCAN)
@@ -203,19 +203,21 @@ pci_fill_info_v35(struct pci_dev *d, int flags)
}
/* In version 3.1, pci_fill_info got new flags => versioned alias */
-/* In versions 3.2, 3.3, 3.4 and 3.5, the same has happened */
-STATIC_ALIAS(int pci_fill_info(struct pci_dev *d, int flags), pci_fill_info_v35(d, flags));
-DEFINE_ALIAS(int pci_fill_info_v30(struct pci_dev *d, int flags), pci_fill_info_v35);
-DEFINE_ALIAS(int pci_fill_info_v31(struct pci_dev *d, int flags), pci_fill_info_v35);
-DEFINE_ALIAS(int pci_fill_info_v32(struct pci_dev *d, int flags), pci_fill_info_v35);
-DEFINE_ALIAS(int pci_fill_info_v33(struct pci_dev *d, int flags), pci_fill_info_v35);
-DEFINE_ALIAS(int pci_fill_info_v34(struct pci_dev *d, int flags), pci_fill_info_v35);
+/* In versions 3.2, 3.3, 3.4, 3.5 and 3.8, the same has happened */
+STATIC_ALIAS(int pci_fill_info(struct pci_dev *d, int flags), pci_fill_info_v38(d, flags));
+DEFINE_ALIAS(int pci_fill_info_v30(struct pci_dev *d, int flags), pci_fill_info_v38);
+DEFINE_ALIAS(int pci_fill_info_v31(struct pci_dev *d, int flags), pci_fill_info_v38);
+DEFINE_ALIAS(int pci_fill_info_v32(struct pci_dev *d, int flags), pci_fill_info_v38);
+DEFINE_ALIAS(int pci_fill_info_v33(struct pci_dev *d, int flags), pci_fill_info_v38);
+DEFINE_ALIAS(int pci_fill_info_v34(struct pci_dev *d, int flags), pci_fill_info_v38);
+DEFINE_ALIAS(int pci_fill_info_v35(struct pci_dev *d, int flags), pci_fill_info_v38);
SYMBOL_VERSION(pci_fill_info_v30, pci_fill_info@LIBPCI_3.0);
SYMBOL_VERSION(pci_fill_info_v31, pci_fill_info@LIBPCI_3.1);
SYMBOL_VERSION(pci_fill_info_v32, pci_fill_info@LIBPCI_3.2);
SYMBOL_VERSION(pci_fill_info_v33, pci_fill_info@LIBPCI_3.3);
SYMBOL_VERSION(pci_fill_info_v34, pci_fill_info@LIBPCI_3.4);
-SYMBOL_VERSION(pci_fill_info_v35, pci_fill_info@@LIBPCI_3.5);
+SYMBOL_VERSION(pci_fill_info_v35, pci_fill_info@LIBPCI_3.5);
+SYMBOL_VERSION(pci_fill_info_v38, pci_fill_info@@LIBPCI_3.8);
void
pci_setup_cache(struct pci_dev *d, byte *cache, int len)
diff --git a/lib/caps.c b/lib/caps.c
index c3b918059fe1..70a41b836e31 100644
--- a/lib/caps.c
+++ b/lib/caps.c
@@ -129,7 +129,7 @@ pci_find_cap_nr(struct pci_dev *d, unsigned int id, unsigned int type,
unsigned int target = (cap_number ? *cap_number : 0);
unsigned int index = 0;
- pci_fill_info_v35(d, ((type == PCI_CAP_NORMAL) ? PCI_FILL_CAPS : PCI_FILL_EXT_CAPS));
+ pci_fill_info_v38(d, ((type == PCI_CAP_NORMAL) ? PCI_FILL_CAPS : PCI_FILL_EXT_CAPS));
for (c=d->first_cap; c; c=c->next)
{
diff --git a/lib/filter.c b/lib/filter.c
index 573fb2810363..195f813193c4 100644
--- a/lib/filter.c
+++ b/lib/filter.c
@@ -129,7 +129,7 @@ pci_filter_match_v33(struct pci_filter *f, struct pci_dev *d)
return 0;
if (f->device >= 0 || f->vendor >= 0)
{
- pci_fill_info_v35(d, PCI_FILL_IDENT);
+ pci_fill_info_v38(d, PCI_FILL_IDENT);
if ((f->device >= 0 && f->device != d->device_id) ||
(f->vendor >= 0 && f->vendor != d->vendor_id))
return 0;
diff --git a/lib/internal.h b/lib/internal.h
index 17c27e194a29..4df8dd70c2c6 100644
--- a/lib/internal.h
+++ b/lib/internal.h
@@ -74,6 +74,7 @@ int pci_fill_info_v32(struct pci_dev *, int flags) VERSIONED_ABI;
int pci_fill_info_v33(struct pci_dev *, int flags) VERSIONED_ABI;
int pci_fill_info_v34(struct pci_dev *, int flags) VERSIONED_ABI;
int pci_fill_info_v35(struct pci_dev *, int flags) VERSIONED_ABI;
+int pci_fill_info_v38(struct pci_dev *, int flags) VERSIONED_ABI;
struct pci_property {
struct pci_property *next;
diff --git a/lib/libpci.ver b/lib/libpci.ver
index e20c3f581c71..73f7fa71e357 100644
--- a/lib/libpci.ver
+++ b/lib/libpci.ver
@@ -82,3 +82,8 @@ LIBPCI_3.7 {
global:
pci_find_cap_nr;
};
+
+LIBPCI_3.8 {
+ global:
+ pci_fill_info;
+};
diff --git a/lib/pci.h b/lib/pci.h
index 814247691086..0ec7f211ca24 100644
--- a/lib/pci.h
+++ b/lib/pci.h
@@ -142,6 +142,9 @@ struct pci_dev {
pciaddr_t flags[6]; /* PCI_IORESOURCE_* flags for regions */
pciaddr_t rom_flags; /* PCI_IORESOURCE_* flags for expansion ROM */
int domain; /* PCI domain (host bridge) */
+ pciaddr_t bridge_base_addr[4]; /* Bridge base addresses (without flags) */
+ pciaddr_t bridge_size[4]; /* Bridge sizes */
+ pciaddr_t bridge_flags[4]; /* PCI_IORESOURCE_* flags for bridge addresses */
/* Fields used internally */
struct pci_access *access;
@@ -205,6 +208,7 @@ char *pci_get_string_property(struct pci_dev *d, u32 prop) PCI_ABI;
#define PCI_FILL_IO_FLAGS 0x1000
#define PCI_FILL_DT_NODE 0x2000 /* Device tree node */
#define PCI_FILL_IOMMU_GROUP 0x4000
+#define PCI_FILL_BRIDGE_BASES 0x8000
#define PCI_FILL_RESCAN 0x00010000
void pci_setup_cache(struct pci_dev *, u8 *cache, int len) PCI_ABI;
diff --git a/lib/sysfs.c b/lib/sysfs.c
index fb6424105e84..7c157a2688ad 100644
--- a/lib/sysfs.c
+++ b/lib/sysfs.c
@@ -148,19 +148,22 @@ sysfs_get_value(struct pci_dev *d, char *object, int mandatory)
return -1;
}
-static void
+static unsigned int
sysfs_get_resources(struct pci_dev *d)
{
struct pci_access *a = d->access;
char namebuf[OBJNAMELEN], buf[256];
+ struct { pciaddr_t flags, base_addr, size; } lines[10];
+ unsigned int done;
FILE *file;
int i;
+ done = 0;
sysfs_obj_name(d, "resource", namebuf);
file = fopen(namebuf, "r");
if (!file)
a->error("Cannot open %s: %s", namebuf, strerror(errno));
- for (i = 0; i < 7; i++)
+ for (i = 0; i < 7+6+4+1; i++)
{
unsigned long long start, end, size, flags;
if (!fgets(buf, sizeof(buf), file))
@@ -177,16 +180,50 @@ sysfs_get_resources(struct pci_dev *d)
flags &= PCI_ADDR_FLAG_MASK;
d->base_addr[i] = start | flags;
d->size[i] = size;
+ done |= PCI_FILL_BASES | PCI_FILL_SIZES | PCI_FILL_IO_FLAGS;
}
- else
+ else if (i == 6)
{
d->rom_flags = flags;
flags &= PCI_ADDR_FLAG_MASK;
d->rom_base_addr = start | flags;
d->rom_size = size;
+ done |= PCI_FILL_ROM_BASE;
}
+ else if (i < 7+6+4)
+ {
+ /*
+ * If kernel was compiled without CONFIG_PCI_IOV option then after
+ * the ROM line for configured bridge device (that which had set
+ * subordinary bus number to non-zero value) are four additional lines
+ * which describe resources behind bridge. For PCI-to-PCI bridges they
+ * are: IO, MEM, PREFMEM and empty. For CardBus bridges they are: IO0,
+ * IO1, MEM0 and MEM1. For unconfigured bridges and other devices
+ * there is no additional line after the ROM line. If kernel was
+ * compiled with CONFIG_PCI_IOV option then after the ROM line and
+ * before the first bridge resource line are six additional lines
+ * which describe IOV resources. Read all remaining lines in resource
+ * file and based on the number of remaining lines (0, 4, 6, 10) parse
+ * resources behind bridge.
+ */
+ lines[i-7].flags = flags;
+ lines[i-7].base_addr = start;
+ lines[i-7].size = size;
+ }
+ }
+ if (i == 7+4 || i == 7+6+4)
+ {
+ int offset = (i == 7+6+4) ? 6 : 0;
+ for (i = 0; i < 4; i++)
+ {
+ d->bridge_flags[i] = lines[offset+i].flags;
+ d->bridge_base_addr[i] = lines[offset+i].base_addr;
+ d->bridge_size[i] = lines[offset+i].size;
+ }
+ done |= PCI_FILL_BRIDGE_BASES;
}
fclose(file);
+ return done;
}
static void sysfs_scan(struct pci_access *a)
@@ -316,10 +353,9 @@ sysfs_fill_info(struct pci_dev *d, unsigned int flags)
d->irq = sysfs_get_value(d, "irq", 1);
done |= PCI_FILL_IRQ;
}
- if (flags & (PCI_FILL_BASES | PCI_FILL_ROM_BASE | PCI_FILL_SIZES | PCI_FILL_IO_FLAGS))
+ if (flags & (PCI_FILL_BASES | PCI_FILL_ROM_BASE | PCI_FILL_SIZES | PCI_FILL_IO_FLAGS | PCI_FILL_BRIDGE_BASES))
{
- sysfs_get_resources(d);
- done |= PCI_FILL_BASES | PCI_FILL_ROM_BASE | PCI_FILL_SIZES | PCI_FILL_IO_FLAGS;
+ done |= sysfs_get_resources(d);
}
}
--
2.20.1
next prev parent reply other threads:[~2021-12-20 15:55 UTC|newest]
Thread overview: 15+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-12-20 15:54 [PATCH pciutils 1/4] lspci: Show 16/32/64 bit width for address ranges behind bridge Pali Rohár
2021-12-20 15:54 ` [PATCH pciutils 2/4] lspci: Simplify printing range in show_range() Pali Rohár
2021-12-20 15:54 ` Pali Rohár [this message]
2021-12-26 22:13 ` [PATCH pciutils 3/4] libpci: Add support for filling bridge resources Martin Mareš
2021-12-26 22:20 ` Pali Rohár
2021-12-31 22:27 ` Pali Rohár
2022-01-20 20:33 ` Bjorn Helgaas
2022-01-20 20:45 ` Pali Rohár
2022-01-20 21:02 ` Bjorn Helgaas
2022-01-20 21:19 ` Pali Rohár
2022-11-11 20:09 ` IORESOURCE_WINDOW for PCI-to-PCI bridges Pali Rohár
2022-11-11 21:05 ` Bjorn Helgaas
2022-11-11 21:48 ` Pali Rohár
2022-11-15 22:15 ` Bjorn Helgaas
2021-12-20 15:54 ` [PATCH pciutils 4/4] lspci: Use PCI_FILL_BRIDGE_BASES to detect if range behind bridge is disabled or unsupported Pali Rohár
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20211220155448.1233-3-pali@kernel.org \
--to=pali@kernel.org \
--cc=helgaas@kernel.org \
--cc=kw@linux.com \
--cc=linux-pci@vger.kernel.org \
--cc=mj@ucw.cz \
--cc=willy@infradead.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.