📄 qla_isr.c
字号:
*/ memset(cp->sense_buffer, 0, sizeof(cp->sense_buffer)); if (!(scsi_status & SS_SENSE_LEN_VALID)) break; if (le16_to_cpu(pkt->req_sense_length) < sizeof(cp->sense_buffer)) sense_sz = le16_to_cpu(pkt->req_sense_length); else sense_sz = sizeof(cp->sense_buffer); CMD_ACTUAL_SNSLEN(cp) = sense_sz; sp->request_sense_length = sense_sz; sp->request_sense_ptr = cp->sense_buffer; if (sp->request_sense_length > 32) sense_sz = 32; memcpy(cp->sense_buffer, pkt->req_sense_data, sense_sz); sp->request_sense_ptr += sense_sz; sp->request_sense_length -= sense_sz; if (sp->request_sense_length != 0) ha->status_srb = sp; if (!(sp->flags & (SRB_IOCTL | SRB_TAPE)) && qla2x00_check_sense(cp, lq) == QLA_SUCCESS) { /* Throw away status_cont if any */ ha->status_srb = NULL; add_to_scsi_retry_queue(ha, sp); return; } DEBUG5(printk("%s(): Check condition Sense data, " "scsi(%ld:%d:%d:%d) cmd=%p pid=%ld\n", __func__, ha->host_no, b, t, l, cp, cp->serial_number)); if (sense_sz) DEBUG5(qla2x00_dump_buffer(cp->sense_buffer, CMD_ACTUAL_SNSLEN(cp))); break; case CS_DATA_UNDERRUN: DEBUG2(printk(KERN_INFO "scsi(%ld:%d:%d) UNDERRUN status detected 0x%x-0x%x.\n", ha->host_no, t, l, comp_status, scsi_status)); resid = le32_to_cpu(pkt->residual_length); if (scsi_status & SS_RESIDUAL_UNDER) { cp->resid = resid; CMD_RESID_LEN(cp) = resid; } /* * Check to see if SCSI Status is non zero. If so report SCSI * Status. */ if (lscsi_status != 0) { if (lscsi_status == SS_BUSY_CONDITION) { cp->result = DID_BUS_BUSY << 16 | lscsi_status; break; } cp->result = DID_OK << 16 | lscsi_status; if (lscsi_status != SS_CHECK_CONDITION) break; /* Copy Sense Data into sense buffer */ memset(cp->sense_buffer, 0, sizeof(cp->sense_buffer)); if (!(scsi_status & SS_SENSE_LEN_VALID)) break; if (le16_to_cpu(pkt->req_sense_length) < sizeof(cp->sense_buffer)) sense_sz = le16_to_cpu(pkt->req_sense_length); else sense_sz = sizeof(cp->sense_buffer); CMD_ACTUAL_SNSLEN(cp) = sense_sz; sp->request_sense_length = sense_sz; sp->request_sense_ptr = cp->sense_buffer; if (sp->request_sense_length > 32) sense_sz = 32; memcpy(cp->sense_buffer, pkt->req_sense_data, sense_sz); sp->request_sense_ptr += sense_sz; sp->request_sense_length -= sense_sz; if (sp->request_sense_length != 0) ha->status_srb = sp; if (!(sp->flags & (SRB_IOCTL | SRB_TAPE)) && (qla2x00_check_sense(cp, lq) == QLA_SUCCESS)) { ha->status_srb = NULL; add_to_scsi_retry_queue(ha, sp); return; } DEBUG5(printk("%s(): Check condition Sense data, " "scsi(%ld:%d:%d:%d) cmd=%p pid=%ld\n", __func__, ha->host_no, b, t, l, cp, cp->serial_number)); if (sense_sz) DEBUG5(qla2x00_dump_buffer(cp->sense_buffer, CMD_ACTUAL_SNSLEN(cp))); } else { /* * If RISC reports underrun and target does not report * it then we must have a lost frame, so tell upper * layer to retry it by reporting a bus busy. */ if (!(scsi_status & SS_RESIDUAL_UNDER)) { DEBUG2(printk("scsi(%ld:%d:%d:%d) Dropped " "frame(s) detected (%x of %x bytes)..." "retrying command.\n", ha->host_no, b, t, l, resid, cp->request_bufflen)); cp->result = DID_BUS_BUSY << 16; ha->dropped_frame_error_cnt++; 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, b, t, l, 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, t, l, 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, le32_to_cpu(pkt->residual_length))); 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. */ fcport = sp->fclun->fcport; DEBUG2(printk("scsi(%ld:%d:%d): status_entry: Port Down " "pid=%ld, compl status=0x%x, port state=0x%x\n", ha->host_no, t, l, cp->serial_number, comp_status, atomic_read(&fcport->state))); if ((sp->flags & (SRB_IOCTL | SRB_TAPE)) || atomic_read(&fcport->state) == FCS_DEVICE_DEAD) { cp->result = DID_NO_CONNECT << 16; if (atomic_read(&ha->loop_state) == LOOP_DOWN) sp->err_id = SRB_ERR_LOOP; else sp->err_id = SRB_ERR_PORT; add_to_done_queue(ha, sp); } else { qla2x00_extend_timeout(cp, EXTEND_CMD_TIMEOUT); add_to_retry_queue(ha, sp); } if (atomic_read(&fcport->state) == FCS_ONLINE) { qla2x00_mark_device_lost(ha, fcport, 1); } return; 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)); if (sp->flags & (SRB_IOCTL | SRB_TAPE)) { cp->result = DID_RESET << 16; } else { qla2x00_extend_timeout(cp, EXTEND_CMD_TIMEOUT); add_to_retry_queue(ha, sp); return; } 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: DEBUG2(printk(KERN_INFO "scsi(%ld:%d:%d:%d): TIMEOUT status detected 0x%x-0x%x " "sflags=%x.\n", ha->host_no, b, t, l, comp_status, scsi_status, le16_to_cpu(pkt->status_flags))); cp->result = DID_BUS_BUSY << 16; fcport = lq->fclun->fcport; /* Check to see if logout occurred */ if ((le16_to_cpu(pkt->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; /* TODO: ??? */ /* Adjust queue depth */ ret = scsi_track_queue_full(cp->device, sp->lun_queue->out_cnt - 1); if (ret) { qla_printk(KERN_INFO, ha, "scsi(%ld:%d:%d:%d): Queue depth adjusted to %d.\n", ha->host_no, cp->device->channel, cp->device->id, cp->device->lun, ret); } 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) add_to_done_queue(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. */ 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) { add_to_done_queue(ha, sp); ha->status_srb = NULL; } }}/** * 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; if (ha->actthreads) ha->actthreads--; sp->lun_queue->out_cnt--; /* 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; } /* Place command on done queue. */ add_to_done_queue(ha, sp); } else if (pkt->entry_type == COMMAND_A64_TYPE || pkt->entry_type == COMMAND_TYPE) { 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; add_to_done_queue(ha, sp);}/** * qla2x00_check_sense() - Perform any sense data interrogation. * @cp: SCSI Command * @lq: Lun queue * * Returns QLA_SUCCESS if the lun queue is suspended, else * QLA_FUNCTION_FAILED (lun queue not suspended). */static int qla2x00_check_sense(struct scsi_cmnd *cp, os_lun_t *lq){ scsi_qla_host_t *ha; srb_t *sp; fc_port_t *fcport; ha = (scsi_qla_host_t *) cp->device->host->hostdata; if ((cp->sense_buffer[0] & 0x70) != 0x70) { return (QLA_FUNCTION_FAILED); } sp = (srb_t * )CMD_SP(cp); sp->flags |= SRB_GOT_SENSE; switch (cp->sense_buffer[2] & 0xf) { case RECOVERED_ERROR: cp->result = DID_OK << 16; cp->sense_buffer[0] = 0; break; case NOT_READY: fcport = lq->fclun->fcport; /* * Suspend the lun only for hard disk device type. */ if ((fcport->flags & FCF_TAPE_PRESENT) == 0 && lq->q_state != LUN_STATE_TIMEOUT) { /* * If target is in process of being ready then suspend * lun for 6 secs and retry all the commands. */ if (cp->sense_buffer[12] == 0x4 && cp->sense_buffer[13] == 0x1) { /* Suspend the lun for 6 secs */ qla2x00_suspend_lun(ha, lq, 6, ql2xsuspendcount); return (QLA_SUCCESS); } } break; } return (QLA_FUNCTION_FAILED);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -