diff options
author | David Woodhouse <dwmw2@infradead.org> | 2006-08-05 15:15:19 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-08-06 11:57:49 -0400 |
commit | 3e3183bab0257a6d02038658c53b491e1378612f (patch) | |
tree | 35221f1808e85674d9ba0ff93ce0cc4bce7edf7f /drivers/i2c | |
parent | 225add619624b4877941470f31d297e0151b21be (diff) |
[PATCH] SCX200_ACB: eliminate spurious timeout errors
While busy-waiting for completion, check the hardware after scheduling;
don't schedule and then immediately check the _timeout_. If the yield()
took a long time (as it does on my OLPC prototype board when it's busy),
we'd report a timeout even though the hardware was now ready.
This fixes it, and also switches the yield() for a cond_resched() because
we don't actually want to be _that_ nice about it. I see nice
tightly-packed SMBus transactions now, rather than waiting for milliseconds
between successive phases.
Actually, we shouldn't be busy-waiting here at all. We should be using
interrupts. That's an exercise for another day though.
Signed-off-by: David Woodhouse <dwmw2@infradead.org>
Cc: Christer Weinigel <wingel@nano-system.com>
Cc: <Jordan.Crouse@amd.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'drivers/i2c')
-rw-r--r-- | drivers/i2c/busses/scx200_acb.c | 7 |
1 files changed, 5 insertions, 2 deletions
diff --git a/drivers/i2c/busses/scx200_acb.c b/drivers/i2c/busses/scx200_acb.c index ced309ff056f..eae9e81be375 100644 --- a/drivers/i2c/busses/scx200_acb.c +++ b/drivers/i2c/busses/scx200_acb.c | |||
@@ -232,7 +232,7 @@ static void scx200_acb_poll(struct scx200_acb_iface *iface) | |||
232 | unsigned long timeout; | 232 | unsigned long timeout; |
233 | 233 | ||
234 | timeout = jiffies + POLL_TIMEOUT; | 234 | timeout = jiffies + POLL_TIMEOUT; |
235 | while (time_before(jiffies, timeout)) { | 235 | while (1) { |
236 | status = inb(ACBST); | 236 | status = inb(ACBST); |
237 | 237 | ||
238 | /* Reset the status register to avoid the hang */ | 238 | /* Reset the status register to avoid the hang */ |
@@ -242,7 +242,10 @@ static void scx200_acb_poll(struct scx200_acb_iface *iface) | |||
242 | scx200_acb_machine(iface, status); | 242 | scx200_acb_machine(iface, status); |
243 | return; | 243 | return; |
244 | } | 244 | } |
245 | yield(); | 245 | if (time_after(jiffies, timeout)) |
246 | break; | ||
247 | cpu_relax(); | ||
248 | cond_resched(); | ||
246 | } | 249 | } |
247 | 250 | ||
248 | dev_err(&iface->adapter.dev, "timeout in state %s\n", | 251 | dev_err(&iface->adapter.dev, "timeout in state %s\n", |