📄 qla_isr.c
字号:
"frame(s) detected (%x of %x bytes)..." "retrying command.\n", ha->host_no, cp->device->channel, cp->device->id, cp->device->lun, resid, cp->request_bufflen)); cp->result = DID_BUS_BUSY << 16; break; } /* Handle mid-layer underflow */ if ((unsigned)(cp->request_bufflen - resid) < cp->underflow) { 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, cp->request_bufflen); cp->result = DID_ERROR << 16; break; } /* Everybody online, looking good... */ cp->result = DID_OK << 16; } break; case CS_DATA_OVERRUN: DEBUG2(printk(KERN_INFO "scsi(%ld:%d:%d): OVERRUN status detected 0x%x-0x%x\n", ha->host_no, cp->device->id, cp->device->lun, comp_status, scsi_status)); DEBUG2(printk(KERN_INFO "CDB: 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n", cp->cmnd[0], cp->cmnd[1], cp->cmnd[2], cp->cmnd[3], cp->cmnd[4], cp->cmnd[5])); DEBUG2(printk(KERN_INFO "PID=0x%lx req=0x%x xtra=0x%x -- returning DID_ERROR " "status!\n", cp->serial_number, cp->request_bufflen, resid_len)); cp->result = DID_ERROR << 16; break; case CS_PORT_LOGGED_OUT: case CS_PORT_CONFIG_CHG: case CS_PORT_BUSY: case CS_INCOMPLETE: case CS_PORT_UNAVAILABLE: /* * If the port is in Target Down state, return all IOs for this * Target with DID_NO_CONNECT ELSE Queue the IOs in the * retry_queue. */ DEBUG2(printk("scsi(%ld:%d:%d): status_entry: Port Down " "pid=%ld, compl status=0x%x, port state=0x%x\n", ha->host_no, cp->device->id, cp->device->lun, cp->serial_number, comp_status, atomic_read(&fcport->state))); cp->result = DID_BUS_BUSY << 16; if (atomic_read(&fcport->state) == FCS_ONLINE) { qla2x00_mark_device_lost(ha, fcport, 1); } break; case CS_RESET: DEBUG2(printk(KERN_INFO "scsi(%ld): RESET status detected 0x%x-0x%x.\n", ha->host_no, comp_status, scsi_status)); cp->result = DID_RESET << 16; break; case CS_ABORTED: /* * hv2.19.12 - DID_ABORT does not retry the request if we * aborted this request then abort otherwise it must be a * reset. */ DEBUG2(printk(KERN_INFO "scsi(%ld): ABORT status detected 0x%x-0x%x.\n", ha->host_no, comp_status, scsi_status)); cp->result = DID_RESET << 16; break; case CS_TIMEOUT: cp->result = DID_BUS_BUSY << 16; if (IS_QLA24XX(ha) || IS_QLA25XX(ha)) { DEBUG2(printk(KERN_INFO "scsi(%ld:%d:%d:%d): TIMEOUT status detected " "0x%x-0x%x\n", ha->host_no, cp->device->channel, cp->device->id, cp->device->lun, comp_status, scsi_status)); break; } DEBUG2(printk(KERN_INFO "scsi(%ld:%d:%d:%d): TIMEOUT status detected 0x%x-0x%x " "sflags=%x.\n", ha->host_no, cp->device->channel, cp->device->id, cp->device->lun, comp_status, scsi_status, le16_to_cpu(sts->status_flags))); /* Check to see if logout occurred. */ if ((le16_to_cpu(sts->status_flags) & SF_LOGOUT_SENT)) qla2x00_mark_device_lost(ha, fcport, 1); break; case CS_QUEUE_FULL: DEBUG2(printk(KERN_INFO "scsi(%ld): QUEUE FULL status detected 0x%x-0x%x.\n", ha->host_no, comp_status, scsi_status)); /* SCSI Mid-Layer handles device queue full */ cp->result = DID_OK << 16 | lscsi_status; break; default: DEBUG3(printk("scsi(%ld): Error detected (unknown status) " "0x%x-0x%x.\n", ha->host_no, comp_status, scsi_status)); qla_printk(KERN_INFO, ha, "Unknown status detected 0x%x-0x%x.\n", comp_status, scsi_status); cp->result = DID_ERROR << 16; break; } /* Place command on done queue. */ if (ha->status_srb == NULL) qla2x00_sp_compl(ha, sp);}/** * qla2x00_status_cont_entry() - Process a Status Continuations entry. * @ha: SCSI driver HA context * @pkt: Entry pointer * * Extended sense data. */static voidqla2x00_status_cont_entry(scsi_qla_host_t *ha, sts_cont_entry_t *pkt){ uint8_t sense_sz = 0; srb_t *sp = ha->status_srb; struct scsi_cmnd *cp; if (sp != NULL && sp->request_sense_length != 0) { cp = sp->cmd; if (cp == NULL) { DEBUG2(printk("%s(): Cmd already returned back to OS " "sp=%p sp->state:%d\n", __func__, sp, sp->state)); qla_printk(KERN_INFO, ha, "cmd is NULL: already returned to OS (sp=%p)\n", sp); ha->status_srb = NULL; return; } if (sp->request_sense_length > sizeof(pkt->data)) { sense_sz = sizeof(pkt->data); } else { sense_sz = sp->request_sense_length; } /* Move sense data. */ if (IS_QLA24XX(ha) || IS_QLA25XX(ha)) host_to_fcp_swap(pkt->data, sizeof(pkt->data)); memcpy(sp->request_sense_ptr, pkt->data, sense_sz); DEBUG5(qla2x00_dump_buffer(sp->request_sense_ptr, sense_sz)); sp->request_sense_ptr += sense_sz; sp->request_sense_length -= sense_sz; /* Place command on done queue. */ if (sp->request_sense_length == 0) { ha->status_srb = NULL; qla2x00_sp_compl(ha, sp); } }}/** * qla2x00_error_entry() - Process an error entry. * @ha: SCSI driver HA context * @pkt: Entry pointer */static voidqla2x00_error_entry(scsi_qla_host_t *ha, sts_entry_t *pkt){ srb_t *sp;#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__); else if (pkt->entry_status & RF_INV_E_COUNT) qla_printk(KERN_ERR, ha, "%s: Invalid Entry Count\n", __func__); else if (pkt->entry_status & RF_INV_E_PARAM) qla_printk(KERN_ERR, ha, "%s: Invalid Entry Parameter\n", __func__); else if (pkt->entry_status & RF_INV_E_TYPE) qla_printk(KERN_ERR, ha, "%s: Invalid Entry Type\n", __func__); else if (pkt->entry_status & RF_BUSY) qla_printk(KERN_ERR, ha, "%s: Busy\n", __func__); else qla_printk(KERN_ERR, ha, "%s: UNKNOWN flag error\n", __func__);#endif /* Validate handle. */ if (pkt->handle < MAX_OUTSTANDING_COMMANDS) sp = ha->outstanding_cmds[pkt->handle]; else sp = NULL; if (sp) { /* Free outstanding command slot. */ ha->outstanding_cmds[pkt->handle] = NULL; /* Bad payload or header */ if (pkt->entry_status & (RF_INV_E_ORDER | RF_INV_E_COUNT | RF_INV_E_PARAM | RF_INV_E_TYPE)) { sp->cmd->result = DID_ERROR << 16; } else if (pkt->entry_status & RF_BUSY) { sp->cmd->result = DID_BUS_BUSY << 16; } else { sp->cmd->result = DID_ERROR << 16; } qla2x00_sp_compl(ha, sp); } else if (pkt->entry_type == COMMAND_A64_TYPE || pkt->entry_type == COMMAND_TYPE || pkt->entry_type == COMMAND_TYPE_7) { DEBUG2(printk("scsi(%ld): Error entry - invalid handle\n", ha->host_no)); qla_printk(KERN_WARNING, ha, "Error entry - invalid handle\n"); set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags); if (ha->dpc_wait && !ha->dpc_active) up(ha->dpc_wait); }}/** * qla2x00_ms_entry() - Process a Management Server entry. * @ha: SCSI driver HA context * @index: Response queue out pointer */static voidqla2x00_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 * @mb0: Mailbox0 register */static voidqla24xx_mbx_completion(scsi_qla_host_t *ha, uint16_t mb0){ uint16_t cnt; uint16_t __iomem *wptr; struct device_reg_24xx __iomem *reg = &ha->iobase->isp24; /* Load return mailbox registers. */ ha->flags.mbox_int = 1; ha->mailbox_out[0] = mb0; wptr = (uint16_t __iomem *)®->mailbox1; for (cnt = 1; cnt < ha->mbx_count; cnt++) { ha->mailbox_out[cnt] = RD_REG_WORD(wptr); wptr++; } if (ha->mcp) { DEBUG3(printk("%s(%ld): Got mailbox completion. cmd=%x.\n", __func__, ha->host_no, ha->mcp->mb[0])); } else { DEBUG2_3(printk("%s(%ld): MBX pointer ERROR!\n", __func__, ha->host_no)); }}/** * qla24xx_process_response_queue() - Process response queue entries. * @ha: SCSI driver HA context */voidqla24xx_process_response_queue(struct scsi_qla_host *ha){ struct device_reg_24xx __iomem *reg = &ha->iobase->isp24; struct sts_entry_24xx *pkt; if (!ha->flags.online) return; while (ha->response_ring_ptr->signature != RESPONSE_PROCESSED) { pkt = (struct sts_entry_24xx *)ha->response_ring_ptr; ha->rsp_ring_index++; if (ha->rsp_ring_index == ha->response_q_length) { ha->rsp_ring_index = 0; ha->response_ring_ptr = ha->response_ring; } else { ha->response_ring_ptr++; } if (pkt->entry_status != 0) { DEBUG3(printk(KERN_INFO "scsi(%ld): Process error entry.\n", ha->host_no)); qla2x00_error_entry(ha, (sts_entry_t *) pkt); ((response_t *)pkt)->signature = RESPONSE_PROCESSED; wmb(); continue; } switch (pkt->entry_type) { case STATUS_TYPE: qla2x00_status_entry(ha, pkt); break; 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; default: /* Type Not Supported. */ DEBUG4(printk(KERN_WARNING "scsi(%ld): Received unknown response pkt type %x " "entry status=%x.\n", ha->host_no, pkt->entry_type, pkt->entry_status)); break; } ((response_t *)pkt)->signature = RESPONSE_PROCESSED; wmb(); } /* Adjust ring index */ WRT_REG_DWORD(®->rsp_q_out, ha->rsp_ring_index);}/** * qla24xx_intr_handler() - Process interrupts for the ISP23xx and ISP63xx. * @irq: * @dev_id: SCSI driver HA context * @regs: * * Called by system whenever the host adapter generates an interrupt. * * Returns handled flag. */irqreturn_tqla24xx_intr_handler(int irq, void *dev_id, struct pt_regs *regs){ 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; uint16_t mb[4]; ha = (scsi_qla_host_t *) dev_id; if (!ha) { printk(KERN_INFO "%s(): NULL host pointer\n", __func__); return IRQ_NONE; } reg = &ha->iobase->isp24; status = 0; spin_lock_irqsave(&ha->hardware_lock, flags); for (iter = 50; iter--; ) { stat = RD_REG_DWORD(®->host_status); if (stat & HSRX_RISC_PAUSED) { hccr = RD_REG_DWORD(®->hccr); qla_printk(KERN_INFO, ha, "RISC paused -- HCCR=%x, " "Dumping firmware!\n", hccr); qla24xx_fw_dump(ha, 1); set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags); break; } else if ((stat & HSRX_RISC_INT) == 0) break; switch (stat & 0xff) { case 0x1: case 0x2: case 0x10: case 0x11: qla24xx_mbx_completion(ha, MSW(stat)); status |= MBX_INTERRUPT; break; case 0x12: mb[0] = MSW(stat); mb[1] = RD_REG_WORD(®->mailbox1); mb[2] = RD_REG_WORD(®->mailbox2); mb[3] = RD_REG_WORD(®->mailbox3); qla2x00_async_event(ha, mb); break; case 0x13: qla24xx_process_response_queue(ha); break; default: DEBUG2(printk("scsi(%ld): Unrecognized interrupt type " "(%d).\n", ha->host_no, stat & 0xff)); break; } WRT_REG_DWORD(®->hccr, HCCRX_CLR_RISC_INT); RD_REG_DWORD_RELAXED(®->hccr); } spin_unlock_irqrestore(&ha->hardware_lock, flags); if (test_bit(MBX_INTR_WAIT, &ha->mbx_cmd_flags) && (status & MBX_INTERRUPT) && ha->flags.mbox_int) { spin_lock_irqsave(&ha->mbx_reg_lock, flags); set_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags); up(&ha->mbx_intr_sem); spin_unlock_irqrestore(&ha->mbx_reg_lock, flags); } return IRQ_HANDLED;}/** * qla24xx_ms_entry() - Process a Management Server entry. * @ha: SCSI driver HA context * @index: Response queue out pointer */static voidqla24xx_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);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -