diff options
author | Andrea Bastoni <bastoni@cs.unc.edu> | 2010-05-30 19:16:45 -0400 |
---|---|---|
committer | Andrea Bastoni <bastoni@cs.unc.edu> | 2010-05-30 19:16:45 -0400 |
commit | ada47b5fe13d89735805b566185f4885f5a3f750 (patch) | |
tree | 644b88f8a71896307d71438e9b3af49126ffb22b /drivers/usb/serial/generic.c | |
parent | 43e98717ad40a4ae64545b5ba047c7b86aa44f4f (diff) | |
parent | 3280f21d43ee541f97f8cda5792150d2dbec20d5 (diff) |
Merge branch 'wip-2.6.34' into old-private-masterarchived-private-master
Diffstat (limited to 'drivers/usb/serial/generic.c')
-rw-r--r-- | drivers/usb/serial/generic.c | 76 |
1 files changed, 42 insertions, 34 deletions
diff --git a/drivers/usb/serial/generic.c b/drivers/usb/serial/generic.c index bbe005cefcfb..f804acb138ec 100644 --- a/drivers/usb/serial/generic.c +++ b/drivers/usb/serial/generic.c | |||
@@ -20,6 +20,7 @@ | |||
20 | #include <linux/usb/serial.h> | 20 | #include <linux/usb/serial.h> |
21 | #include <linux/uaccess.h> | 21 | #include <linux/uaccess.h> |
22 | #include <linux/kfifo.h> | 22 | #include <linux/kfifo.h> |
23 | #include <linux/serial.h> | ||
23 | 24 | ||
24 | static int debug; | 25 | static int debug; |
25 | 26 | ||
@@ -41,7 +42,7 @@ static struct usb_device_id generic_device_ids[2]; /* Initially all zeroes. */ | |||
41 | 42 | ||
42 | /* we want to look at all devices, as the vendor/product id can change | 43 | /* we want to look at all devices, as the vendor/product id can change |
43 | * depending on the command line argument */ | 44 | * depending on the command line argument */ |
44 | static struct usb_device_id generic_serial_ids[] = { | 45 | static const struct usb_device_id generic_serial_ids[] = { |
45 | {.driver_info = 42}, | 46 | {.driver_info = 42}, |
46 | {} | 47 | {} |
47 | }; | 48 | }; |
@@ -129,7 +130,7 @@ int usb_serial_generic_open(struct tty_struct *tty, struct usb_serial_port *port | |||
129 | spin_unlock_irqrestore(&port->lock, flags); | 130 | spin_unlock_irqrestore(&port->lock, flags); |
130 | 131 | ||
131 | /* if we have a bulk endpoint, start reading from it */ | 132 | /* if we have a bulk endpoint, start reading from it */ |
132 | if (serial->num_bulk_in) { | 133 | if (port->bulk_in_size) { |
133 | /* Start reading from the device */ | 134 | /* Start reading from the device */ |
134 | usb_fill_bulk_urb(port->read_urb, serial->dev, | 135 | usb_fill_bulk_urb(port->read_urb, serial->dev, |
135 | usb_rcvbulkpipe(serial->dev, | 136 | usb_rcvbulkpipe(serial->dev, |
@@ -158,10 +159,10 @@ static void generic_cleanup(struct usb_serial_port *port) | |||
158 | dbg("%s - port %d", __func__, port->number); | 159 | dbg("%s - port %d", __func__, port->number); |
159 | 160 | ||
160 | if (serial->dev) { | 161 | if (serial->dev) { |
161 | /* shutdown any bulk reads that might be going on */ | 162 | /* shutdown any bulk transfers that might be going on */ |
162 | if (serial->num_bulk_out) | 163 | if (port->bulk_out_size) |
163 | usb_kill_urb(port->write_urb); | 164 | usb_kill_urb(port->write_urb); |
164 | if (serial->num_bulk_in) | 165 | if (port->bulk_in_size) |
165 | usb_kill_urb(port->read_urb); | 166 | usb_kill_urb(port->read_urb); |
166 | } | 167 | } |
167 | } | 168 | } |
@@ -194,7 +195,7 @@ static int usb_serial_multi_urb_write(struct tty_struct *tty, | |||
194 | if (port->urbs_in_flight > | 195 | if (port->urbs_in_flight > |
195 | port->serial->type->max_in_flight_urbs) { | 196 | port->serial->type->max_in_flight_urbs) { |
196 | spin_unlock_irqrestore(&port->lock, flags); | 197 | spin_unlock_irqrestore(&port->lock, flags); |
197 | dbg("%s - write limit hit\n", __func__); | 198 | dbg("%s - write limit hit", __func__); |
198 | return bwrite; | 199 | return bwrite; |
199 | } | 200 | } |
200 | port->tx_bytes_flight += towrite; | 201 | port->tx_bytes_flight += towrite; |
@@ -276,7 +277,7 @@ static int usb_serial_generic_write_start(struct usb_serial_port *port) | |||
276 | if (port->write_urb_busy) | 277 | if (port->write_urb_busy) |
277 | start_io = false; | 278 | start_io = false; |
278 | else { | 279 | else { |
279 | start_io = (__kfifo_len(port->write_fifo) != 0); | 280 | start_io = (kfifo_len(&port->write_fifo) != 0); |
280 | port->write_urb_busy = start_io; | 281 | port->write_urb_busy = start_io; |
281 | } | 282 | } |
282 | spin_unlock_irqrestore(&port->lock, flags); | 283 | spin_unlock_irqrestore(&port->lock, flags); |
@@ -285,7 +286,7 @@ static int usb_serial_generic_write_start(struct usb_serial_port *port) | |||
285 | return 0; | 286 | return 0; |
286 | 287 | ||
287 | data = port->write_urb->transfer_buffer; | 288 | data = port->write_urb->transfer_buffer; |
288 | count = kfifo_get(port->write_fifo, data, port->bulk_out_size); | 289 | count = kfifo_out_locked(&port->write_fifo, data, port->bulk_out_size, &port->lock); |
289 | usb_serial_debug_data(debug, &port->dev, __func__, count, data); | 290 | usb_serial_debug_data(debug, &port->dev, __func__, count, data); |
290 | 291 | ||
291 | /* set up our urb */ | 292 | /* set up our urb */ |
@@ -332,20 +333,20 @@ int usb_serial_generic_write(struct tty_struct *tty, | |||
332 | 333 | ||
333 | dbg("%s - port %d", __func__, port->number); | 334 | dbg("%s - port %d", __func__, port->number); |
334 | 335 | ||
336 | /* only do something if we have a bulk out endpoint */ | ||
337 | if (!port->bulk_out_size) | ||
338 | return -ENODEV; | ||
339 | |||
335 | if (count == 0) { | 340 | if (count == 0) { |
336 | dbg("%s - write request of 0 bytes", __func__); | 341 | dbg("%s - write request of 0 bytes", __func__); |
337 | return 0; | 342 | return 0; |
338 | } | 343 | } |
339 | 344 | ||
340 | /* only do something if we have a bulk out endpoint */ | ||
341 | if (!serial->num_bulk_out) | ||
342 | return 0; | ||
343 | |||
344 | if (serial->type->max_in_flight_urbs) | 345 | if (serial->type->max_in_flight_urbs) |
345 | return usb_serial_multi_urb_write(tty, port, | 346 | return usb_serial_multi_urb_write(tty, port, |
346 | buf, count); | 347 | buf, count); |
347 | 348 | ||
348 | count = kfifo_put(port->write_fifo, buf, count); | 349 | count = kfifo_in_locked(&port->write_fifo, buf, count, &port->lock); |
349 | result = usb_serial_generic_write_start(port); | 350 | result = usb_serial_generic_write_start(port); |
350 | 351 | ||
351 | if (result >= 0) | 352 | if (result >= 0) |
@@ -363,14 +364,19 @@ int usb_serial_generic_write_room(struct tty_struct *tty) | |||
363 | int room = 0; | 364 | int room = 0; |
364 | 365 | ||
365 | dbg("%s - port %d", __func__, port->number); | 366 | dbg("%s - port %d", __func__, port->number); |
367 | |||
368 | if (!port->bulk_out_size) | ||
369 | return 0; | ||
370 | |||
366 | spin_lock_irqsave(&port->lock, flags); | 371 | spin_lock_irqsave(&port->lock, flags); |
367 | if (serial->type->max_in_flight_urbs) { | 372 | if (serial->type->max_in_flight_urbs) { |
368 | if (port->urbs_in_flight < serial->type->max_in_flight_urbs) | 373 | if (port->urbs_in_flight < serial->type->max_in_flight_urbs) |
369 | room = port->bulk_out_size * | 374 | room = port->bulk_out_size * |
370 | (serial->type->max_in_flight_urbs - | 375 | (serial->type->max_in_flight_urbs - |
371 | port->urbs_in_flight); | 376 | port->urbs_in_flight); |
372 | } else if (serial->num_bulk_out) | 377 | } else { |
373 | room = port->write_fifo->size - __kfifo_len(port->write_fifo); | 378 | room = kfifo_avail(&port->write_fifo); |
379 | } | ||
374 | spin_unlock_irqrestore(&port->lock, flags); | 380 | spin_unlock_irqrestore(&port->lock, flags); |
375 | 381 | ||
376 | dbg("%s - returns %d", __func__, room); | 382 | dbg("%s - returns %d", __func__, room); |
@@ -381,17 +387,20 @@ int usb_serial_generic_chars_in_buffer(struct tty_struct *tty) | |||
381 | { | 387 | { |
382 | struct usb_serial_port *port = tty->driver_data; | 388 | struct usb_serial_port *port = tty->driver_data; |
383 | struct usb_serial *serial = port->serial; | 389 | struct usb_serial *serial = port->serial; |
384 | int chars = 0; | ||
385 | unsigned long flags; | 390 | unsigned long flags; |
391 | int chars; | ||
386 | 392 | ||
387 | dbg("%s - port %d", __func__, port->number); | 393 | dbg("%s - port %d", __func__, port->number); |
388 | 394 | ||
389 | if (serial->type->max_in_flight_urbs) { | 395 | if (!port->bulk_out_size) |
390 | spin_lock_irqsave(&port->lock, flags); | 396 | return 0; |
397 | |||
398 | spin_lock_irqsave(&port->lock, flags); | ||
399 | if (serial->type->max_in_flight_urbs) | ||
391 | chars = port->tx_bytes_flight; | 400 | chars = port->tx_bytes_flight; |
392 | spin_unlock_irqrestore(&port->lock, flags); | 401 | else |
393 | } else if (serial->num_bulk_out) | 402 | chars = kfifo_len(&port->write_fifo); |
394 | chars = kfifo_len(port->write_fifo); | 403 | spin_unlock_irqrestore(&port->lock, flags); |
395 | 404 | ||
396 | dbg("%s - returns %d", __func__, chars); | 405 | dbg("%s - returns %d", __func__, chars); |
397 | return chars; | 406 | return chars; |
@@ -414,11 +423,13 @@ void usb_serial_generic_resubmit_read_urb(struct usb_serial_port *port, | |||
414 | ((serial->type->read_bulk_callback) ? | 423 | ((serial->type->read_bulk_callback) ? |
415 | serial->type->read_bulk_callback : | 424 | serial->type->read_bulk_callback : |
416 | usb_serial_generic_read_bulk_callback), port); | 425 | usb_serial_generic_read_bulk_callback), port); |
426 | |||
417 | result = usb_submit_urb(urb, mem_flags); | 427 | result = usb_submit_urb(urb, mem_flags); |
418 | if (result) | 428 | if (result && result != -EPERM) { |
419 | dev_err(&port->dev, | 429 | dev_err(&port->dev, |
420 | "%s - failed resubmitting read urb, error %d\n", | 430 | "%s - failed resubmitting read urb, error %d\n", |
421 | __func__, result); | 431 | __func__, result); |
432 | } | ||
422 | } | 433 | } |
423 | EXPORT_SYMBOL_GPL(usb_serial_generic_resubmit_read_urb); | 434 | EXPORT_SYMBOL_GPL(usb_serial_generic_resubmit_read_urb); |
424 | 435 | ||
@@ -489,29 +500,26 @@ void usb_serial_generic_write_bulk_callback(struct urb *urb) | |||
489 | dbg("%s - port %d", __func__, port->number); | 500 | dbg("%s - port %d", __func__, port->number); |
490 | 501 | ||
491 | if (port->serial->type->max_in_flight_urbs) { | 502 | if (port->serial->type->max_in_flight_urbs) { |
503 | kfree(urb->transfer_buffer); | ||
504 | |||
492 | spin_lock_irqsave(&port->lock, flags); | 505 | spin_lock_irqsave(&port->lock, flags); |
493 | --port->urbs_in_flight; | 506 | --port->urbs_in_flight; |
494 | port->tx_bytes_flight -= urb->transfer_buffer_length; | 507 | port->tx_bytes_flight -= urb->transfer_buffer_length; |
495 | if (port->urbs_in_flight < 0) | 508 | if (port->urbs_in_flight < 0) |
496 | port->urbs_in_flight = 0; | 509 | port->urbs_in_flight = 0; |
497 | spin_unlock_irqrestore(&port->lock, flags); | 510 | spin_unlock_irqrestore(&port->lock, flags); |
498 | |||
499 | if (status) { | ||
500 | dbg("%s - nonzero multi-urb write bulk status " | ||
501 | "received: %d", __func__, status); | ||
502 | return; | ||
503 | } | ||
504 | } else { | 511 | } else { |
505 | port->write_urb_busy = 0; | 512 | port->write_urb_busy = 0; |
506 | 513 | ||
507 | if (status) { | 514 | if (status) |
508 | dbg("%s - nonzero multi-urb write bulk status " | 515 | kfifo_reset_out(&port->write_fifo); |
509 | "received: %d", __func__, status); | 516 | else |
510 | kfifo_reset(port->write_fifo); | ||
511 | } else | ||
512 | usb_serial_generic_write_start(port); | 517 | usb_serial_generic_write_start(port); |
513 | } | 518 | } |
514 | 519 | ||
520 | if (status) | ||
521 | dbg("%s - non-zero urb status: %d", __func__, status); | ||
522 | |||
515 | usb_serial_port_softint(port); | 523 | usb_serial_port_softint(port); |
516 | } | 524 | } |
517 | EXPORT_SYMBOL_GPL(usb_serial_generic_write_bulk_callback); | 525 | EXPORT_SYMBOL_GPL(usb_serial_generic_write_bulk_callback); |
@@ -583,7 +591,7 @@ int usb_serial_generic_resume(struct usb_serial *serial) | |||
583 | 591 | ||
584 | for (i = 0; i < serial->num_ports; i++) { | 592 | for (i = 0; i < serial->num_ports; i++) { |
585 | port = serial->port[i]; | 593 | port = serial->port[i]; |
586 | if (!port->port.count) | 594 | if (!test_bit(ASYNCB_INITIALIZED, &port->port.flags)) |
587 | continue; | 595 | continue; |
588 | 596 | ||
589 | if (port->read_urb) { | 597 | if (port->read_urb) { |