linux-scsi.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: 서호영 <hy50.seo@samsung.com>
To: "'Asutosh Das \(asd\)'" <asutoshd@codeaurora.org>,
	<linux-scsi@vger.kernel.org>, <alim.akhtar@samsung.com>,
	<avri.altman@wdc.com>, <jejb@linux.ibm.com>,
	<martin.petersen@oracle.com>, <beanhuo@micron.com>,
	<cang@codeaurora.org>, <bvanassche@acm.org>,
	<grant.jung@samsung.com>
Subject: RE: [RFC PATCH v2 3/3] scsi: ufs: add vendor specific write booster To support the fuction of writebooster by vendor. The WB behavior that the vendor wants is slightly different. But we have to support it
Date: Tue, 21 Jul 2020 18:47:45 +0900	[thread overview]
Message-ID: <02dd01d65f43$fc837710$f58a6530$@samsung.com> (raw)
In-Reply-To: <588c1a29-38b9-8c5f-d9c5-899272b9f3a3@codeaurora.org>



> -----Original Message-----
> From: asutoshd=codeaurora.org@mg.codeaurora.org
> [mailto:asutoshd=codeaurora.org@mg.codeaurora.org] On Behalf Of Asutosh
> Das (asd)
> Sent: Tuesday, July 21, 2020 1:55 AM
> To: SEO HOYOUNG; linux-scsi@vger.kernel.org; alim.akhtar@samsung.com;
> avri.altman@wdc.com; jejb@linux.ibm.com; martin.petersen@oracle.com;
> beanhuo@micron.com; cang@codeaurora.org; bvanassche@acm.org;
> grant.jung@samsung.com
> Subject: Re: [RFC PATCH v2 3/3] scsi: ufs: add vendor specific write
> booster To support the fuction of writebooster by vendor. The WB behavior
> that the vendor wants is slightly different. But we have to support it
> 
> On 7/20/2020 3:40 AM, SEO HOYOUNG wrote:
> > Signed-off-by: SEO HOYOUNG <hy50.seo@samsung.com>
> > ---
> >   drivers/scsi/ufs/Makefile     |   1 +
> >   drivers/scsi/ufs/ufs-exynos.c |   6 +
> >   drivers/scsi/ufs/ufs_ctmwb.c  | 279 ++++++++++++++++++++++++++++++++++
> >   drivers/scsi/ufs/ufs_ctmwb.h  |  27 ++++
> >   4 files changed, 313 insertions(+)
> >   create mode 100644 drivers/scsi/ufs/ufs_ctmwb.c
> >   create mode 100644 drivers/scsi/ufs/ufs_ctmwb.h
> >
> > diff --git a/drivers/scsi/ufs/Makefile b/drivers/scsi/ufs/Makefile
> > index 9810963bc049..b1ba36c7d66f 100644
> > --- a/drivers/scsi/ufs/Makefile
> > +++ b/drivers/scsi/ufs/Makefile
> > @@ -5,6 +5,7 @@ obj-$(CONFIG_SCSI_UFS_DWC_TC_PLATFORM) += tc-dwc-g210-
> pltfrm.o ufshcd-dwc.o tc-d
> >   obj-$(CONFIG_SCSI_UFS_CDNS_PLATFORM) += cdns-pltfrm.o
> >   obj-$(CONFIG_SCSI_UFS_QCOM) += ufs-qcom.o
> >   obj-$(CONFIG_SCSI_UFS_EXYNOS) += ufs-exynos.o
> > +obj-$(CONFIG_SCSI_UFS_VENDOR_WB) += ufs_ctmwb.o
> >   obj-$(CONFIG_SCSI_UFSHCD) += ufshcd-core.o
> >   ufshcd-core-y				+= ufshcd.o ufs-sysfs.o
> >   ufshcd-core-$(CONFIG_SCSI_UFS_BSG)	+= ufs_bsg.o
> > diff --git a/drivers/scsi/ufs/ufs-exynos.c
> > b/drivers/scsi/ufs/ufs-exynos.c index 32b61ba77241..f127f5f2bf36
> > 100644
> > --- a/drivers/scsi/ufs/ufs-exynos.c
> > +++ b/drivers/scsi/ufs/ufs-exynos.c
> > @@ -22,6 +22,9 @@
> >
> 
> To me it looks like, you want to have your own flush policy &
> initializations etc, is that understanding correct?
> I don't understand why though. The current implementation is spec
> compliant. If there're benefits that you see in this implementation,
> please highlight those. It'd be interesting to see that.

