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 4/4] lspci: Use PCI_FILL_BRIDGE_BASES to detect if range behind bridge is disabled or unsupported
Date: Mon, 20 Dec 2021 16:54:48 +0100 [thread overview]
Message-ID: <20211220155448.1233-4-pali@kernel.org> (raw)
In-Reply-To: <20211220155448.1233-1-pali@kernel.org>
Show resources behind bridge as reported by PCI_FILL_BRIDGE_BASES.
I/O or Prefetchable memory behind bridge is unsupported by bridge if both
base and limit bridge registers are read-only and returns zero. So if base
and limit registers returns zero (which is valid enabled range) and kernel
reports that particular resource is disabled it means that resource is
unsupported. Both I/O or Prefetchable memory resources are only optional.
---
lspci.c | 58 ++++++++++++++++++++++++++++++++++++++++++++++++---------
1 file changed, 49 insertions(+), 9 deletions(-)
diff --git a/lspci.c b/lspci.c
index 67ac19b61a29..d14d1b9185d6 100644
--- a/lspci.c
+++ b/lspci.c
@@ -374,12 +374,12 @@ show_size(u64 x)
}
static void
-show_range(char *prefix, u64 base, u64 limit, int bits)
+show_range(char *prefix, u64 base, u64 limit, int bits, int disabled)
{
printf("%s:", prefix);
if (base <= limit || verbose > 2)
printf(" %0*" PCI_U64_FMT_X "-%0*" PCI_U64_FMT_X, (bits+3)/4, base, (bits+3)/4, limit);
- if (base <= limit)
+ if (!disabled && base <= limit)
show_size(limit - base + 1);
else
printf(" [disabled]");
@@ -543,6 +543,7 @@ show_htype0(struct device *d)
static void
show_htype1(struct device *d)
{
+ struct pci_dev *p = d->dev;
u32 io_base = get_conf_byte(d, PCI_IO_BASE);
u32 io_limit = get_conf_byte(d, PCI_IO_LIMIT);
u32 io_type = io_base & PCI_IO_RANGE_TYPE_MASK;
@@ -554,6 +555,10 @@ show_htype1(struct device *d)
u32 pref_type = pref_base & PCI_PREF_RANGE_TYPE_MASK;
word sec_stat = get_conf_word(d, PCI_SEC_STATUS);
word brc = get_conf_word(d, PCI_BRIDGE_CONTROL);
+ int io_disabled = (p->known_fields & PCI_FILL_BRIDGE_BASES) && !p->bridge_size[0];
+ int mem_disabled = (p->known_fields & PCI_FILL_BRIDGE_BASES) && !p->bridge_size[1];
+ int pref_disabled = (p->known_fields & PCI_FILL_BRIDGE_BASES) && !p->bridge_size[2];
+ int io_bits, pref_bits;
show_bases(d, 2);
printf("\tBus: primary=%02x, secondary=%02x, subordinate=%02x, sec-latency=%d\n",
@@ -562,7 +567,15 @@ show_htype1(struct device *d)
get_conf_byte(d, PCI_SUBORDINATE_BUS),
get_conf_byte(d, PCI_SEC_LATENCY_TIMER));
- if (io_type != (io_limit & PCI_IO_RANGE_TYPE_MASK) ||
+ if ((p->known_fields & PCI_FILL_BRIDGE_BASES) && !io_disabled)
+ {
+ io_base = p->bridge_base_addr[0] & PCI_IO_RANGE_MASK;
+ io_limit = io_base + p->bridge_size[0] - 1;
+ io_type = p->bridge_base_addr[0] & PCI_IO_RANGE_TYPE_MASK;
+ io_bits = (io_type == PCI_IO_RANGE_TYPE_32) ? 32 : 16;
+ show_range("\tI/O behind bridge", io_base, io_limit, io_bits, io_disabled);
+ }
+ else if (io_type != (io_limit & PCI_IO_RANGE_TYPE_MASK) ||
(io_type != PCI_IO_RANGE_TYPE_16 && io_type != PCI_IO_RANGE_TYPE_32))
printf("\t!!! Unknown I/O range types %x/%x\n", io_base, io_limit);
else
@@ -574,20 +587,40 @@ show_htype1(struct device *d)
io_base |= (get_conf_word(d, PCI_IO_BASE_UPPER16) << 16);
io_limit |= (get_conf_word(d, PCI_IO_LIMIT_UPPER16) << 16);
}
- show_range("\tI/O behind bridge", io_base, io_limit+0xfff, (io_type == PCI_IO_RANGE_TYPE_32) ? 32 : 16);
+ /* I/O is unsupported if both base and limit are zeros and resource is disabled */
+ if (!(io_base == 0x0 && io_limit == 0x0 && io_disabled))
+ {
+ io_limit += 0xfff;
+ io_bits = (io_type == PCI_IO_RANGE_TYPE_32) ? 32 : 16;
+ show_range("\tI/O behind bridge", io_base, io_limit, io_bits, io_disabled);
+ }
}
- if (mem_type != (mem_limit & PCI_MEMORY_RANGE_TYPE_MASK) ||
+ if ((p->known_fields & PCI_FILL_BRIDGE_BASES) && !mem_disabled)
+ {
+ mem_base = p->bridge_base_addr[1] & PCI_MEMORY_RANGE_MASK;
+ mem_limit = mem_base + p->bridge_size[1] - 1;
+ show_range("\tMemory behind bridge", mem_base, mem_limit, 32, mem_disabled);
+ }
+ else if (mem_type != (mem_limit & PCI_MEMORY_RANGE_TYPE_MASK) ||
mem_type)
printf("\t!!! Unknown memory range types %x/%x\n", mem_base, mem_limit);
else
{
mem_base = (mem_base & PCI_MEMORY_RANGE_MASK) << 16;
mem_limit = (mem_limit & PCI_MEMORY_RANGE_MASK) << 16;
- show_range("\tMemory behind bridge", mem_base, mem_limit + 0xfffff, 32);
+ show_range("\tMemory behind bridge", mem_base, mem_limit + 0xfffff, 32, mem_disabled);
}
- if (pref_type != (pref_limit & PCI_PREF_RANGE_TYPE_MASK) ||
+ if ((p->known_fields & PCI_FILL_BRIDGE_BASES) && !pref_disabled)
+ {
+ u64 pref_base_64 = p->bridge_base_addr[2] & PCI_MEMORY_RANGE_MASK;
+ u64 pref_limit_64 = pref_base_64 + p->bridge_size[2] - 1;
+ pref_type = p->bridge_base_addr[2] & PCI_MEMORY_RANGE_TYPE_MASK;
+ pref_bits = (pref_type == PCI_PREF_RANGE_TYPE_64) ? 64 : 32;
+ show_range("\tPrefetchable memory behind bridge", pref_base_64, pref_limit_64, pref_bits, pref_disabled);
+ }
+ else if (pref_type != (pref_limit & PCI_PREF_RANGE_TYPE_MASK) ||
(pref_type != PCI_PREF_RANGE_TYPE_32 && pref_type != PCI_PREF_RANGE_TYPE_64))
printf("\t!!! Unknown prefetchable memory range types %x/%x\n", pref_base, pref_limit);
else
@@ -599,7 +632,13 @@ show_htype1(struct device *d)
pref_base_64 |= (u64) get_conf_long(d, PCI_PREF_BASE_UPPER32) << 32;
pref_limit_64 |= (u64) get_conf_long(d, PCI_PREF_LIMIT_UPPER32) << 32;
}
- show_range("\tPrefetchable memory behind bridge", pref_base_64, pref_limit_64 + 0xfffff, (pref_type == PCI_PREF_RANGE_TYPE_64) ? 64 : 32);
+ /* Prefetchable memory is unsupported if both base and limit are zeros and resource is disabled */
+ if (!(pref_base_64 == 0x0 && pref_limit_64 == 0x0 && pref_disabled))
+ {
+ pref_limit_64 += 0xfffff;
+ pref_bits = (pref_type == PCI_PREF_RANGE_TYPE_64) ? 64 : 32;
+ show_range("\tPrefetchable memory behind bridge", pref_base_64, pref_limit_64, pref_bits, pref_disabled);
+ }
}
if (verbose > 1)
@@ -726,7 +765,8 @@ show_verbose(struct device *d)
show_terse(d);
pci_fill_info(p, PCI_FILL_IRQ | PCI_FILL_BASES | PCI_FILL_ROM_BASE | PCI_FILL_SIZES |
- PCI_FILL_PHYS_SLOT | PCI_FILL_NUMA_NODE | PCI_FILL_DT_NODE | PCI_FILL_IOMMU_GROUP);
+ PCI_FILL_PHYS_SLOT | PCI_FILL_NUMA_NODE | PCI_FILL_DT_NODE | PCI_FILL_IOMMU_GROUP |
+ PCI_FILL_BRIDGE_BASES);
irq = p->irq;
switch (htype)
--
2.20.1
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 ` [PATCH pciutils 3/4] libpci: Add support for filling bridge resources Pali Rohár
2021-12-26 22:13 ` 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 ` Pali Rohár [this message]
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-4-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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).