svn commit: r360196 - in head/sys/compat/linuxkpi/common: include/linux src
Hans Petter Selasky
hselasky at FreeBSD.org
Wed Apr 22 14:33:26 UTC 2020
Author: hselasky
Date: Wed Apr 22 14:33:25 2020
New Revision: 360196
URL: https://svnweb.freebsd.org/changeset/base/360196
Log:
Factor code in LinuxKPI to allow attach and detach using any BSD device.
This allows non-LinuxKPI based infiniband device drivers to attach
correctly to ibcore.
No functional change intended.
Reviewed by: np @
Differential Revision: https://reviews.freebsd.org/D24514
MFC after: 1 week
Sponsored by: Mellanox Technologies
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 Wed Apr 22 13:53:22 2020 (r360195)
+++ head/sys/compat/linuxkpi/common/include/linux/pci.h Wed Apr 22 14:33:25 2020 (r360196)
@@ -954,4 +954,15 @@ pcie_get_width_cap(struct pci_dev *dev)
return (PCIE_LNK_WIDTH_UNKNOWN);
}
+/*
+ * The following functions can be used to attach/detach the LinuxKPI's
+ * PCI device runtime. The pci_driver and pci_device_id pointer is
+ * allowed to be NULL. Other pointers must be all valid.
+ * The pci_dev structure should be zero-initialized before passed
+ * to the linux_pci_attach_device function.
+ */
+extern int linux_pci_attach_device(device_t, struct pci_driver *,
+ const struct pci_device_id *, struct pci_dev *);
+extern int linux_pci_detach_device(struct pci_dev *);
+
#endif /* _LINUX_PCI_H_ */
Modified: head/sys/compat/linuxkpi/common/src/linux_pci.c
==============================================================================
--- head/sys/compat/linuxkpi/common/src/linux_pci.c Wed Apr 22 13:53:22 2020 (r360195)
+++ head/sys/compat/linuxkpi/common/src/linux_pci.c Wed Apr 22 14:33:25 2020 (r360196)
@@ -213,22 +213,33 @@ linux_pci_probe(device_t dev)
static int
linux_pci_attach(device_t dev)
{
+ const struct pci_device_id *id;
+ struct pci_driver *pdrv;
+ struct pci_dev *pdev;
+
+ pdrv = linux_pci_find(dev, &id);
+ pdev = device_get_softc(dev);
+
+ MPASS(pdrv != NULL);
+ MPASS(pdev != NULL);
+
+ return (linux_pci_attach_device(dev, pdrv, id, pdev));
+}
+
+int
+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_bus *pbus;
- struct pci_dev *pdev;
struct pci_devinfo *dinfo;
- struct pci_driver *pdrv;
- const struct pci_device_id *id;
device_t parent;
int error;
linux_set_current(curthread);
- pdrv = linux_pci_find(dev, &id);
- pdev = device_get_softc(dev);
-
- parent = device_get_parent(dev);
- if (pdrv->isdrm) {
+ if (pdrv != NULL && pdrv->isdrm) {
+ parent = device_get_parent(dev);
dinfo = device_get_ivars(parent);
device_set_ivars(dev, dinfo);
} else {
@@ -270,9 +281,11 @@ linux_pci_attach(device_t dev)
list_add(&pdev->links, &pci_devices);
spin_unlock(&pci_lock);
- error = pdrv->probe(pdev, id);
- if (error)
- goto out_probe;
+ if (pdrv != NULL) {
+ error = pdrv->probe(pdev, id);
+ if (error)
+ goto out_probe;
+ }
return (0);
out_probe:
@@ -291,18 +304,30 @@ linux_pci_detach(device_t dev)
{
struct pci_dev *pdev;
- linux_set_current(curthread);
pdev = device_get_softc(dev);
- pdev->pdrv->remove(pdev);
+ MPASS(pdev != NULL);
+ device_set_desc(dev, NULL);
+
+ return (linux_pci_detach_device(pdev));
+}
+
+int
+linux_pci_detach_device(struct pci_dev *pdev)
+{
+
+ linux_set_current(curthread);
+
+ if (pdev->pdrv != NULL)
+ pdev->pdrv->remove(pdev);
+
free(pdev->bus, M_DEVBUF);
linux_pdev_dma_uninit(pdev);
spin_lock(&pci_lock);
list_del(&pdev->links);
spin_unlock(&pci_lock);
- device_set_desc(dev, NULL);
put_device(&pdev->dev);
return (0);
More information about the svn-src-head
mailing list