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

Commit 640fdb50 authored by Jeff Garzik's avatar Jeff Garzik
Browse files

[libata] pdc_adma: convert to new exception handling (EH) framework



Signed-off-by: default avatarJeff Garzik <jeff@garzik.org>
parent 782e3b3b
Loading
Loading
Loading
Loading
+67 −15
Original line number Diff line number Diff line
@@ -92,6 +92,8 @@ enum {

	/* CPB bits */
	cDONE			= (1 << 0),
	cATERR			= (1 << 3),

	cVLD			= (1 << 0),
	cDAT			= (1 << 2),
	cIEN			= (1 << 3),
@@ -131,14 +133,15 @@ static int adma_ata_init_one (struct pci_dev *pdev,
static int adma_port_start(struct ata_port *ap);
static void adma_host_stop(struct ata_host *host);
static void adma_port_stop(struct ata_port *ap);
static void adma_phy_reset(struct ata_port *ap);
static void adma_qc_prep(struct ata_queued_cmd *qc);
static unsigned int adma_qc_issue(struct ata_queued_cmd *qc);
static int adma_check_atapi_dma(struct ata_queued_cmd *qc);
static void adma_bmdma_stop(struct ata_queued_cmd *qc);
static u8 adma_bmdma_status(struct ata_port *ap);
static void adma_irq_clear(struct ata_port *ap);
static void adma_eng_timeout(struct ata_port *ap);
static void adma_freeze(struct ata_port *ap);
static void adma_thaw(struct ata_port *ap);
static void adma_error_handler(struct ata_port *ap);

static struct scsi_host_template adma_ata_sht = {
	.module			= THIS_MODULE,
@@ -165,12 +168,13 @@ static const struct ata_port_operations adma_ata_ops = {
	.exec_command		= ata_exec_command,
	.check_status		= ata_check_status,
	.dev_select		= ata_std_dev_select,
	.phy_reset		= adma_phy_reset,
	.check_atapi_dma	= adma_check_atapi_dma,
	.data_xfer		= ata_data_xfer,
	.qc_prep		= adma_qc_prep,
	.qc_issue		= adma_qc_issue,
	.eng_timeout		= adma_eng_timeout,
	.freeze			= adma_freeze,
	.thaw			= adma_thaw,
	.error_handler		= adma_error_handler,
	.irq_clear		= adma_irq_clear,
	.irq_on			= ata_irq_on,
	.irq_ack		= ata_irq_ack,
@@ -184,7 +188,7 @@ static const struct ata_port_operations adma_ata_ops = {
static struct ata_port_info adma_port_info[] = {
	/* board_1841_idx */
	{
		.flags		= ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST |
		.flags		= ATA_FLAG_SLAVE_POSS |
				  ATA_FLAG_NO_LEGACY | ATA_FLAG_MMIO |
				  ATA_FLAG_PIO_POLLING,
		.pio_mask	= 0x10, /* pio4 */
@@ -273,24 +277,41 @@ static inline void adma_enter_reg_mode(struct ata_port *ap)
	readb(chan + ADMA_STATUS);	/* flush */
}

static void adma_phy_reset(struct ata_port *ap)
static void adma_freeze(struct ata_port *ap)
{
	struct adma_port_priv *pp = ap->private_data;
	void __iomem *chan = ADMA_PORT_REGS(ap);

	pp->state = adma_state_idle;
	/* mask/clear ATA interrupts */
	writeb(ATA_NIEN, ap->ioaddr.ctl_addr);
	ata_check_status(ap);

	/* reset ADMA to idle state */
	writew(aPIOMD4 | aNIEN | aRSTADM, chan + ADMA_CONTROL);
	udelay(2);
	writew(aPIOMD4 | aNIEN, chan + ADMA_CONTROL);
	udelay(2);
}

static void adma_thaw(struct ata_port *ap)
{
	adma_reinit_engine(ap);
	ata_port_probe(ap);
	ata_bus_reset(ap);
}

static void adma_eng_timeout(struct ata_port *ap)
static int adma_prereset(struct ata_port *ap, unsigned long deadline)
{
	struct adma_port_priv *pp = ap->private_data;

	if (pp->state != adma_state_idle) /* healthy paranoia */
		pp->state = adma_state_mmio;
	adma_reinit_engine(ap);
	ata_eng_timeout(ap);

	return ata_std_prereset(ap, deadline);
}

static void adma_error_handler(struct ata_port *ap)
{
	ata_do_eh(ap, adma_prereset, ata_std_softreset, NULL,
		  ata_std_postreset);
}

static int adma_fill_sg(struct ata_queued_cmd *qc)
@@ -466,12 +487,31 @@ static inline unsigned int adma_intr_pkt(struct ata_host *host)
			continue;
		qc = ata_qc_from_tag(ap, ap->active_tag);
		if (qc && (!(qc->tf.flags & ATA_TFLAG_POLLING))) {
			if ((status & (aPERR | aPSD | aUIRQ)))
			if (status & aPERR)
				qc->err_mask |= AC_ERR_HOST_BUS;
			else if ((status & (aPSD | aUIRQ)))
				qc->err_mask |= AC_ERR_OTHER;

			if (pp->pkt[0] & cATERR)
				qc->err_mask |= AC_ERR_DEV;
			else if (pp->pkt[0] != cDONE)
				qc->err_mask |= AC_ERR_OTHER;

			if (!qc->err_mask)
				ata_qc_complete(qc);
			else {
				struct ata_eh_info *ehi = &ap->eh_info;
				ata_ehi_clear_desc(ehi);
				ata_ehi_push_desc(ehi,
					"ADMA-status 0x%02X", status);
				ata_ehi_push_desc(ehi,
					"pkt[0] 0x%02X", pp->pkt[0]);

				if (qc->err_mask == AC_ERR_DEV)
					ata_port_abort(ap);
				else
					ata_port_freeze(ap);
			}
		}
	}
	return handled;
@@ -502,7 +542,19 @@ static inline unsigned int adma_intr_mmio(struct ata_host *host)
				/* complete taskfile transaction */
				pp->state = adma_state_idle;
				qc->err_mask |= ac_err_mask(status);
				if (!qc->err_mask)
					ata_qc_complete(qc);
				else {
					struct ata_eh_info *ehi = &ap->eh_info;
					ata_ehi_clear_desc(ehi);
					ata_ehi_push_desc(ehi,
						"status 0x%02X", status);

					if (qc->err_mask == AC_ERR_DEV)
						ata_port_abort(ap);
					else
						ata_port_freeze(ap);
				}
				handled = 1;
			}
		}