USB: mos7840: remove smp barriers from icount handling
[deliverable/linux.git] / drivers / usb / serial / mos7840.c
index 809fb329eca5f945d13c25e75f74bf79145389df..7af3d4206523eeb0937fe373dfd9fb9eace9add6 100644 (file)
@@ -219,7 +219,6 @@ struct moschip_port {
        char open;
        char open_ports;
        wait_queue_head_t wait_chase;   /* for handling sleeping while waiting for chase to finish */
-       wait_queue_head_t delta_msr_wait;       /* for handling sleeping while waiting for msr change to happen */
        int delta_msr_cond;
        struct async_icount icount;
        struct usb_serial_port *port;   /* loop back to the owner of this object */
@@ -407,22 +406,17 @@ static void mos7840_handle_new_msr(struct moschip_port *port, __u8 new_msr)
                icount = &mos7840_port->icount;
 
                /* update input line counters */
-               if (new_msr & MOS_MSR_DELTA_CTS) {
+               if (new_msr & MOS_MSR_DELTA_CTS)
                        icount->cts++;
-                       smp_wmb();
-               }
-               if (new_msr & MOS_MSR_DELTA_DSR) {
+               if (new_msr & MOS_MSR_DELTA_DSR)
                        icount->dsr++;
-                       smp_wmb();
-               }
-               if (new_msr & MOS_MSR_DELTA_CD) {
+               if (new_msr & MOS_MSR_DELTA_CD)
                        icount->dcd++;
-                       smp_wmb();
-               }
-               if (new_msr & MOS_MSR_DELTA_RI) {
+               if (new_msr & MOS_MSR_DELTA_RI)
                        icount->rng++;
-                       smp_wmb();
-               }
+
+               mos7840_port->delta_msr_cond = 1;
+               wake_up_interruptible(&port->port->delta_msr_wait);
        }
 }
 
@@ -441,22 +435,14 @@ static void mos7840_handle_new_lsr(struct moschip_port *port, __u8 new_lsr)
 
        /* update input line counters */
        icount = &port->icount;
-       if (new_lsr & SERIAL_LSR_BI) {
+       if (new_lsr & SERIAL_LSR_BI)
                icount->brk++;
-               smp_wmb();
-       }
-       if (new_lsr & SERIAL_LSR_OE) {
+       if (new_lsr & SERIAL_LSR_OE)
                icount->overrun++;
-               smp_wmb();
-       }
-       if (new_lsr & SERIAL_LSR_PE) {
+       if (new_lsr & SERIAL_LSR_PE)
                icount->parity++;
-               smp_wmb();
-       }
-       if (new_lsr & SERIAL_LSR_FE) {
+       if (new_lsr & SERIAL_LSR_FE)
                icount->frame++;
-               smp_wmb();
-       }
 }
 
 /************************************************************************/
@@ -776,7 +762,6 @@ static void mos7840_bulk_in_callback(struct urb *urb)
                tty_insert_flip_string(tport, data, urb->actual_length);
                tty_flip_buffer_push(tport);
                mos7840_port->icount.rx += urb->actual_length;
-               smp_wmb();
                dev_dbg(&port->dev, "mos7840_port->icount.rx is %d:\n", mos7840_port->icount.rx);
        }
 
@@ -1127,7 +1112,6 @@ static int mos7840_open(struct tty_struct *tty, struct usb_serial_port *port)
 
        /* initialize our wait queues */
        init_waitqueue_head(&mos7840_port->wait_chase);
-       init_waitqueue_head(&mos7840_port->delta_msr_wait);
 
        /* initialize our icount structure */
        memset(&(mos7840_port->icount), 0x00, sizeof(mos7840_port->icount));
@@ -1222,25 +1206,10 @@ static void mos7840_close(struct usb_serial_port *port)
                }
        }
 
