fedora core 2.6.10-1.12-FC2
[linux-2.6.git] / drivers / ide / ide-io.c
index 9c6b720..b24d550 100644 (file)
@@ -47,6 +47,7 @@
 #include <linux/seq_file.h>
 #include <linux/device.h>
 #include <linux/kmod.h>
+#include <linux/scatterlist.h>
 
 #include <asm/byteorder.h>
 #include <asm/irq.h>
@@ -598,8 +599,6 @@ media_out:
        return ide_stopped;
 }
 
-EXPORT_SYMBOL(ide_error);
-
 /**
  *     ide_abort       -       abort pending IDE operatins
  *     @drive: drive the error occurred on
@@ -612,36 +611,42 @@ EXPORT_SYMBOL(ide_error);
  *     This differs fundamentally from ide_error because in 
  *     this case the command is doing just fine when we
  *     blow it away.
+ *
+ *     FIXME: need to fix locking corner cases
  */
  
 ide_startstop_t ide_abort(ide_drive_t *drive, const char *msg)
 {
        ide_hwif_t *hwif;
        struct request *rq;
+       unsigned long flags;
 
-       if (drive == NULL || (rq = HWGROUP(drive)->rq) == NULL)
+       spin_lock_irqsave(&ide_lock, flags);
+       if (drive == NULL || (rq = HWGROUP(drive)->rq) == NULL) {
+               spin_unlock_irqrestore(&ide_lock, flags);
                return ide_stopped;
-
+       }
        hwif = HWIF(drive);
        /* retry only "normal" I/O: */
        if (rq->flags & (REQ_DRIVE_CMD | REQ_DRIVE_TASK)) {
                rq->errors = 1;
+               spin_unlock_irqrestore(&ide_lock, flags);
                ide_end_drive_cmd(drive, BUSY_STAT, 0);
                return ide_stopped;
        }
        if (rq->flags & REQ_DRIVE_TASKFILE) {
                rq->errors = 1;
+               spin_unlock_irqrestore(&ide_lock, flags);
                ide_end_drive_cmd(drive, BUSY_STAT, 0);
                return ide_stopped;
        }
 
        rq->errors |= ERROR_RESET;
+       spin_unlock_irqrestore(&ide_lock, flags);
        DRIVER(drive)->end_request(drive, 0, 0);
        return ide_stopped;
 }
 
-EXPORT_SYMBOL(ide_abort);
-
 /**
  *     ide_cmd         -       issue a simple drive command
  *     @drive: drive the command is for
@@ -653,7 +658,8 @@ EXPORT_SYMBOL(ide_abort);
  *     The drive must be selected beforehand.
  */
 
-void ide_cmd (ide_drive_t *drive, u8 cmd, u8 nsect, ide_handler_t *handler)
+static void ide_cmd (ide_drive_t *drive, u8 cmd, u8 nsect,
+               ide_handler_t *handler)
 {
        ide_hwif_t *hwif = HWIF(drive);
        if (IDE_CONTROL_REG)
@@ -663,8 +669,6 @@ void ide_cmd (ide_drive_t *drive, u8 cmd, u8 nsect, ide_handler_t *handler)
        ide_execute_command(drive, cmd, handler, WAIT_CMD, NULL);
 }
 
-EXPORT_SYMBOL(ide_cmd);
-
 /**
  *     drive_cmd_intr          -       drive command completion interrupt
  *     @drive: drive the completion interrupt occurred on
@@ -675,7 +679,7 @@ EXPORT_SYMBOL(ide_cmd);
  *     the request
  */
  
-ide_startstop_t drive_cmd_intr (ide_drive_t *drive)
+static ide_startstop_t drive_cmd_intr (ide_drive_t *drive)
 {
        struct request *rq = HWGROUP(drive)->rq;
        ide_hwif_t *hwif = HWIF(drive);
@@ -700,8 +704,6 @@ ide_startstop_t drive_cmd_intr (ide_drive_t *drive)
        return ide_stopped;
 }
 
-EXPORT_SYMBOL(drive_cmd_intr);
-
 /**
  *     do_special              -       issue some special commands
  *     @drive: drive the command is for
@@ -711,7 +713,7 @@ EXPORT_SYMBOL(drive_cmd_intr);
  *     back.
  */
 
-ide_startstop_t do_special (ide_drive_t *drive)
+static ide_startstop_t do_special (ide_drive_t *drive)
 {
        special_t *s = &drive->special;
 
@@ -728,7 +730,33 @@ ide_startstop_t do_special (ide_drive_t *drive)
                return DRIVER(drive)->special(drive);
 }
 
-EXPORT_SYMBOL(do_special);
+void ide_map_sg(ide_drive_t *drive, struct request *rq)
+{
+       ide_hwif_t *hwif = drive->hwif;
+       struct scatterlist *sg = hwif->sg_table;
+
+       if (hwif->sg_mapped)    /* needed by ide-scsi */
+               return;
+
+       if ((rq->flags & REQ_DRIVE_TASKFILE) == 0) {
+               hwif->sg_nents = blk_rq_map_sg(drive->queue, rq, sg);
+       } else {
+               sg_init_one(sg, rq->buffer, rq->nr_sectors * SECTOR_SIZE);
+               hwif->sg_nents = 1;
+       }
+}
+
+EXPORT_SYMBOL_GPL(ide_map_sg);
+
+void ide_init_sg_cmd(ide_drive_t *drive, struct request *rq)
+{
+       ide_hwif_t *hwif = drive->hwif;
+
+       hwif->nsect = hwif->nleft = rq->nr_sectors;
+       hwif->cursg = hwif->cursg_ofs = 0;
+}
+
+EXPORT_SYMBOL_GPL(ide_init_sg_cmd);
 
 /**
  *     execute_drive_command   -       issue special drive command
@@ -742,7 +770,8 @@ EXPORT_SYMBOL(do_special);
  *     all commands to finish. Don't do this as that is due to change
  */
 
