diff options
Diffstat (limited to 'drivers/scsi/scsi_lib.c')
| -rw-r--r-- | drivers/scsi/scsi_lib.c | 43 | 
1 files changed, 21 insertions, 22 deletions
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index 249757ddd8fe..9ed1ebcb7443 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -308,6 +308,18 @@ static void scsi_kick_queue(struct request_queue *q)  }  /* + * Kick the queue of SCSI device @sdev if @sdev != current_sdev. Called with + * interrupts disabled. + */ +static void scsi_kick_sdev_queue(struct scsi_device *sdev, void *data) +{ +	struct scsi_device *current_sdev = data; + +	if (sdev != current_sdev) +		blk_mq_run_hw_queues(sdev->request_queue, true); +} + +/*   * Called for single_lun devices on IO completion. Clear starget_sdev_user,   * and call blk_run_queue for all the scsi_devices on the target -   * including current_sdev first. @@ -317,7 +329,6 @@ static void scsi_kick_queue(struct request_queue *q)  static void scsi_single_lun_run(struct scsi_device *current_sdev)  {  	struct Scsi_Host *shost = current_sdev->host; -	struct scsi_device *sdev, *tmp;  	struct scsi_target *starget = scsi_target(current_sdev);  	unsigned long flags; @@ -334,22 +345,9 @@ static void scsi_single_lun_run(struct scsi_device *current_sdev)  	scsi_kick_queue(current_sdev->request_queue);  	spin_lock_irqsave(shost->host_lock, flags); -	if (starget->starget_sdev_user) -		goto out; -	list_for_each_entry_safe(sdev, tmp, &starget->devices, -			same_target_siblings) { -		if (sdev == current_sdev) -			continue; -		if (scsi_device_get(sdev)) -			continue; - -		spin_unlock_irqrestore(shost->host_lock, flags); -		scsi_kick_queue(sdev->request_queue); -		spin_lock_irqsave(shost->host_lock, flags); - -		scsi_device_put(sdev); -	} - out: +	if (!starget->starget_sdev_user) +		__starget_for_each_device(starget, current_sdev, +					  scsi_kick_sdev_queue);  	spin_unlock_irqrestore(shost->host_lock, flags);  } @@ -1343,9 +1341,6 @@ static inline int scsi_host_queue_ready(struct request_queue *q,  				   struct scsi_device *sdev,  				   struct scsi_cmnd *cmd)  { -	if (scsi_host_in_recovery(shost)) -		return 0; -  	if (atomic_read(&shost->host_blocked) > 0) {  		if (scsi_host_busy(shost) > 0)  			goto starved; @@ -1469,8 +1464,6 @@ static 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 @@ -1734,6 +1727,11 @@ static blk_status_t scsi_queue_rq(struct blk_mq_hw_ctx *hctx,  	ret = BLK_STS_RESOURCE;  	if (!scsi_target_queue_ready(shost, sdev))  		goto out_put_budget; +	if (unlikely(scsi_host_in_recovery(shost))) { +		if (cmd->flags & SCMD_FAIL_IF_RECOVERING) +			ret = BLK_STS_OFFLINE; +		goto out_dec_target_busy; +	}  	if (!scsi_host_queue_ready(q, shost, sdev, cmd))  		goto out_dec_target_busy; @@ -1764,6 +1762,7 @@ static blk_status_t scsi_queue_rq(struct blk_mq_hw_ctx *hctx,  		goto out_dec_host_busy;  	} +	atomic_inc(&cmd->device->iorequest_cnt);  	return BLK_STS_OK;  out_dec_host_busy:  | 
