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 
(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>
This commit is contained in:
Bartlomiej Zolnierkiewicz 2007-03-26 23:03:19 +02:00
parent f68d9320cd
commit 8799620400

View file

@ -1124,17 +1124,40 @@ static int set_io_32bit(ide_drive_t *drive, int arg)
static int set_using_dma (ide_drive_t *drive, int arg)
{
#ifdef CONFIG_BLK_DEV_IDEDMA
ide_hwif_t *hwif = drive->hwif;
int err = -EPERM;
if (!drive->id || !(drive->id->capability & 1))
return -EPERM;
if (HWIF(drive)->ide_dma_check == NULL)
return -EPERM;
goto out;
if (hwif->ide_dma_check == NULL)
goto out;
err = -EBUSY;
if (ide_spin_wait_hwgroup(drive))
goto out;
/*
* set ->busy flag, unlock and let it ride
*/
hwif->hwgroup->busy = 1;
spin_unlock_irq(&ide_lock);
err = 0;
if (arg) {
if (ide_set_dma(drive))
return -EIO;
if (HWIF(drive)->ide_dma_on(drive)) return -EIO;
if (ide_set_dma(drive) || hwif->ide_dma_on(drive))
err = -EIO;
} else
ide_dma_off(drive);
return 0;
/*
* lock, clear ->busy flag and unlock before leaving
*/
spin_lock_irq(&ide_lock);
hwif->hwgroup->busy = 0;
spin_unlock_irq(&ide_lock);
out:
return err;
#else
return -EPERM;
#endif