From: Christoph Hellwig <h...@lst.de>

Add a helper that takes a utp_task_req_desc and issues it, which will
be useful for UFS bsg support.  Rewrite ufshcd_issue_tm_cmd0x to use
this new helper.

Signed-off-by: Christoph Hellwig <h...@lst.de>
---
 drivers/scsi/ufs/ufshcd.c | 141 ++++++++++++++++++++--------------------------
 1 file changed, 61 insertions(+), 80 deletions(-)

diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index 178bbf7..566474f 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -634,19 +634,6 @@ static inline int ufshcd_get_tr_ocs(struct ufshcd_lrb 
*lrbp)
 }
 
 /**
- * ufshcd_get_tmr_ocs - Get the UTMRD Overall Command Status
- * @task_req_descp: pointer to utp_task_req_desc structure
- *
- * This function is used to get the OCS field from UTMRD
- * Returns the OCS field in the UTMRD
- */
-static inline int
-ufshcd_get_tmr_ocs(struct utp_task_req_desc *task_req_descp)
-{
-       return le32_to_cpu(task_req_descp->header.dword_2) & MASK_OCS;
-}
-
-/**
  * ufshcd_get_tm_free_slot - get a free slot for task management request
  * @hba: per adapter instance
  * @free_slot: pointer to variable with available slot value
@@ -4589,37 +4576,6 @@ static void ufshcd_slave_destroy(struct scsi_device 
*sdev)
 }
 
 /**
- * ufshcd_task_req_compl - handle task management request completion
- * @hba: per adapter instance
- * @index: index of the completed request
- * @resp: task management service response
- *
- * Returns non-zero value on error, zero on success
- */
-static int ufshcd_task_req_compl(struct ufs_hba *hba, u32 index, u8 *resp)
-{
-       struct utp_task_req_desc *treq = hba->utmrdl_base_addr + index;
-       unsigned long flags;
-       int ocs_value;
-
-       spin_lock_irqsave(hba->host->host_lock, flags);
-
-       /* Clear completed tasks from outstanding_tasks */
-       __clear_bit(index, &hba->outstanding_tasks);
-
-       ocs_value = ufshcd_get_tmr_ocs(treq);
-
-       if (ocs_value != OCS_SUCCESS)
-               dev_err(hba->dev, "%s: failed, ocs = 0x%x\n",
-                               __func__, ocs_value);
-       else if (resp)
-               *resp = be32_to_cpu(treq->output_param1) & MASK_TM_SERVICE_RESP;
-       spin_unlock_irqrestore(hba->host->host_lock, flags);
-
-       return ocs_value;
-}
-
-/**
  * ufshcd_scsi_cmd_status - Update SCSI command result based on SCSI status
  * @lrbp: pointer to local reference block of completed command
  * @scsi_status: SCSI command status
@@ -5576,27 +5532,12 @@ static int ufshcd_clear_tm_cmd(struct ufs_hba *hba, int 
tag)
        return err;
 }
 
-/**
- * ufshcd_issue_tm_cmd - issues task management commands to controller
- * @hba: per adapter instance
- * @lun_id: LUN ID to which TM command is sent
- * @task_id: task ID to which the TM command is applicable
- * @tm_function: task management function opcode
- * @tm_response: task management service response return value
- *
- * 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_task_req_desc *treq, u8 tm_function)
 {
-       struct utp_task_req_desc *treq;
-       struct Scsi_Host *host;
+       struct Scsi_Host *host = hba->host;
        unsigned long flags;
-       int free_slot;
-       int err;
-       int task_tag;
-
-       host = hba->host;
+       int free_slot, task_tag, err;
 
        /*
         * Get free slot, sleep if slots are unavailable.
@@ -5607,24 +5548,11 @@ static int ufshcd_issue_tm_cmd(struct ufs_hba *hba, int 
lun_id, int task_id,
        ufshcd_hold(hba, false);
 
        spin_lock_irqsave(host->host_lock, flags);
-       treq = hba->utmrdl_base_addr + free_slot;
-
-       /* 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);
-
-       /* Configure task request UPIU */
        task_tag = hba->nutrs + free_slot;
-       treq->req_header.dword_0 = UPIU_HEADER_DWORD(UPIU_TRANSACTION_TASK_REQ,
-                       0, lun_id, task_tag);
-       treq->req_header.dword_1 = UPIU_HEADER_DWORD(0, tm_function, 0, 0);
-       /*
-        * The host shall provide the same value for LUN field in the basic
-        * header and for Input Parameter.
-        */
-       treq->input_param1 = cpu_to_be32(lun_id);
-       treq->input_param2 = cpu_to_be32(task_id);
 
+       treq->req_header.dword_0 |= cpu_to_be32(task_tag);
+
+       memcpy(hba->utmrdl_base_addr + free_slot, treq, sizeof(*treq));
        ufshcd_vops_setup_task_mgmt(hba, free_slot, tm_function);
 
        /* send command to the controller */
@@ -5654,8 +5582,15 @@ static int ufshcd_issue_tm_cmd(struct ufs_hba *hba, int 
lun_id, int task_id,
                                        __func__, free_slot);
                err = -ETIMEDOUT;
        } else {
-               err = ufshcd_task_req_compl(hba, free_slot, tm_response);
+               err = 0;
+               memcpy(treq, hba->utmrdl_base_addr + free_slot, sizeof(*treq));
+
                ufshcd_add_tm_upiu_trace(hba, task_tag, "tm_complete");
+
+               spin_lock_irqsave(hba->host->host_lock, flags);
+               __clear_bit(free_slot, &hba->outstanding_tasks);
+               spin_unlock_irqrestore(hba->host->host_lock, flags);
+
        }
 
        clear_bit(free_slot, &hba->tm_condition);
@@ -5667,6 +5602,52 @@ static int ufshcd_issue_tm_cmd(struct ufs_hba *hba, int 
lun_id, int task_id,
 }
 
 /**
+ * ufshcd_issue_tm_cmd - issues task management commands to controller
+ * @hba: per adapter instance
+ * @lun_id: LUN ID to which TM command is sent
+ * @task_id: task ID to which the TM command is applicable
+ * @tm_function: task management function opcode
+ * @tm_response: task management service response return value
+ *
+ * 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)
+{
+       struct utp_task_req_desc treq = { { 0 }, };
+       int ocs_value, err;
+
+       /* 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);
+
+       /* Configure task request UPIU */
+       treq.req_header.dword_0 = cpu_to_be32(lun_id << 8) |
+                                 cpu_to_be32(UPIU_TRANSACTION_TASK_REQ << 24);
+       treq.req_header.dword_1 = cpu_to_be32(tm_function << 16);
+
+       /*
+        * The host shall provide the same value for LUN field in the basic
+        * header and for Input Parameter.
+        */
+       treq.input_param1 = cpu_to_be32(lun_id);
+       treq.input_param2 = cpu_to_be32(task_id);
+
+       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)
+               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;
+       return err;
+}
+
+/**
  * ufshcd_eh_device_reset_handler - device reset handler registered to
  *                                    scsi layer.
  * @cmd: SCSI command pointer
-- 
1.9.1

Reply via email to