Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e50362ec authored by Albert Lee's avatar Albert Lee Committed by Jeff Garzik
Browse files

[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: default avatarAlbert Lee <albertcc@tw.ibm.com>
Signed-off-by: default avatarJeff Garzik <jgarzik@pobox.com>
parent 312f7da2
Loading
Loading
Loading
Loading
+19 −0
Original line number Diff line number Diff line
@@ -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);

+5 −2
Original line number Diff line number Diff line
@@ -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 */
+2 −2
Original line number Diff line number Diff line
@@ -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);
		}

+8 −5
Original line number Diff line number Diff line
@@ -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);
		}
	}
+5 −6
Original line number Diff line number Diff line
@@ -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);
Loading