diff options
author | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2016-04-22 04:09:05 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2016-04-22 04:09:05 -0400 |
commit | 5813dea9f33fff0420eab6b5892e5698094f838f (patch) | |
tree | 3846402f09e425009ae20f6f0f58be4227291cab | |
parent | c3b46c73264b03000d1e18b22f5caf63332547c9 (diff) | |
parent | 38740a5b87d53ceb89eb2c970150f6e94e00373a (diff) |
Merge tag 'fixes-for-v4.6-rc5' of git://git.kernel.org/pub/scm/linux/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.
-rw-r--r-- | drivers/usb/dwc3/core.c | 23 | ||||
-rw-r--r-- | drivers/usb/dwc3/debugfs.c | 13 | ||||
-rw-r--r-- | drivers/usb/dwc3/dwc3-omap.c | 12 | ||||
-rw-r--r-- | drivers/usb/dwc3/gadget.c | 6 | ||||
-rw-r--r-- | drivers/usb/gadget/composite.c | 2 | ||||
-rw-r--r-- | drivers/usb/gadget/function/f_fs.c | 5 |
6 files changed, 44 insertions, 17 deletions
diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index fa20f5a99d12..34277ced26bd 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c | |||
@@ -1150,6 +1150,11 @@ static int dwc3_suspend(struct device *dev) | |||
1150 | phy_exit(dwc->usb2_generic_phy); | 1150 | phy_exit(dwc->usb2_generic_phy); |
1151 | phy_exit(dwc->usb3_generic_phy); | 1151 | phy_exit(dwc->usb3_generic_phy); |
1152 | 1152 | ||
1153 | usb_phy_set_suspend(dwc->usb2_phy, 1); | ||
1154 | usb_phy_set_suspend(dwc->usb3_phy, 1); | ||
1155 | WARN_ON(phy_power_off(dwc->usb2_generic_phy) < 0); | ||
1156 | WARN_ON(phy_power_off(dwc->usb3_generic_phy) < 0); | ||
1157 | |||
1153 | pinctrl_pm_select_sleep_state(dev); | 1158 | pinctrl_pm_select_sleep_state(dev); |
1154 | 1159 | ||
1155 | return 0; | 1160 | return 0; |
@@ -1163,11 +1168,21 @@ static int dwc3_resume(struct device *dev) | |||
1163 | 1168 | ||
1164 | pinctrl_pm_select_default_state(dev); | 1169 | pinctrl_pm_select_default_state(dev); |
1165 | 1170 | ||
1171 | usb_phy_set_suspend(dwc->usb2_phy, 0); | ||
1172 | usb_phy_set_suspend(dwc->usb3_phy, 0); | ||
1173 | ret = phy_power_on(dwc->usb2_generic_phy); | ||
1174 | if (ret < 0) | ||
1175 | return ret; | ||
1176 | |||
1177 | ret = phy_power_on(dwc->usb3_generic_phy); | ||
1178 | if (ret < 0) | ||
1179 | goto err_usb2phy_power; | ||
1180 | |||
1166 | usb_phy_init(dwc->usb3_phy); | 1181 | usb_phy_init(dwc->usb3_phy); |
1167 | usb_phy_init(dwc->usb2_phy); | 1182 | usb_phy_init(dwc->usb2_phy); |
1168 | ret = phy_init(dwc->usb2_generic_phy); | 1183 | ret = phy_init(dwc->usb2_generic_phy); |
1169 | if (ret < 0) | 1184 | if (ret < 0) |
1170 | return ret; | 1185 | goto err_usb3phy_power; |
1171 | 1186 | ||
1172 | ret = phy_init(dwc->usb3_generic_phy); | 1187 | ret = phy_init(dwc->usb3_generic_phy); |
1173 | if (ret < 0) | 1188 | if (ret < 0) |
@@ -1200,6 +1215,12 @@ static int dwc3_resume(struct device *dev) | |||
1200 | err_usb2phy_init: | 1215 | err_usb2phy_init: |
1201 | phy_exit(dwc->usb2_generic_phy); | 1216 | phy_exit(dwc->usb2_generic_phy); |
1202 | 1217 | ||
1218 | err_usb3phy_power: | ||
1219 | phy_power_off(dwc->usb3_generic_phy); | ||
1220 | |||
1221 | err_usb2phy_power: | ||
1222 | phy_power_off(dwc->usb2_generic_phy); | ||
1223 | |||
1203 | return ret; | 1224 | return ret; |
1204 | } | 1225 | } |
1205 | 1226 | ||
diff --git a/drivers/usb/dwc3/debugfs.c b/drivers/usb/dwc3/debugfs.c index 9ac37fe1b6a7..cebf9e38b60a 100644 --- a/drivers/usb/dwc3/debugfs.c +++ b/drivers/usb/dwc3/debugfs.c | |||
@@ -645,7 +645,7 @@ int dwc3_debugfs_init(struct dwc3 *dwc) | |||
645 | file = debugfs_create_regset32("regdump", S_IRUGO, root, dwc->regset); | 645 | file = debugfs_create_regset32("regdump", S_IRUGO, root, dwc->regset); |
646 | if (!file) { | 646 | if (!file) { |
647 | ret = -ENOMEM; | 647 | ret = -ENOMEM; |
648 | goto err1; | 648 | goto err2; |
649 | } | 649 | } |
650 | 650 | ||
651 | if (IS_ENABLED(CONFIG_USB_DWC3_DUAL_ROLE)) { | 651 | if (IS_ENABLED(CONFIG_USB_DWC3_DUAL_ROLE)) { |
@@ -653,7 +653,7 @@ int dwc3_debugfs_init(struct dwc3 *dwc) | |||
653 | dwc, &dwc3_mode_fops); | 653 | dwc, &dwc3_mode_fops); |
654 | if (!file) { | 654 | if (!file) { |
655 | ret = -ENOMEM; | 655 | ret = -ENOMEM; |
656 | goto err1; | 656 | goto err2; |
657 | } | 657 | } |
658 | } | 658 | } |
659 | 659 | ||
@@ -663,19 +663,22 @@ int dwc3_debugfs_init(struct dwc3 *dwc) | |||
663 | dwc, &dwc3_testmode_fops); | 663 | dwc, &dwc3_testmode_fops); |
664 | if (!file) { | 664 | if (!file) { |
665 | ret = -ENOMEM; | 665 | ret = -ENOMEM; |
666 | goto err1; | 666 | goto err2; |
667 | } | 667 | } |
668 | 668 | ||
669 | file = debugfs_create_file("link_state", S_IRUGO | S_IWUSR, root, | 669 | file = debugfs_create_file("link_state", S_IRUGO | S_IWUSR, root, |
670 | dwc, &dwc3_link_state_fops); | 670 | dwc, &dwc3_link_state_fops); |
671 | if (!file) { | 671 | if (!file) { |
672 | ret = -ENOMEM; | 672 | ret = -ENOMEM; |
673 | goto err1; | 673 | goto err2; |
674 | } | 674 | } |
675 | } | 675 | } |
676 | 676 | ||
677 | return 0; | 677 | return 0; |
678 | 678 | ||
679 | err2: | ||
680 | kfree(dwc->regset); | ||
681 | |||
679 | err1: | 682 | err1: |
680 | debugfs_remove_recursive(root); | 683 | debugfs_remove_recursive(root); |
681 | 684 | ||
@@ -686,5 +689,5 @@ err0: | |||
686 | void dwc3_debugfs_exit(struct dwc3 *dwc) | 689 | void dwc3_debugfs_exit(struct dwc3 *dwc) |
687 | { | 690 | { |
688 | debugfs_remove_recursive(dwc->root); | 691 | debugfs_remove_recursive(dwc->root); |
689 | dwc->root = NULL; | 692 | kfree(dwc->regset); |
690 | } | 693 | } |
diff --git a/drivers/usb/dwc3/dwc3-omap.c b/drivers/usb/dwc3/dwc3-omap.c index 22e9606d8e08..55da2c7f727f 100644 --- a/drivers/usb/dwc3/dwc3-omap.c +++ b/drivers/usb/dwc3/dwc3-omap.c | |||
@@ -496,7 +496,7 @@ static int dwc3_omap_probe(struct platform_device *pdev) | |||
496 | ret = pm_runtime_get_sync(dev); | 496 | ret = pm_runtime_get_sync(dev); |
497 | if (ret < 0) { | 497 | if (ret < 0) { |
498 | dev_err(dev, "get_sync failed with err %d\n", ret); | 498 | dev_err(dev, "get_sync failed with err %d\n", ret); |
499 | goto err0; | 499 | goto err1; |
500 | } | 500 | } |
501 | 501 | ||
502 | dwc3_omap_map_offset(omap); | 502 | dwc3_omap_map_offset(omap); |
@@ -516,28 +516,24 @@ static int dwc3_omap_probe(struct platform_device *pdev) | |||
516 | 516 | ||
517 | ret = dwc3_omap_extcon_register(omap); | 517 | ret = dwc3_omap_extcon_register(omap); |
518 | if (ret < 0) | 518 | if (ret < 0) |
519 | goto err2; | 519 | goto err1; |
520 | 520 | ||
521 | ret = of_platform_populate(node, NULL, NULL, dev); | 521 | ret = of_platform_populate(node, NULL, NULL, dev); |
522 | if (ret) { | 522 | if (ret) { |
523 | dev_err(&pdev->dev, "failed to create dwc3 core\n"); | 523 | dev_err(&pdev->dev, "failed to create dwc3 core\n"); |
524 | goto err3; | 524 | goto err2; |
525 | } | 525 | } |
526 | 526 | ||
527 | dwc3_omap_enable_irqs(omap); | 527 | dwc3_omap_enable_irqs(omap); |
528 | 528 | ||
529 | return 0; | 529 | return 0; |
530 | 530 | ||
531 | err3: | 531 | err2: |
532 | extcon_unregister_notifier(omap->edev, EXTCON_USB, &omap->vbus_nb); | 532 | extcon_unregister_notifier(omap->edev, EXTCON_USB, &omap->vbus_nb); |
533 | extcon_unregister_notifier(omap->edev, EXTCON_USB_HOST, &omap->id_nb); | 533 | extcon_unregister_notifier(omap->edev, EXTCON_USB_HOST, &omap->id_nb); |
534 | err2: | ||
535 | dwc3_omap_disable_irqs(omap); | ||
536 | 534 | ||
537 | err1: | 535 | err1: |
538 | pm_runtime_put_sync(dev); | 536 | pm_runtime_put_sync(dev); |
539 | |||
540 | err0: | ||
541 | pm_runtime_disable(dev); | 537 | pm_runtime_disable(dev); |
542 | 538 | ||
543 | return ret; | 539 | return ret; |
diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index d54a028cdfeb..8e4a1b195e9b 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c | |||
@@ -2936,6 +2936,9 @@ void dwc3_gadget_exit(struct dwc3 *dwc) | |||
2936 | 2936 | ||
2937 | int dwc3_gadget_suspend(struct dwc3 *dwc) | 2937 | int dwc3_gadget_suspend(struct dwc3 *dwc) |
2938 | { | 2938 | { |
2939 | if (!dwc->gadget_driver) | ||
2940 | return 0; | ||
2941 | |||
2939 | if (dwc->pullups_connected) { | 2942 | if (dwc->pullups_connected) { |
2940 | dwc3_gadget_disable_irq(dwc); | 2943 | dwc3_gadget_disable_irq(dwc); |
2941 | dwc3_gadget_run_stop(dwc, true, true); | 2944 | dwc3_gadget_run_stop(dwc, true, true); |
@@ -2954,6 +2957,9 @@ int dwc3_gadget_resume(struct dwc3 *dwc) | |||
2954 | struct dwc3_ep *dep; | 2957 | struct dwc3_ep *dep; |
2955 | int ret; | 2958 | int ret; |
2956 | 2959 | ||
2960 | if (!dwc->gadget_driver) | ||
2961 | return 0; | ||
2962 | |||
2957 | /* Start with SuperSpeed Default */ | 2963 | /* Start with SuperSpeed Default */ |
2958 | dwc3_gadget_ep0_desc.wMaxPacketSize = cpu_to_le16(512); | 2964 | dwc3_gadget_ep0_desc.wMaxPacketSize = cpu_to_le16(512); |
2959 | 2965 | ||
diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c index de9ffd60fcfa..524e233d48de 100644 --- a/drivers/usb/gadget/composite.c +++ b/drivers/usb/gadget/composite.c | |||
@@ -651,6 +651,8 @@ static int bos_desc(struct usb_composite_dev *cdev) | |||
651 | ssp_cap->bLength = USB_DT_USB_SSP_CAP_SIZE(1); | 651 | ssp_cap->bLength = USB_DT_USB_SSP_CAP_SIZE(1); |
652 | ssp_cap->bDescriptorType = USB_DT_DEVICE_CAPABILITY; | 652 | ssp_cap->bDescriptorType = USB_DT_DEVICE_CAPABILITY; |
653 | ssp_cap->bDevCapabilityType = USB_SSP_CAP_TYPE; | 653 | ssp_cap->bDevCapabilityType = USB_SSP_CAP_TYPE; |
654 | ssp_cap->bReserved = 0; | ||
655 | ssp_cap->wReserved = 0; | ||
654 | 656 | ||
655 | /* SSAC = 1 (2 attributes) */ | 657 | /* SSAC = 1 (2 attributes) */ |
656 | ssp_cap->bmAttributes = cpu_to_le32(1); | 658 | ssp_cap->bmAttributes = cpu_to_le32(1); |
diff --git a/drivers/usb/gadget/function/f_fs.c b/drivers/usb/gadget/function/f_fs.c index e21ca2bd6839..15b648cbc75c 100644 --- a/drivers/usb/gadget/function/f_fs.c +++ b/drivers/usb/gadget/function/f_fs.c | |||
@@ -646,6 +646,7 @@ static void ffs_user_copy_worker(struct work_struct *work) | |||
646 | work); | 646 | work); |
647 | int ret = io_data->req->status ? io_data->req->status : | 647 | int ret = io_data->req->status ? io_data->req->status : |
648 | io_data->req->actual; | 648 | io_data->req->actual; |
649 | bool kiocb_has_eventfd = io_data->kiocb->ki_flags & IOCB_EVENTFD; | ||
649 | 650 | ||
650 | if (io_data->read && ret > 0) { | 651 | if (io_data->read && ret > 0) { |
651 | use_mm(io_data->mm); | 652 | use_mm(io_data->mm); |
@@ -657,13 +658,11 @@ static void ffs_user_copy_worker(struct work_struct *work) | |||
657 | 658 | ||
658 | io_data->kiocb->ki_complete(io_data->kiocb, ret, ret); | 659 | io_data->kiocb->ki_complete(io_data->kiocb, ret, ret); |
659 | 660 | ||
660 | if (io_data->ffs->ffs_eventfd && | 661 | if (io_data->ffs->ffs_eventfd && !kiocb_has_eventfd) |
661 | !(io_data->kiocb->ki_flags & IOCB_EVENTFD)) | ||
662 | eventfd_signal(io_data->ffs->ffs_eventfd, 1); | 662 | eventfd_signal(io_data->ffs->ffs_eventfd, 1); |
663 | 663 | ||
664 | usb_ep_free_request(io_data->ep, io_data->req); | 664 | usb_ep_free_request(io_data->ep, io_data->req); |
665 | 665 | ||
666 | io_data->kiocb->private = NULL; | ||
667 | if (io_data->read) | 666 | if (io_data->read) |
668 | kfree(io_data->to_free); | 667 | kfree(io_data->to_free); |
669 | kfree(io_data->buf); | 668 | kfree(io_data->buf); |