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 | |
| 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')
| -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", |
