aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi
diff options
context:
space:
mode:
authorChristoph Hellwig <hch@lst.de>2015-04-23 03:48:49 -0400
committerJames Bottomley <JBottomley@Odin.com>2015-04-27 13:04:39 -0400
commit579d69bc1fd56d5af5761969aa529d1d1c188300 (patch)
tree0596feafadf90a837647d3e1b473c41b9fbecbac /drivers/scsi
parent8c08a6215a432a8f3629da0e8ccfd534ffa480f5 (diff)
3w-sas: fix command completion race
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 <hch@lst.de> Reported-by: Torsten Luettgert <ml-lkml@enda.eu> Tested-by: Bernd Kardatzki <Bernd.Kardatzki@med.uni-tuebingen.de> Cc: stable@vger.kernel.org Acked-by: Adam Radford <aradford@gmail.com> Signed-off-by: James Bottomley <JBottomley@Odin.com>
Diffstat (limited to 'drivers/scsi')
-rw-r--r--drivers/scsi/3w-sas.c50
-rw-r--r--drivers/scsi/3w-sas.h4
2 files changed, 10 insertions, 44 deletions
diff --git a/drivers/scsi/3w-sas.c b/drivers/scsi/3w-sas.c
index 2361772d5909..f8374850f714 100644
--- a/drivers/scsi/3w-sas.c
+++ b/drivers/scsi/3w-sas.c
@@ -290,26 +290,6 @@ static int twl_post_command_packet(TW_Device_Extension *tw_dev, int request_id)
290 return 0; 290 return 0;
291} /* End twl_post_command_packet() */ 291} /* End twl_post_command_packet() */
292 292
293/* This function will perform a pci-dma mapping for a scatter gather list */
294static int twl_map_scsi_sg_data(TW_Device_Extension *tw_dev, int request_id)
295{
296 int use_sg;
297 struct scsi_cmnd *cmd = tw_dev->srb[request_id];
298
299 use_sg = scsi_dma_map(cmd);
300 if (!use_sg)
301 return 0;
302 else if (use_sg < 0) {
303 TW_PRINTK(tw_dev->host, TW_DRIVER, 0x1, "Failed to map scatter gather list");
304 return 0;
305 }
306
307 cmd->SCp.phase = TW_PHASE_SGLIST;
308 cmd->SCp.have_data_in = use_sg;
309
310 return use_sg;
311} /* End twl_map_scsi_sg_data() */
312
313/* This function hands scsi cdb's to the firmware */ 293/* This function hands scsi cdb's to the firmware */
314static int twl_scsiop_execute_scsi(TW_Device_Extension *tw_dev, int request_id, char *cdb, int use_sg, TW_SG_Entry_ISO *sglistarg) 294static int twl_scsiop_execute_scsi(TW_Device_Extension *tw_dev, int request_id, char *cdb, int use_sg, TW_SG_Entry_ISO *sglistarg)
315{ 295{
@@ -357,8 +337,8 @@ static int twl_scsiop_execute_scsi(TW_Device_Extension *tw_dev, int request_id,
357 if (!sglistarg) { 337 if (!sglistarg) {
358 /* Map sglist from scsi layer to cmd packet */ 338 /* Map sglist from scsi layer to cmd packet */
359 if (scsi_sg_count(srb)) { 339 if (scsi_sg_count(srb)) {
360 sg_count = twl_map_scsi_sg_data(tw_dev, request_id); 340 sg_count = scsi_dma_map(srb);
361 if (sg_count == 0) 341 if (sg_count <= 0)
362 goto out; 342 goto out;
363 343
364 scsi_for_each_sg(srb, sg, sg_count, i) { 344 scsi_for_each_sg(srb, sg, sg_count, i) {
@@ -1102,15 +1082,6 @@ out:
1102 return retval; 1082 return retval;
1103} /* End twl_initialize_device_extension() */ 1083} /* End twl_initialize_device_extension() */
1104 1084
1105/* This function will perform a pci-dma unmap */
1106static void twl_unmap_scsi_data(TW_Device_Extension *tw_dev, int request_id)
1107{
1108 struct scsi_cmnd *cmd = tw_dev->srb[request_id];
1109
1110 if (cmd->SCp.phase == TW_PHASE_SGLIST)
1111 scsi_dma_unmap(cmd);
1112} /* End twl_unmap_scsi_data() */
1113
1114/* This function will handle attention interrupts */ 1085/* This function will handle attention interrupts */
1115static int twl_handle_attention_interrupt(TW_Device_Extension *tw_dev) 1086static int twl_handle_attention_interrupt(TW_Device_Extension *tw_dev)
1116{ 1087{
@@ -1251,11 +1222,11 @@ static irqreturn_t twl_interrupt(int irq, void *dev_instance)
1251 } 1222 }
1252 1223
1253 /* Now complete the io */ 1224 /* Now complete the io */
1225 scsi_dma_unmap(cmd);
1226 cmd->scsi_done(cmd);
1254 tw_dev->state[request_id] = TW_S_COMPLETED; 1227 tw_dev->state[request_id] = TW_S_COMPLETED;
1255 twl_free_request_id(tw_dev, request_id); 1228 twl_free_request_id(tw_dev, request_id);
1256 tw_dev->posted_request_count--; 1229 tw_dev->posted_request_count--;
1257 tw_dev->srb[request_id]->scsi_done(tw_dev->srb[request_id]);
1258 twl_unmap_scsi_data(tw_dev, request_id);
1259 } 1230 }
1260 1231
1261 /* Check for another response interrupt */ 1232 /* Check for another response interrupt */
@@ -1400,10 +1371,12 @@ static int twl_reset_device_extension(TW_Device_Extension *tw_dev, int ioctl_res
1400 if ((tw_dev->state[i] != TW_S_FINISHED) && 1371 if ((tw_dev->state[i] != TW_S_FINISHED) &&
1401 (tw_dev->state[i] != TW_S_INITIAL) && 1372 (tw_dev->state[i] != TW_S_INITIAL) &&
1402 (tw_dev->state[i] != TW_S_COMPLETED)) { 1373 (tw_dev->state[i] != TW_S_COMPLETED)) {
1403 if (tw_dev->srb[i]) { 1374 struct scsi_cmnd *cmd = tw_dev->srb[i];
1404 tw_dev->srb[i]->result = (DID_RESET << 16); 1375
1405 tw_dev->srb[i]->scsi_done(tw_dev->srb[i]); 1376 if (cmd) {
1406 twl_unmap_scsi_data(tw_dev, i); 1377 cmd->result = (DID_RESET << 16);
1378 scsi_dma_unmap(cmd);
1379 cmd->scsi_done(cmd);
1407 } 1380 }
1408 } 1381 }
1409 } 1382 }
@@ -1507,9 +1480,6 @@ static int twl_scsi_queue_lck(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_
1507 /* Save the scsi command for use by the ISR */ 1480 /* Save the scsi command for use by the ISR */
1508 tw_dev->srb[request_id] = SCpnt; 1481 tw_dev->srb[request_id] = SCpnt;
1509 1482
1510 /* Initialize phase to zero */
1511 SCpnt->SCp.phase = TW_PHASE_INITIAL;
1512
1513 retval = twl_scsiop_execute_scsi(tw_dev, request_id, NULL, 0, NULL); 1483 retval = twl_scsiop_execute_scsi(tw_dev, request_id, NULL, 0, NULL);
1514 if (retval) { 1484 if (retval) {
1515 tw_dev->state[request_id] = TW_S_COMPLETED; 1485 tw_dev->state[request_id] = TW_S_COMPLETED;
diff --git a/drivers/scsi/3w-sas.h b/drivers/scsi/3w-sas.h
index d474892701d4..fec6449c7595 100644
--- a/drivers/scsi/3w-sas.h
+++ b/drivers/scsi/3w-sas.h
@@ -103,10 +103,6 @@ static char *twl_aen_severity_table[] =
103#define TW_CURRENT_DRIVER_BUILD 0 103#define TW_CURRENT_DRIVER_BUILD 0
104#define TW_CURRENT_DRIVER_BRANCH 0 104#define TW_CURRENT_DRIVER_BRANCH 0
105 105
106/* Phase defines */
107#define TW_PHASE_INITIAL 0
108#define TW_PHASE_SGLIST 2
109
110/* Misc defines */ 106/* Misc defines */
111#define TW_SECTOR_SIZE 512 107#define TW_SECTOR_SIZE 512
112#define TW_MAX_UNITS 32 108#define TW_MAX_UNITS 32