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

2018-09-05 Thread Avri Altman


> > ---
> >  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.


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

2018-09-04 Thread Christoph Hellwig
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 
> ---
>  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.


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

2018-09-03 Thread Avri Altman
Do that in order to re-use its code if the task request and response
UPIUs are given externally.

Signed-off-by: Avri Altman 
---
 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;
+   }
+
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 = >lrb[tag];
-   err = ufshcd_issue_tm_cmd(hba, lrbp->lun, 0, UFS_LOGICAL_RESET, );
+   err = ufshcd_issue_tm_cmd(hba, NULL, NULL, lrbp->lun, 0,
+ UFS_LOGICAL_RESET, );
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, );
+   err = ufshcd_issue_tm_cmd(hba, NULL, NULL, lrbp->lun,
+ lrbp->task_tag, UFS_QUERY_TASK,
+ );
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, );
+   err = ufshcd_issue_tm_cmd(hba, NULL, NULL, lrbp->lun, lrbp->task_tag,
+ UFS_ABORT_TASK, );
if (err || resp != UPIU_TASK_MANAGEMENT_FUNC_COMPL) {
if (!err) {
err = resp; /* service response error */
-- 
1.9.1