summaryrefslogtreecommitdiffstats
path: root/drivers/usb/serial/mos7840.c
diff options
context:
space:
mode:
authorJohan Hovold <jhovold@gmail.com>2013-03-21 12:37:15 +0100
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2013-03-25 13:52:24 -0700
commitc9fac85345ca8fd7f6519232a4c0024f648647b5 (patch)
tree3415517cb5833e8f377c544f94e0e107bdd73d5e /drivers/usb/serial/mos7840.c
parent35711578044076d00d396cb6787d3cc593a4c35a (diff)
downloadlinux-stable-c9fac85345ca8fd7f6519232a4c0024f648647b5.tar.gz
linux-stable-c9fac85345ca8fd7f6519232a4c0024f648647b5.tar.bz2
linux-stable-c9fac85345ca8fd7f6519232a4c0024f648647b5.zip
USB: mos7840: remove smp barriers from icount handling
Remove SMP memory barriers from icount handling and rely on the barriers implied by wait_event, sleep and locks, while using the port lock to guarantee atomicity. This is a step in moving over to the generic icount implementations. Signed-off-by: Johan Hovold <jhovold@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/usb/serial/mos7840.c')
-rw-r--r--drivers/usb/serial/mos7840.c48
1 files changed, 19 insertions, 29 deletions
diff --git a/drivers/usb/serial/mos7840.c b/drivers/usb/serial/mos7840.c
index 979ef1999581..7af3d4206523 100644
--- a/drivers/usb/serial/mos7840.c
+++ b/drivers/usb/serial/mos7840.c
@@ -406,22 +406,14 @@ 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);
@@ -443,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();
- }
}
/************************************************************************/
@@ -778,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);
}
@@ -1507,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;
@@ -2133,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;
@@ -2166,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;
@@ -2197,7 +2182,9 @@ 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;
@@ -2213,11 +2200,14 @@ static int mos7840_ioctl(struct tty_struct *tty,
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)) ||