X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=drivers%2Fchar%2Fserial167.c;h=21a710cb4bbaed1df2ebfc6a6044bcf5abeb67c4;hb=a81b60294dec2c421c53e8545ee9731c0d753e1d;hp=885621edb4a65e985d7e297b8734b94b1fbae78c;hpb=1a69f36a78895dad9a6b97ffa2d6d2b7c3975b5d;p=linux-2.6.git diff --git a/drivers/char/serial167.c b/drivers/char/serial167.c index 885621edb..21a710cb4 100644 --- a/drivers/char/serial167.c +++ b/drivers/char/serial167.c @@ -39,9 +39,11 @@ * - don't use the panic function in serial167_init * - do resource release on failure on serial167_init * - include missing restore_flags in mvme167_serial_console_setup + * + * Kars de Jong - 2004/09/06 + * - replace bottom half handler with task queue handler */ -#include #include #include #include @@ -59,10 +61,10 @@ #include #include #include +#include #include #include -#include #include #include #include @@ -89,8 +91,6 @@ #define SERIAL_TYPE_NORMAL 1 -DECLARE_TASK_QUEUE(tq_cyclades); - static struct tty_driver *cy_serial_driver; extern int serial_console; static struct cyclades_port *serial_console_info = NULL; @@ -116,7 +116,7 @@ struct cyclades_port cy_port[] = { {-1 }, /* ttyS2 */ {-1 }, /* ttyS3 */ }; -#define NR_PORTS (sizeof(cy_port)/sizeof(struct cyclades_port)) +#define NR_PORTS ARRAY_SIZE(cy_port) /* * tmp_buf is used as a temporary buffer by serial_write. We need to @@ -128,7 +128,6 @@ struct cyclades_port cy_port[] = { * memory if large numbers of serial ports are open. */ static unsigned char *tmp_buf = 0; -DECLARE_MUTEX(tmp_buf_sem); /* * This is used to look up the divisor speeds and the timeouts @@ -373,8 +372,7 @@ static inline void cy_sched_event(struct cyclades_port *info, int event) { info->event |= 1 << event; /* remember what kind of event and who */ - queue_task(&info->tqueue, &tq_cyclades); /* it belongs to */ - mark_bh(CYCLADES_BH); /* then trigger event */ + schedule_work(&info->tqueue); } /* cy_sched_event */ @@ -422,52 +420,42 @@ cd2401_rxerr_interrupt(int irq, void *dev_id, struct pt_regs *fp) base_addr[CyREOIR] = rfoc ? 0 : CyNOTRANS; return IRQ_HANDLED; } - if (tty->flip.count < TTY_FLIPBUF_SIZE){ - tty->flip.count++; + if (tty_buffer_request_room(tty, 1) != 0){ if (err & info->read_status_mask){ if(err & CyBREAK){ - *tty->flip.flag_buf_ptr++ = TTY_BREAK; - *tty->flip.char_buf_ptr++ = data; + tty_insert_flip_char(tty, data, TTY_BREAK); if (info->flags & ASYNC_SAK){ do_SAK(tty); } }else if(err & CyFRAME){ - *tty->flip.flag_buf_ptr++ = TTY_FRAME; - *tty->flip.char_buf_ptr++ = data; + tty_insert_flip_char(tty, data, TTY_FRAME); }else if(err & CyPARITY){ - *tty->flip.flag_buf_ptr++ = TTY_PARITY; - *tty->flip.char_buf_ptr++ = data; + tty_insert_flip_char(tty, data, TTY_PARITY); }else if(err & CyOVERRUN){ - *tty->flip.flag_buf_ptr++ = TTY_OVERRUN; - *tty->flip.char_buf_ptr++ = 0; + tty_insert_flip_char(tty, 0, TTY_OVERRUN); /* If the flip buffer itself is overflowing, we still loose the next incoming character. */ - if(tty->flip.count < TTY_FLIPBUF_SIZE){ - tty->flip.count++; - *tty->flip.flag_buf_ptr++ = TTY_NORMAL; - *tty->flip.char_buf_ptr++ = data; - } + tty_insert_flip_char(tty, data, TTY_NORMAL); + } /* These two conditions may imply */ /* a normal read should be done. */ /* else if(data & CyTIMEOUT) */ /* else if(data & CySPECHAR) */ }else{ - *tty->flip.flag_buf_ptr++ = 0; - *tty->flip.char_buf_ptr++ = 0; + tty_insert_flip_char(tty, 0, TTY_NORMAL); } }else{ - *tty->flip.flag_buf_ptr++ = 0; - *tty->flip.char_buf_ptr++ = 0; + tty_insert_flip_char(tty, data, TTY_NORMAL); } }else{ /* there was a software buffer overrun and nothing could be done about it!!! */ } } - queue_task(&tty->flip.tqueue, &tq_timer); + schedule_delayed_work(&tty->flip.work, 1); /* end of service */ base_addr[CyREOIR] = rfoc ? 0 : CyNOTRANS; return IRQ_HANDLED; @@ -692,17 +680,12 @@ cd2401_rx_interrupt(int irq, void *dev_id, struct pt_regs *fp) #endif while(char_count--){ data = base_addr[CyRDR]; - if (tty->flip.count >= TTY_FLIPBUF_SIZE){ - continue; - } - tty->flip.count++; - *tty->flip.flag_buf_ptr++ = TTY_NORMAL; - *tty->flip.char_buf_ptr++ = data; + tty_insert_flip_char(tty, data, TTY_NORMAL); #ifdef CYCLOM_16Y_HACK udelay(10L); #endif } - queue_task(&tty->flip.tqueue, &tq_timer); + schedule_delayed_work(&tty->flip.work, 1); } /* end of service */ base_addr[CyREOIR] = save_cnt ? 0 : CyNOTRANS; @@ -713,7 +696,7 @@ cd2401_rx_interrupt(int irq, void *dev_id, struct pt_regs *fp) * This routine is used to handle the "bottom half" processing for the * serial driver, known also the "software interrupt" processing. * This processing is done at the kernel interrupt level, after the - * cy_interrupt() has returned, BUT WITH INTERRUPTS TURNED ON. This + * cy#/_interrupt() has returned, BUT WITH INTERRUPTS TURNED ON. This * is where time-consuming activities which can not be done in the * interrupt driver proper are done; the interrupt driver schedules * them using cy_sched_event(), and they get done here. @@ -721,9 +704,7 @@ cd2401_rx_interrupt(int irq, void *dev_id, struct pt_regs *fp) * This is done through one level of indirection--the task queue. * When a hardware interrupt service routine wants service by the * driver's bottom half, it enqueues the appropriate tq_struct (one - * per port) to the tq_cyclades work queue and sets a request flag - * via mark_bh for processing that queue. When the time is right, - * do_cyclades_bh is called (because of the mark_bh) and it requests + * per port) to the keventd work queue and sets a request flag * that the work queue be processed. * * Although this may seem unwieldy, it gives the system a way to @@ -731,12 +712,6 @@ cd2401_rx_interrupt(int irq, void *dev_id, struct pt_regs *fp) * structure) to the bottom half of the driver. Previous kernels * had to poll every port to see if that port needed servicing. */ -static void -do_cyclades_bh(void) -{ - run_task_queue(&tq_cyclades); -} /* do_cyclades_bh */ - static void do_softint(void *private_) { @@ -1208,7 +1183,7 @@ cy_flush_chars(struct tty_struct *tty) port is already active, there is no need to kick it. */ static int -cy_write(struct tty_struct * tty, int from_user, +cy_write(struct tty_struct * tty, const unsigned char *buf, int count) { struct cyclades_port *info = (struct cyclades_port *)tty->driver_data; @@ -1227,53 +1202,23 @@ cy_write(struct tty_struct * tty, int from_user, return 0; } - if (from_user) { - down(&tmp_buf_sem); - while (1) { - c = min_t(int, count, min(SERIAL_XMIT_SIZE - info->xmit_cnt - 1, - SERIAL_XMIT_SIZE - info->xmit_head)); - if (c <= 0) - break; - - c -= copy_from_user(tmp_buf, buf, c); - if (!c) { - if (!total) - total = -EFAULT; - break; - } - - local_irq_save(flags); - c = min_t(int, c, min(SERIAL_XMIT_SIZE - info->xmit_cnt - 1, - SERIAL_XMIT_SIZE - info->xmit_head)); - memcpy(info->xmit_buf + info->xmit_head, tmp_buf, c); - info->xmit_head = (info->xmit_head + c) & (SERIAL_XMIT_SIZE-1); - info->xmit_cnt += c; + while (1) { + local_irq_save(flags); + c = min_t(int, count, min(SERIAL_XMIT_SIZE - info->xmit_cnt - 1, + SERIAL_XMIT_SIZE - info->xmit_head)); + if (c <= 0) { local_irq_restore(flags); - - buf += c; - count -= c; - total += c; + break; } - up(&tmp_buf_sem); - } else { - while (1) { - local_irq_save(flags); - c = min_t(int, count, min(SERIAL_XMIT_SIZE - info->xmit_cnt - 1, - SERIAL_XMIT_SIZE - info->xmit_head)); - if (c <= 0) { - local_irq_restore(flags); - break; - } - memcpy(info->xmit_buf + info->xmit_head, buf, c); - info->xmit_head = (info->xmit_head + c) & (SERIAL_XMIT_SIZE-1); - info->xmit_cnt += c; - local_irq_restore(flags); + memcpy(info->xmit_buf + info->xmit_head, buf, c); + info->xmit_head = (info->xmit_head + c) & (SERIAL_XMIT_SIZE-1); + info->xmit_cnt += c; + local_irq_restore(flags); - buf += c; - count -= c; - total += c; - } + buf += c; + count -= c; + total += c; } if (info->xmit_cnt @@ -1840,8 +1785,7 @@ cy_close(struct tty_struct * tty, struct file * filp) info->tty = 0; if (info->blocked_open) { if (info->close_delay) { - current->state = TASK_INTERRUPTIBLE; - schedule_timeout(info->close_delay); + msleep_interruptible(jiffies_to_msecs(info->close_delay)); } wake_up_interruptible(&info->open_wait); } @@ -2290,7 +2234,6 @@ scrn[1] = '\0'; /* Initialize the tty_driver structure */ cy_serial_driver->owner = THIS_MODULE; - cy_serial_driver->devfs_name = "tts/"; cy_serial_driver->name = "ttyS"; cy_serial_driver->major = TTY_MAJOR; cy_serial_driver->minor_start = 64; @@ -2309,8 +2252,6 @@ scrn[1] = '\0'; return ret; } - init_bh(CYCLADES_BH, do_cyclades_bh); - port_num = 0; info = cy_port; for (index = 0; index < 1; index++) { @@ -2348,8 +2289,7 @@ scrn[1] = '\0'; info->blocked_open = 0; info->default_threshold = 0; info->default_timeout = 0; - info->tqueue.routine = do_softint; - info->tqueue.data = info; + INIT_WORK(&info->tqueue, do_softint, info); init_waitqueue_head(&info->open_wait); init_waitqueue_head(&info->close_wait); /* info->session */