From: Alim Akhtar Date: Sun, 6 May 2018 10:14:15 +0000 (+0530) Subject: scsi: ufs: add quirk to fix mishandling utrlclr/utmrlclr X-Git-Tag: v5.15~8644^2~77 X-Git-Url: https://git.proxmox.com/?a=commitdiff_plain;h=1399c5b02c568700ba50ce1ec19c12e71b25c73d;p=mirror_ubuntu-kernels.git scsi: ufs: add quirk to fix mishandling utrlclr/utmrlclr In the right behavior, setting the bit to '0' indicates clear and '1' indicates no change. If host controller handles this the other way, UFSHCI_QUIRK_BROKEN_REQ_LIST_CLR can be used. [mkp: typo] Signed-off-by: Seungwon Jeon Signed-off-by: Alim Akhtar Reviewed-by: Subhash Jadavani Reviewed-by: "Asutosh Das (asd)" Signed-off-by: Martin K. Petersen --- diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index bbad34738bea..937355b04e4a 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -643,7 +643,24 @@ static inline void ufshcd_put_tm_slot(struct ufs_hba *hba, int slot) */ static inline void ufshcd_utrl_clear(struct ufs_hba *hba, u32 pos) { - ufshcd_writel(hba, ~(1 << pos), REG_UTP_TRANSFER_REQ_LIST_CLEAR); + if (hba->quirks & UFSHCI_QUIRK_BROKEN_REQ_LIST_CLR) + ufshcd_writel(hba, (1 << pos), REG_UTP_TRANSFER_REQ_LIST_CLEAR); + else + ufshcd_writel(hba, ~(1 << pos), + REG_UTP_TRANSFER_REQ_LIST_CLEAR); +} + +/** + * ufshcd_utmrl_clear - Clear a bit in UTRMLCLR register + * @hba: per adapter instance + * @pos: position of the bit to be cleared + */ +static inline void ufshcd_utmrl_clear(struct ufs_hba *hba, u32 pos) +{ + if (hba->quirks & UFSHCI_QUIRK_BROKEN_REQ_LIST_CLR) + ufshcd_writel(hba, (1 << pos), REG_UTP_TASK_REQ_LIST_CLEAR); + else + ufshcd_writel(hba, ~(1 << pos), REG_UTP_TASK_REQ_LIST_CLEAR); } /** @@ -5362,7 +5379,7 @@ static int ufshcd_clear_tm_cmd(struct ufs_hba *hba, int tag) goto out; spin_lock_irqsave(hba->host->host_lock, flags); - ufshcd_writel(hba, ~(1 << tag), REG_UTP_TASK_REQ_LIST_CLEAR); + ufshcd_utmrl_clear(hba, tag); spin_unlock_irqrestore(hba->host->host_lock, flags); /* poll for max. 1 sec to clear door bell register by h/w */ diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h index 8110dcd04d22..09c285f62c6a 100644 --- a/drivers/scsi/ufs/ufshcd.h +++ b/drivers/scsi/ufs/ufshcd.h @@ -595,6 +595,11 @@ struct ufs_hba { */ #define UFSHCD_QUIRK_PRDT_BYTE_GRAN 0x80 + /* + * Clear handling for transfer/task request list is just opposite. + */ + #define UFSHCI_QUIRK_BROKEN_REQ_LIST_CLR 0x100 + unsigned int quirks; /* Deviations from standard UFSHCI spec. */ /* Device deviations from standard UFS device spec. */