usb: hcd: use managed device resources [Linux 4.19.70]

This Linux kernel change "usb: hcd: use managed device resources" is included in the Linux 4.19.70 release. This change is authored by Schmid, Carsten <Carsten_Schmid [at] mentor.com> on Fri Aug 23 14:11:28 2019 +0000. The commit for this change in Linux stable tree is 97bec7a (patch) which is from upstream commit 76da906. The same Linux upstream change may have been applied to various maintained Linux releases and you can find all Linux releases containing changes from upstream 76da906.

usb: hcd: use managed device resources

commit 76da906ad727048a74bb8067031ee99fc070c7da upstream.

Using managed device resources in usb_hcd_pci_probe() allows devm usage for
resource subranges, such as the mmio resource for the platform device
created to control host/device mode mux, which is a xhci extended
capability, and sits inside the xhci mmio region.

If managed device resources are not used then "parent" resource
is released before subrange at driver removal as .remove callback is
called before the devres list of resources for this device is walked
and released.

This has been observed with the xhci extended capability driver causing a
use-after-free which is now fixed.

An additional nice benefit is that error handling on driver initialisation
is simplified much.

Signed-off-by: Carsten Schmid <carsten_schmid@mentor.com>
Tested-by: Carsten Schmid <carsten_schmid@mentor.com>
Reviewed-by: Mathias Nyman <mathias.nyman@linux.intel.com>
Fixes: fa31b3cb2ae1 ("xhci: Add Intel extended cap / otg phy mux handling")
Cc: <stable@vger.kernel.org> # v4.19+
Link: https://lore.kernel.org/r/1566569488679.31808@mentor.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

There are 30 lines of Linux source code added/deleted in this change. Code changes to Linux kernel are as follows.

 drivers/usb/core/hcd-pci.c | 30 ++++++++----------------------
 1 file changed, 8 insertions(+), 22 deletions(-)

diff --git a/drivers/usb/core/hcd-pci.c b/drivers/usb/core/hcd-pci.c
index 0343246..7537681 100644
--- a/drivers/usb/core/hcd-pci.c
+++ b/drivers/usb/core/hcd-pci.c
@@ -216,17 +216,18 @@ int usb_hcd_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
        /* EHCI, OHCI */
        hcd->rsrc_start = pci_resource_start(dev, 0);
        hcd->rsrc_len = pci_resource_len(dev, 0);
-       if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len,
-               driver->description)) {
+       if (!devm_request_mem_region(&dev->dev, hcd->rsrc_start,
+               hcd->rsrc_len, driver->description)) {
            dev_dbg(&dev->dev, "controller already in use\n");
            retval = -EBUSY;
            goto put_hcd;
        }
-       hcd->regs = ioremap_nocache(hcd->rsrc_start, hcd->rsrc_len);
+       hcd->regs = devm_ioremap_nocache(&dev->dev, hcd->rsrc_start,
+               hcd->rsrc_len);
        if (hcd->regs == NULL) {
            dev_dbg(&dev->dev, "error mapping memory\n");
            retval = -EFAULT;
-           goto release_mem_region;
+           goto put_hcd;
        }

    } else {
@@ -240,8 +241,8 @@ int usb_hcd_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)

            hcd->rsrc_start = pci_resource_start(dev, region);
            hcd->rsrc_len = pci_resource_len(dev, region);
-           if (request_region(hcd->rsrc_start, hcd->rsrc_len,
-                   driver->description))
+           if (devm_request_region(&dev->dev, hcd->rsrc_start,
+                   hcd->rsrc_len, driver->description))
                break;
        }
        if (region == PCI_ROM_RESOURCE) {
@@ -275,20 +276,13 @@ int usb_hcd_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
    }

    if (retval != 0)
-       goto unmap_registers;
+       goto put_hcd;
    device_wakeup_enable(hcd->self.controller);

    if (pci_dev_run_wake(dev))
        pm_runtime_put_noidle(&dev->dev);
    return retval;

-unmap_registers:
-   if (driver->flags & HCD_MEMORY) {
-       iounmap(hcd->regs);
-release_mem_region:
-       release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
-   } else
-       release_region(hcd->rsrc_start, hcd->rsrc_len);
 put_hcd:
    usb_put_hcd(hcd);
 disable_pci:
@@ -347,14 +341,6 @@ void usb_hcd_pci_remove(struct pci_dev *dev)
        dev_set_drvdata(&dev->dev, NULL);
        up_read(&companions_rwsem);
    }
-
-   if (hcd->driver->flags & HCD_MEMORY) {
-       iounmap(hcd->regs);
-       release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
-   } else {
-       release_region(hcd->rsrc_start, hcd->rsrc_len);
-   }
-
    usb_put_hcd(hcd);
    pci_disable_device(dev);
 }

Leave a Reply

Your email address will not be published. Required fields are marked *