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

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

[PATCH] libata-dev: Move out the HSM code from ata_host_intr()



Move out the irq-pio HSM code from ata_host_intr() to the new ata_hsm_move() function verbatim.

Signed-off-by: default avatarAlbert Lee <albertcc@tw.ibm.com>
Signed-off-by: default avatarJeff Garzik <jeff@garzik.org>
parent 19d5d730
Loading
Loading
Loading
Loading
+106 −100
Original line number Diff line number Diff line
@@ -3805,6 +3805,111 @@ static void ata_pio_error(struct ata_port *ap)
	ata_poll_qc_complete(qc);
}

static void ata_hsm_move(struct ata_port *ap, struct ata_queued_cmd *qc,
			 u8 status)
{
	/* check error */
	if (unlikely(status & (ATA_ERR | ATA_DF))) {
		qc->err_mask |= AC_ERR_DEV;
		ap->hsm_task_state = HSM_ST_ERR;
	}

fsm_start:
	switch (ap->hsm_task_state) {
	case HSM_ST_FIRST:
		/* Some pre-ATAPI-4 devices assert INTRQ
		 * at this state when ready to receive CDB.
		 */

		/* check device status */
		if (unlikely((status & (ATA_BUSY | ATA_DRQ)) != ATA_DRQ)) {
			/* Wrong status. Let EH handle this */
			qc->err_mask |= AC_ERR_HSM;
			ap->hsm_task_state = HSM_ST_ERR;
			goto fsm_start;
		}

		atapi_send_cdb(ap, qc);

		break;

	case HSM_ST:
		/* complete command or read/write the data register */
		if (qc->tf.protocol == ATA_PROT_ATAPI) {
			/* ATAPI PIO protocol */
			if ((status & ATA_DRQ) == 0) {
				/* no more data to transfer */
				ap->hsm_task_state = HSM_ST_LAST;
				goto fsm_start;
			}

			atapi_pio_bytes(qc);

			if (unlikely(ap->hsm_task_state == HSM_ST_ERR))
				/* bad ireason reported by device */
				goto fsm_start;

		} else {
			/* ATA PIO protocol */
			if (unlikely((status & ATA_DRQ) == 0)) {
				/* handle BSY=0, DRQ=0 as error */
				qc->err_mask |= AC_ERR_HSM;
				ap->hsm_task_state = HSM_ST_ERR;
				goto fsm_start;
			}

			ata_pio_sectors(qc);

			if (ap->hsm_task_state == HSM_ST_LAST &&
			    (!(qc->tf.flags & ATA_TFLAG_WRITE))) {
				/* all data read */
				ata_altstatus(ap);
				status = ata_chk_status(ap);
				goto fsm_start;
			}
		}

		ata_altstatus(ap); /* flush */
		break;

	case HSM_ST_LAST:
		if (unlikely(status & ATA_DRQ)) {
			/* handle DRQ=1 as error */
			qc->err_mask |= AC_ERR_HSM;
			ap->hsm_task_state = HSM_ST_ERR;
			goto fsm_start;
		}

		/* no more data to transfer */
		DPRINTK("ata%u: command complete, drv_stat 0x%x\n",
			ap->id, status);

		ap->hsm_task_state = HSM_ST_IDLE;

		/* complete taskfile transaction */
		qc->err_mask |= ac_err_mask(status);
		ata_qc_complete(qc);
		break;

	case HSM_ST_ERR:
		if (qc->tf.command != ATA_CMD_PACKET)
			printk(KERN_ERR "ata%u: command error, drv_stat 0x%x host_stat 0x%x\n",
			       ap->id, status, host_stat);

		/* make sure qc->err_mask is available to
		 * know what's wrong and recover
		 */
		WARN_ON(qc->err_mask == 0);

		ap->hsm_task_state = HSM_ST_IDLE;
		ata_qc_complete(qc);
		break;
	default:
		goto idle_irq;
	}

}

static void ata_pio_task(void *_data)
{
	struct ata_port *ap = _data;
@@ -4316,106 +4421,7 @@ inline unsigned int ata_host_intr (struct ata_port *ap,
	/* ack bmdma irq events */
	ap->ops->irq_clear(ap);

	/* check error */
	if (unlikely(status & (ATA_ERR | ATA_DF))) {
		qc->err_mask |= AC_ERR_DEV;
		ap->hsm_task_state = HSM_ST_ERR;
	}

fsm_start:
	switch (ap->hsm_task_state) {
	case HSM_ST_FIRST:
		/* Some pre-ATAPI-4 devices assert INTRQ
		 * at this state when ready to receive CDB.
		 */

		/* check device status */
		if (unlikely((status & (ATA_BUSY | ATA_DRQ)) != ATA_DRQ)) {
			/* Wrong status. Let EH handle this */
			qc->err_mask |= AC_ERR_HSM;
			ap->hsm_task_state = HSM_ST_ERR;
			goto fsm_start;
		}

		atapi_send_cdb(ap, qc);

		break;

	case HSM_ST:
		/* complete command or read/write the data register */
		if (qc->tf.protocol == ATA_PROT_ATAPI) {
			/* ATAPI PIO protocol */
			if ((status & ATA_DRQ) == 0) {
				/* no more data to transfer */
				ap->hsm_task_state = HSM_ST_LAST;
				goto fsm_start;
			}

			atapi_pio_bytes(qc);

			if (unlikely(ap->hsm_task_state == HSM_ST_ERR))
				/* bad ireason reported by device */
				goto fsm_start;

		} else {
			/* ATA PIO protocol */
			if (unlikely((status & ATA_DRQ) == 0)) {
				/* handle BSY=0, DRQ=0 as error */
				qc->err_mask |= AC_ERR_HSM;
				ap->hsm_task_state = HSM_ST_ERR;
				goto fsm_start;
			}

			ata_pio_sectors(qc);

			if (ap->hsm_task_state == HSM_ST_LAST &&
			    (!(qc->tf.flags & ATA_TFLAG_WRITE))) {
				/* all data read */
				ata_altstatus(ap);
				status = ata_chk_status(ap);
				goto fsm_start;
			}
		}

		ata_altstatus(ap); /* flush */
		break;

	case HSM_ST_LAST:
		if (unlikely(status & ATA_DRQ)) {
			/* handle DRQ=1 as error */
			qc->err_mask |= AC_ERR_HSM;
			ap->hsm_task_state = HSM_ST_ERR;
			goto fsm_start;
		}

		/* no more data to transfer */
		DPRINTK("ata%u: command complete, drv_stat 0x%x\n",
			ap->id, status);

		ap->hsm_task_state = HSM_ST_IDLE;

		/* complete taskfile transaction */
		qc->err_mask |= ac_err_mask(status);
		ata_qc_complete(qc);
		break;

	case HSM_ST_ERR:
		if (qc->tf.command != ATA_CMD_PACKET)
			printk(KERN_ERR "ata%u: command error, drv_stat 0x%x host_stat 0x%x\n",
			       ap->id, status, host_stat);

		/* make sure qc->err_mask is available to
		 * know what's wrong and recover
		 */
		WARN_ON(qc->err_mask == 0);

		ap->hsm_task_state = HSM_ST_IDLE;
		ata_qc_complete(qc);
		break;
	default:
		goto idle_irq;
	}

	ata_hsm_move(ap, qc, status);
	return 1;	/* irq handled */

idle_irq: