aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/qla2xxx/qla_isr.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/qla2xxx/qla_isr.c')
-rw-r--r--drivers/scsi/qla2xxx/qla_isr.c215
1 files changed, 215 insertions, 0 deletions
diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c
index b95fcb2c065e..e883b5fc3b08 100644
--- a/drivers/scsi/qla2xxx/qla_isr.c
+++ b/drivers/scsi/qla2xxx/qla_isr.c
@@ -1529,3 +1529,218 @@ qla24xx_ms_entry(scsi_qla_host_t *ha, struct ct_entry_24xx *pkt)
1529 qla2x00_sp_compl(ha, sp); 1529 qla2x00_sp_compl(ha, sp);
1530} 1530}
1531 1531
1532static irqreturn_t
1533qla24xx_msix_rsp_q(int irq, void *dev_id)
1534{
1535 scsi_qla_host_t *ha;
1536 struct device_reg_24xx __iomem *reg;
1537 unsigned long flags;
1538
1539 ha = dev_id;
1540 reg = &ha->iobase->isp24;
1541
1542 spin_lock_irqsave(&ha->hardware_lock, flags);
1543
1544 qla24xx_process_response_queue(ha);
1545
1546 WRT_REG_DWORD(&reg->hccr, HCCRX_CLR_RISC_INT);
1547 RD_REG_DWORD_RELAXED(&reg->hccr);
1548
1549 spin_unlock_irqrestore(&ha->hardware_lock, flags);
1550
1551 return IRQ_HANDLED;
1552}
1553
1554static irqreturn_t
1555qla24xx_msix_default(int irq, void *dev_id)
1556{
1557 scsi_qla_host_t *ha;
1558 struct device_reg_24xx __iomem *reg;
1559 int status;
1560 unsigned long flags;
1561 unsigned long iter;
1562 uint32_t stat;
1563 uint32_t hccr;
1564 uint16_t mb[4];
1565
1566 ha = dev_id;
1567 reg = &ha->iobase->isp24;
1568 status = 0;
1569
1570 spin_lock_irqsave(&ha->hardware_lock, flags);
1571 for (iter = 50; iter--; ) {
1572 stat = RD_REG_DWORD(&reg->host_status);
1573 if (stat & HSRX_RISC_PAUSED) {
1574 hccr = RD_REG_DWORD(&reg->hccr);
1575
1576 qla_printk(KERN_INFO, ha, "RISC paused -- HCCR=%x, "
1577 "Dumping firmware!\n", hccr);
1578 ha->isp_ops.fw_dump(ha, 1);
1579 set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags);
1580 break;
1581 } else if ((stat & HSRX_RISC_INT) == 0)
1582 break;
1583
1584 switch (stat & 0xff) {
1585 case 0x1:
1586 case 0x2:
1587 case 0x10:
1588 case 0x11:
1589 qla24xx_mbx_completion(ha, MSW(stat));
1590 status |= MBX_INTERRUPT;
1591
1592 break;
1593 case 0x12:
1594 mb[0] = MSW(stat);
1595 mb[1] = RD_REG_WORD(&reg->mailbox1);
1596 mb[2] = RD_REG_WORD(&reg->mailbox2);
1597 mb[3] = RD_REG_WORD(&reg->mailbox3);
1598 qla2x00_async_event(ha, mb);
1599 break;
1600 case 0x13:
1601 qla24xx_process_response_queue(ha);
1602 break;
1603 default:
1604 DEBUG2(printk("scsi(%ld): Unrecognized interrupt type "
1605 "(%d).\n",
1606 ha->host_no, stat & 0xff));
1607 break;
1608 }
1609 WRT_REG_DWORD(&reg->hccr, HCCRX_CLR_RISC_INT);
1610 RD_REG_DWORD_RELAXED(&reg->hccr);
1611 }
1612 spin_unlock_irqrestore(&ha->hardware_lock, flags);
1613
1614 if (test_bit(MBX_INTR_WAIT, &ha->mbx_cmd_flags) &&
1615 (status & MBX_INTERRUPT) && ha->flags.mbox_int) {
1616 spin_lock_irqsave(&ha->mbx_reg_lock, flags);
1617
1618 set_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags);
1619 up(&ha->mbx_intr_sem);
1620
1621 spin_unlock_irqrestore(&ha->mbx_reg_lock, flags);
1622 }
1623
1624 return IRQ_HANDLED;
1625}
1626
1627/* Interrupt handling helpers. */
1628
1629struct qla_init_msix_entry {
1630 uint16_t entry;
1631 uint16_t index;
1632 const char *name;
1633 irqreturn_t (*handler)(int, void *);
1634};
1635
1636static struct qla_init_msix_entry imsix_entries[QLA_MSIX_ENTRIES] = {
1637 { QLA_MSIX_DEFAULT, QLA_MIDX_DEFAULT,
1638 "qla2xxx (default)", qla24xx_msix_default },
1639
1640 { QLA_MSIX_RSP_Q, QLA_MIDX_RSP_Q,
1641 "qla2xxx (rsp_q)", qla24xx_msix_rsp_q },
1642};
1643
1644static void
1645qla24xx_disable_msix(scsi_qla_host_t *ha)
1646{
1647 int i;
1648 struct qla_msix_entry *qentry;
1649
1650 for (i = 0; i < QLA_MSIX_ENTRIES; i++) {
1651 qentry = &ha->msix_entries[imsix_entries[i].index];
1652 if (qentry->have_irq)
1653 free_irq(qentry->msix_vector, ha);
1654 }
1655 pci_disable_msix(ha->pdev);
1656}
1657
1658static int
1659qla24xx_enable_msix(scsi_qla_host_t *ha)
1660{
1661 int i, ret;
1662 struct msix_entry entries[QLA_MSIX_ENTRIES];
1663 struct qla_msix_entry *qentry;
1664
1665 for (i = 0; i < QLA_MSIX_ENTRIES; i++)
1666 entries[i].entry = imsix_entries[i].entry;
1667
1668 ret = pci_enable_msix(ha->pdev, entries, ARRAY_SIZE(entries));
1669 if (ret) {
1670 qla_printk(KERN_WARNING, ha,
1671 "MSI-X: Failed to enable support -- %d/%d\n",
1672 QLA_MSIX_ENTRIES, ret);
1673 goto msix_out;
1674 }
1675 ha->flags.msix_enabled = 1;
1676
1677 for (i = 0; i < QLA_MSIX_ENTRIES; i++) {
1678 qentry = &ha->msix_entries[imsix_entries[i].index];
1679 qentry->msix_vector = entries[i].vector;
1680 qentry->msix_entry = entries[i].entry;
1681 qentry->have_irq = 0;
1682 ret = request_irq(qentry->msix_vector,
1683 imsix_entries[i].handler, 0, imsix_entries[i].name, ha);
1684 if (ret) {
1685 qla_printk(KERN_WARNING, ha,
1686 "MSI-X: Unable to register handler -- %x/%d.\n",
1687 imsix_entries[i].index, ret);
1688 qla24xx_disable_msix(ha);
1689 goto msix_out;
1690 }
1691 qentry->have_irq = 1;
1692 }
1693
1694msix_out:
1695 return ret;
1696}
1697
1698int
1699qla2x00_request_irqs(scsi_qla_host_t *ha)
1700{
1701 int ret;
1702
1703 /* If possible, enable MSI-X. */
1704 if (!IS_QLA2432(ha))
1705 goto skip_msix;
1706
1707 if (ha->chip_revision < QLA_MSIX_CHIP_REV_24XX ||
1708 !QLA_MSIX_FW_MODE_1(ha->fw_attributes)) {
1709 DEBUG2(qla_printk(KERN_WARNING, ha,
1710 "MSI-X: Unsupported ISP2432 (0x%X, 0x%X).\n",
1711 ha->chip_revision, ha->fw_attributes));
1712
1713 goto skip_msix;
1714 }
1715
1716 ret = qla24xx_enable_msix(ha);
1717 if (!ret) {
1718 DEBUG2(qla_printk(KERN_INFO, ha,
1719 "MSI-X: Enabled (0x%X, 0x%X).\n", ha->chip_revision,
1720 ha->fw_attributes));
1721 return ret;
1722 }
1723 qla_printk(KERN_WARNING, ha,
1724 "MSI-X: Falling back-to INTa mode -- %d.\n", ret);
1725skip_msix:
1726 ret = request_irq(ha->pdev->irq, ha->isp_ops.intr_handler,
1727 IRQF_DISABLED|IRQF_SHARED, QLA2XXX_DRIVER_NAME, ha);
1728 if (ret) {
1729 qla_printk(KERN_WARNING, ha,
1730 "Failed to reserve interrupt %d already in use.\n",
1731 ha->pdev->irq);
1732 }
1733 ha->host->irq = ha->pdev->irq;
1734
1735 return ret;
1736}
1737
1738void
1739qla2x00_free_irqs(scsi_qla_host_t *ha)
1740{
1741
1742 if (ha->flags.msix_enabled)
1743 qla24xx_disable_msix(ha);
1744 else if (ha->host->irq)
1745 free_irq(ha->host->irq, ha);
1746}