Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F140117713
D34305.id104069.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
2 KB
Referenced Files
None
Subscribers
None
D34305.id104069.diff
View Options
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
Details
Attached
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)
Attached To
Mode
D34305: LinuxKPI: pci: implement pci_upstream_bridge()
Attached
Detach File
Event Timeline
Log In to Comment