-       /* While closing port, shutdown all bulk read, write  *
-        * and interrupt read if they exists                  */
-       if (serial->dev) {
-               if (mos7840_port->write_urb) {
-                       dev_dbg(&port->dev, "%s", "Shutdown bulk write\n");
-                       usb_kill_urb(mos7840_port->write_urb);
-               }
-               if (mos7840_port->read_urb) {
-                       dev_dbg(&port->dev, "%s", "Shutdown bulk read\n");
-                       usb_kill_urb(mos7840_port->read_urb);
-                       mos7840_port->read_urb_busy = false;
-               }
-               if ((&mos7840_port->control_urb)) {
-                       dev_dbg(&port->dev, "%s", "Shutdown control read\n");
-                       /*/      usb_kill_urb (mos7840_port->control_urb); */
-               }
-       }
-/*      if(mos7840_port->ctrl_buf != NULL) */
-/*              kfree(mos7840_port->ctrl_buf); */
+       usb_kill_urb(mos7840_port->write_urb);
+       usb_kill_urb(mos7840_port->read_urb);
+       mos7840_port->read_urb_busy = false;
+
        port0->open_ports--;
        dev_dbg(&port->dev, "%s in close%d:in port%d\n", __func__, port0->open_ports, port->number);
        if (port0->open_ports == 0) {
@@ -1252,8 +1221,7 @@ static void mos7840_close(struct usb_serial_port *port)
 
        if (mos7840_port->write_urb) {
                /* if this urb had a transfer buffer already (old tx) free it */
-               if (mos7840_port->write_urb->transfer_buffer != NULL)
-                       kfree(mos7840_port->write_urb->transfer_buffer);
+               kfree(mos7840_port->write_urb->transfer_buffer);
                usb_free_urb(mos7840_port->write_urb);
        }
 
@@ -1330,9 +1298,8 @@ static void mos7840_break(struct tty_struct *tty, int break_state)
        if (mos7840_port == NULL)
                return;
 
-       if (serial->dev)
-               /* flush and block until tx is empty */
-               mos7840_block_until_chase_response(tty, mos7840_port);
+       /* flush and block until tx is empty */
+       mos7840_block_until_chase_response(tty, mos7840_port);
 
        if (break_state == -1)
                data = mos7840_port->shadowLCR | LCR_SET_BREAK;
@@ -1523,7 +1490,6 @@ static int mos7840_write(struct tty_struct *tty, struct usb_serial_port *port,
        }
        bytes_sent = transfer_size;
        mos7840_port->icount.tx += transfer_size;
-       smp_wmb();
        dev_dbg(&port->dev, "mos7840_port->icount.tx is %d:\n", mos7840_port->icount.tx);
 exit:
        return bytes_sent;
@@ -2017,8 +1983,6 @@ static void mos7840_change_port_settings(struct tty_struct *tty,
                        mos7840_port->read_urb_busy = false;
                }
        }
-       wake_up(&mos7840_port->delta_msr_wait);
-       mos7840_port->delta_msr_cond = 1;
        dev_dbg(&port->dev, "%s - mos7840_port->shadowLCR is End %x\n", __func__,
                mos7840_port->shadowLCR);
 }
@@ -2151,11 +2115,14 @@ static int mos7840_get_icount(struct tty_struct *tty,
        struct usb_serial_port *port = tty->driver_data;
        struct moschip_port *mos7840_port;
        struct async_icount cnow;
+       unsigned long flags;
 
        mos7840_port = mos7840_get_port_private(port);
+
+       spin_lock_irqsave(&port->lock, flags);
        cnow = mos7840_port->icount;
+       spin_unlock_irqrestore(&port->lock, flags);
 
-       smp_rmb();
        icount->cts = cnow.cts;
        icount->dsr = cnow.dsr;
        icount->rng = cnow.rng;
@@ -2184,7 +2151,7 @@ static int mos7840_ioctl(struct tty_struct *tty,
        struct usb_serial_port *port = tty->driver_data;
        void __user *argp = (void __user *)arg;
        struct moschip_port *mos7840_port;
-
+       unsigned long flags;
        struct async_icount cnow;
        struct async_icount cprev;
 
@@ -2215,22 +2182,32 @@ static int mos7840_ioctl(struct tty_struct *tty,
 
        case TIOCMIWAIT:
                dev_dbg(&port->dev, "%s  TIOCMIWAIT\n", __func__);
+               spin_lock_irqsave(&port->lock, flags);
                cprev = mos7840_port->icount;
+               spin_unlock_irqrestore(&port->lock, flags);
                while (1) {
                        /* interruptible_sleep_on(&mos7840_port->delta_msr_wait); */
                        mos7840_port->delta_msr_cond = 0;
-                       wait_event_interruptible(mos7840_port->delta_msr_wait,
-                                                (mos7840_port->
+                       wait_event_interruptible(port->delta_msr_wait,
+                                                (port->serial->disconnected ||
+                                                 mos7840_port->
                                                  delta_msr_cond == 1));
 
                        /* see if a signal did it */
                        if (signal_pending(current))
                                return -ERESTARTSYS;
+
+                       if (port->serial->disconnected)
+                               return -EIO;
+
+                       spin_lock_irqsave(&port->lock, flags);
                        cnow = mos7840_port->icount;
-                       smp_rmb();
+                       spin_unlock_irqrestore(&port->lock, flags);
+
                        if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr &&
                            cnow.dcd == cprev.dcd && cnow.cts == cprev.cts)
                                return -EIO;    /* no change => error */
+
                        if (((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) ||
                            ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) ||
                            ((arg & TIOCM_CD) && (cnow.dcd != cprev.dcd)) ||
This page took 0.027457 seconds and 5 git commands to generate.