diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2011-03-16 18:04:26 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2011-03-16 18:04:26 -0400 |
commit | 971f115a50afbe409825c9f3399d5a3b9aca4381 (patch) | |
tree | cb42dc07a032e325f22b64d961587c081225c6d6 /drivers/usb/serial | |
parent | 2e270d84223262a38d4755c61d55f5c73ea89e56 (diff) | |
parent | 500132a0f26ad7d9916102193cbc6c1b1becb373 (diff) |
Merge branch 'usb-next' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb-2.6
* 'usb-next' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb-2.6: (172 commits)
USB: Add support for SuperSpeed isoc endpoints
xhci: Clean up cycle bit math used during stalls.
xhci: Fix cycle bit calculation during stall handling.
xhci: Update internal dequeue pointers after stalls.
USB: Disable auto-suspend for USB 3.0 hubs.
USB: Remove bogus USB_PORT_STAT_SUPER_SPEED symbol.
xhci: Return canceled URBs immediately when host is halted.
xhci: Fixes for suspend/resume of shared HCDs.
xhci: Fix re-init on power loss after resume.
xhci: Make roothub functions deal with device removal.
xhci: Limit roothub ports to 15 USB3 & 31 USB2 ports.
xhci: Return a USB 3.0 hub descriptor for USB3 roothub.
xhci: Register second xHCI roothub.
xhci: Change xhci_find_slot_id_by_port() API.
xhci: Refactor bus suspend state into a struct.
xhci: Index with a port array instead of PORTSC addresses.
USB: Set usb_hcd->state and flags for shared roothubs.
usb: Make core allocate resources per PCI-device.
usb: Store bus type in usb_hcd, not in driver flags.
usb: Change usb_hcd->bandwidth_mutex to a pointer.
...
Diffstat (limited to 'drivers/usb/serial')
-rw-r--r-- | drivers/usb/serial/ch341.c | 1 | ||||
-rw-r--r-- | drivers/usb/serial/ftdi_sio.c | 4 | ||||
-rw-r--r-- | drivers/usb/serial/ftdi_sio_ids.h | 1 | ||||
-rw-r--r-- | drivers/usb/serial/io_edgeport.c | 3 | ||||
-rw-r--r-- | drivers/usb/serial/keyspan.c | 10 | ||||
-rw-r--r-- | drivers/usb/serial/keyspan_pda.c | 15 | ||||
-rw-r--r-- | drivers/usb/serial/kobil_sct.c | 2 | ||||
-rw-r--r-- | drivers/usb/serial/mct_u232.c | 107 | ||||
-rw-r--r-- | drivers/usb/serial/mos7720.c | 3 | ||||
-rw-r--r-- | drivers/usb/serial/opticon.c | 156 | ||||
-rw-r--r-- | drivers/usb/serial/option.c | 3 | ||||
-rw-r--r-- | drivers/usb/serial/sierra.c | 16 | ||||
-rw-r--r-- | drivers/usb/serial/usb-serial.c | 5 | ||||
-rw-r--r-- | drivers/usb/serial/usb_wwan.c | 43 |
14 files changed, 290 insertions, 79 deletions
diff --git a/drivers/usb/serial/ch341.c b/drivers/usb/serial/ch341.c index 7b8815ddf368..14ac87ee9251 100644 --- a/drivers/usb/serial/ch341.c +++ b/drivers/usb/serial/ch341.c | |||
@@ -75,6 +75,7 @@ static int debug; | |||
75 | static const struct usb_device_id id_table[] = { | 75 | static const struct usb_device_id id_table[] = { |
76 | { USB_DEVICE(0x4348, 0x5523) }, | 76 | { USB_DEVICE(0x4348, 0x5523) }, |
77 | { USB_DEVICE(0x1a86, 0x7523) }, | 77 | { USB_DEVICE(0x1a86, 0x7523) }, |
78 | { USB_DEVICE(0x1a86, 0x5523) }, | ||
78 | { }, | 79 | { }, |
79 | }; | 80 | }; |
80 | MODULE_DEVICE_TABLE(usb, id_table); | 81 | MODULE_DEVICE_TABLE(usb, id_table); |
diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index f349a3629d00..a75f9298d88f 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c | |||
@@ -722,6 +722,8 @@ static struct usb_device_id id_table_combined [] = { | |||
722 | { USB_DEVICE(FTDI_VID, FTDI_PROPOX_JTAGCABLEII_PID) }, | 722 | { USB_DEVICE(FTDI_VID, FTDI_PROPOX_JTAGCABLEII_PID) }, |
723 | { USB_DEVICE(OLIMEX_VID, OLIMEX_ARM_USB_OCD_PID), | 723 | { USB_DEVICE(OLIMEX_VID, OLIMEX_ARM_USB_OCD_PID), |
724 | .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, | 724 | .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, |
725 | { USB_DEVICE(OLIMEX_VID, OLIMEX_ARM_USB_OCD_H_PID), | ||
726 | .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, | ||
725 | { USB_DEVICE(FIC_VID, FIC_NEO1973_DEBUG_PID), | 727 | { USB_DEVICE(FIC_VID, FIC_NEO1973_DEBUG_PID), |
726 | .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, | 728 | .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, |
727 | { USB_DEVICE(FTDI_VID, FTDI_OOCDLINK_PID), | 729 | { USB_DEVICE(FTDI_VID, FTDI_OOCDLINK_PID), |
@@ -973,7 +975,7 @@ static __u32 ftdi_2232h_baud_base_to_divisor(int baud, int base) | |||
973 | int divisor3; | 975 | int divisor3; |
974 | 976 | ||
975 | /* hi-speed baud rate is 10-bit sampling instead of 16-bit */ | 977 | /* hi-speed baud rate is 10-bit sampling instead of 16-bit */ |
976 | divisor3 = (base / 10 / baud) * 8; | 978 | divisor3 = base * 8 / (baud * 10); |
977 | 979 | ||
978 | divisor = divisor3 >> 3; | 980 | divisor = divisor3 >> 3; |
979 | divisor |= (__u32)divfrac[divisor3 & 0x7] << 14; | 981 | divisor |= (__u32)divfrac[divisor3 & 0x7] << 14; |
diff --git a/drivers/usb/serial/ftdi_sio_ids.h b/drivers/usb/serial/ftdi_sio_ids.h index 117e8e6f93c6..c543e55bafba 100644 --- a/drivers/usb/serial/ftdi_sio_ids.h +++ b/drivers/usb/serial/ftdi_sio_ids.h | |||
@@ -730,6 +730,7 @@ | |||
730 | /* Olimex */ | 730 | /* Olimex */ |
731 | #define OLIMEX_VID 0x15BA | 731 | #define OLIMEX_VID 0x15BA |
732 | #define OLIMEX_ARM_USB_OCD_PID 0x0003 | 732 | #define OLIMEX_ARM_USB_OCD_PID 0x0003 |
733 | #define OLIMEX_ARM_USB_OCD_H_PID 0x002b | ||
733 | 734 | ||
734 | /* | 735 | /* |
735 | * Telldus Technologies | 736 | * Telldus Technologies |
diff --git a/drivers/usb/serial/io_edgeport.c b/drivers/usb/serial/io_edgeport.c index 3b246d93cf22..76e3e502c23d 100644 --- a/drivers/usb/serial/io_edgeport.c +++ b/drivers/usb/serial/io_edgeport.c | |||
@@ -2343,7 +2343,6 @@ static int write_cmd_usb(struct edgeport_port *edge_port, | |||
2343 | usb_get_serial_data(edge_port->port->serial); | 2343 | usb_get_serial_data(edge_port->port->serial); |
2344 | int status = 0; | 2344 | int status = 0; |
2345 | struct urb *urb; | 2345 | struct urb *urb; |
2346 | int timeout; | ||
2347 | 2346 | ||
2348 | usb_serial_debug_data(debug, &edge_port->port->dev, | 2347 | usb_serial_debug_data(debug, &edge_port->port->dev, |
2349 | __func__, length, buffer); | 2348 | __func__, length, buffer); |
@@ -2376,8 +2375,6 @@ static int write_cmd_usb(struct edgeport_port *edge_port, | |||
2376 | return status; | 2375 | return status; |
2377 | } | 2376 | } |
2378 | 2377 | ||
2379 | /* wait for command to finish */ | ||
2380 | timeout = COMMAND_TIMEOUT; | ||
2381 | #if 0 | 2378 | #if 0 |
2382 | wait_event(&edge_port->wait_command, !edge_port->commandPending); | 2379 | wait_event(&edge_port->wait_command, !edge_port->commandPending); |
2383 | 2380 | ||
diff --git a/drivers/usb/serial/keyspan.c b/drivers/usb/serial/keyspan.c index 0791778a66f3..67f41b526570 100644 --- a/drivers/usb/serial/keyspan.c +++ b/drivers/usb/serial/keyspan.c | |||
@@ -2121,16 +2121,16 @@ static int keyspan_usa49_send_setup(struct usb_serial *serial, | |||
2121 | /* Work out which port within the device is being setup */ | 2121 | /* Work out which port within the device is being setup */ |
2122 | device_port = port->number - port->serial->minor; | 2122 | device_port = port->number - port->serial->minor; |
2123 | 2123 | ||
2124 | dbg("%s - endpoint %d port %d (%d)", | 2124 | /* Make sure we have an urb then send the message */ |
2125 | __func__, usb_pipeendpoint(this_urb->pipe), | ||
2126 | port->number, device_port); | ||
2127 | |||
2128 | /* Make sure we have an urb then send the message */ | ||
2129 | if (this_urb == NULL) { | 2125 | if (this_urb == NULL) { |
2130 | dbg("%s - oops no urb for port %d.", __func__, port->number); | 2126 | dbg("%s - oops no urb for port %d.", __func__, port->number); |
2131 | return -1; | 2127 | return -1; |
2132 | } | 2128 | } |
2133 | 2129 | ||
2130 | dbg("%s - endpoint %d port %d (%d)", | ||
2131 | __func__, usb_pipeendpoint(this_urb->pipe), | ||
2132 | port->number, device_port); | ||
2133 | |||
2134 | /* Save reset port val for resend. | 2134 | /* Save reset port val for resend. |
2135 | Don't overwrite resend for open/close condition. */ | 2135 | Don't overwrite resend for open/close condition. */ |
2136 | if ((reset_port + 1) > p_priv->resend_cont) | 2136 | if ((reset_port + 1) > p_priv->resend_cont) |
diff --git a/drivers/usb/serial/keyspan_pda.c b/drivers/usb/serial/keyspan_pda.c index 554a8693a463..7b690f3282a2 100644 --- a/drivers/usb/serial/keyspan_pda.c +++ b/drivers/usb/serial/keyspan_pda.c | |||
@@ -173,7 +173,8 @@ static void keyspan_pda_wakeup_write(struct work_struct *work) | |||
173 | container_of(work, struct keyspan_pda_private, wakeup_work); | 173 | container_of(work, struct keyspan_pda_private, wakeup_work); |
174 | struct usb_serial_port *port = priv->port; | 174 | struct usb_serial_port *port = priv->port; |
175 | struct tty_struct *tty = tty_port_tty_get(&port->port); | 175 | struct tty_struct *tty = tty_port_tty_get(&port->port); |
176 | tty_wakeup(tty); | 176 | if (tty) |
177 | tty_wakeup(tty); | ||
177 | tty_kref_put(tty); | 178 | tty_kref_put(tty); |
178 | } | 179 | } |
179 | 180 | ||
@@ -206,7 +207,7 @@ static void keyspan_pda_request_unthrottle(struct work_struct *work) | |||
206 | static void keyspan_pda_rx_interrupt(struct urb *urb) | 207 | static void keyspan_pda_rx_interrupt(struct urb *urb) |
207 | { | 208 | { |
208 | struct usb_serial_port *port = urb->context; | 209 | struct usb_serial_port *port = urb->context; |
209 | struct tty_struct *tty = tty_port_tty_get(&port->port); | 210 | struct tty_struct *tty; |
210 | unsigned char *data = urb->transfer_buffer; | 211 | unsigned char *data = urb->transfer_buffer; |
211 | int retval; | 212 | int retval; |
212 | int status = urb->status; | 213 | int status = urb->status; |
@@ -223,7 +224,7 @@ static void keyspan_pda_rx_interrupt(struct urb *urb) | |||
223 | /* this urb is terminated, clean up */ | 224 | /* this urb is terminated, clean up */ |
224 | dbg("%s - urb shutting down with status: %d", | 225 | dbg("%s - urb shutting down with status: %d", |
225 | __func__, status); | 226 | __func__, status); |
226 | goto out; | 227 | return; |
227 | default: | 228 | default: |
228 | dbg("%s - nonzero urb status received: %d", | 229 | dbg("%s - nonzero urb status received: %d", |
229 | __func__, status); | 230 | __func__, status); |
@@ -233,12 +234,14 @@ static void keyspan_pda_rx_interrupt(struct urb *urb) | |||
233 | /* see if the message is data or a status interrupt */ | 234 | /* see if the message is data or a status interrupt */ |
234 | switch (data[0]) { | 235 | switch (data[0]) { |
235 | case 0: | 236 | case 0: |
236 | /* rest of message is rx data */ | 237 | tty = tty_port_tty_get(&port->port); |
237 | if (urb->actual_length) { | 238 | /* rest of message is rx data */ |
239 | if (tty && urb->actual_length) { | ||
238 | tty_insert_flip_string(tty, data + 1, | 240 | tty_insert_flip_string(tty, data + 1, |
239 | urb->actual_length - 1); | 241 | urb->actual_length - 1); |
240 | tty_flip_buffer_push(tty); | 242 | tty_flip_buffer_push(tty); |
241 | } | 243 | } |
244 | tty_kref_put(tty); | ||
242 | break; | 245 | break; |
243 | case 1: | 246 | case 1: |
244 | /* status interrupt */ | 247 | /* status interrupt */ |
@@ -265,8 +268,6 @@ exit: | |||
265 | dev_err(&port->dev, | 268 | dev_err(&port->dev, |
266 | "%s - usb_submit_urb failed with result %d", | 269 | "%s - usb_submit_urb failed with result %d", |
267 | __func__, retval); | 270 | __func__, retval); |
268 | out: | ||
269 | tty_kref_put(tty); | ||
270 | } | 271 | } |
271 | 272 | ||
272 | 273 | ||
diff --git a/drivers/usb/serial/kobil_sct.c b/drivers/usb/serial/kobil_sct.c index bd5bd8589e04..b382d9a0274d 100644 --- a/drivers/usb/serial/kobil_sct.c +++ b/drivers/usb/serial/kobil_sct.c | |||
@@ -372,7 +372,7 @@ static void kobil_read_int_callback(struct urb *urb) | |||
372 | } | 372 | } |
373 | 373 | ||
374 | tty = tty_port_tty_get(&port->port); | 374 | tty = tty_port_tty_get(&port->port); |
375 | if (urb->actual_length) { | 375 | if (tty && urb->actual_length) { |
376 | 376 | ||
377 | /* BEGIN DEBUG */ | 377 | /* BEGIN DEBUG */ |
378 | /* | 378 | /* |
diff --git a/drivers/usb/serial/mct_u232.c b/drivers/usb/serial/mct_u232.c index 2849f8c32015..1e225aacf46e 100644 --- a/drivers/usb/serial/mct_u232.c +++ b/drivers/usb/serial/mct_u232.c | |||
@@ -78,6 +78,8 @@ | |||
78 | #include <asm/unaligned.h> | 78 | #include <asm/unaligned.h> |
79 | #include <linux/usb.h> | 79 | #include <linux/usb.h> |
80 | #include <linux/usb/serial.h> | 80 | #include <linux/usb/serial.h> |
81 | #include <linux/serial.h> | ||
82 | #include <linux/ioctl.h> | ||
81 | #include "mct_u232.h" | 83 | #include "mct_u232.h" |
82 | 84 | ||
83 | /* | 85 | /* |
@@ -104,6 +106,10 @@ static void mct_u232_break_ctl(struct tty_struct *tty, int break_state); | |||
104 | static int mct_u232_tiocmget(struct tty_struct *tty, struct file *file); | 106 | static int mct_u232_tiocmget(struct tty_struct *tty, struct file *file); |
105 | static int mct_u232_tiocmset(struct tty_struct *tty, struct file *file, | 107 | static int mct_u232_tiocmset(struct tty_struct *tty, struct file *file, |
106 | unsigned int set, unsigned int clear); | 108 | unsigned int set, unsigned int clear); |
109 | static int mct_u232_ioctl(struct tty_struct *tty, struct file *file, | ||
110 | unsigned int cmd, unsigned long arg); | ||
111 | static int mct_u232_get_icount(struct tty_struct *tty, | ||
112 | struct serial_icounter_struct *icount); | ||
107 | static void mct_u232_throttle(struct tty_struct *tty); | 113 | static void mct_u232_throttle(struct tty_struct *tty); |
108 | static void mct_u232_unthrottle(struct tty_struct *tty); | 114 | static void mct_u232_unthrottle(struct tty_struct *tty); |
109 | 115 | ||
@@ -150,9 +156,10 @@ static struct usb_serial_driver mct_u232_device = { | |||
150 | .tiocmset = mct_u232_tiocmset, | 156 | .tiocmset = mct_u232_tiocmset, |
151 | .attach = mct_u232_startup, | 157 | .attach = mct_u232_startup, |
152 | .release = mct_u232_release, | 158 | .release = mct_u232_release, |
159 | .ioctl = mct_u232_ioctl, | ||
160 | .get_icount = mct_u232_get_icount, | ||
153 | }; | 161 | }; |
154 | 162 | ||
155 | |||
156 | struct mct_u232_private { | 163 | struct mct_u232_private { |
157 | spinlock_t lock; | 164 | spinlock_t lock; |
158 | unsigned int control_state; /* Modem Line Setting (TIOCM) */ | 165 | unsigned int control_state; /* Modem Line Setting (TIOCM) */ |
@@ -160,6 +167,9 @@ struct mct_u232_private { | |||
160 | unsigned char last_lsr; /* Line Status Register */ | 167 | unsigned char last_lsr; /* Line Status Register */ |
161 | unsigned char last_msr; /* Modem Status Register */ | 168 | unsigned char last_msr; /* Modem Status Register */ |
162 | unsigned int rx_flags; /* Throttling flags */ | 169 | unsigned int rx_flags; /* Throttling flags */ |
170 | struct async_icount icount; | ||
171 | wait_queue_head_t msr_wait; /* for handling sleeping while waiting | ||
172 | for msr change to happen */ | ||
163 | }; | 173 | }; |
164 | 174 | ||
165 | #define THROTTLED 0x01 | 175 | #define THROTTLED 0x01 |
@@ -386,6 +396,20 @@ static int mct_u232_get_modem_stat(struct usb_serial *serial, | |||
386 | return rc; | 396 | return rc; |
387 | } /* mct_u232_get_modem_stat */ | 397 | } /* mct_u232_get_modem_stat */ |
388 | 398 | ||
399 | static void mct_u232_msr_to_icount(struct async_icount *icount, | ||
400 | unsigned char msr) | ||
401 | { | ||
402 | /* Translate Control Line states */ | ||
403 | if (msr & MCT_U232_MSR_DDSR) | ||
404 | icount->dsr++; | ||
405 | if (msr & MCT_U232_MSR_DCTS) | ||
406 | icount->cts++; | ||
407 | if (msr & MCT_U232_MSR_DRI) | ||
408 | icount->rng++; | ||
409 | if (msr & MCT_U232_MSR_DCD) | ||
410 | icount->dcd++; | ||
411 | } /* mct_u232_msr_to_icount */ | ||
412 | |||
389 | static void mct_u232_msr_to_state(unsigned int *control_state, | 413 | static void mct_u232_msr_to_state(unsigned int *control_state, |
390 | unsigned char msr) | 414 | unsigned char msr) |
391 | { | 415 | { |
@@ -422,6 +446,7 @@ static int mct_u232_startup(struct usb_serial *serial) | |||
422 | if (!priv) | 446 | if (!priv) |
423 | return -ENOMEM; | 447 | return -ENOMEM; |
424 | spin_lock_init(&priv->lock); | 448 | spin_lock_init(&priv->lock); |
449 | init_waitqueue_head(&priv->msr_wait); | ||
425 | usb_set_serial_port_data(serial->port[0], priv); | 450 | usb_set_serial_port_data(serial->port[0], priv); |
426 | 451 | ||
427 | init_waitqueue_head(&serial->port[0]->write_wait); | 452 | init_waitqueue_head(&serial->port[0]->write_wait); |
@@ -621,6 +646,8 @@ static void mct_u232_read_int_callback(struct urb *urb) | |||
621 | /* Record Control Line states */ | 646 | /* Record Control Line states */ |
622 | mct_u232_msr_to_state(&priv->control_state, priv->last_msr); | 647 | mct_u232_msr_to_state(&priv->control_state, priv->last_msr); |
623 | 648 | ||
649 | mct_u232_msr_to_icount(&priv->icount, priv->last_msr); | ||
650 | |||
624 | #if 0 | 651 | #if 0 |
625 | /* Not yet handled. See belkin_sa.c for further information */ | 652 | /* Not yet handled. See belkin_sa.c for further information */ |
626 | /* Now to report any errors */ | 653 | /* Now to report any errors */ |
@@ -647,6 +674,7 @@ static void mct_u232_read_int_callback(struct urb *urb) | |||
647 | tty_kref_put(tty); | 674 | tty_kref_put(tty); |
648 | } | 675 | } |
649 | #endif | 676 | #endif |
677 | wake_up_interruptible(&priv->msr_wait); | ||
650 | spin_unlock_irqrestore(&priv->lock, flags); | 678 | spin_unlock_irqrestore(&priv->lock, flags); |
651 | exit: | 679 | exit: |
652 | retval = usb_submit_urb(urb, GFP_ATOMIC); | 680 | retval = usb_submit_urb(urb, GFP_ATOMIC); |
@@ -826,7 +854,6 @@ static void mct_u232_throttle(struct tty_struct *tty) | |||
826 | } | 854 | } |
827 | } | 855 | } |
828 | 856 | ||
829 | |||
830 | static void mct_u232_unthrottle(struct tty_struct *tty) | 857 | static void mct_u232_unthrottle(struct tty_struct *tty) |
831 | { | 858 | { |
832 | struct usb_serial_port *port = tty->driver_data; | 859 | struct usb_serial_port *port = tty->driver_data; |
@@ -847,6 +874,82 @@ static void mct_u232_unthrottle(struct tty_struct *tty) | |||
847 | } | 874 | } |
848 | } | 875 | } |
849 | 876 | ||
877 | static int mct_u232_ioctl(struct tty_struct *tty, struct file *file, | ||
878 | unsigned int cmd, unsigned long arg) | ||
879 | { | ||
880 | DEFINE_WAIT(wait); | ||
881 | struct usb_serial_port *port = tty->driver_data; | ||
882 | struct mct_u232_private *mct_u232_port = usb_get_serial_port_data(port); | ||
883 | struct async_icount cnow, cprev; | ||
884 | unsigned long flags; | ||
885 | |||
886 | dbg("%s - port %d, cmd = 0x%x", __func__, port->number, cmd); | ||
887 | |||
888 | switch (cmd) { | ||
889 | |||
890 | case TIOCMIWAIT: | ||
891 | |||
892 | dbg("%s (%d) TIOCMIWAIT", __func__, port->number); | ||
893 | |||
894 | spin_lock_irqsave(&mct_u232_port->lock, flags); | ||
895 | cprev = mct_u232_port->icount; | ||
896 | spin_unlock_irqrestore(&mct_u232_port->lock, flags); | ||
897 | for ( ; ; ) { | ||
898 | prepare_to_wait(&mct_u232_port->msr_wait, | ||
899 | &wait, TASK_INTERRUPTIBLE); | ||
900 | schedule(); | ||
901 | finish_wait(&mct_u232_port->msr_wait, &wait); | ||
902 | /* see if a signal did it */ | ||
903 | if (signal_pending(current)) | ||
904 | return -ERESTARTSYS; | ||
905 | spin_lock_irqsave(&mct_u232_port->lock, flags); | ||
906 | cnow = mct_u232_port->icount; | ||
907 | spin_unlock_irqrestore(&mct_u232_port->lock, flags); | ||
908 | if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr && | ||
909 | cnow.dcd == cprev.dcd && cnow.cts == cprev.cts) | ||
910 | return -EIO; /* no change => error */ | ||
911 | if (((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) || | ||
912 | ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) || | ||
913 | ((arg & TIOCM_CD) && (cnow.dcd != cprev.dcd)) || | ||
914 | ((arg & TIOCM_CTS) && (cnow.cts != cprev.cts))) { | ||
915 | return 0; | ||
916 | } | ||
917 | cprev = cnow; | ||
918 | } | ||
919 | |||
920 | } | ||
921 | return -ENOIOCTLCMD; | ||
922 | } | ||
923 | |||
924 | static int mct_u232_get_icount(struct tty_struct *tty, | ||
925 | struct serial_icounter_struct *icount) | ||
926 | { | ||
927 | struct usb_serial_port *port = tty->driver_data; | ||
928 | struct mct_u232_private *mct_u232_port = usb_get_serial_port_data(port); | ||
929 | struct async_icount *ic = &mct_u232_port->icount; | ||
930 | unsigned long flags; | ||
931 | |||
932 | spin_lock_irqsave(&mct_u232_port->lock, flags); | ||
933 | |||
934 | icount->cts = ic->cts; | ||
935 | icount->dsr = ic->dsr; | ||
936 | icount->rng = ic->rng; | ||
937 | icount->dcd = ic->dcd; | ||
938 | icount->rx = ic->rx; | ||
939 | icount->tx = ic->tx; | ||
940 | icount->frame = ic->frame; | ||
941 | icount->overrun = ic->overrun; | ||
942 | icount->parity = ic->parity; | ||
943 | icount->brk = ic->brk; | ||
944 | icount->buf_overrun = ic->buf_overrun; | ||
945 | |||
946 | spin_unlock_irqrestore(&mct_u232_port->lock, flags); | ||
947 | |||
948 | dbg("%s (%d) TIOCGICOUNT RX=%d, TX=%d", | ||
949 | __func__, port->number, icount->rx, icount->tx); | ||
950 | return 0; | ||
951 | } | ||
952 | |||
850 | static int __init mct_u232_init(void) | 953 | static int __init mct_u232_init(void) |
851 | { | 954 | { |
852 | int retval; | 955 | int retval; |
diff --git a/drivers/usb/serial/mos7720.c b/drivers/usb/serial/mos7720.c index 7d3bc9a3e2b6..ae506f4ee29d 100644 --- a/drivers/usb/serial/mos7720.c +++ b/drivers/usb/serial/mos7720.c | |||
@@ -2052,7 +2052,7 @@ static int mos7720_startup(struct usb_serial *serial) | |||
2052 | struct usb_device *dev; | 2052 | struct usb_device *dev; |
2053 | int i; | 2053 | int i; |
2054 | char data; | 2054 | char data; |
2055 | u16 product = le16_to_cpu(serial->dev->descriptor.idProduct); | 2055 | u16 product; |
2056 | int ret_val; | 2056 | int ret_val; |
2057 | 2057 | ||
2058 | dbg("%s: Entering ..........", __func__); | 2058 | dbg("%s: Entering ..........", __func__); |
@@ -2062,6 +2062,7 @@ static int mos7720_startup(struct usb_serial *serial) | |||
2062 | return -ENODEV; | 2062 | return -ENODEV; |
2063 | } | 2063 | } |
2064 | 2064 | ||
2065 | product = le16_to_cpu(serial->dev->descriptor.idProduct); | ||
2065 | dev = serial->dev; | 2066 | dev = serial->dev; |
2066 | 2067 | ||
2067 | /* | 2068 | /* |
diff --git a/drivers/usb/serial/opticon.c b/drivers/usb/serial/opticon.c index eda1f9266c4e..ce82396fc4e8 100644 --- a/drivers/usb/serial/opticon.c +++ b/drivers/usb/serial/opticon.c | |||
@@ -1,6 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * Opticon USB barcode to serial driver | 2 | * Opticon USB barcode to serial driver |
3 | * | 3 | * |
4 | * Copyright (C) 2011 Martin Jansen <martin.jansen@opticon.com> | ||
4 | * Copyright (C) 2008 - 2009 Greg Kroah-Hartman <gregkh@suse.de> | 5 | * Copyright (C) 2008 - 2009 Greg Kroah-Hartman <gregkh@suse.de> |
5 | * Copyright (C) 2008 - 2009 Novell Inc. | 6 | * Copyright (C) 2008 - 2009 Novell Inc. |
6 | * | 7 | * |
@@ -21,6 +22,16 @@ | |||
21 | #include <linux/usb/serial.h> | 22 | #include <linux/usb/serial.h> |
22 | #include <linux/uaccess.h> | 23 | #include <linux/uaccess.h> |
23 | 24 | ||
25 | #define CONTROL_RTS 0x02 | ||
26 | #define RESEND_CTS_STATE 0x03 | ||
27 | |||
28 | /* max number of write urbs in flight */ | ||
29 | #define URB_UPPER_LIMIT 8 | ||
30 | |||
31 | /* This driver works for the Opticon 1D barcode reader | ||
32 | * an examples of 1D barcode types are EAN, UPC, Code39, IATA etc.. */ | ||
33 | #define DRIVER_DESC "Opticon USB barcode to serial driver (1D)" | ||
34 | |||
24 | static int debug; | 35 | static int debug; |
25 | 36 | ||
26 | static const struct usb_device_id id_table[] = { | 37 | static const struct usb_device_id id_table[] = { |
@@ -42,13 +53,13 @@ struct opticon_private { | |||
42 | bool throttled; | 53 | bool throttled; |
43 | bool actually_throttled; | 54 | bool actually_throttled; |
44 | bool rts; | 55 | bool rts; |
56 | bool cts; | ||
45 | int outstanding_urbs; | 57 | int outstanding_urbs; |
46 | }; | 58 | }; |
47 | 59 | ||
48 | /* max number of write urbs in flight */ | ||
49 | #define URB_UPPER_LIMIT 4 | ||
50 | 60 | ||
51 | static void opticon_bulk_callback(struct urb *urb) | 61 | |
62 | static void opticon_read_bulk_callback(struct urb *urb) | ||
52 | { | 63 | { |
53 | struct opticon_private *priv = urb->context; | 64 | struct opticon_private *priv = urb->context; |
54 | unsigned char *data = urb->transfer_buffer; | 65 | unsigned char *data = urb->transfer_buffer; |
@@ -57,6 +68,7 @@ static void opticon_bulk_callback(struct urb *urb) | |||
57 | struct tty_struct *tty; | 68 | struct tty_struct *tty; |
58 | int result; | 69 | int result; |
59 | int data_length; | 70 | int data_length; |
71 | unsigned long flags; | ||
60 | 72 | ||
61 | dbg("%s - port %d", __func__, port->number); | 73 | dbg("%s - port %d", __func__, port->number); |
62 | 74 | ||
@@ -87,10 +99,10 @@ static void opticon_bulk_callback(struct urb *urb) | |||
87 | * Data from the device comes with a 2 byte header: | 99 | * Data from the device comes with a 2 byte header: |
88 | * | 100 | * |
89 | * <0x00><0x00>data... | 101 | * <0x00><0x00>data... |
90 | * This is real data to be sent to the tty layer | 102 | * This is real data to be sent to the tty layer |
91 | * <0x00><0x01)level | 103 | * <0x00><0x01)level |
92 | * This is a RTS level change, the third byte is the RTS | 104 | * This is a CTS level change, the third byte is the CTS |
93 | * value (0 for low, 1 for high). | 105 | * value (0 for low, 1 for high). |
94 | */ | 106 | */ |
95 | if ((data[0] == 0x00) && (data[1] == 0x00)) { | 107 | if ((data[0] == 0x00) && (data[1] == 0x00)) { |
96 | /* real data, send it to the tty layer */ | 108 | /* real data, send it to the tty layer */ |
@@ -103,10 +115,13 @@ static void opticon_bulk_callback(struct urb *urb) | |||
103 | } | 115 | } |
104 | } else { | 116 | } else { |
105 | if ((data[0] == 0x00) && (data[1] == 0x01)) { | 117 | if ((data[0] == 0x00) && (data[1] == 0x01)) { |
118 | spin_lock_irqsave(&priv->lock, flags); | ||
119 | /* CTS status infomation package */ | ||
106 | if (data[2] == 0x00) | 120 | if (data[2] == 0x00) |
107 | priv->rts = false; | 121 | priv->cts = false; |
108 | else | 122 | else |
109 | priv->rts = true; | 123 | priv->cts = true; |
124 | spin_unlock_irqrestore(&priv->lock, flags); | ||
110 | } else { | 125 | } else { |
111 | dev_dbg(&priv->udev->dev, | 126 | dev_dbg(&priv->udev->dev, |
112 | "Unknown data packet received from the device:" | 127 | "Unknown data packet received from the device:" |
@@ -129,7 +144,7 @@ exit: | |||
129 | usb_rcvbulkpipe(priv->udev, | 144 | usb_rcvbulkpipe(priv->udev, |
130 | priv->bulk_address), | 145 | priv->bulk_address), |
131 | priv->bulk_in_buffer, priv->buffer_size, | 146 | priv->bulk_in_buffer, priv->buffer_size, |
132 | opticon_bulk_callback, priv); | 147 | opticon_read_bulk_callback, priv); |
133 | result = usb_submit_urb(priv->bulk_read_urb, GFP_ATOMIC); | 148 | result = usb_submit_urb(priv->bulk_read_urb, GFP_ATOMIC); |
134 | if (result) | 149 | if (result) |
135 | dev_err(&port->dev, | 150 | dev_err(&port->dev, |
@@ -140,6 +155,24 @@ exit: | |||
140 | spin_unlock(&priv->lock); | 155 | spin_unlock(&priv->lock); |
141 | } | 156 | } |
142 | 157 | ||
158 | static int send_control_msg(struct usb_serial_port *port, u8 requesttype, | ||
159 | u8 val) | ||
160 | { | ||
161 | struct usb_serial *serial = port->serial; | ||
162 | int retval; | ||
163 | u8 buffer[2]; | ||
164 | |||
165 | buffer[0] = val; | ||
166 | /* Send the message to the vendor control endpoint | ||
167 | * of the connected device */ | ||
168 | retval = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), | ||
169 | requesttype, | ||
170 | USB_DIR_OUT|USB_TYPE_VENDOR|USB_RECIP_INTERFACE, | ||
171 | 0, 0, buffer, 1, 0); | ||
172 | |||
173 | return retval; | ||
174 | } | ||
175 | |||
143 | static int opticon_open(struct tty_struct *tty, struct usb_serial_port *port) | 176 | static int opticon_open(struct tty_struct *tty, struct usb_serial_port *port) |
144 | { | 177 | { |
145 | struct opticon_private *priv = usb_get_serial_data(port->serial); | 178 | struct opticon_private *priv = usb_get_serial_data(port->serial); |
@@ -152,19 +185,30 @@ static int opticon_open(struct tty_struct *tty, struct usb_serial_port *port) | |||
152 | priv->throttled = false; | 185 | priv->throttled = false; |
153 | priv->actually_throttled = false; | 186 | priv->actually_throttled = false; |
154 | priv->port = port; | 187 | priv->port = port; |
188 | priv->rts = false; | ||
155 | spin_unlock_irqrestore(&priv->lock, flags); | 189 | spin_unlock_irqrestore(&priv->lock, flags); |
156 | 190 | ||
157 | /* Start reading from the device */ | 191 | /* Clear RTS line */ |
192 | send_control_msg(port, CONTROL_RTS, 0); | ||
193 | |||
194 | /* Setup the read URB and start reading from the device */ | ||
158 | usb_fill_bulk_urb(priv->bulk_read_urb, priv->udev, | 195 | usb_fill_bulk_urb(priv->bulk_read_urb, priv->udev, |
159 | usb_rcvbulkpipe(priv->udev, | 196 | usb_rcvbulkpipe(priv->udev, |
160 | priv->bulk_address), | 197 | priv->bulk_address), |
161 | priv->bulk_in_buffer, priv->buffer_size, | 198 | priv->bulk_in_buffer, priv->buffer_size, |
162 | opticon_bulk_callback, priv); | 199 | opticon_read_bulk_callback, priv); |
200 | |||
201 | /* clear the halt status of the enpoint */ | ||
202 | usb_clear_halt(priv->udev, priv->bulk_read_urb->pipe); | ||
203 | |||
163 | result = usb_submit_urb(priv->bulk_read_urb, GFP_KERNEL); | 204 | result = usb_submit_urb(priv->bulk_read_urb, GFP_KERNEL); |
164 | if (result) | 205 | if (result) |
165 | dev_err(&port->dev, | 206 | dev_err(&port->dev, |
166 | "%s - failed resubmitting read urb, error %d\n", | 207 | "%s - failed resubmitting read urb, error %d\n", |
167 | __func__, result); | 208 | __func__, result); |
209 | /* Request CTS line state, sometimes during opening the current | ||
210 | * CTS state can be missed. */ | ||
211 | send_control_msg(port, RESEND_CTS_STATE, 1); | ||
168 | return result; | 212 | return result; |
169 | } | 213 | } |
170 | 214 | ||
@@ -178,7 +222,7 @@ static void opticon_close(struct usb_serial_port *port) | |||
178 | usb_kill_urb(priv->bulk_read_urb); | 222 | usb_kill_urb(priv->bulk_read_urb); |
179 | } | 223 | } |
180 | 224 | ||
181 | static void opticon_write_bulk_callback(struct urb *urb) | 225 | static void opticon_write_control_callback(struct urb *urb) |
182 | { | 226 | { |
183 | struct opticon_private *priv = urb->context; | 227 | struct opticon_private *priv = urb->context; |
184 | int status = urb->status; | 228 | int status = urb->status; |
@@ -210,6 +254,7 @@ static int opticon_write(struct tty_struct *tty, struct usb_serial_port *port, | |||
210 | unsigned char *buffer; | 254 | unsigned char *buffer; |
211 | unsigned long flags; | 255 | unsigned long flags; |
212 | int status; | 256 | int status; |
257 | struct usb_ctrlrequest *dr; | ||
213 | 258 | ||
214 | dbg("%s - port %d", __func__, port->number); | 259 | dbg("%s - port %d", __func__, port->number); |
215 | 260 | ||
@@ -226,6 +271,7 @@ static int opticon_write(struct tty_struct *tty, struct usb_serial_port *port, | |||
226 | if (!buffer) { | 271 | if (!buffer) { |
227 | dev_err(&port->dev, "out of memory\n"); | 272 | dev_err(&port->dev, "out of memory\n"); |
228 | count = -ENOMEM; | 273 | count = -ENOMEM; |
274 | |||
229 | goto error_no_buffer; | 275 | goto error_no_buffer; |
230 | } | 276 | } |
231 | 277 | ||
@@ -240,35 +286,28 @@ static int opticon_write(struct tty_struct *tty, struct usb_serial_port *port, | |||
240 | 286 | ||
241 | usb_serial_debug_data(debug, &port->dev, __func__, count, buffer); | 287 | usb_serial_debug_data(debug, &port->dev, __func__, count, buffer); |
242 | 288 | ||
243 | if (port->bulk_out_endpointAddress) { | 289 | /* The conncected devices do not have a bulk write endpoint, |
244 | usb_fill_bulk_urb(urb, serial->dev, | 290 | * to transmit data to de barcode device the control endpoint is used */ |
245 | usb_sndbulkpipe(serial->dev, | 291 | dr = kmalloc(sizeof(struct usb_ctrlrequest), GFP_NOIO); |
246 | port->bulk_out_endpointAddress), | 292 | if (!dr) |
247 | buffer, count, opticon_write_bulk_callback, priv); | 293 | return -ENOMEM; |
248 | } else { | 294 | |
249 | struct usb_ctrlrequest *dr; | 295 | dr->bRequestType = USB_TYPE_VENDOR | USB_RECIP_INTERFACE | USB_DIR_OUT; |
250 | 296 | dr->bRequest = 0x01; | |
251 | dr = kmalloc(sizeof(struct usb_ctrlrequest), GFP_NOIO); | 297 | dr->wValue = 0; |
252 | if (!dr) | 298 | dr->wIndex = 0; |
253 | return -ENOMEM; | 299 | dr->wLength = cpu_to_le16(count); |
254 | 300 | ||
255 | dr->bRequestType = USB_TYPE_VENDOR | USB_RECIP_INTERFACE | USB_DIR_OUT; | 301 | usb_fill_control_urb(urb, serial->dev, |
256 | dr->bRequest = 0x01; | 302 | usb_sndctrlpipe(serial->dev, 0), |
257 | dr->wValue = 0; | 303 | (unsigned char *)dr, buffer, count, |
258 | dr->wIndex = 0; | 304 | opticon_write_control_callback, priv); |
259 | dr->wLength = cpu_to_le16(count); | ||
260 | |||
261 | usb_fill_control_urb(urb, serial->dev, | ||
262 | usb_sndctrlpipe(serial->dev, 0), | ||
263 | (unsigned char *)dr, buffer, count, | ||
264 | opticon_write_bulk_callback, priv); | ||
265 | } | ||
266 | 305 | ||
267 | /* send it down the pipe */ | 306 | /* send it down the pipe */ |
268 | status = usb_submit_urb(urb, GFP_ATOMIC); | 307 | status = usb_submit_urb(urb, GFP_ATOMIC); |
269 | if (status) { | 308 | if (status) { |
270 | dev_err(&port->dev, | 309 | dev_err(&port->dev, |
271 | "%s - usb_submit_urb(write bulk) failed with status = %d\n", | 310 | "%s - usb_submit_urb(write endpoint) failed status = %d\n", |
272 | __func__, status); | 311 | __func__, status); |
273 | count = status; | 312 | count = status; |
274 | goto error; | 313 | goto error; |
@@ -360,16 +399,49 @@ static int opticon_tiocmget(struct tty_struct *tty, struct file *file) | |||
360 | int result = 0; | 399 | int result = 0; |
361 | 400 | ||
362 | dbg("%s - port %d", __func__, port->number); | 401 | dbg("%s - port %d", __func__, port->number); |
402 | if (!usb_get_intfdata(port->serial->interface)) | ||
403 | return -ENODEV; | ||
363 | 404 | ||
364 | spin_lock_irqsave(&priv->lock, flags); | 405 | spin_lock_irqsave(&priv->lock, flags); |
365 | if (priv->rts) | 406 | if (priv->rts) |
366 | result = TIOCM_RTS; | 407 | result |= TIOCM_RTS; |
408 | if (priv->cts) | ||
409 | result |= TIOCM_CTS; | ||
367 | spin_unlock_irqrestore(&priv->lock, flags); | 410 | spin_unlock_irqrestore(&priv->lock, flags); |
368 | 411 | ||
369 | dbg("%s - %x", __func__, result); | 412 | dbg("%s - %x", __func__, result); |
370 | return result; | 413 | return result; |
371 | } | 414 | } |
372 | 415 | ||
416 | static int opticon_tiocmset(struct tty_struct *tty, struct file *file, | ||
417 | unsigned int set, unsigned int clear) | ||
418 | { | ||
419 | struct usb_serial_port *port = tty->driver_data; | ||
420 | struct opticon_private *priv = usb_get_serial_data(port->serial); | ||
421 | unsigned long flags; | ||
422 | bool rts; | ||
423 | bool changed = false; | ||
424 | |||
425 | if (!usb_get_intfdata(port->serial->interface)) | ||
426 | return -ENODEV; | ||
427 | /* We only support RTS so we only handle that */ | ||
428 | spin_lock_irqsave(&priv->lock, flags); | ||
429 | |||
430 | rts = priv->rts; | ||
431 | if (set & TIOCM_RTS) | ||
432 | priv->rts = true; | ||
433 | if (clear & TIOCM_RTS) | ||
434 | priv->rts = false; | ||
435 | changed = rts ^ priv->rts; | ||
436 | spin_unlock_irqrestore(&priv->lock, flags); | ||
437 | |||
438 | if (!changed) | ||
439 | return 0; | ||
440 | |||
441 | /* Send the new RTS state to the connected device */ | ||
442 | return send_control_msg(port, CONTROL_RTS, !rts); | ||
443 | } | ||
444 | |||
373 | static int get_serial_info(struct opticon_private *priv, | 445 | static int get_serial_info(struct opticon_private *priv, |
374 | struct serial_struct __user *serial) | 446 | struct serial_struct __user *serial) |
375 | { | 447 | { |
@@ -431,6 +503,7 @@ static int opticon_startup(struct usb_serial *serial) | |||
431 | priv->serial = serial; | 503 | priv->serial = serial; |
432 | priv->port = serial->port[0]; | 504 | priv->port = serial->port[0]; |
433 | priv->udev = serial->dev; | 505 | priv->udev = serial->dev; |
506 | priv->outstanding_urbs = 0; /* Init the outstanding urbs */ | ||
434 | 507 | ||
435 | /* find our bulk endpoint */ | 508 | /* find our bulk endpoint */ |
436 | intf = serial->interface->altsetting; | 509 | intf = serial->interface->altsetting; |
@@ -456,13 +529,6 @@ static int opticon_startup(struct usb_serial *serial) | |||
456 | 529 | ||
457 | priv->bulk_address = endpoint->bEndpointAddress; | 530 | priv->bulk_address = endpoint->bEndpointAddress; |
458 | 531 | ||
459 | /* set up our bulk urb */ | ||
460 | usb_fill_bulk_urb(priv->bulk_read_urb, priv->udev, | ||
461 | usb_rcvbulkpipe(priv->udev, | ||
462 | endpoint->bEndpointAddress), | ||
463 | priv->bulk_in_buffer, priv->buffer_size, | ||
464 | opticon_bulk_callback, priv); | ||
465 | |||
466 | bulk_in_found = true; | 532 | bulk_in_found = true; |
467 | break; | 533 | break; |
468 | } | 534 | } |
@@ -558,6 +624,7 @@ static struct usb_serial_driver opticon_device = { | |||
558 | .unthrottle = opticon_unthrottle, | 624 | .unthrottle = opticon_unthrottle, |
559 | .ioctl = opticon_ioctl, | 625 | .ioctl = opticon_ioctl, |
560 | .tiocmget = opticon_tiocmget, | 626 | .tiocmget = opticon_tiocmget, |
627 | .tiocmset = opticon_tiocmset, | ||
561 | }; | 628 | }; |
562 | 629 | ||
563 | static int __init opticon_init(void) | 630 | static int __init opticon_init(void) |
@@ -581,6 +648,7 @@ static void __exit opticon_exit(void) | |||
581 | 648 | ||
582 | module_init(opticon_init); | 649 | module_init(opticon_init); |
583 | module_exit(opticon_exit); | 650 | module_exit(opticon_exit); |
651 | MODULE_DESCRIPTION(DRIVER_DESC); | ||
584 | MODULE_LICENSE("GPL"); | 652 | MODULE_LICENSE("GPL"); |
585 | 653 | ||
586 | module_param(debug, bool, S_IRUGO | S_IWUSR); | 654 | module_param(debug, bool, S_IRUGO | S_IWUSR); |
diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index 5f46838dfee5..75c7f456eed5 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c | |||
@@ -652,7 +652,8 @@ static const struct usb_device_id option_ids[] = { | |||
652 | { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0028, 0xff, 0xff, 0xff) }, | 652 | { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0028, 0xff, 0xff, 0xff) }, |
653 | { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0029, 0xff, 0xff, 0xff) }, | 653 | { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0029, 0xff, 0xff, 0xff) }, |
654 | { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0030, 0xff, 0xff, 0xff) }, | 654 | { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0030, 0xff, 0xff, 0xff) }, |
655 | { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_MF626, 0xff, 0xff, 0xff) }, | 655 | { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_MF626, 0xff, |
656 | 0xff, 0xff), .driver_info = (kernel_ulong_t)&four_g_w14_blacklist }, | ||
656 | { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0032, 0xff, 0xff, 0xff) }, | 657 | { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0032, 0xff, 0xff, 0xff) }, |
657 | { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0033, 0xff, 0xff, 0xff) }, | 658 | { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0033, 0xff, 0xff, 0xff) }, |
658 | { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0034, 0xff, 0xff, 0xff) }, | 659 | { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0034, 0xff, 0xff, 0xff) }, |
diff --git a/drivers/usb/serial/sierra.c b/drivers/usb/serial/sierra.c index 0457813eebee..5b88b6836a81 100644 --- a/drivers/usb/serial/sierra.c +++ b/drivers/usb/serial/sierra.c | |||
@@ -376,7 +376,10 @@ static int sierra_send_setup(struct usb_serial_port *port) | |||
376 | if (!do_send) | 376 | if (!do_send) |
377 | return 0; | 377 | return 0; |
378 | 378 | ||
379 | usb_autopm_get_interface(serial->interface); | 379 | retval = usb_autopm_get_interface(serial->interface); |
380 | if (retval < 0) | ||
381 | return retval; | ||
382 | |||
380 | retval = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0), | 383 | retval = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0), |
381 | 0x22, 0x21, val, interface, NULL, 0, USB_CTRL_SET_TIMEOUT); | 384 | 0x22, 0x21, val, interface, NULL, 0, USB_CTRL_SET_TIMEOUT); |
382 | usb_autopm_put_interface(serial->interface); | 385 | usb_autopm_put_interface(serial->interface); |
@@ -811,8 +814,12 @@ static void sierra_close(struct usb_serial_port *port) | |||
811 | mutex_lock(&serial->disc_mutex); | 814 | mutex_lock(&serial->disc_mutex); |
812 | if (!serial->disconnected) { | 815 | if (!serial->disconnected) { |
813 | serial->interface->needs_remote_wakeup = 0; | 816 | serial->interface->needs_remote_wakeup = 0; |
814 | usb_autopm_get_interface(serial->interface); | 817 | /* odd error handling due to pm counters */ |
815 | sierra_send_setup(port); | 818 | if (!usb_autopm_get_interface(serial->interface)) |
819 | sierra_send_setup(port); | ||
820 | else | ||
821 | usb_autopm_get_interface_no_resume(serial->interface); | ||
822 | |||
816 | } | 823 | } |
817 | mutex_unlock(&serial->disc_mutex); | 824 | mutex_unlock(&serial->disc_mutex); |
818 | spin_lock_irq(&intfdata->susp_lock); | 825 | spin_lock_irq(&intfdata->susp_lock); |
@@ -865,7 +872,8 @@ static int sierra_open(struct tty_struct *tty, struct usb_serial_port *port) | |||
865 | /* get rid of everything as in close */ | 872 | /* get rid of everything as in close */ |
866 | sierra_close(port); | 873 | sierra_close(port); |
867 | /* restore balance for autopm */ | 874 | /* restore balance for autopm */ |
868 | usb_autopm_put_interface(serial->interface); | 875 | if (!serial->disconnected) |
876 | usb_autopm_put_interface(serial->interface); | ||
869 | return err; | 877 | return err; |
870 | } | 878 | } |
871 | sierra_send_setup(port); | 879 | sierra_send_setup(port); |
diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c index 546a52179bec..2ff90a9c8f47 100644 --- a/drivers/usb/serial/usb-serial.c +++ b/drivers/usb/serial/usb-serial.c | |||
@@ -911,9 +911,8 @@ int usb_serial_probe(struct usb_interface *interface, | |||
911 | dev_err(&interface->dev, "No free urbs available\n"); | 911 | dev_err(&interface->dev, "No free urbs available\n"); |
912 | goto probe_error; | 912 | goto probe_error; |
913 | } | 913 | } |
914 | buffer_size = serial->type->bulk_in_size; | 914 | buffer_size = max_t(int, serial->type->bulk_in_size, |
915 | if (!buffer_size) | 915 | le16_to_cpu(endpoint->wMaxPacketSize)); |
916 | buffer_size = le16_to_cpu(endpoint->wMaxPacketSize); | ||
917 | port->bulk_in_size = buffer_size; | 916 | port->bulk_in_size = buffer_size; |
918 | port->bulk_in_endpointAddress = endpoint->bEndpointAddress; | 917 | port->bulk_in_endpointAddress = endpoint->bEndpointAddress; |
919 | port->bulk_in_buffer = kmalloc(buffer_size, GFP_KERNEL); | 918 | port->bulk_in_buffer = kmalloc(buffer_size, GFP_KERNEL); |
diff --git a/drivers/usb/serial/usb_wwan.c b/drivers/usb/serial/usb_wwan.c index 9c014e2ecd68..eb95aecc0015 100644 --- a/drivers/usb/serial/usb_wwan.c +++ b/drivers/usb/serial/usb_wwan.c | |||
@@ -261,7 +261,8 @@ int usb_wwan_write(struct tty_struct *tty, struct usb_serial_port *port, | |||
261 | intfdata->in_flight--; | 261 | intfdata->in_flight--; |
262 | spin_unlock_irqrestore(&intfdata->susp_lock, | 262 | spin_unlock_irqrestore(&intfdata->susp_lock, |
263 | flags); | 263 | flags); |
264 | continue; | 264 | usb_autopm_put_interface_async(port->serial->interface); |
265 | break; | ||
265 | } | 266 | } |
266 | } | 267 | } |
267 | 268 | ||
@@ -308,11 +309,16 @@ static void usb_wwan_indat_callback(struct urb *urb) | |||
308 | /* Resubmit urb so we continue receiving */ | 309 | /* Resubmit urb so we continue receiving */ |
309 | if (status != -ESHUTDOWN) { | 310 | if (status != -ESHUTDOWN) { |
310 | err = usb_submit_urb(urb, GFP_ATOMIC); | 311 | err = usb_submit_urb(urb, GFP_ATOMIC); |
311 | if (err && err != -EPERM) | 312 | if (err) { |
312 | printk(KERN_ERR "%s: resubmit read urb failed. " | 313 | if (err != -EPERM) { |
313 | "(%d)", __func__, err); | 314 | printk(KERN_ERR "%s: resubmit read urb failed. " |
314 | else | 315 | "(%d)", __func__, err); |
316 | /* busy also in error unless we are killed */ | ||
317 | usb_mark_last_busy(port->serial->dev); | ||
318 | } | ||
319 | } else { | ||
315 | usb_mark_last_busy(port->serial->dev); | 320 | usb_mark_last_busy(port->serial->dev); |
321 | } | ||
316 | } | 322 | } |
317 | 323 | ||
318 | } | 324 | } |
@@ -421,6 +427,7 @@ int usb_wwan_open(struct tty_struct *tty, struct usb_serial_port *port) | |||
421 | spin_lock_irq(&intfdata->susp_lock); | 427 | spin_lock_irq(&intfdata->susp_lock); |
422 | portdata->opened = 1; | 428 | portdata->opened = 1; |
423 | spin_unlock_irq(&intfdata->susp_lock); | 429 | spin_unlock_irq(&intfdata->susp_lock); |
430 | /* this balances a get in the generic USB serial code */ | ||
424 | usb_autopm_put_interface(serial->interface); | 431 | usb_autopm_put_interface(serial->interface); |
425 | 432 | ||
426 | return 0; | 433 | return 0; |
@@ -447,7 +454,8 @@ void usb_wwan_close(struct usb_serial_port *port) | |||
447 | usb_kill_urb(portdata->in_urbs[i]); | 454 | usb_kill_urb(portdata->in_urbs[i]); |
448 | for (i = 0; i < N_OUT_URB; i++) | 455 | for (i = 0; i < N_OUT_URB; i++) |
449 | usb_kill_urb(portdata->out_urbs[i]); | 456 | usb_kill_urb(portdata->out_urbs[i]); |
450 | usb_autopm_get_interface(serial->interface); | 457 | /* balancing - important as an error cannot be handled*/ |
458 | usb_autopm_get_interface_no_resume(serial->interface); | ||
451 | serial->interface->needs_remote_wakeup = 0; | 459 | serial->interface->needs_remote_wakeup = 0; |
452 | } | 460 | } |
453 | } | 461 | } |
@@ -661,6 +669,18 @@ int usb_wwan_suspend(struct usb_serial *serial, pm_message_t message) | |||
661 | } | 669 | } |
662 | EXPORT_SYMBOL(usb_wwan_suspend); | 670 | EXPORT_SYMBOL(usb_wwan_suspend); |
663 | 671 | ||
672 | static void unbusy_queued_urb(struct urb *urb, struct usb_wwan_port_private *portdata) | ||
673 | { | ||
674 | int i; | ||
675 | |||
676 | for (i = 0; i < N_OUT_URB; i++) { | ||
677 | if (urb == portdata->out_urbs[i]) { | ||
678 | clear_bit(i, &portdata->out_busy); | ||
679 | break; | ||
680 | } | ||
681 | } | ||
682 | } | ||
683 | |||
664 | static void play_delayed(struct usb_serial_port *port) | 684 | static void play_delayed(struct usb_serial_port *port) |
665 | { | 685 | { |
666 | struct usb_wwan_intf_private *data; | 686 | struct usb_wwan_intf_private *data; |
@@ -672,8 +692,17 @@ static void play_delayed(struct usb_serial_port *port) | |||
672 | data = port->serial->private; | 692 | data = port->serial->private; |
673 | while ((urb = usb_get_from_anchor(&portdata->delayed))) { | 693 | while ((urb = usb_get_from_anchor(&portdata->delayed))) { |
674 | err = usb_submit_urb(urb, GFP_ATOMIC); | 694 | err = usb_submit_urb(urb, GFP_ATOMIC); |
675 | if (!err) | 695 | if (!err) { |
676 | data->in_flight++; | 696 | data->in_flight++; |
697 | } else { | ||
698 | /* we have to throw away the rest */ | ||
699 | do { | ||
700 | unbusy_queued_urb(urb, portdata); | ||
701 | //extremely dirty | ||
702 | atomic_dec(&port->serial->interface->dev.power.usage_count); | ||
703 | } while ((urb = usb_get_from_anchor(&portdata->delayed))); | ||
704 | break; | ||
705 | } | ||
677 | } | 706 | } |
678 | } | 707 | } |
679 | 708 | ||