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

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>
Tested-by: Guenter Roeck <li...@roeck-us.net>
Reviewed-by: Finn Thain <fth...@telegraphics.com.au>
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;
 
-- 
2.20.1

Reply via email to