Skip to content

Commit 07acd41

Browse files
committed
Merge tag 'usb-serial-7.2-rc2' of ssh://gitolite.kernel.org/pub/scm/linux/kernel/git/johan/usb-serial into usb-linus
Johan writes: USB serial fixes for 7.2-rc2 Here is a fix for an information leak in the keyspan_pda driver and three fixes for digi_acceleport addressing stuck rx if a port is closed while throttled, a hard lockup on disconnect and write buffer corruption. Included are also some new modem device ids. All have been in linux-next for a few days with no reported issues. * tag 'usb-serial-7.2-rc2' of ssh://gitolite.kernel.org/pub/scm/linux/kernel/git/johan/usb-serial: USB: serial: keyspan_pda: fix information leak USB: serial: option: add Telit Cinterion FE990D50 compositions USB: serial: digi_acceleport: fix broken rx after throttle USB: serial: digi_acceleport: fix hard lockup on disconnect USB: serial: digi_acceleport: fix write buffer corruption
2 parents 464fe6c + 6bfc8d0 commit 07acd41

3 files changed

Lines changed: 50 additions & 11 deletions

File tree

drivers/usb/serial/digi_acceleport.c

Lines changed: 33 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -392,12 +392,14 @@ static int digi_write_oob_command(struct usb_serial_port *port,
392392
len &= ~3;
393393
memcpy(oob_port->write_urb->transfer_buffer, buf, len);
394394
oob_port->write_urb->transfer_buffer_length = len;
395+
395396
ret = usb_submit_urb(oob_port->write_urb, GFP_ATOMIC);
396-
if (ret == 0) {
397-
oob_priv->dp_write_urb_in_use = 1;
398-
count -= len;
399-
buf += len;
400-
}
397+
if (ret)
398+
break;
399+
400+
oob_priv->dp_write_urb_in_use = 1;
401+
count -= len;
402+
buf += len;
401403
}
402404
spin_unlock_irqrestore(&oob_priv->dp_port_lock, flags);
403405
if (ret)
@@ -427,20 +429,22 @@ static int digi_write_inb_command(struct usb_serial_port *port,
427429
int len;
428430
struct digi_port *priv = usb_get_serial_port_data(port);
429431
unsigned char *data = port->write_urb->transfer_buffer;
432+
unsigned long expire;
430433
unsigned long flags;
431434

432435
dev_dbg(&port->dev, "digi_write_inb_command: TOP: port=%d, count=%d\n",
433436
priv->dp_port_num, count);
434437

435438
if (timeout)
436-
timeout += jiffies;
437-
else
438-
timeout = ULONG_MAX;
439+
expire = jiffies + timeout;
439440

440441
spin_lock_irqsave(&priv->dp_port_lock, flags);
441442
while (count > 0 && ret == 0) {
442-
while (priv->dp_write_urb_in_use &&
443-
time_before(jiffies, timeout)) {
443+
while (priv->dp_write_urb_in_use) {
444+
if (timeout && time_after(jiffies, expire)) {
445+
ret = -ETIMEDOUT;
446+
break;
447+
}
444448
cond_wait_interruptible_timeout_irqrestore(
445449
&priv->write_wait, DIGI_RETRY_TIMEOUT,
446450
&priv->dp_port_lock, flags);
@@ -449,6 +453,9 @@ static int digi_write_inb_command(struct usb_serial_port *port,
449453
spin_lock_irqsave(&priv->dp_port_lock, flags);
450454
}
451455

456+
if (ret)
457+
break;
458+
452459
/* len must be a multiple of 4 and small enough to */
453460
/* guarantee the write will send buffered data first, */
454461
/* so commands are in order with data and not split */
@@ -1069,6 +1076,7 @@ static int digi_open(struct tty_struct *tty, struct usb_serial_port *port)
10691076
unsigned char buf[32];
10701077
struct digi_port *priv = usb_get_serial_port_data(port);
10711078
struct ktermios not_termios;
1079+
int throttled;
10721080

10731081
/* be sure the device is started up */
10741082
if (digi_startup_device(port->serial) != 0)
@@ -1096,6 +1104,21 @@ static int digi_open(struct tty_struct *tty, struct usb_serial_port *port)
10961104
not_termios.c_iflag = ~tty->termios.c_iflag;
10971105
digi_set_termios(tty, port, &not_termios);
10981106
}
1107+
1108+
spin_lock_irq(&priv->dp_port_lock);
1109+
throttled = priv->dp_throttle_restart;
1110+
priv->dp_throttled = 0;
1111+
priv->dp_throttle_restart = 0;
1112+
spin_unlock_irq(&priv->dp_port_lock);
1113+
1114+
if (throttled) {
1115+
ret = usb_submit_urb(port->read_urb, GFP_KERNEL);
1116+
if (ret) {
1117+
dev_err(&port->dev, "failed to submit read urb: %d\n", ret);
1118+
return ret;
1119+
}
1120+
}
1121+
10991122
return 0;
11001123
}
11011124

drivers/usb/serial/keyspan_pda.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -516,7 +516,7 @@ static int keyspan_pda_write_start(struct usb_serial_port *port)
516516
if (count == room)
517517
schedule_work(&priv->unthrottle_work);
518518

519-
return count;
519+
return 0;
520520
}
521521

522522
static void keyspan_pda_write_bulk_callback(struct urb *urb)

drivers/usb/serial/option.c

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1325,6 +1325,22 @@ static const struct usb_device_id option_ids[] = {
13251325
{ USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_CC864_SINGLE) },
13261326
{ USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_DE910_DUAL) },
13271327
{ USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_UE910_V2) },
1328+
{ USB_DEVICE_AND_INTERFACE_INFO(TELIT_VENDOR_ID, 0x0990, 0xff, 0xff, 0x30), /* Telit FE990D50 (RNDIS) */
1329+
.driver_info = NCTRL(6) },
1330+
{ USB_DEVICE_AND_INTERFACE_INFO(TELIT_VENDOR_ID, 0x0990, 0xff, 0xff, 0x40) },
1331+
{ USB_DEVICE_AND_INTERFACE_INFO(TELIT_VENDOR_ID, 0x0990, 0xff, 0xff, 0x60) },
1332+
{ USB_DEVICE_AND_INTERFACE_INFO(TELIT_VENDOR_ID, 0x0991, 0xff, 0xff, 0x30), /* Telit FE990D50 (rmnet) */
1333+
.driver_info = NCTRL(5) },
1334+
{ USB_DEVICE_AND_INTERFACE_INFO(TELIT_VENDOR_ID, 0x0991, 0xff, 0xff, 0x40) },
1335+
{ USB_DEVICE_AND_INTERFACE_INFO(TELIT_VENDOR_ID, 0x0991, 0xff, 0xff, 0x60) },
1336+
{ USB_DEVICE_AND_INTERFACE_INFO(TELIT_VENDOR_ID, 0x0992, 0xff, 0xff, 0x30), /* Telit FE990D50 (MBIM) */
1337+
.driver_info = NCTRL(6) },
1338+
{ USB_DEVICE_AND_INTERFACE_INFO(TELIT_VENDOR_ID, 0x0992, 0xff, 0xff, 0x40) },
1339+
{ USB_DEVICE_AND_INTERFACE_INFO(TELIT_VENDOR_ID, 0x0992, 0xff, 0xff, 0x60) },
1340+
{ USB_DEVICE_AND_INTERFACE_INFO(TELIT_VENDOR_ID, 0x0993, 0xff, 0xff, 0x30), /* Telit FE990D50 (ECM) */
1341+
.driver_info = NCTRL(6) },
1342+
{ USB_DEVICE_AND_INTERFACE_INFO(TELIT_VENDOR_ID, 0x0993, 0xff, 0xff, 0x40) },
1343+
{ USB_DEVICE_AND_INTERFACE_INFO(TELIT_VENDOR_ID, 0x0993, 0xff, 0xff, 0x60) },
13281344
{ USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1031, 0xff), /* Telit LE910C1-EUX */
13291345
.driver_info = NCTRL(0) | RSVD(3) },
13301346
{ USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1033, 0xff), /* Telit LE910C1-EUX (ECM) */

0 commit comments

Comments
 (0)