>From 8ce84d4e1e9c34d7b36d40e5e5678da52070af02 Mon Sep 17 00:00:00 2001 From: Deenadayalan K <[email protected]> Date: Sun, 21 Jun 2026 15:15:16 +0530 Subject: [PATCH] UFS error handling for reject upiu.
ufshcd_handle_reject_upiu - Handle and display REJECT UPIU fields Per UFS spec, the device sends a REJECT UPIU when it receives a UPIU with an invalid Transaction Type. This function extracts and displays the REJECT UPIU header fields for diagnostics. task tag appears default 0 for UPIUs, it is a unique id for each UPIU If UFS host controller gets a reject upiu for the request UPIU then it does make sense to reattempt to issue the same request UPIU again a possible scenario where UFS device is not supporting though it is a valid transaction type. Signed-off-by: Deenadayalan K <[email protected]> --- drivers/ufs/ufs-uclass.c | 60 ++++++++++++++++++++++++++++++++++------ 1 file changed, 52 insertions(+), 8 deletions(-) diff --git a/drivers/ufs/ufs-uclass.c b/drivers/ufs/ufs-uclass.c index 6a51f337e47..fcafebd5203 100644 --- a/drivers/ufs/ufs-uclass.c +++ b/drivers/ufs/ufs-uclass.c @@ -1020,6 +1020,56 @@ static int ufshcd_copy_query_response(struct ufs_hba *hba) return 0; } +/** + * ufshcd_handle_reject_upiu - Handle and display REJECT UPIU fields + * + * Per UFS spec, the device sends a REJECT UPIU when it + * receives a UPIU with an invalid Transaction Type. This function extracts + * and displays the REJECT UPIU header fields for diagnostics. + */ +static int ufshcd_handle_reject_upiu(struct ufs_hba *hba) +{ + u32 dword_0 = be32_to_cpu(hba->ucd_rsp_ptr->header.dword_0); + u32 dword_1 = be32_to_cpu(hba->ucd_rsp_ptr->header.dword_1); + u8 *rsp = (u8 *)&hba->ucd_rsp_ptr->header; + u8 trans_type = (dword_0 >> 24) & 0xFF; + u8 hd = (trans_type >> 7) & 0x1; + u8 dd = (trans_type >> 6) & 0x1; + u8 flags = (dword_0 >> 16) & 0xFF; + u8 lun = (dword_0 >> 8) & 0xFF; + u8 task_tag = dword_0 & 0xFF; + u8 iid = (dword_1 >> 24) & 0x0F; + u8 ext_iid = (dword_1 >> 20) & 0x0F; + u8 response = (dword_1 >> 8) & 0xFF; + u8 basic_hdr_status = rsp[12]; + u8 e2e_status = rsp[14]; + + dev_err(hba->dev, "%s: Reject UPIU: LUN=0x%02x Task Tag=0x%02x IID=0x%x EXT_IID=0x%x Response=0x%02x Basic Header Status=0x%02x E2E Status=0x%02x", + __func__, lun, task_tag, iid, ext_iid, response, basic_hdr_status, e2e_status); + + if (response != 0x01) + dev_warn(hba->dev, "Reject UPIU: Unexpected Response=0x%02x (expected 0x01 Target Failure)\n", + response); + + if (hd && (e2e_status & BIT(0))) + dev_err(hba->dev, "Reject UPIU: Header E2ECRC error detected (HD=1, E2E Status bit0=1)\n"); + + if (dd && (e2e_status & BIT(1))) + dev_err(hba->dev, "Reject UPIU: Data E2ECRC error detected (DD=1, E2E Status bit1=1)\n"); + + if (!hd && !dd && (e2e_status & (BIT(0) | BIT(1)))) + dev_warn(hba->dev, "Reject UPIU: Unexpected E2E Status=0x%02x when CRC is disabled (HD=0, DD=0)\n", + e2e_status); + + /* task tag appears default 0 for UPIUs, it is a unique id for each UPIU + * If UFS host controller gets a reject upiu for the request UPIU then + * it does make sense to reattempt to issue the same request UPIU again + * a possible scenario where UFS device is not supporting though it is a valid + * transaction type. + */ + return -EPERM; +} + /** * ufshcd_exec_dev_cmd - API for sending device management requests */ @@ -1053,10 +1103,7 @@ static int ufshcd_exec_dev_cmd(struct ufs_hba *hba, enum dev_cmd_type cmd_type, err = ufshcd_copy_query_response(hba); break; case UPIU_TRANSACTION_REJECT_UPIU: - /* TODO: handle Reject UPIU Response */ - err = -EPERM; - dev_err(hba->dev, "%s: Reject UPIU not fully implemented\n", - __func__); + err = ufshcd_handle_reject_upiu(hba); break; default: err = -EINVAL; @@ -1687,10 +1734,7 @@ static int ufs_scsi_exec(struct udevice *scsi_dev, struct scsi_cmd *pccb) break; case UPIU_TRANSACTION_REJECT_UPIU: - /* TODO: handle Reject UPIU Response */ - dev_err(hba->dev, - "Reject UPIU not fully implemented\n"); - return -EINVAL; + return ufshcd_handle_reject_upiu(hba); default: dev_err(hba->dev, "Unexpected request response code = %x\n",

