Merge git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb-2.6
[safe/jmp/linux-2.6] / drivers / ide / ide-park.c
index 63d01c5..88a380c 100644 (file)
@@ -1,4 +1,5 @@
 #include <linux/kernel.h>
+#include <linux/gfp.h>
 #include <linux/ide.h>
 #include <linux/jiffies.h>
 #include <linux/blkdev.h>
@@ -7,28 +8,28 @@ DECLARE_WAIT_QUEUE_HEAD(ide_park_wq);
 
 static void issue_park_cmd(ide_drive_t *drive, unsigned long timeout)
 {
-       ide_hwgroup_t *hwgroup = drive->hwif->hwgroup;
+       ide_hwif_t *hwif = drive->hwif;
        struct request_queue *q = drive->queue;
        struct request *rq;
        int rc;
 
        timeout += jiffies;
-       spin_lock_irq(&hwgroup->lock);
+       spin_lock_irq(&hwif->lock);
        if (drive->dev_flags & IDE_DFLAG_PARKED) {
                int reset_timer = time_before(timeout, drive->sleep);
+               int start_queue = 0;
 
                drive->sleep = timeout;
                wake_up_all(&ide_park_wq);
-               if (reset_timer && hwgroup->sleeping &&
-                   del_timer(&hwgroup->timer)) {
-                       hwgroup->sleeping = 0;
-                       hwgroup->busy = 0;
-                       blk_start_queueing(q);
-               }
-               spin_unlock_irq(&hwgroup->lock);
+               if (reset_timer && del_timer(&hwif->timer))
+                       start_queue = 1;
+               spin_unlock_irq(&hwif->lock);
+
+               if (start_queue)
+                       blk_run_queue(q);
                return;
        }
-       spin_unlock_irq(&hwgroup->lock);
+       spin_unlock_irq(&hwif->lock);
 
        rq = blk_get_request(q, READ, __GFP_WAIT);
        rq->cmd[0] = REQ_PARK_HEADS;
@@ -57,25 +58,52 @@ out:
        return;
 }
 
+ide_startstop_t ide_do_park_unpark(ide_drive_t *drive, struct request *rq)
+{
+       struct ide_cmd cmd;
+       struct ide_taskfile *tf = &cmd.tf;
+
+       memset(&cmd, 0, sizeof(cmd));
+       if (rq->cmd[0] == REQ_PARK_HEADS) {
+               drive->sleep = *(unsigned long *)rq->special;
+               drive->dev_flags |= IDE_DFLAG_SLEEPING;
+               tf->command = ATA_CMD_IDLEIMMEDIATE;
+               tf->feature = 0x44;
+               tf->lbal = 0x4c;
+               tf->lbam = 0x4e;
+               tf->lbah = 0x55;
+               cmd.valid.out.tf = IDE_VALID_OUT_TF | IDE_VALID_DEVICE;
+               cmd.valid.in.tf  = IDE_VALID_IN_TF  | IDE_VALID_DEVICE;
+       } else          /* cmd == REQ_UNPARK_HEADS */
+               tf->command = ATA_CMD_CHK_POWER;
+
+       cmd.tf_flags |= IDE_TFLAG_CUSTOM_HANDLER;
+       cmd.protocol = ATA_PROT_NODATA;
+
+       cmd.rq = rq;
+
+       return do_rw_taskfile(drive, &cmd);
+}
+
 ssize_t ide_park_show(struct device *dev, struct device_attribute *attr,
                      char *buf)
 {
        ide_drive_t *drive = to_ide_device(dev);
-       ide_hwgroup_t *hwgroup = drive->hwif->hwgroup;
+       ide_hwif_t *hwif = drive->hwif;
        unsigned long now;
        unsigned int msecs;
 
        if (drive->dev_flags & IDE_DFLAG_NO_UNLOAD)
                return -EOPNOTSUPP;
 
-       spin_lock_irq(&hwgroup->lock);
+       spin_lock_irq(&hwif->lock);
        now = jiffies;
        if (drive->dev_flags & IDE_DFLAG_PARKED &&
            time_after(drive->sleep, now))
                msecs = jiffies_to_msecs(drive->sleep - now);
        else
                msecs = 0;
-       spin_unlock_irq(&hwgroup->lock);
+       spin_unlock_irq(&hwif->lock);
 
        return snprintf(buf, 20, "%u\n", msecs);
 }