diff options
Diffstat (limited to 'drivers/scsi/qla2xxx/qla_isr.c')
-rw-r--r-- | drivers/scsi/qla2xxx/qla_isr.c | 144 |
1 files changed, 86 insertions, 58 deletions
diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c index 69bbea9239cc..78aec50abe0f 100644 --- a/drivers/scsi/qla2xxx/qla_isr.c +++ b/drivers/scsi/qla2xxx/qla_isr.c @@ -23,6 +23,14 @@ static void qla2x00_status_cont_entry(struct rsp_que *, sts_cont_entry_t *); static int qla2x00_error_entry(scsi_qla_host_t *, struct rsp_que *, sts_entry_t *); +const char *const port_state_str[] = { + "Unknown", + "UNCONFIGURED", + "DEAD", + "LOST", + "ONLINE" +}; + /** * qla2100_intr_handler() - Process interrupts for the ISP2100 and ISP2200. * @irq: interrupt number @@ -41,7 +49,7 @@ qla2100_intr_handler(int irq, void *dev_id) int status; unsigned long iter; uint16_t hccr; - uint16_t mb[4]; + uint16_t mb[8]; struct rsp_que *rsp; unsigned long flags; @@ -160,7 +168,7 @@ qla2300_intr_handler(int irq, void *dev_id) unsigned long iter; uint32_t stat; uint16_t hccr; - uint16_t mb[4]; + uint16_t mb[8]; struct rsp_que *rsp; struct qla_hw_data *ha; unsigned long flags; @@ -366,7 +374,7 @@ qla2x00_get_link_speed_str(struct qla_hw_data *ha, uint16_t speed) static const char *const link_speeds[] = { "1", "2", "?", "4", "8", "16", "32", "10" }; -#define QLA_LAST_SPEED 7 +#define QLA_LAST_SPEED (ARRAY_SIZE(link_speeds) - 1) if (IS_QLA2100(ha) || IS_QLA2200(ha)) return link_speeds[0]; @@ -708,12 +716,15 @@ skip_rio: break; case MBA_SYSTEM_ERR: /* System Error */ - mbx = (IS_QLA81XX(ha) || IS_QLA83XX(ha) || IS_QLA27XX(ha)) ? + mbx = (IS_QLA81XX(ha) || IS_QLA83XX(ha) || IS_QLA27XX(ha) || + IS_QLA28XX(ha)) ? RD_REG_WORD(®24->mailbox7) : 0; ql_log(ql_log_warn, vha, 0x5003, "ISP System Error - mbx1=%xh mbx2=%xh mbx3=%xh " "mbx7=%xh.\n", mb[1], mb[2], mb[3], mbx); - + ha->fw_dump_mpi = + (IS_QLA27XX(ha) || IS_QLA28XX(ha)) && + RD_REG_WORD(®24->mailbox7) & BIT_8; ha->isp_ops->fw_dump(vha, 1); ha->flags.fw_init_done = 0; QLA_FW_STOPPED(ha); @@ -837,6 +848,7 @@ skip_rio: if (ha->flags.fawwpn_enabled && (ha->current_topology == ISP_CFG_F)) { void *wwpn = ha->init_cb->port_name; + memcpy(vha->port_name, wwpn, WWN_SIZE); fc_host_port_name(vha->host) = wwn_to_u64(vha->port_name); @@ -1372,7 +1384,7 @@ qla2x00_mbx_iocb_entry(scsi_qla_host_t *vha, struct req_que *req, le16_to_cpu(mbx->status_flags)); ql_dump_buffer(ql_dbg_async + ql_dbg_buffer, vha, 0x5029, - (uint8_t *)mbx, sizeof(*mbx)); + mbx, sizeof(*mbx)); goto logio_done; } @@ -1516,7 +1528,7 @@ qla2x00_ct_entry(scsi_qla_host_t *vha, struct req_que *req, bsg_reply->reply_payload_rcv_len = 0; } ql_dump_buffer(ql_dbg_async + ql_dbg_buffer, vha, 0x5035, - (uint8_t *)pkt, sizeof(*pkt)); + pkt, sizeof(*pkt)); } else { res = DID_OK << 16; bsg_reply->reply_payload_rcv_len = @@ -1591,8 +1603,8 @@ qla24xx_els_ct_entry(scsi_qla_host_t *vha, struct req_que *req, } comp_status = fw_status[0] = le16_to_cpu(pkt->comp_status); - fw_status[1] = le16_to_cpu(((struct els_sts_entry_24xx*)pkt)->error_subcode_1); - fw_status[2] = le16_to_cpu(((struct els_sts_entry_24xx*)pkt)->error_subcode_2); + fw_status[1] = le16_to_cpu(((struct els_sts_entry_24xx *)pkt)->error_subcode_1); + fw_status[2] = le16_to_cpu(((struct els_sts_entry_24xx *)pkt)->error_subcode_2); if (iocb_type == ELS_IOCB_TYPE) { els = &sp->u.iocb_cmd; @@ -1613,7 +1625,7 @@ qla24xx_els_ct_entry(scsi_qla_host_t *vha, struct req_que *req, res = DID_ERROR << 16; } } - ql_log(ql_log_info, vha, 0x503f, + ql_dbg(ql_dbg_user, vha, 0x503f, "ELS IOCB Done -%s error hdl=%x comp_status=0x%x error subcode 1=0x%x error subcode 2=0x%x total_byte=0x%x\n", type, sp->handle, comp_status, fw_status[1], fw_status[2], le16_to_cpu(((struct els_sts_entry_24xx *) @@ -1656,7 +1668,7 @@ qla24xx_els_ct_entry(scsi_qla_host_t *vha, struct req_que *req, memcpy(bsg_job->reply + sizeof(struct fc_bsg_reply), fw_status, sizeof(fw_status)); ql_dump_buffer(ql_dbg_user + ql_dbg_buffer, vha, 0x5056, - (uint8_t *)pkt, sizeof(*pkt)); + pkt, sizeof(*pkt)); } else { res = DID_OK << 16; @@ -1700,7 +1712,7 @@ qla24xx_logio_entry(scsi_qla_host_t *vha, struct req_que *req, fcport->d_id.b.area, fcport->d_id.b.al_pa, logio->entry_status); ql_dump_buffer(ql_dbg_async + ql_dbg_buffer, vha, 0x504d, - (uint8_t *)logio, sizeof(*logio)); + logio, sizeof(*logio)); goto logio_done; } @@ -1846,8 +1858,8 @@ qla24xx_tm_iocb_entry(scsi_qla_host_t *vha, struct req_que *req, void *tsk) } if (iocb->u.tmf.data != QLA_SUCCESS) - ql_dump_buffer(ql_dbg_async + ql_dbg_buffer, vha, 0x5055, - (uint8_t *)sts, sizeof(*sts)); + ql_dump_buffer(ql_dbg_async + ql_dbg_buffer, sp->vha, 0x5055, + sts, sizeof(*sts)); sp->done(sp, 0); } @@ -1969,6 +1981,52 @@ static void qla_ctrlvp_completed(scsi_qla_host_t *vha, struct req_que *req, sp->done(sp, rval); } +/* Process a single response queue entry. */ +static void qla2x00_process_response_entry(struct scsi_qla_host *vha, + struct rsp_que *rsp, + sts_entry_t *pkt) +{ + sts21_entry_t *sts21_entry; + sts22_entry_t *sts22_entry; + uint16_t handle_cnt; + uint16_t cnt; + + switch (pkt->entry_type) { + case STATUS_TYPE: + qla2x00_status_entry(vha, rsp, pkt); + break; + case STATUS_TYPE_21: + sts21_entry = (sts21_entry_t *)pkt; + handle_cnt = sts21_entry->handle_count; + for (cnt = 0; cnt < handle_cnt; cnt++) + qla2x00_process_completed_request(vha, rsp->req, + sts21_entry->handle[cnt]); + break; + case STATUS_TYPE_22: + sts22_entry = (sts22_entry_t *)pkt; + handle_cnt = sts22_entry->handle_count; + for (cnt = 0; cnt < handle_cnt; cnt++) + qla2x00_process_completed_request(vha, rsp->req, + sts22_entry->handle[cnt]); + break; + case STATUS_CONT_TYPE: + qla2x00_status_cont_entry(rsp, (sts_cont_entry_t *)pkt); + break; + case MBX_IOCB_TYPE: + qla2x00_mbx_iocb_entry(vha, rsp->req, (struct mbx_entry *)pkt); + break; + case CT_IOCB_TYPE: + qla2x00_ct_entry(vha, rsp->req, pkt, CT_IOCB_TYPE); + break; + default: + /* Type Not Supported. */ + ql_log(ql_log_warn, vha, 0x504a, + "Received unknown response pkt type %x entry status=%x.\n", + pkt->entry_type, pkt->entry_status); + break; + } +} + /** * qla2x00_process_response_queue() - Process response queue entries. * @rsp: response queue @@ -1980,8 +2038,6 @@ qla2x00_process_response_queue(struct rsp_que *rsp) struct qla_hw_data *ha = rsp->hw; struct device_reg_2xxx __iomem *reg = &ha->iobase->isp; sts_entry_t *pkt; - uint16_t handle_cnt; - uint16_t cnt; vha = pci_get_drvdata(ha->pdev); @@ -2006,42 +2062,7 @@ qla2x00_process_response_queue(struct rsp_que *rsp) continue; } - switch (pkt->entry_type) { - case STATUS_TYPE: - qla2x00_status_entry(vha, rsp, pkt); - break; - case STATUS_TYPE_21: - handle_cnt = ((sts21_entry_t *)pkt)->handle_count; - for (cnt = 0; cnt < handle_cnt; cnt++) { - qla2x00_process_completed_request(vha, rsp->req, - ((sts21_entry_t *)pkt)->handle[cnt]); - } - break; - case STATUS_TYPE_22: - handle_cnt = ((sts22_entry_t *)pkt)->handle_count; - for (cnt = 0; cnt < handle_cnt; cnt++) { - qla2x00_process_completed_request(vha, rsp->req, - ((sts22_entry_t *)pkt)->handle[cnt]); - } - break; - case STATUS_CONT_TYPE: - qla2x00_status_cont_entry(rsp, (sts_cont_entry_t *)pkt); - break; - case MBX_IOCB_TYPE: - qla2x00_mbx_iocb_entry(vha, rsp->req, - (struct mbx_entry *)pkt); - break; - case CT_IOCB_TYPE: - qla2x00_ct_entry(vha, rsp->req, pkt, CT_IOCB_TYPE); - break; - default: - /* Type Not Supported. */ - ql_log(ql_log_warn, vha, 0x504a, - "Received unknown response pkt type %x " - "entry status=%x.\n", - pkt->entry_type, pkt->entry_status); - break; - } + qla2x00_process_response_entry(vha, rsp, pkt); ((response_t *)pkt)->signature = RESPONSE_PROCESSED; wmb(); } @@ -2238,6 +2259,7 @@ qla25xx_process_bidir_status_iocb(scsi_qla_host_t *vha, void *pkt, struct fc_bsg_reply *bsg_reply; sts_entry_t *sts; struct sts_entry_24xx *sts24; + sts = (sts_entry_t *) pkt; sts24 = (struct sts_entry_24xx *) pkt; @@ -3014,7 +3036,8 @@ process_err: qla24xx_els_ct_entry(vha, rsp->req, pkt, ELS_IOCB_TYPE); break; case ABTS_RECV_24XX: - if (IS_QLA83XX(ha) || IS_QLA27XX(ha)) { + if (IS_QLA83XX(ha) || IS_QLA27XX(ha) || + IS_QLA28XX(ha)) { /* ensure that the ATIO queue is empty */ qlt_handle_abts_recv(vha, rsp, (response_t *)pkt); @@ -3072,6 +3095,7 @@ process_err: /* Adjust ring index */ if (IS_P3P_TYPE(ha)) { struct device_reg_82xx __iomem *reg = &ha->iobase->isp82; + WRT_REG_DWORD(®->rsp_q_out[0], rsp->ring_index); } else { WRT_REG_DWORD(rsp->rsp_q_out, rsp->ring_index); @@ -3087,7 +3111,7 @@ qla2xxx_check_risc_status(scsi_qla_host_t *vha) struct device_reg_24xx __iomem *reg = &ha->iobase->isp24; if (!IS_QLA25XX(ha) && !IS_QLA81XX(ha) && !IS_QLA83XX(ha) && - !IS_QLA27XX(ha)) + !IS_QLA27XX(ha) && !IS_QLA28XX(ha)) return; rval = QLA_SUCCESS; @@ -3475,7 +3499,7 @@ qla24xx_enable_msix(struct qla_hw_data *ha, struct rsp_que *rsp) ql_log(ql_log_fatal, vha, 0x00c8, "Failed to allocate memory for ha->msix_entries.\n"); ret = -ENOMEM; - goto msix_out; + goto free_irqs; } ha->flags.msix_enabled = 1; @@ -3539,7 +3563,7 @@ msix_register_fail: } /* Enable MSI-X vector for response queue update for queue 0 */ - if (IS_QLA83XX(ha) || IS_QLA27XX(ha)) { + if (IS_QLA83XX(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha)) { if (ha->msixbase && ha->mqiobase && (ha->max_rsp_queues > 1 || ha->max_req_queues > 1 || ql2xmqsupport)) @@ -3558,6 +3582,10 @@ msix_register_fail: msix_out: return ret; + +free_irqs: + pci_free_irq_vectors(ha->pdev); + goto msix_out; } int @@ -3570,7 +3598,7 @@ qla2x00_request_irqs(struct qla_hw_data *ha, struct rsp_que *rsp) /* If possible, enable MSI-X. */ if (ql2xenablemsix == 0 || (!IS_QLA2432(ha) && !IS_QLA2532(ha) && !IS_QLA8432(ha) && !IS_CNA_CAPABLE(ha) && !IS_QLA2031(ha) && - !IS_QLAFX00(ha) && !IS_QLA27XX(ha))) + !IS_QLAFX00(ha) && !IS_QLA27XX(ha) && !IS_QLA28XX(ha))) goto skip_msi; if (ql2xenablemsix == 2) @@ -3609,7 +3637,7 @@ skip_msix: if (!IS_QLA24XX(ha) && !IS_QLA2532(ha) && !IS_QLA8432(ha) && !IS_QLA8001(ha) && !IS_P3P_TYPE(ha) && !IS_QLAFX00(ha) && - !IS_QLA27XX(ha)) + !IS_QLA27XX(ha) && !IS_QLA28XX(ha)) goto skip_msi; ret = pci_alloc_irq_vectors(ha->pdev, 1, 1, PCI_IRQ_MSI); |