lkml.org 
[lkml]   [2003]   [Apr]   [8]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    Date
    SubjectRe: uart_ioctl OOPS with irtty-sir
    From
    On Fri, Apr 04, 2003 at 10:25:35AM +0100, Russell King wrote:
    > On Thu, Apr 03, 2003 at 05:34:05PM -0800, Jean Tourrilhes wrote:
    > > Unfortunately, the irtty-sir driver, which is a TTY line
    > > discipline and a network driver, need to be able to change the RTS and
    > > DTR line from a kernel thread.
    >
    > I'd prefer if we added an tty API to allow line disciplines to read/set
    > the modem control lines to the tty later, rather than having line
    > disciplines play games with IOCTLs.

    So, the patch has to look like what is below.
    I've decided to use the internal set/clear API, because it
    allow to ignore the default state of control line (all the troubles
    with TIOCM_OUT2/TIOCM_OUT1 on various platforms), so it's definitely a
    win.
    I'm not too sure about locking. I guess the spinlock in
    uart_update_mctrl() is probably good enough.
    I was tempted to create the same API for setting the speed
    (baud rate), but that may need to wait for another time.

    As you can't use IrDA SIR with 2.5.X, would you mind giving a
    look at the issue ? Feel free to forward as needed to get comments
    from all the interested parties. Thanks in advance...

    Have fun...

    Jean

    ---------------------------------------------------------------

    diff -u -p linux/include/linux/tty_driver.d0.h linux/include/linux/tty_driver.h
    --- linux/include/linux/tty_driver.d0.h Tue Apr 8 09:56:21 2003
    +++ linux/include/linux/tty_driver.h Tue Apr 8 10:09:09 2003
    @@ -157,6 +157,8 @@ struct tty_driver {
    int (*chars_in_buffer)(struct tty_struct *tty);
    int (*ioctl)(struct tty_struct *tty, struct file * file,
    unsigned int cmd, unsigned long arg);
    + int (*modem_ctrl)(struct tty_struct *tty,
    + unsigned int set, unsigned int clear);
    void (*set_termios)(struct tty_struct *tty, struct termios * old);
    void (*throttle)(struct tty_struct * tty);
    void (*unthrottle)(struct tty_struct * tty);
    diff -u -p linux/drivers/serial/core.d0.c linux/drivers/serial/core.c
    --- linux/drivers/serial/core.d0.c Tue Apr 8 09:51:00 2003
    +++ linux/drivers/serial/core.c Tue Apr 8 10:15:29 2003
    @@ -1158,6 +1158,26 @@ uart_ioctl(struct tty_struct *tty, struc
    return ret;
    }

    +/*
    + * Called by line disciplines to change the various modem control bits...
    + * Line disciplines are implemented within the kernel, and therefore
    + * we don't want them to use the ioctl function above.
    + * Jean II
    + */
    +static int
    +uart_modem_ctrl(struct tty_struct *tty, unsigned int set, unsigned int clear)
    +{
    + struct uart_state *state = tty->driver_data;
    +
    + /* Set new values, if any */
    + /* Locking will be done in there */
    + uart_update_mctrl(state->port, set, clear);
    +
    + /* Return new value */
    + return state->port->ops->get_mctrl(state->port);
    +}
    +
    +
    static void uart_set_termios(struct tty_struct *tty, struct termios *old_termios)
    {
    struct uart_state *state = tty->driver_data;
    @@ -2150,6 +2170,7 @@ int uart_register_driver(struct uart_dri
    normal->chars_in_buffer = uart_chars_in_buffer;
    normal->flush_buffer = uart_flush_buffer;
    normal->ioctl = uart_ioctl;
    + normal->modem_ctrl = uart_modem_ctrl;
    normal->throttle = uart_throttle;
    normal->unthrottle = uart_unthrottle;
    normal->send_xchar = uart_send_xchar;
    diff -u -p linux/drivers/net/irda/irtty-sir.d0.c linux/drivers/net/irda/irtty-sir.c
    --- linux/drivers/net/irda/irtty-sir.d0.c Tue Apr 8 09:46:54 2003
    +++ linux/drivers/net/irda/irtty-sir.c Tue Apr 8 10:34:53 2003
    @@ -180,32 +180,29 @@ static int irtty_change_speed(struct sir
    static int irtty_set_dtr_rts(struct sir_dev *dev, int dtr, int rts)
    {
    struct sirtty_cb *priv = dev->priv;
    - int arg = 0;
    + int set = 0;
    + int clear = 0;

    ASSERT(priv != NULL, return -1;);
    ASSERT(priv->magic == IRTTY_MAGIC, return -1;);

    -#ifdef TIOCM_OUT2 /* Not defined for ARM */
    - arg = TIOCM_OUT2;
    -#endif
    if (rts)
    - arg |= TIOCM_RTS;
    + set |= TIOCM_RTS;
    + else
    + clear |= TIOCM_RTS;
    if (dtr)
    - arg |= TIOCM_DTR;
    + set |= TIOCM_DTR;
    + else
    + clear |= TIOCM_DTR;

    /*
    - * The ioctl() function, or actually set_modem_info() in serial.c
    - * expects a pointer to the argument in user space. This is working
    - * here because we are always called from the kIrDAd thread which
    - * has set_fs(KERNEL_DS) permanently set. Therefore copy_from_user()
    - * is happy with our arg-parameter being local here in kernel space.
    + * We can't use ioctl() because it expects a non-null file structure,
    + * and we don't have that here.
    + * This function is not yet defined for all tty driver, so
    + * let's be careful... Jean II
    */
    -
    - lock_kernel();
    - if (priv->tty->driver.ioctl(priv->tty, NULL, TIOCMSET, (unsigned long) &arg)) {
    - IRDA_DEBUG(2, "%s(), error doing ioctl!\n", __FUNCTION__);
    - }
    - unlock_kernel();
    + ASSERT(priv->tty->driver.modem_ctrl != NULL, return -1;);
    + priv->tty->driver.modem_ctrl(priv->tty, set, clear);

    return 0;
    }
    diff -u -p linux/drivers/net/irda/sir_kthread.d0.c linux/drivers/net/irda/sir_kthread.c
    --- linux/drivers/net/irda/sir_kthread.d0.c Mon Apr 7 18:56:28 2003
    +++ linux/drivers/net/irda/sir_kthread.c Mon Apr 7 18:59:31 2003
    @@ -151,6 +151,13 @@ static int irda_thread(void *startup)

    while (irda_rq_queue.thread != NULL) {

    + /* We use TASK_INTERRUPTIBLE, rather than
    + * TASK_UNINTERRUPTIBLE. Andrew Morton made this
    + * change ; he told me that it is safe, because "signal
    + * blocking is now handled in daemonize()", he added
    + * that the problem is that "uninterruptible sleep
    + * contributes to load average", making user worry.
    + * Jean II */
    set_task_state(current, TASK_INTERRUPTIBLE);
    add_wait_queue(&irda_rq_queue.kick, &wait);
    if (list_empty(&irda_rq_queue.request_list))
    -
    To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
    the body of a message to majordomo@vger.kernel.org
    More majordomo info at http://vger.kernel.org/majordomo-info.html
    Please read the FAQ at http://www.tux.org/lkml/
    \
     
     \ /
      Last update: 2005-03-22 13:34    [W:0.036 / U:5.496 seconds]
    ©2003-2017 Jasper Spaans. hosted at Digital OceanAdvertise on this site