]> err.no Git - linux-2.6/blobdiff - drivers/scsi/qla2xxx/qla_isr.c
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/ieee1394...
[linux-2.6] / drivers / scsi / qla2xxx / qla_isr.c
index 370fba59dfd236dee6c77477d9865f9bb7e954f8..874d802edb7de482c79774bd760bdf61a7210ca4 100644 (file)
@@ -14,9 +14,6 @@ static void qla2x00_process_completed_request(struct scsi_qla_host *, uint32_t);
 static void qla2x00_status_entry(scsi_qla_host_t *, void *);
 static void qla2x00_status_cont_entry(scsi_qla_host_t *, sts_cont_entry_t *);
 static void qla2x00_error_entry(scsi_qla_host_t *, sts_entry_t *);
-static void qla2x00_ms_entry(scsi_qla_host_t *, ms_iocb_entry_t *);
-
-static void qla24xx_ms_entry(scsi_qla_host_t *, struct ct_entry_24xx *);
 
 /**
  * qla2100_intr_handler() - Process interrupts for the ISP2100 and ISP2200.
@@ -33,7 +30,6 @@ qla2100_intr_handler(int irq, void *dev_id)
        scsi_qla_host_t *ha;
        struct device_reg_2xxx __iomem *reg;
        int             status;
-       unsigned long   flags;
        unsigned long   iter;
        uint16_t        hccr;
        uint16_t        mb[4];
@@ -48,7 +44,7 @@ qla2100_intr_handler(int irq, void *dev_id)
        reg = &ha->iobase->isp;
        status = 0;
 
-       spin_lock_irqsave(&ha->hardware_lock, flags);
+       spin_lock(&ha->hardware_lock);
        for (iter = 50; iter--; ) {
                hccr = RD_REG_WORD(&reg->hccr);
                if (hccr & HCCR_RISC_PAUSE) {
@@ -99,7 +95,7 @@ qla2100_intr_handler(int irq, void *dev_id)
                        RD_REG_WORD(&reg->hccr);
                }
        }
-       spin_unlock_irqrestore(&ha->hardware_lock, flags);
+       spin_unlock(&ha->hardware_lock);
 
        if (test_bit(MBX_INTR_WAIT, &ha->mbx_cmd_flags) &&
            (status & MBX_INTERRUPT) && ha->flags.mbox_int) {
@@ -125,7 +121,6 @@ qla2300_intr_handler(int irq, void *dev_id)
        scsi_qla_host_t *ha;
        struct device_reg_2xxx __iomem *reg;
        int             status;
-       unsigned long   flags;
        unsigned long   iter;
        uint32_t        stat;
        uint16_t        hccr;
@@ -141,7 +136,7 @@ qla2300_intr_handler(int irq, void *dev_id)
        reg = &ha->iobase->isp;
        status = 0;
 
-       spin_lock_irqsave(&ha->hardware_lock, flags);
+       spin_lock(&ha->hardware_lock);
        for (iter = 50; iter--; ) {
                stat = RD_REG_DWORD(&reg->u.isp2300.host_status);
                if (stat & HSR_RISC_PAUSED) {
@@ -211,7 +206,7 @@ qla2300_intr_handler(int irq, void *dev_id)
                WRT_REG_WORD(&reg->hccr, HCCR_CLR_RISC_INT);
                RD_REG_WORD_RELAXED(&reg->hccr);
        }
-       spin_unlock_irqrestore(&ha->hardware_lock, flags);
+       spin_unlock(&ha->hardware_lock);
 
        if (test_bit(MBX_INTR_WAIT, &ha->mbx_cmd_flags) &&
            (status & MBX_INTERRUPT) && ha->flags.mbox_int) {
@@ -276,6 +271,7 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb)
        struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
        uint32_t        rscn_entry, host_pid;
        uint8_t         rscn_queue_index;
+       unsigned long   flags;
 
        /* Setup to process RIO completion. */
        handle_cnt = 0;
@@ -351,6 +347,7 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb)
                    "ISP System Error - mbx1=%xh mbx2=%xh mbx3=%xh.\n",
                    mb[1], mb[2], mb[3]);
 
+               qla2x00_post_hwe_work(ha, mb[0], mb[1], mb[2], mb[3]);
                ha->isp_ops->fw_dump(ha, 1);
 
                if (IS_FWI2_CAPABLE(ha)) {
@@ -375,6 +372,7 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb)
                    ha->host_no));
                qla_printk(KERN_WARNING, ha, "ISP Request Transfer Error.\n");
 
+               qla2x00_post_hwe_work(ha, mb[0], mb[1], mb[2], mb[3]);
                set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags);
                break;
 
