| From 0f6d93aa9d96cc9022b51bd10d462b03296be146 Mon Sep 17 00:00:00 2001 |
| From: Martin Michlmayr <tbm@cyrius.com> |
| Date: Thu, 4 Oct 2012 17:11:25 -0700 |
| Subject: drivers/scsi/atp870u.c: fix bad use of udelay |
| |
| From: Martin Michlmayr <tbm@cyrius.com> |
| |
| commit 0f6d93aa9d96cc9022b51bd10d462b03296be146 upstream. |
| |
| The ACARD driver calls udelay() with a value > 2000, which leads to to |
| the following compilation error on ARM: |
| |
| ERROR: "__bad_udelay" [drivers/scsi/atp870u.ko] undefined! |
| make[1]: *** [__modpost] Error 1 |
| |
| This is because udelay is defined on ARM, roughly speaking, as |
| |
| #define udelay(n) ((n) > 2000 ? __bad_udelay() : \ |
| __const_udelay((n) * ((2199023U*HZ)>>11))) |
| |
| The argument to __const_udelay is the number of jiffies to wait divided |
| by 4, but this does not work unless the multiplication does not |
| overflow, and that is what the build error is designed to prevent. The |
| intended behavior can be achieved by using mdelay to call udelay |
| multiple times in a loop. |
| |
| [jrnieder@gmail.com: adding context] |
| Signed-off-by: Martin Michlmayr <tbm@cyrius.com> |
| Signed-off-by: Jonathan Nieder <jrnieder@gmail.com> |
| Cc: James Bottomley <James.Bottomley@HansenPartnership.com> |
| Signed-off-by: Andrew Morton <akpm@linux-foundation.org> |
| Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| drivers/scsi/atp870u.c | 11 ++++++++++- |
| 1 file changed, 10 insertions(+), 1 deletion(-) |
| |
| --- a/drivers/scsi/atp870u.c |
| +++ b/drivers/scsi/atp870u.c |
| @@ -1174,7 +1174,16 @@ wait_io1: |
| outw(val, tmport); |
| outb(2, 0x80); |
| TCM_SYNC: |
| - udelay(0x800); |
| + /* |
| + * The funny division into multiple delays is to accomodate |
| + * arches like ARM where udelay() multiplies its argument by |
| + * a large number to initialize a loop counter. To avoid |
| + * overflow, the maximum supported udelay is 2000 microseconds. |
| + * |
| + * XXX it would be more polite to find a way to use msleep() |
| + */ |
| + mdelay(2); |
| + udelay(48); |
| if ((inb(tmport) & 0x80) == 0x00) { /* bsy ? */ |
| outw(0, tmport--); |
| outb(0, tmport); |