Skip to content

Commit

Permalink
ide: fix locking for manual DMA enable/disable ("hdparm -d")
Browse files Browse the repository at this point in the history
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 <[email protected]>
Cc: Alan Cox <[email protected]>
Signed-off-by: Bartlomiej Zolnierkiewicz <[email protected]>
  • Loading branch information
bzolnier committed Mar 26, 2007
1 parent f68d932 commit 8799620
Showing 1 changed file with 30 additions and 7 deletions.
37 changes: 30 additions & 7 deletions drivers/ide/ide.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down

0 comments on commit 8799620

Please sign in to comment.