[PATCH 3.13.y-ckt 024/122] 3w-sas: fix command completion race

2015-06-17 Thread Kamal Mostafa
3.13.11-ckt22 -stable review patch.  If anyone has any objections, please let 
me know.

--

From: Christoph Hellwig 

commit 579d69bc1fd56d5af5761969aa529d1d1c188300 upstream.

The 3w-sas driver needs to tear down the dma mappings before returning
the command to the midlayer, as there is no guarantee the sglist and
count are valid after that point.  Also remove the dma mapping helpers
which have another inherent race due to the request_id index.

Signed-off-by: Christoph Hellwig 
Reported-by: Torsten Luettgert 
Tested-by: Bernd Kardatzki 
Acked-by: Adam Radford 
Signed-off-by: James Bottomley 
Signed-off-by: Kamal Mostafa 
---
 drivers/scsi/3w-sas.c | 50 ++
 drivers/scsi/3w-sas.h |  4 
 2 files changed, 10 insertions(+), 44 deletions(-)

diff --git a/drivers/scsi/3w-sas.c b/drivers/scsi/3w-sas.c
index 4de3460..61702ac 100644
--- a/drivers/scsi/3w-sas.c
+++ b/drivers/scsi/3w-sas.c
@@ -303,26 +303,6 @@ static int twl_post_command_packet(TW_Device_Extension 
*tw_dev, int request_id)
return 0;
 } /* End twl_post_command_packet() */
 