Yes. I want to own flush policy, initialization.. 
I already know current implementation is spec compliant.
But some vendor want to change flush policy.
So we modify below code.
Additionally when use below code, we can use WB without UFS 3.1 devices
> 
> 
> >   #include "ufs-exynos.h"
> >
> > +#ifdef CONFIG_SCSI_UFS_VENDOR_WB
> > +#include "ufs_ctmwb.h"
> > +#endif
> >   /*
> >    * Exynos's Vendor specific registers for UFSHCI
> >    */
> > @@ -989,6 +992,9 @@ static int exynos_ufs_init(struct ufs_hba *hba)
> >   		goto phy_off;
> >
> >   	ufs->hba = hba;
> > +#ifdef CONFIG_SCSI_UFS_VENDOR_WB
> > +	ufs->hba->wb_ops = ufshcd_ctmwb_init(); #endif
> >   	ufs->opts = ufs->drv_data->opts;
> >   	ufs->rx_sel_idx = PA_MAXDATALANES;
> >   	if (ufs->opts & EXYNOS_UFS_OPT_BROKEN_RX_SEL_IDX) diff --git
> > a/drivers/scsi/ufs/ufs_ctmwb.c b/drivers/scsi/ufs/ufs_ctmwb.c new file
> > mode 100644 index 000000000000..ab39f40721ae
> > --- /dev/null
> > +++ b/drivers/scsi/ufs/ufs_ctmwb.c
> > @@ -0,0 +1,279 @@
> > +#include "ufshcd.h"
> > +#include "ufshci.h"
> > +#include "ufs_ctmwb.h"
> > +
> > +static struct ufshba_ctmwb hba_ctmwb;
> > +
> > +/* Query request retries */
> > +#define QUERY_REQ_RETRIES 3
> > +
> > +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;
> > +}
> > +
> > +static int ufshcd_query_flag_retry(struct ufs_hba *hba,
> > +	enum query_opcode opcode, enum flag_idn idn, bool *flag_res) {
> > +	int ret;
> > +	int retries;
> > +
> > +	for (retries = 0; retries < QUERY_REQ_RETRIES; retries++) {
> > +		ret = ufshcd_query_flag(hba, opcode, idn, flag_res);
> > +		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, opcode %d, idn %d, failed with
> error %d after %d retries\n",
> > +			__func__, (int)opcode, (int)idn, ret, retries);
> > +	return ret;
> > +}
> > +
> > +static int ufshcd_reset_ctmwb(struct ufs_hba *hba, bool force) {
> > +	int err = 0;
> > +
> > +	if (!hba_ctmwb.support_ctmwb)
> > +		return 0;
> > +
> > +	if (ufshcd_is_ctmwb_off(hba_ctmwb)) {
> > +		dev_info(hba->dev, "%s: turbo write already disabled.
> ctmwb_state = %d\n",
> > +			__func__, hba_ctmwb.ufs_ctmwb_state);
> > +		return 0;
> > +	}
> > +
> > +	if (ufshcd_is_ctmwb_err(hba_ctmwb))
> > +		dev_err(hba->dev, "%s: previous turbo write control was
> failed.\n",
> > +			__func__);
> > +
> > +	if (force)
> > +		err = ufshcd_query_flag_retry(hba,
> UPIU_QUERY_OPCODE_CLEAR_FLAG,
> > +				QUERY_FLAG_IDN_WB_EN, NULL);
> > +
> > +	if (err) {
> > +		ufshcd_set_ctmwb_err(hba_ctmwb);
> > +		dev_err(hba->dev, "%s: disable turbo write failed. err
> = %d\n",
> > +			__func__, err);
> > +	} else {
> > +		ufshcd_set_ctmwb_off(hba_ctmwb);
> > +		dev_info(hba->dev, "%s: ufs turbo write disabled \n",
> __func__);
> > +	}
> > +
> > +	return 0;
> > +}
> > +
> > +static int ufshcd_get_ctmwb_buf_status(struct ufs_hba *hba, u32
> > +*status) {
> > +	return ufshcd_query_attr_retry(hba, UPIU_QUERY_OPCODE_READ_ATTR,
> > +			QUERY_ATTR_IDN_AVAIL_WB_BUFF_SIZE, 0, 0, status); }
> > +
> > +static int ufshcd_ctmwb_manual_flush_ctrl(struct ufs_hba *hba, int
> > +en) {
> > +	int err = 0;
> > +
> > +	dev_info(hba->dev, "%s: %sable turbo write manual flush\n",
> > +				__func__, en ? "en" : "dis");
> > +	if (en) {
> > +		err = ufshcd_query_flag_retry(hba,
> UPIU_QUERY_OPCODE_SET_FLAG,
> > +					QUERY_FLAG_IDN_WB_BUFF_FLUSH_EN, NULL);
> > +		if (err)
> > +			dev_err(hba->dev, "%s: enable turbo write failed. err
> = %d\n",
> > +				__func__, err);
> > +	} else {
> > +		err = ufshcd_query_flag_retry(hba,
> UPIU_QUERY_OPCODE_CLEAR_FLAG,
> > +					QUERY_FLAG_IDN_WB_BUFF_FLUSH_EN, NULL);
> > +		if (err)
> > +			dev_err(hba->dev, "%s: disable turbo write failed. err
> = %d\n",
> > +				__func__, err);
> > +	}
> > +
> > +	return err;
> > +}
> > +
> > +static int ufshcd_ctmwb_flush_ctrl(struct ufs_hba *hba) {
> > +	int err = 0;
> > +	u32 curr_status = 0;
> > +
> > +	err = ufshcd_get_ctmwb_buf_status(hba, &curr_status);
> > +
> > +	if (!err && (curr_status <= UFS_WB_MANUAL_FLUSH_THRESHOLD)) {
> > +		dev_info(hba->dev, "%s: enable ctmwb manual flush, buf
> status : %d\n",
> > +				__func__, curr_status);
> > +		scsi_block_requests(hba->host);
> > +		err = ufshcd_ctmwb_manual_flush_ctrl(hba, 1);
> > +		if (!err) {
> > +			mdelay(100);
> > +			err = ufshcd_ctmwb_manual_flush_ctrl(hba, 0);
> > +			if (err)
> > +				dev_err(hba->dev, "%s: disable ctmwb manual
> flush failed. err = %d\n",
> > +						__func__, err);
> > +		} else
> > +			dev_err(hba->dev, "%s: enable ctmwb manual flush
> failed. err = %d\n",
> > +					__func__, err);
> > +		scsi_unblock_requests(hba->host);
> > +	}
> > +	return err;
> > +}
> > +
> > +static int ufshcd_ctmwb_ctrl(struct ufs_hba *hba, bool enable) {
> > +	int err;
> > +#if 0
> Did you miss removing these #if 0?
I will modify this code.
> 
> > +	if (!hba->support_ctmwb)
> > +		return;
> > +
> > +	if (hba->pm_op_in_progress) {
> > +		dev_err(hba->dev, "%s: ctmwb ctrl during pm operation is not
> allowed.\n",
> > +			__func__);
> > +		return;
> > +	}
> > +
> > +	if (hba->ufshcd_state != UFSHCD_STATE_OPERATIONAL) {
> > +		dev_err(hba->dev, "%s: ufs host is not available.\n",
> > +			__func__);
> > +		return;
> > +	}
> > +	if (ufshcd_is_ctmwb_err(hba_ctmwb))
> > +		dev_err(hba->dev, "%s: previous turbo write control was
> failed.\n",
> > +			__func__);
> > +#endif
> > +	if (enable) {
> > +		if (ufshcd_is_ctmwb_on(hba_ctmwb)) {
> > +			dev_err(hba->dev, "%s: turbo write already enabled.
> ctmwb_state = %d\n",
> > +				__func__, hba_ctmwb.ufs_ctmwb_state);
> > +			return 0;
> > +		}
> > +		pm_runtime_get_sync(hba->dev);
> > +		err = ufshcd_query_flag_retry(hba,
> UPIU_QUERY_OPCODE_SET_FLAG,
> > +					QUERY_FLAG_IDN_WB_EN, NULL);
> > +		if (err) {
> > +			ufshcd_set_ctmwb_err(hba_ctmwb);
> > +			dev_err(hba->dev, "%s: enable turbo write failed. err
> = %d\n",
> > +				__func__, err);
> > +		} else {
> > +			ufshcd_set_ctmwb_on(hba_ctmwb);
> > +			dev_info(hba->dev, "%s: ufs turbo write enabled \n",
> __func__);
> > +		}
> > +	} else {
> > +		if (ufshcd_is_ctmwb_off(hba_ctmwb)) {
> > +			dev_err(hba->dev, "%s: turbo write already disabled.
> ctmwb_state = %d\n",
> > +				__func__, hba_ctmwb.ufs_ctmwb_state);
> > +			return 0;
> > +		}
> > +		pm_runtime_get_sync(hba->dev);
> > +		err = ufshcd_query_flag_retry(hba,
> UPIU_QUERY_OPCODE_CLEAR_FLAG,
> > +					QUERY_FLAG_IDN_WB_EN, NULL);
> > +		if (err) {
> > +			ufshcd_set_ctmwb_err(hba_ctmwb);
> > +			dev_err(hba->dev, "%s: disable turbo write failed. err
> = %d\n",
> > +				__func__, err);
> > +		} else {
> > +			ufshcd_set_ctmwb_off(hba_ctmwb);
> > +			dev_info(hba->dev, "%s: ufs turbo write disabled \n",
> __func__);
> What is 'turbo write'?
I wrote it wrong. I will collect it.

> > +		}
> > +	}
> > +
> > +	pm_runtime_put_sync(hba->dev);
> > +
> > +	return 0;
> > +}
> > +
> > +/**
> > + * ufshcd_get_ctmwbbuf_unit - get ctmwb buffer alloc units
> > + * @sdev: pointer to SCSI device
> > + *
> > + * Read dLUNumTurboWriteBufferAllocUnits in UNIT Descriptor
> > + * to check if LU supports turbo write feature  */ static int
> > +ufshcd_get_ctmwbbuf_unit(struct ufs_hba *hba) {
> > +	struct scsi_device *sdev = hba->sdev_ufs_device;
> > +	struct ufshba_ctmwb *hba_ctmwb = (struct ufshba_ctmwb *)hba->wb_ops;
> > +	int ret = 0;
> > +
> > +	u32 dLUNumTurboWriteBufferAllocUnits = 0;
> > +	u8 desc_buf[4];
> > +
> > +	if (!hba_ctmwb->support_ctmwb)
> > +		return 0;
> > +
> > +	ret = ufshcd_read_unit_desc_param(hba,
> > +			ufshcd_scsi_to_upiu_lun(sdev->lun),
> > +			UNIT_DESC_PARAM_WB_BUF_ALLOC_UNITS,
> > +			desc_buf,
> > +			sizeof(dLUNumTurboWriteBufferAllocUnits));
> > +
> > +	/* Some WLUN doesn't support unit descriptor */
> > +	if ((ret == -EOPNOTSUPP) || scsi_is_wlun(sdev->lun)){
> > +		hba_ctmwb->support_ctmwb_lu = false;
> > +		dev_info(hba->dev,"%s: do not support WB\n", __func__);
> > +		return 0;
> > +	}
> > +
> > +	dLUNumTurboWriteBufferAllocUnits = ((desc_buf[0] << 24)|
> > +			(desc_buf[1] << 16) |
> > +			(desc_buf[2] << 8) |
> > +			desc_buf[3]);
> > +
> > +	if (dLUNumTurboWriteBufferAllocUnits) {
> > +		hba_ctmwb->support_ctmwb_lu = true;
> > +		dev_info(hba->dev, "%s: LU %d supports ctmwb, ctmwbbuf unit :
> 0x%x\n",
> > +				__func__, (int)sdev->lun,
> dLUNumTurboWriteBufferAllocUnits);
> > +	} else
> > +		hba_ctmwb->support_ctmwb_lu = false;
> > +
> > +	return 0;
> > +}
> > +
> > +static inline int ufshcd_ctmwb_toggle_flush(struct ufs_hba *hba, enum
> > +ufs_pm_op pm_op) {
> > +	ufshcd_ctmwb_flush_ctrl(hba);
> > +
> > +	if (ufshcd_is_system_pm(pm_op))
> > +		ufshcd_reset_ctmwb(hba, true);
> > +
> > +	return 0;
> > +}
> > +
> > +static struct ufs_wb_ops exynos_ctmwb_ops = {
> > +	.wb_toggle_flush_vendor = ufshcd_ctmwb_toggle_flush,
> > +	.wb_alloc_units_vendor = ufshcd_get_ctmwbbuf_unit,
> > +	.wb_ctrl_vendor = ufshcd_ctmwb_ctrl,
> > +	.wb_reset_vendor = ufshcd_reset_ctmwb, };
> > +
> > +struct ufs_wb_ops *ufshcd_ctmwb_init(void) {
> > +	hba_ctmwb.support_ctmwb = 1;
> > +
> > +	return &exynos_ctmwb_ops;
> > +}
> > +EXPORT_SYMBOL_GPL(ufshcd_ctmwb_init);
> > +
> > diff --git a/drivers/scsi/ufs/ufs_ctmwb.h
> > b/drivers/scsi/ufs/ufs_ctmwb.h new file mode 100644 index
> > 000000000000..073e21a4900b
> > --- /dev/null
> > +++ b/drivers/scsi/ufs/ufs_ctmwb.h
> > @@ -0,0 +1,27 @@
> > +#ifndef _UFS_CTMWB_H_
> > +#define _UFS_CTMWB_H_
> > +
> > +enum ufs_ctmwb_state {
> > +       UFS_WB_OFF_STATE	= 0,    /* turbo write disabled state */
> > +       UFS_WB_ON_STATE	= 1,            /* turbo write enabled state */
> > +       UFS_WB_ERR_STATE	= 2,            /* turbo write error state */
> > +};
> > +
> > +#define ufshcd_is_ctmwb_off(hba) ((hba).ufs_ctmwb_state ==
> > +UFS_WB_OFF_STATE) #define ufshcd_is_ctmwb_on(hba)
> > +((hba).ufs_ctmwb_state == UFS_WB_ON_STATE) #define
> > +ufshcd_is_ctmwb_err(hba) ((hba).ufs_ctmwb_state == UFS_WB_ERR_STATE)
> > +#define ufshcd_set_ctmwb_off(hba) ((hba).ufs_ctmwb_state =
> > +UFS_WB_OFF_STATE) #define ufshcd_set_ctmwb_on(hba)
> > +((hba).ufs_ctmwb_state = UFS_WB_ON_STATE) #define
> > +ufshcd_set_ctmwb_err(hba) ((hba).ufs_ctmwb_state = UFS_WB_ERR_STATE)
> > +
> > +#define UFS_WB_MANUAL_FLUSH_THRESHOLD	5
> > +
> > +struct ufshba_ctmwb {
> > +	enum ufs_ctmwb_state ufs_ctmwb_state;
> > +	bool support_ctmwb;
> > +
> > +	bool support_ctmwb_lu;
> > +};
> > +
> > +struct ufs_wb_ops *ufshcd_ctmwb_init(void); #endif
> >
> 
> -Asutosh
> 
> --
> The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
> Linux Foundation Collaborative Project


  reply	other threads:[~2020-07-21  9:47 UTC|newest]

