diff options
author | Alan Cox <alan@redhat.com> | 2009-01-02 08:48:30 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-01-02 13:19:41 -0500 |
commit | 47b01b3a5fc7239f3e8d5d5cadc88afbea24d0c3 (patch) | |
tree | 74faa32048c31c53efb2789bec407e1c40d06bdc /drivers/char | |
parent | 21bed701da009b4192d9e86b3596cf210ac7369c (diff) |
tty: kref the rocket driver
We will need this kref fitted to make full use of the port operations.
Signed-off-by: Alan Cox <alan@redhat.com>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/char')
-rw-r--r-- | drivers/char/rocket.c | 78 |
1 files changed, 41 insertions, 37 deletions
diff --git a/drivers/char/rocket.c b/drivers/char/rocket.c index ca6fcdcca56e..b5e5e77c59de 100644 --- a/drivers/char/rocket.c +++ b/drivers/char/rocket.c | |||
@@ -436,15 +436,15 @@ static void rp_do_transmit(struct r_port *info) | |||
436 | #endif | 436 | #endif |
437 | if (!info) | 437 | if (!info) |
438 | return; | 438 | return; |
439 | if (!info->port.tty) { | 439 | tty = tty_port_tty_get(&info->port); |
440 | printk(KERN_WARNING "rp: WARNING %s called with " | 440 | |
441 | "info->port.tty==NULL\n", __func__); | 441 | if (tty == NULL) { |
442 | printk(KERN_WARNING "rp: WARNING %s called with tty==NULL\n", __func__); | ||
442 | clear_bit((info->aiop * 8) + info->chan, (void *) &xmit_flags[info->board]); | 443 | clear_bit((info->aiop * 8) + info->chan, (void *) &xmit_flags[info->board]); |
443 | return; | 444 | return; |
444 | } | 445 | } |
445 | 446 | ||
446 | spin_lock_irqsave(&info->slock, flags); | 447 | spin_lock_irqsave(&info->slock, flags); |
447 | tty = info->port.tty; | ||
448 | info->xmit_fifo_room = TXFIFO_SIZE - sGetTxCnt(cp); | 448 | info->xmit_fifo_room = TXFIFO_SIZE - sGetTxCnt(cp); |
449 | 449 | ||
450 | /* Loop sending data to FIFO until done or FIFO full */ | 450 | /* Loop sending data to FIFO until done or FIFO full */ |
@@ -478,6 +478,7 @@ static void rp_do_transmit(struct r_port *info) | |||
478 | } | 478 | } |
479 | 479 | ||
480 | spin_unlock_irqrestore(&info->slock, flags); | 480 | spin_unlock_irqrestore(&info->slock, flags); |
481 | tty_kref_put(tty); | ||
481 | 482 | ||
482 | #ifdef ROCKET_DEBUG_INTR | 483 | #ifdef ROCKET_DEBUG_INTR |
483 | printk(KERN_DEBUG "(%d,%d,%d,%d)...\n", info->xmit_cnt, info->xmit_head, | 484 | printk(KERN_DEBUG "(%d,%d,%d,%d)...\n", info->xmit_cnt, info->xmit_head, |
@@ -504,13 +505,13 @@ static void rp_handle_port(struct r_port *info) | |||
504 | "info->flags & NOT_INIT\n"); | 505 | "info->flags & NOT_INIT\n"); |
505 | return; | 506 | return; |
506 | } | 507 | } |
507 | if (!info->port.tty) { | 508 | tty = tty_port_tty_get(&info->port); |
509 | if (!tty) { | ||
508 | printk(KERN_WARNING "rp: WARNING: rp_handle_port called with " | 510 | printk(KERN_WARNING "rp: WARNING: rp_handle_port called with " |
509 | "info->port.tty==NULL\n"); | 511 | "tty==NULL\n"); |
510 | return; | 512 | return; |
511 | } | 513 | } |
512 | cp = &info->channel; | 514 | cp = &info->channel; |
513 | tty = info->port.tty; | ||
514 | 515 | ||
515 | IntMask = sGetChanIntID(cp) & info->intmask; | 516 | IntMask = sGetChanIntID(cp) & info->intmask; |
516 | #ifdef ROCKET_DEBUG_INTR | 517 | #ifdef ROCKET_DEBUG_INTR |
@@ -542,6 +543,7 @@ static void rp_handle_port(struct r_port *info) | |||
542 | printk(KERN_INFO "DSR change...\n"); | 543 | printk(KERN_INFO "DSR change...\n"); |
543 | } | 544 | } |
544 | #endif | 545 | #endif |
546 | tty_kref_put(tty); | ||
545 | } | 547 | } |
546 | 548 | ||
547 | /* | 549 | /* |
@@ -710,7 +712,7 @@ static void init_r_port(int board, int aiop, int chan, struct pci_dev *pci_dev) | |||
710 | * Configures a rocketport port according to its termio settings. Called from | 712 | * Configures a rocketport port according to its termio settings. Called from |
711 | * user mode into the driver (exception handler). *info CD manipulation is spinlock protected. | 713 | * user mode into the driver (exception handler). *info CD manipulation is spinlock protected. |
712 | */ | 714 | */ |
713 | static void configure_r_port(struct r_port *info, | 715 | static void configure_r_port(struct tty_struct *tty, struct r_port *info, |
714 | struct ktermios *old_termios) | 716 | struct ktermios *old_termios) |
715 | { | 717 | { |
716 | unsigned cflag; | 718 | unsigned cflag; |
@@ -718,7 +720,7 @@ static void configure_r_port(struct r_port *info, | |||
718 | unsigned rocketMode; | 720 | unsigned rocketMode; |
719 | int bits, baud, divisor; | 721 | int bits, baud, divisor; |
720 | CHANNEL_t *cp; | 722 | CHANNEL_t *cp; |
721 | struct ktermios *t = info->port.tty->termios; | 723 | struct ktermios *t = tty->termios; |
722 | 724 | ||
723 | cp = &info->channel; | 725 | cp = &info->channel; |
724 | cflag = t->c_cflag; | 726 | cflag = t->c_cflag; |
@@ -751,7 +753,7 @@ static void configure_r_port(struct r_port *info, | |||
751 | } | 753 | } |
752 | 754 | ||
753 | /* baud rate */ | 755 | /* baud rate */ |
754 | baud = tty_get_baud_rate(info->port.tty); | 756 | baud = tty_get_baud_rate(tty); |
755 | if (!baud) | 757 | if (!baud) |
756 | baud = 9600; | 758 | baud = 9600; |
757 | divisor = ((rp_baud_base[info->board] + (baud >> 1)) / baud) - 1; | 759 | divisor = ((rp_baud_base[info->board] + (baud >> 1)) / baud) - 1; |
@@ -769,7 +771,7 @@ static void configure_r_port(struct r_port *info, | |||
769 | sSetBaud(cp, divisor); | 771 | sSetBaud(cp, divisor); |
770 | 772 | ||
771 | /* FIXME: Should really back compute a baud rate from the divisor */ | 773 | /* FIXME: Should really back compute a baud rate from the divisor */ |
772 | tty_encode_baud_rate(info->port.tty, baud, baud); | 774 | tty_encode_baud_rate(tty, baud, baud); |
773 | 775 | ||
774 | if (cflag & CRTSCTS) { | 776 | if (cflag & CRTSCTS) { |
775 | info->intmask |= DELTA_CTS; | 777 | info->intmask |= DELTA_CTS; |
@@ -794,15 +796,15 @@ static void configure_r_port(struct r_port *info, | |||
794 | * Handle software flow control in the board | 796 | * Handle software flow control in the board |
795 | */ | 797 | */ |
796 | #ifdef ROCKET_SOFT_FLOW | 798 | #ifdef ROCKET_SOFT_FLOW |
797 | if (I_IXON(info->port.tty)) { | 799 | if (I_IXON(tty)) { |
798 | sEnTxSoftFlowCtl(cp); | 800 | sEnTxSoftFlowCtl(cp); |
799 | if (I_IXANY(info->port.tty)) { | 801 | if (I_IXANY(tty)) { |
800 | sEnIXANY(cp); | 802 | sEnIXANY(cp); |
801 | } else { | 803 | } else { |
802 | sDisIXANY(cp); | 804 | sDisIXANY(cp); |
803 | } | 805 | } |
804 | sSetTxXONChar(cp, START_CHAR(info->port.tty)); | 806 | sSetTxXONChar(cp, START_CHAR(tty)); |
805 | sSetTxXOFFChar(cp, STOP_CHAR(info->port.tty)); | 807 | sSetTxXOFFChar(cp, STOP_CHAR(tty)); |
806 | } else { | 808 | } else { |
807 | sDisTxSoftFlowCtl(cp); | 809 | sDisTxSoftFlowCtl(cp); |
808 | sDisIXANY(cp); | 810 | sDisIXANY(cp); |
@@ -814,24 +816,24 @@ static void configure_r_port(struct r_port *info, | |||
814 | * Set up ignore/read mask words | 816 | * Set up ignore/read mask words |
815 | */ | 817 | */ |
816 | info->read_status_mask = STMRCVROVRH | 0xFF; | 818 | info->read_status_mask = STMRCVROVRH | 0xFF; |
817 | if (I_INPCK(info->port.tty)) | 819 | if (I_INPCK(tty)) |
818 | info->read_status_mask |= STMFRAMEH | STMPARITYH; | 820 | info->read_status_mask |= STMFRAMEH | STMPARITYH; |
819 | if (I_BRKINT(info->port.tty) || I_PARMRK(info->port.tty)) | 821 | if (I_BRKINT(tty) || I_PARMRK(tty)) |
820 | info->read_status_mask |= STMBREAKH; | 822 | info->read_status_mask |= STMBREAKH; |
821 | 823 | ||
822 | /* | 824 | /* |
823 | * Characters to ignore | 825 | * Characters to ignore |
824 | */ | 826 | */ |
825 | info->ignore_status_mask = 0; | 827 | info->ignore_status_mask = 0; |
826 | if (I_IGNPAR(info->port.tty)) | 828 | if (I_IGNPAR(tty)) |
827 | info->ignore_status_mask |= STMFRAMEH | STMPARITYH; | 829 | info->ignore_status_mask |= STMFRAMEH | STMPARITYH; |
828 | if (I_IGNBRK(info->port.tty)) { | 830 | if (I_IGNBRK(tty)) { |
829 | info->ignore_status_mask |= STMBREAKH; | 831 | info->ignore_status_mask |= STMBREAKH; |
830 | /* | 832 | /* |
831 | * If we're ignoring parity and break indicators, | 833 | * If we're ignoring parity and break indicators, |
832 | * ignore overruns too. (For real raw support). | 834 | * ignore overruns too. (For real raw support). |
833 | */ | 835 | */ |
834 | if (I_IGNPAR(info->port.tty)) | 836 | if (I_IGNPAR(tty)) |
835 | info->ignore_status_mask |= STMRCVROVRH; | 837 | info->ignore_status_mask |= STMRCVROVRH; |
836 | } | 838 | } |
837 | 839 | ||
@@ -1015,7 +1017,7 @@ static int rp_open(struct tty_struct *tty, struct file *filp) | |||
1015 | info->xmit_buf = (unsigned char *) page; | 1017 | info->xmit_buf = (unsigned char *) page; |
1016 | 1018 | ||
1017 | tty->driver_data = info; | 1019 | tty->driver_data = info; |
1018 | info->port.tty = tty; | 1020 | tty_port_tty_set(&info->port, tty); |
1019 | 1021 | ||
1020 | if (info->port.count++ == 0) { | 1022 | if (info->port.count++ == 0) { |
1021 | atomic_inc(&rp_num_ports_open); | 1023 | atomic_inc(&rp_num_ports_open); |
@@ -1062,15 +1064,15 @@ static int rp_open(struct tty_struct *tty, struct file *filp) | |||
1062 | * Set up the tty->alt_speed kludge | 1064 | * Set up the tty->alt_speed kludge |
1063 | */ | 1065 | */ |
1064 | if ((info->flags & ROCKET_SPD_MASK) == ROCKET_SPD_HI) | 1066 | if ((info->flags & ROCKET_SPD_MASK) == ROCKET_SPD_HI) |
1065 | info->port.tty->alt_speed = 57600; | 1067 | tty->alt_speed = 57600; |
1066 | if ((info->flags & ROCKET_SPD_MASK) == ROCKET_SPD_VHI) | 1068 | if ((info->flags & ROCKET_SPD_MASK) == ROCKET_SPD_VHI) |
1067 | info->port.tty->alt_speed = 115200; | 1069 | tty->alt_speed = 115200; |
1068 | if ((info->flags & ROCKET_SPD_MASK) == ROCKET_SPD_SHI) | 1070 | if ((info->flags & ROCKET_SPD_MASK) == ROCKET_SPD_SHI) |
1069 | info->port.tty->alt_speed = 230400; | 1071 | tty->alt_speed = 230400; |
1070 | if ((info->flags & ROCKET_SPD_MASK) == ROCKET_SPD_WARP) | 1072 | if ((info->flags & ROCKET_SPD_MASK) == ROCKET_SPD_WARP) |
1071 | info->port.tty->alt_speed = 460800; | 1073 | tty->alt_speed = 460800; |
1072 | 1074 | ||
1073 | configure_r_port(info, NULL); | 1075 | configure_r_port(tty, info, NULL); |
1074 | if (tty->termios->c_cflag & CBAUD) { | 1076 | if (tty->termios->c_cflag & CBAUD) { |
1075 | sSetDTR(cp); | 1077 | sSetDTR(cp); |
1076 | sSetRTS(cp); | 1078 | sSetRTS(cp); |
@@ -1227,7 +1229,7 @@ static void rp_set_termios(struct tty_struct *tty, | |||
1227 | /* Or CMSPAR */ | 1229 | /* Or CMSPAR */ |
1228 | tty->termios->c_cflag &= ~CMSPAR; | 1230 | tty->termios->c_cflag &= ~CMSPAR; |
1229 | 1231 | ||
1230 | configure_r_port(info, old_termios); | 1232 | configure_r_port(tty, info, old_termios); |
1231 | 1233 | ||
1232 | cp = &info->channel; | 1234 | cp = &info->channel; |
1233 | 1235 | ||
@@ -1352,7 +1354,8 @@ static int get_config(struct r_port *info, struct rocket_config __user *retinfo) | |||
1352 | return 0; | 1354 | return 0; |
1353 | } | 1355 | } |
1354 | 1356 | ||
1355 | static int set_config(struct r_port *info, struct rocket_config __user *new_info) | 1357 | static int set_config(struct tty_struct *tty, struct r_port *info, |
1358 | struct rocket_config __user *new_info) | ||
1356 | { | 1359 | { |
1357 | struct rocket_config new_serial; | 1360 | struct rocket_config new_serial; |
1358 | 1361 | ||
@@ -1364,7 +1367,7 @@ static int set_config(struct r_port *info, struct rocket_config __user *new_info | |||
1364 | if ((new_serial.flags & ~ROCKET_USR_MASK) != (info->flags & ~ROCKET_USR_MASK)) | 1367 | if ((new_serial.flags & ~ROCKET_USR_MASK) != (info->flags & ~ROCKET_USR_MASK)) |
1365 | return -EPERM; | 1368 | return -EPERM; |
1366 | info->flags = ((info->flags & ~ROCKET_USR_MASK) | (new_serial.flags & ROCKET_USR_MASK)); | 1369 | info->flags = ((info->flags & ~ROCKET_USR_MASK) | (new_serial.flags & ROCKET_USR_MASK)); |
1367 | configure_r_port(info, NULL); | 1370 | configure_r_port(tty, info, NULL); |
1368 | return 0; | 1371 | return 0; |
1369 | } | 1372 | } |
1370 | 1373 | ||
@@ -1373,15 +1376,15 @@ static int set_config(struct r_port *info, struct rocket_config __user *new_info | |||
1373 | info->port.closing_wait = new_serial.closing_wait; | 1376 | info->port.closing_wait = new_serial.closing_wait; |
1374 | 1377 | ||
1375 | if ((info->flags & ROCKET_SPD_MASK) == ROCKET_SPD_HI) | 1378 | if ((info->flags & ROCKET_SPD_MASK) == ROCKET_SPD_HI) |
1376 | info->port.tty->alt_speed = 57600; | 1379 | tty->alt_speed = 57600; |
1377 | if ((info->flags & ROCKET_SPD_MASK) == ROCKET_SPD_VHI) | 1380 | if ((info->flags & ROCKET_SPD_MASK) == ROCKET_SPD_VHI) |
1378 | info->port.tty->alt_speed = 115200; | 1381 | tty->alt_speed = 115200; |
1379 | if ((info->flags & ROCKET_SPD_MASK) == ROCKET_SPD_SHI) | 1382 | if ((info->flags & ROCKET_SPD_MASK) == ROCKET_SPD_SHI) |
1380 | info->port.tty->alt_speed = 230400; | 1383 | tty->alt_speed = 230400; |
1381 | if ((info->flags & ROCKET_SPD_MASK) == ROCKET_SPD_WARP) | 1384 | if ((info->flags & ROCKET_SPD_MASK) == ROCKET_SPD_WARP) |
1382 | info->port.tty->alt_speed = 460800; | 1385 | tty->alt_speed = 460800; |
1383 | 1386 | ||
1384 | configure_r_port(info, NULL); | 1387 | configure_r_port(tty, info, NULL); |
1385 | return 0; | 1388 | return 0; |
1386 | } | 1389 | } |
1387 | 1390 | ||
@@ -1466,7 +1469,7 @@ static int rp_ioctl(struct tty_struct *tty, struct file *file, | |||
1466 | ret = get_config(info, argp); | 1469 | ret = get_config(info, argp); |
1467 | break; | 1470 | break; |
1468 | case RCKP_SET_CONFIG: | 1471 | case RCKP_SET_CONFIG: |
1469 | ret = set_config(info, argp); | 1472 | ret = set_config(tty, info, argp); |
1470 | break; | 1473 | break; |
1471 | case RCKP_GET_PORTS: | 1474 | case RCKP_GET_PORTS: |
1472 | ret = get_ports(info, argp); | 1475 | ret = get_ports(info, argp); |
@@ -1658,7 +1661,7 @@ static void rp_hangup(struct tty_struct *tty) | |||
1658 | 1661 | ||
1659 | info->port.count = 0; | 1662 | info->port.count = 0; |
1660 | info->port.flags &= ~ASYNC_NORMAL_ACTIVE; | 1663 | info->port.flags &= ~ASYNC_NORMAL_ACTIVE; |
1661 | info->port.tty = NULL; | 1664 | tty_port_tty_set(&info->port, NULL); |
1662 | 1665 | ||
1663 | cp = &info->channel; | 1666 | cp = &info->channel; |
1664 | sDisRxFIFO(cp); | 1667 | sDisRxFIFO(cp); |
@@ -1778,7 +1781,8 @@ static int rp_write(struct tty_struct *tty, | |||
1778 | 1781 | ||
1779 | /* Write remaining data into the port's xmit_buf */ | 1782 | /* Write remaining data into the port's xmit_buf */ |
1780 | while (1) { | 1783 | while (1) { |
1781 | if (!info->port.tty) /* Seemingly obligatory check... */ | 1784 | /* Hung up ? */ |
1785 | if (!test_bit(ASYNC_NORMAL_ACTIVE, &info->port.flags)) | ||
1782 | goto end; | 1786 | goto end; |
1783 | c = min(count, XMIT_BUF_SIZE - info->xmit_cnt - 1); | 1787 | c = min(count, XMIT_BUF_SIZE - info->xmit_cnt - 1); |
1784 | c = min(c, XMIT_BUF_SIZE - info->xmit_head); | 1788 | c = min(c, XMIT_BUF_SIZE - info->xmit_head); |