Skip to content

Commit b68c189

Browse files
committed
Merge tag 'usb-6.12-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb
Pull USB driver fixes from Greg KH: "Here are some small USB driver fixes and new device ids for 6.12-rc4: - xhci driver fixes for a number of reported issues - new usb-serial driver ids - dwc3 driver fixes for reported problems. - usb gadget driver fixes for reported problems - typec driver fixes - MAINTAINER file updates All of these have been in linux-next this week with no reported issues" * tag 'usb-6.12-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb: USB: serial: option: add Telit FN920C04 MBIM compositions USB: serial: option: add support for Quectel EG916Q-GL xhci: dbc: honor usb transfer size boundaries. usb: xhci: Fix handling errors mid TD followed by other errors xhci: Mitigate failed set dequeue pointer commands xhci: Fix incorrect stream context type macro USB: gadget: dummy-hcd: Fix "task hung" problem usb: gadget: f_uac2: fix return value for UAC2_ATTRIBUTE_STRING store usb: dwc3: core: Fix system suspend on TI AM62 platforms xhci: tegra: fix checked USB2 port number usb: dwc3: Wait for EndXfer completion before restoring GUSB2PHYCFG usb: typec: qcom-pmic-typec: fix sink status being overwritten with RP_DEF usb: typec: altmode should keep reference to parent MAINTAINERS: usb: raw-gadget: add bug tracker link MAINTAINERS: Add an entry for the LJCA drivers
2 parents db87114 + 1154a59 commit b68c189

File tree

14 files changed

+151
-58
lines changed

14 files changed

+151
-58
lines changed

MAINTAINERS

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11604,6 +11604,16 @@ F: drivers/crypto/intel/keembay/keembay-ocs-hcu-core.c
1160411604
F: drivers/crypto/intel/keembay/ocs-hcu.c
1160511605
F: drivers/crypto/intel/keembay/ocs-hcu.h
1160611606

11607+
INTEL LA JOLLA COVE ADAPTER (LJCA) USB I/O EXPANDER DRIVERS
11608+
M: Wentong Wu <wentong.wu@intel.com>
11609+
M: Sakari Ailus <sakari.ailus@linux.intel.com>
11610+
S: Maintained
11611+
F: drivers/gpio/gpio-ljca.c
11612+
F: drivers/i2c/busses/i2c-ljca.c
11613+
F: drivers/spi/spi-ljca.c
11614+
F: drivers/usb/misc/usb-ljca.c
11615+
F: include/linux/usb/ljca.h
11616+
1160711617
INTEL MANAGEMENT ENGINE (mei)
1160811618
M: Tomas Winkler <tomas.winkler@intel.com>
1160911619
L: linux-kernel@vger.kernel.org
@@ -24078,6 +24088,7 @@ USB RAW GADGET DRIVER
2407824088
R: Andrey Konovalov <andreyknvl@gmail.com>
2407924089
L: linux-usb@vger.kernel.org
2408024090
S: Maintained
24091+
B: https://github.com/xairy/raw-gadget/issues
2408124092
F: Documentation/usb/raw-gadget.rst
2408224093
F: drivers/usb/gadget/legacy/raw_gadget.c
2408324094
F: include/uapi/linux/usb/raw_gadget.h

drivers/usb/dwc3/core.c

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2342,6 +2342,11 @@ static int dwc3_suspend_common(struct dwc3 *dwc, pm_message_t msg)
23422342
u32 reg;
23432343
int i;
23442344

2345+
dwc->susphy_state = (dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0)) &
2346+
DWC3_GUSB2PHYCFG_SUSPHY) ||
2347+
(dwc3_readl(dwc->regs, DWC3_GUSB3PIPECTL(0)) &
2348+
DWC3_GUSB3PIPECTL_SUSPHY);
2349+
23452350
switch (dwc->current_dr_role) {
23462351
case DWC3_GCTL_PRTCAP_DEVICE:
23472352
if (pm_runtime_suspended(dwc->dev))
@@ -2393,6 +2398,15 @@ static int dwc3_suspend_common(struct dwc3 *dwc, pm_message_t msg)
23932398
break;
23942399
}
23952400