@@ -383,6 +381,7 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb)
                    ha->host_no));
                qla_printk(KERN_WARNING, ha, "ISP Response Transfer Error.\n");
 
+               qla2x00_post_hwe_work(ha, mb[0], mb[1], mb[2], mb[3]);
                set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags);
                break;
 
@@ -408,8 +407,10 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb)
                }
 
                set_bit(REGISTER_FC4_NEEDED, &ha->dpc_flags);
+               set_bit(REGISTER_FDMI_NEEDED, &ha->dpc_flags);
 
                ha->flags.management_server_logged_in = 0;
+               qla2x00_post_aen_work(ha, FCH_EVT_LIP, mb[1]);
                break;
 
        case MBA_LOOP_UP:               /* Loop Up Event */
@@ -429,12 +430,14 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb)
                    link_speed);
 
                ha->flags.management_server_logged_in = 0;
+               qla2x00_post_aen_work(ha, FCH_EVT_LINKUP, ha->link_data_rate);
                break;
 
        case MBA_LOOP_DOWN:             /* Loop Down Event */
-               DEBUG2(printk("scsi(%ld): Asynchronous LOOP DOWN (%x).\n",
-                   ha->host_no, mb[1]));
-               qla_printk(KERN_INFO, ha, "LOOP DOWN detected (%x).\n", mb[1]);
+               DEBUG2(printk("scsi(%ld): Asynchronous LOOP DOWN "
+                   "(%x %x %x).\n", ha->host_no, mb[1], mb[2], mb[3]));
+               qla_printk(KERN_INFO, ha, "LOOP DOWN detected (%x %x %x).\n",
+                   mb[1], mb[2], mb[3]);
 
                if (atomic_read(&ha->loop_state) != LOOP_DOWN) {
                        atomic_set(&ha->loop_state, LOOP_DOWN);
@@ -450,8 +453,7 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb)
 
                ha->flags.management_server_logged_in = 0;
                ha->link_data_rate = PORT_SPEED_UNKNOWN;
-               if (ql2xfdmienable)
-                       set_bit(REGISTER_FDMI_NEEDED, &ha->dpc_flags);
+               qla2x00_post_aen_work(ha, FCH_EVT_LINKDOWN, 0);
                break;
 
        case MBA_LIP_RESET:             /* LIP reset occurred */
@@ -475,6 +477,7 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb)
 
                ha->operating_mode = LOOP;
                ha->flags.management_server_logged_in = 0;
+               qla2x00_post_aen_work(ha, FCH_EVT_LIPRESET, mb[1]);
                break;
 
        case MBA_POINT_TO_POINT:        /* Point-to-Point */
@@ -505,6 +508,7 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb)
                        set_bit(RESET_MARKER_NEEDED, &ha->dpc_flags);
                }
                set_bit(REGISTER_FC4_NEEDED, &ha->dpc_flags);
+               set_bit(REGISTER_FDMI_NEEDED, &ha->dpc_flags);
 
                ha->flags.gpsc_supported = 1;
                ha->flags.management_server_logged_in = 0;
@@ -576,7 +580,7 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb)
                if (ha->parent && test_bit(VP_SCR_NEEDED, &ha->vp_flags))
                        break;
                /* Only handle SCNs for our Vport index. */
-               if (ha->flags.npiv_supported && ha->vp_idx != mb[3])
+               if (ha->parent && ha->vp_idx != (mb[3] & 0xff))
                        break;
 
                DEBUG2(printk("scsi(%ld): Asynchronous RSCR UPDATE.\n",
@@ -612,6 +616,7 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb)
 
                set_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags);
                set_bit(RSCN_UPDATE, &ha->dpc_flags);
+               qla2x00_post_aen_work(ha, FCH_EVT_RSCN, rscn_entry);
                break;
 
        /* case MBA_RIO_RESPONSE: */
@@ -637,6 +642,42 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb)
                DEBUG2(printk("scsi(%ld): Trace Notification -- %04x %04x.\n",
                ha->host_no, mb[1], mb[2]));
                break;
