Skip to content

Commit

Permalink
Merge tag 'fixes-for-v4.6-rc5' of git://git.kernel.org/pub/scm/linux/…
Browse files Browse the repository at this point in the history
…kernel/git/balbi/usb into usb-linus

Felipe writes:

usb: fixes for v4.6-rc5

No more major fixes left. Out of the 6 fixes we have
here, 4 are on dwc3.

The most important is the memory leak fix in
dwc3/debugfs.c. We also have a fix for PHY handling
in suspend/resume and a fix for dwc3-omap's error
handling.

Suspend/resume also had the potential to trigger a
NULL pointer dereference on dwc3; that's also fixed
now.

Our good ol' ffs function gets a use-after-free fix
while the generic composite.c layer has a robustness
fix by making sure reserved fields of a possible SSP
device capability descriptor is cleared to 0.
  • Loading branch information
Greg Kroah-Hartman committed Apr 22, 2016
2 parents c3b46c7 + 38740a5 commit 5813dea
Show file tree
Hide file tree
Showing 6 changed files with 44 additions and 17 deletions.
23 changes: 22 additions & 1 deletion drivers/usb/dwc3/core.c
Original file line number Diff line number Diff line change
Expand Up @@ -1150,6 +1150,11 @@ static int dwc3_suspend(struct device *dev)
phy_exit(dwc->usb2_generic_phy);
phy_exit(dwc->usb3_generic_phy);

usb_phy_set_suspend(dwc->usb2_phy, 1);
usb_phy_set_suspend(dwc->usb3_phy, 1);
WARN_ON(phy_power_off(dwc->usb2_generic_phy) < 0);
WARN_ON(phy_power_off(dwc->usb3_generic_phy) < 0);

pinctrl_pm_select_sleep_state(dev);

return 0;
Expand All @@ -1163,11 +1168,21 @@ static int dwc3_resume(struct device *dev)

pinctrl_pm_select_default_state(dev);

usb_phy_set_suspend(dwc->usb2_phy, 0);
usb_phy_set_suspend(dwc->usb3_phy, 0);
ret = phy_power_on(dwc->usb2_generic_phy);
if (ret < 0)
return ret;

ret = phy_power_on(dwc->usb3_generic_phy);
if (ret < 0)
goto err_usb2phy_power;

usb_phy_init(dwc->usb3_phy);
usb_phy_init(dwc->usb2_phy);
ret = phy_init(dwc->usb2_generic_phy);
if (ret < 0)
return ret;
goto err_usb3phy_power;

ret = phy_init(dwc->usb3_generic_phy);
if (ret < 0)
Expand Down Expand Up @@ -1200,6 +1215,12 @@ static int dwc3_resume(struct device *dev)
err_usb2phy_init:
phy_exit(dwc->usb2_generic_phy);

err_usb3phy_power:
phy_power_off(dwc->usb3_generic_phy);

err_usb2phy_power:
phy_power_off(dwc->usb2_generic_phy);

return ret;
}

Expand Down
13 changes: 8 additions & 5 deletions drivers/usb/dwc3/debugfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -645,15 +645,15 @@ int dwc3_debugfs_init(struct dwc3 *dwc)
file = debugfs_create_regset32("regdump", S_IRUGO, root, dwc->regset);
if (!file) {
ret = -ENOMEM;
goto err1;
goto err2;
}

if (IS_ENABLED(CONFIG_USB_DWC3_DUAL_ROLE)) {
file = debugfs_create_file("mode", S_IRUGO | S_IWUSR, root,
dwc, &dwc3_mode_fops);
if (!file) {
ret = -ENOMEM;
goto err1;
goto err2;
}
}

Expand All @@ -663,19 +663,22 @@ int dwc3_debugfs_init(struct dwc3 *dwc)
dwc, &dwc3_testmode_fops);
if (!file) {
ret = -ENOMEM;
goto err1;
goto err2;
}

file = debugfs_create_file("link_state", S_IRUGO | S_IWUSR, root,
dwc, &dwc3_link_state_fops);
if (!file) {
ret = -ENOMEM;
goto err1;
goto err2;
}
}

return 0;

err2:
kfree(dwc->regset);

err1:
debugfs_remove_recursive(root);

