aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/ide/ide.c
diff options
context:
space:
mode:
authorBartlomiej Zolnierkiewicz <bzolnier@gmail.com>2007-03-26 17:03:19 -0400
committerBartlomiej Zolnierkiewicz <bzolnier@gmail.com>2007-03-26 17:03:19 -0400
commit8799620400b0b1a4729d8be828b5bfb3d2a8db1a (patch)
tree4c5f3bb3360dddcc9638c4e92ddb7f1f2e0b1578 /drivers/ide/ide.c
parentf68d9320cd06fdec19735143b42e5197b63165b4 (diff)
ide: fix locking for manual DMA enable/disable ("hdparm -d")
Since hwif->ide_dma_check and hwif->ide_dma_on never queue any commands (ide_config_drive_speed() sets transfer mode using polling and has no error recovery) we are safe with setting hwgroup->busy for the time while DMA setting for a drive is changed (so it won't race against I/O commands in fly). I audited briefly all ->ide_dma_check/->ide_dma_on/->tuneproc/->speedproc implementations and they all look OK wrt to this change. This patch finally allowed me to close kernel bugzilla bug #8169 (once again thanks to Patrick Horn for reporting the issue & testing patches). Cc: Sergei Shtylyov <sshtylyov@ru.mvista.com> Cc: Alan Cox <alan@lxorguk.ukuu.org.uk> Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
Diffstat (limited to 'drivers/ide/ide.c')
-rw-r--r--drivers/ide/ide.c37
1 files changed, 30 insertions, 7 deletions
diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c
index 695610f0e3e..a6f098fda88 100644
--- a/drivers/ide/ide.c
+++ b/drivers/ide/ide.c
@@ -1124,17 +1124,40 @@ static int set_io_32bit(ide_drive_t *drive, int arg)
1124static int set_using_dma (ide_drive_t *drive, int arg) 1124static int set_using_dma (ide_drive_t *drive, int arg)
1125{ 1125{
1126#ifdef CONFIG_BLK_DEV_IDEDMA 1126#ifdef CONFIG_BLK_DEV_IDEDMA
1127 ide_hwif_t *hwif = drive->hwif;
1128 int err = -EPERM;
1129
1127 if (!drive->id || !(drive->id->capability & 1)) 1130 if (!drive->id || !(drive->id->capability & 1))
1128 return -EPERM; 1131 goto out;
1129 if (HWIF(drive)->ide_dma_check == NULL) 1132
1130 return -EPERM; 1133 if (hwif->ide_dma_check == NULL)
1134 goto out;
1135
1136 err = -EBUSY;
1137 if (ide_spin_wait_hwgroup(drive))
1138 goto out;
1139 /*
1140 * set ->busy flag, unlock and let it ride
1141 */
1142 hwif->hwgroup->busy = 1;
1143 spin_unlock_irq(&ide_lock);
1144
1145 err = 0;
1146
1131 if (arg) { 1147 if (arg) {
1132 if (ide_set_dma(drive)) 1148 if (ide_set_dma(drive) || hwif->ide_dma_on(drive))
1133 return -EIO; 1149 err = -EIO;
1134 if (HWIF(drive)->ide_dma_on(drive)) return -EIO;
1135 } else 1150 } else
1136 ide_dma_off(drive); 1151 ide_dma_off(drive);
1137 return 0; 1152
1153 /*
1154 * lock, clear ->busy flag and unlock before leaving
1155 */
1156 spin_lock_irq(&ide_lock);
1157 hwif->hwgroup->busy = 0;
1158 spin_unlock_irq(&ide_lock);
1159out:
1160 return err;
1138#else 1161#else
1139 return -EPERM; 1162 return -EPERM;
1140#endif 1163#endif