diff mbox

twa generates WARNING upon boot

Message ID 20150930160835.GA16534@infradead.org (mailing list archive)
State New, archived
Headers show

Commit Message

Christoph Hellwig Sept. 30, 2015, 4:08 p.m. UTC
Hi all,

I'd like to propose the following patch intead.  It uses a helper
to check the conditions for the copied commands, and also fixes another
place to use it which uses a different and I think buggy check:

This avoids the usage of scsi_cmnd.SCp which I'd like to get rid of
mid-term.

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Comments

James Bottomley Sept. 30, 2015, 4:15 p.m. UTC | #1
On Wed, 2015-09-30 at 09:08 -0700, Christoph Hellwig wrote:
> Hi all,
> 
> I'd like to propose the following patch intead.  It uses a helper
> to check the conditions for the copied commands, and also fixes another
> place to use it which uses a different and I think buggy check:
> 
> This avoids the usage of scsi_cmnd.SCp which I'd like to get rid of
> mid-term.
> 
> diff --git a/drivers/scsi/3w-9xxx.c b/drivers/scsi/3w-9xxx.c
> index add419d..74eac90 100644
> --- a/drivers/scsi/3w-9xxx.c
> +++ b/drivers/scsi/3w-9xxx.c
> @@ -212,6 +212,17 @@ static const struct file_operations twa_fops = {
>  	.llseek		= noop_llseek,
>  };
>  
> +/*
> + * The controllers use an inline buffer instead of a mapped SGL for small,
> + * single entry buffers.  Note that we treat a zero-length transfer like
> + * a mapped SGL.
> + */
> +static bool twa_command_mapped(struct scsi_cmnd *cmd)
> +{
> +	return scsi_sg_count(cmd) != 1 ||
> +		scsi_bufflen(cmd) >= TW_MIN_SGL_LENGTH;
> +}

I already thought of this.  Unfortunately, it fails if the internally
posted command is a single sector (the size of TW_MIN_SGL_LENGTH), which
is true for most of them.

James


--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
kernel test robot Sept. 30, 2015, 4:20 p.m. UTC | #2
Hi Christoph,

