aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTejun Heo <tj@kernel.org>2010-04-08 04:45:46 -0400
committerDavid S. Miller <davem@davemloft.net>2010-10-26 13:17:30 -0400
commitdd8717da6da9b0e745df49762be4573010f1013c (patch)
treee1875e541ce097b30edc17e431b4dd7074218c00
parentbbe54d78cc59a39f1ef3ffbe70423376ad9aab4c (diff)
ide: clean up timed out request handling
8f6205cd572fece673da0255d74843680f67f879 introduced a bug where a timed out DMA request is never requeued and lost. 6072f7491f5ef391a575e18a1165e72a3eef1601 fixed this by making ide_dma_timeout_retry() requeue the request itself. While the fix is correct, it makes DMA and non-DMA paths asymmetric regarding how the in flight request is requeued. As long as hwif->rq is set, the IDE driver is assuming ownership of the request and the request should either be completed or requeued when clearing hwif->rq. In the timeout path, the ide driver holds onto the request as long as the recovery action (ie. reset) is in progress and clears it after the state machine is stopped (ide_stopped return), so the existing requeueing logic is correct. The bug occurred because ide_dma_timeout_retry() explicitly clears hwif->rq without requeueing it. ide_dma_timeout_retry() is called only by ide_timer_expiry() and returns ide_started only when ide_error() would return it - ie. after reset state machine has started in which case the state machine will eventually end up executing the ide_stopped path in ide_timer_expiry() after reset protocol is complete. So, there is no need to clear hwif->rq from ide_dma_timeout_retry(). ide_timer_expiry() will handle it the same way as PIO timeout path. Kill hwif->rq clearing and requeueing from ide_dma_timeout_retry() and let ide_timer_expiry() deal with it. The end result should remain the same. grepping shows ide_dma_timeout_retry() is the only site which clears hwif->rq without taking care of the request, so there shouldn't be similar fallouts. Signed-off-by: Tejun Heo <tj@kernel.org> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/ide/ide-dma.c11
1 files changed, 3 insertions, 8 deletions
diff --git a/drivers/ide/ide-dma.c b/drivers/ide/ide-dma.c
index 06b14bc9a1d4..d4136908f916 100644
--- a/drivers/ide/ide-dma.c
+++ b/drivers/ide/ide-dma.c
@@ -449,7 +449,6 @@ ide_startstop_t ide_dma_timeout_retry(ide_drive_t *drive, int error)
449 ide_hwif_t *hwif = drive->hwif; 449 ide_hwif_t *hwif = drive->hwif;
450 const struct ide_dma_ops *dma_ops = hwif->dma_ops; 450 const struct ide_dma_ops *dma_ops = hwif->dma_ops;
451 struct ide_cmd *cmd = &hwif->cmd; 451 struct ide_cmd *cmd = &hwif->cmd;
452 struct request *rq;
453 ide_startstop_t ret = ide_stopped; 452 ide_startstop_t ret = ide_stopped;
454 453
455 /* 454 /*
@@ -487,14 +486,10 @@ ide_startstop_t ide_dma_timeout_retry(ide_drive_t *drive, int error)
487 ide_dma_off_quietly(drive); 486 ide_dma_off_quietly(drive);
488 487
489 /* 488 /*
490 * un-busy drive etc and make sure request is sane 489 * make sure request is sane
491 */ 490 */
492 rq = hwif->rq; 491 if (hwif->rq)
493 if (rq) { 492 hwif->rq->errors = 0;
494 hwif->rq = NULL;
495 rq->errors = 0;
496 ide_requeue_and_plug(drive, rq);
497 }
498 return ret; 493 return ret;
499} 494}
500 495