[3/3] scsi: ufs: add quirk to support host reset only

Message ID 20210527030901.88403-4-jjmin.jeong@samsung.com
State New
Headers show
Series
  • Untitled series #131394
Related show

Commit Message

정종민 May 27, 2021, 3:09 a.m.
samsung ExynosAuto SoC has two types of host controller interface to
support the virtualization of UFS Device.
One is the physical host(PH) that the same as conventaional UFSHCI,
and the other is the virtual host(VH) that support data transfer function only.

In this structure, the virtual host does support host reset handler only.
This patch calls the host reset handler when abort or device reset handler
has occured in the virtual host.

Change-Id: I3f07e772415a35fe1e7374e02b3c37ef0bf5660d
Signed-off-by: jongmin jeong <jjmin.jeong@samsung.com>
---
 drivers/scsi/ufs/ufshcd.c | 7 +++++++
 drivers/scsi/ufs/ufshcd.h | 6 ++++++
 2 files changed, 13 insertions(+)

Comments

Can Guo May 27, 2021, 6:31 a.m. | #1
On 2021-05-27 11:09, jongmin jeong wrote:
> samsung ExynosAuto SoC has two types of host controller interface to
> support the virtualization of UFS Device.
> One is the physical host(PH) that the same as conventaional UFSHCI,
> and the other is the virtual host(VH) that support data transfer 
> function only.
> 
> In this structure, the virtual host does support host reset handler 
> only.
> This patch calls the host reset handler when abort or device reset 
> handler
> has occured in the virtual host.
> 
> Change-Id: I3f07e772415a35fe1e7374e02b3c37ef0bf5660d
> Signed-off-by: jongmin jeong <jjmin.jeong@samsung.com>
> ---
>  drivers/scsi/ufs/ufshcd.c | 7 +++++++
>  drivers/scsi/ufs/ufshcd.h | 6 ++++++
>  2 files changed, 13 insertions(+)
> 
> diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
> index 4787e40c6a2d..9d1912290f87 100644
> --- a/drivers/scsi/ufs/ufshcd.c
> +++ b/drivers/scsi/ufs/ufshcd.c
> @@ -6826,6 +6826,9 @@ static int ufshcd_eh_device_reset_handler(struct
> scsi_cmnd *cmd)
>  	u8 resp = 0xF, lun;
>  	unsigned long flags;
> 
> +	if (hba->quirks & UFSHCD_QUIRK_BROKEN_RESET_HANDLER)
> +		return ufshcd_eh_host_reset_handler(cmd);
> +
>  	host = cmd->device->host;
>  	hba = shost_priv(host);
> 
> @@ -6972,6 +6975,10 @@ static int ufshcd_abort(struct scsi_cmnd *cmd)
>  	host = cmd->device->host;
>  	hba = shost_priv(host);
>  	tag = cmd->request->tag;
> +
> +	if (hba->quirks & UFSHCD_QUIRK_BROKEN_RESET_HANDLER)
> +		return ufshcd_eh_host_reset_handler(cmd);
> +

Unless you are not using runtime PM. Otherwise, when abort happens
to SSU cmd (sent from pm ops), your change will lead to a live lock,
because ufshcd_eh_host_reset_handler() invokes error handling and
flushes it, error handling calls runtime_pm_get_sync(), which flushes
pm ops, while pm ops is blocked by SSU cmd.

To be on the safe side, you should move these codes after below
check in ufshcd_abort(), right before sending task abort TMRs.

  /*
   * Task abort to the device W-LUN is illegal. When this command
   * will fail, due to spec violation, scsi err handling next step
   * will be to send LU reset which, again, is a spec violation.
   * To avoid these unnecessary/illegal steps, first we clean up
   * the lrb taken by this cmd and mark the lrb as in_use, then
   * queue the eh_work and bail.
   */
   if (lrbp->lun == UFS_UPIU_UFS_DEVICE_WLUN) {
     ...

     goto out;
   }

Thanks,

Can Guo.

