aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristoph Hellwig <hch@lst.de>2015-04-23 03:48:50 -0400
committerJames Bottomley <JBottomley@Odin.com>2015-04-27 13:05:55 -0400
commit9cd9554615cba14f0877cc9972a6537ad2bdde61 (patch)
treec046377992e59614f19630da661f64436a507ccb
parent579d69bc1fd56d5af5761969aa529d1d1c188300 (diff)
3w-xxxx: fix command completion race
The 3w-xxxx 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>
-rw-r--r--drivers/scsi/3w-xxxx.c42
-rw-r--r--drivers/scsi/3w-xxxx.h5
2 files changed, 6 insertions, 41 deletions
diff --git a/drivers/scsi/3w-xxxx.c b/drivers/scsi/3w-xxxx.c
index c75f2048319f..2940bd769936 100644
--- a/drivers/scsi/3w-xxxx.c
+++ b/drivers/scsi/3w-xxxx.c
@@ -1271,32 +1271,6 @@ static int tw_initialize_device_extension(TW_Device_Extension *tw_dev)
1271 return 0; 1271 return 0;
1272} /* End tw_initialize_device_extension() */ 1272} /* End tw_initialize_device_extension() */
1273 1273
1274static int tw_map_scsi_sg_data(struct pci_dev *pdev, struct scsi_cmnd *cmd)
1275{
1276 int use_sg;
1277
1278 dprintk(KERN_WARNING "3w-xxxx: tw_map_scsi_sg_data()\n");
1279
1280 use_sg = scsi_dma_map(cmd);
1281 if (use_sg < 0) {
1282 printk(KERN_WARNING "3w-xxxx: tw_map_scsi_sg_data(): pci_map_sg() failed.\n");
1283 return 0;
1284 }
1285
1286 cmd->SCp.phase = TW_PHASE_SGLIST;
1287 cmd->SCp.have_data_in = use_sg;
1288
1289 return use_sg;
1290} /* End tw_map_scsi_sg_data() */
1291
1292static void tw_unmap_scsi_data(struct pci_dev *pdev, struct scsi_cmnd *cmd)
1293{
1294 dprintk(KERN_WARNING "3w-xxxx: tw_unmap_scsi_data()\n");
1295
1296 if (cmd->SCp.phase == TW_PHASE_SGLIST)
1297 scsi_dma_unmap(cmd);
1298} /* End tw_unmap_scsi_data() */
1299
1300/* This function will reset a device extension */ 1274/* This function will reset a device extension */
1301static int tw_reset_device_extension(TW_Device_Extension *tw_dev) 1275static int tw_reset_device_extension(TW_Device_Extension *tw_dev)
1302{ 1276{
@@ -1319,8 +1293,8 @@ static int tw_reset_device_extension(TW_Device_Extension *tw_dev)
1319 srb = tw_dev->srb[i]; 1293 srb = tw_dev->srb[i];
1320 if (srb != NULL) { 1294 if (srb != NULL) {
1321 srb->result = (DID_RESET << 16); 1295 srb->result = (DID_RESET << 16);
1322 tw_dev->srb[i]->scsi_done(tw_dev->srb[i]); 1296 scsi_dma_unmap(srb);
1323 tw_unmap_scsi_data(tw_dev->tw_pci_dev, tw_dev->srb[i]); 1297 srb->scsi_done(srb);
1324 } 1298 }
1325 } 1299 }
1326 } 1300 }
@@ -1767,8 +1741,8 @@ static int tw_scsiop_read_write(TW_Device_Extension *tw_dev, int request_id)
1767 command_packet->byte8.io.lba = lba; 1741 command_packet->byte8.io.lba = lba;
1768 command_packet->byte6.block_count = num_sectors; 1742 command_packet->byte6.block_count = num_sectors;
1769 1743
1770 use_sg = tw_map_scsi_sg_data(tw_dev->tw_pci_dev, tw_dev->srb[request_id]); 1744 use_sg = scsi_dma_map(srb);
1771 if (!use_sg) 1745 if (use_sg <= 0)
1772 return 1; 1746 return 1;
1773 1747
1774 scsi_for_each_sg(tw_dev->srb[request_id], sg, use_sg, i) { 1748 scsi_for_each_sg(tw_dev->srb[request_id], sg, use_sg, i) {
@@ -1955,9 +1929,6 @@ static int tw_scsi_queue_lck(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_c
1955 /* Save the scsi command for use by the ISR */ 1929 /* Save the scsi command for use by the ISR */
1956 tw_dev->srb[request_id] = SCpnt; 1930 tw_dev->srb[request_id] = SCpnt;
1957 1931
1958 /* Initialize phase to zero */
1959 SCpnt->SCp.phase = TW_PHASE_INITIAL;
1960
1961 switch (*command) { 1932 switch (*command) {
1962 case READ_10: 1933 case READ_10:
1963 case READ_6: 1934 case READ_6:
@@ -2185,12 +2156,11 @@ static irqreturn_t tw_interrupt(int irq, void *dev_instance)
2185 2156
2186 /* Now complete the io */ 2157 /* Now complete the io */
2187 if ((error != TW_ISR_DONT_COMPLETE)) { 2158 if ((error != TW_ISR_DONT_COMPLETE)) {
2159 scsi_dma_unmap(tw_dev->srb[request_id]);
2160 tw_dev->srb[request_id]->scsi_done(tw_dev->srb[request_id]);
2188 tw_dev->state[request_id] = TW_S_COMPLETED; 2161 tw_dev->state[request_id] = TW_S_COMPLETED;
2189 tw_state_request_finish(tw_dev, request_id); 2162 tw_state_request_finish(tw_dev, request_id);
2190 tw_dev->posted_request_count--; 2163 tw_dev->posted_request_count--;
2191 tw_dev->srb[request_id]->scsi_done(tw_dev->srb[request_id]);
2192
2193 tw_unmap_scsi_data(tw_dev->tw_pci_dev, tw_dev->srb[request_id]);
2194 } 2164 }
2195 } 2165 }
2196 2166
diff --git a/drivers/scsi/3w-xxxx.h b/drivers/scsi/3w-xxxx.h
index 29b0b84ed69e..6f65e663d393 100644
--- a/drivers/scsi/3w-xxxx.h
+++ b/drivers/scsi/3w-xxxx.h
@@ -195,11 +195,6 @@ static unsigned char tw_sense_table[][4] =
195#define TW_AEN_SMART_FAIL 0x000F 195#define TW_AEN_SMART_FAIL 0x000F
196#define TW_AEN_SBUF_FAIL 0x0024 196#define TW_AEN_SBUF_FAIL 0x0024
197 197
198/* Phase defines */
199#define TW_PHASE_INITIAL 0
200#define TW_PHASE_SINGLE 1
201#define TW_PHASE_SGLIST 2
202
203/* Misc defines */ 198/* Misc defines */
204#define TW_ALIGNMENT_6000 64 /* 64 bytes */ 199#define TW_ALIGNMENT_6000 64 /* 64 bytes */
205#define TW_ALIGNMENT_7000 4 /* 4 bytes */ 200#define TW_ALIGNMENT_7000 4 /* 4 bytes */