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

Commit 2ab0dfad authored by Maya Erez's avatar Maya Erez Committed by David Keitel
Browse files

scsi: ufs: fix exception event handling



The device can set the exception event bit in one of the response UPIU,
for example to notify the need for urgent BKOPs operation.
In such a case the host driver calls ufshcd_exception_event_handler to
handle this notification.
When trying to check the exception event status (for finding the cause for
the exception event), the device may be busy with additional SCSI commands
handling and may not respond within the 100ms timeout.

To prevent that, we need to block SCSI commands during handling of
exception events and allow retransmissions of the query requests,
in case of timeout.

CRs-Fixed: 725525
Change-Id: I67a55ad5f891a018f1dfff319233f875789805a1
Signed-off-by: default avatarSubhash Jadavani <subhashj@codeaurora.org>
Signed-off-by: default avatarMaya Erez <merez@codeaurora.org>
parent 963b6843
Loading
Loading
Loading
Loading
+6 −4
Original line number Diff line number Diff line
@@ -3870,7 +3870,7 @@ static int ufshcd_disable_ee(struct ufs_hba *hba, u16 mask)

	val = hba->ee_ctrl_mask & ~mask;
	val &= 0xFFFF; /* 2 bytes */
	err = ufshcd_query_attr(hba, UPIU_QUERY_OPCODE_WRITE_ATTR,
	err = ufshcd_query_attr_retry(hba, UPIU_QUERY_OPCODE_WRITE_ATTR,
			QUERY_ATTR_IDN_EE_CONTROL, 0, 0, &val);
	if (!err)
		hba->ee_ctrl_mask &= ~mask;
@@ -3898,7 +3898,7 @@ static int ufshcd_enable_ee(struct ufs_hba *hba, u16 mask)

	val = hba->ee_ctrl_mask | mask;
	val &= 0xFFFF; /* 2 bytes */
	err = ufshcd_query_attr(hba, UPIU_QUERY_OPCODE_WRITE_ATTR,
	err = ufshcd_query_attr_retry(hba, UPIU_QUERY_OPCODE_WRITE_ATTR,
			QUERY_ATTR_IDN_EE_CONTROL, 0, 0, &val);
	if (!err)
		hba->ee_ctrl_mask |= mask;
@@ -4006,7 +4006,7 @@ static void ufshcd_force_reset_auto_bkops(struct ufs_hba *hba)

static inline int ufshcd_get_bkops_status(struct ufs_hba *hba, u32 *status)
{
	return ufshcd_query_attr(hba, UPIU_QUERY_OPCODE_READ_ATTR,
	return ufshcd_query_attr_retry(hba, UPIU_QUERY_OPCODE_READ_ATTR,
			QUERY_ATTR_IDN_BKOPS_STATUS, 0, 0, status);
}

@@ -4069,7 +4069,7 @@ static int ufshcd_urgent_bkops(struct ufs_hba *hba)

static inline int ufshcd_get_ee_status(struct ufs_hba *hba, u32 *status)
{
	return ufshcd_query_attr(hba, UPIU_QUERY_OPCODE_READ_ATTR,
	return ufshcd_query_attr_retry(hba, UPIU_QUERY_OPCODE_READ_ATTR,
			QUERY_ATTR_IDN_EE_STATUS, 0, 0, status);
}

@@ -4088,6 +4088,7 @@ static void ufshcd_exception_event_handler(struct work_struct *work)
	hba = container_of(work, struct ufs_hba, eeh_work);

	pm_runtime_get_sync(hba->dev);
	scsi_block_requests(hba->host);
	err = ufshcd_get_ee_status(hba, &status);
	if (err) {
		dev_err(hba->dev, "%s: failed to get exception status %d\n",
@@ -4103,6 +4104,7 @@ static void ufshcd_exception_event_handler(struct work_struct *work)
					__func__, err);
	}
out:
	scsi_unblock_requests(hba->host);
	pm_runtime_put_sync(hba->dev);
	return;
}