>  	lrbp = &hba->lrb[tag];
>  	if (!ufshcd_valid_tag(hba, tag)) {
>  		dev_err(hba->dev,
> diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h
> index 0ab4c296be32..82a9c6889978 100644
> --- a/drivers/scsi/ufs/ufshcd.h
> +++ b/drivers/scsi/ufs/ufshcd.h
> @@ -581,6 +581,12 @@ enum ufshcd_quirks {
>  	 * support interface configuration.
>  	 */
>  	UFSHCD_QUIRK_SKIP_INTERFACE_CONFIGURATION	= 1 << 16,
> +
> +	/*
> +	 * This quirk needs to be enabled if the host controller support
> +	 * host reset handler only.
> +	 */
> +	UFSHCD_QUIRK_BROKEN_RESET_HANDLER		= 1 << 17,
>  };
> 
>  enum ufshcd_caps {
정종민 June 3, 2021, 3:21 a.m. | #2
> > samsung ExynosAuto SoC has two types of host controller interface to

> > support the virtualization of UFS Device.

> > One is the physical host(PH) that the same as conventaional UFSHCI,

> > and the other is the virtual host(VH) that support data transfer

> > function only.

> >

> > In this structure, the virtual host does support host reset handler

> > only.

> > This patch calls the host reset handler when abort or device reset

> > handler has occured in the virtual host.

> 

> One more question, as per the plot in the cover letter, the VH does

> support TMRs.

> Why are you trying to make ufshcd_abort() and

> ufshcd_eh_device_reset_handler()

> no-ops?

> 

> Thanks,

> 

> Can Guo.



Can, 
Thanks for your review.
Yes, you are right about ufshcd_abort.
it would be better to call if it fails abort handling has failed.
I will apply this modification to the next patch.

device reset handler case is a little different. We do not want the virtual
host to do device reset(LUN reset).

According to our virtualization architecture, virtual OSs can share LUNs.
Therefore, we are trying to prevent the reset for LUN in guest OS.

> >

> > Change-Id: I3f07e772415a35fe1e7374e02b3c37ef0bf5660d

> > Signed-off-by: jongmin jeong <jjmin.jeong@samsung.com>

> > ---

> >  drivers/scsi/ufs/ufshcd.c | 7 +++++++  drivers/scsi/ufs/ufshcd.h | 6

> > ++++++

> >  2 files changed, 13 insertions(+)

> >

> > diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c

> > index 4787e40c6a2d..9d1912290f87 100644

> > --- a/drivers/scsi/ufs/ufshcd.c

> > +++ b/drivers/scsi/ufs/ufshcd.c

> > @@ -6826,6 +6826,9 @@ static int ufshcd_eh_device_reset_handler(struct

> > scsi_cmnd *cmd)

> >  	u8 resp = 0xF, lun;

> >  	unsigned long flags;

> >

> > +	if (hba->quirks & UFSHCD_QUIRK_BROKEN_RESET_HANDLER)

> > +		return ufshcd_eh_host_reset_handler(cmd);

> > +

> >  	host = cmd->device->host;

> >  	hba = shost_priv(host);

> >

> > @@ -6972,6 +6975,10 @@ static int ufshcd_abort(struct scsi_cmnd *cmd)

> >  	host = cmd->device->host;

> >  	hba = shost_priv(host);

> >  	tag = cmd->request->tag;

> > +

> > +	if (hba->quirks & UFSHCD_QUIRK_BROKEN_RESET_HANDLER)

> > +		return ufshcd_eh_host_reset_handler(cmd);

> > +

> >  	lrbp = &hba->lrb[tag];

> >  	if (!ufshcd_valid_tag(hba, tag)) {

> >  		dev_err(hba->dev,

> > diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h

> > index 0ab4c296be32..82a9c6889978 100644

> > --- a/drivers/scsi/ufs/ufshcd.h

> > +++ b/drivers/scsi/ufs/ufshcd.h

> > @@ -581,6 +581,12 @@ enum ufshcd_quirks {

> >  	 * support interface configuration.

> >  	 */

> >  	UFSHCD_QUIRK_SKIP_INTERFACE_CONFIGURATION	= 1 << 16,

> > +

> > +	/*

> > +	 * This quirk needs to be enabled if the host controller support

> > +	 * host reset handler only.

> > +	 */

> > +	UFSHCD_QUIRK_BROKEN_RESET_HANDLER		= 1 << 17,

> >  };

> >

> >  enum ufshcd_caps {



Best Regards,
Jongmin jeong

Patch

diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index 4787e40c6a2d..9d1912290f87 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -6826,6 +6826,9 @@  static int ufshcd_eh_device_reset_handler(struct scsi_cmnd *cmd)
 	u8 resp = 0xF, lun;
 	unsigned long flags;
 
+	if (hba->quirks & UFSHCD_QUIRK_BROKEN_RESET_HANDLER)
+		return ufshcd_eh_host_reset_handler(cmd);
+
 	host = cmd->device->host;
 	hba = shost_priv(host);
 
@@ -6972,6 +6975,10 @@  static int ufshcd_abort(struct scsi_cmnd *cmd)
 	host = cmd->device->host;
 	hba = shost_priv(host);
 	tag = cmd->request->tag;
+
+	if (hba->quirks & UFSHCD_QUIRK_BROKEN_RESET_HANDLER)
+		return ufshcd_eh_host_reset_handler(cmd);
+
 	lrbp = &hba->lrb[tag];
 	if (!ufshcd_valid_tag(hba, tag)) {
 		dev_err(hba->dev,
diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h
index 0ab4c296be32..82a9c6889978 100644
--- a/drivers/scsi/ufs/ufshcd.h
+++ b/drivers/scsi/ufs/ufshcd.h
@@ -581,6 +581,12 @@  enum ufshcd_quirks {
 	 * support interface configuration.
 	 */
 	UFSHCD_QUIRK_SKIP_INTERFACE_CONFIGURATION	= 1 << 16,
+
+	/*
+	 * This quirk needs to be enabled if the host controller support
+	 * host reset handler only.
+	 */
+	UFSHCD_QUIRK_BROKEN_RESET_HANDLER		= 1 << 17,
 };
 
 enum ufshcd_caps {