📄 qla1280.c
字号:
/* Bookkeeping information */ sp->r_start = jiffies; /* time the request was received */ sp->u_start = 0; /* add the command to our queue */ ha->qthreads++; qla1280_putq_t(q,sp); DEBUG(sprintf(debug_buff,"qla1280_queuecmd: queue pid=%d, hndl=0x%x\n\r",cmd->pid,handle)); DEBUG(qla1280_print(debug_buff)); /* send command to adapter */ DRIVER_LOCK if (q->q_outcnt == 0) qla1280_restart_queues(ha); DRIVER_UNLOCK LEAVE("qla1280_queuecommand"); return (0);}/************************************************************************** * qla1200_abort * Abort the speciifed SCSI command(s). **************************************************************************/intqla1280_abort(Scsi_Cmnd *cmd){ scsi_qla_host_t *ha; srb_t *sp;#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,95) unsigned long cpu_flags = 0;#endif struct Scsi_Host *host; uint32_t b, t, l; scsi_lu_t *q; int return_status = SCSI_ABORT_SUCCESS; int found = 0; int i; u_long handle; u_short data; ENTER("qla1280_abort"); COMTRACE('A') ha = (scsi_qla_host_t *) cmd->host->hostdata; host = cmd->host; DRIVER_LOCK /* Get the SCSI request ptr */ sp = (srb_t *) CMD_SP(cmd); handle = (u_long) CMD_HANDLE(cmd); if (qla1280_verbose) printk("scsi(%d): ABORT Command=0x%lx, handle=0x%lx\n",(int)ha->host_no,(long)cmd,handle); /* Check for pending interrupts. */ if( handle == 0L ) { COMTRACE('a') /* we never got this command */ printk(KERN_INFO "qla1280: Aborting a NULL handle\n"); DRIVER_UNLOCK return(SCSI_ABORT_NOT_RUNNING); /* no action - we don't have command */ } data = qla1280_debounce_register(&ha->iobase->istatus); if( !(ha->flags.in_isr) && (data & RISC_INT) ) { /* put any pending command in done queue */ qla1280_isr(ha, (srb_t **)&ha->done_q_first, (srb_t **)&ha->done_q_last); } handle = (u_long) CMD_HANDLE(cmd); /* Generate LU queue on bus, target, LUN */ b = SCSI_BUS_32(cmd); t = SCSI_TCN_32(cmd); l = SCSI_LUN_32(cmd); if((q = LU_Q(ha, b, t, l)) == NULL ) { COMTRACE('a') /* No lun queue -- command must not be active */ DRIVER_UNLOCK printk(KERN_WARNING "qla1280 (%d:%d:%d): No LUN queue for the specified device\n",(int)b,(int)t,(int)l); return(SCSI_ABORT_NOT_RUNNING); /* no action - we don't have command */ }#if AUTO_ESCALATE_ABORT if ( (sp->flags & SRB_ABORTED) ) { DRIVER_UNLOCK DEBUG(qla1280_print("qla1280_abort: Abort escalayted - returning SCSI_ABORT_SNOOZE.\n\r")); return(SCSI_ABORT_SNOOZE); }#endif if ( (sp->flags & SRB_ABORT_PENDING) ) { COMTRACE('a') DRIVER_UNLOCK if( qla1280_verbose ) printk("scsi(): Command has a pending abort message - ABORT_PENDING.\n"); DEBUG(qla1280_print("qla1280: Command has a pending abort message - ABORT_PENDING.\n\r")); return(SCSI_ABORT_PENDING); }#if STOP_ON_ABORT printk("Scsi layer issued a ABORT command= 0x%x\n",(int)cmd); DEBUG2(qla1280_print_scsi_cmd(cmd));#endif ha->flags.in_abort = TRUE; /* * Normally, would would need to search our queue for the specified command * but; since our sp contains the cmd ptr, we can just remove it from our * LUN queue. */ if( !(sp->flags&SRB_SENT) ) { found++; if( qla1280_verbose ) printk("scsi(): Command returned from queue aborted.\n"); DEBUG(qla1280_print("qla1280: Command returned from queue aborted.\n\r")); /* Remove srb from SCSI LU queue. */ qla1280_removeq(q, sp); sp->flags |= SRB_ABORTED; CMD_RESULT(cmd) = DID_ABORT << 16; qla1280_done_q_put(sp, &ha->done_q_first, &ha->done_q_last); return_status = SCSI_ABORT_SUCCESS; } else { /* find the command in our active list */ for (i = 1; i < MAX_OUTSTANDING_COMMANDS; i++) { if( sp == ha->outstanding_cmds[i] ) { found++; DEBUG(qla1280_print("qla1280: RISC aborting command.\n\r")); qla1280_abort_command(ha,sp); return_status = SCSI_ABORT_PENDING; break; } } }#if STOP_ON_ABORT qla1280_panic("qla1280_abort",ha->host);#endif if ( found == 0 ) return_status = SCSI_ABORT_NOT_RUNNING; /* no action - we don't have command */ DEBUG(sprintf(debug_buff, "qla1280_abort: Aborted status returned = 0x%x.\n\r",return_status)); DEBUG(qla1280_print(debug_buff)); if( ha->done_q_first ) qla1280_done(ha, (srb_t **)&ha->done_q_first, (srb_t **)&ha->done_q_last); if ( found ) { qla1280_restart_queues(ha); } ha->flags.in_abort = FALSE; DRIVER_UNLOCK LEAVE("qla1280_abort"); COMTRACE('a') return(return_status);}/************************************************************************** * qla1200_reset * The reset function will reset the SCSI bus and abort any executing * commands. * * Input: * cmd = Linux SCSI command packet of the command that cause the * bus reset. * flags = SCSI bus reset option flags (see scsi.h) * * Returns: * DID_RESET in cmd.host_byte of aborted command(s) * * Note: * Resetting the bus always succeeds - is has to, otherwise the * kernel will panic! Try a surgical technique - sending a BUS * DEVICE RESET message - on the offending target before pulling * the SCSI bus reset line. **************************************************************************/intqla1280_reset(Scsi_Cmnd *cmd, unsigned int flags){ scsi_qla_host_t *ha;#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,95) unsigned long cpu_flags = 0;#endif uint32_t b, t, l; srb_t *sp; typedef enum { ABORT_DEVICE = 1, DEVICE_RESET = 2, BUS_RESET = 3, ADAPTER_RESET= 4, RESET_DELAYED= 5, FAIL = 6 } action_t; action_t action = ADAPTER_RESET; u_short data; scsi_lu_t *q; int result; ENTER("qla1280_reset"); COMTRACE('R') if (qla1280_verbose) printk("scsi(): Resetting Cmnd=0x%lx, Handle=0x%lx, flags=0x%x\n",(long)cmd,(long)CMD_HANDLE(cmd),flags); if ( cmd == NULL ) { printk(KERN_WARNING "(scsi?:?:?:?) Reset called with NULL Scsi_Cmnd " "pointer, failing.\n"); return(SCSI_RESET_SNOOZE); } ha = (scsi_qla_host_t *) cmd->host->hostdata; sp = (srb_t *) CMD_SP(cmd);#if STOP_ON_RESET qla1280_panic("qla1280_reset",ha->host);#endif DRIVER_LOCK /* Check for pending interrupts. */ data = qla1280_debounce_register(&ha->iobase->istatus); if( !(ha->flags.in_isr) && (data & RISC_INT) ) { qla1280_isr(ha, (srb_t **)&ha->done_q_first, (srb_t **)&ha->done_q_last); } DRIVER_UNLOCK /* * Determine the suggested action that the mid-level driver wants * us to perform. */ if( CMD_HANDLE(cmd) == (unsigned char *) 0 ) { /* * if mid-level driver called reset with a orphan SCSI_Cmnd * (i.e. a command that's not pending ), so perform the * function specified. */ if( (flags & SCSI_RESET_SUGGEST_HOST_RESET) ) action = ADAPTER_RESET; else action = BUS_RESET; } else { /* * Mid-level driver has called reset with this SCSI_Cmnd and * its pending. */ if( flags & SCSI_RESET_SUGGEST_HOST_RESET ) action = ADAPTER_RESET; else if( flags & SCSI_RESET_SUGGEST_BUS_RESET ) action = BUS_RESET; else action = DEVICE_RESET; } b = SCSI_BUS_32(cmd); t = SCSI_TCN_32(cmd); l = SCSI_LUN_32(cmd); q = LU_Q(ha, b, t, l);#if AUTO_ESCALATE_RESET if ( (action & DEVICE_RESET) && (q->q_flag & QLA1280_QRESET) ) { printk(KERN_INFO "qla1280(%d): Bus device reset already sent to " "device, escalating.\n", (int)ha->host_no); action = BUS_RESET; } if ( (action & DEVICE_RESET) && (sp->flags & SRB_ABORT_PENDING) ) { printk(KERN_INFO "qla1280(%d):Have already attempted to reach " "device with abort device\n", (int)ha->host_no); printk(KERN_INFO "qla1280(%d):message, will escalate to BUS " "RESET.\n",(int) ha->host_no); action = BUS_RESET; }#endif /* * By this point, we want to already know what we are going to do, * so we only need to perform the course of action. */ DRIVER_LOCK result = SCSI_RESET_ERROR; switch (action) { case FAIL: break; case RESET_DELAYED: result = SCSI_RESET_PENDING; break; case ABORT_DEVICE: ha->flags.in_reset = TRUE; if (qla1280_verbose) printk(KERN_INFO "scsi(%d:%d:%d:%d): Queueing abort device command.\n", (int)ha->host_no,(int)b,(int)t,(int)l); qla1280_abort_queue_single(ha,b,t,l,DID_ABORT); if( qla1280_abort_device(ha, b, t, l) == 0) result = SCSI_RESET_PENDING; break; case DEVICE_RESET: if (qla1280_verbose) printk(KERN_INFO "scsi(%d:%d:%d:%d): Queueing device reset command.\n",(int) ha->host_no,(int)b,(int)t,(int)l); ha->flags.in_reset = TRUE; for (l = 0; l < MAX_LUNS; l++) qla1280_abort_queue_single(ha,b,t,l,DID_ABORT); if( qla1280_device_reset(ha, b, t) == 0 ) result = SCSI_RESET_PENDING; q->q_flag |= QLA1280_QRESET; break; case BUS_RESET: if (qla1280_verbose) printk(KERN_INFO "qla1280(%d:%d:%d:%d): Issuing BUS DEVICE RESET.\n",(int) ha->host_no,(int)b,(int)t,(int)l); ha->flags.in_reset = TRUE; for (t = 0; t < MAX_TARGETS; t++) for (l = 0; l < MAX_LUNS; l++) qla1280_abort_queue_single(ha,b,t,l,DID_RESET); qla1280_bus_reset(ha, b); /* * The bus reset routine returns all the outstanding commands back * with "DID_RESET" in the status field after a short delay * by the firmware. If the mid-level time out the SCSI reset before * our delay we may need to ignore it. */ /* result = SCSI_RESET_PENDING | SCSI_RESET_BUS_RESET; */ result = SCSI_RESET_SUCCESS | SCSI_RESET_BUS_RESET; mdelay(4 * 1000); barrier(); if( flags & SCSI_RESET_SYNCHRONOUS ) { CMD_RESULT(cmd) = (int) (DID_BUS_BUSY << 16); (*(cmd)->scsi_done)(cmd); } /* ha->reset_start = jiffies; */ break; case ADAPTER_RESET: default: if (qla1280_verbose) { printk(KERN_INFO "scsi(%d:%d:%d:%d): Issued an ADAPTER RESET.\n",(int) ha->host_no,(int)b,(int)t,(int)l); printk(KERN_INFO "scsi(%d:%d:%d:%d): I/O processing will continue automatically.\n",(int) ha->host_no,(int)b,(int)t,(int)l); } ha->flags.reset_active = TRUE; /* * We restarted all of the commands automatically, so the mid-level code can expect * completions momentitarily. */ if( qla1280_abort_isp(ha) == 0 ) result = SCSI_RESET_SUCCESS | SCSI_RESET_HOST_RESET; ha->flags.reset_active = FALSE; } if( ha->done_q_first ) qla1280_done(ha, (srb_t **)&ha->done_q_first, (srb_t **)&ha->done_q_last); qla1280_restart_queues(ha); ha->flags.in_reset = FALSE;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -