Skip to content

Commit 118c855

Browse files
Christoph HellwigJames Bottomley
authored andcommitted
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>
1 parent 9cd9554 commit 118c855

File tree

2 files changed

+13
-49
lines changed

2 files changed

+13
-49
lines changed

drivers/scsi/3w-9xxx.c

Lines changed: 13 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,6 @@ static int twa_reset_sequence(TW_Device_Extension *tw_dev, int soft_reset);
149149
static int twa_scsiop_execute_scsi(TW_Device_Extension *tw_dev, int request_id, char *cdb, int use_sg, TW_SG_Entry *sglistarg);
150150
static void twa_scsiop_execute_scsi_complete(TW_Device_Extension *tw_dev, int request_id);
151151
static char *twa_string_lookup(twa_message_type *table, unsigned int aen_code);
152-
static void twa_unmap_scsi_data(TW_Device_Extension *tw_dev, int request_id);
153152

154153
/* Functions */
155154

@@ -1340,11 +1339,11 @@ static irqreturn_t twa_interrupt(int irq, void *dev_instance)
13401339
}
13411340

13421341
/* Now complete the io */
1342+
scsi_dma_unmap(cmd);
1343+
cmd->scsi_done(cmd);
13431344
tw_dev->state[request_id] = TW_S_COMPLETED;
13441345
twa_free_request_id(tw_dev, request_id);
13451346
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);
13481347
}
13491348

13501349
/* 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
14021401
}
14031402
} /* End twa_load_sgl() */
14041403

1405-
/* This function will perform a pci-dma mapping for a scatter gather list */
1406-
static 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-
14251404
/* This function will poll for a response interrupt of a request */
14261405
static int twa_poll_response(TW_Device_Extension *tw_dev, int request_id, int seconds)
14271406
{
@@ -1600,9 +1579,11 @@ static int twa_reset_device_extension(TW_Device_Extension *tw_dev)
16001579
(tw_dev->state[i] != TW_S_INITIAL) &&
16011580
(tw_dev->state[i] != TW_S_COMPLETED)) {
16021581
if (tw_dev->srb[i]) {
1603-
tw_dev->srb[i]->result = (DID_RESET << 16);
1604-
tw_dev->srb[i]->scsi_done(tw_dev->srb[i]);
1605-
twa_unmap_scsi_data(tw_dev, i);
1582+
struct scsi_cmnd *cmd = tw_dev->srb[i];
1583+
1584+
cmd->result = (DID_RESET << 16);
1585+
scsi_dma_unmap(cmd);
1586+
cmd->scsi_done(cmd);
16061587
}
16071588
}
16081589
}
@@ -1781,21 +1762,18 @@ static int twa_scsi_queue_lck(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_
17811762
/* Save the scsi command for use by the ISR */
17821763
tw_dev->srb[request_id] = SCpnt;
17831764

1784-
/* Initialize phase to zero */
1785-
SCpnt->SCp.phase = TW_PHASE_INITIAL;
1786-
17871765
retval = twa_scsiop_execute_scsi(tw_dev, request_id, NULL, 0, NULL);
17881766
switch (retval) {
17891767
case SCSI_MLQUEUE_HOST_BUSY:
1768+
scsi_dma_unmap(SCpnt);
17901769
twa_free_request_id(tw_dev, request_id);
1791-
twa_unmap_scsi_data(tw_dev, request_id);
17921770
break;
17931771
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);
17971772
SCpnt->result = (DID_ERROR << 16);
1773+
scsi_dma_unmap(SCpnt);
17981774
done(SCpnt);
1775+
tw_dev->state[request_id] = TW_S_COMPLETED;
1776+
twa_free_request_id(tw_dev, request_id);
17991777
retval = 0;
18001778
}
18011779
out:
@@ -1863,8 +1841,8 @@ static int twa_scsiop_execute_scsi(TW_Device_Extension *tw_dev, int request_id,
18631841
command_packet->sg_list[0].address = TW_CPU_TO_SGL(tw_dev->generic_buffer_phys[request_id]);
18641842
command_packet->sg_list[0].length = cpu_to_le32(TW_MIN_SGL_LENGTH);
18651843
} else {
1866-
sg_count = twa_map_scsi_sg_data(tw_dev, request_id);
1867-
if (sg_count == 0)
1844+
sg_count = scsi_dma_map(srb);
1845+
if (sg_count < 0)
18681846
goto out;
18691847

18701848
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)
19791957
return(table[index].text);
19801958
} /* End twa_string_lookup() */
19811959

1982-
/* This function will perform a pci-dma unmap */
1983-
static 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-
19911960
/* This function gets called when a disk is coming on-line */
19921961
static int twa_slave_configure(struct scsi_device *sdev)
19931962
{

drivers/scsi/3w-9xxx.h

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -324,11 +324,6 @@ static twa_message_type twa_error_table[] = {
324324
#define TW_CURRENT_DRIVER_BUILD 0
325325
#define TW_CURRENT_DRIVER_BRANCH 0
326326

327-
/* Phase defines */
328-
#define TW_PHASE_INITIAL 0
329-
#define TW_PHASE_SINGLE 1
330-
#define TW_PHASE_SGLIST 2
331-
332327
/* Misc defines */
333328
#define TW_9550SX_DRAIN_COMPLETED 0xFFFF
334329
#define TW_SECTOR_SIZE 512

0 commit comments

Comments
 (0)