+
+       case MBA_ISP84XX_ALERT:
+               DEBUG2(printk("scsi(%ld): ISP84XX Alert Notification -- "
+                   "%04x %04x %04x\n", ha->host_no, mb[1], mb[2], mb[3]));
+
+               spin_lock_irqsave(&ha->cs84xx->access_lock, flags);
+               switch (mb[1]) {
+               case A84_PANIC_RECOVERY:
+                       qla_printk(KERN_INFO, ha, "Alert 84XX: panic recovery "
+                           "%04x %04x\n", mb[2], mb[3]);
+                       break;
+               case A84_OP_LOGIN_COMPLETE:
+                       ha->cs84xx->op_fw_version = mb[3] << 16 | mb[2];
+                       DEBUG2(qla_printk(KERN_INFO, ha, "Alert 84XX:"
+                           "firmware version %x\n", ha->cs84xx->op_fw_version));
+                       break;
+               case A84_DIAG_LOGIN_COMPLETE:
+                       ha->cs84xx->diag_fw_version = mb[3] << 16 | mb[2];
+                       DEBUG2(qla_printk(KERN_INFO, ha, "Alert 84XX:"
+                           "diagnostic firmware version %x\n",
+                           ha->cs84xx->diag_fw_version));
+                       break;
+               case A84_GOLD_LOGIN_COMPLETE:
+                       ha->cs84xx->diag_fw_version = mb[3] << 16 | mb[2];
+                       ha->cs84xx->fw_update = 1;
+                       DEBUG2(qla_printk(KERN_INFO, ha, "Alert 84XX: gold "
+                           "firmware version %x\n",
+                           ha->cs84xx->gold_fw_version));
+                       break;
+               default:
+                       qla_printk(KERN_ERR, ha,
+                           "Alert 84xx: Invalid Alert %04x %04x %04x\n",
+                           mb[1], mb[2], mb[3]);
+               }
+               spin_unlock_irqrestore(&ha->cs84xx->access_lock, flags);
+               break;
        }
 
        if (!ha->parent && ha->num_vhosts)
@@ -803,9 +844,6 @@ qla2x00_process_response_queue(struct scsi_qla_host *ha)
                case STATUS_CONT_TYPE:
                        qla2x00_status_cont_entry(ha, (sts_cont_entry_t *)pkt);
                        break;