-ide_startstop_t execute_drive_cmd (ide_drive_t *drive, struct request *rq)
+static ide_startstop_t execute_drive_cmd (ide_drive_t *drive,
+               struct request *rq)
 {
        ide_hwif_t *hwif = HWIF(drive);
        if (rq->flags & REQ_DRIVE_TASKFILE) {
@@ -753,6 +782,17 @@ ide_startstop_t execute_drive_cmd (ide_drive_t *drive, struct request *rq)
 
                hwif->data_phase = args->data_phase;
 
+               switch (hwif->data_phase) {
+               case TASKFILE_MULTI_OUT:
+               case TASKFILE_OUT:
+               case TASKFILE_MULTI_IN:
+               case TASKFILE_IN:
+                       ide_init_sg_cmd(drive, rq);
+                       ide_map_sg(drive, rq);
+               default:
+                       break;
+               }
+
                if (args->tf_out_flags.all != 0) 
                        return flagged_taskfile(drive, args);
                return do_rw_taskfile(drive, args);
@@ -821,8 +861,6 @@ done:
        return ide_stopped;
 }
 
-EXPORT_SYMBOL(execute_drive_cmd);
-
 /**
  *     start_request   -       start of I/O and command issuing for IDE
  *
@@ -834,7 +872,7 @@ EXPORT_SYMBOL(execute_drive_cmd);
  *     FIXME: this function needs a rename
  */
  
-ide_startstop_t start_request (ide_drive_t *drive, struct request *rq)
+static ide_startstop_t start_request (ide_drive_t *drive, struct request *rq)
 {
        ide_startstop_t startstop;
        sector_t block;
@@ -925,8 +963,6 @@ kill_rq:
        return ide_stopped;
 }
 
-EXPORT_SYMBOL(start_request);
-
 /**
  *     ide_stall_queue         -       pause an IDE device
  *     @drive: drive to stall
@@ -1049,10 +1085,7 @@ repeat:
  * the driver.  This makes the driver much more friendlier to shared IRQs
  * than previous designs, while remaining 100% (?) SMP safe and capable.
  */
-/* --BenH: made non-static as ide-pmac.c uses it to kick the hwgroup back
- *         into life on wakeup from machine sleep.
- */ 
-void ide_do_request (ide_hwgroup_t *hwgroup, int masked_irq)
+static void ide_do_request (ide_hwgroup_t *hwgroup, int masked_irq)
 {
        ide_drive_t     *drive;
        ide_hwif_t      *hwif;
@@ -1184,8 +1217,6 @@ void ide_do_request (ide_hwgroup_t *hwgroup, int masked_irq)
        }
 }
 
-EXPORT_SYMBOL(ide_do_request);
-
 /*
  * Passes the stuff to ide_do_request
  */
@@ -1238,12 +1269,15 @@ static ide_startstop_t ide_dma_timeout_retry(ide_drive_t *drive, int error)
        HWGROUP(drive)->rq = NULL;
 
        rq->errors = 0;
+
+       if (!rq->bio)
+               goto out;
+
        rq->sector = rq->bio->bi_sector;
        rq->current_nr_sectors = bio_iovec(rq->bio)->bv_len >> 9;
        rq->hard_cur_sectors = rq->current_nr_sectors;
-       if (rq->bio)
-               rq->buffer = NULL;
-
+       rq->buffer = bio_data(rq->bio);
+out:
        return ret;
 }
 
@@ -1347,8 +1381,6 @@ void ide_timer_expiry (unsigned long data)
        spin_unlock_irqrestore(&ide_lock, flags);
 }
 
-EXPORT_SYMBOL(ide_timer_expiry);
-
 /**
  *     unexpected_intr         -       handle an unexpected IDE interrupt
  *     @irq: interrupt line
@@ -1451,6 +1483,13 @@ irqreturn_t ide_intr (int irq, void *dev_id, struct pt_regs *regs)
                return IRQ_NONE;
        }
 
+       if (hwif->polling) {
+               /* We took an interrupt during a polled drive retune. 
+                  This should go away eventually when that code uses
+                  the polling logic like do_reset1 */
+               spin_unlock_irqrestore(&ide_lock, flags);
+               return IRQ_HANDLED;
+       }
        if ((handler = hwgroup->handler) == NULL ||
            hwgroup->poll_timeout != 0) {
                /*
@@ -1546,8 +1585,6 @@ irqreturn_t ide_intr (int irq, void *dev_id, struct pt_regs *regs)
        return IRQ_HANDLED;
 }
 
-EXPORT_SYMBOL(ide_intr);
-
 /**
  *     ide_init_drive_cmd      -       initialize a drive command request
  *     @rq: request object
@@ -1606,18 +1643,6 @@ int ide_do_drive_cmd (ide_drive_t *drive, struct request *rq, ide_action_t actio
        int where = ELEVATOR_INSERT_BACK, err;
        int must_wait = (action == ide_wait || action == ide_head_wait);
 
-#ifdef CONFIG_BLK_DEV_PDC4030
-       /*
-        *      FIXME: there should be a drive or hwif->special
-        *      handler that points here by default, not hacks
-        *      in the ide-io.c code
-        *
-        *      FIXME2: That code breaks power management if used with
-        *      this chipset, that really doesn't belong here !
-        */
-       if (HWIF(drive)->chipset == ide_pdc4030 && rq->buffer != NULL)
-               return -ENOSYS;  /* special drive cmds not supported */
-#endif
        rq->errors = 0;
        rq->rq_status = RQ_ACTIVE;