diff options
Diffstat (limited to 'drivers/scsi/scsi.c')
| -rw-r--r-- | drivers/scsi/scsi.c | 211 | 
1 files changed, 40 insertions, 171 deletions
diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c index 79c77b485a67..1ad0c36375b8 100644 --- a/drivers/scsi/scsi.c +++ b/drivers/scsi/scsi.c @@ -527,9 +527,9 @@ void scsi_log_send(struct scsi_cmnd *cmd)  	 *  	 * 1: nothing (match completion)  	 * -	 * 2: log opcode + command of all commands +	 * 2: log opcode + command of all commands + cmd address  	 * -	 * 3: same as 2 plus dump cmd address +	 * 3: same as 2  	 *  	 * 4: same as 3 plus dump extra junk  	 */ @@ -537,10 +537,8 @@ void scsi_log_send(struct scsi_cmnd *cmd)  		level = SCSI_LOG_LEVEL(SCSI_LOG_MLQUEUE_SHIFT,  				       SCSI_LOG_MLQUEUE_BITS);  		if (level > 1) { -			scmd_printk(KERN_INFO, cmd, "Send: "); -			if (level > 2) -				printk("0x%p ", cmd); -			printk("\n"); +			scmd_printk(KERN_INFO, cmd, +				    "Send: scmd 0x%p\n", cmd);  			scsi_print_command(cmd);  			if (level > 3) {  				printk(KERN_INFO "buffer = 0x%p, bufflen = %d," @@ -565,7 +563,7 @@ void scsi_log_completion(struct scsi_cmnd *cmd, int disposition)  	 *  	 * 2: same as 1 but for all command completions.  	 * -	 * 3: same as 2 plus dump cmd address +	 * 3: same as 2  	 *  	 * 4: same as 3 plus dump extra junk  	 */ @@ -574,39 +572,10 @@ void scsi_log_completion(struct scsi_cmnd *cmd, int disposition)  				       SCSI_LOG_MLCOMPLETE_BITS);  		if (((level > 0) && (cmd->result || disposition != SUCCESS)) ||  		    (level > 1)) { -			scmd_printk(KERN_INFO, cmd, "Done: "); -			if (level > 2) -				printk("0x%p ", cmd); -			/* -			 * Dump truncated values, so we usually fit within -			 * 80 chars. -			 */ -			switch (disposition) { -			case SUCCESS: -				printk("SUCCESS\n"); -				break; -			case NEEDS_RETRY: -				printk("RETRY\n"); -				break; -			case ADD_TO_MLQUEUE: -				printk("MLQUEUE\n"); -				break; -			case FAILED: -				printk("FAILED\n"); -				break; -			case TIMEOUT_ERROR: -				/*  -				 * If called via scsi_times_out. -				 */ -				printk("TIMEOUT\n"); -				break; -			default: -				printk("UNKNOWN\n"); -			} -			scsi_print_result(cmd); +			scsi_print_result(cmd, "Done: ", disposition);  			scsi_print_command(cmd);  			if (status_byte(cmd->result) & CHECK_CONDITION) -				scsi_print_sense("", cmd); +				scsi_print_sense(cmd);  			if (level > 3)  				scmd_printk(KERN_INFO, cmd,  					    "scsi host busy %d failed %d\n", @@ -634,87 +603,6 @@ void scsi_cmd_get_serial(struct Scsi_Host *host, struct scsi_cmnd *cmd)  EXPORT_SYMBOL(scsi_cmd_get_serial);  /** - * scsi_dispatch_command - Dispatch a command to the low-level driver. - * @cmd: command block we are dispatching. - * - * Return: nonzero return request was rejected and device's queue needs to be - * plugged. - */ -int scsi_dispatch_cmd(struct scsi_cmnd *cmd) -{ -	struct Scsi_Host *host = cmd->device->host; -	int rtn = 0; - -	atomic_inc(&cmd->device->iorequest_cnt); - -	/* check if the device is still usable */ -	if (unlikely(cmd->device->sdev_state == SDEV_DEL)) { -		/* in SDEV_DEL we error all commands. DID_NO_CONNECT -		 * returns an immediate error upwards, and signals -		 * that the device is no longer present */ -		cmd->result = DID_NO_CONNECT << 16; -		goto done; -	} - -	/* Check to see if the scsi lld made this device blocked. */ -	if (unlikely(scsi_device_blocked(cmd->device))) { -		/* -		 * in blocked state, the command is just put back on -		 * the device queue.  The suspend state has already -		 * blocked the queue so future requests should not -		 * occur until the device transitions out of the -		 * suspend state. -		 */ -		SCSI_LOG_MLQUEUE(3, scmd_printk(KERN_INFO, cmd, -			"queuecommand : device blocked\n")); -		return SCSI_MLQUEUE_DEVICE_BUSY; -	} - -	/* Store the LUN value in cmnd, if needed. */ -	if (cmd->device->lun_in_cdb) -		cmd->cmnd[1] = (cmd->cmnd[1] & 0x1f) | -			       (cmd->device->lun << 5 & 0xe0); - -	scsi_log_send(cmd); - -	/* -	 * Before we queue this command, check if the command -	 * length exceeds what the host adapter can handle. -	 */ -	if (cmd->cmd_len > cmd->device->host->max_cmd_len) { -		SCSI_LOG_MLQUEUE(3, scmd_printk(KERN_INFO, cmd, -			       "queuecommand : command too long. " -			       "cdb_size=%d host->max_cmd_len=%d\n", -			       cmd->cmd_len, cmd->device->host->max_cmd_len)); -		cmd->result = (DID_ABORT << 16); -		goto done; -	} - -	if (unlikely(host->shost_state == SHOST_DEL)) { -		cmd->result = (DID_NO_CONNECT << 16); -		goto done; - -	} - -	trace_scsi_dispatch_cmd_start(cmd); -	rtn = host->hostt->queuecommand(host, cmd); -	if (rtn) { -		trace_scsi_dispatch_cmd_error(cmd, rtn); -		if (rtn != SCSI_MLQUEUE_DEVICE_BUSY && -		    rtn != SCSI_MLQUEUE_TARGET_BUSY) -			rtn = SCSI_MLQUEUE_HOST_BUSY; - -		SCSI_LOG_MLQUEUE(3, scmd_printk(KERN_INFO, cmd, -			"queuecommand : request rejected\n")); -	} - -	return rtn; - done: -	cmd->scsi_done(cmd); -	return 0; -} - -/**   * scsi_finish_command - cleanup and pass command back to upper layer   * @cmd: the command   * @@ -773,32 +661,18 @@ void scsi_finish_command(struct scsi_cmnd *cmd)  }  /** - * scsi_adjust_queue_depth - Let low level drivers change a device's queue depth + * scsi_change_queue_depth - change a device's queue depth   * @sdev: SCSI Device in question - * @tagged: Do we use tagged queueing (non-0) or do we treat - *          this device as an untagged device (0) - * @tags: Number of tags allowed if tagged queueing enabled, - *        or number of commands the low level driver can - *        queue up in non-tagged mode (as per cmd_per_lun). - * - * Returns:	Nothing + * @depth: number of commands allowed to be queued to the driver   * - * Lock Status:	None held on entry - * - * Notes:	Low level drivers may call this at any time and we will do - * 		the right thing depending on whether or not the device is - * 		currently active and whether or not it even has the - * 		command blocks built yet. + * Sets the device queue depth and returns the new value.   */ -void scsi_adjust_queue_depth(struct scsi_device *sdev, int tagged, int tags) +int scsi_change_queue_depth(struct scsi_device *sdev, int depth)  {  	unsigned long flags; -	/* -	 * refuse to set tagged depth to an unworkable size -	 */ -	if (tags <= 0) -		return; +	if (depth <= 0) +		goto out;  	spin_lock_irqsave(sdev->request_queue->queue_lock, flags); @@ -813,35 +687,17 @@ void scsi_adjust_queue_depth(struct scsi_device *sdev, int tagged, int tags)  	 */  	if (!shost_use_blk_mq(sdev->host) && !sdev->host->bqt) {  		if (blk_queue_tagged(sdev->request_queue) && -		    blk_queue_resize_tags(sdev->request_queue, tags) != 0) -			goto out; +		    blk_queue_resize_tags(sdev->request_queue, depth) != 0) +			goto out_unlock;  	} -	sdev->queue_depth = tags; -	switch (tagged) { -		case 0: -			sdev->ordered_tags = 0; -			sdev->simple_tags = 0; -			break; -		case MSG_ORDERED_TAG: -			sdev->ordered_tags = 1; -			sdev->simple_tags = 1; -			break; -		case MSG_SIMPLE_TAG: -			sdev->ordered_tags = 0; -			sdev->simple_tags = 1; -			break; -		default: -			sdev->ordered_tags = 0; -			sdev->simple_tags = 0; -			sdev_printk(KERN_WARNING, sdev, -				    "scsi_adjust_queue_depth, bad queue type, " -				    "disabled\n"); -	} - out: +	sdev->queue_depth = depth; +out_unlock:  	spin_unlock_irqrestore(sdev->request_queue->queue_lock, flags); +out: +	return sdev->queue_depth;  } -EXPORT_SYMBOL(scsi_adjust_queue_depth); +EXPORT_SYMBOL(scsi_change_queue_depth);  /**   * scsi_track_queue_full - track QUEUE_FULL events to adjust queue depth @@ -885,19 +741,32 @@ int scsi_track_queue_full(struct scsi_device *sdev, int depth)  		return 0;  	if (sdev->last_queue_full_depth < 8) {  		/* Drop back to untagged */ -		scsi_adjust_queue_depth(sdev, 0, sdev->host->cmd_per_lun); +		scsi_set_tag_type(sdev, 0); +		scsi_change_queue_depth(sdev, sdev->host->cmd_per_lun);  		return -1;  	} -	 -	if (sdev->ordered_tags) -		scsi_adjust_queue_depth(sdev, MSG_ORDERED_TAG, depth); -	else -		scsi_adjust_queue_depth(sdev, MSG_SIMPLE_TAG, depth); -	return depth; + +	return scsi_change_queue_depth(sdev, depth);  }  EXPORT_SYMBOL(scsi_track_queue_full);  /** + * scsi_change_queue_type() - Change a device's queue type + * @sdev:     The SCSI device whose queue depth is to change + * @tag_type: Identifier for queue type + */ +int scsi_change_queue_type(struct scsi_device *sdev, int tag_type) +{ +	if (!sdev->tagged_supported) +		return 0; + +	scsi_set_tag_type(sdev, tag_type); +	return tag_type; + +} +EXPORT_SYMBOL(scsi_change_queue_type); + +/**   * scsi_vpd_inquiry - Request a device provide us with a VPD page   * @sdev: The device to ask   * @buffer: Where to put the result  |