diff options
author | Alan Cox <alan@redhat.com> | 2009-01-02 08:48:04 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-01-02 13:19:41 -0500 |
commit | 3969ffba71d39ced700d09d9cfde83174396299e (patch) | |
tree | 8cbb5528f31ed4ca44eb0fd7ecdd45db8d5acef4 /drivers/char | |
parent | d1c815e549ff40f9e9db65654855118e6bdff6a4 (diff) |
tty: refcount the epca driver
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/epca.c | 27 |
1 files changed, 15 insertions, 12 deletions
diff --git a/drivers/char/epca.c b/drivers/char/epca.c index e07d7925c300..7a697055e4f6 100644 --- a/drivers/char/epca.c +++ b/drivers/char/epca.c | |||
@@ -175,7 +175,7 @@ static unsigned termios2digi_h(struct channel *ch, unsigned); | |||
175 | static unsigned termios2digi_i(struct channel *ch, unsigned); | 175 | static unsigned termios2digi_i(struct channel *ch, unsigned); |
176 | static unsigned termios2digi_c(struct channel *ch, unsigned); | 176 | static unsigned termios2digi_c(struct channel *ch, unsigned); |
177 | static void epcaparam(struct tty_struct *, struct channel *); | 177 | static void epcaparam(struct tty_struct *, struct channel *); |
178 | static void receive_data(struct channel *); | 178 | static void receive_data(struct channel *, struct tty_struct *tty); |
179 | static int pc_ioctl(struct tty_struct *, struct file *, | 179 | static int pc_ioctl(struct tty_struct *, struct file *, |
180 | unsigned int, unsigned long); | 180 | unsigned int, unsigned long); |
181 | static int info_ioctl(struct tty_struct *, struct file *, | 181 | static int info_ioctl(struct tty_struct *, struct file *, |
@@ -473,7 +473,7 @@ static void pc_close(struct tty_struct *tty, struct file *filp) | |||
473 | spin_lock_irqsave(&port->lock, flags); | 473 | spin_lock_irqsave(&port->lock, flags); |
474 | tty->closing = 0; | 474 | tty->closing = 0; |
475 | ch->event = 0; | 475 | ch->event = 0; |
476 | port->tty = NULL; | 476 | tty_port_tty_set(port, NULL); |
477 | spin_unlock_irqrestore(&port->lock, flags); | 477 | spin_unlock_irqrestore(&port->lock, flags); |
478 | 478 | ||
479 | if (port->blocked_open) { | 479 | if (port->blocked_open) { |
@@ -1029,8 +1029,11 @@ static void __exit epca_module_exit(void) | |||
1029 | } | 1029 | } |
1030 | ch = card_ptr[crd]; | 1030 | ch = card_ptr[crd]; |
1031 | for (count = 0; count < bd->numports; count++, ch++) { | 1031 | for (count = 0; count < bd->numports; count++, ch++) { |
1032 | if (ch && ch->port.tty) | 1032 | struct tty_struct *tty = tty_port_tty_get(&ch->port); |
1033 | tty_hangup(ch->port.tty); | 1033 | if (tty) { |
1034 | tty_hangup(tty); | ||
1035 | tty_kref_put(tty); | ||
1036 | } | ||
1034 | } | 1037 | } |
1035 | } | 1038 | } |
1036 | pci_unregister_driver(&epca_driver); | 1039 | pci_unregister_driver(&epca_driver); |
@@ -1441,7 +1444,7 @@ static void post_fep_init(unsigned int crd) | |||
1441 | ch->boardnum = crd; | 1444 | ch->boardnum = crd; |
1442 | ch->channelnum = i; | 1445 | ch->channelnum = i; |
1443 | ch->magic = EPCA_MAGIC; | 1446 | ch->magic = EPCA_MAGIC; |
1444 | ch->port.tty = NULL; | 1447 | tty_port_tty_set(&ch->port, NULL); |
1445 | 1448 | ||
1446 | if (shrinkmem) { | 1449 | if (shrinkmem) { |
1447 | fepcmd(ch, SETBUFFER, 32, 0, 0, 0); | 1450 | fepcmd(ch, SETBUFFER, 32, 0, 0, 0); |
@@ -1635,8 +1638,9 @@ static void doevent(int crd) | |||
1635 | if (bc == NULL) | 1638 | if (bc == NULL) |
1636 | goto next; | 1639 | goto next; |
1637 | 1640 | ||
1641 | tty = tty_port_tty_get(&ch->port); | ||
1638 | if (event & DATA_IND) { /* Begin DATA_IND */ | 1642 | if (event & DATA_IND) { /* Begin DATA_IND */ |
1639 | receive_data(ch); | 1643 | receive_data(ch, tty); |
1640 | assertgwinon(ch); | 1644 | assertgwinon(ch); |
1641 | } /* End DATA_IND */ | 1645 | } /* End DATA_IND */ |
1642 | /* else *//* Fix for DCD transition missed bug */ | 1646 | /* else *//* Fix for DCD transition missed bug */ |
@@ -1651,7 +1655,6 @@ static void doevent(int crd) | |||
1651 | pc_sched_event(ch, EPCA_EVENT_HANGUP); | 1655 | pc_sched_event(ch, EPCA_EVENT_HANGUP); |
1652 | } | 1656 | } |
1653 | } | 1657 | } |
1654 | tty = ch->port.tty; | ||
1655 | if (tty) { | 1658 | if (tty) { |
1656 | if (event & BREAK_IND) { | 1659 | if (event & BREAK_IND) { |
1657 | /* A break has been indicated */ | 1660 | /* A break has been indicated */ |
@@ -1671,6 +1674,7 @@ static void doevent(int crd) | |||
1671 | tty_wakeup(tty); | 1674 | tty_wakeup(tty); |
1672 | } | 1675 | } |
1673 | } | 1676 | } |
1677 | tty_kref_put(tty); | ||
1674 | } | 1678 | } |
1675 | next: | 1679 | next: |
1676 | globalwinon(ch); | 1680 | globalwinon(ch); |
@@ -1965,11 +1969,10 @@ static void epcaparam(struct tty_struct *tty, struct channel *ch) | |||
1965 | } | 1969 | } |
1966 | 1970 | ||
1967 | /* Caller holds lock */ | 1971 | /* Caller holds lock */ |
1968 | static void receive_data(struct channel *ch) | 1972 | static void receive_data(struct channel *ch, struct tty_struct *tty) |
1969 | { | 1973 | { |
1970 | unchar *rptr; | 1974 | unchar *rptr; |
1971 | struct ktermios *ts = NULL; | 1975 | struct ktermios *ts = NULL; |
1972 | struct tty_struct *tty; | ||
1973 | struct board_chan __iomem *bc; | 1976 | struct board_chan __iomem *bc; |
1974 | int dataToRead, wrapgap, bytesAvailable; | 1977 | int dataToRead, wrapgap, bytesAvailable; |
1975 | unsigned int tail, head; | 1978 | unsigned int tail, head; |
@@ -1982,7 +1985,6 @@ static void receive_data(struct channel *ch) | |||
1982 | globalwinon(ch); | 1985 | globalwinon(ch); |
1983 | if (ch->statusflags & RXSTOPPED) | 1986 | if (ch->statusflags & RXSTOPPED) |
1984 | return; | 1987 | return; |
1985 | tty = ch->port.tty; | ||
1986 | if (tty) | 1988 | if (tty) |
1987 | ts = tty->termios; | 1989 | ts = tty->termios; |
1988 | bc = ch->brdchan; | 1990 | bc = ch->brdchan; |
@@ -2042,7 +2044,7 @@ static void receive_data(struct channel *ch) | |||
2042 | globalwinon(ch); | 2044 | globalwinon(ch); |
2043 | writew(tail, &bc->rout); | 2045 | writew(tail, &bc->rout); |
2044 | /* Must be called with global data */ | 2046 | /* Must be called with global data */ |
2045 | tty_schedule_flip(ch->port.tty); | 2047 | tty_schedule_flip(tty); |
2046 | } | 2048 | } |
2047 | 2049 | ||
2048 | static int info_ioctl(struct tty_struct *tty, struct file *file, | 2050 | static int info_ioctl(struct tty_struct *tty, struct file *file, |
@@ -2365,7 +2367,7 @@ static void do_softint(struct work_struct *work) | |||
2365 | struct channel *ch = container_of(work, struct channel, tqueue); | 2367 | struct channel *ch = container_of(work, struct channel, tqueue); |
2366 | /* Called in response to a modem change event */ | 2368 | /* Called in response to a modem change event */ |
2367 | if (ch && ch->magic == EPCA_MAGIC) { | 2369 | if (ch && ch->magic == EPCA_MAGIC) { |
2368 | struct tty_struct *tty = ch->port.tty; | 2370 | struct tty_struct *tty = tty_port_tty_get(&ch->port);; |
2369 | 2371 | ||
2370 | if (tty && tty->driver_data) { | 2372 | if (tty && tty->driver_data) { |
2371 | if (test_and_clear_bit(EPCA_EVENT_HANGUP, &ch->event)) { | 2373 | if (test_and_clear_bit(EPCA_EVENT_HANGUP, &ch->event)) { |
@@ -2374,6 +2376,7 @@ static void do_softint(struct work_struct *work) | |||
2374 | ch->port.flags &= ~ASYNC_NORMAL_ACTIVE; | 2376 | ch->port.flags &= ~ASYNC_NORMAL_ACTIVE; |
2375 | } | 2377 | } |
2376 | } | 2378 | } |
2379 | tty_kref_put(tty); | ||
2377 | } | 2380 | } |
2378 | } | 2381 | } |
2379 | 2382 | ||