diff options
author | Bjoern A. Zeeb <bz@FreeBSD.org> | 2021-01-28 16:23:19 +0000 |
---|---|---|
committer | Bjoern A. Zeeb <bz@FreeBSD.org> | 2021-01-28 16:23:19 +0000 |
commit | 1fac2cb4d6e5cfa1b8ff689213011b0fe077ffa7 (patch) | |
tree | 5502183de7d1eb177f208223a8289db382827370 /sys/compat/linuxkpi/common | |
parent | 4abbf816bf06aa70200c5d1d976dd61c2752bdaf (diff) | |
download | src-1fac2cb4d6e5cfa1b8ff689213011b0fe077ffa7.tar.gz src-1fac2cb4d6e5cfa1b8ff689213011b0fe077ffa7.zip |
LinuxKPI: enhance PCI bits for DRM
In pci_domain_nr() directly return the domain which got set in
lkpifill_pci_dev() in all cases. This was missed between D27550
and 105a37cac76b971f7a94409fbdc4f508a7e97fa0 .
In order to implement pci_dev_put() harmonize further code
(which was started in the aforementioned commit) and add kobj
related bits (through the now common lkpifill_pci_dev() code)
to the DRM specific calls without adding the DRM allocated
pci devices to the pci_devices list.
Add a release for the lkpinew_pci_dev() (DRM) case so freeing
will work.
This allows the DRM created devices to use the normal kobj/refcount
logic and work with, e.g., pci_dev_put().
(For a slightly more detailed code walk see the review).
Sponsored-by: The FreeBSD Foundation
Obtained-from: bz_iwlwifi (partially)
MFC after: 3 days
Differential Revision: https://reviews.freebsd.org/D28188
Diffstat (limited to 'sys/compat/linuxkpi/common')
-rw-r--r-- | sys/compat/linuxkpi/common/include/linux/pci.h | 10 | ||||
-rw-r--r-- | sys/compat/linuxkpi/common/src/linux_pci.c | 42 |
2 files changed, 33 insertions, 19 deletions
diff --git a/sys/compat/linuxkpi/common/include/linux/pci.h b/sys/compat/linuxkpi/common/include/linux/pci.h index 6338f5795f0a..ddb3f0b222a5 100644 --- a/sys/compat/linuxkpi/common/include/linux/pci.h +++ b/sys/compat/linuxkpi/common/include/linux/pci.h @@ -338,6 +338,14 @@ pci_set_drvdata(struct pci_dev *pdev, void *data) dev_set_drvdata(&pdev->dev, data); } +static __inline void +pci_dev_put(struct pci_dev *pdev) +{ + + if (pdev != NULL) + put_device(&pdev->dev); +} + static inline int pci_enable_device(struct pci_dev *pdev) { @@ -1094,7 +1102,7 @@ static inline int pci_domain_nr(struct pci_bus *pbus) { - return (pci_get_domain(pbus->self->dev.bsddev)); + return (pbus->domain); } static inline int diff --git a/sys/compat/linuxkpi/common/src/linux_pci.c b/sys/compat/linuxkpi/common/src/linux_pci.c index 0e184b64884b..075df3c2adf7 100644 --- a/sys/compat/linuxkpi/common/src/linux_pci.c +++ b/sys/compat/linuxkpi/common/src/linux_pci.c @@ -220,24 +220,42 @@ lkpifill_pci_dev(device_t dev, struct pci_dev *pdev) pdev->devfn = PCI_DEVFN(pci_get_slot(dev), pci_get_function(dev)); pdev->vendor = pci_get_vendor(dev); pdev->device = pci_get_device(dev); + pdev->subsystem_vendor = pci_get_subvendor(dev); + pdev->subsystem_device = pci_get_subdevice(dev); pdev->class = pci_get_class(dev); pdev->revision = pci_get_revid(dev); - pdev->dev.bsddev = dev; + pdev->bus = malloc(sizeof(*pdev->bus), M_DEVBUF, M_WAITOK | M_ZERO); pdev->bus->self = pdev; pdev->bus->number = pci_get_bus(dev); pdev->bus->domain = pci_get_domain(dev); + pdev->dev.bsddev = dev; + pdev->dev.parent = &linux_root_device; + INIT_LIST_HEAD(&pdev->dev.irqents); + kobject_init(&pdev->dev.kobj, &linux_dev_ktype); + kobject_set_name(&pdev->dev.kobj, device_get_nameunit(dev)); + kobject_add(&pdev->dev.kobj, &linux_root_device.kobj, + kobject_name(&pdev->dev.kobj)); +} + +static void +lkpinew_pci_dev_release(struct device *dev) +{ + struct pci_dev *pdev; + + pdev = to_pci_dev(dev); + free(pdev->bus, M_DEVBUF); + free(pdev, M_DEVBUF); } static struct pci_dev * lkpinew_pci_dev(device_t dev) { struct pci_dev *pdev; - struct pci_bus *pbus; pdev = malloc(sizeof(*pdev), M_DEVBUF, M_WAITOK|M_ZERO); - pbus = malloc(sizeof(*pbus), M_DEVBUF, M_WAITOK|M_ZERO); - pdev->bus = pbus; lkpifill_pci_dev(dev, pdev); + pdev->dev.release = lkpinew_pci_dev_release; + return (pdev); } @@ -309,7 +327,6 @@ linux_pci_attach_device(device_t dev, struct pci_driver *pdrv, const struct pci_device_id *id, struct pci_dev *pdev) { struct resource_list_entry *rle; - struct pci_devinfo *dinfo; device_t parent; uintptr_t rid; int error; @@ -321,30 +338,19 @@ linux_pci_attach_device(device_t dev, struct pci_driver *pdrv, isdrm = pdrv != NULL && pdrv->isdrm; if (isdrm) { + struct pci_devinfo *dinfo; + dinfo = device_get_ivars(parent); device_set_ivars(dev, dinfo); - } else { - dinfo = device_get_ivars(dev); } - pdev->bus = malloc(sizeof(*pdev->bus), M_DEVBUF, M_WAITOK | M_ZERO); lkpifill_pci_dev(dev, pdev); - pdev->dev.parent = &linux_root_device; - INIT_LIST_HEAD(&pdev->dev.irqents); if (isdrm) PCI_GET_ID(device_get_parent(parent), parent, PCI_ID_RID, &rid); else PCI_GET_ID(parent, dev, PCI_ID_RID, &rid); pdev->devfn = rid; - pdev->device = dinfo->cfg.device; - pdev->vendor = dinfo->cfg.vendor; - pdev->subsystem_vendor = dinfo->cfg.subvendor; - pdev->subsystem_device = dinfo->cfg.subdevice; pdev->pdrv = pdrv; - kobject_init(&pdev->dev.kobj, &linux_dev_ktype); - kobject_set_name(&pdev->dev.kobj, device_get_nameunit(dev)); - kobject_add(&pdev->dev.kobj, &linux_root_device.kobj, - kobject_name(&pdev->dev.kobj)); rle = linux_pci_get_rle(pdev, SYS_RES_IRQ, 0); if (rle != NULL) pdev->dev.irq = rle->start; |