summaryrefslogtreecommitdiffstats
path: root/drivers/scsi/libata-core.c
diff options
context:
space:
mode:
authorAlbert Lee2005-11-01 12:33:20 +0100
committerJeff Garzik2005-11-09 07:22:19 +0100
commit07f6f7d074e68d56d82e7cc5c65096033ac8dc56 (patch)
treed420722be7721691e5c56dc5a0ff326e926a58e6 /drivers/scsi/libata-core.c
parent[PATCH] libata irq-pio: eliminate unnecessary queuing in ata_pio_first_block() (diff)
downloadkernel-qcow2-linux-07f6f7d074e68d56d82e7cc5c65096033ac8dc56.tar.gz
kernel-qcow2-linux-07f6f7d074e68d56d82e7cc5c65096033ac8dc56.tar.xz
kernel-qcow2-linux-07f6f7d074e68d56d82e7cc5c65096033ac8dc56.zip
[PATCH] libata irq-pio: add read/write multiple support
- add is_multi_taskfile() to ata.h - initialize ata_device->multi_count with device identify data - use ata_pio_sectors() to support r/w multiple commands Signed-off-by: Albert Lee <albertcc@tw.ibm.com> ======== Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
Diffstat (limited to 'drivers/scsi/libata-core.c')
-rw-r--r--drivers/scsi/libata-core.c44
1 files changed, 38 insertions, 6 deletions
diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c
index 2e0e6cca327c..59a4a26bc13f 100644
--- a/drivers/scsi/libata-core.c
+++ b/drivers/scsi/libata-core.c
@@ -1261,6 +1261,12 @@ retry:
}
+ if (dev->id[59] & 0x100) {
+ dev->multi_count = dev->id[59] & 0xff;
+ DPRINTK("ata%u: dev %u multi count %u\n",
+ ap->id, device, dev->multi_count);
+ }
+
ap->host->max_cmd_len = 16;
}
@@ -2804,7 +2810,7 @@ static int ata_pio_complete (struct ata_port *ap)
* we enter, BSY will be cleared in a chk-status or two. If not,
* the drive is probably seeking or something. Snooze for a couple
* msecs, then chk-status again. If still busy, fall back to
- * HSM_ST_POLL state.
+ * HSM_ST_LAST_POLL state.
*/
drv_stat = ata_busy_wait(ap, ATA_BUSY | ATA_DRQ, 10);
if (drv_stat & (ATA_BUSY | ATA_DRQ)) {
@@ -3021,6 +3027,32 @@ static void ata_pio_sector(struct ata_queued_cmd *qc)
}
/**
+ * ata_pio_sectors - Transfer one or many 512-byte sectors.
+ * @qc: Command on going
+ *
+ * Transfer one or many ATA_SECT_SIZE of data from/to the
+ * ATA device for the DRQ request.
+ *
+ * LOCKING:
+ * Inherited from caller.
+ */
+
+static void ata_pio_sectors(struct ata_queued_cmd *qc)
+{
+ if (is_multi_taskfile(&qc->tf)) {
+ /* READ/WRITE MULTIPLE */
+ unsigned int nsect;
+
+ assert(qc->dev->multi_count);
+
+ nsect = min(qc->nsect - qc->cursect, qc->dev->multi_count);
+ while (nsect--)
+ ata_pio_sector(qc);
+ } else
+ ata_pio_sector(qc);
+}
+
+/**
* atapi_send_cdb - Write CDB bytes to hardware
* @ap: Port to which ATAPI device is attached.
* @qc: Taskfile currently active
@@ -3118,11 +3150,11 @@ static int ata_pio_first_block(struct ata_port *ap)
* send first data block.
*/
- /* ata_pio_sector() might change the state to HSM_ST_LAST.
- * so, the state is changed here before ata_pio_sector().
+ /* ata_pio_sectors() might change the state to HSM_ST_LAST.
+ * so, the state is changed here before ata_pio_sectors().
*/
ap->hsm_task_state = HSM_ST;
- ata_pio_sector(qc);
+ ata_pio_sectors(qc);
ata_altstatus(ap); /* flush */
} else
/* send CDB */
@@ -3327,7 +3359,7 @@ static void ata_pio_block(struct ata_port *ap)
return;
}
- ata_pio_sector(qc);
+ ata_pio_sectors(qc);
}
ata_altstatus(ap); /* flush */
@@ -4213,7 +4245,7 @@ fsm_start:
goto fsm_start;
}
- ata_pio_sector(qc);
+ ata_pio_sectors(qc);
if (ap->hsm_task_state == HSM_ST_LAST &&
(!(qc->tf.flags & ATA_TFLAG_WRITE))) {