aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/core/hcd-pci.c
diff options
context:
space:
mode:
authorSchmid, Carsten <Carsten_Schmid@mentor.com>2019-08-23 10:11:28 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2019-08-28 16:48:37 -0400
commit76da906ad727048a74bb8067031ee99fc070c7da (patch)
treec61e24615835399d53a00ca60039f34c97a6c6df /drivers/usb/core/hcd-pci.c
parenta684d8fd87182090ee96e34519ecdf009cef093a (diff)
usb: hcd: use managed device resources
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>
Diffstat (limited to 'drivers/usb/core/hcd-pci.c')
-rw-r--r--drivers/usb/core/hcd-pci.c30
1 files changed, 8 insertions, 22 deletions
diff --git a/drivers/usb/core/hcd-pci.c b/drivers/usb/core/hcd-pci.c
index 03432467b05f..7537681355f6 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)
216 /* EHCI, OHCI */ 216 /* EHCI, OHCI */
217 hcd->rsrc_start = pci_resource_start(dev, 0); 217 hcd->rsrc_start = pci_resource_start(dev, 0);
218 hcd->rsrc_len = pci_resource_len(dev, 0); 218 hcd->rsrc_len = pci_resource_len(dev, 0);
219 if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, 219 if (!devm_request_mem_region(&dev->dev, hcd->rsrc_start,
220 driver->description)) { 220 hcd->rsrc_len, driver->description)) {
221 dev_dbg(&dev->dev, "controller already in use\n"); 221 dev_dbg(&dev->dev, "controller already in use\n");
222 retval = -EBUSY; 222 retval = -EBUSY;
223 goto put_hcd; 223 goto put_hcd;
224 } 224 }
225 hcd->regs = ioremap_nocache(hcd->rsrc_start, hcd->rsrc_len); 225 hcd->regs = devm_ioremap_nocache(&dev->dev, hcd->rsrc_start,
226 hcd->rsrc_len);
226 if (hcd->regs == NULL) { 227 if (hcd->regs == NULL) {
227 dev_dbg(&dev->dev, "error mapping memory\n"); 228 dev_dbg(&dev->dev, "error mapping memory\n");
228 retval = -EFAULT; 229 retval = -EFAULT;
229 goto release_mem_region; 230 goto put_hcd;
230 } 231 }
231 232
232 } else { 233 } else {
@@ -240,8 +241,8 @@ int usb_hcd_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
240 241
241 hcd->rsrc_start = pci_resource_start(dev, region); 242 hcd->rsrc_start = pci_resource_start(dev, region);
242 hcd->rsrc_len = pci_resource_len(dev, region); 243 hcd->rsrc_len = pci_resource_len(dev, region);
243 if (request_region(hcd->rsrc_start, hcd->rsrc_len, 244 if (devm_request_region(&dev->dev, hcd->rsrc_start,
244 driver->description)) 245 hcd->rsrc_len, driver->description))
245 break; 246 break;
246 } 247 }
247 if (region == PCI_ROM_RESOURCE) { 248 if (region == PCI_ROM_RESOURCE) {
@@ -275,20 +276,13 @@ int usb_hcd_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
275 } 276 }
276 277
277 if (retval != 0) 278 if (retval != 0)
278 goto unmap_registers; 279 goto put_hcd;
279 device_wakeup_enable(hcd->self.controller); 280 device_wakeup_enable(hcd->self.controller);
280 281
281 if (pci_dev_run_wake(dev)) 282 if (pci_dev_run_wake(dev))
282 pm_runtime_put_noidle(&dev->dev); 283 pm_runtime_put_noidle(&dev->dev);
283 return retval; 284 return retval;
284 285
285unmap_registers:
286 if (driver->flags & HCD_MEMORY) {
287 iounmap(hcd->regs);
288release_mem_region:
289 release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
290 } else
291 release_region(hcd->rsrc_start, hcd->rsrc_len);
292put_hcd: 286put_hcd:
293 usb_put_hcd(hcd); 287 usb_put_hcd(hcd);
294disable_pci: 288disable_pci:
@@ -347,14 +341,6 @@ void usb_hcd_pci_remove(struct pci_dev *dev)
347 dev_set_drvdata(&dev->dev, NULL); 341 dev_set_drvdata(&dev->dev, NULL);
348 up_read(&companions_rwsem); 342 up_read(&companions_rwsem);
349 } 343 }
350
351 if (hcd->driver->flags & HCD_MEMORY) {
352 iounmap(hcd->regs);
353 release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
354 } else {
355 release_region(hcd->rsrc_start, hcd->rsrc_len);
356 }
357
358 usb_put_hcd(hcd); 344 usb_put_hcd(hcd);
359 pci_disable_device(dev); 345 pci_disable_device(dev);
360} 346}