diff options
Diffstat (limited to 'drivers/scsi/scsi_lib.c')
| -rw-r--r-- | drivers/scsi/scsi_lib.c | 84 | 
1 files changed, 18 insertions, 66 deletions
| diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index a6828391d6b3..601b9f1de267 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -316,7 +316,6 @@ EXPORT_SYMBOL(__scsi_execute);   */  static void scsi_init_cmd_errh(struct scsi_cmnd *cmd)  { -	cmd->serial_number = 0;  	scsi_set_resid(cmd, 0);  	memset(cmd->sense_buffer, 0, SCSI_SENSE_BUFFERSIZE);  	if (cmd->cmd_len == 0) @@ -556,15 +555,8 @@ static void scsi_uninit_cmd(struct scsi_cmnd *cmd)  static void scsi_mq_free_sgtables(struct scsi_cmnd *cmd)  { -	struct scsi_data_buffer *sdb; -  	if (cmd->sdb.table.nents)  		sg_free_table_chained(&cmd->sdb.table, true); -	if (cmd->request->next_rq) { -		sdb = cmd->request->next_rq->special; -		if (sdb) -			sg_free_table_chained(&sdb->table, true); -	}  	if (scsi_prot_sg_count(cmd))  		sg_free_table_chained(&cmd->prot_sdb->table, true);  } @@ -578,7 +570,7 @@ static void scsi_mq_uninit_cmd(struct scsi_cmnd *cmd)  /* Returns false when no more bytes to process, true if there are more */  static bool scsi_end_request(struct request *req, blk_status_t error, -		unsigned int bytes, unsigned int bidi_bytes) +		unsigned int bytes)  {  	struct scsi_cmnd *cmd = blk_mq_rq_to_pdu(req);  	struct scsi_device *sdev = cmd->device; @@ -587,21 +579,23 @@ static bool scsi_end_request(struct request *req, blk_status_t error,  	if (blk_update_request(req, error, bytes))  		return true; -	/* Bidi request must be completed as a whole */ -	if (unlikely(bidi_bytes) && -	    blk_update_request(req->next_rq, error, bidi_bytes)) -		return true; -  	if (blk_queue_add_random(q))  		add_disk_randomness(req->rq_disk);  	if (!blk_rq_is_scsi(req)) {  		WARN_ON_ONCE(!(cmd->flags & SCMD_INITIALIZED));  		cmd->flags &= ~SCMD_INITIALIZED; -		destroy_rcu_head(&cmd->rcu);  	}  	/* +	 * Calling rcu_barrier() is not necessary here because the +	 * SCSI error handler guarantees that the function called by +	 * call_rcu() has been called before scsi_end_request() is +	 * called. +	 */ +	destroy_rcu_head(&cmd->rcu); + +	/*  	 * In the MQ case the command gets freed by __blk_mq_end_request,  	 * so we have to do all cleanup that depends on it earlier.  	 * @@ -817,7 +811,7 @@ static void scsi_io_completion_action(struct scsi_cmnd *cmd, int result)  				scsi_print_command(cmd);  			}  		} -		if (!scsi_end_request(req, blk_stat, blk_rq_err_bytes(req), 0)) +		if (!scsi_end_request(req, blk_stat, blk_rq_err_bytes(req)))  			return;  		/*FALLTHRU*/  	case ACTION_REPREP: @@ -951,30 +945,6 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes)  		 * scsi_result_to_blk_status may have reset the host_byte  		 */  		scsi_req(req)->result = cmd->result; -		scsi_req(req)->resid_len = scsi_get_resid(cmd); - -		if (unlikely(scsi_bidi_cmnd(cmd))) { -			/* -			 * Bidi commands Must be complete as a whole, -			 * both sides at once. -			 */ -			scsi_req(req->next_rq)->resid_len = scsi_in(cmd)->resid; -			if (scsi_end_request(req, BLK_STS_OK, blk_rq_bytes(req), -					blk_rq_bytes(req->next_rq))) -				WARN_ONCE(true, -					  "Bidi command with remaining bytes"); -			return; -		} -	} - -	/* no bidi support yet, other than in pass-through */ -	if (unlikely(blk_bidi_rq(req))) { -		WARN_ONCE(true, "Only support bidi command in passthrough"); -		scmd_printk(KERN_ERR, cmd, "Killing bidi command\n"); -		if (scsi_end_request(req, BLK_STS_IOERR, blk_rq_bytes(req), -				     blk_rq_bytes(req->next_rq))) -			WARN_ONCE(true, "Bidi command with remaining bytes"); -		return;  	}  	/* @@ -991,13 +961,13 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes)  	 * to retry code. Fast path should return in this block.  	 */  	if (likely(blk_rq_bytes(req) > 0 || blk_stat == BLK_STS_OK)) { -		if (likely(!scsi_end_request(req, blk_stat, good_bytes, 0))) +		if (likely(!scsi_end_request(req, blk_stat, good_bytes)))  			return; /* no bytes remaining */  	}  	/* Kill remainder if no retries. */  	if (unlikely(blk_stat && scsi_noretry_cmd(cmd))) { -		if (scsi_end_request(req, blk_stat, blk_rq_bytes(req), 0)) +		if (scsi_end_request(req, blk_stat, blk_rq_bytes(req)))  			WARN_ONCE(true,  			    "Bytes remaining after failed, no-retry command");  		return; @@ -1059,12 +1029,6 @@ blk_status_t scsi_init_io(struct scsi_cmnd *cmd)  	if (ret)  		return ret; -	if (blk_bidi_rq(rq)) { -		ret = scsi_init_sgtable(rq->next_rq, rq->next_rq->special); -		if (ret) -			goto out_free_sgtables; -	} -  	if (blk_integrity_rq(rq)) {  		struct scsi_data_buffer *prot_sdb = cmd->prot_sdb;  		int ivecs, count; @@ -1608,10 +1572,7 @@ static blk_status_t scsi_mq_prep_fn(struct request *req)  	scsi_init_command(sdev, cmd); -	req->special = cmd; -  	cmd->request = req; -  	cmd->tag = req->tag;  	cmd->prot_op = SCSI_PROT_NORMAL; @@ -1625,17 +1586,6 @@ static blk_status_t scsi_mq_prep_fn(struct request *req)  			(struct scatterlist *)(cmd->prot_sdb + 1);  	} -	if (blk_bidi_rq(req)) { -		struct request *next_rq = req->next_rq; -		struct scsi_data_buffer *bidi_sdb = blk_mq_rq_to_pdu(next_rq); - -		memset(bidi_sdb, 0, sizeof(struct scsi_data_buffer)); -		bidi_sdb->table.sgl = -			(struct scatterlist *)(bidi_sdb + 1); - -		next_rq->special = bidi_sdb; -	} -  	blk_mq_start_request(req);  	return scsi_setup_cmnd(sdev, req); @@ -1713,13 +1663,13 @@ static blk_status_t scsi_queue_rq(struct blk_mq_hw_ctx *hctx,  	if (!scsi_host_queue_ready(q, shost, sdev))  		goto out_dec_target_busy; -	clear_bit(SCMD_STATE_COMPLETE, &cmd->state);  	if (!(req->rq_flags & RQF_DONTPREP)) {  		ret = scsi_mq_prep_fn(req);  		if (ret != BLK_STS_OK)  			goto out_dec_host_busy;  		req->rq_flags |= RQF_DONTPREP;  	} else { +		clear_bit(SCMD_STATE_COMPLETE, &cmd->state);  		blk_mq_start_request(req);  	} @@ -1900,7 +1850,7 @@ int scsi_mq_setup_tags(struct Scsi_Host *shost)  	shost->tag_set.queue_depth = shost->can_queue;  	shost->tag_set.cmd_size = cmd_size;  	shost->tag_set.numa_node = NUMA_NO_NODE; -	shost->tag_set.flags = BLK_MQ_F_SHOULD_MERGE | BLK_MQ_F_SG_MERGE; +	shost->tag_set.flags = BLK_MQ_F_SHOULD_MERGE;  	shost->tag_set.flags |=  		BLK_ALLOC_POLICY_TO_MQ_FLAG(shost->hostt->tag_alloc_policy);  	shost->tag_set.driver_data = shost; @@ -2598,8 +2548,10 @@ void scsi_device_resume(struct scsi_device *sdev)  	 * device deleted during suspend)  	 */  	mutex_lock(&sdev->state_mutex); -	sdev->quiesced_by = NULL; -	blk_clear_pm_only(sdev->request_queue); +	if (sdev->quiesced_by) { +		sdev->quiesced_by = NULL; +		blk_clear_pm_only(sdev->request_queue); +	}  	if (sdev->sdev_state == SDEV_QUIESCE)  		scsi_device_set_state(sdev, SDEV_RUNNING);  	mutex_unlock(&sdev->state_mutex); | 
