[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>
This commit is contained in:
parent
312f7da282
commit
e50362eccd
@ -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);
|
||||
|
||||
|
@ -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 */
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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? */
|
||||
|
Loading…
Reference in New Issue
Block a user