[PATCH 04/10] scsi: ufs: rework link start-up process

2013-06-26 Thread Santosh Y
From: Seungwon Jeon tgih@samsung.com

Link start-up requires long time with multiphase handshakes
between UFS host and device. This affects driver's probe time.
This patch let link start-up run asynchronously. Link start-up
will be executed at the end of prove separately.
Along with this change, the following is worked.

Defined completion time of uic command to avoid a permanent wait.
Added mutex to guarantee of uic command at a time.
Adapted some sequence of controller initialization after link statup
according to HCI standard.

Signed-off-by: Seungwon Jeon tgih@samsung.com
Signed-off-by: Sujit Reddy Thumma sthu...@codeaurora.org
Tested-by: Maya Erez me...@codeaurora.org
Signed-off-by: Santosh Y santos...@gmail.com

diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index 2e02483..48a7645 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -33,11 +33,15 @@
  * this program.
  */
 
+#include linux/async.h
+
 #include ufshcd.h
 
 #define UFSHCD_ENABLE_INTRS(UTP_TRANSFER_REQ_COMPL |\
 UTP_TASK_REQ_COMPL |\
 UFSHCD_ERROR_MASK)
+/* UIC command timeout, unit: ms */
+#define UIC_CMD_TIMEOUT500
 
 enum {
UFSHCD_MAX_CHANNEL  = 0,
@@ -349,24 +353,122 @@ static inline void ufshcd_hba_capabilities(struct 
ufs_hba *hba)
 }
 
 /**
- * ufshcd_send_uic_command - Send UIC commands to unipro layers
+ * ufshcd_ready_for_uic_cmd - Check if controller is ready
+ *to accept UIC commands
  * @hba: per adapter instance
- * @uic_command: UIC command
+ * Return true on success, else false
+ */
+static inline bool ufshcd_ready_for_uic_cmd(struct ufs_hba *hba)
+{
+   if (ufshcd_readl(hba, REG_CONTROLLER_STATUS)  UIC_COMMAND_READY)
+   return true;
+   else
+   return false;
+}
+
+/**
+ * ufshcd_dispatch_uic_cmd - Dispatch UIC commands to unipro layers
+ * @hba: per adapter instance
+ * @uic_cmd: UIC command
+ *
+ * Mutex must be held.
  */
 static inline void
