diff mbox series

[v3,4/7] scsi: ufs: Allow ufshcd_issue_tm_cmd accept raw task upius

Message ID 1535970796-25582-5-git-send-email-avri.altman@wdc.com (mailing list archive)
State Superseded
Headers show
Series scsi: ufs bsg endpoint | expand

Commit Message

Avri Altman Sept. 3, 2018, 10:33 a.m. UTC
Do that in order to re-use its code if the task request and response
UPIUs are given externally.

Signed-off-by: Avri Altman <avri.altman@wdc.com>
---
 drivers/scsi/ufs/ufshcd.c | 35 ++++++++++++++++++++++++++---------
 1 file changed, 26 insertions(+), 9 deletions(-)

Comments

Christoph Hellwig Sept. 4, 2018, 7:15 p.m. UTC | #1
On Mon, Sep 03, 2018 at 01:33:13PM +0300, Avri Altman wrote:
> Do that in order to re-use its code if the task request and response
> UPIUs are given externally.
> 
> Signed-off-by: Avri Altman <avri.altman@wdc.com>
> ---
>  drivers/scsi/ufs/ufshcd.c | 35 ++++++++++++++++++++++++++---------
>  1 file changed, 26 insertions(+), 9 deletions(-)
> 
> diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
> index d18832a..15be103 100644
> --- a/drivers/scsi/ufs/ufshcd.c
> +++ b/drivers/scsi/ufs/ufshcd.c
> @@ -5599,6 +5599,7 @@ static int ufshcd_clear_tm_cmd(struct ufs_hba *hba, int tag)
>  }
>  
>  static void ufshcd_fill_tm_req(struct utp_task_req_desc *task_req_descp,
> +			       struct utp_upiu_task_req *raw_task_req_upiup,
>  			       int lun_id, int task_id, u8 tm_function,
>  			       int task_tag)
>  {
> @@ -5609,6 +5610,13 @@ static void ufshcd_fill_tm_req(struct utp_task_req_desc *task_req_descp,
>  	task_req_descp->header.dword_2 =
>  			cpu_to_le32(OCS_INVALID_COMMAND_STATUS);
>  
> +	if (raw_task_req_upiup) {
> +		raw_task_req_upiup->header.dword_0 |= cpu_to_be32(task_tag);
> +		memcpy(task_req_descp->task_req_upiu, raw_task_req_upiup,
> +		       GENERAL_UPIU_REQUEST_SIZE);
> +		return;
> +	}

The only thing actually shared here is initializing two fields.  Why
can't we always pass in the a raw

> +static int ufshcd_issue_tm_cmd(struct ufs_hba *hba,
> +			       struct utp_upiu_task_req *raw_task_req_upiup,
> +			       struct utp_upiu_task_req *raw_task_rsp_upiup,
> +			       int lun_id, int task_id, u8 tm_function,
> +			       u8 *tm_response)
>  {

And the architecture here seems similar odd.  I think someone needs
to untangle how the data structures are used in this part of the code.

E.g. aways prepare a raw structure in the caller (possibly on stack)
and pass it into ufshcd_issue_tm_cmd, which copies it into the
DMAable region.
Avri Altman Sept. 5, 2018, 8:21 a.m. UTC | #2
> > ---
> >  drivers/scsi/ufs/ufshcd.c | 35 ++++++++++++++++++++++++++---------
> >  1 file changed, 26 insertions(+), 9 deletions(-)
> >
> > diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
> > index d18832a..15be103 100644
> > --- a/drivers/scsi/ufs/ufshcd.c
> > +++ b/drivers/scsi/ufs/ufshcd.c
> > @@ -5599,6 +5599,7 @@ static int ufshcd_clear_tm_cmd(struct ufs_hba
> *hba, int tag)
> >  }
> >
> >  static void ufshcd_fill_tm_req(struct utp_task_req_desc *task_req_descp,
> > +			       struct utp_upiu_task_req *raw_task_req_upiup,
> >  			       int lun_id, int task_id, u8 tm_function,
> >  			       int task_tag)
> >  {
> > @@ -5609,6 +5610,13 @@ static void ufshcd_fill_tm_req(struct
> utp_task_req_desc *task_req_descp,
> >  	task_req_descp->header.dword_2 =
> >  			cpu_to_le32(OCS_INVALID_COMMAND_STATUS);
> >
> > +	if (raw_task_req_upiup) {
> > +		raw_task_req_upiup->header.dword_0 |=
> cpu_to_be32(task_tag);
> > +		memcpy(task_req_descp->task_req_upiu,
> raw_task_req_upiup,
> > +		       GENERAL_UPIU_REQUEST_SIZE);
> > +		return;
> > +	}
> 
> The only thing actually shared here is initializing two fields.  Why
> can't we always pass in the a raw
See below
 
> 
> > +static int ufshcd_issue_tm_cmd(struct ufs_hba *hba,
> > +			       struct utp_upiu_task_req *raw_task_req_upiup,
> > +			       struct utp_upiu_task_req *raw_task_rsp_upiup,
> > +			       int lun_id, int task_id, u8 tm_function,
> > +			       u8 *tm_response)
> >  {
> 
> And the architecture here seems similar odd.  I think someone needs
> to untangle how the data structures are used in this part of the code.
> 
> E.g. aways prepare a raw structure in the caller (possibly on stack)
> and pass it into ufshcd_issue_tm_cmd, which copies it into the
> DMAable region.
Task management is sent on device reset and task abort.
This is actually a rare event, and on some platforms, I find it quite difficult to trigger.
So preparing the request upiu as a separate step seems a little bit excessive.
Another reason why it is a good idea to do it together, Is that both
preparing the task request upiu and ringing its doorbell are done under
the same host lock.

We can however, as you proposed, prepare a "raw" upiu if none is given,
But I think we'll end up with the same amount of code,
Maybe even less obvious than filling the upiu in one place.
diff mbox series

Patch

diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index d18832a..15be103 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -5599,6 +5599,7 @@  static int ufshcd_clear_tm_cmd(struct ufs_hba *hba, int tag)
 }
 
 static void ufshcd_fill_tm_req(struct utp_task_req_desc *task_req_descp,
+			       struct utp_upiu_task_req *raw_task_req_upiup,
 			       int lun_id, int task_id, u8 tm_function,
 			       int task_tag)
 {
@@ -5609,6 +5610,13 @@  static void ufshcd_fill_tm_req(struct utp_task_req_desc *task_req_descp,
 	task_req_descp->header.dword_2 =
 			cpu_to_le32(OCS_INVALID_COMMAND_STATUS);
 
+	if (raw_task_req_upiup) {
+		raw_task_req_upiup->header.dword_0 |= cpu_to_be32(task_tag);
+		memcpy(task_req_descp->task_req_upiu, raw_task_req_upiup,
+		       GENERAL_UPIU_REQUEST_SIZE);
+		return;
+	}
+
 	task_req_upiup =
 		(struct utp_upiu_task_req *)task_req_descp->task_req_upiu;
 	task_req_upiup->header.dword_0 =
@@ -5634,8 +5642,11 @@  static void ufshcd_fill_tm_req(struct utp_task_req_desc *task_req_descp,
  *
  * Returns non-zero value on error, zero on success.
  */
-static int ufshcd_issue_tm_cmd(struct ufs_hba *hba, int lun_id, int task_id,
-		u8 tm_function, u8 *tm_response)
+static int ufshcd_issue_tm_cmd(struct ufs_hba *hba,
+			       struct utp_upiu_task_req *raw_task_req_upiup,
+			       struct utp_upiu_task_req *raw_task_rsp_upiup,
+			       int lun_id, int task_id, u8 tm_function,
+			       u8 *tm_response)
 {
 	struct utp_task_req_desc *task_req_descp;
 	struct Scsi_Host *host;
@@ -5659,8 +5670,8 @@  static int ufshcd_issue_tm_cmd(struct ufs_hba *hba, int lun_id, int task_id,
 	task_req_descp += free_slot;
 	task_tag = hba->nutrs + free_slot;
 
-	ufshcd_fill_tm_req(task_req_descp, lun_id, task_id, tm_function,
-			   task_tag);
+	ufshcd_fill_tm_req(task_req_descp, raw_task_req_upiup, lun_id, task_id,
+			   tm_function, task_tag);
 
 	ufshcd_vops_setup_task_mgmt(hba, free_slot, tm_function);
 
@@ -5692,6 +5703,10 @@  static int ufshcd_issue_tm_cmd(struct ufs_hba *hba, int lun_id, int task_id,
 		err = -ETIMEDOUT;
 	} else {
 		err = ufshcd_task_req_compl(hba, free_slot, tm_response);
+		if (raw_task_rsp_upiup)
+			memcpy(raw_task_rsp_upiup,
+			       task_req_descp->task_rsp_upiu,
+			       GENERAL_UPIU_REQUEST_SIZE);
 		ufshcd_add_tm_upiu_trace(hba, task_tag, "tm_complete");
 	}
 
@@ -5726,7 +5741,8 @@  static int ufshcd_eh_device_reset_handler(struct scsi_cmnd *cmd)
 	tag = cmd->request->tag;
 
 	lrbp = &hba->lrb[tag];
-	err = ufshcd_issue_tm_cmd(hba, lrbp->lun, 0, UFS_LOGICAL_RESET, &resp);
+	err = ufshcd_issue_tm_cmd(hba, NULL, NULL, lrbp->lun, 0,
+				  UFS_LOGICAL_RESET, &resp);
 	if (err || resp != UPIU_TASK_MANAGEMENT_FUNC_COMPL) {
 		if (!err)
 			err = resp;
@@ -5856,8 +5872,9 @@  static int ufshcd_abort(struct scsi_cmnd *cmd)
 	}
 
 	for (poll_cnt = 100; poll_cnt; poll_cnt--) {
-		err = ufshcd_issue_tm_cmd(hba, lrbp->lun, lrbp->task_tag,
-				UFS_QUERY_TASK, &resp);
+		err = ufshcd_issue_tm_cmd(hba, NULL, NULL, lrbp->lun,
+					  lrbp->task_tag, UFS_QUERY_TASK,
+					  &resp);
 		if (!err && resp == UPIU_TASK_MANAGEMENT_FUNC_SUCCEEDED) {
 			/* cmd pending in the device */
 			dev_err(hba->dev, "%s: cmd pending in the device. tag = %d\n",
@@ -5895,8 +5912,8 @@  static int ufshcd_abort(struct scsi_cmnd *cmd)
 		goto out;
 	}
 
-	err = ufshcd_issue_tm_cmd(hba, lrbp->lun, lrbp->task_tag,
-			UFS_ABORT_TASK, &resp);
+	err = ufshcd_issue_tm_cmd(hba, NULL, NULL, lrbp->lun, lrbp->task_tag,
+				  UFS_ABORT_TASK, &resp);
 	if (err || resp != UPIU_TASK_MANAGEMENT_FUNC_COMPL) {
 		if (!err) {
 			err = resp; /* service response error */