Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 91854e86 authored by Yaniv Gardi's avatar Yaniv Gardi
Browse files

scsi: ufs: clear outstanding_request bit in case query timeout



When sending a query to the device returns with a timeout error,
we clear the corresponding bit in the DOORBELL register but
we don't clear the outstanding_request field as we should.
This patch fixes this bug.

Change-Id: Ia7e0aa29b0d822742654ba206a5837b9091fdb4a
Signed-off-by: default avatarYaniv Gardi <ygardi@codeaurora.org>
parent 7a0bc71a
Loading
Loading
Loading
Loading
+20 −4
Original line number Diff line number Diff line
@@ -673,6 +673,16 @@ static inline void ufshcd_utrl_clear(struct ufs_hba *hba, u32 pos)
	ufshcd_writel(hba, ~(1 << pos), REG_UTP_TRANSFER_REQ_LIST_CLEAR);
}

/**
 * ufshcd_outstanding_req_clear - Clear a bit in outstanding request field
 * @hba: per adapter instance
 * @tag: position of the bit to be cleared
 */
static inline void ufshcd_outstanding_req_clear(struct ufs_hba *hba, int tag)
{
	__clear_bit(tag, &hba->outstanding_reqs);
}

/**
 * ufshcd_get_lists_status - Check UCRDY, UTRLRDY and UTMRLRDY
 * @reg: Register value of host controller status
@@ -2553,8 +2563,14 @@ static int ufshcd_wait_for_dev_cmd(struct ufs_hba *hba,
		dev_dbg(hba->dev, "%s: dev_cmd request timedout, tag %d\n",
			__func__, lrbp->task_tag);
		if (!ufshcd_clear_cmd(hba, lrbp->task_tag))
			/* sucessfully cleared the command, retry if needed */
			/* successfully cleared the command, retry if needed */
			err = -EAGAIN;
		/*
		 * in case of an error, after clearing the doorbell,
		 * we also need to clear the outstanding_request
		 * field in hba
		 */
		ufshcd_outstanding_req_clear(hba, lrbp->task_tag);
	}

	return err;
@@ -4675,7 +4691,7 @@ void ufshcd_abort_outstanding_transfer_requests(struct ufs_hba *hba, int result)
			lrbp->cmd = NULL;
			/* Clear pending transfer requests */
			ufshcd_clear_cmd(hba, index);
			__clear_bit(index, &hba->outstanding_reqs);
			ufshcd_outstanding_req_clear(hba, index);
			clear_bit_unlock(index, &hba->lrb_in_use);
			/* Do not touch lrbp after scsi done */
			cmd->scsi_done(cmd);
@@ -4684,7 +4700,7 @@ void ufshcd_abort_outstanding_transfer_requests(struct ufs_hba *hba, int result)
			if (hba->dev_cmd.complete) {
				ufshcd_cond_add_cmd_trace(hba, index,
							"dev_failed");
				__clear_bit(index, &hba->outstanding_reqs);
				ufshcd_outstanding_req_clear(hba, index);
				complete(hba->dev_cmd.complete);
			}
		}
@@ -5802,7 +5818,7 @@ static int ufshcd_abort(struct scsi_cmnd *cmd)
	scsi_dma_unmap(cmd);

	spin_lock_irqsave(host->host_lock, flags);
	__clear_bit(tag, &hba->outstanding_reqs);
	ufshcd_outstanding_req_clear(hba, tag);
	hba->lrb[tag].cmd = NULL;
	spin_unlock_irqrestore(host->host_lock, flags);