Skip to content

Commit fc49583

Browse files
committed
Merge tag 'usb-5.18-rc7' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb
Pull USB fixes from Greg KH: "Here are some small fixes for reported issues with some USB drivers. They include: - xhci fixes for xhci-mtk platform driver - typec driver fixes for reported problems. - cdc-wdm read-stuck fix - gadget driver fix for reported race condition - new usb-serial driver ids All of these have been in linux-next with no reported problems" * tag 'usb-5.18-rc7' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb: usb: xhci-mtk: remove bandwidth budget table usb: xhci-mtk: fix fs isoc's transfer error usb: gadget: fix race when gadget driver register via ioctl usb: typec: tcpci_mt6360: Update for BMC PHY setting usb: gadget: uvc: allow for application to cleanly shutdown usb: typec: tcpci: Don't skip cleanup in .remove() on error usb: cdc-wdm: fix reading stuck on device close USB: serial: qcserial: add support for Sierra Wireless EM7590 USB: serial: option: add Fibocom MA510 modem USB: serial: option: add Fibocom L610 modem USB: serial: pl2303: add device id for HP LM930 Display
2 parents bc40320 + 757b9f6 commit fc49583

File tree

13 files changed

+86
-75
lines changed

13 files changed

+86
-75
lines changed

drivers/usb/class/cdc-wdm.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -774,6 +774,7 @@ static int wdm_release(struct inode *inode, struct file *file)
774774
poison_urbs(desc);
775775
spin_lock_irq(&desc->iuspin);
776776
desc->resp_count = 0;
777+
clear_bit(WDM_RESPONDING, &desc->flags);
777778
spin_unlock_irq(&desc->iuspin);
778779
desc->manage_power(desc->intf, 0);
779780
unpoison_urbs(desc);

