Page MenuHomeFreeBSD

D34305.id104069.diff
No OneTemporary

D34305.id104069.diff

diff --git a/sys/compat/linuxkpi/common/include/linux/pci.h b/sys/compat/linuxkpi/common/include/linux/pci.h
--- a/sys/compat/linuxkpi/common/include/linux/pci.h
+++ b/sys/compat/linuxkpi/common/include/linux/pci.h
@@ -478,6 +478,48 @@
return (0);
}
+static inline bool
+pci_is_root_bus(struct pci_bus *pbus)
+{
+
+ return (pbus->self == NULL);
+}
+
+static inline struct pci_dev *
+pci_upstream_bridge(struct pci_dev *pdev)
+{
+
+ if (pci_is_root_bus(pdev->bus))
+ return (NULL);
+
+ /*
+ * If we do not have a (proper) "upstream bridge" set, e.g., we point
+ * to ourselves, try to handle this case on the fly like we do
+ * for pcie_find_root_port().
+ */
+ if (pdev == pdev->bus->self) {
+ device_t bridge;
+
+ bridge = device_get_parent(pdev->dev.bsddev);
+ if (bridge == NULL)
+ goto done;
+ bridge = device_get_parent(bridge);
+ if (bridge == NULL)
+ goto done;
+ if (device_get_devclass(device_get_parent(bridge)) !=
+ devclass_find("pci"))
+ goto done;
+
+ /*
+ * "bridge" is a PCI-to-PCI bridge. Create a Linux pci_dev
+ * for it so it can be returned.
+ */
+ pdev->bus->self = lkpinew_pci_dev(bridge);
+ }
+done:
+ return (pdev->bus->self);
+}
+
static inline struct pci_devres *
lkpi_pci_devres_get_alloc(struct pci_dev *pdev)
{
@@ -1399,13 +1441,6 @@
return (0);
}
-static inline bool
-pci_is_root_bus(struct pci_bus *pbus)
-{
-
- return (pbus->self == NULL);
-}
-
struct pci_dev *lkpi_pci_get_domain_bus_and_slot(int domain,
unsigned int bus, unsigned int devfn);
#define pci_get_domain_bus_and_slot(domain, bus, devfn) \
diff --git a/sys/compat/linuxkpi/common/src/linux_pci.c b/sys/compat/linuxkpi/common/src/linux_pci.c
--- a/sys/compat/linuxkpi/common/src/linux_pci.c
+++ b/sys/compat/linuxkpi/common/src/linux_pci.c
@@ -278,6 +278,11 @@
pdev->class = pci_get_class(dev);
pdev->revision = pci_get_revid(dev);
pdev->bus = malloc(sizeof(*pdev->bus), M_DEVBUF, M_WAITOK | M_ZERO);
+ /*
+ * This should be the upstream bridge; pci_upstream_bridge()
+ * handles that case on demand as otherwise we'll shadow the
+ * entire PCI hierarchy.
+ */
pdev->bus->self = pdev;
pdev->bus->number = pci_get_bus(dev);
pdev->bus->domain = pci_get_domain(dev);
@@ -301,6 +306,8 @@
pdev = to_pci_dev(dev);
if (pdev->root != NULL)
pci_dev_put(pdev->root);
+ if (pdev->bus->self != pdev)
+ pci_dev_put(pdev->bus->self);
free(pdev->bus, M_DEVBUF);
free(pdev, M_DEVBUF);
}

File Metadata

Mime Type
text/plain
Expires
Sun, Dec 21, 11:37 AM (3 h, 26 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
27112389
Default Alt Text
D34305.id104069.diff (2 KB)

Event Timeline