Skip to content

Commit 3c2bd25

Browse files
committed
Merge tag 'usb-6.16-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb
Pull USB fixes from Greg KH: "Here are some USB driver fixes for 6.16-rc5. I originally wanted this to get into -rc4, but there were some regressions that had to be handled first. Now all looks good. Included in here are the following fixes: - cdns3 driver fixes - xhci driver fixes - typec driver fixes - USB hub fixes (this is what took the longest to get right) - new USB driver quirks added - chipidea driver fixes All of these have been in linux-next for a while and now we have no more reported problems with them" * tag 'usb-6.16-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb: (21 commits) usb: hub: Fix flushing of delayed work used for post resume purposes xhci: dbc: Flush queued requests before stopping dbc xhci: dbctty: disable ECHO flag by default xhci: Disable stream for xHC controller with XHCI_BROKEN_STREAMS usb: xhci: quirk for data loss in ISOC transfers usb: dwc3: gadget: Fix TRB reclaim logic for short transfers and ZLPs usb: hub: Fix flushing and scheduling of delayed work that tunes runtime pm usb: typec: displayport: Fix potential deadlock usb: typec: altmodes/displayport: do not index invalid pin_assignments usb: cdnsp: Fix issue with CV Bad Descriptor test usb: typec: tcpm: apply vbus before data bringup in tcpm_src_attach Revert "usb: xhci: Implement xhci_handshake_check_state() helper" usb: xhci: Skip xhci_reset in xhci_resume if xhci is being removed usb: gadget: u_serial: Fix race condition in TTY wakeup Revert "usb: gadget: u_serial: Add null pointer check in gs_start_io" usb: chipidea: udc: disconnect/reconnect from host when do suspend/resume usb: acpi: fix device link removal usb: hub: fix detection of high tier USB3 devices behind suspended hubs Logitech C-270 even more broken usb: dwc3: Abort suspend on soft disconnect failure ...
2 parents d46971e + 9bd9c80 commit 3c2bd25

File tree

24 files changed

+160
-85
lines changed

24 files changed

+160
-85
lines changed

drivers/usb/cdns3/cdnsp-debug.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -327,12 +327,13 @@ static inline const char *cdnsp_decode_trb(char *str, size_t size, u32 field0,
327327
case TRB_RESET_EP:
328328
case TRB_HALT_ENDPOINT:
329329
ret = scnprintf(str, size,
330-
"%s: ep%d%s(%d) ctx %08x%08x slot %ld flags %c",
330+
"%s: ep%d%s(%d) ctx %08x%08x slot %ld flags %c %c",
331331
cdnsp_trb_type_string(type),
332332
ep_num, ep_id % 2 ? "out" : "in",
333333
TRB_TO_EP_INDEX(field3), field1, field0,
334334
TRB_TO_SLOT_ID(field3),
335-
field3 & TRB_CYCLE ? 'C' : 'c');
335+
field3 & TRB_CYCLE ? 'C' : 'c',
336+
field3 & TRB_ESP ? 'P' : 'p');
336337
break;
337338
case TRB_STOP_RING:
338339
ret = scnprintf(str, size,

drivers/usb/cdns3/cdnsp-ep0.c

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -414,6 +414,7 @@ static int cdnsp_ep0_std_request(struct cdnsp_device *pdev,
414414
void cdnsp_setup_analyze(struct cdnsp_device *pdev)
415415
{
416416
struct usb_ctrlrequest *ctrl = &pdev->setup;
417+
struct cdnsp_ep *pep;
417418
int ret = -EINVAL;
418419
u16 len;
419420

@@ -427,10 +428,21 @@ void cdnsp_setup_analyze(struct cdnsp_device *pdev)
427428
goto out;
428429
}
429430

431+
pep = &pdev->eps[0];
432+
430433
/* Restore the ep0 to Stopped/Running state. */
431-
if (pdev->eps[0].ep_state & EP_HALTED) {
432-
trace_cdnsp_ep0_halted("Restore to normal state");
433-
cdnsp_halt_endpoint(pdev, &pdev->eps[0], 0);
434+
if (pep->ep_state & EP_HALTED) {
435+
if (GET_EP_CTX_STATE(pep->out_ctx) == EP_STATE_HALTED)
436+
cdnsp_halt_endpoint(pdev, pep, 0);
437+
438+
/*
439+
* Halt Endpoint Command for SSP2 for ep0 preserve current
440+
* endpoint state and driver has to synchronize the
441+
* software endpoint state with endpoint output context
442+
* state.
443+
*/
444+
pep->ep_state &= ~EP_HALTED;
445+
pep->ep_state |= EP_STOPPED;
434446
}
435447

436448
/*

drivers/usb/cdns3/cdnsp-gadget.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -987,6 +987,12 @@ enum cdnsp_setup_dev {
987987
#define STREAM_ID_FOR_TRB(p) ((((p)) << 16) & GENMASK(31, 16))
988988
#define SCT_FOR_TRB(p) (((p) << 1) & 0x7)
989989

990+
/*
991+
* Halt Endpoint Command TRB field.
992+
* The ESP bit only exists in the SSP2 controller.
993+
*/
994+
#define TRB_ESP BIT(9)
995+
990996
/* Link TRB specific fields. */
991997
#define TRB_TC BIT(1)
992998

drivers/usb/cdns3/cdnsp-ring.c

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -772,7 +772,9 @@ static int cdnsp_update_port_id(struct cdnsp_device *pdev, u32 port_id)
772772
}
773773

774774
if (port_id != old_port) {
775-
cdnsp_disable_slot(pdev);
775+
if (pdev->slot_id)
776+
cdnsp_disable_slot(pdev);
777+
776778
pdev->active_port = port;
777779
cdnsp_enable_slot(pdev);
778780
}
@@ -2483,7 +2485,8 @@ void cdnsp_queue_halt_endpoint(struct cdnsp_device *pdev, unsigned int ep_index)
24832485
{
24842486
cdnsp_queue_command(pdev, 0, 0, 0, TRB_TYPE(TRB_HALT_ENDPOINT) |
24852487
SLOT_ID_FOR_TRB(pdev->slot_id) |
2486-
EP_ID_FOR_TRB(ep_index));
2488+
EP_ID_FOR_TRB(ep_index) |
2489+
(!ep_index ? TRB_ESP : 0));
24872490
}
24882491

24892492
void cdnsp_force_header_wakeup(struct cdnsp_device *pdev, int intf_num)

drivers/usb/chipidea/udc.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2374,6 +2374,10 @@ static void udc_suspend(struct ci_hdrc *ci)
23742374
*/
23752375
if (hw_read(ci, OP_ENDPTLISTADDR, ~0) == 0)
23762376
hw_write(ci, OP_ENDPTLISTADDR, ~0, ~0);
2377+
2378+
if (ci->gadget.connected &&
2379+
(!ci->suspended || !device_may_wakeup(ci->dev)))
2380+
usb_gadget_disconnect(&ci->gadget);
23772381
}
23782382