drivers/usb/gadget/function/f_uvc.c

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -890,13 +890,37 @@ static void uvc_function_unbind(struct usb_configuration *c,
890890
{
891891
struct usb_composite_dev *cdev = c->cdev;
892892
struct uvc_device *uvc = to_uvc(f);
893+
long wait_ret = 1;
893894

894895
uvcg_info(f, "%s()\n", __func__);
895896

897+
/* If we know we're connected via v4l2, then there should be a cleanup
898+
* of the device from userspace either via UVC_EVENT_DISCONNECT or
899+
* though the video device removal uevent. Allow some time for the
900+
* application to close out before things get deleted.
901+
*/
902+
if (uvc->func_connected) {
903+
uvcg_dbg(f, "waiting for clean disconnect\n");
904+
wait_ret = wait_event_interruptible_timeout(uvc->func_connected_queue,
905+
uvc->func_connected == false, msecs_to_jiffies(500));
906+
uvcg_dbg(f, "done waiting with ret: %ld\n", wait_ret);
907+
}
908+
896909
device_remove_file(&uvc->vdev.dev, &dev_attr_function_name);
897910
video_unregister_device(&uvc->vdev);
898911
v4l2_device_unregister(&uvc->v4l2_dev);
899912

913+
if (uvc->func_connected) {
914+
/* Wait for the release to occur to ensure there are no longer any
915+
* pending operations that may cause panics when resources are cleaned
916+
* up.
917+
*/
918+
uvcg_warn(f, "%s no clean disconnect, wait for release\n", __func__);
919+
wait_ret = wait_event_interruptible_timeout(uvc->func_connected_queue,
920+
uvc->func_connected == false, msecs_to_jiffies(1000));
921+
uvcg_dbg(f, "done waiting for release with ret: %ld\n", wait_ret);
922+
}
923+
900924
usb_ep_free_request(cdev->gadget->ep0, uvc->control_req);
901925
kfree(uvc->control_buf);
902926

@@ -915,6 +939,7 @@ static struct usb_function *uvc_alloc(struct usb_function_instance *fi)
915939

916940
mutex_init(&uvc->video.mutex);
917941
uvc->state = UVC_STATE_DISCONNECTED;
942+
init_waitqueue_head(&uvc->func_connected_queue);
918943
opts = fi_to_f_uvc_opts(fi);
919944

920945
mutex_lock(&opts->lock);

drivers/usb/gadget/function/uvc.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#include <linux/spinlock.h>
1515
#include <linux/usb/composite.h>
1616
#include <linux/videodev2.h>
17+
#include <linux/wait.h>
1718

1819
#include <media/v4l2-device.h>
1920
#include <media/v4l2-dev.h>
@@ -129,6 +130,7 @@ struct uvc_device {
129130
struct usb_function func;
130131
struct uvc_video video;
131132
bool func_connected;
133+
wait_queue_head_t func_connected_queue;
132134

133135
/* Descriptors */
134136
struct {

drivers/usb/gadget/function/uvc_v4l2.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -253,10 +253,11 @@ uvc_v4l2_subscribe_event(struct v4l2_fh *fh,
253253

254254
static void uvc_v4l2_disable(struct uvc_device *uvc)
255255
{
256-
uvc->func_connected = false;
257256
uvc_function_disconnect(uvc);
258257
uvcg_video_enable(&uvc->video, 0);
259258
uvcg_free_buffers(&uvc->video.queue);
259+
uvc->func_connected = false;
260+
wake_up_interruptible(&uvc->func_connected_queue);
260261
}
261262

262263
static int

drivers/usb/gadget/legacy/raw_gadget.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,7 @@ enum dev_state {
145145
STATE_DEV_INVALID = 0,
146146
STATE_DEV_OPENED,
147147
STATE_DEV_INITIALIZED,
148+
STATE_DEV_REGISTERING,
148149
STATE_DEV_RUNNING,
149150
STATE_DEV_CLOSED,
150151
STATE_DEV_FAILED
@@ -508,6 +509,7 @@ static int raw_ioctl_run(struct raw_dev *dev, unsigned long value)
508509
ret = -EINVAL;
509510
goto out_unlock;
510511
}
512+
dev->state = STATE_DEV_REGISTERING;
511513
spin_unlock_irqrestore(&dev->lock, flags);
512514

513515
ret = usb_gadget_probe_driver(&dev->driver);

drivers/usb/host/xhci-mtk-sch.c

Lines changed: 19 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,6 @@
1919
#define HS_BW_BOUNDARY 6144
2020
/* usb2 spec section11.18.1: at most 188 FS bytes per microframe */
2121
#define FS_PAYLOAD_MAX 188
22-
/*
23-
* max number of microframes for split transfer,
24-
* for fs isoc in : 1 ss + 1 idle + 7 cs
25-
*/
26-
#define TT_MICROFRAMES_MAX 9
2722

2823
#define DBG_BUF_EN 64
2924

@@ -242,28 +237,17 @@ static void drop_tt(struct usb_device *udev)
242237

243238
static struct mu3h_sch_ep_info *
244239
create_sch_ep(struct xhci_hcd_mtk *mtk, struct usb_device *udev,
245-
struct usb_host_endpoint *ep, struct xhci_ep_ctx *ep_ctx)
240+
struct usb_host_endpoint *ep)
246241
{
247242
struct mu3h_sch_ep_info *sch_ep;
248243
struct mu3h_sch_bw_info *bw_info;
249244
struct mu3h_sch_tt *tt = NULL;
250-
u32 len_bw_budget_table;
251245

252246
bw_info = get_bw_info(mtk, udev, ep);
253247
if (!bw_info)
254248
return ERR_PTR(-ENODEV);
255249

256-
if (is_fs_or_ls(udev->speed))
257-
len_bw_budget_table = TT_MICROFRAMES_MAX;
258-
else if ((udev->speed >= USB_SPEED_SUPER)
259-
&& usb_endpoint_xfer_isoc(&ep->desc))
260-
len_bw_budget_table = get_esit(ep_ctx);
261-
else
262-
len_bw_budget_table = 1;
263-
264-
sch_ep = kzalloc(struct_size(sch_ep, bw_budget_table,
265-
len_bw_budget_table),
266-
GFP_KERNEL);
250+
sch_ep = kzalloc(sizeof(*sch_ep), GFP_KERNEL);
267251
if (!sch_ep)
268252
return ERR_PTR(-ENOMEM);
269253

@@ -295,8 +279,6 @@ static void setup_sch_info(struct xhci_ep_ctx *ep_ctx,
295279
u32 mult;
296280
u32 esit_pkts;
297281
u32 max_esit_payload;
298-
u32 *bwb_table = sch_ep->bw_budget_table;
299-
int i;
300282

301283
ep_type = CTX_TO_EP_TYPE(le32_to_cpu(ep_ctx->ep_info2));
302284
maxpkt = MAX_PACKET_DECODED(le32_to_cpu(ep_ctx->ep_info2));
@@ -332,7 +314,6 @@ static void setup_sch_info(struct xhci_ep_ctx *ep_ctx,
332314
*/
333315
sch_ep->pkts = max_burst + 1;
334316
sch_ep->bw_cost_per_microframe = maxpkt * sch_ep->pkts;
335-
bwb_table[0] = sch_ep->bw_cost_per_microframe;
336317
} else if (sch_ep->speed >= USB_SPEED_SUPER) {
337318
/* usb3_r1 spec section4.4.7 & 4.4.8 */
338319
sch_ep->cs_count = 0;
@@ -349,7 +330,6 @@ static void setup_sch_info(struct xhci_ep_ctx *ep_ctx,
349330
if (ep_type == INT_IN_EP || ep_type == INT_OUT_EP) {
350331
sch_ep->pkts = esit_pkts;
351332
sch_ep->num_budget_microframes = 1;
352-
bwb_table[0] = maxpkt * sch_ep->pkts;
353333
}
354334

355335
if (ep_type == ISOC_IN_EP || ep_type == ISOC_OUT_EP) {
@@ -366,15 +346,8 @@ static void setup_sch_info(struct xhci_ep_ctx *ep_ctx,
366346
DIV_ROUND_UP(esit_pkts, sch_ep->pkts);
367347

368348
sch_ep->repeat = !!(sch_ep->num_budget_microframes > 1);
369-
sch_ep->bw_cost_per_microframe = maxpkt * sch_ep->pkts;
370-
371-
for (i = 0; i < sch_ep->num_budget_microframes - 1; i++)
372-
bwb_table[i] = sch_ep->bw_cost_per_microframe;
373-
374-
/* last one <= bw_cost_per_microframe */
375-
bwb_table[i] = maxpkt * esit_pkts
376-
- i * sch_ep->bw_cost_per_microframe;
377349
}
350+
sch_ep->bw_cost_per_microframe = maxpkt * sch_ep->pkts;
378351
} else if (is_fs_or_ls(sch_ep->speed)) {
379352
sch_ep->pkts = 1; /* at most one packet for each microframe */
380353

@@ -384,28 +357,7 @@ static void setup_sch_info(struct xhci_ep_ctx *ep_ctx,
384357
*/
385358
sch_ep->cs_count = DIV_ROUND_UP(maxpkt, FS_PAYLOAD_MAX);
386359
sch_ep->num_budget_microframes = sch_ep->cs_count;
387-
sch_ep->bw_cost_per_microframe =
388-
(maxpkt < FS_PAYLOAD_MAX) ? maxpkt : FS_PAYLOAD_MAX;
389-
390-
/* init budget table */
391-
if (ep_type == ISOC_OUT_EP) {
392-
for (i = 0; i < sch_ep->num_budget_microframes; i++)
393-
bwb_table[i] = sch_ep->bw_cost_per_microframe;
394-
} else if (ep_type == INT_OUT_EP) {
395-
/* only first one consumes bandwidth, others as zero */
396-
bwb_table[0] = sch_ep->bw_cost_per_microframe;
397-
} else { /* INT_IN_EP or ISOC_IN_EP */
398-
bwb_table[0] = 0; /* start split */
399-
bwb_table[1] = 0; /* idle */
400-
/*
401-
* due to cs_count will be updated according to cs
402-
* position, assign all remainder budget array
403-
* elements as @bw_cost_per_microframe, but only first
404-
* @num_budget_microframes elements will be used later
405-
*/
406-
for (i = 2; i < TT_MICROFRAMES_MAX; i++)
407-
bwb_table[i] = sch_ep->bw_cost_per_microframe;
408-
}
360+
sch_ep->bw_cost_per_microframe = min_t(u32, maxpkt, FS_PAYLOAD_MAX);
409361
}
410362
}
411363

@@ -422,7 +374,7 @@ static u32 get_max_bw(struct mu3h_sch_bw_info *sch_bw,
422374

423375
for (j = 0; j < sch_ep->num_budget_microframes; j++) {
424376
k = XHCI_MTK_BW_INDEX(base + j);
425-
bw = sch_bw->bus_bw[k] + sch_ep->bw_budget_table[j];
377+
bw = sch_bw->bus_bw[k] + sch_ep->bw_cost_per_microframe;
426378
if (bw > max_bw)
427379
max_bw = bw;
428380
}
@@ -433,18 +385,16 @@ static u32 get_max_bw(struct mu3h_sch_bw_info *sch_bw,
433385
static void update_bus_bw(struct mu3h_sch_bw_info *sch_bw,
434386
struct mu3h_sch_ep_info *sch_ep, bool used)
435387
{
388+
int bw_updated;
436389
u32 base;
437-
int i, j, k;
390+
int i, j;
391+
392+
bw_updated = sch_ep->bw_cost_per_microframe * (used ? 1 : -1);
438393

439394
for (i = 0; i < sch_ep->num_esit; i++) {
440395
base = sch_ep->offset + i * sch_ep->esit;
441-
for (j = 0; j < sch_ep->num_budget_microframes; j++) {
442-
k = XHCI_MTK_BW_INDEX(base + j);
443-
if (used)
444-
sch_bw->bus_bw[k] += sch_ep->bw_budget_table[j];
445-
else
446-
sch_bw->bus_bw[k] -= sch_ep->bw_budget_table[j];
447-
}
396+
for (j = 0; j < sch_ep->num_budget_microframes; j++)
397+
sch_bw->bus_bw[XHCI_MTK_BW_INDEX(base + j)] += bw_updated;
448398
}
449399
}
450400

@@ -464,7 +414,7 @@ static int check_fs_bus_bw(struct mu3h_sch_ep_info *sch_ep, int offset)
464414
*/
465415
for (j = 0; j < sch_ep->num_budget_microframes; j++) {
466416
k = XHCI_MTK_BW_INDEX(base + j);
467-
tmp = tt->fs_bus_bw[k] + sch_ep->bw_budget_table[j];
417+
tmp = tt->fs_bus_bw[k] + sch_ep->bw_cost_per_microframe;
468418
if (tmp > FS_PAYLOAD_MAX)
469419
return -ESCH_BW_OVERFLOW;
470420
}
@@ -538,19 +488,17 @@ static int check_sch_tt(struct mu3h_sch_ep_info *sch_ep, u32 offset)
538488
static void update_sch_tt(struct mu3h_sch_ep_info *sch_ep, bool used)
539489
{
540490
struct mu3h_sch_tt *tt = sch_ep->sch_tt;
491+
int bw_updated;
541492
u32 base;
542-
int i, j, k;
493+
int i, j;
494+
495+
bw_updated = sch_ep->bw_cost_per_microframe * (used ? 1 : -1);
543496

544497
for (i = 0; i < sch_ep->num_esit; i++) {
545498
base = sch_ep->offset + i * sch_ep->esit;
546499

547-
for (j = 0; j < sch_ep->num_budget_microframes; j++) {
548-
k = XHCI_MTK_BW_INDEX(base + j);
549-
if (used)
550-
tt->fs_bus_bw[k] += sch_ep->bw_budget_table[j];
551-
else
552-
tt->fs_bus_bw[k] -= sch_ep->bw_budget_table[j];
553-
}
500+
for (j = 0; j < sch_ep->num_budget_microframes; j++)
501+
tt->fs_bus_bw[XHCI_MTK_BW_INDEX(base + j)] += bw_updated;
554502
}
555503

556504
if (used)
@@ -710,7 +658,7 @@ static int add_ep_quirk(struct usb_hcd *hcd, struct usb_device *udev,
710658

711659
xhci_dbg(xhci, "%s %s\n", __func__, decode_ep(ep, udev->speed));
712660

713-
sch_ep = create_sch_ep(mtk, udev, ep, ep_ctx);
661+
sch_ep = create_sch_ep(mtk, udev, ep);
714662
if (IS_ERR_OR_NULL(sch_ep))
715663
return -ENOMEM;
716664

drivers/usb/host/xhci-mtk.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,6 @@ struct mu3h_sch_bw_info {
8383
* times; 1: distribute the (bMaxBurst+1)*(Mult+1) packets
8484
* according to @pkts and @repeat. normal mode is used by
8585
* default
86-
* @bw_budget_table: table to record bandwidth budget per microframe
8786
*/
8887
struct mu3h_sch_ep_info {
8988
u32 esit;
@@ -109,7 +108,6 @@ struct mu3h_sch_ep_info {
109108
u32 pkts;
110109
u32 cs_count;
111110
u32 burst_mode;
112-
u32 bw_budget_table[];
113111
};
114112

115113
#define MU3C_U3_PORT_MAX 4

drivers/usb/serial/option.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2123,10 +2123,14 @@ static const struct usb_device_id option_ids[] = {
21232123
.driver_info = RSVD(3) },
21242124
{ USB_DEVICE(0x1508, 0x1001), /* Fibocom NL668 (IOT version) */
21252125
.driver_info = RSVD(4) | RSVD(5) | RSVD(6) },
2126+
{ USB_DEVICE(0x1782, 0x4d10) }, /* Fibocom L610 (AT mode) */
2127+
{ USB_DEVICE_INTERFACE_CLASS(0x1782, 0x4d11, 0xff) }, /* Fibocom L610 (ECM/RNDIS mode) */
21262128
{ USB_DEVICE(0x2cb7, 0x0104), /* Fibocom NL678 series */
21272129
.driver_info = RSVD(4) | RSVD(5) },
21282130
{ USB_DEVICE_INTERFACE_CLASS(0x2cb7, 0x0105, 0xff), /* Fibocom NL678 series */
21292131
.driver_info = RSVD(6) },
2132+
{ USB_DEVICE_INTERFACE_CLASS(0x2cb7, 0x0106, 0xff) }, /* Fibocom MA510 (ECM mode w/ diag intf.) */
2133+
{ USB_DEVICE_INTERFACE_CLASS(0x2cb7, 0x010a, 0xff) }, /* Fibocom MA510 (ECM mode) */
21302134
{ USB_DEVICE_AND_INTERFACE_INFO(0x2cb7, 0x010b, 0xff, 0xff, 0x30) }, /* Fibocom FG150 Diag */
21312135
{ USB_DEVICE_AND_INTERFACE_INFO(0x2cb7, 0x010b, 0xff, 0, 0) }, /* Fibocom FG150 AT */
21322136
{ USB_DEVICE_INTERFACE_CLASS(0x2cb7, 0x01a0, 0xff) }, /* Fibocom NL668-AM/NL652-EU (laptop MBIM) */

drivers/usb/serial/pl2303.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,7 @@ static const struct usb_device_id id_table[] = {
106106
{ USB_DEVICE(HP_VENDOR_ID, HP_LCM220_PRODUCT_ID) },
107107
{ USB_DEVICE(HP_VENDOR_ID, HP_LCM960_PRODUCT_ID) },
108108
{ USB_DEVICE(HP_VENDOR_ID, HP_LM920_PRODUCT_ID) },
109+
{ USB_DEVICE(HP_VENDOR_ID, HP_LM930_PRODUCT_ID) },
109110
{ USB_DEVICE(HP_VENDOR_ID, HP_LM940_PRODUCT_ID) },
110111
{ USB_DEVICE(HP_VENDOR_ID, HP_TD620_PRODUCT_ID) },
111112
{ USB_DEVICE(CRESSI_VENDOR_ID, CRESSI_EDY_PRODUCT_ID) },

drivers/usb/serial/pl2303.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,7 @@
135135
#define HP_TD620_PRODUCT_ID 0x0956
136136
#define HP_LD960_PRODUCT_ID 0x0b39
137137
#define HP_LD381_PRODUCT_ID 0x0f7f
138+
#define HP_LM930_PRODUCT_ID 0x0f9b
138139
#define HP_LCM220_PRODUCT_ID 0x3139
139140
#define HP_LCM960_PRODUCT_ID 0x3239
140141
#define HP_LD220_PRODUCT_ID 0x3524

0 commit comments

Comments
 (0)