diff options
author | Albert Lee <albertcc@tw.ibm.com> | 2005-09-27 17:39:50 +0800 |
---|---|---|
committer | Jeff Garzik <jgarzik@pobox.com> | 2005-09-28 12:07:13 -0400 |
commit | e50362eccd8809a224cda5f71714a088ba37b2ab (patch) | |
tree | 762b753691ef8c4645efaa677b32c57fd33ecbc0 | |
parent | 312f7da2824c82800ee78d6190f12854456957af (diff) | |
download | op-kernel-dev-e50362eccd8809a224cda5f71714a088ba37b2ab.zip op-kernel-dev-e50362eccd8809a224cda5f71714a088ba37b2ab.tar.gz |
[PATCH] libata: interrupt driven pio for LLD
libata.h:
libata-core:
Add ATA_FLAG_PIO_POLLING flag for LLDs that expect interrupt for
command completion only.
sata_nv.c:
sata_vsc.c:
irq handler is wrapper around ata_host_intr(), can handle PIO interrupts.
sata_promise.c:
sata_sx4.c:
sata_qstor.c:
sata_mv.c:
Private irq handler.
Polling mode ATA_FLAG_PIO_POLLING used for compatibility.
Signed-off-by: Albert Lee <albertcc@tw.ibm.com>
Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
-rw-r--r-- | drivers/scsi/libata-core.c | 19 | ||||
-rw-r--r-- | drivers/scsi/sata_mv.c | 7 | ||||
-rw-r--r-- | drivers/scsi/sata_nv.c | 4 | ||||
-rw-r--r-- | drivers/scsi/sata_promise.c | 13 | ||||
-rw-r--r-- | drivers/scsi/sata_qstor.c | 11 | ||||
-rw-r--r-- | drivers/scsi/sata_sx4.c | 7 | ||||
-rw-r--r-- | drivers/scsi/sata_vsc.c | 6 | ||||
-rw-r--r-- | include/linux/libata.h | 2 |
8 files changed, 48 insertions, 21 deletions
diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index cc2d130..f8a590e 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -3356,6 +3356,25 @@ int ata_qc_issue_prot(struct ata_queued_cmd *qc) { struct ata_port *ap = qc->ap; + /* Use polling pio if the LLD doesn't handle + * interrupt driven pio and atapi CDB interrupt. + */ + if (ap->flags & ATA_FLAG_PIO_POLLING) { + switch (qc->tf.protocol) { + case ATA_PROT_PIO: + case ATA_PROT_ATAPI: + case ATA_PROT_ATAPI_NODATA: + qc->tf.flags |= ATA_TFLAG_POLLING; + break; + case ATA_PROT_ATAPI_DMA: + if (qc->dev->flags & ATA_DFLAG_CDB_INTR) + BUG(); + break; + default: + break; + } + } + /* select the device */ ata_dev_select(ap, qc->dev->devno, 1, 0); diff --git a/drivers/scsi/sata_mv.c b/drivers/scsi/sata_mv.c index ea76fe4..b8f1f69 100644 --- a/drivers/scsi/sata_mv.c +++ b/drivers/scsi/sata_mv.c @@ -241,7 +241,8 @@ static struct ata_port_info mv_port_info[] = { { /* chip_504x */ .sht = &mv_sht, .host_flags = (ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | - ATA_FLAG_SATA_RESET | ATA_FLAG_MMIO), + ATA_FLAG_SATA_RESET | ATA_FLAG_MMIO | + ATA_FLAG_PIO_POLLING), .pio_mask = 0x1f, /* pio4-0 */ .udma_mask = 0, /* 0x7f (udma6-0 disabled for now) */ .port_ops = &mv_ops, @@ -250,7 +251,7 @@ static struct ata_port_info mv_port_info[] = { .sht = &mv_sht, .host_flags = (ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | ATA_FLAG_SATA_RESET | ATA_FLAG_MMIO | - MV_FLAG_DUAL_HC), + ATA_FLAG_PIO_POLLING | MV_FLAG_DUAL_HC), .pio_mask = 0x1f, /* pio4-0 */ .udma_mask = 0, /* 0x7f (udma6-0 disabled for now) */ .port_ops = &mv_ops, @@ -259,6 +260,7 @@ static struct ata_port_info mv_port_info[] = { .sht = &mv_sht, .host_flags = (ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | ATA_FLAG_SATA_RESET | ATA_FLAG_MMIO | + ATA_FLAG_PIO_POLLING | MV_FLAG_IRQ_COALESCE | MV_FLAG_BDMA), .pio_mask = 0x1f, /* pio4-0 */ .udma_mask = 0, /* 0x7f (udma6-0 disabled for now) */ @@ -268,6 +270,7 @@ static struct ata_port_info mv_port_info[] = { .sht = &mv_sht, .host_flags = (ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | ATA_FLAG_SATA_RESET | ATA_FLAG_MMIO | + ATA_FLAG_PIO_POLLING | MV_FLAG_IRQ_COALESCE | MV_FLAG_DUAL_HC | MV_FLAG_BDMA), .pio_mask = 0x1f, /* pio4-0 */ diff --git a/drivers/scsi/sata_nv.c b/drivers/scsi/sata_nv.c index c05653c..8b7e871e 100644 --- a/drivers/scsi/sata_nv.c +++ b/drivers/scsi/sata_nv.c @@ -304,11 +304,11 @@ static irqreturn_t nv_interrupt (int irq, void *dev_instance, ap = host_set->ports[i]; if (ap && - !(ap->flags & (ATA_FLAG_PORT_DISABLED | ATA_FLAG_NOINTR))) { + !(ap->flags & ATA_FLAG_PORT_DISABLED)) { struct ata_queued_cmd *qc; qc = ata_qc_from_tag(ap, ap->active_tag); - if (qc && (!(qc->tf.ctl & ATA_NIEN))) + if (qc && (!(qc->tf.flags & ATA_TFLAG_POLLING))) handled += ata_host_intr(ap, qc); } diff --git a/drivers/scsi/sata_promise.c b/drivers/scsi/sata_promise.c index def7e0d..f67deb0 100644 --- a/drivers/scsi/sata_promise.c +++ b/drivers/scsi/sata_promise.c @@ -162,7 +162,8 @@ static struct ata_port_info pdc_port_info[] = { { .sht = &pdc_ata_sht, .host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | - ATA_FLAG_SRST | ATA_FLAG_MMIO, + ATA_FLAG_SRST | ATA_FLAG_MMIO | + ATA_FLAG_PIO_POLLING, .pio_mask = 0x1f, /* pio0-4 */ .mwdma_mask = 0x07, /* mwdma0-2 */ .udma_mask = 0x7f, /* udma0-6 ; FIXME */ @@ -173,7 +174,8 @@ static struct ata_port_info pdc_port_info[] = { { .sht = &pdc_ata_sht, .host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | - ATA_FLAG_SRST | ATA_FLAG_MMIO, + ATA_FLAG_SRST | ATA_FLAG_MMIO | + ATA_FLAG_PIO_POLLING, .pio_mask = 0x1f, /* pio0-4 */ .mwdma_mask = 0x07, /* mwdma0-2 */ .udma_mask = 0x7f, /* udma0-6 ; FIXME */ @@ -184,7 +186,8 @@ static struct ata_port_info pdc_port_info[] = { { .sht = &pdc_ata_sht, .host_flags = ATA_FLAG_NO_LEGACY | ATA_FLAG_SRST | - ATA_FLAG_MMIO | ATA_FLAG_SLAVE_POSS, + ATA_FLAG_MMIO | ATA_FLAG_SLAVE_POSS | + ATA_FLAG_PIO_POLLING, .pio_mask = 0x1f, /* pio0-4 */ .mwdma_mask = 0x07, /* mwdma0-2 */ .udma_mask = 0x7f, /* udma0-6 ; FIXME */ @@ -493,11 +496,11 @@ static irqreturn_t pdc_interrupt (int irq, void *dev_instance, struct pt_regs *r ap = host_set->ports[i]; tmp = mask & (1 << (i + 1)); if (tmp && ap && - !(ap->flags & (ATA_FLAG_PORT_DISABLED | ATA_FLAG_NOINTR))) { + !(ap->flags & ATA_FLAG_PORT_DISABLED)) { struct ata_queued_cmd *qc; qc = ata_qc_from_tag(ap, ap->active_tag); - if (qc && (!(qc->tf.ctl & ATA_NIEN))) + if (qc && (!(qc->tf.flags & ATA_TFLAG_POLLING))) handled += pdc_host_intr(ap, qc); } } diff --git a/drivers/scsi/sata_qstor.c b/drivers/scsi/sata_qstor.c index ffcdeb6..a604afa 100644 --- a/drivers/scsi/sata_qstor.c +++ b/drivers/scsi/sata_qstor.c @@ -175,7 +175,7 @@ static struct ata_port_info qs_port_info[] = { .host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | ATA_FLAG_SATA_RESET | //FIXME ATA_FLAG_SRST | - ATA_FLAG_MMIO, + ATA_FLAG_MMIO | ATA_FLAG_PIO_POLLING, .pio_mask = 0x10, /* pio4 */ .udma_mask = 0x7f, /* udma0-6 */ .port_ops = &qs_ata_ops, @@ -389,14 +389,13 @@ static inline unsigned int qs_intr_pkt(struct ata_host_set *host_set) DPRINTK("SFF=%08x%08x: sCHAN=%u sHST=%d sDST=%02x\n", sff1, sff0, port_no, sHST, sDST); handled = 1; - if (ap && !(ap->flags & - (ATA_FLAG_PORT_DISABLED|ATA_FLAG_NOINTR))) { + if (ap && !(ap->flags & ATA_FLAG_PORT_DISABLED)) { struct ata_queued_cmd *qc; struct qs_port_priv *pp = ap->private_data; if (!pp || pp->state != qs_state_pkt) continue; qc = ata_qc_from_tag(ap, ap->active_tag); - if (qc && (!(qc->tf.ctl & ATA_NIEN))) { + if (qc && (!(qc->tf.flags & ATA_TFLAG_POLLING))) { switch (sHST) { case 0: /* sucessful CPB */ case 3: /* device error */ @@ -422,13 +421,13 @@ static inline unsigned int qs_intr_mmio(struct ata_host_set *host_set) struct ata_port *ap; ap = host_set->ports[port_no]; if (ap && - !(ap->flags & (ATA_FLAG_PORT_DISABLED | ATA_FLAG_NOINTR))) { + !(ap->flags & ATA_FLAG_PORT_DISABLED)) { struct ata_queued_cmd *qc; struct qs_port_priv *pp = ap->private_data; if (!pp || pp->state != qs_state_mmio) continue; qc = ata_qc_from_tag(ap, ap->active_tag); - if (qc && (!(qc->tf.ctl & ATA_NIEN))) { + if (qc && (!(qc->tf.flags & ATA_TFLAG_POLLING))) { /* check main status, clearing INTRQ */ u8 status = ata_chk_status(ap); diff --git a/drivers/scsi/sata_sx4.c b/drivers/scsi/sata_sx4.c index 540a851..a9f9f76 100644 --- a/drivers/scsi/sata_sx4.c +++ b/drivers/scsi/sata_sx4.c @@ -219,7 +219,8 @@ static struct ata_port_info pdc_port_info[] = { { .sht = &pdc_sata_sht, .host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | - ATA_FLAG_SRST | ATA_FLAG_MMIO, + ATA_FLAG_SRST | ATA_FLAG_MMIO | + ATA_FLAG_PIO_POLLING, .pio_mask = 0x1f, /* pio0-4 */ .mwdma_mask = 0x07, /* mwdma0-2 */ .udma_mask = 0x7f, /* udma0-6 ; FIXME */ @@ -832,11 +833,11 @@ static irqreturn_t pdc20621_interrupt (int irq, void *dev_instance, struct pt_re tmp = mask & (1 << i); VPRINTK("seq %u, port_no %u, ap %p, tmp %x\n", i, port_no, ap, tmp); if (tmp && ap && - !(ap->flags & (ATA_FLAG_PORT_DISABLED | ATA_FLAG_NOINTR))) { + !(ap->flags & ATA_FLAG_PORT_DISABLED)) { struct ata_queued_cmd *qc; qc = ata_qc_from_tag(ap, ap->active_tag); - if (qc && (!(qc->tf.ctl & ATA_NIEN))) + if (qc && (!(qc->tf.flags & ATA_TFLAG_POLLING))) handled += pdc20621_host_intr(ap, qc, (i > 4), mmio_base); } diff --git a/drivers/scsi/sata_vsc.c b/drivers/scsi/sata_vsc.c index cf94e01..92378d7 100644 --- a/drivers/scsi/sata_vsc.c +++ b/drivers/scsi/sata_vsc.c @@ -193,12 +193,12 @@ static irqreturn_t vsc_sata_interrupt (int irq, void *dev_instance, struct ata_port *ap; ap = host_set->ports[i]; - if (ap && !(ap->flags & - (ATA_FLAG_PORT_DISABLED|ATA_FLAG_NOINTR))) { + if (ap && + !(ap->flags & ATA_FLAG_PORT_DISABLED)) { struct ata_queued_cmd *qc; qc = ata_qc_from_tag(ap, ap->active_tag); - if (qc && (!(qc->tf.ctl & ATA_NIEN))) + if (qc && (!(qc->tf.flags & ATA_TFLAG_POLLING))) handled += ata_host_intr(ap, qc); } } diff --git a/include/linux/libata.h b/include/linux/libata.h index 9ac2b69..ea8ab29 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -116,6 +116,8 @@ enum { ATA_FLAG_MMIO = (1 << 6), /* use MMIO, not PIO */ ATA_FLAG_SATA_RESET = (1 << 7), /* use COMRESET */ ATA_FLAG_PIO_DMA = (1 << 8), /* PIO cmds via DMA */ + ATA_FLAG_PIO_POLLING = (1 << 9), /* use polling PIO if LLD + * doesn't handle PIO interrupts */ ATA_QCFLAG_ACTIVE = (1 << 1), /* cmd not yet ack'd to scsi lyer */ ATA_QCFLAG_SG = (1 << 3), /* have s/g table? */ |