On Wed, 5 Jun 2019, Ming Lei wrote:

> The driver expects that SCSI SGL is a simply array of SG, and itereate
> the SGL via integer index. This way is obviously wrong, because of
> SG_CHAIN.
> 
> Fixes it by using sgl helper.
> 
> V2:
>       - as suggested by Finn Thain, introduce .prv_sg for getting previous
>       scatterlist pointer
> 

Thanks. I'd forgotten about the consequences for SAVE/RESTORE POINTERS 
until I saw your patch.

I can't test the change to the IGNORE WIDE RESIDUE message handling but I 
did confirm that the patch series works in QEMU/m68k.

Reviewed-by: Finn Thain <fth...@telegraphics.com.au>

-- 

> Cc: Christoph Hellwig <h...@lst.de>
> Cc: Bart Van Assche <bvanass...@acm.org>
> Cc: Ewan D. Milne <emi...@redhat.com>
> Cc: Hannes Reinecke <h...@suse.com>
> Cc: Finn Thain <fth...@telegraphics.com.au>
> Cc: Guenter Roeck <li...@roeck-us.net>
> Reported-by: Guenter Roeck <li...@roeck-us.net>
> Signed-off-by: Ming Lei <ming....@redhat.com>
> ---
>  drivers/scsi/esp_scsi.c | 20 +++++++++++++-------
>  drivers/scsi/esp_scsi.h |  2 ++
>  2 files changed, 15 insertions(+), 7 deletions(-)
> 
> diff --git a/drivers/scsi/esp_scsi.c b/drivers/scsi/esp_scsi.c
> index 76e7ca864d6a..bb88995a12c7 100644
> --- a/drivers/scsi/esp_scsi.c
> +++ b/drivers/scsi/esp_scsi.c
> @@ -371,6 +371,7 @@ static void esp_map_dma(struct esp *esp, struct scsi_cmnd 
> *cmd)
>       struct esp_cmd_priv *spriv = ESP_CMD_PRIV(cmd);
>       struct scatterlist *sg = scsi_sglist(cmd);
>       int total = 0, i;
> +     struct scatterlist *s;
>  
>       if (cmd->sc_data_direction == DMA_NONE)
>               return;
> @@ -381,16 +382,18 @@ static void esp_map_dma(struct esp *esp, struct 
> scsi_cmnd *cmd)
>                * a dma address, so perform an identity mapping.
>                */
>               spriv->num_sg = scsi_sg_count(cmd);
> -             for (i = 0; i < spriv->num_sg; i++) {
> -                     sg[i].dma_address = (uintptr_t)sg_virt(&sg[i]);
> -                     total += sg_dma_len(&sg[i]);
> +
> +             scsi_for_each_sg(cmd, s, spriv->num_sg, i) {
> +                     s->dma_address = (uintptr_t)sg_virt(s);
> +                     total += sg_dma_len(s);
>               }
>       } else {
>               spriv->num_sg = scsi_dma_map(cmd);
> -             for (i = 0; i < spriv->num_sg; i++)
> -                     total += sg_dma_len(&sg[i]);
> +             scsi_for_each_sg(cmd, s, spriv->num_sg, i)
> +                     total += sg_dma_len(s);
>       }
>       spriv->cur_residue = sg_dma_len(sg);
> +     spriv->prv_sg = NULL;
>       spriv->cur_sg = sg;
>       spriv->tot_residue = total;
>  }
> @@ -444,7 +447,8 @@ static void esp_advance_dma(struct esp *esp, struct 
> esp_cmd_entry *ent,
>               p->tot_residue = 0;
>       }
>       if (!p->cur_residue && p->tot_residue) {
> -             p->cur_sg++;
> +             p->prv_sg = p->cur_sg;
> +             p->cur_sg = sg_next(p->cur_sg);
>               p->cur_residue = sg_dma_len(p->cur_sg);
>       }
>  }
> @@ -465,6 +469,7 @@ static void esp_save_pointers(struct esp *esp, struct 
> esp_cmd_entry *ent)
>               return;
>       }
>       ent->saved_cur_residue = spriv->cur_residue;
> +     ent->saved_prv_sg = spriv->prv_sg;
>       ent->saved_cur_sg = spriv->cur_sg;
>       ent->saved_tot_residue = spriv->tot_residue;
>  }
> @@ -479,6 +484,7 @@ static void esp_restore_pointers(struct esp *esp, struct 
> esp_cmd_entry *ent)
>               return;
>       }
>       spriv->cur_residue = ent->saved_cur_residue;
> +     spriv->prv_sg = ent->saved_prv_sg;
>       spriv->cur_sg = ent->saved_cur_sg;
>       spriv->tot_residue = ent->saved_tot_residue;
>  }
> @@ -1647,7 +1653,7 @@ static int esp_msgin_process(struct esp *esp)
>               spriv = ESP_CMD_PRIV(ent->cmd);
>  
>               if (spriv->cur_residue == sg_dma_len(spriv->cur_sg)) {
> -                     spriv->cur_sg--;
> +                     spriv->cur_sg = spriv->prv_sg;
>                       spriv->cur_residue = 1;
>               } else
>                       spriv->cur_residue++;
> diff --git a/drivers/scsi/esp_scsi.h b/drivers/scsi/esp_scsi.h
> index aa87a6b72dcc..91b32f2a1a1b 100644
> --- a/drivers/scsi/esp_scsi.h
> +++ b/drivers/scsi/esp_scsi.h
> @@ -251,6 +251,7 @@
>  struct esp_cmd_priv {
>       int                     num_sg;
>       int                     cur_residue;
> +     struct scatterlist      *prv_sg;
>       struct scatterlist      *cur_sg;
>       int                     tot_residue;
>  };
> @@ -273,6 +274,7 @@ struct esp_cmd_entry {
>       struct scsi_cmnd        *cmd;
>  
>       unsigned int            saved_cur_residue;
> +     struct scatterlist      *saved_prv_sg;
>       struct scatterlist      *saved_cur_sg;
>       unsigned int            saved_tot_residue;
>  
> 

Reply via email to