Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
fork

Configure Feed

Select the types of activity you want to include in your feed.

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>

authored by

Christoph Hellwig and committed by
James Bottomley
118c855b 9cd95546

+13 -49
+13 -44
drivers/scsi/3w-9xxx.c
··· 149 149 static int twa_scsiop_execute_scsi(TW_Device_Extension *tw_dev, int request_id, char *cdb, int use_sg, TW_SG_Entry *sglistarg); 150 150 static void twa_scsiop_execute_scsi_complete(TW_Device_Extension *tw_dev, int request_id); 151 151 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); 153 152 154 153 /* Functions */ 155 154 ··· 1339 1340 } 1340 1341 1341 1342 /* Now complete the io */ 1343 + scsi_dma_unmap(cmd); 1344 + cmd->scsi_done(cmd); 1342 1345 tw_dev->state[request_id] = TW_S_COMPLETED; 1343 1346 twa_free_request_id(tw_dev, request_id); 1344 1347 tw_dev->posted_request_count--; 1345 - tw_dev->srb[request_id]->scsi_done(tw_dev->srb[request_id]); 1346 - twa_unmap_scsi_data(tw_dev, request_id); 1347 1348 } 1348 1349 1349 1350 /* Check for valid status after each drain */ ··· 1400 1401 } 1401 1402 } 1402 1403 } /* End twa_load_sgl() */ 1403 - 1404 - /* This function will perform a pci-dma mapping for a scatter gather list */ 1405 - static int twa_map_scsi_sg_data(TW_Device_Extension *tw_dev, int request_id) 1406 - { 1407 - int use_sg; 1408 - struct scsi_cmnd *cmd = tw_dev->srb[request_id]; 1409 - 1410 - use_sg = scsi_dma_map(cmd); 1411 - if (!use_sg) 1412 - return 0; 1413 - else if (use_sg < 0) { 1414 - TW_PRINTK(tw_dev->host, TW_DRIVER, 0x1c, "Failed to map scatter gather list"); 1415 - return 0; 1416 - } 1417 - 1418 - cmd->SCp.phase = TW_PHASE_SGLIST; 1419 - cmd->SCp.have_data_in = use_sg; 1420 - 1421 - return use_sg; 1422 - } /* End twa_map_scsi_sg_data() */ 1423 1404 1424 1405 /* This function will poll for a response interrupt of a request */ 1425 1406 static int twa_poll_response(TW_Device_Extension *tw_dev, int request_id, int seconds) ··· 1579 1600 (tw_dev->state[i] != TW_S_INITIAL) && 1580 1601 (tw_dev->state[i] != TW_S_COMPLETED)) { 1581 1602 if (tw_dev->srb[i]) { 1582 - tw_dev->srb[i]->result = (DID_RESET << 16); 1583 - tw_dev->srb[i]->scsi_done(tw_dev->srb[i]); 1584 - twa_unmap_scsi_data(tw_dev, i); 1603 + struct scsi_cmnd *cmd = tw_dev->srb[i]; 1604 + 1605 + cmd->result = (DID_RESET << 16); 1606 + scsi_dma_unmap(cmd); 1607 + cmd->scsi_done(cmd); 1585 1608 } 1586 1609 } 1587 1610 } ··· 1762 1781 /* Save the scsi command for use by the ISR */ 1763 1782 tw_dev->srb[request_id] = SCpnt; 1764 1783 1765 - /* Initialize phase to zero */ 1766 - SCpnt->SCp.phase = TW_PHASE_INITIAL; 1767 - 1768 1784 retval = twa_scsiop_execute_scsi(tw_dev, request_id, NULL, 0, NULL); 1769 1785 switch (retval) { 1770 1786 case SCSI_MLQUEUE_HOST_BUSY: 1787 + scsi_dma_unmap(SCpnt); 1771 1788 twa_free_request_id(tw_dev, request_id); 1772 - twa_unmap_scsi_data(tw_dev, request_id); 1773 1789 break; 1774 1790 case 1: 1791 + SCpnt->result = (DID_ERROR << 16); 1792 + scsi_dma_unmap(SCpnt); 1793 + done(SCpnt); 1775 1794 tw_dev->state[request_id] = TW_S_COMPLETED; 1776 1795 twa_free_request_id(tw_dev, request_id); 1777 - twa_unmap_scsi_data(tw_dev, request_id); 1778 - SCpnt->result = (DID_ERROR << 16); 1779 - done(SCpnt); 1780 1796 retval = 0; 1781 1797 } 1782 1798 out: ··· 1841 1863 command_packet->sg_list[0].address = TW_CPU_TO_SGL(tw_dev->generic_buffer_phys[request_id]); 1842 1864 command_packet->sg_list[0].length = cpu_to_le32(TW_MIN_SGL_LENGTH); 1843 1865 } else { 1844 - sg_count = twa_map_scsi_sg_data(tw_dev, request_id); 1845 - if (sg_count == 0) 1866 + sg_count = scsi_dma_map(srb); 1867 + if (sg_count < 0) 1846 1868 goto out; 1847 1869 1848 1870 scsi_for_each_sg(srb, sg, sg_count, i) { ··· 1956 1978 (table[index].text != (char *)0)); index++); 1957 1979 return(table[index].text); 1958 1980 } /* End twa_string_lookup() */ 1959 - 1960 - /* This function will perform a pci-dma unmap */ 1961 - static void twa_unmap_scsi_data(TW_Device_Extension *tw_dev, int request_id) 1962 - { 1963 - struct scsi_cmnd *cmd = tw_dev->srb[request_id]; 1964 - 1965 - if (cmd->SCp.phase == TW_PHASE_SGLIST) 1966 - scsi_dma_unmap(cmd); 1967 - } /* End twa_unmap_scsi_data() */ 1968 1981 1969 1982 /* This function gets called when a disk is coming on-line */ 1970 1983 static int twa_slave_configure(struct scsi_device *sdev)
-5
drivers/scsi/3w-9xxx.h
··· 324 324 #define TW_CURRENT_DRIVER_BUILD 0 325 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 327 /* Misc defines */ 333 328 #define TW_9550SX_DRAIN_COMPLETED 0xFFFF 334 329 #define TW_SECTOR_SIZE 512