serial: fix off by one errors
authorRoel Kluin <roel.kluin@gmail.com>
Mon, 22 Jun 2009 17:41:56 +0000 (18:41 +0100)
committerLinus Torvalds <torvalds@linux-foundation.org>
Mon, 22 Jun 2009 18:32:23 +0000 (11:32 -0700)
In zs_console_putchar() occurs:

if (zs_transmit_drain(zport, irq))
write_zsdata(zport, ch);

However if in zs_transmit_drain() no empty Tx Buffer occurs, limit reaches
-1 => true, and the write still occurs.

This patch changes postfix to prefix decrements in this and similar
functions to prevent similar mistakes in the future.  This decreases the
iterations with one but the chosen loop count was arbitrary anyway.

In sunhv limit reaches -1, not 0, so the test is off by one.

Signed-off-by: Roel Kluin <roel.kluin@gmail.com>
Acked-by: David S. Miller <davem@davemloft.net>
Acked-by: Maciej W. Rozycki <macro@linux-mips.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Alan Cox <alan@linux.intel.com>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
drivers/serial/sb1250-duart.c
drivers/serial/sunhv.c
drivers/serial/zs.c

index a4fb343a08da30de886425ec4e371310671a303b..319e8b83f6be5b488e451c7dc4db7103e0ba8edb 100644 (file)
@@ -204,7 +204,7 @@ static int sbd_receive_drain(struct sbd_port *sport)
 {
        int loops = 10000;
 
-       while (sbd_receive_ready(sport) && loops--)
+       while (sbd_receive_ready(sport) && --loops)
                read_sbdchn(sport, R_DUART_RX_HOLD);
        return loops;
 }
@@ -218,7 +218,7 @@ static int __maybe_unused sbd_transmit_drain(struct sbd_port *sport)
 {
        int loops = 10000;
 
-       while (!sbd_transmit_ready(sport) && loops--)
+       while (!sbd_transmit_ready(sport) && --loops)
                udelay(2);
        return loops;
 }
@@ -232,7 +232,7 @@ static int sbd_line_drain(struct sbd_port *sport)
 {
        int loops = 10000;
 
-       while (!sbd_transmit_empty(sport) && loops--)
+       while (!sbd_transmit_empty(sport) && --loops)
                udelay(2);
        return loops;
 }
index a94a2ab4b5716cbb983d8d3d81e2d3e505dbc3e4..1df5325faab2605d9be2bdcd2bc470981049459c 100644 (file)
@@ -461,7 +461,7 @@ static void sunhv_console_write_paged(struct console *con, const char *s, unsign
                                        break;
                                udelay(1);
                        }
-                       if (limit <= 0)
+                       if (limit < 0)
                                break;
                        page_bytes -= written;
                        ra += written;
index 9e6a873f8203ec83f7965fe2711a026089c476fa..d8c2809b1ab616b7fc7209577218d6017fe6cea8 100644 (file)
@@ -231,7 +231,7 @@ static int zs_receive_drain(struct zs_port *zport)
 {
        int loops = 10000;
 
-       while ((read_zsreg(zport, R0) & Rx_CH_AV) && loops--)
+       while ((read_zsreg(zport, R0) & Rx_CH_AV) && --loops)
                read_zsdata(zport);
        return loops;
 }
@@ -241,7 +241,7 @@ static int zs_transmit_drain(struct zs_port *zport, int irq)
        struct zs_scc *scc = zport->scc;
        int loops = 10000;
 
-       while (!(read_zsreg(zport, R0) & Tx_BUF_EMP) && loops--) {
+       while (!(read_zsreg(zport, R0) & Tx_BUF_EMP) && --loops) {
                zs_spin_unlock_cond_irq(&scc->zlock, irq);
                udelay(2);
                zs_spin_lock_cond_irq(&scc->zlock, irq);
@@ -254,7 +254,7 @@ static int zs_line_drain(struct zs_port *zport, int irq)
        struct zs_scc *scc = zport->scc;
        int loops = 10000;
 
-       while (!(read_zsreg(zport, R1) & ALL_SNT) && loops--) {
+       while (!(read_zsreg(zport, R1) & ALL_SNT) && --loops) {
                zs_spin_unlock_cond_irq(&scc->zlock, irq);
                udelay(2);
                zs_spin_lock_cond_irq(&scc->zlock, irq);