diff options
Diffstat (limited to 'drivers/char/stallion.c')
| -rw-r--r-- | drivers/char/stallion.c | 129 |
1 files changed, 42 insertions, 87 deletions
diff --git a/drivers/char/stallion.c b/drivers/char/stallion.c index db6dcfa35ba0..0e511d61f544 100644 --- a/drivers/char/stallion.c +++ b/drivers/char/stallion.c | |||
| @@ -407,7 +407,7 @@ static unsigned int stl_baudrates[] = { | |||
| 407 | * Declare all those functions in this driver! | 407 | * Declare all those functions in this driver! |
| 408 | */ | 408 | */ |
| 409 | 409 | ||
| 410 | static int stl_memioctl(struct inode *ip, struct file *fp, unsigned int cmd, unsigned long arg); | 410 | static long stl_memioctl(struct file *fp, unsigned int cmd, unsigned long arg); |
| 411 | static int stl_brdinit(struct stlbrd *brdp); | 411 | static int stl_brdinit(struct stlbrd *brdp); |
| 412 | static int stl_getportstats(struct tty_struct *tty, struct stlport *portp, comstats_t __user *cp); | 412 | static int stl_getportstats(struct tty_struct *tty, struct stlport *portp, comstats_t __user *cp); |
| 413 | static int stl_clrportstats(struct stlport *portp, comstats_t __user *cp); | 413 | static int stl_clrportstats(struct stlport *portp, comstats_t __user *cp); |
| @@ -607,7 +607,7 @@ static unsigned int sc26198_baudtable[] = { | |||
| 607 | */ | 607 | */ |
| 608 | static const struct file_operations stl_fsiomem = { | 608 | static const struct file_operations stl_fsiomem = { |
| 609 | .owner = THIS_MODULE, | 609 | .owner = THIS_MODULE, |
| 610 | .ioctl = stl_memioctl, | 610 | .unlocked_ioctl = stl_memioctl, |
| 611 | }; | 611 | }; |
| 612 | 612 | ||
| 613 | static struct class *stallion_class; | 613 | static struct class *stallion_class; |
| @@ -702,6 +702,24 @@ static struct stlbrd *stl_allocbrd(void) | |||
| 702 | 702 | ||
| 703 | /*****************************************************************************/ | 703 | /*****************************************************************************/ |
| 704 | 704 | ||
| 705 | static int stl_activate(struct tty_port *port, struct tty_struct *tty) | ||
| 706 | { | ||
| 707 | struct stlport *portp = container_of(port, struct stlport, port); | ||
| 708 | if (!portp->tx.buf) { | ||
| 709 | portp->tx.buf = kmalloc(STL_TXBUFSIZE, GFP_KERNEL); | ||
| 710 | if (!portp->tx.buf) | ||
| 711 | return -ENOMEM; | ||
| 712 | portp->tx.head = portp->tx.buf; | ||
| 713 | portp->tx.tail = portp->tx.buf; | ||
| 714 | } | ||
| 715 | stl_setport(portp, tty->termios); | ||
| 716 | portp->sigs = stl_getsignals(portp); | ||
| 717 | stl_setsignals(portp, 1, 1); | ||
| 718 | stl_enablerxtx(portp, 1, 1); | ||
| 719 | stl_startrxtx(portp, 1, 0); | ||
| 720 | return 0; | ||
| 721 | } | ||
| 722 | |||
| 705 | static int stl_open(struct tty_struct *tty, struct file *filp) | 723 | static int stl_open(struct tty_struct *tty, struct file *filp) |
| 706 | { | 724 | { |
| 707 | struct stlport *portp; | 725 | struct stlport *portp; |
| @@ -737,32 +755,8 @@ static int stl_open(struct tty_struct *tty, struct file *filp) | |||
| 737 | if (portp == NULL) | 755 | if (portp == NULL) |
| 738 | return -ENODEV; | 756 | return -ENODEV; |
| 739 | port = &portp->port; | 757 | port = &portp->port; |
| 758 | return tty_port_open(&portp->port, tty, filp); | ||
| 740 | 759 | ||
| 741 | /* | ||
| 742 | * On the first open of the device setup the port hardware, and | ||
| 743 | * initialize the per port data structure. | ||
| 744 | */ | ||
| 745 | tty_port_tty_set(port, tty); | ||
| 746 | tty->driver_data = portp; | ||
| 747 | port->count++; | ||
| 748 | |||
| 749 | if ((port->flags & ASYNC_INITIALIZED) == 0) { | ||
| 750 | if (!portp->tx.buf) { | ||
| 751 | portp->tx.buf = kmalloc(STL_TXBUFSIZE, GFP_KERNEL); | ||
| 752 | if (!portp->tx.buf) | ||
| 753 | return -ENOMEM; | ||
| 754 | portp->tx.head = portp->tx.buf; | ||
| 755 | portp->tx.tail = portp->tx.buf; | ||
| 756 | } | ||
| 757 | stl_setport(portp, tty->termios); | ||
| 758 | portp->sigs = stl_getsignals(portp); | ||
| 759 | stl_setsignals(portp, 1, 1); | ||
| 760 | stl_enablerxtx(portp, 1, 1); | ||
| 761 | stl_startrxtx(portp, 1, 0); | ||
| 762 | clear_bit(TTY_IO_ERROR, &tty->flags); | ||
| 763 | port->flags |= ASYNC_INITIALIZED; | ||
| 764 | } | ||
| 765 | return tty_port_block_til_ready(port, tty, filp); | ||
| 766 | } | 760 | } |
| 767 | 761 | ||
| 768 | /*****************************************************************************/ | 762 | /*****************************************************************************/ |
| @@ -826,38 +820,12 @@ static void stl_waituntilsent(struct tty_struct *tty, int timeout) | |||
| 826 | 820 | ||
| 827 | /*****************************************************************************/ | 821 | /*****************************************************************************/ |
| 828 | 822 | ||
| 829 | static void stl_close(struct tty_struct *tty, struct file *filp) | 823 | static void stl_shutdown(struct tty_port *port) |
| 830 | { | 824 | { |
| 831 | struct stlport *portp; | 825 | struct stlport *portp = container_of(port, struct stlport, port); |
| 832 | struct tty_port *port; | ||
| 833 | unsigned long flags; | ||
| 834 | |||
| 835 | pr_debug("stl_close(tty=%p,filp=%p)\n", tty, filp); | ||
| 836 | |||
| 837 | portp = tty->driver_data; | ||
| 838 | BUG_ON(portp == NULL); | ||
| 839 | |||
| 840 | port = &portp->port; | ||
| 841 | |||
| 842 | if (tty_port_close_start(port, tty, filp) == 0) | ||
| 843 | return; | ||
| 844 | /* | ||
| 845 | * May want to wait for any data to drain before closing. The BUSY | ||
| 846 | * flag keeps track of whether we are still sending or not - it is | ||
| 847 | * very accurate for the cd1400, not quite so for the sc26198. | ||
| 848 | * (The sc26198 has no "end-of-data" interrupt only empty FIFO) | ||
| 849 | */ | ||
| 850 | stl_waituntilsent(tty, (HZ / 2)); | ||
| 851 | |||
| 852 | spin_lock_irqsave(&port->lock, flags); | ||
| 853 | portp->port.flags &= ~ASYNC_INITIALIZED; | ||
| 854 | spin_unlock_irqrestore(&port->lock, flags); | ||
| 855 | |||
| 856 | stl_disableintrs(portp); | 826 | stl_disableintrs(portp); |
| 857 | if (tty->termios->c_cflag & HUPCL) | ||
| 858 | stl_setsignals(portp, 0, 0); | ||
| 859 | stl_enablerxtx(portp, 0, 0); | 827 | stl_enablerxtx(portp, 0, 0); |
| 860 | stl_flushbuffer(tty); | 828 | stl_flush(portp); |
| 861 | portp->istate = 0; | 829 | portp->istate = 0; |
| 862 | if (portp->tx.buf != NULL) { | 830 | if (portp->tx.buf != NULL) { |
| 863 | kfree(portp->tx.buf); | 831 | kfree(portp->tx.buf); |
| @@ -865,9 +833,16 @@ static void stl_close(struct tty_struct *tty, struct file *filp) | |||
| 865 | portp->tx.head = NULL; | 833 | portp->tx.head = NULL; |
| 866 | portp->tx.tail = NULL; | 834 | portp->tx.tail = NULL; |
| 867 | } | 835 | } |
| 836 | } | ||
| 837 | |||
| 838 | static void stl_close(struct tty_struct *tty, struct file *filp) | ||
| 839 | { | ||
| 840 | struct stlport*portp; | ||
| 841 | pr_debug("stl_close(tty=%p,filp=%p)\n", tty, filp); | ||
| 868 | 842 | ||
| 869 | tty_port_close_end(port, tty); | 843 | portp = tty->driver_data; |
| 870 | tty_port_tty_set(port, NULL); | 844 | BUG_ON(portp == NULL); |
| 845 | tty_port_close(&portp->port, tty, filp); | ||
| 871 | } | 846 | } |
| 872 | 847 | ||
| 873 | /*****************************************************************************/ | 848 | /*****************************************************************************/ |
| @@ -1314,35 +1289,12 @@ static void stl_stop(struct tty_struct *tty) | |||
| 1314 | 1289 | ||
| 1315 | static void stl_hangup(struct tty_struct *tty) | 1290 | static void stl_hangup(struct tty_struct *tty) |
| 1316 | { | 1291 | { |
| 1317 | struct stlport *portp; | 1292 | struct stlport *portp = tty->driver_data; |
| 1318 | struct tty_port *port; | ||
| 1319 | unsigned long flags; | ||
| 1320 | |||
| 1321 | pr_debug("stl_hangup(tty=%p)\n", tty); | 1293 | pr_debug("stl_hangup(tty=%p)\n", tty); |
| 1322 | 1294 | ||
| 1323 | portp = tty->driver_data; | ||
| 1324 | if (portp == NULL) | 1295 | if (portp == NULL) |
| 1325 | return; | 1296 | return; |
| 1326 | port = &portp->port; | 1297 | tty_port_hangup(&portp->port); |
| 1327 | |||
| 1328 | spin_lock_irqsave(&port->lock, flags); | ||
| 1329 | port->flags &= ~ASYNC_INITIALIZED; | ||
| 1330 | spin_unlock_irqrestore(&port->lock, flags); | ||
| 1331 | |||
| 1332 | stl_disableintrs(portp); | ||
| 1333 | if (tty->termios->c_cflag & HUPCL) | ||
| 1334 | stl_setsignals(portp, 0, 0); | ||
| 1335 | stl_enablerxtx(portp, 0, 0); | ||
| 1336 | stl_flushbuffer(tty); | ||
| 1337 | portp->istate = 0; | ||
| 1338 | set_bit(TTY_IO_ERROR, &tty->flags); | ||
| 1339 | if (portp->tx.buf != NULL) { | ||
| 1340 | kfree(portp->tx.buf); | ||
| 1341 | portp->tx.buf = NULL; | ||
| 1342 | portp->tx.head = NULL; | ||
| 1343 | portp->tx.tail = NULL; | ||
| 1344 | } | ||
| 1345 | tty_port_hangup(port); | ||
| 1346 | } | 1298 | } |
| 1347 | 1299 | ||
| 1348 | /*****************************************************************************/ | 1300 | /*****************************************************************************/ |
| @@ -2486,18 +2438,19 @@ static int stl_getbrdstruct(struct stlbrd __user *arg) | |||
| 2486 | * collection. | 2438 | * collection. |
| 2487 | */ | 2439 | */ |
| 2488 | 2440 | ||
| 2489 | static int stl_memioctl(struct inode *ip, struct file *fp, unsigned int cmd, unsigned long arg) | 2441 | static long stl_memioctl(struct file *fp, unsigned int cmd, unsigned long arg) |
| 2490 | { | 2442 | { |
| 2491 | int brdnr, rc; | 2443 | int brdnr, rc; |
| 2492 | void __user *argp = (void __user *)arg; | 2444 | void __user *argp = (void __user *)arg; |
| 2493 | 2445 | ||
| 2494 | pr_debug("stl_memioctl(ip=%p,fp=%p,cmd=%x,arg=%lx)\n", ip, fp, cmd,arg); | 2446 | pr_debug("stl_memioctl(fp=%p,cmd=%x,arg=%lx)\n", fp, cmd,arg); |
| 2495 | 2447 | ||
| 2496 | brdnr = iminor(ip); | 2448 | brdnr = iminor(fp->f_dentry->d_inode); |
| 2497 | if (brdnr >= STL_MAXBRDS) | 2449 | if (brdnr >= STL_MAXBRDS) |
| 2498 | return -ENODEV; | 2450 | return -ENODEV; |
| 2499 | rc = 0; | 2451 | rc = 0; |
| 2500 | 2452 | ||
| 2453 | lock_kernel(); | ||
| 2501 | switch (cmd) { | 2454 | switch (cmd) { |
| 2502 | case COM_GETPORTSTATS: | 2455 | case COM_GETPORTSTATS: |
| 2503 | rc = stl_getportstats(NULL, NULL, argp); | 2456 | rc = stl_getportstats(NULL, NULL, argp); |
| @@ -2518,7 +2471,7 @@ static int stl_memioctl(struct inode *ip, struct file *fp, unsigned int cmd, uns | |||
| 2518 | rc = -ENOIOCTLCMD; | 2471 | rc = -ENOIOCTLCMD; |
| 2519 | break; | 2472 | break; |
| 2520 | } | 2473 | } |
| 2521 | 2474 | unlock_kernel(); | |
| 2522 | return rc; | 2475 | return rc; |
| 2523 | } | 2476 | } |
| 2524 | 2477 | ||
| @@ -2549,6 +2502,8 @@ static const struct tty_operations stl_ops = { | |||
| 2549 | static const struct tty_port_operations stl_port_ops = { | 2502 | static const struct tty_port_operations stl_port_ops = { |
| 2550 | .carrier_raised = stl_carrier_raised, | 2503 | .carrier_raised = stl_carrier_raised, |
| 2551 | .dtr_rts = stl_dtr_rts, | 2504 | .dtr_rts = stl_dtr_rts, |
| 2505 | .activate = stl_activate, | ||
| 2506 | .shutdown = stl_shutdown, | ||
| 2552 | }; | 2507 | }; |
| 2553 | 2508 | ||
| 2554 | /*****************************************************************************/ | 2509 | /*****************************************************************************/ |