23792383
static void udc_resume(struct ci_hdrc *ci, bool power_lost)
@@ -2384,6 +2388,9 @@ static void udc_resume(struct ci_hdrc *ci, bool power_lost)
23842388
OTGSC_BSVIS | OTGSC_BSVIE);
23852389
if (ci->vbus_active)
23862390
usb_gadget_vbus_disconnect(&ci->gadget);
2391+
} else if (ci->vbus_active && ci->driver &&
2392+
!ci->gadget.connected) {
2393+
usb_gadget_connect(&ci->gadget);
23872394
}
23882395

23892396
/* Restore value 0 if it was set for power lost check */

drivers/usb/core/hub.c

Lines changed: 31 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);
@@ -2337,6 +2365,9 @@ void usb_disconnect(struct usb_device **pdev)
23372365
usb_remove_ep_devs(&udev->ep0);
23382366
usb_unlock_device(udev);
23392367

2368+
if (udev->usb4_link)
2369+
device_link_del(udev->usb4_link);
2370+
23402371
/* Unregister the device. The device driver is responsible
23412372
* for de-configuring the device and invoking the remove-device
23422373
* notifier chain (used by usbfs and possibly others).

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;

drivers/usb/core/quirks.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -227,7 +227,8 @@ static const struct usb_device_id usb_quirk_list[] = {
227227
{ USB_DEVICE(0x046a, 0x0023), .driver_info = USB_QUIRK_RESET_RESUME },
228228

229229
/* Logitech HD Webcam C270 */
230-
{ USB_DEVICE(0x046d, 0x0825), .driver_info = USB_QUIRK_RESET_RESUME },
230+
{ USB_DEVICE(0x046d, 0x0825), .driver_info = USB_QUIRK_RESET_RESUME |
231+
USB_QUIRK_NO_LPM},
231232

232233
/* Logitech HD Pro Webcams C920, C920-C, C922, C925e and C930e */
233234
{ USB_DEVICE(0x046d, 0x082d), .driver_info = USB_QUIRK_DELAY_INIT },

drivers/usb/core/usb-acpi.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,7 @@ EXPORT_SYMBOL_GPL(usb_acpi_set_power_state);
157157
*/
158158
static int usb_acpi_add_usb4_devlink(struct usb_device *udev)
159159
{
160-
const struct device_link *link;
160+
struct device_link *link;
161161
struct usb_port *port_dev;
162162
struct usb_hub *hub;
163163

@@ -188,6 +188,8 @@ static int usb_acpi_add_usb4_devlink(struct usb_device *udev)
188188
dev_dbg(&port_dev->dev, "Created device link from %s to %s\n",
189189
dev_name(&port_dev->child->dev), dev_name(nhi_fwnode->dev));
190190

191+
udev->usb4_link = link;
192+
191193
return 0;
192194
}
193195

drivers/usb/dwc3/core.c

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2422,6 +2422,7 @@ static int dwc3_suspend_common(struct dwc3 *dwc, pm_message_t msg)
24222422
{
24232423
u32 reg;
24242424
int i;
2425+
int ret;
24252426

24262427
if (!pm_runtime_suspended(dwc->dev) && !PMSG_IS_AUTO(msg)) {
24272428
dwc->susphy_state = (dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0)) &
@@ -2440,7 +2441,9 @@ static int dwc3_suspend_common(struct dwc3 *dwc, pm_message_t msg)
24402441
case DWC3_GCTL_PRTCAP_DEVICE:
24412442
if (pm_runtime_suspended(dwc->dev))
24422443
break;
2443-
dwc3_gadget_suspend(dwc);
2444+
ret = dwc3_gadget_suspend(dwc);
2445+
if (ret)
2446+
return ret;
24442447
synchronize_irq(dwc->irq_gadget);
24452448
dwc3_core_exit(dwc);
24462449
break;
@@ -2475,7 +2478,9 @@ static int dwc3_suspend_common(struct dwc3 *dwc, pm_message_t msg)
24752478
break;
24762479

24772480
if (dwc->current_otg_role == DWC3_OTG_ROLE_DEVICE) {
2478-
dwc3_gadget_suspend(dwc);
2481+
ret = dwc3_gadget_suspend(dwc);
2482+
if (ret)
2483+
return ret;
24792484
synchronize_irq(dwc->irq_gadget);
24802485
}
24812486

0 commit comments

Comments
 (0)