static void sata_dwc_error_intr(struct ata_port *ap,
                                struct sata_dwc_device *hsdev, uint intpr)
{
    struct sata_dwc_device_port *hsdevp = HSDEVP_FROM_AP(ap);
    struct ata_eh_info *ehi = &ap->link.eh_info;
    unsigned int err_mask = 0, action = 0;
    struct ata_queued_cmd *qc;
    u32 serror;
    u8 status, tag;
    u32 err_reg;

    ata_ehi_clear_desc(ehi);

    serror = core_scr_read(SCR_ERROR);
    status = ap->ops->sff_check_status(ap);

    err_reg = in_le32(&(host_pvt.sata_dma_regs->interrupt_status.error.\
                        low));
    tag = ap->link.active_tag;

    dev_err(ap->dev, "%s SCR_ERROR=0x%08x intpr=0x%08x status=0x%08x "
            "dma_intp=%d pending=%d issued=%d dma_err_status=0x%08x\n",
            __func__, serror, intpr, status, host_pvt.dma_interrupt_count,
            hsdevp->dma_pending[tag], hsdevp->cmd_issued[tag], err_reg);


    clear_serror();
    clear_interrupt_bit(hsdev, SATA_DWC_INTPR_ERR);



    err_mask |= AC_ERR_HOST_BUS;
    action |= ATA_EH_RESET;


    ehi->serror |= serror;
    ehi->action |= action;

    qc = ata_qc_from_tag(ap, tag);
    if (qc)
        qc->err_mask |= err_mask;
    else
        ehi->err_mask |= err_mask;

    ata_port_abort(ap);
}
Example #2
0
static void inic_host_intr(struct ata_port *ap)
{
	void __iomem *port_base = inic_port_base(ap);
	struct ata_eh_info *ehi = &ap->link.eh_info;
	u8 irq_stat;

	/* fetch and clear irq */
	irq_stat = readb(port_base + PORT_IRQ_STAT);
	writeb(irq_stat, port_base + PORT_IRQ_STAT);

	if (likely(!(irq_stat & PIRQ_ERR))) {
		struct ata_queued_cmd *qc =
			ata_qc_from_tag(ap, ap->link.active_tag);

		if (unlikely(!qc || (qc->tf.flags & ATA_TFLAG_POLLING))) {
			ata_chk_status(ap);	/* clear ATA interrupt */
			return;
		}

		if (likely(ata_host_intr(ap, qc)))
			return;

		ata_chk_status(ap);	/* clear ATA interrupt */
		ata_port_printk(ap, KERN_WARNING, "unhandled "
				"interrupt, irq_stat=%x\n", irq_stat);
		return;
	}

	/* error */
	ata_ehi_push_desc(ehi, "irq_stat=0x%x", irq_stat);

	if (irq_stat & (PIRQ_OFFLINE | PIRQ_ONLINE)) {
		ata_ehi_hotplugged(ehi);
		ata_port_freeze(ap);
	} else
		ata_port_abort(ap);
}