diff options
Diffstat (limited to 'drivers/serial/ioc4_serial.c')
-rw-r--r-- | drivers/serial/ioc4_serial.c | 80 |
1 files changed, 44 insertions, 36 deletions
diff --git a/drivers/serial/ioc4_serial.c b/drivers/serial/ioc4_serial.c index f88fdd480685..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" |
@@ -1038,6 +1041,7 @@ static int inline ioc4_attach_local(struct ioc4_driver_data *idd) | |||
1038 | return -ENOMEM; | 1041 | return -ENOMEM; |
1039 | } | 1042 | } |
1040 | memset(port, 0, sizeof(struct ioc4_port)); | 1043 | memset(port, 0, sizeof(struct ioc4_port)); |
1044 | spin_lock_init(&port->ip_lock); | ||
1041 | 1045 | ||
1042 | /* we need to remember the previous ones, to point back to | 1046 | /* we need to remember the previous ones, to point back to |
1043 | * them farther down - setting up the ring buffers. | 1047 | * them farther down - setting up the ring buffers. |
@@ -1691,12 +1695,14 @@ ioc4_change_speed(struct uart_port *the_port, | |||
1691 | baud = 9600; | 1695 | baud = 9600; |
1692 | 1696 | ||
1693 | if (!the_port->fifosize) | 1697 | if (!the_port->fifosize) |
1694 | the_port->fifosize = IOC4_MAX_CHARS; | 1698 | the_port->fifosize = IOC4_FIFO_CHARS; |
1695 | the_port->timeout = ((the_port->fifosize * HZ * bits) / (baud / 10)); | 1699 | the_port->timeout = ((the_port->fifosize * HZ * bits) / (baud / 10)); |
1696 | the_port->timeout += HZ / 50; /* Add .02 seconds of slop */ | 1700 | the_port->timeout += HZ / 50; /* Add .02 seconds of slop */ |
1697 | 1701 | ||
1698 | the_port->ignore_status_mask = N_ALL_INPUT; | 1702 | the_port->ignore_status_mask = N_ALL_INPUT; |
1699 | 1703 | ||
1704 | info->tty->low_latency = 1; | ||
1705 | |||
1700 | if (I_IGNPAR(info->tty)) | 1706 | if (I_IGNPAR(info->tty)) |
1701 | the_port->ignore_status_mask &= ~(N_PARITY_ERROR | 1707 | the_port->ignore_status_mask &= ~(N_PARITY_ERROR |
1702 | | N_FRAMING_ERROR); | 1708 | | N_FRAMING_ERROR); |
@@ -1742,7 +1748,6 @@ ioc4_change_speed(struct uart_port *the_port, | |||
1742 | */ | 1748 | */ |
1743 | static inline int ic4_startup_local(struct uart_port *the_port) | 1749 | static inline int ic4_startup_local(struct uart_port *the_port) |
1744 | { | 1750 | { |
1745 | int retval = 0; | ||
1746 | struct ioc4_port *port; | 1751 | struct ioc4_port *port; |
1747 | struct uart_info *info; | 1752 | struct uart_info *info; |
1748 | 1753 | ||
@@ -1754,9 +1759,6 @@ static inline int ic4_startup_local(struct uart_port *the_port) | |||
1754 | return -1; | 1759 | return -1; |
1755 | 1760 | ||
1756 | info = the_port->info; | 1761 | info = the_port->info; |
1757 | if (info->flags & UIF_INITIALIZED) { | ||
1758 | return retval; | ||
1759 | } | ||
1760 | 1762 | ||
1761 | if (info->tty) { | 1763 | if (info->tty) { |
1762 | set_bit(TTY_IO_ERROR, &info->tty->flags); | 1764 | set_bit(TTY_IO_ERROR, &info->tty->flags); |
@@ -1775,7 +1777,6 @@ static inline int ic4_startup_local(struct uart_port *the_port) | |||
1775 | /* set the speed of the serial port */ | 1777 | /* set the speed of the serial port */ |
1776 | ioc4_change_speed(the_port, info->tty->termios, (struct termios *)0); | 1778 | ioc4_change_speed(the_port, info->tty->termios, (struct termios *)0); |
1777 | 1779 | ||
1778 | info->flags |= UIF_INITIALIZED; | ||
1779 | return 0; | 1780 | return 0; |
1780 | } | 1781 | } |
1781 | 1782 | ||
@@ -1785,9 +1786,13 @@ static inline int ic4_startup_local(struct uart_port *the_port) | |||
1785 | */ | 1786 | */ |
1786 | static void ioc4_cb_output_lowat(struct ioc4_port *port) | 1787 | static void ioc4_cb_output_lowat(struct ioc4_port *port) |
1787 | { | 1788 | { |
1789 | unsigned long pflags; | ||
1790 | |||
1788 | /* ip_lock is set on the call here */ | 1791 | /* ip_lock is set on the call here */ |
1789 | if (port->ip_port) { | 1792 | if (port->ip_port) { |
1793 | spin_lock_irqsave(&port->ip_port->lock, pflags); | ||
1790 | transmit_chars(port->ip_port); | 1794 | transmit_chars(port->ip_port); |
1795 | spin_unlock_irqrestore(&port->ip_port->lock, pflags); | ||
1791 | } | 1796 | } |
1792 | } | 1797 | } |
1793 | 1798 | ||
@@ -2064,8 +2069,7 @@ static inline int do_read(struct uart_port *the_port, unsigned char *buf, | |||
2064 | * available data as long as it returns some. | 2069 | * available data as long as it returns some. |
2065 | */ | 2070 | */ |
2066 | /* Re-arm the timer */ | 2071 | /* Re-arm the timer */ |
2067 | writel(port->ip_rx_cons | IOC4_SRCIR_ARM, | 2072 | writel(port->ip_rx_cons | IOC4_SRCIR_ARM, &port->ip_serial_regs->srcir); |
2068 | &port->ip_serial_regs->srcir); | ||
2069 | 2073 | ||
2070 | prod_ptr = readl(&port->ip_serial_regs->srpir) & PROD_CONS_MASK; | 2074 | prod_ptr = readl(&port->ip_serial_regs->srpir) & PROD_CONS_MASK; |
2071 | cons_ptr = port->ip_rx_cons; | 2075 | cons_ptr = port->ip_rx_cons; |
@@ -2299,6 +2303,7 @@ static inline int do_read(struct uart_port *the_port, unsigned char *buf, | |||
2299 | } | 2303 | } |
2300 | return total; | 2304 | return total; |
2301 | } | 2305 | } |
2306 | |||
2302 | /** | 2307 | /** |
2303 | * receive_chars - upper level read. Called with ip_lock. | 2308 | * receive_chars - upper level read. Called with ip_lock. |
2304 | * @the_port: port to read from | 2309 | * @the_port: port to read from |
@@ -2307,9 +2312,11 @@ static void receive_chars(struct uart_port *the_port) | |||
2307 | { | 2312 | { |
2308 | struct tty_struct *tty; | 2313 | struct tty_struct *tty; |
2309 | unsigned char ch[IOC4_MAX_CHARS]; | 2314 | unsigned char ch[IOC4_MAX_CHARS]; |
2310 | int read_count, request_count; | 2315 | int read_count, request_count = IOC4_MAX_CHARS; |
2311 | struct uart_icount *icount; | 2316 | struct uart_icount *icount; |
2312 | struct uart_info *info = the_port->info; | 2317 | struct uart_info *info = the_port->info; |
2318 | int flip = 0; | ||
2319 | unsigned long pflags; | ||
2313 | 2320 | ||
2314 | /* Make sure all the pointers are "good" ones */ | 2321 | /* Make sure all the pointers are "good" ones */ |
2315 | if (!info) | 2322 | if (!info) |
@@ -2317,16 +2324,17 @@ static void receive_chars(struct uart_port *the_port) | |||
2317 | if (!info->tty) | 2324 | if (!info->tty) |
2318 | return; | 2325 | return; |
2319 | 2326 | ||
2327 | spin_lock_irqsave(&the_port->lock, pflags); | ||
2320 | tty = info->tty; | 2328 | tty = info->tty; |
2321 | 2329 | ||
2322 | 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; | ||
2323 | 2332 | ||
2324 | if (request_count > 0) { | 2333 | if (request_count > 0) { |
2325 | if (request_count > IOC4_MAX_CHARS - 2) | ||
2326 | request_count = IOC4_MAX_CHARS - 2; | ||
2327 | icount = &the_port->icount; | 2334 | icount = &the_port->icount; |
2328 | read_count = do_read(the_port, ch, request_count); | 2335 | read_count = do_read(the_port, ch, request_count); |
2329 | if (read_count > 0) { | 2336 | if (read_count > 0) { |
2337 | flip = 1; | ||
2330 | memcpy(tty->flip.char_buf_ptr, ch, read_count); | 2338 | memcpy(tty->flip.char_buf_ptr, ch, read_count); |
2331 | memset(tty->flip.flag_buf_ptr, TTY_NORMAL, read_count); | 2339 | memset(tty->flip.flag_buf_ptr, TTY_NORMAL, read_count); |
2332 | tty->flip.char_buf_ptr += read_count; | 2340 | tty->flip.char_buf_ptr += read_count; |
@@ -2335,7 +2343,11 @@ static void receive_chars(struct uart_port *the_port) | |||
2335 | icount->rx += read_count; | 2343 | icount->rx += read_count; |
2336 | } | 2344 | } |
2337 | } | 2345 | } |
2338 | tty_flip_buffer_push(tty); | 2346 | |
2347 | spin_unlock_irqrestore(&the_port->lock, pflags); | ||
2348 | |||
2349 | if (flip) | ||
2350 | tty_flip_buffer_push(tty); | ||
2339 | } | 2351 | } |
2340 | 2352 | ||
2341 | /** | 2353 | /** |
@@ -2393,18 +2405,14 @@ static void ic4_shutdown(struct uart_port *the_port) | |||
2393 | 2405 | ||
2394 | info = the_port->info; | 2406 | info = the_port->info; |
2395 | 2407 | ||
2396 | if (!(info->flags & UIF_INITIALIZED)) | ||
2397 | return; | ||
2398 | |||
2399 | wake_up_interruptible(&info->delta_msr_wait); | 2408 | wake_up_interruptible(&info->delta_msr_wait); |
2400 | 2409 | ||
2401 | if (info->tty) | 2410 | if (info->tty) |
2402 | set_bit(TTY_IO_ERROR, &info->tty->flags); | 2411 | set_bit(TTY_IO_ERROR, &info->tty->flags); |
2403 | 2412 | ||
2404 | spin_lock_irqsave(&port->ip_lock, port_flags); | 2413 | spin_lock_irqsave(&the_port->lock, port_flags); |
2405 | set_notification(port, N_ALL, 0); | 2414 | set_notification(port, N_ALL, 0); |
2406 | info->flags &= ~UIF_INITIALIZED; | 2415 | spin_unlock_irqrestore(&the_port->lock, port_flags); |
2407 | spin_unlock_irqrestore(&port->ip_lock, port_flags); | ||
2408 | } | 2416 | } |
2409 | 2417 | ||
2410 | /** | 2418 | /** |
@@ -2463,12 +2471,10 @@ static unsigned int ic4_get_mctrl(struct uart_port *the_port) | |||
2463 | static void ic4_start_tx(struct uart_port *the_port) | 2471 | static void ic4_start_tx(struct uart_port *the_port) |
2464 | { | 2472 | { |
2465 | struct ioc4_port *port = get_ioc4_port(the_port); | 2473 | struct ioc4_port *port = get_ioc4_port(the_port); |
2466 | unsigned long flags; | ||
2467 | 2474 | ||
2468 | if (port) { | 2475 | if (port) { |
2469 | spin_lock_irqsave(&port->ip_lock, flags); | 2476 | set_notification(port, N_OUTPUT_LOWAT, 1); |
2470 | transmit_chars(the_port); | 2477 | enable_intrs(port, port->ip_hooks->intr_tx_mt); |
2471 | spin_unlock_irqrestore(&port->ip_lock, flags); | ||
2472 | } | 2478 | } |
2473 | } | 2479 | } |
2474 | 2480 | ||
@@ -2510,9 +2516,9 @@ static int ic4_startup(struct uart_port *the_port) | |||
2510 | } | 2516 | } |
2511 | 2517 | ||
2512 | /* Start up the serial port */ | 2518 | /* Start up the serial port */ |
2513 | spin_lock_irqsave(&port->ip_lock, port_flags); | 2519 | spin_lock_irqsave(&the_port->lock, port_flags); |
2514 | retval = ic4_startup_local(the_port); | 2520 | retval = ic4_startup_local(the_port); |
2515 | spin_unlock_irqrestore(&port->ip_lock, port_flags); | 2521 | spin_unlock_irqrestore(&the_port->lock, port_flags); |
2516 | return retval; | 2522 | return retval; |
2517 | } | 2523 | } |
2518 | 2524 | ||
@@ -2527,12 +2533,11 @@ static void | |||
2527 | ic4_set_termios(struct uart_port *the_port, | 2533 | ic4_set_termios(struct uart_port *the_port, |
2528 | struct termios *termios, struct termios *old_termios) | 2534 | struct termios *termios, struct termios *old_termios) |
2529 | { | 2535 | { |
2530 | struct ioc4_port *port = get_ioc4_port(the_port); | ||
2531 | unsigned long port_flags; | 2536 | unsigned long port_flags; |
2532 | 2537 | ||
2533 | spin_lock_irqsave(&port->ip_lock, port_flags); | 2538 | spin_lock_irqsave(&the_port->lock, port_flags); |
2534 | ioc4_change_speed(the_port, termios, old_termios); | 2539 | ioc4_change_speed(the_port, termios, old_termios); |
2535 | spin_unlock_irqrestore(&port->ip_lock, port_flags); | 2540 | spin_unlock_irqrestore(&the_port->lock, port_flags); |
2536 | } | 2541 | } |
2537 | 2542 | ||
2538 | /** | 2543 | /** |
@@ -2607,24 +2612,25 @@ ioc4_serial_core_attach(struct pci_dev *pdev) | |||
2607 | __FUNCTION__, (void *)the_port, | 2612 | __FUNCTION__, (void *)the_port, |
2608 | (void *)port)); | 2613 | (void *)port)); |
2609 | 2614 | ||
2610 | spin_lock_init(&the_port->lock); | ||
2611 | /* membase, iobase and mapbase just need to be non-0 */ | 2615 | /* membase, iobase and mapbase just need to be non-0 */ |
2612 | the_port->membase = (unsigned char __iomem *)1; | 2616 | the_port->membase = (unsigned char __iomem *)1; |
2613 | 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; | ||
2614 | the_port->mapbase = 1; | 2619 | the_port->mapbase = 1; |
2615 | the_port->type = PORT_16550A; | 2620 | the_port->type = PORT_16550A; |
2616 | the_port->fifosize = IOC4_MAX_CHARS; | 2621 | the_port->fifosize = IOC4_FIFO_CHARS; |
2617 | the_port->ops = &ioc4_ops; | 2622 | the_port->ops = &ioc4_ops; |
2618 | the_port->irq = control->ic_irq; | 2623 | the_port->irq = control->ic_irq; |
2619 | the_port->dev = &pdev->dev; | 2624 | the_port->dev = &pdev->dev; |
2625 | spin_lock_init(&the_port->lock); | ||
2620 | if (uart_add_one_port(&ioc4_uart, the_port) < 0) { | 2626 | if (uart_add_one_port(&ioc4_uart, the_port) < 0) { |
2621 | printk(KERN_WARNING | 2627 | printk(KERN_WARNING |
2622 | "%s: unable to add port %d\n", | 2628 | "%s: unable to add port %d bus %d\n", |
2623 | __FUNCTION__, the_port->line); | 2629 | __FUNCTION__, the_port->line, pdev->bus->number); |
2624 | } else { | 2630 | } else { |
2625 | DPRINT_CONFIG( | 2631 | DPRINT_CONFIG( |
2626 | ("IOC4 serial driver port %d irq = %d\n", | 2632 | ("IOC4 serial port %d irq = %d, bus %d\n", |
2627 | the_port->line, the_port->irq)); | 2633 | the_port->line, the_port->irq, pdev->bus->number)); |
2628 | } | 2634 | } |
2629 | /* all ports are rs232 for now */ | 2635 | /* all ports are rs232 for now */ |
2630 | ioc4_set_proto(port, PROTO_RS232); | 2636 | ioc4_set_proto(port, PROTO_RS232); |
@@ -2734,6 +2740,8 @@ ioc4_serial_attach_one(struct ioc4_driver_data *idd) | |||
2734 | if ((ret = ioc4_serial_core_attach(idd->idd_pdev))) | 2740 | if ((ret = ioc4_serial_core_attach(idd->idd_pdev))) |
2735 | goto out4; | 2741 | goto out4; |
2736 | 2742 | ||
2743 | Num_of_ioc4_cards++; | ||
2744 | |||
2737 | return ret; | 2745 | return ret; |
2738 | 2746 | ||
2739 | /* error exits that give back resources */ | 2747 | /* error exits that give back resources */ |