Skip to content

Commit

Permalink
usb: hcd: use managed device resources
Browse files Browse the repository at this point in the history
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: fa31b3c ("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>
  • Loading branch information
Schmid, Carsten authored and gregkh committed Aug 28, 2019
1 parent a684d8f commit 76da906
Showing 1 changed file with 8 additions and 22 deletions.
30 changes: 8 additions & 22 deletions drivers/usb/core/hcd-pci.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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) {
Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -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);
}
Expand Down

0 comments on commit 76da906

Please sign in to comment.