diff options
author | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2017-01-05 11:41:16 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2017-01-05 11:41:16 -0500 |
commit | c8d204b38a558d74fafb6915e2593602b7f4b823 (patch) | |
tree | d4e076845e4d6dfbef70b1f4740e8fa246958059 /drivers/usb | |
parent | 29fc1aa454d0603493b47a8e2410ae6e9ab20258 (diff) | |
parent | ef079936d3cd09e63612834fe2698eeada0d8e3f (diff) |
Merge tag 'usb-serial-4.10-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/johan/usb-serial into usb-linus
Johan writes:
USB-serial fixes for v4.10-rc3
These fixes address a number of long-standing issues in various
USB-serial drivers which would lead to crashes should a malicious device
lack the expected endpoints.
Included are also a few related fixes, and a couple of unrelated ones
that were found during my survey (e.g. a memleak and a
sleep-while-atomic).
A compiler warning revealed an error-handling issue in the new f81534
driver which is also fixed.
Signed-off-by: Johan Hovold <johan@kernel.org>
Diffstat (limited to 'drivers/usb')
-rw-r--r-- | drivers/usb/serial/cyberjack.c | 10 | ||||
-rw-r--r-- | drivers/usb/serial/f81534.c | 8 | ||||
-rw-r--r-- | drivers/usb/serial/garmin_gps.c | 1 | ||||
-rw-r--r-- | drivers/usb/serial/io_edgeport.c | 5 | ||||
-rw-r--r-- | drivers/usb/serial/io_ti.c | 22 | ||||
-rw-r--r-- | drivers/usb/serial/iuu_phoenix.c | 11 | ||||
-rw-r--r-- | drivers/usb/serial/keyspan_pda.c | 14 | ||||
-rw-r--r-- | drivers/usb/serial/kobil_sct.c | 12 | ||||
-rw-r--r-- | drivers/usb/serial/mos7720.c | 56 | ||||
-rw-r--r-- | drivers/usb/serial/mos7840.c | 24 | ||||
-rw-r--r-- | drivers/usb/serial/omninet.c | 13 | ||||
-rw-r--r-- | drivers/usb/serial/oti6858.c | 16 | ||||
-rw-r--r-- | drivers/usb/serial/pl2303.c | 8 | ||||
-rw-r--r-- | drivers/usb/serial/quatech2.c | 4 | ||||
-rw-r--r-- | drivers/usb/serial/spcp8x5.c | 14 | ||||
-rw-r--r-- | drivers/usb/serial/ti_usb_3410_5052.c | 7 |
16 files changed, 167 insertions, 58 deletions
diff --git a/drivers/usb/serial/cyberjack.c b/drivers/usb/serial/cyberjack.c index 5f17a3b9916d..80260b08398b 100644 --- a/drivers/usb/serial/cyberjack.c +++ b/drivers/usb/serial/cyberjack.c | |||
@@ -50,6 +50,7 @@ | |||
50 | #define CYBERJACK_PRODUCT_ID 0x0100 | 50 | #define CYBERJACK_PRODUCT_ID 0x0100 |
51 | 51 | ||
52 | /* Function prototypes */ | 52 | /* Function prototypes */ |
53 | static int cyberjack_attach(struct usb_serial *serial); | ||
53 | static int cyberjack_port_probe(struct usb_serial_port *port); | 54 | static int cyberjack_port_probe(struct usb_serial_port *port); |
54 | static int cyberjack_port_remove(struct usb_serial_port *port); | 55 | static int cyberjack_port_remove(struct usb_serial_port *port); |
55 | static int cyberjack_open(struct tty_struct *tty, | 56 | static int cyberjack_open(struct tty_struct *tty, |
@@ -77,6 +78,7 @@ static struct usb_serial_driver cyberjack_device = { | |||
77 | .description = "Reiner SCT Cyberjack USB card reader", | 78 | .description = "Reiner SCT Cyberjack USB card reader", |
78 | .id_table = id_table, | 79 | .id_table = id_table, |
79 | .num_ports = 1, | 80 | .num_ports = 1, |
81 | .attach = cyberjack_attach, | ||
80 | .port_probe = cyberjack_port_probe, | 82 | .port_probe = cyberjack_port_probe, |
81 | .port_remove = cyberjack_port_remove, | 83 | .port_remove = cyberjack_port_remove, |
82 | .open = cyberjack_open, | 84 | .open = cyberjack_open, |
@@ -100,6 +102,14 @@ struct cyberjack_private { | |||
100 | short wrsent; /* Data already sent */ | 102 | short wrsent; /* Data already sent */ |
101 | }; | 103 | }; |
102 | 104 | ||
105 | static int cyberjack_attach(struct usb_serial *serial) | ||
106 | { | ||
107 | if (serial->num_bulk_out < serial->num_ports) | ||
108 | return -ENODEV; | ||
109 | |||
110 | return 0; | ||
111 | } | ||
112 | |||
103 | static int cyberjack_port_probe(struct usb_serial_port *port) | 113 | static int cyberjack_port_probe(struct usb_serial_port *port) |
104 | { | 114 | { |
105 | struct cyberjack_private *priv; | 115 | struct cyberjack_private *priv; |
diff --git a/drivers/usb/serial/f81534.c b/drivers/usb/serial/f81534.c index 8282a6a18fee..22f23a429a95 100644 --- a/drivers/usb/serial/f81534.c +++ b/drivers/usb/serial/f81534.c | |||
@@ -1237,6 +1237,7 @@ static int f81534_attach(struct usb_serial *serial) | |||
1237 | static int f81534_port_probe(struct usb_serial_port *port) | 1237 | static int f81534_port_probe(struct usb_serial_port *port) |
1238 | { | 1238 | { |
1239 | struct f81534_port_private *port_priv; | 1239 | struct f81534_port_private *port_priv; |
1240 | int ret; | ||
1240 | 1241 | ||
1241 | port_priv = devm_kzalloc(&port->dev, sizeof(*port_priv), GFP_KERNEL); | 1242 | port_priv = devm_kzalloc(&port->dev, sizeof(*port_priv), GFP_KERNEL); |
1242 | if (!port_priv) | 1243 | if (!port_priv) |
@@ -1246,10 +1247,11 @@ static int f81534_port_probe(struct usb_serial_port *port) | |||
1246 | mutex_init(&port_priv->mcr_mutex); | 1247 | mutex_init(&port_priv->mcr_mutex); |
1247 | 1248 | ||
1248 | /* Assign logic-to-phy mapping */ | 1249 | /* Assign logic-to-phy mapping */ |
1249 | port_priv->phy_num = f81534_logic_to_phy_port(port->serial, port); | 1250 | ret = f81534_logic_to_phy_port(port->serial, port); |
1250 | if (port_priv->phy_num < 0 || port_priv->phy_num >= F81534_NUM_PORT) | 1251 | if (ret < 0) |
1251 | return -ENODEV; | 1252 | return ret; |
1252 | 1253 | ||
1254 | port_priv->phy_num = ret; | ||
1253 | usb_set_serial_port_data(port, port_priv); | 1255 | usb_set_serial_port_data(port, port_priv); |
1254 | dev_dbg(&port->dev, "%s: port_number: %d, phy_num: %d\n", __func__, | 1256 | dev_dbg(&port->dev, "%s: port_number: %d, phy_num: %d\n", __func__, |
1255 | port->port_number, port_priv->phy_num); | 1257 | port->port_number, port_priv->phy_num); |
diff --git a/drivers/usb/serial/garmin_gps.c b/drivers/usb/serial/garmin_gps.c index 97cabf803c2f..b2f2e87aed94 100644 --- a/drivers/usb/serial/garmin_gps.c +++ b/drivers/usb/serial/garmin_gps.c | |||
@@ -1043,6 +1043,7 @@ static int garmin_write_bulk(struct usb_serial_port *port, | |||
1043 | "%s - usb_submit_urb(write bulk) failed with status = %d\n", | 1043 | "%s - usb_submit_urb(write bulk) failed with status = %d\n", |
1044 | __func__, status); | 1044 | __func__, status); |
1045 | count = status; | 1045 | count = status; |
1046 | kfree(buffer); | ||
1046 | } | 1047 | } |
1047 | 1048 | ||
1048 | /* we are done with this urb, so let the host driver | 1049 | /* we are done with this urb, so let the host driver |
diff --git a/drivers/usb/serial/io_edgeport.c b/drivers/usb/serial/io_edgeport.c index dcc0c58aaad5..d50e5773483f 100644 --- a/drivers/usb/serial/io_edgeport.c +++ b/drivers/usb/serial/io_edgeport.c | |||
@@ -2751,6 +2751,11 @@ static int edge_startup(struct usb_serial *serial) | |||
2751 | EDGE_COMPATIBILITY_MASK1, | 2751 | EDGE_COMPATIBILITY_MASK1, |
2752 | EDGE_COMPATIBILITY_MASK2 }; | 2752 | EDGE_COMPATIBILITY_MASK2 }; |
2753 | 2753 | ||
2754 | if (serial->num_bulk_in < 1 || serial->num_interrupt_in < 1) { | ||
2755 | dev_err(&serial->interface->dev, "missing endpoints\n"); | ||
2756 | return -ENODEV; | ||
2757 | } | ||
2758 | |||
2754 | dev = serial->dev; | 2759 | dev = serial->dev; |
2755 | 2760 | ||
2756 | /* create our private serial structure */ | 2761 | /* create our private serial structure */ |
diff --git a/drivers/usb/serial/io_ti.c b/drivers/usb/serial/io_ti.c index c339163698eb..9a0db2965fbb 100644 --- a/drivers/usb/serial/io_ti.c +++ b/drivers/usb/serial/io_ti.c | |||
@@ -1499,8 +1499,7 @@ static int do_boot_mode(struct edgeport_serial *serial, | |||
1499 | 1499 | ||
1500 | dev_dbg(dev, "%s - Download successful -- Device rebooting...\n", __func__); | 1500 | dev_dbg(dev, "%s - Download successful -- Device rebooting...\n", __func__); |
1501 | 1501 | ||
1502 | /* return an error on purpose */ | 1502 | return 1; |
1503 | return -ENODEV; | ||
1504 | } | 1503 | } |
1505 | 1504 | ||
1506 | stayinbootmode: | 1505 | stayinbootmode: |
@@ -1508,7 +1507,7 @@ stayinbootmode: | |||
1508 | dev_dbg(dev, "%s - STAYING IN BOOT MODE\n", __func__); | 1507 | dev_dbg(dev, "%s - STAYING IN BOOT MODE\n", __func__); |
1509 | serial->product_info.TiMode = TI_MODE_BOOT; | 1508 | serial->product_info.TiMode = TI_MODE_BOOT; |
1510 | 1509 | ||
1511 | return 0; | 1510 | return 1; |
1512 | } | 1511 | } |
1513 | 1512 | ||
1514 | static int ti_do_config(struct edgeport_port *port, int feature, int on) | 1513 | static int ti_do_config(struct edgeport_port *port, int feature, int on) |
@@ -2546,6 +2545,13 @@ static int edge_startup(struct usb_serial *serial) | |||
2546 | int status; | 2545 | int status; |
2547 | u16 product_id; | 2546 | u16 product_id; |
2548 | 2547 | ||
2548 | /* Make sure we have the required endpoints when in download mode. */ | ||
2549 | if (serial->interface->cur_altsetting->desc.bNumEndpoints > 1) { | ||
2550 | if (serial->num_bulk_in < serial->num_ports || | ||
2551 | serial->num_bulk_out < serial->num_ports) | ||
2552 | return -ENODEV; | ||
2553 | } | ||
2554 | |||
2549 | /* create our private serial structure */ | 2555 | /* create our private serial structure */ |
2550 | edge_serial = kzalloc(sizeof(struct edgeport_serial), GFP_KERNEL); | 2556 | edge_serial = kzalloc(sizeof(struct edgeport_serial), GFP_KERNEL); |
2551 | if (!edge_serial) | 2557 | if (!edge_serial) |
@@ -2553,14 +2559,18 @@ static int edge_startup(struct usb_serial *serial) | |||
2553 | 2559 | ||
2554 | mutex_init(&edge_serial->es_lock); | 2560 | mutex_init(&edge_serial->es_lock); |
2555 | edge_serial->serial = serial; | 2561 | edge_serial->serial = serial; |
2562 | INIT_DELAYED_WORK(&edge_serial->heartbeat_work, edge_heartbeat_work); | ||
2556 | usb_set_serial_data(serial, edge_serial); | 2563 | usb_set_serial_data(serial, edge_serial); |
2557 | 2564 | ||
2558 | status = download_fw(edge_serial); | 2565 | status = download_fw(edge_serial); |
2559 | if (status) { | 2566 | if (status < 0) { |
2560 | kfree(edge_serial); | 2567 | kfree(edge_serial); |
2561 | return status; | 2568 | return status; |
2562 | } | 2569 | } |
2563 | 2570 | ||
2571 | if (status > 0) | ||
2572 | return 1; /* bind but do not register any ports */ | ||
2573 | |||
2564 | product_id = le16_to_cpu( | 2574 | product_id = le16_to_cpu( |
2565 | edge_serial->serial->dev->descriptor.idProduct); | 2575 | edge_serial->serial->dev->descriptor.idProduct); |
2566 | 2576 | ||
@@ -2572,7 +2582,6 @@ static int edge_startup(struct usb_serial *serial) | |||
2572 | } | 2582 | } |
2573 | } | 2583 | } |
2574 | 2584 | ||
2575 | INIT_DELAYED_WORK(&edge_serial->heartbeat_work, edge_heartbeat_work); | ||
2576 | edge_heartbeat_schedule(edge_serial); | 2585 | edge_heartbeat_schedule(edge_serial); |
2577 | 2586 | ||
2578 | return 0; | 2587 | return 0; |
@@ -2580,6 +2589,9 @@ static int edge_startup(struct usb_serial *serial) | |||
2580 | 2589 | ||
2581 | static void edge_disconnect(struct usb_serial *serial) | 2590 | static void edge_disconnect(struct usb_serial *serial) |
2582 | { | 2591 | { |
2592 | struct edgeport_serial *edge_serial = usb_get_serial_data(serial); | ||
2593 | |||
2594 | cancel_delayed_work_sync(&edge_serial->heartbeat_work); | ||
2583 | } | 2595 | } |
2584 | 2596 | ||
2585 | static void edge_release(struct usb_serial *serial) | 2597 | static void edge_release(struct usb_serial *serial) |
diff --git a/drivers/usb/serial/iuu_phoenix.c b/drivers/usb/serial/iuu_phoenix.c index 344b4eea4bd5..d57fb5199218 100644 --- a/drivers/usb/serial/iuu_phoenix.c +++ b/drivers/usb/serial/iuu_phoenix.c | |||
@@ -68,6 +68,16 @@ struct iuu_private { | |||
68 | u32 clk; | 68 | u32 clk; |
69 | }; | 69 | }; |
70 | 70 | ||
71 | static int iuu_attach(struct usb_serial *serial) | ||
72 | { | ||
73 | unsigned char num_ports = serial->num_ports; | ||
74 | |||
75 | if (serial->num_bulk_in < num_ports || serial->num_bulk_out < num_ports) | ||
76 | return -ENODEV; | ||
77 | |||
78 | return 0; | ||
79 | } | ||
80 | |||
71 | static int iuu_port_probe(struct usb_serial_port *port) | 81 | static int iuu_port_probe(struct usb_serial_port *port) |
72 | { | 82 | { |
73 | struct iuu_private *priv; | 83 | struct iuu_private *priv; |
@@ -1196,6 +1206,7 @@ static struct usb_serial_driver iuu_device = { | |||
1196 | .tiocmset = iuu_tiocmset, | 1206 | .tiocmset = iuu_tiocmset, |
1197 | .set_termios = iuu_set_termios, | 1207 | .set_termios = iuu_set_termios, |
1198 | .init_termios = iuu_init_termios, | 1208 | .init_termios = iuu_init_termios, |
1209 | .attach = iuu_attach, | ||
1199 | .port_probe = iuu_port_probe, | 1210 | .port_probe = iuu_port_probe, |
1200 | .port_remove = iuu_port_remove, | 1211 | .port_remove = iuu_port_remove, |
1201 | }; | 1212 | }; |
diff --git a/drivers/usb/serial/keyspan_pda.c b/drivers/usb/serial/keyspan_pda.c index e49ad0c63ad8..83523fcf6fb9 100644 --- a/drivers/usb/serial/keyspan_pda.c +++ b/drivers/usb/serial/keyspan_pda.c | |||
@@ -699,6 +699,19 @@ MODULE_FIRMWARE("keyspan_pda/keyspan_pda.fw"); | |||
699 | MODULE_FIRMWARE("keyspan_pda/xircom_pgs.fw"); | 699 | MODULE_FIRMWARE("keyspan_pda/xircom_pgs.fw"); |
700 | #endif | 700 | #endif |
701 | 701 | ||
702 | static int keyspan_pda_attach(struct usb_serial *serial) | ||
703 | { | ||
704 | unsigned char num_ports = serial->num_ports; | ||
705 | |||
706 | if (serial->num_bulk_out < num_ports || | ||
707 | serial->num_interrupt_in < num_ports) { | ||
708 | dev_err(&serial->interface->dev, "missing endpoints\n"); | ||
709 | return -ENODEV; | ||
710 | } | ||
711 | |||
712 | return 0; | ||
713 | } | ||
714 | |||
702 | static int keyspan_pda_port_probe(struct usb_serial_port *port) | 715 | static int keyspan_pda_port_probe(struct usb_serial_port *port) |
703 | { | 716 | { |
704 | 717 | ||
@@ -776,6 +789,7 @@ static struct usb_serial_driver keyspan_pda_device = { | |||
776 | .break_ctl = keyspan_pda_break_ctl, | 789 | .break_ctl = keyspan_pda_break_ctl, |
777 | .tiocmget = keyspan_pda_tiocmget, | 790 | .tiocmget = keyspan_pda_tiocmget, |
778 | .tiocmset = keyspan_pda_tiocmset, | 791 | .tiocmset = keyspan_pda_tiocmset, |
792 | .attach = keyspan_pda_attach, | ||
779 | .port_probe = keyspan_pda_port_probe, | 793 | .port_probe = keyspan_pda_port_probe, |
780 | .port_remove = keyspan_pda_port_remove, | 794 | .port_remove = keyspan_pda_port_remove, |
781 | }; | 795 | }; |
diff --git a/drivers/usb/serial/kobil_sct.c b/drivers/usb/serial/kobil_sct.c index 2363654cafc9..813035f51fe7 100644 --- a/drivers/usb/serial/kobil_sct.c +++ b/drivers/usb/serial/kobil_sct.c | |||
@@ -51,6 +51,7 @@ | |||
51 | 51 | ||
52 | 52 | ||
53 | /* Function prototypes */ | 53 | /* Function prototypes */ |
54 | static int kobil_attach(struct usb_serial *serial); | ||
54 | static int kobil_port_probe(struct usb_serial_port *probe); | 55 | static int kobil_port_probe(struct usb_serial_port *probe); |
55 | static int kobil_port_remove(struct usb_serial_port *probe); | 56 | static int kobil_port_remove(struct usb_serial_port *probe); |
56 | static int kobil_open(struct tty_struct *tty, struct usb_serial_port *port); | 57 | static int kobil_open(struct tty_struct *tty, struct usb_serial_port *port); |
@@ -86,6 +87,7 @@ static struct usb_serial_driver kobil_device = { | |||
86 | .description = "KOBIL USB smart card terminal", | 87 | .description = "KOBIL USB smart card terminal", |
87 | .id_table = id_table, | 88 | .id_table = id_table, |
88 | .num_ports = 1, | 89 | .num_ports = 1, |
90 | .attach = kobil_attach, | ||
89 | .port_probe = kobil_port_probe, | 91 | .port_probe = kobil_port_probe, |
90 | .port_remove = kobil_port_remove, | 92 | .port_remove = kobil_port_remove, |
91 | .ioctl = kobil_ioctl, | 93 | .ioctl = kobil_ioctl, |
@@ -113,6 +115,16 @@ struct kobil_private { | |||
113 | }; | 115 | }; |
114 | 116 | ||
115 | 117 | ||
118 | static int kobil_attach(struct usb_serial *serial) | ||
119 | { | ||
120 | if (serial->num_interrupt_out < serial->num_ports) { | ||
121 | dev_err(&serial->interface->dev, "missing interrupt-out endpoint\n"); | ||
122 | return -ENODEV; | ||
123 | } | ||
124 | |||
125 | return 0; | ||
126 | } | ||
127 | |||
116 | static int kobil_port_probe(struct usb_serial_port *port) | 128 | static int kobil_port_probe(struct usb_serial_port *port) |
117 | { | 129 | { |
118 | struct usb_serial *serial = port->serial; | 130 | struct usb_serial *serial = port->serial; |
diff --git a/drivers/usb/serial/mos7720.c b/drivers/usb/serial/mos7720.c index d52caa03679c..91bc170b408a 100644 --- a/drivers/usb/serial/mos7720.c +++ b/drivers/usb/serial/mos7720.c | |||
@@ -65,8 +65,6 @@ struct moschip_port { | |||
65 | struct urb *write_urb_pool[NUM_URBS]; | 65 | struct urb *write_urb_pool[NUM_URBS]; |
66 | }; | 66 | }; |
67 | 67 | ||
68 | static struct usb_serial_driver moschip7720_2port_driver; | ||
69 | |||
70 | #define USB_VENDOR_ID_MOSCHIP 0x9710 | 68 | #define USB_VENDOR_ID_MOSCHIP 0x9710 |
71 | #define MOSCHIP_DEVICE_ID_7720 0x7720 | 69 | #define MOSCHIP_DEVICE_ID_7720 0x7720 |
72 | #define MOSCHIP_DEVICE_ID_7715 0x7715 | 70 | #define MOSCHIP_DEVICE_ID_7715 0x7715 |
@@ -970,25 +968,6 @@ static void mos7720_bulk_out_data_callback(struct urb *urb) | |||
970 | tty_port_tty_wakeup(&mos7720_port->port->port); | 968 | tty_port_tty_wakeup(&mos7720_port->port->port); |
971 | } | 969 | } |
972 | 970 | ||
973 | /* | ||
974 | * mos77xx_probe | ||
975 | * this function installs the appropriate read interrupt endpoint callback | ||
976 | * depending on whether the device is a 7720 or 7715, thus avoiding costly | ||
977 | * run-time checks in the high-frequency callback routine itself. | ||
978 | */ | ||
979 | static int mos77xx_probe(struct usb_serial *serial, | ||
980 | const struct usb_device_id *id) | ||
981 | { | ||
982 | if (id->idProduct == MOSCHIP_DEVICE_ID_7715) | ||
983 | moschip7720_2port_driver.read_int_callback = | ||
984 | mos7715_interrupt_callback; | ||
985 | else | ||
986 | moschip7720_2port_driver.read_int_callback = | ||
987 | mos7720_interrupt_callback; | ||
988 | |||
989 | return 0; | ||
990 | } | ||
991 | |||
992 | static int mos77xx_calc_num_ports(struct usb_serial *serial) | 971 | static int mos77xx_calc_num_ports(struct usb_serial *serial) |
993 | { | 972 | { |
994 | u16 product = le16_to_cpu(serial->dev->descriptor.idProduct); | 973 | u16 product = le16_to_cpu(serial->dev->descriptor.idProduct); |
@@ -1917,6 +1896,11 @@ static int mos7720_startup(struct usb_serial *serial) | |||
1917 | u16 product; | 1896 | u16 product; |
1918 | int ret_val; | 1897 | int ret_val; |
1919 | 1898 | ||
1899 | if (serial->num_bulk_in < 2 || serial->num_bulk_out < 2) { | ||
1900 | dev_err(&serial->interface->dev, "missing bulk endpoints\n"); | ||
1901 | return -ENODEV; | ||
1902 | } | ||
1903 | |||
1920 | product = le16_to_cpu(serial->dev->descriptor.idProduct); | 1904 | product = le16_to_cpu(serial->dev->descriptor.idProduct); |
1921 | dev = serial->dev; | 1905 | dev = serial->dev; |
1922 | 1906 | ||
@@ -1941,19 +1925,18 @@ static int mos7720_startup(struct usb_serial *serial) | |||
1941 | tmp->interrupt_in_endpointAddress; | 1925 | tmp->interrupt_in_endpointAddress; |
1942 | serial->port[1]->interrupt_in_urb = NULL; | 1926 | serial->port[1]->interrupt_in_urb = NULL; |
1943 | serial->port[1]->interrupt_in_buffer = NULL; | 1927 | serial->port[1]->interrupt_in_buffer = NULL; |
1928 | |||
1929 | if (serial->port[0]->interrupt_in_urb) { | ||
1930 | struct urb *urb = serial->port[0]->interrupt_in_urb; | ||
1931 | |||
1932 | urb->complete = mos7715_interrupt_callback; | ||
1933 | } | ||
1944 | } | 1934 | } |
1945 | 1935 | ||
1946 | /* setting configuration feature to one */ | 1936 | /* setting configuration feature to one */ |
1947 | usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), | 1937 | usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), |
1948 | (__u8)0x03, 0x00, 0x01, 0x00, NULL, 0x00, 5000); | 1938 | (__u8)0x03, 0x00, 0x01, 0x00, NULL, 0x00, 5000); |
1949 | 1939 | ||
1950 | /* start the interrupt urb */ | ||
1951 | ret_val = usb_submit_urb(serial->port[0]->interrupt_in_urb, GFP_KERNEL); | ||
1952 | if (ret_val) | ||
1953 | dev_err(&dev->dev, | ||
1954 | "%s - Error %d submitting control urb\n", | ||
1955 | __func__, ret_val); | ||
1956 | |||
1957 | #ifdef CONFIG_USB_SERIAL_MOS7715_PARPORT | 1940 | #ifdef CONFIG_USB_SERIAL_MOS7715_PARPORT |
1958 | if (product == MOSCHIP_DEVICE_ID_7715) { | 1941 | if (product == MOSCHIP_DEVICE_ID_7715) { |
1959 | ret_val = mos7715_parport_init(serial); | 1942 | ret_val = mos7715_parport_init(serial); |
@@ -1961,6 +1944,13 @@ static int mos7720_startup(struct usb_serial *serial) | |||
1961 | return ret_val; | 1944 | return ret_val; |
1962 | } | 1945 | } |
1963 | #endif | 1946 | #endif |
1947 | /* start the interrupt urb */ | ||
1948 | ret_val = usb_submit_urb(serial->port[0]->interrupt_in_urb, GFP_KERNEL); | ||
1949 | if (ret_val) { | ||
1950 | dev_err(&dev->dev, "failed to submit interrupt urb: %d\n", | ||
1951 | ret_val); | ||
1952 | } | ||
1953 | |||
1964 | /* LSR For Port 1 */ | 1954 | /* LSR For Port 1 */ |
1965 | read_mos_reg(serial, 0, MOS7720_LSR, &data); | 1955 | read_mos_reg(serial, 0, MOS7720_LSR, &data); |
1966 | dev_dbg(&dev->dev, "LSR:%x\n", data); | 1956 | dev_dbg(&dev->dev, "LSR:%x\n", data); |
@@ -1970,6 +1960,8 @@ static int mos7720_startup(struct usb_serial *serial) | |||
1970 | 1960 | ||
1971 | static void mos7720_release(struct usb_serial *serial) | 1961 | static void mos7720_release(struct usb_serial *serial) |
1972 | { | 1962 | { |
1963 | usb_kill_urb(serial->port[0]->interrupt_in_urb); | ||
1964 | |||
1973 | #ifdef CONFIG_USB_SERIAL_MOS7715_PARPORT | 1965 | #ifdef CONFIG_USB_SERIAL_MOS7715_PARPORT |
1974 | /* close the parallel port */ | 1966 | /* close the parallel port */ |
1975 | 1967 | ||
@@ -2019,11 +2011,6 @@ static int mos7720_port_probe(struct usb_serial_port *port) | |||
2019 | if (!mos7720_port) | 2011 | if (!mos7720_port) |
2020 | return -ENOMEM; | 2012 | return -ENOMEM; |
2021 | 2013 | ||
2022 | /* Initialize all port interrupt end point to port 0 int endpoint. | ||
2023 | * Our device has only one interrupt endpoint common to all ports. | ||
2024 | */ | ||
2025 | port->interrupt_in_endpointAddress = | ||
2026 | port->serial->port[0]->interrupt_in_endpointAddress; | ||
2027 | mos7720_port->port = port; | 2014 | mos7720_port->port = port; |
2028 | 2015 | ||
2029 | usb_set_serial_port_data(port, mos7720_port); | 2016 | usb_set_serial_port_data(port, mos7720_port); |
@@ -2053,7 +2040,6 @@ static struct usb_serial_driver moschip7720_2port_driver = { | |||
2053 | .close = mos7720_close, | 2040 | .close = mos7720_close, |
2054 | .throttle = mos7720_throttle, | 2041 | .throttle = mos7720_throttle, |
2055 | .unthrottle = mos7720_unthrottle, | 2042 | .unthrottle = mos7720_unthrottle, |
2056 | .probe = mos77xx_probe, | ||
2057 | .attach = mos7720_startup, | 2043 | .attach = mos7720_startup, |
2058 | .release = mos7720_release, | 2044 | .release = mos7720_release, |
2059 | .port_probe = mos7720_port_probe, | 2045 | .port_probe = mos7720_port_probe, |
@@ -2067,7 +2053,7 @@ static struct usb_serial_driver moschip7720_2port_driver = { | |||
2067 | .chars_in_buffer = mos7720_chars_in_buffer, | 2053 | .chars_in_buffer = mos7720_chars_in_buffer, |
2068 | .break_ctl = mos7720_break, | 2054 | .break_ctl = mos7720_break, |
2069 | .read_bulk_callback = mos7720_bulk_in_callback, | 2055 | .read_bulk_callback = mos7720_bulk_in_callback, |
2070 | .read_int_callback = NULL /* dynamically assigned in probe() */ | 2056 | .read_int_callback = mos7720_interrupt_callback, |
2071 | }; | 2057 | }; |
2072 | 2058 | ||
2073 | static struct usb_serial_driver * const serial_drivers[] = { | 2059 | static struct usb_serial_driver * const serial_drivers[] = { |
diff --git a/drivers/usb/serial/mos7840.c b/drivers/usb/serial/mos7840.c index 9a220b8e810f..ea27fb23967a 100644 --- a/drivers/usb/serial/mos7840.c +++ b/drivers/usb/serial/mos7840.c | |||
@@ -214,7 +214,6 @@ MODULE_DEVICE_TABLE(usb, id_table); | |||
214 | 214 | ||
215 | struct moschip_port { | 215 | struct moschip_port { |
216 | int port_num; /*Actual port number in the device(1,2,etc) */ | 216 | int port_num; /*Actual port number in the device(1,2,etc) */ |
217 | struct urb *write_urb; /* write URB for this port */ | ||
218 | struct urb *read_urb; /* read URB for this port */ | 217 | struct urb *read_urb; /* read URB for this port */ |
219 | __u8 shadowLCR; /* last LCR value received */ | 218 | __u8 shadowLCR; /* last LCR value received */ |
220 | __u8 shadowMCR; /* last MCR value received */ | 219 | __u8 shadowMCR; /* last MCR value received */ |
@@ -1037,9 +1036,7 @@ static int mos7840_open(struct tty_struct *tty, struct usb_serial_port *port) | |||
1037 | serial, | 1036 | serial, |
1038 | serial->port[0]->interrupt_in_urb->interval); | 1037 | serial->port[0]->interrupt_in_urb->interval); |
1039 | 1038 | ||
1040 | /* start interrupt read for mos7840 * | 1039 | /* start interrupt read for mos7840 */ |
1041 | * will continue as long as mos7840 is connected */ | ||
1042 | |||
1043 | response = | 1040 | response = |
1044 | usb_submit_urb(serial->port[0]->interrupt_in_urb, | 1041 | usb_submit_urb(serial->port[0]->interrupt_in_urb, |
1045 | GFP_KERNEL); | 1042 | GFP_KERNEL); |
@@ -1186,7 +1183,6 @@ static void mos7840_close(struct usb_serial_port *port) | |||
1186 | } | 1183 | } |
1187 | } | 1184 | } |
1188 | 1185 | ||
1189 | usb_kill_urb(mos7840_port->write_urb); | ||
1190 | usb_kill_urb(mos7840_port->read_urb); | 1186 | usb_kill_urb(mos7840_port->read_urb); |
1191 | mos7840_port->read_urb_busy = false; | 1187 | mos7840_port->read_urb_busy = false; |
1192 | 1188 | ||
@@ -1199,12 +1195,6 @@ static void mos7840_close(struct usb_serial_port *port) | |||
1199 | } | 1195 | } |
1200 | } | 1196 | } |
1201 | 1197 | ||
1202 | if (mos7840_port->write_urb) { | ||
1203 | /* if this urb had a transfer buffer already (old tx) free it */ | ||
1204 | kfree(mos7840_port->write_urb->transfer_buffer); | ||
1205 | usb_free_urb(mos7840_port->write_urb); | ||
1206 | } | ||
1207 | |||
1208 | Data = 0x0; | 1198 | Data = 0x0; |
1209 | mos7840_set_uart_reg(port, MODEM_CONTROL_REGISTER, Data); | 1199 | mos7840_set_uart_reg(port, MODEM_CONTROL_REGISTER, Data); |
1210 | 1200 | ||
@@ -2113,6 +2103,17 @@ static int mos7840_calc_num_ports(struct usb_serial *serial) | |||
2113 | return mos7840_num_ports; | 2103 | return mos7840_num_ports; |
2114 | } | 2104 | } |
2115 | 2105 | ||
2106 | static int mos7840_attach(struct usb_serial *serial) | ||
2107 | { | ||
2108 | if (serial->num_bulk_in < serial->num_ports || | ||
2109 | serial->num_bulk_out < serial->num_ports) { | ||
2110 | dev_err(&serial->interface->dev, "missing endpoints\n"); | ||
2111 | return -ENODEV; | ||
2112 | } | ||
2113 | |||
2114 | return 0; | ||
2115 | } | ||
2116 | |||
2116 | static int mos7840_port_probe(struct usb_serial_port *port) | 2117 | static int mos7840_port_probe(struct usb_serial_port *port) |
2117 | { | 2118 | { |
2118 | struct usb_serial *serial = port->serial; | 2119 | struct usb_serial *serial = port->serial; |
@@ -2388,6 +2389,7 @@ static struct usb_serial_driver moschip7840_4port_device = { | |||
2388 | .tiocmset = mos7840_tiocmset, | 2389 | .tiocmset = mos7840_tiocmset, |
2389 | .tiocmiwait = usb_serial_generic_tiocmiwait, | 2390 | .tiocmiwait = usb_serial_generic_tiocmiwait, |
2390 | .get_icount = usb_serial_generic_get_icount, | 2391 | .get_icount = usb_serial_generic_get_icount, |
2392 | .attach = mos7840_attach, | ||
2391 | .port_probe = mos7840_port_probe, | 2393 | .port_probe = mos7840_port_probe, |
2392 | .port_remove = mos7840_port_remove, | 2394 | .port_remove = mos7840_port_remove, |
2393 | .read_bulk_callback = mos7840_bulk_in_callback, | 2395 | .read_bulk_callback = mos7840_bulk_in_callback, |
diff --git a/drivers/usb/serial/omninet.c b/drivers/usb/serial/omninet.c index f6c6900bccf0..a180b17d2432 100644 --- a/drivers/usb/serial/omninet.c +++ b/drivers/usb/serial/omninet.c | |||
@@ -38,6 +38,7 @@ static int omninet_write(struct tty_struct *tty, struct usb_serial_port *port, | |||
38 | const unsigned char *buf, int count); | 38 | const unsigned char *buf, int count); |
39 | static int omninet_write_room(struct tty_struct *tty); | 39 | static int omninet_write_room(struct tty_struct *tty); |
40 | static void omninet_disconnect(struct usb_serial *serial); | 40 | static void omninet_disconnect(struct usb_serial *serial); |
41 | static int omninet_attach(struct usb_serial *serial); | ||
41 | static int omninet_port_probe(struct usb_serial_port *port); | 42 | static int omninet_port_probe(struct usb_serial_port *port); |
42 | static int omninet_port_remove(struct usb_serial_port *port); | 43 | static int omninet_port_remove(struct usb_serial_port *port); |
43 | 44 | ||
@@ -56,6 +57,7 @@ static struct usb_serial_driver zyxel_omninet_device = { | |||
56 | .description = "ZyXEL - omni.net lcd plus usb", | 57 | .description = "ZyXEL - omni.net lcd plus usb", |
57 | .id_table = id_table, | 58 | .id_table = id_table, |
58 | .num_ports = 1, | 59 | .num_ports = 1, |
60 | .attach = omninet_attach, | ||
59 | .port_probe = omninet_port_probe, | 61 | .port_probe = omninet_port_probe, |
60 | .port_remove = omninet_port_remove, | 62 | .port_remove = omninet_port_remove, |
61 | .open = omninet_open, | 63 | .open = omninet_open, |
@@ -104,6 +106,17 @@ struct omninet_data { | |||
104 | __u8 od_outseq; /* Sequence number for bulk_out URBs */ | 106 | __u8 od_outseq; /* Sequence number for bulk_out URBs */ |
105 | }; | 107 | }; |
106 | 108 | ||
109 | static int omninet_attach(struct usb_serial *serial) | ||
110 | { | ||
111 | /* The second bulk-out endpoint is used for writing. */ | ||
112 | if (serial->num_bulk_out < 2) { | ||
113 | dev_err(&serial->interface->dev, "missing endpoints\n"); | ||
114 | return -ENODEV; | ||
115 | } | ||
116 | |||
117 | return 0; | ||
118 | } | ||
119 | |||
107 | static int omninet_port_probe(struct usb_serial_port *port) | 120 | static int omninet_port_probe(struct usb_serial_port *port) |
108 | { | 121 | { |
109 | struct omninet_data *od; | 122 | struct omninet_data *od; |
diff --git a/drivers/usb/serial/oti6858.c b/drivers/usb/serial/oti6858.c index a4b88bc038b6..b8bf52bf7a94 100644 --- a/drivers/usb/serial/oti6858.c +++ b/drivers/usb/serial/oti6858.c | |||
@@ -134,6 +134,7 @@ static int oti6858_chars_in_buffer(struct tty_struct *tty); | |||
134 | static int oti6858_tiocmget(struct tty_struct *tty); | 134 | static int oti6858_tiocmget(struct tty_struct *tty); |
135 | static int oti6858_tiocmset(struct tty_struct *tty, | 135 | static int oti6858_tiocmset(struct tty_struct *tty, |
136 | unsigned int set, unsigned int clear); | 136 | unsigned int set, unsigned int clear); |
137 | static int oti6858_attach(struct usb_serial *serial); | ||
137 | static int oti6858_port_probe(struct usb_serial_port *port); | 138 | static int oti6858_port_probe(struct usb_serial_port *port); |
138 | static int oti6858_port_remove(struct usb_serial_port *port); | 139 | static int oti6858_port_remove(struct usb_serial_port *port); |
139 | 140 | ||
@@ -158,6 +159,7 @@ static struct usb_serial_driver oti6858_device = { | |||
158 | .write_bulk_callback = oti6858_write_bulk_callback, | 159 | .write_bulk_callback = oti6858_write_bulk_callback, |
159 | .write_room = oti6858_write_room, | 160 | .write_room = oti6858_write_room, |
160 | .chars_in_buffer = oti6858_chars_in_buffer, | 161 | .chars_in_buffer = oti6858_chars_in_buffer, |
162 | .attach = oti6858_attach, | ||
161 | .port_probe = oti6858_port_probe, | 163 | .port_probe = oti6858_port_probe, |
162 | .port_remove = oti6858_port_remove, | 164 | .port_remove = oti6858_port_remove, |
163 | }; | 165 | }; |
@@ -324,6 +326,20 @@ static void send_data(struct work_struct *work) | |||
324 | usb_serial_port_softint(port); | 326 | usb_serial_port_softint(port); |
325 | } | 327 | } |
326 | 328 | ||
329 | static int oti6858_attach(struct usb_serial *serial) | ||
330 | { | ||
331 | unsigned char num_ports = serial->num_ports; | ||
332 | |||
333 | if (serial->num_bulk_in < num_ports || | ||
334 | serial->num_bulk_out < num_ports || | ||
335 | serial->num_interrupt_in < num_ports) { | ||
336 | dev_err(&serial->interface->dev, "missing endpoints\n"); | ||
337 | return -ENODEV; | ||
338 | } | ||
339 | |||
340 | return 0; | ||
341 | } | ||
342 | |||
327 | static int oti6858_port_probe(struct usb_serial_port *port) | 343 | static int oti6858_port_probe(struct usb_serial_port *port) |
328 | { | 344 | { |
329 | struct oti6858_private *priv; | 345 | struct oti6858_private *priv; |
diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c index ae682e4eeaef..46fca6b75846 100644 --- a/drivers/usb/serial/pl2303.c +++ b/drivers/usb/serial/pl2303.c | |||
@@ -220,9 +220,17 @@ static int pl2303_probe(struct usb_serial *serial, | |||
220 | static int pl2303_startup(struct usb_serial *serial) | 220 | static int pl2303_startup(struct usb_serial *serial) |
221 | { | 221 | { |
222 | struct pl2303_serial_private *spriv; | 222 | struct pl2303_serial_private *spriv; |
223 | unsigned char num_ports = serial->num_ports; | ||
223 | enum pl2303_type type = TYPE_01; | 224 | enum pl2303_type type = TYPE_01; |
224 | unsigned char *buf; | 225 | unsigned char *buf; |
225 | 226 | ||
227 | if (serial->num_bulk_in < num_ports || | ||
228 | serial->num_bulk_out < num_ports || | ||
229 | serial->num_interrupt_in < num_ports) { | ||
230 | dev_err(&serial->interface->dev, "missing endpoints\n"); | ||
231 | return -ENODEV; | ||
232 | } | ||
233 | |||
226 | spriv = kzalloc(sizeof(*spriv), GFP_KERNEL); | 234 | spriv = kzalloc(sizeof(*spriv), GFP_KERNEL); |
227 | if (!spriv) | 235 | if (!spriv) |
228 | return -ENOMEM; | 236 | return -ENOMEM; |
diff --git a/drivers/usb/serial/quatech2.c b/drivers/usb/serial/quatech2.c index 659cb8606bd9..5709cc93b083 100644 --- a/drivers/usb/serial/quatech2.c +++ b/drivers/usb/serial/quatech2.c | |||
@@ -408,16 +408,12 @@ static void qt2_close(struct usb_serial_port *port) | |||
408 | { | 408 | { |
409 | struct usb_serial *serial; | 409 | struct usb_serial *serial; |
410 | struct qt2_port_private *port_priv; | 410 | struct qt2_port_private *port_priv; |
411 | unsigned long flags; | ||
412 | int i; | 411 | int i; |
413 | 412 | ||
414 | serial = port->serial; | 413 | serial = port->serial; |
415 | port_priv = usb_get_serial_port_data(port); | 414 | port_priv = usb_get_serial_port_data(port); |
416 | 415 | ||
417 | spin_lock_irqsave(&port_priv->urb_lock, flags); | ||
418 | usb_kill_urb(port_priv->write_urb); | 416 | usb_kill_urb(port_priv->write_urb); |
419 | port_priv->urb_in_use = false; | ||
420 | spin_unlock_irqrestore(&port_priv->urb_lock, flags); | ||
421 | 417 | ||
422 | /* flush the port transmit buffer */ | 418 | /* flush the port transmit buffer */ |
423 | i = usb_control_msg(serial->dev, | 419 | i = usb_control_msg(serial->dev, |
diff --git a/drivers/usb/serial/spcp8x5.c b/drivers/usb/serial/spcp8x5.c index ef0dbf0703c5..475e6c31b266 100644 --- a/drivers/usb/serial/spcp8x5.c +++ b/drivers/usb/serial/spcp8x5.c | |||
@@ -154,6 +154,19 @@ static int spcp8x5_probe(struct usb_serial *serial, | |||
154 | return 0; | 154 | return 0; |
155 | } | 155 | } |
156 | 156 | ||
157 | static int spcp8x5_attach(struct usb_serial *serial) | ||
158 | { | ||
159 | unsigned char num_ports = serial->num_ports; | ||
160 | |||
161 | if (serial->num_bulk_in < num_ports || | ||
162 | serial->num_bulk_out < num_ports) { | ||
163 | dev_err(&serial->interface->dev, "missing endpoints\n"); | ||
164 | return -ENODEV; | ||
165 | } | ||
166 | |||
167 | return 0; | ||
168 | } | ||
169 | |||
157 | static int spcp8x5_port_probe(struct usb_serial_port *port) | 170 | static int spcp8x5_port_probe(struct usb_serial_port *port) |
158 | { | 171 | { |
159 | const struct usb_device_id *id = usb_get_serial_data(port->serial); | 172 | const struct usb_device_id *id = usb_get_serial_data(port->serial); |
@@ -477,6 +490,7 @@ static struct usb_serial_driver spcp8x5_device = { | |||
477 | .tiocmget = spcp8x5_tiocmget, | 490 | .tiocmget = spcp8x5_tiocmget, |
478 | .tiocmset = spcp8x5_tiocmset, | 491 | .tiocmset = spcp8x5_tiocmset, |
479 | .probe = spcp8x5_probe, | 492 | .probe = spcp8x5_probe, |
493 | .attach = spcp8x5_attach, | ||
480 | .port_probe = spcp8x5_port_probe, | 494 | .port_probe = spcp8x5_port_probe, |
481 | .port_remove = spcp8x5_port_remove, | 495 | .port_remove = spcp8x5_port_remove, |
482 | }; | 496 | }; |
diff --git a/drivers/usb/serial/ti_usb_3410_5052.c b/drivers/usb/serial/ti_usb_3410_5052.c index 8db9d071d940..64b85b8dedf3 100644 --- a/drivers/usb/serial/ti_usb_3410_5052.c +++ b/drivers/usb/serial/ti_usb_3410_5052.c | |||
@@ -579,6 +579,13 @@ static int ti_startup(struct usb_serial *serial) | |||
579 | goto free_tdev; | 579 | goto free_tdev; |
580 | } | 580 | } |
581 | 581 | ||
582 | if (serial->num_bulk_in < serial->num_ports || | ||
583 | serial->num_bulk_out < serial->num_ports) { | ||
584 | dev_err(&serial->interface->dev, "missing endpoints\n"); | ||
585 | status = -ENODEV; | ||
586 | goto free_tdev; | ||
587 | } | ||
588 | |||
582 | return 0; | 589 | return 0; |
583 | 590 | ||
584 | free_tdev: | 591 | free_tdev: |