Index: sys/compat/linuxkpi/common/include/linux/pci.h =================================================================== --- sys/compat/linuxkpi/common/include/linux/pci.h +++ sys/compat/linuxkpi/common/include/linux/pci.h @@ -187,6 +187,12 @@ devclass_t bsdclass; struct device_driver driver; const struct pci_error_handlers *err_handler; + bool isdrm; +}; + +struct pci_bus { + struct pci_dev *self; + int number; }; extern struct list_head pci_drivers; @@ -199,6 +205,7 @@ struct device dev; struct list_head links; struct pci_driver *pdrv; + struct pci_bus *bus; uint64_t dma_mask; uint16_t device; uint16_t vendor; @@ -502,8 +509,12 @@ return (0); } -extern int pci_register_driver(struct pci_driver *pdrv); -extern void pci_unregister_driver(struct pci_driver *pdrv); +int linux_pci_register_driver(struct pci_driver *pdrv); +int linux_pci_register_drm_driver(struct pci_driver *pdrv); +void linux_pci_unregister_driver(struct pci_driver *pdrv); + +#define pci_register_driver(pdrv) linux_pci_register_driver(pdrv) +#define pci_unregister_driver(pdrv) linux_pci_unregister_driver(pdrv) struct msix_entry { int entry; Index: sys/compat/linuxkpi/common/src/linux_pci.c =================================================================== --- sys/compat/linuxkpi/common/src/linux_pci.c +++ sys/compat/linuxkpi/common/src/linux_pci.c @@ -118,17 +118,27 @@ linux_pci_attach(device_t dev) { struct resource_list_entry *rle; + struct pci_bus *pbus; struct pci_dev *pdev; struct pci_devinfo *dinfo; struct pci_driver *pdrv; const struct pci_device_id *id; + device_t parent; + devclass_t devclass; int error; - dinfo = device_get_ivars(dev); - linux_set_current(curthread); + pdrv = linux_pci_find(dev, &id); pdev = device_get_softc(dev); + + parent = device_get_parent(dev); + devclass = device_get_devclass(parent); + if (pdrv->isdrm) + device_set_ivars(dev, device_get_ivars(parent)); + + dinfo = device_get_ivars(dev); + pdev->dev.parent = &linux_root_device; pdev->dev.bsddev = dev; INIT_LIST_HEAD(&pdev->dev.irqents); @@ -151,6 +161,13 @@ else pdev->dev.irq = LINUX_IRQ_INVALID; pdev->irq = pdev->dev.irq; + + if (pdev->bus == NULL) { + pbus = malloc(sizeof(*pbus), M_DEVBUF, M_WAITOK | M_ZERO); + pbus->self = pdev; + pdev->bus = pbus; + } + DROP_GIANT(); spin_lock(&pci_lock); list_add(&pdev->links, &pci_devices); @@ -246,13 +263,10 @@ return (0); } -int -pci_register_driver(struct pci_driver *pdrv) +static int +_linux_pci_register_driver(struct pci_driver *pdrv, devclass_t dc) { - devclass_t bus; - int error = 0; - - bus = devclass_find("pci"); + int error; linux_set_current(curthread); spin_lock(&pci_lock); @@ -263,16 +277,37 @@ pdrv->bsddriver.size = sizeof(struct pci_dev); mtx_lock(&Giant); - if (bus != NULL) { - error = devclass_add_driver(bus, &pdrv->bsddriver, - BUS_PASS_DEFAULT, &pdrv->bsdclass); - } + error = devclass_add_driver(dc, &pdrv->bsddriver, + BUS_PASS_DEFAULT, &pdrv->bsdclass); mtx_unlock(&Giant); return (-error); } +int +linux_pci_register_driver(struct pci_driver *pdrv) +{ + devclass_t dc; + + dc = devclass_find("pci"); + pdrv->isdrm = false; + return (_linux_pci_register_driver(pdrv, dc)); +} + +int +linux_pci_register_drm_driver(struct pci_driver *pdrv) +{ + static devclass_t drm_devclass; + devclass_t dc; + + dc = devclass_create("vgapci"); + pdrv->bsdclass = drm_devclass; + pdrv->isdrm = true; + pdrv->name = "drmn"; + return (_linux_pci_register_driver(pdrv, dc)); +} + void -pci_unregister_driver(struct pci_driver *pdrv) +linux_pci_unregister_driver(struct pci_driver *pdrv) { devclass_t bus;