-               case MS_IOCB_TYPE:
-                       qla2x00_ms_entry(ha, (ms_iocb_entry_t *)pkt);
-                       break;
                default:
                        /* Type Not Supported. */
                        DEBUG4(printk(KERN_WARNING
@@ -1074,25 +1112,6 @@ qla2x00_status_entry(scsi_qla_host_t *ha, void *pkt)
                                break;
 
                        qla2x00_handle_sense(sp, sense_data, sense_len);
-
-                       /*
-                        * In case of a Underrun condition, set both the lscsi
-                        * status and the completion status to appropriate
-                        * values.
-                        */
-                       if (resid &&
-                           ((unsigned)(scsi_bufflen(cp) - resid) <
-                            cp->underflow)) {
-                               DEBUG2(qla_printk(KERN_INFO, ha,
-                                   "scsi(%ld:%d:%d:%d): Mid-layer underflow "
-                                   "detected (%x of %x bytes)...returning "
-                                   "error status.\n", ha->host_no,
-                                   cp->device->channel, cp->device->id,
-                                   cp->device->lun, resid,
-                                   scsi_bufflen(cp)));
-
-                               cp->result = DID_ERROR << 16 | lscsi_status;
-                       }
                } else {
                        /*
                         * If RISC reports underrun and target does not report
@@ -1339,44 +1358,6 @@ qla2x00_error_entry(scsi_qla_host_t *ha, sts_entry_t *pkt)
        }
 }
 
-/**
- * qla2x00_ms_entry() - Process a Management Server entry.
- * @ha: SCSI driver HA context
- * @index: Response queue out pointer
- */
-static void
-qla2x00_ms_entry(scsi_qla_host_t *ha, ms_iocb_entry_t *pkt)
-{
-       srb_t          *sp;
-
-       DEBUG3(printk("%s(%ld): pkt=%p pkthandle=%d.\n",
-           __func__, ha->host_no, pkt, pkt->handle1));
-
-       /* Validate handle. */
-       if (pkt->handle1 < MAX_OUTSTANDING_COMMANDS)
-               sp = ha->outstanding_cmds[pkt->handle1];
-       else
-               sp = NULL;
-
-       if (sp == NULL) {
-               DEBUG2(printk("scsi(%ld): MS entry - invalid handle\n",
-                   ha->host_no));
-               qla_printk(KERN_WARNING, ha, "MS entry - invalid handle\n");
-
-               set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags);
-               return;
-       }
-
-       CMD_COMPL_STATUS(sp->cmd) = le16_to_cpu(pkt->status);
-       CMD_ENTRY_STATUS(sp->cmd) = pkt->entry_status;
-
-       /* Free outstanding command slot. */
-       ha->outstanding_cmds[pkt->handle1] = NULL;
-
-       qla2x00_sp_compl(ha, sp);
-}
-
-
 /**
  * qla24xx_mbx_completion() - Process mailbox command completions.
  * @ha: SCSI driver HA context
@@ -1449,9 +1430,6 @@ qla24xx_process_response_queue(struct scsi_qla_host *ha)
                case STATUS_CONT_TYPE:
                        qla2x00_status_cont_entry(ha, (sts_cont_entry_t *)pkt);
                        break;
-               case MS_IOCB_TYPE:
-                       qla24xx_ms_entry(ha, (struct ct_entry_24xx *)pkt);
-                       break;
                case VP_RPT_ID_IOCB_TYPE:
                        qla24xx_report_id_acquisition(ha,
                            (struct vp_rpt_id_entry_24xx *)pkt);
@@ -1533,7 +1511,6 @@ qla24xx_intr_handler(int irq, void *dev_id)
        scsi_qla_host_t *ha;
        struct device_reg_24xx __iomem *reg;
        int             status;
-       unsigned long   flags;
        unsigned long   iter;
        uint32_t        stat;
        uint32_t        hccr;
@@ -1549,13 +1526,19 @@ qla24xx_intr_handler(int irq, void *dev_id)
        reg = &ha->iobase->isp24;
        status = 0;
 
-       spin_lock_irqsave(&ha->hardware_lock, flags);
+       spin_lock(&ha->hardware_lock);
        for (iter = 50; iter--; ) {
                stat = RD_REG_DWORD(&reg->host_status);
                if (stat & HSRX_RISC_PAUSED) {
                        if (pci_channel_offline(ha->pdev))
                                break;
 
+                       if (ha->hw_event_pause_errors == 0)
+                               qla2x00_post_hwe_work(ha, HW_EVENT_PARITY_ERR,
+                                   0, MSW(stat), LSW(stat));
+                       else if (ha->hw_event_pause_errors < 0xffffffff)
+                               ha->hw_event_pause_errors++;
+
                        hccr = RD_REG_DWORD(&reg->hccr);
 
                        qla_printk(KERN_INFO, ha, "RISC paused -- HCCR=%x, "
@@ -1597,7 +1580,7 @@ qla24xx_intr_handler(int irq, void *dev_id)
                WRT_REG_DWORD(&reg->hccr, HCCRX_CLR_RISC_INT);
                RD_REG_DWORD_RELAXED(&reg->hccr);
        }
-       spin_unlock_irqrestore(&ha->hardware_lock, flags);
+       spin_unlock(&ha->hardware_lock);
 
        if (test_bit(MBX_INTR_WAIT, &ha->mbx_cmd_flags) &&
            (status & MBX_INTERRUPT) && ha->flags.mbox_int) {
@@ -1608,66 +1591,21 @@ qla24xx_intr_handler(int irq, void *dev_id)
        return IRQ_HANDLED;
 }
 
-/**
- * qla24xx_ms_entry() - Process a Management Server entry.
- * @ha: SCSI driver HA context
- * @index: Response queue out pointer
- */
-static void
-qla24xx_ms_entry(scsi_qla_host_t *ha, struct ct_entry_24xx *pkt)
-{
-       srb_t          *sp;
-
-       DEBUG3(printk("%s(%ld): pkt=%p pkthandle=%d.\n",
-           __func__, ha->host_no, pkt, pkt->handle));
-
-       DEBUG9(printk("%s: ct pkt dump:\n", __func__));
-       DEBUG9(qla2x00_dump_buffer((void *)pkt, sizeof(struct ct_entry_24xx)));
-
-       /* Validate handle. */
-       if (pkt->handle < MAX_OUTSTANDING_COMMANDS)
-               sp = ha->outstanding_cmds[pkt->handle];
-       else
-               sp = NULL;
-
-       if (sp == NULL) {
-               DEBUG2(printk("scsi(%ld): MS entry - invalid handle\n",
-                   ha->host_no));
-               DEBUG10(printk("scsi(%ld): MS entry - invalid handle\n",
-                   ha->host_no));
-               qla_printk(KERN_WARNING, ha, "MS entry - invalid handle %d\n",
-                   pkt->handle);
-
-               set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags);
-               return;
-       }
-
-       CMD_COMPL_STATUS(sp->cmd) = le16_to_cpu(pkt->comp_status);
-       CMD_ENTRY_STATUS(sp->cmd) = pkt->entry_status;
-
-       /* Free outstanding command slot. */
-       ha->outstanding_cmds[pkt->handle] = NULL;
-
-       qla2x00_sp_compl(ha, sp);
-}
-
 static irqreturn_t
 qla24xx_msix_rsp_q(int irq, void *dev_id)
 {
        scsi_qla_host_t *ha;
        struct device_reg_24xx __iomem *reg;
-       unsigned long flags;
 
        ha = dev_id;
        reg = &ha->iobase->isp24;
 
-       spin_lock_irqsave(&ha->hardware_lock, flags);
+       spin_lock_irq(&ha->hardware_lock);
 
        qla24xx_process_response_queue(ha);
-
        WRT_REG_DWORD(&reg->hccr, HCCRX_CLR_RISC_INT);
 
-       spin_unlock_irqrestore(&ha->hardware_lock, flags);
+       spin_unlock_irq(&ha->hardware_lock);
 
        return IRQ_HANDLED;
 }
