Re: [PATCH v2 4/5] [SCSI] ufshcd: SCSI error handling

2012-02-26 Thread Santosh Y
On Sun, Feb 26, 2012 at 10:16 AM, Hillf Danton dhi...@gmail.com wrote:
 On Fri, Feb 24, 2012 at 3:19 PM, Santosh Y santos...@gmail.com wrote:
 +/**
 + * ufshcd_is_tmq_full - checks if the task management slots are full
 + * @hba: per adapter instance
 + *
 + * Returns maximum number of task management request slots in case of
 + * task management queue full or returns the free slot number
 + */
 +static inline int ufshcd_is_tmq_full(struct ufs_hba *hba)

 This helper function is named to be misleading, little to do with
 its functionality as full is checked at callsite.

ok, thanks, I'll change it.


 -hd

 +{
 +       return find_first_zero_bit(hba-outstanding_tasks, hba-nutmrs);
 +}
 +
 [...]
 +       host = hba-host;
 +
 +       spin_lock_irqsave(host-host_lock, flags);
 +
 +       /* If task management queue is full */
 +       free_slot = ufshcd_is_tmq_full(hba);
 +       if (free_slot = hba-nutmrs) {
 +               spin_unlock_irqrestore(host-host_lock, flags);
 +               dev_err(hba-pdev-dev, Task management queue full\n);
 +               err = FAILED;
 +               goto out;
 +       }

-- 
~Santosh
--
To unsubscribe from this list: send the line unsubscribe linux-samsung-soc in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v2 4/5] [SCSI] ufshcd: SCSI error handling

2012-02-25 Thread Hillf Danton
On Fri, Feb 24, 2012 at 3:19 PM, Santosh Y santos...@gmail.com wrote:
 +/**
 + * ufshcd_is_tmq_full - checks if the task management slots are full
 + * @hba: per adapter instance
 + *
 + * Returns maximum number of task management request slots in case of
 + * task management queue full or returns the free slot number
 + */
 +static inline int ufshcd_is_tmq_full(struct ufs_hba *hba)

This helper function is named to be misleading, little to do with
its functionality as full is checked at callsite.

-hd

 +{
 +       return find_first_zero_bit(hba-outstanding_tasks, hba-nutmrs);
 +}
 +
[...]
 +       host = hba-host;
 +
 +       spin_lock_irqsave(host-host_lock, flags);
 +
 +       /* If task management queue is full */
 +       free_slot = ufshcd_is_tmq_full(hba);
 +       if (free_slot = hba-nutmrs) {
 +               spin_unlock_irqrestore(host-host_lock, flags);
 +               dev_err(hba-pdev-dev, Task management queue full\n);
 +               err = FAILED;
 +               goto out;
 +       }
--
To unsubscribe from this list: send the line unsubscribe linux-samsung-soc in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v2 4/5] [SCSI] ufshcd: SCSI error handling

2012-02-23 Thread Santosh Y
From: Santosh Yaraganavi santos...@gmail.com

UFSHCD SCSI error handling includes following implementations,
 - Abort task
 - Device reset
 - Host reset

Signed-off-by: Santosh Yaraganavi santos...@gmail.com
Signed-off-by: Vinayak Holikatti vinholika...@gmail.com
Reviewed-by: Arnd Bergmann a...@linaro.org
Reviewed-by: Vishak G visha...@samsung.com
Reviewed-by: Girish K S girish.shivananja...@linaro.org
---
v1 - v2:
- Change task management function return value to SUCCESS/FAILED,
  SCSI midlayer expects SUCCESS/FAILED return value for
  error handling routines.
  Ex: .eh_host_reset_handler, eh_abort_handler...
- ufshcd_tmc_handler(): use wake_up_interruptible() outside for loop
  to wake up all the waiting threads at once.
  Change hba-tm_condition[] to hba-tm_condition bitmask.
- ufshcd_abort(): add missing spin_unlock_irqrestore().

 drivers/scsi/ufs/ufshcd.c |  298 -
 1 files changed, 297 insertions(+), 1 deletions(-)

diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index 1c6a9ed..856dbc1 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -65,6 +65,7 @@
 #include scsi/scsi_host.h
 #include scsi/scsi_tcq.h
 #include scsi/scsi_dbg.h
+#include scsi/scsi_eh.h
 
 #include ufs.h
 #include ufshci.h
@@ -131,11 +132,14 @@ struct uic_command {
  * @host: Scsi_Host instance of the driver
  * @pdev: PCI device handle
  * @lrb: local reference block
+ * @outstanding_tasks: Bits representing outstanding task requests
  * @outstanding_reqs: Bits representing outstanding transfer requests
  * @capabilities: UFS Controller Capabilities
  * @nutrs: Transfer Request Queue depth supported by controller
  * @nutmrs: Task Management Queue depth supported by controller
  * @active_uic_cmd: handle of active UIC command
+ * @ufshcd_tm_wait_queue: wait queue for task management
+ * @tm_condition: condition variable for task management
  * @ufshcd_state: UFSHCD states
  * @int_enable_mask: Interrupt Mask Bits
  * @uic_workq: Work queue for UIC completion handling
@@ -160,6 +164,7 @@ struct ufs_hba {
 
struct ufshcd_lrb *lrb;
 
+   unsigned long outstanding_tasks;
unsigned long outstanding_reqs;
 
u32 capabilities;
@@ -168,6 +173,8 @@ struct ufs_hba {
u32 ufs_version;
 
struct uic_command active_uic_cmd;
+   wait_queue_head_t ufshcd_tm_wait_queue;
+   unsigned long tm_condition;
 
u32 ufshcd_state;
u32 int_enable_mask;
@@ -246,6 +253,42 @@ 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 task_req_descp-header.dword_2  MASK_OCS;
+}
+
+/**
+ * ufshcd_is_tmq_full - checks if the task management slots are full
+ * @hba: per adapter instance
+ *
+ * Returns maximum number of task management request slots in case of
+ * task management queue full or returns the free slot number
+ */
+static inline int ufshcd_is_tmq_full(struct ufs_hba *hba)
+{
+   return find_first_zero_bit(hba-outstanding_tasks, hba-nutmrs);
+}
+
+/**
+ * ufshcd_utrl_clear - Clear a bit in UTRLCLR register
+ * @hba: per adapter instance
+ * @pos: position of the bit to be cleared
+ */
+static inline void ufshcd_utrl_clear(struct ufs_hba *hba, u32 pos)
+{
+   writel(~(1  pos),
+   (hba-mmio_base + REG_UTP_TRANSFER_REQ_LIST_CLEAR));
+}
+
+/**
  * ufshcd_get_lists_status - Check UCRDY, UTRLRDY and UTMRLRDY
  * @reg: Register value of host controller status
  *
@@ -1038,8 +1081,9 @@ static int ufshcd_do_reset(struct ufs_hba *hba)
}
}
 
-   /* clear outstanding request bit maps */
+   /* clear outstanding request/task bit maps */
hba-outstanding_reqs = 0;
+   hba-outstanding_tasks = 0;
 
/* start the initialization process */
if (ufshcd_initialize_hba(hba)) {
@@ -1091,6 +1135,47 @@ 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
+ *
+ * Returns SUCCESS/FAILED
+ */
+static int ufshcd_task_req_compl(struct ufs_hba *hba, u32 index)
+{
+   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 =