static int nv_host_intr(struct ata_port *ap, u8 irq_stat) { struct ata_queued_cmd *qc = ata_qc_from_tag(ap, ap->active_tag); int handled; /* freeze if hotplugged */ if (unlikely(irq_stat & (NV_INT_ADDED | NV_INT_REMOVED))) { ata_port_freeze(ap); return 1; } /* bail out if not our interrupt */ if (!(irq_stat & NV_INT_DEV)) return 0; /* DEV interrupt w/ no active qc? */ if (unlikely(!qc || (qc->tf.flags & ATA_TFLAG_POLLING))) { ata_check_status(ap); return 1; } /* handle interrupt */ handled = ata_host_intr(ap, qc); if (unlikely(!handled)) { /* spurious, clear it */ ata_check_status(ap); } return 1; }
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); }