Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F144394317
D52069.id161631.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
D52069.id161631.diff
View Options
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
@@ -339,6 +339,7 @@
static int
lkpifill_pci_dev(device_t dev, struct pci_dev *pdev)
{
+ struct pci_devinfo *dinfo;
int error;
error = kobject_init_and_add(&pdev->dev.kobj, &linux_dev_ktype,
@@ -359,15 +360,24 @@
pdev->path_name = kasprintf(GFP_KERNEL, "%04d:%02d:%02d.%d",
pci_get_domain(dev), pci_get_bus(dev), pci_get_slot(dev),
pci_get_function(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);
+
+ /* Check if we have reached the root to satisfy pci_is_root_bus() */
+ dinfo = device_get_ivars(dev);
+ if (dinfo->cfg.pcie.pcie_location != 0 &&
+ dinfo->cfg.pcie.pcie_type == PCIEM_TYPE_ROOT_PORT) {
+ pdev->bus->self = NULL;
+ } else {
+ /*
+ * 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->dev.bsddev = dev;
pdev->dev.parent = &linux_root_device;
pdev->dev.release = lkpi_pci_dev_release;
@@ -392,7 +402,7 @@
pdev = to_pci_dev(dev);
if (pdev->root != NULL)
pci_dev_put(pdev->root);
- if (pdev->bus->self != pdev)
+ if (pdev->bus->self != pdev && pdev->bus->self != NULL)
pci_dev_put(pdev->bus->self);
free(pdev->bus, M_DEVBUF);
if (pdev->msi_desc != NULL) {
@@ -548,6 +558,7 @@
{
struct resource_list_entry *rle;
device_t parent;
+ struct pci_dev *pbus, *ppbus;
uintptr_t rid;
int error;
bool isdrm;
@@ -591,6 +602,27 @@
list_add(&pdev->links, &pci_devices);
spin_unlock(&pci_lock);
+ /*
+ * Create the hierarchy now as we cannot on demand later.
+ * Take special care of DRM as there is a non-PCI device in the chain.
+ */
+ pbus = pdev;
+ if (isdrm) {
+ pbus = lkpinew_pci_dev(parent);
+ if (pbus == NULL) {
+ error = ENXIO;
+ goto out_dma_init;
+ }
+ }
+ pcie_find_root_port(pbus);
+ if (isdrm)
+ pdev->root = pbus->root;
+ ppbus = pci_upstream_bridge(pbus);
+ while (ppbus != NULL && ppbus != pbus) {
+ pbus = ppbus;
+ ppbus = pci_upstream_bridge(pbus);
+ }
+
if (pdrv != NULL) {
error = pdrv->probe(pdev, id);
if (error)
@@ -598,6 +630,7 @@
}
return (0);
+/* XXX the cleanup does not match the allocation up there. */
out_probe:
free(pdev->bus, M_DEVBUF);
spin_lock_destroy(&pdev->pcie_cap_lock);
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Mon, Feb 9, 5:24 AM (17 m, 32 s)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
28542522
Default Alt Text
D52069.id161631.diff (2 KB)
Attached To
Mode
D52069: LinuxKPI: pci: allocate entire pci_dev hiereachy up to root port on attach
Attached
Detach File
Event Timeline
Log In to Comment