Merge tag 'scsi-misc' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi
[linux-2.6-microblaze.git] / drivers / scsi / ufs / ufshcd.c
index c55f38e..23d7cca 100644 (file)
@@ -46,6 +46,7 @@
 #include "ufs_quirks.h"
 #include "unipro.h"
 #include "ufs-sysfs.h"
+#include "ufs_bsg.h"
 
 #define CREATE_TRACE_POINTS
 #include <trace/events/ufs.h>
@@ -326,14 +327,11 @@ static void ufshcd_add_query_upiu_trace(struct ufs_hba *hba, unsigned int tag,
 static void ufshcd_add_tm_upiu_trace(struct ufs_hba *hba, unsigned int tag,
                const char *str)
 {
-       struct utp_task_req_desc *descp;
-       struct utp_upiu_task_req *task_req;
        int off = (int)tag - hba->nutrs;
+       struct utp_task_req_desc *descp = &hba->utmrdl_base_addr[off];
 
-       descp = &hba->utmrdl_base_addr[off];
-       task_req = (struct utp_upiu_task_req *)descp->task_req_upiu;
-       trace_ufshcd_upiu(dev_name(hba->dev), str, &task_req->header,
-                       &task_req->input_param1);
+       trace_ufshcd_upiu(dev_name(hba->dev), str, &descp->req_header,
+                       &descp->input_param1);
 }
 
 static void ufshcd_add_command_trace(struct ufs_hba *hba,
@@ -475,22 +473,13 @@ void ufshcd_print_trs(struct ufs_hba *hba, unsigned long bitmap, bool pr_prdt)
 
 static void ufshcd_print_tmrs(struct ufs_hba *hba, unsigned long bitmap)
 {
-       struct utp_task_req_desc *tmrdp;
        int tag;
 
        for_each_set_bit(tag, &bitmap, hba->nutmrs) {
-               tmrdp = &hba->utmrdl_base_addr[tag];
+               struct utp_task_req_desc *tmrdp = &hba->utmrdl_base_addr[tag];
+
                dev_err(hba->dev, "TM[%d] - Task Management Header\n", tag);
-               ufshcd_hex_dump("TM TRD: ", &tmrdp->header,
-                               sizeof(struct request_desc_header));
-               dev_err(hba->dev, "TM[%d] - Task Management Request UPIU\n",
-                               tag);
-               ufshcd_hex_dump("TM REQ: ", tmrdp->task_req_upiu,
-                               sizeof(struct utp_upiu_req));
-               dev_err(hba->dev, "TM[%d] - Task Management Response UPIU\n",
-                               tag);
-               ufshcd_hex_dump("TM RSP: ", tmrdp->task_rsp_upiu,
-                               sizeof(struct utp_task_req_desc));
+               ufshcd_hex_dump("", tmrdp, sizeof(*tmrdp));
        }
 }
 
@@ -645,19 +634,6 @@ static inline int ufshcd_get_tr_ocs(struct ufshcd_lrb *lrbp)
        return le32_to_cpu(lrbp->utr_descriptor_ptr->header.dword_2) & MASK_OCS;
 }
 
-/**
- * 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
@@ -1691,8 +1667,9 @@ static void __ufshcd_release(struct ufs_hba *hba)
 
        hba->clk_gating.state = REQ_CLKS_OFF;
        trace_ufshcd_clk_gating(dev_name(hba->dev), hba->clk_gating.state);
-       schedule_delayed_work(&hba->clk_gating.gate_work,
-                       msecs_to_jiffies(hba->clk_gating.delay_ms));
+       queue_delayed_work(hba->clk_gating.clk_gating_workq,
+                          &hba->clk_gating.gate_work,
+                          msecs_to_jiffies(hba->clk_gating.delay_ms));
 }
 
 void ufshcd_release(struct ufs_hba *hba)
@@ -1763,6 +1740,34 @@ out:
        return count;
 }
 
+static void ufshcd_init_clk_scaling(struct ufs_hba *hba)
+{
+       char wq_name[sizeof("ufs_clkscaling_00")];
+
+       if (!ufshcd_is_clkscaling_supported(hba))
+               return;
+
+       INIT_WORK(&hba->clk_scaling.suspend_work,
+                 ufshcd_clk_scaling_suspend_work);
+       INIT_WORK(&hba->clk_scaling.resume_work,
+                 ufshcd_clk_scaling_resume_work);
+
+       snprintf(wq_name, sizeof(wq_name), "ufs_clkscaling_%d",
+                hba->host->host_no);
+       hba->clk_scaling.workq = create_singlethread_workqueue(wq_name);
+
+       ufshcd_clkscaling_init_sysfs(hba);
+}
+
+static void ufshcd_exit_clk_scaling(struct ufs_hba *hba)
+{
+       if (!ufshcd_is_clkscaling_supported(hba))
+               return;
+
+       destroy_workqueue(hba->clk_scaling.workq);
+       ufshcd_devfreq_remove(hba);
+}
+
 static void ufshcd_init_clk_gating(struct ufs_hba *hba)
 {
        char wq_name[sizeof("ufs_clk_gating_00")];
@@ -2055,8 +2060,7 @@ __ufshcd_send_uic_cmd(struct ufs_hba *hba, struct uic_command *uic_cmd,
  *
  * Returns 0 only if success.
  */
-static int
-ufshcd_send_uic_cmd(struct ufs_hba *hba, struct uic_command *uic_cmd)
+int ufshcd_send_uic_cmd(struct ufs_hba *hba, struct uic_command *uic_cmd)
 {
        int ret;
        unsigned long flags;
@@ -2238,8 +2242,8 @@ void ufshcd_prepare_utp_scsi_cmd_upiu(struct ufshcd_lrb *lrbp, u32 upiu_flags)
        ucd_req_ptr->sc.exp_data_transfer_len =
                cpu_to_be32(lrbp->cmd->sdb.length);
 
-       cdb_len = min_t(unsigned short, lrbp->cmd->cmd_len, MAX_CDB_SIZE);
-       memset(ucd_req_ptr->sc.cdb, 0, MAX_CDB_SIZE);
+       cdb_len = min_t(unsigned short, lrbp->cmd->cmd_len, UFS_CDB_SIZE);
+       memset(ucd_req_ptr->sc.cdb, 0, UFS_CDB_SIZE);
        memcpy(ucd_req_ptr->sc.cdb, lrbp->cmd->cmnd, cdb_len);
 
        memset(lrbp->ucd_rsp_ptr, 0, sizeof(struct utp_upiu_rsp));
@@ -2258,7 +2262,6 @@ static void ufshcd_prepare_utp_query_req_upiu(struct ufs_hba *hba,
        struct utp_upiu_req *ucd_req_ptr = lrbp->ucd_req_ptr;
        struct ufs_query *query = &hba->dev_cmd.query;
        u16 len = be16_to_cpu(query->request.upiu_req.length);
-       u8 *descp = (u8 *)lrbp->ucd_req_ptr + GENERAL_UPIU_REQUEST_SIZE;
 
        /* Query request header */
        ucd_req_ptr->header.dword_0 = UPIU_HEADER_DWORD(
@@ -2280,7 +2283,7 @@ static void ufshcd_prepare_utp_query_req_upiu(struct ufs_hba *hba,
 
        /* Copy the Descriptor */
        if (query->request.upiu_req.opcode == UPIU_QUERY_OPCODE_WRITE_DESC)
-               memcpy(descp, query->descriptor, len);
+               memcpy(ucd_req_ptr + 1, query->descriptor, len);
 
        memset(lrbp->ucd_rsp_ptr, 0, sizeof(struct utp_upiu_rsp));
 }
@@ -4600,46 +4603,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 *task_req_descp;
-       struct utp_upiu_task_rsp *task_rsp_upiup;
-       unsigned long flags;
-       int ocs_value;
-       int task_result;
-
-       spin_lock_irqsave(hba->host->host_lock, flags);
-
-       /* Clear completed tasks from outstanding_tasks */
-       __clear_bit(index, &hba->outstanding_tasks);
-
-       task_req_descp = hba->utmrdl_base_addr;
-       ocs_value = ufshcd_get_tmr_ocs(&task_req_descp[index]);
-
-       if (ocs_value == OCS_SUCCESS) {
-               task_rsp_upiup = (struct utp_upiu_task_rsp *)
-                               task_req_descp[index].task_rsp_upiu;
-               task_result = be32_to_cpu(task_rsp_upiup->output_param1);
-               task_result = task_result & MASK_TM_SERVICE_RESP;
-               if (resp)
-                       *resp = (u8)task_result;
-       } else {
-               dev_err(hba->dev, "%s: failed, ocs = 0x%x\n",
-                               __func__, ocs_value);
-       }
-       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
@@ -5597,28 +5560,12 @@ out:
        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 *task_req_descp;
-       struct utp_upiu_task_req *task_req_upiup;
-       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.
@@ -5629,30 +5576,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);
-       task_req_descp = hba->utmrdl_base_addr;
-       task_req_descp += free_slot;
-
-       /* Configure task request descriptor */
-       task_req_descp->header.dword_0 = cpu_to_le32(UTP_REQ_DESC_INT_CMD);
-       task_req_descp->header.dword_2 =
-                       cpu_to_le32(OCS_INVALID_COMMAND_STATUS);
-
-       /* Configure task request UPIU */
-       task_req_upiup =
-               (struct utp_upiu_task_req *) task_req_descp->task_req_upiu;
        task_tag = hba->nutrs + free_slot;
-       task_req_upiup->header.dword_0 =
-               UPIU_HEADER_DWORD(UPIU_TRANSACTION_TASK_REQ, 0,
-                                             lun_id, task_tag);
-       task_req_upiup->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.
-        */
-       task_req_upiup->input_param1 = cpu_to_be32(lun_id);
-       task_req_upiup->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 */
@@ -5682,8 +5610,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);
@@ -5694,6 +5629,228 @@ static int ufshcd_issue_tm_cmd(struct ufs_hba *hba, int lun_id, int task_id,
        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)
+{
+       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_issue_devman_upiu_cmd - API for sending "utrd" type requests
+ * @hba:       per-adapter instance
+ * @req_upiu:  upiu request
+ * @rsp_upiu:  upiu reply
+ * @msgcode:   message code, one of UPIU Transaction Codes Initiator to Target
+ * @desc_buff: pointer to descriptor buffer, NULL if NA
+ * @buff_len:  descriptor size, 0 if NA
+ * @desc_op:   descriptor operation
+ *
+ * Those type of requests uses UTP Transfer Request Descriptor - utrd.
+ * Therefore, it "rides" the device management infrastructure: uses its tag and
+ * tasks work queues.
+ *
+ * Since there is only one available tag for device management commands,
+ * the caller is expected to hold the hba->dev_cmd.lock mutex.
+ */
+static int ufshcd_issue_devman_upiu_cmd(struct ufs_hba *hba,
+                                       struct utp_upiu_req *req_upiu,
+                                       struct utp_upiu_req *rsp_upiu,
+                                       u8 *desc_buff, int *buff_len,
+                                       int cmd_type,
+                                       enum query_opcode desc_op)
+{
+       struct ufshcd_lrb *lrbp;
+       int err = 0;
+       int tag;
+       struct completion wait;
+       unsigned long flags;
+       u32 upiu_flags;
+
+       down_read(&hba->clk_scaling_lock);
+
+       wait_event(hba->dev_cmd.tag_wq, ufshcd_get_dev_cmd_tag(hba, &tag));
+
+       init_completion(&wait);
+       lrbp = &hba->lrb[tag];
+       WARN_ON(lrbp->cmd);
+
+       lrbp->cmd = NULL;
+       lrbp->sense_bufflen = 0;
+       lrbp->sense_buffer = NULL;
+       lrbp->task_tag = tag;
+       lrbp->lun = 0;
+       lrbp->intr_cmd = true;
+       hba->dev_cmd.type = cmd_type;
+
+       switch (hba->ufs_version) {
+       case UFSHCI_VERSION_10:
+       case UFSHCI_VERSION_11:
+               lrbp->command_type = UTP_CMD_TYPE_DEV_MANAGE;
+               break;
+       default:
+               lrbp->command_type = UTP_CMD_TYPE_UFS_STORAGE;
+               break;
+       }
+
+       /* update the task tag in the request upiu */
+       req_upiu->header.dword_0 |= cpu_to_be32(tag);
+
+       ufshcd_prepare_req_desc_hdr(lrbp, &upiu_flags, DMA_NONE);
+
+       /* just copy the upiu request as it is */
+       memcpy(lrbp->ucd_req_ptr, req_upiu, sizeof(*lrbp->ucd_req_ptr));
+       if (desc_buff && desc_op == UPIU_QUERY_OPCODE_WRITE_DESC) {
+               /* The Data Segment Area is optional depending upon the query
+                * function value. for WRITE DESCRIPTOR, the data segment
+                * follows right after the tsf.
+                */
+               memcpy(lrbp->ucd_req_ptr + 1, desc_buff, *buff_len);
+               *buff_len = 0;
+       }
+
+       memset(lrbp->ucd_rsp_ptr, 0, sizeof(struct utp_upiu_rsp));
+
+       hba->dev_cmd.complete = &wait;
+
+       /* Make sure descriptors are ready before ringing the doorbell */
+       wmb();
+       spin_lock_irqsave(hba->host->host_lock, flags);
+       ufshcd_send_command(hba, tag);
+       spin_unlock_irqrestore(hba->host->host_lock, flags);
+
+       /*
+        * ignore the returning value here - ufshcd_check_query_response is
+        * bound to fail since dev_cmd.query and dev_cmd.type were left empty.
+        * read the response directly ignoring all errors.
+        */
+       ufshcd_wait_for_dev_cmd(hba, lrbp, QUERY_REQ_TIMEOUT);
+
+       /* just copy the upiu response as it is */
+       memcpy(rsp_upiu, lrbp->ucd_rsp_ptr, sizeof(*rsp_upiu));
+
+       ufshcd_put_dev_cmd_tag(hba, tag);
+       wake_up(&hba->dev_cmd.tag_wq);
+       up_read(&hba->clk_scaling_lock);
+       return err;
+}
+
+/**
+ * ufshcd_exec_raw_upiu_cmd - API function for sending raw upiu commands
+ * @hba:       per-adapter instance
+ * @req_upiu:  upiu request
+ * @rsp_upiu:  upiu reply - only 8 DW as we do not support scsi commands
+ * @msgcode:   message code, one of UPIU Transaction Codes Initiator to Target
+ * @desc_buff: pointer to descriptor buffer, NULL if NA
+ * @buff_len:  descriptor size, 0 if NA
+ * @desc_op:   descriptor operation
+ *
+ * Supports UTP Transfer requests (nop and query), and UTP Task
+ * Management requests.
+ * It is up to the caller to fill the upiu conent properly, as it will
+ * be copied without any further input validations.
+ */
+int ufshcd_exec_raw_upiu_cmd(struct ufs_hba *hba,
+                            struct utp_upiu_req *req_upiu,
+                            struct utp_upiu_req *rsp_upiu,
+                            int msgcode,
+                            u8 *desc_buff, int *buff_len,
+                            enum query_opcode desc_op)
+{
+       int err;
+       int cmd_type = DEV_CMD_TYPE_QUERY;
+       struct utp_task_req_desc treq = { { 0 }, };
+       int ocs_value;
+       u8 tm_f = be32_to_cpu(req_upiu->header.dword_1) >> 16 & MASK_TM_FUNC;
+
+       if (desc_buff && desc_op != UPIU_QUERY_OPCODE_WRITE_DESC) {
+               err = -ENOTSUPP;
+               goto out;
+       }
+
+       switch (msgcode) {
+       case UPIU_TRANSACTION_NOP_OUT:
+               cmd_type = DEV_CMD_TYPE_NOP;
+               /* fall through */
+       case UPIU_TRANSACTION_QUERY_REQ:
+               ufshcd_hold(hba, false);
+               mutex_lock(&hba->dev_cmd.lock);
+               err = ufshcd_issue_devman_upiu_cmd(hba, req_upiu, rsp_upiu,
+                                                  desc_buff, buff_len,
+                                                  cmd_type, desc_op);
+               mutex_unlock(&hba->dev_cmd.lock);
+               ufshcd_release(hba);
+
+               break;
+       case UPIU_TRANSACTION_TASK_REQ:
+               treq.header.dword_0 = cpu_to_le32(UTP_REQ_DESC_INT_CMD);
+               treq.header.dword_2 = cpu_to_le32(OCS_INVALID_COMMAND_STATUS);
+
+               memcpy(&treq.req_header, req_upiu, sizeof(*req_upiu));
+
+               err = __ufshcd_issue_tm_cmd(hba, &treq, tm_f);
+               if (err == -ETIMEDOUT)
+                       break;
+
+               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);
+                       break;
+               }
+
+               memcpy(rsp_upiu, &treq.rsp_header, sizeof(*rsp_upiu));
+
+               break;
+       default:
+               err = -EINVAL;
+
+               break;
+       }
+
+out:
+       return err;
+}
+
 /**
  * ufshcd_eh_device_reset_handler - device reset handler registered to
  *                                    scsi layer.
@@ -6652,6 +6809,8 @@ static int ufshcd_probe_hba(struct ufs_hba *hba)
                        hba->clk_scaling.is_allowed = true;
                }
 
+               ufs_bsg_probe(hba);
+
                scsi_scan_host(hba->host);
                pm_runtime_put_sync(hba->dev);
        }
@@ -6666,6 +6825,7 @@ out:
         */
        if (ret && !ufshcd_eh_in_progress(hba) && !hba->pm_op_in_progress) {
                pm_runtime_put_sync(hba->dev);
+               ufshcd_exit_clk_scaling(hba);
                ufshcd_hba_exit(hba);
        }
 
@@ -7201,12 +7361,9 @@ static void ufshcd_hba_exit(struct ufs_hba *hba)
                ufshcd_variant_hba_exit(hba);
                ufshcd_setup_vreg(hba, false);
                ufshcd_suspend_clkscaling(hba);
-               if (ufshcd_is_clkscaling_supported(hba)) {
+               if (ufshcd_is_clkscaling_supported(hba))
                        if (hba->devfreq)
                                ufshcd_suspend_clkscaling(hba);
-                       destroy_workqueue(hba->clk_scaling.workq);
-                       ufshcd_devfreq_remove(hba);
-               }
                ufshcd_setup_clocks(hba, false);
                ufshcd_setup_hba_vreg(hba, false);
                hba->is_powered = false;
@@ -7875,12 +8032,14 @@ EXPORT_SYMBOL(ufshcd_shutdown);
  */
 void ufshcd_remove(struct ufs_hba *hba)
 {
+       ufs_bsg_remove(hba);
        ufs_sysfs_remove_nodes(hba->dev);
        scsi_remove_host(hba->host);
        /* disable interrupts */
        ufshcd_disable_intr(hba, hba->intr_mask);
        ufshcd_hba_stop(hba, true);
 
+       ufshcd_exit_clk_scaling(hba);
        ufshcd_exit_clk_gating(hba);
        if (ufshcd_is_clkscaling_supported(hba))
                device_remove_file(hba->dev, &hba->clk_scaling.enable_attr);
@@ -8027,7 +8186,7 @@ int ufshcd_init(struct ufs_hba *hba, void __iomem *mmio_base, unsigned int irq)
        host->max_lun = UFS_MAX_LUNS;
        host->max_channel = UFSHCD_MAX_CHANNEL;
        host->unique_id = host->host_no;
-       host->max_cmd_len = MAX_CDB_SIZE;
+       host->max_cmd_len = UFS_CDB_SIZE;
 
        hba->max_pwr_info.is_valid = false;
 
@@ -8052,6 +8211,8 @@ int ufshcd_init(struct ufs_hba *hba, void __iomem *mmio_base, unsigned int irq)
 
        ufshcd_init_clk_gating(hba);
 
+       ufshcd_init_clk_scaling(hba);
+
        /*
         * In order to avoid any spurious interrupt immediately after
         * registering UFS controller interrupt handler, clear any pending UFS
@@ -8090,21 +8251,6 @@ int ufshcd_init(struct ufs_hba *hba, void __iomem *mmio_base, unsigned int irq)
                goto out_remove_scsi_host;
        }
 
-       if (ufshcd_is_clkscaling_supported(hba)) {
-               char wq_name[sizeof("ufs_clkscaling_00")];
-
-               INIT_WORK(&hba->clk_scaling.suspend_work,
-                         ufshcd_clk_scaling_suspend_work);
-               INIT_WORK(&hba->clk_scaling.resume_work,
-                         ufshcd_clk_scaling_resume_work);
-
-               snprintf(wq_name, sizeof(wq_name), "ufs_clkscaling_%d",
-                        host->host_no);
-               hba->clk_scaling.workq = create_singlethread_workqueue(wq_name);
-
-               ufshcd_clkscaling_init_sysfs(hba);
-       }
-
        /*
         * Set the default power management level for runtime and system PM.
         * Default power saving mode is to keep UFS link in Hibern8 state
@@ -8142,6 +8288,7 @@ int ufshcd_init(struct ufs_hba *hba, void __iomem *mmio_base, unsigned int irq)
 out_remove_scsi_host:
        scsi_remove_host(hba->host);
 exit_gating:
+       ufshcd_exit_clk_scaling(hba);
        ufshcd_exit_clk_gating(hba);
 out_disable:
        hba->is_irq_enabled = false;