Thread overview: 13+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
     [not found] <CGME20200720103946epcas2p46e38e8d585d2882d167e5aa548e53217@epcas2p4.samsung.com>
2020-07-20 10:40 ` [RFC PATCH v2 0/3] Support vendor specific operations for WB SEO HOYOUNG
     [not found]   ` <CGME20200720103949epcas2p4a49b245d9cebf0478d42fb6c607fc236@epcas2p4.samsung.com>
2020-07-20 10:40     ` [RFC PATCH v2 1/3] scsi: ufs: modify write booster SEO HOYOUNG
2020-07-20 16:46       ` Asutosh Das (asd)
2020-07-21  9:26         ` 서호영
     [not found]   ` <CGME20200720103950epcas2p16278643a6f62b446b653c834de448543@epcas2p1.samsung.com>
2020-07-20 10:40     ` [RFC PATCH v2 2/3] scsi: ufs: modify function call name When ufs reset and restore, need to disable " SEO HOYOUNG
2020-07-21  6:36       ` Avri Altman
     [not found]   ` <CGME20200720103951epcas2p246072985a70a459f0acb31d339298a47@epcas2p2.samsung.com>
2020-07-20 10:40     ` [RFC PATCH v2 3/3] scsi: ufs: add vendor specific write booster To support the fuction of writebooster by vendor. The WB behavior that the vendor wants is slightly different. But we have to support it SEO HOYOUNG
2020-07-20 16:55       ` Asutosh Das (asd)
2020-07-21  9:47         ` 서호영 [this message]
2020-07-21 16:18           ` Asutosh Das (asd)
2020-07-24  9:42             ` 서호영
2020-07-24 15:57               ` Asutosh Das (asd)
2020-07-21  6:37       ` Avri Altman

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to='02dd01d65f43$fc837710$f58a6530$@samsung.com' \
    --to=hy50.seo@samsung.com \
    --cc=alim.akhtar@samsung.com \
    --cc=asutoshd@codeaurora.org \
    --cc=avri.altman@wdc.com \
    --cc=beanhuo@micron.com \
    --cc=bvanassche@acm.org \
    --cc=cang@codeaurora.org \
    --cc=grant.jung@samsung.com \
    --cc=jejb@linux.ibm.com \
    --cc=linux-scsi@vger.kernel.org \
    --cc=martin.petersen@oracle.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).