Re: [PATCH v6 15/17] scsi: ufs-qcom: set PA_Local_TX_LCC_Enable before link startup

2016-03-07 Thread Gilad Broner
Reviewed-by: Gilad Broner <gbro...@codeaurora.org>

> Some UFS devices (and may be host) have issues if LCC is
> enabled. So we are setting PA_Local_TX_LCC_Enable to 0
> before link startup which will make sure that both host
> and device TX LCC are disabled once link startup is
> completed.
>
> Signed-off-by: Yaniv Gardi <yga...@codeaurora.org>
>
> ---
>  drivers/scsi/ufs/ufs-qcom.c | 27 ---
>  drivers/scsi/ufs/unipro.h   |  1 +
>  2 files changed, 21 insertions(+), 7 deletions(-)
>
> diff --git a/drivers/scsi/ufs/ufs-qcom.c b/drivers/scsi/ufs/ufs-qcom.c
> index ed57729..966bacf 100644
> --- a/drivers/scsi/ufs/ufs-qcom.c
> +++ b/drivers/scsi/ufs/ufs-qcom.c
> @@ -16,8 +16,8 @@
>  #include 
>  #include 
>  #include 
> -
>  #include 
> +
>  #include "ufshcd.h"
>  #include "ufshcd-pltfrm.h"
>  #include "unipro.h"
> @@ -106,9 +106,11 @@ static void ufs_qcom_disable_lane_clks(struct
> ufs_qcom_host *host)
>   if (!host->is_lane_clks_enabled)
>   return;
>
> - clk_disable_unprepare(host->tx_l1_sync_clk);
> + if (host->hba->lanes_per_direction > 1)
> + clk_disable_unprepare(host->tx_l1_sync_clk);
>   clk_disable_unprepare(host->tx_l0_sync_clk);
> - clk_disable_unprepare(host->rx_l1_sync_clk);
> + if (host->hba->lanes_per_direction > 1)
> + clk_disable_unprepare(host->rx_l1_sync_clk);
>   clk_disable_unprepare(host->rx_l0_sync_clk);
>
>   host->is_lane_clks_enabled = false;
> @@ -272,9 +274,8 @@ static int ufs_qcom_power_up_sequence(struct ufs_hba
> *hba)
>   ret = ufs_qcom_phy_calibrate_phy(phy, is_rate_B);
>
>   if (ret) {
> - dev_err(hba->dev,
> - "%s: ufs_qcom_phy_calibrate_phy()failed, ret = %d\n",
> - __func__, ret);
> + dev_err(hba->dev, "%s: ufs_qcom_phy_calibrate_phy() failed, ret 
> =
> %d\n",
> + __func__, ret);
>   goto out;
>   }
>
> @@ -524,6 +525,18 @@ static int ufs_qcom_link_startup_notify(struct
> ufs_hba *hba,
>   err = ufs_qcom_set_dme_vs_core_clk_ctrl_clear_div(hba,
> 150);
>
> + /*
> +  * Some UFS devices (and may be host) have issues if LCC is
> +  * enabled. So we are setting PA_Local_TX_LCC_Enable to 0
> +  * before link startup which will make sure that both host
> +  * and device TX LCC are disabled once link startup is
> +  * completed.
> +  */
> + if (ufshcd_get_local_unipro_ver(hba) != UFS_UNIPRO_VER_1_41)
> + err = ufshcd_dme_set(hba,
> + UIC_ARG_MIB(PA_LOCAL_TX_LCC_ENABLE),
> + 0);
> +
>   break;
>   case POST_CHANGE:
>   ufs_qcom_link_startup_post_change(hba);
> @@ -1542,7 +1555,7 @@ static int ufs_qcom_probe(struct platform_device
> *pdev)
>   * ufs_qcom_remove - set driver_data of the device to NULL
>   * @pdev: pointer to platform device handle
>   *
> - * Always return 0
> + * Always returns 0
>   */
>  static int ufs_qcom_remove(struct platform_device *pdev)
>  {
> diff --git a/drivers/scsi/ufs/unipro.h b/drivers/scsi/ufs/unipro.h
> index 8082020..e2854e4 100644
> --- a/drivers/scsi/ufs/unipro.h
> +++ b/drivers/scsi/ufs/unipro.h
> @@ -75,6 +75,7 @@
>  #define PA_MAXRXSPEEDFAST0x1541
>  #define PA_MAXRXSPEEDSLOW0x1542
>  #define PA_TXLINKSTARTUPHS   0x1544
> +#define PA_LOCAL_TX_LCC_ENABLE   0x155E
>  #define PA_TXSPEEDFAST   0x1565
>  #define PA_TXSPEEDSLOW   0x1566
>  #define PA_REMOTEVERINFO 0x15A0
> --
> 1.8.5.2
>
> --
> QUALCOMM ISRAEL, on behalf of Qualcomm Innovation Center, Inc. is a member
> of Code Aurora Forum, hosted by The Linux Foundation
> --
> To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
> the body of a message to majord...@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>


-- 
Qualcomm Israel, on behalf of Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project



Re: [PATCH v6 15/17] scsi: ufs-qcom: set PA_Local_TX_LCC_Enable before link startup

2016-03-07 Thread Gilad Broner
Reviewed-by: Gilad Broner 

> Some UFS devices (and may be host) have issues if LCC is
> enabled. So we are setting PA_Local_TX_LCC_Enable to 0
> before link startup which will make sure that both host
> and device TX LCC are disabled once link startup is
> completed.
>
> Signed-off-by: Yaniv Gardi 
>
> ---
>  drivers/scsi/ufs/ufs-qcom.c | 27 ---
>  drivers/scsi/ufs/unipro.h   |  1 +
>  2 files changed, 21 insertions(+), 7 deletions(-)
>
> diff --git a/drivers/scsi/ufs/ufs-qcom.c b/drivers/scsi/ufs/ufs-qcom.c
> index ed57729..966bacf 100644
> --- a/drivers/scsi/ufs/ufs-qcom.c
> +++ b/drivers/scsi/ufs/ufs-qcom.c
> @@ -16,8 +16,8 @@
>  #include 
>  #include 
>  #include 
> -
>  #include 
> +
>  #include "ufshcd.h"
>  #include "ufshcd-pltfrm.h"
>  #include "unipro.h"
> @@ -106,9 +106,11 @@ static void ufs_qcom_disable_lane_clks(struct
> ufs_qcom_host *host)
>   if (!host->is_lane_clks_enabled)
>   return;
>
> - clk_disable_unprepare(host->tx_l1_sync_clk);
> + if (host->hba->lanes_per_direction > 1)
> + clk_disable_unprepare(host->tx_l1_sync_clk);
>   clk_disable_unprepare(host->tx_l0_sync_clk);
> - clk_disable_unprepare(host->rx_l1_sync_clk);
> + if (host->hba->lanes_per_direction > 1)
> + clk_disable_unprepare(host->rx_l1_sync_clk);
>   clk_disable_unprepare(host->rx_l0_sync_clk);
>
>   host->is_lane_clks_enabled = false;
> @@ -272,9 +274,8 @@ static int ufs_qcom_power_up_sequence(struct ufs_hba
> *hba)
>   ret = ufs_qcom_phy_calibrate_phy(phy, is_rate_B);
>
>   if (ret) {
> - dev_err(hba->dev,
> - "%s: ufs_qcom_phy_calibrate_phy()failed, ret = %d\n",
> - __func__, ret);
> + dev_err(hba->dev, "%s: ufs_qcom_phy_calibrate_phy() failed, ret 
> =
> %d\n",
> + __func__, ret);
>   goto out;
>   }
>
> @@ -524,6 +525,18 @@ static int ufs_qcom_link_startup_notify(struct
> ufs_hba *hba,
>   err = ufs_qcom_set_dme_vs_core_clk_ctrl_clear_div(hba,
> 150);
>
> + /*
> +  * Some UFS devices (and may be host) have issues if LCC is
> +  * enabled. So we are setting PA_Local_TX_LCC_Enable to 0
> +  * before link startup which will make sure that both host
> +  * and device TX LCC are disabled once link startup is
> +  * completed.
> +  */
> + if (ufshcd_get_local_unipro_ver(hba) != UFS_UNIPRO_VER_1_41)
> + err = ufshcd_dme_set(hba,
> + UIC_ARG_MIB(PA_LOCAL_TX_LCC_ENABLE),
> + 0);
> +
>   break;
>   case POST_CHANGE:
>   ufs_qcom_link_startup_post_change(hba);
> @@ -1542,7 +1555,7 @@ static int ufs_qcom_probe(struct platform_device
> *pdev)
>   * ufs_qcom_remove - set driver_data of the device to NULL
>   * @pdev: pointer to platform device handle
>   *
> - * Always return 0
> + * Always returns 0
>   */
>  static int ufs_qcom_remove(struct platform_device *pdev)
>  {
> diff --git a/drivers/scsi/ufs/unipro.h b/drivers/scsi/ufs/unipro.h
> index 8082020..e2854e4 100644
> --- a/drivers/scsi/ufs/unipro.h
> +++ b/drivers/scsi/ufs/unipro.h
> @@ -75,6 +75,7 @@
>  #define PA_MAXRXSPEEDFAST0x1541
>  #define PA_MAXRXSPEEDSLOW0x1542
>  #define PA_TXLINKSTARTUPHS   0x1544
> +#define PA_LOCAL_TX_LCC_ENABLE   0x155E
>  #define PA_TXSPEEDFAST   0x1565
>  #define PA_TXSPEEDSLOW   0x1566
>  #define PA_REMOTEVERINFO 0x15A0
> --
> 1.8.5.2
>
> --
> QUALCOMM ISRAEL, on behalf of Qualcomm Innovation Center, Inc. is a member
> of Code Aurora Forum, hosted by The Linux Foundation
> --
> To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
> the body of a message to majord...@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>


-- 
Qualcomm Israel, on behalf of Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project



Re: [PATCH v6 16/17] scsi: ufs-qcom: enable/disable the device ref clock

2016-03-07 Thread Gilad Broner
Reviewed-by: Gilad Broner <gbro...@codeaurora.org>

> This change enables the device ref clock before changing to HS mode
> and disables it if entered to PWM mode.
>
> Signed-off-by: Yaniv Gardi <yga...@codeaurora.org>
>
> ---
>  drivers/scsi/ufs/ufs-qcom.c | 12 
>  drivers/scsi/ufs/ufshcd.h   |  9 +
>  2 files changed, 21 insertions(+)
>
> diff --git a/drivers/scsi/ufs/ufs-qcom.c b/drivers/scsi/ufs/ufs-qcom.c
> index 966bacf..849fcf3 100644
> --- a/drivers/scsi/ufs/ufs-qcom.c
> +++ b/drivers/scsi/ufs/ufs-qcom.c
> @@ -980,6 +980,10 @@ static int ufs_qcom_pwr_change_notify(struct ufs_hba
> *hba,
>   goto out;
>   }
>
> + /* enable the device ref clock before changing to HS mode */
> + if (!ufshcd_is_hs_mode(>pwr_info) &&
> + ufshcd_is_hs_mode(dev_req_params))
> + ufs_qcom_dev_ref_clk_ctrl(host, true);
>   break;
>   case POST_CHANGE:
>   if (ufs_qcom_cfg_timers(hba, dev_req_params->gear_rx,
> @@ -1007,6 +1011,11 @@ static int ufs_qcom_pwr_change_notify(struct
> ufs_hba *hba,
>   memcpy(>dev_req_params,
>   dev_req_params, sizeof(*dev_req_params));
>   ufs_qcom_update_bus_bw_vote(host);
> +
> + /* disable the device ref clock if entered PWM mode */
> + if (ufshcd_is_hs_mode(>pwr_info) &&
> + !ufshcd_is_hs_mode(dev_req_params))
> + ufs_qcom_dev_ref_clk_ctrl(host, false);
>   break;
>   default:
>   ret = -EINVAL;
> @@ -1108,6 +1117,9 @@ static int ufs_qcom_setup_clocks(struct ufs_hba
> *hba, bool on)
>   ufs_qcom_phy_disable_iface_clk(host->generic_phy);
>   goto out;
>   }
> + /* enable the device ref clock for HS mode*/
> + if (ufshcd_is_hs_mode(>pwr_info))
> + ufs_qcom_dev_ref_clk_ctrl(host, true);
>   vote = host->bus_vote.saved_vote;
>   if (vote == host->bus_vote.min_bw_vote)
>   ufs_qcom_update_bus_bw_vote(host);
> diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h
> index 41d9bfd..4bb6566 100644
> --- a/drivers/scsi/ufs/ufshcd.h
> +++ b/drivers/scsi/ufs/ufshcd.h
> @@ -54,6 +54,7 @@
>  #include 
>  #include 
>  #include 
> +#include "unipro.h"
>
>  #include 
>  #include 
> @@ -689,6 +690,14 @@ static inline int ufshcd_dme_peer_get(struct ufs_hba
> *hba,
>
>  int ufshcd_read_device_desc(struct ufs_hba *hba, u8 *buf, u32 size);
>
> +static inline bool ufshcd_is_hs_mode(struct ufs_pa_layer_attr *pwr_info)
> +{
> + return (pwr_info->pwr_rx == FAST_MODE ||
> + pwr_info->pwr_rx == FASTAUTO_MODE) &&
> + (pwr_info->pwr_tx == FAST_MODE ||
> + pwr_info->pwr_tx == FASTAUTO_MODE);
> +}
> +
>  #define ASCII_STD true
>
>  int ufshcd_read_string_desc(struct ufs_hba *hba, int desc_index, u8 *buf,
> --
> 1.8.5.2
>
> --
> QUALCOMM ISRAEL, on behalf of Qualcomm Innovation Center, Inc. is a member
> of Code Aurora Forum, hosted by The Linux Foundation
> --
> To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
> the body of a message to majord...@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>


-- 
Qualcomm Israel, on behalf of Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project



Re: [PATCH v6 16/17] scsi: ufs-qcom: enable/disable the device ref clock

2016-03-07 Thread Gilad Broner
Reviewed-by: Gilad Broner 

> This change enables the device ref clock before changing to HS mode
> and disables it if entered to PWM mode.
>
> Signed-off-by: Yaniv Gardi 
>
> ---
>  drivers/scsi/ufs/ufs-qcom.c | 12 
>  drivers/scsi/ufs/ufshcd.h   |  9 +
>  2 files changed, 21 insertions(+)
>
> diff --git a/drivers/scsi/ufs/ufs-qcom.c b/drivers/scsi/ufs/ufs-qcom.c
> index 966bacf..849fcf3 100644
> --- a/drivers/scsi/ufs/ufs-qcom.c
> +++ b/drivers/scsi/ufs/ufs-qcom.c
> @@ -980,6 +980,10 @@ static int ufs_qcom_pwr_change_notify(struct ufs_hba
> *hba,
>   goto out;
>   }
>
> + /* enable the device ref clock before changing to HS mode */
> + if (!ufshcd_is_hs_mode(>pwr_info) &&
> + ufshcd_is_hs_mode(dev_req_params))
> + ufs_qcom_dev_ref_clk_ctrl(host, true);
>   break;
>   case POST_CHANGE:
>   if (ufs_qcom_cfg_timers(hba, dev_req_params->gear_rx,
> @@ -1007,6 +1011,11 @@ static int ufs_qcom_pwr_change_notify(struct
> ufs_hba *hba,
>   memcpy(>dev_req_params,
>   dev_req_params, sizeof(*dev_req_params));
>   ufs_qcom_update_bus_bw_vote(host);
> +
> + /* disable the device ref clock if entered PWM mode */
> + if (ufshcd_is_hs_mode(>pwr_info) &&
> + !ufshcd_is_hs_mode(dev_req_params))
> + ufs_qcom_dev_ref_clk_ctrl(host, false);
>   break;
>   default:
>   ret = -EINVAL;
> @@ -1108,6 +1117,9 @@ static int ufs_qcom_setup_clocks(struct ufs_hba
> *hba, bool on)
>   ufs_qcom_phy_disable_iface_clk(host->generic_phy);
>   goto out;
>   }
> + /* enable the device ref clock for HS mode*/
> + if (ufshcd_is_hs_mode(>pwr_info))
> + ufs_qcom_dev_ref_clk_ctrl(host, true);
>   vote = host->bus_vote.saved_vote;
>   if (vote == host->bus_vote.min_bw_vote)
>   ufs_qcom_update_bus_bw_vote(host);
> diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h
> index 41d9bfd..4bb6566 100644
> --- a/drivers/scsi/ufs/ufshcd.h
> +++ b/drivers/scsi/ufs/ufshcd.h
> @@ -54,6 +54,7 @@
>  #include 
>  #include 
>  #include 
> +#include "unipro.h"
>
>  #include 
>  #include 
> @@ -689,6 +690,14 @@ static inline int ufshcd_dme_peer_get(struct ufs_hba
> *hba,
>
>  int ufshcd_read_device_desc(struct ufs_hba *hba, u8 *buf, u32 size);
>
> +static inline bool ufshcd_is_hs_mode(struct ufs_pa_layer_attr *pwr_info)
> +{
> + return (pwr_info->pwr_rx == FAST_MODE ||
> + pwr_info->pwr_rx == FASTAUTO_MODE) &&
> + (pwr_info->pwr_tx == FAST_MODE ||
> + pwr_info->pwr_tx == FASTAUTO_MODE);
> +}
> +
>  #define ASCII_STD true
>
>  int ufshcd_read_string_desc(struct ufs_hba *hba, int desc_index, u8 *buf,
> --
> 1.8.5.2
>
> --
> QUALCOMM ISRAEL, on behalf of Qualcomm Innovation Center, Inc. is a member
> of Code Aurora Forum, hosted by The Linux Foundation
> --
> To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
> the body of a message to majord...@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>


-- 
Qualcomm Israel, on behalf of Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project



Re: [PATCH v6 17/17] scsi: ufs-qcom: add printouts of testbus debug registers

2016-03-07 Thread Gilad Broner
Reviewed-by: Gilad Broner <gbro...@codeaurora.org>

> This change adds printouts of testbus and debug registers.
>
> Signed-off-by: Yaniv Gardi <yga...@codeaurora.org>
>
> ---
>  drivers/scsi/ufs/ufs-qcom.c | 77
> +
>  drivers/scsi/ufs/ufs-qcom.h |  9 ++
>  2 files changed, 86 insertions(+)
>
> diff --git a/drivers/scsi/ufs/ufs-qcom.c b/drivers/scsi/ufs/ufs-qcom.c
> index 849fcf3..3aedf73 100644
> --- a/drivers/scsi/ufs/ufs-qcom.c
> +++ b/drivers/scsi/ufs/ufs-qcom.c
> @@ -58,6 +58,12 @@ static void ufs_qcom_dump_regs(struct ufs_hba *hba, int
> offset, int len,
>   len * 4, false);
>  }
>
> +static void ufs_qcom_dump_regs_wrapper(struct ufs_hba *hba, int offset,
> int len,
> + char *prefix, void *priv)
> +{
> + ufs_qcom_dump_regs(hba, offset, len, prefix);
> +}
> +
>  static int ufs_qcom_get_connected_tx_lanes(struct ufs_hba *hba, u32
> *tx_lanes)
>  {
>   int err = 0;
> @@ -1397,6 +1403,74 @@ out:
>   return err;
>  }
>
> +static void ufs_qcom_print_hw_debug_reg_all(struct ufs_hba *hba,
> + void *priv, void (*print_fn)(struct ufs_hba *hba,
> + int offset, int num_regs, char *str, void *priv))
> +{
> + u32 reg;
> + struct ufs_qcom_host *host;
> +
> + if (unlikely(!hba)) {
> + pr_err("%s: hba is NULL\n", __func__);
> + return;
> + }
> + if (unlikely(!print_fn)) {
> + dev_err(hba->dev, "%s: print_fn is NULL\n", __func__);
> + return;
> + }
> +
> + host = ufshcd_get_variant(hba);
> + if (!(host->dbg_print_en & UFS_QCOM_DBG_PRINT_REGS_EN))
> + return;
> +
> + reg = ufs_qcom_get_debug_reg_offset(host, UFS_UFS_DBG_RD_REG_OCSC);
> + print_fn(hba, reg, 44, "UFS_UFS_DBG_RD_REG_OCSC ", priv);
> +
> + reg = ufshcd_readl(hba, REG_UFS_CFG1);
> + reg |= UFS_BIT(17);
> + ufshcd_writel(hba, reg, REG_UFS_CFG1);
> +
> + reg = ufs_qcom_get_debug_reg_offset(host, UFS_UFS_DBG_RD_EDTL_RAM);
> + print_fn(hba, reg, 32, "UFS_UFS_DBG_RD_EDTL_RAM ", priv);
> +
> + reg = ufs_qcom_get_debug_reg_offset(host, UFS_UFS_DBG_RD_DESC_RAM);
> + print_fn(hba, reg, 128, "UFS_UFS_DBG_RD_DESC_RAM ", priv);
> +
> + reg = ufs_qcom_get_debug_reg_offset(host, UFS_UFS_DBG_RD_PRDT_RAM);
> + print_fn(hba, reg, 64, "UFS_UFS_DBG_RD_PRDT_RAM ", priv);
> +
> + ufshcd_writel(hba, (reg & ~UFS_BIT(17)), REG_UFS_CFG1);
> +
> + reg = ufs_qcom_get_debug_reg_offset(host, UFS_DBG_RD_REG_UAWM);
> + print_fn(hba, reg, 4, "UFS_DBG_RD_REG_UAWM ", priv);
> +
> + reg = ufs_qcom_get_debug_reg_offset(host, UFS_DBG_RD_REG_UARM);
> + print_fn(hba, reg, 4, "UFS_DBG_RD_REG_UARM ", priv);
> +
> + reg = ufs_qcom_get_debug_reg_offset(host, UFS_DBG_RD_REG_TXUC);
> + print_fn(hba, reg, 48, "UFS_DBG_RD_REG_TXUC ", priv);
> +
> + reg = ufs_qcom_get_debug_reg_offset(host, UFS_DBG_RD_REG_RXUC);
> + print_fn(hba, reg, 27, "UFS_DBG_RD_REG_RXUC ", priv);
> +
> + reg = ufs_qcom_get_debug_reg_offset(host, UFS_DBG_RD_REG_DFC);
> + print_fn(hba, reg, 19, "UFS_DBG_RD_REG_DFC ", priv);
> +
> + reg = ufs_qcom_get_debug_reg_offset(host, UFS_DBG_RD_REG_TRLUT);
> + print_fn(hba, reg, 34, "UFS_DBG_RD_REG_TRLUT ", priv);
> +
> + reg = ufs_qcom_get_debug_reg_offset(host, UFS_DBG_RD_REG_TMRLUT);
> + print_fn(hba, reg, 9, "UFS_DBG_RD_REG_TMRLUT ", priv);
> +}
> +
> +static void ufs_qcom_enable_test_bus(struct ufs_qcom_host *host)
> +{
> + if (host->dbg_print_en & UFS_QCOM_DBG_PRINT_TEST_BUS_EN)
> + ufshcd_rmwl(host->hba, TEST_BUS_EN, TEST_BUS_EN, REG_UFS_CFG1);
> + else
> + ufshcd_rmwl(host->hba, TEST_BUS_EN, 0, REG_UFS_CFG1);
> +}
> +
>  static void ufs_qcom_get_default_testbus_cfg(struct ufs_qcom_host *host)
>  {
>   /* provide a legal default configuration */
> @@ -1505,6 +1579,7 @@ int ufs_qcom_testbus_config(struct ufs_qcom_host
> *host)
>   ufshcd_rmwl(host->hba, mask,
>   (u32)host->testbus.select_minor << offset,
>   reg);
> + ufs_qcom_enable_test_bus(host);
>   ufshcd_release(host->hba);
>   pm_runtime_put_sync(host->hba->dev);
>
> @@ -1521,8 +1596,10 @@ static void ufs_qcom_dump_dbg_regs(struct ufs_hba
> *hba)
>   ufs_qcom_dump_regs(hba, REG_UFS_SYS1CLK_1US, 16,
>   "HCI Vendor Specific Registers ");
>
> + u

Re: [PATCH v6 17/17] scsi: ufs-qcom: add printouts of testbus debug registers

2016-03-07 Thread Gilad Broner
Reviewed-by: Gilad Broner 

> This change adds printouts of testbus and debug registers.
>
> Signed-off-by: Yaniv Gardi 
>
> ---
>  drivers/scsi/ufs/ufs-qcom.c | 77
> +
>  drivers/scsi/ufs/ufs-qcom.h |  9 ++
>  2 files changed, 86 insertions(+)
>
> diff --git a/drivers/scsi/ufs/ufs-qcom.c b/drivers/scsi/ufs/ufs-qcom.c
> index 849fcf3..3aedf73 100644
> --- a/drivers/scsi/ufs/ufs-qcom.c
> +++ b/drivers/scsi/ufs/ufs-qcom.c
> @@ -58,6 +58,12 @@ static void ufs_qcom_dump_regs(struct ufs_hba *hba, int
> offset, int len,
>   len * 4, false);
>  }
>
> +static void ufs_qcom_dump_regs_wrapper(struct ufs_hba *hba, int offset,
> int len,
> + char *prefix, void *priv)
> +{
> + ufs_qcom_dump_regs(hba, offset, len, prefix);
> +}
> +
>  static int ufs_qcom_get_connected_tx_lanes(struct ufs_hba *hba, u32
> *tx_lanes)
>  {
>   int err = 0;
> @@ -1397,6 +1403,74 @@ out:
>   return err;
>  }
>
> +static void ufs_qcom_print_hw_debug_reg_all(struct ufs_hba *hba,
> + void *priv, void (*print_fn)(struct ufs_hba *hba,
> + int offset, int num_regs, char *str, void *priv))
> +{
> + u32 reg;
> + struct ufs_qcom_host *host;
> +
> + if (unlikely(!hba)) {
> + pr_err("%s: hba is NULL\n", __func__);
> + return;
> + }
> + if (unlikely(!print_fn)) {
> + dev_err(hba->dev, "%s: print_fn is NULL\n", __func__);
> + return;
> + }
> +
> + host = ufshcd_get_variant(hba);
> + if (!(host->dbg_print_en & UFS_QCOM_DBG_PRINT_REGS_EN))
> + return;
> +
> + reg = ufs_qcom_get_debug_reg_offset(host, UFS_UFS_DBG_RD_REG_OCSC);
> + print_fn(hba, reg, 44, "UFS_UFS_DBG_RD_REG_OCSC ", priv);
> +
> + reg = ufshcd_readl(hba, REG_UFS_CFG1);
> + reg |= UFS_BIT(17);
> + ufshcd_writel(hba, reg, REG_UFS_CFG1);
> +
> + reg = ufs_qcom_get_debug_reg_offset(host, UFS_UFS_DBG_RD_EDTL_RAM);
> + print_fn(hba, reg, 32, "UFS_UFS_DBG_RD_EDTL_RAM ", priv);
> +
> + reg = ufs_qcom_get_debug_reg_offset(host, UFS_UFS_DBG_RD_DESC_RAM);
> + print_fn(hba, reg, 128, "UFS_UFS_DBG_RD_DESC_RAM ", priv);
> +
> + reg = ufs_qcom_get_debug_reg_offset(host, UFS_UFS_DBG_RD_PRDT_RAM);
> + print_fn(hba, reg, 64, "UFS_UFS_DBG_RD_PRDT_RAM ", priv);
> +
> + ufshcd_writel(hba, (reg & ~UFS_BIT(17)), REG_UFS_CFG1);
> +
> + reg = ufs_qcom_get_debug_reg_offset(host, UFS_DBG_RD_REG_UAWM);
> + print_fn(hba, reg, 4, "UFS_DBG_RD_REG_UAWM ", priv);
> +
> + reg = ufs_qcom_get_debug_reg_offset(host, UFS_DBG_RD_REG_UARM);
> + print_fn(hba, reg, 4, "UFS_DBG_RD_REG_UARM ", priv);
> +
> + reg = ufs_qcom_get_debug_reg_offset(host, UFS_DBG_RD_REG_TXUC);
> + print_fn(hba, reg, 48, "UFS_DBG_RD_REG_TXUC ", priv);
> +
> + reg = ufs_qcom_get_debug_reg_offset(host, UFS_DBG_RD_REG_RXUC);
> + print_fn(hba, reg, 27, "UFS_DBG_RD_REG_RXUC ", priv);
> +
> + reg = ufs_qcom_get_debug_reg_offset(host, UFS_DBG_RD_REG_DFC);
> + print_fn(hba, reg, 19, "UFS_DBG_RD_REG_DFC ", priv);
> +
> + reg = ufs_qcom_get_debug_reg_offset(host, UFS_DBG_RD_REG_TRLUT);
> + print_fn(hba, reg, 34, "UFS_DBG_RD_REG_TRLUT ", priv);
> +
> + reg = ufs_qcom_get_debug_reg_offset(host, UFS_DBG_RD_REG_TMRLUT);
> + print_fn(hba, reg, 9, "UFS_DBG_RD_REG_TMRLUT ", priv);
> +}
> +
> +static void ufs_qcom_enable_test_bus(struct ufs_qcom_host *host)
> +{
> + if (host->dbg_print_en & UFS_QCOM_DBG_PRINT_TEST_BUS_EN)
> + ufshcd_rmwl(host->hba, TEST_BUS_EN, TEST_BUS_EN, REG_UFS_CFG1);
> + else
> + ufshcd_rmwl(host->hba, TEST_BUS_EN, 0, REG_UFS_CFG1);
> +}
> +
>  static void ufs_qcom_get_default_testbus_cfg(struct ufs_qcom_host *host)
>  {
>   /* provide a legal default configuration */
> @@ -1505,6 +1579,7 @@ int ufs_qcom_testbus_config(struct ufs_qcom_host
> *host)
>   ufshcd_rmwl(host->hba, mask,
>   (u32)host->testbus.select_minor << offset,
>   reg);
> + ufs_qcom_enable_test_bus(host);
>   ufshcd_release(host->hba);
>   pm_runtime_put_sync(host->hba->dev);
>
> @@ -1521,8 +1596,10 @@ static void ufs_qcom_dump_dbg_regs(struct ufs_hba
> *hba)
>   ufs_qcom_dump_regs(hba, REG_UFS_SYS1CLK_1US, 16,
>   "HCI Vendor Specific Registers ");
>
> + ufs_qcom_print_hw_debug_reg_all(hba, NULL, ufs_qcom_dump_r

Re: [PATCH v2 00/17] add fixes, device quirks, error recovery,

2015-10-28 Thread Gilad Broner
Looks good to me.
Reviewed-by: Gilad Broner 

> V2:
> This series should be pushed on top of 15 patches series:
> "Big fixes, retries, handle a race condition"
> fixed and few comments.
>
> V1:
> This series should be pushed on top of 15 patches series:
> "Big fixes, retries, handle a race condition"
>
> Yaniv Gardi (17):
>   scsi: ufs-qcom: add number of lanes per direction
>   scsi: ufs: add option to change default UFS power management level
>   scsi: ufs: optimize system suspend handling
>   scsi: ufs: avoid spurious UFS host controller interrupts
>   scsi: ufs: implement scsi host timeout handler
>   scsi :ufs: verify hba controller hce reg value
>   scsi: ufs: separate device and host quirks
>   scsi: ufs: disable vccq if it's not needed by UFS device
>   scsi: ufs: make error handling bit faster
>   scsi: ufs: add error recovery after DL NAC error
>   scsi: ufs: add retry for query descriptors
>   scsi: ufs: handle non spec compliant bkops behaviour by device
>   scsi: ufs: tune UniPro parameters to optimize hibern8 exit time
>   scsi: ufs: fix leakage during link off state
>   scsi: ufs: add device quirk delay before putting UFS rails in LPM
>   scsi: ufs-qcom: set PA_Local_TX_LCC_Enable before link startup
>   scsi: ufs-qcom: fix compilation warnings
>
>  .../devicetree/bindings/ufs/ufshcd-pltfrm.txt  |  11 +
>  drivers/scsi/ufs/Makefile  |   2 +-
>  drivers/scsi/ufs/ufs-qcom.c| 163 -
>  drivers/scsi/ufs/ufs-qcom.h|   9 +
>  drivers/scsi/ufs/ufs.h |  32 +
>  drivers/scsi/ufs/ufs_quirks.c  | 104 +++
>  drivers/scsi/ufs/ufs_quirks.h  | 131 
>  drivers/scsi/ufs/ufshcd-pltfrm.c   |  36 +-
>  drivers/scsi/ufs/ufshcd.c  | 803
> ++---
>  drivers/scsi/ufs/ufshcd.h  |  44 +-
>  drivers/scsi/ufs/ufshci.h  |   4 +
>  drivers/scsi/ufs/unipro.h  |  22 +
>  12 files changed, 1217 insertions(+), 144 deletions(-)
>  create mode 100644 drivers/scsi/ufs/ufs_quirks.c
>  create mode 100644 drivers/scsi/ufs/ufs_quirks.h
>
> --
> 1.8.5.2
>
> --
> QUALCOMM ISRAEL, on behalf of Qualcomm Innovation Center, Inc. is a member
> of Code Aurora Forum, hosted by The Linux Foundation
>


-- 
Qualcomm Israel, on behalf of Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH v2 00/17] add fixes, device quirks, error recovery,

2015-10-28 Thread Gilad Broner
Looks good to me.
Reviewed-by: Gilad Broner <gbro...@codeaurora.org>

> V2:
> This series should be pushed on top of 15 patches series:
> "Big fixes, retries, handle a race condition"
> fixed and few comments.
>
> V1:
> This series should be pushed on top of 15 patches series:
> "Big fixes, retries, handle a race condition"
>
> Yaniv Gardi (17):
>   scsi: ufs-qcom: add number of lanes per direction
>   scsi: ufs: add option to change default UFS power management level
>   scsi: ufs: optimize system suspend handling
>   scsi: ufs: avoid spurious UFS host controller interrupts
>   scsi: ufs: implement scsi host timeout handler
>   scsi :ufs: verify hba controller hce reg value
>   scsi: ufs: separate device and host quirks
>   scsi: ufs: disable vccq if it's not needed by UFS device
>   scsi: ufs: make error handling bit faster
>   scsi: ufs: add error recovery after DL NAC error
>   scsi: ufs: add retry for query descriptors
>   scsi: ufs: handle non spec compliant bkops behaviour by device
>   scsi: ufs: tune UniPro parameters to optimize hibern8 exit time
>   scsi: ufs: fix leakage during link off state
>   scsi: ufs: add device quirk delay before putting UFS rails in LPM
>   scsi: ufs-qcom: set PA_Local_TX_LCC_Enable before link startup
>   scsi: ufs-qcom: fix compilation warnings
>
>  .../devicetree/bindings/ufs/ufshcd-pltfrm.txt  |  11 +
>  drivers/scsi/ufs/Makefile  |   2 +-
>  drivers/scsi/ufs/ufs-qcom.c| 163 -
>  drivers/scsi/ufs/ufs-qcom.h|   9 +
>  drivers/scsi/ufs/ufs.h |  32 +
>  drivers/scsi/ufs/ufs_quirks.c  | 104 +++
>  drivers/scsi/ufs/ufs_quirks.h  | 131 
>  drivers/scsi/ufs/ufshcd-pltfrm.c   |  36 +-
>  drivers/scsi/ufs/ufshcd.c  | 803
> ++---
>  drivers/scsi/ufs/ufshcd.h  |  44 +-
>  drivers/scsi/ufs/ufshci.h  |   4 +
>  drivers/scsi/ufs/unipro.h  |  22 +
>  12 files changed, 1217 insertions(+), 144 deletions(-)
>  create mode 100644 drivers/scsi/ufs/ufs_quirks.c
>  create mode 100644 drivers/scsi/ufs/ufs_quirks.h
>
> --
> 1.8.5.2
>
> --
> QUALCOMM ISRAEL, on behalf of Qualcomm Innovation Center, Inc. is a member
> of Code Aurora Forum, hosted by The Linux Foundation
>


-- 
Qualcomm Israel, on behalf of Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH v8 6/8] scsi: ufs: make the UFS variant a platform device

2015-10-27 Thread Gilad Broner
Reviewed-by: Gilad Broner 

> This change turns the UFS variant (SCSI_UFS_QCOM) into a UFS
> a platform device.
> In order to do so a few additional changes are required:
> 1. The ufshcd-pltfrm is no longer serves as a platform device.
>Now it only serves as a group of platform APIs such as PM APIs
>(runtime suspend/resume, system suspend/resume etc), parsers of
>clocks, regulators and pm_levels from DT.
> 2. What used to be the old platform "probe" is now "only"
>a pltfrm_init() routine, that does exactly the same, but only
>being called by the new probe function of the UFS variant.
>
> Signed-off-by: Yaniv Gardi 
>
> ---
>  Documentation/devicetree/bindings/ufs/ufs-qcom.txt | 58 +
>  .../devicetree/bindings/ufs/ufshcd-pltfrm.txt  | 11 ++-
>  drivers/scsi/ufs/ufs-qcom.c| 62 +-
>  drivers/scsi/ufs/ufshcd-pltfrm.c   | 98
> ++
>  drivers/scsi/ufs/ufshcd-pltfrm.h   | 41 +
>  drivers/scsi/ufs/ufshcd.c  | 10 +++
>  drivers/scsi/ufs/ufshcd.h  |  1 +
>  7 files changed, 207 insertions(+), 74 deletions(-)
>  create mode 100644 Documentation/devicetree/bindings/ufs/ufs-qcom.txt
>  create mode 100644 drivers/scsi/ufs/ufshcd-pltfrm.h
>
> diff --git a/Documentation/devicetree/bindings/ufs/ufs-qcom.txt
> b/Documentation/devicetree/bindings/ufs/ufs-qcom.txt
> new file mode 100644
> index 000..070baf4
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/ufs/ufs-qcom.txt
> @@ -0,0 +1,58 @@
> +* Qualcomm Technologies Inc Universal Flash Storage (UFS) PHY
> +
> +UFSPHY nodes are defined to describe on-chip UFS PHY hardware macro.
> +Each UFS PHY node should have its own node.
> +
> +To bind UFS PHY with UFS host controller, the controller node should
> +contain a phandle reference to UFS PHY node.
> +
> +Required properties:
> +- compatible: compatible list, contains "qcom,ufs-phy-qmp-20nm"
> +   or "qcom,ufs-phy-qmp-14nm" according to the relevant phy 
> in use.
> +- reg   : should contain PHY register address space
> (mandatory),
> +- reg-names : indicates various resources passed to driver (via
> reg proptery) by name.
> +  Required "reg-names" is "phy_mem".
> +- #phy-cells: This property shall be set to 0
> +- vdda-phy-supply   : phandle to main PHY supply for analog domain
> +- vdda-pll-supply   : phandle to PHY PLL and Power-Gen block power supply
> +- clocks : List of phandle and clock specifier pairs
> +- clock-names   : List of clock input name strings sorted in the same
> +   order as the clocks property. "ref_clk_src", "ref_clk",
> +   "tx_iface_clk" & "rx_iface_clk" are mandatory but
> +   "ref_clk_parent" is optional
> +
> +Optional properties:
> +- vdda-phy-max-microamp : specifies max. load that can be drawn from phy
> supply
> +- vdda-pll-max-microamp : specifies max. load that can be drawn from pll
> supply
> +- vddp-ref-clk-supply   : phandle to UFS device ref_clk pad power supply
> +- vddp-ref-clk-max-microamp : specifies max. load that can be drawn from
> this supply
> +- vddp-ref-clk-always-on : specifies if this supply needs to be kept
> always on
> +
> +Example:
> +
> + ufsphy1: ufsphy@0xfc597000 {
> + compatible = "qcom,ufs-phy-qmp-20nm";
> + reg = <0xfc597000 0x800>;
> + reg-names = "phy_mem";
> + #phy-cells = <0>;
> + vdda-phy-supply = <_l4>;
> + vdda-pll-supply = <_l12>;
> + vdda-phy-max-microamp = <5>;
> + vdda-pll-max-microamp = <1000>;
> + clock-names = "ref_clk_src",
> + "ref_clk_parent",
> + "ref_clk",
> + "tx_iface_clk",
> + "rx_iface_clk";
> + clocks = <_rpm clk_ln_bb_clk>,
> + <_gcc clk_pcie_1_phy_ldo >,
> + <_gcc clk_ufs_phy_ldo>,
> + <_gcc clk_gcc_ufs_tx_cfg_clk>,
> + <_gcc clk_gcc_ufs_rx_cfg_clk>;
> + };
> +
> + ufshc@0xfc598000 {
> + ...
> + phys = <>;
> + phy-names = "ufsphy";
> + };
> diff --git a/Documentation/devicetree/bindings/uf

Re: [PATCH v8 4/8] add ufshcd_get_variant ufshcd_set_variant

2015-10-27 Thread Gilad Broner
Reviewed-by: Gilad Broner 

> Signed-off-by: Yaniv Gardi 
>
> ---
>  drivers/scsi/ufs/ufs-qcom.c | 34 +-
>  drivers/scsi/ufs/ufshcd.h   | 21 +
>  2 files changed, 38 insertions(+), 17 deletions(-)
>
> diff --git a/drivers/scsi/ufs/ufs-qcom.c b/drivers/scsi/ufs/ufs-qcom.c
> index 6c23bbf..64c54b7 100644
> --- a/drivers/scsi/ufs/ufs-qcom.c
> +++ b/drivers/scsi/ufs/ufs-qcom.c
> @@ -155,7 +155,7 @@ out:
>
>  static int ufs_qcom_link_startup_post_change(struct ufs_hba *hba)
>  {
> - struct ufs_qcom_host *host = hba->priv;
> + struct ufs_qcom_host *host = ufshcd_get_variant(hba);
>   struct phy *phy = host->generic_phy;
>   u32 tx_lanes;
>   int err = 0;
> @@ -211,7 +211,7 @@ static int ufs_qcom_check_hibern8(struct ufs_hba *hba)
>
>  static int ufs_qcom_power_up_sequence(struct ufs_hba *hba)
>  {
> - struct ufs_qcom_host *host = hba->priv;
> + struct ufs_qcom_host *host = ufshcd_get_variant(hba);
>   struct phy *phy = host->generic_phy;
>   int ret = 0;
>   bool is_rate_B = (UFS_QCOM_LIMIT_HS_RATE == PA_HS_MODE_B)
> @@ -273,7 +273,7 @@ static void ufs_qcom_enable_hw_clk_gating(struct
> ufs_hba *hba)
>
>  static int ufs_qcom_hce_enable_notify(struct ufs_hba *hba, bool status)
>  {
> - struct ufs_qcom_host *host = hba->priv;
> + struct ufs_qcom_host *host = ufshcd_get_variant(hba);
>   int err = 0;
>
>   switch (status) {
> @@ -307,7 +307,7 @@ static int ufs_qcom_hce_enable_notify(struct ufs_hba
> *hba, bool status)
>  static unsigned long
>  ufs_qcom_cfg_timers(struct ufs_hba *hba, u32 gear, u32 hs, u32 rate)
>  {
> - struct ufs_qcom_host *host = hba->priv;
> + struct ufs_qcom_host *host = ufshcd_get_variant(hba);
>   struct ufs_clk_info *clki;
>   u32 core_clk_period_in_ns;
>   u32 tx_clk_cycles_per_us = 0;
> @@ -448,7 +448,7 @@ static int ufs_qcom_link_startup_notify(struct ufs_hba
> *hba, bool status)
>
>  static int ufs_qcom_suspend(struct ufs_hba *hba, enum ufs_pm_op pm_op)
>  {
> - struct ufs_qcom_host *host = hba->priv;
> + struct ufs_qcom_host *host = ufshcd_get_variant(hba);
>   struct phy *phy = host->generic_phy;
>   int ret = 0;
>
> @@ -479,7 +479,7 @@ out:
>
>  static int ufs_qcom_resume(struct ufs_hba *hba, enum ufs_pm_op pm_op)
>  {
> - struct ufs_qcom_host *host = hba->priv;
> + struct ufs_qcom_host *host = ufshcd_get_variant(hba);
>   struct phy *phy = host->generic_phy;
>   int err;
>
> @@ -621,7 +621,7 @@ static int ufs_qcom_pwr_change_notify(struct ufs_hba
> *hba,
>   struct ufs_pa_layer_attr *dev_req_params)
>  {
>   u32 val;
> - struct ufs_qcom_host *host = hba->priv;
> + struct ufs_qcom_host *host = ufshcd_get_variant(hba);
>   struct phy *phy = host->generic_phy;
>   struct ufs_qcom_dev_params ufs_qcom_cap;
>   int ret = 0;
> @@ -696,7 +696,7 @@ out:
>
>  static u32 ufs_qcom_get_ufs_hci_version(struct ufs_hba *hba)
>  {
> - struct ufs_qcom_host *host = hba->priv;
> + struct ufs_qcom_host *host = ufshcd_get_variant(hba);
>
>   if (host->hw_ver.major == 0x1)
>   return UFSHCI_VERSION_11;
> @@ -715,7 +715,7 @@ static u32 ufs_qcom_get_ufs_hci_version(struct ufs_hba
> *hba)
>   */
>  static void ufs_qcom_advertise_quirks(struct ufs_hba *hba)
>  {
> - struct ufs_qcom_host *host = hba->priv;
> + struct ufs_qcom_host *host = ufshcd_get_variant(hba);
>
>   if (host->hw_ver.major == 0x01) {
>   hba->quirks |= UFSHCD_QUIRK_DELAY_BEFORE_DME_CMDS
> @@ -740,7 +740,7 @@ static void ufs_qcom_advertise_quirks(struct ufs_hba
> *hba)
>
>  static void ufs_qcom_set_caps(struct ufs_hba *hba)
>  {
> - struct ufs_qcom_host *host = hba->priv;
> + struct ufs_qcom_host *host = ufshcd_get_variant(hba);
>
>   if (host->hw_ver.major >= 0x2)
>   host->caps = UFS_QCOM_CAP_QUNIPRO;
> @@ -811,7 +811,7 @@ static void ufs_qcom_get_speed_mode(struct
> ufs_pa_layer_attr *p, char *result)
>
>  static int ufs_qcom_setup_clocks(struct ufs_hba *hba, bool on)
>  {
> - struct ufs_qcom_host *host = hba->priv;
> + struct ufs_qcom_host *host = ufshcd_get_variant(hba);
>   int err = 0;
>   int vote = 0;
>
> @@ -866,7 +866,7 @@ show_ufs_to_mem_max_bus_bw(struct device *dev, struct
> device_attribute *attr,
>   char *buf)
>  {
>   struct ufs_hba *hba = dev_get_drvdata(dev);
> - struct ufs_qcom_host *host = hba->priv;
> + struct ufs_qcom_host *host = ufshcd_get_variant(hba);

Re: [PATCH v8 8/8] scsi: ufs-qcom: add QUniPro hardware support and power optimizations

2015-10-27 Thread Gilad Broner
Reviewed-by: Gilad Broner 

> New revisions of UFS host controller supports the new UniPro
> hardware controller (referred as QUniPro). This patch adds
> the support to enable this new UniPro controller hardware.
>
> This change also adds power optimization for bus scaling feature,
> as well as support for HS-G3 power mode.
>
> Signed-off-by: Yaniv Gardi 
>
> ---
>  drivers/scsi/ufs/ufs-qcom.c | 640
> 
>  drivers/scsi/ufs/ufs-qcom.h |  31 ++-
>  drivers/scsi/ufs/ufshcd.c   |   8 +-
>  drivers/scsi/ufs/ufshcd.h   |  27 +-
>  4 files changed, 525 insertions(+), 181 deletions(-)
>
> diff --git a/drivers/scsi/ufs/ufs-qcom.c b/drivers/scsi/ufs/ufs-qcom.c
> index 1633808..4f38d00 100644
> --- a/drivers/scsi/ufs/ufs-qcom.c
> +++ b/drivers/scsi/ufs/ufs-qcom.c
> @@ -44,11 +44,11 @@ enum {
>
>  static struct ufs_qcom_host *ufs_qcom_hosts[MAX_UFS_QCOM_HOSTS];
>
> -static void ufs_qcom_get_speed_mode(struct ufs_pa_layer_attr *p, char
> *result);
> -static int ufs_qcom_get_bus_vote(struct ufs_qcom_host *host,
> - const char *speed_mode);
>  static int ufs_qcom_set_bus_vote(struct ufs_qcom_host *host, int vote);
>  static void ufs_qcom_get_default_testbus_cfg(struct ufs_qcom_host *host);
> +static int ufs_qcom_set_dme_vs_core_clk_ctrl_clear_div(struct ufs_hba
> *hba,
> +u32 clk_cycles);
> +
>  static void ufs_qcom_dump_regs(struct ufs_hba *hba, int offset, int len,
>   char *prefix)
>  {
> @@ -177,6 +177,7 @@ static int ufs_qcom_init_lane_clks(struct
> ufs_qcom_host *host)
>
>   err = ufs_qcom_host_clk_get(dev, "tx_lane1_sync_clk",
>   >tx_l1_sync_clk);
> +
>  out:
>   return err;
>  }
> @@ -209,7 +210,9 @@ static int ufs_qcom_check_hibern8(struct ufs_hba *hba)
>
>   do {
>   err = ufshcd_dme_get(hba,
> - UIC_ARG_MIB(MPHY_TX_FSM_STATE), _fsm_val);
> + UIC_ARG_MIB_SEL(MPHY_TX_FSM_STATE,
> + UIC_ARG_MPHY_TX_GEN_SEL_INDEX(0)),
> + _fsm_val);
>   if (err || tx_fsm_val == TX_FSM_HIBERN8)
>   break;
>
> @@ -223,7 +226,9 @@ static int ufs_qcom_check_hibern8(struct ufs_hba *hba)
>*/
>   if (time_after(jiffies, timeout))
>   err = ufshcd_dme_get(hba,
> - UIC_ARG_MIB(MPHY_TX_FSM_STATE), _fsm_val);
> + UIC_ARG_MIB_SEL(MPHY_TX_FSM_STATE,
> + UIC_ARG_MPHY_TX_GEN_SEL_INDEX(0)),
> + _fsm_val);
>
>   if (err) {
>   dev_err(hba->dev, "%s: unable to get TX_FSM_STATE, err %d\n",
> @@ -237,6 +242,15 @@ static int ufs_qcom_check_hibern8(struct ufs_hba
> *hba)
>   return err;
>  }
>
> +static void ufs_qcom_select_unipro_mode(struct ufs_qcom_host *host)
> +{
> + ufshcd_rmwl(host->hba, QUNIPRO_SEL,
> +ufs_qcom_cap_qunipro(host) ? QUNIPRO_SEL : 0,
> +REG_UFS_CFG1);
> + /* make sure above configuration is applied before we return */
> + mb();
> +}
> +
>  static int ufs_qcom_power_up_sequence(struct ufs_hba *hba)
>  {
>   struct ufs_qcom_host *host = ufshcd_get_variant(hba);
> @@ -251,9 +265,11 @@ static int ufs_qcom_power_up_sequence(struct ufs_hba
> *hba)
>   usleep_range(1000, 1100);
>
>   ret = ufs_qcom_phy_calibrate_phy(phy, is_rate_B);
> +
>   if (ret) {
> - dev_err(hba->dev, "%s: ufs_qcom_phy_calibrate_phy() failed, ret 
> =
> %d\n",
> - __func__, ret);
> + dev_err(hba->dev,
> + "%s: ufs_qcom_phy_calibrate_phy()failed, ret = %d\n",
> + __func__, ret);
>   goto out;
>   }
>
> @@ -274,9 +290,12 @@ static int ufs_qcom_power_up_sequence(struct ufs_hba
> *hba)
>
>   ret = ufs_qcom_phy_is_pcs_ready(phy);
>   if (ret)
> - dev_err(hba->dev, "%s: is_physical_coding_sublayer_ready() 
> failed, ret
> = %d\n",
> + dev_err(hba->dev,
> + "%s: is_physical_coding_sublayer_ready() failed, ret = 
> %d\n",
>   __func__, ret);
>
> + ufs_qcom_select_unipro_mode(host);
> +
>  out:
>   return ret;
>  }
> @@ -299,7 +318,8 @@ static void ufs_qcom_enable_hw_clk_gating(struct
> ufs_hba *hba)
>   mb();
>  }
>
> -static int ufs_qcom_hce_enable_notify(struct ufs_hba *hba, bool status)
> +static int ufs_qcom_hce_enable_notify(struct

Re: [PATCH v8 7/8] scsi: ufs-qcom: add debug prints for test bus

2015-10-27 Thread Gilad Broner
Reviewed-by: Gilad Broner 

> Adds support for configuring and reading the test bus and debug
> registers. This change also adds another vops in order to print the
> debug registers.
>
> Signed-off-by: Yaniv Gardi 
>
> ---
>  drivers/scsi/ufs/ufs-qcom.c | 165
> +++-
>  drivers/scsi/ufs/ufs-qcom.h |  37 +-
>  drivers/scsi/ufs/ufshcd.c   |   2 +
>  drivers/scsi/ufs/ufshcd.h   |   8 +++
>  4 files changed, 208 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/scsi/ufs/ufs-qcom.c b/drivers/scsi/ufs/ufs-qcom.c
> index b275a9a..1633808 100644
> --- a/drivers/scsi/ufs/ufs-qcom.c
> +++ b/drivers/scsi/ufs/ufs-qcom.c
> @@ -23,6 +23,24 @@
>  #include "unipro.h"
>  #include "ufs-qcom.h"
>  #include "ufshci.h"
> +#define UFS_QCOM_DEFAULT_DBG_PRINT_EN\
> + (UFS_QCOM_DBG_PRINT_REGS_EN | UFS_QCOM_DBG_PRINT_TEST_BUS_EN)
> +
> +enum {
> + TSTBUS_UAWM,
> + TSTBUS_UARM,
> + TSTBUS_TXUC,
> + TSTBUS_RXUC,
> + TSTBUS_DFC,
> + TSTBUS_TRLUT,
> + TSTBUS_TMRLUT,
> + TSTBUS_OCSC,
> + TSTBUS_UTP_HCI,
> + TSTBUS_COMBINED,
> + TSTBUS_WRAPPER,
> + TSTBUS_UNIPRO,
> + TSTBUS_MAX,
> +};
>
>  static struct ufs_qcom_host *ufs_qcom_hosts[MAX_UFS_QCOM_HOSTS];
>
> @@ -30,6 +48,15 @@ static void ufs_qcom_get_speed_mode(struct
> ufs_pa_layer_attr *p, char *result);
>  static int ufs_qcom_get_bus_vote(struct ufs_qcom_host *host,
>   const char *speed_mode);
>  static int ufs_qcom_set_bus_vote(struct ufs_qcom_host *host, int vote);
> +static void ufs_qcom_get_default_testbus_cfg(struct ufs_qcom_host *host);
> +static void ufs_qcom_dump_regs(struct ufs_hba *hba, int offset, int len,
> + char *prefix)
> +{
> + print_hex_dump(KERN_ERR, prefix,
> + len > 4 ? DUMP_PREFIX_OFFSET : DUMP_PREFIX_NONE,
> + 16, 4, (void __force *)hba->mmio_base + offset,
> + len * 4, false);
> +}
>
>  static int ufs_qcom_get_connected_tx_lanes(struct ufs_hba *hba, u32
> *tx_lanes)
>  {
> @@ -996,6 +1023,15 @@ static int ufs_qcom_init(struct ufs_hba *hba)
>   if (hba->dev->id < MAX_UFS_QCOM_HOSTS)
>   ufs_qcom_hosts[hba->dev->id] = host;
>
> + host->dbg_print_en |= UFS_QCOM_DEFAULT_DBG_PRINT_EN;
> + ufs_qcom_get_default_testbus_cfg(host);
> + err = ufs_qcom_testbus_config(host);
> + if (err) {
> + dev_warn(dev, "%s: failed to configure the testbus %d\n",
> + __func__, err);
> + err = 0;
> + }
> +
>   goto out;
>
>  out_disable_phy:
> @@ -1025,12 +1061,134 @@ void ufs_qcom_clk_scale_notify(struct ufs_hba
> *hba)
>
>   if (!dev_req_params)
>   return;
> +}
> +
> +static void ufs_qcom_get_default_testbus_cfg(struct ufs_qcom_host *host)
> +{
> + /* provide a legal default configuration */
> + host->testbus.select_major = TSTBUS_UAWM;
> + host->testbus.select_minor = 1;
> +}
> +
> +static bool ufs_qcom_testbus_cfg_is_ok(struct ufs_qcom_host *host)
> +{
> + if (host->testbus.select_major >= TSTBUS_MAX) {
> + dev_err(host->hba->dev,
> + "%s: UFS_CFG1[TEST_BUS_SEL} may not equal 0x%05X\n",
> + __func__, host->testbus.select_major);
> + return false;
> + }
> +
> + /*
> +  * Not performing check for each individual select_major
> +  * mappings of select_minor, since there is no harm in
> +  * configuring a non-existent select_minor
> +  */
> + if (host->testbus.select_minor > 0x1F) {
> + dev_err(host->hba->dev,
> + "%s: 0x%05X is not a legal testbus option\n",
> + __func__, host->testbus.select_minor);
> + return false;
> + }
> +
> + return true;
> +}
> +
> +int ufs_qcom_testbus_config(struct ufs_qcom_host *host)
> +{
> + int reg;
> + int offset;
> + u32 mask = TEST_BUS_SUB_SEL_MASK;
> +
> + if (!host)
> + return -EINVAL;
>
> - ufs_qcom_cfg_timers(hba, dev_req_params->gear_rx,
> - dev_req_params->pwr_rx,
> - dev_req_params->hs_rate);
> + if (!ufs_qcom_testbus_cfg_is_ok(host))
> + return -EPERM;
> +
> + switch (host->testbus.select_major) {
> + case TSTBUS_UAWM:
> + reg = UFS_TEST_BUS_CTRL_0;
> + offset = 24;
> + break;
> + c

Re: [PATCH v8 5/8] scsi: ufs: creates wrapper functions for vops

2015-10-27 Thread Gilad Broner
Reviewed-by: Gilad Broner 

> In order to simplify the code a set of wrapper functions is created
> to test and call each of the variant operations.
>
> Signed-off-by: Yaniv Gardi 
>
> ---
>  drivers/scsi/ufs/ufs-qcom.c |   1 -
>  drivers/scsi/ufs/ufshcd.c   | 104
> +---
>  drivers/scsi/ufs/ufshcd.h   |  98
> +
>  3 files changed, 137 insertions(+), 66 deletions(-)
>
> diff --git a/drivers/scsi/ufs/ufs-qcom.c b/drivers/scsi/ufs/ufs-qcom.c
> index 64c54b7..329ac84 100644
> --- a/drivers/scsi/ufs/ufs-qcom.c
> +++ b/drivers/scsi/ufs/ufs-qcom.c
> @@ -1049,6 +1049,5 @@ static const struct ufs_hba_variant_ops
> ufs_hba_qcom_vops = {
>   .suspend= ufs_qcom_suspend,
>   .resume = ufs_qcom_resume,
>  };
> -EXPORT_SYMBOL(ufs_hba_qcom_vops);
>
>  MODULE_LICENSE("GPL v2");
> diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
> index b0ade73..9e79c33 100644
> --- a/drivers/scsi/ufs/ufshcd.c
> +++ b/drivers/scsi/ufs/ufshcd.c
> @@ -271,10 +271,8 @@ static inline u32 ufshcd_get_intr_mask(struct ufs_hba
> *hba)
>   */
>  static inline u32 ufshcd_get_ufs_version(struct ufs_hba *hba)
>  {
> - if (hba->quirks & UFSHCD_QUIRK_BROKEN_UFS_HCI_VERSION) {
> - if (hba->vops && hba->vops->get_ufs_hci_version)
> - return hba->vops->get_ufs_hci_version(hba);
> - }
> + if (hba->quirks & UFSHCD_QUIRK_BROKEN_UFS_HCI_VERSION)
> + return ufshcd_vops_get_ufs_hci_version(hba);
>
>   return ufshcd_readl(hba, REG_UFS_VERSION);
>  }
> @@ -2473,9 +2471,8 @@ static int ufshcd_change_power_mode(struct ufs_hba
> *hba,
>   dev_err(hba->dev,
>   "%s: power mode change failed %d\n", __func__, ret);
>   } else {
> - if (hba->vops && hba->vops->pwr_change_notify)
> - hba->vops->pwr_change_notify(hba,
> - POST_CHANGE, NULL, pwr_mode);
> + ufshcd_vops_pwr_change_notify(hba, POST_CHANGE, NULL,
> + pwr_mode);
>
>   memcpy(>pwr_info, pwr_mode,
>   sizeof(struct ufs_pa_layer_attr));
> @@ -2495,10 +2492,10 @@ static int ufshcd_config_pwr_mode(struct ufs_hba
> *hba,
>   struct ufs_pa_layer_attr final_params = { 0 };
>   int ret;
>
> - if (hba->vops && hba->vops->pwr_change_notify)
> - hba->vops->pwr_change_notify(hba,
> -  PRE_CHANGE, desired_pwr_mode, _params);
> - else
> + ret = ufshcd_vops_pwr_change_notify(hba, PRE_CHANGE,
> + desired_pwr_mode, _params);
> +
> + if (ret)
>   memcpy(_params, desired_pwr_mode, sizeof(final_params));
>
>   ret = ufshcd_change_power_mode(hba, _params);
> @@ -2647,8 +2644,7 @@ static int ufshcd_hba_enable(struct ufs_hba *hba)
>   /* UniPro link is disabled at this point */
>   ufshcd_set_link_off(hba);
>
> - if (hba->vops && hba->vops->hce_enable_notify)
> - hba->vops->hce_enable_notify(hba, PRE_CHANGE);
> + ufshcd_vops_hce_enable_notify(hba, PRE_CHANGE);
>
>   /* start controller initialization sequence */
>   ufshcd_hba_start(hba);
> @@ -2681,8 +2677,7 @@ static int ufshcd_hba_enable(struct ufs_hba *hba)
>   /* enable UIC related interrupts */
>   ufshcd_enable_intr(hba, UFSHCD_UIC_MASK);
>
> - if (hba->vops && hba->vops->hce_enable_notify)
> - hba->vops->hce_enable_notify(hba, POST_CHANGE);
> + ufshcd_vops_hce_enable_notify(hba, POST_CHANGE);
>
>   return 0;
>  }
> @@ -2735,8 +2730,7 @@ static int ufshcd_link_startup(struct ufs_hba *hba)
>   int retries = DME_LINKSTARTUP_RETRIES;
>
>   do {
> - if (hba->vops && hba->vops->link_startup_notify)
> - hba->vops->link_startup_notify(hba, PRE_CHANGE);
> + ufshcd_vops_link_startup_notify(hba, PRE_CHANGE);
>
>   ret = ufshcd_dme_link_startup(hba);
>
> @@ -2767,11 +2761,9 @@ static int ufshcd_link_startup(struct ufs_hba *hba)
>   }
>
>   /* Include any host controller configuration via UIC commands */
> - if (hba->vops && hba->vops->link_startup_notify) {
> - ret = hba->vops->link_startup_notify(hba, POST_CHANGE);
> - if (ret)
> - goto out;
> - }
> + ret = ufshcd_v

Re: [PATCH v8 3/8] scsi: ufs-qcom: update configuration option of SCSI_UFS_QCOM component

2015-10-27 Thread Gilad Broner
Reviewed-by: Gilad Broner 

> This change is required in order to be able to build the component
> as a module.
>
> Signed-off-by: Yaniv Gardi 
>
> ---
>  drivers/scsi/ufs/Kconfig | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/drivers/scsi/ufs/Kconfig b/drivers/scsi/ufs/Kconfig
> index e945383..5f45307 100644
> --- a/drivers/scsi/ufs/Kconfig
> +++ b/drivers/scsi/ufs/Kconfig
> @@ -72,7 +72,7 @@ config SCSI_UFSHCD_PLATFORM
> If unsure, say N.
>
>  config SCSI_UFS_QCOM
> - bool "QCOM specific hooks to UFS controller platform driver"
> + tristate "QCOM specific hooks to UFS controller platform driver"
>   depends on SCSI_UFSHCD_PLATFORM && ARCH_QCOM
>   select PHY_QCOM_UFS
>   help
> --
> 1.8.5.2
>
> --
> QUALCOMM ISRAEL, on behalf of Qualcomm Innovation Center, Inc. is a member
> of Code Aurora Forum, hosted by The Linux Foundation
> --
> To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
> the body of a message to majord...@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>


-- 
Qualcomm Israel, on behalf of Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH v8 2/8] scsi: ufs-qcom: fix compilation warning if compiled as a module

2015-10-27 Thread Gilad Broner
Reviewed-by: Gilad Broner 

> This change fixes a compilation warning that happens if SCSI_UFS_QCOM
> is compiled as a module.
> Also this patch fixes an error happens when insmod the module:
> "ufs_qcom: module license 'unspecified' taints kernel."
>
> Signed-off-by: Yaniv Gardi 
>
> ---
>  drivers/scsi/ufs/ufs-qcom.c | 7 ++-
>  1 file changed, 6 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/scsi/ufs/ufs-qcom.c b/drivers/scsi/ufs/ufs-qcom.c
> index 4cdffa4..6c23bbf 100644
> --- a/drivers/scsi/ufs/ufs-qcom.c
> +++ b/drivers/scsi/ufs/ufs-qcom.c
> @@ -917,12 +917,15 @@ out:
>
>  #define  ANDROID_BOOT_DEV_MAX30
>  static char android_boot_dev[ANDROID_BOOT_DEV_MAX];
> -static int get_android_boot_dev(char *str)
> +
> +#ifndef MODULE
> +static int __init get_android_boot_dev(char *str)
>  {
>   strlcpy(android_boot_dev, str, ANDROID_BOOT_DEV_MAX);
>   return 1;
>  }
>  __setup("androidboot.bootdevice=", get_android_boot_dev);
> +#endif
>
>  /**
>   * ufs_qcom_init - bind phy with controller
> @@ -1047,3 +1050,5 @@ static const struct ufs_hba_variant_ops
> ufs_hba_qcom_vops = {
>   .resume = ufs_qcom_resume,
>  };
>  EXPORT_SYMBOL(ufs_hba_qcom_vops);
> +
> +MODULE_LICENSE("GPL v2");
> --
> 1.8.5.2
>
> --
> QUALCOMM ISRAEL, on behalf of Qualcomm Innovation Center, Inc. is a member
> of Code Aurora Forum, hosted by The Linux Foundation
> --
> To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
> the body of a message to majord...@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>


-- 
Qualcomm Israel, on behalf of Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH v8 1/8] phy: qcom-ufs: fix build error when the component is built as a module

2015-10-27 Thread Gilad Broner
Reviewed-by: Gilad Broner 

> Export the following functions in order to avoid build errors
> when the component PHY_QCOM_UFS is compiled as a module:
>
> ERROR: "ufs_qcom_phy_disable_ref_clk"
>   [drivers/scsi/ufs/ufs-qcom.ko] undefined!
> ERROR: "ufs_qcom_phy_enable_ref_clk"
>   [drivers/scsi/ufs/ufs-qcom.ko] undefined!
> ERROR: "ufs_qcom_phy_is_pcs_ready"
>   [drivers/scsi/ufs/ufs-qcom.ko] undefined!
> ERROR: "ufs_qcom_phy_disable_iface_clk"
>   [drivers/scsi/ufs/ufs-qcom.ko] undefined!
> ERROR: "ufs_qcom_phy_start_serdes"
>   [drivers/scsi/ufs/ufs-qcom.ko] undefined!
> ERROR: "ufs_qcom_phy_calibrate_phy"
>   [drivers/scsi/ufs/ufs-qcom.ko] undefined!
> ERROR: "ufs_qcom_phy_enable_dev_ref_clk"
>   [drivers/scsi/ufs/ufs-qcom.ko] undefined!
> ERROR: "ufs_qcom_phy_set_tx_lane_enable"
>   [drivers/scsi/ufs/ufs-qcom.ko] undefined!
> ERROR: "ufs_qcom_phy_disable_dev_ref_clk"
>   [drivers/scsi/ufs/ufs-qcom.ko] undefined!
> ERROR: "ufs_qcom_phy_save_controller_version"
>   [drivers/scsi/ufs/ufs-qcom.ko] undefined!
> ERROR: "ufs_qcom_phy_enable_iface_clk"
>   [drivers/scsi/ufs/ufs-qcom.ko] undefined!
> make[1]: *** [__modpost] Error 1
>
> Signed-off-by: Yaniv Gardi 
>
> ---
>  drivers/phy/phy-qcom-ufs.c | 11 +++
>  1 file changed, 11 insertions(+)
>
> diff --git a/drivers/phy/phy-qcom-ufs.c b/drivers/phy/phy-qcom-ufs.c
> index f9c618f..6140a8b 100644
> --- a/drivers/phy/phy-qcom-ufs.c
> +++ b/drivers/phy/phy-qcom-ufs.c
> @@ -432,6 +432,7 @@ out_disable_src:
>  out:
>   return ret;
>  }
> +EXPORT_SYMBOL_GPL(ufs_qcom_phy_enable_ref_clk);
>
>  static
>  int ufs_qcom_phy_disable_vreg(struct phy *phy,
> @@ -474,6 +475,7 @@ void ufs_qcom_phy_disable_ref_clk(struct phy
> *generic_phy)
>   phy->is_ref_clk_enabled = false;
>   }
>  }
> +EXPORT_SYMBOL_GPL(ufs_qcom_phy_disable_ref_clk);
>
>  #define UFS_REF_CLK_EN   (1 << 5)
>
> @@ -517,11 +519,13 @@ void ufs_qcom_phy_enable_dev_ref_clk(struct phy
> *generic_phy)
>  {
>   ufs_qcom_phy_dev_ref_clk_ctrl(generic_phy, true);
>  }
> +EXPORT_SYMBOL_GPL(ufs_qcom_phy_enable_dev_ref_clk);
>
>  void ufs_qcom_phy_disable_dev_ref_clk(struct phy *generic_phy)
>  {
>   ufs_qcom_phy_dev_ref_clk_ctrl(generic_phy, false);
>  }
> +EXPORT_SYMBOL_GPL(ufs_qcom_phy_disable_dev_ref_clk);
>
>  /* Turn ON M-PHY RMMI interface clocks */
>  int ufs_qcom_phy_enable_iface_clk(struct phy *generic_phy)
> @@ -550,6 +554,7 @@ int ufs_qcom_phy_enable_iface_clk(struct phy
> *generic_phy)
>  out:
>   return ret;
>  }
> +EXPORT_SYMBOL_GPL(ufs_qcom_phy_enable_iface_clk);
>
>  /* Turn OFF M-PHY RMMI interface clocks */
>  void ufs_qcom_phy_disable_iface_clk(struct phy *generic_phy)
> @@ -562,6 +567,7 @@ void ufs_qcom_phy_disable_iface_clk(struct phy
> *generic_phy)
>   phy->is_iface_clk_enabled = false;
>   }
>  }
> +EXPORT_SYMBOL_GPL(ufs_qcom_phy_disable_iface_clk);
>
>  int ufs_qcom_phy_start_serdes(struct phy *generic_phy)
>  {
> @@ -578,6 +584,7 @@ int ufs_qcom_phy_start_serdes(struct phy *generic_phy)
>
>   return ret;
>  }
> +EXPORT_SYMBOL_GPL(ufs_qcom_phy_start_serdes);
>
>  int ufs_qcom_phy_set_tx_lane_enable(struct phy *generic_phy, u32
> tx_lanes)
>  {
> @@ -595,6 +602,7 @@ int ufs_qcom_phy_set_tx_lane_enable(struct phy
> *generic_phy, u32 tx_lanes)
>
>   return ret;
>  }
> +EXPORT_SYMBOL_GPL(ufs_qcom_phy_set_tx_lane_enable);
>
>  void ufs_qcom_phy_save_controller_version(struct phy *generic_phy,
> u8 major, u16 minor, u16 step)
> @@ -605,6 +613,7 @@ void ufs_qcom_phy_save_controller_version(struct phy
> *generic_phy,
>   ufs_qcom_phy->host_ctrl_rev_minor = minor;
>   ufs_qcom_phy->host_ctrl_rev_step = step;
>  }
> +EXPORT_SYMBOL_GPL(ufs_qcom_phy_save_controller_version);
>
>  int ufs_qcom_phy_calibrate_phy(struct phy *generic_phy, bool is_rate_B)
>  {
> @@ -625,6 +634,7 @@ int ufs_qcom_phy_calibrate_phy(struct phy
> *generic_phy, bool is_rate_B)
>
>   return ret;
>  }
> +EXPORT_SYMBOL_GPL(ufs_qcom_phy_calibrate_phy);
>
>  int ufs_qcom_phy_remove(struct phy *generic_phy,
>   struct ufs_qcom_phy *ufs_qcom_phy)
> @@ -662,6 +672,7 @@ int ufs_qcom_phy_is_pcs_ready(struct phy *generic_phy)
>   return ufs_qcom_phy->phy_spec_ops->
>   is_physical_coding_sublayer_ready(ufs_qcom_phy);
>  }
> +EXPORT_SYMBOL_GPL(ufs_qcom_phy_is_pcs_ready);
>
>  int ufs_qcom_phy_power_on(struct phy *gen

Re: [PATCH v5 15/15] scsi: ufs: add wrapper for retrying sending query attribute

2015-10-27 Thread Gilad Broner
Reviewed-by: Gilad Broner 

> Sometimes queries from the device might return a failure so it is
> recommended to retry sending the query, before giving up.
> This change adds a wrapper to retry sending a query attribute,
> in cases where we need to wait longer, before we continue,
> or before reporting a failure.
>
> Signed-off-by: Yaniv Gardi 
>
> ---
>  drivers/scsi/ufs/ufshcd.c | 51
> ---
>  1 file changed, 44 insertions(+), 7 deletions(-)
>
> diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
> index ec90504..1d1e681 100644
> --- a/drivers/scsi/ufs/ufshcd.c
> +++ b/drivers/scsi/ufs/ufshcd.c
> @@ -1824,6 +1824,43 @@ out:
>  }
>
>  /**
> + * ufshcd_query_attr_retry() - API function for sending query
> + * attribute with retries
> + * @hba: per-adapter instance
> + * @opcode: attribute opcode
> + * @idn: attribute idn to access
> + * @index: index field
> + * @selector: selector field
> + * @attr_val: the attribute value after the query request
> + * completes
> + *
> + * Returns 0 for success, non-zero in case of failure
> +*/
> +static 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 ret = 0;
> + u32 retries;
> +
> +  for (retries = QUERY_REQ_RETRIES; retries > 0; retries--) {
> + ret = ufshcd_query_attr(hba, opcode, idn, index,
> + selector, attr_val);
> + if (ret)
> + dev_dbg(hba->dev, "%s: failed with error %d, retries 
> %d\n",
> + __func__, ret, retries);
> + else
> + break;
> + }
> +
> + if (ret)
> + dev_err(hba->dev,
> + "%s: query attribute, idn %d, failed with error %d 
> after %d
> retires\n",
> + __func__, idn, ret, QUERY_REQ_RETRIES);
> + return ret;
> +}
> +
> +/**
>   * ufshcd_query_descriptor - API function for sending descriptor requests
>   * hba: per-adapter instance
>   * opcode: attribute opcode
> @@ -3404,7 +3441,7 @@ static int ufshcd_disable_ee(struct ufs_hba *hba,
> u16 mask)
>
>   val = hba->ee_ctrl_mask & ~mask;
>   val &= 0x; /* 2 bytes */
> - err = ufshcd_query_attr(hba, UPIU_QUERY_OPCODE_WRITE_ATTR,
> + err = ufshcd_query_attr_retry(hba, UPIU_QUERY_OPCODE_WRITE_ATTR,
>   QUERY_ATTR_IDN_EE_CONTROL, 0, 0, );
>   if (!err)
>   hba->ee_ctrl_mask &= ~mask;
> @@ -3432,7 +3469,7 @@ static int ufshcd_enable_ee(struct ufs_hba *hba, u16
> mask)
>
>   val = hba->ee_ctrl_mask | mask;
>   val &= 0x; /* 2 bytes */
> - err = ufshcd_query_attr(hba, UPIU_QUERY_OPCODE_WRITE_ATTR,
> + err = ufshcd_query_attr_retry(hba, UPIU_QUERY_OPCODE_WRITE_ATTR,
>   QUERY_ATTR_IDN_EE_CONTROL, 0, 0, );
>   if (!err)
>   hba->ee_ctrl_mask |= mask;
> @@ -3538,7 +3575,7 @@ static void  ufshcd_force_reset_auto_bkops(struct
> ufs_hba *hba)
>
>  static inline int ufshcd_get_bkops_status(struct ufs_hba *hba, u32
> *status)
>  {
> - return ufshcd_query_attr(hba, UPIU_QUERY_OPCODE_READ_ATTR,
> + return ufshcd_query_attr_retry(hba, UPIU_QUERY_OPCODE_READ_ATTR,
>   QUERY_ATTR_IDN_BKOPS_STATUS, 0, 0, status);
>  }
>
> @@ -3601,7 +3638,7 @@ static int ufshcd_urgent_bkops(struct ufs_hba *hba)
>
>  static inline int ufshcd_get_ee_status(struct ufs_hba *hba, u32 *status)
>  {
> - return ufshcd_query_attr(hba, UPIU_QUERY_OPCODE_READ_ATTR,
> + return ufshcd_query_attr_retry(hba, UPIU_QUERY_OPCODE_READ_ATTR,
>   QUERY_ATTR_IDN_EE_STATUS, 0, 0, status);
>  }
>
> @@ -4355,9 +4392,9 @@ static void ufshcd_init_icc_levels(struct ufs_hba
> *hba)
>   dev_dbg(hba->dev, "%s: setting icc_level 0x%x",
>   __func__, hba->init_prefetch_data.icc_level);
>
> - ret = ufshcd_query_attr(hba, UPIU_QUERY_OPCODE_WRITE_ATTR,
> - QUERY_ATTR_IDN_ACTIVE_ICC_LVL, 0, 0,
> - >init_prefetch_data.icc_level);
> + ret = ufshcd_query_attr_retry(hba, UPIU_QUERY_OPCODE_WRITE_ATTR,
> + QUERY_ATTR_IDN_ACTIVE_ICC_LVL, 0, 0,
> + >init_prefetch_data.icc_level);
>
>   if (ret)
>   dev_err(hba->dev,
> --
> 1.8.5.2
>
> --
> QUALCOMM ISRAEL, on behalf of Qualcomm Innovation Center, Inc. is a member
> of Code Aurora Forum, hosted by The Linux Foundation
&g

Re: [PATCH v5 10/15] scsi: ufs: fix error recovery after the hibern8 exit failure

2015-10-27 Thread Gilad Broner
Reviewed-by: Gilad Broner 

> Hibern8 exit can be called from 3 different context:
> - ufshcd_hibern8_exit_work
> - ufshcd_ungate_work
> - runtime/system resume
>
> If hibern8 exit fails for some reason then we try to bring the link to
> active state by link startup but this recovery mechanism results into
> deadlock or errors from first 2 context listed above. This change fixes
> the recovery by adding proper error handling mechanism.
>
> Signed-off-by: Subhash Jadavani 
> Signed-off-by: Yaniv Gardi 
>
> ---
>  drivers/scsi/ufs/ufshcd.c | 58
> +++
>  1 file changed, 53 insertions(+), 5 deletions(-)
>
> diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
> index ed134d6..60ba729 100644
> --- a/drivers/scsi/ufs/ufshcd.c
> +++ b/drivers/scsi/ufs/ufshcd.c
> @@ -610,6 +610,11 @@ int ufshcd_hold(struct ufs_hba *hba, bool async)
>   spin_lock_irqsave(hba->host->host_lock, flags);
>   hba->clk_gating.active_reqs++;
>
> + if (ufshcd_eh_in_progress(hba)) {
> + spin_unlock_irqrestore(hba->host->host_lock, flags);
> + return 0;
> + }
> +
>  start:
>   switch (hba->clk_gating.state) {
>   case CLKS_ON:
> @@ -725,7 +730,8 @@ static void __ufshcd_release(struct ufs_hba *hba)
>   if (hba->clk_gating.active_reqs || hba->clk_gating.is_suspended
>   || hba->ufshcd_state != UFSHCD_STATE_OPERATIONAL
>   || hba->lrb_in_use || hba->outstanding_tasks
> - || hba->active_uic_cmd || hba->uic_async_done)
> + || hba->active_uic_cmd || hba->uic_async_done
> + || ufshcd_eh_in_progress(hba))
>   return;
>
>   hba->clk_gating.state = REQ_CLKS_OFF;
> @@ -1363,6 +1369,13 @@ static int ufshcd_queuecommand(struct Scsi_Host
> *host, struct scsi_cmnd *cmd)
>   cmd->scsi_done(cmd);
>   goto out_unlock;
>   }
> +
> + /* if error handling is in progress, don't issue commands */
> + if (ufshcd_eh_in_progress(hba)) {
> + set_host_byte(cmd, DID_ERROR);
> + cmd->scsi_done(cmd);
> + goto out_unlock;
> + }
>   spin_unlock_irqrestore(hba->host->host_lock, flags);
>
>   /* acquire the tag to make sure device cmds don't use it */
> @@ -2393,6 +2406,31 @@ out:
>   return ret;
>  }
>
> +static int ufshcd_link_recovery(struct ufs_hba *hba)
> +{
> + int ret;
> + unsigned long flags;
> +
> + spin_lock_irqsave(hba->host->host_lock, flags);
> + hba->ufshcd_state = UFSHCD_STATE_RESET;
> + ufshcd_set_eh_in_progress(hba);
> + spin_unlock_irqrestore(hba->host->host_lock, flags);
> +
> + ret = ufshcd_host_reset_and_restore(hba);
> +
> + spin_lock_irqsave(hba->host->host_lock, flags);
> + if (ret)
> + hba->ufshcd_state = UFSHCD_STATE_ERROR;
> + ufshcd_clear_eh_in_progress(hba);
> + spin_unlock_irqrestore(hba->host->host_lock, flags);
> +
> + if (ret)
> + dev_err(hba->dev, "%s: link recovery failed, err %d",
> + __func__, ret);
> +
> + return ret;
> +}
> +
>  static int __ufshcd_uic_hibern8_enter(struct ufs_hba *hba)
>  {
>   int ret;
> @@ -2401,10 +2439,18 @@ static int __ufshcd_uic_hibern8_enter(struct
> ufs_hba *hba)
>   uic_cmd.command = UIC_CMD_DME_HIBER_ENTER;
>   ret = ufshcd_uic_pwr_ctrl(hba, _cmd);
>
> - if (ret)
> + if (ret) {
>   dev_err(hba->dev, "%s: hibern8 enter failed. ret = %d\n",
>   __func__, ret);
>
> + /*
> +  * If link recovery fails then return error so that caller
> +  * don't retry the hibern8 enter again.
> +  */
> + if (ufshcd_link_recovery(hba))
> + ret = -ENOLINK;
> + }
> +
>   return ret;
>  }
>
> @@ -2429,8 +2475,9 @@ static int ufshcd_uic_hibern8_exit(struct ufs_hba
> *hba)
>   uic_cmd.command = UIC_CMD_DME_HIBER_EXIT;
>   ret = ufshcd_uic_pwr_ctrl(hba, _cmd);
>   if (ret) {
> - ufshcd_set_link_off(hba);
> - ret = ufshcd_host_reset_and_restore(hba);
> + dev_err(hba->dev, "%s: hibern8 exit failed. ret = %d\n",
> + __func__, ret);
> + ret = ufshcd_link_recovery(hba);
>   }
>
>   return ret;
> @@ -4382,7 +4429,6 @@ static int ufshcd_probe_hba(struct ufs_hba *hba)
>   /* UFS device is also active now */
>   ufshcd_set_ufs_dev_

Re: [PATCH v5 12/15] scsi: ufs: reduce the interrupts for power mode change requests

2015-10-27 Thread Gilad Broner
Reviewed-by: Gilad Broner 

> DME commands such as Hibern8 enter/exit and gear switch generate 2
> completion interrupts, one for confirmation that command is received
> by local UniPro and 2nd one is the final confirmation after communication
> with remote UniPro. Currently both of these completions are registered
> as interrupt events which is not quite necessary and instead we can
> just wait for the interrupt of 2nd completion, this should reduce
> the number of interrupts and could reduce the unnecessary CPU wakeups
> to handle extra interrupts.
>
> Signed-off-by: Subhash Jadavani 
> Signed-off-by: Yaniv Gardi 
>
> ---
>  drivers/scsi/ufs/ufshcd.c | 41 +++--
>  1 file changed, 27 insertions(+), 14 deletions(-)
>
> diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
> index 889a7be..24a879d 100644
> --- a/drivers/scsi/ufs/ufshcd.c
> +++ b/drivers/scsi/ufs/ufshcd.c
> @@ -987,13 +987,15 @@ ufshcd_wait_for_uic_cmd(struct ufs_hba *hba, struct
> uic_command *uic_cmd)
>   * __ufshcd_send_uic_cmd - Send UIC commands and retrieve the result
>   * @hba: per adapter instance
>   * @uic_cmd: UIC command
> + * @completion: initialize the completion only if this is set to true
>   *
>   * Identical to ufshcd_send_uic_cmd() expect mutex. Must be called
>   * with mutex held and host_lock locked.
>   * Returns 0 only if success.
>   */
>  static int
> -__ufshcd_send_uic_cmd(struct ufs_hba *hba, struct uic_command *uic_cmd)
> +__ufshcd_send_uic_cmd(struct ufs_hba *hba, struct uic_command *uic_cmd,
> +   bool completion)
>  {
>   if (!ufshcd_ready_for_uic_cmd(hba)) {
>   dev_err(hba->dev,
> @@ -1001,7 +1003,8 @@ __ufshcd_send_uic_cmd(struct ufs_hba *hba, struct
> uic_command *uic_cmd)
>   return -EIO;
>   }
>
> - init_completion(_cmd->done);
> + if (completion)
> + init_completion(_cmd->done);
>
>   ufshcd_dispatch_uic_cmd(hba, uic_cmd);
>
> @@ -1026,7 +1029,7 @@ ufshcd_send_uic_cmd(struct ufs_hba *hba, struct
> uic_command *uic_cmd)
>   ufshcd_add_delay_before_dme_cmd(hba);
>
>   spin_lock_irqsave(hba->host->host_lock, flags);
> - ret = __ufshcd_send_uic_cmd(hba, uic_cmd);
> + ret = __ufshcd_send_uic_cmd(hba, uic_cmd, true);
>   spin_unlock_irqrestore(hba->host->host_lock, flags);
>   if (!ret)
>   ret = ufshcd_wait_for_uic_cmd(hba, uic_cmd);
> @@ -2347,6 +2350,7 @@ static int ufshcd_uic_pwr_ctrl(struct ufs_hba *hba,
> struct uic_command *cmd)
>   unsigned long flags;
>   u8 status;
>   int ret;
> + bool reenable_intr = false;
>
>   mutex_lock(>uic_cmd_mutex);
>   init_completion(_async_done);
> @@ -2354,15 +2358,17 @@ static int ufshcd_uic_pwr_ctrl(struct ufs_hba
> *hba, struct uic_command *cmd)
>
>   spin_lock_irqsave(hba->host->host_lock, flags);
>   hba->uic_async_done = _async_done;
> - ret = __ufshcd_send_uic_cmd(hba, cmd);
> - spin_unlock_irqrestore(hba->host->host_lock, flags);
> - if (ret) {
> - dev_err(hba->dev,
> - "pwr ctrl cmd 0x%x with mode 0x%x uic error %d\n",
> - cmd->command, cmd->argument3, ret);
> - goto out;
> + if (ufshcd_readl(hba, REG_INTERRUPT_ENABLE) & UIC_COMMAND_COMPL) {
> + ufshcd_disable_intr(hba, UIC_COMMAND_COMPL);
> + /*
> +  * Make sure UIC command completion interrupt is disabled before
> +  * issuing UIC command.
> +  */
> + wmb();
> + reenable_intr = true;
>   }
> - ret = ufshcd_wait_for_uic_cmd(hba, cmd);
> + ret = __ufshcd_send_uic_cmd(hba, cmd, false);
> + spin_unlock_irqrestore(hba->host->host_lock, flags);
>   if (ret) {
>   dev_err(hba->dev,
>   "pwr ctrl cmd 0x%x with mode 0x%x uic error %d\n",
> @@ -2388,7 +2394,10 @@ static int ufshcd_uic_pwr_ctrl(struct ufs_hba *hba,
> struct uic_command *cmd)
>   }
>  out:
>   spin_lock_irqsave(hba->host->host_lock, flags);
> + hba->active_uic_cmd = NULL;
>   hba->uic_async_done = NULL;
> + if (reenable_intr)
> + ufshcd_enable_intr(hba, UIC_COMMAND_COMPL);
>   spin_unlock_irqrestore(hba->host->host_lock, flags);
>   mutex_unlock(>uic_cmd_mutex);
>
> @@ -3813,16 +3822,20 @@ static void ufshcd_sl_intr(struct ufs_hba *hba,
> u32 intr_status)
>   */
>  static irqreturn_t ufshcd_intr(int irq, void *__hba)
>  {
> - u32 intr_status;
> +

Re: [PATCH v5 08/15] scsi: ufs: add retries to dme_peer get and set attribute

2015-10-27 Thread Gilad Broner
Reviewed-by: Gilad Broner 

> The dme_peer get/set attribute commands are prone to errors, therefore
> we add three retries for the UIC command sending.
> Error code returned from ufshcd_send_uic_cmd() is checked, and unless
> it was successful or the retries have finished, another command will be
> sent.
>
> Signed-off-by: Lee Susman 
> Signed-off-by: Yaniv Gardi 
>
> ---
>  drivers/scsi/ufs/ufshcd.c | 40 +---
>  1 file changed, 29 insertions(+), 11 deletions(-)
>
> diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
> index 8a04691..5005d12 100644
> --- a/drivers/scsi/ufs/ufshcd.c
> +++ b/drivers/scsi/ufs/ufshcd.c
> @@ -70,6 +70,9 @@
>  /* Task management command timeout */
>  #define TM_CMD_TIMEOUT   100 /* msecs */
>
> +/* maximum number of retries for a general UIC command  */
> +#define UFS_UIC_COMMAND_RETRIES 3
> +
>  /* maximum number of link-startup retries */
>  #define DME_LINKSTARTUP_RETRIES 3
>
> @@ -2185,6 +2188,7 @@ int ufshcd_dme_set_attr(struct ufs_hba *hba, u32
> attr_sel,
>   };
>   const char *set = action[!!peer];
>   int ret;
> + int retries = UFS_UIC_COMMAND_RETRIES;
>
>   uic_cmd.command = peer ?
>   UIC_CMD_DME_PEER_SET : UIC_CMD_DME_SET;
> @@ -2192,10 +2196,18 @@ int ufshcd_dme_set_attr(struct ufs_hba *hba, u32
> attr_sel,
>   uic_cmd.argument2 = UIC_ARG_ATTR_TYPE(attr_set);
>   uic_cmd.argument3 = mib_val;
>
> - ret = ufshcd_send_uic_cmd(hba, _cmd);
> - if (ret)
> - dev_err(hba->dev, "%s: attr-id 0x%x val 0x%x error code %d\n",
> - set, UIC_GET_ATTR_ID(attr_sel), mib_val, ret);
> + do {
> + /* for peer attributes we retry upon failure */
> + ret = ufshcd_send_uic_cmd(hba, _cmd);
> + if (ret)
> + dev_dbg(hba->dev, "%s: attr-id 0x%x val 0x%x error code 
> %d\n",
> + set, UIC_GET_ATTR_ID(attr_sel), mib_val, ret);
> + } while (ret && peer && --retries);
> +
> + if (!retries)
> + dev_err(hba->dev, "%s: attr-id 0x%x val 0x%x failed %d 
> retries\n",
> + set, UIC_GET_ATTR_ID(attr_sel), mib_val,
> + retries);
>
>   return ret;
>  }
> @@ -2220,6 +2232,7 @@ int ufshcd_dme_get_attr(struct ufs_hba *hba, u32
> attr_sel,
>   };
>   const char *get = action[!!peer];
>   int ret;
> + int retries = UFS_UIC_COMMAND_RETRIES;
>   struct ufs_pa_layer_attr orig_pwr_info;
>   struct ufs_pa_layer_attr temp_pwr_info;
>   bool pwr_mode_change = false;
> @@ -2250,14 +2263,19 @@ int ufshcd_dme_get_attr(struct ufs_hba *hba, u32
> attr_sel,
>   UIC_CMD_DME_PEER_GET : UIC_CMD_DME_GET;
>   uic_cmd.argument1 = attr_sel;
>
> - ret = ufshcd_send_uic_cmd(hba, _cmd);
> - if (ret) {
> - dev_err(hba->dev, "%s: attr-id 0x%x error code %d\n",
> - get, UIC_GET_ATTR_ID(attr_sel), ret);
> - goto out;
> - }
> + do {
> + /* for peer attributes we retry upon failure */
> + ret = ufshcd_send_uic_cmd(hba, _cmd);
> + if (ret)
> + dev_dbg(hba->dev, "%s: attr-id 0x%x error code %d\n",
> + get, UIC_GET_ATTR_ID(attr_sel), ret);
> + } while (ret && peer && --retries);
> +
> + if (!retries)
> + dev_err(hba->dev, "%s: attr-id 0x%x failed %d retries\n",
> + get, UIC_GET_ATTR_ID(attr_sel), retries);
>
> - if (mib_val)
> + if (mib_val && !ret)
>   *mib_val = uic_cmd.argument3;
>
>   if (peer && (hba->quirks & UFSHCD_QUIRK_DME_PEER_ACCESS_AUTO_MODE)
> --
> 1.8.5.2
>
> --
> QUALCOMM ISRAEL, on behalf of Qualcomm Innovation Center, Inc. is a member
> of Code Aurora Forum, hosted by The Linux Foundation
> --
> To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
> the body of a message to majord...@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>


-- 
Qualcomm Israel, on behalf of Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH v5 09/15] scsi: ufs: add retries for hibern8 enter

2015-10-27 Thread Gilad Broner
Reviewed-by: Gilad Broner 

> If hibern8 enter command fails then UFS link state may be unknown which
> may result into timeout of all the commands issued after failure.
>
> This change does 2 things (for pre-defined number of retry counts) after
> hibern8 enter failure:
> 1. Recovers the UFS link to active state
> 2. If link is recovered to active state, tries to put the UFS link in
>hibern8 enter again until retry count expires.
>
> Signed-off-by: Subhash Jadavani 
> Signed-off-by: Yaniv Gardi 
>
> ---
>  drivers/scsi/ufs/ufshcd.c | 26 --
>  1 file changed, 24 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
> index 5005d12..ed134d6 100644
> --- a/drivers/scsi/ufs/ufshcd.c
> +++ b/drivers/scsi/ufs/ufshcd.c
> @@ -76,6 +76,9 @@
>  /* maximum number of link-startup retries */
>  #define DME_LINKSTARTUP_RETRIES 3
>
> +/* Maximum retries for Hibern8 enter */
> +#define UIC_HIBERN8_ENTER_RETRIES 3
> +
>  /* maximum number of reset retries before giving up */
>  #define MAX_HOST_RESET_RETRIES 5
>
> @@ -2390,13 +2393,32 @@ out:
>   return ret;
>  }
>
> -static int ufshcd_uic_hibern8_enter(struct ufs_hba *hba)
> +static int __ufshcd_uic_hibern8_enter(struct ufs_hba *hba)
>  {
> + int ret;
>   struct uic_command uic_cmd = {0};
>
>   uic_cmd.command = UIC_CMD_DME_HIBER_ENTER;
> + ret = ufshcd_uic_pwr_ctrl(hba, _cmd);
> +
> + if (ret)
> + dev_err(hba->dev, "%s: hibern8 enter failed. ret = %d\n",
> + __func__, ret);
> +
> + return ret;
> +}
> +
> +static int ufshcd_uic_hibern8_enter(struct ufs_hba *hba)
> +{
> + int ret = 0, retries;
>
> - return ufshcd_uic_pwr_ctrl(hba, _cmd);
> + for (retries = UIC_HIBERN8_ENTER_RETRIES; retries > 0; retries--) {
> + ret = __ufshcd_uic_hibern8_enter(hba);
> + if (!ret || ret == -ENOLINK)
> + goto out;
> + }
> +out:
> + return ret;
>  }
>
>  static int ufshcd_uic_hibern8_exit(struct ufs_hba *hba)
> --
> 1.8.5.2
>
> --
> QUALCOMM ISRAEL, on behalf of Qualcomm Innovation Center, Inc. is a member
> of Code Aurora Forum, hosted by The Linux Foundation
> --
> To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
> the body of a message to majord...@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>


-- 
Qualcomm Israel, on behalf of Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH v5 06/15] scsi: ufs: avoid exception event handler racing with PM callbacks

2015-10-27 Thread Gilad Broner
Reviewed-by: Gilad Broner 

> If device raises the exception event in the response to the commands
> sent during the runtime/system PM callbacks, exception event handler
> might run in parallel with PM callbacks and may see unclocked register
> accesses. This change fixes this issue by not scheduling the exception
> event handler while PM callbacks are running.
>
> Signed-off-by: Subhash Jadavani 
> Signed-off-by: Yaniv Gardi 
>
> ---
>  drivers/scsi/ufs/ufshcd.c | 15 ++-
>  1 file changed, 14 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
> index 573a8cb..0e54183 100644
> --- a/drivers/scsi/ufs/ufshcd.c
> +++ b/drivers/scsi/ufs/ufshcd.c
> @@ -3145,7 +3145,20 @@ ufshcd_transfer_rsp_status(struct ufs_hba *hba,
> struct ufshcd_lrb *lrbp)
>   scsi_status = result & MASK_SCSI_STATUS;
>   result = ufshcd_scsi_cmd_status(lrbp, scsi_status);
>
> - if (ufshcd_is_exception_event(lrbp->ucd_rsp_ptr))
> + /*
> +  * Currently we are only supporting BKOPs exception
> +  * events hence we can ignore BKOPs exception event
> +  * during power management callbacks. BKOPs exception
> +  * event is not expected to be raised in runtime suspend
> +  * callback as it allows the urgent bkops.
> +  * During system suspend, we are anyway forcefully
> +  * disabling the bkops and if urgent bkops is needed
> +  * it will be enabled on system resume. Long term
> +  * solution could be to abort the system suspend if
> +  * UFS device needs urgent BKOPs.
> +  */
> + if (!hba->pm_op_in_progress &&
> + ufshcd_is_exception_event(lrbp->ucd_rsp_ptr))
>   schedule_work(>eeh_work);
>   break;
>   case UPIU_TRANSACTION_REJECT_UPIU:
> --
> 1.8.5.2
>
> --
> QUALCOMM ISRAEL, on behalf of Qualcomm Innovation Center, Inc. is a member
> of Code Aurora Forum, hosted by The Linux Foundation
> --
> To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
> the body of a message to majord...@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>


-- 
Qualcomm Israel, on behalf of Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH v5 05/15] scsi: ufs: increase fDeviceInit query response timeout

2015-10-27 Thread Gilad Broner
Reviewed-by: Gilad Broner 

> fDeviceInit query response time for some devices is too long that default
> query request timeout of 100ms may not be enough. Experiments show that
> fDeviceInit response sometimes takes 500ms so to be on safer side this
> change sets the timeout to 600ms. Without this change, we might
> unnecessarily have to retry fDeviceInit query requests multiple times and
> each query request timeout prints one error message.
>
> Signed-off-by: Subhash Jadavani 
> Signed-off-by: Yaniv Gardi 
>
> ---
>  drivers/scsi/ufs/ufshcd.c | 12 +++-
>  1 file changed, 11 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
> index e0b8755..573a8cb 100644
> --- a/drivers/scsi/ufs/ufshcd.c
> +++ b/drivers/scsi/ufs/ufshcd.c
> @@ -58,6 +58,12 @@
>  #define QUERY_REQ_RETRIES 10
>  /* Query request timeout */
>  #define QUERY_REQ_TIMEOUT 30 /* msec */
> +/*
> + * Query request timeout for fDeviceInit flag
> + * fDeviceInit query response time for some devices is too large that
> default
> + * QUERY_REQ_TIMEOUT may not be enough for such devices.
> + */
> +#define QUERY_FDEVICEINIT_REQ_TIMEOUT 600 /* msec */
>
>  /* Task management command timeout */
>  #define TM_CMD_TIMEOUT   100 /* msecs */
> @@ -1651,6 +1657,7 @@ static int ufshcd_query_flag(struct ufs_hba *hba,
> enum query_opcode opcode,
>   struct ufs_query_req *request = NULL;
>   struct ufs_query_res *response = NULL;
>   int err, index = 0, selector = 0;
> + int timeout = QUERY_REQ_TIMEOUT;
>
>   BUG_ON(!hba);
>
> @@ -1683,7 +1690,10 @@ static int ufshcd_query_flag(struct ufs_hba *hba,
> enum query_opcode opcode,
>   goto out_unlock;
>   }
>
> - err = ufshcd_exec_dev_cmd(hba, DEV_CMD_TYPE_QUERY, QUERY_REQ_TIMEOUT);
> + if (idn == QUERY_FLAG_IDN_FDEVICEINIT)
> + timeout = QUERY_FDEVICEINIT_REQ_TIMEOUT;
> +
> + err = ufshcd_exec_dev_cmd(hba, DEV_CMD_TYPE_QUERY, timeout);
>
>   if (err) {
>   dev_err(hba->dev,
> --
> 1.8.5.2
>
> --
> QUALCOMM ISRAEL, on behalf of Qualcomm Innovation Center, Inc. is a member
> of Code Aurora Forum, hosted by The Linux Foundation
> --
> To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
> the body of a message to majord...@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>


-- 
Qualcomm Israel, on behalf of Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH v5 02/15] scsi: ufs: clear fields UTRD, UPIU req and rsp before new transfers

2015-10-27 Thread Gilad Broner
Looks OK.
Reviewed-by: Gilad Broner 

> Some of the data structures (like response UPIU) and/or its elements
> (unused fields) should be cleared before sending out the respective
> command to UFS device.
>
> This change clears the UPIU response data structure for query commands
> and NOP command before sending out the command. We also initialize the
> PRDT table length to zero which should take care of commands which doesn't
> have any data associated with it. We are also clearing the unused fields
> in
> request UPIU for NOP command.
>
> Signed-off-by: Subhash Jadavani 
> Signed-off-by: Yaniv Gardi 
>
> ---
>  drivers/scsi/ufs/ufshcd.c | 8 
>  1 file changed, 8 insertions(+)
>
> diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
> index 3428f72..2d3ebca 100644
> --- a/drivers/scsi/ufs/ufshcd.c
> +++ b/drivers/scsi/ufs/ufshcd.c
> @@ -1129,6 +1129,8 @@ static void ufshcd_prepare_req_desc_hdr(struct
> ufshcd_lrb *lrbp,
>   cpu_to_le32(OCS_INVALID_COMMAND_STATUS);
>   /* dword_3 is reserved, hence it is set to 0 */
>   req_desc->header.dword_3 = 0;
> +
> + req_desc->prd_table_length = 0;
>  }
>
>  /**
> @@ -1198,6 +1200,7 @@ static void ufshcd_prepare_utp_query_req_upiu(struct
> ufs_hba *hba,
>   if (query->request.upiu_req.opcode == UPIU_QUERY_OPCODE_WRITE_DESC)
>   memcpy(descp, query->descriptor, len);
>
> + memset(lrbp->ucd_rsp_ptr, 0, sizeof(struct utp_upiu_rsp));
>  }
>
>  static inline void ufshcd_prepare_utp_nop_upiu(struct ufshcd_lrb *lrbp)
> @@ -1210,6 +1213,11 @@ static inline void
> ufshcd_prepare_utp_nop_upiu(struct ufshcd_lrb *lrbp)
>   ucd_req_ptr->header.dword_0 =
>   UPIU_HEADER_DWORD(
>   UPIU_TRANSACTION_NOP_OUT, 0, 0, lrbp->task_tag);
> + /* clear rest of the fields of basic header */
> + ucd_req_ptr->header.dword_1 = 0;
> + ucd_req_ptr->header.dword_2 = 0;
> +
> + memset(lrbp->ucd_rsp_ptr, 0, sizeof(struct utp_upiu_rsp));
>  }
>
>  /**
> --
> 1.8.5.2
>
> --
> QUALCOMM ISRAEL, on behalf of Qualcomm Innovation Center, Inc. is a member
> of Code Aurora Forum, hosted by The Linux Foundation
> --
> To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
> the body of a message to majord...@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>


-- 
Qualcomm Israel, on behalf of Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH v5 04/15] scsi: ufs: clear outstanding_request bit in case query timeout

2015-10-27 Thread Gilad Broner
Reviewed-by: Gilad Broner 

> When sending a query to the device returns with a timeout error,
> we clear the corresponding bit in the DOORBELL register but
> we don't clear the outstanding_request field as we should.
> This patch fixes this bug.
>
> Signed-off-by: Yaniv Gardi 
>
> ---
>  drivers/scsi/ufs/ufshcd.c | 22 --
>  1 file changed, 20 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
> index 8860a57..e0b8755 100644
> --- a/drivers/scsi/ufs/ufshcd.c
> +++ b/drivers/scsi/ufs/ufshcd.c
> @@ -364,6 +364,16 @@ static inline void ufshcd_utrl_clear(struct ufs_hba
> *hba, u32 pos)
>  }
>
>  /**
> + * ufshcd_outstanding_req_clear - Clear a bit in outstanding request
> field
> + * @hba: per adapter instance
> + * @tag: position of the bit to be cleared
> + */
> +static inline void ufshcd_outstanding_req_clear(struct ufs_hba *hba, int
> tag)
> +{
> + __clear_bit(tag, >outstanding_reqs);
> +}
> +
> +/**
>   * ufshcd_get_lists_status - Check UCRDY, UTRLRDY and UTMRLRDY
>   * @reg: Register value of host controller status
>   *
> @@ -1502,9 +1512,17 @@ static int ufshcd_wait_for_dev_cmd(struct ufs_hba
> *hba,
>
>   if (!time_left) {
>   err = -ETIMEDOUT;
> + dev_dbg(hba->dev, "%s: dev_cmd request timedout, tag %d\n",
> + __func__, lrbp->task_tag);
>   if (!ufshcd_clear_cmd(hba, lrbp->task_tag))
> - /* sucessfully cleared the command, retry if needed */
> + /* successfully cleared the command, retry if needed */
>   err = -EAGAIN;
> + /*
> +  * in case of an error, after clearing the doorbell,
> +  * we also need to clear the outstanding_request
> +  * field in hba
> +  */
> + ufshcd_outstanding_req_clear(hba, lrbp->task_tag);
>   }
>
>   return err;
> @@ -3942,7 +3960,7 @@ static int ufshcd_abort(struct scsi_cmnd *cmd)
>   scsi_dma_unmap(cmd);
>
>   spin_lock_irqsave(host->host_lock, flags);
> - __clear_bit(tag, >outstanding_reqs);
> + ufshcd_outstanding_req_clear(hba, tag);
>   hba->lrb[tag].cmd = NULL;
>   spin_unlock_irqrestore(host->host_lock, flags);
>
> --
> 1.8.5.2
>
> --
> QUALCOMM ISRAEL, on behalf of Qualcomm Innovation Center, Inc. is a member
> of Code Aurora Forum, hosted by The Linux Foundation
> --
> To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
> the body of a message to majord...@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>


-- 
Qualcomm Israel, on behalf of Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH v5 01/15] scsi: ufs: clear UTRD, UPIU req and rsp before new transfers

2015-10-27 Thread Gilad Broner
Looks OK.
Reviewed-by: Gilad Broner 

> Clear the UFS data structures before sending new request.
>
> The SCSI command is sent to the device within the UFS UPIU request.
> As part of the transfer UPIU preparation, the SCSI command is copied
> to the UPIU structure according to the SCSI command size.
> As different SCSI commands differ in size from each other, we need
> to clear the whole SCSI command field to prevent sending uninitialized
> data to the device.
>
> The UPIU response doesn't always include the sense data and can differ
> in size.
> Hence, the UPIU response should also be cleared before the transfer.
>
> Signed-off-by: Subhash Jadavani 
> Signed-off-by: Maya Erez 
> Signed-off-by: Yaniv Gardi 
>
> ---
>  drivers/scsi/ufs/ufshcd.c | 17 +
>  1 file changed, 13 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
> index 131c720..3428f72 100644
> --- a/drivers/scsi/ufs/ufshcd.c
> +++ b/drivers/scsi/ufs/ufshcd.c
> @@ -3,7 +3,7 @@
>   *
>   * This code is based on drivers/scsi/ufs/ufshcd.c
>   * Copyright (C) 2011-2013 Samsung India Software Operations
> - * Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
> + * Copyright (c) 2013-2015, The Linux Foundation. All rights reserved.
>   *
>   * Authors:
>   *   Santosh Yaraganavi 
> @@ -1035,6 +1035,7 @@ static int ufshcd_map_sg(struct ufshcd_lrb *lrbp)
>   cpu_to_le32(lower_32_bits(sg->dma_address));
>   prd_table[i].upper_addr =
>   cpu_to_le32(upper_32_bits(sg->dma_address));
> + prd_table[i].reserved = 0;
>   }
>   } else {
>   lrbp->utr_descriptor_ptr->prd_table_length = 0;
> @@ -1117,7 +1118,8 @@ static void ufshcd_prepare_req_desc_hdr(struct
> ufshcd_lrb *lrbp,
>
>   /* Transfer request descriptor header fields */
>   req_desc->header.dword_0 = cpu_to_le32(dword_0);
> -
> + /* dword_1 is reserved, hence it is set to 0 */
> + req_desc->header.dword_1 = 0;
>   /*
>* assigning invalid value for command status. Controller
>* updates OCS on command completion, with the command
> @@ -1125,6 +1127,8 @@ static void ufshcd_prepare_req_desc_hdr(struct
> ufshcd_lrb *lrbp,
>*/
>   req_desc->header.dword_2 =
>   cpu_to_le32(OCS_INVALID_COMMAND_STATUS);
> + /* dword_3 is reserved, hence it is set to 0 */
> + req_desc->header.dword_3 = 0;
>  }
>
>  /**
> @@ -1137,6 +1141,7 @@ static
>  void ufshcd_prepare_utp_scsi_cmd_upiu(struct ufshcd_lrb *lrbp, u32
> upiu_flags)
>  {
>   struct utp_upiu_req *ucd_req_ptr = lrbp->ucd_req_ptr;
> + unsigned short cdb_len;
>
>   /* command descriptor fields */
>   ucd_req_ptr->header.dword_0 = UPIU_HEADER_DWORD(
> @@ -1151,8 +1156,12 @@ 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);
>
> - memcpy(ucd_req_ptr->sc.cdb, lrbp->cmd->cmnd,
> - (min_t(unsigned short, lrbp->cmd->cmd_len, MAX_CDB_SIZE)));
> + cdb_len = min_t(unsigned short, lrbp->cmd->cmd_len, MAX_CDB_SIZE);
> + memcpy(ucd_req_ptr->sc.cdb, lrbp->cmd->cmnd, cdb_len);
> + if (cdb_len < MAX_CDB_SIZE)
> + memset(ucd_req_ptr->sc.cdb + cdb_len, 0,
> +(MAX_CDB_SIZE - cdb_len));
> + memset(lrbp->ucd_rsp_ptr, 0, sizeof(struct utp_upiu_rsp));
>  }
>
>  /**
> --
> 1.8.5.2
>
> --
> QUALCOMM ISRAEL, on behalf of Qualcomm Innovation Center, Inc. is a member
> of Code Aurora Forum, hosted by The Linux Foundation
> --
> To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
> the body of a message to majord...@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>


-- 
Qualcomm Israel, on behalf of Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH v5 05/15] scsi: ufs: increase fDeviceInit query response timeout

2015-10-27 Thread Gilad Broner
Reviewed-by: Gilad Broner <gbro...@codeaurora.org>

> fDeviceInit query response time for some devices is too long that default
> query request timeout of 100ms may not be enough. Experiments show that
> fDeviceInit response sometimes takes 500ms so to be on safer side this
> change sets the timeout to 600ms. Without this change, we might
> unnecessarily have to retry fDeviceInit query requests multiple times and
> each query request timeout prints one error message.
>
> Signed-off-by: Subhash Jadavani <subha...@codeaurora.org>
> Signed-off-by: Yaniv Gardi <yga...@codeaurora.org>
>
> ---
>  drivers/scsi/ufs/ufshcd.c | 12 +++-
>  1 file changed, 11 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
> index e0b8755..573a8cb 100644
> --- a/drivers/scsi/ufs/ufshcd.c
> +++ b/drivers/scsi/ufs/ufshcd.c
> @@ -58,6 +58,12 @@
>  #define QUERY_REQ_RETRIES 10
>  /* Query request timeout */
>  #define QUERY_REQ_TIMEOUT 30 /* msec */
> +/*
> + * Query request timeout for fDeviceInit flag
> + * fDeviceInit query response time for some devices is too large that
> default
> + * QUERY_REQ_TIMEOUT may not be enough for such devices.
> + */
> +#define QUERY_FDEVICEINIT_REQ_TIMEOUT 600 /* msec */
>
>  /* Task management command timeout */
>  #define TM_CMD_TIMEOUT   100 /* msecs */
> @@ -1651,6 +1657,7 @@ static int ufshcd_query_flag(struct ufs_hba *hba,
> enum query_opcode opcode,
>   struct ufs_query_req *request = NULL;
>   struct ufs_query_res *response = NULL;
>   int err, index = 0, selector = 0;
> + int timeout = QUERY_REQ_TIMEOUT;
>
>   BUG_ON(!hba);
>
> @@ -1683,7 +1690,10 @@ static int ufshcd_query_flag(struct ufs_hba *hba,
> enum query_opcode opcode,
>   goto out_unlock;
>   }
>
> - err = ufshcd_exec_dev_cmd(hba, DEV_CMD_TYPE_QUERY, QUERY_REQ_TIMEOUT);
> + if (idn == QUERY_FLAG_IDN_FDEVICEINIT)
> + timeout = QUERY_FDEVICEINIT_REQ_TIMEOUT;
> +
> + err = ufshcd_exec_dev_cmd(hba, DEV_CMD_TYPE_QUERY, timeout);
>
>   if (err) {
>   dev_err(hba->dev,
> --
> 1.8.5.2
>
> --
> QUALCOMM ISRAEL, on behalf of Qualcomm Innovation Center, Inc. is a member
> of Code Aurora Forum, hosted by The Linux Foundation
> --
> To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
> the body of a message to majord...@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>


-- 
Qualcomm Israel, on behalf of Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH v8 8/8] scsi: ufs-qcom: add QUniPro hardware support and power optimizations

2015-10-27 Thread Gilad Broner
Reviewed-by: Gilad Broner <gbro...@codeaurora.org>

> New revisions of UFS host controller supports the new UniPro
> hardware controller (referred as QUniPro). This patch adds
> the support to enable this new UniPro controller hardware.
>
> This change also adds power optimization for bus scaling feature,
> as well as support for HS-G3 power mode.
>
> Signed-off-by: Yaniv Gardi <yga...@codeaurora.org>
>
> ---
>  drivers/scsi/ufs/ufs-qcom.c | 640
> 
>  drivers/scsi/ufs/ufs-qcom.h |  31 ++-
>  drivers/scsi/ufs/ufshcd.c   |   8 +-
>  drivers/scsi/ufs/ufshcd.h   |  27 +-
>  4 files changed, 525 insertions(+), 181 deletions(-)
>
> diff --git a/drivers/scsi/ufs/ufs-qcom.c b/drivers/scsi/ufs/ufs-qcom.c
> index 1633808..4f38d00 100644
> --- a/drivers/scsi/ufs/ufs-qcom.c
> +++ b/drivers/scsi/ufs/ufs-qcom.c
> @@ -44,11 +44,11 @@ enum {
>
>  static struct ufs_qcom_host *ufs_qcom_hosts[MAX_UFS_QCOM_HOSTS];
>
> -static void ufs_qcom_get_speed_mode(struct ufs_pa_layer_attr *p, char
> *result);
> -static int ufs_qcom_get_bus_vote(struct ufs_qcom_host *host,
> - const char *speed_mode);
>  static int ufs_qcom_set_bus_vote(struct ufs_qcom_host *host, int vote);
>  static void ufs_qcom_get_default_testbus_cfg(struct ufs_qcom_host *host);
> +static int ufs_qcom_set_dme_vs_core_clk_ctrl_clear_div(struct ufs_hba
> *hba,
> +u32 clk_cycles);
> +
>  static void ufs_qcom_dump_regs(struct ufs_hba *hba, int offset, int len,
>   char *prefix)
>  {
> @@ -177,6 +177,7 @@ static int ufs_qcom_init_lane_clks(struct
> ufs_qcom_host *host)
>
>   err = ufs_qcom_host_clk_get(dev, "tx_lane1_sync_clk",
>   >tx_l1_sync_clk);
> +
>  out:
>   return err;
>  }
> @@ -209,7 +210,9 @@ static int ufs_qcom_check_hibern8(struct ufs_hba *hba)
>
>   do {
>   err = ufshcd_dme_get(hba,
> - UIC_ARG_MIB(MPHY_TX_FSM_STATE), _fsm_val);
> + UIC_ARG_MIB_SEL(MPHY_TX_FSM_STATE,
> + UIC_ARG_MPHY_TX_GEN_SEL_INDEX(0)),
> + _fsm_val);
>   if (err || tx_fsm_val == TX_FSM_HIBERN8)
>   break;
>
> @@ -223,7 +226,9 @@ static int ufs_qcom_check_hibern8(struct ufs_hba *hba)
>*/
>   if (time_after(jiffies, timeout))
>   err = ufshcd_dme_get(hba,
> - UIC_ARG_MIB(MPHY_TX_FSM_STATE), _fsm_val);
> + UIC_ARG_MIB_SEL(MPHY_TX_FSM_STATE,
> + UIC_ARG_MPHY_TX_GEN_SEL_INDEX(0)),
> + _fsm_val);
>
>   if (err) {
>   dev_err(hba->dev, "%s: unable to get TX_FSM_STATE, err %d\n",
> @@ -237,6 +242,15 @@ static int ufs_qcom_check_hibern8(struct ufs_hba
> *hba)
>   return err;
>  }
>
> +static void ufs_qcom_select_unipro_mode(struct ufs_qcom_host *host)
> +{
> + ufshcd_rmwl(host->hba, QUNIPRO_SEL,
> +ufs_qcom_cap_qunipro(host) ? QUNIPRO_SEL : 0,
> +REG_UFS_CFG1);
> + /* make sure above configuration is applied before we return */
> + mb();
> +}
> +
>  static int ufs_qcom_power_up_sequence(struct ufs_hba *hba)
>  {
>   struct ufs_qcom_host *host = ufshcd_get_variant(hba);
> @@ -251,9 +265,11 @@ static int ufs_qcom_power_up_sequence(struct ufs_hba
> *hba)
>   usleep_range(1000, 1100);
>
>   ret = ufs_qcom_phy_calibrate_phy(phy, is_rate_B);
> +
>   if (ret) {
> - dev_err(hba->dev, "%s: ufs_qcom_phy_calibrate_phy() failed, ret 
> =
> %d\n",
> - __func__, ret);
> + dev_err(hba->dev,
> + "%s: ufs_qcom_phy_calibrate_phy()failed, ret = %d\n",
> + __func__, ret);
>   goto out;
>   }
>
> @@ -274,9 +290,12 @@ static int ufs_qcom_power_up_sequence(struct ufs_hba
> *hba)
>
>   ret = ufs_qcom_phy_is_pcs_ready(phy);
>   if (ret)
> - dev_err(hba->dev, "%s: is_physical_coding_sublayer_ready() 
> failed, ret
> = %d\n",
> + dev_err(hba->dev,
> + "%s: is_physical_coding_sublayer_ready() failed, ret = 
> %d\n",
>   __func__, ret);
>
> + ufs_qcom_select_unipro_mode(host);
> +
>  out:
>   return ret;
>  }
> @@ -299,7 +318,8 @@ static void ufs_qcom_enable_hw_clk_gating(struct
> ufs_hba *hba)
>   mb();
>  }
>
> -static int ufs_qcom_hce_enable_notify(struct ufs_hba *hba, 

Re: [PATCH v8 7/8] scsi: ufs-qcom: add debug prints for test bus

2015-10-27 Thread Gilad Broner
Reviewed-by: Gilad Broner <gbro...@codeaurora.org>

> Adds support for configuring and reading the test bus and debug
> registers. This change also adds another vops in order to print the
> debug registers.
>
> Signed-off-by: Yaniv Gardi <yga...@codeaurora.org>
>
> ---
>  drivers/scsi/ufs/ufs-qcom.c | 165
> +++-
>  drivers/scsi/ufs/ufs-qcom.h |  37 +-
>  drivers/scsi/ufs/ufshcd.c   |   2 +
>  drivers/scsi/ufs/ufshcd.h   |   8 +++
>  4 files changed, 208 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/scsi/ufs/ufs-qcom.c b/drivers/scsi/ufs/ufs-qcom.c
> index b275a9a..1633808 100644
> --- a/drivers/scsi/ufs/ufs-qcom.c
> +++ b/drivers/scsi/ufs/ufs-qcom.c
> @@ -23,6 +23,24 @@
>  #include "unipro.h"
>  #include "ufs-qcom.h"
>  #include "ufshci.h"
> +#define UFS_QCOM_DEFAULT_DBG_PRINT_EN\
> + (UFS_QCOM_DBG_PRINT_REGS_EN | UFS_QCOM_DBG_PRINT_TEST_BUS_EN)
> +
> +enum {
> + TSTBUS_UAWM,
> + TSTBUS_UARM,
> + TSTBUS_TXUC,
> + TSTBUS_RXUC,
> + TSTBUS_DFC,
> + TSTBUS_TRLUT,
> + TSTBUS_TMRLUT,
> + TSTBUS_OCSC,
> + TSTBUS_UTP_HCI,
> + TSTBUS_COMBINED,
> + TSTBUS_WRAPPER,
> + TSTBUS_UNIPRO,
> + TSTBUS_MAX,
> +};
>
>  static struct ufs_qcom_host *ufs_qcom_hosts[MAX_UFS_QCOM_HOSTS];
>
> @@ -30,6 +48,15 @@ static void ufs_qcom_get_speed_mode(struct
> ufs_pa_layer_attr *p, char *result);
>  static int ufs_qcom_get_bus_vote(struct ufs_qcom_host *host,
>   const char *speed_mode);
>  static int ufs_qcom_set_bus_vote(struct ufs_qcom_host *host, int vote);
> +static void ufs_qcom_get_default_testbus_cfg(struct ufs_qcom_host *host);
> +static void ufs_qcom_dump_regs(struct ufs_hba *hba, int offset, int len,
> + char *prefix)
> +{
> + print_hex_dump(KERN_ERR, prefix,
> + len > 4 ? DUMP_PREFIX_OFFSET : DUMP_PREFIX_NONE,
> + 16, 4, (void __force *)hba->mmio_base + offset,
> + len * 4, false);
> +}
>
>  static int ufs_qcom_get_connected_tx_lanes(struct ufs_hba *hba, u32
> *tx_lanes)
>  {
> @@ -996,6 +1023,15 @@ static int ufs_qcom_init(struct ufs_hba *hba)
>   if (hba->dev->id < MAX_UFS_QCOM_HOSTS)
>   ufs_qcom_hosts[hba->dev->id] = host;
>
> + host->dbg_print_en |= UFS_QCOM_DEFAULT_DBG_PRINT_EN;
> + ufs_qcom_get_default_testbus_cfg(host);
> + err = ufs_qcom_testbus_config(host);
> + if (err) {
> + dev_warn(dev, "%s: failed to configure the testbus %d\n",
> + __func__, err);
> + err = 0;
> + }
> +
>   goto out;
>
>  out_disable_phy:
> @@ -1025,12 +1061,134 @@ void ufs_qcom_clk_scale_notify(struct ufs_hba
> *hba)
>
>   if (!dev_req_params)
>   return;
> +}
> +
> +static void ufs_qcom_get_default_testbus_cfg(struct ufs_qcom_host *host)
> +{
> + /* provide a legal default configuration */
> + host->testbus.select_major = TSTBUS_UAWM;
> + host->testbus.select_minor = 1;
> +}
> +
> +static bool ufs_qcom_testbus_cfg_is_ok(struct ufs_qcom_host *host)
> +{
> + if (host->testbus.select_major >= TSTBUS_MAX) {
> + dev_err(host->hba->dev,
> + "%s: UFS_CFG1[TEST_BUS_SEL} may not equal 0x%05X\n",
> + __func__, host->testbus.select_major);
> + return false;
> + }
> +
> + /*
> +  * Not performing check for each individual select_major
> +  * mappings of select_minor, since there is no harm in
> +  * configuring a non-existent select_minor
> +  */
> + if (host->testbus.select_minor > 0x1F) {
> + dev_err(host->hba->dev,
> + "%s: 0x%05X is not a legal testbus option\n",
> + __func__, host->testbus.select_minor);
> + return false;
> + }
> +
> + return true;
> +}
> +
> +int ufs_qcom_testbus_config(struct ufs_qcom_host *host)
> +{
> + int reg;
> + int offset;
> + u32 mask = TEST_BUS_SUB_SEL_MASK;
> +
> + if (!host)
> + return -EINVAL;
>
> - ufs_qcom_cfg_timers(hba, dev_req_params->gear_rx,
> - dev_req_params->pwr_rx,
> - dev_req_params->hs_rate);
> + if (!ufs_qcom_testbus_cfg_is_ok(host))
> + return -EPERM;
> +
> + switch (host->testbus.select_major) {
> + case TSTBUS_UAWM:
> + reg = UFS_TEST_BUS_CTRL_0;
&g

Re: [PATCH v8 5/8] scsi: ufs: creates wrapper functions for vops

2015-10-27 Thread Gilad Broner
Reviewed-by: Gilad Broner <gbro...@codeaurora.org>

> In order to simplify the code a set of wrapper functions is created
> to test and call each of the variant operations.
>
> Signed-off-by: Yaniv Gardi <yga...@codeaurora.org>
>
> ---
>  drivers/scsi/ufs/ufs-qcom.c |   1 -
>  drivers/scsi/ufs/ufshcd.c   | 104
> +---
>  drivers/scsi/ufs/ufshcd.h   |  98
> +
>  3 files changed, 137 insertions(+), 66 deletions(-)
>
> diff --git a/drivers/scsi/ufs/ufs-qcom.c b/drivers/scsi/ufs/ufs-qcom.c
> index 64c54b7..329ac84 100644
> --- a/drivers/scsi/ufs/ufs-qcom.c
> +++ b/drivers/scsi/ufs/ufs-qcom.c
> @@ -1049,6 +1049,5 @@ static const struct ufs_hba_variant_ops
> ufs_hba_qcom_vops = {
>   .suspend= ufs_qcom_suspend,
>   .resume = ufs_qcom_resume,
>  };
> -EXPORT_SYMBOL(ufs_hba_qcom_vops);
>
>  MODULE_LICENSE("GPL v2");
> diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
> index b0ade73..9e79c33 100644
> --- a/drivers/scsi/ufs/ufshcd.c
> +++ b/drivers/scsi/ufs/ufshcd.c
> @@ -271,10 +271,8 @@ static inline u32 ufshcd_get_intr_mask(struct ufs_hba
> *hba)
>   */
>  static inline u32 ufshcd_get_ufs_version(struct ufs_hba *hba)
>  {
> - if (hba->quirks & UFSHCD_QUIRK_BROKEN_UFS_HCI_VERSION) {
> - if (hba->vops && hba->vops->get_ufs_hci_version)
> - return hba->vops->get_ufs_hci_version(hba);
> - }
> + if (hba->quirks & UFSHCD_QUIRK_BROKEN_UFS_HCI_VERSION)
> + return ufshcd_vops_get_ufs_hci_version(hba);
>
>   return ufshcd_readl(hba, REG_UFS_VERSION);
>  }
> @@ -2473,9 +2471,8 @@ static int ufshcd_change_power_mode(struct ufs_hba
> *hba,
>   dev_err(hba->dev,
>   "%s: power mode change failed %d\n", __func__, ret);
>   } else {
> - if (hba->vops && hba->vops->pwr_change_notify)
> - hba->vops->pwr_change_notify(hba,
> - POST_CHANGE, NULL, pwr_mode);
> + ufshcd_vops_pwr_change_notify(hba, POST_CHANGE, NULL,
> + pwr_mode);
>
>   memcpy(>pwr_info, pwr_mode,
>   sizeof(struct ufs_pa_layer_attr));
> @@ -2495,10 +2492,10 @@ static int ufshcd_config_pwr_mode(struct ufs_hba
> *hba,
>   struct ufs_pa_layer_attr final_params = { 0 };
>   int ret;
>
> - if (hba->vops && hba->vops->pwr_change_notify)
> - hba->vops->pwr_change_notify(hba,
> -  PRE_CHANGE, desired_pwr_mode, _params);
> - else
> + ret = ufshcd_vops_pwr_change_notify(hba, PRE_CHANGE,
> + desired_pwr_mode, _params);
> +
> + if (ret)
>   memcpy(_params, desired_pwr_mode, sizeof(final_params));
>
>   ret = ufshcd_change_power_mode(hba, _params);
> @@ -2647,8 +2644,7 @@ static int ufshcd_hba_enable(struct ufs_hba *hba)
>   /* UniPro link is disabled at this point */
>   ufshcd_set_link_off(hba);
>
> - if (hba->vops && hba->vops->hce_enable_notify)
> - hba->vops->hce_enable_notify(hba, PRE_CHANGE);
> + ufshcd_vops_hce_enable_notify(hba, PRE_CHANGE);
>
>   /* start controller initialization sequence */
>   ufshcd_hba_start(hba);
> @@ -2681,8 +2677,7 @@ static int ufshcd_hba_enable(struct ufs_hba *hba)
>   /* enable UIC related interrupts */
>   ufshcd_enable_intr(hba, UFSHCD_UIC_MASK);
>
> - if (hba->vops && hba->vops->hce_enable_notify)
> - hba->vops->hce_enable_notify(hba, POST_CHANGE);
> + ufshcd_vops_hce_enable_notify(hba, POST_CHANGE);
>
>   return 0;
>  }
> @@ -2735,8 +2730,7 @@ static int ufshcd_link_startup(struct ufs_hba *hba)
>   int retries = DME_LINKSTARTUP_RETRIES;
>
>   do {
> - if (hba->vops && hba->vops->link_startup_notify)
> - hba->vops->link_startup_notify(hba, PRE_CHANGE);
> + ufshcd_vops_link_startup_notify(hba, PRE_CHANGE);
>
>   ret = ufshcd_dme_link_startup(hba);
>
> @@ -2767,11 +2761,9 @@ static int ufshcd_link_startup(struct ufs_hba *hba)
>   }
>
>   /* Include any host controller configuration via UIC commands */
> - if (hba->vops && hba->vops->link_startup_notify) {
> - ret = hba->vops->link_startup_notify(hba, POST_CHANGE);
> - if (ret)
> - 

Re: [PATCH v8 6/8] scsi: ufs: make the UFS variant a platform device

2015-10-27 Thread Gilad Broner
Reviewed-by: Gilad Broner <gbro...@codeaurora.org>

> This change turns the UFS variant (SCSI_UFS_QCOM) into a UFS
> a platform device.
> In order to do so a few additional changes are required:
> 1. The ufshcd-pltfrm is no longer serves as a platform device.
>Now it only serves as a group of platform APIs such as PM APIs
>(runtime suspend/resume, system suspend/resume etc), parsers of
>clocks, regulators and pm_levels from DT.
> 2. What used to be the old platform "probe" is now "only"
>a pltfrm_init() routine, that does exactly the same, but only
>being called by the new probe function of the UFS variant.
>
> Signed-off-by: Yaniv Gardi <yga...@codeaurora.org>
>
> ---
>  Documentation/devicetree/bindings/ufs/ufs-qcom.txt | 58 +
>  .../devicetree/bindings/ufs/ufshcd-pltfrm.txt  | 11 ++-
>  drivers/scsi/ufs/ufs-qcom.c| 62 +-
>  drivers/scsi/ufs/ufshcd-pltfrm.c   | 98
> ++
>  drivers/scsi/ufs/ufshcd-pltfrm.h   | 41 +
>  drivers/scsi/ufs/ufshcd.c  | 10 +++
>  drivers/scsi/ufs/ufshcd.h  |  1 +
>  7 files changed, 207 insertions(+), 74 deletions(-)
>  create mode 100644 Documentation/devicetree/bindings/ufs/ufs-qcom.txt
>  create mode 100644 drivers/scsi/ufs/ufshcd-pltfrm.h
>
> diff --git a/Documentation/devicetree/bindings/ufs/ufs-qcom.txt
> b/Documentation/devicetree/bindings/ufs/ufs-qcom.txt
> new file mode 100644
> index 000..070baf4
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/ufs/ufs-qcom.txt
> @@ -0,0 +1,58 @@
> +* Qualcomm Technologies Inc Universal Flash Storage (UFS) PHY
> +
> +UFSPHY nodes are defined to describe on-chip UFS PHY hardware macro.
> +Each UFS PHY node should have its own node.
> +
> +To bind UFS PHY with UFS host controller, the controller node should
> +contain a phandle reference to UFS PHY node.
> +
> +Required properties:
> +- compatible: compatible list, contains "qcom,ufs-phy-qmp-20nm"
> +   or "qcom,ufs-phy-qmp-14nm" according to the relevant phy 
> in use.
> +- reg   : should contain PHY register address space
> (mandatory),
> +- reg-names : indicates various resources passed to driver (via
> reg proptery) by name.
> +  Required "reg-names" is "phy_mem".
> +- #phy-cells: This property shall be set to 0
> +- vdda-phy-supply   : phandle to main PHY supply for analog domain
> +- vdda-pll-supply   : phandle to PHY PLL and Power-Gen block power supply
> +- clocks : List of phandle and clock specifier pairs
> +- clock-names   : List of clock input name strings sorted in the same
> +   order as the clocks property. "ref_clk_src", "ref_clk",
> +   "tx_iface_clk" & "rx_iface_clk" are mandatory but
> +   "ref_clk_parent" is optional
> +
> +Optional properties:
> +- vdda-phy-max-microamp : specifies max. load that can be drawn from phy
> supply
> +- vdda-pll-max-microamp : specifies max. load that can be drawn from pll
> supply
> +- vddp-ref-clk-supply   : phandle to UFS device ref_clk pad power supply
> +- vddp-ref-clk-max-microamp : specifies max. load that can be drawn from
> this supply
> +- vddp-ref-clk-always-on : specifies if this supply needs to be kept
> always on
> +
> +Example:
> +
> + ufsphy1: ufsphy@0xfc597000 {
> + compatible = "qcom,ufs-phy-qmp-20nm";
> + reg = <0xfc597000 0x800>;
> + reg-names = "phy_mem";
> + #phy-cells = <0>;
> + vdda-phy-supply = <_l4>;
> + vdda-pll-supply = <_l12>;
> + vdda-phy-max-microamp = <5>;
> + vdda-pll-max-microamp = <1000>;
> + clock-names = "ref_clk_src",
> + "ref_clk_parent",
> + "ref_clk",
> + "tx_iface_clk",
> + "rx_iface_clk";
> + clocks = <_rpm clk_ln_bb_clk>,
> + <_gcc clk_pcie_1_phy_ldo >,
> + <_gcc clk_ufs_phy_ldo>,
> + <_gcc clk_gcc_ufs_tx_cfg_clk>,
> + <_gcc clk_gcc_ufs_rx_cfg_clk>;
> + };
> +
> + ufshc@0xfc598000 {
> + ...
> + phys = <>;
> + phy-names = "ufsphy";
> + };
> diff --git a/Documentation/devicetree

Re: [PATCH v8 4/8] add ufshcd_get_variant ufshcd_set_variant

2015-10-27 Thread Gilad Broner
Reviewed-by: Gilad Broner <gbro...@codeaurora.org>

> Signed-off-by: Yaniv Gardi <yga...@codeaurora.org>
>
> ---
>  drivers/scsi/ufs/ufs-qcom.c | 34 +-
>  drivers/scsi/ufs/ufshcd.h   | 21 +
>  2 files changed, 38 insertions(+), 17 deletions(-)
>
> diff --git a/drivers/scsi/ufs/ufs-qcom.c b/drivers/scsi/ufs/ufs-qcom.c
> index 6c23bbf..64c54b7 100644
> --- a/drivers/scsi/ufs/ufs-qcom.c
> +++ b/drivers/scsi/ufs/ufs-qcom.c
> @@ -155,7 +155,7 @@ out:
>
>  static int ufs_qcom_link_startup_post_change(struct ufs_hba *hba)
>  {
> - struct ufs_qcom_host *host = hba->priv;
> + struct ufs_qcom_host *host = ufshcd_get_variant(hba);
>   struct phy *phy = host->generic_phy;
>   u32 tx_lanes;
>   int err = 0;
> @@ -211,7 +211,7 @@ static int ufs_qcom_check_hibern8(struct ufs_hba *hba)
>
>  static int ufs_qcom_power_up_sequence(struct ufs_hba *hba)
>  {
> - struct ufs_qcom_host *host = hba->priv;
> + struct ufs_qcom_host *host = ufshcd_get_variant(hba);
>   struct phy *phy = host->generic_phy;
>   int ret = 0;
>   bool is_rate_B = (UFS_QCOM_LIMIT_HS_RATE == PA_HS_MODE_B)
> @@ -273,7 +273,7 @@ static void ufs_qcom_enable_hw_clk_gating(struct
> ufs_hba *hba)
>
>  static int ufs_qcom_hce_enable_notify(struct ufs_hba *hba, bool status)
>  {
> - struct ufs_qcom_host *host = hba->priv;
> + struct ufs_qcom_host *host = ufshcd_get_variant(hba);
>   int err = 0;
>
>   switch (status) {
> @@ -307,7 +307,7 @@ static int ufs_qcom_hce_enable_notify(struct ufs_hba
> *hba, bool status)
>  static unsigned long
>  ufs_qcom_cfg_timers(struct ufs_hba *hba, u32 gear, u32 hs, u32 rate)
>  {
> - struct ufs_qcom_host *host = hba->priv;
> + struct ufs_qcom_host *host = ufshcd_get_variant(hba);
>   struct ufs_clk_info *clki;
>   u32 core_clk_period_in_ns;
>   u32 tx_clk_cycles_per_us = 0;
> @@ -448,7 +448,7 @@ static int ufs_qcom_link_startup_notify(struct ufs_hba
> *hba, bool status)
>
>  static int ufs_qcom_suspend(struct ufs_hba *hba, enum ufs_pm_op pm_op)
>  {
> - struct ufs_qcom_host *host = hba->priv;
> + struct ufs_qcom_host *host = ufshcd_get_variant(hba);
>   struct phy *phy = host->generic_phy;
>   int ret = 0;
>
> @@ -479,7 +479,7 @@ out:
>
>  static int ufs_qcom_resume(struct ufs_hba *hba, enum ufs_pm_op pm_op)
>  {
> - struct ufs_qcom_host *host = hba->priv;
> + struct ufs_qcom_host *host = ufshcd_get_variant(hba);
>   struct phy *phy = host->generic_phy;
>   int err;
>
> @@ -621,7 +621,7 @@ static int ufs_qcom_pwr_change_notify(struct ufs_hba
> *hba,
>   struct ufs_pa_layer_attr *dev_req_params)
>  {
>   u32 val;
> - struct ufs_qcom_host *host = hba->priv;
> + struct ufs_qcom_host *host = ufshcd_get_variant(hba);
>   struct phy *phy = host->generic_phy;
>   struct ufs_qcom_dev_params ufs_qcom_cap;
>   int ret = 0;
> @@ -696,7 +696,7 @@ out:
>
>  static u32 ufs_qcom_get_ufs_hci_version(struct ufs_hba *hba)
>  {
> - struct ufs_qcom_host *host = hba->priv;
> + struct ufs_qcom_host *host = ufshcd_get_variant(hba);
>
>   if (host->hw_ver.major == 0x1)
>   return UFSHCI_VERSION_11;
> @@ -715,7 +715,7 @@ static u32 ufs_qcom_get_ufs_hci_version(struct ufs_hba
> *hba)
>   */
>  static void ufs_qcom_advertise_quirks(struct ufs_hba *hba)
>  {
> - struct ufs_qcom_host *host = hba->priv;
> + struct ufs_qcom_host *host = ufshcd_get_variant(hba);
>
>   if (host->hw_ver.major == 0x01) {
>   hba->quirks |= UFSHCD_QUIRK_DELAY_BEFORE_DME_CMDS
> @@ -740,7 +740,7 @@ static void ufs_qcom_advertise_quirks(struct ufs_hba
> *hba)
>
>  static void ufs_qcom_set_caps(struct ufs_hba *hba)
>  {
> - struct ufs_qcom_host *host = hba->priv;
> + struct ufs_qcom_host *host = ufshcd_get_variant(hba);
>
>   if (host->hw_ver.major >= 0x2)
>   host->caps = UFS_QCOM_CAP_QUNIPRO;
> @@ -811,7 +811,7 @@ static void ufs_qcom_get_speed_mode(struct
> ufs_pa_layer_attr *p, char *result)
>
>  static int ufs_qcom_setup_clocks(struct ufs_hba *hba, bool on)
>  {
> - struct ufs_qcom_host *host = hba->priv;
> + struct ufs_qcom_host *host = ufshcd_get_variant(hba);
>   int err = 0;
>   int vote = 0;
>
> @@ -866,7 +866,7 @@ show_ufs_to_mem_max_bus_bw(struct device *dev, struct
> device_attribute *attr,
>   char *buf)
>  {
>   struct ufs_hba *hba = dev_get_drvdata(dev);
> - struct ufs_qcom_host *host = hba->priv;
> +   

Re: [PATCH v5 01/15] scsi: ufs: clear UTRD, UPIU req and rsp before new transfers

2015-10-27 Thread Gilad Broner
Looks OK.
Reviewed-by: Gilad Broner <gbro...@codeaurora.org>

> Clear the UFS data structures before sending new request.
>
> The SCSI command is sent to the device within the UFS UPIU request.
> As part of the transfer UPIU preparation, the SCSI command is copied
> to the UPIU structure according to the SCSI command size.
> As different SCSI commands differ in size from each other, we need
> to clear the whole SCSI command field to prevent sending uninitialized
> data to the device.
>
> The UPIU response doesn't always include the sense data and can differ
> in size.
> Hence, the UPIU response should also be cleared before the transfer.
>
> Signed-off-by: Subhash Jadavani <subha...@codeaurora.org>
> Signed-off-by: Maya Erez <me...@codeaurora.org>
> Signed-off-by: Yaniv Gardi <yga...@codeaurora.org>
>
> ---
>  drivers/scsi/ufs/ufshcd.c | 17 +
>  1 file changed, 13 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
> index 131c720..3428f72 100644
> --- a/drivers/scsi/ufs/ufshcd.c
> +++ b/drivers/scsi/ufs/ufshcd.c
> @@ -3,7 +3,7 @@
>   *
>   * This code is based on drivers/scsi/ufs/ufshcd.c
>   * Copyright (C) 2011-2013 Samsung India Software Operations
> - * Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
> + * Copyright (c) 2013-2015, The Linux Foundation. All rights reserved.
>   *
>   * Authors:
>   *   Santosh Yaraganavi <santosh...@samsung.com>
> @@ -1035,6 +1035,7 @@ static int ufshcd_map_sg(struct ufshcd_lrb *lrbp)
>   cpu_to_le32(lower_32_bits(sg->dma_address));
>   prd_table[i].upper_addr =
>   cpu_to_le32(upper_32_bits(sg->dma_address));
> + prd_table[i].reserved = 0;
>   }
>   } else {
>   lrbp->utr_descriptor_ptr->prd_table_length = 0;
> @@ -1117,7 +1118,8 @@ static void ufshcd_prepare_req_desc_hdr(struct
> ufshcd_lrb *lrbp,
>
>   /* Transfer request descriptor header fields */
>   req_desc->header.dword_0 = cpu_to_le32(dword_0);
> -
> + /* dword_1 is reserved, hence it is set to 0 */
> + req_desc->header.dword_1 = 0;
>   /*
>* assigning invalid value for command status. Controller
>* updates OCS on command completion, with the command
> @@ -1125,6 +1127,8 @@ static void ufshcd_prepare_req_desc_hdr(struct
> ufshcd_lrb *lrbp,
>*/
>   req_desc->header.dword_2 =
>   cpu_to_le32(OCS_INVALID_COMMAND_STATUS);
> + /* dword_3 is reserved, hence it is set to 0 */
> + req_desc->header.dword_3 = 0;
>  }
>
>  /**
> @@ -1137,6 +1141,7 @@ static
>  void ufshcd_prepare_utp_scsi_cmd_upiu(struct ufshcd_lrb *lrbp, u32
> upiu_flags)
>  {
>   struct utp_upiu_req *ucd_req_ptr = lrbp->ucd_req_ptr;
> + unsigned short cdb_len;
>
>   /* command descriptor fields */
>   ucd_req_ptr->header.dword_0 = UPIU_HEADER_DWORD(
> @@ -1151,8 +1156,12 @@ 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);
>
> - memcpy(ucd_req_ptr->sc.cdb, lrbp->cmd->cmnd,
> - (min_t(unsigned short, lrbp->cmd->cmd_len, MAX_CDB_SIZE)));
> + cdb_len = min_t(unsigned short, lrbp->cmd->cmd_len, MAX_CDB_SIZE);
> + memcpy(ucd_req_ptr->sc.cdb, lrbp->cmd->cmnd, cdb_len);
> + if (cdb_len < MAX_CDB_SIZE)
> + memset(ucd_req_ptr->sc.cdb + cdb_len, 0,
> +(MAX_CDB_SIZE - cdb_len));
> + memset(lrbp->ucd_rsp_ptr, 0, sizeof(struct utp_upiu_rsp));
>  }
>
>  /**
> --
> 1.8.5.2
>
> --
> QUALCOMM ISRAEL, on behalf of Qualcomm Innovation Center, Inc. is a member
> of Code Aurora Forum, hosted by The Linux Foundation
> --
> To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
> the body of a message to majord...@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>


-- 
Qualcomm Israel, on behalf of Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH v8 2/8] scsi: ufs-qcom: fix compilation warning if compiled as a module

2015-10-27 Thread Gilad Broner
Reviewed-by: Gilad Broner <gbro...@codeaurora.org>

> This change fixes a compilation warning that happens if SCSI_UFS_QCOM
> is compiled as a module.
> Also this patch fixes an error happens when insmod the module:
> "ufs_qcom: module license 'unspecified' taints kernel."
>
> Signed-off-by: Yaniv Gardi <yga...@codeaurora.org>
>
> ---
>  drivers/scsi/ufs/ufs-qcom.c | 7 ++-
>  1 file changed, 6 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/scsi/ufs/ufs-qcom.c b/drivers/scsi/ufs/ufs-qcom.c
> index 4cdffa4..6c23bbf 100644
> --- a/drivers/scsi/ufs/ufs-qcom.c
> +++ b/drivers/scsi/ufs/ufs-qcom.c
> @@ -917,12 +917,15 @@ out:
>
>  #define  ANDROID_BOOT_DEV_MAX30
>  static char android_boot_dev[ANDROID_BOOT_DEV_MAX];
> -static int get_android_boot_dev(char *str)
> +
> +#ifndef MODULE
> +static int __init get_android_boot_dev(char *str)
>  {
>   strlcpy(android_boot_dev, str, ANDROID_BOOT_DEV_MAX);
>   return 1;
>  }
>  __setup("androidboot.bootdevice=", get_android_boot_dev);
> +#endif
>
>  /**
>   * ufs_qcom_init - bind phy with controller
> @@ -1047,3 +1050,5 @@ static const struct ufs_hba_variant_ops
> ufs_hba_qcom_vops = {
>   .resume = ufs_qcom_resume,
>  };
>  EXPORT_SYMBOL(ufs_hba_qcom_vops);
> +
> +MODULE_LICENSE("GPL v2");
> --
> 1.8.5.2
>
> --
> QUALCOMM ISRAEL, on behalf of Qualcomm Innovation Center, Inc. is a member
> of Code Aurora Forum, hosted by The Linux Foundation
> --
> To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
> the body of a message to majord...@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>


-- 
Qualcomm Israel, on behalf of Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH v8 1/8] phy: qcom-ufs: fix build error when the component is built as a module

2015-10-27 Thread Gilad Broner
Reviewed-by: Gilad Broner <gbro...@codeaurora.org>

> Export the following functions in order to avoid build errors
> when the component PHY_QCOM_UFS is compiled as a module:
>
> ERROR: "ufs_qcom_phy_disable_ref_clk"
>   [drivers/scsi/ufs/ufs-qcom.ko] undefined!
> ERROR: "ufs_qcom_phy_enable_ref_clk"
>   [drivers/scsi/ufs/ufs-qcom.ko] undefined!
> ERROR: "ufs_qcom_phy_is_pcs_ready"
>   [drivers/scsi/ufs/ufs-qcom.ko] undefined!
> ERROR: "ufs_qcom_phy_disable_iface_clk"
>   [drivers/scsi/ufs/ufs-qcom.ko] undefined!
> ERROR: "ufs_qcom_phy_start_serdes"
>   [drivers/scsi/ufs/ufs-qcom.ko] undefined!
> ERROR: "ufs_qcom_phy_calibrate_phy"
>   [drivers/scsi/ufs/ufs-qcom.ko] undefined!
> ERROR: "ufs_qcom_phy_enable_dev_ref_clk"
>   [drivers/scsi/ufs/ufs-qcom.ko] undefined!
> ERROR: "ufs_qcom_phy_set_tx_lane_enable"
>   [drivers/scsi/ufs/ufs-qcom.ko] undefined!
> ERROR: "ufs_qcom_phy_disable_dev_ref_clk"
>   [drivers/scsi/ufs/ufs-qcom.ko] undefined!
> ERROR: "ufs_qcom_phy_save_controller_version"
>   [drivers/scsi/ufs/ufs-qcom.ko] undefined!
> ERROR: "ufs_qcom_phy_enable_iface_clk"
>   [drivers/scsi/ufs/ufs-qcom.ko] undefined!
> make[1]: *** [__modpost] Error 1
>
> Signed-off-by: Yaniv Gardi <yga...@codeaurora.org>
>
> ---
>  drivers/phy/phy-qcom-ufs.c | 11 +++
>  1 file changed, 11 insertions(+)
>
> diff --git a/drivers/phy/phy-qcom-ufs.c b/drivers/phy/phy-qcom-ufs.c
> index f9c618f..6140a8b 100644
> --- a/drivers/phy/phy-qcom-ufs.c
> +++ b/drivers/phy/phy-qcom-ufs.c
> @@ -432,6 +432,7 @@ out_disable_src:
>  out:
>   return ret;
>  }
> +EXPORT_SYMBOL_GPL(ufs_qcom_phy_enable_ref_clk);
>
>  static
>  int ufs_qcom_phy_disable_vreg(struct phy *phy,
> @@ -474,6 +475,7 @@ void ufs_qcom_phy_disable_ref_clk(struct phy
> *generic_phy)
>   phy->is_ref_clk_enabled = false;
>   }
>  }
> +EXPORT_SYMBOL_GPL(ufs_qcom_phy_disable_ref_clk);
>
>  #define UFS_REF_CLK_EN   (1 << 5)
>
> @@ -517,11 +519,13 @@ void ufs_qcom_phy_enable_dev_ref_clk(struct phy
> *generic_phy)
>  {
>   ufs_qcom_phy_dev_ref_clk_ctrl(generic_phy, true);
>  }
> +EXPORT_SYMBOL_GPL(ufs_qcom_phy_enable_dev_ref_clk);
>
>  void ufs_qcom_phy_disable_dev_ref_clk(struct phy *generic_phy)
>  {
>   ufs_qcom_phy_dev_ref_clk_ctrl(generic_phy, false);
>  }
> +EXPORT_SYMBOL_GPL(ufs_qcom_phy_disable_dev_ref_clk);
>
>  /* Turn ON M-PHY RMMI interface clocks */
>  int ufs_qcom_phy_enable_iface_clk(struct phy *generic_phy)
> @@ -550,6 +554,7 @@ int ufs_qcom_phy_enable_iface_clk(struct phy
> *generic_phy)
>  out:
>   return ret;
>  }
> +EXPORT_SYMBOL_GPL(ufs_qcom_phy_enable_iface_clk);
>
>  /* Turn OFF M-PHY RMMI interface clocks */
>  void ufs_qcom_phy_disable_iface_clk(struct phy *generic_phy)
> @@ -562,6 +567,7 @@ void ufs_qcom_phy_disable_iface_clk(struct phy
> *generic_phy)
>   phy->is_iface_clk_enabled = false;
>   }
>  }
> +EXPORT_SYMBOL_GPL(ufs_qcom_phy_disable_iface_clk);
>
>  int ufs_qcom_phy_start_serdes(struct phy *generic_phy)
>  {
> @@ -578,6 +584,7 @@ int ufs_qcom_phy_start_serdes(struct phy *generic_phy)
>
>   return ret;
>  }
> +EXPORT_SYMBOL_GPL(ufs_qcom_phy_start_serdes);
>
>  int ufs_qcom_phy_set_tx_lane_enable(struct phy *generic_phy, u32
> tx_lanes)
>  {
> @@ -595,6 +602,7 @@ int ufs_qcom_phy_set_tx_lane_enable(struct phy
> *generic_phy, u32 tx_lanes)
>
>   return ret;
>  }
> +EXPORT_SYMBOL_GPL(ufs_qcom_phy_set_tx_lane_enable);
>
>  void ufs_qcom_phy_save_controller_version(struct phy *generic_phy,
> u8 major, u16 minor, u16 step)
> @@ -605,6 +613,7 @@ void ufs_qcom_phy_save_controller_version(struct phy
> *generic_phy,
>   ufs_qcom_phy->host_ctrl_rev_minor = minor;
>   ufs_qcom_phy->host_ctrl_rev_step = step;
>  }
> +EXPORT_SYMBOL_GPL(ufs_qcom_phy_save_controller_version);
>
>  int ufs_qcom_phy_calibrate_phy(struct phy *generic_phy, bool is_rate_B)
>  {
> @@ -625,6 +634,7 @@ int ufs_qcom_phy_calibrate_phy(struct phy
> *generic_phy, bool is_rate_B)
>
>   return ret;
>  }
> +EXPORT_SYMBOL_GPL(ufs_qcom_phy_calibrate_phy);
>
>  int ufs_qcom_phy_remove(struct phy *generic_phy,
>   struct ufs_qcom_phy *ufs_qcom_phy)
> @@ -662,6 +672,7 @@ int ufs_qcom_phy_is_pcs_ready(struct phy *generic_phy)
>   return ufs_qcom_phy->phy_spec_ops->
>   is_physical_coding_sublayer_ready(ufs_qcom_phy);
>  }
> +EXPORT_SYMBOL_GPL(ufs_qcom_phy_is_pcs_r

Re: [PATCH v5 08/15] scsi: ufs: add retries to dme_peer get and set attribute

2015-10-27 Thread Gilad Broner
Reviewed-by: Gilad Broner <gbro...@codeaurora.org>

> The dme_peer get/set attribute commands are prone to errors, therefore
> we add three retries for the UIC command sending.
> Error code returned from ufshcd_send_uic_cmd() is checked, and unless
> it was successful or the retries have finished, another command will be
> sent.
>
> Signed-off-by: Lee Susman <lsus...@codeaurora.org>
> Signed-off-by: Yaniv Gardi <yga...@codeaurora.org>
>
> ---
>  drivers/scsi/ufs/ufshcd.c | 40 +---
>  1 file changed, 29 insertions(+), 11 deletions(-)
>
> diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
> index 8a04691..5005d12 100644
> --- a/drivers/scsi/ufs/ufshcd.c
> +++ b/drivers/scsi/ufs/ufshcd.c
> @@ -70,6 +70,9 @@
>  /* Task management command timeout */
>  #define TM_CMD_TIMEOUT   100 /* msecs */
>
> +/* maximum number of retries for a general UIC command  */
> +#define UFS_UIC_COMMAND_RETRIES 3
> +
>  /* maximum number of link-startup retries */
>  #define DME_LINKSTARTUP_RETRIES 3
>
> @@ -2185,6 +2188,7 @@ int ufshcd_dme_set_attr(struct ufs_hba *hba, u32
> attr_sel,
>   };
>   const char *set = action[!!peer];
>   int ret;
> + int retries = UFS_UIC_COMMAND_RETRIES;
>
>   uic_cmd.command = peer ?
>   UIC_CMD_DME_PEER_SET : UIC_CMD_DME_SET;
> @@ -2192,10 +2196,18 @@ int ufshcd_dme_set_attr(struct ufs_hba *hba, u32
> attr_sel,
>   uic_cmd.argument2 = UIC_ARG_ATTR_TYPE(attr_set);
>   uic_cmd.argument3 = mib_val;
>
> - ret = ufshcd_send_uic_cmd(hba, _cmd);
> - if (ret)
> - dev_err(hba->dev, "%s: attr-id 0x%x val 0x%x error code %d\n",
> - set, UIC_GET_ATTR_ID(attr_sel), mib_val, ret);
> + do {
> + /* for peer attributes we retry upon failure */
> + ret = ufshcd_send_uic_cmd(hba, _cmd);
> + if (ret)
> + dev_dbg(hba->dev, "%s: attr-id 0x%x val 0x%x error code 
> %d\n",
> + set, UIC_GET_ATTR_ID(attr_sel), mib_val, ret);
> + } while (ret && peer && --retries);
> +
> + if (!retries)
> + dev_err(hba->dev, "%s: attr-id 0x%x val 0x%x failed %d 
> retries\n",
> + set, UIC_GET_ATTR_ID(attr_sel), mib_val,
> + retries);
>
>   return ret;
>  }
> @@ -2220,6 +2232,7 @@ int ufshcd_dme_get_attr(struct ufs_hba *hba, u32
> attr_sel,
>   };
>   const char *get = action[!!peer];
>   int ret;
> + int retries = UFS_UIC_COMMAND_RETRIES;
>   struct ufs_pa_layer_attr orig_pwr_info;
>   struct ufs_pa_layer_attr temp_pwr_info;
>   bool pwr_mode_change = false;
> @@ -2250,14 +2263,19 @@ int ufshcd_dme_get_attr(struct ufs_hba *hba, u32
> attr_sel,
>   UIC_CMD_DME_PEER_GET : UIC_CMD_DME_GET;
>   uic_cmd.argument1 = attr_sel;
>
> - ret = ufshcd_send_uic_cmd(hba, _cmd);
> - if (ret) {
> - dev_err(hba->dev, "%s: attr-id 0x%x error code %d\n",
> - get, UIC_GET_ATTR_ID(attr_sel), ret);
> - goto out;
> - }
> + do {
> + /* for peer attributes we retry upon failure */
> + ret = ufshcd_send_uic_cmd(hba, _cmd);
> + if (ret)
> + dev_dbg(hba->dev, "%s: attr-id 0x%x error code %d\n",
> + get, UIC_GET_ATTR_ID(attr_sel), ret);
> + } while (ret && peer && --retries);
> +
> + if (!retries)
> + dev_err(hba->dev, "%s: attr-id 0x%x failed %d retries\n",
> + get, UIC_GET_ATTR_ID(attr_sel), retries);
>
> - if (mib_val)
> + if (mib_val && !ret)
>   *mib_val = uic_cmd.argument3;
>
>   if (peer && (hba->quirks & UFSHCD_QUIRK_DME_PEER_ACCESS_AUTO_MODE)
> --
> 1.8.5.2
>
> --
> QUALCOMM ISRAEL, on behalf of Qualcomm Innovation Center, Inc. is a member
> of Code Aurora Forum, hosted by The Linux Foundation
> --
> To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
> the body of a message to majord...@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>


-- 
Qualcomm Israel, on behalf of Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH v5 09/15] scsi: ufs: add retries for hibern8 enter

2015-10-27 Thread Gilad Broner
Reviewed-by: Gilad Broner <gbro...@codeaurora.org>

> If hibern8 enter command fails then UFS link state may be unknown which
> may result into timeout of all the commands issued after failure.
>
> This change does 2 things (for pre-defined number of retry counts) after
> hibern8 enter failure:
> 1. Recovers the UFS link to active state
> 2. If link is recovered to active state, tries to put the UFS link in
>hibern8 enter again until retry count expires.
>
> Signed-off-by: Subhash Jadavani <subha...@codeaurora.org>
> Signed-off-by: Yaniv Gardi <yga...@codeaurora.org>
>
> ---
>  drivers/scsi/ufs/ufshcd.c | 26 --
>  1 file changed, 24 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
> index 5005d12..ed134d6 100644
> --- a/drivers/scsi/ufs/ufshcd.c
> +++ b/drivers/scsi/ufs/ufshcd.c
> @@ -76,6 +76,9 @@
>  /* maximum number of link-startup retries */
>  #define DME_LINKSTARTUP_RETRIES 3
>
> +/* Maximum retries for Hibern8 enter */
> +#define UIC_HIBERN8_ENTER_RETRIES 3
> +
>  /* maximum number of reset retries before giving up */
>  #define MAX_HOST_RESET_RETRIES 5
>
> @@ -2390,13 +2393,32 @@ out:
>   return ret;
>  }
>
> -static int ufshcd_uic_hibern8_enter(struct ufs_hba *hba)
> +static int __ufshcd_uic_hibern8_enter(struct ufs_hba *hba)
>  {
> + int ret;
>   struct uic_command uic_cmd = {0};
>
>   uic_cmd.command = UIC_CMD_DME_HIBER_ENTER;
> + ret = ufshcd_uic_pwr_ctrl(hba, _cmd);
> +
> + if (ret)
> + dev_err(hba->dev, "%s: hibern8 enter failed. ret = %d\n",
> + __func__, ret);
> +
> + return ret;
> +}
> +
> +static int ufshcd_uic_hibern8_enter(struct ufs_hba *hba)
> +{
> + int ret = 0, retries;
>
> - return ufshcd_uic_pwr_ctrl(hba, _cmd);
> + for (retries = UIC_HIBERN8_ENTER_RETRIES; retries > 0; retries--) {
> + ret = __ufshcd_uic_hibern8_enter(hba);
> + if (!ret || ret == -ENOLINK)
> + goto out;
> + }
> +out:
> + return ret;
>  }
>
>  static int ufshcd_uic_hibern8_exit(struct ufs_hba *hba)
> --
> 1.8.5.2
>
> --
> QUALCOMM ISRAEL, on behalf of Qualcomm Innovation Center, Inc. is a member
> of Code Aurora Forum, hosted by The Linux Foundation
> --
> To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
> the body of a message to majord...@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>


-- 
Qualcomm Israel, on behalf of Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH v5 06/15] scsi: ufs: avoid exception event handler racing with PM callbacks

2015-10-27 Thread Gilad Broner
Reviewed-by: Gilad Broner <gbro...@codeaurora.org>

> If device raises the exception event in the response to the commands
> sent during the runtime/system PM callbacks, exception event handler
> might run in parallel with PM callbacks and may see unclocked register
> accesses. This change fixes this issue by not scheduling the exception
> event handler while PM callbacks are running.
>
> Signed-off-by: Subhash Jadavani <subha...@codeaurora.org>
> Signed-off-by: Yaniv Gardi <yga...@codeaurora.org>
>
> ---
>  drivers/scsi/ufs/ufshcd.c | 15 ++-
>  1 file changed, 14 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
> index 573a8cb..0e54183 100644
> --- a/drivers/scsi/ufs/ufshcd.c
> +++ b/drivers/scsi/ufs/ufshcd.c
> @@ -3145,7 +3145,20 @@ ufshcd_transfer_rsp_status(struct ufs_hba *hba,
> struct ufshcd_lrb *lrbp)
>   scsi_status = result & MASK_SCSI_STATUS;
>   result = ufshcd_scsi_cmd_status(lrbp, scsi_status);
>
> - if (ufshcd_is_exception_event(lrbp->ucd_rsp_ptr))
> + /*
> +  * Currently we are only supporting BKOPs exception
> +  * events hence we can ignore BKOPs exception event
> +  * during power management callbacks. BKOPs exception
> +  * event is not expected to be raised in runtime suspend
> +  * callback as it allows the urgent bkops.
> +  * During system suspend, we are anyway forcefully
> +  * disabling the bkops and if urgent bkops is needed
> +  * it will be enabled on system resume. Long term
> +  * solution could be to abort the system suspend if
> +  * UFS device needs urgent BKOPs.
> +  */
> + if (!hba->pm_op_in_progress &&
> + ufshcd_is_exception_event(lrbp->ucd_rsp_ptr))
>   schedule_work(>eeh_work);
>   break;
>   case UPIU_TRANSACTION_REJECT_UPIU:
> --
> 1.8.5.2
>
> --
> QUALCOMM ISRAEL, on behalf of Qualcomm Innovation Center, Inc. is a member
> of Code Aurora Forum, hosted by The Linux Foundation
> --
> To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
> the body of a message to majord...@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>


-- 
Qualcomm Israel, on behalf of Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH v5 15/15] scsi: ufs: add wrapper for retrying sending query attribute

2015-10-27 Thread Gilad Broner
Reviewed-by: Gilad Broner <gbro...@codeaurora.org>

> Sometimes queries from the device might return a failure so it is
> recommended to retry sending the query, before giving up.
> This change adds a wrapper to retry sending a query attribute,
> in cases where we need to wait longer, before we continue,
> or before reporting a failure.
>
> Signed-off-by: Yaniv Gardi <yga...@codeaurora.org>
>
> ---
>  drivers/scsi/ufs/ufshcd.c | 51
> ---
>  1 file changed, 44 insertions(+), 7 deletions(-)
>
> diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
> index ec90504..1d1e681 100644
> --- a/drivers/scsi/ufs/ufshcd.c
> +++ b/drivers/scsi/ufs/ufshcd.c
> @@ -1824,6 +1824,43 @@ out:
>  }
>
>  /**
> + * ufshcd_query_attr_retry() - API function for sending query
> + * attribute with retries
> + * @hba: per-adapter instance
> + * @opcode: attribute opcode
> + * @idn: attribute idn to access
> + * @index: index field
> + * @selector: selector field
> + * @attr_val: the attribute value after the query request
> + * completes
> + *
> + * Returns 0 for success, non-zero in case of failure
> +*/
> +static 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 ret = 0;
> + u32 retries;
> +
> +  for (retries = QUERY_REQ_RETRIES; retries > 0; retries--) {
> + ret = ufshcd_query_attr(hba, opcode, idn, index,
> + selector, attr_val);
> + if (ret)
> + dev_dbg(hba->dev, "%s: failed with error %d, retries 
> %d\n",
> + __func__, ret, retries);
> + else
> + break;
> + }
> +
> + if (ret)
> + dev_err(hba->dev,
> + "%s: query attribute, idn %d, failed with error %d 
> after %d
> retires\n",
> + __func__, idn, ret, QUERY_REQ_RETRIES);
> + return ret;
> +}
> +
> +/**
>   * ufshcd_query_descriptor - API function for sending descriptor requests
>   * hba: per-adapter instance
>   * opcode: attribute opcode
> @@ -3404,7 +3441,7 @@ static int ufshcd_disable_ee(struct ufs_hba *hba,
> u16 mask)
>
>   val = hba->ee_ctrl_mask & ~mask;
>   val &= 0x; /* 2 bytes */
> - err = ufshcd_query_attr(hba, UPIU_QUERY_OPCODE_WRITE_ATTR,
> + err = ufshcd_query_attr_retry(hba, UPIU_QUERY_OPCODE_WRITE_ATTR,
>   QUERY_ATTR_IDN_EE_CONTROL, 0, 0, );
>   if (!err)
>   hba->ee_ctrl_mask &= ~mask;
> @@ -3432,7 +3469,7 @@ static int ufshcd_enable_ee(struct ufs_hba *hba, u16
> mask)
>
>   val = hba->ee_ctrl_mask | mask;
>   val &= 0x; /* 2 bytes */
> - err = ufshcd_query_attr(hba, UPIU_QUERY_OPCODE_WRITE_ATTR,
> + err = ufshcd_query_attr_retry(hba, UPIU_QUERY_OPCODE_WRITE_ATTR,
>   QUERY_ATTR_IDN_EE_CONTROL, 0, 0, );
>   if (!err)
>   hba->ee_ctrl_mask |= mask;
> @@ -3538,7 +3575,7 @@ static void  ufshcd_force_reset_auto_bkops(struct
> ufs_hba *hba)
>
>  static inline int ufshcd_get_bkops_status(struct ufs_hba *hba, u32
> *status)
>  {
> - return ufshcd_query_attr(hba, UPIU_QUERY_OPCODE_READ_ATTR,
> + return ufshcd_query_attr_retry(hba, UPIU_QUERY_OPCODE_READ_ATTR,
>   QUERY_ATTR_IDN_BKOPS_STATUS, 0, 0, status);
>  }
>
> @@ -3601,7 +3638,7 @@ static int ufshcd_urgent_bkops(struct ufs_hba *hba)
>
>  static inline int ufshcd_get_ee_status(struct ufs_hba *hba, u32 *status)
>  {
> - return ufshcd_query_attr(hba, UPIU_QUERY_OPCODE_READ_ATTR,
> + return ufshcd_query_attr_retry(hba, UPIU_QUERY_OPCODE_READ_ATTR,
>   QUERY_ATTR_IDN_EE_STATUS, 0, 0, status);
>  }
>
> @@ -4355,9 +4392,9 @@ static void ufshcd_init_icc_levels(struct ufs_hba
> *hba)
>   dev_dbg(hba->dev, "%s: setting icc_level 0x%x",
>   __func__, hba->init_prefetch_data.icc_level);
>
> - ret = ufshcd_query_attr(hba, UPIU_QUERY_OPCODE_WRITE_ATTR,
> - QUERY_ATTR_IDN_ACTIVE_ICC_LVL, 0, 0,
> - >init_prefetch_data.icc_level);
> + ret = ufshcd_query_attr_retry(hba, UPIU_QUERY_OPCODE_WRITE_ATTR,
> + QUERY_ATTR_IDN_ACTIVE_ICC_LVL, 0, 0,
> + >init_prefetch_data.icc_level);
>
>   if (ret)
>   dev_err(hba->dev,
> --
> 1.8.5.2
>
> --
> QUALCOMM ISRAEL, on behalf of Qualcomm Innovation Center, Inc. is a member
>

Re: [PATCH v5 10/15] scsi: ufs: fix error recovery after the hibern8 exit failure

2015-10-27 Thread Gilad Broner
Reviewed-by: Gilad Broner <gbro...@codeaurora.org>

> Hibern8 exit can be called from 3 different context:
> - ufshcd_hibern8_exit_work
> - ufshcd_ungate_work
> - runtime/system resume
>
> If hibern8 exit fails for some reason then we try to bring the link to
> active state by link startup but this recovery mechanism results into
> deadlock or errors from first 2 context listed above. This change fixes
> the recovery by adding proper error handling mechanism.
>
> Signed-off-by: Subhash Jadavani <subha...@codeaurora.org>
> Signed-off-by: Yaniv Gardi <yga...@codeaurora.org>
>
> ---
>  drivers/scsi/ufs/ufshcd.c | 58
> +++
>  1 file changed, 53 insertions(+), 5 deletions(-)
>
> diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
> index ed134d6..60ba729 100644
> --- a/drivers/scsi/ufs/ufshcd.c
> +++ b/drivers/scsi/ufs/ufshcd.c
> @@ -610,6 +610,11 @@ int ufshcd_hold(struct ufs_hba *hba, bool async)
>   spin_lock_irqsave(hba->host->host_lock, flags);
>   hba->clk_gating.active_reqs++;
>
> + if (ufshcd_eh_in_progress(hba)) {
> + spin_unlock_irqrestore(hba->host->host_lock, flags);
> + return 0;
> + }
> +
>  start:
>   switch (hba->clk_gating.state) {
>   case CLKS_ON:
> @@ -725,7 +730,8 @@ static void __ufshcd_release(struct ufs_hba *hba)
>   if (hba->clk_gating.active_reqs || hba->clk_gating.is_suspended
>   || hba->ufshcd_state != UFSHCD_STATE_OPERATIONAL
>   || hba->lrb_in_use || hba->outstanding_tasks
> - || hba->active_uic_cmd || hba->uic_async_done)
> + || hba->active_uic_cmd || hba->uic_async_done
> + || ufshcd_eh_in_progress(hba))
>   return;
>
>   hba->clk_gating.state = REQ_CLKS_OFF;
> @@ -1363,6 +1369,13 @@ static int ufshcd_queuecommand(struct Scsi_Host
> *host, struct scsi_cmnd *cmd)
>   cmd->scsi_done(cmd);
>   goto out_unlock;
>   }
> +
> + /* if error handling is in progress, don't issue commands */
> + if (ufshcd_eh_in_progress(hba)) {
> + set_host_byte(cmd, DID_ERROR);
> + cmd->scsi_done(cmd);
> + goto out_unlock;
> + }
>   spin_unlock_irqrestore(hba->host->host_lock, flags);
>
>   /* acquire the tag to make sure device cmds don't use it */
> @@ -2393,6 +2406,31 @@ out:
>   return ret;
>  }
>
> +static int ufshcd_link_recovery(struct ufs_hba *hba)
> +{
> + int ret;
> + unsigned long flags;
> +
> + spin_lock_irqsave(hba->host->host_lock, flags);
> + hba->ufshcd_state = UFSHCD_STATE_RESET;
> + ufshcd_set_eh_in_progress(hba);
> + spin_unlock_irqrestore(hba->host->host_lock, flags);
> +
> + ret = ufshcd_host_reset_and_restore(hba);
> +
> + spin_lock_irqsave(hba->host->host_lock, flags);
> + if (ret)
> + hba->ufshcd_state = UFSHCD_STATE_ERROR;
> + ufshcd_clear_eh_in_progress(hba);
> + spin_unlock_irqrestore(hba->host->host_lock, flags);
> +
> + if (ret)
> + dev_err(hba->dev, "%s: link recovery failed, err %d",
> + __func__, ret);
> +
> + return ret;
> +}
> +
>  static int __ufshcd_uic_hibern8_enter(struct ufs_hba *hba)
>  {
>   int ret;
> @@ -2401,10 +2439,18 @@ static int __ufshcd_uic_hibern8_enter(struct
> ufs_hba *hba)
>   uic_cmd.command = UIC_CMD_DME_HIBER_ENTER;
>   ret = ufshcd_uic_pwr_ctrl(hba, _cmd);
>
> - if (ret)
> + if (ret) {
>   dev_err(hba->dev, "%s: hibern8 enter failed. ret = %d\n",
>   __func__, ret);
>
> + /*
> +  * If link recovery fails then return error so that caller
> +  * don't retry the hibern8 enter again.
> +  */
> + if (ufshcd_link_recovery(hba))
> + ret = -ENOLINK;
> + }
> +
>   return ret;
>  }
>
> @@ -2429,8 +2475,9 @@ static int ufshcd_uic_hibern8_exit(struct ufs_hba
> *hba)
>   uic_cmd.command = UIC_CMD_DME_HIBER_EXIT;
>   ret = ufshcd_uic_pwr_ctrl(hba, _cmd);
>   if (ret) {
> - ufshcd_set_link_off(hba);
> - ret = ufshcd_host_reset_and_restore(hba);
> + dev_err(hba->dev, "%s: hibern8 exit failed. ret = %d\n",
> + __func__, ret);
> + ret = ufshcd_link_recovery(hba);
>   }
>
>   return ret;
> @@ -4382,7 +4429,6 @@ static int ufshcd_probe_hba(st

Re: [PATCH v5 12/15] scsi: ufs: reduce the interrupts for power mode change requests

2015-10-27 Thread Gilad Broner
Reviewed-by: Gilad Broner <gbro...@codeaurora.org>

> DME commands such as Hibern8 enter/exit and gear switch generate 2
> completion interrupts, one for confirmation that command is received
> by local UniPro and 2nd one is the final confirmation after communication
> with remote UniPro. Currently both of these completions are registered
> as interrupt events which is not quite necessary and instead we can
> just wait for the interrupt of 2nd completion, this should reduce
> the number of interrupts and could reduce the unnecessary CPU wakeups
> to handle extra interrupts.
>
> Signed-off-by: Subhash Jadavani <subha...@codeaurora.org>
> Signed-off-by: Yaniv Gardi <yga...@codeaurora.org>
>
> ---
>  drivers/scsi/ufs/ufshcd.c | 41 +++--
>  1 file changed, 27 insertions(+), 14 deletions(-)
>
> diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
> index 889a7be..24a879d 100644
> --- a/drivers/scsi/ufs/ufshcd.c
> +++ b/drivers/scsi/ufs/ufshcd.c
> @@ -987,13 +987,15 @@ ufshcd_wait_for_uic_cmd(struct ufs_hba *hba, struct
> uic_command *uic_cmd)
>   * __ufshcd_send_uic_cmd - Send UIC commands and retrieve the result
>   * @hba: per adapter instance
>   * @uic_cmd: UIC command
> + * @completion: initialize the completion only if this is set to true
>   *
>   * Identical to ufshcd_send_uic_cmd() expect mutex. Must be called
>   * with mutex held and host_lock locked.
>   * Returns 0 only if success.
>   */
>  static int
> -__ufshcd_send_uic_cmd(struct ufs_hba *hba, struct uic_command *uic_cmd)
> +__ufshcd_send_uic_cmd(struct ufs_hba *hba, struct uic_command *uic_cmd,
> +   bool completion)
>  {
>   if (!ufshcd_ready_for_uic_cmd(hba)) {
>   dev_err(hba->dev,
> @@ -1001,7 +1003,8 @@ __ufshcd_send_uic_cmd(struct ufs_hba *hba, struct
> uic_command *uic_cmd)
>   return -EIO;
>   }
>
> - init_completion(_cmd->done);
> + if (completion)
> + init_completion(_cmd->done);
>
>   ufshcd_dispatch_uic_cmd(hba, uic_cmd);
>
> @@ -1026,7 +1029,7 @@ ufshcd_send_uic_cmd(struct ufs_hba *hba, struct
> uic_command *uic_cmd)
>   ufshcd_add_delay_before_dme_cmd(hba);
>
>   spin_lock_irqsave(hba->host->host_lock, flags);
> - ret = __ufshcd_send_uic_cmd(hba, uic_cmd);
> + ret = __ufshcd_send_uic_cmd(hba, uic_cmd, true);
>   spin_unlock_irqrestore(hba->host->host_lock, flags);
>   if (!ret)
>   ret = ufshcd_wait_for_uic_cmd(hba, uic_cmd);
> @@ -2347,6 +2350,7 @@ static int ufshcd_uic_pwr_ctrl(struct ufs_hba *hba,
> struct uic_command *cmd)
>   unsigned long flags;
>   u8 status;
>   int ret;
> + bool reenable_intr = false;
>
>   mutex_lock(>uic_cmd_mutex);
>   init_completion(_async_done);
> @@ -2354,15 +2358,17 @@ static int ufshcd_uic_pwr_ctrl(struct ufs_hba
> *hba, struct uic_command *cmd)
>
>   spin_lock_irqsave(hba->host->host_lock, flags);
>   hba->uic_async_done = _async_done;
> - ret = __ufshcd_send_uic_cmd(hba, cmd);
> - spin_unlock_irqrestore(hba->host->host_lock, flags);
> - if (ret) {
> - dev_err(hba->dev,
> - "pwr ctrl cmd 0x%x with mode 0x%x uic error %d\n",
> - cmd->command, cmd->argument3, ret);
> - goto out;
> + if (ufshcd_readl(hba, REG_INTERRUPT_ENABLE) & UIC_COMMAND_COMPL) {
> + ufshcd_disable_intr(hba, UIC_COMMAND_COMPL);
> + /*
> +  * Make sure UIC command completion interrupt is disabled before
> +  * issuing UIC command.
> +  */
> + wmb();
> + reenable_intr = true;
>   }
> - ret = ufshcd_wait_for_uic_cmd(hba, cmd);
> + ret = __ufshcd_send_uic_cmd(hba, cmd, false);
> + spin_unlock_irqrestore(hba->host->host_lock, flags);
>   if (ret) {
>   dev_err(hba->dev,
>   "pwr ctrl cmd 0x%x with mode 0x%x uic error %d\n",
> @@ -2388,7 +2394,10 @@ static int ufshcd_uic_pwr_ctrl(struct ufs_hba *hba,
> struct uic_command *cmd)
>   }
>  out:
>   spin_lock_irqsave(hba->host->host_lock, flags);
> + hba->active_uic_cmd = NULL;
>   hba->uic_async_done = NULL;
> + if (reenable_intr)
> + ufshcd_enable_intr(hba, UIC_COMMAND_COMPL);
>   spin_unlock_irqrestore(hba->host->host_lock, flags);
>   mutex_unlock(>uic_cmd_mutex);
>
> @@ -3813,16 +3822,20 @@ static void ufshcd_sl_intr(struct ufs_hba *hba,
> u32 intr_status)
>   */
>  static irqr

Re: [PATCH v5 04/15] scsi: ufs: clear outstanding_request bit in case query timeout

2015-10-27 Thread Gilad Broner
Reviewed-by: Gilad Broner <gbro...@codeaurora.org>

> When sending a query to the device returns with a timeout error,
> we clear the corresponding bit in the DOORBELL register but
> we don't clear the outstanding_request field as we should.
> This patch fixes this bug.
>
> Signed-off-by: Yaniv Gardi <yga...@codeaurora.org>
>
> ---
>  drivers/scsi/ufs/ufshcd.c | 22 --
>  1 file changed, 20 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
> index 8860a57..e0b8755 100644
> --- a/drivers/scsi/ufs/ufshcd.c
> +++ b/drivers/scsi/ufs/ufshcd.c
> @@ -364,6 +364,16 @@ static inline void ufshcd_utrl_clear(struct ufs_hba
> *hba, u32 pos)
>  }
>
>  /**
> + * ufshcd_outstanding_req_clear - Clear a bit in outstanding request
> field
> + * @hba: per adapter instance
> + * @tag: position of the bit to be cleared
> + */
> +static inline void ufshcd_outstanding_req_clear(struct ufs_hba *hba, int
> tag)
> +{
> + __clear_bit(tag, >outstanding_reqs);
> +}
> +
> +/**
>   * ufshcd_get_lists_status - Check UCRDY, UTRLRDY and UTMRLRDY
>   * @reg: Register value of host controller status
>   *
> @@ -1502,9 +1512,17 @@ static int ufshcd_wait_for_dev_cmd(struct ufs_hba
> *hba,
>
>   if (!time_left) {
>   err = -ETIMEDOUT;
> + dev_dbg(hba->dev, "%s: dev_cmd request timedout, tag %d\n",
> + __func__, lrbp->task_tag);
>   if (!ufshcd_clear_cmd(hba, lrbp->task_tag))
> - /* sucessfully cleared the command, retry if needed */
> + /* successfully cleared the command, retry if needed */
>   err = -EAGAIN;
> + /*
> +  * in case of an error, after clearing the doorbell,
> +  * we also need to clear the outstanding_request
> +  * field in hba
> +  */
> + ufshcd_outstanding_req_clear(hba, lrbp->task_tag);
>   }
>
>   return err;
> @@ -3942,7 +3960,7 @@ static int ufshcd_abort(struct scsi_cmnd *cmd)
>   scsi_dma_unmap(cmd);
>
>   spin_lock_irqsave(host->host_lock, flags);
> - __clear_bit(tag, >outstanding_reqs);
> + ufshcd_outstanding_req_clear(hba, tag);
>   hba->lrb[tag].cmd = NULL;
>   spin_unlock_irqrestore(host->host_lock, flags);
>
> --
> 1.8.5.2
>
> --
> QUALCOMM ISRAEL, on behalf of Qualcomm Innovation Center, Inc. is a member
> of Code Aurora Forum, hosted by The Linux Foundation
> --
> To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
> the body of a message to majord...@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>


-- 
Qualcomm Israel, on behalf of Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH v5 02/15] scsi: ufs: clear fields UTRD, UPIU req and rsp before new transfers

2015-10-27 Thread Gilad Broner
Looks OK.
Reviewed-by: Gilad Broner <gbro...@codeaurora.org>

> Some of the data structures (like response UPIU) and/or its elements
> (unused fields) should be cleared before sending out the respective
> command to UFS device.
>
> This change clears the UPIU response data structure for query commands
> and NOP command before sending out the command. We also initialize the
> PRDT table length to zero which should take care of commands which doesn't
> have any data associated with it. We are also clearing the unused fields
> in
> request UPIU for NOP command.
>
> Signed-off-by: Subhash Jadavani <subha...@codeaurora.org>
> Signed-off-by: Yaniv Gardi <yga...@codeaurora.org>
>
> ---
>  drivers/scsi/ufs/ufshcd.c | 8 
>  1 file changed, 8 insertions(+)
>
> diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
> index 3428f72..2d3ebca 100644
> --- a/drivers/scsi/ufs/ufshcd.c
> +++ b/drivers/scsi/ufs/ufshcd.c
> @@ -1129,6 +1129,8 @@ static void ufshcd_prepare_req_desc_hdr(struct
> ufshcd_lrb *lrbp,
>   cpu_to_le32(OCS_INVALID_COMMAND_STATUS);
>   /* dword_3 is reserved, hence it is set to 0 */
>   req_desc->header.dword_3 = 0;
> +
> + req_desc->prd_table_length = 0;
>  }
>
>  /**
> @@ -1198,6 +1200,7 @@ static void ufshcd_prepare_utp_query_req_upiu(struct
> ufs_hba *hba,
>   if (query->request.upiu_req.opcode == UPIU_QUERY_OPCODE_WRITE_DESC)
>   memcpy(descp, query->descriptor, len);
>
> + memset(lrbp->ucd_rsp_ptr, 0, sizeof(struct utp_upiu_rsp));
>  }
>
>  static inline void ufshcd_prepare_utp_nop_upiu(struct ufshcd_lrb *lrbp)
> @@ -1210,6 +1213,11 @@ static inline void
> ufshcd_prepare_utp_nop_upiu(struct ufshcd_lrb *lrbp)
>   ucd_req_ptr->header.dword_0 =
>   UPIU_HEADER_DWORD(
>   UPIU_TRANSACTION_NOP_OUT, 0, 0, lrbp->task_tag);
> + /* clear rest of the fields of basic header */
> + ucd_req_ptr->header.dword_1 = 0;
> + ucd_req_ptr->header.dword_2 = 0;
> +
> + memset(lrbp->ucd_rsp_ptr, 0, sizeof(struct utp_upiu_rsp));
>  }
>
>  /**
> --
> 1.8.5.2
>
> --
> QUALCOMM ISRAEL, on behalf of Qualcomm Innovation Center, Inc. is a member
> of Code Aurora Forum, hosted by The Linux Foundation
> --
> To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
> the body of a message to majord...@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>


-- 
Qualcomm Israel, on behalf of Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH v8 3/8] scsi: ufs-qcom: update configuration option of SCSI_UFS_QCOM component

2015-10-27 Thread Gilad Broner
Reviewed-by: Gilad Broner <gbro...@codeaurora.org>

> This change is required in order to be able to build the component
> as a module.
>
> Signed-off-by: Yaniv Gardi <yga...@codeaurora.org>
>
> ---
>  drivers/scsi/ufs/Kconfig | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/drivers/scsi/ufs/Kconfig b/drivers/scsi/ufs/Kconfig
> index e945383..5f45307 100644
> --- a/drivers/scsi/ufs/Kconfig
> +++ b/drivers/scsi/ufs/Kconfig
> @@ -72,7 +72,7 @@ config SCSI_UFSHCD_PLATFORM
> If unsure, say N.
>
>  config SCSI_UFS_QCOM
> - bool "QCOM specific hooks to UFS controller platform driver"
> + tristate "QCOM specific hooks to UFS controller platform driver"
>   depends on SCSI_UFSHCD_PLATFORM && ARCH_QCOM
>   select PHY_QCOM_UFS
>   help
> --
> 1.8.5.2
>
> --
> QUALCOMM ISRAEL, on behalf of Qualcomm Innovation Center, Inc. is a member
> of Code Aurora Forum, hosted by The Linux Foundation
> --
> To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
> the body of a message to majord...@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>


-- 
Qualcomm Israel, on behalf of Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH v9] scsi: ufs: add ioctl interface for query request

2015-05-19 Thread Gilad Broner
From: Dolev Raviv 

This patch exposes the ioctl interface for UFS driver via SCSI device
ioctl interface. As of now UFS driver would provide the ioctl for query
interface to connected UFS device.

Changes from V8:
Removed error prints and cleaned up some typos.

Signed-off-by: Dolev Raviv 
Signed-off-by: Noa Rubens 
Signed-off-by: Raviv Shvili 
Signed-off-by: Yaniv Gardi 
Signed-off-by: Gilad Broner 
---
 drivers/scsi/ufs/ufs.h|  53 +++
 drivers/scsi/ufs/ufshcd.c | 205 +-
 include/scsi/scsi.h   |   1 +
 include/uapi/scsi/Kbuild  |   1 +
 include/uapi/scsi/ufs/Kbuild  |   3 +
 include/uapi/scsi/ufs/ioctl.h |  57 
 include/uapi/scsi/ufs/ufs.h   |  66 ++
 7 files changed, 342 insertions(+), 44 deletions(-)
 create mode 100644 include/uapi/scsi/ufs/Kbuild
 create mode 100644 include/uapi/scsi/ufs/ioctl.h
 create mode 100644 include/uapi/scsi/ufs/ufs.h

diff --git a/drivers/scsi/ufs/ufs.h b/drivers/scsi/ufs/ufs.h
index 42c459a..1f023c4 100644
--- a/drivers/scsi/ufs/ufs.h
+++ b/drivers/scsi/ufs/ufs.h
@@ -38,6 +38,7 @@
 
 #include 
 #include 
+#include 
 
 #define MAX_CDB_SIZE   16
 #define GENERAL_UPIU_REQUEST_SIZE 32
@@ -71,6 +72,16 @@ enum {
UFS_UPIU_RPMB_WLUN  = 0xC4,
 };
 
+/**
+ * ufs_is_valid_unit_desc_lun - checks if the given LUN has a unit descriptor
+ * @lun: LU number to check
+ * @return: true if the lun has a matching unit descriptor, false otherwise
+ */
+static inline bool ufs_is_valid_unit_desc_lun(u8 lun)
+{
+   return (lun == UFS_UPIU_RPMB_WLUN || (lun < UFS_UPIU_MAX_GENERAL_LUN));
+}
+
 /*
  * UFS Protocol Information Unit related definitions
  */
@@ -126,35 +137,6 @@ enum {
UPIU_QUERY_FUNC_STANDARD_WRITE_REQUEST  = 0x81,
 };
 
-/* Flag idn for Query Requests*/
-enum flag_idn {
-   QUERY_FLAG_IDN_FDEVICEINIT  = 0x01,
-   QUERY_FLAG_IDN_PWR_ON_WPE   = 0x03,
-   QUERY_FLAG_IDN_BKOPS_EN = 0x04,
-};
-
-/* Attribute idn for Query requests */
-enum attr_idn {
-   QUERY_ATTR_IDN_ACTIVE_ICC_LVL   = 0x03,
-   QUERY_ATTR_IDN_BKOPS_STATUS = 0x05,
-   QUERY_ATTR_IDN_EE_CONTROL   = 0x0D,
-   QUERY_ATTR_IDN_EE_STATUS= 0x0E,
-};
-
-/* Descriptor idn for Query requests */
-enum desc_idn {
-   QUERY_DESC_IDN_DEVICE   = 0x0,
-   QUERY_DESC_IDN_CONFIGURAION = 0x1,
-   QUERY_DESC_IDN_UNIT = 0x2,
-   QUERY_DESC_IDN_RFU_0= 0x3,
-   QUERY_DESC_IDN_INTERCONNECT = 0x4,
-   QUERY_DESC_IDN_STRING   = 0x5,
-   QUERY_DESC_IDN_RFU_1= 0x6,
-   QUERY_DESC_IDN_GEOMETRY = 0x7,
-   QUERY_DESC_IDN_POWER= 0x8,
-   QUERY_DESC_IDN_MAX,
-};
-
 enum desc_header_offset {
QUERY_DESC_LENGTH_OFFSET= 0x00,
QUERY_DESC_DESC_TYPE_OFFSET = 0x01,
@@ -247,19 +229,6 @@ enum bkops_status {
BKOPS_STATUS_MAX = BKOPS_STATUS_CRITICAL,
 };
 
-/* UTP QUERY Transaction Specific Fields OpCode */
-enum query_opcode {
-   UPIU_QUERY_OPCODE_NOP   = 0x0,
-   UPIU_QUERY_OPCODE_READ_DESC = 0x1,
-   UPIU_QUERY_OPCODE_WRITE_DESC= 0x2,
-   UPIU_QUERY_OPCODE_READ_ATTR = 0x3,
-   UPIU_QUERY_OPCODE_WRITE_ATTR= 0x4,
-   UPIU_QUERY_OPCODE_READ_FLAG = 0x5,
-   UPIU_QUERY_OPCODE_SET_FLAG  = 0x6,
-   UPIU_QUERY_OPCODE_CLEAR_FLAG= 0x7,
-   UPIU_QUERY_OPCODE_TOGGLE_FLAG   = 0x8,
-};
-
 /* Query response result code */
 enum {
QUERY_RESULT_SUCCESS= 0x00,
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index 648a446..4674dee 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -3,7 +3,7 @@
  *
  * This code is based on drivers/scsi/ufs/ufshcd.c
  * Copyright (C) 2011-2013 Samsung India Software Operations
- * Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-2015, The Linux Foundation. All rights reserved.
  *
  * Authors:
  * Santosh Yaraganavi 
@@ -39,6 +39,7 @@
 
 #include 
 #include 
+#include 
 
 #include "ufshcd.h"
 #include "unipro.h"
@@ -74,6 +75,9 @@
 /* Interrupt aggregation default timeout, unit: 40us */
 #define INT_AGGR_DEF_TO0x02
 
+/* IOCTL opcode for command - ufs set device read only */
+#define UFS_IOCTL_BLKROSET  BLKROSET
+
 #define ufshcd_toggle_vreg(_dev, _vreg, _on)   \
({  \
int _ret;   \
@@ -1885,7 +1889,7 @@ static inline int ufshcd_read_unit_desc_param(struct 
ufs_hba *hba,
 * Unit descriptors are only available for general purpose LUs (LUN id
 * from 0 to 7) and RPMB Well known LU.
 */
-   if (lun != UFS_UPIU_RPMB_WLUN && (lun >= UFS_UPIU_MAX_GENERAL_LUN))
+   i

[PATCH v9] scsi: ufs: add ioctl interface for query request

2015-05-19 Thread Gilad Broner
This patch was originally patch 1/3 in a patch series titled "Add ioctl and 
debug utilities to UFS driver".
As it has no dependency with the debug utilities it is separated from the 
series, and now stands on its own.

Dolev Raviv (1):
  scsi: ufs: add ioctl interface for query request

 drivers/scsi/ufs/ufs.h|  53 +++
 drivers/scsi/ufs/ufshcd.c | 205 +-
 include/scsi/scsi.h   |   1 +
 include/uapi/scsi/Kbuild  |   1 +
 include/uapi/scsi/ufs/Kbuild  |   3 +
 include/uapi/scsi/ufs/ioctl.h |  57 
 include/uapi/scsi/ufs/ufs.h   |  66 ++
 7 files changed, 342 insertions(+), 44 deletions(-)
 create mode 100644 include/uapi/scsi/ufs/Kbuild
 create mode 100644 include/uapi/scsi/ufs/ioctl.h
 create mode 100644 include/uapi/scsi/ufs/ufs.h

-- 
Qualcomm Israel, on behalf of Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH v9] scsi: ufs: add ioctl interface for query request

2015-05-19 Thread Gilad Broner
From: Dolev Raviv dra...@codeaurora.org

This patch exposes the ioctl interface for UFS driver via SCSI device
ioctl interface. As of now UFS driver would provide the ioctl for query
interface to connected UFS device.

Changes from V8:
Removed error prints and cleaned up some typos.

Signed-off-by: Dolev Raviv dra...@codeaurora.org
Signed-off-by: Noa Rubens n...@codeaurora.org
Signed-off-by: Raviv Shvili rshv...@codeaurora.org
Signed-off-by: Yaniv Gardi yga...@codeaurora.org
Signed-off-by: Gilad Broner gbro...@codeaurora.org
---
 drivers/scsi/ufs/ufs.h|  53 +++
 drivers/scsi/ufs/ufshcd.c | 205 +-
 include/scsi/scsi.h   |   1 +
 include/uapi/scsi/Kbuild  |   1 +
 include/uapi/scsi/ufs/Kbuild  |   3 +
 include/uapi/scsi/ufs/ioctl.h |  57 
 include/uapi/scsi/ufs/ufs.h   |  66 ++
 7 files changed, 342 insertions(+), 44 deletions(-)
 create mode 100644 include/uapi/scsi/ufs/Kbuild
 create mode 100644 include/uapi/scsi/ufs/ioctl.h
 create mode 100644 include/uapi/scsi/ufs/ufs.h

diff --git a/drivers/scsi/ufs/ufs.h b/drivers/scsi/ufs/ufs.h
index 42c459a..1f023c4 100644
--- a/drivers/scsi/ufs/ufs.h
+++ b/drivers/scsi/ufs/ufs.h
@@ -38,6 +38,7 @@
 
 #include linux/mutex.h
 #include linux/types.h
+#include scsi/ufs/ufs.h
 
 #define MAX_CDB_SIZE   16
 #define GENERAL_UPIU_REQUEST_SIZE 32
@@ -71,6 +72,16 @@ enum {
UFS_UPIU_RPMB_WLUN  = 0xC4,
 };
 
+/**
+ * ufs_is_valid_unit_desc_lun - checks if the given LUN has a unit descriptor
+ * @lun: LU number to check
+ * @return: true if the lun has a matching unit descriptor, false otherwise
+ */
+static inline bool ufs_is_valid_unit_desc_lun(u8 lun)
+{
+   return (lun == UFS_UPIU_RPMB_WLUN || (lun  UFS_UPIU_MAX_GENERAL_LUN));
+}
+
 /*
  * UFS Protocol Information Unit related definitions
  */
@@ -126,35 +137,6 @@ enum {
UPIU_QUERY_FUNC_STANDARD_WRITE_REQUEST  = 0x81,
 };
 
-/* Flag idn for Query Requests*/
-enum flag_idn {
-   QUERY_FLAG_IDN_FDEVICEINIT  = 0x01,
-   QUERY_FLAG_IDN_PWR_ON_WPE   = 0x03,
-   QUERY_FLAG_IDN_BKOPS_EN = 0x04,
-};
-
-/* Attribute idn for Query requests */
-enum attr_idn {
-   QUERY_ATTR_IDN_ACTIVE_ICC_LVL   = 0x03,
-   QUERY_ATTR_IDN_BKOPS_STATUS = 0x05,
-   QUERY_ATTR_IDN_EE_CONTROL   = 0x0D,
-   QUERY_ATTR_IDN_EE_STATUS= 0x0E,
-};
-
-/* Descriptor idn for Query requests */
-enum desc_idn {
-   QUERY_DESC_IDN_DEVICE   = 0x0,
-   QUERY_DESC_IDN_CONFIGURAION = 0x1,
-   QUERY_DESC_IDN_UNIT = 0x2,
-   QUERY_DESC_IDN_RFU_0= 0x3,
-   QUERY_DESC_IDN_INTERCONNECT = 0x4,
-   QUERY_DESC_IDN_STRING   = 0x5,
-   QUERY_DESC_IDN_RFU_1= 0x6,
-   QUERY_DESC_IDN_GEOMETRY = 0x7,
-   QUERY_DESC_IDN_POWER= 0x8,
-   QUERY_DESC_IDN_MAX,
-};
-
 enum desc_header_offset {
QUERY_DESC_LENGTH_OFFSET= 0x00,
QUERY_DESC_DESC_TYPE_OFFSET = 0x01,
@@ -247,19 +229,6 @@ enum bkops_status {
BKOPS_STATUS_MAX = BKOPS_STATUS_CRITICAL,
 };
 
-/* UTP QUERY Transaction Specific Fields OpCode */
-enum query_opcode {
-   UPIU_QUERY_OPCODE_NOP   = 0x0,
-   UPIU_QUERY_OPCODE_READ_DESC = 0x1,
-   UPIU_QUERY_OPCODE_WRITE_DESC= 0x2,
-   UPIU_QUERY_OPCODE_READ_ATTR = 0x3,
-   UPIU_QUERY_OPCODE_WRITE_ATTR= 0x4,
-   UPIU_QUERY_OPCODE_READ_FLAG = 0x5,
-   UPIU_QUERY_OPCODE_SET_FLAG  = 0x6,
-   UPIU_QUERY_OPCODE_CLEAR_FLAG= 0x7,
-   UPIU_QUERY_OPCODE_TOGGLE_FLAG   = 0x8,
-};
-
 /* Query response result code */
 enum {
QUERY_RESULT_SUCCESS= 0x00,
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index 648a446..4674dee 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -3,7 +3,7 @@
  *
  * This code is based on drivers/scsi/ufs/ufshcd.c
  * Copyright (C) 2011-2013 Samsung India Software Operations
- * Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-2015, The Linux Foundation. All rights reserved.
  *
  * Authors:
  * Santosh Yaraganavi santosh...@samsung.com
@@ -39,6 +39,7 @@
 
 #include linux/async.h
 #include linux/devfreq.h
+#include scsi/ufs/ioctl.h
 
 #include ufshcd.h
 #include unipro.h
@@ -74,6 +75,9 @@
 /* Interrupt aggregation default timeout, unit: 40us */
 #define INT_AGGR_DEF_TO0x02
 
+/* IOCTL opcode for command - ufs set device read only */
+#define UFS_IOCTL_BLKROSET  BLKROSET
+
 #define ufshcd_toggle_vreg(_dev, _vreg, _on)   \
({  \
int _ret;   \
@@ -1885,7 +1889,7 @@ static inline int ufshcd_read_unit_desc_param(struct 
ufs_hba *hba,
 * Unit descriptors are only available

[PATCH v9] scsi: ufs: add ioctl interface for query request

2015-05-19 Thread Gilad Broner
This patch was originally patch 1/3 in a patch series titled Add ioctl and 
debug utilities to UFS driver.
As it has no dependency with the debug utilities it is separated from the 
series, and now stands on its own.

Dolev Raviv (1):
  scsi: ufs: add ioctl interface for query request

 drivers/scsi/ufs/ufs.h|  53 +++
 drivers/scsi/ufs/ufshcd.c | 205 +-
 include/scsi/scsi.h   |   1 +
 include/uapi/scsi/Kbuild  |   1 +
 include/uapi/scsi/ufs/Kbuild  |   3 +
 include/uapi/scsi/ufs/ioctl.h |  57 
 include/uapi/scsi/ufs/ufs.h   |  66 ++
 7 files changed, 342 insertions(+), 44 deletions(-)
 create mode 100644 include/uapi/scsi/ufs/Kbuild
 create mode 100644 include/uapi/scsi/ufs/ioctl.h
 create mode 100644 include/uapi/scsi/ufs/ufs.h

-- 
Qualcomm Israel, on behalf of Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH v8 1/3] scsi: ufs: add ioctl interface for query request

2015-04-14 Thread Gilad Broner
From: Dolev Raviv 

This patch exposes the ioctl interface for UFS driver via SCSI device
ioctl interface. As of now UFS driver would provide the ioctl for query
interface to connected UFS device.

Signed-off-by: Dolev Raviv 
Signed-off-by: Noa Rubens 
Signed-off-by: Raviv Shvili 
Signed-off-by: Yaniv Gardi 
Signed-off-by: Gilad Broner 
---
 drivers/scsi/ufs/ufs.h|  53 +++---
 drivers/scsi/ufs/ufshcd.c | 219 +-
 include/scsi/scsi.h   |   1 +
 include/uapi/scsi/Kbuild  |   1 +
 include/uapi/scsi/ufs/Kbuild  |   3 +
 include/uapi/scsi/ufs/ioctl.h |  57 +++
 include/uapi/scsi/ufs/ufs.h   |  66 +
 7 files changed, 356 insertions(+), 44 deletions(-)
 create mode 100644 include/uapi/scsi/ufs/Kbuild
 create mode 100644 include/uapi/scsi/ufs/ioctl.h
 create mode 100644 include/uapi/scsi/ufs/ufs.h

diff --git a/drivers/scsi/ufs/ufs.h b/drivers/scsi/ufs/ufs.h
index 42c459a..1f023c4 100644
--- a/drivers/scsi/ufs/ufs.h
+++ b/drivers/scsi/ufs/ufs.h
@@ -38,6 +38,7 @@
 
 #include 
 #include 
+#include 
 
 #define MAX_CDB_SIZE   16
 #define GENERAL_UPIU_REQUEST_SIZE 32
@@ -71,6 +72,16 @@ enum {
UFS_UPIU_RPMB_WLUN  = 0xC4,
 };
 
+/**
+ * ufs_is_valid_unit_desc_lun - checks if the given LUN has a unit descriptor
+ * @lun: LU number to check
+ * @return: true if the lun has a matching unit descriptor, false otherwise
+ */
+static inline bool ufs_is_valid_unit_desc_lun(u8 lun)
+{
+   return (lun == UFS_UPIU_RPMB_WLUN || (lun < UFS_UPIU_MAX_GENERAL_LUN));
+}
+
 /*
  * UFS Protocol Information Unit related definitions
  */
@@ -126,35 +137,6 @@ enum {
UPIU_QUERY_FUNC_STANDARD_WRITE_REQUEST  = 0x81,
 };
 
-/* Flag idn for Query Requests*/
-enum flag_idn {
-   QUERY_FLAG_IDN_FDEVICEINIT  = 0x01,
-   QUERY_FLAG_IDN_PWR_ON_WPE   = 0x03,
-   QUERY_FLAG_IDN_BKOPS_EN = 0x04,
-};
-
-/* Attribute idn for Query requests */
-enum attr_idn {
-   QUERY_ATTR_IDN_ACTIVE_ICC_LVL   = 0x03,
-   QUERY_ATTR_IDN_BKOPS_STATUS = 0x05,
-   QUERY_ATTR_IDN_EE_CONTROL   = 0x0D,
-   QUERY_ATTR_IDN_EE_STATUS= 0x0E,
-};
-
-/* Descriptor idn for Query requests */
-enum desc_idn {
-   QUERY_DESC_IDN_DEVICE   = 0x0,
-   QUERY_DESC_IDN_CONFIGURAION = 0x1,
-   QUERY_DESC_IDN_UNIT = 0x2,
-   QUERY_DESC_IDN_RFU_0= 0x3,
-   QUERY_DESC_IDN_INTERCONNECT = 0x4,
-   QUERY_DESC_IDN_STRING   = 0x5,
-   QUERY_DESC_IDN_RFU_1= 0x6,
-   QUERY_DESC_IDN_GEOMETRY = 0x7,
-   QUERY_DESC_IDN_POWER= 0x8,
-   QUERY_DESC_IDN_MAX,
-};
-
 enum desc_header_offset {
QUERY_DESC_LENGTH_OFFSET= 0x00,
QUERY_DESC_DESC_TYPE_OFFSET = 0x01,
@@ -247,19 +229,6 @@ enum bkops_status {
BKOPS_STATUS_MAX = BKOPS_STATUS_CRITICAL,
 };
 
-/* UTP QUERY Transaction Specific Fields OpCode */
-enum query_opcode {
-   UPIU_QUERY_OPCODE_NOP   = 0x0,
-   UPIU_QUERY_OPCODE_READ_DESC = 0x1,
-   UPIU_QUERY_OPCODE_WRITE_DESC= 0x2,
-   UPIU_QUERY_OPCODE_READ_ATTR = 0x3,
-   UPIU_QUERY_OPCODE_WRITE_ATTR= 0x4,
-   UPIU_QUERY_OPCODE_READ_FLAG = 0x5,
-   UPIU_QUERY_OPCODE_SET_FLAG  = 0x6,
-   UPIU_QUERY_OPCODE_CLEAR_FLAG= 0x7,
-   UPIU_QUERY_OPCODE_TOGGLE_FLAG   = 0x8,
-};
-
 /* Query response result code */
 enum {
QUERY_RESULT_SUCCESS= 0x00,
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index dfd72af..b6aa7fb 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -3,7 +3,7 @@
  *
  * This code is based on drivers/scsi/ufs/ufshcd.c
  * Copyright (C) 2011-2013 Samsung India Software Operations
- * Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-2015, The Linux Foundation. All rights reserved.
  *
  * Authors:
  * Santosh Yaraganavi 
@@ -39,6 +39,7 @@
 
 #include 
 #include 
+#include 
 
 #include "ufshcd.h"
 #include "unipro.h"
@@ -74,6 +75,9 @@
 /* Interrupt aggregation default timeout, unit: 40us */
 #define INT_AGGR_DEF_TO0x02
 
+/* IOCTL opcode for command - ufs set device read only */
+#define UFS_IOCTL_BLKROSET  BLKROSET
+
 #define ufshcd_toggle_vreg(_dev, _vreg, _on)   \
({  \
int _ret;   \
@@ -1885,7 +1889,7 @@ static inline int ufshcd_read_unit_desc_param(struct 
ufs_hba *hba,
 * Unit descriptors are only available for general purpose LUs (LUN id
 * from 0 to 7) and RPMB Well known LU.
 */
-   if (lun != UFS_UPIU_RPMB_WLUN && (lun >= UFS_UPIU_MAX_GENERAL_LUN))
+   if (!ufs_is_valid_unit_desc_lun(lun))
return -EOPNOTSUPP;
 
   

[RESEND/PATCH v8 3/3] scsi: ufs: add trace events and dump prints for debug

2015-04-14 Thread Gilad Broner
Add trace events to driver to allow monitoring and profilig
of activities such as PM suspend/resume, hibernate enter/exit,
clock gating and clock scaling up/down.
In addition, add UFS host controller register dumps to provide
detailed information in case of errors to assist in analysis
of issues.

Signed-off-by: Dolev Raviv 
Signed-off-by: Subhash Jadavani 
Signed-off-by: Lee Susman 
Signed-off-by: Sujit Reddy Thumma 
Signed-off-by: Yaniv Gardi 
---
 drivers/scsi/ufs/ufs-qcom.c |  53 +
 drivers/scsi/ufs/ufshcd.c   | 511 +---
 drivers/scsi/ufs/ufshcd.h   |  49 -
 drivers/scsi/ufs/ufshci.h   |   1 +
 include/trace/events/ufs.h  | 213 ++
 5 files changed, 790 insertions(+), 37 deletions(-)
 create mode 100644 include/trace/events/ufs.h

diff --git a/drivers/scsi/ufs/ufs-qcom.c b/drivers/scsi/ufs/ufs-qcom.c
index 6652a81..68cbba4 100644
--- a/drivers/scsi/ufs/ufs-qcom.c
+++ b/drivers/scsi/ufs/ufs-qcom.c
@@ -30,6 +30,14 @@ static int ufs_qcom_get_bus_vote(struct ufs_qcom_host *host,
const char *speed_mode);
 static int ufs_qcom_set_bus_vote(struct ufs_qcom_host *host, int vote);
 
+static void ufs_qcom_dump_regs(struct ufs_hba *hba, int offset, int len,
+   char *prefix)
+{
+   print_hex_dump(KERN_ERR, prefix,
+   len > 4 ? DUMP_PREFIX_OFFSET : DUMP_PREFIX_NONE,
+   16, 4, hba->mmio_base + offset, len * 4, false);
+}
+
 static int ufs_qcom_get_connected_tx_lanes(struct ufs_hba *hba, u32 *tx_lanes)
 {
int err = 0;
@@ -995,6 +1003,50 @@ void ufs_qcom_clk_scale_notify(struct ufs_hba *hba)
dev_req_params->hs_rate);
 }
 
+static void ufs_qcom_print_hw_debug_reg_all(struct ufs_hba *hba)
+{
+   u32 reg;
+
+   ufs_qcom_dump_regs(hba, UFS_UFS_DBG_RD_REG_OCSC, 44,
+   "UFS_UFS_DBG_RD_REG_OCSC ");
+
+   reg = ufshcd_readl(hba, REG_UFS_CFG1);
+   reg |= UFS_BIT(17);
+   ufshcd_writel(hba, reg, REG_UFS_CFG1);
+
+   ufs_qcom_dump_regs(hba, UFS_UFS_DBG_RD_EDTL_RAM, 32,
+   "UFS_UFS_DBG_RD_EDTL_RAM ");
+   ufs_qcom_dump_regs(hba, UFS_UFS_DBG_RD_DESC_RAM, 128,
+   "UFS_UFS_DBG_RD_DESC_RAM ");
+   ufs_qcom_dump_regs(hba, UFS_UFS_DBG_RD_PRDT_RAM, 64,
+   "UFS_UFS_DBG_RD_PRDT_RAM ");
+
+   ufshcd_writel(hba, (reg & ~UFS_BIT(17)), REG_UFS_CFG1);
+
+   ufs_qcom_dump_regs(hba, UFS_DBG_RD_REG_UAWM, 4,
+   "UFS_DBG_RD_REG_UAWM ");
+   ufs_qcom_dump_regs(hba, UFS_DBG_RD_REG_UARM, 4,
+   "UFS_DBG_RD_REG_UARM ");
+   ufs_qcom_dump_regs(hba, UFS_DBG_RD_REG_TXUC, 48,
+   "UFS_DBG_RD_REG_TXUC ");
+   ufs_qcom_dump_regs(hba, UFS_DBG_RD_REG_RXUC, 27,
+   "UFS_DBG_RD_REG_RXUC ");
+   ufs_qcom_dump_regs(hba, UFS_DBG_RD_REG_DFC, 19,
+   "UFS_DBG_RD_REG_DFC ");
+   ufs_qcom_dump_regs(hba, UFS_DBG_RD_REG_TRLUT, 34,
+   "UFS_DBG_RD_REG_TRLUT ");
+   ufs_qcom_dump_regs(hba, UFS_DBG_RD_REG_TMRLUT, 9,
+   "UFS_DBG_RD_REG_TMRLUT ");
+}
+
+static void ufs_qcom_dump_dbg_regs(struct ufs_hba *hba)
+{
+   ufs_qcom_dump_regs(hba, REG_UFS_SYS1CLK_1US, 5,
+   "REG_UFS_SYS1CLK_1US ");
+
+   ufs_qcom_print_hw_debug_reg_all(hba);
+}
+
 /**
  * struct ufs_hba_qcom_vops - UFS QCOM specific variant operations
  *
@@ -1012,5 +1064,6 @@ static const struct ufs_hba_variant_ops ufs_hba_qcom_vops 
= {
.pwr_change_notify  = ufs_qcom_pwr_change_notify,
.suspend= ufs_qcom_suspend,
.resume = ufs_qcom_resume,
+   .dbg_register_dump  = ufs_qcom_dump_dbg_regs,
 };
 EXPORT_SYMBOL(ufs_hba_qcom_vops);
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index 9d48464..fe99be0 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -45,6 +45,9 @@
 #include "unipro.h"
 #include "ufs-debugfs.h"
 
+#define CREATE_TRACE_POINTS
+#include 
+
 #ifdef CONFIG_DEBUG_FS
 
 static void ufshcd_update_error_stats(struct ufs_hba *hba, int type)
@@ -145,6 +148,8 @@ static inline ufshcd_update_error_stats(struct ufs_hba 
*hba, int type)
_ret = ufshcd_disable_vreg(_dev, _vreg);\
_ret;   \
})
+#define ufshcd_hex_dump(prefix_str, buf, len) \
+print_hex_dump(KERN_ERR, prefix_str, DUMP_PREFIX_OFFSET, 16, 4, buf, len, 
false)
 
 static u32 ufs_query_desc_max_size[] = {
QUERY_DESC_DEVICE_MAX_SIZE,
@@ -273,6 +278,151 @@ static inline void ufshcd_disable_irq(struct ufs_hba *hba)
}
 }
 
+#ifdef CONFIG_TRACEPOINTS
+static void ufshcd_add_command_trace(struct ufs_hba *hba,
+   unsigned int tag, const char *str)
+{
+   sector_t lba = -1;
+   u8 opcode = 0;
+   u32 intr, doorbell;
+   

[PATCH v8 2/3] scsi: ufs: add debugfs for ufs

2015-04-14 Thread Gilad Broner
From: Lee Susman 

Adding debugfs capability for ufshcd.

debugfs attributes introduced in this patch:
 - View driver/controller runtime data
 - Command tag statistics for performance analisis
 - Dump device descriptor info
 - Track recoverable errors statistics during runtime
 - Change UFS power mode during runtime
 entry a string in the format 'GGLLMM' where:
 G - selected gear
 L - number of lanes
 M - power mode
 (1=fast mode, 2=slow mode, 4=fast-auto mode,
  5=slow-auto mode)
 First letter is for RX, second is for TX.
 - Get/set DME attributes

Signed-off-by: Lee Susman 
Signed-off-by: Dolev Raviv 
Signed-off-by: Yaniv Gardi 
Signed-off-by: Raviv Shvili 
Signed-off-by: Gilad Broner 
---
 drivers/scsi/ufs/Makefile  |   3 +-
 drivers/scsi/ufs/ufs-debugfs.c | 901 +
 drivers/scsi/ufs/ufs-debugfs.h |  38 ++
 drivers/scsi/ufs/ufshcd.c  | 229 ++-
 drivers/scsi/ufs/ufshcd.h  |  65 +++
 drivers/scsi/ufs/ufshci.h  |   2 +
 6 files changed, 1225 insertions(+), 13 deletions(-)
 create mode 100644 drivers/scsi/ufs/ufs-debugfs.c
 create mode 100644 drivers/scsi/ufs/ufs-debugfs.h

diff --git a/drivers/scsi/ufs/Makefile b/drivers/scsi/ufs/Makefile
index 8303bcc..3291ce3 100644
--- a/drivers/scsi/ufs/Makefile
+++ b/drivers/scsi/ufs/Makefile
@@ -1,5 +1,6 @@
 # UFSHCD makefile
+scsi_ufshcd_mod-y := ufshcd.o ufs-debugfs.o
 obj-$(CONFIG_SCSI_UFS_QCOM) += ufs-qcom.o
-obj-$(CONFIG_SCSI_UFSHCD) += ufshcd.o
+obj-$(CONFIG_SCSI_UFSHCD) += scsi_ufshcd_mod.o
 obj-$(CONFIG_SCSI_UFSHCD_PCI) += ufshcd-pci.o
 obj-$(CONFIG_SCSI_UFSHCD_PLATFORM) += ufshcd-pltfrm.o
diff --git a/drivers/scsi/ufs/ufs-debugfs.c b/drivers/scsi/ufs/ufs-debugfs.c
new file mode 100644
index 000..6d3fec7
--- /dev/null
+++ b/drivers/scsi/ufs/ufs-debugfs.c
@@ -0,0 +1,901 @@
+/* Copyright (c) 2013-2015, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * UFS debugfs - add debugfs interface to the ufshcd.
+ * This is currently used for statistics collection and exporting from the
+ * UFS driver.
+ * This infrastructure can be used for debugging or direct tweaking
+ * of the driver from userspace.
+ *
+ */
+
+#include "ufs-debugfs.h"
+#include "unipro.h"
+
+enum field_width {
+   BYTE= 1,
+   WORD= 2,
+};
+
+struct desc_field_offset {
+   char *name;
+   int offset;
+   enum field_width width_byte;
+};
+
+#define UFS_ERR_STATS_PRINT(file, error_index, string, error_seen) \
+   do {\
+   if (err_stats[error_index]) {   \
+   seq_printf(file, string,\
+   err_stats[error_index]);\
+   error_seen = true;  \
+   }   \
+   } while (0)
+#define DOORBELL_CLR_TOUT_US   (1000 * 1000) /* 1 sec */
+
+#define BUFF_LINE_CAPACITY 16
+#define TAB_CHARS 8
+
+static int ufsdbg_tag_stats_show(struct seq_file *file, void *data)
+{
+   struct ufs_hba *hba = (struct ufs_hba *)file->private;
+   struct ufs_stats *ufs_stats;
+   int i, j;
+   int max_depth;
+   bool is_tag_empty = true;
+   unsigned long flags;
+   char *sep = " | * | ";
+
+   if (!hba)
+   goto exit;
+
+   ufs_stats = >ufs_stats;
+
+   if (!ufs_stats->enabled) {
+   pr_debug("%s: ufs statistics are disabled\n", __func__);
+   seq_puts(file, "ufs statistics are disabled");
+   goto exit;
+   }
+
+   max_depth = hba->nutrs;
+
+   spin_lock_irqsave(hba->host->host_lock, flags);
+   /* Header */
+   seq_printf(file, " Tag Stat\t\t%s Queue Fullness\n", sep);
+   for (i = 0; i < TAB_CHARS * (TS_NUM_STATS + 4); i++) {
+   seq_puts(file, "-");
+   if (i == (TAB_CHARS * 3 - 1))
+   seq_puts(file, sep);
+   }
+   seq_printf(file,
+   "\n #\tnum uses\t%s\t #\tAll\t Read\t Write\t Flush\n",
+   sep);
+
+   /* values */
+   for (i = 0; i < max_depth; i++) {
+   if (ufs_stats->tag_stats[i][0] <= 0 &&
+   ufs_stats->tag_stats[i][1] <= 0 &&

[PATCH v8 0/3] Add ioctl and debug utilities to UFS driver

2015-04-14 Thread Gilad Broner
Changes from V7:
Fix handling of copy_from_user() result in case of incomplete copy in 
ufshcd_query_ioctl().
Fix ufs-debugfs build in case UFS is configured as a loadable kernel module.

Dolev Raviv (1):
  scsi: ufs: add ioctl interface for query request

Gilad Broner (1):
  scsi: ufs: add trace events and dump prints for debug

Lee Susman (1):
  scsi: ufs: add debugfs for ufs

 drivers/scsi/ufs/Makefile  |   3 +-
 drivers/scsi/ufs/ufs-debugfs.c | 901 ++
 drivers/scsi/ufs/ufs-debugfs.h |  38 ++
 drivers/scsi/ufs/ufs-qcom.c|  53 +++
 drivers/scsi/ufs/ufs.h |  53 +--
 drivers/scsi/ufs/ufshcd.c  | 957 ++---
 drivers/scsi/ufs/ufshcd.h  | 110 +
 drivers/scsi/ufs/ufshci.h  |   3 +
 include/scsi/scsi.h|   1 +
 include/trace/events/ufs.h | 213 +
 include/uapi/scsi/Kbuild   |   1 +
 include/uapi/scsi/ufs/Kbuild   |   3 +
 include/uapi/scsi/ufs/ioctl.h  |  57 +++
 include/uapi/scsi/ufs/ufs.h|  66 +++
 14 files changed, 2368 insertions(+), 91 deletions(-)
 create mode 100644 drivers/scsi/ufs/ufs-debugfs.c
 create mode 100644 drivers/scsi/ufs/ufs-debugfs.h
 create mode 100644 include/trace/events/ufs.h
 create mode 100644 include/uapi/scsi/ufs/Kbuild
 create mode 100644 include/uapi/scsi/ufs/ioctl.h
 create mode 100644 include/uapi/scsi/ufs/ufs.h

-- 
Qualcomm Israel, on behalf of Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH v8 0/3] Add ioctl and debug utilities to UFS driver

2015-04-14 Thread Gilad Broner
Changes from V7:
Fix handling of copy_from_user() result in case of incomplete copy in 
ufshcd_query_ioctl().
Fix ufs-debugfs build in case UFS is configured as a loadable kernel module.

Dolev Raviv (1):
  scsi: ufs: add ioctl interface for query request

Gilad Broner (1):
  scsi: ufs: add trace events and dump prints for debug

Lee Susman (1):
  scsi: ufs: add debugfs for ufs

 drivers/scsi/ufs/Makefile  |   3 +-
 drivers/scsi/ufs/ufs-debugfs.c | 901 ++
 drivers/scsi/ufs/ufs-debugfs.h |  38 ++
 drivers/scsi/ufs/ufs-qcom.c|  53 +++
 drivers/scsi/ufs/ufs.h |  53 +--
 drivers/scsi/ufs/ufshcd.c  | 957 ++---
 drivers/scsi/ufs/ufshcd.h  | 110 +
 drivers/scsi/ufs/ufshci.h  |   3 +
 include/scsi/scsi.h|   1 +
 include/trace/events/ufs.h | 213 +
 include/uapi/scsi/Kbuild   |   1 +
 include/uapi/scsi/ufs/Kbuild   |   3 +
 include/uapi/scsi/ufs/ioctl.h  |  57 +++
 include/uapi/scsi/ufs/ufs.h|  66 +++
 14 files changed, 2368 insertions(+), 91 deletions(-)
 create mode 100644 drivers/scsi/ufs/ufs-debugfs.c
 create mode 100644 drivers/scsi/ufs/ufs-debugfs.h
 create mode 100644 include/trace/events/ufs.h
 create mode 100644 include/uapi/scsi/ufs/Kbuild
 create mode 100644 include/uapi/scsi/ufs/ioctl.h
 create mode 100644 include/uapi/scsi/ufs/ufs.h

-- 
Qualcomm Israel, on behalf of Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[RESEND/PATCH v8 3/3] scsi: ufs: add trace events and dump prints for debug

2015-04-14 Thread Gilad Broner
Add trace events to driver to allow monitoring and profilig
of activities such as PM suspend/resume, hibernate enter/exit,
clock gating and clock scaling up/down.
In addition, add UFS host controller register dumps to provide
detailed information in case of errors to assist in analysis
of issues.

Signed-off-by: Dolev Raviv dra...@codeaurora.org
Signed-off-by: Subhash Jadavani subha...@codeaurora.org
Signed-off-by: Lee Susman lsus...@codeaurora.org
Signed-off-by: Sujit Reddy Thumma sthu...@codeaurora.org
Signed-off-by: Yaniv Gardi yga...@codeaurora.org
---
 drivers/scsi/ufs/ufs-qcom.c |  53 +
 drivers/scsi/ufs/ufshcd.c   | 511 +---
 drivers/scsi/ufs/ufshcd.h   |  49 -
 drivers/scsi/ufs/ufshci.h   |   1 +
 include/trace/events/ufs.h  | 213 ++
 5 files changed, 790 insertions(+), 37 deletions(-)
 create mode 100644 include/trace/events/ufs.h

diff --git a/drivers/scsi/ufs/ufs-qcom.c b/drivers/scsi/ufs/ufs-qcom.c
index 6652a81..68cbba4 100644
--- a/drivers/scsi/ufs/ufs-qcom.c
+++ b/drivers/scsi/ufs/ufs-qcom.c
@@ -30,6 +30,14 @@ static int ufs_qcom_get_bus_vote(struct ufs_qcom_host *host,
const char *speed_mode);
 static int ufs_qcom_set_bus_vote(struct ufs_qcom_host *host, int vote);
 
+static void ufs_qcom_dump_regs(struct ufs_hba *hba, int offset, int len,
+   char *prefix)
+{
+   print_hex_dump(KERN_ERR, prefix,
+   len  4 ? DUMP_PREFIX_OFFSET : DUMP_PREFIX_NONE,
+   16, 4, hba-mmio_base + offset, len * 4, false);
+}
+
 static int ufs_qcom_get_connected_tx_lanes(struct ufs_hba *hba, u32 *tx_lanes)
 {
int err = 0;
@@ -995,6 +1003,50 @@ void ufs_qcom_clk_scale_notify(struct ufs_hba *hba)
dev_req_params-hs_rate);
 }
 
+static void ufs_qcom_print_hw_debug_reg_all(struct ufs_hba *hba)
+{
+   u32 reg;
+
+   ufs_qcom_dump_regs(hba, UFS_UFS_DBG_RD_REG_OCSC, 44,
+   UFS_UFS_DBG_RD_REG_OCSC );
+
+   reg = ufshcd_readl(hba, REG_UFS_CFG1);
+   reg |= UFS_BIT(17);
+   ufshcd_writel(hba, reg, REG_UFS_CFG1);
+
+   ufs_qcom_dump_regs(hba, UFS_UFS_DBG_RD_EDTL_RAM, 32,
+   UFS_UFS_DBG_RD_EDTL_RAM );
+   ufs_qcom_dump_regs(hba, UFS_UFS_DBG_RD_DESC_RAM, 128,
+   UFS_UFS_DBG_RD_DESC_RAM );
+   ufs_qcom_dump_regs(hba, UFS_UFS_DBG_RD_PRDT_RAM, 64,
+   UFS_UFS_DBG_RD_PRDT_RAM );
+
+   ufshcd_writel(hba, (reg  ~UFS_BIT(17)), REG_UFS_CFG1);
+
+   ufs_qcom_dump_regs(hba, UFS_DBG_RD_REG_UAWM, 4,
+   UFS_DBG_RD_REG_UAWM );
+   ufs_qcom_dump_regs(hba, UFS_DBG_RD_REG_UARM, 4,
+   UFS_DBG_RD_REG_UARM );
+   ufs_qcom_dump_regs(hba, UFS_DBG_RD_REG_TXUC, 48,
+   UFS_DBG_RD_REG_TXUC );
+   ufs_qcom_dump_regs(hba, UFS_DBG_RD_REG_RXUC, 27,
+   UFS_DBG_RD_REG_RXUC );
+   ufs_qcom_dump_regs(hba, UFS_DBG_RD_REG_DFC, 19,
+   UFS_DBG_RD_REG_DFC );
+   ufs_qcom_dump_regs(hba, UFS_DBG_RD_REG_TRLUT, 34,
+   UFS_DBG_RD_REG_TRLUT );
+   ufs_qcom_dump_regs(hba, UFS_DBG_RD_REG_TMRLUT, 9,
+   UFS_DBG_RD_REG_TMRLUT );
+}
+
+static void ufs_qcom_dump_dbg_regs(struct ufs_hba *hba)
+{
+   ufs_qcom_dump_regs(hba, REG_UFS_SYS1CLK_1US, 5,
+   REG_UFS_SYS1CLK_1US );
+
+   ufs_qcom_print_hw_debug_reg_all(hba);
+}
+
 /**
  * struct ufs_hba_qcom_vops - UFS QCOM specific variant operations
  *
@@ -1012,5 +1064,6 @@ static const struct ufs_hba_variant_ops ufs_hba_qcom_vops 
= {
.pwr_change_notify  = ufs_qcom_pwr_change_notify,
.suspend= ufs_qcom_suspend,
.resume = ufs_qcom_resume,
+   .dbg_register_dump  = ufs_qcom_dump_dbg_regs,
 };
 EXPORT_SYMBOL(ufs_hba_qcom_vops);
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index 9d48464..fe99be0 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -45,6 +45,9 @@
 #include unipro.h
 #include ufs-debugfs.h
 
+#define CREATE_TRACE_POINTS
+#include trace/events/ufs.h
+
 #ifdef CONFIG_DEBUG_FS
 
 static void ufshcd_update_error_stats(struct ufs_hba *hba, int type)
@@ -145,6 +148,8 @@ static inline ufshcd_update_error_stats(struct ufs_hba 
*hba, int type)
_ret = ufshcd_disable_vreg(_dev, _vreg);\
_ret;   \
})
+#define ufshcd_hex_dump(prefix_str, buf, len) \
+print_hex_dump(KERN_ERR, prefix_str, DUMP_PREFIX_OFFSET, 16, 4, buf, len, 
false)
 
 static u32 ufs_query_desc_max_size[] = {
QUERY_DESC_DEVICE_MAX_SIZE,
@@ -273,6 +278,151 @@ static inline void ufshcd_disable_irq(struct ufs_hba *hba)
}
 }
 
+#ifdef CONFIG_TRACEPOINTS
+static void ufshcd_add_command_trace(struct ufs_hba *hba,
+   unsigned int tag, const char *str)

[PATCH v8 2/3] scsi: ufs: add debugfs for ufs

2015-04-14 Thread Gilad Broner
From: Lee Susman lsus...@codeaurora.org

Adding debugfs capability for ufshcd.

debugfs attributes introduced in this patch:
 - View driver/controller runtime data
 - Command tag statistics for performance analisis
 - Dump device descriptor info
 - Track recoverable errors statistics during runtime
 - Change UFS power mode during runtime
 entry a string in the format 'GGLLMM' where:
 G - selected gear
 L - number of lanes
 M - power mode
 (1=fast mode, 2=slow mode, 4=fast-auto mode,
  5=slow-auto mode)
 First letter is for RX, second is for TX.
 - Get/set DME attributes

Signed-off-by: Lee Susman lsus...@codeaurora.org
Signed-off-by: Dolev Raviv dra...@codeaurora.org
Signed-off-by: Yaniv Gardi yga...@codeaurora.org
Signed-off-by: Raviv Shvili rshv...@codeaurora.org
Signed-off-by: Gilad Broner gbro...@codeaurora.org
---
 drivers/scsi/ufs/Makefile  |   3 +-
 drivers/scsi/ufs/ufs-debugfs.c | 901 +
 drivers/scsi/ufs/ufs-debugfs.h |  38 ++
 drivers/scsi/ufs/ufshcd.c  | 229 ++-
 drivers/scsi/ufs/ufshcd.h  |  65 +++
 drivers/scsi/ufs/ufshci.h  |   2 +
 6 files changed, 1225 insertions(+), 13 deletions(-)
 create mode 100644 drivers/scsi/ufs/ufs-debugfs.c
 create mode 100644 drivers/scsi/ufs/ufs-debugfs.h

diff --git a/drivers/scsi/ufs/Makefile b/drivers/scsi/ufs/Makefile
index 8303bcc..3291ce3 100644
--- a/drivers/scsi/ufs/Makefile
+++ b/drivers/scsi/ufs/Makefile
@@ -1,5 +1,6 @@
 # UFSHCD makefile
+scsi_ufshcd_mod-y := ufshcd.o ufs-debugfs.o
 obj-$(CONFIG_SCSI_UFS_QCOM) += ufs-qcom.o
-obj-$(CONFIG_SCSI_UFSHCD) += ufshcd.o
+obj-$(CONFIG_SCSI_UFSHCD) += scsi_ufshcd_mod.o
 obj-$(CONFIG_SCSI_UFSHCD_PCI) += ufshcd-pci.o
 obj-$(CONFIG_SCSI_UFSHCD_PLATFORM) += ufshcd-pltfrm.o
diff --git a/drivers/scsi/ufs/ufs-debugfs.c b/drivers/scsi/ufs/ufs-debugfs.c
new file mode 100644
index 000..6d3fec7
--- /dev/null
+++ b/drivers/scsi/ufs/ufs-debugfs.c
@@ -0,0 +1,901 @@
+/* Copyright (c) 2013-2015, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * UFS debugfs - add debugfs interface to the ufshcd.
+ * This is currently used for statistics collection and exporting from the
+ * UFS driver.
+ * This infrastructure can be used for debugging or direct tweaking
+ * of the driver from userspace.
+ *
+ */
+
+#include ufs-debugfs.h
+#include unipro.h
+
+enum field_width {
+   BYTE= 1,
+   WORD= 2,
+};
+
+struct desc_field_offset {
+   char *name;
+   int offset;
+   enum field_width width_byte;
+};
+
+#define UFS_ERR_STATS_PRINT(file, error_index, string, error_seen) \
+   do {\
+   if (err_stats[error_index]) {   \
+   seq_printf(file, string,\
+   err_stats[error_index]);\
+   error_seen = true;  \
+   }   \
+   } while (0)
+#define DOORBELL_CLR_TOUT_US   (1000 * 1000) /* 1 sec */
+
+#define BUFF_LINE_CAPACITY 16
+#define TAB_CHARS 8
+
+static int ufsdbg_tag_stats_show(struct seq_file *file, void *data)
+{
+   struct ufs_hba *hba = (struct ufs_hba *)file-private;
+   struct ufs_stats *ufs_stats;
+   int i, j;
+   int max_depth;
+   bool is_tag_empty = true;
+   unsigned long flags;
+   char *sep =  | * | ;
+
+   if (!hba)
+   goto exit;
+
+   ufs_stats = hba-ufs_stats;
+
+   if (!ufs_stats-enabled) {
+   pr_debug(%s: ufs statistics are disabled\n, __func__);
+   seq_puts(file, ufs statistics are disabled);
+   goto exit;
+   }
+
+   max_depth = hba-nutrs;
+
+   spin_lock_irqsave(hba-host-host_lock, flags);
+   /* Header */
+   seq_printf(file,  Tag Stat\t\t%s Queue Fullness\n, sep);
+   for (i = 0; i  TAB_CHARS * (TS_NUM_STATS + 4); i++) {
+   seq_puts(file, -);
+   if (i == (TAB_CHARS * 3 - 1))
+   seq_puts(file, sep);
+   }
+   seq_printf(file,
+   \n #\tnum uses\t%s\t #\tAll\t Read\t Write\t Flush\n,
+   sep);
+
+   /* values */
+   for (i = 0; i  max_depth; i++) {
+   if (ufs_stats-tag_stats[i][0] = 0 
+   ufs_stats-tag_stats[i][1] = 0 
+   ufs_stats-tag_stats[i][2

[PATCH v8 1/3] scsi: ufs: add ioctl interface for query request

2015-04-14 Thread Gilad Broner
From: Dolev Raviv dra...@codeaurora.org

This patch exposes the ioctl interface for UFS driver via SCSI device
ioctl interface. As of now UFS driver would provide the ioctl for query
interface to connected UFS device.

Signed-off-by: Dolev Raviv dra...@codeaurora.org
Signed-off-by: Noa Rubens n...@codeaurora.org
Signed-off-by: Raviv Shvili rshv...@codeaurora.org
Signed-off-by: Yaniv Gardi yga...@codeaurora.org
Signed-off-by: Gilad Broner gbro...@codeaurora.org
---
 drivers/scsi/ufs/ufs.h|  53 +++---
 drivers/scsi/ufs/ufshcd.c | 219 +-
 include/scsi/scsi.h   |   1 +
 include/uapi/scsi/Kbuild  |   1 +
 include/uapi/scsi/ufs/Kbuild  |   3 +
 include/uapi/scsi/ufs/ioctl.h |  57 +++
 include/uapi/scsi/ufs/ufs.h   |  66 +
 7 files changed, 356 insertions(+), 44 deletions(-)
 create mode 100644 include/uapi/scsi/ufs/Kbuild
 create mode 100644 include/uapi/scsi/ufs/ioctl.h
 create mode 100644 include/uapi/scsi/ufs/ufs.h

diff --git a/drivers/scsi/ufs/ufs.h b/drivers/scsi/ufs/ufs.h
index 42c459a..1f023c4 100644
--- a/drivers/scsi/ufs/ufs.h
+++ b/drivers/scsi/ufs/ufs.h
@@ -38,6 +38,7 @@
 
 #include linux/mutex.h
 #include linux/types.h
+#include scsi/ufs/ufs.h
 
 #define MAX_CDB_SIZE   16
 #define GENERAL_UPIU_REQUEST_SIZE 32
@@ -71,6 +72,16 @@ enum {
UFS_UPIU_RPMB_WLUN  = 0xC4,
 };
 
+/**
+ * ufs_is_valid_unit_desc_lun - checks if the given LUN has a unit descriptor
+ * @lun: LU number to check
+ * @return: true if the lun has a matching unit descriptor, false otherwise
+ */
+static inline bool ufs_is_valid_unit_desc_lun(u8 lun)
+{
+   return (lun == UFS_UPIU_RPMB_WLUN || (lun  UFS_UPIU_MAX_GENERAL_LUN));
+}
+
 /*
  * UFS Protocol Information Unit related definitions
  */
@@ -126,35 +137,6 @@ enum {
UPIU_QUERY_FUNC_STANDARD_WRITE_REQUEST  = 0x81,
 };
 
-/* Flag idn for Query Requests*/
-enum flag_idn {
-   QUERY_FLAG_IDN_FDEVICEINIT  = 0x01,
-   QUERY_FLAG_IDN_PWR_ON_WPE   = 0x03,
-   QUERY_FLAG_IDN_BKOPS_EN = 0x04,
-};
-
-/* Attribute idn for Query requests */
-enum attr_idn {
-   QUERY_ATTR_IDN_ACTIVE_ICC_LVL   = 0x03,
-   QUERY_ATTR_IDN_BKOPS_STATUS = 0x05,
-   QUERY_ATTR_IDN_EE_CONTROL   = 0x0D,
-   QUERY_ATTR_IDN_EE_STATUS= 0x0E,
-};
-
-/* Descriptor idn for Query requests */
-enum desc_idn {
-   QUERY_DESC_IDN_DEVICE   = 0x0,
-   QUERY_DESC_IDN_CONFIGURAION = 0x1,
-   QUERY_DESC_IDN_UNIT = 0x2,
-   QUERY_DESC_IDN_RFU_0= 0x3,
-   QUERY_DESC_IDN_INTERCONNECT = 0x4,
-   QUERY_DESC_IDN_STRING   = 0x5,
-   QUERY_DESC_IDN_RFU_1= 0x6,
-   QUERY_DESC_IDN_GEOMETRY = 0x7,
-   QUERY_DESC_IDN_POWER= 0x8,
-   QUERY_DESC_IDN_MAX,
-};
-
 enum desc_header_offset {
QUERY_DESC_LENGTH_OFFSET= 0x00,
QUERY_DESC_DESC_TYPE_OFFSET = 0x01,
@@ -247,19 +229,6 @@ enum bkops_status {
BKOPS_STATUS_MAX = BKOPS_STATUS_CRITICAL,
 };
 
-/* UTP QUERY Transaction Specific Fields OpCode */
-enum query_opcode {
-   UPIU_QUERY_OPCODE_NOP   = 0x0,
-   UPIU_QUERY_OPCODE_READ_DESC = 0x1,
-   UPIU_QUERY_OPCODE_WRITE_DESC= 0x2,
-   UPIU_QUERY_OPCODE_READ_ATTR = 0x3,
-   UPIU_QUERY_OPCODE_WRITE_ATTR= 0x4,
-   UPIU_QUERY_OPCODE_READ_FLAG = 0x5,
-   UPIU_QUERY_OPCODE_SET_FLAG  = 0x6,
-   UPIU_QUERY_OPCODE_CLEAR_FLAG= 0x7,
-   UPIU_QUERY_OPCODE_TOGGLE_FLAG   = 0x8,
-};
-
 /* Query response result code */
 enum {
QUERY_RESULT_SUCCESS= 0x00,
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index dfd72af..b6aa7fb 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -3,7 +3,7 @@
  *
  * This code is based on drivers/scsi/ufs/ufshcd.c
  * Copyright (C) 2011-2013 Samsung India Software Operations
- * Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-2015, The Linux Foundation. All rights reserved.
  *
  * Authors:
  * Santosh Yaraganavi santosh...@samsung.com
@@ -39,6 +39,7 @@
 
 #include linux/async.h
 #include linux/devfreq.h
+#include scsi/ufs/ioctl.h
 
 #include ufshcd.h
 #include unipro.h
@@ -74,6 +75,9 @@
 /* Interrupt aggregation default timeout, unit: 40us */
 #define INT_AGGR_DEF_TO0x02
 
+/* IOCTL opcode for command - ufs set device read only */
+#define UFS_IOCTL_BLKROSET  BLKROSET
+
 #define ufshcd_toggle_vreg(_dev, _vreg, _on)   \
({  \
int _ret;   \
@@ -1885,7 +1889,7 @@ static inline int ufshcd_read_unit_desc_param(struct 
ufs_hba *hba,
 * Unit descriptors are only available for general purpose LUs (LUN id
 * from 0 to 7) and RPMB Well

Re: [PATCH v1 2/2] scsi: ufs: add support to allow non standard behaviours (quirks)

2015-04-07 Thread Gilad Broner

> Some implementation of UFS host controller HW might have some non-standard
> behaviours (quirks) when compared to behaviour specified by UFSHCI
> specification. This patch add support to allow specifying all such quirks
> to standard UFS host controller driver so standard driver takes them into
> account.
>
> In this change a UFSHCD_QUIRK_DELAY_BEFORE_DME_CMDS is introduced,
> where a minimum delay of 1ms is required before DME commands for
> stability purposes.
>
> Signed-off-by: Yaniv Gardi 
>
> ---
>  drivers/scsi/ufs/ufs-qcom.c | 22 +-
>  drivers/scsi/ufs/ufs-qcom.h | 18 ++
>  drivers/scsi/ufs/ufshcd.c   | 35 +++
>  drivers/scsi/ufs/ufshcd.h   |  9 +
>  4 files changed, 79 insertions(+), 5 deletions(-)
>

Reviewed-by: Gilad Broner 

-- 
Qualcomm Israel, on behalf of Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH v1 1/2] scsi: ufs-qcom: save controller revision info in internal structure

2015-04-07 Thread Gilad Broner

> Sometimes, specific information about the UFS controller revision is
> required in order to determine certain operations or execute
> controller dependent quirks.
> In order to avoid reading the controller revision multiple times,
> we simply read it once and save this information in internal structure.
>
> Signed-off-by: Yaniv Gardi 
>
> ---
>  drivers/scsi/ufs/ufs-qcom.c | 14 +++---
>  drivers/scsi/ufs/ufs-qcom.h |  8 
>  2 files changed, 15 insertions(+), 7 deletions(-)
>

Reviewed-by: Gilad Broner 


-- 
Qualcomm Israel, on behalf of Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH v1 1/2] scsi: ufs-qcom: save controller revision info in internal structure

2015-04-07 Thread Gilad Broner

 Sometimes, specific information about the UFS controller revision is
 required in order to determine certain operations or execute
 controller dependent quirks.
 In order to avoid reading the controller revision multiple times,
 we simply read it once and save this information in internal structure.

 Signed-off-by: Yaniv Gardi yga...@codeaurora.org

 ---
  drivers/scsi/ufs/ufs-qcom.c | 14 +++---
  drivers/scsi/ufs/ufs-qcom.h |  8 
  2 files changed, 15 insertions(+), 7 deletions(-)


Reviewed-by: Gilad Broner gbro...@codeaurora.org


-- 
Qualcomm Israel, on behalf of Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH v1 2/2] scsi: ufs: add support to allow non standard behaviours (quirks)

2015-04-07 Thread Gilad Broner

 Some implementation of UFS host controller HW might have some non-standard
 behaviours (quirks) when compared to behaviour specified by UFSHCI
 specification. This patch add support to allow specifying all such quirks
 to standard UFS host controller driver so standard driver takes them into
 account.

 In this change a UFSHCD_QUIRK_DELAY_BEFORE_DME_CMDS is introduced,
 where a minimum delay of 1ms is required before DME commands for
 stability purposes.

 Signed-off-by: Yaniv Gardi yga...@codeaurora.org

 ---
  drivers/scsi/ufs/ufs-qcom.c | 22 +-
  drivers/scsi/ufs/ufs-qcom.h | 18 ++
  drivers/scsi/ufs/ufshcd.c   | 35 +++
  drivers/scsi/ufs/ufshcd.h   |  9 +
  4 files changed, 79 insertions(+), 5 deletions(-)


Reviewed-by: Gilad Broner gbro...@codeaurora.org

-- 
Qualcomm Israel, on behalf of Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH v7 0/3] Add ioctl and debug utilities to UFS driver

2015-03-12 Thread Gilad Broner
Changes from V6:
Moved NULL user argument check from ufshcd_ioctl to ufshcd_query_ioctl.
Add comment in include/scsi/scsi.h to note 0x5388 is in use.

*** BLURB HERE ***

Dolev Raviv (1):
  scsi: ufs: add ioctl interface for query request

Gilad Broner (1):
  scsi: ufs: add trace events and dump prints for debug

Lee Susman (1):
  scsi: ufs: add debugfs for ufs

 drivers/scsi/ufs/Makefile  |   1 +
 drivers/scsi/ufs/ufs-debugfs.c | 902 ++
 drivers/scsi/ufs/ufs-debugfs.h |  38 ++
 drivers/scsi/ufs/ufs-qcom.c|  53 +++
 drivers/scsi/ufs/ufs.h |  53 +--
 drivers/scsi/ufs/ufshcd.c  | 964 +++--
 drivers/scsi/ufs/ufshcd.h  | 110 +
 drivers/scsi/ufs/ufshci.h  |   3 +
 include/scsi/scsi.h|   1 +
 include/trace/events/ufs.h | 213 +
 include/uapi/scsi/Kbuild   |   1 +
 include/uapi/scsi/ufs/Kbuild   |   3 +
 include/uapi/scsi/ufs/ioctl.h  |  57 +++
 include/uapi/scsi/ufs/ufs.h|  66 +++
 14 files changed, 2375 insertions(+), 90 deletions(-)
 create mode 100644 drivers/scsi/ufs/ufs-debugfs.c
 create mode 100644 drivers/scsi/ufs/ufs-debugfs.h
 create mode 100644 include/trace/events/ufs.h
 create mode 100644 include/uapi/scsi/ufs/Kbuild
 create mode 100644 include/uapi/scsi/ufs/ioctl.h
 create mode 100644 include/uapi/scsi/ufs/ufs.h

-- 
Qualcomm Israel, on behalf of Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH v7 2/3] scsi: ufs: add debugfs for ufs

2015-03-12 Thread Gilad Broner
From: Lee Susman 

Adding debugfs capability for ufshcd.

debugfs attributes introduced in this patch:
 - View driver/controller runtime data
 - Command tag statistics for performance analisis
 - Dump device descriptor info
 - Track recoverable errors statistics during runtime
 - Change UFS power mode during runtime
 entry a string in the format 'GGLLMM' where:
 G - selected gear
 L - number of lanes
 M - power mode
 (1=fast mode, 2=slow mode, 4=fast-auto mode,
  5=slow-auto mode)
 First letter is for RX, second is for TX.
 - Get/set DME attributes

Signed-off-by: Lee Susman 
Signed-off-by: Dolev Raviv 
Signed-off-by: Yaniv Gardi 
Signed-off-by: Raviv Shvili 
Signed-off-by: Gilad Broner 
---
 drivers/scsi/ufs/Makefile  |   1 +
 drivers/scsi/ufs/ufs-debugfs.c | 902 +
 drivers/scsi/ufs/ufs-debugfs.h |  38 ++
 drivers/scsi/ufs/ufshcd.c  | 229 ++-
 drivers/scsi/ufs/ufshcd.h  |  65 +++
 drivers/scsi/ufs/ufshci.h  |   2 +
 6 files changed, 1225 insertions(+), 12 deletions(-)
 create mode 100644 drivers/scsi/ufs/ufs-debugfs.c
 create mode 100644 drivers/scsi/ufs/ufs-debugfs.h

diff --git a/drivers/scsi/ufs/Makefile b/drivers/scsi/ufs/Makefile
index 8303bcc..0692314 100644
--- a/drivers/scsi/ufs/Makefile
+++ b/drivers/scsi/ufs/Makefile
@@ -3,3 +3,4 @@ obj-$(CONFIG_SCSI_UFS_QCOM) += ufs-qcom.o
 obj-$(CONFIG_SCSI_UFSHCD) += ufshcd.o
 obj-$(CONFIG_SCSI_UFSHCD_PCI) += ufshcd-pci.o
 obj-$(CONFIG_SCSI_UFSHCD_PLATFORM) += ufshcd-pltfrm.o
+obj-$(CONFIG_DEBUG_FS) += ufs-debugfs.o
diff --git a/drivers/scsi/ufs/ufs-debugfs.c b/drivers/scsi/ufs/ufs-debugfs.c
new file mode 100644
index 000..27ab053
--- /dev/null
+++ b/drivers/scsi/ufs/ufs-debugfs.c
@@ -0,0 +1,902 @@
+/* Copyright (c) 2013-2015, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * UFS debugfs - add debugfs interface to the ufshcd.
+ * This is currently used for statistics collection and exporting from the
+ * UFS driver.
+ * This infrastructure can be used for debugging or direct tweaking
+ * of the driver from userspace.
+ *
+ */
+
+#include "ufs-debugfs.h"
+#include "unipro.h"
+
+enum field_width {
+   BYTE= 1,
+   WORD= 2,
+};
+
+struct desc_field_offset {
+   char *name;
+   int offset;
+   enum field_width width_byte;
+};
+
+#define UFS_ERR_STATS_PRINT(file, error_index, string, error_seen) \
+   do {\
+   if (err_stats[error_index]) {   \
+   seq_printf(file, string,\
+   err_stats[error_index]);\
+   error_seen = true;  \
+   }   \
+   } while (0)
+#define DOORBELL_CLR_TOUT_US   (1000 * 1000) /* 1 sec */
+
+#define BUFF_LINE_CAPACITY 16
+#define TAB_CHARS 8
+
+static int ufsdbg_tag_stats_show(struct seq_file *file, void *data)
+{
+   struct ufs_hba *hba = (struct ufs_hba *)file->private;
+   struct ufs_stats *ufs_stats;
+   int i, j;
+   int max_depth;
+   bool is_tag_empty = true;
+   unsigned long flags;
+   char *sep = " | * | ";
+
+   if (!hba)
+   goto exit;
+
+   ufs_stats = >ufs_stats;
+
+   if (!ufs_stats->enabled) {
+   pr_debug("%s: ufs statistics are disabled\n", __func__);
+   seq_puts(file, "ufs statistics are disabled");
+   goto exit;
+   }
+
+   max_depth = hba->nutrs;
+
+   spin_lock_irqsave(hba->host->host_lock, flags);
+   /* Header */
+   seq_printf(file, " Tag Stat\t\t%s Queue Fullness\n", sep);
+   for (i = 0; i < TAB_CHARS * (TS_NUM_STATS + 4); i++) {
+   seq_puts(file, "-");
+   if (i == (TAB_CHARS * 3 - 1))
+   seq_puts(file, sep);
+   }
+   seq_printf(file,
+   "\n #\tnum uses\t%s\t #\tAll\t Read\t Write\t Flush\n",
+   sep);
+
+   /* values */
+   for (i = 0; i < max_depth; i++) {
+   if (ufs_stats->tag_stats[i][0] <= 0 &&
+   ufs_stats->tag_stats[i][1] <= 0 &&
+   ufs_stats->tag_stats[i][2] <= 0 &a

[PATCH v7 1/3] scsi: ufs: add ioctl interface for query request

2015-03-12 Thread Gilad Broner
From: Dolev Raviv 

This patch exposes the ioctl interface for UFS driver via SCSI device
ioctl interface. As of now UFS driver would provide the ioctl for query
interface to connected UFS device.

Signed-off-by: Dolev Raviv 
Signed-off-by: Noa Rubens 
Signed-off-by: Raviv Shvili 
Signed-off-by: Yaniv Gardi 
---
 drivers/scsi/ufs/ufs.h|  53 ++
 drivers/scsi/ufs/ufshcd.c | 226 +-
 include/scsi/scsi.h   |   1 +
 include/uapi/scsi/Kbuild  |   1 +
 include/uapi/scsi/ufs/Kbuild  |   3 +
 include/uapi/scsi/ufs/ioctl.h |  57 +++
 include/uapi/scsi/ufs/ufs.h   |  66 
 7 files changed, 363 insertions(+), 44 deletions(-)
 create mode 100644 include/uapi/scsi/ufs/Kbuild
 create mode 100644 include/uapi/scsi/ufs/ioctl.h
 create mode 100644 include/uapi/scsi/ufs/ufs.h

diff --git a/drivers/scsi/ufs/ufs.h b/drivers/scsi/ufs/ufs.h
index 42c459a..1f023c4 100644
--- a/drivers/scsi/ufs/ufs.h
+++ b/drivers/scsi/ufs/ufs.h
@@ -38,6 +38,7 @@
 
 #include 
 #include 
+#include 
 
 #define MAX_CDB_SIZE   16
 #define GENERAL_UPIU_REQUEST_SIZE 32
@@ -71,6 +72,16 @@ enum {
UFS_UPIU_RPMB_WLUN  = 0xC4,
 };
 
+/**
+ * ufs_is_valid_unit_desc_lun - checks if the given LUN has a unit descriptor
+ * @lun: LU number to check
+ * @return: true if the lun has a matching unit descriptor, false otherwise
+ */
+static inline bool ufs_is_valid_unit_desc_lun(u8 lun)
+{
+   return (lun == UFS_UPIU_RPMB_WLUN || (lun < UFS_UPIU_MAX_GENERAL_LUN));
+}
+
 /*
  * UFS Protocol Information Unit related definitions
  */
@@ -126,35 +137,6 @@ enum {
UPIU_QUERY_FUNC_STANDARD_WRITE_REQUEST  = 0x81,
 };
 
-/* Flag idn for Query Requests*/
-enum flag_idn {
-   QUERY_FLAG_IDN_FDEVICEINIT  = 0x01,
-   QUERY_FLAG_IDN_PWR_ON_WPE   = 0x03,
-   QUERY_FLAG_IDN_BKOPS_EN = 0x04,
-};
-
-/* Attribute idn for Query requests */
-enum attr_idn {
-   QUERY_ATTR_IDN_ACTIVE_ICC_LVL   = 0x03,
-   QUERY_ATTR_IDN_BKOPS_STATUS = 0x05,
-   QUERY_ATTR_IDN_EE_CONTROL   = 0x0D,
-   QUERY_ATTR_IDN_EE_STATUS= 0x0E,
-};
-
-/* Descriptor idn for Query requests */
-enum desc_idn {
-   QUERY_DESC_IDN_DEVICE   = 0x0,
-   QUERY_DESC_IDN_CONFIGURAION = 0x1,
-   QUERY_DESC_IDN_UNIT = 0x2,
-   QUERY_DESC_IDN_RFU_0= 0x3,
-   QUERY_DESC_IDN_INTERCONNECT = 0x4,
-   QUERY_DESC_IDN_STRING   = 0x5,
-   QUERY_DESC_IDN_RFU_1= 0x6,
-   QUERY_DESC_IDN_GEOMETRY = 0x7,
-   QUERY_DESC_IDN_POWER= 0x8,
-   QUERY_DESC_IDN_MAX,
-};
-
 enum desc_header_offset {
QUERY_DESC_LENGTH_OFFSET= 0x00,
QUERY_DESC_DESC_TYPE_OFFSET = 0x01,
@@ -247,19 +229,6 @@ enum bkops_status {
BKOPS_STATUS_MAX = BKOPS_STATUS_CRITICAL,
 };
 
-/* UTP QUERY Transaction Specific Fields OpCode */
-enum query_opcode {
-   UPIU_QUERY_OPCODE_NOP   = 0x0,
-   UPIU_QUERY_OPCODE_READ_DESC = 0x1,
-   UPIU_QUERY_OPCODE_WRITE_DESC= 0x2,
-   UPIU_QUERY_OPCODE_READ_ATTR = 0x3,
-   UPIU_QUERY_OPCODE_WRITE_ATTR= 0x4,
-   UPIU_QUERY_OPCODE_READ_FLAG = 0x5,
-   UPIU_QUERY_OPCODE_SET_FLAG  = 0x6,
-   UPIU_QUERY_OPCODE_CLEAR_FLAG= 0x7,
-   UPIU_QUERY_OPCODE_TOGGLE_FLAG   = 0x8,
-};
-
 /* Query response result code */
 enum {
QUERY_RESULT_SUCCESS= 0x00,
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index 5d60a86..5d82220 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -3,7 +3,7 @@
  *
  * This code is based on drivers/scsi/ufs/ufshcd.c
  * Copyright (C) 2011-2013 Samsung India Software Operations
- * Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-2015, The Linux Foundation. All rights reserved.
  *
  * Authors:
  * Santosh Yaraganavi 
@@ -39,6 +39,7 @@
 
 #include 
 #include 
+#include 
 
 #include "ufshcd.h"
 #include "unipro.h"
@@ -74,6 +75,9 @@
 /* Interrupt aggregation default timeout, unit: 40us */
 #define INT_AGGR_DEF_TO0x02
 
+/* IOCTL opcode for command - ufs set device read only */
+#define UFS_IOCTL_BLKROSET  BLKROSET
+
 #define ufshcd_toggle_vreg(_dev, _vreg, _on)   \
({  \
int _ret;   \
@@ -1882,7 +1886,7 @@ static inline int ufshcd_read_unit_desc_param(struct 
ufs_hba *hba,
 * Unit descriptors are only available for general purpose LUs (LUN id
 * from 0 to 7) and RPMB Well known LU.
 */
-   if (lun != UFS_UPIU_RPMB_WLUN && (lun >= UFS_UPIU_MAX_GENERAL_LUN))
+   if (!ufs_is_valid_unit_desc_lun(lun))
return -EOPNOTSUPP;
 
return ufshcd_read_desc_param(hba, QUERY_DESC_IDN_UNIT, lun,
@@ 

[PATCH v7 3/3] scsi: ufs: add trace events and dump prints for debug

2015-03-12 Thread Gilad Broner
Add trace events to driver to allow monitoring and profilig
of activities such as PM suspend/resume, hibernate enter/exit,
clock gating and clock scaling up/down.
In addition, add UFS host controller register dumps to provide
detailed information in case of errors to assist in analysis
of issues.

Signed-off-by: Dolev Raviv 
Signed-off-by: Subhash Jadavani 
Signed-off-by: Lee Susman 
Signed-off-by: Sujit Reddy Thumma 
Signed-off-by: Yaniv Gardi 
---
 drivers/scsi/ufs/ufs-qcom.c |  53 +
 drivers/scsi/ufs/ufshcd.c   | 511 +---
 drivers/scsi/ufs/ufshcd.h   |  49 -
 drivers/scsi/ufs/ufshci.h   |   1 +
 include/trace/events/ufs.h  | 213 ++
 5 files changed, 790 insertions(+), 37 deletions(-)
 create mode 100644 include/trace/events/ufs.h

diff --git a/drivers/scsi/ufs/ufs-qcom.c b/drivers/scsi/ufs/ufs-qcom.c
index 9217af9..9fe675d 100644
--- a/drivers/scsi/ufs/ufs-qcom.c
+++ b/drivers/scsi/ufs/ufs-qcom.c
@@ -30,6 +30,14 @@ static int ufs_qcom_get_bus_vote(struct ufs_qcom_host *host,
const char *speed_mode);
 static int ufs_qcom_set_bus_vote(struct ufs_qcom_host *host, int vote);
 
+static void ufs_qcom_dump_regs(struct ufs_hba *hba, int offset, int len,
+   char *prefix)
+{
+   print_hex_dump(KERN_ERR, prefix,
+   len > 4 ? DUMP_PREFIX_OFFSET : DUMP_PREFIX_NONE,
+   16, 4, hba->mmio_base + offset, len * 4, false);
+}
+
 static int ufs_qcom_get_connected_tx_lanes(struct ufs_hba *hba, u32 *tx_lanes)
 {
int err = 0;
@@ -983,6 +991,50 @@ void ufs_qcom_clk_scale_notify(struct ufs_hba *hba)
dev_req_params->hs_rate);
 }
 
+static void ufs_qcom_print_hw_debug_reg_all(struct ufs_hba *hba)
+{
+   u32 reg;
+
+   ufs_qcom_dump_regs(hba, UFS_UFS_DBG_RD_REG_OCSC, 44,
+   "UFS_UFS_DBG_RD_REG_OCSC ");
+
+   reg = ufshcd_readl(hba, REG_UFS_CFG1);
+   reg |= UFS_BIT(17);
+   ufshcd_writel(hba, reg, REG_UFS_CFG1);
+
+   ufs_qcom_dump_regs(hba, UFS_UFS_DBG_RD_EDTL_RAM, 32,
+   "UFS_UFS_DBG_RD_EDTL_RAM ");
+   ufs_qcom_dump_regs(hba, UFS_UFS_DBG_RD_DESC_RAM, 128,
+   "UFS_UFS_DBG_RD_DESC_RAM ");
+   ufs_qcom_dump_regs(hba, UFS_UFS_DBG_RD_PRDT_RAM, 64,
+   "UFS_UFS_DBG_RD_PRDT_RAM ");
+
+   ufshcd_writel(hba, (reg & ~UFS_BIT(17)), REG_UFS_CFG1);
+
+   ufs_qcom_dump_regs(hba, UFS_DBG_RD_REG_UAWM, 4,
+   "UFS_DBG_RD_REG_UAWM ");
+   ufs_qcom_dump_regs(hba, UFS_DBG_RD_REG_UARM, 4,
+   "UFS_DBG_RD_REG_UARM ");
+   ufs_qcom_dump_regs(hba, UFS_DBG_RD_REG_TXUC, 48,
+   "UFS_DBG_RD_REG_TXUC ");
+   ufs_qcom_dump_regs(hba, UFS_DBG_RD_REG_RXUC, 27,
+   "UFS_DBG_RD_REG_RXUC ");
+   ufs_qcom_dump_regs(hba, UFS_DBG_RD_REG_DFC, 19,
+   "UFS_DBG_RD_REG_DFC ");
+   ufs_qcom_dump_regs(hba, UFS_DBG_RD_REG_TRLUT, 34,
+   "UFS_DBG_RD_REG_TRLUT ");
+   ufs_qcom_dump_regs(hba, UFS_DBG_RD_REG_TMRLUT, 9,
+   "UFS_DBG_RD_REG_TMRLUT ");
+}
+
+static void ufs_qcom_dump_dbg_regs(struct ufs_hba *hba)
+{
+   ufs_qcom_dump_regs(hba, REG_UFS_SYS1CLK_1US, 5,
+   "REG_UFS_SYS1CLK_1US ");
+
+   ufs_qcom_print_hw_debug_reg_all(hba);
+}
+
 /**
  * struct ufs_hba_qcom_vops - UFS QCOM specific variant operations
  *
@@ -1000,5 +1052,6 @@ static const struct ufs_hba_variant_ops ufs_hba_qcom_vops 
= {
.pwr_change_notify  = ufs_qcom_pwr_change_notify,
.suspend= ufs_qcom_suspend,
.resume = ufs_qcom_resume,
+   .dbg_register_dump  = ufs_qcom_dump_dbg_regs,
 };
 EXPORT_SYMBOL(ufs_hba_qcom_vops);
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index 24e1985..e852d12b 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -45,6 +45,9 @@
 #include "unipro.h"
 #include "ufs-debugfs.h"
 
+#define CREATE_TRACE_POINTS
+#include 
+
 #ifdef CONFIG_DEBUG_FS
 
 static void ufshcd_update_error_stats(struct ufs_hba *hba, int type)
@@ -145,6 +148,8 @@ static inline ufshcd_update_error_stats(struct ufs_hba 
*hba, int type)
_ret = ufshcd_disable_vreg(_dev, _vreg);\
_ret;   \
})
+#define ufshcd_hex_dump(prefix_str, buf, len) \
+print_hex_dump(KERN_ERR, prefix_str, DUMP_PREFIX_OFFSET, 16, 4, buf, len, 
false)
 
 static u32 ufs_query_desc_max_size[] = {
QUERY_DESC_DEVICE_MAX_SIZE,
@@ -272,6 +277,151 @@ static inline void ufshcd_disable_irq(struct ufs_hba *hba)
}
 }
 
+#ifdef CONFIG_TRACEPOINTS
+static void ufshcd_add_command_trace(struct ufs_hba *hba,
+   unsigned int tag, const char *str)
+{
+   sector_t lba = -1;
+   u8 opcode = 0;
+   u32 intr, doorbell;
+   

[PATCH v7 1/3] scsi: ufs: add ioctl interface for query request

2015-03-12 Thread Gilad Broner
From: Dolev Raviv 

This patch exposes the ioctl interface for UFS driver via SCSI device
ioctl interface. As of now UFS driver would provide the ioctl for query
interface to connected UFS device.

Signed-off-by: Dolev Raviv 
Signed-off-by: Noa Rubens 
Signed-off-by: Raviv Shvili 
Signed-off-by: Yaniv Gardi 
---
 drivers/scsi/ufs/ufs.h|  53 ++
 drivers/scsi/ufs/ufshcd.c | 226 +-
 include/scsi/scsi.h   |   1 +
 include/uapi/scsi/Kbuild  |   1 +
 include/uapi/scsi/ufs/Kbuild  |   3 +
 include/uapi/scsi/ufs/ioctl.h |  57 +++
 include/uapi/scsi/ufs/ufs.h   |  66 
 7 files changed, 363 insertions(+), 44 deletions(-)
 create mode 100644 include/uapi/scsi/ufs/Kbuild
 create mode 100644 include/uapi/scsi/ufs/ioctl.h
 create mode 100644 include/uapi/scsi/ufs/ufs.h

diff --git a/drivers/scsi/ufs/ufs.h b/drivers/scsi/ufs/ufs.h
index 42c459a..1f023c4 100644
--- a/drivers/scsi/ufs/ufs.h
+++ b/drivers/scsi/ufs/ufs.h
@@ -38,6 +38,7 @@
 
 #include 
 #include 
+#include 
 
 #define MAX_CDB_SIZE   16
 #define GENERAL_UPIU_REQUEST_SIZE 32
@@ -71,6 +72,16 @@ enum {
UFS_UPIU_RPMB_WLUN  = 0xC4,
 };
 
+/**
+ * ufs_is_valid_unit_desc_lun - checks if the given LUN has a unit descriptor
+ * @lun: LU number to check
+ * @return: true if the lun has a matching unit descriptor, false otherwise
+ */
+static inline bool ufs_is_valid_unit_desc_lun(u8 lun)
+{
+   return (lun == UFS_UPIU_RPMB_WLUN || (lun < UFS_UPIU_MAX_GENERAL_LUN));
+}
+
 /*
  * UFS Protocol Information Unit related definitions
  */
@@ -126,35 +137,6 @@ enum {
UPIU_QUERY_FUNC_STANDARD_WRITE_REQUEST  = 0x81,
 };
 
-/* Flag idn for Query Requests*/
-enum flag_idn {
-   QUERY_FLAG_IDN_FDEVICEINIT  = 0x01,
-   QUERY_FLAG_IDN_PWR_ON_WPE   = 0x03,
-   QUERY_FLAG_IDN_BKOPS_EN = 0x04,
-};
-
-/* Attribute idn for Query requests */
-enum attr_idn {
-   QUERY_ATTR_IDN_ACTIVE_ICC_LVL   = 0x03,
-   QUERY_ATTR_IDN_BKOPS_STATUS = 0x05,
-   QUERY_ATTR_IDN_EE_CONTROL   = 0x0D,
-   QUERY_ATTR_IDN_EE_STATUS= 0x0E,
-};
-
-/* Descriptor idn for Query requests */
-enum desc_idn {
-   QUERY_DESC_IDN_DEVICE   = 0x0,
-   QUERY_DESC_IDN_CONFIGURAION = 0x1,
-   QUERY_DESC_IDN_UNIT = 0x2,
-   QUERY_DESC_IDN_RFU_0= 0x3,
-   QUERY_DESC_IDN_INTERCONNECT = 0x4,
-   QUERY_DESC_IDN_STRING   = 0x5,
-   QUERY_DESC_IDN_RFU_1= 0x6,
-   QUERY_DESC_IDN_GEOMETRY = 0x7,
-   QUERY_DESC_IDN_POWER= 0x8,
-   QUERY_DESC_IDN_MAX,
-};
-
 enum desc_header_offset {
QUERY_DESC_LENGTH_OFFSET= 0x00,
QUERY_DESC_DESC_TYPE_OFFSET = 0x01,
@@ -247,19 +229,6 @@ enum bkops_status {
BKOPS_STATUS_MAX = BKOPS_STATUS_CRITICAL,
 };
 
-/* UTP QUERY Transaction Specific Fields OpCode */
-enum query_opcode {
-   UPIU_QUERY_OPCODE_NOP   = 0x0,
-   UPIU_QUERY_OPCODE_READ_DESC = 0x1,
-   UPIU_QUERY_OPCODE_WRITE_DESC= 0x2,
-   UPIU_QUERY_OPCODE_READ_ATTR = 0x3,
-   UPIU_QUERY_OPCODE_WRITE_ATTR= 0x4,
-   UPIU_QUERY_OPCODE_READ_FLAG = 0x5,
-   UPIU_QUERY_OPCODE_SET_FLAG  = 0x6,
-   UPIU_QUERY_OPCODE_CLEAR_FLAG= 0x7,
-   UPIU_QUERY_OPCODE_TOGGLE_FLAG   = 0x8,
-};
-
 /* Query response result code */
 enum {
QUERY_RESULT_SUCCESS= 0x00,
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index 5d60a86..5d82220 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -3,7 +3,7 @@
  *
  * This code is based on drivers/scsi/ufs/ufshcd.c
  * Copyright (C) 2011-2013 Samsung India Software Operations
- * Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-2015, The Linux Foundation. All rights reserved.
  *
  * Authors:
  * Santosh Yaraganavi 
@@ -39,6 +39,7 @@
 
 #include 
 #include 
+#include 
 
 #include "ufshcd.h"
 #include "unipro.h"
@@ -74,6 +75,9 @@
 /* Interrupt aggregation default timeout, unit: 40us */
 #define INT_AGGR_DEF_TO0x02
 
+/* IOCTL opcode for command - ufs set device read only */
+#define UFS_IOCTL_BLKROSET  BLKROSET
+
 #define ufshcd_toggle_vreg(_dev, _vreg, _on)   \
({  \
int _ret;   \
@@ -1882,7 +1886,7 @@ static inline int ufshcd_read_unit_desc_param(struct 
ufs_hba *hba,
 * Unit descriptors are only available for general purpose LUs (LUN id
 * from 0 to 7) and RPMB Well known LU.
 */
-   if (lun != UFS_UPIU_RPMB_WLUN && (lun >= UFS_UPIU_MAX_GENERAL_LUN))
+   if (!ufs_is_valid_unit_desc_lun(lun))
return -EOPNOTSUPP;
 
return ufshcd_read_desc_param(hba, QUERY_DESC_IDN_UNIT, lun,
@@ 

[PATCH v7 0/3] Add ioctl and debug utilities to UFS driver

2015-03-12 Thread Gilad Broner
Changes from V6:
Moved NULL user argument check from ufshcd_ioctl to ufshcd_query_ioctl.
Add comment in include/scsi/scsi.h to note 0x5388 is in use.

Dolev Raviv (1):
  scsi: ufs: add ioctl interface for query request

Gilad Broner (1):
  scsi: ufs: add trace events and dump prints for debug

Lee Susman (1):
  scsi: ufs: add debugfs for ufs

 drivers/scsi/ufs/Makefile  |   1 +
 drivers/scsi/ufs/ufs-debugfs.c | 902 ++
 drivers/scsi/ufs/ufs-debugfs.h |  38 ++
 drivers/scsi/ufs/ufs-qcom.c|  53 +++
 drivers/scsi/ufs/ufs.h |  53 +--
 drivers/scsi/ufs/ufshcd.c  | 964 +++--
 drivers/scsi/ufs/ufshcd.h  | 110 +
 drivers/scsi/ufs/ufshci.h  |   3 +
 include/scsi/scsi.h|   1 +
 include/trace/events/ufs.h | 213 +
 include/uapi/scsi/Kbuild   |   1 +
 include/uapi/scsi/ufs/Kbuild   |   3 +
 include/uapi/scsi/ufs/ioctl.h  |  57 +++
 include/uapi/scsi/ufs/ufs.h|  66 +++
 14 files changed, 2375 insertions(+), 90 deletions(-)
 create mode 100644 drivers/scsi/ufs/ufs-debugfs.c
 create mode 100644 drivers/scsi/ufs/ufs-debugfs.h
 create mode 100644 include/trace/events/ufs.h
 create mode 100644 include/uapi/scsi/ufs/Kbuild
 create mode 100644 include/uapi/scsi/ufs/ioctl.h
 create mode 100644 include/uapi/scsi/ufs/ufs.h

-- 
Qualcomm Israel, on behalf of Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH v6 1/3] scsi: ufs: add ioctl interface for query request

2015-03-12 Thread Gilad Broner
>> +   if (!buffer) {
>> +   dev_err(hba->dev, "%s: User buffer is NULL!\n",
>> __func__);
>> +   return -EINVAL;
>> +   }
>> +
>
> Should we remove this check or move it into ufshcd_query_ioctl()?
> For example, BLKFLS ioctl without argument is correct usage, but
> it always triggers this message. (blkdev_ioctl -> __blkdev_driver_ioctl
> -> sd_ioctl -> scsi_ioctl -> ufshcd_ioctl)

You're right, I'll move the check to ufshcd_query_ioctl().

>  +++ b/include/uapi/scsi/ufs/ioctl.h
>> @@ -0,0 +1,57 @@
>> +#ifndef UAPI_UFS_IOCTL_H_
>> +#define UAPI_UFS_IOCTL_H_
>> +
>> +#include 
>> +
>> +/*
>> + *  IOCTL opcode for ufs queries has the following opcode after
>> + *  SCSI_IOCTL_GET_PCI
>> + */
>> +#define UFS_IOCTL_QUERY0x5388
>
> Should we also need some comments near SCSI_IOCTL_GET_PCI in
> include/scsi/scsi.h in order to avoid someone trying to define
> the same ioctl code in the future?
>
Indeed - I will add a comment.

Gilad.

-- 
Qualcomm Israel, on behalf of Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH v6 3/3] scsi: ufs: add trace events and dump prints for debug

2015-03-12 Thread Gilad Broner
Add trace events to driver to allow monitoring and profilig
of activities such as PM suspend/resume, hibernate enter/exit,
clock gating and clock scaling up/down.
In addition, add UFS host controller register dumps to provide
detailed information in case of errors to assist in analysis
of issues.

Signed-off-by: Dolev Raviv 
Signed-off-by: Subhash Jadavani 
Signed-off-by: Lee Susman 
Signed-off-by: Sujit Reddy Thumma 
Signed-off-by: Yaniv Gardi 
---
 drivers/scsi/ufs/ufs-qcom.c |  53 +
 drivers/scsi/ufs/ufshcd.c   | 511 +---
 drivers/scsi/ufs/ufshcd.h   |  49 -
 drivers/scsi/ufs/ufshci.h   |   1 +
 include/trace/events/ufs.h  | 213 ++
 5 files changed, 790 insertions(+), 37 deletions(-)
 create mode 100644 include/trace/events/ufs.h

diff --git a/drivers/scsi/ufs/ufs-qcom.c b/drivers/scsi/ufs/ufs-qcom.c
index 9217af9..9fe675d 100644
--- a/drivers/scsi/ufs/ufs-qcom.c
+++ b/drivers/scsi/ufs/ufs-qcom.c
@@ -30,6 +30,14 @@ static int ufs_qcom_get_bus_vote(struct ufs_qcom_host *host,
const char *speed_mode);
 static int ufs_qcom_set_bus_vote(struct ufs_qcom_host *host, int vote);
 
+static void ufs_qcom_dump_regs(struct ufs_hba *hba, int offset, int len,
+   char *prefix)
+{
+   print_hex_dump(KERN_ERR, prefix,
+   len > 4 ? DUMP_PREFIX_OFFSET : DUMP_PREFIX_NONE,
+   16, 4, hba->mmio_base + offset, len * 4, false);
+}
+
 static int ufs_qcom_get_connected_tx_lanes(struct ufs_hba *hba, u32 *tx_lanes)
 {
int err = 0;
@@ -983,6 +991,50 @@ void ufs_qcom_clk_scale_notify(struct ufs_hba *hba)
dev_req_params->hs_rate);
 }
 
+static void ufs_qcom_print_hw_debug_reg_all(struct ufs_hba *hba)
+{
+   u32 reg;
+
+   ufs_qcom_dump_regs(hba, UFS_UFS_DBG_RD_REG_OCSC, 44,
+   "UFS_UFS_DBG_RD_REG_OCSC ");
+
+   reg = ufshcd_readl(hba, REG_UFS_CFG1);
+   reg |= UFS_BIT(17);
+   ufshcd_writel(hba, reg, REG_UFS_CFG1);
+
+   ufs_qcom_dump_regs(hba, UFS_UFS_DBG_RD_EDTL_RAM, 32,
+   "UFS_UFS_DBG_RD_EDTL_RAM ");
+   ufs_qcom_dump_regs(hba, UFS_UFS_DBG_RD_DESC_RAM, 128,
+   "UFS_UFS_DBG_RD_DESC_RAM ");
+   ufs_qcom_dump_regs(hba, UFS_UFS_DBG_RD_PRDT_RAM, 64,
+   "UFS_UFS_DBG_RD_PRDT_RAM ");
+
+   ufshcd_writel(hba, (reg & ~UFS_BIT(17)), REG_UFS_CFG1);
+
+   ufs_qcom_dump_regs(hba, UFS_DBG_RD_REG_UAWM, 4,
+   "UFS_DBG_RD_REG_UAWM ");
+   ufs_qcom_dump_regs(hba, UFS_DBG_RD_REG_UARM, 4,
+   "UFS_DBG_RD_REG_UARM ");
+   ufs_qcom_dump_regs(hba, UFS_DBG_RD_REG_TXUC, 48,
+   "UFS_DBG_RD_REG_TXUC ");
+   ufs_qcom_dump_regs(hba, UFS_DBG_RD_REG_RXUC, 27,
+   "UFS_DBG_RD_REG_RXUC ");
+   ufs_qcom_dump_regs(hba, UFS_DBG_RD_REG_DFC, 19,
+   "UFS_DBG_RD_REG_DFC ");
+   ufs_qcom_dump_regs(hba, UFS_DBG_RD_REG_TRLUT, 34,
+   "UFS_DBG_RD_REG_TRLUT ");
+   ufs_qcom_dump_regs(hba, UFS_DBG_RD_REG_TMRLUT, 9,
+   "UFS_DBG_RD_REG_TMRLUT ");
+}
+
+static void ufs_qcom_dump_dbg_regs(struct ufs_hba *hba)
+{
+   ufs_qcom_dump_regs(hba, REG_UFS_SYS1CLK_1US, 5,
+   "REG_UFS_SYS1CLK_1US ");
+
+   ufs_qcom_print_hw_debug_reg_all(hba);
+}
+
 /**
  * struct ufs_hba_qcom_vops - UFS QCOM specific variant operations
  *
@@ -1000,5 +1052,6 @@ static const struct ufs_hba_variant_ops ufs_hba_qcom_vops 
= {
.pwr_change_notify  = ufs_qcom_pwr_change_notify,
.suspend= ufs_qcom_suspend,
.resume = ufs_qcom_resume,
+   .dbg_register_dump  = ufs_qcom_dump_dbg_regs,
 };
 EXPORT_SYMBOL(ufs_hba_qcom_vops);
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index 7697cc6..3ae0b3f 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -45,6 +45,9 @@
 #include "unipro.h"
 #include "ufs-debugfs.h"
 
+#define CREATE_TRACE_POINTS
+#include 
+
 #ifdef CONFIG_DEBUG_FS
 
 static void ufshcd_update_error_stats(struct ufs_hba *hba, int type)
@@ -145,6 +148,8 @@ static inline ufshcd_update_error_stats(struct ufs_hba 
*hba, int type)
_ret = ufshcd_disable_vreg(_dev, _vreg);\
_ret;   \
})
+#define ufshcd_hex_dump(prefix_str, buf, len) \
+print_hex_dump(KERN_ERR, prefix_str, DUMP_PREFIX_OFFSET, 16, 4, buf, len, 
false)
 
 static u32 ufs_query_desc_max_size[] = {
QUERY_DESC_DEVICE_MAX_SIZE,
@@ -272,6 +277,151 @@ static inline void ufshcd_disable_irq(struct ufs_hba *hba)
}
 }
 
+#ifdef CONFIG_TRACEPOINTS
+static void ufshcd_add_command_trace(struct ufs_hba *hba,
+   unsigned int tag, const char *str)
+{
+   sector_t lba = -1;
+   u8 opcode = 0;
+   u32 intr, doorbell;
+   struct 

[PATCH v6 2/3] scsi: ufs: add debugfs for ufs

2015-03-12 Thread Gilad Broner
From: Lee Susman 

Adding debugfs capability for ufshcd.

debugfs attributes introduced in this patch:
 - View driver/controller runtime data
 - Command tag statistics for performance analisis
 - Dump device descriptor info
 - Track recoverable errors statistics during runtime
 - Change UFS power mode during runtime
 entry a string in the format 'GGLLMM' where:
 G - selected gear
 L - number of lanes
 M - power mode
 (1=fast mode, 2=slow mode, 4=fast-auto mode,
  5=slow-auto mode)
 First letter is for RX, second is for TX.
 - Get/set DME attributes

Signed-off-by: Lee Susman 
Signed-off-by: Dolev Raviv 
Signed-off-by: Yaniv Gardi 
Signed-off-by: Raviv Shvili 
Signed-off-by: Gilad Broner 
---
 drivers/scsi/ufs/Makefile  |   1 +
 drivers/scsi/ufs/ufs-debugfs.c | 902 +
 drivers/scsi/ufs/ufs-debugfs.h |  38 ++
 drivers/scsi/ufs/ufshcd.c  | 229 ++-
 drivers/scsi/ufs/ufshcd.h  |  65 +++
 drivers/scsi/ufs/ufshci.h  |   2 +
 6 files changed, 1225 insertions(+), 12 deletions(-)
 create mode 100644 drivers/scsi/ufs/ufs-debugfs.c
 create mode 100644 drivers/scsi/ufs/ufs-debugfs.h

diff --git a/drivers/scsi/ufs/Makefile b/drivers/scsi/ufs/Makefile
index 8303bcc..0692314 100644
--- a/drivers/scsi/ufs/Makefile
+++ b/drivers/scsi/ufs/Makefile
@@ -3,3 +3,4 @@ obj-$(CONFIG_SCSI_UFS_QCOM) += ufs-qcom.o
 obj-$(CONFIG_SCSI_UFSHCD) += ufshcd.o
 obj-$(CONFIG_SCSI_UFSHCD_PCI) += ufshcd-pci.o
 obj-$(CONFIG_SCSI_UFSHCD_PLATFORM) += ufshcd-pltfrm.o
+obj-$(CONFIG_DEBUG_FS) += ufs-debugfs.o
diff --git a/drivers/scsi/ufs/ufs-debugfs.c b/drivers/scsi/ufs/ufs-debugfs.c
new file mode 100644
index 000..27ab053
--- /dev/null
+++ b/drivers/scsi/ufs/ufs-debugfs.c
@@ -0,0 +1,902 @@
+/* Copyright (c) 2013-2015, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * UFS debugfs - add debugfs interface to the ufshcd.
+ * This is currently used for statistics collection and exporting from the
+ * UFS driver.
+ * This infrastructure can be used for debugging or direct tweaking
+ * of the driver from userspace.
+ *
+ */
+
+#include "ufs-debugfs.h"
+#include "unipro.h"
+
+enum field_width {
+   BYTE= 1,
+   WORD= 2,
+};
+
+struct desc_field_offset {
+   char *name;
+   int offset;
+   enum field_width width_byte;
+};
+
+#define UFS_ERR_STATS_PRINT(file, error_index, string, error_seen) \
+   do {\
+   if (err_stats[error_index]) {   \
+   seq_printf(file, string,\
+   err_stats[error_index]);\
+   error_seen = true;  \
+   }   \
+   } while (0)
+#define DOORBELL_CLR_TOUT_US   (1000 * 1000) /* 1 sec */
+
+#define BUFF_LINE_CAPACITY 16
+#define TAB_CHARS 8
+
+static int ufsdbg_tag_stats_show(struct seq_file *file, void *data)
+{
+   struct ufs_hba *hba = (struct ufs_hba *)file->private;
+   struct ufs_stats *ufs_stats;
+   int i, j;
+   int max_depth;
+   bool is_tag_empty = true;
+   unsigned long flags;
+   char *sep = " | * | ";
+
+   if (!hba)
+   goto exit;
+
+   ufs_stats = >ufs_stats;
+
+   if (!ufs_stats->enabled) {
+   pr_debug("%s: ufs statistics are disabled\n", __func__);
+   seq_puts(file, "ufs statistics are disabled");
+   goto exit;
+   }
+
+   max_depth = hba->nutrs;
+
+   spin_lock_irqsave(hba->host->host_lock, flags);
+   /* Header */
+   seq_printf(file, " Tag Stat\t\t%s Queue Fullness\n", sep);
+   for (i = 0; i < TAB_CHARS * (TS_NUM_STATS + 4); i++) {
+   seq_puts(file, "-");
+   if (i == (TAB_CHARS * 3 - 1))
+   seq_puts(file, sep);
+   }
+   seq_printf(file,
+   "\n #\tnum uses\t%s\t #\tAll\t Read\t Write\t Flush\n",
+   sep);
+
+   /* values */
+   for (i = 0; i < max_depth; i++) {
+   if (ufs_stats->tag_stats[i][0] <= 0 &&
+   ufs_stats->tag_stats[i][1] <= 0 &&
+   ufs_stats->tag_stats[i][2] <= 0 &a

[PATCH v6 1/3] scsi: ufs: add ioctl interface for query request

2015-03-12 Thread Gilad Broner
From: Dolev Raviv 

This patch exposes the ioctl interface for UFS driver via SCSI device
ioctl interface. As of now UFS driver would provide the ioctl for query
interface to connected UFS device.

Signed-off-by: Dolev Raviv 
Signed-off-by: Noa Rubens 
Signed-off-by: Raviv Shvili 
Signed-off-by: Yaniv Gardi 
---
 drivers/scsi/ufs/ufs.h|  53 +++---
 drivers/scsi/ufs/ufshcd.c | 225 +-
 include/uapi/scsi/Kbuild  |   1 +
 include/uapi/scsi/ufs/Kbuild  |   3 +
 include/uapi/scsi/ufs/ioctl.h |  57 +++
 include/uapi/scsi/ufs/ufs.h   |  66 +
 6 files changed, 361 insertions(+), 44 deletions(-)
 create mode 100644 include/uapi/scsi/ufs/Kbuild
 create mode 100644 include/uapi/scsi/ufs/ioctl.h
 create mode 100644 include/uapi/scsi/ufs/ufs.h

diff --git a/drivers/scsi/ufs/ufs.h b/drivers/scsi/ufs/ufs.h
index 42c459a..1f023c4 100644
--- a/drivers/scsi/ufs/ufs.h
+++ b/drivers/scsi/ufs/ufs.h
@@ -38,6 +38,7 @@
 
 #include 
 #include 
+#include 
 
 #define MAX_CDB_SIZE   16
 #define GENERAL_UPIU_REQUEST_SIZE 32
@@ -71,6 +72,16 @@ enum {
UFS_UPIU_RPMB_WLUN  = 0xC4,
 };
 
+/**
+ * ufs_is_valid_unit_desc_lun - checks if the given LUN has a unit descriptor
+ * @lun: LU number to check
+ * @return: true if the lun has a matching unit descriptor, false otherwise
+ */
+static inline bool ufs_is_valid_unit_desc_lun(u8 lun)
+{
+   return (lun == UFS_UPIU_RPMB_WLUN || (lun < UFS_UPIU_MAX_GENERAL_LUN));
+}
+
 /*
  * UFS Protocol Information Unit related definitions
  */
@@ -126,35 +137,6 @@ enum {
UPIU_QUERY_FUNC_STANDARD_WRITE_REQUEST  = 0x81,
 };
 
-/* Flag idn for Query Requests*/
-enum flag_idn {
-   QUERY_FLAG_IDN_FDEVICEINIT  = 0x01,
-   QUERY_FLAG_IDN_PWR_ON_WPE   = 0x03,
-   QUERY_FLAG_IDN_BKOPS_EN = 0x04,
-};
-
-/* Attribute idn for Query requests */
-enum attr_idn {
-   QUERY_ATTR_IDN_ACTIVE_ICC_LVL   = 0x03,
-   QUERY_ATTR_IDN_BKOPS_STATUS = 0x05,
-   QUERY_ATTR_IDN_EE_CONTROL   = 0x0D,
-   QUERY_ATTR_IDN_EE_STATUS= 0x0E,
-};
-
-/* Descriptor idn for Query requests */
-enum desc_idn {
-   QUERY_DESC_IDN_DEVICE   = 0x0,
-   QUERY_DESC_IDN_CONFIGURAION = 0x1,
-   QUERY_DESC_IDN_UNIT = 0x2,
-   QUERY_DESC_IDN_RFU_0= 0x3,
-   QUERY_DESC_IDN_INTERCONNECT = 0x4,
-   QUERY_DESC_IDN_STRING   = 0x5,
-   QUERY_DESC_IDN_RFU_1= 0x6,
-   QUERY_DESC_IDN_GEOMETRY = 0x7,
-   QUERY_DESC_IDN_POWER= 0x8,
-   QUERY_DESC_IDN_MAX,
-};
-
 enum desc_header_offset {
QUERY_DESC_LENGTH_OFFSET= 0x00,
QUERY_DESC_DESC_TYPE_OFFSET = 0x01,
@@ -247,19 +229,6 @@ enum bkops_status {
BKOPS_STATUS_MAX = BKOPS_STATUS_CRITICAL,
 };
 
-/* UTP QUERY Transaction Specific Fields OpCode */
-enum query_opcode {
-   UPIU_QUERY_OPCODE_NOP   = 0x0,
-   UPIU_QUERY_OPCODE_READ_DESC = 0x1,
-   UPIU_QUERY_OPCODE_WRITE_DESC= 0x2,
-   UPIU_QUERY_OPCODE_READ_ATTR = 0x3,
-   UPIU_QUERY_OPCODE_WRITE_ATTR= 0x4,
-   UPIU_QUERY_OPCODE_READ_FLAG = 0x5,
-   UPIU_QUERY_OPCODE_SET_FLAG  = 0x6,
-   UPIU_QUERY_OPCODE_CLEAR_FLAG= 0x7,
-   UPIU_QUERY_OPCODE_TOGGLE_FLAG   = 0x8,
-};
-
 /* Query response result code */
 enum {
QUERY_RESULT_SUCCESS= 0x00,
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index 5d60a86..cb357f8 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -3,7 +3,7 @@
  *
  * This code is based on drivers/scsi/ufs/ufshcd.c
  * Copyright (C) 2011-2013 Samsung India Software Operations
- * Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-2015, The Linux Foundation. All rights reserved.
  *
  * Authors:
  * Santosh Yaraganavi 
@@ -39,6 +39,7 @@
 
 #include 
 #include 
+#include 
 
 #include "ufshcd.h"
 #include "unipro.h"
@@ -74,6 +75,9 @@
 /* Interrupt aggregation default timeout, unit: 40us */
 #define INT_AGGR_DEF_TO0x02
 
+/* IOCTL opcode for command - ufs set device read only */
+#define UFS_IOCTL_BLKROSET  BLKROSET
+
 #define ufshcd_toggle_vreg(_dev, _vreg, _on)   \
({  \
int _ret;   \
@@ -1882,7 +1886,7 @@ static inline int ufshcd_read_unit_desc_param(struct 
ufs_hba *hba,
 * Unit descriptors are only available for general purpose LUs (LUN id
 * from 0 to 7) and RPMB Well known LU.
 */
-   if (lun != UFS_UPIU_RPMB_WLUN && (lun >= UFS_UPIU_MAX_GENERAL_LUN))
+   if (!ufs_is_valid_unit_desc_lun(lun))
return -EOPNOTSUPP;
 
return ufshcd_read_desc_param(hba, QUERY_DESC_IDN_UNIT, lun,
@@ -4201,6 +4205,222 @@ static void 

[PATCH v6 0/3] Add ioctl and debug utilities to UFS driver

2015-03-12 Thread Gilad Broner
Changes from V5:
Created a common trace event class for driver state changes instead
of individual trace events definitions.

Dolev Raviv (1):
  scsi: ufs: add ioctl interface for query request

Gilad Broner (1):
  scsi: ufs: add trace events and dump prints for debug

Lee Susman (1):
  scsi: ufs: add debugfs for ufs

 drivers/scsi/ufs/Makefile  |   1 +
 drivers/scsi/ufs/ufs-debugfs.c | 902 ++
 drivers/scsi/ufs/ufs-debugfs.h |  38 ++
 drivers/scsi/ufs/ufs-qcom.c|  53 +++
 drivers/scsi/ufs/ufs.h |  53 +--
 drivers/scsi/ufs/ufshcd.c  | 963 +++--
 drivers/scsi/ufs/ufshcd.h  | 110 +
 drivers/scsi/ufs/ufshci.h  |   3 +
 include/trace/events/ufs.h | 213 +
 include/uapi/scsi/Kbuild   |   1 +
 include/uapi/scsi/ufs/Kbuild   |   3 +
 include/uapi/scsi/ufs/ioctl.h  |  57 +++
 include/uapi/scsi/ufs/ufs.h|  66 +++
 13 files changed, 2373 insertions(+), 90 deletions(-)
 create mode 100644 drivers/scsi/ufs/ufs-debugfs.c
 create mode 100644 drivers/scsi/ufs/ufs-debugfs.h
 create mode 100644 include/trace/events/ufs.h
 create mode 100644 include/uapi/scsi/ufs/Kbuild
 create mode 100644 include/uapi/scsi/ufs/ioctl.h
 create mode 100644 include/uapi/scsi/ufs/ufs.h

-- 
Qualcomm Israel, on behalf of Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH v5 3/3] scsi: ufs: add trace events and dump prints for debug

2015-03-12 Thread Gilad Broner
> This and the auto_bkops_state is pretty much the same. Can't you use
> the same TP_printk() and just have a DECLARE_EVENT_CLASS? The trace
> point name is printed with the event to see different events.

I agree. will upload the fix in next patchset.

-- 
Qualcomm Israel, on behalf of Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH v6 2/3] scsi: ufs: add debugfs for ufs

2015-03-12 Thread Gilad Broner
From: Lee Susman lsus...@codeaurora.org

Adding debugfs capability for ufshcd.

debugfs attributes introduced in this patch:
 - View driver/controller runtime data
 - Command tag statistics for performance analisis
 - Dump device descriptor info
 - Track recoverable errors statistics during runtime
 - Change UFS power mode during runtime
 entry a string in the format 'GGLLMM' where:
 G - selected gear
 L - number of lanes
 M - power mode
 (1=fast mode, 2=slow mode, 4=fast-auto mode,
  5=slow-auto mode)
 First letter is for RX, second is for TX.
 - Get/set DME attributes

Signed-off-by: Lee Susman lsus...@codeaurora.org
Signed-off-by: Dolev Raviv dra...@codeaurora.org
Signed-off-by: Yaniv Gardi yga...@codeaurora.org
Signed-off-by: Raviv Shvili rshv...@codeaurora.org
Signed-off-by: Gilad Broner gbro...@codeaurora.org
---
 drivers/scsi/ufs/Makefile  |   1 +
 drivers/scsi/ufs/ufs-debugfs.c | 902 +
 drivers/scsi/ufs/ufs-debugfs.h |  38 ++
 drivers/scsi/ufs/ufshcd.c  | 229 ++-
 drivers/scsi/ufs/ufshcd.h  |  65 +++
 drivers/scsi/ufs/ufshci.h  |   2 +
 6 files changed, 1225 insertions(+), 12 deletions(-)
 create mode 100644 drivers/scsi/ufs/ufs-debugfs.c
 create mode 100644 drivers/scsi/ufs/ufs-debugfs.h

diff --git a/drivers/scsi/ufs/Makefile b/drivers/scsi/ufs/Makefile
index 8303bcc..0692314 100644
--- a/drivers/scsi/ufs/Makefile
+++ b/drivers/scsi/ufs/Makefile
@@ -3,3 +3,4 @@ obj-$(CONFIG_SCSI_UFS_QCOM) += ufs-qcom.o
 obj-$(CONFIG_SCSI_UFSHCD) += ufshcd.o
 obj-$(CONFIG_SCSI_UFSHCD_PCI) += ufshcd-pci.o
 obj-$(CONFIG_SCSI_UFSHCD_PLATFORM) += ufshcd-pltfrm.o
+obj-$(CONFIG_DEBUG_FS) += ufs-debugfs.o
diff --git a/drivers/scsi/ufs/ufs-debugfs.c b/drivers/scsi/ufs/ufs-debugfs.c
new file mode 100644
index 000..27ab053
--- /dev/null
+++ b/drivers/scsi/ufs/ufs-debugfs.c
@@ -0,0 +1,902 @@
+/* Copyright (c) 2013-2015, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * UFS debugfs - add debugfs interface to the ufshcd.
+ * This is currently used for statistics collection and exporting from the
+ * UFS driver.
+ * This infrastructure can be used for debugging or direct tweaking
+ * of the driver from userspace.
+ *
+ */
+
+#include ufs-debugfs.h
+#include unipro.h
+
+enum field_width {
+   BYTE= 1,
+   WORD= 2,
+};
+
+struct desc_field_offset {
+   char *name;
+   int offset;
+   enum field_width width_byte;
+};
+
+#define UFS_ERR_STATS_PRINT(file, error_index, string, error_seen) \
+   do {\
+   if (err_stats[error_index]) {   \
+   seq_printf(file, string,\
+   err_stats[error_index]);\
+   error_seen = true;  \
+   }   \
+   } while (0)
+#define DOORBELL_CLR_TOUT_US   (1000 * 1000) /* 1 sec */
+
+#define BUFF_LINE_CAPACITY 16
+#define TAB_CHARS 8
+
+static int ufsdbg_tag_stats_show(struct seq_file *file, void *data)
+{
+   struct ufs_hba *hba = (struct ufs_hba *)file-private;
+   struct ufs_stats *ufs_stats;
+   int i, j;
+   int max_depth;
+   bool is_tag_empty = true;
+   unsigned long flags;
+   char *sep =  | * | ;
+
+   if (!hba)
+   goto exit;
+
+   ufs_stats = hba-ufs_stats;
+
+   if (!ufs_stats-enabled) {
+   pr_debug(%s: ufs statistics are disabled\n, __func__);
+   seq_puts(file, ufs statistics are disabled);
+   goto exit;
+   }
+
+   max_depth = hba-nutrs;
+
+   spin_lock_irqsave(hba-host-host_lock, flags);
+   /* Header */
+   seq_printf(file,  Tag Stat\t\t%s Queue Fullness\n, sep);
+   for (i = 0; i  TAB_CHARS * (TS_NUM_STATS + 4); i++) {
+   seq_puts(file, -);
+   if (i == (TAB_CHARS * 3 - 1))
+   seq_puts(file, sep);
+   }
+   seq_printf(file,
+   \n #\tnum uses\t%s\t #\tAll\t Read\t Write\t Flush\n,
+   sep);
+
+   /* values */
+   for (i = 0; i  max_depth; i++) {
+   if (ufs_stats-tag_stats[i][0] = 0 
+   ufs_stats-tag_stats[i][1] = 0 
+   ufs_stats-tag_stats[i][2] = 0 
+   ufs_stats-tag_stats[i][3] = 0

[PATCH v6 3/3] scsi: ufs: add trace events and dump prints for debug

2015-03-12 Thread Gilad Broner
Add trace events to driver to allow monitoring and profilig
of activities such as PM suspend/resume, hibernate enter/exit,
clock gating and clock scaling up/down.
In addition, add UFS host controller register dumps to provide
detailed information in case of errors to assist in analysis
of issues.

Signed-off-by: Dolev Raviv dra...@codeaurora.org
Signed-off-by: Subhash Jadavani subha...@codeaurora.org
Signed-off-by: Lee Susman lsus...@codeaurora.org
Signed-off-by: Sujit Reddy Thumma sthu...@codeaurora.org
Signed-off-by: Yaniv Gardi yga...@codeaurora.org
---
 drivers/scsi/ufs/ufs-qcom.c |  53 +
 drivers/scsi/ufs/ufshcd.c   | 511 +---
 drivers/scsi/ufs/ufshcd.h   |  49 -
 drivers/scsi/ufs/ufshci.h   |   1 +
 include/trace/events/ufs.h  | 213 ++
 5 files changed, 790 insertions(+), 37 deletions(-)
 create mode 100644 include/trace/events/ufs.h

diff --git a/drivers/scsi/ufs/ufs-qcom.c b/drivers/scsi/ufs/ufs-qcom.c
index 9217af9..9fe675d 100644
--- a/drivers/scsi/ufs/ufs-qcom.c
+++ b/drivers/scsi/ufs/ufs-qcom.c
@@ -30,6 +30,14 @@ static int ufs_qcom_get_bus_vote(struct ufs_qcom_host *host,
const char *speed_mode);
 static int ufs_qcom_set_bus_vote(struct ufs_qcom_host *host, int vote);
 
+static void ufs_qcom_dump_regs(struct ufs_hba *hba, int offset, int len,
+   char *prefix)
+{
+   print_hex_dump(KERN_ERR, prefix,
+   len  4 ? DUMP_PREFIX_OFFSET : DUMP_PREFIX_NONE,
+   16, 4, hba-mmio_base + offset, len * 4, false);
+}
+
 static int ufs_qcom_get_connected_tx_lanes(struct ufs_hba *hba, u32 *tx_lanes)
 {
int err = 0;
@@ -983,6 +991,50 @@ void ufs_qcom_clk_scale_notify(struct ufs_hba *hba)
dev_req_params-hs_rate);
 }
 
+static void ufs_qcom_print_hw_debug_reg_all(struct ufs_hba *hba)
+{
+   u32 reg;
+
+   ufs_qcom_dump_regs(hba, UFS_UFS_DBG_RD_REG_OCSC, 44,
+   UFS_UFS_DBG_RD_REG_OCSC );
+
+   reg = ufshcd_readl(hba, REG_UFS_CFG1);
+   reg |= UFS_BIT(17);
+   ufshcd_writel(hba, reg, REG_UFS_CFG1);
+
+   ufs_qcom_dump_regs(hba, UFS_UFS_DBG_RD_EDTL_RAM, 32,
+   UFS_UFS_DBG_RD_EDTL_RAM );
+   ufs_qcom_dump_regs(hba, UFS_UFS_DBG_RD_DESC_RAM, 128,
+   UFS_UFS_DBG_RD_DESC_RAM );
+   ufs_qcom_dump_regs(hba, UFS_UFS_DBG_RD_PRDT_RAM, 64,
+   UFS_UFS_DBG_RD_PRDT_RAM );
+
+   ufshcd_writel(hba, (reg  ~UFS_BIT(17)), REG_UFS_CFG1);
+
+   ufs_qcom_dump_regs(hba, UFS_DBG_RD_REG_UAWM, 4,
+   UFS_DBG_RD_REG_UAWM );
+   ufs_qcom_dump_regs(hba, UFS_DBG_RD_REG_UARM, 4,
+   UFS_DBG_RD_REG_UARM );
+   ufs_qcom_dump_regs(hba, UFS_DBG_RD_REG_TXUC, 48,
+   UFS_DBG_RD_REG_TXUC );
+   ufs_qcom_dump_regs(hba, UFS_DBG_RD_REG_RXUC, 27,
+   UFS_DBG_RD_REG_RXUC );
+   ufs_qcom_dump_regs(hba, UFS_DBG_RD_REG_DFC, 19,
+   UFS_DBG_RD_REG_DFC );
+   ufs_qcom_dump_regs(hba, UFS_DBG_RD_REG_TRLUT, 34,
+   UFS_DBG_RD_REG_TRLUT );
+   ufs_qcom_dump_regs(hba, UFS_DBG_RD_REG_TMRLUT, 9,
+   UFS_DBG_RD_REG_TMRLUT );
+}
+
+static void ufs_qcom_dump_dbg_regs(struct ufs_hba *hba)
+{
+   ufs_qcom_dump_regs(hba, REG_UFS_SYS1CLK_1US, 5,
+   REG_UFS_SYS1CLK_1US );
+
+   ufs_qcom_print_hw_debug_reg_all(hba);
+}
+
 /**
  * struct ufs_hba_qcom_vops - UFS QCOM specific variant operations
  *
@@ -1000,5 +1052,6 @@ static const struct ufs_hba_variant_ops ufs_hba_qcom_vops 
= {
.pwr_change_notify  = ufs_qcom_pwr_change_notify,
.suspend= ufs_qcom_suspend,
.resume = ufs_qcom_resume,
+   .dbg_register_dump  = ufs_qcom_dump_dbg_regs,
 };
 EXPORT_SYMBOL(ufs_hba_qcom_vops);
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index 7697cc6..3ae0b3f 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -45,6 +45,9 @@
 #include unipro.h
 #include ufs-debugfs.h
 
+#define CREATE_TRACE_POINTS
+#include trace/events/ufs.h
+
 #ifdef CONFIG_DEBUG_FS
 
 static void ufshcd_update_error_stats(struct ufs_hba *hba, int type)
@@ -145,6 +148,8 @@ static inline ufshcd_update_error_stats(struct ufs_hba 
*hba, int type)
_ret = ufshcd_disable_vreg(_dev, _vreg);\
_ret;   \
})
+#define ufshcd_hex_dump(prefix_str, buf, len) \
+print_hex_dump(KERN_ERR, prefix_str, DUMP_PREFIX_OFFSET, 16, 4, buf, len, 
false)
 
 static u32 ufs_query_desc_max_size[] = {
QUERY_DESC_DEVICE_MAX_SIZE,
@@ -272,6 +277,151 @@ static inline void ufshcd_disable_irq(struct ufs_hba *hba)
}
 }
 
+#ifdef CONFIG_TRACEPOINTS
+static void ufshcd_add_command_trace(struct ufs_hba *hba,
+   unsigned int tag, const char *str)

[PATCH v7 0/3] Add ioctl and debug utilities to UFS driver

2015-03-12 Thread Gilad Broner
Changes from V6:
Moved NULL user argument check from ufshcd_ioctl to ufshcd_query_ioctl.
Add comment in include/scsi/scsi.h to note 0x5388 is in use.

Dolev Raviv (1):
  scsi: ufs: add ioctl interface for query request

Gilad Broner (1):
  scsi: ufs: add trace events and dump prints for debug

Lee Susman (1):
  scsi: ufs: add debugfs for ufs

 drivers/scsi/ufs/Makefile  |   1 +
 drivers/scsi/ufs/ufs-debugfs.c | 902 ++
 drivers/scsi/ufs/ufs-debugfs.h |  38 ++
 drivers/scsi/ufs/ufs-qcom.c|  53 +++
 drivers/scsi/ufs/ufs.h |  53 +--
 drivers/scsi/ufs/ufshcd.c  | 964 +++--
 drivers/scsi/ufs/ufshcd.h  | 110 +
 drivers/scsi/ufs/ufshci.h  |   3 +
 include/scsi/scsi.h|   1 +
 include/trace/events/ufs.h | 213 +
 include/uapi/scsi/Kbuild   |   1 +
 include/uapi/scsi/ufs/Kbuild   |   3 +
 include/uapi/scsi/ufs/ioctl.h  |  57 +++
 include/uapi/scsi/ufs/ufs.h|  66 +++
 14 files changed, 2375 insertions(+), 90 deletions(-)
 create mode 100644 drivers/scsi/ufs/ufs-debugfs.c
 create mode 100644 drivers/scsi/ufs/ufs-debugfs.h
 create mode 100644 include/trace/events/ufs.h
 create mode 100644 include/uapi/scsi/ufs/Kbuild
 create mode 100644 include/uapi/scsi/ufs/ioctl.h
 create mode 100644 include/uapi/scsi/ufs/ufs.h

-- 
Qualcomm Israel, on behalf of Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH v6 1/3] scsi: ufs: add ioctl interface for query request

2015-03-12 Thread Gilad Broner
 +   if (!buffer) {
 +   dev_err(hba-dev, %s: User buffer is NULL!\n,
 __func__);
 +   return -EINVAL;
 +   }
 +

 Should we remove this check or move it into ufshcd_query_ioctl()?
 For example, BLKFLS ioctl without argument is correct usage, but
 it always triggers this message. (blkdev_ioctl - __blkdev_driver_ioctl
 - sd_ioctl - scsi_ioctl - ufshcd_ioctl)

You're right, I'll move the check to ufshcd_query_ioctl().

  +++ b/include/uapi/scsi/ufs/ioctl.h
 @@ -0,0 +1,57 @@
 +#ifndef UAPI_UFS_IOCTL_H_
 +#define UAPI_UFS_IOCTL_H_
 +
 +#include linux/types.h
 +
 +/*
 + *  IOCTL opcode for ufs queries has the following opcode after
 + *  SCSI_IOCTL_GET_PCI
 + */
 +#define UFS_IOCTL_QUERY0x5388

 Should we also need some comments near SCSI_IOCTL_GET_PCI in
 include/scsi/scsi.h in order to avoid someone trying to define
 the same ioctl code in the future?

Indeed - I will add a comment.

Gilad.

-- 
Qualcomm Israel, on behalf of Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH v7 3/3] scsi: ufs: add trace events and dump prints for debug

2015-03-12 Thread Gilad Broner
Add trace events to driver to allow monitoring and profilig
of activities such as PM suspend/resume, hibernate enter/exit,
clock gating and clock scaling up/down.
In addition, add UFS host controller register dumps to provide
detailed information in case of errors to assist in analysis
of issues.

Signed-off-by: Dolev Raviv dra...@codeaurora.org
Signed-off-by: Subhash Jadavani subha...@codeaurora.org
Signed-off-by: Lee Susman lsus...@codeaurora.org
Signed-off-by: Sujit Reddy Thumma sthu...@codeaurora.org
Signed-off-by: Yaniv Gardi yga...@codeaurora.org
---
 drivers/scsi/ufs/ufs-qcom.c |  53 +
 drivers/scsi/ufs/ufshcd.c   | 511 +---
 drivers/scsi/ufs/ufshcd.h   |  49 -
 drivers/scsi/ufs/ufshci.h   |   1 +
 include/trace/events/ufs.h  | 213 ++
 5 files changed, 790 insertions(+), 37 deletions(-)
 create mode 100644 include/trace/events/ufs.h

diff --git a/drivers/scsi/ufs/ufs-qcom.c b/drivers/scsi/ufs/ufs-qcom.c
index 9217af9..9fe675d 100644
--- a/drivers/scsi/ufs/ufs-qcom.c
+++ b/drivers/scsi/ufs/ufs-qcom.c
@@ -30,6 +30,14 @@ static int ufs_qcom_get_bus_vote(struct ufs_qcom_host *host,
const char *speed_mode);
 static int ufs_qcom_set_bus_vote(struct ufs_qcom_host *host, int vote);
 
+static void ufs_qcom_dump_regs(struct ufs_hba *hba, int offset, int len,
+   char *prefix)
+{
+   print_hex_dump(KERN_ERR, prefix,
+   len  4 ? DUMP_PREFIX_OFFSET : DUMP_PREFIX_NONE,
+   16, 4, hba-mmio_base + offset, len * 4, false);
+}
+
 static int ufs_qcom_get_connected_tx_lanes(struct ufs_hba *hba, u32 *tx_lanes)
 {
int err = 0;
@@ -983,6 +991,50 @@ void ufs_qcom_clk_scale_notify(struct ufs_hba *hba)
dev_req_params-hs_rate);
 }
 
+static void ufs_qcom_print_hw_debug_reg_all(struct ufs_hba *hba)
+{
+   u32 reg;
+
+   ufs_qcom_dump_regs(hba, UFS_UFS_DBG_RD_REG_OCSC, 44,
+   UFS_UFS_DBG_RD_REG_OCSC );
+
+   reg = ufshcd_readl(hba, REG_UFS_CFG1);
+   reg |= UFS_BIT(17);
+   ufshcd_writel(hba, reg, REG_UFS_CFG1);
+
+   ufs_qcom_dump_regs(hba, UFS_UFS_DBG_RD_EDTL_RAM, 32,
+   UFS_UFS_DBG_RD_EDTL_RAM );
+   ufs_qcom_dump_regs(hba, UFS_UFS_DBG_RD_DESC_RAM, 128,
+   UFS_UFS_DBG_RD_DESC_RAM );
+   ufs_qcom_dump_regs(hba, UFS_UFS_DBG_RD_PRDT_RAM, 64,
+   UFS_UFS_DBG_RD_PRDT_RAM );
+
+   ufshcd_writel(hba, (reg  ~UFS_BIT(17)), REG_UFS_CFG1);
+
+   ufs_qcom_dump_regs(hba, UFS_DBG_RD_REG_UAWM, 4,
+   UFS_DBG_RD_REG_UAWM );
+   ufs_qcom_dump_regs(hba, UFS_DBG_RD_REG_UARM, 4,
+   UFS_DBG_RD_REG_UARM );
+   ufs_qcom_dump_regs(hba, UFS_DBG_RD_REG_TXUC, 48,
+   UFS_DBG_RD_REG_TXUC );
+   ufs_qcom_dump_regs(hba, UFS_DBG_RD_REG_RXUC, 27,
+   UFS_DBG_RD_REG_RXUC );
+   ufs_qcom_dump_regs(hba, UFS_DBG_RD_REG_DFC, 19,
+   UFS_DBG_RD_REG_DFC );
+   ufs_qcom_dump_regs(hba, UFS_DBG_RD_REG_TRLUT, 34,
+   UFS_DBG_RD_REG_TRLUT );
+   ufs_qcom_dump_regs(hba, UFS_DBG_RD_REG_TMRLUT, 9,
+   UFS_DBG_RD_REG_TMRLUT );
+}
+
+static void ufs_qcom_dump_dbg_regs(struct ufs_hba *hba)
+{
+   ufs_qcom_dump_regs(hba, REG_UFS_SYS1CLK_1US, 5,
+   REG_UFS_SYS1CLK_1US );
+
+   ufs_qcom_print_hw_debug_reg_all(hba);
+}
+
 /**
  * struct ufs_hba_qcom_vops - UFS QCOM specific variant operations
  *
@@ -1000,5 +1052,6 @@ static const struct ufs_hba_variant_ops ufs_hba_qcom_vops 
= {
.pwr_change_notify  = ufs_qcom_pwr_change_notify,
.suspend= ufs_qcom_suspend,
.resume = ufs_qcom_resume,
+   .dbg_register_dump  = ufs_qcom_dump_dbg_regs,
 };
 EXPORT_SYMBOL(ufs_hba_qcom_vops);
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index 24e1985..e852d12b 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -45,6 +45,9 @@
 #include unipro.h
 #include ufs-debugfs.h
 
+#define CREATE_TRACE_POINTS
+#include trace/events/ufs.h
+
 #ifdef CONFIG_DEBUG_FS
 
 static void ufshcd_update_error_stats(struct ufs_hba *hba, int type)
@@ -145,6 +148,8 @@ static inline ufshcd_update_error_stats(struct ufs_hba 
*hba, int type)
_ret = ufshcd_disable_vreg(_dev, _vreg);\
_ret;   \
})
+#define ufshcd_hex_dump(prefix_str, buf, len) \
+print_hex_dump(KERN_ERR, prefix_str, DUMP_PREFIX_OFFSET, 16, 4, buf, len, 
false)
 
 static u32 ufs_query_desc_max_size[] = {
QUERY_DESC_DEVICE_MAX_SIZE,
@@ -272,6 +277,151 @@ static inline void ufshcd_disable_irq(struct ufs_hba *hba)
}
 }
 
+#ifdef CONFIG_TRACEPOINTS
+static void ufshcd_add_command_trace(struct ufs_hba *hba,
+   unsigned int tag, const char *str)

[PATCH v7 1/3] scsi: ufs: add ioctl interface for query request

2015-03-12 Thread Gilad Broner
From: Dolev Raviv dra...@codeaurora.org

This patch exposes the ioctl interface for UFS driver via SCSI device
ioctl interface. As of now UFS driver would provide the ioctl for query
interface to connected UFS device.

Signed-off-by: Dolev Raviv dra...@codeaurora.org
Signed-off-by: Noa Rubens n...@codeaurora.org
Signed-off-by: Raviv Shvili rshv...@codeaurora.org
Signed-off-by: Yaniv Gardi yga...@codeaurora.org
---
 drivers/scsi/ufs/ufs.h|  53 ++
 drivers/scsi/ufs/ufshcd.c | 226 +-
 include/scsi/scsi.h   |   1 +
 include/uapi/scsi/Kbuild  |   1 +
 include/uapi/scsi/ufs/Kbuild  |   3 +
 include/uapi/scsi/ufs/ioctl.h |  57 +++
 include/uapi/scsi/ufs/ufs.h   |  66 
 7 files changed, 363 insertions(+), 44 deletions(-)
 create mode 100644 include/uapi/scsi/ufs/Kbuild
 create mode 100644 include/uapi/scsi/ufs/ioctl.h
 create mode 100644 include/uapi/scsi/ufs/ufs.h

diff --git a/drivers/scsi/ufs/ufs.h b/drivers/scsi/ufs/ufs.h
index 42c459a..1f023c4 100644
--- a/drivers/scsi/ufs/ufs.h
+++ b/drivers/scsi/ufs/ufs.h
@@ -38,6 +38,7 @@
 
 #include linux/mutex.h
 #include linux/types.h
+#include scsi/ufs/ufs.h
 
 #define MAX_CDB_SIZE   16
 #define GENERAL_UPIU_REQUEST_SIZE 32
@@ -71,6 +72,16 @@ enum {
UFS_UPIU_RPMB_WLUN  = 0xC4,
 };
 
+/**
+ * ufs_is_valid_unit_desc_lun - checks if the given LUN has a unit descriptor
+ * @lun: LU number to check
+ * @return: true if the lun has a matching unit descriptor, false otherwise
+ */
+static inline bool ufs_is_valid_unit_desc_lun(u8 lun)
+{
+   return (lun == UFS_UPIU_RPMB_WLUN || (lun  UFS_UPIU_MAX_GENERAL_LUN));
+}
+
 /*
  * UFS Protocol Information Unit related definitions
  */
@@ -126,35 +137,6 @@ enum {
UPIU_QUERY_FUNC_STANDARD_WRITE_REQUEST  = 0x81,
 };
 
-/* Flag idn for Query Requests*/
-enum flag_idn {
-   QUERY_FLAG_IDN_FDEVICEINIT  = 0x01,
-   QUERY_FLAG_IDN_PWR_ON_WPE   = 0x03,
-   QUERY_FLAG_IDN_BKOPS_EN = 0x04,
-};
-
-/* Attribute idn for Query requests */
-enum attr_idn {
-   QUERY_ATTR_IDN_ACTIVE_ICC_LVL   = 0x03,
-   QUERY_ATTR_IDN_BKOPS_STATUS = 0x05,
-   QUERY_ATTR_IDN_EE_CONTROL   = 0x0D,
-   QUERY_ATTR_IDN_EE_STATUS= 0x0E,
-};
-
-/* Descriptor idn for Query requests */
-enum desc_idn {
-   QUERY_DESC_IDN_DEVICE   = 0x0,
-   QUERY_DESC_IDN_CONFIGURAION = 0x1,
-   QUERY_DESC_IDN_UNIT = 0x2,
-   QUERY_DESC_IDN_RFU_0= 0x3,
-   QUERY_DESC_IDN_INTERCONNECT = 0x4,
-   QUERY_DESC_IDN_STRING   = 0x5,
-   QUERY_DESC_IDN_RFU_1= 0x6,
-   QUERY_DESC_IDN_GEOMETRY = 0x7,
-   QUERY_DESC_IDN_POWER= 0x8,
-   QUERY_DESC_IDN_MAX,
-};
-
 enum desc_header_offset {
QUERY_DESC_LENGTH_OFFSET= 0x00,
QUERY_DESC_DESC_TYPE_OFFSET = 0x01,
@@ -247,19 +229,6 @@ enum bkops_status {
BKOPS_STATUS_MAX = BKOPS_STATUS_CRITICAL,
 };
 
-/* UTP QUERY Transaction Specific Fields OpCode */
-enum query_opcode {
-   UPIU_QUERY_OPCODE_NOP   = 0x0,
-   UPIU_QUERY_OPCODE_READ_DESC = 0x1,
-   UPIU_QUERY_OPCODE_WRITE_DESC= 0x2,
-   UPIU_QUERY_OPCODE_READ_ATTR = 0x3,
-   UPIU_QUERY_OPCODE_WRITE_ATTR= 0x4,
-   UPIU_QUERY_OPCODE_READ_FLAG = 0x5,
-   UPIU_QUERY_OPCODE_SET_FLAG  = 0x6,
-   UPIU_QUERY_OPCODE_CLEAR_FLAG= 0x7,
-   UPIU_QUERY_OPCODE_TOGGLE_FLAG   = 0x8,
-};
-
 /* Query response result code */
 enum {
QUERY_RESULT_SUCCESS= 0x00,
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index 5d60a86..5d82220 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -3,7 +3,7 @@
  *
  * This code is based on drivers/scsi/ufs/ufshcd.c
  * Copyright (C) 2011-2013 Samsung India Software Operations
- * Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-2015, The Linux Foundation. All rights reserved.
  *
  * Authors:
  * Santosh Yaraganavi santosh...@samsung.com
@@ -39,6 +39,7 @@
 
 #include linux/async.h
 #include linux/devfreq.h
+#include scsi/ufs/ioctl.h
 
 #include ufshcd.h
 #include unipro.h
@@ -74,6 +75,9 @@
 /* Interrupt aggregation default timeout, unit: 40us */
 #define INT_AGGR_DEF_TO0x02
 
+/* IOCTL opcode for command - ufs set device read only */
+#define UFS_IOCTL_BLKROSET  BLKROSET
+
 #define ufshcd_toggle_vreg(_dev, _vreg, _on)   \
({  \
int _ret;   \
@@ -1882,7 +1886,7 @@ static inline int ufshcd_read_unit_desc_param(struct 
ufs_hba *hba,
 * Unit descriptors are only available for general purpose LUs (LUN id
 * from 0 to 7) and RPMB Well known LU.
 */
-   if (lun != 

[PATCH v7 1/3] scsi: ufs: add ioctl interface for query request

2015-03-12 Thread Gilad Broner
From: Dolev Raviv dra...@codeaurora.org

This patch exposes the ioctl interface for UFS driver via SCSI device
ioctl interface. As of now UFS driver would provide the ioctl for query
interface to connected UFS device.

Signed-off-by: Dolev Raviv dra...@codeaurora.org
Signed-off-by: Noa Rubens n...@codeaurora.org
Signed-off-by: Raviv Shvili rshv...@codeaurora.org
Signed-off-by: Yaniv Gardi yga...@codeaurora.org
---
 drivers/scsi/ufs/ufs.h|  53 ++
 drivers/scsi/ufs/ufshcd.c | 226 +-
 include/scsi/scsi.h   |   1 +
 include/uapi/scsi/Kbuild  |   1 +
 include/uapi/scsi/ufs/Kbuild  |   3 +
 include/uapi/scsi/ufs/ioctl.h |  57 +++
 include/uapi/scsi/ufs/ufs.h   |  66 
 7 files changed, 363 insertions(+), 44 deletions(-)
 create mode 100644 include/uapi/scsi/ufs/Kbuild
 create mode 100644 include/uapi/scsi/ufs/ioctl.h
 create mode 100644 include/uapi/scsi/ufs/ufs.h

diff --git a/drivers/scsi/ufs/ufs.h b/drivers/scsi/ufs/ufs.h
index 42c459a..1f023c4 100644
--- a/drivers/scsi/ufs/ufs.h
+++ b/drivers/scsi/ufs/ufs.h
@@ -38,6 +38,7 @@
 
 #include linux/mutex.h
 #include linux/types.h
+#include scsi/ufs/ufs.h
 
 #define MAX_CDB_SIZE   16
 #define GENERAL_UPIU_REQUEST_SIZE 32
@@ -71,6 +72,16 @@ enum {
UFS_UPIU_RPMB_WLUN  = 0xC4,
 };
 
+/**
+ * ufs_is_valid_unit_desc_lun - checks if the given LUN has a unit descriptor
+ * @lun: LU number to check
+ * @return: true if the lun has a matching unit descriptor, false otherwise
+ */
+static inline bool ufs_is_valid_unit_desc_lun(u8 lun)
+{
+   return (lun == UFS_UPIU_RPMB_WLUN || (lun  UFS_UPIU_MAX_GENERAL_LUN));
+}
+
 /*
  * UFS Protocol Information Unit related definitions
  */
@@ -126,35 +137,6 @@ enum {
UPIU_QUERY_FUNC_STANDARD_WRITE_REQUEST  = 0x81,
 };
 
-/* Flag idn for Query Requests*/
-enum flag_idn {
-   QUERY_FLAG_IDN_FDEVICEINIT  = 0x01,
-   QUERY_FLAG_IDN_PWR_ON_WPE   = 0x03,
-   QUERY_FLAG_IDN_BKOPS_EN = 0x04,
-};
-
-/* Attribute idn for Query requests */
-enum attr_idn {
-   QUERY_ATTR_IDN_ACTIVE_ICC_LVL   = 0x03,
-   QUERY_ATTR_IDN_BKOPS_STATUS = 0x05,
-   QUERY_ATTR_IDN_EE_CONTROL   = 0x0D,
-   QUERY_ATTR_IDN_EE_STATUS= 0x0E,
-};
-
-/* Descriptor idn for Query requests */
-enum desc_idn {
-   QUERY_DESC_IDN_DEVICE   = 0x0,
-   QUERY_DESC_IDN_CONFIGURAION = 0x1,
-   QUERY_DESC_IDN_UNIT = 0x2,
-   QUERY_DESC_IDN_RFU_0= 0x3,
-   QUERY_DESC_IDN_INTERCONNECT = 0x4,
-   QUERY_DESC_IDN_STRING   = 0x5,
-   QUERY_DESC_IDN_RFU_1= 0x6,
-   QUERY_DESC_IDN_GEOMETRY = 0x7,
-   QUERY_DESC_IDN_POWER= 0x8,
-   QUERY_DESC_IDN_MAX,
-};
-
 enum desc_header_offset {
QUERY_DESC_LENGTH_OFFSET= 0x00,
QUERY_DESC_DESC_TYPE_OFFSET = 0x01,
@@ -247,19 +229,6 @@ enum bkops_status {
BKOPS_STATUS_MAX = BKOPS_STATUS_CRITICAL,
 };
 
-/* UTP QUERY Transaction Specific Fields OpCode */
-enum query_opcode {
-   UPIU_QUERY_OPCODE_NOP   = 0x0,
-   UPIU_QUERY_OPCODE_READ_DESC = 0x1,
-   UPIU_QUERY_OPCODE_WRITE_DESC= 0x2,
-   UPIU_QUERY_OPCODE_READ_ATTR = 0x3,
-   UPIU_QUERY_OPCODE_WRITE_ATTR= 0x4,
-   UPIU_QUERY_OPCODE_READ_FLAG = 0x5,
-   UPIU_QUERY_OPCODE_SET_FLAG  = 0x6,
-   UPIU_QUERY_OPCODE_CLEAR_FLAG= 0x7,
-   UPIU_QUERY_OPCODE_TOGGLE_FLAG   = 0x8,
-};
-
 /* Query response result code */
 enum {
QUERY_RESULT_SUCCESS= 0x00,
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index 5d60a86..5d82220 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -3,7 +3,7 @@
  *
  * This code is based on drivers/scsi/ufs/ufshcd.c
  * Copyright (C) 2011-2013 Samsung India Software Operations
- * Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-2015, The Linux Foundation. All rights reserved.
  *
  * Authors:
  * Santosh Yaraganavi santosh...@samsung.com
@@ -39,6 +39,7 @@
 
 #include linux/async.h
 #include linux/devfreq.h
+#include scsi/ufs/ioctl.h
 
 #include ufshcd.h
 #include unipro.h
@@ -74,6 +75,9 @@
 /* Interrupt aggregation default timeout, unit: 40us */
 #define INT_AGGR_DEF_TO0x02
 
+/* IOCTL opcode for command - ufs set device read only */
+#define UFS_IOCTL_BLKROSET  BLKROSET
+
 #define ufshcd_toggle_vreg(_dev, _vreg, _on)   \
({  \
int _ret;   \
@@ -1882,7 +1886,7 @@ static inline int ufshcd_read_unit_desc_param(struct 
ufs_hba *hba,
 * Unit descriptors are only available for general purpose LUs (LUN id
 * from 0 to 7) and RPMB Well known LU.
 */
-   if (lun != 

[PATCH v7 2/3] scsi: ufs: add debugfs for ufs

2015-03-12 Thread Gilad Broner
From: Lee Susman lsus...@codeaurora.org

Adding debugfs capability for ufshcd.

debugfs attributes introduced in this patch:
 - View driver/controller runtime data
 - Command tag statistics for performance analisis
 - Dump device descriptor info
 - Track recoverable errors statistics during runtime
 - Change UFS power mode during runtime
 entry a string in the format 'GGLLMM' where:
 G - selected gear
 L - number of lanes
 M - power mode
 (1=fast mode, 2=slow mode, 4=fast-auto mode,
  5=slow-auto mode)
 First letter is for RX, second is for TX.
 - Get/set DME attributes

Signed-off-by: Lee Susman lsus...@codeaurora.org
Signed-off-by: Dolev Raviv dra...@codeaurora.org
Signed-off-by: Yaniv Gardi yga...@codeaurora.org
Signed-off-by: Raviv Shvili rshv...@codeaurora.org
Signed-off-by: Gilad Broner gbro...@codeaurora.org
---
 drivers/scsi/ufs/Makefile  |   1 +
 drivers/scsi/ufs/ufs-debugfs.c | 902 +
 drivers/scsi/ufs/ufs-debugfs.h |  38 ++
 drivers/scsi/ufs/ufshcd.c  | 229 ++-
 drivers/scsi/ufs/ufshcd.h  |  65 +++
 drivers/scsi/ufs/ufshci.h  |   2 +
 6 files changed, 1225 insertions(+), 12 deletions(-)
 create mode 100644 drivers/scsi/ufs/ufs-debugfs.c
 create mode 100644 drivers/scsi/ufs/ufs-debugfs.h

diff --git a/drivers/scsi/ufs/Makefile b/drivers/scsi/ufs/Makefile
index 8303bcc..0692314 100644
--- a/drivers/scsi/ufs/Makefile
+++ b/drivers/scsi/ufs/Makefile
@@ -3,3 +3,4 @@ obj-$(CONFIG_SCSI_UFS_QCOM) += ufs-qcom.o
 obj-$(CONFIG_SCSI_UFSHCD) += ufshcd.o
 obj-$(CONFIG_SCSI_UFSHCD_PCI) += ufshcd-pci.o
 obj-$(CONFIG_SCSI_UFSHCD_PLATFORM) += ufshcd-pltfrm.o
+obj-$(CONFIG_DEBUG_FS) += ufs-debugfs.o
diff --git a/drivers/scsi/ufs/ufs-debugfs.c b/drivers/scsi/ufs/ufs-debugfs.c
new file mode 100644
index 000..27ab053
--- /dev/null
+++ b/drivers/scsi/ufs/ufs-debugfs.c
@@ -0,0 +1,902 @@
+/* Copyright (c) 2013-2015, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * UFS debugfs - add debugfs interface to the ufshcd.
+ * This is currently used for statistics collection and exporting from the
+ * UFS driver.
+ * This infrastructure can be used for debugging or direct tweaking
+ * of the driver from userspace.
+ *
+ */
+
+#include ufs-debugfs.h
+#include unipro.h
+
+enum field_width {
+   BYTE= 1,
+   WORD= 2,
+};
+
+struct desc_field_offset {
+   char *name;
+   int offset;
+   enum field_width width_byte;
+};
+
+#define UFS_ERR_STATS_PRINT(file, error_index, string, error_seen) \
+   do {\
+   if (err_stats[error_index]) {   \
+   seq_printf(file, string,\
+   err_stats[error_index]);\
+   error_seen = true;  \
+   }   \
+   } while (0)
+#define DOORBELL_CLR_TOUT_US   (1000 * 1000) /* 1 sec */
+
+#define BUFF_LINE_CAPACITY 16
+#define TAB_CHARS 8
+
+static int ufsdbg_tag_stats_show(struct seq_file *file, void *data)
+{
+   struct ufs_hba *hba = (struct ufs_hba *)file-private;
+   struct ufs_stats *ufs_stats;
+   int i, j;
+   int max_depth;
+   bool is_tag_empty = true;
+   unsigned long flags;
+   char *sep =  | * | ;
+
+   if (!hba)
+   goto exit;
+
+   ufs_stats = hba-ufs_stats;
+
+   if (!ufs_stats-enabled) {
+   pr_debug(%s: ufs statistics are disabled\n, __func__);
+   seq_puts(file, ufs statistics are disabled);
+   goto exit;
+   }
+
+   max_depth = hba-nutrs;
+
+   spin_lock_irqsave(hba-host-host_lock, flags);
+   /* Header */
+   seq_printf(file,  Tag Stat\t\t%s Queue Fullness\n, sep);
+   for (i = 0; i  TAB_CHARS * (TS_NUM_STATS + 4); i++) {
+   seq_puts(file, -);
+   if (i == (TAB_CHARS * 3 - 1))
+   seq_puts(file, sep);
+   }
+   seq_printf(file,
+   \n #\tnum uses\t%s\t #\tAll\t Read\t Write\t Flush\n,
+   sep);
+
+   /* values */
+   for (i = 0; i  max_depth; i++) {
+   if (ufs_stats-tag_stats[i][0] = 0 
+   ufs_stats-tag_stats[i][1] = 0 
+   ufs_stats-tag_stats[i][2] = 0 
+   ufs_stats-tag_stats[i][3] = 0

[PATCH v7 0/3] Add ioctl and debug utilities to UFS driver

2015-03-12 Thread Gilad Broner
Changes from V6:
Moved NULL user argument check from ufshcd_ioctl to ufshcd_query_ioctl.
Add comment in include/scsi/scsi.h to note 0x5388 is in use.

*** BLURB HERE ***

Dolev Raviv (1):
  scsi: ufs: add ioctl interface for query request

Gilad Broner (1):
  scsi: ufs: add trace events and dump prints for debug

Lee Susman (1):
  scsi: ufs: add debugfs for ufs

 drivers/scsi/ufs/Makefile  |   1 +
 drivers/scsi/ufs/ufs-debugfs.c | 902 ++
 drivers/scsi/ufs/ufs-debugfs.h |  38 ++
 drivers/scsi/ufs/ufs-qcom.c|  53 +++
 drivers/scsi/ufs/ufs.h |  53 +--
 drivers/scsi/ufs/ufshcd.c  | 964 +++--
 drivers/scsi/ufs/ufshcd.h  | 110 +
 drivers/scsi/ufs/ufshci.h  |   3 +
 include/scsi/scsi.h|   1 +
 include/trace/events/ufs.h | 213 +
 include/uapi/scsi/Kbuild   |   1 +
 include/uapi/scsi/ufs/Kbuild   |   3 +
 include/uapi/scsi/ufs/ioctl.h  |  57 +++
 include/uapi/scsi/ufs/ufs.h|  66 +++
 14 files changed, 2375 insertions(+), 90 deletions(-)
 create mode 100644 drivers/scsi/ufs/ufs-debugfs.c
 create mode 100644 drivers/scsi/ufs/ufs-debugfs.h
 create mode 100644 include/trace/events/ufs.h
 create mode 100644 include/uapi/scsi/ufs/Kbuild
 create mode 100644 include/uapi/scsi/ufs/ioctl.h
 create mode 100644 include/uapi/scsi/ufs/ufs.h

-- 
Qualcomm Israel, on behalf of Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH v6 0/3] Add ioctl and debug utilities to UFS driver

2015-03-12 Thread Gilad Broner
Changes from V5:
Created a common trace event class for driver state changes instead
of individual trace events definitions.

Dolev Raviv (1):
  scsi: ufs: add ioctl interface for query request

Gilad Broner (1):
  scsi: ufs: add trace events and dump prints for debug

Lee Susman (1):
  scsi: ufs: add debugfs for ufs

 drivers/scsi/ufs/Makefile  |   1 +
 drivers/scsi/ufs/ufs-debugfs.c | 902 ++
 drivers/scsi/ufs/ufs-debugfs.h |  38 ++
 drivers/scsi/ufs/ufs-qcom.c|  53 +++
 drivers/scsi/ufs/ufs.h |  53 +--
 drivers/scsi/ufs/ufshcd.c  | 963 +++--
 drivers/scsi/ufs/ufshcd.h  | 110 +
 drivers/scsi/ufs/ufshci.h  |   3 +
 include/trace/events/ufs.h | 213 +
 include/uapi/scsi/Kbuild   |   1 +
 include/uapi/scsi/ufs/Kbuild   |   3 +
 include/uapi/scsi/ufs/ioctl.h  |  57 +++
 include/uapi/scsi/ufs/ufs.h|  66 +++
 13 files changed, 2373 insertions(+), 90 deletions(-)
 create mode 100644 drivers/scsi/ufs/ufs-debugfs.c
 create mode 100644 drivers/scsi/ufs/ufs-debugfs.h
 create mode 100644 include/trace/events/ufs.h
 create mode 100644 include/uapi/scsi/ufs/Kbuild
 create mode 100644 include/uapi/scsi/ufs/ioctl.h
 create mode 100644 include/uapi/scsi/ufs/ufs.h

-- 
Qualcomm Israel, on behalf of Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH v6 1/3] scsi: ufs: add ioctl interface for query request

2015-03-12 Thread Gilad Broner
From: Dolev Raviv dra...@codeaurora.org

This patch exposes the ioctl interface for UFS driver via SCSI device
ioctl interface. As of now UFS driver would provide the ioctl for query
interface to connected UFS device.

Signed-off-by: Dolev Raviv dra...@codeaurora.org
Signed-off-by: Noa Rubens n...@codeaurora.org
Signed-off-by: Raviv Shvili rshv...@codeaurora.org
Signed-off-by: Yaniv Gardi yga...@codeaurora.org
---
 drivers/scsi/ufs/ufs.h|  53 +++---
 drivers/scsi/ufs/ufshcd.c | 225 +-
 include/uapi/scsi/Kbuild  |   1 +
 include/uapi/scsi/ufs/Kbuild  |   3 +
 include/uapi/scsi/ufs/ioctl.h |  57 +++
 include/uapi/scsi/ufs/ufs.h   |  66 +
 6 files changed, 361 insertions(+), 44 deletions(-)
 create mode 100644 include/uapi/scsi/ufs/Kbuild
 create mode 100644 include/uapi/scsi/ufs/ioctl.h
 create mode 100644 include/uapi/scsi/ufs/ufs.h

diff --git a/drivers/scsi/ufs/ufs.h b/drivers/scsi/ufs/ufs.h
index 42c459a..1f023c4 100644
--- a/drivers/scsi/ufs/ufs.h
+++ b/drivers/scsi/ufs/ufs.h
@@ -38,6 +38,7 @@
 
 #include linux/mutex.h
 #include linux/types.h
+#include scsi/ufs/ufs.h
 
 #define MAX_CDB_SIZE   16
 #define GENERAL_UPIU_REQUEST_SIZE 32
@@ -71,6 +72,16 @@ enum {
UFS_UPIU_RPMB_WLUN  = 0xC4,
 };
 
+/**
+ * ufs_is_valid_unit_desc_lun - checks if the given LUN has a unit descriptor
+ * @lun: LU number to check
+ * @return: true if the lun has a matching unit descriptor, false otherwise
+ */
+static inline bool ufs_is_valid_unit_desc_lun(u8 lun)
+{
+   return (lun == UFS_UPIU_RPMB_WLUN || (lun  UFS_UPIU_MAX_GENERAL_LUN));
+}
+
 /*
  * UFS Protocol Information Unit related definitions
  */
@@ -126,35 +137,6 @@ enum {
UPIU_QUERY_FUNC_STANDARD_WRITE_REQUEST  = 0x81,
 };
 
-/* Flag idn for Query Requests*/
-enum flag_idn {
-   QUERY_FLAG_IDN_FDEVICEINIT  = 0x01,
-   QUERY_FLAG_IDN_PWR_ON_WPE   = 0x03,
-   QUERY_FLAG_IDN_BKOPS_EN = 0x04,
-};
-
-/* Attribute idn for Query requests */
-enum attr_idn {
-   QUERY_ATTR_IDN_ACTIVE_ICC_LVL   = 0x03,
-   QUERY_ATTR_IDN_BKOPS_STATUS = 0x05,
-   QUERY_ATTR_IDN_EE_CONTROL   = 0x0D,
-   QUERY_ATTR_IDN_EE_STATUS= 0x0E,
-};
-
-/* Descriptor idn for Query requests */
-enum desc_idn {
-   QUERY_DESC_IDN_DEVICE   = 0x0,
-   QUERY_DESC_IDN_CONFIGURAION = 0x1,
-   QUERY_DESC_IDN_UNIT = 0x2,
-   QUERY_DESC_IDN_RFU_0= 0x3,
-   QUERY_DESC_IDN_INTERCONNECT = 0x4,
-   QUERY_DESC_IDN_STRING   = 0x5,
-   QUERY_DESC_IDN_RFU_1= 0x6,
-   QUERY_DESC_IDN_GEOMETRY = 0x7,
-   QUERY_DESC_IDN_POWER= 0x8,
-   QUERY_DESC_IDN_MAX,
-};
-
 enum desc_header_offset {
QUERY_DESC_LENGTH_OFFSET= 0x00,
QUERY_DESC_DESC_TYPE_OFFSET = 0x01,
@@ -247,19 +229,6 @@ enum bkops_status {
BKOPS_STATUS_MAX = BKOPS_STATUS_CRITICAL,
 };
 
-/* UTP QUERY Transaction Specific Fields OpCode */
-enum query_opcode {
-   UPIU_QUERY_OPCODE_NOP   = 0x0,
-   UPIU_QUERY_OPCODE_READ_DESC = 0x1,
-   UPIU_QUERY_OPCODE_WRITE_DESC= 0x2,
-   UPIU_QUERY_OPCODE_READ_ATTR = 0x3,
-   UPIU_QUERY_OPCODE_WRITE_ATTR= 0x4,
-   UPIU_QUERY_OPCODE_READ_FLAG = 0x5,
-   UPIU_QUERY_OPCODE_SET_FLAG  = 0x6,
-   UPIU_QUERY_OPCODE_CLEAR_FLAG= 0x7,
-   UPIU_QUERY_OPCODE_TOGGLE_FLAG   = 0x8,
-};
-
 /* Query response result code */
 enum {
QUERY_RESULT_SUCCESS= 0x00,
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index 5d60a86..cb357f8 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -3,7 +3,7 @@
  *
  * This code is based on drivers/scsi/ufs/ufshcd.c
  * Copyright (C) 2011-2013 Samsung India Software Operations
- * Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-2015, The Linux Foundation. All rights reserved.
  *
  * Authors:
  * Santosh Yaraganavi santosh...@samsung.com
@@ -39,6 +39,7 @@
 
 #include linux/async.h
 #include linux/devfreq.h
+#include scsi/ufs/ioctl.h
 
 #include ufshcd.h
 #include unipro.h
@@ -74,6 +75,9 @@
 /* Interrupt aggregation default timeout, unit: 40us */
 #define INT_AGGR_DEF_TO0x02
 
+/* IOCTL opcode for command - ufs set device read only */
+#define UFS_IOCTL_BLKROSET  BLKROSET
+
 #define ufshcd_toggle_vreg(_dev, _vreg, _on)   \
({  \
int _ret;   \
@@ -1882,7 +1886,7 @@ static inline int ufshcd_read_unit_desc_param(struct 
ufs_hba *hba,
 * Unit descriptors are only available for general purpose LUs (LUN id
 * from 0 to 7) and RPMB Well known LU.
 */
-   if (lun != UFS_UPIU_RPMB_WLUN  (lun = 

Re: [PATCH v5 3/3] scsi: ufs: add trace events and dump prints for debug

2015-03-12 Thread Gilad Broner
 This and the auto_bkops_state is pretty much the same. Can't you use
 the same TP_printk() and just have a DECLARE_EVENT_CLASS? The trace
 point name is printed with the event to see different events.

I agree. will upload the fix in next patchset.

-- 
Qualcomm Israel, on behalf of Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH v5 3/3] scsi: ufs: add trace events and dump prints for debug

2015-03-10 Thread Gilad Broner
Add trace events to driver to allow monitoring and profilig
of activities such as PM suspend/resume, hibernate enter/exit,
clock gating and clock scaling up/down.
In addition, add UFS host controller register dumps to provide
detailed information in case of errors to assist in analysis
of issues.

Signed-off-by: Dolev Raviv 
Signed-off-by: Subhash Jadavani 
Signed-off-by: Lee Susman 
Signed-off-by: Sujit Reddy Thumma 
Signed-off-by: Yaniv Gardi 
---
 drivers/scsi/ufs/ufs-qcom.c |  53 +
 drivers/scsi/ufs/ufshcd.c   | 511 +---
 drivers/scsi/ufs/ufshcd.h   |  49 -
 drivers/scsi/ufs/ufshci.h   |   1 +
 include/trace/events/ufs.h  | 227 
 5 files changed, 804 insertions(+), 37 deletions(-)
 create mode 100644 include/trace/events/ufs.h

diff --git a/drivers/scsi/ufs/ufs-qcom.c b/drivers/scsi/ufs/ufs-qcom.c
index 9217af9..9fe675d 100644
--- a/drivers/scsi/ufs/ufs-qcom.c
+++ b/drivers/scsi/ufs/ufs-qcom.c
@@ -30,6 +30,14 @@ static int ufs_qcom_get_bus_vote(struct ufs_qcom_host *host,
const char *speed_mode);
 static int ufs_qcom_set_bus_vote(struct ufs_qcom_host *host, int vote);
 
+static void ufs_qcom_dump_regs(struct ufs_hba *hba, int offset, int len,
+   char *prefix)
+{
+   print_hex_dump(KERN_ERR, prefix,
+   len > 4 ? DUMP_PREFIX_OFFSET : DUMP_PREFIX_NONE,
+   16, 4, hba->mmio_base + offset, len * 4, false);
+}
+
 static int ufs_qcom_get_connected_tx_lanes(struct ufs_hba *hba, u32 *tx_lanes)
 {
int err = 0;
@@ -983,6 +991,50 @@ void ufs_qcom_clk_scale_notify(struct ufs_hba *hba)
dev_req_params->hs_rate);
 }
 
+static void ufs_qcom_print_hw_debug_reg_all(struct ufs_hba *hba)
+{
+   u32 reg;
+
+   ufs_qcom_dump_regs(hba, UFS_UFS_DBG_RD_REG_OCSC, 44,
+   "UFS_UFS_DBG_RD_REG_OCSC ");
+
+   reg = ufshcd_readl(hba, REG_UFS_CFG1);
+   reg |= UFS_BIT(17);
+   ufshcd_writel(hba, reg, REG_UFS_CFG1);
+
+   ufs_qcom_dump_regs(hba, UFS_UFS_DBG_RD_EDTL_RAM, 32,
+   "UFS_UFS_DBG_RD_EDTL_RAM ");
+   ufs_qcom_dump_regs(hba, UFS_UFS_DBG_RD_DESC_RAM, 128,
+   "UFS_UFS_DBG_RD_DESC_RAM ");
+   ufs_qcom_dump_regs(hba, UFS_UFS_DBG_RD_PRDT_RAM, 64,
+   "UFS_UFS_DBG_RD_PRDT_RAM ");
+
+   ufshcd_writel(hba, (reg & ~UFS_BIT(17)), REG_UFS_CFG1);
+
+   ufs_qcom_dump_regs(hba, UFS_DBG_RD_REG_UAWM, 4,
+   "UFS_DBG_RD_REG_UAWM ");
+   ufs_qcom_dump_regs(hba, UFS_DBG_RD_REG_UARM, 4,
+   "UFS_DBG_RD_REG_UARM ");
+   ufs_qcom_dump_regs(hba, UFS_DBG_RD_REG_TXUC, 48,
+   "UFS_DBG_RD_REG_TXUC ");
+   ufs_qcom_dump_regs(hba, UFS_DBG_RD_REG_RXUC, 27,
+   "UFS_DBG_RD_REG_RXUC ");
+   ufs_qcom_dump_regs(hba, UFS_DBG_RD_REG_DFC, 19,
+   "UFS_DBG_RD_REG_DFC ");
+   ufs_qcom_dump_regs(hba, UFS_DBG_RD_REG_TRLUT, 34,
+   "UFS_DBG_RD_REG_TRLUT ");
+   ufs_qcom_dump_regs(hba, UFS_DBG_RD_REG_TMRLUT, 9,
+   "UFS_DBG_RD_REG_TMRLUT ");
+}
+
+static void ufs_qcom_dump_dbg_regs(struct ufs_hba *hba)
+{
+   ufs_qcom_dump_regs(hba, REG_UFS_SYS1CLK_1US, 5,
+   "REG_UFS_SYS1CLK_1US ");
+
+   ufs_qcom_print_hw_debug_reg_all(hba);
+}
+
 /**
  * struct ufs_hba_qcom_vops - UFS QCOM specific variant operations
  *
@@ -1000,5 +1052,6 @@ static const struct ufs_hba_variant_ops ufs_hba_qcom_vops 
= {
.pwr_change_notify  = ufs_qcom_pwr_change_notify,
.suspend= ufs_qcom_suspend,
.resume = ufs_qcom_resume,
+   .dbg_register_dump  = ufs_qcom_dump_dbg_regs,
 };
 EXPORT_SYMBOL(ufs_hba_qcom_vops);
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index 7697cc6..3ae0b3f 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -45,6 +45,9 @@
 #include "unipro.h"
 #include "ufs-debugfs.h"
 
+#define CREATE_TRACE_POINTS
+#include 
+
 #ifdef CONFIG_DEBUG_FS
 
 static void ufshcd_update_error_stats(struct ufs_hba *hba, int type)
@@ -145,6 +148,8 @@ static inline ufshcd_update_error_stats(struct ufs_hba 
*hba, int type)
_ret = ufshcd_disable_vreg(_dev, _vreg);\
_ret;   \
})
+#define ufshcd_hex_dump(prefix_str, buf, len) \
+print_hex_dump(KERN_ERR, prefix_str, DUMP_PREFIX_OFFSET, 16, 4, buf, len, 
false)
 
 static u32 ufs_query_desc_max_size[] = {
QUERY_DESC_DEVICE_MAX_SIZE,
@@ -272,6 +277,151 @@ static inline void ufshcd_disable_irq(struct ufs_hba *hba)
}
 }
 
+#ifdef CONFIG_TRACEPOINTS
+static void ufshcd_add_command_trace(struct ufs_hba *hba,
+   unsigned int tag, const char *str)
+{
+   sector_t lba = -1;
+   u8 opcode = 0;
+   u32 intr, doorbell;
+   

[PATCH v5 2/3] scsi: ufs: add debugfs for ufs

2015-03-10 Thread Gilad Broner
From: Lee Susman 

Adding debugfs capability for ufshcd.

debugfs attributes introduced in this patch:
 - View driver/controller runtime data
 - Command tag statistics for performance analisis
 - Dump device descriptor info
 - Track recoverable errors statistics during runtime
 - Change UFS power mode during runtime
 entry a string in the format 'GGLLMM' where:
 G - selected gear
 L - number of lanes
 M - power mode
 (1=fast mode, 2=slow mode, 4=fast-auto mode,
  5=slow-auto mode)
 First letter is for RX, second is for TX.
 - Get/set DME attributes

Signed-off-by: Lee Susman 
Signed-off-by: Dolev Raviv 
Signed-off-by: Yaniv Gardi 
Signed-off-by: Raviv Shvili 
Signed-off-by: Gilad Broner 
---
 drivers/scsi/ufs/Makefile  |   1 +
 drivers/scsi/ufs/ufs-debugfs.c | 902 +
 drivers/scsi/ufs/ufs-debugfs.h |  38 ++
 drivers/scsi/ufs/ufshcd.c  | 229 ++-
 drivers/scsi/ufs/ufshcd.h  |  65 +++
 drivers/scsi/ufs/ufshci.h  |   2 +
 6 files changed, 1225 insertions(+), 12 deletions(-)
 create mode 100644 drivers/scsi/ufs/ufs-debugfs.c
 create mode 100644 drivers/scsi/ufs/ufs-debugfs.h

diff --git a/drivers/scsi/ufs/Makefile b/drivers/scsi/ufs/Makefile
index 8303bcc..0692314 100644
--- a/drivers/scsi/ufs/Makefile
+++ b/drivers/scsi/ufs/Makefile
@@ -3,3 +3,4 @@ obj-$(CONFIG_SCSI_UFS_QCOM) += ufs-qcom.o
 obj-$(CONFIG_SCSI_UFSHCD) += ufshcd.o
 obj-$(CONFIG_SCSI_UFSHCD_PCI) += ufshcd-pci.o
 obj-$(CONFIG_SCSI_UFSHCD_PLATFORM) += ufshcd-pltfrm.o
+obj-$(CONFIG_DEBUG_FS) += ufs-debugfs.o
diff --git a/drivers/scsi/ufs/ufs-debugfs.c b/drivers/scsi/ufs/ufs-debugfs.c
new file mode 100644
index 000..27ab053
--- /dev/null
+++ b/drivers/scsi/ufs/ufs-debugfs.c
@@ -0,0 +1,902 @@
+/* Copyright (c) 2013-2015, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * UFS debugfs - add debugfs interface to the ufshcd.
+ * This is currently used for statistics collection and exporting from the
+ * UFS driver.
+ * This infrastructure can be used for debugging or direct tweaking
+ * of the driver from userspace.
+ *
+ */
+
+#include "ufs-debugfs.h"
+#include "unipro.h"
+
+enum field_width {
+   BYTE= 1,
+   WORD= 2,
+};
+
+struct desc_field_offset {
+   char *name;
+   int offset;
+   enum field_width width_byte;
+};
+
+#define UFS_ERR_STATS_PRINT(file, error_index, string, error_seen) \
+   do {\
+   if (err_stats[error_index]) {   \
+   seq_printf(file, string,\
+   err_stats[error_index]);\
+   error_seen = true;  \
+   }   \
+   } while (0)
+#define DOORBELL_CLR_TOUT_US   (1000 * 1000) /* 1 sec */
+
+#define BUFF_LINE_CAPACITY 16
+#define TAB_CHARS 8
+
+static int ufsdbg_tag_stats_show(struct seq_file *file, void *data)
+{
+   struct ufs_hba *hba = (struct ufs_hba *)file->private;
+   struct ufs_stats *ufs_stats;
+   int i, j;
+   int max_depth;
+   bool is_tag_empty = true;
+   unsigned long flags;
+   char *sep = " | * | ";
+
+   if (!hba)
+   goto exit;
+
+   ufs_stats = >ufs_stats;
+
+   if (!ufs_stats->enabled) {
+   pr_debug("%s: ufs statistics are disabled\n", __func__);
+   seq_puts(file, "ufs statistics are disabled");
+   goto exit;
+   }
+
+   max_depth = hba->nutrs;
+
+   spin_lock_irqsave(hba->host->host_lock, flags);
+   /* Header */
+   seq_printf(file, " Tag Stat\t\t%s Queue Fullness\n", sep);
+   for (i = 0; i < TAB_CHARS * (TS_NUM_STATS + 4); i++) {
+   seq_puts(file, "-");
+   if (i == (TAB_CHARS * 3 - 1))
+   seq_puts(file, sep);
+   }
+   seq_printf(file,
+   "\n #\tnum uses\t%s\t #\tAll\t Read\t Write\t Flush\n",
+   sep);
+
+   /* values */
+   for (i = 0; i < max_depth; i++) {
+   if (ufs_stats->tag_stats[i][0] <= 0 &&
+   ufs_stats->tag_stats[i][1] <= 0 &&
+   ufs_stats->tag_stats[i][2] <= 0 &a

[PATCH v5 1/3] scsi: ufs: add ioctl interface for query request

2015-03-10 Thread Gilad Broner
From: Dolev Raviv 

This patch exposes the ioctl interface for UFS driver via SCSI device
ioctl interface. As of now UFS driver would provide the ioctl for query
interface to connected UFS device.

Signed-off-by: Dolev Raviv 
Signed-off-by: Noa Rubens 
Signed-off-by: Raviv Shvili 
Signed-off-by: Yaniv Gardi 
---
 drivers/scsi/ufs/ufs.h|  53 +++---
 drivers/scsi/ufs/ufshcd.c | 225 +-
 include/uapi/scsi/Kbuild  |   1 +
 include/uapi/scsi/ufs/Kbuild  |   3 +
 include/uapi/scsi/ufs/ioctl.h |  57 +++
 include/uapi/scsi/ufs/ufs.h   |  66 +
 6 files changed, 361 insertions(+), 44 deletions(-)
 create mode 100644 include/uapi/scsi/ufs/Kbuild
 create mode 100644 include/uapi/scsi/ufs/ioctl.h
 create mode 100644 include/uapi/scsi/ufs/ufs.h

diff --git a/drivers/scsi/ufs/ufs.h b/drivers/scsi/ufs/ufs.h
index 42c459a..1f023c4 100644
--- a/drivers/scsi/ufs/ufs.h
+++ b/drivers/scsi/ufs/ufs.h
@@ -38,6 +38,7 @@
 
 #include 
 #include 
+#include 
 
 #define MAX_CDB_SIZE   16
 #define GENERAL_UPIU_REQUEST_SIZE 32
@@ -71,6 +72,16 @@ enum {
UFS_UPIU_RPMB_WLUN  = 0xC4,
 };
 
+/**
+ * ufs_is_valid_unit_desc_lun - checks if the given LUN has a unit descriptor
+ * @lun: LU number to check
+ * @return: true if the lun has a matching unit descriptor, false otherwise
+ */
+static inline bool ufs_is_valid_unit_desc_lun(u8 lun)
+{
+   return (lun == UFS_UPIU_RPMB_WLUN || (lun < UFS_UPIU_MAX_GENERAL_LUN));
+}
+
 /*
  * UFS Protocol Information Unit related definitions
  */
@@ -126,35 +137,6 @@ enum {
UPIU_QUERY_FUNC_STANDARD_WRITE_REQUEST  = 0x81,
 };
 
-/* Flag idn for Query Requests*/
-enum flag_idn {
-   QUERY_FLAG_IDN_FDEVICEINIT  = 0x01,
-   QUERY_FLAG_IDN_PWR_ON_WPE   = 0x03,
-   QUERY_FLAG_IDN_BKOPS_EN = 0x04,
-};
-
-/* Attribute idn for Query requests */
-enum attr_idn {
-   QUERY_ATTR_IDN_ACTIVE_ICC_LVL   = 0x03,
-   QUERY_ATTR_IDN_BKOPS_STATUS = 0x05,
-   QUERY_ATTR_IDN_EE_CONTROL   = 0x0D,
-   QUERY_ATTR_IDN_EE_STATUS= 0x0E,
-};
-
-/* Descriptor idn for Query requests */
-enum desc_idn {
-   QUERY_DESC_IDN_DEVICE   = 0x0,
-   QUERY_DESC_IDN_CONFIGURAION = 0x1,
-   QUERY_DESC_IDN_UNIT = 0x2,
-   QUERY_DESC_IDN_RFU_0= 0x3,
-   QUERY_DESC_IDN_INTERCONNECT = 0x4,
-   QUERY_DESC_IDN_STRING   = 0x5,
-   QUERY_DESC_IDN_RFU_1= 0x6,
-   QUERY_DESC_IDN_GEOMETRY = 0x7,
-   QUERY_DESC_IDN_POWER= 0x8,
-   QUERY_DESC_IDN_MAX,
-};
-
 enum desc_header_offset {
QUERY_DESC_LENGTH_OFFSET= 0x00,
QUERY_DESC_DESC_TYPE_OFFSET = 0x01,
@@ -247,19 +229,6 @@ enum bkops_status {
BKOPS_STATUS_MAX = BKOPS_STATUS_CRITICAL,
 };
 
-/* UTP QUERY Transaction Specific Fields OpCode */
-enum query_opcode {
-   UPIU_QUERY_OPCODE_NOP   = 0x0,
-   UPIU_QUERY_OPCODE_READ_DESC = 0x1,
-   UPIU_QUERY_OPCODE_WRITE_DESC= 0x2,
-   UPIU_QUERY_OPCODE_READ_ATTR = 0x3,
-   UPIU_QUERY_OPCODE_WRITE_ATTR= 0x4,
-   UPIU_QUERY_OPCODE_READ_FLAG = 0x5,
-   UPIU_QUERY_OPCODE_SET_FLAG  = 0x6,
-   UPIU_QUERY_OPCODE_CLEAR_FLAG= 0x7,
-   UPIU_QUERY_OPCODE_TOGGLE_FLAG   = 0x8,
-};
-
 /* Query response result code */
 enum {
QUERY_RESULT_SUCCESS= 0x00,
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index 5d60a86..cb357f8 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -3,7 +3,7 @@
  *
  * This code is based on drivers/scsi/ufs/ufshcd.c
  * Copyright (C) 2011-2013 Samsung India Software Operations
- * Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-2015, The Linux Foundation. All rights reserved.
  *
  * Authors:
  * Santosh Yaraganavi 
@@ -39,6 +39,7 @@
 
 #include 
 #include 
+#include 
 
 #include "ufshcd.h"
 #include "unipro.h"
@@ -74,6 +75,9 @@
 /* Interrupt aggregation default timeout, unit: 40us */
 #define INT_AGGR_DEF_TO0x02
 
+/* IOCTL opcode for command - ufs set device read only */
+#define UFS_IOCTL_BLKROSET  BLKROSET
+
 #define ufshcd_toggle_vreg(_dev, _vreg, _on)   \
({  \
int _ret;   \
@@ -1882,7 +1886,7 @@ static inline int ufshcd_read_unit_desc_param(struct 
ufs_hba *hba,
 * Unit descriptors are only available for general purpose LUs (LUN id
 * from 0 to 7) and RPMB Well known LU.
 */
-   if (lun != UFS_UPIU_RPMB_WLUN && (lun >= UFS_UPIU_MAX_GENERAL_LUN))
+   if (!ufs_is_valid_unit_desc_lun(lun))
return -EOPNOTSUPP;
 
return ufshcd_read_desc_param(hba, QUERY_DESC_IDN_UNIT, lun,
@@ -4201,6 +4205,222 @@ static void 

[PATCH v5 0/3] Add ioctl and debug utilities to UFS driver

2015-03-10 Thread Gilad Broner
Changes from V4:
Dropped error injection change titled:
scsi: ufs: inject errors to verify error handling

Dolev Raviv (1):
  scsi: ufs: add ioctl interface for query request

Gilad Broner (1):
  scsi: ufs: add trace events and dump prints for debug

Lee Susman (1):
  scsi: ufs: add debugfs for ufs

 drivers/scsi/ufs/Makefile  |   1 +
 drivers/scsi/ufs/ufs-debugfs.c | 902 ++
 drivers/scsi/ufs/ufs-debugfs.h |  38 ++
 drivers/scsi/ufs/ufs-qcom.c|  53 +++
 drivers/scsi/ufs/ufs.h |  53 +--
 drivers/scsi/ufs/ufshcd.c  | 963 +++--
 drivers/scsi/ufs/ufshcd.h  | 110 +
 drivers/scsi/ufs/ufshci.h  |   3 +
 include/trace/events/ufs.h | 227 ++
 include/uapi/scsi/Kbuild   |   1 +
 include/uapi/scsi/ufs/Kbuild   |   3 +
 include/uapi/scsi/ufs/ioctl.h  |  57 +++
 include/uapi/scsi/ufs/ufs.h|  66 +++
 13 files changed, 2387 insertions(+), 90 deletions(-)
 create mode 100644 drivers/scsi/ufs/ufs-debugfs.c
 create mode 100644 drivers/scsi/ufs/ufs-debugfs.h
 create mode 100644 include/trace/events/ufs.h
 create mode 100644 include/uapi/scsi/ufs/Kbuild
 create mode 100644 include/uapi/scsi/ufs/ioctl.h
 create mode 100644 include/uapi/scsi/ufs/ufs.h

-- 
Qualcomm Israel, on behalf of Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH] drivers: scsi: ufs: Fix possible null derefrence

2015-03-10 Thread Gilad Broner
> Check for null before being dereferenced to avoid a invalid null
> dereference.
>
> Found using Coccinelle.
>
> Signed-off-by: Tapasweni Pathak 
> Acked-by: Julia Lawall 
> ---
>  drivers/scsi/ufs/ufshcd.c |7 +--
>  1 file changed, 5 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
> index 5d60a86..c54e64f 100644
> --- a/drivers/scsi/ufs/ufshcd.c
> +++ b/drivers/scsi/ufs/ufshcd.c
> @@ -4268,12 +4268,15 @@ static int ufshcd_config_vreg(struct device *dev,
>   struct ufs_vreg *vreg, bool on)
>  {
>   int ret = 0;
> - struct regulator *reg = vreg->reg;
> - const char *name = vreg->name;
> + struct regulator *reg;
> + const char *name;
>   int min_uV, uA_load;
>
>   BUG_ON(!vreg);


Please add to the patch fix for another instance of this  in
ufshcd_config_vreg_load():

static int ufshcd_config_vreg_load(struct device *dev,
struct ufs_vreg *vreg, int ua)
{
int ret = 0;
struct regulator *reg = vreg->reg;
const char *name = vreg->name;

BUG_ON(!vreg);


Gilad.

-- 
Qualcomm Israel, on behalf of Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH v4 4/4] scsi: ufs: inject errors to verify error handling

2015-03-10 Thread Gilad Broner
>> +static bool inject_cmd_hang_tr(struct ufs_hba *hba)
>> +{
>> +   int tag;
>> +
>> +   tag = find_first_bit(>outstanding_reqs, hba->nutrs);
>> +   if (tag == hba->nutrs)
>> +   return 0;
>> +
>> +   __clear_bit(tag, >outstanding_reqs);
>> +   hba->lrb[tag].cmd = NULL;
>> +   __clear_bit(tag, >lrb_in_use);
>
> hba->lrb_in_use is a bitmap set by test_and_set_bit_lock().  So
> this should be cleared by clear_bit_unlock().

You are correct. Thanks.

>
> And as soon as the bit corresponds to this slot in hba->lrb_in_use is
> cleared, this slot could be reused.  But if the request corresponds
> to the slot is not completed yet, it could sacrifice the new request,
> too.  So should we only inject into the commands which have been
> completed like this?

Please note that we only clear the bit in hba->lrb_in_use. scsi_done is
not called for this request. Therefore, the tag is not yet free in the
block layer and next calls for queuecommand will not pass down this tag to
be used in the UFS driver. So there is no danger of a new request being
sacrificed.

On a different note, we are debating internally on a few other changes so
until we consolidate those I will drop this patch with error injection.

Gilad.

-- 
Qualcomm Israel, on behalf of Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH v4 4/4] scsi: ufs: inject errors to verify error handling

2015-03-10 Thread Gilad Broner
 +static bool inject_cmd_hang_tr(struct ufs_hba *hba)
 +{
 +   int tag;
 +
 +   tag = find_first_bit(hba-outstanding_reqs, hba-nutrs);
 +   if (tag == hba-nutrs)
 +   return 0;
 +
 +   __clear_bit(tag, hba-outstanding_reqs);
 +   hba-lrb[tag].cmd = NULL;
 +   __clear_bit(tag, hba-lrb_in_use);

 hba-lrb_in_use is a bitmap set by test_and_set_bit_lock().  So
 this should be cleared by clear_bit_unlock().

You are correct. Thanks.


 And as soon as the bit corresponds to this slot in hba-lrb_in_use is
 cleared, this slot could be reused.  But if the request corresponds
 to the slot is not completed yet, it could sacrifice the new request,
 too.  So should we only inject into the commands which have been
 completed like this?

Please note that we only clear the bit in hba-lrb_in_use. scsi_done is
not called for this request. Therefore, the tag is not yet free in the
block layer and next calls for queuecommand will not pass down this tag to
be used in the UFS driver. So there is no danger of a new request being
sacrificed.

On a different note, we are debating internally on a few other changes so
until we consolidate those I will drop this patch with error injection.

Gilad.

-- 
Qualcomm Israel, on behalf of Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH v5 0/3] Add ioctl and debug utilities to UFS driver

2015-03-10 Thread Gilad Broner
Changes from V4:
Dropped error injection change titled:
scsi: ufs: inject errors to verify error handling

Dolev Raviv (1):
  scsi: ufs: add ioctl interface for query request

Gilad Broner (1):
  scsi: ufs: add trace events and dump prints for debug

Lee Susman (1):
  scsi: ufs: add debugfs for ufs

 drivers/scsi/ufs/Makefile  |   1 +
 drivers/scsi/ufs/ufs-debugfs.c | 902 ++
 drivers/scsi/ufs/ufs-debugfs.h |  38 ++
 drivers/scsi/ufs/ufs-qcom.c|  53 +++
 drivers/scsi/ufs/ufs.h |  53 +--
 drivers/scsi/ufs/ufshcd.c  | 963 +++--
 drivers/scsi/ufs/ufshcd.h  | 110 +
 drivers/scsi/ufs/ufshci.h  |   3 +
 include/trace/events/ufs.h | 227 ++
 include/uapi/scsi/Kbuild   |   1 +
 include/uapi/scsi/ufs/Kbuild   |   3 +
 include/uapi/scsi/ufs/ioctl.h  |  57 +++
 include/uapi/scsi/ufs/ufs.h|  66 +++
 13 files changed, 2387 insertions(+), 90 deletions(-)
 create mode 100644 drivers/scsi/ufs/ufs-debugfs.c
 create mode 100644 drivers/scsi/ufs/ufs-debugfs.h
 create mode 100644 include/trace/events/ufs.h
 create mode 100644 include/uapi/scsi/ufs/Kbuild
 create mode 100644 include/uapi/scsi/ufs/ioctl.h
 create mode 100644 include/uapi/scsi/ufs/ufs.h

-- 
Qualcomm Israel, on behalf of Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH v5 2/3] scsi: ufs: add debugfs for ufs

2015-03-10 Thread Gilad Broner
From: Lee Susman lsus...@codeaurora.org

Adding debugfs capability for ufshcd.

debugfs attributes introduced in this patch:
 - View driver/controller runtime data
 - Command tag statistics for performance analisis
 - Dump device descriptor info
 - Track recoverable errors statistics during runtime
 - Change UFS power mode during runtime
 entry a string in the format 'GGLLMM' where:
 G - selected gear
 L - number of lanes
 M - power mode
 (1=fast mode, 2=slow mode, 4=fast-auto mode,
  5=slow-auto mode)
 First letter is for RX, second is for TX.
 - Get/set DME attributes

Signed-off-by: Lee Susman lsus...@codeaurora.org
Signed-off-by: Dolev Raviv dra...@codeaurora.org
Signed-off-by: Yaniv Gardi yga...@codeaurora.org
Signed-off-by: Raviv Shvili rshv...@codeaurora.org
Signed-off-by: Gilad Broner gbro...@codeaurora.org
---
 drivers/scsi/ufs/Makefile  |   1 +
 drivers/scsi/ufs/ufs-debugfs.c | 902 +
 drivers/scsi/ufs/ufs-debugfs.h |  38 ++
 drivers/scsi/ufs/ufshcd.c  | 229 ++-
 drivers/scsi/ufs/ufshcd.h  |  65 +++
 drivers/scsi/ufs/ufshci.h  |   2 +
 6 files changed, 1225 insertions(+), 12 deletions(-)
 create mode 100644 drivers/scsi/ufs/ufs-debugfs.c
 create mode 100644 drivers/scsi/ufs/ufs-debugfs.h

diff --git a/drivers/scsi/ufs/Makefile b/drivers/scsi/ufs/Makefile
index 8303bcc..0692314 100644
--- a/drivers/scsi/ufs/Makefile
+++ b/drivers/scsi/ufs/Makefile
@@ -3,3 +3,4 @@ obj-$(CONFIG_SCSI_UFS_QCOM) += ufs-qcom.o
 obj-$(CONFIG_SCSI_UFSHCD) += ufshcd.o
 obj-$(CONFIG_SCSI_UFSHCD_PCI) += ufshcd-pci.o
 obj-$(CONFIG_SCSI_UFSHCD_PLATFORM) += ufshcd-pltfrm.o
+obj-$(CONFIG_DEBUG_FS) += ufs-debugfs.o
diff --git a/drivers/scsi/ufs/ufs-debugfs.c b/drivers/scsi/ufs/ufs-debugfs.c
new file mode 100644
index 000..27ab053
--- /dev/null
+++ b/drivers/scsi/ufs/ufs-debugfs.c
@@ -0,0 +1,902 @@
+/* Copyright (c) 2013-2015, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * UFS debugfs - add debugfs interface to the ufshcd.
+ * This is currently used for statistics collection and exporting from the
+ * UFS driver.
+ * This infrastructure can be used for debugging or direct tweaking
+ * of the driver from userspace.
+ *
+ */
+
+#include ufs-debugfs.h
+#include unipro.h
+
+enum field_width {
+   BYTE= 1,
+   WORD= 2,
+};
+
+struct desc_field_offset {
+   char *name;
+   int offset;
+   enum field_width width_byte;
+};
+
+#define UFS_ERR_STATS_PRINT(file, error_index, string, error_seen) \
+   do {\
+   if (err_stats[error_index]) {   \
+   seq_printf(file, string,\
+   err_stats[error_index]);\
+   error_seen = true;  \
+   }   \
+   } while (0)
+#define DOORBELL_CLR_TOUT_US   (1000 * 1000) /* 1 sec */
+
+#define BUFF_LINE_CAPACITY 16
+#define TAB_CHARS 8
+
+static int ufsdbg_tag_stats_show(struct seq_file *file, void *data)
+{
+   struct ufs_hba *hba = (struct ufs_hba *)file-private;
+   struct ufs_stats *ufs_stats;
+   int i, j;
+   int max_depth;
+   bool is_tag_empty = true;
+   unsigned long flags;
+   char *sep =  | * | ;
+
+   if (!hba)
+   goto exit;
+
+   ufs_stats = hba-ufs_stats;
+
+   if (!ufs_stats-enabled) {
+   pr_debug(%s: ufs statistics are disabled\n, __func__);
+   seq_puts(file, ufs statistics are disabled);
+   goto exit;
+   }
+
+   max_depth = hba-nutrs;
+
+   spin_lock_irqsave(hba-host-host_lock, flags);
+   /* Header */
+   seq_printf(file,  Tag Stat\t\t%s Queue Fullness\n, sep);
+   for (i = 0; i  TAB_CHARS * (TS_NUM_STATS + 4); i++) {
+   seq_puts(file, -);
+   if (i == (TAB_CHARS * 3 - 1))
+   seq_puts(file, sep);
+   }
+   seq_printf(file,
+   \n #\tnum uses\t%s\t #\tAll\t Read\t Write\t Flush\n,
+   sep);
+
+   /* values */
+   for (i = 0; i  max_depth; i++) {
+   if (ufs_stats-tag_stats[i][0] = 0 
+   ufs_stats-tag_stats[i][1] = 0 
+   ufs_stats-tag_stats[i][2] = 0 
+   ufs_stats-tag_stats[i][3] = 0

[PATCH v5 1/3] scsi: ufs: add ioctl interface for query request

2015-03-10 Thread Gilad Broner
From: Dolev Raviv dra...@codeaurora.org

This patch exposes the ioctl interface for UFS driver via SCSI device
ioctl interface. As of now UFS driver would provide the ioctl for query
interface to connected UFS device.

Signed-off-by: Dolev Raviv dra...@codeaurora.org
Signed-off-by: Noa Rubens n...@codeaurora.org
Signed-off-by: Raviv Shvili rshv...@codeaurora.org
Signed-off-by: Yaniv Gardi yga...@codeaurora.org
---
 drivers/scsi/ufs/ufs.h|  53 +++---
 drivers/scsi/ufs/ufshcd.c | 225 +-
 include/uapi/scsi/Kbuild  |   1 +
 include/uapi/scsi/ufs/Kbuild  |   3 +
 include/uapi/scsi/ufs/ioctl.h |  57 +++
 include/uapi/scsi/ufs/ufs.h   |  66 +
 6 files changed, 361 insertions(+), 44 deletions(-)
 create mode 100644 include/uapi/scsi/ufs/Kbuild
 create mode 100644 include/uapi/scsi/ufs/ioctl.h
 create mode 100644 include/uapi/scsi/ufs/ufs.h

diff --git a/drivers/scsi/ufs/ufs.h b/drivers/scsi/ufs/ufs.h
index 42c459a..1f023c4 100644
--- a/drivers/scsi/ufs/ufs.h
+++ b/drivers/scsi/ufs/ufs.h
@@ -38,6 +38,7 @@
 
 #include linux/mutex.h
 #include linux/types.h
+#include scsi/ufs/ufs.h
 
 #define MAX_CDB_SIZE   16
 #define GENERAL_UPIU_REQUEST_SIZE 32
@@ -71,6 +72,16 @@ enum {
UFS_UPIU_RPMB_WLUN  = 0xC4,
 };
 
+/**
+ * ufs_is_valid_unit_desc_lun - checks if the given LUN has a unit descriptor
+ * @lun: LU number to check
+ * @return: true if the lun has a matching unit descriptor, false otherwise
+ */
+static inline bool ufs_is_valid_unit_desc_lun(u8 lun)
+{
+   return (lun == UFS_UPIU_RPMB_WLUN || (lun  UFS_UPIU_MAX_GENERAL_LUN));
+}
+
 /*
  * UFS Protocol Information Unit related definitions
  */
@@ -126,35 +137,6 @@ enum {
UPIU_QUERY_FUNC_STANDARD_WRITE_REQUEST  = 0x81,
 };
 
-/* Flag idn for Query Requests*/
-enum flag_idn {
-   QUERY_FLAG_IDN_FDEVICEINIT  = 0x01,
-   QUERY_FLAG_IDN_PWR_ON_WPE   = 0x03,
-   QUERY_FLAG_IDN_BKOPS_EN = 0x04,
-};
-
-/* Attribute idn for Query requests */
-enum attr_idn {
-   QUERY_ATTR_IDN_ACTIVE_ICC_LVL   = 0x03,
-   QUERY_ATTR_IDN_BKOPS_STATUS = 0x05,
-   QUERY_ATTR_IDN_EE_CONTROL   = 0x0D,
-   QUERY_ATTR_IDN_EE_STATUS= 0x0E,
-};
-
-/* Descriptor idn for Query requests */
-enum desc_idn {
-   QUERY_DESC_IDN_DEVICE   = 0x0,
-   QUERY_DESC_IDN_CONFIGURAION = 0x1,
-   QUERY_DESC_IDN_UNIT = 0x2,
-   QUERY_DESC_IDN_RFU_0= 0x3,
-   QUERY_DESC_IDN_INTERCONNECT = 0x4,
-   QUERY_DESC_IDN_STRING   = 0x5,
-   QUERY_DESC_IDN_RFU_1= 0x6,
-   QUERY_DESC_IDN_GEOMETRY = 0x7,
-   QUERY_DESC_IDN_POWER= 0x8,
-   QUERY_DESC_IDN_MAX,
-};
-
 enum desc_header_offset {
QUERY_DESC_LENGTH_OFFSET= 0x00,
QUERY_DESC_DESC_TYPE_OFFSET = 0x01,
@@ -247,19 +229,6 @@ enum bkops_status {
BKOPS_STATUS_MAX = BKOPS_STATUS_CRITICAL,
 };
 
-/* UTP QUERY Transaction Specific Fields OpCode */
-enum query_opcode {
-   UPIU_QUERY_OPCODE_NOP   = 0x0,
-   UPIU_QUERY_OPCODE_READ_DESC = 0x1,
-   UPIU_QUERY_OPCODE_WRITE_DESC= 0x2,
-   UPIU_QUERY_OPCODE_READ_ATTR = 0x3,
-   UPIU_QUERY_OPCODE_WRITE_ATTR= 0x4,
-   UPIU_QUERY_OPCODE_READ_FLAG = 0x5,
-   UPIU_QUERY_OPCODE_SET_FLAG  = 0x6,
-   UPIU_QUERY_OPCODE_CLEAR_FLAG= 0x7,
-   UPIU_QUERY_OPCODE_TOGGLE_FLAG   = 0x8,
-};
-
 /* Query response result code */
 enum {
QUERY_RESULT_SUCCESS= 0x00,
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index 5d60a86..cb357f8 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -3,7 +3,7 @@
  *
  * This code is based on drivers/scsi/ufs/ufshcd.c
  * Copyright (C) 2011-2013 Samsung India Software Operations
- * Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-2015, The Linux Foundation. All rights reserved.
  *
  * Authors:
  * Santosh Yaraganavi santosh...@samsung.com
@@ -39,6 +39,7 @@
 
 #include linux/async.h
 #include linux/devfreq.h
+#include scsi/ufs/ioctl.h
 
 #include ufshcd.h
 #include unipro.h
@@ -74,6 +75,9 @@
 /* Interrupt aggregation default timeout, unit: 40us */
 #define INT_AGGR_DEF_TO0x02
 
+/* IOCTL opcode for command - ufs set device read only */
+#define UFS_IOCTL_BLKROSET  BLKROSET
+
 #define ufshcd_toggle_vreg(_dev, _vreg, _on)   \
({  \
int _ret;   \
@@ -1882,7 +1886,7 @@ static inline int ufshcd_read_unit_desc_param(struct 
ufs_hba *hba,
 * Unit descriptors are only available for general purpose LUs (LUN id
 * from 0 to 7) and RPMB Well known LU.
 */
-   if (lun != UFS_UPIU_RPMB_WLUN  (lun = 

[PATCH v5 3/3] scsi: ufs: add trace events and dump prints for debug

2015-03-10 Thread Gilad Broner
Add trace events to driver to allow monitoring and profilig
of activities such as PM suspend/resume, hibernate enter/exit,
clock gating and clock scaling up/down.
In addition, add UFS host controller register dumps to provide
detailed information in case of errors to assist in analysis
of issues.

Signed-off-by: Dolev Raviv dra...@codeaurora.org
Signed-off-by: Subhash Jadavani subha...@codeaurora.org
Signed-off-by: Lee Susman lsus...@codeaurora.org
Signed-off-by: Sujit Reddy Thumma sthu...@codeaurora.org
Signed-off-by: Yaniv Gardi yga...@codeaurora.org
---
 drivers/scsi/ufs/ufs-qcom.c |  53 +
 drivers/scsi/ufs/ufshcd.c   | 511 +---
 drivers/scsi/ufs/ufshcd.h   |  49 -
 drivers/scsi/ufs/ufshci.h   |   1 +
 include/trace/events/ufs.h  | 227 
 5 files changed, 804 insertions(+), 37 deletions(-)
 create mode 100644 include/trace/events/ufs.h

diff --git a/drivers/scsi/ufs/ufs-qcom.c b/drivers/scsi/ufs/ufs-qcom.c
index 9217af9..9fe675d 100644
--- a/drivers/scsi/ufs/ufs-qcom.c
+++ b/drivers/scsi/ufs/ufs-qcom.c
@@ -30,6 +30,14 @@ static int ufs_qcom_get_bus_vote(struct ufs_qcom_host *host,
const char *speed_mode);
 static int ufs_qcom_set_bus_vote(struct ufs_qcom_host *host, int vote);
 
+static void ufs_qcom_dump_regs(struct ufs_hba *hba, int offset, int len,
+   char *prefix)
+{
+   print_hex_dump(KERN_ERR, prefix,
+   len  4 ? DUMP_PREFIX_OFFSET : DUMP_PREFIX_NONE,
+   16, 4, hba-mmio_base + offset, len * 4, false);
+}
+
 static int ufs_qcom_get_connected_tx_lanes(struct ufs_hba *hba, u32 *tx_lanes)
 {
int err = 0;
@@ -983,6 +991,50 @@ void ufs_qcom_clk_scale_notify(struct ufs_hba *hba)
dev_req_params-hs_rate);
 }
 
+static void ufs_qcom_print_hw_debug_reg_all(struct ufs_hba *hba)
+{
+   u32 reg;
+
+   ufs_qcom_dump_regs(hba, UFS_UFS_DBG_RD_REG_OCSC, 44,
+   UFS_UFS_DBG_RD_REG_OCSC );
+
+   reg = ufshcd_readl(hba, REG_UFS_CFG1);
+   reg |= UFS_BIT(17);
+   ufshcd_writel(hba, reg, REG_UFS_CFG1);
+
+   ufs_qcom_dump_regs(hba, UFS_UFS_DBG_RD_EDTL_RAM, 32,
+   UFS_UFS_DBG_RD_EDTL_RAM );
+   ufs_qcom_dump_regs(hba, UFS_UFS_DBG_RD_DESC_RAM, 128,
+   UFS_UFS_DBG_RD_DESC_RAM );
+   ufs_qcom_dump_regs(hba, UFS_UFS_DBG_RD_PRDT_RAM, 64,
+   UFS_UFS_DBG_RD_PRDT_RAM );
+
+   ufshcd_writel(hba, (reg  ~UFS_BIT(17)), REG_UFS_CFG1);
+
+   ufs_qcom_dump_regs(hba, UFS_DBG_RD_REG_UAWM, 4,
+   UFS_DBG_RD_REG_UAWM );
+   ufs_qcom_dump_regs(hba, UFS_DBG_RD_REG_UARM, 4,
+   UFS_DBG_RD_REG_UARM );
+   ufs_qcom_dump_regs(hba, UFS_DBG_RD_REG_TXUC, 48,
+   UFS_DBG_RD_REG_TXUC );
+   ufs_qcom_dump_regs(hba, UFS_DBG_RD_REG_RXUC, 27,
+   UFS_DBG_RD_REG_RXUC );
+   ufs_qcom_dump_regs(hba, UFS_DBG_RD_REG_DFC, 19,
+   UFS_DBG_RD_REG_DFC );
+   ufs_qcom_dump_regs(hba, UFS_DBG_RD_REG_TRLUT, 34,
+   UFS_DBG_RD_REG_TRLUT );
+   ufs_qcom_dump_regs(hba, UFS_DBG_RD_REG_TMRLUT, 9,
+   UFS_DBG_RD_REG_TMRLUT );
+}
+
+static void ufs_qcom_dump_dbg_regs(struct ufs_hba *hba)
+{
+   ufs_qcom_dump_regs(hba, REG_UFS_SYS1CLK_1US, 5,
+   REG_UFS_SYS1CLK_1US );
+
+   ufs_qcom_print_hw_debug_reg_all(hba);
+}
+
 /**
  * struct ufs_hba_qcom_vops - UFS QCOM specific variant operations
  *
@@ -1000,5 +1052,6 @@ static const struct ufs_hba_variant_ops ufs_hba_qcom_vops 
= {
.pwr_change_notify  = ufs_qcom_pwr_change_notify,
.suspend= ufs_qcom_suspend,
.resume = ufs_qcom_resume,
+   .dbg_register_dump  = ufs_qcom_dump_dbg_regs,
 };
 EXPORT_SYMBOL(ufs_hba_qcom_vops);
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index 7697cc6..3ae0b3f 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -45,6 +45,9 @@
 #include unipro.h
 #include ufs-debugfs.h
 
+#define CREATE_TRACE_POINTS
+#include trace/events/ufs.h
+
 #ifdef CONFIG_DEBUG_FS
 
 static void ufshcd_update_error_stats(struct ufs_hba *hba, int type)
@@ -145,6 +148,8 @@ static inline ufshcd_update_error_stats(struct ufs_hba 
*hba, int type)
_ret = ufshcd_disable_vreg(_dev, _vreg);\
_ret;   \
})
+#define ufshcd_hex_dump(prefix_str, buf, len) \
+print_hex_dump(KERN_ERR, prefix_str, DUMP_PREFIX_OFFSET, 16, 4, buf, len, 
false)
 
 static u32 ufs_query_desc_max_size[] = {
QUERY_DESC_DEVICE_MAX_SIZE,
@@ -272,6 +277,151 @@ static inline void ufshcd_disable_irq(struct ufs_hba *hba)
}
 }
 
+#ifdef CONFIG_TRACEPOINTS
+static void ufshcd_add_command_trace(struct ufs_hba *hba,
+   unsigned int tag, const char 

Re: [PATCH] drivers: scsi: ufs: Fix possible null derefrence

2015-03-10 Thread Gilad Broner
 Check for null before being dereferenced to avoid a invalid null
 dereference.

 Found using Coccinelle.

 Signed-off-by: Tapasweni Pathak tapaswenipat...@gmail.com
 Acked-by: Julia Lawall julia.law...@lip6.fr
 ---
  drivers/scsi/ufs/ufshcd.c |7 +--
  1 file changed, 5 insertions(+), 2 deletions(-)

 diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
 index 5d60a86..c54e64f 100644
 --- a/drivers/scsi/ufs/ufshcd.c
 +++ b/drivers/scsi/ufs/ufshcd.c
 @@ -4268,12 +4268,15 @@ static int ufshcd_config_vreg(struct device *dev,
   struct ufs_vreg *vreg, bool on)
  {
   int ret = 0;
 - struct regulator *reg = vreg-reg;
 - const char *name = vreg-name;
 + struct regulator *reg;
 + const char *name;
   int min_uV, uA_load;

   BUG_ON(!vreg);


Please add to the patch fix for another instance of this  in
ufshcd_config_vreg_load():

static int ufshcd_config_vreg_load(struct device *dev,
struct ufs_vreg *vreg, int ua)
{
int ret = 0;
struct regulator *reg = vreg-reg;
const char *name = vreg-name;

BUG_ON(!vreg);


Gilad.

-- 
Qualcomm Israel, on behalf of Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH v4 3/4] scsi: ufs: add trace events and dump prints for debug

2015-03-02 Thread Gilad Broner
Add trace events to driver to allow monitoring and profilig
of activities such as PM suspend/resume, hibernate enter/exit,
clock gating and clock scaling up/down.
In addition, add UFS host controller register dumps to provide
detailed information in case of errors to assist in analysis
of issues.

Signed-off-by: Dolev Raviv 
Signed-off-by: Subhash Jadavani 
Signed-off-by: Lee Susman 
Signed-off-by: Sujit Reddy Thumma 
Signed-off-by: Yaniv Gardi 
---
 drivers/scsi/ufs/ufs-qcom.c |  53 +
 drivers/scsi/ufs/ufshcd.c   | 511 +---
 drivers/scsi/ufs/ufshcd.h   |  49 -
 drivers/scsi/ufs/ufshci.h   |   1 +
 include/trace/events/ufs.h  | 227 
 5 files changed, 804 insertions(+), 37 deletions(-)
 create mode 100644 include/trace/events/ufs.h

diff --git a/drivers/scsi/ufs/ufs-qcom.c b/drivers/scsi/ufs/ufs-qcom.c
index 9217af9..9fe675d 100644
--- a/drivers/scsi/ufs/ufs-qcom.c
+++ b/drivers/scsi/ufs/ufs-qcom.c
@@ -30,6 +30,14 @@ static int ufs_qcom_get_bus_vote(struct ufs_qcom_host *host,
const char *speed_mode);
 static int ufs_qcom_set_bus_vote(struct ufs_qcom_host *host, int vote);
 
+static void ufs_qcom_dump_regs(struct ufs_hba *hba, int offset, int len,
+   char *prefix)
+{
+   print_hex_dump(KERN_ERR, prefix,
+   len > 4 ? DUMP_PREFIX_OFFSET : DUMP_PREFIX_NONE,
+   16, 4, hba->mmio_base + offset, len * 4, false);
+}
+
 static int ufs_qcom_get_connected_tx_lanes(struct ufs_hba *hba, u32 *tx_lanes)
 {
int err = 0;
@@ -983,6 +991,50 @@ void ufs_qcom_clk_scale_notify(struct ufs_hba *hba)
dev_req_params->hs_rate);
 }
 
+static void ufs_qcom_print_hw_debug_reg_all(struct ufs_hba *hba)
+{
+   u32 reg;
+
+   ufs_qcom_dump_regs(hba, UFS_UFS_DBG_RD_REG_OCSC, 44,
+   "UFS_UFS_DBG_RD_REG_OCSC ");
+
+   reg = ufshcd_readl(hba, REG_UFS_CFG1);
+   reg |= UFS_BIT(17);
+   ufshcd_writel(hba, reg, REG_UFS_CFG1);
+
+   ufs_qcom_dump_regs(hba, UFS_UFS_DBG_RD_EDTL_RAM, 32,
+   "UFS_UFS_DBG_RD_EDTL_RAM ");
+   ufs_qcom_dump_regs(hba, UFS_UFS_DBG_RD_DESC_RAM, 128,
+   "UFS_UFS_DBG_RD_DESC_RAM ");
+   ufs_qcom_dump_regs(hba, UFS_UFS_DBG_RD_PRDT_RAM, 64,
+   "UFS_UFS_DBG_RD_PRDT_RAM ");
+
+   ufshcd_writel(hba, (reg & ~UFS_BIT(17)), REG_UFS_CFG1);
+
+   ufs_qcom_dump_regs(hba, UFS_DBG_RD_REG_UAWM, 4,
+   "UFS_DBG_RD_REG_UAWM ");
+   ufs_qcom_dump_regs(hba, UFS_DBG_RD_REG_UARM, 4,
+   "UFS_DBG_RD_REG_UARM ");
+   ufs_qcom_dump_regs(hba, UFS_DBG_RD_REG_TXUC, 48,
+   "UFS_DBG_RD_REG_TXUC ");
+   ufs_qcom_dump_regs(hba, UFS_DBG_RD_REG_RXUC, 27,
+   "UFS_DBG_RD_REG_RXUC ");
+   ufs_qcom_dump_regs(hba, UFS_DBG_RD_REG_DFC, 19,
+   "UFS_DBG_RD_REG_DFC ");
+   ufs_qcom_dump_regs(hba, UFS_DBG_RD_REG_TRLUT, 34,
+   "UFS_DBG_RD_REG_TRLUT ");
+   ufs_qcom_dump_regs(hba, UFS_DBG_RD_REG_TMRLUT, 9,
+   "UFS_DBG_RD_REG_TMRLUT ");
+}
+
+static void ufs_qcom_dump_dbg_regs(struct ufs_hba *hba)
+{
+   ufs_qcom_dump_regs(hba, REG_UFS_SYS1CLK_1US, 5,
+   "REG_UFS_SYS1CLK_1US ");
+
+   ufs_qcom_print_hw_debug_reg_all(hba);
+}
+
 /**
  * struct ufs_hba_qcom_vops - UFS QCOM specific variant operations
  *
@@ -1000,5 +1052,6 @@ static const struct ufs_hba_variant_ops ufs_hba_qcom_vops 
= {
.pwr_change_notify  = ufs_qcom_pwr_change_notify,
.suspend= ufs_qcom_suspend,
.resume = ufs_qcom_resume,
+   .dbg_register_dump  = ufs_qcom_dump_dbg_regs,
 };
 EXPORT_SYMBOL(ufs_hba_qcom_vops);
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index 7697cc6..3ae0b3f 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -45,6 +45,9 @@
 #include "unipro.h"
 #include "ufs-debugfs.h"
 
+#define CREATE_TRACE_POINTS
+#include 
+
 #ifdef CONFIG_DEBUG_FS
 
 static void ufshcd_update_error_stats(struct ufs_hba *hba, int type)
@@ -145,6 +148,8 @@ static inline ufshcd_update_error_stats(struct ufs_hba 
*hba, int type)
_ret = ufshcd_disable_vreg(_dev, _vreg);\
_ret;   \
})
+#define ufshcd_hex_dump(prefix_str, buf, len) \
+print_hex_dump(KERN_ERR, prefix_str, DUMP_PREFIX_OFFSET, 16, 4, buf, len, 
false)
 
 static u32 ufs_query_desc_max_size[] = {
QUERY_DESC_DEVICE_MAX_SIZE,
@@ -272,6 +277,151 @@ static inline void ufshcd_disable_irq(struct ufs_hba *hba)
}
 }
 
+#ifdef CONFIG_TRACEPOINTS
+static void ufshcd_add_command_trace(struct ufs_hba *hba,
+   unsigned int tag, const char *str)
+{
+   sector_t lba = -1;
+   u8 opcode = 0;
+   u32 intr, doorbell;
+   

[PATCH v4 4/4] scsi: ufs: inject errors to verify error handling

2015-03-02 Thread Gilad Broner
From: Sujit Reddy Thumma 

Use fault-injection framework to simulate error conditions
in the controller and verify error handling mechanisms
implemented in UFS host controller driver.

This is used only during development and hence
guarded by CONFIG_UFS_FAULT_INJECTION debug config option.

Signed-off-by: Sujit Reddy Thumma 
---
 drivers/scsi/ufs/ufs-debugfs.c | 140 +
 drivers/scsi/ufs/ufs-debugfs.h |   4 ++
 drivers/scsi/ufs/ufshcd.c  |   2 +
 drivers/scsi/ufs/ufshcd.h  |   5 ++
 lib/Kconfig.debug  |  14 +
 5 files changed, 165 insertions(+)

diff --git a/drivers/scsi/ufs/ufs-debugfs.c b/drivers/scsi/ufs/ufs-debugfs.c
index 27ab053..bac72d0 100644
--- a/drivers/scsi/ufs/ufs-debugfs.c
+++ b/drivers/scsi/ufs/ufs-debugfs.c
@@ -17,6 +17,7 @@
  *
  */
 
+#include 
 #include "ufs-debugfs.h"
 #include "unipro.h"
 
@@ -41,6 +42,143 @@ struct desc_field_offset {
} while (0)
 #define DOORBELL_CLR_TOUT_US   (1000 * 1000) /* 1 sec */
 
+#ifdef CONFIG_UFS_FAULT_INJECTION
+
+#define INJECT_COMMAND_HANG (0x0)
+
+static DECLARE_FAULT_ATTR(fail_default_attr);
+static char *fail_request;
+module_param(fail_request, charp, 0);
+
+static bool inject_fatal_err_tr(struct ufs_hba *hba, u8 ocs_err)
+{
+   int tag;
+
+   tag = find_first_bit(>outstanding_reqs, hba->nutrs);
+   if (tag == hba->nutrs)
+   return 0;
+
+   ufshcd_writel(hba, ~(1 << tag), REG_UTP_TRANSFER_REQ_LIST_CLEAR);
+   (>lrb[tag])->utr_descriptor_ptr->header.dword_2 =
+   cpu_to_be32(ocs_err);
+
+   /* fatal error injected */
+   return 1;
+}
+
+static bool inject_fatal_err_tm(struct ufs_hba *hba, u8 ocs_err)
+{
+   int tag;
+
+   tag = find_first_bit(>outstanding_tasks, hba->nutmrs);
+   if (tag == hba->nutmrs)
+   return 0;
+
+   ufshcd_writel(hba, ~(1 << tag), REG_UTP_TASK_REQ_LIST_CLEAR);
+   (>utmrdl_base_addr[tag])->header.dword_2 =
+   cpu_to_be32(ocs_err);
+
+   /* fatal error injected */
+   return 1;
+}
+
+static bool inject_cmd_hang_tr(struct ufs_hba *hba)
+{
+   int tag;
+
+   tag = find_first_bit(>outstanding_reqs, hba->nutrs);
+   if (tag == hba->nutrs)
+   return 0;
+
+   __clear_bit(tag, >outstanding_reqs);
+   hba->lrb[tag].cmd = NULL;
+   __clear_bit(tag, >lrb_in_use);
+
+   /* command hang injected */
+   return 1;
+}
+
+static int inject_cmd_hang_tm(struct ufs_hba *hba)
+{
+   int tag;
+
+   tag = find_first_bit(>outstanding_tasks, hba->nutmrs);
+   if (tag == hba->nutmrs)
+   return 0;
+
+   __clear_bit(tag, >outstanding_tasks);
+   __clear_bit(tag, >tm_slots_in_use);
+
+   /* command hang injected */
+   return 1;
+}
+
+void ufsdbg_fail_request(struct ufs_hba *hba, u32 *intr_status)
+{
+   u8 ocs_err;
+   static const u32 errors[] = {
+   CONTROLLER_FATAL_ERROR,
+   SYSTEM_BUS_FATAL_ERROR,
+   INJECT_COMMAND_HANG,
+   };
+
+   if (!should_fail(>debugfs_files.fail_attr, 1))
+   goto out;
+
+   *intr_status = errors[prandom_u32() % ARRAY_SIZE(errors)];
+   dev_info(hba->dev, "%s: fault-inject error: 0x%x\n",
+   __func__, *intr_status);
+
+   switch (*intr_status) {
+   case CONTROLLER_FATAL_ERROR: /* fall through */
+   ocs_err = OCS_FATAL_ERROR;
+   goto set_ocs;
+   case SYSTEM_BUS_FATAL_ERROR:
+   ocs_err = OCS_INVALID_CMD_TABLE_ATTR;
+set_ocs:
+   if (!inject_fatal_err_tr(hba, ocs_err))
+   if (!inject_fatal_err_tm(hba, ocs_err))
+   *intr_status = 0;
+   break;
+   case INJECT_COMMAND_HANG:
+   if (!inject_cmd_hang_tr(hba))
+   inject_cmd_hang_tm(hba);
+   break;
+   default:
+   BUG();
+   /* some configurations ignore panics caused by BUG() */
+   break;
+   }
+out:
+   return;
+}
+
+static void ufsdbg_setup_fault_injection(struct ufs_hba *hba)
+{
+   hba->debugfs_files.fail_attr = fail_default_attr;
+
+   if (fail_request)
+   setup_fault_attr(>debugfs_files.fail_attr, fail_request);
+
+   /* suppress dump stack everytime failure is injected */
+   hba->debugfs_files.fail_attr.verbose = 0;
+
+   if (IS_ERR(fault_create_debugfs_attr("inject_fault",
+   hba->debugfs_files.debugfs_root,
+   >debugfs_files.fail_attr)))
+   dev_err(hba->dev, "%s: failed to create debugfs entry\n",
+   __func__);
+}
+#else
+void ufsdbg_fail_request(struct ufs_hba *hba, u32 *intr_status)
+{
+}
+
+static void ufsdbg_setup_fault_injection(struct ufs_hba *hba)
+{
+}
+#endif /* 

[PATCH v4 1/4] scsi: ufs: add ioctl interface for query request

2015-03-02 Thread Gilad Broner
From: Dolev Raviv 

This patch exposes the ioctl interface for UFS driver via SCSI device
ioctl interface. As of now UFS driver would provide the ioctl for query
interface to connected UFS device.

Signed-off-by: Dolev Raviv 
Signed-off-by: Noa Rubens 
Signed-off-by: Raviv Shvili 
Signed-off-by: Yaniv Gardi 
---
 drivers/scsi/ufs/ufs.h|  53 +++---
 drivers/scsi/ufs/ufshcd.c | 225 +-
 include/uapi/scsi/Kbuild  |   1 +
 include/uapi/scsi/ufs/Kbuild  |   3 +
 include/uapi/scsi/ufs/ioctl.h |  57 +++
 include/uapi/scsi/ufs/ufs.h   |  66 +
 6 files changed, 361 insertions(+), 44 deletions(-)
 create mode 100644 include/uapi/scsi/ufs/Kbuild
 create mode 100644 include/uapi/scsi/ufs/ioctl.h
 create mode 100644 include/uapi/scsi/ufs/ufs.h

diff --git a/drivers/scsi/ufs/ufs.h b/drivers/scsi/ufs/ufs.h
index 42c459a..1f023c4 100644
--- a/drivers/scsi/ufs/ufs.h
+++ b/drivers/scsi/ufs/ufs.h
@@ -38,6 +38,7 @@
 
 #include 
 #include 
+#include 
 
 #define MAX_CDB_SIZE   16
 #define GENERAL_UPIU_REQUEST_SIZE 32
@@ -71,6 +72,16 @@ enum {
UFS_UPIU_RPMB_WLUN  = 0xC4,
 };
 
+/**
+ * ufs_is_valid_unit_desc_lun - checks if the given LUN has a unit descriptor
+ * @lun: LU number to check
+ * @return: true if the lun has a matching unit descriptor, false otherwise
+ */
+static inline bool ufs_is_valid_unit_desc_lun(u8 lun)
+{
+   return (lun == UFS_UPIU_RPMB_WLUN || (lun < UFS_UPIU_MAX_GENERAL_LUN));
+}
+
 /*
  * UFS Protocol Information Unit related definitions
  */
@@ -126,35 +137,6 @@ enum {
UPIU_QUERY_FUNC_STANDARD_WRITE_REQUEST  = 0x81,
 };
 
-/* Flag idn for Query Requests*/
-enum flag_idn {
-   QUERY_FLAG_IDN_FDEVICEINIT  = 0x01,
-   QUERY_FLAG_IDN_PWR_ON_WPE   = 0x03,
-   QUERY_FLAG_IDN_BKOPS_EN = 0x04,
-};
-
-/* Attribute idn for Query requests */
-enum attr_idn {
-   QUERY_ATTR_IDN_ACTIVE_ICC_LVL   = 0x03,
-   QUERY_ATTR_IDN_BKOPS_STATUS = 0x05,
-   QUERY_ATTR_IDN_EE_CONTROL   = 0x0D,
-   QUERY_ATTR_IDN_EE_STATUS= 0x0E,
-};
-
-/* Descriptor idn for Query requests */
-enum desc_idn {
-   QUERY_DESC_IDN_DEVICE   = 0x0,
-   QUERY_DESC_IDN_CONFIGURAION = 0x1,
-   QUERY_DESC_IDN_UNIT = 0x2,
-   QUERY_DESC_IDN_RFU_0= 0x3,
-   QUERY_DESC_IDN_INTERCONNECT = 0x4,
-   QUERY_DESC_IDN_STRING   = 0x5,
-   QUERY_DESC_IDN_RFU_1= 0x6,
-   QUERY_DESC_IDN_GEOMETRY = 0x7,
-   QUERY_DESC_IDN_POWER= 0x8,
-   QUERY_DESC_IDN_MAX,
-};
-
 enum desc_header_offset {
QUERY_DESC_LENGTH_OFFSET= 0x00,
QUERY_DESC_DESC_TYPE_OFFSET = 0x01,
@@ -247,19 +229,6 @@ enum bkops_status {
BKOPS_STATUS_MAX = BKOPS_STATUS_CRITICAL,
 };
 
-/* UTP QUERY Transaction Specific Fields OpCode */
-enum query_opcode {
-   UPIU_QUERY_OPCODE_NOP   = 0x0,
-   UPIU_QUERY_OPCODE_READ_DESC = 0x1,
-   UPIU_QUERY_OPCODE_WRITE_DESC= 0x2,
-   UPIU_QUERY_OPCODE_READ_ATTR = 0x3,
-   UPIU_QUERY_OPCODE_WRITE_ATTR= 0x4,
-   UPIU_QUERY_OPCODE_READ_FLAG = 0x5,
-   UPIU_QUERY_OPCODE_SET_FLAG  = 0x6,
-   UPIU_QUERY_OPCODE_CLEAR_FLAG= 0x7,
-   UPIU_QUERY_OPCODE_TOGGLE_FLAG   = 0x8,
-};
-
 /* Query response result code */
 enum {
QUERY_RESULT_SUCCESS= 0x00,
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index 5d60a86..cb357f8 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -3,7 +3,7 @@
  *
  * This code is based on drivers/scsi/ufs/ufshcd.c
  * Copyright (C) 2011-2013 Samsung India Software Operations
- * Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-2015, The Linux Foundation. All rights reserved.
  *
  * Authors:
  * Santosh Yaraganavi 
@@ -39,6 +39,7 @@
 
 #include 
 #include 
+#include 
 
 #include "ufshcd.h"
 #include "unipro.h"
@@ -74,6 +75,9 @@
 /* Interrupt aggregation default timeout, unit: 40us */
 #define INT_AGGR_DEF_TO0x02
 
+/* IOCTL opcode for command - ufs set device read only */
+#define UFS_IOCTL_BLKROSET  BLKROSET
+
 #define ufshcd_toggle_vreg(_dev, _vreg, _on)   \
({  \
int _ret;   \
@@ -1882,7 +1886,7 @@ static inline int ufshcd_read_unit_desc_param(struct 
ufs_hba *hba,
 * Unit descriptors are only available for general purpose LUs (LUN id
 * from 0 to 7) and RPMB Well known LU.
 */
-   if (lun != UFS_UPIU_RPMB_WLUN && (lun >= UFS_UPIU_MAX_GENERAL_LUN))
+   if (!ufs_is_valid_unit_desc_lun(lun))
return -EOPNOTSUPP;
 
return ufshcd_read_desc_param(hba, QUERY_DESC_IDN_UNIT, lun,
@@ -4201,6 +4205,222 @@ static void 

[PATCH v4 2/4] scsi: ufs: add debugfs for ufs

2015-03-02 Thread Gilad Broner
From: Lee Susman 

Adding debugfs capability for ufshcd.

debugfs attributes introduced in this patch:
 - View driver/controller runtime data
 - Command tag statistics for performance analisis
 - Dump device descriptor info
 - Track recoverable errors statistics during runtime
 - Change UFS power mode during runtime
 entry a string in the format 'GGLLMM' where:
 G - selected gear
 L - number of lanes
 M - power mode
 (1=fast mode, 2=slow mode, 4=fast-auto mode,
  5=slow-auto mode)
 First letter is for RX, second is for TX.
 - Get/set DME attributes

Signed-off-by: Lee Susman 
Signed-off-by: Dolev Raviv 
Signed-off-by: Yaniv Gardi 
Signed-off-by: Raviv Shvili 
Signed-off-by: Gilad Broner 
---
 drivers/scsi/ufs/Makefile  |   1 +
 drivers/scsi/ufs/ufs-debugfs.c | 902 +
 drivers/scsi/ufs/ufs-debugfs.h |  38 ++
 drivers/scsi/ufs/ufshcd.c  | 229 ++-
 drivers/scsi/ufs/ufshcd.h  |  65 +++
 drivers/scsi/ufs/ufshci.h  |   2 +
 6 files changed, 1225 insertions(+), 12 deletions(-)
 create mode 100644 drivers/scsi/ufs/ufs-debugfs.c
 create mode 100644 drivers/scsi/ufs/ufs-debugfs.h

diff --git a/drivers/scsi/ufs/Makefile b/drivers/scsi/ufs/Makefile
index 8303bcc..0692314 100644
--- a/drivers/scsi/ufs/Makefile
+++ b/drivers/scsi/ufs/Makefile
@@ -3,3 +3,4 @@ obj-$(CONFIG_SCSI_UFS_QCOM) += ufs-qcom.o
 obj-$(CONFIG_SCSI_UFSHCD) += ufshcd.o
 obj-$(CONFIG_SCSI_UFSHCD_PCI) += ufshcd-pci.o
 obj-$(CONFIG_SCSI_UFSHCD_PLATFORM) += ufshcd-pltfrm.o
+obj-$(CONFIG_DEBUG_FS) += ufs-debugfs.o
diff --git a/drivers/scsi/ufs/ufs-debugfs.c b/drivers/scsi/ufs/ufs-debugfs.c
new file mode 100644
index 000..27ab053
--- /dev/null
+++ b/drivers/scsi/ufs/ufs-debugfs.c
@@ -0,0 +1,902 @@
+/* Copyright (c) 2013-2015, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * UFS debugfs - add debugfs interface to the ufshcd.
+ * This is currently used for statistics collection and exporting from the
+ * UFS driver.
+ * This infrastructure can be used for debugging or direct tweaking
+ * of the driver from userspace.
+ *
+ */
+
+#include "ufs-debugfs.h"
+#include "unipro.h"
+
+enum field_width {
+   BYTE= 1,
+   WORD= 2,
+};
+
+struct desc_field_offset {
+   char *name;
+   int offset;
+   enum field_width width_byte;
+};
+
+#define UFS_ERR_STATS_PRINT(file, error_index, string, error_seen) \
+   do {\
+   if (err_stats[error_index]) {   \
+   seq_printf(file, string,\
+   err_stats[error_index]);\
+   error_seen = true;  \
+   }   \
+   } while (0)
+#define DOORBELL_CLR_TOUT_US   (1000 * 1000) /* 1 sec */
+
+#define BUFF_LINE_CAPACITY 16
+#define TAB_CHARS 8
+
+static int ufsdbg_tag_stats_show(struct seq_file *file, void *data)
+{
+   struct ufs_hba *hba = (struct ufs_hba *)file->private;
+   struct ufs_stats *ufs_stats;
+   int i, j;
+   int max_depth;
+   bool is_tag_empty = true;
+   unsigned long flags;
+   char *sep = " | * | ";
+
+   if (!hba)
+   goto exit;
+
+   ufs_stats = >ufs_stats;
+
+   if (!ufs_stats->enabled) {
+   pr_debug("%s: ufs statistics are disabled\n", __func__);
+   seq_puts(file, "ufs statistics are disabled");
+   goto exit;
+   }
+
+   max_depth = hba->nutrs;
+
+   spin_lock_irqsave(hba->host->host_lock, flags);
+   /* Header */
+   seq_printf(file, " Tag Stat\t\t%s Queue Fullness\n", sep);
+   for (i = 0; i < TAB_CHARS * (TS_NUM_STATS + 4); i++) {
+   seq_puts(file, "-");
+   if (i == (TAB_CHARS * 3 - 1))
+   seq_puts(file, sep);
+   }
+   seq_printf(file,
+   "\n #\tnum uses\t%s\t #\tAll\t Read\t Write\t Flush\n",
+   sep);
+
+   /* values */
+   for (i = 0; i < max_depth; i++) {
+   if (ufs_stats->tag_stats[i][0] <= 0 &&
+   ufs_stats->tag_stats[i][1] <= 0 &&
+   ufs_stats->tag_stats[i][2] <= 0 &a

  1   2   >