2401+
if (!PMSG_IS_AUTO(msg)) {
2402+
/*
2403+
* TI AM62 platform requires SUSPHY to be
2404+
* enabled for system suspend to work.
2405+
*/
2406+
if (!dwc->susphy_state)
2407+
dwc3_enable_susphy(dwc, true);
2408+
}
2409+
23962410
return 0;
23972411
}
23982412

@@ -2460,6 +2474,11 @@ static int dwc3_resume_common(struct dwc3 *dwc, pm_message_t msg)
24602474
break;
24612475
}
24622476

2477+
if (!PMSG_IS_AUTO(msg)) {
2478+
/* restore SUSPHY state to that before system suspend. */
2479+
dwc3_enable_susphy(dwc, dwc->susphy_state);
2480+
}
2481+
24632482
return 0;
24642483
}
24652484

drivers/usb/dwc3/core.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1150,6 +1150,8 @@ struct dwc3_scratchpad_array {
11501150
* @sys_wakeup: set if the device may do system wakeup.
11511151
* @wakeup_configured: set if the device is configured for remote wakeup.
11521152
* @suspended: set to track suspend event due to U3/L2.
1153+
* @susphy_state: state of DWC3_GUSB2PHYCFG_SUSPHY + DWC3_GUSB3PIPECTL_SUSPHY
1154+
* before PM suspend.
11531155
* @imod_interval: set the interrupt moderation interval in 250ns
11541156
* increments or 0 to disable.
11551157
* @max_cfg_eps: current max number of IN eps used across all USB configs.
@@ -1382,6 +1384,7 @@ struct dwc3 {
13821384
unsigned sys_wakeup:1;
13831385
unsigned wakeup_configured:1;
13841386
unsigned suspended:1;
1387+
unsigned susphy_state:1;
13851388

13861389
u16 imod_interval;
13871390

drivers/usb/dwc3/gadget.c

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -438,6 +438,10 @@ int dwc3_send_gadget_ep_cmd(struct dwc3_ep *dep, unsigned int cmd,
438438
dwc3_gadget_ep_get_transfer_index(dep);
439439
}
440440

441+
if (DWC3_DEPCMD_CMD(cmd) == DWC3_DEPCMD_ENDTRANSFER &&
442+
!(cmd & DWC3_DEPCMD_CMDIOC))
443+
mdelay(1);
444+
441445
if (saved_config) {
442446
reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0));
443447
reg |= saved_config;
@@ -1715,12 +1719,10 @@ static int __dwc3_stop_active_transfer(struct dwc3_ep *dep, bool force, bool int
17151719
WARN_ON_ONCE(ret);
17161720
dep->resource_index = 0;
17171721

1718-
if (!interrupt) {
1719-
mdelay(1);
1722+
if (!interrupt)
17201723
dep->flags &= ~DWC3_EP_TRANSFER_STARTED;
1721-
} else if (!ret) {
1724+
else if (!ret)
17221725
dep->flags |= DWC3_EP_END_TRANSFER_PENDING;
1723-
}
17241726

17251727
dep->flags &= ~DWC3_EP_DELAY_STOP;
17261728
return ret;

drivers/usb/gadget/function/f_uac2.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2061,7 +2061,7 @@ static ssize_t f_uac2_opts_##name##_store(struct config_item *item, \
20612061
const char *page, size_t len) \
20622062
{ \
20632063
struct f_uac2_opts *opts = to_f_uac2_opts(item); \
2064-
int ret = 0; \
2064+
int ret = len; \
20652065
\
20662066
mutex_lock(&opts->lock); \
20672067
if (opts->refcnt) { \
@@ -2072,8 +2072,8 @@ static ssize_t f_uac2_opts_##name##_store(struct config_item *item, \
20722072
if (len && page[len - 1] == '\n') \
20732073
len--; \
20742074
\
2075-
ret = scnprintf(opts->name, min(sizeof(opts->name), len + 1), \
2076-
"%s", page); \
2075+
scnprintf(opts->name, min(sizeof(opts->name), len + 1), \
2076+
"%s", page); \
20772077
\
20782078
end: \
20792079
mutex_unlock(&opts->lock); \

drivers/usb/gadget/udc/dummy_hcd.c

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -254,6 +254,7 @@ struct dummy_hcd {
254254
u32 stream_en_ep;
255255
u8 num_stream[30 / 2];
256256

257+
unsigned timer_pending:1;
257258
unsigned active:1;
258259
unsigned old_active:1;
259260
unsigned resuming:1;
@@ -1303,9 +1304,11 @@ static int dummy_urb_enqueue(
13031304
urb->error_count = 1; /* mark as a new urb */
13041305

13051306
/* kick the scheduler, it'll do the rest */
1306-
if (!hrtimer_active(&dum_hcd->timer))
1307+
if (!dum_hcd->timer_pending) {
1308+
dum_hcd->timer_pending = 1;
13071309
hrtimer_start(&dum_hcd->timer, ns_to_ktime(DUMMY_TIMER_INT_NSECS),
13081310
HRTIMER_MODE_REL_SOFT);
1311+
}
13091312

13101313
done:
13111314
spin_unlock_irqrestore(&dum_hcd->dum->lock, flags);
@@ -1324,9 +1327,10 @@ static int dummy_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
13241327
spin_lock_irqsave(&dum_hcd->dum->lock, flags);
13251328

13261329
rc = usb_hcd_check_unlink_urb(hcd, urb, status);
1327-
if (!rc && dum_hcd->rh_state != DUMMY_RH_RUNNING &&
1328-
!list_empty(&dum_hcd->urbp_list))
1330+
if (rc == 0 && !dum_hcd->timer_pending) {
1331+
dum_hcd->timer_pending = 1;
13291332
hrtimer_start(&dum_hcd->timer, ns_to_ktime(0), HRTIMER_MODE_REL_SOFT);
1333+
}
13301334

13311335
spin_unlock_irqrestore(&dum_hcd->dum->lock, flags);
13321336
return rc;
@@ -1813,6 +1817,7 @@ static enum hrtimer_restart dummy_timer(struct hrtimer *t)
18131817

18141818
/* look at each urb queued by the host side driver */
18151819
spin_lock_irqsave(&dum->lock, flags);
1820+
dum_hcd->timer_pending = 0;
18161821

18171822
if (!dum_hcd->udev) {
18181823
dev_err(dummy_dev(dum_hcd),
@@ -1994,8 +1999,10 @@ static enum hrtimer_restart dummy_timer(struct hrtimer *t)
19941999
if (list_empty(&dum_hcd->urbp_list)) {
19952000
usb_put_dev(dum_hcd->udev);
19962001
dum_hcd->udev = NULL;
1997-
} else if (dum_hcd->rh_state == DUMMY_RH_RUNNING) {
2002+
} else if (!dum_hcd->timer_pending &&
2003+
dum_hcd->rh_state == DUMMY_RH_RUNNING) {
19982004
/* want a 1 msec delay here */
2005+
dum_hcd->timer_pending = 1;
19992006
hrtimer_start(&dum_hcd->timer, ns_to_ktime(DUMMY_TIMER_INT_NSECS),
20002007
HRTIMER_MODE_REL_SOFT);
20012008
}
@@ -2390,8 +2397,10 @@ static int dummy_bus_resume(struct usb_hcd *hcd)
23902397
} else {
23912398
dum_hcd->rh_state = DUMMY_RH_RUNNING;
23922399
set_link_state(dum_hcd);
2393-
if (!list_empty(&dum_hcd->urbp_list))
2400+
if (!list_empty(&dum_hcd->urbp_list)) {
2401+
dum_hcd->timer_pending = 1;
23942402
hrtimer_start(&dum_hcd->timer, ns_to_ktime(0), HRTIMER_MODE_REL_SOFT);
2403+
}
23952404
hcd->state = HC_STATE_RUNNING;
23962405
}
23972406
spin_unlock_irq(&dum_hcd->dum->lock);
@@ -2522,6 +2531,7 @@ static void dummy_stop(struct usb_hcd *hcd)
25222531
struct dummy_hcd *dum_hcd = hcd_to_dummy_hcd(hcd);
25232532

25242533
hrtimer_cancel(&dum_hcd->timer);
2534+
dum_hcd->timer_pending = 0;
25252535
device_remove_file(dummy_dev(dum_hcd), &dev_attr_urbs);
25262536
dev_info(dummy_dev(dum_hcd), "stopped\n");
25272537
}

drivers/usb/host/xhci-dbgcap.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,7 @@ struct dbc_port {
110110
struct tasklet_struct push;
111111

112112
struct list_head write_pool;
113+
unsigned int tx_boundary;
113114

114115
bool registered;
115116
};

drivers/usb/host/xhci-dbgtty.c

Lines changed: 50 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,29 @@ static inline struct dbc_port *dbc_to_port(struct xhci_dbc *dbc)
2424
return dbc->priv;
2525
}
2626

27+
static unsigned int
28+
dbc_kfifo_to_req(struct dbc_port *port, char *packet)
29+
{
30+
unsigned int len;
31+
32+
len = kfifo_len(&port->port.xmit_fifo);
33+
34+
if (len == 0)
35+
return 0;
36+
37+
len = min(len, DBC_MAX_PACKET);
38+
39+
if (port->tx_boundary)
40+
len = min(port->tx_boundary, len);
41+
42+
len = kfifo_out(&port->port.xmit_fifo, packet, len);
43+
44+
if (port->tx_boundary)
45+
port->tx_boundary -= len;
46+
47+
return len;
48+
}
49+
2750
static int dbc_start_tx(struct dbc_port *port)
2851
__releases(&port->port_lock)
2952
__acquires(&port->port_lock)
@@ -36,7 +59,7 @@ static int dbc_start_tx(struct dbc_port *port)
3659

3760
while (!list_empty(pool)) {
3861
req = list_entry(pool->next, struct dbc_request, list_pool);
39-
len = kfifo_out(&port->port.xmit_fifo, req->buf, DBC_MAX_PACKET);
62+
len = dbc_kfifo_to_req(port, req->buf);
4063
if (len == 0)
4164
break;
4265
do_tty_wake = true;
@@ -200,14 +223,32 @@ static ssize_t dbc_tty_write(struct tty_struct *tty, const u8 *buf,
200223
{
201224
struct dbc_port *port = tty->driver_data;
202225
unsigned long flags;
226+
unsigned int written = 0;
203227

204228
spin_lock_irqsave(&port->port_lock, flags);
205-
if (count)
206-
count = kfifo_in(&port->port.xmit_fifo, buf, count);
207-
dbc_start_tx(port);
229+
230+
/*
231+
* Treat tty write as one usb transfer. Make sure the writes are turned
232+
* into TRB request having the same size boundaries as the tty writes.
233+
* Don't add data to kfifo before previous write is turned into TRBs
234+
*/
235+
if (port->tx_boundary) {
236+
spin_unlock_irqrestore(&port->port_lock, flags);
237+
return 0;
238+
}
239+
240+
if (count) {
241+
written = kfifo_in(&port->port.xmit_fifo, buf, count);
242+
243+
if (written == count)
244+
port->tx_boundary = kfifo_len(&port->port.xmit_fifo);
245+
246+
dbc_start_tx(port);
247+
}
248+
208249
spin_unlock_irqrestore(&port->port_lock, flags);
209250

210-
return count;
251+
return written;
211252
}
212253

213254
static int dbc_tty_put_char(struct tty_struct *tty, u8 ch)
@@ -241,6 +282,10 @@ static unsigned int dbc_tty_write_room(struct tty_struct *tty)
241282

242283
spin_lock_irqsave(&port->port_lock, flags);
243284
room = kfifo_avail(&port->port.xmit_fifo);
285+
286+
if (port->tx_boundary)
287+
room = 0;
288+
244289
spin_unlock_irqrestore(&port->port_lock, flags);
245290

246291
return room;

drivers/usb/host/xhci-ring.c

Lines changed: 30 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1023,7 +1023,7 @@ static int xhci_invalidate_cancelled_tds(struct xhci_virt_ep *ep)
10231023
td_to_noop(xhci, ring, cached_td, false);
10241024
cached_td->cancel_status = TD_CLEARED;
10251025
}
1026-
1026+
td_to_noop(xhci, ring, td, false);
10271027
td->cancel_status = TD_CLEARING_CACHE;
10281028
cached_td = td;
10291029
break;
@@ -2775,6 +2775,29 @@ static int handle_tx_event(struct xhci_hcd *xhci,
27752775
return 0;
27762776
}
27772777

2778+
/*
2779+
* xhci 4.10.2 states isoc endpoints should continue
2780+
* processing the next TD if there was an error mid TD.
2781+
* So host like NEC don't generate an event for the last
2782+
* isoc TRB even if the IOC flag is set.
2783+
* xhci 4.9.1 states that if there are errors in mult-TRB
2784+
* TDs xHC should generate an error for that TRB, and if xHC
2785+
* proceeds to the next TD it should genete an event for
2786+
* any TRB with IOC flag on the way. Other host follow this.
2787+
*
2788+
* We wait for the final IOC event, but if we get an event
2789+
* anywhere outside this TD, just give it back already.
2790+
*/
2791+
td = list_first_entry_or_null(&ep_ring->td_list, struct xhci_td, td_list);
2792+
2793+
if (td && td->error_mid_td && !trb_in_td(xhci, td, ep_trb_dma, false)) {
2794+
xhci_dbg(xhci, "Missing TD completion event after mid TD error\n");
2795+
ep_ring->dequeue = td->last_trb;
2796+
ep_ring->deq_seg = td->last_trb_seg;
2797+
inc_deq(xhci, ep_ring);
2798+
xhci_td_cleanup(xhci, td, ep_ring, td->status);
2799+
}
2800+
27782801
if (list_empty(&ep_ring->td_list)) {
27792802
/*
27802803
* Don't print wanings if ring is empty due to a stopped endpoint generating an
@@ -2836,44 +2859,13 @@ static int handle_tx_event(struct xhci_hcd *xhci,
28362859
return 0;
28372860
}
28382861

2839-
/*
2840-
* xhci 4.10.2 states isoc endpoints should continue
2841-
* processing the next TD if there was an error mid TD.
2842-
* So host like NEC don't generate an event for the last
2843-
* isoc TRB even if the IOC flag is set.
2844-
* xhci 4.9.1 states that if there are errors in mult-TRB
2845-
* TDs xHC should generate an error for that TRB, and if xHC
2846-
* proceeds to the next TD it should genete an event for
2847-
* any TRB with IOC flag on the way. Other host follow this.
2848-
* So this event might be for the next TD.
2849-
*/
2850-
if (td->error_mid_td &&
2851-
!list_is_last(&td->td_list, &ep_ring->td_list)) {
2852-
struct xhci_td *td_next = list_next_entry(td, td_list);
2853-
2854-
ep_seg = trb_in_td(xhci, td_next, ep_trb_dma, false);
2855-
if (ep_seg) {
2856-
/* give back previous TD, start handling new */
2857-
xhci_dbg(xhci, "Missing TD completion event after mid TD error\n");
2858-
ep_ring->dequeue = td->last_trb;
2859-
ep_ring->deq_seg = td->last_trb_seg;
2860-
inc_deq(xhci, ep_ring);
2861-
xhci_td_cleanup(xhci, td, ep_ring, td->status);
2862-
td = td_next;
2863-
}
2864-
}
2865-
2866-
if (!ep_seg) {
2867-
/* HC is busted, give up! */
2868-
xhci_err(xhci,
2869-
"ERROR Transfer event TRB DMA ptr not "
2870-
"part of current TD ep_index %d "
2871-
"comp_code %u\n", ep_index,
2872-
trb_comp_code);
2873-
trb_in_td(xhci, td, ep_trb_dma, true);
2862+
/* HC is busted, give up! */
2863+
xhci_err(xhci,
2864+
"ERROR Transfer event TRB DMA ptr not part of current TD ep_index %d comp_code %u\n",
2865+
ep_index, trb_comp_code);
2866+
trb_in_td(xhci, td, ep_trb_dma, true);
28742867

2875-
return -ESHUTDOWN;
2876-
}
2868+
return -ESHUTDOWN;
28772869
}
28782870

28792871
if (ep->skip) {

drivers/usb/host/xhci-tegra.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2183,7 +2183,7 @@ static int tegra_xusb_enter_elpg(struct tegra_xusb *tegra, bool runtime)
21832183
goto out;
21842184
}
21852185

2186-
for (i = 0; i < tegra->num_usb_phys; i++) {
2186+
for (i = 0; i < xhci->usb2_rhub.num_ports; i++) {
21872187
if (!xhci->usb2_rhub.ports[i])
21882188
continue;
21892189
portsc = readl(xhci->usb2_rhub.ports[i]->addr);

0 commit comments

Comments
 (0)