scsi: ufs: Optimize serialization of setup_xfer_req() calls
[linux-2.6-block.git] / drivers / scsi / ufs / ufshcd.h
index c98d540ac044d06081673dc3c90cc0a10d14555c..38a09ab52f534a68ca674ea58b5a1b815bde2589 100644 (file)
@@ -476,6 +476,27 @@ struct ufs_stats {
        struct ufs_event_hist event[UFS_EVT_CNT];
 };
 
+/**
+ * enum ufshcd_state - UFS host controller state
+ * @UFSHCD_STATE_RESET: Link is not operational. Postpone SCSI command
+ *     processing.
+ * @UFSHCD_STATE_OPERATIONAL: The host controller is operational and can process
+ *     SCSI commands.
+ * @UFSHCD_STATE_EH_SCHEDULED_NON_FATAL: The error handler has been scheduled.
+ *     SCSI commands may be submitted to the controller.
+ * @UFSHCD_STATE_EH_SCHEDULED_FATAL: The error handler has been scheduled. Fail
+ *     newly submitted SCSI commands with error code DID_BAD_TARGET.
+ * @UFSHCD_STATE_ERROR: An unrecoverable error occurred, e.g. link recovery
+ *     failed. Fail all SCSI commands with error code DID_ERROR.
+ */
+enum ufshcd_state {
+       UFSHCD_STATE_RESET,
+       UFSHCD_STATE_OPERATIONAL,
+       UFSHCD_STATE_EH_SCHEDULED_NON_FATAL,
+       UFSHCD_STATE_EH_SCHEDULED_FATAL,
+       UFSHCD_STATE_ERROR,
+};
+
 enum ufshcd_quirks {
        /* Interrupt aggregation support is broken */
        UFSHCD_QUIRK_BROKEN_INTR_AGGR                   = 1 << 0,
@@ -641,6 +662,31 @@ struct ufs_hba_variant_params {
        u32 wb_flush_threshold;
 };
 
+#ifdef CONFIG_SCSI_UFS_HPB
+/**
+ * struct ufshpb_dev_info - UFSHPB device related info
+ * @num_lu: the number of user logical unit to check whether all lu finished
+ *          initialization
+ * @rgn_size: device reported HPB region size
+ * @srgn_size: device reported HPB sub-region size
+ * @slave_conf_cnt: counter to check all lu finished initialization
+ * @hpb_disabled: flag to check if HPB is disabled
+ * @max_hpb_single_cmd: device reported bMAX_DATA_SIZE_FOR_SINGLE_CMD value
+ * @is_legacy: flag to check HPB 1.0
+ * @control_mode: either host or device
+ */
+struct ufshpb_dev_info {
+       int num_lu;
+       int rgn_size;
+       int srgn_size;
+       atomic_t slave_conf_cnt;
+       bool hpb_disabled;
+       u8 max_hpb_single_cmd;
+       bool is_legacy;
+       u8 control_mode;
+};
+#endif
+
 struct ufs_hba_monitor {
        unsigned long chunk_size;
 
@@ -683,11 +729,11 @@ struct ufs_hba_monitor {
  * @priv: pointer to variant specific private data
  * @irq: Irq number of the controller
  * @active_uic_cmd: handle of active UIC command
- * @uic_cmd_mutex: mutex for uic command
+ * @uic_cmd_mutex: mutex for UIC command
  * @tmf_tag_set: TMF tag set.
  * @tmf_queue: Used to allocate TMF tags.
  * @pwr_done: completion for power mode change
- * @ufshcd_state: UFSHCD states
+ * @ufshcd_state: UFSHCD state
  * @eh_flags: Error handling flags
  * @intr_mask: Interrupt Mask Bits
  * @ee_ctrl_mask: Exception event control mask
@@ -785,7 +831,7 @@ struct ufs_hba {
        struct mutex uic_cmd_mutex;
        struct completion *uic_async_done;
 
-       u32 ufshcd_state;
+       enum ufshcd_state ufshcd_state;
        u32 eh_flags;
        u32 intr_mask;
        u16 ee_ctrl_mask; /* Exception event mask */
@@ -851,6 +897,10 @@ struct ufs_hba {
        struct request_queue    *bsg_queue;
        struct delayed_work rpm_dev_flush_recheck_work;
 
+#ifdef CONFIG_SCSI_UFS_HPB
+       struct ufshpb_dev_info ufshpb_dev;
+#endif
+
        struct ufs_hba_monitor  monitor;
 
 #ifdef CONFIG_SCSI_UFS_CRYPTO
@@ -893,16 +943,8 @@ static inline bool ufshcd_is_rpm_autosuspend_allowed(struct ufs_hba *hba)
 
 static inline bool ufshcd_is_intr_aggr_allowed(struct ufs_hba *hba)
 {
-/* DWC UFS Core has the Interrupt aggregation feature but is not detectable*/
-#ifndef CONFIG_SCSI_UFS_DWC
-       if ((hba->caps & UFSHCD_CAP_INTR_AGGR) &&
-           !(hba->quirks & UFSHCD_QUIRK_BROKEN_INTR_AGGR))
-               return true;
-       else
-               return false;
-#else
-return true;
-#endif
+       return (hba->caps & UFSHCD_CAP_INTR_AGGR) &&
+               !(hba->quirks & UFSHCD_QUIRK_BROKEN_INTR_AGGR);
 }
 
 static inline bool ufshcd_can_aggressive_pc(struct ufs_hba *hba)
@@ -1009,11 +1051,14 @@ static inline u8 ufshcd_wb_get_query_index(struct ufs_hba *hba)
        return 0;
 }
 
-extern int ufshcd_runtime_suspend(struct ufs_hba *hba);
-extern int ufshcd_runtime_resume(struct ufs_hba *hba);
-extern int ufshcd_runtime_idle(struct ufs_hba *hba);
-extern int ufshcd_system_suspend(struct ufs_hba *hba);
-extern int ufshcd_system_resume(struct ufs_hba *hba);
+#ifdef CONFIG_PM
+extern int ufshcd_runtime_suspend(struct device *dev);
+extern int ufshcd_runtime_resume(struct device *dev);
+#endif
+#ifdef CONFIG_PM_SLEEP
+extern int ufshcd_system_suspend(struct device *dev);
+extern int ufshcd_system_resume(struct device *dev);
+#endif
 extern int ufshcd_shutdown(struct ufs_hba *hba);
 extern int ufshcd_dme_configure_adapt(struct ufs_hba *hba,
                                      int agreed_gear,
@@ -1096,6 +1141,9 @@ int ufshcd_read_desc_param(struct ufs_hba *hba,
                           u8 param_offset,
                           u8 *param_read_buf,
                           u8 param_size);
+int ufshcd_query_attr_retry(struct ufs_hba *hba, enum query_opcode opcode,
+                           enum attr_idn idn, u8 index, u8 selector,
+                           u32 *attr_val);
 int ufshcd_query_attr(struct ufs_hba *hba, enum query_opcode opcode,
                      enum attr_idn idn, u8 index, u8 selector, u32 *attr_val);
 int ufshcd_query_flag(struct ufs_hba *hba, enum query_opcode opcode,
@@ -1160,11 +1208,6 @@ static inline u32 ufshcd_vops_get_ufs_hci_version(struct ufs_hba *hba)
        return ufshcd_readl(hba, REG_UFS_VERSION);
 }
 
-static inline bool ufshcd_has_utrlcnr(struct ufs_hba *hba)
-{
-       return (hba->ufs_version >= ufshci_version(3, 0));
-}
-
 static inline int ufshcd_vops_clk_scale_notify(struct ufs_hba *hba,
                        bool up, enum ufs_notify_change_status status)
 {
@@ -1226,13 +1269,6 @@ static inline int ufshcd_vops_pwr_change_notify(struct ufs_hba *hba,
        return -ENOTSUPP;
 }
 
-static inline void ufshcd_vops_setup_xfer_req(struct ufs_hba *hba, int tag,
-                                       bool is_scsi_cmd)
-{
-       if (hba->vops && hba->vops->setup_xfer_req)
-               return hba->vops->setup_xfer_req(hba, tag, is_scsi_cmd);
-}
-
 static inline void ufshcd_vops_setup_task_mgmt(struct ufs_hba *hba,
                                        int tag, u8 tm_function)
 {