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);
_______________________________________________
svn-src-head@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to