Skip to content

Commit b5beaa4

Browse files
committed
Merge tag 'usb-6.10-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb
Pull USB / Thunderbolt fixes from Greg KH: "Here are some small USB and Thunderbolt driver fixes for 6.10-rc4. Included in here are: - thunderbolt debugfs bugfix - USB typec bugfixes - kcov usb bugfix - xhci bugfixes - usb-storage bugfix - dt-bindings bugfix - cdc-wdm log message spam bugfix All of these, except for the last cdc-wdm log level change, have been in linux-next for a while with no reported problems. The cdc-wdm bugfix has been tested by syzbot and proved to fix the reported cpu lockup issues when the log is constantly spammed by a broken device" * tag 'usb-6.10-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb: USB: class: cdc-wdm: Fix CPU lockup caused by excessive log messages xhci: Handle TD clearing for multiple streams case xhci: Apply broken streams quirk to Etron EJ188 xHCI host xhci: Apply reset resume quirk to Etron EJ188 xHCI host xhci: Set correct transferred length for cancelled bulk transfers usb-storage: alauda: Check whether the media is initialized usb: typec: ucsi: Ack also failed Get Error commands kcov, usb: disable interrupts in kcov_remote_start_usb_softirq dt-bindings: usb: realtek,rts5411: Add missing "additionalProperties" on child nodes usb: typec: tcpm: Ignore received Hard Reset in TOGGLING state usb: typec: tcpm: fix use-after-free case in tcpm_register_source_caps USB: xen-hcd: Traverse host/ when CONFIG_USB_XEN_HCD is selected usb: typec: ucsi: glink: increase max ports for x1e80100 Revert "usb: chipidea: move ci_ulpi_init after the phy initialization" thunderbolt: debugfs: Fix margin debugfs node creation condition
2 parents 6efc63a + 22f0081 commit b5beaa4

File tree

15 files changed

+131
-42
lines changed

15 files changed

+131
-42
lines changed

Documentation/devicetree/bindings/usb/realtek,rts5411.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ patternProperties:
6565
description: The hard wired USB devices
6666
type: object
6767
$ref: /schemas/usb/usb-device.yaml
68+
additionalProperties: true
6869

6970
required:
7071
- peer-hub

drivers/thunderbolt/debugfs.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -943,8 +943,9 @@ static void margining_port_init(struct tb_port *port)
943943
debugfs_create_file("run", 0600, dir, port, &margining_run_fops);
944944
debugfs_create_file("results", 0600, dir, port, &margining_results_fops);
945945
debugfs_create_file("test", 0600, dir, port, &margining_test_fops);
946-
if (independent_voltage_margins(usb4) ||
947-
(supports_time(usb4) && independent_time_margins(usb4)))
946+
if (independent_voltage_margins(usb4) == USB4_MARGIN_CAP_0_VOLTAGE_HL ||
947+
(supports_time(usb4) &&
948+
independent_time_margins(usb4) == USB4_MARGIN_CAP_1_TIME_LR))
948949
debugfs_create_file("margin", 0600, dir, port, &margining_margin_fops);
949950
}
950951

drivers/usb/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ obj-$(CONFIG_USB_R8A66597_HCD) += host/
3535
obj-$(CONFIG_USB_FSL_USB2) += host/
3636
obj-$(CONFIG_USB_FOTG210_HCD) += host/
3737
obj-$(CONFIG_USB_MAX3421_HCD) += host/
38+
obj-$(CONFIG_USB_XEN_HCD) += host/
3839

3940
obj-$(CONFIG_USB_C67X00_HCD) += c67x00/
4041

drivers/usb/chipidea/core.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1084,6 +1084,10 @@ static int ci_hdrc_probe(struct platform_device *pdev)
10841084
return -ENODEV;
10851085
}
10861086

1087+
ret = ci_ulpi_init(ci);
1088+
if (ret)
1089+
return ret;
1090+
10871091
if (ci->platdata->phy) {
10881092
ci->phy = ci->platdata->phy;
10891093
} else if (ci->platdata->usb_phy) {
@@ -1138,10 +1142,6 @@ static int ci_hdrc_probe(struct platform_device *pdev)
11381142
goto ulpi_exit;
11391143
}
11401144

1141-
ret = ci_ulpi_init(ci);
1142-
if (ret)
1143-
return ret;
1144-
11451145
ci->hw_bank.phys = res->start;
11461146

