📄 scsi.c
字号:
scsi_bh_queue_head = NULL; if( SCpnt == NULL ) { spin_unlock_irqrestore(&io_request_lock, flags); return; } SCnext = SCpnt->bh_next; for(; SCpnt; SCpnt = SCnext) { SCnext = SCpnt->bh_next; switch( scsi_decide_disposition(SCpnt) ) { case SUCCESS: /* * Add to BH queue. */ SCSI_LOG_MLCOMPLETE(3,printk("Command finished %d %d 0x%x\n", SCpnt->host->host_busy, SCpnt->host->host_failed, SCpnt->result)); scsi_finish_command(SCpnt); break; case NEEDS_RETRY: /* * We only come in here if we want to retry a command. The * test to see whether the command should be retried should be * keeping track of the number of tries, so we don't end up looping, * of course. */ SCSI_LOG_MLCOMPLETE(3,printk("Command needs retry %d %d 0x%x\n", SCpnt->host->host_busy, SCpnt->host->host_failed, SCpnt->result)); scsi_retry_command(SCpnt); break; case ADD_TO_MLQUEUE: /* * This typically happens for a QUEUE_FULL message - * typically only when the queue depth is only * approximate for a given device. Adding a command * to the queue for the device will prevent further commands * from being sent to the device, so we shouldn't end up * with tons of things being sent down that shouldn't be. */ scsi_mlqueue_insert(SCpnt, SCSI_MLQUEUE_DEVICE_BUSY); break; default: /* * Here we have a fatal error of some sort. Turn it over to * the error handler. */ SCSI_LOG_MLCOMPLETE(3,printk("Command failed %p %x active=%d busy=%d failed=%d\n", SCpnt, SCpnt->result, atomic_read(&SCpnt->host->host_active), SCpnt->host->host_busy, SCpnt->host->host_failed)); /* * Dump the sense information too. */ if ((status_byte (SCpnt->result) & CHECK_CONDITION) != 0) { SCSI_LOG_MLCOMPLETE(3,print_sense("bh",SCpnt)); } if( SCpnt->host->eh_wait != NULL ) { SCpnt->host->host_failed++; SCpnt->owner = SCSI_OWNER_ERROR_HANDLER; SCpnt->state = SCSI_STATE_FAILED; SCpnt->host->in_recovery = 1; /* * If the host is having troubles, then look to see if this was the last * command that might have failed. If so, wake up the error handler. */ if( SCpnt->host->host_busy == SCpnt->host->host_failed ) { SCSI_LOG_ERROR_RECOVERY(5, printk("Waking error handler thread (%d)\n", atomic_read(&SCpnt->host->eh_wait->count))); up(SCpnt->host->eh_wait); } } else { /* * We only get here if the error recovery thread has died. */ scsi_finish_command(SCpnt); } } } /* for(; SCpnt...) */ } /* while(1==1) */ spin_unlock_irqrestore(&io_request_lock, flags);}/* * Function: scsi_retry_command * * Purpose: Send a command back to the low level to be retried. * * Notes: This command is always executed in the context of the * bottom half handler, or the error handler thread. Low * level drivers should not become re-entrant as a result of * this. */intscsi_retry_command(Scsi_Cmnd * SCpnt){ memcpy ((void *) SCpnt->cmnd, (void*) SCpnt->data_cmnd, sizeof(SCpnt->data_cmnd)); SCpnt->request_buffer = SCpnt->buffer; SCpnt->request_bufflen = SCpnt->bufflen; SCpnt->use_sg = SCpnt->old_use_sg; SCpnt->cmd_len = SCpnt->old_cmd_len; SCpnt->result = 0; memset ((void *) SCpnt->sense_buffer, 0, sizeof SCpnt->sense_buffer); return internal_cmnd (SCpnt);}/* * Function: scsi_finish_command * * Purpose: Pass command off to upper layer for finishing of I/O * request, waking processes that are waiting on results, * etc. */voidscsi_finish_command(Scsi_Cmnd * SCpnt){ struct Scsi_Host * host; Scsi_Device * device; host = SCpnt->host; device = SCpnt->device; host->host_busy--; /* Indicate that we are free */ device->device_busy--; /* Decrement device usage counter. */ if (host->block && host->host_busy == 0) { host_active = NULL; /* For block devices "wake_up" is done in end_scsi_request */ if (!SCSI_BLK_MAJOR(MAJOR(SCpnt->request.rq_dev))) { struct Scsi_Host * next; for (next = host->block; next != host; next = next->block) wake_up(&next->host_wait); } } /* * Now try and drain the mid-level queue if any commands have been * inserted. Check to see whether the queue even has anything in * it first, as otherwise this is useless overhead. */ if( SCpnt->host->pending_commands != NULL ) { scsi_mlqueue_finish(SCpnt->host, SCpnt->device); } wake_up(&host->host_wait); /* * If we have valid sense information, then some kind of recovery * must have taken place. Make a note of this. */ if( scsi_sense_valid(SCpnt) ) { SCpnt->result |= (DRIVER_SENSE << 24); } SCSI_LOG_MLCOMPLETE(3,printk("Notifying upper driver of completion for device %d %x\n", SCpnt->device->id, SCpnt->result)); SCpnt->owner = SCSI_OWNER_HIGHLEVEL; SCpnt->state = SCSI_STATE_FINISHED; /* We can get here with use_sg=0, causing a panic in the upper level (DB) */ SCpnt->use_sg = SCpnt->old_use_sg; SCpnt->done (SCpnt);}#ifdef CONFIG_MODULESstatic int scsi_register_host(Scsi_Host_Template *);static void scsi_unregister_host(Scsi_Host_Template *);#endifvoid *scsi_malloc(unsigned int len){ unsigned int nbits, mask; int i, j; if(len % SECTOR_SIZE != 0 || len > PAGE_SIZE) return NULL; nbits = len >> 9; mask = (1 << nbits) - 1; for(i=0;i < dma_sectors / SECTORS_PER_PAGE; i++) for(j=0; j<=SECTORS_PER_PAGE - nbits; j++){ if ((dma_malloc_freelist[i] & (mask << j)) == 0){ dma_malloc_freelist[i] |= (mask << j); scsi_dma_free_sectors -= nbits;#ifdef DEBUG SCSI_LOG_MLQUEUE(3,printk("SMalloc: %d %p [From:%p]\n",len, dma_malloc_pages[i] + (j << 9))); printk("SMalloc: %d %p [From:%p]\n",len, dma_malloc_pages[i] + (j << 9));#endif return (void *) ((unsigned long) dma_malloc_pages[i] + (j << 9)); } } return NULL; /* Nope. No more */}int scsi_free(void *obj, unsigned int len){ unsigned int page, sector, nbits, mask;#ifdef DEBUG unsigned long ret = 0;#ifdef __mips__ __asm__ __volatile__ ("move\t%0,$31":"=r"(ret));#else ret = __builtin_return_address(0);#endif printk("scsi_free %p %d\n",obj, len); SCSI_LOG_MLQUEUE(3,printk("SFree: %p %d\n",obj, len));#endif for (page = 0; page < dma_sectors / SECTORS_PER_PAGE; page++) { unsigned long page_addr = (unsigned long) dma_malloc_pages[page]; if ((unsigned long) obj >= page_addr && (unsigned long) obj < page_addr + PAGE_SIZE) { sector = (((unsigned long) obj) - page_addr) >> 9; nbits = len >> 9; mask = (1 << nbits) - 1; if ((mask << sector) >= (1 << SECTORS_PER_PAGE)) panic ("scsi_free:Bad memory alignment"); if((dma_malloc_freelist[page] & (mask << sector)) != (mask<<sector)){#ifdef DEBUG printk("scsi_free(obj=%p, len=%d) called from %08lx\n", obj, len, ret);#endif panic("scsi_free:Trying to free unused memory"); } scsi_dma_free_sectors += nbits; dma_malloc_freelist[page] &= ~(mask << sector); return 0; } } panic("scsi_free:Bad offset");}int scsi_loadable_module_flag; /* Set after we scan builtin drivers */void * scsi_init_malloc(unsigned int size, int gfp_mask){ void * retval; /* * For buffers used by the DMA pool, we assume page aligned * structures. */ if ((size % PAGE_SIZE) == 0) { int order, a_size; for (order = 0, a_size = PAGE_SIZE; a_size < size; order++, a_size <<= 1) ; retval = (void *) __get_free_pages(gfp_mask | GFP_DMA, order); } else retval = kmalloc(size, gfp_mask); if (retval) memset(retval, 0, size); return retval;}void scsi_init_free(char * ptr, unsigned int size){ /* * We need this special code here because the DMA pool assumes * page aligned data. Besides, it is wasteful to allocate * page sized chunks with kmalloc. */ if ((size % PAGE_SIZE) == 0) { int order, a_size; for (order = 0, a_size = PAGE_SIZE; a_size < size; order++, a_size <<= 1) ; free_pages((unsigned long)ptr, order); } else kfree(ptr);}void scsi_build_commandblocks(Scsi_Device * SDpnt){ struct Scsi_Host *host = SDpnt->host; int j; Scsi_Cmnd * SCpnt; if (SDpnt->queue_depth == 0) SDpnt->queue_depth = host->cmd_per_lun; SDpnt->device_queue = NULL; for(j=0;j<SDpnt->queue_depth;j++){ SCpnt = (Scsi_Cmnd *) scsi_init_malloc(sizeof(Scsi_Cmnd), GFP_ATOMIC | (host->unchecked_isa_dma ? GFP_DMA : 0)); if (NULL == SCpnt) break; /* If not, the next line will oops ... */ memset(&SCpnt->eh_timeout, 0, sizeof(SCpnt->eh_timeout)); SCpnt->host = host; SCpnt->device = SDpnt; SCpnt->target = SDpnt->id; SCpnt->lun = SDpnt->lun; SCpnt->channel = SDpnt->channel; SCpnt->request.rq_status = RQ_INACTIVE; SCpnt->host_wait = FALSE; SCpnt->device_wait = FALSE; SCpnt->use_sg = 0; SCpnt->old_use_sg = 0; SCpnt->old_cmd_len = 0; SCpnt->underflow = 0; SCpnt->transfersize = 0; SCpnt->serial_number = 0; SCpnt->serial_number_at_timeout = 0; SCpnt->host_scribble = NULL; SCpnt->next = SDpnt->device_queue; SDpnt->device_queue = SCpnt; SCpnt->state = SCSI_STATE_UNUSED; SCpnt->owner = SCSI_OWNER_NOBODY; } if (j < SDpnt->queue_depth) { /* low on space (D.Gilbert 990424) */ printk("scsi_build_commandblocks: want=%d, space for=%d blocks\n", SDpnt->queue_depth, j); SDpnt->queue_depth = j; SDpnt->has_cmdblocks = (0 != j); } else SDpnt->has_cmdblocks = 1;}#ifndef MODULE /* { *//* * scsi_dev_init() is our initialization routine, which in turn calls host * initialization, bus scanning, and sd/st initialization routines. * This is only used at boot time. */__initfunc(int scsi_dev_init(void)){ Scsi_Device * SDpnt; struct Scsi_Host * shpnt; struct Scsi_Device_Template * sdtpnt;#ifdef FOO_ON_YOU return;#endif /* Yes we're here... */#if CONFIG_PROC_FS dispatch_scsi_info_ptr = dispatch_scsi_info;#endif /* Init a few things so we can "malloc" memory. */ scsi_loadable_module_flag = 0; /* Register the /proc/scsi/scsi entry */#if CONFIG_PROC_FS proc_scsi_register(0, &proc_scsi_scsi);#endif /* initialize all hosts */ scsi_init(); /* * This is where the processing takes place for most everything * when commands are completed. Until we do this, we will not be able * to queue any commands. */ init_bh(SCSI_BH, scsi_bottom_half_handler); for (shpnt = scsi_hostlist; shpnt; shpnt = shpnt->next) { scan_scsis(shpnt,0,0,0,0); /* scan for scsi devices */ if (shpnt->select_queue_depths != NULL) (shpnt->select_queue_depths)(shpnt, shpnt->host_queue); } printk("scsi : detected "); for (sdtpnt = scsi_devicelist; sdtpnt; sdtpnt = sdtpnt->next) if (sdtpnt->dev_noticed && sdtpnt->name) printk("%d SCSI %s%s ", sdtpnt->dev_noticed, sdtpnt->name, (sdtpnt->dev_noticed != 1) ? "s" : ""); printk("total.\n"); for(sdtpnt = scsi_devicelist; sdtpnt; sdtpnt = sdtpnt->next) if(sdtpnt->init && s
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -