diff options
author | Johan Hovold <jhovold@gmail.com> | 2012-03-22 11:50:55 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2012-04-10 16:32:07 -0400 |
commit | 5c0c7582a618e843bdcf9c4b20d019d8ffd176ee (patch) | |
tree | 79429a3d1e56e3ba960f600bd85a495c20a25dce /drivers/usb | |
parent | a6765cbafa1570617fd68e4ff5fa525329c72e66 (diff) |
USB: whiteheat: reimplement using generic framework
Kill custom list-based read and write implementations and reimplement
using the generic framework.
Compile-only tested.
Signed-off-by: Johan Hovold <jhovold@gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/usb')
-rw-r--r-- | drivers/usb/serial/whiteheat.c | 539 |
1 files changed, 8 insertions, 531 deletions
diff --git a/drivers/usb/serial/whiteheat.c b/drivers/usb/serial/whiteheat.c index 522bf850a05d..c141b472b6a2 100644 --- a/drivers/usb/serial/whiteheat.c +++ b/drivers/usb/serial/whiteheat.c | |||
@@ -95,10 +95,6 @@ static void whiteheat_release(struct usb_serial *serial); | |||
95 | static int whiteheat_open(struct tty_struct *tty, | 95 | static int whiteheat_open(struct tty_struct *tty, |
96 | struct usb_serial_port *port); | 96 | struct usb_serial_port *port); |
97 | static void whiteheat_close(struct usb_serial_port *port); | 97 | static void whiteheat_close(struct usb_serial_port *port); |
98 | static int whiteheat_write(struct tty_struct *tty, | ||
99 | struct usb_serial_port *port, | ||
100 | const unsigned char *buf, int count); | ||
101 | static int whiteheat_write_room(struct tty_struct *tty); | ||
102 | static int whiteheat_ioctl(struct tty_struct *tty, | 98 | static int whiteheat_ioctl(struct tty_struct *tty, |
103 | unsigned int cmd, unsigned long arg); | 99 | unsigned int cmd, unsigned long arg); |
104 | static void whiteheat_set_termios(struct tty_struct *tty, | 100 | static void whiteheat_set_termios(struct tty_struct *tty, |
@@ -107,11 +103,6 @@ static int whiteheat_tiocmget(struct tty_struct *tty); | |||
107 | static int whiteheat_tiocmset(struct tty_struct *tty, | 103 | static int whiteheat_tiocmset(struct tty_struct *tty, |
108 | unsigned int set, unsigned int clear); | 104 | unsigned int set, unsigned int clear); |
109 | static void whiteheat_break_ctl(struct tty_struct *tty, int break_state); | 105 | static void whiteheat_break_ctl(struct tty_struct *tty, int break_state); |
110 | static int whiteheat_chars_in_buffer(struct tty_struct *tty); | ||
111 | static void whiteheat_throttle(struct tty_struct *tty); | ||
112 | static void whiteheat_unthrottle(struct tty_struct *tty); | ||
113 | static void whiteheat_read_callback(struct urb *urb); | ||
114 | static void whiteheat_write_callback(struct urb *urb); | ||
115 | 106 | ||
116 | static struct usb_serial_driver whiteheat_fake_device = { | 107 | static struct usb_serial_driver whiteheat_fake_device = { |
117 | .driver = { | 108 | .driver = { |
@@ -137,18 +128,13 @@ static struct usb_serial_driver whiteheat_device = { | |||
137 | .release = whiteheat_release, | 128 | .release = whiteheat_release, |
138 | .open = whiteheat_open, | 129 | .open = whiteheat_open, |
139 | .close = whiteheat_close, | 130 | .close = whiteheat_close, |
140 | .write = whiteheat_write, | ||
141 | .write_room = whiteheat_write_room, | ||
142 | .ioctl = whiteheat_ioctl, | 131 | .ioctl = whiteheat_ioctl, |
143 | .set_termios = whiteheat_set_termios, | 132 | .set_termios = whiteheat_set_termios, |
144 | .break_ctl = whiteheat_break_ctl, | 133 | .break_ctl = whiteheat_break_ctl, |
145 | .tiocmget = whiteheat_tiocmget, | 134 | .tiocmget = whiteheat_tiocmget, |
146 | .tiocmset = whiteheat_tiocmset, | 135 | .tiocmset = whiteheat_tiocmset, |
147 | .chars_in_buffer = whiteheat_chars_in_buffer, | 136 | .throttle = usb_serial_generic_throttle, |
148 | .throttle = whiteheat_throttle, | 137 | .unthrottle = usb_serial_generic_unthrottle, |
149 | .unthrottle = whiteheat_unthrottle, | ||
150 | .read_bulk_callback = whiteheat_read_callback, | ||
151 | .write_bulk_callback = whiteheat_write_callback, | ||
152 | }; | 138 | }; |
153 | 139 | ||
154 | static struct usb_serial_driver * const serial_drivers[] = { | 140 | static struct usb_serial_driver * const serial_drivers[] = { |
@@ -165,29 +151,8 @@ struct whiteheat_command_private { | |||
165 | __u8 result_buffer[64]; | 151 | __u8 result_buffer[64]; |
166 | }; | 152 | }; |
167 | 153 | ||
168 | |||
169 | #define THROTTLED 0x01 | ||
170 | #define ACTUALLY_THROTTLED 0x02 | ||
171 | |||
172 | static int urb_pool_size = 8; | ||
173 | |||
174 | struct whiteheat_urb_wrap { | ||
175 | struct list_head list; | ||
176 | struct urb *urb; | ||
177 | }; | ||
178 | |||
179 | struct whiteheat_private { | 154 | struct whiteheat_private { |
180 | spinlock_t lock; | ||
181 | __u8 flags; | ||
182 | __u8 mcr; /* FIXME: no locking on mcr */ | 155 | __u8 mcr; /* FIXME: no locking on mcr */ |
183 | struct list_head rx_urbs_free; | ||
184 | struct list_head rx_urbs_submitted; | ||
185 | struct list_head rx_urb_q; | ||
186 | struct work_struct rx_work; | ||
187 | struct usb_serial_port *port; | ||
188 | struct list_head tx_urbs_free; | ||
189 | struct list_head tx_urbs_submitted; | ||
190 | struct mutex deathwarrant; | ||
191 | }; | 156 | }; |
192 | 157 | ||
193 | 158 | ||
@@ -197,12 +162,6 @@ static void stop_command_port(struct usb_serial *serial); | |||
197 | static void command_port_write_callback(struct urb *urb); | 162 | static void command_port_write_callback(struct urb *urb); |
198 | static void command_port_read_callback(struct urb *urb); | 163 | static void command_port_read_callback(struct urb *urb); |
199 | 164 | ||
200 | static int start_port_read(struct usb_serial_port *port); | ||
201 | static struct whiteheat_urb_wrap *urb_to_wrap(struct urb *urb, | ||
202 | struct list_head *head); | ||
203 | static struct list_head *list_first(struct list_head *head); | ||
204 | static void rx_data_softint(struct work_struct *work); | ||
205 | |||
206 | static int firm_send_command(struct usb_serial_port *port, __u8 command, | 165 | static int firm_send_command(struct usb_serial_port *port, __u8 command, |
207 | __u8 *data, __u8 datasize); | 166 | __u8 *data, __u8 datasize); |
208 | static int firm_open(struct usb_serial_port *port); | 167 | static int firm_open(struct usb_serial_port *port); |
@@ -348,11 +307,6 @@ static int whiteheat_attach(struct usb_serial *serial) | |||
348 | __u8 *command; | 307 | __u8 *command; |
349 | __u8 *result; | 308 | __u8 *result; |
350 | int i; | 309 | int i; |
351 | int j; | ||
352 | struct urb *urb; | ||
353 | int buf_size; | ||
354 | struct whiteheat_urb_wrap *wrap; | ||
355 | struct list_head *tmp; | ||
356 | 310 | ||
357 | command_port = serial->port[COMMAND_PORT]; | 311 | command_port = serial->port[COMMAND_PORT]; |
358 | 312 | ||
@@ -422,72 +376,7 @@ static int whiteheat_attach(struct usb_serial *serial) | |||
422 | goto no_private; | 376 | goto no_private; |
423 | } | 377 | } |
424 | 378 | ||
425 | spin_lock_init(&info->lock); | ||
426 | mutex_init(&info->deathwarrant); | ||
427 | info->flags = 0; | ||
428 | info->mcr = 0; | 379 | info->mcr = 0; |
429 | INIT_WORK(&info->rx_work, rx_data_softint); | ||
430 | info->port = port; | ||
431 | |||
432 | INIT_LIST_HEAD(&info->rx_urbs_free); | ||
433 | INIT_LIST_HEAD(&info->rx_urbs_submitted); | ||
434 | INIT_LIST_HEAD(&info->rx_urb_q); | ||
435 | INIT_LIST_HEAD(&info->tx_urbs_free); | ||
436 | INIT_LIST_HEAD(&info->tx_urbs_submitted); | ||
437 | |||
438 | for (j = 0; j < urb_pool_size; j++) { | ||
439 | urb = usb_alloc_urb(0, GFP_KERNEL); | ||
440 | if (!urb) { | ||
441 | dev_err(&port->dev, "No free urbs available\n"); | ||
442 | goto no_rx_urb; | ||
443 | } | ||
444 | buf_size = port->read_urb->transfer_buffer_length; | ||
445 | urb->transfer_buffer = kmalloc(buf_size, GFP_KERNEL); | ||
446 | if (!urb->transfer_buffer) { | ||
447 | dev_err(&port->dev, | ||
448 | "Couldn't allocate urb buffer\n"); | ||
449 | goto no_rx_buf; | ||
450 | } | ||
451 | wrap = kmalloc(sizeof(*wrap), GFP_KERNEL); | ||
452 | if (!wrap) { | ||
453 | dev_err(&port->dev, | ||
454 | "Couldn't allocate urb wrapper\n"); | ||
455 | goto no_rx_wrap; | ||
456 | } | ||
457 | usb_fill_bulk_urb(urb, serial->dev, | ||
458 | usb_rcvbulkpipe(serial->dev, | ||
459 | port->bulk_in_endpointAddress), | ||
460 | urb->transfer_buffer, buf_size, | ||
461 | whiteheat_read_callback, port); | ||
462 | wrap->urb = urb; | ||
463 | list_add(&wrap->list, &info->rx_urbs_free); | ||
464 | |||
465 | urb = usb_alloc_urb(0, GFP_KERNEL); | ||
466 | if (!urb) { | ||
467 | dev_err(&port->dev, "No free urbs available\n"); | ||
468 | goto no_tx_urb; | ||
469 | } | ||
470 | buf_size = port->write_urb->transfer_buffer_length; | ||
471 | urb->transfer_buffer = kmalloc(buf_size, GFP_KERNEL); | ||
472 | if (!urb->transfer_buffer) { | ||
473 | dev_err(&port->dev, | ||
474 | "Couldn't allocate urb buffer\n"); | ||
475 | goto no_tx_buf; | ||
476 | } | ||
477 | wrap = kmalloc(sizeof(*wrap), GFP_KERNEL); | ||
478 | if (!wrap) { | ||
479 | dev_err(&port->dev, | ||
480 | "Couldn't allocate urb wrapper\n"); | ||
481 | goto no_tx_wrap; | ||
482 | } | ||
483 | usb_fill_bulk_urb(urb, serial->dev, | ||
484 | usb_sndbulkpipe(serial->dev, | ||
485 | port->bulk_out_endpointAddress), | ||
486 | urb->transfer_buffer, buf_size, | ||
487 | whiteheat_write_callback, port); | ||
488 | wrap->urb = urb; | ||
489 | list_add(&wrap->list, &info->tx_urbs_free); | ||
490 | } | ||
491 | 380 | ||
492 | usb_set_serial_port_data(port, info); | 381 | usb_set_serial_port_data(port, info); |
493 | } | 382 | } |
@@ -530,29 +419,6 @@ no_command_private: | |||
530 | for (i = serial->num_ports - 1; i >= 0; i--) { | 419 | for (i = serial->num_ports - 1; i >= 0; i--) { |
531 | port = serial->port[i]; | 420 | port = serial->port[i]; |
532 | info = usb_get_serial_port_data(port); | 421 | info = usb_get_serial_port_data(port); |
533 | for (j = urb_pool_size - 1; j >= 0; j--) { | ||
534 | tmp = list_first(&info->tx_urbs_free); | ||
535 | list_del(tmp); | ||
536 | wrap = list_entry(tmp, struct whiteheat_urb_wrap, list); | ||
537 | urb = wrap->urb; | ||
538 | kfree(wrap); | ||
539 | no_tx_wrap: | ||
540 | kfree(urb->transfer_buffer); | ||
541 | no_tx_buf: | ||
542 | usb_free_urb(urb); | ||
543 | no_tx_urb: | ||
544 | tmp = list_first(&info->rx_urbs_free); | ||
545 | list_del(tmp); | ||
546 | wrap = list_entry(tmp, struct whiteheat_urb_wrap, list); | ||
547 | urb = wrap->urb; | ||
548 | kfree(wrap); | ||
549 | no_rx_wrap: | ||
550 | kfree(urb->transfer_buffer); | ||
551 | no_rx_buf: | ||
552 | usb_free_urb(urb); | ||
553 | no_rx_urb: | ||
554 | ; | ||
555 | } | ||
556 | kfree(info); | 422 | kfree(info); |
557 | no_private: | 423 | no_private: |
558 | ; | 424 | ; |
@@ -568,12 +434,7 @@ no_command_buffer: | |||
568 | static void whiteheat_release(struct usb_serial *serial) | 434 | static void whiteheat_release(struct usb_serial *serial) |
569 | { | 435 | { |
570 | struct usb_serial_port *command_port; | 436 | struct usb_serial_port *command_port; |
571 | struct usb_serial_port *port; | ||
572 | struct whiteheat_private *info; | 437 | struct whiteheat_private *info; |
573 | struct whiteheat_urb_wrap *wrap; | ||
574 | struct urb *urb; | ||
575 | struct list_head *tmp; | ||
576 | struct list_head *tmp2; | ||
577 | int i; | 438 | int i; |
578 | 439 | ||
579 | dbg("%s", __func__); | 440 | dbg("%s", __func__); |
@@ -583,31 +444,14 @@ static void whiteheat_release(struct usb_serial *serial) | |||
583 | kfree(usb_get_serial_port_data(command_port)); | 444 | kfree(usb_get_serial_port_data(command_port)); |
584 | 445 | ||
585 | for (i = 0; i < serial->num_ports; i++) { | 446 | for (i = 0; i < serial->num_ports; i++) { |
586 | port = serial->port[i]; | 447 | info = usb_get_serial_port_data(serial->port[i]); |
587 | info = usb_get_serial_port_data(port); | ||
588 | list_for_each_safe(tmp, tmp2, &info->rx_urbs_free) { | ||
589 | list_del(tmp); | ||
590 | wrap = list_entry(tmp, struct whiteheat_urb_wrap, list); | ||
591 | urb = wrap->urb; | ||
592 | kfree(wrap); | ||
593 | kfree(urb->transfer_buffer); | ||
594 | usb_free_urb(urb); | ||
595 | } | ||
596 | list_for_each_safe(tmp, tmp2, &info->tx_urbs_free) { | ||
597 | list_del(tmp); | ||
598 | wrap = list_entry(tmp, struct whiteheat_urb_wrap, list); | ||
599 | urb = wrap->urb; | ||
600 | kfree(wrap); | ||
601 | kfree(urb->transfer_buffer); | ||
602 | usb_free_urb(urb); | ||
603 | } | ||
604 | kfree(info); | 448 | kfree(info); |
605 | } | 449 | } |
606 | } | 450 | } |
607 | 451 | ||
608 | static int whiteheat_open(struct tty_struct *tty, struct usb_serial_port *port) | 452 | static int whiteheat_open(struct tty_struct *tty, struct usb_serial_port *port) |
609 | { | 453 | { |
610 | int retval = 0; | 454 | int retval; |
611 | 455 | ||
612 | dbg("%s - port %d", __func__, port->number); | 456 | dbg("%s - port %d", __func__, port->number); |
613 | 457 | ||
@@ -615,9 +459,6 @@ static int whiteheat_open(struct tty_struct *tty, struct usb_serial_port *port) | |||
615 | if (retval) | 459 | if (retval) |
616 | goto exit; | 460 | goto exit; |
617 | 461 | ||
618 | if (tty) | ||
619 | tty->low_latency = 1; | ||
620 | |||
621 | /* send an open port command */ | 462 | /* send an open port command */ |
622 | retval = firm_open(port); | 463 | retval = firm_open(port); |
623 | if (retval) { | 464 | if (retval) { |
@@ -639,17 +480,12 @@ static int whiteheat_open(struct tty_struct *tty, struct usb_serial_port *port) | |||
639 | usb_clear_halt(port->serial->dev, port->read_urb->pipe); | 480 | usb_clear_halt(port->serial->dev, port->read_urb->pipe); |
640 | usb_clear_halt(port->serial->dev, port->write_urb->pipe); | 481 | usb_clear_halt(port->serial->dev, port->write_urb->pipe); |
641 | 482 | ||
642 | /* Start reading from the device */ | 483 | retval = usb_serial_generic_open(tty, port); |
643 | retval = start_port_read(port); | ||
644 | if (retval) { | 484 | if (retval) { |
645 | dev_err(&port->dev, | ||
646 | "%s - failed submitting read urb, error %d\n", | ||
647 | __func__, retval); | ||
648 | firm_close(port); | 485 | firm_close(port); |
649 | stop_command_port(port->serial); | 486 | stop_command_port(port->serial); |
650 | goto exit; | 487 | goto exit; |
651 | } | 488 | } |
652 | |||
653 | exit: | 489 | exit: |
654 | dbg("%s - exit, retval = %d", __func__, retval); | 490 | dbg("%s - exit, retval = %d", __func__, retval); |
655 | return retval; | 491 | return retval; |
@@ -658,125 +494,14 @@ exit: | |||
658 | 494 | ||
659 | static void whiteheat_close(struct usb_serial_port *port) | 495 | static void whiteheat_close(struct usb_serial_port *port) |
660 | { | 496 | { |
661 | struct whiteheat_private *info = usb_get_serial_port_data(port); | ||
662 | struct whiteheat_urb_wrap *wrap; | ||
663 | struct urb *urb; | ||
664 | struct list_head *tmp; | ||
665 | struct list_head *tmp2; | ||
666 | |||
667 | dbg("%s - port %d", __func__, port->number); | 497 | dbg("%s - port %d", __func__, port->number); |
668 | 498 | ||
669 | firm_report_tx_done(port); | 499 | firm_report_tx_done(port); |
670 | firm_close(port); | 500 | firm_close(port); |
671 | 501 | ||
672 | /* shutdown our bulk reads and writes */ | 502 | usb_serial_generic_close(port); |
673 | mutex_lock(&info->deathwarrant); | ||
674 | spin_lock_irq(&info->lock); | ||
675 | list_for_each_safe(tmp, tmp2, &info->rx_urbs_submitted) { | ||
676 | wrap = list_entry(tmp, struct whiteheat_urb_wrap, list); | ||
677 | urb = wrap->urb; | ||
678 | list_del(tmp); | ||
679 | spin_unlock_irq(&info->lock); | ||
680 | usb_kill_urb(urb); | ||
681 | spin_lock_irq(&info->lock); | ||
682 | list_add(tmp, &info->rx_urbs_free); | ||
683 | } | ||
684 | list_for_each_safe(tmp, tmp2, &info->rx_urb_q) | ||
685 | list_move(tmp, &info->rx_urbs_free); | ||
686 | list_for_each_safe(tmp, tmp2, &info->tx_urbs_submitted) { | ||
687 | wrap = list_entry(tmp, struct whiteheat_urb_wrap, list); | ||
688 | urb = wrap->urb; | ||
689 | list_del(tmp); | ||
690 | spin_unlock_irq(&info->lock); | ||
691 | usb_kill_urb(urb); | ||
692 | spin_lock_irq(&info->lock); | ||
693 | list_add(tmp, &info->tx_urbs_free); | ||
694 | } | ||
695 | spin_unlock_irq(&info->lock); | ||
696 | mutex_unlock(&info->deathwarrant); | ||
697 | stop_command_port(port->serial); | ||
698 | } | ||
699 | |||
700 | |||
701 | static int whiteheat_write(struct tty_struct *tty, | ||
702 | struct usb_serial_port *port, const unsigned char *buf, int count) | ||
703 | { | ||
704 | struct whiteheat_private *info = usb_get_serial_port_data(port); | ||
705 | struct whiteheat_urb_wrap *wrap; | ||
706 | struct urb *urb; | ||
707 | int result; | ||
708 | int bytes; | ||
709 | int sent = 0; | ||
710 | unsigned long flags; | ||
711 | struct list_head *tmp; | ||
712 | |||
713 | dbg("%s - port %d", __func__, port->number); | ||
714 | |||
715 | if (count == 0) { | ||
716 | dbg("%s - write request of 0 bytes", __func__); | ||
717 | return (0); | ||
718 | } | ||
719 | |||
720 | while (count) { | ||
721 | spin_lock_irqsave(&info->lock, flags); | ||
722 | if (list_empty(&info->tx_urbs_free)) { | ||
723 | spin_unlock_irqrestore(&info->lock, flags); | ||
724 | break; | ||
725 | } | ||
726 | tmp = list_first(&info->tx_urbs_free); | ||
727 | list_del(tmp); | ||
728 | spin_unlock_irqrestore(&info->lock, flags); | ||
729 | |||
730 | wrap = list_entry(tmp, struct whiteheat_urb_wrap, list); | ||
731 | urb = wrap->urb; | ||
732 | bytes = (count > port->bulk_out_size) ? | ||
733 | port->bulk_out_size : count; | ||
734 | memcpy(urb->transfer_buffer, buf + sent, bytes); | ||
735 | |||
736 | usb_serial_debug_data(debug, &port->dev, | ||
737 | __func__, bytes, urb->transfer_buffer); | ||
738 | |||
739 | urb->transfer_buffer_length = bytes; | ||
740 | result = usb_submit_urb(urb, GFP_ATOMIC); | ||
741 | if (result) { | ||
742 | dev_err_console(port, | ||
743 | "%s - failed submitting write urb, error %d\n", | ||
744 | __func__, result); | ||
745 | sent = result; | ||
746 | spin_lock_irqsave(&info->lock, flags); | ||
747 | list_add(tmp, &info->tx_urbs_free); | ||
748 | spin_unlock_irqrestore(&info->lock, flags); | ||
749 | break; | ||
750 | } else { | ||
751 | sent += bytes; | ||
752 | count -= bytes; | ||
753 | spin_lock_irqsave(&info->lock, flags); | ||
754 | list_add(tmp, &info->tx_urbs_submitted); | ||
755 | spin_unlock_irqrestore(&info->lock, flags); | ||
756 | } | ||
757 | } | ||
758 | 503 | ||
759 | return sent; | 504 | stop_command_port(port->serial); |
760 | } | ||
761 | |||
762 | static int whiteheat_write_room(struct tty_struct *tty) | ||
763 | { | ||
764 | struct usb_serial_port *port = tty->driver_data; | ||
765 | struct whiteheat_private *info = usb_get_serial_port_data(port); | ||
766 | struct list_head *tmp; | ||
767 | int room = 0; | ||
768 | unsigned long flags; | ||
769 | |||
770 | dbg("%s - port %d", __func__, port->number); | ||
771 | |||
772 | spin_lock_irqsave(&info->lock, flags); | ||
773 | list_for_each(tmp, &info->tx_urbs_free) | ||
774 | room++; | ||
775 | spin_unlock_irqrestore(&info->lock, flags); | ||
776 | room *= port->bulk_out_size; | ||
777 | |||
778 | dbg("%s - returns %d", __func__, room); | ||
779 | return (room); | ||
780 | } | 505 | } |
781 | 506 | ||
782 | static int whiteheat_tiocmget(struct tty_struct *tty) | 507 | static int whiteheat_tiocmget(struct tty_struct *tty) |
@@ -836,7 +561,7 @@ static int whiteheat_ioctl(struct tty_struct *tty, | |||
836 | serstruct.line = port->serial->minor; | 561 | serstruct.line = port->serial->minor; |
837 | serstruct.port = port->number; | 562 | serstruct.port = port->number; |
838 | serstruct.flags = ASYNC_SKIP_TEST | ASYNC_AUTO_IRQ; | 563 | serstruct.flags = ASYNC_SKIP_TEST | ASYNC_AUTO_IRQ; |
839 | serstruct.xmit_fifo_size = port->bulk_out_size; | 564 | serstruct.xmit_fifo_size = kfifo_size(&port->write_fifo); |
840 | serstruct.custom_divisor = 0; | 565 | serstruct.custom_divisor = 0; |
841 | serstruct.baud_base = 460800; | 566 | serstruct.baud_base = 460800; |
842 | serstruct.close_delay = CLOSING_DELAY; | 567 | serstruct.close_delay = CLOSING_DELAY; |
@@ -866,60 +591,6 @@ static void whiteheat_break_ctl(struct tty_struct *tty, int break_state) | |||
866 | } | 591 | } |
867 | 592 | ||
868 | 593 | ||
869 | static int whiteheat_chars_in_buffer(struct tty_struct *tty) | ||
870 | { | ||
871 | struct usb_serial_port *port = tty->driver_data; | ||
872 | struct whiteheat_private *info = usb_get_serial_port_data(port); | ||
873 | struct list_head *tmp; | ||
874 | struct whiteheat_urb_wrap *wrap; | ||
875 | int chars = 0; | ||
876 | unsigned long flags; | ||
877 | |||
878 | dbg("%s - port %d", __func__, port->number); | ||
879 | |||
880 | spin_lock_irqsave(&info->lock, flags); | ||
881 | list_for_each(tmp, &info->tx_urbs_submitted) { | ||
882 | wrap = list_entry(tmp, struct whiteheat_urb_wrap, list); | ||
883 | chars += wrap->urb->transfer_buffer_length; | ||
884 | } | ||
885 | spin_unlock_irqrestore(&info->lock, flags); | ||
886 | |||
887 | dbg("%s - returns %d", __func__, chars); | ||
888 | return chars; | ||
889 | } | ||
890 | |||
891 | |||
892 | static void whiteheat_throttle(struct tty_struct *tty) | ||
893 | { | ||
894 | struct usb_serial_port *port = tty->driver_data; | ||
895 | struct whiteheat_private *info = usb_get_serial_port_data(port); | ||
896 | |||
897 | dbg("%s - port %d", __func__, port->number); | ||
898 | |||
899 | spin_lock_irq(&info->lock); | ||
900 | info->flags |= THROTTLED; | ||
901 | spin_unlock_irq(&info->lock); | ||
902 | } | ||
903 | |||
904 | |||
905 | static void whiteheat_unthrottle(struct tty_struct *tty) | ||
906 | { | ||
907 | struct usb_serial_port *port = tty->driver_data; | ||
908 | struct whiteheat_private *info = usb_get_serial_port_data(port); | ||
909 | int actually_throttled; | ||
910 | |||
911 | dbg("%s - port %d", __func__, port->number); | ||
912 | |||
913 | spin_lock_irq(&info->lock); | ||
914 | actually_throttled = info->flags & ACTUALLY_THROTTLED; | ||
915 | info->flags &= ~(THROTTLED | ACTUALLY_THROTTLED); | ||
916 | spin_unlock_irq(&info->lock); | ||
917 | |||
918 | if (actually_throttled) | ||
919 | rx_data_softint(&info->rx_work); | ||
920 | } | ||
921 | |||
922 | |||
923 | /***************************************************************************** | 594 | /***************************************************************************** |
924 | * Connect Tech's White Heat callback routines | 595 | * Connect Tech's White Heat callback routines |
925 | *****************************************************************************/ | 596 | *****************************************************************************/ |
@@ -988,80 +659,6 @@ static void command_port_read_callback(struct urb *urb) | |||
988 | } | 659 | } |
989 | 660 | ||
990 | 661 | ||
991 | static void whiteheat_read_callback(struct urb *urb) | ||
992 | { | ||
993 | struct usb_serial_port *port = urb->context; | ||
994 | struct whiteheat_urb_wrap *wrap; | ||
995 | unsigned char *data = urb->transfer_buffer; | ||
996 | struct whiteheat_private *info = usb_get_serial_port_data(port); | ||
997 | int status = urb->status; | ||
998 | |||
999 | dbg("%s - port %d", __func__, port->number); | ||
1000 | |||
1001 | spin_lock(&info->lock); | ||
1002 | wrap = urb_to_wrap(urb, &info->rx_urbs_submitted); | ||
1003 | if (!wrap) { | ||
1004 | spin_unlock(&info->lock); | ||
1005 | dev_err(&port->dev, "%s - Not my urb!\n", __func__); | ||
1006 | return; | ||
1007 | } | ||
1008 | list_del(&wrap->list); | ||
1009 | spin_unlock(&info->lock); | ||
1010 | |||
1011 | if (status) { | ||
1012 | dbg("%s - nonzero read bulk status received: %d", | ||
1013 | __func__, status); | ||
1014 | spin_lock(&info->lock); | ||
1015 | list_add(&wrap->list, &info->rx_urbs_free); | ||
1016 | spin_unlock(&info->lock); | ||
1017 | return; | ||
1018 | } | ||
1019 | |||
1020 | usb_serial_debug_data(debug, &port->dev, | ||
1021 | __func__, urb->actual_length, data); | ||
1022 | |||
1023 | spin_lock(&info->lock); | ||
1024 | list_add_tail(&wrap->list, &info->rx_urb_q); | ||
1025 | if (info->flags & THROTTLED) { | ||
1026 | info->flags |= ACTUALLY_THROTTLED; | ||
1027 | spin_unlock(&info->lock); | ||
1028 | return; | ||
1029 | } | ||
1030 | spin_unlock(&info->lock); | ||
1031 | |||
1032 | schedule_work(&info->rx_work); | ||
1033 | } | ||
1034 | |||
1035 | |||
1036 | static void whiteheat_write_callback(struct urb *urb) | ||
1037 | { | ||
1038 | struct usb_serial_port *port = urb->context; | ||
1039 | struct whiteheat_private *info = usb_get_serial_port_data(port); | ||
1040 | struct whiteheat_urb_wrap *wrap; | ||
1041 | int status = urb->status; | ||
1042 | |||
1043 | dbg("%s - port %d", __func__, port->number); | ||
1044 | |||
1045 | spin_lock(&info->lock); | ||
1046 | wrap = urb_to_wrap(urb, &info->tx_urbs_submitted); | ||
1047 | if (!wrap) { | ||
1048 | spin_unlock(&info->lock); | ||
1049 | dev_err(&port->dev, "%s - Not my urb!\n", __func__); | ||
1050 | return; | ||
1051 | } | ||
1052 | list_move(&wrap->list, &info->tx_urbs_free); | ||
1053 | spin_unlock(&info->lock); | ||
1054 | |||
1055 | if (status) { | ||
1056 | dbg("%s - nonzero write bulk status received: %d", | ||
1057 | __func__, status); | ||
1058 | return; | ||
1059 | } | ||
1060 | |||
1061 | usb_serial_port_softint(port); | ||
1062 | } | ||
1063 | |||
1064 | |||
1065 | /***************************************************************************** | 662 | /***************************************************************************** |
1066 | * Connect Tech's White Heat firmware interface | 663 | * Connect Tech's White Heat firmware interface |
1067 | *****************************************************************************/ | 664 | *****************************************************************************/ |
@@ -1336,123 +933,6 @@ static void stop_command_port(struct usb_serial *serial) | |||
1336 | mutex_unlock(&command_info->mutex); | 933 | mutex_unlock(&command_info->mutex); |
1337 | } | 934 | } |
1338 | 935 | ||
1339 | |||
1340 | static int start_port_read(struct usb_serial_port *port) | ||
1341 | { | ||
1342 | struct whiteheat_private *info = usb_get_serial_port_data(port); | ||
1343 | struct whiteheat_urb_wrap *wrap; | ||
1344 | struct urb *urb; | ||
1345 | int retval = 0; | ||
1346 | unsigned long flags; | ||
1347 | struct list_head *tmp; | ||
1348 | struct list_head *tmp2; | ||
1349 | |||
1350 | spin_lock_irqsave(&info->lock, flags); | ||
1351 | |||
1352 | list_for_each_safe(tmp, tmp2, &info->rx_urbs_free) { | ||
1353 | list_del(tmp); | ||
1354 | wrap = list_entry(tmp, struct whiteheat_urb_wrap, list); | ||
1355 | urb = wrap->urb; | ||
1356 | spin_unlock_irqrestore(&info->lock, flags); | ||
1357 | retval = usb_submit_urb(urb, GFP_KERNEL); | ||
1358 | if (retval) { | ||
1359 | spin_lock_irqsave(&info->lock, flags); | ||
1360 | list_add(tmp, &info->rx_urbs_free); | ||
1361 | list_for_each_safe(tmp, tmp2, &info->rx_urbs_submitted) { | ||
1362 | wrap = list_entry(tmp, struct whiteheat_urb_wrap, list); | ||
1363 | urb = wrap->urb; | ||
1364 | list_del(tmp); | ||
1365 | spin_unlock_irqrestore(&info->lock, flags); | ||
1366 | usb_kill_urb(urb); | ||
1367 | spin_lock_irqsave(&info->lock, flags); | ||
1368 | list_add(tmp, &info->rx_urbs_free); | ||
1369 | } | ||
1370 | break; | ||
1371 | } | ||
1372 | spin_lock_irqsave(&info->lock, flags); | ||
1373 | list_add(tmp, &info->rx_urbs_submitted); | ||
1374 | } | ||
1375 | |||
1376 | spin_unlock_irqrestore(&info->lock, flags); | ||
1377 | |||
1378 | return retval; | ||
1379 | } | ||
1380 | |||
1381 | |||
1382 | static struct whiteheat_urb_wrap *urb_to_wrap(struct urb *urb, | ||
1383 | struct list_head *head) | ||
1384 | { | ||
1385 | struct whiteheat_urb_wrap *wrap; | ||
1386 | struct list_head *tmp; | ||
1387 | |||
1388 | list_for_each(tmp, head) { | ||
1389 | wrap = list_entry(tmp, struct whiteheat_urb_wrap, list); | ||
1390 | if (wrap->urb == urb) | ||
1391 | return wrap; | ||
1392 | } | ||
1393 | |||
1394 | return NULL; | ||
1395 | } | ||
1396 | |||
1397 | |||
1398 | static struct list_head *list_first(struct list_head *head) | ||
1399 | { | ||
1400 | return head->next; | ||
1401 | } | ||
1402 | |||
1403 | |||
1404 | static void rx_data_softint(struct work_struct *work) | ||
1405 | { | ||
1406 | struct whiteheat_private *info = | ||
1407 | container_of(work, struct whiteheat_private, rx_work); | ||
1408 | struct usb_serial_port *port = info->port; | ||
1409 | struct tty_struct *tty = tty_port_tty_get(&port->port); | ||
1410 | struct whiteheat_urb_wrap *wrap; | ||
1411 | struct urb *urb; | ||
1412 | unsigned long flags; | ||
1413 | struct list_head *tmp; | ||
1414 | struct list_head *tmp2; | ||
1415 | int result; | ||
1416 | int sent = 0; | ||
1417 | |||
1418 | spin_lock_irqsave(&info->lock, flags); | ||
1419 | if (info->flags & THROTTLED) { | ||
1420 | spin_unlock_irqrestore(&info->lock, flags); | ||
1421 | goto out; | ||
1422 | } | ||
1423 | |||
1424 | list_for_each_safe(tmp, tmp2, &info->rx_urb_q) { | ||
1425 | list_del(tmp); | ||
1426 | spin_unlock_irqrestore(&info->lock, flags); | ||
1427 | |||
1428 | wrap = list_entry(tmp, struct whiteheat_urb_wrap, list); | ||
1429 | urb = wrap->urb; | ||
1430 | |||
1431 | if (tty && urb->actual_length) | ||
1432 | sent += tty_insert_flip_string(tty, | ||
1433 | urb->transfer_buffer, urb->actual_length); | ||
1434 | |||
1435 | result = usb_submit_urb(urb, GFP_ATOMIC); | ||
1436 | if (result) { | ||
1437 | dev_err(&port->dev, | ||
1438 | "%s - failed resubmitting read urb, error %d\n", | ||
1439 | __func__, result); | ||
1440 | spin_lock_irqsave(&info->lock, flags); | ||
1441 | list_add(tmp, &info->rx_urbs_free); | ||
1442 | continue; | ||
1443 | } | ||
1444 | |||
1445 | spin_lock_irqsave(&info->lock, flags); | ||
1446 | list_add(tmp, &info->rx_urbs_submitted); | ||
1447 | } | ||
1448 | spin_unlock_irqrestore(&info->lock, flags); | ||
1449 | |||
1450 | if (sent) | ||
1451 | tty_flip_buffer_push(tty); | ||
1452 | out: | ||
1453 | tty_kref_put(tty); | ||
1454 | } | ||
1455 | |||
1456 | module_usb_serial_driver(whiteheat_driver, serial_drivers); | 936 | module_usb_serial_driver(whiteheat_driver, serial_drivers); |
1457 | 937 | ||
1458 | MODULE_AUTHOR(DRIVER_AUTHOR); | 938 | MODULE_AUTHOR(DRIVER_AUTHOR); |
@@ -1462,8 +942,5 @@ MODULE_LICENSE("GPL"); | |||
1462 | MODULE_FIRMWARE("whiteheat.fw"); | 942 | MODULE_FIRMWARE("whiteheat.fw"); |
1463 | MODULE_FIRMWARE("whiteheat_loader.fw"); | 943 | MODULE_FIRMWARE("whiteheat_loader.fw"); |
1464 | 944 | ||
1465 | module_param(urb_pool_size, int, 0); | ||
1466 | MODULE_PARM_DESC(urb_pool_size, "Number of urbs to use for buffering"); | ||
1467 | |||
1468 | module_param(debug, bool, S_IRUGO | S_IWUSR); | 945 | module_param(debug, bool, S_IRUGO | S_IWUSR); |
1469 | MODULE_PARM_DESC(debug, "Debug enabled or not"); | 946 | MODULE_PARM_DESC(debug, "Debug enabled or not"); |