-/* This function will perform a pci-dma mapping for a scatter gather list */
-static int twl_map_scsi_sg_data(TW_Device_Extension *tw_dev, int request_id)
-{
-   int use_sg;
-   struct scsi_cmnd *cmd = tw_dev->srb[request_id];
-
-   use_sg = scsi_dma_map(cmd);
-   if (!use_sg)
-   return 0;
-   else if (use_sg < 0) {
-   TW_PRINTK(tw_dev->host, TW_DRIVER, 0x1, "Failed to map scatter 
gather list");
-   return 0;
-   }
-
-   cmd->SCp.phase = TW_PHASE_SGLIST;
-   cmd->SCp.have_data_in = use_sg;
-
-   return use_sg;
-} /* End twl_map_scsi_sg_data() */
-
 /* This function hands scsi cdb's to the firmware */
 static int twl_scsiop_execute_scsi(TW_Device_Extension *tw_dev, int 
request_id, char *cdb, int use_sg, TW_SG_Entry_ISO *sglistarg)
 {
@@ -370,8 +350,8 @@ static int twl_scsiop_execute_scsi(TW_Device_Extension 
*tw_dev, int request_id,
if (!sglistarg) {
/* Map sglist from scsi layer to cmd packet */
if (scsi_sg_count(srb)) {
-   sg_count = twl_map_scsi_sg_data(tw_dev, request_id);
-   if (sg_count == 0)
+   sg_count = scsi_dma_map(srb);
+   if (sg_count <= 0)
goto out;
 
scsi_for_each_sg(srb, sg, sg_count, i) {
@@ -1116,15 +1096,6 @@ out:
return retval;
 } /* End twl_initialize_device_extension() */
 
-/* This function will perform a pci-dma unmap */
-static void twl_unmap_scsi_data(TW_Device_Extension *tw_dev, int request_id)
-{
-   struct scsi_cmnd *cmd = tw_dev->srb[request_id];
-
-   if (cmd->SCp.phase == TW_PHASE_SGLIST)
-   scsi_dma_unmap(cmd);
-} /* End twl_unmap_scsi_data() */
-
 /* This function will handle attention interrupts */
 static int twl_handle_attention_interrupt(TW_Device_Extension *tw_dev)
 {
@@ -1265,11 +1236,11 @@ static irqreturn_t twl_interrupt(int irq, void 
*dev_instance)
}
 
/* Now complete the io */
+   scsi_dma_unmap(cmd);
+   cmd->scsi_done(cmd);
tw_dev->state[request_id] = TW_S_COMPLETED;
twl_free_request_id(tw_dev, request_id);
tw_dev->posted_request_count--;
-   
tw_dev->srb[request_id]->scsi_done(tw_dev->srb[request_id]);
-   twl_unmap_scsi_data(tw_dev, request_id);
}
 
/* Check for another response interrupt */
@@ -1414,10 +1385,12 @@ static int 
twl_reset_device_extension(TW_Device_Extension *tw_dev, int ioctl_res
if ((tw_dev->state[i] != TW_S_FINISHED) &&
(tw_dev->state[i] != TW_S_INITIAL) &&
(tw_dev->state[i] != TW_S_COMPLETED)) {
-   if (tw_dev->srb[i]) {
-   tw_dev->srb[i]->result = (DID_RESET << 16);
-   tw_dev->srb[i]->scsi_done(tw_dev->srb[i]);
-   twl_unmap_scsi_data(tw_dev, i);
+   struct scsi_cmnd *cmd = tw_dev->srb[i];
+
+   if (cmd) {
+   cmd->result = (DID_RESET << 16);
+   scsi_dma_unmap(cmd);
+   cmd->scsi_done(cmd);
}
}
}
@@ -1521,9 +1494,6 @@ static int twl_scsi_queue_lck(struct scsi_cmnd *SCpnt, 
void (*done)(struct scsi_
/* Save the scsi command for use by the ISR */
tw_dev->srb[request_id] = SCpnt;
 
-   /* Initialize phase to zero */
-   SCpnt->SCp.phase = TW_PHASE_INITIAL;
-
retval = twl_scsiop_execute_scsi(tw_dev, request_id, NULL, 0, NULL);
if (retval) {

[PATCH 3.13.y-ckt 024/122] 3w-sas: fix command completion race

2015-06-17 Thread Kamal Mostafa
3.13.11-ckt22 -stable review patch.  If anyone has any objections, please let 
me know.

--

From: Christoph Hellwig h...@lst.de

commit 579d69bc1fd56d5af5761969aa529d1d1c188300 upstream.

The 3w-sas driver needs to tear down the dma mappings before returning
the command to the midlayer, as there is no guarantee the sglist and
count are valid after that point.  Also remove the dma mapping helpers
which have another inherent race due to the request_id index.

Signed-off-by: Christoph Hellwig h...@lst.de
Reported-by: Torsten Luettgert ml-l...@enda.eu
Tested-by: Bernd Kardatzki bernd.kardat...@med.uni-tuebingen.de
Acked-by: Adam Radford aradf...@gmail.com
Signed-off-by: James Bottomley jbottom...@odin.com
Signed-off-by: Kamal Mostafa ka...@canonical.com
---
 drivers/scsi/3w-sas.c | 50 ++
 drivers/scsi/3w-sas.h |  4 
 2 files changed, 10 insertions(+), 44 deletions(-)

diff --git a/drivers/scsi/3w-sas.c b/drivers/scsi/3w-sas.c
index 4de3460..61702ac 100644
--- a/drivers/scsi/3w-sas.c
+++ b/drivers/scsi/3w-sas.c
@@ -303,26 +303,6 @@ static int twl_post_command_packet(TW_Device_Extension 
*tw_dev, int request_id)
return 0;
 } /* End twl_post_command_packet() */
 
-/* This function will perform a pci-dma mapping for a scatter gather list */
-static int twl_map_scsi_sg_data(TW_Device_Extension *tw_dev, int request_id)
-{
-   int use_sg;
-   struct scsi_cmnd *cmd = tw_dev-srb[request_id];
-
-   use_sg = scsi_dma_map(cmd);
-   if (!use_sg)
-   return 0;
-   else if (use_sg  0) {
-   TW_PRINTK(tw_dev-host, TW_DRIVER, 0x1, Failed to map scatter 
gather list);
-   return 0;
-   }
-
-   cmd-SCp.phase = TW_PHASE_SGLIST;
-   cmd-SCp.have_data_in = use_sg;
-
-   return use_sg;
-} /* End twl_map_scsi_sg_data() */
-
 /* This function hands scsi cdb's to the firmware */
 static int twl_scsiop_execute_scsi(TW_Device_Extension *tw_dev, int 
request_id, char *cdb, int use_sg, TW_SG_Entry_ISO *sglistarg)
 {
@@ -370,8 +350,8 @@ static int twl_scsiop_execute_scsi(TW_Device_Extension 
*tw_dev, int request_id,
if (!sglistarg) {
/* Map sglist from scsi layer to cmd packet */
if (scsi_sg_count(srb)) {
-   sg_count = twl_map_scsi_sg_data(tw_dev, request_id);
-   if (sg_count == 0)
+   sg_count = scsi_dma_map(srb);
+   if (sg_count = 0)
goto out;
 
scsi_for_each_sg(srb, sg, sg_count, i) {
@@ -1116,15 +1096,6 @@ out:
return retval;
 } /* End twl_initialize_device_extension() */
 
-/* This function will perform a pci-dma unmap */
-static void twl_unmap_scsi_data(TW_Device_Extension *tw_dev, int request_id)
-{
-   struct scsi_cmnd *cmd = tw_dev-srb[request_id];
-
-   if (cmd-SCp.phase == TW_PHASE_SGLIST)
-   scsi_dma_unmap(cmd);
-} /* End twl_unmap_scsi_data() */
-
 /* This function will handle attention interrupts */
 static int twl_handle_attention_interrupt(TW_Device_Extension *tw_dev)
 {
@@ -1265,11 +1236,11 @@ static irqreturn_t twl_interrupt(int irq, void 
*dev_instance)
}
 
/* Now complete the io */
+   scsi_dma_unmap(cmd);
+   cmd-scsi_done(cmd);
tw_dev-state[request_id] = TW_S_COMPLETED;
twl_free_request_id(tw_dev, request_id);
tw_dev-posted_request_count--;
-   
tw_dev-srb[request_id]-scsi_done(tw_dev-srb[request_id]);
-   twl_unmap_scsi_data(tw_dev, request_id);
}
 
/* Check for another response interrupt */
@@ -1414,10 +1385,12 @@ static int 
twl_reset_device_extension(TW_Device_Extension *tw_dev, int ioctl_res
if ((tw_dev-state[i] != TW_S_FINISHED) 
(tw_dev-state[i] != TW_S_INITIAL) 
(tw_dev-state[i] != TW_S_COMPLETED)) {
-   if (tw_dev-srb[i]) {
-   tw_dev-srb[i]-result = (DID_RESET  16);
-   tw_dev-srb[i]-scsi_done(tw_dev-srb[i]);
-   twl_unmap_scsi_data(tw_dev, i);
+   struct scsi_cmnd *cmd = tw_dev-srb[i];
+
+   if (cmd) {
+   cmd-result = (DID_RESET  16);
+   scsi_dma_unmap(cmd);
+   cmd-scsi_done(cmd);
}
}
}
@@ -1521,9 +1494,6 @@ static int twl_scsi_queue_lck(struct scsi_cmnd *SCpnt, 
void (*done)(struct scsi_
/* Save the scsi command for use by the ISR */
tw_dev-srb[request_id] = SCpnt;
 
-   /* Initialize phase to zero */
-   SCpnt-SCp.phase = TW_PHASE_INITIAL;
-
retval =