@@ -5610,12 +5610,20 @@ static int __ufshcd_issue_tm_cmd(struct ufs_hba *hba,
*
* Returns non-zero value on error, zero on success.
*/
-static int ufshcd_issue_tm_cmd(struct ufs_hba *hba, int lun_id, int task_id,
- u8 tm_function, u8 *tm_response)
+static int ufshcd_issue_tm_cmd(struct ufs_hba *hba,
+ struct utp_upiu_req *req_upiu,
+ struct utp_upiu_req *rsp_upiu,
+ int lun_id, int task_id,
+ u8 tm_function, u8 *tm_response)
{
struct utp_task_req_desc treq = { { 0 }, };
int ocs_value, err;
+ if (req_upiu) {
+ memcpy(&treq.req_header, req_upiu, GENERAL_UPIU_REQUEST_SIZE);
+ goto issue_tm_cmd;
+ }
+
/* Configure task request descriptor */
treq.header.dword_0 = cpu_to_le32(UTP_REQ_DESC_INT_CMD);
treq.header.dword_2 = cpu_to_le32(OCS_INVALID_COMMAND_STATUS);
@@ -5632,17 +5640,24 @@ static int ufshcd_issue_tm_cmd(struct ufs_hba *hba, int lun_id, int task_id,
treq.input_param1 = cpu_to_be32(lun_id);
treq.input_param2 = cpu_to_be32(task_id);
+issue_tm_cmd:
err = __ufshcd_issue_tm_cmd(hba, &treq, tm_function);
if (err == -ETIMEDOUT)
return err;
ocs_value = le32_to_cpu(treq.header.dword_2) & MASK_OCS;
- if (ocs_value != OCS_SUCCESS)
+ if (ocs_value != OCS_SUCCESS) {
dev_err(hba->dev, "%s: failed, ocs = 0x%x\n",
__func__, ocs_value);
- else if (tm_response)
- *tm_response = be32_to_cpu(treq.output_param1) &
- MASK_TM_SERVICE_RESP;
+ } else {
+ if (tm_response)
+ *tm_response = be32_to_cpu(treq.output_param1) &
+ MASK_TM_SERVICE_RESP;
+ if (rsp_upiu)
+ memcpy(rsp_upiu, &treq.rsp_header,
+ GENERAL_UPIU_REQUEST_SIZE);
+
+ }
return err;
}
@@ -5669,7 +5684,8 @@ static int ufshcd_eh_device_reset_handler(struct scsi_cmnd *cmd)
tag = cmd->request->tag;
lrbp = &hba->lrb[tag];
- err = ufshcd_issue_tm_cmd(hba, lrbp->lun, 0, UFS_LOGICAL_RESET, &resp);
+ err = ufshcd_issue_tm_cmd(hba, NULL, NULL, lrbp->lun, 0,
+ UFS_LOGICAL_RESET, &resp);
if (err || resp != UPIU_TASK_MANAGEMENT_FUNC_COMPL) {
if (!err)
err = resp;
@@ -5799,8 +5815,9 @@ static int ufshcd_abort(struct scsi_cmnd *cmd)
}
for (poll_cnt = 100; poll_cnt; poll_cnt--) {
- err = ufshcd_issue_tm_cmd(hba, lrbp->lun, lrbp->task_tag,
- UFS_QUERY_TASK, &resp);
+ err = ufshcd_issue_tm_cmd(hba, NULL, NULL, lrbp->lun,
+ lrbp->task_tag, UFS_QUERY_TASK,
+ &resp);
if (!err && resp == UPIU_TASK_MANAGEMENT_FUNC_SUCCEEDED) {
/* cmd pending in the device */
dev_err(hba->dev, "%s: cmd pending in the device. tag = %d\n",
@@ -5838,8 +5855,8 @@ static int ufshcd_abort(struct scsi_cmnd *cmd)
goto out;
}
- err = ufshcd_issue_tm_cmd(hba, lrbp->lun, lrbp->task_tag,
- UFS_ABORT_TASK, &resp);
+ err = ufshcd_issue_tm_cmd(hba, NULL, NULL, lrbp->lun, lrbp->task_tag,
+ UFS_ABORT_TASK, &resp);
if (err || resp != UPIU_TASK_MANAGEMENT_FUNC_COMPL) {
if (!err) {
err = resp; /* service response error */
Do that in order to re-use its code if the task request and response UPIUs are given externally. Signed-off-by: Avri Altman <avri.altman@wdc.com> --- drivers/scsi/ufs/ufshcd.c | 39 ++++++++++++++++++++++++++++----------- 1 file changed, 28 insertions(+), 11 deletions(-)