mirror of
https://github.com/adulau/aha.git
synced 2025-01-01 13:46:24 +00:00
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>
This commit is contained in:
parent
f68d9320cd
commit
8799620400
1 changed files with 30 additions and 7 deletions
|
@ -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)
|
static int set_using_dma (ide_drive_t *drive, int arg)
|
||||||
{
|
{
|
||||||
#ifdef CONFIG_BLK_DEV_IDEDMA
|
#ifdef CONFIG_BLK_DEV_IDEDMA
|
||||||
|
ide_hwif_t *hwif = drive->hwif;
|
||||||
|
int err = -EPERM;
|
||||||
|
|
||||||
if (!drive->id || !(drive->id->capability & 1))
|
if (!drive->id || !(drive->id->capability & 1))
|
||||||
return -EPERM;
|
goto out;
|
||||||
if (HWIF(drive)->ide_dma_check == NULL)
|
|
||||||
return -EPERM;
|
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 (arg) {
|
||||||
if (ide_set_dma(drive))
|
if (ide_set_dma(drive) || hwif->ide_dma_on(drive))
|
||||||
return -EIO;
|
err = -EIO;
|
||||||
if (HWIF(drive)->ide_dma_on(drive)) return -EIO;
|
|
||||||
} else
|
} else
|
||||||
ide_dma_off(drive);
|
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
|
#else
|
||||||
return -EPERM;
|
return -EPERM;
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in a new issue