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.c245
1 files changed, 229 insertions, 16 deletions
diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c
index 39fd17b05be5..d4885616cd39 100644
--- a/drivers/scsi/qla2xxx/qla_isr.c
+++ b/drivers/scsi/qla2xxx/qla_isr.c
@@ -86,12 +86,8 @@ qla2100_intr_handler(int irq, void *dev_id)
86 86
87 if (test_bit(MBX_INTR_WAIT, &ha->mbx_cmd_flags) && 87 if (test_bit(MBX_INTR_WAIT, &ha->mbx_cmd_flags) &&
88 (status & MBX_INTERRUPT) && ha->flags.mbox_int) { 88 (status & MBX_INTERRUPT) && ha->flags.mbox_int) {
89 spin_lock_irqsave(&ha->mbx_reg_lock, flags);
90
91 set_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags); 89 set_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags);
92 up(&ha->mbx_intr_sem); 90 up(&ha->mbx_intr_sem);
93
94 spin_unlock_irqrestore(&ha->mbx_reg_lock, flags);
95 } 91 }
96 92
97 return (IRQ_HANDLED); 93 return (IRQ_HANDLED);
@@ -199,12 +195,8 @@ qla2300_intr_handler(int irq, void *dev_id)
199 195
200 if (test_bit(MBX_INTR_WAIT, &ha->mbx_cmd_flags) && 196 if (test_bit(MBX_INTR_WAIT, &ha->mbx_cmd_flags) &&
201 (status & MBX_INTERRUPT) && ha->flags.mbox_int) { 197 (status & MBX_INTERRUPT) && ha->flags.mbox_int) {
202 spin_lock_irqsave(&ha->mbx_reg_lock, flags);
203
204 set_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags); 198 set_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags);
205 up(&ha->mbx_intr_sem); 199 up(&ha->mbx_intr_sem);
206
207 spin_unlock_irqrestore(&ha->mbx_reg_lock, flags);
208 } 200 }
209 201
210 return (IRQ_HANDLED); 202 return (IRQ_HANDLED);
@@ -654,10 +646,8 @@ qla2x00_ramp_up_queue_depth(scsi_qla_host_t *ha, srb_t *sp)
654 fcport->last_queue_full + ql2xqfullrampup * HZ)) 646 fcport->last_queue_full + ql2xqfullrampup * HZ))
655 return; 647 return;
656 648
657 spin_unlock_irq(&ha->hardware_lock);
658 starget_for_each_device(sdev->sdev_target, fcport, 649 starget_for_each_device(sdev->sdev_target, fcport,
659 qla2x00_adjust_sdev_qdepth_up); 650 qla2x00_adjust_sdev_qdepth_up);
660 spin_lock_irq(&ha->hardware_lock);
661} 651}
662 652
663/** 653/**
@@ -927,10 +917,8 @@ qla2x00_status_entry(scsi_qla_host_t *ha, void *pkt)
927 917
928 /* Adjust queue depth for all luns on the port. */ 918 /* Adjust queue depth for all luns on the port. */
929 fcport->last_queue_full = jiffies; 919 fcport->last_queue_full = jiffies;
930 spin_unlock_irq(&ha->hardware_lock);
931 starget_for_each_device(cp->device->sdev_target, 920 starget_for_each_device(cp->device->sdev_target,
932 fcport, qla2x00_adjust_sdev_qdepth_down); 921 fcport, qla2x00_adjust_sdev_qdepth_down);
933 spin_lock_irq(&ha->hardware_lock);
934 break; 922 break;
935 } 923 }
936 if (lscsi_status != SS_CHECK_CONDITION) 924 if (lscsi_status != SS_CHECK_CONDITION)
@@ -995,6 +983,22 @@ qla2x00_status_entry(scsi_qla_host_t *ha, void *pkt)
995 if (lscsi_status != 0) { 983 if (lscsi_status != 0) {
996 cp->result = DID_OK << 16 | lscsi_status; 984 cp->result = DID_OK << 16 | lscsi_status;
997 985
986 if (lscsi_status == SAM_STAT_TASK_SET_FULL) {
987 DEBUG2(printk(KERN_INFO
988 "scsi(%ld): QUEUE FULL status detected "
989 "0x%x-0x%x.\n", ha->host_no, comp_status,
990 scsi_status));
991
992 /*
993 * Adjust queue depth for all luns on the
994 * port.
995 */
996 fcport->last_queue_full = jiffies;
997 starget_for_each_device(
998 cp->device->sdev_target, fcport,
999 qla2x00_adjust_sdev_qdepth_down);
1000 break;
1001 }
998 if (lscsi_status != SS_CHECK_CONDITION) 1002 if (lscsi_status != SS_CHECK_CONDITION)
999 break; 1003 break;
1000 1004
@@ -1482,12 +1486,8 @@ qla24xx_intr_handler(int irq, void *dev_id)
1482 1486
1483 if (test_bit(MBX_INTR_WAIT, &ha->mbx_cmd_flags) && 1487 if (test_bit(MBX_INTR_WAIT, &ha->mbx_cmd_flags) &&
1484 (status & MBX_INTERRUPT) && ha->flags.mbox_int) { 1488 (status & MBX_INTERRUPT) && ha->flags.mbox_int) {
1485 spin_lock_irqsave(&ha->mbx_reg_lock, flags);
1486
1487 set_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags); 1489 set_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags);
1488 up(&ha->mbx_intr_sem); 1490 up(&ha->mbx_intr_sem);
1489
1490 spin_unlock_irqrestore(&ha->mbx_reg_lock, flags);
1491 } 1491 }
1492 1492
1493 return IRQ_HANDLED; 1493 return IRQ_HANDLED;
@@ -1536,3 +1536,216 @@ qla24xx_ms_entry(scsi_qla_host_t *ha, struct ct_entry_24xx *pkt)
1536 qla2x00_sp_compl(ha, sp); 1536 qla2x00_sp_compl(ha, sp);
1537} 1537}
1538 1538
1539static irqreturn_t
1540qla24xx_msix_rsp_q(int irq, void *dev_id)
1541{
1542 scsi_qla_host_t *ha;
1543 struct device_reg_24xx __iomem *reg;
1544 unsigned long flags;
1545
1546 ha = dev_id;
1547 reg = &ha->iobase->isp24;
1548
1549 spin_lock_irqsave(&ha->hardware_lock, flags);
1550
1551 qla24xx_process_response_queue(ha);
1552
1553 WRT_REG_DWORD(&reg->hccr, HCCRX_CLR_RISC_INT);
1554 RD_REG_DWORD_RELAXED(&reg->hccr);
1555
1556 spin_unlock_irqrestore(&ha->hardware_lock, flags);
1557
1558 return IRQ_HANDLED;
1559}
1560
1561static irqreturn_t
1562qla24xx_msix_default(int irq, void *dev_id)
1563{
1564 scsi_qla_host_t *ha;
1565 struct device_reg_24xx __iomem *reg;
1566 int status;
1567 unsigned long flags;
1568 unsigned long iter;
1569 uint32_t stat;
1570 uint32_t hccr;
1571 uint16_t mb[4];
1572
1573 ha = dev_id;
1574 reg = &ha->iobase->isp24;
1575 status = 0;
1576
1577 spin_lock_irqsave(&ha->hardware_lock, flags);
1578 for (iter = 50; iter--; ) {
1579 stat = RD_REG_DWORD(&reg->host_status);
1580 if (stat & HSRX_RISC_PAUSED) {
1581 hccr = RD_REG_DWORD(&reg->hccr);
1582
1583 qla_printk(KERN_INFO, ha, "RISC paused -- HCCR=%x, "
1584 "Dumping firmware!\n", hccr);
1585 ha->isp_ops.fw_dump(ha, 1);
1586 set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags);
1587 break;
1588 } else if ((stat & HSRX_RISC_INT) == 0)
1589 break;
1590
1591 switch (stat & 0xff) {
1592 case 0x1:
1593 case 0x2:
1594 case 0x10:
1595 case 0x11:
1596 qla24xx_mbx_completion(ha, MSW(stat));
1597 status |= MBX_INTERRUPT;
1598
1599 break;
1600 case 0x12:
1601 mb[0] = MSW(stat);
1602 mb[1] = RD_REG_WORD(&reg->mailbox1);
1603 mb[2] = RD_REG_WORD(&reg->mailbox2);
1604 mb[3] = RD_REG_WORD(&reg->mailbox3);
1605 qla2x00_async_event(ha, mb);
1606 break;
1607 case 0x13:
1608 qla24xx_process_response_queue(ha);
1609 break;
1610 default:
1611 DEBUG2(printk("scsi(%ld): Unrecognized interrupt type "
1612 "(%d).\n",
1613 ha->host_no, stat & 0xff));
1614 break;
1615 }
1616 WRT_REG_DWORD(&reg->hccr, HCCRX_CLR_RISC_INT);
1617 RD_REG_DWORD_RELAXED(&reg->hccr);
1618 }
1619 spin_unlock_irqrestore(&ha->hardware_lock, flags);
1620
1621 if (test_bit(MBX_INTR_WAIT, &ha->mbx_cmd_flags) &&
1622 (status & MBX_INTERRUPT) && ha->flags.mbox_int) {
1623 set_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags);
1624 up(&ha->mbx_intr_sem);
1625 }
1626
1627 return IRQ_HANDLED;
1628}
1629
1630/* Interrupt handling helpers. */
1631
1632struct qla_init_msix_entry {
1633 uint16_t entry;
1634 uint16_t index;
1635 const char *name;
1636 irqreturn_t (*handler)(int, void *);
1637};
1638
1639static struct qla_init_msix_entry imsix_entries[QLA_MSIX_ENTRIES] = {
1640 { QLA_MSIX_DEFAULT, QLA_MIDX_DEFAULT,
1641 "qla2xxx (default)", qla24xx_msix_default },
1642
1643 { QLA_MSIX_RSP_Q, QLA_MIDX_RSP_Q,
1644 "qla2xxx (rsp_q)", qla24xx_msix_rsp_q },
1645};
1646
1647static void
1648qla24xx_disable_msix(scsi_qla_host_t *ha)
1649{
1650 int i;
1651 struct qla_msix_entry *qentry;
1652
1653 for (i = 0; i < QLA_MSIX_ENTRIES; i++) {
1654 qentry = &ha->msix_entries[imsix_entries[i].index];
1655 if (qentry->have_irq)
1656 free_irq(qentry->msix_vector, ha);
1657 }
1658 pci_disable_msix(ha->pdev);
1659}
1660
1661static int
1662qla24xx_enable_msix(scsi_qla_host_t *ha)
1663{
1664 int i, ret;
1665 struct msix_entry entries[QLA_MSIX_ENTRIES];
1666 struct qla_msix_entry *qentry;
1667
1668 for (i = 0; i < QLA_MSIX_ENTRIES; i++)
1669 entries[i].entry = imsix_entries[i].entry;
1670
1671 ret = pci_enable_msix(ha->pdev, entries, ARRAY_SIZE(entries));
1672 if (ret) {
1673 qla_printk(KERN_WARNING, ha,
1674 "MSI-X: Failed to enable support -- %d/%d\n",
1675 QLA_MSIX_ENTRIES, ret);
1676 goto msix_out;
1677 }
1678 ha->flags.msix_enabled = 1;
1679
1680 for (i = 0; i < QLA_MSIX_ENTRIES; i++) {
1681 qentry = &ha->msix_entries[imsix_entries[i].index];
1682 qentry->msix_vector = entries[i].vector;
1683 qentry->msix_entry = entries[i].entry;
1684 qentry->have_irq = 0;
1685 ret = request_irq(qentry->msix_vector,
1686 imsix_entries[i].handler, 0, imsix_entries[i].name, ha);
1687 if (ret) {
1688 qla_printk(KERN_WARNING, ha,
1689 "MSI-X: Unable to register handler -- %x/%d.\n",
1690 imsix_entries[i].index, ret);
1691 qla24xx_disable_msix(ha);
1692 goto msix_out;
1693 }
1694 qentry->have_irq = 1;
1695 }
1696
1697msix_out:
1698 return ret;
1699}
1700
1701int
1702qla2x00_request_irqs(scsi_qla_host_t *ha)
1703{
1704 int ret;
1705
1706 /* If possible, enable MSI-X. */
1707 if (!IS_QLA2432(ha))
1708 goto skip_msix;
1709
1710 if (ha->chip_revision < QLA_MSIX_CHIP_REV_24XX ||
1711 !QLA_MSIX_FW_MODE_1(ha->fw_attributes)) {
1712 DEBUG2(qla_printk(KERN_WARNING, ha,
1713 "MSI-X: Unsupported ISP2432 (0x%X, 0x%X).\n",
1714 ha->chip_revision, ha->fw_attributes));
1715
1716 goto skip_msix;
1717 }
1718
1719 ret = qla24xx_enable_msix(ha);
1720 if (!ret) {
1721 DEBUG2(qla_printk(KERN_INFO, ha,
1722 "MSI-X: Enabled (0x%X, 0x%X).\n", ha->chip_revision,
1723 ha->fw_attributes));
1724 return ret;
1725 }
1726 qla_printk(KERN_WARNING, ha,
1727 "MSI-X: Falling back-to INTa mode -- %d.\n", ret);
1728skip_msix:
1729 ret = request_irq(ha->pdev->irq, ha->isp_ops.intr_handler,
1730 IRQF_DISABLED|IRQF_SHARED, QLA2XXX_DRIVER_NAME, ha);
1731 if (!ret) {
1732 ha->flags.inta_enabled = 1;
1733 ha->host->irq = ha->pdev->irq;
1734 } else {
1735 qla_printk(KERN_WARNING, ha,
1736 "Failed to reserve interrupt %d already in use.\n",
1737 ha->pdev->irq);
1738 }
1739
1740 return ret;
1741}
1742
1743void
1744qla2x00_free_irqs(scsi_qla_host_t *ha)
1745{
1746
1747 if (ha->flags.msix_enabled)
1748 qla24xx_disable_msix(ha);
1749 else if (ha->flags.inta_enabled)
1750 free_irq(ha->host->irq, ha);
1751}