[auto build test results on v4.3-rc3 -- if it's inappropriate base, please ignore]

config: x86_64-allmodconfig (attached as .config)
reproduce:
  git checkout 6e392493504e88ec3b44596c22f08acf4eed11ee
  # save the attached .config to linux build tree
  make ARCH=x86_64 

All error/warnings (new ones prefixed by >>):

   drivers/scsi/3w-9xxx.c:394:15: sparse: cast to restricted __le16
   drivers/scsi/3w-9xxx.c:491:61: sparse: restricted __le64 degrades to integer
   drivers/scsi/3w-9xxx.c:491:61: sparse: restricted __le32 degrades to integer
   drivers/scsi/3w-9xxx.c:492:58: sparse: incorrect type in assignment (different base types)
   drivers/scsi/3w-9xxx.c:492:58:    expected unsigned int [unsigned] [usertype] length
   drivers/scsi/3w-9xxx.c:492:58:    got restricted __le32 [usertype] <noident>
   drivers/scsi/3w-9xxx.c:494:54: sparse: incorrect type in assignment (different base types)
   drivers/scsi/3w-9xxx.c:494:54:    expected unsigned short [unsigned] [usertype] parameter_count
   drivers/scsi/3w-9xxx.c:494:54:    got restricted __le16 [usertype] <noident>
   drivers/scsi/3w-9xxx.c:499:25: sparse: incorrect type in assignment (different base types)
   drivers/scsi/3w-9xxx.c:499:25:    expected unsigned short [unsigned] [usertype] table_id
   drivers/scsi/3w-9xxx.c:499:25:    got restricted __le16 [usertype] <noident>
   drivers/scsi/3w-9xxx.c:500:29: sparse: incorrect type in assignment (different base types)
   drivers/scsi/3w-9xxx.c:500:29:    expected unsigned short [unsigned] [usertype] parameter_id
   drivers/scsi/3w-9xxx.c:500:29:    got restricted __le16 [usertype] <noident>
   drivers/scsi/3w-9xxx.c:501:37: sparse: incorrect type in assignment (different base types)
   drivers/scsi/3w-9xxx.c:501:37:    expected unsigned short [unsigned] [usertype] parameter_size_bytes
   drivers/scsi/3w-9xxx.c:501:37:    got restricted __le16 [usertype] <noident>
   drivers/scsi/3w-9xxx.c:508:23: sparse: incorrect type in assignment (different base types)
   drivers/scsi/3w-9xxx.c:508:23:    expected unsigned int [unsigned] [assigned] [usertype] schedulertime
   drivers/scsi/3w-9xxx.c:508:23:    got restricted __le32 [usertype] <noident>
   drivers/scsi/3w-9xxx.c:996:17: sparse: cast to restricted __le16
   drivers/scsi/3w-9xxx.c:1129:41: sparse: incorrect type in assignment (different base types)
   drivers/scsi/3w-9xxx.c:1129:41:    expected unsigned short [unsigned] [usertype] message_credits
   drivers/scsi/3w-9xxx.c:1129:41:    got restricted __le16 [usertype] <noident>
   drivers/scsi/3w-9xxx.c:1135:34: sparse: incorrect type in assignment (different base types)
   drivers/scsi/3w-9xxx.c:1135:34:    expected unsigned int [unsigned] [usertype] features
   drivers/scsi/3w-9xxx.c:1135:34:    got restricted __le32 [usertype] <noident>
   drivers/scsi/3w-9xxx.c:1139:40: sparse: incorrect type in assignment (different base types)
   drivers/scsi/3w-9xxx.c:1139:40:    expected unsigned short [unsigned] [usertype] fw_srl
   drivers/scsi/3w-9xxx.c:1139:40:    got restricted __le16 [usertype] <noident>
   drivers/scsi/3w-9xxx.c:1140:44: sparse: incorrect type in assignment (different base types)
   drivers/scsi/3w-9xxx.c:1140:44:    expected unsigned short [unsigned] [usertype] fw_arch_id
   drivers/scsi/3w-9xxx.c:1140:44:    got restricted __le16 [usertype] <noident>
   drivers/scsi/3w-9xxx.c:1141:43: sparse: incorrect type in assignment (different base types)
   drivers/scsi/3w-9xxx.c:1141:43:    expected unsigned short [unsigned] [usertype] fw_branch
   drivers/scsi/3w-9xxx.c:1141:43:    got restricted __le16 [usertype] <noident>
   drivers/scsi/3w-9xxx.c:1142:42: sparse: incorrect type in assignment (different base types)
   drivers/scsi/3w-9xxx.c:1142:42:    expected unsigned short [unsigned] [usertype] fw_build
   drivers/scsi/3w-9xxx.c:1142:42:    got restricted __le16 [usertype] <noident>
   drivers/scsi/3w-9xxx.c:1154:43: sparse: cast to restricted __le16
   drivers/scsi/3w-9xxx.c:1155:47: sparse: cast to restricted __le16
   drivers/scsi/3w-9xxx.c:1156:46: sparse: cast to restricted __le16
   drivers/scsi/3w-9xxx.c:1157:45: sparse: cast to restricted __le16
   drivers/scsi/3w-9xxx.c:1158:48: sparse: cast to restricted __le32
   drivers/scsi/3w-9xxx.c:1390:46: sparse: incorrect type in assignment (different base types)
   drivers/scsi/3w-9xxx.c:1390:46:    expected unsigned short [unsigned] [usertype] request_id__lunl
   drivers/scsi/3w-9xxx.c:1390:46:    got restricted __le16 [usertype] <noident>
   drivers/scsi/3w-9xxx.c:1393:58: sparse: restricted __le64 degrades to integer
   drivers/scsi/3w-9xxx.c:1393:58: sparse: restricted __le32 degrades to integer
   drivers/scsi/3w-9xxx.c:1394:55: sparse: incorrect type in assignment (different base types)
   drivers/scsi/3w-9xxx.c:1394:55:    expected unsigned int [unsigned] [usertype] length
   drivers/scsi/3w-9xxx.c:1394:55:    got restricted __le32 [usertype] <noident>
   drivers/scsi/3w-9xxx.c:1396:47: sparse: incorrect type in assignment (different base types)
   drivers/scsi/3w-9xxx.c:1396:47:    expected unsigned short [unsigned] [usertype] sgl_entries__lunh
   drivers/scsi/3w-9xxx.c:1396:47:    got restricted __le16 [usertype] <noident>
   drivers/scsi/3w-9xxx.c:1408:40: sparse: restricted __le64 degrades to integer
   drivers/scsi/3w-9xxx.c:1408:40: sparse: restricted __le32 degrades to integer
   drivers/scsi/3w-9xxx.c:1409:37: sparse: incorrect type in assignment (different base types)
   drivers/scsi/3w-9xxx.c:1409:37:    expected unsigned int [unsigned] [usertype] length
   drivers/scsi/3w-9xxx.c:1409:37:    got restricted __le32 [usertype] <noident>
   drivers/scsi/3w-9xxx.c:1835:50: sparse: incorrect type in assignment (different base types)
   drivers/scsi/3w-9xxx.c:1835:50:    expected unsigned short [unsigned] [usertype] request_id__lunl
   drivers/scsi/3w-9xxx.c:1835:50:    got restricted __le16 [usertype] <noident>
   drivers/scsi/3w-9xxx.c:1838:50: sparse: incorrect type in assignment (different base types)
   drivers/scsi/3w-9xxx.c:1838:50:    expected unsigned short [unsigned] [usertype] request_id__lunl
   drivers/scsi/3w-9xxx.c:1838:50:    got restricted __le16 [usertype] <noident>
   drivers/scsi/3w-9xxx.c:1855:70: sparse: restricted __le64 degrades to integer
   drivers/scsi/3w-9xxx.c:1855:70: sparse: restricted __le32 degrades to integer
   drivers/scsi/3w-9xxx.c:1856:67: sparse: incorrect type in assignment (different base types)
   drivers/scsi/3w-9xxx.c:1856:67:    expected unsigned int [unsigned] [usertype] length
   drivers/scsi/3w-9xxx.c:1856:67:    got restricted __le32 [usertype] <noident>
   drivers/scsi/3w-9xxx.c:1863:78: sparse: restricted __le64 degrades to integer
   drivers/scsi/3w-9xxx.c:1863:78: sparse: restricted __le32 degrades to integer
   drivers/scsi/3w-9xxx.c:1864:75: sparse: incorrect type in assignment (different base types)
   drivers/scsi/3w-9xxx.c:1864:75:    expected unsigned int [unsigned] [usertype] length
   drivers/scsi/3w-9xxx.c:1864:75:    got restricted __le32 [usertype] <noident>
   drivers/scsi/3w-9xxx.c:1865:82: sparse: restricted __le64 degrades to integer
   drivers/scsi/3w-9xxx.c:1865:82: sparse: restricted __le32 degrades to integer
   drivers/scsi/3w-9xxx.c:1871:59: sparse: incorrect type in assignment (different base types)
   drivers/scsi/3w-9xxx.c:1871:59:    expected unsigned short [unsigned] [usertype] sgl_entries__lunh
   drivers/scsi/3w-9xxx.c:1871:59:    got restricted __le16 [usertype] <noident>
   drivers/scsi/3w-9xxx.c:1876:62: sparse: restricted __le64 degrades to integer
   drivers/scsi/3w-9xxx.c:1876:62: sparse: restricted __le32 degrades to integer
   drivers/scsi/3w-9xxx.c:1877:59: sparse: incorrect type in assignment (different base types)
   drivers/scsi/3w-9xxx.c:1877:59:    expected unsigned int [unsigned] [usertype] length
   drivers/scsi/3w-9xxx.c:1877:59:    got restricted __le32 [usertype] <noident>
   drivers/scsi/3w-9xxx.c:1878:66: sparse: restricted __le64 degrades to integer
   drivers/scsi/3w-9xxx.c:1878:66: sparse: restricted __le32 degrades to integer
   drivers/scsi/3w-9xxx.c:1883:51: sparse: incorrect type in assignment (different base types)
   drivers/scsi/3w-9xxx.c:1883:51:    expected unsigned short [unsigned] [usertype] sgl_entries__lunh
   drivers/scsi/3w-9xxx.c:1883:51:    got restricted __le16 [usertype] <noident>
   drivers/scsi/3w-9xxx.c:1922:33: sparse: undefined identifier 'srb'
   drivers/scsi/3w-9xxx.c:1781:40: sparse: undefined identifier 'cmd'
   drivers/scsi/3w-9xxx.c:1787:40: sparse: undefined identifier 'cmd'
   drivers/scsi/3w-9xxx.c: In function 'twa_scsi_queue_lck':
>> drivers/scsi/3w-9xxx.c:1781:26: error: 'cmd' undeclared (first use in this function)
      if (twa_command_mapped(cmd))
                             ^
   drivers/scsi/3w-9xxx.c:1781:26: note: each undeclared identifier is reported only once for each function it appears in
   drivers/scsi/3w-9xxx.c: In function 'twa_scsiop_execute_scsi_complete':
>> drivers/scsi/3w-9xxx.c:1922:26: error: 'srb' undeclared (first use in this function)
     if (!twa_command_mapped(srb) &&
                             ^

vim +/cmd +1781 drivers/scsi/3w-9xxx.c

  1775		/* Save the scsi command for use by the ISR */
  1776		tw_dev->srb[request_id] = SCpnt;
  1777	
  1778		retval = twa_scsiop_execute_scsi(tw_dev, request_id, NULL, 0, NULL);
  1779		switch (retval) {
  1780		case SCSI_MLQUEUE_HOST_BUSY:
> 1781			if (twa_command_mapped(cmd))
  1782				scsi_dma_unmap(SCpnt);
  1783			twa_free_request_id(tw_dev, request_id);
  1784			break;
  1785		case 1:
  1786			SCpnt->result = (DID_ERROR << 16);
  1787			if (twa_command_mapped(cmd))
  1788				scsi_dma_unmap(SCpnt);
  1789			done(SCpnt);
  1790			tw_dev->state[request_id] = TW_S_COMPLETED;
  1791			twa_free_request_id(tw_dev, request_id);
  1792			retval = 0;
  1793		}
  1794	out:
  1795		return retval;
  1796	} /* End twa_scsi_queue() */
  1797	
  1798	static DEF_SCSI_QCMD(twa_scsi_queue)
  1799	
  1800	/* This function hands scsi cdb's to the firmware */
  1801	static int twa_scsiop_execute_scsi(TW_Device_Extension *tw_dev, int request_id, char *cdb, int use_sg, TW_SG_Entry *sglistarg)
  1802	{
  1803		TW_Command_Full *full_command_packet;
  1804		TW_Command_Apache *command_packet;
  1805		u32 num_sectors = 0x0;
  1806		int i, sg_count;
  1807		struct scsi_cmnd *srb = NULL;
  1808		struct scatterlist *sglist = NULL, *sg;
  1809		int retval = 1;
  1810	
  1811		if (tw_dev->srb[request_id]) {
  1812			srb = tw_dev->srb[request_id];
  1813			if (scsi_sglist(srb))
  1814				sglist = scsi_sglist(srb);
  1815		}
  1816	
  1817		/* Initialize command packet */
  1818		full_command_packet = tw_dev->command_packet_virt[request_id];
  1819		full_command_packet->header.header_desc.size_header = 128;
  1820		full_command_packet->header.status_block.error = 0;
  1821		full_command_packet->header.status_block.severity__reserved = 0;
  1822	
  1823		command_packet = &full_command_packet->command.newcommand;
  1824		command_packet->status = 0;
  1825		command_packet->opcode__reserved = TW_OPRES_IN(0, TW_OP_EXECUTE_SCSI);
  1826	
  1827		/* We forced 16 byte cdb use earlier */
  1828		if (!cdb)
  1829			memcpy(command_packet->cdb, srb->cmnd, TW_MAX_CDB_LEN);
  1830		else
  1831			memcpy(command_packet->cdb, cdb, TW_MAX_CDB_LEN);
  1832	
  1833		if (srb) {
  1834			command_packet->unit = srb->device->id;
  1835			command_packet->request_id__lunl =
  1836				cpu_to_le16(TW_REQ_LUN_IN(srb->device->lun, request_id));
  1837		} else {
  1838			command_packet->request_id__lunl =
  1839				cpu_to_le16(TW_REQ_LUN_IN(0, request_id));
  1840			command_packet->unit = 0;
  1841		}
  1842	
  1843		command_packet->sgl_offset = 16;
  1844	
  1845		if (!sglistarg) {
  1846			/* Map sglist from scsi layer to cmd packet */
  1847	
  1848			if (scsi_sg_count(srb)) {
  1849				if (!twa_command_mapped(srb)) {
  1850					if (srb->sc_data_direction == DMA_TO_DEVICE ||
  1851					    srb->sc_data_direction == DMA_BIDIRECTIONAL)
  1852						scsi_sg_copy_to_buffer(srb,
  1853								       tw_dev->generic_buffer_virt[request_id],
  1854								       TW_SECTOR_SIZE);
  1855					command_packet->sg_list[0].address = TW_CPU_TO_SGL(tw_dev->generic_buffer_phys[request_id]);
  1856					command_packet->sg_list[0].length = cpu_to_le32(TW_MIN_SGL_LENGTH);
  1857				} else {
  1858					sg_count = scsi_dma_map(srb);
  1859					if (sg_count < 0)
  1860						goto out;
  1861	
  1862					scsi_for_each_sg(srb, sg, sg_count, i) {
  1863						command_packet->sg_list[i].address = TW_CPU_TO_SGL(sg_dma_address(sg));
  1864						command_packet->sg_list[i].length = cpu_to_le32(sg_dma_len(sg));
  1865						if (command_packet->sg_list[i].address & TW_CPU_TO_SGL(TW_ALIGNMENT_9000_SGL)) {
  1866							TW_PRINTK(tw_dev->host, TW_DRIVER, 0x2e, "Found unaligned sgl address during execute scsi");
  1867							goto out;
  1868						}
  1869					}
  1870				}
  1871				command_packet->sgl_entries__lunh = cpu_to_le16(TW_REQ_LUN_IN((srb->device->lun >> 4), scsi_sg_count(tw_dev->srb[request_id])));
  1872			}
  1873		} else {
  1874			/* Internal cdb post */
  1875			for (i = 0; i < use_sg; i++) {
  1876				command_packet->sg_list[i].address = TW_CPU_TO_SGL(sglistarg[i].address);
  1877				command_packet->sg_list[i].length = cpu_to_le32(sglistarg[i].length);
> 1878				if (command_packet->sg_list[i].address & TW_CPU_TO_SGL(TW_ALIGNMENT_9000_SGL)) {
  1879					TW_PRINTK(tw_dev->host, TW_DRIVER, 0x2f, "Found unaligned sgl address during internal post");
  1880					goto out;
  1881				}
  1882			}
  1883			command_packet->sgl_entries__lunh = cpu_to_le16(TW_REQ_LUN_IN(0, use_sg));
  1884		}
  1885	
  1886		if (srb) {
  1887			if (srb->cmnd[0] == READ_6 || srb->cmnd[0] == WRITE_6)
  1888				num_sectors = (u32)srb->cmnd[4];
  1889	
  1890			if (srb->cmnd[0] == READ_10 || srb->cmnd[0] == WRITE_10)
  1891				num_sectors = (u32)srb->cmnd[8] | ((u32)srb->cmnd[7] << 8);
  1892		}
  1893	
  1894		/* Update sector statistic */
  1895		tw_dev->sector_count = num_sectors;
  1896		if (tw_dev->sector_count > tw_dev->max_sector_count)
  1897			tw_dev->max_sector_count = tw_dev->sector_count;
  1898	
  1899		/* Update SG statistics */
  1900		if (srb) {
  1901			tw_dev->sgl_entries = scsi_sg_count(tw_dev->srb[request_id]);
  1902			if (tw_dev->sgl_entries > tw_dev->max_sgl_entries)
  1903				tw_dev->max_sgl_entries = tw_dev->sgl_entries;
  1904		}
  1905	
  1906		/* Now post the command to the board */
  1907		if (srb) {
  1908			retval = twa_post_command_packet(tw_dev, request_id, 0);
  1909		} else {
  1910			twa_post_command_packet(tw_dev, request_id, 1);
  1911			retval = 0;
  1912		}
  1913	out:
  1914		return retval;
  1915	} /* End twa_scsiop_execute_scsi() */
  1916	
  1917	/* This function completes an execute scsi operation */
  1918	static void twa_scsiop_execute_scsi_complete(TW_Device_Extension *tw_dev, int request_id)
  1919	{
  1920		struct scsi_cmnd *cmd = tw_dev->srb[request_id];
  1921	
> 1922		if (!twa_command_mapped(srb) &&
  1923		    (cmd->sc_data_direction == DMA_FROM_DEVICE ||
  1924		     cmd->sc_data_direction == DMA_BIDIRECTIONAL)) {
  1925			if (scsi_sg_count(cmd) == 1) {

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation
Christoph Hellwig Sept. 30, 2015, 4:31 p.m. UTC | #3
On Wed, Sep 30, 2015 at 09:15:30AM -0700, James Bottomley wrote:
> I already thought of this.  Unfortunately, it fails if the internally
> posted command is a single sector (the size of TW_MIN_SGL_LENGTH), which
> is true for most of them.

Which internally posted command?  All the usual suspects set
tw_dev->srb[request_id] to NULL and thus neither have a scsi_cmnd
associated with them, nor will they ever reach a code path where we call
twa_command_mapped().
--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
James Bottomley Sept. 30, 2015, 4:36 p.m. UTC | #4
On Wed, 2015-09-30 at 09:31 -0700, Christoph Hellwig wrote:
> On Wed, Sep 30, 2015 at 09:15:30AM -0700, James Bottomley wrote:
> > I already thought of this.  Unfortunately, it fails if the internally
> > posted command is a single sector (the size of TW_MIN_SGL_LENGTH), which
> > is true for most of them.
> 
> Which internally posted command?  All the usual suspects set
> tw_dev->srb[request_id] to NULL and thus neither have a scsi_cmnd
> associated with them, nor will they ever reach a code path where we call
> twa_command_mapped().

Are you sure?  The init trace that kicked all this off still has
twa_init in it.  I was figuring the most likely suspect is
twa_get_param().

James


--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Christoph Hellwig Sept. 30, 2015, 4:41 p.m. UTC | #5
On Wed, Sep 30, 2015 at 09:36:24AM -0700, James Bottomley wrote:
> Are you sure?  The init trace that kicked all this off still has
> twa_init in it.  I was figuring the most likely suspect is
> twa_get_param().

That one doesnt set ->srb at all, but given that it's called before
any SCSI commands can sent ->srb will be all NULL.  It certainly
doesn't use a scsi_cmnd anywhere and does not expect to hit any
code path calling scsi_dma_unmap.  If it ends up there it's a bad bug
and would blow up a lot more spectacularly.
--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
James Bottomley Sept. 30, 2015, 4:43 p.m. UTC | #6
On Wed, 2015-09-30 at 09:41 -0700, Christoph Hellwig wrote:
> On Wed, Sep 30, 2015 at 09:36:24AM -0700, James Bottomley wrote:
> > Are you sure?  The init trace that kicked all this off still has
> > twa_init in it.  I was figuring the most likely suspect is
> > twa_get_param().
> 
> That one doesnt set ->srb at all, but given that it's called before
> any SCSI commands can sent ->srb will be all NULL.  It certainly
> doesn't use a scsi_cmnd anywhere and does not expect to hit any
> code path calling scsi_dma_unmap.  If it ends up there it's a bad bug
> and would blow up a lot more spectacularly.

OK, post a compilable version of the patch and lets get the reporter to
try it out.  Not resurrecting esoteric flags suits me.

James


--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
diff mbox

Patch

diff --git a/drivers/scsi/3w-9xxx.c b/drivers/scsi/3w-9xxx.c
index add419d..74eac90 100644
--- a/drivers/scsi/3w-9xxx.c
+++ b/drivers/scsi/3w-9xxx.c
@@ -212,6 +212,17 @@  static const struct file_operations twa_fops = {
 	.llseek		= noop_llseek,
 };
 
+/*
+ * The controllers use an inline buffer instead of a mapped SGL for small,
+ * single entry buffers.  Note that we treat a zero-length transfer like
+ * a mapped SGL.
+ */
+static bool twa_command_mapped(struct scsi_cmnd *cmd)
+{
+	return scsi_sg_count(cmd) != 1 ||
+		scsi_bufflen(cmd) >= TW_MIN_SGL_LENGTH;
+}
+
 /* This function will complete an aen request from the isr */
 static int twa_aen_complete(TW_Device_Extension *tw_dev, int request_id)
 {
@@ -1339,7 +1350,8 @@  static irqreturn_t twa_interrupt(int irq, void *dev_instance)
 				}
 
 				/* Now complete the io */
-				scsi_dma_unmap(cmd);
+				if (twa_command_mapped(cmd))
+					scsi_dma_unmap(cmd);
 				cmd->scsi_done(cmd);
 				tw_dev->state[request_id] = TW_S_COMPLETED;
 				twa_free_request_id(tw_dev, request_id);
@@ -1582,7 +1594,8 @@  static int twa_reset_device_extension(TW_Device_Extension *tw_dev)
 				struct scsi_cmnd *cmd = tw_dev->srb[i];
 
 				cmd->result = (DID_RESET << 16);
-				scsi_dma_unmap(cmd);
+				if (twa_command_mapped(cmd))
+					scsi_dma_unmap(cmd);
 				cmd->scsi_done(cmd);
 			}
 		}
@@ -1765,12 +1778,14 @@  static int twa_scsi_queue_lck(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_
 	retval = twa_scsiop_execute_scsi(tw_dev, request_id, NULL, 0, NULL);
 	switch (retval) {
 	case SCSI_MLQUEUE_HOST_BUSY:
-		scsi_dma_unmap(SCpnt);
+		if (twa_command_mapped(cmd))
+			scsi_dma_unmap(SCpnt);
 		twa_free_request_id(tw_dev, request_id);
 		break;
 	case 1:
 		SCpnt->result = (DID_ERROR << 16);
-		scsi_dma_unmap(SCpnt);
+		if (twa_command_mapped(cmd))
+			scsi_dma_unmap(SCpnt);
 		done(SCpnt);
 		tw_dev->state[request_id] = TW_S_COMPLETED;
 		twa_free_request_id(tw_dev, request_id);
@@ -1831,8 +1846,7 @@  static int twa_scsiop_execute_scsi(TW_Device_Extension *tw_dev, int request_id,
 		/* Map sglist from scsi layer to cmd packet */
 
 		if (scsi_sg_count(srb)) {
-			if ((scsi_sg_count(srb) == 1) &&
-			    (scsi_bufflen(srb) < TW_MIN_SGL_LENGTH)) {
+			if (!twa_command_mapped(srb)) {
 				if (srb->sc_data_direction == DMA_TO_DEVICE ||
 				    srb->sc_data_direction == DMA_BIDIRECTIONAL)
 					scsi_sg_copy_to_buffer(srb,
@@ -1905,7 +1919,7 @@  static void twa_scsiop_execute_scsi_complete(TW_Device_Extension *tw_dev, int re
 {
 	struct scsi_cmnd *cmd = tw_dev->srb[request_id];
 
-	if (scsi_bufflen(cmd) < TW_MIN_SGL_LENGTH &&
+	if (!twa_command_mapped(srb) &&
 	    (cmd->sc_data_direction == DMA_FROM_DEVICE ||
 	     cmd->sc_data_direction == DMA_BIDIRECTIONAL)) {
 		if (scsi_sg_count(cmd) == 1) {