]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - drivers/ide/ide-dma.c
ide: remove try_to_identify() wrapper
[linux-2.6-omap-h63xx.git] / drivers / ide / ide-dma.c
index fffd11717b2d169e3557c501db7c51780db5a4b1..a878f4734f8129139efc995bd8c65337f6dad0fc 100644 (file)
@@ -96,7 +96,7 @@ ide_startstop_t ide_dma_intr(ide_drive_t *drive)
 
        if (OK_STAT(stat, DRIVE_READY, drive->bad_wstat | ATA_DRQ)) {
                if (!dma_stat) {
-                       struct request *rq = hwif->hwgroup->rq;
+                       struct request *rq = hwif->rq;
 
                        task_end_request(drive, rq, stat);
                        return ide_stopped;
@@ -128,6 +128,7 @@ int ide_build_sglist(ide_drive_t *drive, struct request *rq)
 {
        ide_hwif_t *hwif = drive->hwif;
        struct scatterlist *sg = hwif->sg_table;
+       int i;
 
        ide_map_sg(drive, rq);
 
@@ -136,8 +137,13 @@ int ide_build_sglist(ide_drive_t *drive, struct request *rq)
        else
                hwif->sg_dma_direction = DMA_TO_DEVICE;
 
-       return dma_map_sg(hwif->dev, sg, hwif->sg_nents,
-                         hwif->sg_dma_direction);
+       i = dma_map_sg(hwif->dev, sg, hwif->sg_nents, hwif->sg_dma_direction);
+       if (i) {
+               hwif->orig_sg_nents = hwif->sg_nents;
+               hwif->sg_nents = i;
+       }
+
+       return i;
 }
 EXPORT_SYMBOL_GPL(ide_build_sglist);
 
@@ -156,7 +162,7 @@ void ide_destroy_dmatable(ide_drive_t *drive)
 {
        ide_hwif_t *hwif = drive->hwif;
 
-       dma_unmap_sg(hwif->dev, hwif->sg_table, hwif->sg_nents,
+       dma_unmap_sg(hwif->dev, hwif->sg_table, hwif->orig_sg_nents,
                     hwif->sg_dma_direction);
 }
 EXPORT_SYMBOL_GPL(ide_destroy_dmatable);
@@ -464,6 +470,63 @@ void ide_dma_timeout(ide_drive_t *drive)
 }
 EXPORT_SYMBOL_GPL(ide_dma_timeout);
 
+/*
+ * un-busy the port etc, and clear any pending DMA status. we want to
+ * retry the current request in pio mode instead of risking tossing it
+ * all away
+ */
+ide_startstop_t ide_dma_timeout_retry(ide_drive_t *drive, int error)
+{
+       ide_hwif_t *hwif = drive->hwif;
+       struct request *rq;
+       ide_startstop_t ret = ide_stopped;
+
+       /*
+        * end current dma transaction
+        */
+
+       if (error < 0) {
+               printk(KERN_WARNING "%s: DMA timeout error\n", drive->name);
+               (void)hwif->dma_ops->dma_end(drive);
+               ret = ide_error(drive, "dma timeout error",
+                               hwif->tp_ops->read_status(hwif));
+       } else {
+               printk(KERN_WARNING "%s: DMA timeout retry\n", drive->name);
+               hwif->dma_ops->dma_timeout(drive);
+       }
+
+       /*
+        * disable dma for now, but remember that we did so because of
+        * a timeout -- we'll reenable after we finish this next request
+        * (or rather the first chunk of it) in pio.
+        */
+       drive->dev_flags |= IDE_DFLAG_DMA_PIO_RETRY;
+       drive->retry_pio++;
+       ide_dma_off_quietly(drive);
+
+       /*
+        * un-busy drive etc and make sure request is sane
+        */
+
+       rq = hwif->rq;
+       if (!rq)
+               goto out;
+
+       hwif->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;
+       rq->buffer = bio_data(rq->bio);
+out:
+       return ret;
+}
+
 void ide_release_dma_engine(ide_hwif_t *hwif)
 {
        if (hwif->dmatable_cpu) {