aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBjoern A. Zeeb <bz@FreeBSD.org>2021-01-28 16:23:19 +0000
committerBjoern A. Zeeb <bz@FreeBSD.org>2021-01-28 16:23:19 +0000
commit1fac2cb4d6e5cfa1b8ff689213011b0fe077ffa7 (patch)
tree5502183de7d1eb177f208223a8289db382827370
parent4abbf816bf06aa70200c5d1d976dd61c2752bdaf (diff)
downloadsrc-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
-rw-r--r--sys/compat/linuxkpi/common/include/linux/pci.h10
-rw-r--r--sys/compat/linuxkpi/common/src/linux_pci.c42
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;