diff options
Diffstat (limited to 'drivers/serial/ioc4_serial.c')
-rw-r--r-- | drivers/serial/ioc4_serial.c | 92 |
1 files changed, 44 insertions, 48 deletions
diff --git a/drivers/serial/ioc4_serial.c b/drivers/serial/ioc4_serial.c index 0c5c96a582b3..771676abee60 100644 --- a/drivers/serial/ioc4_serial.c +++ b/drivers/serial/ioc4_serial.c | |||
@@ -308,6 +308,8 @@ struct ioc4_serial { | |||
308 | typedef void ioc4_intr_func_f(void *, uint32_t); | 308 | typedef void ioc4_intr_func_f(void *, uint32_t); |
309 | typedef ioc4_intr_func_f *ioc4_intr_func_t; | 309 | typedef ioc4_intr_func_f *ioc4_intr_func_t; |
310 | 310 | ||
311 | static unsigned int Num_of_ioc4_cards; | ||
312 | |||
311 | /* defining this will get you LOTS of great debug info */ | 313 | /* defining this will get you LOTS of great debug info */ |
312 | //#define DEBUG_INTERRUPTS | 314 | //#define DEBUG_INTERRUPTS |
313 | #define DPRINT_CONFIG(_x...) ; | 315 | #define DPRINT_CONFIG(_x...) ; |
@@ -317,7 +319,8 @@ typedef ioc4_intr_func_f *ioc4_intr_func_t; | |||
317 | #define WAKEUP_CHARS 256 | 319 | #define WAKEUP_CHARS 256 |
318 | 320 | ||
319 | /* number of characters we want to transmit to the lower level at a time */ | 321 | /* number of characters we want to transmit to the lower level at a time */ |
320 | #define IOC4_MAX_CHARS 128 | 322 | #define IOC4_MAX_CHARS 256 |
323 | #define IOC4_FIFO_CHARS 255 | ||
321 | 324 | ||
322 | /* Device name we're using */ | 325 | /* Device name we're using */ |
323 | #define DEVICE_NAME "ttyIOC" | 326 | #define DEVICE_NAME "ttyIOC" |
@@ -973,18 +976,6 @@ static irqreturn_t ioc4_intr(int irq, void *arg, struct pt_regs *regs) | |||
973 | this_ir &= ~this_mir; | 976 | this_ir &= ~this_mir; |
974 | } | 977 | } |
975 | } | 978 | } |
976 | if (this_ir) { | ||
977 | printk(KERN_ERR | ||
978 | "unknown IOC4 %s interrupt 0x%x, sio_ir = 0x%x," | ||
979 | " sio_ies = 0x%x, other_ir = 0x%x :" | ||
980 | "other_ies = 0x%x\n", | ||
981 | (intr_type == IOC4_SIO_INTR_TYPE) ? "sio" : | ||
982 | "other", this_ir, | ||
983 | readl(&soft->is_ioc4_misc_addr->sio_ir.raw), | ||
984 | readl(&soft->is_ioc4_misc_addr->sio_ies.raw), | ||
985 | readl(&soft->is_ioc4_misc_addr->other_ir.raw), | ||
986 | readl(&soft->is_ioc4_misc_addr->other_ies.raw)); | ||
987 | } | ||
988 | } | 979 | } |
989 | #ifdef DEBUG_INTERRUPTS | 980 | #ifdef DEBUG_INTERRUPTS |
990 | { | 981 | { |
@@ -1050,6 +1041,7 @@ static int inline ioc4_attach_local(struct ioc4_driver_data *idd) | |||
1050 | return -ENOMEM; | 1041 | return -ENOMEM; |
1051 | } | 1042 | } |
1052 | memset(port, 0, sizeof(struct ioc4_port)); | 1043 | memset(port, 0, sizeof(struct ioc4_port)); |
1044 | spin_lock_init(&port->ip_lock); | ||
1053 | 1045 | ||
1054 | /* we need to remember the previous ones, to point back to | 1046 | /* we need to remember the previous ones, to point back to |
1055 | * them farther down - setting up the ring buffers. | 1047 | * them farther down - setting up the ring buffers. |
@@ -1703,12 +1695,14 @@ ioc4_change_speed(struct uart_port *the_port, | |||
1703 | baud = 9600; | 1695 | baud = 9600; |
1704 | 1696 | ||
1705 | if (!the_port->fifosize) | 1697 | if (!the_port->fifosize) |
1706 | the_port->fifosize = IOC4_MAX_CHARS; | 1698 | the_port->fifosize = IOC4_FIFO_CHARS; |
1707 | the_port->timeout = ((the_port->fifosize * HZ * bits) / (baud / 10)); | 1699 | the_port->timeout = ((the_port->fifosize * HZ * bits) / (baud / 10)); |
1708 | the_port->timeout += HZ / 50; /* Add .02 seconds of slop */ | 1700 | the_port->timeout += HZ / 50; /* Add .02 seconds of slop */ |
1709 | 1701 | ||
1710 | the_port->ignore_status_mask = N_ALL_INPUT; | 1702 | the_port->ignore_status_mask = N_ALL_INPUT; |
1711 | 1703 | ||
1704 | info->tty->low_latency = 1; | ||
1705 | |||
1712 | if (I_IGNPAR(info->tty)) | 1706 | if (I_IGNPAR(info->tty)) |
1713 | the_port->ignore_status_mask &= ~(N_PARITY_ERROR | 1707 | the_port->ignore_status_mask &= ~(N_PARITY_ERROR |
1714 | | N_FRAMING_ERROR); | 1708 | | N_FRAMING_ERROR); |
@@ -1754,7 +1748,6 @@ ioc4_change_speed(struct uart_port *the_port, | |||
1754 | */ | 1748 | */ |
1755 | static inline int ic4_startup_local(struct uart_port *the_port) | 1749 | static inline int ic4_startup_local(struct uart_port *the_port) |
1756 | { | 1750 | { |
1757 | int retval = 0; | ||
1758 | struct ioc4_port *port; | 1751 | struct ioc4_port *port; |
1759 | struct uart_info *info; | 1752 | struct uart_info *info; |
1760 | 1753 | ||
@@ -1766,9 +1759,6 @@ static inline int ic4_startup_local(struct uart_port *the_port) | |||
1766 | return -1; | 1759 | return -1; |
1767 | 1760 | ||
1768 | info = the_port->info; | 1761 | info = the_port->info; |
1769 | if (info->flags & UIF_INITIALIZED) { | ||
1770 | return retval; | ||
1771 | } | ||
1772 | 1762 | ||
1773 | if (info->tty) { | 1763 | if (info->tty) { |
1774 | set_bit(TTY_IO_ERROR, &info->tty->flags); | 1764 | set_bit(TTY_IO_ERROR, &info->tty->flags); |
@@ -1787,7 +1777,6 @@ static inline int ic4_startup_local(struct uart_port *the_port) | |||
1787 | /* set the speed of the serial port */ | 1777 | /* set the speed of the serial port */ |
1788 | ioc4_change_speed(the_port, info->tty->termios, (struct termios *)0); | 1778 | ioc4_change_speed(the_port, info->tty->termios, (struct termios *)0); |
1789 | 1779 | ||
1790 | info->flags |= UIF_INITIALIZED; | ||
1791 | return 0; | 1780 | return 0; |
1792 | } | 1781 | } |
1793 | 1782 | ||
@@ -1797,9 +1786,13 @@ static inline int ic4_startup_local(struct uart_port *the_port) | |||
1797 | */ | 1786 | */ |
1798 | static void ioc4_cb_output_lowat(struct ioc4_port *port) | 1787 | static void ioc4_cb_output_lowat(struct ioc4_port *port) |
1799 | { | 1788 | { |
1789 | unsigned long pflags; | ||
1790 | |||
1800 | /* ip_lock is set on the call here */ | 1791 | /* ip_lock is set on the call here */ |
1801 | if (port->ip_port) { | 1792 | if (port->ip_port) { |
1793 | spin_lock_irqsave(&port->ip_port->lock, pflags); | ||
1802 | transmit_chars(port->ip_port); | 1794 | transmit_chars(port->ip_port); |
1795 | spin_unlock_irqrestore(&port->ip_port->lock, pflags); | ||
1803 | } | 1796 | } |
1804 | } | 1797 | } |
1805 | 1798 | ||
@@ -2076,8 +2069,7 @@ static inline int do_read(struct uart_port *the_port, unsigned char *buf, | |||
2076 | * available data as long as it returns some. | 2069 | * available data as long as it returns some. |
2077 | */ | 2070 | */ |
2078 | /* Re-arm the timer */ | 2071 | /* Re-arm the timer */ |
2079 | writel(port->ip_rx_cons | IOC4_SRCIR_ARM, | 2072 | writel(port->ip_rx_cons | IOC4_SRCIR_ARM, &port->ip_serial_regs->srcir); |
2080 | &port->ip_serial_regs->srcir); | ||
2081 | 2073 | ||
2082 | prod_ptr = readl(&port->ip_serial_regs->srpir) & PROD_CONS_MASK; | 2074 | prod_ptr = readl(&port->ip_serial_regs->srpir) & PROD_CONS_MASK; |
2083 | cons_ptr = port->ip_rx_cons; | 2075 | cons_ptr = port->ip_rx_cons; |
@@ -2311,6 +2303,7 @@ static inline int do_read(struct uart_port *the_port, unsigned char *buf, | |||
2311 | } | 2303 | } |
2312 | return total; | 2304 | return total; |
2313 | } | 2305 | } |
2306 | |||
2314 | /** | 2307 | /** |
2315 | * receive_chars - upper level read. Called with ip_lock. | 2308 | * receive_chars - upper level read. Called with ip_lock. |
2316 | * @the_port: port to read from | 2309 | * @the_port: port to read from |
@@ -2319,9 +2312,11 @@ static void receive_chars(struct uart_port *the_port) | |||
2319 | { | 2312 | { |
2320 | struct tty_struct *tty; | 2313 | struct tty_struct *tty; |
2321 | unsigned char ch[IOC4_MAX_CHARS]; | 2314 | unsigned char ch[IOC4_MAX_CHARS]; |
2322 | int read_count, request_count; | 2315 | int read_count, request_count = IOC4_MAX_CHARS; |
2323 | struct uart_icount *icount; | 2316 | struct uart_icount *icount; |
2324 | struct uart_info *info = the_port->info; | 2317 | struct uart_info *info = the_port->info; |
2318 | int flip = 0; | ||
2319 | unsigned long pflags; | ||
2325 | 2320 | ||
2326 | /* Make sure all the pointers are "good" ones */ | 2321 | /* Make sure all the pointers are "good" ones */ |
2327 | if (!info) | 2322 | if (!info) |
@@ -2329,16 +2324,17 @@ static void receive_chars(struct uart_port *the_port) | |||
2329 | if (!info->tty) | 2324 | if (!info->tty) |
2330 | return; | 2325 | return; |
2331 | 2326 | ||
2327 | spin_lock_irqsave(&the_port->lock, pflags); | ||
2332 | tty = info->tty; | 2328 | tty = info->tty; |
2333 | 2329 | ||
2334 | request_count = TTY_FLIPBUF_SIZE - tty->flip.count - 1; | 2330 | if (request_count > TTY_FLIPBUF_SIZE - tty->flip.count) |
2331 | request_count = TTY_FLIPBUF_SIZE - tty->flip.count; | ||
2335 | 2332 | ||
2336 | if (request_count > 0) { | 2333 | if (request_count > 0) { |
2337 | if (request_count > IOC4_MAX_CHARS - 2) | ||
2338 | request_count = IOC4_MAX_CHARS - 2; | ||
2339 | icount = &the_port->icount; | 2334 | icount = &the_port->icount; |
2340 | read_count = do_read(the_port, ch, request_count); | 2335 | read_count = do_read(the_port, ch, request_count); |
2341 | if (read_count > 0) { | 2336 | if (read_count > 0) { |
2337 | flip = 1; | ||
2342 | memcpy(tty->flip.char_buf_ptr, ch, read_count); | 2338 | memcpy(tty->flip.char_buf_ptr, ch, read_count); |
2343 | memset(tty->flip.flag_buf_ptr, TTY_NORMAL, read_count); | 2339 | memset(tty->flip.flag_buf_ptr, TTY_NORMAL, read_count); |
2344 | tty->flip.char_buf_ptr += read_count; | 2340 | tty->flip.char_buf_ptr += read_count; |
@@ -2347,7 +2343,11 @@ static void receive_chars(struct uart_port *the_port) | |||
2347 | icount->rx += read_count; | 2343 | icount->rx += read_count; |
2348 | } | 2344 | } |
2349 | } | 2345 | } |
2350 | tty_flip_buffer_push(tty); | 2346 | |
2347 | spin_unlock_irqrestore(&the_port->lock, pflags); | ||
2348 | |||
2349 | if (flip) | ||
2350 | tty_flip_buffer_push(tty); | ||
2351 | } | 2351 | } |
2352 | 2352 | ||
2353 | /** | 2353 | /** |
@@ -2405,18 +2405,14 @@ static void ic4_shutdown(struct uart_port *the_port) | |||
2405 | 2405 | ||
2406 | info = the_port->info; | 2406 | info = the_port->info; |
2407 | 2407 | ||
2408 | if (!(info->flags & UIF_INITIALIZED)) | ||
2409 | return; | ||
2410 | |||
2411 | wake_up_interruptible(&info->delta_msr_wait); | 2408 | wake_up_interruptible(&info->delta_msr_wait); |
2412 | 2409 | ||
2413 | if (info->tty) | 2410 | if (info->tty) |
2414 | set_bit(TTY_IO_ERROR, &info->tty->flags); | 2411 | set_bit(TTY_IO_ERROR, &info->tty->flags); |
2415 | 2412 | ||
2416 | spin_lock_irqsave(&port->ip_lock, port_flags); | 2413 | spin_lock_irqsave(&the_port->lock, port_flags); |
2417 | set_notification(port, N_ALL, 0); | 2414 | set_notification(port, N_ALL, 0); |
2418 | info->flags &= ~UIF_INITIALIZED; | 2415 | spin_unlock_irqrestore(&the_port->lock, port_flags); |
2419 | spin_unlock_irqrestore(&port->ip_lock, port_flags); | ||
2420 | } | 2416 | } |
2421 | 2417 | ||
2422 | /** | 2418 | /** |
@@ -2475,12 +2471,10 @@ static unsigned int ic4_get_mctrl(struct uart_port *the_port) | |||
2475 | static void ic4_start_tx(struct uart_port *the_port) | 2471 | static void ic4_start_tx(struct uart_port *the_port) |
2476 | { | 2472 | { |
2477 | struct ioc4_port *port = get_ioc4_port(the_port); | 2473 | struct ioc4_port *port = get_ioc4_port(the_port); |
2478 | unsigned long flags; | ||
2479 | 2474 | ||
2480 | if (port) { | 2475 | if (port) { |
2481 | spin_lock_irqsave(&port->ip_lock, flags); | 2476 | set_notification(port, N_OUTPUT_LOWAT, 1); |
2482 | transmit_chars(the_port); | 2477 | enable_intrs(port, port->ip_hooks->intr_tx_mt); |
2483 | spin_unlock_irqrestore(&port->ip_lock, flags); | ||
2484 | } | 2478 | } |
2485 | } | 2479 | } |
2486 | 2480 | ||
@@ -2522,9 +2516,9 @@ static int ic4_startup(struct uart_port *the_port) | |||
2522 | } | 2516 | } |
2523 | 2517 | ||
2524 | /* Start up the serial port */ | 2518 | /* Start up the serial port */ |
2525 | spin_lock_irqsave(&port->ip_lock, port_flags); | 2519 | spin_lock_irqsave(&the_port->lock, port_flags); |
2526 | retval = ic4_startup_local(the_port); | 2520 | retval = ic4_startup_local(the_port); |
2527 | spin_unlock_irqrestore(&port->ip_lock, port_flags); | 2521 | spin_unlock_irqrestore(&the_port->lock, port_flags); |
2528 | return retval; | 2522 | return retval; |
2529 | } | 2523 | } |
2530 | 2524 | ||
@@ -2539,12 +2533,11 @@ static void | |||
2539 | ic4_set_termios(struct uart_port *the_port, | 2533 | ic4_set_termios(struct uart_port *the_port, |
2540 | struct termios *termios, struct termios *old_termios) | 2534 | struct termios *termios, struct termios *old_termios) |
2541 | { | 2535 | { |
2542 | struct ioc4_port *port = get_ioc4_port(the_port); | ||
2543 | unsigned long port_flags; | 2536 | unsigned long port_flags; |
2544 | 2537 | ||
2545 | spin_lock_irqsave(&port->ip_lock, port_flags); | 2538 | spin_lock_irqsave(&the_port->lock, port_flags); |
2546 | ioc4_change_speed(the_port, termios, old_termios); | 2539 | ioc4_change_speed(the_port, termios, old_termios); |
2547 | spin_unlock_irqrestore(&port->ip_lock, port_flags); | 2540 | spin_unlock_irqrestore(&the_port->lock, port_flags); |
2548 | } | 2541 | } |
2549 | 2542 | ||
2550 | /** | 2543 | /** |
@@ -2619,24 +2612,25 @@ ioc4_serial_core_attach(struct pci_dev *pdev) | |||
2619 | __FUNCTION__, (void *)the_port, | 2612 | __FUNCTION__, (void *)the_port, |
2620 | (void *)port)); | 2613 | (void *)port)); |
2621 | 2614 | ||
2622 | spin_lock_init(&the_port->lock); | ||
2623 | /* membase, iobase and mapbase just need to be non-0 */ | 2615 | /* membase, iobase and mapbase just need to be non-0 */ |
2624 | the_port->membase = (unsigned char __iomem *)1; | 2616 | the_port->membase = (unsigned char __iomem *)1; |
2625 | the_port->line = the_port->iobase = ii; | 2617 | the_port->iobase = (pdev->bus->number << 16) | ii; |
2618 | the_port->line = (Num_of_ioc4_cards << 2) | ii; | ||
2626 | the_port->mapbase = 1; | 2619 | the_port->mapbase = 1; |
2627 | the_port->type = PORT_16550A; | 2620 | the_port->type = PORT_16550A; |
2628 | the_port->fifosize = IOC4_MAX_CHARS; | 2621 | the_port->fifosize = IOC4_FIFO_CHARS; |
2629 | the_port->ops = &ioc4_ops; | 2622 | the_port->ops = &ioc4_ops; |
2630 | the_port->irq = control->ic_irq; | 2623 | the_port->irq = control->ic_irq; |
2631 | the_port->dev = &pdev->dev; | 2624 | the_port->dev = &pdev->dev; |
2625 | spin_lock_init(&the_port->lock); | ||
2632 | if (uart_add_one_port(&ioc4_uart, the_port) < 0) { | 2626 | if (uart_add_one_port(&ioc4_uart, the_port) < 0) { |
2633 | printk(KERN_WARNING | 2627 | printk(KERN_WARNING |
2634 | "%s: unable to add port %d\n", | 2628 | "%s: unable to add port %d bus %d\n", |
2635 | __FUNCTION__, the_port->line); | 2629 | __FUNCTION__, the_port->line, pdev->bus->number); |
2636 | } else { | 2630 | } else { |
2637 | DPRINT_CONFIG( | 2631 | DPRINT_CONFIG( |
2638 | ("IOC4 serial driver port %d irq = %d\n", | 2632 | ("IOC4 serial port %d irq = %d, bus %d\n", |
2639 | the_port->line, the_port->irq)); | 2633 | the_port->line, the_port->irq, pdev->bus->number)); |
2640 | } | 2634 | } |
2641 | /* all ports are rs232 for now */ | 2635 | /* all ports are rs232 for now */ |
2642 | ioc4_set_proto(port, PROTO_RS232); | 2636 | ioc4_set_proto(port, PROTO_RS232); |
@@ -2746,6 +2740,8 @@ ioc4_serial_attach_one(struct ioc4_driver_data *idd) | |||
2746 | if ((ret = ioc4_serial_core_attach(idd->idd_pdev))) | 2740 | if ((ret = ioc4_serial_core_attach(idd->idd_pdev))) |
2747 | goto out4; | 2741 | goto out4; |
2748 | 2742 | ||
2743 | Num_of_ioc4_cards++; | ||
2744 | |||
2749 | return ret; | 2745 | return ret; |
2750 | 2746 | ||
2751 | /* error exits that give back resources */ | 2747 | /* error exits that give back resources */ |