aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb')
-rw-r--r--drivers/usb/serial/generic.c102
1 files changed, 84 insertions, 18 deletions
diff --git a/drivers/usb/serial/generic.c b/drivers/usb/serial/generic.c
index 601e0648dec6..53baeec8f265 100644
--- a/drivers/usb/serial/generic.c
+++ b/drivers/usb/serial/generic.c
@@ -66,6 +66,8 @@ struct usb_serial_driver usb_serial_generic_device = {
66 .num_bulk_out = NUM_DONT_CARE, 66 .num_bulk_out = NUM_DONT_CARE,
67 .num_ports = 1, 67 .num_ports = 1,
68 .shutdown = usb_serial_generic_shutdown, 68 .shutdown = usb_serial_generic_shutdown,
69 .throttle = usb_serial_generic_throttle,
70 .unthrottle = usb_serial_generic_unthrottle,
69}; 71};
70 72
71static int generic_probe(struct usb_interface *interface, 73static int generic_probe(struct usb_interface *interface,
@@ -115,6 +117,7 @@ int usb_serial_generic_open (struct usb_serial_port *port, struct file *filp)
115{ 117{
116 struct usb_serial *serial = port->serial; 118 struct usb_serial *serial = port->serial;
117 int result = 0; 119 int result = 0;
120 unsigned long flags;
118 121
119 dbg("%s - port %d", __FUNCTION__, port->number); 122 dbg("%s - port %d", __FUNCTION__, port->number);
120 123
@@ -124,7 +127,13 @@ int usb_serial_generic_open (struct usb_serial_port *port, struct file *filp)
124 if (port->tty) 127 if (port->tty)
125 port->tty->low_latency = 1; 128 port->tty->low_latency = 1;
126 129
127 /* if we have a bulk interrupt, start reading from it */ 130 /* clear the throttle flags */
131 spin_lock_irqsave(&port->lock, flags);
132 port->throttled = 0;
133 port->throttle_req = 0;
134 spin_unlock_irqrestore(&port->lock, flags);
135
136 /* if we have a bulk endpoint, start reading from it */
128 if (serial->num_bulk_in) { 137 if (serial->num_bulk_in) {
129 /* Start reading from the device */ 138 /* Start reading from the device */
130 usb_fill_bulk_urb (port->read_urb, serial->dev, 139 usb_fill_bulk_urb (port->read_urb, serial->dev,
@@ -253,31 +262,22 @@ int usb_serial_generic_chars_in_buffer (struct usb_serial_port *port)
253 return (chars); 262 return (chars);
254} 263}
255 264
256void usb_serial_generic_read_bulk_callback (struct urb *urb) 265/* Push data to tty layer and resubmit the bulk read URB */
266static void flush_and_resubmit_read_urb (struct usb_serial_port *port)
257{ 267{
258 struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
259 struct usb_serial *serial = port->serial; 268 struct usb_serial *serial = port->serial;
260 struct tty_struct *tty; 269 struct urb *urb = port->read_urb;
261 unsigned char *data = urb->transfer_buffer; 270 struct tty_struct *tty = port->tty;
262 int result; 271 int result;
263 272
264 dbg("%s - port %d", __FUNCTION__, port->number); 273 /* Push data to tty */
265
266 if (urb->status) {
267 dbg("%s - nonzero read bulk status received: %d", __FUNCTION__, urb->status);
268 return;
269 }
270
271 usb_serial_debug_data(debug, &port->dev, __FUNCTION__, urb->actual_length, data);
272
273 tty = port->tty;
274 if (tty && urb->actual_length) { 274 if (tty && urb->actual_length) {
275 tty_buffer_request_room(tty, urb->actual_length); 275 tty_buffer_request_room(tty, urb->actual_length);
276 tty_insert_flip_string(tty, data, urb->actual_length); 276 tty_insert_flip_string(tty, urb->transfer_buffer, urb->actual_length);
277 tty_flip_buffer_push(tty); 277 tty_flip_buffer_push(tty); /* is this allowed from an URB callback ? */
278 } 278 }
279 279
280 /* Continue trying to always read */ 280 /* Continue reading from device */
281 usb_fill_bulk_urb (port->read_urb, serial->dev, 281 usb_fill_bulk_urb (port->read_urb, serial->dev,
282 usb_rcvbulkpipe (serial->dev, 282 usb_rcvbulkpipe (serial->dev,
283 port->bulk_in_endpointAddress), 283 port->bulk_in_endpointAddress),
@@ -290,6 +290,40 @@ void usb_serial_generic_read_bulk_callback (struct urb *urb)
290 if (result) 290 if (result)
291 dev_err(&port->dev, "%s - failed resubmitting read urb, error %d\n", __FUNCTION__, result); 291 dev_err(&port->dev, "%s - failed resubmitting read urb, error %d\n", __FUNCTION__, result);
292} 292}
293
294void usb_serial_generic_read_bulk_callback (struct urb *urb)
295{
296 struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
297 unsigned char *data = urb->transfer_buffer;
298 int is_throttled;
299 unsigned long flags;
300
301 dbg("%s - port %d", __FUNCTION__, port->number);
302
303 if (urb->status) {
304 dbg("%s - nonzero read bulk status received: %d", __FUNCTION__, urb->status);
305 return;
306 }
307
308 usb_serial_debug_data(debug, &port->dev, __FUNCTION__, urb->actual_length, data);
309
310 /* Throttle the device if requested by tty */
311 if (urb->actual_length) {
312 spin_lock_irqsave(&port->lock, flags);
313 is_throttled = port->throttled = port->throttle_req;
314 spin_unlock_irqrestore(&port->lock, flags);
315 if (is_throttled) {
316 /* Let the received data linger in the read URB;
317 * usb_serial_generic_unthrottle() will pick it
318 * up later. */
319 dbg("%s - throttling device", __FUNCTION__);
320 return;
321 }
322 }
323
324 /* Handle data and continue reading from device */
325 flush_and_resubmit_read_urb(port);
326}
293EXPORT_SYMBOL_GPL(usb_serial_generic_read_bulk_callback); 327EXPORT_SYMBOL_GPL(usb_serial_generic_read_bulk_callback);
294 328
295void usb_serial_generic_write_bulk_callback (struct urb *urb) 329void usb_serial_generic_write_bulk_callback (struct urb *urb)
@@ -308,6 +342,38 @@ void usb_serial_generic_write_bulk_callback (struct urb *urb)
308} 342}
309EXPORT_SYMBOL_GPL(usb_serial_generic_write_bulk_callback); 343EXPORT_SYMBOL_GPL(usb_serial_generic_write_bulk_callback);
310 344
345void usb_serial_generic_throttle (struct usb_serial_port *port)
346{
347 unsigned long flags;
348
349 dbg("%s - port %d", __FUNCTION__, port->number);
350
351 /* Set the throttle request flag. It will be picked up
352 * by usb_serial_generic_read_bulk_callback(). */
353 spin_lock_irqsave(&port->lock, flags);
354 port->throttle_req = 1;
355 spin_unlock_irqrestore(&port->lock, flags);
356}
357
358void usb_serial_generic_unthrottle (struct usb_serial_port *port)
359{
360 int was_throttled;
361 unsigned long flags;
362
363 dbg("%s - port %d", __FUNCTION__, port->number);
364
365 /* Clear the throttle flags */
366 spin_lock_irqsave(&port->lock, flags);
367 was_throttled = port->throttled;
368 port->throttled = port->throttle_req = 0;
369 spin_unlock_irqrestore(&port->lock, flags);
370
371 if (was_throttled) {
372 /* Handle pending data and resume reading from device */
373 flush_and_resubmit_read_urb(port);
374 }
375}
376
311void usb_serial_generic_shutdown (struct usb_serial *serial) 377void usb_serial_generic_shutdown (struct usb_serial *serial)
312{ 378{
313 int i; 379 int i;