@@ -1678,7 +1616,6 @@ qla24xx_msix_default(int irq, void *dev_id)
        scsi_qla_host_t *ha;
        struct device_reg_24xx __iomem *reg;
        int             status;
-       unsigned long   flags;
        uint32_t        stat;
        uint32_t        hccr;
        uint16_t        mb[4];
@@ -1687,13 +1624,19 @@ qla24xx_msix_default(int irq, void *dev_id)
        reg = &ha->iobase->isp24;
        status = 0;
 
-       spin_lock_irqsave(&ha->hardware_lock, flags);
+       spin_lock_irq(&ha->hardware_lock);
        do {
                stat = RD_REG_DWORD(&reg->host_status);
                if (stat & HSRX_RISC_PAUSED) {
                        if (pci_channel_offline(ha->pdev))
                                break;
 
+                       if (ha->hw_event_pause_errors == 0)
+                               qla2x00_post_hwe_work(ha, HW_EVENT_PARITY_ERR,
+                                   0, MSW(stat), LSW(stat));
+                       else if (ha->hw_event_pause_errors < 0xffffffff)
+                               ha->hw_event_pause_errors++;
+
                        hccr = RD_REG_DWORD(&reg->hccr);
 
                        qla_printk(KERN_INFO, ha, "RISC paused -- HCCR=%x, "
@@ -1734,7 +1677,7 @@ qla24xx_msix_default(int irq, void *dev_id)
                }
                WRT_REG_DWORD(&reg->hccr, HCCRX_CLR_RISC_INT);
        } while (0);
-       spin_unlock_irqrestore(&ha->hardware_lock, flags);
+       spin_unlock_irq(&ha->hardware_lock);
 
        if (test_bit(MBX_INTR_WAIT, &ha->mbx_cmd_flags) &&
            (status & MBX_INTERRUPT) && ha->flags.mbox_int) {
@@ -1821,10 +1764,9 @@ qla2x00_request_irqs(scsi_qla_host_t *ha)
 {
        int ret;
        device_reg_t __iomem *reg = ha->iobase;
-       unsigned long flags;
 
        /* If possible, enable MSI-X. */
-       if (!IS_QLA2432(ha) && !IS_QLA2532(ha))
+       if (!IS_QLA2432(ha) && !IS_QLA2532(ha) && !IS_QLA8432(ha))
                goto skip_msix;
 
         if (IS_QLA2432(ha) && (ha->chip_revision < QLA_MSIX_CHIP_REV_24XX ||
@@ -1859,7 +1801,7 @@ qla2x00_request_irqs(scsi_qla_host_t *ha)
            "MSI-X: Falling back-to INTa mode -- %d.\n", ret);
 skip_msix:
 
-       if (!IS_QLA24XX(ha) && !IS_QLA2532(ha))
+       if (!IS_QLA24XX(ha) && !IS_QLA2532(ha) && !IS_QLA8432(ha))
                goto skip_msi;
 
        ret = pci_enable_msi(ha->pdev);
@@ -1882,7 +1824,7 @@ skip_msi:
 clear_risc_ints:
 
        ha->isp_ops->disable_intrs(ha);
-       spin_lock_irqsave(&ha->hardware_lock, flags);
+       spin_lock_irq(&ha->hardware_lock);
        if (IS_FWI2_CAPABLE(ha)) {
                WRT_REG_DWORD(&reg->isp24.hccr, HCCRX_CLR_HOST_INT);
                WRT_REG_DWORD(&reg->isp24.hccr, HCCRX_CLR_RISC_INT);
@@ -1891,7 +1833,7 @@ clear_risc_ints:
                WRT_REG_WORD(&reg->isp.hccr, HCCR_CLR_RISC_INT);
                WRT_REG_WORD(&reg->isp.hccr, HCCR_CLR_HOST_INT);
        }
-       spin_unlock_irqrestore(&ha->hardware_lock, flags);
+       spin_unlock_irq(&ha->hardware_lock);
        ha->isp_ops->enable_intrs(ha);
 
 fail: