Loading drivers/char/nozomi.c +45 −40 Original line number Diff line number Diff line Loading @@ -353,6 +353,7 @@ struct ctrl_ul { /* This holds all information that is needed regarding a port */ struct port { struct tty_port port; u8 update_flow_control; struct ctrl_ul ctrl_ul; struct ctrl_dl ctrl_dl; Loading @@ -365,8 +366,6 @@ struct port { u8 toggle_ul; u16 token_dl; struct tty_struct *tty; int tty_open_count; /* mutex to ensure one access patch to this port */ struct mutex tty_sem; wait_queue_head_t tty_wait; Loading Loading @@ -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 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; const struct port *port = &dc->port[index]; struct port *port = &dc->port[index]; const u8 toggle = port->toggle_ul; void __iomem *addr = port->ul_addr[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 */ size = __kfifo_get(port->fifo_ul, dc->send_buf, Loading @@ -803,6 +802,7 @@ static int send_data(enum port_type index, const struct nozomi *dc) if (size == 0) { DBG4("No more data to send, disable link:"); tty_kref_put(tty); return 0; } Loading @@ -815,6 +815,7 @@ static int send_data(enum port_type index, const struct nozomi *dc) if (tty) tty_wakeup(tty); tty_kref_put(tty); return 1; } Loading @@ -826,7 +827,7 @@ static int receive_data(enum port_type index, struct nozomi *dc) u32 offset = 4; struct port *port = &dc->port[index]; 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; if (unlikely(!tty)) { Loading Loading @@ -870,7 +871,7 @@ static int receive_data(enum port_type index, struct nozomi *dc) } set_bit(index, &dc->flip); tty_kref_put(tty); return 1; } Loading Loading @@ -1276,9 +1277,15 @@ static irqreturn_t interrupt_handler(int irq, void *dev_id) exit_handler: spin_unlock(&dc->spin_mutex); for (a = 0; a < NOZOMI_MAX_PORTS; a++) if (test_and_clear_bit(a, &dc->flip)) tty_flip_buffer_push(dc->port[a].tty); for (a = 0; a < NOZOMI_MAX_PORTS; a++) { struct tty_struct *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; none: spin_unlock(&dc->spin_mutex); Loading Loading @@ -1453,12 +1460,10 @@ static int __devinit nozomi_card_init(struct pci_dev *pdev, for (i = 0; i < MAX_PORT; i++) { mutex_init(&dc->port[i].tty_sem); dc->port[i].tty_open_count = 0; dc->port[i].tty = NULL; tty_port_init(&dc->port[i].port); tty_register_device(ntty_driver, dc->index_start + i, &pdev->dev); } return 0; err_free_sbuf: Loading @@ -1482,14 +1487,16 @@ static void __devexit tty_exit(struct nozomi *dc) flush_scheduled_work(); for (i = 0; i < MAX_PORT; ++i) if (dc->port[i].tty && \ list_empty(&dc->port[i].tty->hangup_work.entry)) tty_hangup(dc->port[i].tty); for (i = 0; i < MAX_PORT; ++i) { struct tty_struct *tty = tty_port_tty_get(&dc->port[i].port); if (tty && list_empty(&tty->hangup_work.entry)) 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) msleep(1); for (i = dc->index_start; i < dc->index_start + MAX_PORT; ++i) tty_unregister_device(ntty_driver, i); } Loading Loading @@ -1579,23 +1586,22 @@ static int ntty_open(struct tty_struct *tty, struct file *file) if (mutex_lock_interruptible(&port->tty_sem)) return -ERESTARTSYS; port->tty_open_count++; port->port.count++; dc->open_ttys++; /* 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->driver_data = port; port->tty = tty; tty_port_tty_set(&port->port, tty); DBG1("open: %d", port->token_dl); spin_lock_irqsave(&dc->spin_mutex, flags); dc->last_ier = dc->last_ier | port->token_dl; writew(dc->last_ier, dc->reg_ier); spin_unlock_irqrestore(&dc->spin_mutex, flags); } mutex_unlock(&port->tty_sem); return 0; } Loading @@ -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) { 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; if (!dc || !port) if (!dc || !nport) return; if (mutex_lock_interruptible(&port->tty_sem)) return; /* Users cannot interrupt a close */ mutex_lock(&nport->tty_sem); if (!port->tty_open_count) goto exit; WARN_ON(!port->count); dc->open_ttys--; port->tty_open_count--; port->count--; tty_port_tty_set(port, NULL); if (port->tty_open_count == 0) { DBG1("close: %d", port->token_dl); if (port->count == 0) { DBG1("close: %d", nport->token_dl); 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); spin_unlock_irqrestore(&dc->spin_mutex, flags); } exit: mutex_unlock(&port->tty_sem); mutex_unlock(&nport->tty_sem); } /* Loading Loading @@ -1660,7 +1665,7 @@ static int ntty_write(struct tty_struct *tty, const unsigned char *buffer, return -EAGAIN; } if (unlikely(!port->tty_open_count)) { if (unlikely(!port->port.count)) { DBG1(" "); goto exit; } Loading Loading @@ -1710,7 +1715,7 @@ static int ntty_write_room(struct tty_struct *tty) if (!mutex_trylock(&port->tty_sem)) return 0; if (!port->tty_open_count) if (!port->port.count) goto exit; room = port->fifo_ul->size - __kfifo_len(port->fifo_ul); Loading Loading @@ -1866,7 +1871,7 @@ static s32 ntty_chars_in_buffer(struct tty_struct *tty) goto exit_in_buffer; } if (unlikely(!port->tty_open_count)) { if (unlikely(!port->port.count)) { dev_err(&dc->pdev->dev, "No tty open?\n"); rval = -ENODEV; goto exit_in_buffer; Loading Loading
drivers/char/nozomi.c +45 −40 Original line number Diff line number Diff line Loading @@ -353,6 +353,7 @@ struct ctrl_ul { /* This holds all information that is needed regarding a port */ struct port { struct tty_port port; u8 update_flow_control; struct ctrl_ul ctrl_ul; struct ctrl_dl ctrl_dl; Loading @@ -365,8 +366,6 @@ struct port { u8 toggle_ul; u16 token_dl; struct tty_struct *tty; int tty_open_count; /* mutex to ensure one access patch to this port */ struct mutex tty_sem; wait_queue_head_t tty_wait; Loading Loading @@ -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 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; const struct port *port = &dc->port[index]; struct port *port = &dc->port[index]; const u8 toggle = port->toggle_ul; void __iomem *addr = port->ul_addr[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 */ size = __kfifo_get(port->fifo_ul, dc->send_buf, Loading @@ -803,6 +802,7 @@ static int send_data(enum port_type index, const struct nozomi *dc) if (size == 0) { DBG4("No more data to send, disable link:"); tty_kref_put(tty); return 0; } Loading @@ -815,6 +815,7 @@ static int send_data(enum port_type index, const struct nozomi *dc) if (tty) tty_wakeup(tty); tty_kref_put(tty); return 1; } Loading @@ -826,7 +827,7 @@ static int receive_data(enum port_type index, struct nozomi *dc) u32 offset = 4; struct port *port = &dc->port[index]; 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; if (unlikely(!tty)) { Loading Loading @@ -870,7 +871,7 @@ static int receive_data(enum port_type index, struct nozomi *dc) } set_bit(index, &dc->flip); tty_kref_put(tty); return 1; } Loading Loading @@ -1276,9 +1277,15 @@ static irqreturn_t interrupt_handler(int irq, void *dev_id) exit_handler: spin_unlock(&dc->spin_mutex); for (a = 0; a < NOZOMI_MAX_PORTS; a++) if (test_and_clear_bit(a, &dc->flip)) tty_flip_buffer_push(dc->port[a].tty); for (a = 0; a < NOZOMI_MAX_PORTS; a++) { struct tty_struct *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; none: spin_unlock(&dc->spin_mutex); Loading Loading @@ -1453,12 +1460,10 @@ static int __devinit nozomi_card_init(struct pci_dev *pdev, for (i = 0; i < MAX_PORT; i++) { mutex_init(&dc->port[i].tty_sem); dc->port[i].tty_open_count = 0; dc->port[i].tty = NULL; tty_port_init(&dc->port[i].port); tty_register_device(ntty_driver, dc->index_start + i, &pdev->dev); } return 0; err_free_sbuf: Loading @@ -1482,14 +1487,16 @@ static void __devexit tty_exit(struct nozomi *dc) flush_scheduled_work(); for (i = 0; i < MAX_PORT; ++i) if (dc->port[i].tty && \ list_empty(&dc->port[i].tty->hangup_work.entry)) tty_hangup(dc->port[i].tty); for (i = 0; i < MAX_PORT; ++i) { struct tty_struct *tty = tty_port_tty_get(&dc->port[i].port); if (tty && list_empty(&tty->hangup_work.entry)) 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) msleep(1); for (i = dc->index_start; i < dc->index_start + MAX_PORT; ++i) tty_unregister_device(ntty_driver, i); } Loading Loading @@ -1579,23 +1586,22 @@ static int ntty_open(struct tty_struct *tty, struct file *file) if (mutex_lock_interruptible(&port->tty_sem)) return -ERESTARTSYS; port->tty_open_count++; port->port.count++; dc->open_ttys++; /* 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->driver_data = port; port->tty = tty; tty_port_tty_set(&port->port, tty); DBG1("open: %d", port->token_dl); spin_lock_irqsave(&dc->spin_mutex, flags); dc->last_ier = dc->last_ier | port->token_dl; writew(dc->last_ier, dc->reg_ier); spin_unlock_irqrestore(&dc->spin_mutex, flags); } mutex_unlock(&port->tty_sem); return 0; } Loading @@ -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) { 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; if (!dc || !port) if (!dc || !nport) return; if (mutex_lock_interruptible(&port->tty_sem)) return; /* Users cannot interrupt a close */ mutex_lock(&nport->tty_sem); if (!port->tty_open_count) goto exit; WARN_ON(!port->count); dc->open_ttys--; port->tty_open_count--; port->count--; tty_port_tty_set(port, NULL); if (port->tty_open_count == 0) { DBG1("close: %d", port->token_dl); if (port->count == 0) { DBG1("close: %d", nport->token_dl); 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); spin_unlock_irqrestore(&dc->spin_mutex, flags); } exit: mutex_unlock(&port->tty_sem); mutex_unlock(&nport->tty_sem); } /* Loading Loading @@ -1660,7 +1665,7 @@ static int ntty_write(struct tty_struct *tty, const unsigned char *buffer, return -EAGAIN; } if (unlikely(!port->tty_open_count)) { if (unlikely(!port->port.count)) { DBG1(" "); goto exit; } Loading Loading @@ -1710,7 +1715,7 @@ static int ntty_write_room(struct tty_struct *tty) if (!mutex_trylock(&port->tty_sem)) return 0; if (!port->tty_open_count) if (!port->port.count) goto exit; room = port->fifo_ul->size - __kfifo_len(port->fifo_ul); Loading Loading @@ -1866,7 +1871,7 @@ static s32 ntty_chars_in_buffer(struct tty_struct *tty) goto exit_in_buffer; } if (unlikely(!port->tty_open_count)) { if (unlikely(!port->port.count)) { dev_err(&dc->pdev->dev, "No tty open?\n"); rval = -ENODEV; goto exit_in_buffer; Loading