diff options
author | Greg Kroah-Hartman <gregkh@suse.de> | 2007-06-20 01:22:23 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2007-07-12 19:34:37 -0400 |
commit | 9e85c5f63268a5700860f53e52b090973652a5b2 (patch) | |
tree | 4d0258d76ceab4621e57b646ad80ace80f5911aa /drivers/usb | |
parent | 17c2327419a889293fb955baf0c69a7d38c5809c (diff) |
USB: sierra: cleanup the startup and shutdown path
This removes the ugly code that was copied from the keyspan driver and
allocates the in urbs in a much shorter code path that can be understood
easier.
Also turned off the interrupt urb when no port was open as it's not nice
to keep the bus busy for no good reason at all (this should be a power
savings.)
All in all, this saved over 40 lines of code and cleaned things up
better.
Cc: Kevin Lloyd <linux@sierrawireless.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb')
-rw-r--r-- | drivers/usb/serial/sierra.c | 130 |
1 files changed, 41 insertions, 89 deletions
diff --git a/drivers/usb/serial/sierra.c b/drivers/usb/serial/sierra.c index 551c6ce89f66..e7db20343d1a 100644 --- a/drivers/usb/serial/sierra.c +++ b/drivers/usb/serial/sierra.c | |||
@@ -418,7 +418,7 @@ static int sierra_open(struct usb_serial_port *port, struct file *filp) | |||
418 | { | 418 | { |
419 | struct sierra_port_private *portdata; | 419 | struct sierra_port_private *portdata; |
420 | struct usb_serial *serial = port->serial; | 420 | struct usb_serial *serial = port->serial; |
421 | int i, err; | 421 | int i; |
422 | struct urb *urb; | 422 | struct urb *urb; |
423 | int result; | 423 | int result; |
424 | __u16 set_mode_dzero = 0x0000; | 424 | __u16 set_mode_dzero = 0x0000; |
@@ -434,7 +434,7 @@ static int sierra_open(struct usb_serial_port *port, struct file *filp) | |||
434 | /* Reset low level data toggle and start reading from endpoints */ | 434 | /* Reset low level data toggle and start reading from endpoints */ |
435 | for (i = 0; i < N_IN_URB; i++) { | 435 | for (i = 0; i < N_IN_URB; i++) { |
436 | urb = portdata->in_urbs[i]; | 436 | urb = portdata->in_urbs[i]; |
437 | if (! urb) | 437 | if (!urb) |
438 | continue; | 438 | continue; |
439 | if (urb->dev != serial->dev) { | 439 | if (urb->dev != serial->dev) { |
440 | dbg("%s: dev %p != %p", __FUNCTION__, | 440 | dbg("%s: dev %p != %p", __FUNCTION__, |
@@ -448,11 +448,10 @@ static int sierra_open(struct usb_serial_port *port, struct file *filp) | |||
448 | */ | 448 | */ |
449 | usb_clear_halt(urb->dev, urb->pipe); | 449 | usb_clear_halt(urb->dev, urb->pipe); |
450 | 450 | ||
451 | err = usb_submit_urb(urb, GFP_KERNEL); | 451 | result = usb_submit_urb(urb, GFP_KERNEL); |
452 | if (err) { | 452 | if (result) { |
453 | dbg("%s: submit urb %d failed (%d) %d", | 453 | dev_err(&port->dev, "submit urb %d failed (%d) %d", |
454 | __FUNCTION__, i, err, | 454 | i, result, urb->transfer_buffer_length); |
455 | urb->transfer_buffer_length); | ||
456 | } | 455 | } |
457 | } | 456 | } |
458 | 457 | ||
@@ -466,7 +465,14 @@ static int sierra_open(struct usb_serial_port *port, struct file *filp) | |||
466 | 465 | ||
467 | sierra_send_setup(port); | 466 | sierra_send_setup(port); |
468 | 467 | ||
469 | return (0); | 468 | /* start up the interrupt endpoint if we have one */ |
469 | if (port->interrupt_in_urb) { | ||
470 | result = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL); | ||
471 | if (result) | ||
472 | dev_err(&port->dev, "submit irq_in urb failed %d", | ||
473 | result); | ||
474 | } | ||
475 | return 0; | ||
470 | } | 476 | } |
471 | 477 | ||
472 | static void sierra_close(struct usb_serial_port *port, struct file *filp) | 478 | static void sierra_close(struct usb_serial_port *port, struct file *filp) |
@@ -486,62 +492,21 @@ static void sierra_close(struct usb_serial_port *port, struct file *filp) | |||
486 | 492 | ||
487 | /* Stop reading/writing urbs */ | 493 | /* Stop reading/writing urbs */ |
488 | for (i = 0; i < N_IN_URB; i++) | 494 | for (i = 0; i < N_IN_URB; i++) |
489 | usb_unlink_urb(portdata->in_urbs[i]); | 495 | usb_kill_urb(portdata->in_urbs[i]); |
490 | } | ||
491 | port->tty = NULL; | ||
492 | } | ||
493 | |||
494 | /* Helper functions used by sierra_setup_urbs */ | ||
495 | static struct urb *sierra_setup_urb(struct usb_serial *serial, int endpoint, | ||
496 | int dir, void *ctx, char *buf, int len, | ||
497 | usb_complete_t callback) | ||
498 | { | ||
499 | struct urb *urb; | ||
500 | |||
501 | if (endpoint == -1) | ||
502 | return NULL; /* endpoint not needed */ | ||
503 | |||
504 | urb = usb_alloc_urb(0, GFP_KERNEL); /* No ISO */ | ||
505 | if (urb == NULL) { | ||
506 | dbg("%s: alloc for endpoint %d failed.", __FUNCTION__, endpoint); | ||
507 | return NULL; | ||
508 | } | 496 | } |
509 | 497 | ||
510 | /* Fill URB using supplied data. */ | 498 | usb_kill_urb(port->interrupt_in_urb); |
511 | usb_fill_bulk_urb(urb, serial->dev, | ||
512 | usb_sndbulkpipe(serial->dev, endpoint) | dir, | ||
513 | buf, len, callback, ctx); | ||
514 | |||
515 | return urb; | ||
516 | } | ||
517 | 499 | ||
518 | /* Setup urbs */ | 500 | port->tty = NULL; |
519 | static void sierra_setup_urbs(struct usb_serial *serial) | ||
520 | { | ||
521 | int i,j; | ||
522 | struct usb_serial_port *port; | ||
523 | struct sierra_port_private *portdata; | ||
524 | |||
525 | dbg("%s", __FUNCTION__); | ||
526 | |||
527 | for (i = 0; i < serial->num_ports; i++) { | ||
528 | port = serial->port[i]; | ||
529 | portdata = usb_get_serial_port_data(port); | ||
530 | |||
531 | /* Do indat endpoints first */ | ||
532 | for (j = 0; j < N_IN_URB; ++j) { | ||
533 | portdata->in_urbs[j] = sierra_setup_urb (serial, | ||
534 | port->bulk_in_endpointAddress, USB_DIR_IN, port, | ||
535 | portdata->in_buffer[j], IN_BUFLEN, sierra_indat_callback); | ||
536 | } | ||
537 | } | ||
538 | } | 501 | } |
539 | 502 | ||
540 | static int sierra_startup(struct usb_serial *serial) | 503 | static int sierra_startup(struct usb_serial *serial) |
541 | { | 504 | { |
542 | int i, err; | ||
543 | struct usb_serial_port *port; | 505 | struct usb_serial_port *port; |
544 | struct sierra_port_private *portdata; | 506 | struct sierra_port_private *portdata; |
507 | struct urb *urb; | ||
508 | int i; | ||
509 | int j; | ||
545 | 510 | ||
546 | dbg("%s", __FUNCTION__); | 511 | dbg("%s", __FUNCTION__); |
547 | 512 | ||
@@ -558,16 +523,24 @@ static int sierra_startup(struct usb_serial *serial) | |||
558 | 523 | ||
559 | usb_set_serial_port_data(port, portdata); | 524 | usb_set_serial_port_data(port, portdata); |
560 | 525 | ||
561 | if (! port->interrupt_in_urb) | 526 | /* initialize the in urbs */ |
562 | continue; | 527 | for (j = 0; j < N_IN_URB; ++j) { |
563 | err = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL); | 528 | urb = usb_alloc_urb(0, GFP_KERNEL); |
564 | if (err) | 529 | if (urb == NULL) { |
565 | dbg("%s: submit irq_in urb failed %d", | 530 | dbg("%s: alloc for in port failed.", |
566 | __FUNCTION__, err); | 531 | __FUNCTION__); |
532 | continue; | ||
533 | } | ||
534 | /* Fill URB using supplied data. */ | ||
535 | usb_fill_bulk_urb(urb, serial->dev, | ||
536 | usb_rcvbulkpipe(serial->dev, | ||
537 | port->bulk_in_endpointAddress), | ||
538 | portdata->in_buffer[j], IN_BUFLEN, | ||
539 | sierra_indat_callback, port); | ||
540 | portdata->in_urbs[j] = urb; | ||
541 | } | ||
567 | } | 542 | } |
568 | 543 | ||
569 | sierra_setup_urbs(serial); | ||
570 | |||
571 | return 0; | 544 | return 0; |
572 | } | 545 | } |
573 | 546 | ||
@@ -579,20 +552,6 @@ static void sierra_shutdown(struct usb_serial *serial) | |||
579 | 552 | ||
580 | dbg("%s", __FUNCTION__); | 553 | dbg("%s", __FUNCTION__); |
581 | 554 | ||
582 | /* Stop reading/writing urbs */ | ||
583 | for (i = 0; i < serial->num_ports; ++i) { | ||
584 | port = serial->port[i]; | ||
585 | if (!port) | ||
586 | continue; | ||
587 | portdata = usb_get_serial_port_data(port); | ||
588 | if (!portdata) | ||
589 | continue; | ||
590 | |||
591 | for (j = 0; j < N_IN_URB; j++) | ||
592 | usb_unlink_urb(portdata->in_urbs[j]); | ||
593 | } | ||
594 | |||
595 | /* Now free them */ | ||
596 | for (i = 0; i < serial->num_ports; ++i) { | 555 | for (i = 0; i < serial->num_ports; ++i) { |
597 | port = serial->port[i]; | 556 | port = serial->port[i]; |
598 | if (!port) | 557 | if (!port) |
@@ -602,19 +561,12 @@ static void sierra_shutdown(struct usb_serial *serial) | |||
602 | continue; | 561 | continue; |
603 | 562 | ||
604 | for (j = 0; j < N_IN_URB; j++) { | 563 | for (j = 0; j < N_IN_URB; j++) { |
605 | if (portdata->in_urbs[j]) { | 564 | usb_kill_urb(portdata->in_urbs[j]); |
606 | usb_free_urb(portdata->in_urbs[j]); | 565 | usb_free_urb(portdata->in_urbs[j]); |
607 | portdata->in_urbs[j] = NULL; | 566 | portdata->in_urbs[j] = NULL; |
608 | } | ||
609 | } | 567 | } |
610 | } | 568 | kfree(portdata); |
611 | 569 | usb_set_serial_port_data(port, NULL); | |
612 | /* Now free per port private data */ | ||
613 | for (i = 0; i < serial->num_ports; i++) { | ||
614 | port = serial->port[i]; | ||
615 | if (!port) | ||
616 | continue; | ||
617 | kfree(usb_get_serial_port_data(port)); | ||
618 | } | 570 | } |
619 | } | 571 | } |
620 | 572 | ||