aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/core
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2018-04-27 12:32:20 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2018-04-27 12:32:20 -0400
commit1993cbf06aa95c0fcf080f2e858c116306b6c29e (patch)
tree48fed02d854e4a1133fcd380da5627401e6292d4 /drivers/usb/core
parent7ff5000268355c63dc948ecb01f4de17987586e5 (diff)
parent573a094873752d225041b1059a662eca013a54f4 (diff)
Merge tag 'usb-4.17-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb
Pull USB fixes from Greg KH: "Here are a number of USB driver fixes for reported problems for 4.17-rc3. The "largest" here is a number of phy core changes for reported problems with the -rc1 release. There's also the usual musb and xhci fixes, as well as new device id updates. There are also some usbip fixes for reported problems as more people start to use that code with containers. All of these have been in linux-next with no reported issues, except the last few new device ids, which are "obviously correct" :)" * tag 'usb-4.17-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb: (26 commits) USB: musb: dsps: drop duplicate phy initialisation USB: musb: host: prevent core phy initialisation usb: core: phy: add the SPDX-License-Identifier and include guard xhci: Fix Kernel oops in xhci dbgtty usb: select USB_COMMON for usb role switch config usb: core: phy: add missing forward declaration for "struct device" usb: core: phy: make it a no-op if CONFIG_GENERIC_PHY is disabled usb: core: use phy_exit during suspend if wake up is not supported usb: core: split usb_phy_roothub_{init,alloc} usb: core: phy: fix return value of usb_phy_roothub_exit() usb: typec: ucsi: Increase command completion timeout value Revert "xhci: plat: Register shutdown for xhci_plat" usb: core: Add quirk for HP v222w 16GB Mini Documentation: typec.rst: Use literal-block element with ascii art usb: typec: ucsi: fix tracepoint related build error usbip: usbip_event: fix to not print kernel pointer address usbip: usbip_host: fix to hold parent lock for device_attach() calls usbip: vhci_hcd: Fix usb device and sockfd leaks usbip: vhci_hcd: check rhport before using in vhci_hub_control() USB: Increment wakeup count on remote wakeup. ...
Diffstat (limited to 'drivers/usb/core')
-rw-r--r--drivers/usb/core/hcd.c19
-rw-r--r--drivers/usb/core/hub.c10
-rw-r--r--drivers/usb/core/phy.c93
-rw-r--r--drivers/usb/core/phy.h22
-rw-r--r--drivers/usb/core/quirks.c3
5 files changed, 112 insertions, 35 deletions
diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
index 777036ae6367..0a42c5df3c0f 100644
--- a/drivers/usb/core/hcd.c
+++ b/drivers/usb/core/hcd.c
@@ -2262,7 +2262,8 @@ int hcd_bus_suspend(struct usb_device *rhdev, pm_message_t msg)
2262 hcd->state = HC_STATE_SUSPENDED; 2262 hcd->state = HC_STATE_SUSPENDED;
2263 2263
2264 if (!PMSG_IS_AUTO(msg)) 2264 if (!PMSG_IS_AUTO(msg))
2265 usb_phy_roothub_power_off(hcd->phy_roothub); 2265 usb_phy_roothub_suspend(hcd->self.sysdev,
2266 hcd->phy_roothub);
2266 2267
2267 /* Did we race with a root-hub wakeup event? */ 2268 /* Did we race with a root-hub wakeup event? */
2268 if (rhdev->do_remote_wakeup) { 2269 if (rhdev->do_remote_wakeup) {
@@ -2302,7 +2303,8 @@ int hcd_bus_resume(struct usb_device *rhdev, pm_message_t msg)
2302 } 2303 }
2303 2304
2304 if (!PMSG_IS_AUTO(msg)) { 2305 if (!PMSG_IS_AUTO(msg)) {
2305 status = usb_phy_roothub_power_on(hcd->phy_roothub); 2306 status = usb_phy_roothub_resume(hcd->self.sysdev,
2307 hcd->phy_roothub);
2306 if (status) 2308 if (status)
2307 return status; 2309 return status;
2308 } 2310 }
@@ -2344,7 +2346,7 @@ int hcd_bus_resume(struct usb_device *rhdev, pm_message_t msg)
2344 } 2346 }
2345 } else { 2347 } else {
2346 hcd->state = old_state; 2348 hcd->state = old_state;
2347 usb_phy_roothub_power_off(hcd->phy_roothub); 2349 usb_phy_roothub_suspend(hcd->self.sysdev, hcd->phy_roothub);
2348 dev_dbg(&rhdev->dev, "bus %s fail, err %d\n", 2350 dev_dbg(&rhdev->dev, "bus %s fail, err %d\n",
2349 "resume", status); 2351 "resume", status);
2350 if (status != -ESHUTDOWN) 2352 if (status != -ESHUTDOWN)
@@ -2377,6 +2379,7 @@ void usb_hcd_resume_root_hub (struct usb_hcd *hcd)
2377 2379
2378 spin_lock_irqsave (&hcd_root_hub_lock, flags); 2380 spin_lock_irqsave (&hcd_root_hub_lock, flags);
2379 if (hcd->rh_registered) { 2381 if (hcd->rh_registered) {
2382 pm_wakeup_event(&hcd->self.root_hub->dev, 0);
2380 set_bit(HCD_FLAG_WAKEUP_PENDING, &hcd->flags); 2383 set_bit(HCD_FLAG_WAKEUP_PENDING, &hcd->flags);
2381 queue_work(pm_wq, &hcd->wakeup_work); 2384 queue_work(pm_wq, &hcd->wakeup_work);
2382 } 2385 }
@@ -2758,12 +2761,16 @@ int usb_add_hcd(struct usb_hcd *hcd,
2758 } 2761 }
2759 2762
2760 if (!hcd->skip_phy_initialization && usb_hcd_is_primary_hcd(hcd)) { 2763 if (!hcd->skip_phy_initialization && usb_hcd_is_primary_hcd(hcd)) {
2761 hcd->phy_roothub = usb_phy_roothub_init(hcd->self.sysdev); 2764 hcd->phy_roothub = usb_phy_roothub_alloc(hcd->self.sysdev);
2762 if (IS_ERR(hcd->phy_roothub)) { 2765 if (IS_ERR(hcd->phy_roothub)) {
2763 retval = PTR_ERR(hcd->phy_roothub); 2766 retval = PTR_ERR(hcd->phy_roothub);
2764 goto err_phy_roothub_init; 2767 goto err_phy_roothub_alloc;
2765 } 2768 }
2766 2769
2770 retval = usb_phy_roothub_init(hcd->phy_roothub);
2771 if (retval)
2772 goto err_phy_roothub_alloc;
2773
2767 retval = usb_phy_roothub_power_on(hcd->phy_roothub); 2774 retval = usb_phy_roothub_power_on(hcd->phy_roothub);
2768 if (retval) 2775 if (retval)
2769 goto err_usb_phy_roothub_power_on; 2776 goto err_usb_phy_roothub_power_on;
@@ -2936,7 +2943,7 @@ err_create_buf:
2936 usb_phy_roothub_power_off(hcd->phy_roothub); 2943 usb_phy_roothub_power_off(hcd->phy_roothub);
2937err_usb_phy_roothub_power_on: 2944err_usb_phy_roothub_power_on:
2938 usb_phy_roothub_exit(hcd->phy_roothub); 2945 usb_phy_roothub_exit(hcd->phy_roothub);
2939err_phy_roothub_init: 2946err_phy_roothub_alloc:
2940 if (hcd->remove_phy && hcd->usb_phy) { 2947 if (hcd->remove_phy && hcd->usb_phy) {
2941 usb_phy_shutdown(hcd->usb_phy); 2948 usb_phy_shutdown(hcd->usb_phy);
2942 usb_put_phy(hcd->usb_phy); 2949 usb_put_phy(hcd->usb_phy);
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index f6ea16e9f6bb..aa9968d90a48 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -653,12 +653,17 @@ void usb_wakeup_notification(struct usb_device *hdev,
653 unsigned int portnum) 653 unsigned int portnum)
654{ 654{
655 struct usb_hub *hub; 655 struct usb_hub *hub;
656 struct usb_port *port_dev;
656 657
657 if (!hdev) 658 if (!hdev)
658 return; 659 return;
659 660
660 hub = usb_hub_to_struct_hub(hdev); 661 hub = usb_hub_to_struct_hub(hdev);
661 if (hub) { 662 if (hub) {
663 port_dev = hub->ports[portnum - 1];
664 if (port_dev && port_dev->child)
665 pm_wakeup_event(&port_dev->child->dev, 0);
666
662 set_bit(portnum, hub->wakeup_bits); 667 set_bit(portnum, hub->wakeup_bits);
663 kick_hub_wq(hub); 668 kick_hub_wq(hub);
664 } 669 }
@@ -3434,8 +3439,11 @@ int usb_port_resume(struct usb_device *udev, pm_message_t msg)
3434 3439
3435 /* Skip the initial Clear-Suspend step for a remote wakeup */ 3440 /* Skip the initial Clear-Suspend step for a remote wakeup */
3436 status = hub_port_status(hub, port1, &portstatus, &portchange); 3441 status = hub_port_status(hub, port1, &portstatus, &portchange);
3437 if (status == 0 && !port_is_suspended(hub, portstatus)) 3442 if (status == 0 && !port_is_suspended(hub, portstatus)) {
3443 if (portchange & USB_PORT_STAT_C_SUSPEND)
3444 pm_wakeup_event(&udev->dev, 0);
3438 goto SuspendCleared; 3445 goto SuspendCleared;
3446 }
3439 3447
3440 /* see 7.1.7.7; affects power usage, but not budgeting */ 3448 /* see 7.1.7.7; affects power usage, but not budgeting */
3441 if (hub_is_superspeed(hub->hdev)) 3449 if (hub_is_superspeed(hub->hdev))
diff --git a/drivers/usb/core/phy.c b/drivers/usb/core/phy.c
index 09b7c43c0ea4..9879767452a2 100644
--- a/drivers/usb/core/phy.c
+++ b/drivers/usb/core/phy.c
@@ -19,19 +19,6 @@ struct usb_phy_roothub {
19 struct list_head list; 19 struct list_head list;
20}; 20};
21 21
22static struct usb_phy_roothub *usb_phy_roothub_alloc(struct device *dev)
23{
24 struct usb_phy_roothub *roothub_entry;
25
26 roothub_entry = devm_kzalloc(dev, sizeof(*roothub_entry), GFP_KERNEL);
27 if (!roothub_entry)
28 return ERR_PTR(-ENOMEM);
29
30 INIT_LIST_HEAD(&roothub_entry->list);
31
32 return roothub_entry;
33}
34
35static int usb_phy_roothub_add_phy(struct device *dev, int index, 22static int usb_phy_roothub_add_phy(struct device *dev, int index,
36 struct list_head *list) 23 struct list_head *list)
37{ 24{
@@ -45,9 +32,11 @@ static int usb_phy_roothub_add_phy(struct device *dev, int index,
45 return PTR_ERR(phy); 32 return PTR_ERR(phy);
46 } 33 }
47 34
48 roothub_entry = usb_phy_roothub_alloc(dev); 35 roothub_entry = devm_kzalloc(dev, sizeof(*roothub_entry), GFP_KERNEL);
49 if (IS_ERR(roothub_entry)) 36 if (!roothub_entry)
50 return PTR_ERR(roothub_entry); 37 return -ENOMEM;
38
39 INIT_LIST_HEAD(&roothub_entry->list);
51 40
52 roothub_entry->phy = phy; 41 roothub_entry->phy = phy;
53 42
@@ -56,28 +45,44 @@ static int usb_phy_roothub_add_phy(struct device *dev, int index,
56 return 0; 45 return 0;
57} 46}
58 47
59struct usb_phy_roothub *usb_phy_roothub_init(struct device *dev) 48struct usb_phy_roothub *usb_phy_roothub_alloc(struct device *dev)
60{ 49{
61 struct usb_phy_roothub *phy_roothub; 50 struct usb_phy_roothub *phy_roothub;
62 struct usb_phy_roothub *roothub_entry;
63 struct list_head *head;
64 int i, num_phys, err; 51 int i, num_phys, err;
65 52
53 if (!IS_ENABLED(CONFIG_GENERIC_PHY))
54 return NULL;
55
66 num_phys = of_count_phandle_with_args(dev->of_node, "phys", 56 num_phys = of_count_phandle_with_args(dev->of_node, "phys",
67 "#phy-cells"); 57 "#phy-cells");
68 if (num_phys <= 0) 58 if (num_phys <= 0)
69 return NULL; 59 return NULL;
70 60
71 phy_roothub = usb_phy_roothub_alloc(dev); 61 phy_roothub = devm_kzalloc(dev, sizeof(*phy_roothub), GFP_KERNEL);
72 if (IS_ERR(phy_roothub)) 62 if (!phy_roothub)
73 return phy_roothub; 63 return ERR_PTR(-ENOMEM);
64
65 INIT_LIST_HEAD(&phy_roothub->list);
74 66
75 for (i = 0; i < num_phys; i++) { 67 for (i = 0; i < num_phys; i++) {
76 err = usb_phy_roothub_add_phy(dev, i, &phy_roothub->list); 68 err = usb_phy_roothub_add_phy(dev, i, &phy_roothub->list);
77 if (err) 69 if (err)
78 goto err_out; 70 return ERR_PTR(err);
79 } 71 }
80 72
73 return phy_roothub;
74}
75EXPORT_SYMBOL_GPL(usb_phy_roothub_alloc);
76
77int usb_phy_roothub_init(struct usb_phy_roothub *phy_roothub)
78{
79 struct usb_phy_roothub *roothub_entry;
80 struct list_head *head;
81 int err;
82
83 if (!phy_roothub)
84 return 0;
85
81 head = &phy_roothub->list; 86 head = &phy_roothub->list;
82 87
83 list_for_each_entry(roothub_entry, head, list) { 88 list_for_each_entry(roothub_entry, head, list) {
@@ -86,14 +91,13 @@ struct usb_phy_roothub *usb_phy_roothub_init(struct device *dev)
86 goto err_exit_phys; 91 goto err_exit_phys;
87 } 92 }
88 93
89 return phy_roothub; 94 return 0;
90 95
91err_exit_phys: 96err_exit_phys:
92 list_for_each_entry_continue_reverse(roothub_entry, head, list) 97 list_for_each_entry_continue_reverse(roothub_entry, head, list)
93 phy_exit(roothub_entry->phy); 98 phy_exit(roothub_entry->phy);
94 99
95err_out: 100 return err;
96 return ERR_PTR(err);
97} 101}
98EXPORT_SYMBOL_GPL(usb_phy_roothub_init); 102EXPORT_SYMBOL_GPL(usb_phy_roothub_init);
99 103
@@ -111,7 +115,7 @@ int usb_phy_roothub_exit(struct usb_phy_roothub *phy_roothub)
111 list_for_each_entry(roothub_entry, head, list) { 115 list_for_each_entry(roothub_entry, head, list) {
112 err = phy_exit(roothub_entry->phy); 116 err = phy_exit(roothub_entry->phy);
113 if (err) 117 if (err)
114 ret = ret; 118 ret = err;
115 } 119 }
116 120
117 return ret; 121 return ret;
@@ -156,3 +160,38 @@ void usb_phy_roothub_power_off(struct usb_phy_roothub *phy_roothub)
156 phy_power_off(roothub_entry->phy); 160 phy_power_off(roothub_entry->phy);
157} 161}
158EXPORT_SYMBOL_GPL(usb_phy_roothub_power_off); 162EXPORT_SYMBOL_GPL(usb_phy_roothub_power_off);
163
164int usb_phy_roothub_suspend(struct device *controller_dev,
165 struct usb_phy_roothub *phy_roothub)
166{
167 usb_phy_roothub_power_off(phy_roothub);
168
169 /* keep the PHYs initialized so the device can wake up the system */
170 if (device_may_wakeup(controller_dev))
171 return 0;
172
173 return usb_phy_roothub_exit(phy_roothub);
174}
175EXPORT_SYMBOL_GPL(usb_phy_roothub_suspend);
176
177int usb_phy_roothub_resume(struct device *controller_dev,
178 struct usb_phy_roothub *phy_roothub)
179{
180 int err;
181
182 /* if the device can't wake up the system _exit was called */
183 if (!device_may_wakeup(controller_dev)) {
184 err = usb_phy_roothub_init(phy_roothub);
185 if (err)
186 return err;
187 }
188
189 err = usb_phy_roothub_power_on(phy_roothub);
190
191 /* undo _init if _power_on failed */
192 if (err && !device_may_wakeup(controller_dev))
193 usb_phy_roothub_exit(phy_roothub);
194
195 return err;
196}
197EXPORT_SYMBOL_GPL(usb_phy_roothub_resume);
diff --git a/drivers/usb/core/phy.h b/drivers/usb/core/phy.h
index 6fde59bfbff8..88a3c037e9df 100644
--- a/drivers/usb/core/phy.h
+++ b/drivers/usb/core/phy.h
@@ -1,7 +1,27 @@
1/* SPDX-License-Identifier: GPL-2.0+ */
2/*
3 * USB roothub wrapper
4 *
5 * Copyright (C) 2018 Martin Blumenstingl <martin.blumenstingl@googlemail.com>
6 */
7
8#ifndef __USB_CORE_PHY_H_
9#define __USB_CORE_PHY_H_
10
11struct device;
1struct usb_phy_roothub; 12struct usb_phy_roothub;
2 13
3struct usb_phy_roothub *usb_phy_roothub_init(struct device *dev); 14struct usb_phy_roothub *usb_phy_roothub_alloc(struct device *dev);
15
16int usb_phy_roothub_init(struct usb_phy_roothub *phy_roothub);
4int usb_phy_roothub_exit(struct usb_phy_roothub *phy_roothub); 17int usb_phy_roothub_exit(struct usb_phy_roothub *phy_roothub);
5 18
6int usb_phy_roothub_power_on(struct usb_phy_roothub *phy_roothub); 19int usb_phy_roothub_power_on(struct usb_phy_roothub *phy_roothub);
7void usb_phy_roothub_power_off(struct usb_phy_roothub *phy_roothub); 20void usb_phy_roothub_power_off(struct usb_phy_roothub *phy_roothub);
21
22int usb_phy_roothub_suspend(struct device *controller_dev,
23 struct usb_phy_roothub *phy_roothub);
24int usb_phy_roothub_resume(struct device *controller_dev,
25 struct usb_phy_roothub *phy_roothub);
26
27#endif /* __USB_CORE_PHY_H_ */
diff --git a/drivers/usb/core/quirks.c b/drivers/usb/core/quirks.c
index 920f48a49a87..c55def2f1320 100644
--- a/drivers/usb/core/quirks.c
+++ b/drivers/usb/core/quirks.c
@@ -186,6 +186,9 @@ static const struct usb_device_id usb_quirk_list[] = {
186 { USB_DEVICE(0x03f0, 0x0701), .driver_info = 186 { USB_DEVICE(0x03f0, 0x0701), .driver_info =
187 USB_QUIRK_STRING_FETCH_255 }, 187 USB_QUIRK_STRING_FETCH_255 },
188 188
189 /* HP v222w 16GB Mini USB Drive */
190 { USB_DEVICE(0x03f0, 0x3f40), .driver_info = USB_QUIRK_DELAY_INIT },
191
189 /* Creative SB Audigy 2 NX */ 192 /* Creative SB Audigy 2 NX */
190 { USB_DEVICE(0x041e, 0x3020), .driver_info = USB_QUIRK_RESET_RESUME }, 193 { USB_DEVICE(0x041e, 0x3020), .driver_info = USB_QUIRK_RESET_RESUME },
191 194