Expand All @@ -686,5 +689,5 @@ int dwc3_debugfs_init(struct dwc3 *dwc)
void dwc3_debugfs_exit(struct dwc3 *dwc)
{
debugfs_remove_recursive(dwc->root);
dwc->root = NULL;
kfree(dwc->regset);
}
12 changes: 4 additions & 8 deletions drivers/usb/dwc3/dwc3-omap.c
Original file line number Diff line number Diff line change
Expand Up @@ -496,7 +496,7 @@ static int dwc3_omap_probe(struct platform_device *pdev)
ret = pm_runtime_get_sync(dev);
if (ret < 0) {
dev_err(dev, "get_sync failed with err %d\n", ret);
goto err0;
goto err1;
}

dwc3_omap_map_offset(omap);
Expand All @@ -516,28 +516,24 @@ static int dwc3_omap_probe(struct platform_device *pdev)

ret = dwc3_omap_extcon_register(omap);
if (ret < 0)
goto err2;
goto err1;

ret = of_platform_populate(node, NULL, NULL, dev);
if (ret) {
dev_err(&pdev->dev, "failed to create dwc3 core\n");
goto err3;
goto err2;
}

dwc3_omap_enable_irqs(omap);

return 0;

err3:
err2:
extcon_unregister_notifier(omap->edev, EXTCON_USB, &omap->vbus_nb);
extcon_unregister_notifier(omap->edev, EXTCON_USB_HOST, &omap->id_nb);
err2:
dwc3_omap_disable_irqs(omap);

err1:
pm_runtime_put_sync(dev);

err0:
pm_runtime_disable(dev);

return ret;
Expand Down
6 changes: 6 additions & 0 deletions drivers/usb/dwc3/gadget.c
Original file line number Diff line number Diff line change
Expand Up @@ -2936,6 +2936,9 @@ void dwc3_gadget_exit(struct dwc3 *dwc)

int dwc3_gadget_suspend(struct dwc3 *dwc)
{
if (!dwc->gadget_driver)
return 0;

if (dwc->pullups_connected) {
dwc3_gadget_disable_irq(dwc);
dwc3_gadget_run_stop(dwc, true, true);
Expand All @@ -2954,6 +2957,9 @@ int dwc3_gadget_resume(struct dwc3 *dwc)
struct dwc3_ep *dep;
int ret;

if (!dwc->gadget_driver)
return 0;

/* Start with SuperSpeed Default */
dwc3_gadget_ep0_desc.wMaxPacketSize = cpu_to_le16(512);

Expand Down
2 changes: 2 additions & 0 deletions drivers/usb/gadget/composite.c
Original file line number Diff line number Diff line change
Expand Up @@ -651,6 +651,8 @@ static int bos_desc(struct usb_composite_dev *cdev)
ssp_cap->bLength = USB_DT_USB_SSP_CAP_SIZE(1);
ssp_cap->bDescriptorType = USB_DT_DEVICE_CAPABILITY;
ssp_cap->bDevCapabilityType = USB_SSP_CAP_TYPE;
ssp_cap->bReserved = 0;
ssp_cap->wReserved = 0;

/* SSAC = 1 (2 attributes) */
ssp_cap->bmAttributes = cpu_to_le32(1);
Expand Down
5 changes: 2 additions & 3 deletions drivers/usb/gadget/function/f_fs.c
Original file line number Diff line number Diff line change
Expand Up @@ -646,6 +646,7 @@ static void ffs_user_copy_worker(struct work_struct *work)
work);
int ret = io_data->req->status ? io_data->req->status :
io_data->req->actual;
bool kiocb_has_eventfd = io_data->kiocb->ki_flags & IOCB_EVENTFD;

if (io_data->read && ret > 0) {
use_mm(io_data->mm);
Expand All @@ -657,13 +658,11 @@ static void ffs_user_copy_worker(struct work_struct *work)

io_data->kiocb->ki_complete(io_data->kiocb, ret, ret);

if (io_data->ffs->ffs_eventfd &&
!(io_data->kiocb->ki_flags & IOCB_EVENTFD))
if (io_data->ffs->ffs_eventfd && !kiocb_has_eventfd)
eventfd_signal(io_data->ffs->ffs_eventfd, 1);

usb_ep_free_request(io_data->ep, io_data->req);

io_data->kiocb->private = NULL;
if (io_data->read)
kfree(io_data->to_free);
kfree(io_data->buf);
Expand Down

0 comments on commit 5813dea

Please sign in to comment.