aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/serial/option.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/serial/option.c')
-rw-r--r--drivers/usb/serial/option.c34
1 files changed, 25 insertions, 9 deletions
diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c
index 5d3999e3ff61..84c12b5f1271 100644
--- a/drivers/usb/serial/option.c
+++ b/drivers/usb/serial/option.c
@@ -38,6 +38,7 @@
38#include <linux/tty.h> 38#include <linux/tty.h>
39#include <linux/tty_flip.h> 39#include <linux/tty_flip.h>
40#include <linux/module.h> 40#include <linux/module.h>
41#include <linux/bitops.h>
41#include <linux/usb.h> 42#include <linux/usb.h>
42#include <linux/usb/serial.h> 43#include <linux/usb/serial.h>
43 44
@@ -240,6 +241,7 @@ struct option_port_private {
240 /* Output endpoints and buffer for this port */ 241 /* Output endpoints and buffer for this port */
241 struct urb *out_urbs[N_OUT_URB]; 242 struct urb *out_urbs[N_OUT_URB];
242 char out_buffer[N_OUT_URB][OUT_BUFLEN]; 243 char out_buffer[N_OUT_URB][OUT_BUFLEN];
244 unsigned long out_busy; /* Bit vector of URBs in use */
243 245
244 /* Settings for the port */ 246 /* Settings for the port */
245 int rts_state; /* Handshaking pins (outputs) */ 247 int rts_state; /* Handshaking pins (outputs) */
@@ -370,7 +372,7 @@ static int option_write(struct usb_serial_port *port,
370 todo = OUT_BUFLEN; 372 todo = OUT_BUFLEN;
371 373
372 this_urb = portdata->out_urbs[i]; 374 this_urb = portdata->out_urbs[i];
373 if (this_urb->status == -EINPROGRESS) { 375 if (test_and_set_bit(i, &portdata->out_busy)) {
374 if (time_before(jiffies, 376 if (time_before(jiffies,
375 portdata->tx_start_time[i] + 10 * HZ)) 377 portdata->tx_start_time[i] + 10 * HZ))
376 continue; 378 continue;
@@ -394,6 +396,7 @@ static int option_write(struct usb_serial_port *port,
394 dbg("usb_submit_urb %p (write bulk) failed " 396 dbg("usb_submit_urb %p (write bulk) failed "
395 "(%d, has %d)", this_urb, 397 "(%d, has %d)", this_urb,
396 err, this_urb->status); 398 err, this_urb->status);
399 clear_bit(i, &portdata->out_busy);
397 continue; 400 continue;
398 } 401 }
399 portdata->tx_start_time[i] = jiffies; 402 portdata->tx_start_time[i] = jiffies;
@@ -413,15 +416,16 @@ static void option_indat_callback(struct urb *urb)
413 struct usb_serial_port *port; 416 struct usb_serial_port *port;
414 struct tty_struct *tty; 417 struct tty_struct *tty;
415 unsigned char *data = urb->transfer_buffer; 418 unsigned char *data = urb->transfer_buffer;
419 int status = urb->status;
416 420
417 dbg("%s: %p", __FUNCTION__, urb); 421 dbg("%s: %p", __FUNCTION__, urb);
418 422
419 endpoint = usb_pipeendpoint(urb->pipe); 423 endpoint = usb_pipeendpoint(urb->pipe);
420 port = (struct usb_serial_port *) urb->context; 424 port = (struct usb_serial_port *) urb->context;
421 425
422 if (urb->status) { 426 if (status) {
423 dbg("%s: nonzero status: %d on endpoint %02x.", 427 dbg("%s: nonzero status: %d on endpoint %02x.",
424 __FUNCTION__, urb->status, endpoint); 428 __FUNCTION__, status, endpoint);
425 } else { 429 } else {
426 tty = port->tty; 430 tty = port->tty;
427 if (urb->actual_length) { 431 if (urb->actual_length) {
@@ -433,7 +437,7 @@ static void option_indat_callback(struct urb *urb)
433 } 437 }
434 438
435 /* Resubmit urb so we continue receiving */ 439 /* Resubmit urb so we continue receiving */
436 if (port->open_count && urb->status != -ESHUTDOWN) { 440 if (port->open_count && status != -ESHUTDOWN) {
437 err = usb_submit_urb(urb, GFP_ATOMIC); 441 err = usb_submit_urb(urb, GFP_ATOMIC);
438 if (err) 442 if (err)
439 printk(KERN_ERR "%s: resubmit read urb failed. " 443 printk(KERN_ERR "%s: resubmit read urb failed. "
@@ -446,17 +450,29 @@ static void option_indat_callback(struct urb *urb)
446static void option_outdat_callback(struct urb *urb) 450static void option_outdat_callback(struct urb *urb)
447{ 451{
448 struct usb_serial_port *port; 452 struct usb_serial_port *port;
453 struct option_port_private *portdata;
454 int i;
449 455
450 dbg("%s", __FUNCTION__); 456 dbg("%s", __FUNCTION__);
451 457
452 port = (struct usb_serial_port *) urb->context; 458 port = (struct usb_serial_port *) urb->context;
453 459
454 usb_serial_port_softint(port); 460 usb_serial_port_softint(port);
461
462 portdata = usb_get_serial_port_data(port);
463 for (i = 0; i < N_OUT_URB; ++i) {
464 if (portdata->out_urbs[i] == urb) {
465 smp_mb__before_clear_bit();
466 clear_bit(i, &portdata->out_busy);
467 break;
468 }
469 }
455} 470}
456 471
457static void option_instat_callback(struct urb *urb) 472static void option_instat_callback(struct urb *urb)
458{ 473{
459 int err; 474 int err;
475 int status = urb->status;
460 struct usb_serial_port *port = (struct usb_serial_port *) urb->context; 476 struct usb_serial_port *port = (struct usb_serial_port *) urb->context;
461 struct option_port_private *portdata = usb_get_serial_port_data(port); 477 struct option_port_private *portdata = usb_get_serial_port_data(port);
462 struct usb_serial *serial = port->serial; 478 struct usb_serial *serial = port->serial;
@@ -464,7 +480,7 @@ static void option_instat_callback(struct urb *urb)
464 dbg("%s", __FUNCTION__); 480 dbg("%s", __FUNCTION__);
465 dbg("%s: urb %p port %p has data %p", __FUNCTION__,urb,port,portdata); 481 dbg("%s: urb %p port %p has data %p", __FUNCTION__,urb,port,portdata);
466 482
467 if (urb->status == 0) { 483 if (status == 0) {
468 struct usb_ctrlrequest *req_pkt = 484 struct usb_ctrlrequest *req_pkt =
469 (struct usb_ctrlrequest *)urb->transfer_buffer; 485 (struct usb_ctrlrequest *)urb->transfer_buffer;
470 486
@@ -495,10 +511,10 @@ static void option_instat_callback(struct urb *urb)
495 req_pkt->bRequestType,req_pkt->bRequest); 511 req_pkt->bRequestType,req_pkt->bRequest);
496 } 512 }
497 } else 513 } else
498 dbg("%s: error %d", __FUNCTION__, urb->status); 514 dbg("%s: error %d", __FUNCTION__, status);
499 515
500 /* Resubmit urb so we continue receiving IRQ data */ 516 /* Resubmit urb so we continue receiving IRQ data */
501 if (urb->status != -ESHUTDOWN) { 517 if (status != -ESHUTDOWN) {
502 urb->dev = serial->dev; 518 urb->dev = serial->dev;
503 err = usb_submit_urb(urb, GFP_ATOMIC); 519 err = usb_submit_urb(urb, GFP_ATOMIC);
504 if (err) 520 if (err)
@@ -518,7 +534,7 @@ static int option_write_room(struct usb_serial_port *port)
518 534
519 for (i=0; i < N_OUT_URB; i++) { 535 for (i=0; i < N_OUT_URB; i++) {
520 this_urb = portdata->out_urbs[i]; 536 this_urb = portdata->out_urbs[i];
521 if (this_urb && this_urb->status != -EINPROGRESS) 537 if (this_urb && !test_bit(i, &portdata->out_busy))
522 data_len += OUT_BUFLEN; 538 data_len += OUT_BUFLEN;
523 } 539 }
524 540
@@ -537,7 +553,7 @@ static int option_chars_in_buffer(struct usb_serial_port *port)
537 553
538 for (i=0; i < N_OUT_URB; i++) { 554 for (i=0; i < N_OUT_URB; i++) {
539 this_urb = portdata->out_urbs[i]; 555 this_urb = portdata->out_urbs[i];
540 if (this_urb && this_urb->status == -EINPROGRESS) 556 if (this_urb && test_bit(i, &portdata->out_busy))
541 data_len += this_urb->transfer_buffer_length; 557 data_len += this_urb->transfer_buffer_length;
542 } 558 }
543 dbg("%s: %d", __FUNCTION__, data_len); 559 dbg("%s: %d", __FUNCTION__, data_len);