aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRavi Chandra Sadineni <ravisadineni@chromium.org>2018-04-20 14:08:21 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2018-04-22 08:45:11 -0400
commit83a62c51ba7b3c0bf45150c4eac7aefc6c785e94 (patch)
tree863882dae9385cf62c736ffd2c7e44d903a0b0da
parent3ae2da7b28b393d4f6faef3d384cc725ef39716b (diff)
USB: Increment wakeup count on remote wakeup.
On chromebooks we depend on wakeup count to identify the wakeup source. But currently USB devices do not increment the wakeup count when they trigger the remote wake. This patch addresses the same. Resume condition is reported differently on USB 2.0 and USB 3.0 devices. On USB 2.0 devices, a wake capable device, if wake enabled, drives resume signal to indicate a remote wake (USB 2.0 spec section 7.1.7.7). The upstream facing port then sets C_PORT_SUSPEND bit and reports a port change event (USB 2.0 spec section 11.24.2.7.2.3). Thus if a port has resumed before driving the resume signal from the host and C_PORT_SUSPEND is set, then the device attached to the given port might be the reason for the last system wakeup. Increment the wakeup count for the same. On USB 3.0 devices, a function may signal that it wants to exit from device suspend by sending a Function Wake Device Notification to the host (USB3.0 spec section 8.5.6.4) Thus on receiving the Function Wake, increment the wakeup count. Signed-off-by: Ravi Chandra Sadineni <ravisadineni@chromium.org> Acked-by: Alan Stern <stern@rowland.harvard.edu> Cc: stable <stable@vger.kernel.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--drivers/usb/core/hcd.c1
-rw-r--r--drivers/usb/core/hub.c10
2 files changed, 10 insertions, 1 deletions
diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
index 777036ae6367..00bb8417050f 100644
--- a/drivers/usb/core/hcd.c
+++ b/drivers/usb/core/hcd.c
@@ -2377,6 +2377,7 @@ void usb_hcd_resume_root_hub (struct usb_hcd *hcd)
2377 2377
2378 spin_lock_irqsave (&hcd_root_hub_lock, flags); 2378 spin_lock_irqsave (&hcd_root_hub_lock, flags);
2379 if (hcd->rh_registered) { 2379 if (hcd->rh_registered) {
2380 pm_wakeup_event(&hcd->self.root_hub->dev, 0);
2380 set_bit(HCD_FLAG_WAKEUP_PENDING, &hcd->flags); 2381 set_bit(HCD_FLAG_WAKEUP_PENDING, &hcd->flags);
2381 queue_work(pm_wq, &hcd->wakeup_work); 2382 queue_work(pm_wq, &hcd->wakeup_work);
2382 } 2383 }
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))