File pciutils-3.5.1-add-support-for-32-bit-pci-domains.patch of Package pciutils.8028
@@ -, +, @@
---
lib/access.c | 11 +++++++++++
lib/filter.c | 2 +-
lib/init.c | 7 ++++++-
lib/internal.h | 3 +++
lib/pci.h | 3 ++-
lib/sysfs.c | 7 ++++++-
ls-tree.c | 2 +-
7 files changed, 30 insertions(+), 5 deletions(-)
--- a/lib/access.c
+++ a/lib/access.c
@@ -39,6 +39,17 @@ pci_link_dev(struct pci_access *a, struct pci_dev *d)
d->next = a->devices;
a->devices = d;
+ /*
+ * Applications compiled with older versions of libpci do not expect
+ * 32-bit domain numbers. To keep them working, we keep a 16-bit
+ * version of the domain number at the previous location in struct
+ * pci_dev. This will keep backward compatibility on systems which
+ * don't require large domain numbers.
+ */
+ if (d->domain > 0xffff)
+ d->domain_16 = 0xffff;
+ else
+ d->domain_16 = d->domain;
return 1;
}
--- a/lib/filter.c
+++ a/lib/filter.c
@@ -40,7 +40,7 @@ pci_filter_parse_slot(struct pci_filter *f, char *str)
if (str[0] && strcmp(str, "*"))
{
long int x = strtol(str, &e, 16);
- if ((e && *e) || (x < 0 || x > 0xffff))
+ if ((e && *e) || (x < 0 || x > 0x7fffffff))
return "Invalid domain number";
f->domain = x;
}
--- a/lib/init.c
+++ a/lib/init.c
@@ -165,7 +165,7 @@ pci_alloc(void)
}
void
-pci_init(struct pci_access *a)
+pci_init_v32(struct pci_access *a)
{
if (!a->error)
a->error = pci_generic_error;
@@ -205,6 +205,11 @@ pci_init(struct pci_access *a)
a->methods->init(a);
}
+STATIC_ALIAS(void pci_init(struct pci_access *a), pci_init_v32(a));
+DEFINE_ALIAS(void pci_init_v30(struct pci_access *a), pci_init_v32);
+SYMBOL_VERSION(pci_init_v30, pci_init@LIBPCI_3.0);
+SYMBOL_VERSION(pci_init_v32, pci_init@@LIBPCI_3.2);
+
void
pci_cleanup(struct pci_access *a)
{
--- a/lib/internal.h
+++ a/lib/internal.h
@@ -50,6 +50,9 @@ void *pci_malloc(struct pci_access *, int);
void pci_mfree(void *);
char *pci_strdup(struct pci_access *a, char *s);
+void pci_init_v30(struct pci_access *a) PCI_ABI;
+void pci_init_v32(struct pci_access *a) PCI_ABI;
+
/* access.c */
struct pci_dev *pci_alloc_dev(struct pci_access *);
int pci_link_dev(struct pci_access *, struct pci_dev *);
--- a/lib/pci.h
+++ a/lib/pci.h
@@ -116,7 +116,7 @@ struct pci_param *pci_walk_params(struct pci_access *acc, struct pci_param *prev
struct pci_dev {
struct pci_dev *next; /* Next device in the chain */
- u16 domain; /* PCI domain (host bridge) */
+ u16 domain_16; /* 16-bit PCI domain (host bridge) */
u8 bus, dev, func; /* Bus inside domain, device and function */
/* These fields are set by pci_fill_info() */
@@ -131,6 +131,7 @@ struct pci_dev {
struct pci_cap *first_cap; /* List of capabilities */
char *phy_slot; /* Physical slot */
char *module_alias; /* Linux kernel module alias */
+ int domain; /* 32-bit PCI domain (host bridge) */
/* Fields used internally: */
struct pci_access *access;
--- a/lib/sysfs.c
+++ a/lib/sysfs.c
@@ -184,6 +184,11 @@ static void sysfs_scan(struct pci_access *a)
d = pci_alloc_dev(a);
if (sscanf(entry->d_name, "%x:%x:%x.%d", &dom, &bus, &dev, &func) < 4)
a->error("sysfs_scan: Couldn't parse entry name %s", entry->d_name);
+
+ /* Ensure kernel provided domain that fits in a signed integer */
+ if (dom > 0x7fffffff)
+ a->error("sysfs_scan: invalid domain:%x", dom);
+
d->domain = dom;
d->bus = bus;
d->dev = dev;
@@ -258,7 +263,7 @@ sysfs_fill_slots(struct pci_access *a)
else
{
for (d = a->devices; d; d = d->next)
- if (dom == d->domain && bus == d->bus && dev == d->dev && !d->phy_slot)
+ if (dom == (unsigned)d->domain && bus == d->bus && dev == d->dev && !d->phy_slot)
d->phy_slot = pci_strdup(a, entry->d_name);
}
fclose(file);
--- a/ls-tree.c
+++ a/ls-tree.c
@@ -63,7 +63,7 @@ insert_dev(struct device *d, struct bridge *b)
{
struct bridge *c;
for (c=b->child; c; c=c->next)
- if (c->domain == p->domain && c->secondary <= p->bus && p->bus <= c->subordinate)
+ if (c->domain == (unsigned)p->domain && c->secondary <= p->bus && p->bus <= c->subordinate)
{
insert_dev(d, c);
return;
--