diff options
Diffstat (limited to 'drivers/char/mxser.c')
-rw-r--r-- | drivers/char/mxser.c | 109 |
1 files changed, 57 insertions, 52 deletions
diff --git a/drivers/char/mxser.c b/drivers/char/mxser.c index 3fc89da856ae..463df27494bd 100644 --- a/drivers/char/mxser.c +++ b/drivers/char/mxser.c @@ -1700,7 +1700,7 @@ static int mxser_ioctl(struct tty_struct *tty, struct file *file, return 0; } - if (cmd != TIOCGSERIAL && cmd != TIOCMIWAIT && cmd != TIOCGICOUNT && + if (cmd != TIOCGSERIAL && cmd != TIOCMIWAIT && test_bit(TTY_IO_ERROR, &tty->flags)) return -EIO; @@ -1730,32 +1730,6 @@ static int mxser_ioctl(struct tty_struct *tty, struct file *file, return wait_event_interruptible(info->port.delta_msr_wait, mxser_cflags_changed(info, arg, &cnow)); - /* - * Get counter of input serial line interrupts (DCD,RI,DSR,CTS) - * Return: write counters to the user passed counter struct - * NB: both 1->0 and 0->1 transitions are counted except for - * RI where only 0->1 is counted. - */ - case TIOCGICOUNT: { - struct serial_icounter_struct icnt = { 0 }; - spin_lock_irqsave(&info->slock, flags); - cnow = info->icount; - spin_unlock_irqrestore(&info->slock, flags); - - icnt.frame = cnow.frame; - icnt.brk = cnow.brk; - icnt.overrun = cnow.overrun; - icnt.buf_overrun = cnow.buf_overrun; - icnt.parity = cnow.parity; - icnt.rx = cnow.rx; - icnt.tx = cnow.tx; - icnt.cts = cnow.cts; - icnt.dsr = cnow.dsr; - icnt.rng = cnow.rng; - icnt.dcd = cnow.dcd; - - return copy_to_user(argp, &icnt, sizeof(icnt)) ? -EFAULT : 0; - } case MOXA_HighSpeedOn: return put_user(info->baud_base != 115200 ? 1 : 0, (int __user *)argp); case MOXA_SDS_RSTICOUNTER: @@ -1828,6 +1802,39 @@ static int mxser_ioctl(struct tty_struct *tty, struct file *file, return 0; } + /* + * Get counter of input serial line interrupts (DCD,RI,DSR,CTS) + * Return: write counters to the user passed counter struct + * NB: both 1->0 and 0->1 transitions are counted except for + * RI where only 0->1 is counted. + */ + +static int mxser_get_icount(struct tty_struct *tty, + struct serial_icounter_struct *icount) + +{ + struct mxser_port *info = tty->driver_data; + struct async_icount cnow; + unsigned long flags; + + spin_lock_irqsave(&info->slock, flags); + cnow = info->icount; + spin_unlock_irqrestore(&info->slock, flags); + + icount->frame = cnow.frame; + icount->brk = cnow.brk; + icount->overrun = cnow.overrun; + icount->buf_overrun = cnow.buf_overrun; + icount->parity = cnow.parity; + icount->rx = cnow.rx; + icount->tx = cnow.tx; + icount->cts = cnow.cts; + icount->dsr = cnow.dsr; + icount->rng = cnow.rng; + icount->dcd = cnow.dcd; + return 0; +} + static void mxser_stoprx(struct tty_struct *tty) { struct mxser_port *info = tty->driver_data; @@ -2326,6 +2333,7 @@ static const struct tty_operations mxser_ops = { .wait_until_sent = mxser_wait_until_sent, .tiocmget = mxser_tiocmget, .tiocmset = mxser_tiocmset, + .get_icount = mxser_get_icount, }; struct tty_port_operations mxser_port_ops = { @@ -2339,20 +2347,11 @@ struct tty_port_operations mxser_port_ops = { * The MOXA Smartio/Industio serial driver boot-time initialization code! */ -static void mxser_release_res(struct mxser_board *brd, struct pci_dev *pdev, - unsigned int irq) +static void mxser_release_ISA_res(struct mxser_board *brd) { - if (irq) - free_irq(brd->irq, brd); - if (pdev != NULL) { /* PCI */ -#ifdef CONFIG_PCI - pci_release_region(pdev, 2); - pci_release_region(pdev, 3); -#endif - } else { - release_region(brd->ports[0].ioaddr, 8 * brd->info->nports); - release_region(brd->vector, 1); - } + free_irq(brd->irq, brd); + release_region(brd->ports[0].ioaddr, 8 * brd->info->nports); + release_region(brd->vector, 1); } static int __devinit mxser_initbrd(struct mxser_board *brd, @@ -2397,13 +2396,11 @@ static int __devinit mxser_initbrd(struct mxser_board *brd, retval = request_irq(brd->irq, mxser_interrupt, IRQF_SHARED, "mxser", brd); - if (retval) { + if (retval) printk(KERN_ERR "Board %s: Request irq failed, IRQ (%d) may " "conflict with another device.\n", brd->info->name, brd->irq); - /* We hold resources, we need to release them. */ - mxser_release_res(brd, pdev, 0); - } + return retval; } @@ -2555,7 +2552,7 @@ static int __devinit mxser_probe(struct pci_dev *pdev, ioaddress = pci_resource_start(pdev, 2); retval = pci_request_region(pdev, 2, "mxser(IO)"); if (retval) - goto err; + goto err_dis; brd->info = &mxser_cards[ent->driver_data]; for (i = 0; i < brd->info->nports; i++) @@ -2565,7 +2562,7 @@ static int __devinit mxser_probe(struct pci_dev *pdev, ioaddress = pci_resource_start(pdev, 3); retval = pci_request_region(pdev, 3, "mxser(vector)"); if (retval) - goto err_relio; + goto err_zero; brd->vector = ioaddress; /* irq */ @@ -2608,7 +2605,7 @@ static int __devinit mxser_probe(struct pci_dev *pdev, /* mxser_initbrd will hook ISR. */ retval = mxser_initbrd(brd, pdev); if (retval) - goto err_null; + goto err_rel3; for (i = 0; i < brd->info->nports; i++) tty_register_device(mxvar_sdriver, brd->idx + i, &pdev->dev); @@ -2616,10 +2613,13 @@ static int __devinit mxser_probe(struct pci_dev *pdev, pci_set_drvdata(pdev, brd); return 0; -err_relio: - pci_release_region(pdev, 2); -err_null: +err_rel3: + pci_release_region(pdev, 3); +err_zero: brd->info = NULL; + pci_release_region(pdev, 2); +err_dis: + pci_disable_device(pdev); err: return retval; #else @@ -2629,14 +2629,19 @@ err: static void __devexit mxser_remove(struct pci_dev *pdev) { +#ifdef CONFIG_PCI struct mxser_board *brd = pci_get_drvdata(pdev); unsigned int i; for (i = 0; i < brd->info->nports; i++) tty_unregister_device(mxvar_sdriver, brd->idx + i); - mxser_release_res(brd, pdev, 1); + free_irq(pdev->irq, brd); + pci_release_region(pdev, 2); + pci_release_region(pdev, 3); + pci_disable_device(pdev); brd->info = NULL; +#endif } static struct pci_driver mxser_driver = { @@ -2741,7 +2746,7 @@ static void __exit mxser_module_exit(void) for (i = 0; i < MXSER_BOARDS; i++) if (mxser_boards[i].info != NULL) - mxser_release_res(&mxser_boards[i], NULL, 1); + mxser_release_ISA_res(&mxser_boards[i]); } module_init(mxser_module_init); |