Message ID | 20220915134956.90086-1-hy50.seo@samsung.com |
---|---|
State | New |
Headers | show |
Series | [v3] scsi: ufs: add a variant operation in struct ufs_hba_variant_ops | expand |
Hi Seo >-----Original Message----- >From: SEO HOYOUNG [mailto:hy50.seo@samsung.com] >Sent: Thursday, September 15, 2022 7:20 PM >To: linux-scsi@vger.kernel.org; linux-kernel@vger.kernel.org; >alim.akhtar@samsung.com; avri.altman@wdc.com; jejb@linux.ibm.com; >martin.petersen@oracle.com; beanhuo@micron.com; bvanassche@acm.org; >bhoon95.kim@samsung.com; kwmad.kim@samsung.com >Cc: SEO HOYOUNG <hy50.seo@samsung.com> >Subject: [PATCH v3] scsi: ufs: add a variant operation in struct >ufs_hba_variant_ops > >Add ufs_hba_variant_ops about vendor error in check_error. >It need to reset when occurred ah8 related error. >At that time could not recovery with pwr cmd. >So add vendor error check function at ufs_hba_variant_ops. > >v1->v2 >fixed warm message of auto build test > >v2->v3 >fixed operator error > >Signed-off-by: SEO HOYOUNG <hy50.seo@samsung.com> >--- Reviewed-by: Alim Akhtar <alim.akhtar@samsung.com> And you forget to add Bart's Reviewed-by on v2 > drivers/ufs/core/ufshcd-priv.h | 7 +++++++ > drivers/ufs/core/ufshcd.c | 2 ++ > drivers/ufs/host/ufs-exynos.c | 20 ++++++++++++++++++++ > include/ufs/ufshcd.h | 1 + > 4 files changed, 30 insertions(+) > >diff --git a/drivers/ufs/core/ufshcd-priv.h b/drivers/ufs/core/ufshcd-priv.h >index d00dba17297d..a615f3533d75 100644 >--- a/drivers/ufs/core/ufshcd-priv.h >+++ b/drivers/ufs/core/ufshcd-priv.h >@@ -221,6 +221,13 @@ static inline void >ufshcd_vops_config_scaling_param(struct ufs_hba *hba, > hba->vops->config_scaling_param(hba, p, data); } > >+static inline void ufshcd_vops_check_int_error(struct ufs_hba *hba, >+ bool *queue_eh_work) >+{ >+ if (hba->vops && hba->vops->check_int_error) >+ hba->vops->check_int_error(hba, queue_eh_work); } >+ > extern const struct ufs_pm_lvl_states ufs_pm_lvl_states[]; > > /** >diff --git a/drivers/ufs/core/ufshcd.c b/drivers/ufs/core/ufshcd.c index >7c15cbc737b4..39ee5192f26a 100644 >--- a/drivers/ufs/core/ufshcd.c >+++ b/drivers/ufs/core/ufshcd.c >@@ -6542,6 +6542,8 @@ static irqreturn_t ufshcd_check_errors(struct >ufs_hba *hba, u32 intr_status) > queue_eh_work = true; > } > >+ ufshcd_vops_check_int_error(hba, &queue_eh_work); >+ > if (queue_eh_work) { > /* > * update the transfer error masks to sticky bits, let's do this >diff --git a/drivers/ufs/host/ufs-exynos.c b/drivers/ufs/host/ufs-exynos.c >index eced97538082..5d9db6870a66 100644 >--- a/drivers/ufs/host/ufs-exynos.c >+++ b/drivers/ufs/host/ufs-exynos.c >@@ -67,6 +67,10 @@ > #define CLK_CTRL_EN_MASK (REFCLK_CTRL_EN |\ > UNIPRO_PCLK_CTRL_EN |\ > UNIPRO_MCLK_CTRL_EN) >+ >+#define HCI_AH8_STATE 0x50C >+#define HCI_AH8_STATE_ERROR BIT(16) >+ > /* Device fatal error */ > #define DFES_ERR_EN BIT(31) > #define DFES_DEF_L2_ERRS (UIC_DATA_LINK_LAYER_ERROR_RX_BUF_OF >|\ >@@ -1376,6 +1380,21 @@ static void exynos_ufs_hibern8_notify(struct >ufs_hba *hba, > } > } > >+static void exynos_ufs_check_int_error(struct ufs_hba *hba, bool >+*queue_eh_work) { >+ struct exynos_ufs *ufs = ufshcd_get_variant(hba); >+ u32 val; >+ >+ if (ufshcd_is_auto_hibern8_supported(hba)) { >+ val = hci_readl(ufs, HCI_AH8_STATE); >+ >+ if (val & HCI_AH8_STATE_ERROR) { >+ ufshcd_set_link_broken(hba); >+ *queue_eh_work = true; >+ } >+ } >+} >+ > static int exynos_ufs_suspend(struct ufs_hba *hba, enum ufs_pm_op >pm_op, > enum ufs_notify_change_status status) > { >@@ -1569,6 +1588,7 @@ static const struct ufs_hba_variant_ops >ufs_hba_exynos_ops = { > .setup_xfer_req = >exynos_ufs_specify_nexus_t_xfer_req, > .setup_task_mgmt = >exynos_ufs_specify_nexus_t_tm_req, > .hibern8_notify = exynos_ufs_hibern8_notify, >+ .check_int_error = exynos_ufs_check_int_error, > .suspend = exynos_ufs_suspend, > .resume = exynos_ufs_resume, > }; >diff --git a/include/ufs/ufshcd.h b/include/ufs/ufshcd.h index >24c97e0772bb..40078c4b9f55 100644 >--- a/include/ufs/ufshcd.h >+++ b/include/ufs/ufshcd.h >@@ -335,6 +335,7 @@ struct ufs_hba_variant_ops { > const union ufs_crypto_cfg_entry *cfg, int slot); > void (*event_notify)(struct ufs_hba *hba, > enum ufs_event_type evt, void *data); >+ void (*check_int_error)(struct ufs_hba *hba, bool >*queue_eh_work); > }; > > /* clock gating state */ >-- >2.26.0
diff --git a/drivers/ufs/core/ufshcd-priv.h b/drivers/ufs/core/ufshcd-priv.h index d00dba17297d..a615f3533d75 100644 --- a/drivers/ufs/core/ufshcd-priv.h +++ b/drivers/ufs/core/ufshcd-priv.h @@ -221,6 +221,13 @@ static inline void ufshcd_vops_config_scaling_param(struct ufs_hba *hba, hba->vops->config_scaling_param(hba, p, data); } +static inline void ufshcd_vops_check_int_error(struct ufs_hba *hba, + bool *queue_eh_work) +{ + if (hba->vops && hba->vops->check_int_error) + hba->vops->check_int_error(hba, queue_eh_work); +} + extern const struct ufs_pm_lvl_states ufs_pm_lvl_states[]; /** diff --git a/drivers/ufs/core/ufshcd.c b/drivers/ufs/core/ufshcd.c index 7c15cbc737b4..39ee5192f26a 100644 --- a/drivers/ufs/core/ufshcd.c +++ b/drivers/ufs/core/ufshcd.c @@ -6542,6 +6542,8 @@ static irqreturn_t ufshcd_check_errors(struct ufs_hba *hba, u32 intr_status) queue_eh_work = true; } + ufshcd_vops_check_int_error(hba, &queue_eh_work); + if (queue_eh_work) { /* * update the transfer error masks to sticky bits, let's do this diff --git a/drivers/ufs/host/ufs-exynos.c b/drivers/ufs/host/ufs-exynos.c index eced97538082..5d9db6870a66 100644 --- a/drivers/ufs/host/ufs-exynos.c +++ b/drivers/ufs/host/ufs-exynos.c @@ -67,6 +67,10 @@ #define CLK_CTRL_EN_MASK (REFCLK_CTRL_EN |\ UNIPRO_PCLK_CTRL_EN |\ UNIPRO_MCLK_CTRL_EN) + +#define HCI_AH8_STATE 0x50C +#define HCI_AH8_STATE_ERROR BIT(16) + /* Device fatal error */ #define DFES_ERR_EN BIT(31) #define DFES_DEF_L2_ERRS (UIC_DATA_LINK_LAYER_ERROR_RX_BUF_OF |\ @@ -1376,6 +1380,21 @@ static void exynos_ufs_hibern8_notify(struct ufs_hba *hba, } } +static void exynos_ufs_check_int_error(struct ufs_hba *hba, bool *queue_eh_work) +{ + struct exynos_ufs *ufs = ufshcd_get_variant(hba); + u32 val; + + if (ufshcd_is_auto_hibern8_supported(hba)) { + val = hci_readl(ufs, HCI_AH8_STATE); + + if (val & HCI_AH8_STATE_ERROR) { + ufshcd_set_link_broken(hba); + *queue_eh_work = true; + } + } +} + static int exynos_ufs_suspend(struct ufs_hba *hba, enum ufs_pm_op pm_op, enum ufs_notify_change_status status) { @@ -1569,6 +1588,7 @@ static const struct ufs_hba_variant_ops ufs_hba_exynos_ops = { .setup_xfer_req = exynos_ufs_specify_nexus_t_xfer_req, .setup_task_mgmt = exynos_ufs_specify_nexus_t_tm_req, .hibern8_notify = exynos_ufs_hibern8_notify, + .check_int_error = exynos_ufs_check_int_error, .suspend = exynos_ufs_suspend, .resume = exynos_ufs_resume, }; diff --git a/include/ufs/ufshcd.h b/include/ufs/ufshcd.h index 24c97e0772bb..40078c4b9f55 100644 --- a/include/ufs/ufshcd.h +++ b/include/ufs/ufshcd.h @@ -335,6 +335,7 @@ struct ufs_hba_variant_ops { const union ufs_crypto_cfg_entry *cfg, int slot); void (*event_notify)(struct ufs_hba *hba, enum ufs_event_type evt, void *data); + void (*check_int_error)(struct ufs_hba *hba, bool *queue_eh_work); }; /* clock gating state */
Add ufs_hba_variant_ops about vendor error in check_error. It need to reset when occurred ah8 related error. At that time could not recovery with pwr cmd. So add vendor error check function at ufs_hba_variant_ops. v1->v2 fixed warm message of auto build test v2->v3 fixed operator error Signed-off-by: SEO HOYOUNG <hy50.seo@samsung.com> --- drivers/ufs/core/ufshcd-priv.h | 7 +++++++ drivers/ufs/core/ufshcd.c | 2 ++ drivers/ufs/host/ufs-exynos.c | 20 ++++++++++++++++++++ include/ufs/ufshcd.h | 1 + 4 files changed, 30 insertions(+)