On Tue, 16 Apr 2019, syzbot wrote:

> Hello,
> 
> syzbot has tested the proposed patch but the reproducer still triggered  
> crash:
> WARNING in usb_submit_urb
> 
> hub 3-0:1.0: 0000000015733366 hub_activate type 4 discon 0
> hub 3-0:1.0: 0000000015733366 Submitting status URB
> hub 3-0:1.0: 0000000015733366 Submitting status URB
> ------------[ cut here ]------------
> URB 000000006ea6e83c submitted while active
> WARNING: CPU: 0 PID: 6476 at drivers/usb/core/urb.c:363  

Here's more of the context, showing the important part:

[  115.102684] hub 3-0:1.0: USB hub found
[  115.107011] hub 3-0:1.0: 8 ports detected

A new USB bus was registered and its root hub was probed.

[  115.114470] hub 3-0:1.0: 0000000015733366 hub_activate type 0 discon 0

Type 0 is HUB_INIT, the first stage of activating a new hub.  This
stage involves a long delay, so it calls
usb_autopm_get_interface_no_resume(), schedules a delayed work routine
to carry out the next stage, and returns.

[  115.180282] hub 3-0:1.0: 0000000015733366 hub_suspend
[  115.214681] hub 3-0:1.0: 0000000015733366 hub_quiesce type 2

Type 2 quiesce is HUB_SUSPEND.  Somehow the hub was autosuspended even 
though its runtime PM usage count was elevated!

[  115.231986] hub 3-0:1.0: 0000000015733366 hub_resume
[  115.241706] hub 3-0:1.0: 0000000015733366 hub_activate type 1 discon 0
[  115.249931] hub 3-0:1.0: 0000000015733366 hub_activate type 4 discon 0

Then the hub was resumed again.  Type 1 activation is HUB_INIT2, the 
second stage of the original hub activation.  Type 4 is HUB_RESUME.  
Evidently both types of activation are running concurrently.

[  115.276027] hub 3-0:1.0: 0000000015733366 Submitting status URB
[  115.288239] hub 3-0:1.0: 0000000015733366 Submitting status URB
[  115.295347] ------------[ cut here ]------------
[  115.300505] URB 000000006ea6e83c submitted while active

Both activation threads submit the same status URB, leading to the
error.

So the question is: Why was the hub suspended at a time when it should 
have remained active?  Let's see what the runtime PM values are when 
hub_suspend is called.

Alan Stern


#syz test: git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git 
e12e00e388de

--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -1016,6 +1016,9 @@ static void hub_activate(struct usb_hub
        bool need_debounce_delay = false;
        unsigned delay;
 
+       dev_info(hub->intfdev, "%p %s type %d discon %d\n",
+                       hub, __func__, type, hub->disconnected);
+
        /* Continue a partial initialization */
        if (type == HUB_INIT2 || type == HUB_INIT3) {
                device_lock(&hdev->dev);
@@ -1254,6 +1257,7 @@ static void hub_activate(struct usb_hub
  init3:
        hub->quiescing = 0;
 
+       dev_info(hub->intfdev, "%p Submitting status URB\n", hub);
        status = usb_submit_urb(hub->urb, GFP_NOIO);
        if (status < 0)
                dev_err(hub->intfdev, "activate --> %d\n", status);
@@ -1299,6 +1303,8 @@ static void hub_quiesce(struct usb_hub *
        unsigned long flags;
        int i;
 
+       dev_info(hub->intfdev, "%p %s type %d\n", hub, __func__, type);
+
        /* hub_wq and related activity won't re-trigger */
        spin_lock_irqsave(&hub->irq_urb_lock, flags);
        hub->quiescing = 1;
@@ -3711,7 +3717,11 @@ static int hub_suspend(struct usb_interf
                }
        }
 
-       dev_dbg(&intf->dev, "%s\n", __func__);
+       dev_info(&intf->dev, "%p %s disable %d usage %d status %d\n",
+                       hub, __func__,
+                       intf->dev.power.disable_depth,
+                       atomic_read(&intf->dev.power.usage_count),
+                       intf->dev.power.runtime_status);
 
        /* stop hub_wq and related activity */
        hub_quiesce(hub, HUB_SUSPEND);
@@ -3756,7 +3766,7 @@ static int hub_resume(struct usb_interfa
 {
        struct usb_hub *hub = usb_get_intfdata(intf);
 
-       dev_dbg(&intf->dev, "%s\n", __func__);
+       dev_info(&intf->dev, "%p %s\n", hub, __func__);
        hub_activate(hub, HUB_RESUME);
 
        /*

Reply via email to