Gitweb:     
http://git.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=8799620400b0b1a4729d8be828b5bfb3d2a8db1a
Commit:     8799620400b0b1a4729d8be828b5bfb3d2a8db1a
Parent:     f68d9320cd06fdec19735143b42e5197b63165b4
Author:     Bartlomiej Zolnierkiewicz <[EMAIL PROTECTED]>
AuthorDate: Mon Mar 26 23:03:19 2007 +0200
Committer:  Bartlomiej Zolnierkiewicz <[EMAIL PROTECTED]>
CommitDate: Mon Mar 26 23:03:19 2007 +0200

    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 <[EMAIL PROTECTED]>
    Cc: Alan Cox <[EMAIL PROTECTED]>
    Signed-off-by: Bartlomiej Zolnierkiewicz <[EMAIL PROTECTED]>
---
 drivers/ide/ide.c |   37 ++++++++++++++++++++++++++++++-------
 1 files changed, 30 insertions(+), 7 deletions(-)

diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c
index 695610f..a6f098f 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)
 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
-
To unsubscribe from this list: send the line "unsubscribe git-commits-head" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to