aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi
diff options
context:
space:
mode:
authorChristoph Hellwig <hch@lst.de>2015-04-23 03:48:51 -0400
committerJames Bottomley <JBottomley@Odin.com>2015-04-27 13:10:19 -0400
commit118c855b5623f3e2e6204f02623d88c09e0c34de (patch)
tree2a6fcd529adaf3b08a06abebb95802dc838ea16d /drivers/scsi
parent9cd9554615cba14f0877cc9972a6537ad2bdde61 (diff)
3w-9xxx: fix command completion race
The 3w-9xxx 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> 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-9xxx.c57
-rw-r--r--drivers/scsi/3w-9xxx.h5
2 files changed, 13 insertions, 49 deletions
diff --git a/drivers/scsi/3w-9xxx.c b/drivers/scsi/3w-9xxx.c
index 7600639db4c4..add419d6ff34 100644
--- a/drivers/scsi/3w-9xxx.c
+++ b/drivers/scsi/3w-9xxx.c
@@ -149,7 +149,6 @@ static int twa_reset_sequence(TW_Device_Extension *tw_dev, int soft_reset);
149static int twa_scsiop_execute_scsi(TW_Device_Extension *tw_dev, int request_id, char *cdb, int use_sg, TW_SG_Entry *sglistarg); 149static int twa_scsiop_execute_scsi(TW_Device_Extension *tw_dev, int request_id, char *cdb, int use_sg, TW_SG_Entry *sglistarg);
150static void twa_scsiop_execute_scsi_complete(TW_Device_Extension *tw_dev, int request_id); 150static void twa_scsiop_execute_scsi_complete(TW_Device_Extension *tw_dev, int request_id);
151static char *twa_string_lookup(twa_message_type *table, unsigned int aen_code); 151static char *twa_string_lookup(twa_message_type *table, unsigned int aen_code);
152static void twa_unmap_scsi_data(TW_Device_Extension *tw_dev, int request_id);
153 152
154/* Functions */ 153/* Functions */
155 154
@@ -1340,11 +1339,11 @@ static irqreturn_t twa_interrupt(int irq, void *dev_instance)
1340 } 1339 }
1341 1340
1342 /* Now complete the io */ 1341 /* Now complete the io */
1342 scsi_dma_unmap(cmd);
1343 cmd->scsi_done(cmd);
1343 tw_dev->state[request_id] = TW_S_COMPLETED; 1344 tw_dev->state[request_id] = TW_S_COMPLETED;
1344 twa_free_request_id(tw_dev, request_id); 1345 twa_free_request_id(tw_dev, request_id);
1345 tw_dev->posted_request_count--; 1346 tw_dev->posted_request_count--;
1346 tw_dev->srb[request_id]->scsi_done(tw_dev->srb[request_id]);
1347 twa_unmap_scsi_data(tw_dev, request_id);
1348 } 1347 }
1349 1348
1350 /* Check for valid status after each drain */ 1349 /* Check for valid status after each drain */
@@ -1402,26 +1401,6 @@ static void twa_load_sgl(TW_Device_Extension *tw_dev, TW_Command_Full *full_comm
1402 } 1401 }
1403} /* End twa_load_sgl() */ 1402} /* End twa_load_sgl() */
1404 1403
1405/* This function will perform a pci-dma mapping for a scatter gather list */
1406static int twa_map_scsi_sg_data(TW_Device_Extension *tw_dev, int request_id)
1407{
1408 int use_sg;
1409 struct scsi_cmnd *cmd = tw_dev->srb[request_id];
1410
1411 use_sg = scsi_dma_map(cmd);
1412 if (!use_sg)
1413 return 0;
1414 else if (use_sg < 0) {
1415 TW_PRINTK(tw_dev->host, TW_DRIVER, 0x1c, "Failed to map scatter gather list");
1416 return 0;
1417 }
1418
1419 cmd->SCp.phase = TW_PHASE_SGLIST;
1420 cmd->SCp.have_data_in = use_sg;
1421
1422 return use_sg;
1423} /* End twa_map_scsi_sg_data() */
1424
1425/* This function will poll for a response interrupt of a request */ 1404/* This function will poll for a response interrupt of a request */
1426static int twa_poll_response(TW_Device_Extension *tw_dev, int request_id, int seconds) 1405static int twa_poll_response(TW_Device_Extension *tw_dev, int request_id, int seconds)
1427{ 1406{
@@ -1600,9 +1579,11 @@ static int twa_reset_device_extension(TW_Device_Extension *tw_dev)
1600 (tw_dev->state[i] != TW_S_INITIAL) && 1579 (tw_dev->state[i] != TW_S_INITIAL) &&
1601 (tw_dev->state[i] != TW_S_COMPLETED)) { 1580 (tw_dev->state[i] != TW_S_COMPLETED)) {
1602 if (tw_dev->srb[i]) { 1581 if (tw_dev->srb[i]) {
1603 tw_dev->srb[i]->result = (DID_RESET << 16); 1582 struct scsi_cmnd *cmd = tw_dev->srb[i];
1604 tw_dev->srb[i]->scsi_done(tw_dev->srb[i]); 1583
1605 twa_unmap_scsi_data(tw_dev, i); 1584 cmd->result = (DID_RESET << 16);
1585 scsi_dma_unmap(cmd);
1586 cmd->scsi_done(cmd);
1606 } 1587 }
1607 } 1588 }
1608 } 1589 }
@@ -1781,21 +1762,18 @@ static int twa_scsi_queue_lck(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_
1781 /* Save the scsi command for use by the ISR */ 1762 /* Save the scsi command for use by the ISR */
1782 tw_dev->srb[request_id] = SCpnt; 1763 tw_dev->srb[request_id] = SCpnt;
1783 1764
1784 /* Initialize phase to zero */
1785 SCpnt->SCp.phase = TW_PHASE_INITIAL;
1786
1787 retval = twa_scsiop_execute_scsi(tw_dev, request_id, NULL, 0, NULL); 1765 retval = twa_scsiop_execute_scsi(tw_dev, request_id, NULL, 0, NULL);
1788 switch (retval) { 1766 switch (retval) {
1789 case SCSI_MLQUEUE_HOST_BUSY: 1767 case SCSI_MLQUEUE_HOST_BUSY:
1768 scsi_dma_unmap(SCpnt);
1790 twa_free_request_id(tw_dev, request_id); 1769 twa_free_request_id(tw_dev, request_id);
1791 twa_unmap_scsi_data(tw_dev, request_id);
1792 break; 1770 break;
1793 case 1: 1771 case 1:
1794 tw_dev->state[request_id] = TW_S_COMPLETED;
1795 twa_free_request_id(tw_dev, request_id);
1796 twa_unmap_scsi_data(tw_dev, request_id);
1797 SCpnt->result = (DID_ERROR << 16); 1772 SCpnt->result = (DID_ERROR << 16);
1773 scsi_dma_unmap(SCpnt);
1798 done(SCpnt); 1774 done(SCpnt);
1775 tw_dev->state[request_id] = TW_S_COMPLETED;
1776 twa_free_request_id(tw_dev, request_id);
1799 retval = 0; 1777 retval = 0;
1800 } 1778 }
1801out: 1779out:
@@ -1863,8 +1841,8 @@ static int twa_scsiop_execute_scsi(TW_Device_Extension *tw_dev, int request_id,
1863 command_packet->sg_list[0].address = TW_CPU_TO_SGL(tw_dev->generic_buffer_phys[request_id]); 1841 command_packet->sg_list[0].address = TW_CPU_TO_SGL(tw_dev->generic_buffer_phys[request_id]);
1864 command_packet->sg_list[0].length = cpu_to_le32(TW_MIN_SGL_LENGTH); 1842 command_packet->sg_list[0].length = cpu_to_le32(TW_MIN_SGL_LENGTH);
1865 } else { 1843 } else {
1866 sg_count = twa_map_scsi_sg_data(tw_dev, request_id); 1844 sg_count = scsi_dma_map(srb);
1867 if (sg_count == 0) 1845 if (sg_count < 0)
1868 goto out; 1846 goto out;
1869 1847
1870 scsi_for_each_sg(srb, sg, sg_count, i) { 1848 scsi_for_each_sg(srb, sg, sg_count, i) {
@@ -1979,15 +1957,6 @@ static char *twa_string_lookup(twa_message_type *table, unsigned int code)
1979 return(table[index].text); 1957 return(table[index].text);
1980} /* End twa_string_lookup() */ 1958} /* End twa_string_lookup() */
1981 1959
1982/* This function will perform a pci-dma unmap */
1983static void twa_unmap_scsi_data(TW_Device_Extension *tw_dev, int request_id)
1984{
1985 struct scsi_cmnd *cmd = tw_dev->srb[request_id];
1986
1987 if (cmd->SCp.phase == TW_PHASE_SGLIST)
1988 scsi_dma_unmap(cmd);
1989} /* End twa_unmap_scsi_data() */
1990
1991/* This function gets called when a disk is coming on-line */ 1960/* This function gets called when a disk is coming on-line */
1992static int twa_slave_configure(struct scsi_device *sdev) 1961static int twa_slave_configure(struct scsi_device *sdev)
1993{ 1962{
diff --git a/drivers/scsi/3w-9xxx.h b/drivers/scsi/3w-9xxx.h
index 040f7214e5b7..0fdc83cfa0e1 100644
--- a/drivers/scsi/3w-9xxx.h
+++ b/drivers/scsi/3w-9xxx.h
@@ -324,11 +324,6 @@ static twa_message_type twa_error_table[] = {
324#define TW_CURRENT_DRIVER_BUILD 0 324#define TW_CURRENT_DRIVER_BUILD 0
325#define TW_CURRENT_DRIVER_BRANCH 0 325#define TW_CURRENT_DRIVER_BRANCH 0
326 326
327/* Phase defines */
328#define TW_PHASE_INITIAL 0
329#define TW_PHASE_SINGLE 1
330#define TW_PHASE_SGLIST 2
331
332/* Misc defines */ 327/* Misc defines */
333#define TW_9550SX_DRAIN_COMPLETED 0xFFFF 328#define TW_9550SX_DRAIN_COMPLETED 0xFFFF
334#define TW_SECTOR_SIZE 512 329#define TW_SECTOR_SIZE 512