Commit 5565ec4e authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull SCSI fixes from James Bottomley:
 "Six small fixes.

  Four in drivers and the two core changes should be read together as a
  correction to a prior iorequest_cnt fix that exposed us to a potential
  use after free"

* tag 'scsi-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi:
  scsi: core: Decrease scsi_device's iorequest_cnt if dispatch failed
  scsi: Revert "scsi: core: Do not increase scsi_device's iorequest_cnt if dispatch failed"
  scsi: storvsc: Don't pass unused PFNs to Hyper-V host
  scsi: ufs: core: Fix MCQ nr_hw_queues
  scsi: ufs: core: Rename symbol sizeof_utp_transfer_cmd_desc()
  scsi: ufs: core: Fix MCQ tag calculation
parents a5948745 09e797c8
Loading
Loading
Loading
Loading
+4 −1
Original line number Diff line number Diff line
@@ -1463,6 +1463,8 @@ 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
@@ -1483,6 +1485,7 @@ static int scsi_dispatch_cmd(struct scsi_cmnd *cmd)
		 */
		SCSI_LOG_MLQUEUE(3, scmd_printk(KERN_INFO, cmd,
			"queuecommand : device blocked\n"));
		atomic_dec(&cmd->device->iorequest_cnt);
		return SCSI_MLQUEUE_DEVICE_BUSY;
	}

@@ -1515,6 +1518,7 @@ static int scsi_dispatch_cmd(struct scsi_cmnd *cmd)
	trace_scsi_dispatch_cmd_start(cmd);
	rtn = host->hostt->queuecommand(host, cmd);
	if (rtn) {
		atomic_dec(&cmd->device->iorequest_cnt);
		trace_scsi_dispatch_cmd_error(cmd, rtn);
		if (rtn != SCSI_MLQUEUE_DEVICE_BUSY &&
		    rtn != SCSI_MLQUEUE_TARGET_BUSY)
@@ -1761,7 +1765,6 @@ 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:
+4 −4
Original line number Diff line number Diff line
@@ -1780,7 +1780,7 @@ static int storvsc_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *scmnd)

	length = scsi_bufflen(scmnd);
	payload = (struct vmbus_packet_mpb_array *)&cmd_request->mpb;
	payload_sz = sizeof(cmd_request->mpb);
	payload_sz = 0;

	if (scsi_sg_count(scmnd)) {
		unsigned long offset_in_hvpg = offset_in_hvpage(sgl->offset);
@@ -1789,10 +1789,10 @@ static int storvsc_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *scmnd)
		unsigned long hvpfn, hvpfns_to_add;
		int j, i = 0, sg_count;

		if (hvpg_count > MAX_PAGE_BUFFER_COUNT) {

		payload_sz = (hvpg_count * sizeof(u64) +
			      sizeof(struct vmbus_packet_mpb_array));

		if (hvpg_count > MAX_PAGE_BUFFER_COUNT) {
			payload = kzalloc(payload_sz, GFP_ATOMIC);
			if (!payload)
				return SCSI_MLQUEUE_DEVICE_BUSY;
+3 −2
Original line number Diff line number Diff line
@@ -150,7 +150,8 @@ static int ufshcd_mcq_config_nr_queues(struct ufs_hba *hba)
	u32 hba_maxq, rem, tot_queues;
	struct Scsi_Host *host = hba->host;

	hba_maxq = FIELD_GET(MAX_QUEUE_SUP, hba->mcq_capabilities);
	/* maxq is 0 based value */
	hba_maxq = FIELD_GET(MAX_QUEUE_SUP, hba->mcq_capabilities) + 1;

	tot_queues = UFS_MCQ_NUM_DEV_CMD_QUEUES + read_queues + poll_queues +
			rw_queues;
@@ -265,7 +266,7 @@ static int ufshcd_mcq_get_tag(struct ufs_hba *hba,
	addr = (le64_to_cpu(cqe->command_desc_base_addr) & CQE_UCD_BA) -
		hba->ucdl_dma_addr;

	return div_u64(addr, sizeof(struct utp_transfer_cmd_desc));
	return div_u64(addr, ufshcd_get_ucd_size(hba));
}

static void ufshcd_mcq_process_cqe(struct ufs_hba *hba,
+5 −5
Original line number Diff line number Diff line
@@ -2849,10 +2849,10 @@ static void ufshcd_map_queues(struct Scsi_Host *shost)
static void ufshcd_init_lrb(struct ufs_hba *hba, struct ufshcd_lrb *lrb, int i)
{
	struct utp_transfer_cmd_desc *cmd_descp = (void *)hba->ucdl_base_addr +
		i * sizeof_utp_transfer_cmd_desc(hba);
		i * ufshcd_get_ucd_size(hba);
	struct utp_transfer_req_desc *utrdlp = hba->utrdl_base_addr;
	dma_addr_t cmd_desc_element_addr = hba->ucdl_dma_addr +
		i * sizeof_utp_transfer_cmd_desc(hba);
		i * ufshcd_get_ucd_size(hba);
	u16 response_offset = offsetof(struct utp_transfer_cmd_desc,
				       response_upiu);
	u16 prdt_offset = offsetof(struct utp_transfer_cmd_desc, prd_table);
@@ -3761,7 +3761,7 @@ static int ufshcd_memory_alloc(struct ufs_hba *hba)
	size_t utmrdl_size, utrdl_size, ucdl_size;

	/* Allocate memory for UTP command descriptors */
	ucdl_size = sizeof_utp_transfer_cmd_desc(hba) * hba->nutrs;
	ucdl_size = ufshcd_get_ucd_size(hba) * hba->nutrs;
	hba->ucdl_base_addr = dmam_alloc_coherent(hba->dev,
						  ucdl_size,
						  &hba->ucdl_dma_addr,
@@ -3861,7 +3861,7 @@ static void ufshcd_host_memory_configure(struct ufs_hba *hba)
	prdt_offset =
		offsetof(struct utp_transfer_cmd_desc, prd_table);

	cmd_desc_size = sizeof_utp_transfer_cmd_desc(hba);
	cmd_desc_size = ufshcd_get_ucd_size(hba);
	cmd_desc_dma_addr = hba->ucdl_dma_addr;

	for (i = 0; i < hba->nutrs; i++) {
@@ -8452,7 +8452,7 @@ static void ufshcd_release_sdb_queue(struct ufs_hba *hba, int nutrs)
{
	size_t ucdl_size, utrdl_size;

	ucdl_size = sizeof(struct utp_transfer_cmd_desc) * nutrs;
	ucdl_size = ufshcd_get_ucd_size(hba) * nutrs;
	dmam_free_coherent(hba->dev, ucdl_size, hba->ucdl_base_addr,
			   hba->ucdl_dma_addr);

+1 −1
Original line number Diff line number Diff line
@@ -1133,7 +1133,7 @@ static inline size_t ufshcd_sg_entry_size(const struct ufs_hba *hba)
	({ (void)(hba); BUILD_BUG_ON(sg_entry_size != sizeof(struct ufshcd_sg_entry)); })
#endif

static inline size_t sizeof_utp_transfer_cmd_desc(const struct ufs_hba *hba)
static inline size_t ufshcd_get_ucd_size(const struct ufs_hba *hba)
{
	return sizeof(struct utp_transfer_cmd_desc) + SG_ALL * ufshcd_sg_entry_size(hba);
}