diff options
Diffstat (limited to 'drivers/scsi/qla2xxx/qla_isr.c')
-rw-r--r-- | drivers/scsi/qla2xxx/qla_isr.c | 335 |
1 files changed, 240 insertions, 95 deletions
diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c index 89d327117aa..eb4b43d7697 100644 --- a/drivers/scsi/qla2xxx/qla_isr.c +++ b/drivers/scsi/qla2xxx/qla_isr.c @@ -10,10 +10,12 @@ #include <scsi/scsi_tcq.h> static void qla2x00_mbx_completion(scsi_qla_host_t *, uint16_t); -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_process_completed_request(struct scsi_qla_host *, + struct req_que *, uint32_t); +static void qla2x00_status_entry(scsi_qla_host_t *, struct rsp_que *, 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_error_entry(scsi_qla_host_t *, struct rsp_que *, + sts_entry_t *); static struct scsi_qla_host *qla2x00_get_rsp_host(struct rsp_que *); /** @@ -83,7 +85,7 @@ qla2100_intr_handler(int irq, void *dev_id) mb[1] = RD_MAILBOX_REG(ha, reg, 1); mb[2] = RD_MAILBOX_REG(ha, reg, 2); mb[3] = RD_MAILBOX_REG(ha, reg, 3); - qla2x00_async_event(vha, mb); + qla2x00_async_event(vha, rsp, mb); } else { /*EMPTY*/ DEBUG2(printk("scsi(%ld): Unrecognized " @@ -94,7 +96,7 @@ qla2100_intr_handler(int irq, void *dev_id) WRT_REG_WORD(®->semaphore, 0); RD_REG_WORD(®->semaphore); } else { - qla2x00_process_response_queue(vha); + qla2x00_process_response_queue(rsp); WRT_REG_WORD(®->hccr, HCCR_CLR_RISC_INT); RD_REG_WORD(®->hccr); @@ -190,21 +192,21 @@ qla2300_intr_handler(int irq, void *dev_id) mb[1] = RD_MAILBOX_REG(ha, reg, 1); mb[2] = RD_MAILBOX_REG(ha, reg, 2); mb[3] = RD_MAILBOX_REG(ha, reg, 3); - qla2x00_async_event(vha, mb); + qla2x00_async_event(vha, rsp, mb); break; case 0x13: - qla2x00_process_response_queue(vha); + qla2x00_process_response_queue(rsp); break; case 0x15: mb[0] = MBA_CMPLT_1_16BIT; mb[1] = MSW(stat); - qla2x00_async_event(vha, mb); + qla2x00_async_event(vha, rsp, mb); break; case 0x16: mb[0] = MBA_SCSI_COMPLETION; mb[1] = MSW(stat); mb[2] = RD_MAILBOX_REG(ha, reg, 2); - qla2x00_async_event(vha, mb); + qla2x00_async_event(vha, rsp, mb); break; default: DEBUG2(printk("scsi(%ld): Unrecognized interrupt type " @@ -270,7 +272,7 @@ qla2x00_mbx_completion(scsi_qla_host_t *vha, uint16_t mb0) * @mb: Mailbox registers (0 - 3) */ void -qla2x00_async_event(scsi_qla_host_t *vha, uint16_t *mb) +qla2x00_async_event(scsi_qla_host_t *vha, struct rsp_que *rsp, uint16_t *mb) { #define LS_UNKNOWN 2 static char *link_speeds[5] = { "1", "2", "?", "4", "8" }; @@ -344,7 +346,8 @@ qla2x00_async_event(scsi_qla_host_t *vha, uint16_t *mb) break; for (cnt = 0; cnt < handle_cnt; cnt++) - qla2x00_process_completed_request(vha, handles[cnt]); + qla2x00_process_completed_request(vha, rsp->req, + handles[cnt]); break; case MBA_RESET: /* Reset */ @@ -554,6 +557,10 @@ qla2x00_async_event(scsi_qla_host_t *vha, uint16_t *mb) break; case MBA_PORT_UPDATE: /* Port database update */ + /* Only handle SCNs for our Vport index. */ + if (vha->vp_idx && vha->vp_idx != (mb[3] & 0xff)) + break; + /* * If PORT UPDATE is global (received LIP_OCCURRED/LIP_RESET * event etc. earlier indicating loop is down) then process @@ -641,9 +648,9 @@ qla2x00_async_event(scsi_qla_host_t *vha, uint16_t *mb) vha->host_no)); if (IS_FWI2_CAPABLE(ha)) - qla24xx_process_response_queue(vha); + qla24xx_process_response_queue(rsp); else - qla2x00_process_response_queue(vha); + qla2x00_process_response_queue(rsp); break; case MBA_DISCARD_RND_FRAME: @@ -694,15 +701,21 @@ qla2x00_async_event(scsi_qla_host_t *vha, uint16_t *mb) } if (!vha->vp_idx && ha->num_vhosts) - qla2x00_alert_all_vps(ha, mb); + qla2x00_alert_all_vps(rsp, mb); } static void qla2x00_adjust_sdev_qdepth_up(struct scsi_device *sdev, void *data) { fc_port_t *fcport = data; - struct qla_hw_data *ha = fcport->vha->hw; - if (ha->req->max_q_depth <= sdev->queue_depth) + struct scsi_qla_host *vha = fcport->vha; + struct qla_hw_data *ha = vha->hw; + struct req_que *req = NULL; + + req = ha->req_q_map[vha->req_ques[0]]; + if (!req) + return; + if (req->max_q_depth <= sdev->queue_depth) return; if (sdev->ordered_tags) @@ -735,14 +748,14 @@ qla2x00_adjust_sdev_qdepth_down(struct scsi_device *sdev, void *data) } static inline void -qla2x00_ramp_up_queue_depth(scsi_qla_host_t *vha, srb_t *sp) +qla2x00_ramp_up_queue_depth(scsi_qla_host_t *vha, struct req_que *req, + srb_t *sp) { fc_port_t *fcport; struct scsi_device *sdev; - struct qla_hw_data *ha = vha->hw; sdev = sp->cmd->device; - if (sdev->queue_depth >= ha->req->max_q_depth) + if (sdev->queue_depth >= req->max_q_depth) return; fcport = sp->fcport; @@ -763,11 +776,11 @@ qla2x00_ramp_up_queue_depth(scsi_qla_host_t *vha, srb_t *sp) * @index: SRB index */ static void -qla2x00_process_completed_request(struct scsi_qla_host *vha, uint32_t index) +qla2x00_process_completed_request(struct scsi_qla_host *vha, + struct req_que *req, uint32_t index) { srb_t *sp; struct qla_hw_data *ha = vha->hw; - struct req_que *req = ha->req; /* Validate handle. */ if (index >= MAX_OUTSTANDING_COMMANDS) { @@ -791,8 +804,8 @@ qla2x00_process_completed_request(struct scsi_qla_host *vha, uint32_t index) /* Save ISP completion status */ sp->cmd->result = DID_OK << 16; - qla2x00_ramp_up_queue_depth(vha, sp); - qla2x00_sp_compl(vha, sp); + qla2x00_ramp_up_queue_depth(vha, req, sp); + qla2x00_sp_compl(ha, sp); } else { DEBUG2(printk("scsi(%ld): Invalid ISP SCSI completion handle\n", vha->host_no)); @@ -808,14 +821,16 @@ qla2x00_process_completed_request(struct scsi_qla_host *vha, uint32_t index) * @ha: SCSI driver HA context */ void -qla2x00_process_response_queue(struct scsi_qla_host *vha) +qla2x00_process_response_queue(struct rsp_que *rsp) { - struct qla_hw_data *ha = vha->hw; + struct scsi_qla_host *vha; + 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; - struct rsp_que *rsp = ha->rsp; + + vha = qla2x00_get_rsp_host(rsp); if (!vha->flags.online) return; @@ -835,7 +850,7 @@ qla2x00_process_response_queue(struct scsi_qla_host *vha) DEBUG3(printk(KERN_INFO "scsi(%ld): Process error entry.\n", vha->host_no)); - qla2x00_error_entry(vha, pkt); + qla2x00_error_entry(vha, rsp, pkt); ((response_t *)pkt)->signature = RESPONSE_PROCESSED; wmb(); continue; @@ -843,19 +858,19 @@ qla2x00_process_response_queue(struct scsi_qla_host *vha) switch (pkt->entry_type) { case STATUS_TYPE: - qla2x00_status_entry(vha, pkt); + 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, + 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, + qla2x00_process_completed_request(vha, rsp->req, ((sts22_entry_t *)pkt)->handle[cnt]); } break; @@ -914,7 +929,7 @@ qla2x00_handle_sense(srb_t *sp, uint8_t *sense_data, uint32_t sense_len) * @pkt: Entry pointer */ static void -qla2x00_status_entry(scsi_qla_host_t *vha, void *pkt) +qla2x00_status_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, void *pkt) { srb_t *sp; fc_port_t *fcport; @@ -928,7 +943,7 @@ qla2x00_status_entry(scsi_qla_host_t *vha, void *pkt) uint32_t sense_len, rsp_info_len, resid_len, fw_resid_len; uint8_t *rsp_info, *sense_data; struct qla_hw_data *ha = vha->hw; - struct req_que *req = ha->req; + struct req_que *req = rsp->req; sts = (sts_entry_t *) pkt; sts24 = (struct sts_entry_24xx *) pkt; @@ -942,7 +957,7 @@ qla2x00_status_entry(scsi_qla_host_t *vha, void *pkt) /* Fast path completion. */ if (comp_status == CS_COMPLETE && scsi_status == 0) { - qla2x00_process_completed_request(vha, sts->handle); + qla2x00_process_completed_request(vha, req, sts->handle); return; } @@ -1012,7 +1027,7 @@ qla2x00_status_entry(scsi_qla_host_t *vha, void *pkt) rsp_info[5], rsp_info[6], rsp_info[7])); cp->result = DID_BUS_BUSY << 16; - qla2x00_sp_compl(vha, sp); + qla2x00_sp_compl(ha, sp); return; } } @@ -1276,7 +1291,7 @@ qla2x00_status_entry(scsi_qla_host_t *vha, void *pkt) /* Place command on done queue. */ if (vha->status_srb == NULL) - qla2x00_sp_compl(vha, sp); + qla2x00_sp_compl(ha, sp); } /** @@ -1325,7 +1340,7 @@ qla2x00_status_cont_entry(scsi_qla_host_t *vha, sts_cont_entry_t *pkt) /* Place command on done queue. */ if (sp->request_sense_length == 0) { vha->status_srb = NULL; - qla2x00_sp_compl(vha, sp); + qla2x00_sp_compl(ha, sp); } } } @@ -1336,11 +1351,11 @@ qla2x00_status_cont_entry(scsi_qla_host_t *vha, sts_cont_entry_t *pkt) * @pkt: Entry pointer */ static void -qla2x00_error_entry(scsi_qla_host_t *vha, sts_entry_t *pkt) +qla2x00_error_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, sts_entry_t *pkt) { srb_t *sp; struct qla_hw_data *ha = vha->hw; - struct req_que *req = ha->req; + struct req_que *req = rsp->req; #if defined(QL_DEBUG_LEVEL_2) if (pkt->entry_status & RF_INV_E_ORDER) qla_printk(KERN_ERR, ha, "%s: Invalid Entry Order\n", __func__); @@ -1377,7 +1392,7 @@ qla2x00_error_entry(scsi_qla_host_t *vha, sts_entry_t *pkt) } else { sp->cmd->result = DID_ERROR << 16; } - qla2x00_sp_compl(vha, sp); + qla2x00_sp_compl(ha, sp); } else if (pkt->entry_type == COMMAND_A64_TYPE || pkt->entry_type == COMMAND_TYPE || pkt->entry_type == COMMAND_TYPE_7) { @@ -1428,12 +1443,14 @@ qla24xx_mbx_completion(scsi_qla_host_t *vha, uint16_t mb0) * @ha: SCSI driver HA context */ void -qla24xx_process_response_queue(struct scsi_qla_host *vha) +qla24xx_process_response_queue(struct rsp_que *rsp) { - struct qla_hw_data *ha = vha->hw; - struct device_reg_24xx __iomem *reg = &ha->iobase->isp24; + struct qla_hw_data *ha = rsp->hw; + device_reg_t __iomem *reg = ISP_QUE_REG(ha, rsp->id); struct sts_entry_24xx *pkt; - struct rsp_que *rsp = ha->rsp; + struct scsi_qla_host *vha; + + vha = qla2x00_get_rsp_host(rsp); if (!vha->flags.online) return; @@ -1453,7 +1470,7 @@ qla24xx_process_response_queue(struct scsi_qla_host *vha) DEBUG3(printk(KERN_INFO "scsi(%ld): Process error entry.\n", vha->host_no)); - qla2x00_error_entry(vha, (sts_entry_t *) pkt); + qla2x00_error_entry(vha, rsp, (sts_entry_t *) pkt); ((response_t *)pkt)->signature = RESPONSE_PROCESSED; wmb(); continue; @@ -1461,7 +1478,7 @@ qla24xx_process_response_queue(struct scsi_qla_host *vha) switch (pkt->entry_type) { case STATUS_TYPE: - qla2x00_status_entry(vha, pkt); + qla2x00_status_entry(vha, rsp, pkt); break; case STATUS_CONT_TYPE: qla2x00_status_cont_entry(vha, (sts_cont_entry_t *)pkt); @@ -1483,7 +1500,10 @@ qla24xx_process_response_queue(struct scsi_qla_host *vha) } /* Adjust ring index */ - WRT_REG_DWORD(®->rsp_q_out, rsp->ring_index); + if (ha->mqenable) + WRT_REG_DWORD(®->isp25mq.rsp_q_out, rsp->ring_index); + else + WRT_REG_DWORD(®->isp24.rsp_q_out, rsp->ring_index); } static void @@ -1607,10 +1627,11 @@ qla24xx_intr_handler(int irq, void *dev_id) mb[1] = RD_REG_WORD(®->mailbox1); mb[2] = RD_REG_WORD(®->mailbox2); mb[3] = RD_REG_WORD(®->mailbox3); - qla2x00_async_event(vha, mb); + qla2x00_async_event(vha, rsp, mb); break; case 0x13: - qla24xx_process_response_queue(vha); + case 0x14: + qla24xx_process_response_queue(rsp); break; default: DEBUG2(printk("scsi(%ld): Unrecognized interrupt type " @@ -1635,7 +1656,6 @@ qla24xx_intr_handler(int irq, void *dev_id) static irqreturn_t qla24xx_msix_rsp_q(int irq, void *dev_id) { - scsi_qla_host_t *vha; struct qla_hw_data *ha; struct rsp_que *rsp; struct device_reg_24xx __iomem *reg; @@ -1651,8 +1671,7 @@ qla24xx_msix_rsp_q(int irq, void *dev_id) spin_lock_irq(&ha->hardware_lock); - vha = qla2x00_get_rsp_host(rsp); - qla24xx_process_response_queue(vha); + qla24xx_process_response_queue(rsp); WRT_REG_DWORD(®->hccr, HCCRX_CLR_RISC_INT); spin_unlock_irq(&ha->hardware_lock); @@ -1661,6 +1680,41 @@ qla24xx_msix_rsp_q(int irq, void *dev_id) } static irqreturn_t +qla25xx_msix_rsp_q(int irq, void *dev_id) +{ + struct qla_hw_data *ha; + struct rsp_que *rsp; + struct device_reg_24xx __iomem *reg; + uint16_t msix_disabled_hccr = 0; + + rsp = (struct rsp_que *) dev_id; + if (!rsp) { + printk(KERN_INFO + "%s(): NULL response queue pointer\n", __func__); + return IRQ_NONE; + } + ha = rsp->hw; + reg = &ha->iobase->isp24; + + spin_lock_irq(&ha->hardware_lock); + + msix_disabled_hccr = rsp->options; + if (!rsp->id) + msix_disabled_hccr &= __constant_cpu_to_le32(BIT_22); + else + msix_disabled_hccr &= BIT_6; + + qla24xx_process_response_queue(rsp); + + if (!msix_disabled_hccr) + WRT_REG_DWORD(®->hccr, HCCRX_CLR_RISC_INT); + + spin_unlock_irq(&ha->hardware_lock); + + return IRQ_HANDLED; +} + +static irqreturn_t qla24xx_msix_default(int irq, void *dev_id) { scsi_qla_host_t *vha; @@ -1723,10 +1777,11 @@ qla24xx_msix_default(int irq, void *dev_id) mb[1] = RD_REG_WORD(®->mailbox1); mb[2] = RD_REG_WORD(®->mailbox2); mb[3] = RD_REG_WORD(®->mailbox3); - qla2x00_async_event(vha, mb); + qla2x00_async_event(vha, rsp, mb); break; case 0x13: - qla24xx_process_response_queue(vha); + case 0x14: + qla24xx_process_response_queue(rsp); break; default: DEBUG2(printk("scsi(%ld): Unrecognized interrupt type " @@ -1756,12 +1811,25 @@ struct qla_init_msix_entry { irq_handler_t handler; }; -static struct qla_init_msix_entry imsix_entries[QLA_MSIX_ENTRIES] = { - { QLA_MSIX_DEFAULT, QLA_MIDX_DEFAULT, - "qla2xxx (default)", qla24xx_msix_default }, +static struct qla_init_msix_entry base_queue = { + .entry = 0, + .index = 0, + .name = "qla2xxx (default)", + .handler = qla24xx_msix_default, +}; + +static struct qla_init_msix_entry base_rsp_queue = { + .entry = 1, + .index = 1, + .name = "qla2xxx (rsp_q)", + .handler = qla24xx_msix_rsp_q, +}; - { QLA_MSIX_RSP_Q, QLA_MIDX_RSP_Q, - "qla2xxx (rsp_q)", qla24xx_msix_rsp_q }, +static struct qla_init_msix_entry multi_rsp_queue = { + .entry = 1, + .index = 1, + .name = "qla2xxx (multi_q)", + .handler = qla25xx_msix_rsp_q, }; static void @@ -1769,63 +1837,115 @@ qla24xx_disable_msix(struct qla_hw_data *ha) { int i; struct qla_msix_entry *qentry; - struct rsp_que *rsp = ha->rsp; - for (i = 0; i < QLA_MSIX_ENTRIES; i++) { - qentry = &ha->msix_entries[imsix_entries[i].index]; + for (i = 0; i < ha->msix_count; i++) { + qentry = &ha->msix_entries[i]; if (qentry->have_irq) - free_irq(qentry->msix_vector, rsp); + free_irq(qentry->vector, qentry->rsp); } pci_disable_msix(ha->pdev); + kfree(ha->msix_entries); + ha->msix_entries = NULL; + ha->flags.msix_enabled = 0; } static int -qla24xx_enable_msix(struct qla_hw_data *ha) +qla24xx_enable_msix(struct qla_hw_data *ha, struct rsp_que *rsp) { int i, ret; - struct rsp_que *rsp = ha->rsp; - struct msix_entry entries[QLA_MSIX_ENTRIES]; + struct msix_entry *entries; struct qla_msix_entry *qentry; + struct qla_init_msix_entry *msix_queue; + + entries = kzalloc(sizeof(struct msix_entry) * ha->msix_count, + GFP_KERNEL); + if (!entries) + return -ENOMEM; - for (i = 0; i < QLA_MSIX_ENTRIES; i++) - entries[i].entry = imsix_entries[i].entry; + for (i = 0; i < ha->msix_count; i++) + entries[i].entry = i; - ret = pci_enable_msix(ha->pdev, entries, ARRAY_SIZE(entries)); + ret = pci_enable_msix(ha->pdev, entries, ha->msix_count); if (ret) { qla_printk(KERN_WARNING, ha, - "MSI-X: Failed to enable support -- %d/%d\n", - QLA_MSIX_ENTRIES, ret); + "MSI-X: Failed to enable support -- %d/%d\n" + " Retry with %d vectors\n", ha->msix_count, ret, ret); + ha->msix_count = ret; + ret = pci_enable_msix(ha->pdev, entries, ha->msix_count); + if (ret) { + qla_printk(KERN_WARNING, ha, "MSI-X: Failed to enable" + " support, giving up -- %d/%d\n", + ha->msix_count, ret); + goto msix_out; + } + ha->max_queues = ha->msix_count - 1; + } + ha->msix_entries = kzalloc(sizeof(struct qla_msix_entry) * + ha->msix_count, GFP_KERNEL); + if (!ha->msix_entries) { + ret = -ENOMEM; goto msix_out; } ha->flags.msix_enabled = 1; - for (i = 0; i < QLA_MSIX_ENTRIES; i++) { - qentry = &ha->msix_entries[imsix_entries[i].index]; - qentry->msix_vector = entries[i].vector; - qentry->msix_entry = entries[i].entry; + for (i = 0; i < ha->msix_count; i++) { + qentry = &ha->msix_entries[i]; + qentry->vector = entries[i].vector; + qentry->entry = entries[i].entry; qentry->have_irq = 0; - ret = request_irq(qentry->msix_vector, - imsix_entries[i].handler, 0, imsix_entries[i].name, rsp); - if (ret) { - qla_printk(KERN_WARNING, ha, - "MSI-X: Unable to register handler -- %x/%d.\n", - imsix_entries[i].index, ret); - qla24xx_disable_msix(ha); - goto msix_out; - } - qentry->have_irq = 1; + qentry->rsp = NULL; } + /* Enable MSI-X for AENs for queue 0 */ + qentry = &ha->msix_entries[0]; + ret = request_irq(qentry->vector, base_queue.handler, 0, + base_queue.name, rsp); + if (ret) { + qla_printk(KERN_WARNING, ha, + "MSI-X: Unable to register handler -- %x/%d.\n", + qentry->vector, ret); + qla24xx_disable_msix(ha); + goto msix_out; + } + qentry->have_irq = 1; + qentry->rsp = rsp; + + /* Enable MSI-X vector for response queue update for queue 0 */ + if (ha->max_queues > 1 && ha->mqiobase) { + ha->mqenable = 1; + msix_queue = &multi_rsp_queue; + qla_printk(KERN_INFO, ha, + "MQ enabled, Number of Queue Resources: %d \n", + ha->max_queues); + } else { + ha->mqenable = 0; + msix_queue = &base_rsp_queue; + } + + qentry = &ha->msix_entries[1]; + ret = request_irq(qentry->vector, msix_queue->handler, 0, + msix_queue->name, rsp); + if (ret) { + qla_printk(KERN_WARNING, ha, + "MSI-X: Unable to register handler -- %x/%d.\n", + qentry->vector, ret); + qla24xx_disable_msix(ha); + ha->mqenable = 0; + goto msix_out; + } + qentry->have_irq = 1; + qentry->rsp = rsp; + msix_out: + kfree(entries); return ret; } int -qla2x00_request_irqs(struct qla_hw_data *ha) +qla2x00_request_irqs(struct qla_hw_data *ha, struct rsp_que *rsp) { int ret; device_reg_t __iomem *reg = ha->iobase; - struct rsp_que *rsp = ha->rsp; /* If possible, enable MSI-X. */ if (!IS_QLA2432(ha) && !IS_QLA2532(ha) && !IS_QLA8432(ha)) @@ -1852,7 +1972,7 @@ qla2x00_request_irqs(struct qla_hw_data *ha) goto skip_msi; } - ret = qla24xx_enable_msix(ha); + ret = qla24xx_enable_msix(ha, rsp); if (!ret) { DEBUG2(qla_printk(KERN_INFO, ha, "MSI-X: Enabled (0x%X, 0x%X).\n", ha->chip_revision, @@ -1903,7 +2023,7 @@ void qla2x00_free_irqs(scsi_qla_host_t *vha) { struct qla_hw_data *ha = vha->hw; - struct rsp_que *rsp = ha->rsp; + struct rsp_que *rsp = ha->rsp_q_map[0]; if (ha->flags.msix_enabled) qla24xx_disable_msix(ha); @@ -1919,16 +2039,41 @@ qla2x00_get_rsp_host(struct rsp_que *rsp) srb_t *sp; struct qla_hw_data *ha = rsp->hw; struct scsi_qla_host *vha = NULL; - struct sts_entry_24xx *pkt = (struct sts_entry_24xx *) rsp->ring_ptr; - - if (pkt && pkt->handle < MAX_OUTSTANDING_COMMANDS) { - sp = ha->req->outstanding_cmds[pkt->handle]; - if (sp) - vha = sp->vha; + struct sts_entry_24xx *pkt; + struct req_que *req; + + if (rsp->id) { + pkt = (struct sts_entry_24xx *) rsp->ring_ptr; + req = rsp->req; + if (pkt && pkt->handle < MAX_OUTSTANDING_COMMANDS) { + sp = req->outstanding_cmds[pkt->handle]; + if (sp) + vha = sp->vha; + } } if (!vha) - /* Invalid entry, handle it in base queue */ + /* handle it in base queue */ vha = pci_get_drvdata(ha->pdev); return vha; } + +int qla25xx_request_irq(struct rsp_que *rsp) +{ + struct qla_hw_data *ha = rsp->hw; + struct qla_init_msix_entry *intr = &multi_rsp_queue; + struct qla_msix_entry *msix = rsp->msix; + int ret; + + ret = request_irq(msix->vector, intr->handler, 0, intr->name, rsp); + if (ret) { + qla_printk(KERN_WARNING, ha, + "MSI-X: Unable to register handler -- %x/%d.\n", + msix->vector, ret); + return ret; + } + msix->have_irq = 1; + msix->rsp = rsp; + return ret; +} + |