svn commit: r322392 - in head/sys/compat/linuxkpi/common: include/linux src
Mark Johnston
markj at FreeBSD.org
Fri Aug 11 03:59:50 UTC 2017
Author: markj
Date: Fri Aug 11 03:59:48 2017
New Revision: 322392
URL: https://svnweb.freebsd.org/changeset/base/322392
Log:
Add a specialized function for DRM drivers to register themselves.
Such drivers attach to a vgapci bus rather than directly to a pci bus. For
the rest of the LinuxKPI to work correctly in this case, we override the
vgapci bus' ivars with those of the grandparent.
Reviewed by: hselasky
MFC after: 1 week
Differential Revision: https://reviews.freebsd.org/D11932
Modified:
head/sys/compat/linuxkpi/common/include/linux/pci.h
head/sys/compat/linuxkpi/common/src/linux_pci.c
Modified: head/sys/compat/linuxkpi/common/include/linux/pci.h
==============================================================================
--- head/sys/compat/linuxkpi/common/include/linux/pci.h Fri Aug 11 03:09:11 2017 (r322391)
+++ head/sys/compat/linuxkpi/common/include/linux/pci.h Fri Aug 11 03:59:48 2017 (r322392)
@@ -187,8 +187,14 @@ struct pci_driver {
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;
extern struct list_head pci_devices;
extern spinlock_t pci_lock;
@@ -199,6 +205,7 @@ struct pci_dev {
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 @@ pci_write_config_dword(struct pci_dev *pdev, int where
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;
Modified: head/sys/compat/linuxkpi/common/src/linux_pci.c
==============================================================================
--- head/sys/compat/linuxkpi/common/src/linux_pci.c Fri Aug 11 03:09:11 2017 (r322391)
+++ head/sys/compat/linuxkpi/common/src/linux_pci.c Fri Aug 11 03:59:48 2017 (r322392)
@@ -118,17 +118,29 @@ static int
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) {
+ dinfo = device_get_ivars(parent);
+ device_set_ivars(dev, dinfo);
+ } else {
+ dinfo = device_get_ivars(dev);
+ }
+
pdev->dev.parent = &linux_root_device;
pdev->dev.bsddev = dev;
INIT_LIST_HEAD(&pdev->dev.irqents);
@@ -151,6 +163,13 @@ linux_pci_attach(device_t dev)
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,14 +265,11 @@ linux_pci_shutdown(device_t dev)
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;
+ int error;
- bus = devclass_find("pci");
-
linux_set_current(curthread);
spin_lock(&pci_lock);
list_add(&pdrv->links, &pci_drivers);
@@ -263,16 +279,39 @@ pci_register_driver(struct pci_driver *pdrv)
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");
+ if (dc == NULL)
+ return (-ENXIO);
+ pdrv->isdrm = false;
+ return (_linux_pci_register_driver(pdrv, dc));
+}
+
+int
+linux_pci_register_drm_driver(struct pci_driver *pdrv)
+{
+ devclass_t dc;
+
+ dc = devclass_create("vgapci");
+ if (dc == NULL)
+ return (-ENXIO);
+ 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;
More information about the svn-src-all
mailing list