-ufshcd_send_uic_command(struct ufs_hba *hba, struct uic_command *uic_cmnd)
+ufshcd_dispatch_uic_cmd(struct ufs_hba *hba, struct uic_command *uic_cmd)
 {
+   WARN_ON(hba-active_uic_cmd);
+
+   hba-active_uic_cmd = uic_cmd;
+
/* Write Args */
-   ufshcd_writel(hba, uic_cmnd-argument1, REG_UIC_COMMAND_ARG_1);
-   ufshcd_writel(hba, uic_cmnd-argument2, REG_UIC_COMMAND_ARG_2);
-   ufshcd_writel(hba, uic_cmnd-argument3, REG_UIC_COMMAND_ARG_3);
+   ufshcd_writel(hba, uic_cmd-argument1, REG_UIC_COMMAND_ARG_1);
+   ufshcd_writel(hba, uic_cmd-argument2, REG_UIC_COMMAND_ARG_2);
+   ufshcd_writel(hba, uic_cmd-argument3, REG_UIC_COMMAND_ARG_3);
 
/* Write UIC Cmd */
-   ufshcd_writel(hba, uic_cmnd-command  COMMAND_OPCODE_MASK,
+   ufshcd_writel(hba, uic_cmd-command  COMMAND_OPCODE_MASK,
  REG_UIC_COMMAND);
 }
 
 /**
+ * ufshcd_wait_for_uic_cmd - Wait complectioin of UIC command
+ * @hba: per adapter instance
+ * @uic_command: UIC command
+ *
+ * Must be called with mutex held.
+ * Returns 0 only if success.
+ */
+static int
+ufshcd_wait_for_uic_cmd(struct ufs_hba *hba, struct uic_command *uic_cmd)
+{
+   int ret;
+   unsigned long flags;
+
+   if (wait_for_completion_timeout(uic_cmd-done,
+   msecs_to_jiffies(UIC_CMD_TIMEOUT)))
+   ret = uic_cmd-argument2  MASK_UIC_COMMAND_RESULT;
+   else
+   ret = -ETIMEDOUT;
+
+   spin_lock_irqsave(hba-host-host_lock, flags);
+   hba-active_uic_cmd = NULL;
+   spin_unlock_irqrestore(hba-host-host_lock, flags);
+
+   return ret;
+}
+
+/**
+ * __ufshcd_send_uic_cmd - Send UIC commands and retrieve the result
+ * @hba: per adapter instance
+ * @uic_cmd: UIC command
+ *
+ * Identical to ufshcd_send_uic_cmd() expect mutex. Must be called
+ * with mutex held.
+ * Returns 0 only if success.
+ */
+static int
+__ufshcd_send_uic_cmd(struct ufs_hba *hba, struct uic_command *uic_cmd)
+{
+   int ret;
+   unsigned long flags;
+
+   if (!ufshcd_ready_for_uic_cmd(hba)) {
+   dev_err(hba-dev,
+   Controller not ready to accept UIC commands\n);
+   return -EIO;
+   }
+
+   init_completion(uic_cmd-done);
+
+   spin_lock_irqsave(hba-host-host_lock, flags);
+   ufshcd_dispatch_uic_cmd(hba, uic_cmd);
+   spin_unlock_irqrestore(hba-host-host_lock, flags);
+
+   ret = ufshcd_wait_for_uic_cmd(hba, uic_cmd);
+
+   return ret;
+}
+
+/**
+ * ufshcd_send_uic_cmd - Send UIC commands and retrieve the result
+ * @hba: per adapter instance
+ * @uic_cmd: UIC command
+ *
+ * Returns 0 only if success.
+ */
+static int
+ufshcd_send_uic_cmd(struct ufs_hba *hba, struct uic_command *uic_cmd)
+{
+   int ret;
+
+   mutex_lock(hba-uic_cmd_mutex);
+   ret = __ufshcd_send_uic_cmd(hba, uic_cmd);
+   mutex_unlock(hba-uic_cmd_mutex);
+
+   

[PATCH 04/10] scsi: ufs: rework link start-up process

2013-06-26 Thread Santosh Y
From: Seungwon Jeon tgih@samsung.com

Link start-up requires long time with multiphase handshakes
between UFS host and device. This affects driver's probe time.
This patch let link start-up run asynchronously. Link start-up
will be executed at the end of prove separately.
Along with this change, the following is worked.

Defined completion time of uic command to avoid a permanent wait.
Added mutex to guarantee of uic command at a time.
Adapted some sequence of controller initialization after link statup
according to HCI standard.

Signed-off-by: Seungwon Jeon tgih@samsung.com
Signed-off-by: Sujit Reddy Thumma sthu...@codeaurora.org
Tested-by: Maya Erez me...@codeaurora.org
Signed-off-by: Santosh Y santos...@gmail.com

diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index 2e02483..48a7645 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -33,11 +33,15 @@
  * this program.
  */
 
+#include linux/async.h
+
 #include ufshcd.h
 
 #define UFSHCD_ENABLE_INTRS(UTP_TRANSFER_REQ_COMPL |\
 UTP_TASK_REQ_COMPL |\
 UFSHCD_ERROR_MASK)
+/* UIC command timeout, unit: ms */
+#define UIC_CMD_TIMEOUT500
 
 enum {
UFSHCD_MAX_CHANNEL  = 0,
@@ -349,24 +353,122 @@ static inline void ufshcd_hba_capabilities(struct 
ufs_hba *hba)
 }
 
 /**
- * ufshcd_send_uic_command - Send UIC commands to unipro layers
+ * ufshcd_ready_for_uic_cmd - Check if controller is ready
+ *to accept UIC commands
  * @hba: per adapter instance
- * @uic_command: UIC command
+ * Return true on success, else false
+ */
+static inline bool ufshcd_ready_for_uic_cmd(struct ufs_hba *hba)
+{
+   if (ufshcd_readl(hba, REG_CONTROLLER_STATUS)  UIC_COMMAND_READY)
+   return true;
+   else
+   return false;
+}
+
+/**
+ * ufshcd_dispatch_uic_cmd - Dispatch UIC commands to unipro layers
+ * @hba: per adapter instance
+ * @uic_cmd: UIC command
+ *
+ * Mutex must be held.
  */
 static inline void
-ufshcd_send_uic_command(struct ufs_hba *hba, struct uic_command *uic_cmnd)
+ufshcd_dispatch_uic_cmd(struct ufs_hba *hba, struct uic_command *uic_cmd)
 {
+   WARN_ON(hba-active_uic_cmd);
+
+   hba-active_uic_cmd = uic_cmd;
+
/* Write Args */
-   ufshcd_writel(hba, uic_cmnd-argument1, REG_UIC_COMMAND_ARG_1);
-   ufshcd_writel(hba, uic_cmnd-argument2, REG_UIC_COMMAND_ARG_2);
-   ufshcd_writel(hba, uic_cmnd-argument3, REG_UIC_COMMAND_ARG_3);
+   ufshcd_writel(hba, uic_cmd-argument1, REG_UIC_COMMAND_ARG_1);
+   ufshcd_writel(hba, uic_cmd-argument2, REG_UIC_COMMAND_ARG_2);
+   ufshcd_writel(hba, uic_cmd-argument3, REG_UIC_COMMAND_ARG_3);
 
/* Write UIC Cmd */
-   ufshcd_writel(hba, uic_cmnd-command  COMMAND_OPCODE_MASK,
+   ufshcd_writel(hba, uic_cmd-command  COMMAND_OPCODE_MASK,
  REG_UIC_COMMAND);
 }
 
 /**
+ * ufshcd_wait_for_uic_cmd - Wait complectioin of UIC command
+ * @hba: per adapter instance
+ * @uic_command: UIC command
+ *
+ * Must be called with mutex held.
+ * Returns 0 only if success.
+ */
+static int
+ufshcd_wait_for_uic_cmd(struct ufs_hba *hba, struct uic_command *uic_cmd)
+{
+   int ret;
+   unsigned long flags;
+
+   if (wait_for_completion_timeout(uic_cmd-done,
+   msecs_to_jiffies(UIC_CMD_TIMEOUT)))
+   ret = uic_cmd-argument2  MASK_UIC_COMMAND_RESULT;
+   else
+   ret = -ETIMEDOUT;
+
+   spin_lock_irqsave(hba-host-host_lock, flags);
+   hba-active_uic_cmd = NULL;
+   spin_unlock_irqrestore(hba-host-host_lock, flags);
+
+   return ret;
+}
+
+/**
+ * __ufshcd_send_uic_cmd - Send UIC commands and retrieve the result
+ * @hba: per adapter instance
+ * @uic_cmd: UIC command
+ *
+ * Identical to ufshcd_send_uic_cmd() expect mutex. Must be called
+ * with mutex held.
+ * Returns 0 only if success.
+ */
+static int
+__ufshcd_send_uic_cmd(struct ufs_hba *hba, struct uic_command *uic_cmd)
+{
+   int ret;
+   unsigned long flags;
+
+   if (!ufshcd_ready_for_uic_cmd(hba)) {
+   dev_err(hba-dev,
+   Controller not ready to accept UIC commands\n);
+   return -EIO;
+   }
+
+   init_completion(uic_cmd-done);
+
+   spin_lock_irqsave(hba-host-host_lock, flags);
+   ufshcd_dispatch_uic_cmd(hba, uic_cmd);
+   spin_unlock_irqrestore(hba-host-host_lock, flags);
+
+   ret = ufshcd_wait_for_uic_cmd(hba, uic_cmd);
+
+   return ret;
+}
+
+/**
+ * ufshcd_send_uic_cmd - Send UIC commands and retrieve the result
+ * @hba: per adapter instance
+ * @uic_cmd: UIC command
+ *
+ * Returns 0 only if success.
+ */
+static int
+ufshcd_send_uic_cmd(struct ufs_hba *hba, struct uic_command *uic_cmd)
+{
+   int ret;
+
+   mutex_lock(hba-uic_cmd_mutex);
+   ret = __ufshcd_send_uic_cmd(hba, uic_cmd);
+   mutex_unlock(hba-uic_cmd_mutex);
+
+