Commit 3969ffba authored by Alan Cox's avatar Alan Cox Committed by Linus Torvalds

tty: refcount the epca driver

Signed-off-by: default avatarAlan Cox <alan@redhat.com>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent d1c815e5
...@@ -175,7 +175,7 @@ static unsigned termios2digi_h(struct channel *ch, unsigned); ...@@ -175,7 +175,7 @@ static unsigned termios2digi_h(struct channel *ch, unsigned);
static unsigned termios2digi_i(struct channel *ch, unsigned); static unsigned termios2digi_i(struct channel *ch, unsigned);
static unsigned termios2digi_c(struct channel *ch, unsigned); static unsigned termios2digi_c(struct channel *ch, unsigned);
static void epcaparam(struct tty_struct *, struct channel *); static void epcaparam(struct tty_struct *, struct channel *);
static void receive_data(struct channel *); static void receive_data(struct channel *, struct tty_struct *tty);
static int pc_ioctl(struct tty_struct *, struct file *, static int pc_ioctl(struct tty_struct *, struct file *,
unsigned int, unsigned long); unsigned int, unsigned long);
static int info_ioctl(struct tty_struct *, struct file *, 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,7 +473,7 @@ static void pc_close(struct tty_struct *tty, struct file *filp)
spin_lock_irqsave(&port->lock, flags); spin_lock_irqsave(&port->lock, flags);
tty->closing = 0; tty->closing = 0;
ch->event = 0; ch->event = 0;
port->tty = NULL; tty_port_tty_set(port, NULL);
spin_unlock_irqrestore(&port->lock, flags); spin_unlock_irqrestore(&port->lock, flags);
if (port->blocked_open) { if (port->blocked_open) {
...@@ -1029,8 +1029,11 @@ static void __exit epca_module_exit(void) ...@@ -1029,8 +1029,11 @@ static void __exit epca_module_exit(void)
} }
ch = card_ptr[crd]; ch = card_ptr[crd];
for (count = 0; count < bd->numports; count++, ch++) { for (count = 0; count < bd->numports; count++, ch++) {
if (ch && ch->port.tty) struct tty_struct *tty = tty_port_tty_get(&ch->port);
tty_hangup(ch->port.tty); if (tty) {
tty_hangup(tty);
tty_kref_put(tty);
}
} }
} }
pci_unregister_driver(&epca_driver); pci_unregister_driver(&epca_driver);
...@@ -1441,7 +1444,7 @@ static void post_fep_init(unsigned int crd) ...@@ -1441,7 +1444,7 @@ static void post_fep_init(unsigned int crd)
ch->boardnum = crd; ch->boardnum = crd;
ch->channelnum = i; ch->channelnum = i;
ch->magic = EPCA_MAGIC; ch->magic = EPCA_MAGIC;
ch->port.tty = NULL; tty_port_tty_set(&ch->port, NULL);
if (shrinkmem) { if (shrinkmem) {
fepcmd(ch, SETBUFFER, 32, 0, 0, 0); fepcmd(ch, SETBUFFER, 32, 0, 0, 0);
...@@ -1635,8 +1638,9 @@ static void doevent(int crd) ...@@ -1635,8 +1638,9 @@ static void doevent(int crd)
if (bc == NULL) if (bc == NULL)
goto next; goto next;
tty = tty_port_tty_get(&ch->port);
if (event & DATA_IND) { /* Begin DATA_IND */ if (event & DATA_IND) { /* Begin DATA_IND */
receive_data(ch); receive_data(ch, tty);
assertgwinon(ch); assertgwinon(ch);
} /* End DATA_IND */ } /* End DATA_IND */
/* else *//* Fix for DCD transition missed bug */ /* else *//* Fix for DCD transition missed bug */
...@@ -1651,7 +1655,6 @@ static void doevent(int crd) ...@@ -1651,7 +1655,6 @@ static void doevent(int crd)
pc_sched_event(ch, EPCA_EVENT_HANGUP); pc_sched_event(ch, EPCA_EVENT_HANGUP);
} }
} }
tty = ch->port.tty;
if (tty) { if (tty) {
if (event & BREAK_IND) { if (event & BREAK_IND) {
/* A break has been indicated */ /* A break has been indicated */
...@@ -1671,6 +1674,7 @@ static void doevent(int crd) ...@@ -1671,6 +1674,7 @@ static void doevent(int crd)
tty_wakeup(tty); tty_wakeup(tty);
} }
} }
tty_kref_put(tty);
} }
next: next:
globalwinon(ch); globalwinon(ch);
...@@ -1965,11 +1969,10 @@ static void epcaparam(struct tty_struct *tty, struct channel *ch) ...@@ -1965,11 +1969,10 @@ static void epcaparam(struct tty_struct *tty, struct channel *ch)
} }
/* Caller holds lock */ /* Caller holds lock */
static void receive_data(struct channel *ch) static void receive_data(struct channel *ch, struct tty_struct *tty)
{ {
unchar *rptr; unchar *rptr;
struct ktermios *ts = NULL; struct ktermios *ts = NULL;
struct tty_struct *tty;
struct board_chan __iomem *bc; struct board_chan __iomem *bc;
int dataToRead, wrapgap, bytesAvailable; int dataToRead, wrapgap, bytesAvailable;
unsigned int tail, head; unsigned int tail, head;
...@@ -1982,7 +1985,6 @@ static void receive_data(struct channel *ch) ...@@ -1982,7 +1985,6 @@ static void receive_data(struct channel *ch)
globalwinon(ch); globalwinon(ch);
if (ch->statusflags & RXSTOPPED) if (ch->statusflags & RXSTOPPED)
return; return;
tty = ch->port.tty;
if (tty) if (tty)
ts = tty->termios; ts = tty->termios;
bc = ch->brdchan; bc = ch->brdchan;
...@@ -2042,7 +2044,7 @@ static void receive_data(struct channel *ch) ...@@ -2042,7 +2044,7 @@ static void receive_data(struct channel *ch)
globalwinon(ch); globalwinon(ch);
writew(tail, &bc->rout); writew(tail, &bc->rout);
/* Must be called with global data */ /* Must be called with global data */
tty_schedule_flip(ch->port.tty); tty_schedule_flip(tty);
} }
static int info_ioctl(struct tty_struct *tty, struct file *file, static int info_ioctl(struct tty_struct *tty, struct file *file,
...@@ -2365,7 +2367,7 @@ static void do_softint(struct work_struct *work) ...@@ -2365,7 +2367,7 @@ static void do_softint(struct work_struct *work)
struct channel *ch = container_of(work, struct channel, tqueue); struct channel *ch = container_of(work, struct channel, tqueue);
/* Called in response to a modem change event */ /* Called in response to a modem change event */
if (ch && ch->magic == EPCA_MAGIC) { if (ch && ch->magic == EPCA_MAGIC) {
struct tty_struct *tty = ch->port.tty; struct tty_struct *tty = tty_port_tty_get(&ch->port);;
if (tty && tty->driver_data) { if (tty && tty->driver_data) {
if (test_and_clear_bit(EPCA_EVENT_HANGUP, &ch->event)) { if (test_and_clear_bit(EPCA_EVENT_HANGUP, &ch->event)) {
...@@ -2374,6 +2376,7 @@ static void do_softint(struct work_struct *work) ...@@ -2374,6 +2376,7 @@ static void do_softint(struct work_struct *work)
ch->port.flags &= ~ASYNC_NORMAL_ACTIVE; ch->port.flags &= ~ASYNC_NORMAL_ACTIVE;
} }
} }
tty_kref_put(tty);
} }
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment