unlock_kernel();  /* acquire a reference to the host, so it won't be deallocated * until we're ready to exit */ scsi_host_get(host);  /* signal that we've started the thread */ complete(&(us->notify)); 
static int usb_stor_control_thread(void * __us){	struct us_data *us = (struct us_data *)__us;	struct Scsi_Host *host = us_to_host(us);	lock_kernel();	/*	 * This thread doesn't need any user-level access,	 * so get rid of all our resources.	 */	daemonize("usb-storage");	current->flags |= PF_NOFREEZE;	unlock_kernel();	/* acquire a reference to the host, so it won't be deallocated	 * until we're ready to exit */	scsi_host_get(host);	/* signal that we've started the thread */	complete(&(us->notify));	for(;;) {		US_DEBUGP("*** thread sleeping.\n");		if(down_interruptible(&us->sema))			break;					US_DEBUGP("*** thread awakened.\n");		/* lock the device pointers */		down(&(us->dev_semaphore));		/* if the device has disconnected, we are free to exit */		if (test_bit(US_FLIDX_DISCONNECTING, &us->flags)) {			US_DEBUGP("-- exiting\n");			up(&(us->dev_semaphore));			break;		}		/* lock access to the state */		scsi_lock(host);		/* has the command timed out *already* ? */		if (test_bit(US_FLIDX_TIMED_OUT, &us->flags)) {			us->srb->result = DID_ABORT << 16;			goto SkipForAbort;		}		scsi_unlock(host);		/* reject the command if the direction indicator 		 * is UNKNOWN		 */		if (us->srb->sc_data_direction == DMA_BIDIRECTIONAL) {			US_DEBUGP("UNKNOWN data direction\n");			us->srb->result = DID_ERROR << 16;		}		/* reject if target != 0 or if LUN is higher than		 * the maximum known LUN		 */		else if (us->srb->device->id && 				!(us->flags & US_FL_SCM_MULT_TARG)) {			US_DEBUGP("Bad target number (%d:%d)\n",				  us->srb->device->id, us->srb->device->lun);			us->srb->result = DID_BAD_TARGET << 16;		}		else if (us->srb->device->lun > us->max_lun) {			US_DEBUGP("Bad LUN (%d:%d)\n",				  us->srb->device->id, us->srb->device->lun);			us->srb->result = DID_BAD_TARGET << 16;		}		/* Handle those devices which need us to fake 		 * their inquiry data */		else if ((us->srb->cmnd[0] == INQUIRY) &&			    (us->flags & US_FL_FIX_INQUIRY)) {			unsigned char data_ptr[36] = {			    0x00, 0x80, 0x02, 0x02,			    0x1F, 0x00, 0x00, 0x00};			US_DEBUGP("Faking INQUIRY command\n");			fill_inquiry_response(us, data_ptr, 36);			us->srb->result = SAM_STAT_GOOD;		}		/* we've got a command, let's do it! */		else {			US_DEBUG(usb_stor_show_command(us->srb));			us->proto_handler(us->srb, us);		}		/* lock access to the state */		scsi_lock(host);		/* indicate that the command is done */		if (us->srb->result != DID_ABORT << 16) {			US_DEBUGP("scsi cmd done, result=0x%x\n", 				   us->srb->result);			us->srb->scsi_done(us->srb);		} else {SkipForAbort:			US_DEBUGP("scsi command aborted\n");		}		/* If an abort request was received we need to signal that		 * the abort has finished.  The proper test for this is		 * the TIMED_OUT flag, not srb->result == DID_ABORT, because		 * the timeout might have occurred after the command had		 * already completed with a different result code. */		if (test_bit(US_FLIDX_TIMED_OUT, &us->flags)) {			complete(&(us->notify));			/* Allow USB transfers to resume */			clear_bit(US_FLIDX_ABORTING, &us->flags);			clear_bit(US_FLIDX_TIMED_OUT, &us->flags);		}		/* finished working on this command */		us->srb = NULL;		scsi_unlock(host);		/* unlock the device pointers */		up(&(us->dev_semaphore));	} /* for (;;) */	scsi_host_put(host);	/* notify the exit routine that we're actually exiting now 	 *	 * complete()/wait_for_completion() is similar to up()/down(),	 * except that complete() is safe in the case where the structure	 * is getting deleted in a parallel mode of execution (i.e. just	 * after the down() -- that's necessary for the thread-shutdown	 * case.	 *	 * complete_and_exit() goes even further than this -- it is safe in	 * the case that the thread of the caller is going away (not just	 * the structure) -- this is necessary for the module-remove case.	 * This is important in preemption kernels, which transfer the flow	 * of execution immediately upon a complete().	 */	complete_and_exit(&threads_gone, 0);}	
4520	/local/tlutelli/issta_data/temp/c/2005_temp/2005/4520/3f13e66e219238e025ff561d69826da9342c3f4a/usb.c/clean/drivers/usb/storage/usb.c