11471147
ci->irq = platform_get_irq(pdev, 0);

drivers/usb/chipidea/ulpi.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,11 @@ int ci_ulpi_init(struct ci_hdrc *ci)
6868
if (ci->platdata->phy_mode != USBPHY_INTERFACE_MODE_ULPI)
6969
return 0;
7070

71+
/*
72+
* Set PORTSC correctly so we can read/write ULPI registers for
73+
* identification purposes
74+
*/
75+
hw_phymode_configure(ci);
7176

7277
ci->ulpi_ops.read = ci_ulpi_read;
7378
ci->ulpi_ops.write = ci_ulpi_write;

drivers/usb/class/cdc-wdm.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -266,14 +266,14 @@ static void wdm_int_callback(struct urb *urb)
266266
dev_err(&desc->intf->dev, "Stall on int endpoint\n");
267267
goto sw; /* halt is cleared in work */
268268
default:
269-
dev_err(&desc->intf->dev,
269+
dev_err_ratelimited(&desc->intf->dev,
270270
"nonzero urb status received: %d\n", status);
271271
break;
272272
}
273273
}
274274

275275
if (urb->actual_length < sizeof(struct usb_cdc_notification)) {
276-
dev_err(&desc->intf->dev, "wdm_int_callback - %d bytes\n",
276+
dev_err_ratelimited(&desc->intf->dev, "wdm_int_callback - %d bytes\n",
277277
urb->actual_length);
278278
goto exit;
279279
}

drivers/usb/core/hcd.c

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1623,6 +1623,7 @@ static void __usb_hcd_giveback_urb(struct urb *urb)
16231623
struct usb_hcd *hcd = bus_to_hcd(urb->dev->bus);
16241624
struct usb_anchor *anchor = urb->anchor;
16251625
int status = urb->unlinked;
1626+
unsigned long flags;
16261627

16271628
urb->hcpriv = NULL;
16281629
if (unlikely((urb->transfer_flags & URB_SHORT_NOT_OK) &&
@@ -1640,13 +1641,14 @@ static void __usb_hcd_giveback_urb(struct urb *urb)
16401641
/* pass ownership to the completion handler */
16411642
urb->status = status;
16421643
/*
1643-
* This function can be called in task context inside another remote
1644-
* coverage collection section, but kcov doesn't support that kind of
1645-
* recursion yet. Only collect coverage in softirq context for now.
1644+
* Only collect coverage in the softirq context and disable interrupts
1645+
* to avoid scenarios with nested remote coverage collection sections
1646+
* that KCOV does not support.
1647+
* See the comment next to kcov_remote_start_usb_softirq() for details.
16461648
*/
1647-
kcov_remote_start_usb_softirq((u64)urb->dev->bus->busnum);
1649+
flags = kcov_remote_start_usb_softirq((u64)urb->dev->bus->busnum);
16481650
urb->complete(urb);
1649-
kcov_remote_stop_softirq();
1651+
kcov_remote_stop_softirq(flags);
16501652

16511653
usb_anchor_resume_wakeups(anchor);
16521654
atomic_dec(&urb->use_count);

drivers/usb/host/xhci-pci.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636

3737
#define PCI_VENDOR_ID_ETRON 0x1b6f
3838
#define PCI_DEVICE_ID_EJ168 0x7023
39+
#define PCI_DEVICE_ID_EJ188 0x7052
3940

4041
#define PCI_DEVICE_ID_INTEL_LYNXPOINT_XHCI 0x8c31
4142
#define PCI_DEVICE_ID_INTEL_LYNXPOINT_LP_XHCI 0x9c31
@@ -395,6 +396,12 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci)
395396
xhci->quirks |= XHCI_RESET_ON_RESUME;
396397
xhci->quirks |= XHCI_BROKEN_STREAMS;
397398
}
399+
if (pdev->vendor == PCI_VENDOR_ID_ETRON &&
400+
pdev->device == PCI_DEVICE_ID_EJ188) {
401+
xhci->quirks |= XHCI_RESET_ON_RESUME;
402+
xhci->quirks |= XHCI_BROKEN_STREAMS;
403+
}
404+
398405
if (pdev->vendor == PCI_VENDOR_ID_RENESAS &&
399406
pdev->device == 0x0014) {
400407
xhci->quirks |= XHCI_ZERO_64B_REGS;

drivers/usb/host/xhci-ring.c

Lines changed: 45 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1031,13 +1031,27 @@ static int xhci_invalidate_cancelled_tds(struct xhci_virt_ep *ep)
10311031
break;
10321032
case TD_DIRTY: /* TD is cached, clear it */
10331033
case TD_HALTED:
1034+
case TD_CLEARING_CACHE_DEFERRED:
1035+
if (cached_td) {
1036+
if (cached_td->urb->stream_id != td->urb->stream_id) {
1037+
/* Multiple streams case, defer move dq */
1038+
xhci_dbg(xhci,
1039+
"Move dq deferred: stream %u URB %p\n",
1040+
td->urb->stream_id, td->urb);
1041+
td->cancel_status = TD_CLEARING_CACHE_DEFERRED;
1042+
break;
1043+
}
1044+
1045+
/* Should never happen, but clear the TD if it does */
1046+
xhci_warn(xhci,
1047+
"Found multiple active URBs %p and %p in stream %u?\n",
1048+
td->urb, cached_td->urb,
1049+
td->urb->stream_id);
1050+
td_to_noop(xhci, ring, cached_td, false);
1051+
cached_td->cancel_status = TD_CLEARED;
1052+
}
1053+
10341054
td->cancel_status = TD_CLEARING_CACHE;
1035-
if (cached_td)
1036-
/* FIXME stream case, several stopped rings */
1037-
xhci_dbg(xhci,
1038-
"Move dq past stream %u URB %p instead of stream %u URB %p\n",
1039-
td->urb->stream_id, td->urb,
1040-
cached_td->urb->stream_id, cached_td->urb);
10411055
cached_td = td;
10421056
break;
10431057
}
@@ -1057,10 +1071,16 @@ static int xhci_invalidate_cancelled_tds(struct xhci_virt_ep *ep)
10571071
if (err) {
10581072
/* Failed to move past cached td, just set cached TDs to no-op */
10591073
list_for_each_entry_safe(td, tmp_td, &ep->cancelled_td_list, cancelled_td_list) {
1060-
if (td->cancel_status != TD_CLEARING_CACHE)
1074+
/*
1075+
* Deferred TDs need to have the deq pointer set after the above command
1076+
* completes, so if that failed we just give up on all of them (and
1077+
* complain loudly since this could cause issues due to caching).
1078+
*/
1079+
if (td->cancel_status != TD_CLEARING_CACHE &&
1080+
td->cancel_status != TD_CLEARING_CACHE_DEFERRED)
10611081
continue;
1062-
xhci_dbg(xhci, "Failed to clear cancelled cached URB %p, mark clear anyway\n",
1063-
td->urb);
1082+
xhci_warn(xhci, "Failed to clear cancelled cached URB %p, mark clear anyway\n",
1083+
td->urb);
10641084
td_to_noop(xhci, ring, td, false);
10651085
td->cancel_status = TD_CLEARED;
10661086
}
@@ -1346,6 +1366,7 @@ static void xhci_handle_cmd_set_deq(struct xhci_hcd *xhci, int slot_id,
13461366
struct xhci_ep_ctx *ep_ctx;
13471367
struct xhci_slot_ctx *slot_ctx;
13481368
struct xhci_td *td, *tmp_td;
1369+
bool deferred = false;
13491370

13501371
ep_index = TRB_TO_EP_INDEX(le32_to_cpu(trb->generic.field[3]));
13511372
stream_id = TRB_TO_STREAM_ID(le32_to_cpu(trb->generic.field[2]));
@@ -1432,6 +1453,8 @@ static void xhci_handle_cmd_set_deq(struct xhci_hcd *xhci, int slot_id,
14321453
xhci_dbg(ep->xhci, "%s: Giveback cancelled URB %p TD\n",
14331454
__func__, td->urb);
14341455
xhci_td_cleanup(ep->xhci, td, ep_ring, td->status);
1456+
} else if (td->cancel_status == TD_CLEARING_CACHE_DEFERRED) {
1457+
deferred = true;
14351458
} else {
14361459
xhci_dbg(ep->xhci, "%s: Keep cancelled URB %p TD as cancel_status is %d\n",
14371460
__func__, td->urb, td->cancel_status);
@@ -1441,8 +1464,17 @@ static void xhci_handle_cmd_set_deq(struct xhci_hcd *xhci, int slot_id,
14411464
ep->ep_state &= ~SET_DEQ_PENDING;
14421465
ep->queued_deq_seg = NULL;
14431466
ep->queued_deq_ptr = NULL;
1444-
/* Restart any rings with pending URBs */
1445-
ring_doorbell_for_active_rings(xhci, slot_id, ep_index);
1467+
1468+
if (deferred) {
1469+
/* We have more streams to clear */
1470+
xhci_dbg(ep->xhci, "%s: Pending TDs to clear, continuing with invalidation\n",
1471+
__func__);
1472+
xhci_invalidate_cancelled_tds(ep);
1473+
} else {
1474+
/* Restart any rings with pending URBs */
1475+
xhci_dbg(ep->xhci, "%s: All TDs cleared, ring doorbell\n", __func__);
1476+
ring_doorbell_for_active_rings(xhci, slot_id, ep_index);
1477+
}
14461478
}
14471479

14481480
static void xhci_handle_cmd_reset_ep(struct xhci_hcd *xhci, int slot_id,
@@ -2524,9 +2556,8 @@ static int process_bulk_intr_td(struct xhci_hcd *xhci, struct xhci_virt_ep *ep,
25242556
goto finish_td;
25252557
case COMP_STOPPED_LENGTH_INVALID:
25262558
/* stopped on ep trb with invalid length, exclude it */
2527-
ep_trb_len = 0;
2528-
remaining = 0;
2529-
break;
2559+
td->urb->actual_length = sum_trb_lengths(xhci, ep_ring, ep_trb);
2560+
goto finish_td;
25302561
case COMP_USB_TRANSACTION_ERROR:
25312562
if (xhci->quirks & XHCI_NO_SOFT_RETRY ||
25322563
(ep->err_count++ > MAX_SOFT_RETRY) ||

drivers/usb/host/xhci.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1276,6 +1276,7 @@ enum xhci_cancelled_td_status {
12761276
TD_DIRTY = 0,
12771277
TD_HALTED,
12781278
TD_CLEARING_CACHE,
1279+
TD_CLEARING_CACHE_DEFERRED,
12791280
TD_CLEARED,
12801281
};
12811282

drivers/usb/storage/alauda.c

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,8 @@ struct alauda_info {
105105
unsigned char sense_key;
106106
unsigned long sense_asc; /* additional sense code */
107107
unsigned long sense_ascq; /* additional sense code qualifier */
108+
109+
bool media_initialized;
108110
};
109111

110112
#define short_pack(lsb,msb) ( ((u16)(lsb)) | ( ((u16)(msb))<<8 ) )
@@ -476,11 +478,12 @@ static int alauda_check_media(struct us_data *us)
476478
}
477479

478480
/* Check for media change */
479-
if (status[0] & 0x08) {
481+
if (status[0] & 0x08 || !info->media_initialized) {
480482
usb_stor_dbg(us, "Media change detected\n");
481483
alauda_free_maps(&MEDIA_INFO(us));
482-
alauda_init_media(us);
483-
484+
rc = alauda_init_media(us);
485+
if (rc == USB_STOR_TRANSPORT_GOOD)
486+
info->media_initialized = true;
484487
info->sense_key = UNIT_ATTENTION;
485488
info->sense_asc = 0x28;
486489
info->sense_ascq = 0x00;

drivers/usb/typec/tcpm/tcpm.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3014,8 +3014,10 @@ static int tcpm_register_source_caps(struct tcpm_port *port)
30143014
memcpy(caps.pdo, port->source_caps, sizeof(u32) * port->nr_source_caps);
30153015
caps.role = TYPEC_SOURCE;
30163016

3017-
if (cap)
3017+
if (cap) {
30183018
usb_power_delivery_unregister_capabilities(cap);
3019+
port->partner_source_caps = NULL;
3020+
}
30193021

30203022
cap = usb_power_delivery_register_capabilities(port->partner_pd, &caps);
30213023
if (IS_ERR(cap))
@@ -6172,6 +6174,7 @@ static void _tcpm_pd_hard_reset(struct tcpm_port *port)
61726174
port->tcpc->set_bist_data(port->tcpc, false);
61736175

61746176
switch (port->state) {
6177+
case TOGGLING:
61756178
case ERROR_RECOVERY:
61766179
case PORT_RESET:
61776180
case PORT_RESET_WAIT_OFF:

drivers/usb/typec/ucsi/ucsi.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -153,8 +153,13 @@ static int ucsi_exec_command(struct ucsi *ucsi, u64 cmd)
153153
}
154154

155155
if (cci & UCSI_CCI_ERROR) {
156-
if (cmd == UCSI_GET_ERROR_STATUS)
156+
if (cmd == UCSI_GET_ERROR_STATUS) {
157+
ret = ucsi_acknowledge(ucsi, false);
158+
if (ret)
159+
return ret;
160+
157161
return -EIO;
162+
}
158163
return ucsi_read_error(ucsi);
159164
}
160165

drivers/usb/typec/ucsi/ucsi_glink.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
#include <linux/soc/qcom/pmic_glink.h>
1515
#include "ucsi.h"
1616

17-
#define PMIC_GLINK_MAX_PORTS 2
17+
#define PMIC_GLINK_MAX_PORTS 3
1818

1919
#define UCSI_BUF_SIZE 48
2020

include/linux/kcov.h

Lines changed: 38 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -55,21 +55,47 @@ static inline void kcov_remote_start_usb(u64 id)
5555

5656
/*
5757
* The softirq flavor of kcov_remote_*() functions is introduced as a temporary
58-
* work around for kcov's lack of nested remote coverage sections support in
59-
* task context. Adding support for nested sections is tracked in:
60-
* https://bugzilla.kernel.org/show_bug.cgi?id=210337
58+
* workaround for KCOV's lack of nested remote coverage sections support.
59+
*
60+
* Adding support is tracked in https://bugzilla.kernel.org/show_bug.cgi?id=210337.
61+
*
62+
* kcov_remote_start_usb_softirq():
63+
*
64+
* 1. Only collects coverage when called in the softirq context. This allows
65+
* avoiding nested remote coverage collection sections in the task context.
66+
* For example, USB/IP calls usb_hcd_giveback_urb() in the task context
67+
* within an existing remote coverage collection section. Thus, KCOV should
68+
* not attempt to start collecting coverage within the coverage collection
69+
* section in __usb_hcd_giveback_urb() in this case.
70+
*
71+
* 2. Disables interrupts for the duration of the coverage collection section.
72+
* This allows avoiding nested remote coverage collection sections in the
73+
* softirq context (a softirq might occur during the execution of a work in
74+
* the BH workqueue, which runs with in_serving_softirq() > 0).
75+
* For example, usb_giveback_urb_bh() runs in the BH workqueue with
76+
* interrupts enabled, so __usb_hcd_giveback_urb() might be interrupted in
77+
* the middle of its remote coverage collection section, and the interrupt
78+
* handler might invoke __usb_hcd_giveback_urb() again.
6179
*/
6280

63-
static inline void kcov_remote_start_usb_softirq(u64 id)
81+
static inline unsigned long kcov_remote_start_usb_softirq(u64 id)
6482
{
65-
if (in_serving_softirq())
83+
unsigned long flags = 0;
84+
85+
if (in_serving_softirq()) {
86+
local_irq_save(flags);
6687
kcov_remote_start_usb(id);
88+
}
89+
90+
return flags;
6791
}
6892

69-
static inline void kcov_remote_stop_softirq(void)
93+
static inline void kcov_remote_stop_softirq(unsigned long flags)
7094
{
71-
if (in_serving_softirq())
95+
if (in_serving_softirq()) {
7296
kcov_remote_stop();
97+
local_irq_restore(flags);
98+
}
7399
}
74100

75101
#ifdef CONFIG_64BIT
@@ -103,8 +129,11 @@ static inline u64 kcov_common_handle(void)
103129
}
104130
static inline void kcov_remote_start_common(u64 id) {}
105131
static inline void kcov_remote_start_usb(u64 id) {}
106-
static inline void kcov_remote_start_usb_softirq(u64 id) {}
107-
static inline void kcov_remote_stop_softirq(void) {}
132+
static inline unsigned long kcov_remote_start_usb_softirq(u64 id)
133+
{
134+
return 0;
135+
}
136+
static inline void kcov_remote_stop_softirq(unsigned long flags) {}
108137

109138
#endif /* CONFIG_KCOV */
110139
#endif /* _LINUX_KCOV_H */

0 commit comments

Comments
 (0)