Skip to content

Commit b470209

Browse files
author
CKI KWF Bot
committed
Merge: usb: hub: fix detection of high tier US3 devices behind suspended hubs
MR: https://gitlab.com/redhat/centos-stream/src/kernel/centos-stream-10/-/merge_requests/1183 JIRA: https://issues.redhat.com/browse/RHEL-102858 Depends: !1166 This fixes a bug disturbing the detection of USB3 devices that are con- nected behind external suspended hubs when plugged in due to aggressive hub runtime pm suspend. Signed-off-by: Desnes Nunes <desnesn@redhat.com> Approved-by: Tony Camuso <tcamuso@redhat.com> Approved-by: David Arcari <darcari@redhat.com> Approved-by: Bastien Nocera <bnocera@redhat.com> Approved-by: CKI KWF Bot <cki-ci-bot+kwf-gitlab-com@redhat.com> Merged-by: CKI GitLab Kmaint Pipeline Bot <26919896-cki-kmaint-pipeline-bot@users.noreply.gitlab.com>
2 parents 557c132 + b4bc4a4 commit b470209

File tree

2 files changed

+29
-0
lines changed

2 files changed

+29
-0
lines changed

drivers/usb/core/hub.c

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,12 @@
6868
*/
6969
#define USB_SHORT_SET_ADDRESS_REQ_TIMEOUT 500 /* ms */
7070

71+
/*
72+
* Give SS hubs 200ms time after wake to train downstream links before
73+
* assuming no port activity and allowing hub to runtime suspend back.
74+
*/
75+
#define USB_SS_PORT_U0_WAKE_TIME 200 /* ms */
76+
7177
/* Protect struct usb_device->state and ->children members
7278
* Note: Both are also protected by ->dev.sem, except that ->state can
7379
* change to USB_STATE_NOTATTACHED even when the semaphore isn't held. */
@@ -1095,6 +1101,7 @@ static void hub_activate(struct usb_hub *hub, enum hub_activation_type type)
10951101
goto init2;
10961102
goto init3;
10971103
}
1104+
10981105
hub_get(hub);
10991106

11001107
/* The superspeed hub except for root hub has to use Hub Depth
@@ -1343,6 +1350,17 @@ static void hub_activate(struct usb_hub *hub, enum hub_activation_type type)
13431350
device_unlock(&hdev->dev);
13441351
}
13451352

1353+
if (type == HUB_RESUME && hub_is_superspeed(hub->hdev)) {
1354+
/* give usb3 downstream links training time after hub resume */
1355+
usb_autopm_get_interface_no_resume(
1356+
to_usb_interface(hub->intfdev));
1357+
1358+
queue_delayed_work(system_power_efficient_wq,
1359+
&hub->post_resume_work,
1360+
msecs_to_jiffies(USB_SS_PORT_U0_WAKE_TIME));
1361+
return;
1362+
}
1363+
13461364
hub_put(hub);
13471365
}
13481366

@@ -1361,6 +1379,14 @@ static void hub_init_func3(struct work_struct *ws)
13611379
hub_activate(hub, HUB_INIT3);
13621380
}
13631381

1382+
static void hub_post_resume(struct work_struct *ws)
1383+
{
1384+
struct usb_hub *hub = container_of(ws, struct usb_hub, post_resume_work.work);
1385+
1386+
usb_autopm_put_interface_async(to_usb_interface(hub->intfdev));
1387+
hub_put(hub);
1388+
}
1389+
13641390
enum hub_quiescing_type {
13651391
HUB_DISCONNECT, HUB_PRE_RESET, HUB_SUSPEND
13661392
};
@@ -1386,6 +1412,7 @@ static void hub_quiesce(struct usb_hub *hub, enum hub_quiescing_type type)
13861412

13871413
/* Stop hub_wq and related activity */
13881414
timer_delete_sync(&hub->irq_urb_retry);
1415+
flush_delayed_work(&hub->post_resume_work);
13891416
usb_kill_urb(hub->urb);
13901417
if (hub->has_indicators)
13911418
cancel_delayed_work_sync(&hub->leds);
@@ -1944,6 +1971,7 @@ static int hub_probe(struct usb_interface *intf, const struct usb_device_id *id)
19441971
hub->hdev = hdev;
19451972
INIT_DELAYED_WORK(&hub->leds, led_work);
19461973
INIT_DELAYED_WORK(&hub->init_work, NULL);
1974+
INIT_DELAYED_WORK(&hub->post_resume_work, hub_post_resume);
19471975
INIT_WORK(&hub->events, hub_event);
19481976
INIT_LIST_HEAD(&hub->onboard_devs);
19491977
spin_lock_init(&hub->irq_urb_lock);

drivers/usb/core/hub.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ struct usb_hub {
7070
u8 indicator[USB_MAXCHILDREN];
7171
struct delayed_work leds;
7272
struct delayed_work init_work;
73+
struct delayed_work post_resume_work;
7374
struct work_struct events;
7475
spinlock_t irq_urb_lock;
7576
struct timer_list irq_urb_retry;

0 commit comments

Comments
 (0)