?? ips.c
字號:
} /* See if the command is on the wait queue */ if (ips_removeq_wait(&ha->scb_waitlist, SC)) { /* command not sent yet */ clear_bit(IPS_IN_ABORT, &ha->flags); return (SUCCESS); } else { /* command must have already been sent */ clear_bit(IPS_IN_ABORT, &ha->flags); return (FAILED); }}/****************************************************************************//* *//* Routine Name: ips_eh_reset *//* *//* Routine Description: *//* *//* Reset the controller (with new eh error code) *//* *//* NOTE: this routine is called under the io_request_lock spinlock *//* *//****************************************************************************/intips_eh_reset(Scsi_Cmnd *SC) { int ret; int i; ips_ha_t *ha; ips_scb_t *scb; ips_copp_wait_item_t *item; unsigned long cpu_flags; METHOD_TRACE("ips_eh_reset", 1);#ifdef NO_IPS_RESET return (FAILED);#else if (!SC) { DEBUG(1, "Reset called with NULL scsi command"); return (FAILED); } ha = (ips_ha_t *) SC->host->hostdata; if (!ha) { DEBUG(1, "Reset called with NULL ha struct"); return (FAILED); } if (!ha->active) return (FAILED); if (test_and_set_bit(IPS_IN_RESET, &ha->flags)) return (FAILED); /* See if the command is on the copp queue */ IPS_QUEUE_LOCK(&ha->copp_waitlist); item = ha->copp_waitlist.head; while ((item) && (item->scsi_cmd != SC)) item = item->next; IPS_QUEUE_UNLOCK(&ha->copp_waitlist); if (item) { /* Found it */ ips_removeq_copp(&ha->copp_waitlist, item); clear_bit(IPS_IN_RESET, &ha->flags); return (SUCCESS); } /* See if the command is on the wait queue */ if (ips_removeq_wait(&ha->scb_waitlist, SC)) { /* command not sent yet */ clear_bit(IPS_IN_RESET, &ha->flags); return (SUCCESS); } /* * command must have already been sent * reset the controller */ printk(KERN_NOTICE "(%s%d) Resetting controller.\n", ips_name, ha->host_num); ret = (*ha->func.reset)(ha); if (!ret) { Scsi_Cmnd *scsi_cmd; printk(KERN_NOTICE "(%s%d) Controller reset failed - controller now offline.\n", ips_name, ha->host_num); /* Now fail all of the active commands */ DEBUG_VAR(1, "(%s%d) Failing active commands", ips_name, ha->host_num); while ((scb = ips_removeq_scb_head(&ha->scb_activelist))) { scb->scsi_cmd->result = DID_ERROR << 16; scb->scsi_cmd->scsi_done(scb->scsi_cmd); ips_freescb(ha, scb); } /* Now fail all of the pending commands */ DEBUG_VAR(1, "(%s%d) Failing pending commands", ips_name, ha->host_num); while ((scsi_cmd = ips_removeq_wait_head(&ha->scb_waitlist))) { scsi_cmd->result = DID_ERROR; scsi_cmd->scsi_done(scsi_cmd); } ha->active = FALSE; clear_bit(IPS_IN_RESET, &ha->flags); return (FAILED); } if (!ips_clear_adapter(ha, IPS_INTR_IORL)) { Scsi_Cmnd *scsi_cmd; printk(KERN_NOTICE "(%s%d) Controller reset failed - controller now offline.\n", ips_name, ha->host_num); /* Now fail all of the active commands */ DEBUG_VAR(1, "(%s%d) Failing active commands", ips_name, ha->host_num); while ((scb = ips_removeq_scb_head(&ha->scb_activelist))) { scb->scsi_cmd->result = DID_ERROR << 16; scb->scsi_cmd->scsi_done(scb->scsi_cmd); ips_freescb(ha, scb); } /* Now fail all of the pending commands */ DEBUG_VAR(1, "(%s%d) Failing pending commands", ips_name, ha->host_num); while ((scsi_cmd = ips_removeq_wait_head(&ha->scb_waitlist))) { scsi_cmd->result = DID_ERROR << 16; scsi_cmd->scsi_done(scsi_cmd); } ha->active = FALSE; clear_bit(IPS_IN_RESET, &ha->flags); return (FAILED); } /* FFDC */ if (le32_to_cpu(ha->subsys->param[3]) & 0x300000) { struct timeval tv; do_gettimeofday(&tv); IPS_HA_LOCK(cpu_flags); ha->last_ffdc = tv.tv_sec; ha->reset_count++; IPS_HA_UNLOCK(cpu_flags); ips_ffdc_reset(ha, IPS_INTR_IORL); } /* Now fail all of the active commands */ DEBUG_VAR(1, "(%s%d) Failing active commands", ips_name, ha->host_num); while ((scb = ips_removeq_scb_head(&ha->scb_activelist))) { scb->scsi_cmd->result = (DID_RESET << 16) | (SUGGEST_RETRY << 24); scb->scsi_cmd->scsi_done(scb->scsi_cmd); ips_freescb(ha, scb); } /* Reset DCDB active command bits */ for (i = 1; i < ha->nbus; i++) ha->dcdb_active[i-1] = 0; /* Reset the number of active IOCTLs */ IPS_HA_LOCK(cpu_flags); ha->num_ioctl = 0; IPS_HA_UNLOCK(cpu_flags); clear_bit(IPS_IN_RESET, &ha->flags); if (!test_bit(IPS_IN_INTR, &ha->flags)) { /* * Only execute the next command when * we are not being called from the * interrupt handler. The interrupt * handler wants to do this and since * interrupts are turned off here.... */ ips_next(ha, IPS_INTR_IORL); } return (SUCCESS);#endif /* NO_IPS_RESET */}/****************************************************************************//* *//* Routine Name: ips_queue *//* *//* Routine Description: *//* *//* Send a command to the controller *//* *//* NOTE: *//* Linux obtains io_request_lock before calling this function *//* *//****************************************************************************/intips_queue(Scsi_Cmnd *SC, void (*done) (Scsi_Cmnd *)) { ips_ha_t *ha; unsigned long cpu_flags; METHOD_TRACE("ips_queue", 1); ha = (ips_ha_t *) SC->host->hostdata; if (!ha) return (1); if (!ha->active) return (DID_ERROR);#ifndef NO_IPS_CMDLINE if (ips_is_passthru(SC)) { IPS_QUEUE_LOCK(&ha->copp_waitlist); if (ha->copp_waitlist.count == IPS_MAX_IOCTL_QUEUE) { IPS_QUEUE_UNLOCK(&ha->copp_waitlist); SC->result = DID_BUS_BUSY << 16; done(SC); return (0); } else { IPS_QUEUE_UNLOCK(&ha->copp_waitlist); } } else {#endif IPS_QUEUE_LOCK(&ha->scb_waitlist); if (ha->scb_waitlist.count == IPS_MAX_QUEUE) { IPS_QUEUE_UNLOCK(&ha->scb_waitlist); SC->result = DID_BUS_BUSY << 16; done(SC); return (0); } else { IPS_QUEUE_UNLOCK(&ha->scb_waitlist); }#ifndef NO_IPS_CMDLINE }#endif SC->scsi_done = done; DEBUG_VAR(2, "(%s%d): ips_queue: cmd 0x%X (%d %d %d)", ips_name, ha->host_num, SC->cmnd[0], SC->channel, SC->target, SC->lun); /* Check for command to initiator IDs */ if ((SC->channel > 0) && (SC->target == ha->ha_id[SC->channel])) { SC->result = DID_NO_CONNECT << 16; done(SC); return (0); }#ifndef NO_IPS_CMDLINE if (ips_is_passthru(SC)) { ips_copp_wait_item_t *scratch; /* The IPS_IOCTL_NEW_COMMAND is only used to flash an adapter. This should */ /* never happen when the adapter is active. Just in case, check here, and */ /* reject the command if anything else is going on. */ if (SC->cmnd[0] == IPS_IOCTL_NEW_COMMAND) { if (ha->scb_activelist.count != 0) { /* printk( KERN_WARNING "New IOCTL Cmd Return BUSY: %d Cmds Active\n", */ /* ha->scb_activelist.count ); */ SC->result = DID_BUS_BUSY << 16; done(SC); return (0); } } /* allocate space for the scribble */ scratch = kmalloc(sizeof(ips_copp_wait_item_t), GFP_ATOMIC); if (!scratch) { SC->result = DID_ERROR << 16; done(SC); return (0); } scratch->scsi_cmd = SC; sema_init(&ha->ioctl_sem, 0); scratch->sem = &ha->ioctl_sem; scratch->next = NULL; ips_putq_copp_tail(&ha->copp_waitlist, scratch); } else#endif ips_putq_wait_tail(&ha->scb_waitlist, SC); IPS_HA_LOCK(cpu_flags); if ((!test_bit(IPS_IN_INTR, &ha->flags)) && (!test_bit(IPS_IN_ABORT, &ha->flags)) && (!test_bit(IPS_IN_RESET, &ha->flags))) { IPS_HA_UNLOCK(cpu_flags); ips_next(ha, IPS_INTR_IORL); } else { IPS_HA_UNLOCK(cpu_flags); } /* * If this request was a new style IOCTL wait * for it to finish. * * NOTE: we relinquished the lock above so this should * not cause contention problems */ if (ips_is_passthru(SC) && SC->cmnd[0] == IPS_IOCTL_NEW_COMMAND) { char *user_area; char *kern_area; u_int32_t datasize; /* free io_request_lock */ spin_unlock_irq(&io_request_lock); /* wait for the command to finish */ down(&ha->ioctl_sem); /* reobtain the lock */ spin_lock_irq(&io_request_lock); /* command finished -- copy back */ user_area = *((char **) &SC->cmnd[4]);
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -