diff options
Diffstat (limited to 'drivers/tty/serial/serial_core.c')
-rw-r--r-- | drivers/tty/serial/serial_core.c | 223 |
1 files changed, 135 insertions, 88 deletions
diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c index a21dc8e3b7c0..046279ce3e8d 100644 --- a/drivers/tty/serial/serial_core.c +++ b/drivers/tty/serial/serial_core.c | |||
@@ -159,7 +159,7 @@ static int uart_port_startup(struct tty_struct *tty, struct uart_state *state, | |||
159 | retval = uport->ops->startup(uport); | 159 | retval = uport->ops->startup(uport); |
160 | if (retval == 0) { | 160 | if (retval == 0) { |
161 | if (uart_console(uport) && uport->cons->cflag) { | 161 | if (uart_console(uport) && uport->cons->cflag) { |
162 | tty->termios->c_cflag = uport->cons->cflag; | 162 | tty->termios.c_cflag = uport->cons->cflag; |
163 | uport->cons->cflag = 0; | 163 | uport->cons->cflag = 0; |
164 | } | 164 | } |
165 | /* | 165 | /* |
@@ -172,11 +172,11 @@ static int uart_port_startup(struct tty_struct *tty, struct uart_state *state, | |||
172 | * Setup the RTS and DTR signals once the | 172 | * Setup the RTS and DTR signals once the |
173 | * port is open and ready to respond. | 173 | * port is open and ready to respond. |
174 | */ | 174 | */ |
175 | if (tty->termios->c_cflag & CBAUD) | 175 | if (tty->termios.c_cflag & CBAUD) |
176 | uart_set_mctrl(uport, TIOCM_RTS | TIOCM_DTR); | 176 | uart_set_mctrl(uport, TIOCM_RTS | TIOCM_DTR); |
177 | } | 177 | } |
178 | 178 | ||
179 | if (port->flags & ASYNC_CTS_FLOW) { | 179 | if (tty_port_cts_enabled(port)) { |
180 | spin_lock_irq(&uport->lock); | 180 | spin_lock_irq(&uport->lock); |
181 | if (!(uport->ops->get_mctrl(uport) & TIOCM_CTS)) | 181 | if (!(uport->ops->get_mctrl(uport) & TIOCM_CTS)) |
182 | tty->hw_stopped = 1; | 182 | tty->hw_stopped = 1; |
@@ -240,7 +240,7 @@ static void uart_shutdown(struct tty_struct *tty, struct uart_state *state) | |||
240 | /* | 240 | /* |
241 | * Turn off DTR and RTS early. | 241 | * Turn off DTR and RTS early. |
242 | */ | 242 | */ |
243 | if (!tty || (tty->termios->c_cflag & HUPCL)) | 243 | if (!tty || (tty->termios.c_cflag & HUPCL)) |
244 | uart_clear_mctrl(uport, TIOCM_DTR | TIOCM_RTS); | 244 | uart_clear_mctrl(uport, TIOCM_DTR | TIOCM_RTS); |
245 | 245 | ||
246 | uart_port_shutdown(port); | 246 | uart_port_shutdown(port); |
@@ -440,10 +440,10 @@ static void uart_change_speed(struct tty_struct *tty, struct uart_state *state, | |||
440 | * If we have no tty, termios, or the port does not exist, | 440 | * If we have no tty, termios, or the port does not exist, |
441 | * then we can't set the parameters for this port. | 441 | * then we can't set the parameters for this port. |
442 | */ | 442 | */ |
443 | if (!tty || !tty->termios || uport->type == PORT_UNKNOWN) | 443 | if (!tty || uport->type == PORT_UNKNOWN) |
444 | return; | 444 | return; |
445 | 445 | ||
446 | termios = tty->termios; | 446 | termios = &tty->termios; |
447 | 447 | ||
448 | /* | 448 | /* |
449 | * Set flags based on termios cflag | 449 | * Set flags based on termios cflag |
@@ -614,7 +614,7 @@ static void uart_throttle(struct tty_struct *tty) | |||
614 | if (I_IXOFF(tty)) | 614 | if (I_IXOFF(tty)) |
615 | uart_send_xchar(tty, STOP_CHAR(tty)); | 615 | uart_send_xchar(tty, STOP_CHAR(tty)); |
616 | 616 | ||
617 | if (tty->termios->c_cflag & CRTSCTS) | 617 | if (tty->termios.c_cflag & CRTSCTS) |
618 | uart_clear_mctrl(state->uart_port, TIOCM_RTS); | 618 | uart_clear_mctrl(state->uart_port, TIOCM_RTS); |
619 | } | 619 | } |
620 | 620 | ||
@@ -630,42 +630,48 @@ static void uart_unthrottle(struct tty_struct *tty) | |||
630 | uart_send_xchar(tty, START_CHAR(tty)); | 630 | uart_send_xchar(tty, START_CHAR(tty)); |
631 | } | 631 | } |
632 | 632 | ||
633 | if (tty->termios->c_cflag & CRTSCTS) | 633 | if (tty->termios.c_cflag & CRTSCTS) |
634 | uart_set_mctrl(port, TIOCM_RTS); | 634 | uart_set_mctrl(port, TIOCM_RTS); |
635 | } | 635 | } |
636 | 636 | ||
637 | static int uart_get_info(struct uart_state *state, | 637 | static void uart_get_info(struct tty_port *port, |
638 | struct serial_struct __user *retinfo) | 638 | struct uart_state *state, |
639 | struct serial_struct *retinfo) | ||
639 | { | 640 | { |
640 | struct uart_port *uport = state->uart_port; | 641 | struct uart_port *uport = state->uart_port; |
641 | struct tty_port *port = &state->port; | ||
642 | struct serial_struct tmp; | ||
643 | |||
644 | memset(&tmp, 0, sizeof(tmp)); | ||
645 | 642 | ||
646 | /* Ensure the state we copy is consistent and no hardware changes | 643 | memset(retinfo, 0, sizeof(*retinfo)); |
647 | occur as we go */ | ||
648 | mutex_lock(&port->mutex); | ||
649 | 644 | ||
650 | tmp.type = uport->type; | 645 | retinfo->type = uport->type; |
651 | tmp.line = uport->line; | 646 | retinfo->line = uport->line; |
652 | tmp.port = uport->iobase; | 647 | retinfo->port = uport->iobase; |
653 | if (HIGH_BITS_OFFSET) | 648 | if (HIGH_BITS_OFFSET) |
654 | tmp.port_high = (long) uport->iobase >> HIGH_BITS_OFFSET; | 649 | retinfo->port_high = (long) uport->iobase >> HIGH_BITS_OFFSET; |
655 | tmp.irq = uport->irq; | 650 | retinfo->irq = uport->irq; |
656 | tmp.flags = uport->flags; | 651 | retinfo->flags = uport->flags; |
657 | tmp.xmit_fifo_size = uport->fifosize; | 652 | retinfo->xmit_fifo_size = uport->fifosize; |
658 | tmp.baud_base = uport->uartclk / 16; | 653 | retinfo->baud_base = uport->uartclk / 16; |
659 | tmp.close_delay = jiffies_to_msecs(port->close_delay) / 10; | 654 | retinfo->close_delay = jiffies_to_msecs(port->close_delay) / 10; |
660 | tmp.closing_wait = port->closing_wait == ASYNC_CLOSING_WAIT_NONE ? | 655 | retinfo->closing_wait = port->closing_wait == ASYNC_CLOSING_WAIT_NONE ? |
661 | ASYNC_CLOSING_WAIT_NONE : | 656 | ASYNC_CLOSING_WAIT_NONE : |
662 | jiffies_to_msecs(port->closing_wait) / 10; | 657 | jiffies_to_msecs(port->closing_wait) / 10; |
663 | tmp.custom_divisor = uport->custom_divisor; | 658 | retinfo->custom_divisor = uport->custom_divisor; |
664 | tmp.hub6 = uport->hub6; | 659 | retinfo->hub6 = uport->hub6; |
665 | tmp.io_type = uport->iotype; | 660 | retinfo->io_type = uport->iotype; |
666 | tmp.iomem_reg_shift = uport->regshift; | 661 | retinfo->iomem_reg_shift = uport->regshift; |
667 | tmp.iomem_base = (void *)(unsigned long)uport->mapbase; | 662 | retinfo->iomem_base = (void *)(unsigned long)uport->mapbase; |
663 | } | ||
668 | 664 | ||
665 | static int uart_get_info_user(struct uart_state *state, | ||
666 | struct serial_struct __user *retinfo) | ||
667 | { | ||
668 | struct tty_port *port = &state->port; | ||
669 | struct serial_struct tmp; | ||
670 | |||
671 | /* Ensure the state we copy is consistent and no hardware changes | ||
672 | occur as we go */ | ||
673 | mutex_lock(&port->mutex); | ||
674 | uart_get_info(port, state, &tmp); | ||
669 | mutex_unlock(&port->mutex); | 675 | mutex_unlock(&port->mutex); |
670 | 676 | ||
671 | if (copy_to_user(retinfo, &tmp, sizeof(*retinfo))) | 677 | if (copy_to_user(retinfo, &tmp, sizeof(*retinfo))) |
@@ -673,42 +679,30 @@ static int uart_get_info(struct uart_state *state, | |||
673 | return 0; | 679 | return 0; |
674 | } | 680 | } |
675 | 681 | ||
676 | static int uart_set_info(struct tty_struct *tty, struct uart_state *state, | 682 | static int uart_set_info(struct tty_struct *tty, struct tty_port *port, |
677 | struct serial_struct __user *newinfo) | 683 | struct uart_state *state, |
684 | struct serial_struct *new_info) | ||
678 | { | 685 | { |
679 | struct serial_struct new_serial; | ||
680 | struct uart_port *uport = state->uart_port; | 686 | struct uart_port *uport = state->uart_port; |
681 | struct tty_port *port = &state->port; | ||
682 | unsigned long new_port; | 687 | unsigned long new_port; |
683 | unsigned int change_irq, change_port, closing_wait; | 688 | unsigned int change_irq, change_port, closing_wait; |
684 | unsigned int old_custom_divisor, close_delay; | 689 | unsigned int old_custom_divisor, close_delay; |
685 | upf_t old_flags, new_flags; | 690 | upf_t old_flags, new_flags; |
686 | int retval = 0; | 691 | int retval = 0; |
687 | 692 | ||
688 | if (copy_from_user(&new_serial, newinfo, sizeof(new_serial))) | 693 | new_port = new_info->port; |
689 | return -EFAULT; | ||
690 | |||
691 | new_port = new_serial.port; | ||
692 | if (HIGH_BITS_OFFSET) | 694 | if (HIGH_BITS_OFFSET) |
693 | new_port += (unsigned long) new_serial.port_high << HIGH_BITS_OFFSET; | 695 | new_port += (unsigned long) new_info->port_high << HIGH_BITS_OFFSET; |
694 | 696 | ||
695 | new_serial.irq = irq_canonicalize(new_serial.irq); | 697 | new_info->irq = irq_canonicalize(new_info->irq); |
696 | close_delay = msecs_to_jiffies(new_serial.close_delay * 10); | 698 | close_delay = msecs_to_jiffies(new_info->close_delay * 10); |
697 | closing_wait = new_serial.closing_wait == ASYNC_CLOSING_WAIT_NONE ? | 699 | closing_wait = new_info->closing_wait == ASYNC_CLOSING_WAIT_NONE ? |
698 | ASYNC_CLOSING_WAIT_NONE : | 700 | ASYNC_CLOSING_WAIT_NONE : |
699 | msecs_to_jiffies(new_serial.closing_wait * 10); | 701 | msecs_to_jiffies(new_info->closing_wait * 10); |
700 | 702 | ||
701 | /* | ||
702 | * This semaphore protects port->count. It is also | ||
703 | * very useful to prevent opens. Also, take the | ||
704 | * port configuration semaphore to make sure that a | ||
705 | * module insertion/removal doesn't change anything | ||
706 | * under us. | ||
707 | */ | ||
708 | mutex_lock(&port->mutex); | ||
709 | 703 | ||
710 | change_irq = !(uport->flags & UPF_FIXED_PORT) | 704 | change_irq = !(uport->flags & UPF_FIXED_PORT) |
711 | && new_serial.irq != uport->irq; | 705 | && new_info->irq != uport->irq; |
712 | 706 | ||
713 | /* | 707 | /* |
714 | * Since changing the 'type' of the port changes its resource | 708 | * Since changing the 'type' of the port changes its resource |
@@ -717,29 +711,29 @@ static int uart_set_info(struct tty_struct *tty, struct uart_state *state, | |||
717 | */ | 711 | */ |
718 | change_port = !(uport->flags & UPF_FIXED_PORT) | 712 | change_port = !(uport->flags & UPF_FIXED_PORT) |
719 | && (new_port != uport->iobase || | 713 | && (new_port != uport->iobase || |
720 | (unsigned long)new_serial.iomem_base != uport->mapbase || | 714 | (unsigned long)new_info->iomem_base != uport->mapbase || |
721 | new_serial.hub6 != uport->hub6 || | 715 | new_info->hub6 != uport->hub6 || |
722 | new_serial.io_type != uport->iotype || | 716 | new_info->io_type != uport->iotype || |
723 | new_serial.iomem_reg_shift != uport->regshift || | 717 | new_info->iomem_reg_shift != uport->regshift || |
724 | new_serial.type != uport->type); | 718 | new_info->type != uport->type); |
725 | 719 | ||
726 | old_flags = uport->flags; | 720 | old_flags = uport->flags; |
727 | new_flags = new_serial.flags; | 721 | new_flags = new_info->flags; |
728 | old_custom_divisor = uport->custom_divisor; | 722 | old_custom_divisor = uport->custom_divisor; |
729 | 723 | ||
730 | if (!capable(CAP_SYS_ADMIN)) { | 724 | if (!capable(CAP_SYS_ADMIN)) { |
731 | retval = -EPERM; | 725 | retval = -EPERM; |
732 | if (change_irq || change_port || | 726 | if (change_irq || change_port || |
733 | (new_serial.baud_base != uport->uartclk / 16) || | 727 | (new_info->baud_base != uport->uartclk / 16) || |
734 | (close_delay != port->close_delay) || | 728 | (close_delay != port->close_delay) || |
735 | (closing_wait != port->closing_wait) || | 729 | (closing_wait != port->closing_wait) || |
736 | (new_serial.xmit_fifo_size && | 730 | (new_info->xmit_fifo_size && |
737 | new_serial.xmit_fifo_size != uport->fifosize) || | 731 | new_info->xmit_fifo_size != uport->fifosize) || |
738 | (((new_flags ^ old_flags) & ~UPF_USR_MASK) != 0)) | 732 | (((new_flags ^ old_flags) & ~UPF_USR_MASK) != 0)) |
739 | goto exit; | 733 | goto exit; |
740 | uport->flags = ((uport->flags & ~UPF_USR_MASK) | | 734 | uport->flags = ((uport->flags & ~UPF_USR_MASK) | |
741 | (new_flags & UPF_USR_MASK)); | 735 | (new_flags & UPF_USR_MASK)); |
742 | uport->custom_divisor = new_serial.custom_divisor; | 736 | uport->custom_divisor = new_info->custom_divisor; |
743 | goto check_and_exit; | 737 | goto check_and_exit; |
744 | } | 738 | } |
745 | 739 | ||
@@ -747,10 +741,10 @@ static int uart_set_info(struct tty_struct *tty, struct uart_state *state, | |||
747 | * Ask the low level driver to verify the settings. | 741 | * Ask the low level driver to verify the settings. |
748 | */ | 742 | */ |
749 | if (uport->ops->verify_port) | 743 | if (uport->ops->verify_port) |
750 | retval = uport->ops->verify_port(uport, &new_serial); | 744 | retval = uport->ops->verify_port(uport, new_info); |
751 | 745 | ||
752 | if ((new_serial.irq >= nr_irqs) || (new_serial.irq < 0) || | 746 | if ((new_info->irq >= nr_irqs) || (new_info->irq < 0) || |
753 | (new_serial.baud_base < 9600)) | 747 | (new_info->baud_base < 9600)) |
754 | retval = -EINVAL; | 748 | retval = -EINVAL; |
755 | 749 | ||
756 | if (retval) | 750 | if (retval) |
@@ -790,11 +784,11 @@ static int uart_set_info(struct tty_struct *tty, struct uart_state *state, | |||
790 | uport->ops->release_port(uport); | 784 | uport->ops->release_port(uport); |
791 | 785 | ||
792 | uport->iobase = new_port; | 786 | uport->iobase = new_port; |
793 | uport->type = new_serial.type; | 787 | uport->type = new_info->type; |
794 | uport->hub6 = new_serial.hub6; | 788 | uport->hub6 = new_info->hub6; |
795 | uport->iotype = new_serial.io_type; | 789 | uport->iotype = new_info->io_type; |
796 | uport->regshift = new_serial.iomem_reg_shift; | 790 | uport->regshift = new_info->iomem_reg_shift; |
797 | uport->mapbase = (unsigned long)new_serial.iomem_base; | 791 | uport->mapbase = (unsigned long)new_info->iomem_base; |
798 | 792 | ||
799 | /* | 793 | /* |
800 | * Claim and map the new regions | 794 | * Claim and map the new regions |
@@ -835,16 +829,16 @@ static int uart_set_info(struct tty_struct *tty, struct uart_state *state, | |||
835 | } | 829 | } |
836 | 830 | ||
837 | if (change_irq) | 831 | if (change_irq) |
838 | uport->irq = new_serial.irq; | 832 | uport->irq = new_info->irq; |
839 | if (!(uport->flags & UPF_FIXED_PORT)) | 833 | if (!(uport->flags & UPF_FIXED_PORT)) |
840 | uport->uartclk = new_serial.baud_base * 16; | 834 | uport->uartclk = new_info->baud_base * 16; |
841 | uport->flags = (uport->flags & ~UPF_CHANGE_MASK) | | 835 | uport->flags = (uport->flags & ~UPF_CHANGE_MASK) | |
842 | (new_flags & UPF_CHANGE_MASK); | 836 | (new_flags & UPF_CHANGE_MASK); |
843 | uport->custom_divisor = new_serial.custom_divisor; | 837 | uport->custom_divisor = new_info->custom_divisor; |
844 | port->close_delay = close_delay; | 838 | port->close_delay = close_delay; |
845 | port->closing_wait = closing_wait; | 839 | port->closing_wait = closing_wait; |
846 | if (new_serial.xmit_fifo_size) | 840 | if (new_info->xmit_fifo_size) |
847 | uport->fifosize = new_serial.xmit_fifo_size; | 841 | uport->fifosize = new_info->xmit_fifo_size; |
848 | if (port->tty) | 842 | if (port->tty) |
849 | port->tty->low_latency = | 843 | port->tty->low_latency = |
850 | (uport->flags & UPF_LOW_LATENCY) ? 1 : 0; | 844 | (uport->flags & UPF_LOW_LATENCY) ? 1 : 0; |
@@ -873,6 +867,28 @@ static int uart_set_info(struct tty_struct *tty, struct uart_state *state, | |||
873 | } else | 867 | } else |
874 | retval = uart_startup(tty, state, 1); | 868 | retval = uart_startup(tty, state, 1); |
875 | exit: | 869 | exit: |
870 | return retval; | ||
871 | } | ||
872 | |||
873 | static int uart_set_info_user(struct tty_struct *tty, struct uart_state *state, | ||
874 | struct serial_struct __user *newinfo) | ||
875 | { | ||
876 | struct serial_struct new_serial; | ||
877 | struct tty_port *port = &state->port; | ||
878 | int retval; | ||
879 | |||
880 | if (copy_from_user(&new_serial, newinfo, sizeof(new_serial))) | ||
881 | return -EFAULT; | ||
882 | |||
883 | /* | ||
884 | * This semaphore protects port->count. It is also | ||
885 | * very useful to prevent opens. Also, take the | ||
886 | * port configuration semaphore to make sure that a | ||
887 | * module insertion/removal doesn't change anything | ||
888 | * under us. | ||
889 | */ | ||
890 | mutex_lock(&port->mutex); | ||
891 | retval = uart_set_info(tty, port, state, &new_serial); | ||
876 | mutex_unlock(&port->mutex); | 892 | mutex_unlock(&port->mutex); |
877 | return retval; | 893 | return retval; |
878 | } | 894 | } |
@@ -1115,11 +1131,11 @@ uart_ioctl(struct tty_struct *tty, unsigned int cmd, | |||
1115 | */ | 1131 | */ |
1116 | switch (cmd) { | 1132 | switch (cmd) { |
1117 | case TIOCGSERIAL: | 1133 | case TIOCGSERIAL: |
1118 | ret = uart_get_info(state, uarg); | 1134 | ret = uart_get_info_user(state, uarg); |
1119 | break; | 1135 | break; |
1120 | 1136 | ||
1121 | case TIOCSSERIAL: | 1137 | case TIOCSSERIAL: |
1122 | ret = uart_set_info(tty, state, uarg); | 1138 | ret = uart_set_info_user(tty, state, uarg); |
1123 | break; | 1139 | break; |
1124 | 1140 | ||
1125 | case TIOCSERCONFIG: | 1141 | case TIOCSERCONFIG: |
@@ -1187,7 +1203,7 @@ static void uart_set_ldisc(struct tty_struct *tty) | |||
1187 | struct uart_port *uport = state->uart_port; | 1203 | struct uart_port *uport = state->uart_port; |
1188 | 1204 | ||
1189 | if (uport->ops->set_ldisc) | 1205 | if (uport->ops->set_ldisc) |
1190 | uport->ops->set_ldisc(uport, tty->termios->c_line); | 1206 | uport->ops->set_ldisc(uport, tty->termios.c_line); |
1191 | } | 1207 | } |
1192 | 1208 | ||
1193 | static void uart_set_termios(struct tty_struct *tty, | 1209 | static void uart_set_termios(struct tty_struct *tty, |
@@ -1195,7 +1211,7 @@ static void uart_set_termios(struct tty_struct *tty, | |||
1195 | { | 1211 | { |
1196 | struct uart_state *state = tty->driver_data; | 1212 | struct uart_state *state = tty->driver_data; |
1197 | unsigned long flags; | 1213 | unsigned long flags; |
1198 | unsigned int cflag = tty->termios->c_cflag; | 1214 | unsigned int cflag = tty->termios.c_cflag; |
1199 | 1215 | ||
1200 | 1216 | ||
1201 | /* | 1217 | /* |
@@ -1206,9 +1222,9 @@ static void uart_set_termios(struct tty_struct *tty, | |||
1206 | */ | 1222 | */ |
1207 | #define RELEVANT_IFLAG(iflag) ((iflag) & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK)) | 1223 | #define RELEVANT_IFLAG(iflag) ((iflag) & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK)) |
1208 | if ((cflag ^ old_termios->c_cflag) == 0 && | 1224 | if ((cflag ^ old_termios->c_cflag) == 0 && |
1209 | tty->termios->c_ospeed == old_termios->c_ospeed && | 1225 | tty->termios.c_ospeed == old_termios->c_ospeed && |
1210 | tty->termios->c_ispeed == old_termios->c_ispeed && | 1226 | tty->termios.c_ispeed == old_termios->c_ispeed && |
1211 | RELEVANT_IFLAG(tty->termios->c_iflag ^ old_termios->c_iflag) == 0) { | 1227 | RELEVANT_IFLAG(tty->termios.c_iflag ^ old_termios->c_iflag) == 0) { |
1212 | return; | 1228 | return; |
1213 | } | 1229 | } |
1214 | 1230 | ||
@@ -1960,8 +1976,8 @@ int uart_resume_port(struct uart_driver *drv, struct uart_port *uport) | |||
1960 | /* | 1976 | /* |
1961 | * If that's unset, use the tty termios setting. | 1977 | * If that's unset, use the tty termios setting. |
1962 | */ | 1978 | */ |
1963 | if (port->tty && port->tty->termios && termios.c_cflag == 0) | 1979 | if (port->tty && termios.c_cflag == 0) |
1964 | termios = *(port->tty->termios); | 1980 | termios = port->tty->termios; |
1965 | 1981 | ||
1966 | if (console_suspend_enabled) | 1982 | if (console_suspend_enabled) |
1967 | uart_change_pm(state, 0); | 1983 | uart_change_pm(state, 0); |
@@ -2293,6 +2309,36 @@ struct tty_driver *uart_console_device(struct console *co, int *index) | |||
2293 | return p->tty_driver; | 2309 | return p->tty_driver; |
2294 | } | 2310 | } |
2295 | 2311 | ||
2312 | static ssize_t uart_get_attr_uartclk(struct device *dev, | ||
2313 | struct device_attribute *attr, char *buf) | ||
2314 | { | ||
2315 | int ret; | ||
2316 | struct tty_port *port = dev_get_drvdata(dev); | ||
2317 | struct uart_state *state = container_of(port, struct uart_state, port); | ||
2318 | |||
2319 | mutex_lock(&state->port.mutex); | ||
2320 | ret = snprintf(buf, PAGE_SIZE, "%d\n", state->uart_port->uartclk); | ||
2321 | mutex_unlock(&state->port.mutex); | ||
2322 | |||
2323 | return ret; | ||
2324 | } | ||
2325 | |||
2326 | static DEVICE_ATTR(uartclk, S_IRUSR | S_IRGRP, uart_get_attr_uartclk, NULL); | ||
2327 | |||
2328 | static struct attribute *tty_dev_attrs[] = { | ||
2329 | &dev_attr_uartclk.attr, | ||
2330 | NULL, | ||
2331 | }; | ||
2332 | |||
2333 | static const struct attribute_group tty_dev_attr_group = { | ||
2334 | .attrs = tty_dev_attrs, | ||
2335 | }; | ||
2336 | |||
2337 | static const struct attribute_group *tty_dev_attr_groups[] = { | ||
2338 | &tty_dev_attr_group, | ||
2339 | NULL | ||
2340 | }; | ||
2341 | |||
2296 | /** | 2342 | /** |
2297 | * uart_add_one_port - attach a driver-defined port structure | 2343 | * uart_add_one_port - attach a driver-defined port structure |
2298 | * @drv: pointer to the uart low level driver structure for this port | 2344 | * @drv: pointer to the uart low level driver structure for this port |
@@ -2346,7 +2392,8 @@ int uart_add_one_port(struct uart_driver *drv, struct uart_port *uport) | |||
2346 | * Register the port whether it's detected or not. This allows | 2392 | * Register the port whether it's detected or not. This allows |
2347 | * setserial to be used to alter this ports parameters. | 2393 | * setserial to be used to alter this ports parameters. |
2348 | */ | 2394 | */ |
2349 | tty_dev = tty_register_device(drv->tty_driver, uport->line, uport->dev); | 2395 | tty_dev = tty_port_register_device_attr(port, drv->tty_driver, |
2396 | uport->line, uport->dev, port, tty_dev_attr_groups); | ||
2350 | if (likely(!IS_ERR(tty_dev))) { | 2397 | if (likely(!IS_ERR(tty_dev))) { |
2351 | device_set_wakeup_capable(tty_dev, 1); | 2398 | device_set_wakeup_capable(tty_dev, 1); |
2352 | } else { | 2399 | } else { |
@@ -2492,7 +2539,7 @@ void uart_handle_cts_change(struct uart_port *uport, unsigned int status) | |||
2492 | 2539 | ||
2493 | uport->icount.cts++; | 2540 | uport->icount.cts++; |
2494 | 2541 | ||
2495 | if (port->flags & ASYNC_CTS_FLOW) { | 2542 | if (tty_port_cts_enabled(port)) { |
2496 | if (tty->hw_stopped) { | 2543 | if (tty->hw_stopped) { |
2497 | if (status) { | 2544 | if (status) { |
2498 | tty->hw_stopped = 0; | 2545 | tty->hw_stopped = 0; |