Commit 33dd474a authored by Alan Cox's avatar Alan Cox Committed by Linus Torvalds

tty: kref nozomi

Update the nozomi driver to use krefs
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent c9f19e96
...@@ -353,6 +353,7 @@ struct ctrl_ul { ...@@ -353,6 +353,7 @@ struct ctrl_ul {
/* This holds all information that is needed regarding a port */ /* This holds all information that is needed regarding a port */
struct port { struct port {
struct tty_port port;
u8 update_flow_control; u8 update_flow_control;
struct ctrl_ul ctrl_ul; struct ctrl_ul ctrl_ul;
struct ctrl_dl ctrl_dl; struct ctrl_dl ctrl_dl;
...@@ -365,8 +366,6 @@ struct port { ...@@ -365,8 +366,6 @@ struct port {
u8 toggle_ul; u8 toggle_ul;
u16 token_dl; u16 token_dl;
struct tty_struct *tty;
int tty_open_count;
/* mutex to ensure one access patch to this port */ /* mutex to ensure one access patch to this port */
struct mutex tty_sem; struct mutex tty_sem;
wait_queue_head_t tty_wait; wait_queue_head_t tty_wait;
...@@ -788,14 +787,14 @@ static void disable_transmit_dl(enum port_type port, struct nozomi *dc) ...@@ -788,14 +787,14 @@ static void disable_transmit_dl(enum port_type port, struct nozomi *dc)
* Return 1 - send buffer to card and ack. * Return 1 - send buffer to card and ack.
* Return 0 - don't ack, don't send buffer to card. * Return 0 - don't ack, don't send buffer to card.
*/ */
static int send_data(enum port_type index, const struct nozomi *dc) static int send_data(enum port_type index, struct nozomi *dc)
{ {
u32 size = 0; u32 size = 0;
const struct port *port = &dc->port[index]; struct port *port = &dc->port[index];
const u8 toggle = port->toggle_ul; const u8 toggle = port->toggle_ul;
void __iomem *addr = port->ul_addr[toggle]; void __iomem *addr = port->ul_addr[toggle];
const u32 ul_size = port->ul_size[toggle]; const u32 ul_size = port->ul_size[toggle];
struct tty_struct *tty = port->tty; struct tty_struct *tty = tty_port_tty_get(&port->port);
/* Get data from tty and place in buf for now */ /* Get data from tty and place in buf for now */
size = __kfifo_get(port->fifo_ul, dc->send_buf, size = __kfifo_get(port->fifo_ul, dc->send_buf,
...@@ -803,6 +802,7 @@ static int send_data(enum port_type index, const struct nozomi *dc) ...@@ -803,6 +802,7 @@ static int send_data(enum port_type index, const struct nozomi *dc)
if (size == 0) { if (size == 0) {
DBG4("No more data to send, disable link:"); DBG4("No more data to send, disable link:");
tty_kref_put(tty);
return 0; return 0;
} }
...@@ -815,6 +815,7 @@ static int send_data(enum port_type index, const struct nozomi *dc) ...@@ -815,6 +815,7 @@ static int send_data(enum port_type index, const struct nozomi *dc)
if (tty) if (tty)
tty_wakeup(tty); tty_wakeup(tty);
tty_kref_put(tty);
return 1; return 1;
} }
...@@ -826,7 +827,7 @@ static int receive_data(enum port_type index, struct nozomi *dc) ...@@ -826,7 +827,7 @@ static int receive_data(enum port_type index, struct nozomi *dc)
u32 offset = 4; u32 offset = 4;
struct port *port = &dc->port[index]; struct port *port = &dc->port[index];
void __iomem *addr = port->dl_addr[port->toggle_dl]; void __iomem *addr = port->dl_addr[port->toggle_dl];
struct tty_struct *tty = port->tty; struct tty_struct *tty = tty_port_tty_get(&port->port);
int i; int i;
if (unlikely(!tty)) { if (unlikely(!tty)) {
...@@ -870,7 +871,7 @@ static int receive_data(enum port_type index, struct nozomi *dc) ...@@ -870,7 +871,7 @@ static int receive_data(enum port_type index, struct nozomi *dc)
} }
set_bit(index, &dc->flip); set_bit(index, &dc->flip);
tty_kref_put(tty);
return 1; return 1;
} }
...@@ -1276,9 +1277,15 @@ static irqreturn_t interrupt_handler(int irq, void *dev_id) ...@@ -1276,9 +1277,15 @@ static irqreturn_t interrupt_handler(int irq, void *dev_id)
exit_handler: exit_handler:
spin_unlock(&dc->spin_mutex); spin_unlock(&dc->spin_mutex);
for (a = 0; a < NOZOMI_MAX_PORTS; a++) for (a = 0; a < NOZOMI_MAX_PORTS; a++) {
if (test_and_clear_bit(a, &dc->flip)) struct tty_struct *tty;
tty_flip_buffer_push(dc->port[a].tty); if (test_and_clear_bit(a, &dc->flip)) {
tty = tty_port_tty_get(&dc->port[a].port);
if (tty)
tty_flip_buffer_push(tty);
tty_kref_put(tty);
}
}
return IRQ_HANDLED; return IRQ_HANDLED;
none: none:
spin_unlock(&dc->spin_mutex); spin_unlock(&dc->spin_mutex);
...@@ -1453,12 +1460,10 @@ static int __devinit nozomi_card_init(struct pci_dev *pdev, ...@@ -1453,12 +1460,10 @@ static int __devinit nozomi_card_init(struct pci_dev *pdev,
for (i = 0; i < MAX_PORT; i++) { for (i = 0; i < MAX_PORT; i++) {
mutex_init(&dc->port[i].tty_sem); mutex_init(&dc->port[i].tty_sem);
dc->port[i].tty_open_count = 0; tty_port_init(&dc->port[i].port);
dc->port[i].tty = NULL;
tty_register_device(ntty_driver, dc->index_start + i, tty_register_device(ntty_driver, dc->index_start + i,
&pdev->dev); &pdev->dev);
} }
return 0; return 0;
err_free_sbuf: err_free_sbuf:
...@@ -1482,14 +1487,16 @@ static void __devexit tty_exit(struct nozomi *dc) ...@@ -1482,14 +1487,16 @@ static void __devexit tty_exit(struct nozomi *dc)
flush_scheduled_work(); flush_scheduled_work();
for (i = 0; i < MAX_PORT; ++i) for (i = 0; i < MAX_PORT; ++i) {
if (dc->port[i].tty && \ struct tty_struct *tty = tty_port_tty_get(&dc->port[i].port);
list_empty(&dc->port[i].tty->hangup_work.entry)) if (tty && list_empty(&tty->hangup_work.entry))
tty_hangup(dc->port[i].tty); tty_hangup(tty);
tty_kref_put(tty);
}
/* Racy below - surely should wait for scheduled work to be done or
complete off a hangup method ? */
while (dc->open_ttys) while (dc->open_ttys)
msleep(1); msleep(1);
for (i = dc->index_start; i < dc->index_start + MAX_PORT; ++i) for (i = dc->index_start; i < dc->index_start + MAX_PORT; ++i)
tty_unregister_device(ntty_driver, i); tty_unregister_device(ntty_driver, i);
} }
...@@ -1579,23 +1586,22 @@ static int ntty_open(struct tty_struct *tty, struct file *file) ...@@ -1579,23 +1586,22 @@ static int ntty_open(struct tty_struct *tty, struct file *file)
if (mutex_lock_interruptible(&port->tty_sem)) if (mutex_lock_interruptible(&port->tty_sem))
return -ERESTARTSYS; return -ERESTARTSYS;
port->tty_open_count++; port->port.count++;
dc->open_ttys++; dc->open_ttys++;
/* Enable interrupt downlink for channel */ /* Enable interrupt downlink for channel */
if (port->tty_open_count == 1) { if (port->port.count == 1) {
/* FIXME: is this needed now ? */
tty->low_latency = 1; tty->low_latency = 1;
tty->driver_data = port; tty->driver_data = port;
port->tty = tty; tty_port_tty_set(&port->port, tty);
DBG1("open: %d", port->token_dl); DBG1("open: %d", port->token_dl);
spin_lock_irqsave(&dc->spin_mutex, flags); spin_lock_irqsave(&dc->spin_mutex, flags);
dc->last_ier = dc->last_ier | port->token_dl; dc->last_ier = dc->last_ier | port->token_dl;
writew(dc->last_ier, dc->reg_ier); writew(dc->last_ier, dc->reg_ier);
spin_unlock_irqrestore(&dc->spin_mutex, flags); spin_unlock_irqrestore(&dc->spin_mutex, flags);
} }
mutex_unlock(&port->tty_sem); mutex_unlock(&port->tty_sem);
return 0; return 0;
} }
...@@ -1606,31 +1612,30 @@ static int ntty_open(struct tty_struct *tty, struct file *file) ...@@ -1606,31 +1612,30 @@ static int ntty_open(struct tty_struct *tty, struct file *file)
static void ntty_close(struct tty_struct *tty, struct file *file) static void ntty_close(struct tty_struct *tty, struct file *file)
{ {
struct nozomi *dc = get_dc_by_tty(tty); struct nozomi *dc = get_dc_by_tty(tty);
struct port *port = tty->driver_data; struct port *nport = tty->driver_data;
struct tty_port *port = &nport->port;
unsigned long flags; unsigned long flags;
if (!dc || !port) if (!dc || !nport)
return; return;
if (mutex_lock_interruptible(&port->tty_sem)) /* Users cannot interrupt a close */
return; mutex_lock(&nport->tty_sem);
if (!port->tty_open_count) WARN_ON(!port->count);
goto exit;
dc->open_ttys--; dc->open_ttys--;
port->tty_open_count--; port->count--;
tty_port_tty_set(port, NULL);
if (port->tty_open_count == 0) { if (port->count == 0) {
DBG1("close: %d", port->token_dl); DBG1("close: %d", nport->token_dl);
spin_lock_irqsave(&dc->spin_mutex, flags); spin_lock_irqsave(&dc->spin_mutex, flags);
dc->last_ier &= ~(port->token_dl); dc->last_ier &= ~(nport->token_dl);
writew(dc->last_ier, dc->reg_ier); writew(dc->last_ier, dc->reg_ier);
spin_unlock_irqrestore(&dc->spin_mutex, flags); spin_unlock_irqrestore(&dc->spin_mutex, flags);
} }
mutex_unlock(&nport->tty_sem);
exit:
mutex_unlock(&port->tty_sem);
} }
/* /*
...@@ -1660,7 +1665,7 @@ static int ntty_write(struct tty_struct *tty, const unsigned char *buffer, ...@@ -1660,7 +1665,7 @@ static int ntty_write(struct tty_struct *tty, const unsigned char *buffer,
return -EAGAIN; return -EAGAIN;
} }
if (unlikely(!port->tty_open_count)) { if (unlikely(!port->port.count)) {
DBG1(" "); DBG1(" ");
goto exit; goto exit;
} }
...@@ -1710,7 +1715,7 @@ static int ntty_write_room(struct tty_struct *tty) ...@@ -1710,7 +1715,7 @@ static int ntty_write_room(struct tty_struct *tty)
if (!mutex_trylock(&port->tty_sem)) if (!mutex_trylock(&port->tty_sem))
return 0; return 0;
if (!port->tty_open_count) if (!port->port.count)
goto exit; goto exit;
room = port->fifo_ul->size - __kfifo_len(port->fifo_ul); room = port->fifo_ul->size - __kfifo_len(port->fifo_ul);
...@@ -1866,7 +1871,7 @@ static s32 ntty_chars_in_buffer(struct tty_struct *tty) ...@@ -1866,7 +1871,7 @@ static s32 ntty_chars_in_buffer(struct tty_struct *tty)
goto exit_in_buffer; goto exit_in_buffer;
} }
if (unlikely(!port->tty_open_count)) { if (unlikely(!port->port.count)) {
dev_err(&dc->pdev->dev, "No tty open?\n"); dev_err(&dc->pdev->dev, "No tty open?\n");
rval = -ENODEV; rval = -ENODEV;
goto exit_in_buffer; goto exit_in_buffer;
......
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