CC: [email protected] CC: [email protected] CC: [email protected] TO: Andy Shevchenko <[email protected]> CC: Ulf Hansson <[email protected]>
tree: git://git.kernel.org/pub/scm/linux/kernel/git/ulfh/mmc.git next head: 141edd9e99eb91393e8a4d97742bd98328bff724 commit: 9bd9c67ce7bf89d2c030f6d1f360669960bd2f98 [22/26] mmc: mmc_spi: Use write_or_read temporary variable in mmc_spi_data_do() :::::: branch date: 2 days ago :::::: commit date: 3 days ago config: i386-randconfig-c001-20211209 (https://download.01.org/0day-ci/archive/20211211/[email protected]/config) compiler: clang version 14.0.0 (https://github.com/llvm/llvm-project 097a1cb1d5ebb3a0ec4bcaed8ba3ff6a8e33c00a) reproduce (this is a W=1 build): wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross chmod +x ~/bin/make.cross # https://git.kernel.org/pub/scm/linux/kernel/git/ulfh/mmc.git/commit/?id=9bd9c67ce7bf89d2c030f6d1f360669960bd2f98 git remote add ulfh-mmc git://git.kernel.org/pub/scm/linux/kernel/git/ulfh/mmc.git git fetch --no-tags ulfh-mmc next git checkout 9bd9c67ce7bf89d2c030f6d1f360669960bd2f98 # save the config file to linux build tree COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross ARCH=i386 clang-analyzer If you fix the issue, kindly add following tag as appropriate Reported-by: kernel test robot <[email protected]> clang-analyzer warnings: (new ones prefixed by >>) ~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ include/linux/compiler.h:78:42: note: expanded from macro 'unlikely' # define unlikely(x) __builtin_expect(!!(x), 0) ^ include/linux/err.h:36:2: note: Returning zero, which participates in a condition later return IS_ERR_VALUE((unsigned long)ptr); ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ drivers/nvmem/core.c:1691:6: note: Returning from 'IS_ERR' if (IS_ERR(buf)) ^~~~~~~~~~~ drivers/nvmem/core.c:1691:2: note: Taking false branch if (IS_ERR(buf)) ^ drivers/nvmem/core.c:1698:6: note: Assuming 'nbits' is 0 if (nbits) ^~~~~ drivers/nvmem/core.c:1698:2: note: Taking false branch if (nbits) ^ drivers/nvmem/core.c:1701:11: note: The left operand of '>' is a garbage value if (*len > max_len) { ~~~~ ^ Suppressed 3 warnings (3 in non-user code). Use -header-filter=.* to display errors from all non-system headers. Use -system-headers to display errors from system headers as well. 3 warnings generated. Suppressed 3 warnings (3 in non-user code). Use -header-filter=.* to display errors from all non-system headers. Use -system-headers to display errors from system headers as well. 3 warnings generated. Suppressed 3 warnings (3 in non-user code). Use -header-filter=.* to display errors from all non-system headers. Use -system-headers to display errors from system headers as well. 13 warnings generated. drivers/most/core.c:175:2: warning: Call to function 'strcpy' is insecure as it does not provide bounding of the memory buffer. Replace unbounded copy functions with analogous functions that support length arguments such as 'strlcpy'. CWE-119 [clang-analyzer-security.insecureAPI.strcpy] strcpy(buf, ""); ^~~~~~ drivers/most/core.c:175:2: note: Call to function 'strcpy' is insecure as it does not provide bounding of the memory buffer. Replace unbounded copy functions with analogous functions that support length arguments such as 'strlcpy'. CWE-119 strcpy(buf, ""); ^~~~~~ drivers/most/core.c:177:3: warning: Call to function 'strcat' is insecure as it does not provide bounding of the memory buffer. Replace unbounded copy functions with analogous functions that support length arguments such as 'strlcat'. CWE-119 [clang-analyzer-security.insecureAPI.strcpy] strcat(buf, "rx "); ^~~~~~ drivers/most/core.c:177:3: note: Call to function 'strcat' is insecure as it does not provide bounding of the memory buffer. Replace unbounded copy functions with analogous functions that support length arguments such as 'strlcat'. CWE-119 strcat(buf, "rx "); ^~~~~~ drivers/most/core.c:179:3: warning: Call to function 'strcat' is insecure as it does not provide bounding of the memory buffer. Replace unbounded copy functions with analogous functions that support length arguments such as 'strlcat'. CWE-119 [clang-analyzer-security.insecureAPI.strcpy] strcat(buf, "tx "); ^~~~~~ drivers/most/core.c:179:3: note: Call to function 'strcat' is insecure as it does not provide bounding of the memory buffer. Replace unbounded copy functions with analogous functions that support length arguments such as 'strlcat'. CWE-119 strcat(buf, "tx "); ^~~~~~ drivers/most/core.c:180:2: warning: Call to function 'strcat' is insecure as it does not provide bounding of the memory buffer. Replace unbounded copy functions with analogous functions that support length arguments such as 'strlcat'. CWE-119 [clang-analyzer-security.insecureAPI.strcpy] strcat(buf, "\n"); ^~~~~~ drivers/most/core.c:180:2: note: Call to function 'strcat' is insecure as it does not provide bounding of the memory buffer. Replace unbounded copy functions with analogous functions that support length arguments such as 'strlcat'. CWE-119 strcat(buf, "\n"); ^~~~~~ drivers/most/core.c:191:2: warning: Call to function 'strcpy' is insecure as it does not provide bounding of the memory buffer. Replace unbounded copy functions with analogous functions that support length arguments such as 'strlcpy'. CWE-119 [clang-analyzer-security.insecureAPI.strcpy] strcpy(buf, ""); ^~~~~~ drivers/most/core.c:191:2: note: Call to function 'strcpy' is insecure as it does not provide bounding of the memory buffer. Replace unbounded copy functions with analogous functions that support length arguments such as 'strlcpy'. CWE-119 strcpy(buf, ""); ^~~~~~ drivers/most/core.c:193:3: warning: Call to function 'strcat' is insecure as it does not provide bounding of the memory buffer. Replace unbounded copy functions with analogous functions that support length arguments such as 'strlcat'. CWE-119 [clang-analyzer-security.insecureAPI.strcpy] strcat(buf, "control "); ^~~~~~ drivers/most/core.c:193:3: note: Call to function 'strcat' is insecure as it does not provide bounding of the memory buffer. Replace unbounded copy functions with analogous functions that support length arguments such as 'strlcat'. CWE-119 strcat(buf, "control "); ^~~~~~ drivers/most/core.c:195:3: warning: Call to function 'strcat' is insecure as it does not provide bounding of the memory buffer. Replace unbounded copy functions with analogous functions that support length arguments such as 'strlcat'. CWE-119 [clang-analyzer-security.insecureAPI.strcpy] strcat(buf, "async "); ^~~~~~ drivers/most/core.c:195:3: note: Call to function 'strcat' is insecure as it does not provide bounding of the memory buffer. Replace unbounded copy functions with analogous functions that support length arguments such as 'strlcat'. CWE-119 strcat(buf, "async "); ^~~~~~ drivers/most/core.c:197:3: warning: Call to function 'strcat' is insecure as it does not provide bounding of the memory buffer. Replace unbounded copy functions with analogous functions that support length arguments such as 'strlcat'. CWE-119 [clang-analyzer-security.insecureAPI.strcpy] strcat(buf, "sync "); ^~~~~~ drivers/most/core.c:197:3: note: Call to function 'strcat' is insecure as it does not provide bounding of the memory buffer. Replace unbounded copy functions with analogous functions that support length arguments such as 'strlcat'. CWE-119 strcat(buf, "sync "); ^~~~~~ drivers/most/core.c:199:3: warning: Call to function 'strcat' is insecure as it does not provide bounding of the memory buffer. Replace unbounded copy functions with analogous functions that support length arguments such as 'strlcat'. CWE-119 [clang-analyzer-security.insecureAPI.strcpy] strcat(buf, "isoc "); ^~~~~~ drivers/most/core.c:199:3: note: Call to function 'strcat' is insecure as it does not provide bounding of the memory buffer. Replace unbounded copy functions with analogous functions that support length arguments such as 'strlcat'. CWE-119 strcat(buf, "isoc "); ^~~~~~ drivers/most/core.c:200:2: warning: Call to function 'strcat' is insecure as it does not provide bounding of the memory buffer. Replace unbounded copy functions with analogous functions that support length arguments such as 'strlcat'. CWE-119 [clang-analyzer-security.insecureAPI.strcpy] strcat(buf, "\n"); ^~~~~~ drivers/most/core.c:200:2: note: Call to function 'strcat' is insecure as it does not provide bounding of the memory buffer. Replace unbounded copy functions with analogous functions that support length arguments such as 'strlcat'. CWE-119 strcat(buf, "\n"); ^~~~~~ Suppressed 3 warnings (3 in non-user code). Use -header-filter=.* to display errors from all non-system headers. Use -system-headers to display errors from system headers as well. 10 warnings generated. drivers/mmc/host/mmc_spi.c:354:4: warning: Value stored to 'end' is never read [clang-analyzer-deadcode.DeadStores] end = cp+1; ^ ~~~~ drivers/mmc/host/mmc_spi.c:354:4: note: Value stored to 'end' is never read end = cp+1; ^ ~~~~ >> drivers/mmc/host/mmc_spi.c:866:15: warning: Value stored to 'write_or_read' >> during its initialization is never read [clang-analyzer-deadcode.DeadStores] const char *write_or_read = (direction == DMA_TO_DEVICE) ? "write" : "read"; ^~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ drivers/mmc/host/mmc_spi.c:866:15: note: Value stored to 'write_or_read' during its initialization is never read const char *write_or_read = (direction == DMA_TO_DEVICE) ? "write" : "read"; ^~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ drivers/mmc/host/mmc_spi.c:1076:4: warning: Value stored to 'status' is never read [clang-analyzer-deadcode.DeadStores] status = mmc_spi_command_send(host, mrq, &stop, 0); ^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ drivers/mmc/host/mmc_spi.c:1076:4: note: Value stored to 'status' is never read status = mmc_spi_command_send(host, mrq, &stop, 0); ^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ drivers/mmc/host/mmc_spi.c:1083:4: warning: Value stored to 'status' is never read [clang-analyzer-deadcode.DeadStores] status = mmc_spi_command_send(host, mrq, mrq->stop, 0); ^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ drivers/mmc/host/mmc_spi.c:1083:4: note: Value stored to 'status' is never read status = mmc_spi_command_send(host, mrq, mrq->stop, 0); ^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ drivers/mmc/host/mmc_spi.c:1238:3: warning: Value stored to 'status' is never read [clang-analyzer-deadcode.DeadStores] status = spi_setup(host->spi); ^ ~~~~~~~~~~~~~~~~~~~~ drivers/mmc/host/mmc_spi.c:1238:3: note: Value stored to 'status' is never read status = spi_setup(host->spi); ^ ~~~~~~~~~~~~~~~~~~~~ Suppressed 5 warnings (5 in non-user code). Use -header-filter=.* to display errors from all non-system headers. Use -system-headers to display errors from system headers as well. 5 warnings generated. Suppressed 5 warnings (5 in non-user code). Use -header-filter=.* to display errors from all non-system headers. Use -system-headers to display errors from system headers as well. 4 warnings generated. Suppressed 4 warnings (4 in non-user code). Use -header-filter=.* to display errors from all non-system headers. Use -system-headers to display errors from system headers as well. 7 warnings generated. Suppressed 7 warnings (7 in non-user code). Use -header-filter=.* to display errors from all non-system headers. Use -system-headers to display errors from system headers as well. 20 warnings generated. Suppressed 20 warnings (8 in non-user code, 12 with check filters). Use -header-filter=.* to display errors from all non-system headers. Use -system-headers to display errors from system headers as well. 9 warnings generated. net/ethtool/ioctl.c:2117:4: warning: Called function pointer is null (null dereference) [clang-analyzer-core.CallAndMessage] ops->get_ethtool_phy_stats(dev, &stats, data); ^~~~~~~~~~~~~~~~~~~~~~~~~~ net/ethtool/ioctl.c:2087:6: note: Assuming 'phydev' is non-null if (!phydev && (!ops->get_ethtool_phy_stats || !ops->get_sset_count)) ^~~~~~~ net/ethtool/ioctl.c:2087:14: note: Left side of '&&' is false if (!phydev && (!ops->get_ethtool_phy_stats || !ops->get_sset_count)) ^ net/ethtool/ioctl.c:2090:11: note: Field 'phydev' is non-null if (dev->phydev && !ops->get_ethtool_phy_stats && ^ net/ethtool/ioctl.c:2090:6: note: Left side of '&&' is true if (dev->phydev && !ops->get_ethtool_phy_stats && ^ net/ethtool/ioctl.c:2090:21: note: Assuming field 'get_ethtool_phy_stats' is null if (dev->phydev && !ops->get_ethtool_phy_stats && ^~~~~~~~~~~~~~~~~~~~~~~~~~~ net/ethtool/ioctl.c:2090:6: note: Left side of '&&' is true if (dev->phydev && !ops->get_ethtool_phy_stats && ^ net/ethtool/ioctl.c:2091:6: note: Assuming 'phy_ops' is null phy_ops && phy_ops->get_sset_count) ^~~~~~~ net/ethtool/ioctl.c:2091:14: note: Left side of '&&' is false phy_ops && phy_ops->get_sset_count) ^ net/ethtool/ioctl.c:2095:6: note: Assuming 'n_stats' is >= 0 if (n_stats < 0) ^~~~~~~~~~~ net/ethtool/ioctl.c:2095:2: note: Taking false branch if (n_stats < 0) ^ net/ethtool/ioctl.c:2097:6: note: Assuming the condition is false if (n_stats > S32_MAX / sizeof(u64)) ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ net/ethtool/ioctl.c:2097:2: note: Taking false branch if (n_stats > S32_MAX / sizeof(u64)) ^ net/ethtool/ioctl.c:2099:15: note: Assuming 'n_stats' is not equal to 0 WARN_ON_ONCE(!n_stats); ^ include/asm-generic/bug.h:104:25: note: expanded from macro 'WARN_ON_ONCE' int __ret_warn_on = !!(condition); \ ^~~~~~~~~ net/ethtool/ioctl.c:2099:2: note: Taking false branch WARN_ON_ONCE(!n_stats); ^ include/asm-generic/bug.h:105:2: note: expanded from macro 'WARN_ON_ONCE' if (unlikely(__ret_warn_on)) \ ^ net/ethtool/ioctl.c:2101:6: note: Calling 'copy_from_user' if (copy_from_user(&stats, useraddr, sizeof(stats))) ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ include/linux/uaccess.h:191:6: note: Assuming the condition is false if (likely(check_copy_size(to, n, false))) ^ include/linux/compiler.h:77:38: note: expanded from macro 'likely' # define likely(x) __builtin_expect(!!(x), 1) ^~~~ include/linux/uaccess.h:191:2: note: Taking true branch if (likely(check_copy_size(to, n, false))) vim +/write_or_read +866 drivers/mmc/host/mmc_spi.c 15a0580ced081a David Brownell 2007-08-08 849 15a0580ced081a David Brownell 2007-08-08 850 /* 15a0580ced081a David Brownell 2007-08-08 851 * An MMC/SD data stage includes one or more blocks, optional CRCs, 15a0580ced081a David Brownell 2007-08-08 852 * and inline handshaking. That handhaking makes it unlike most 15a0580ced081a David Brownell 2007-08-08 853 * other SPI protocol stacks. 15a0580ced081a David Brownell 2007-08-08 854 */ 15a0580ced081a David Brownell 2007-08-08 855 static void 15a0580ced081a David Brownell 2007-08-08 856 mmc_spi_data_do(struct mmc_spi_host *host, struct mmc_command *cmd, 15a0580ced081a David Brownell 2007-08-08 857 struct mmc_data *data, u32 blk_size) 15a0580ced081a David Brownell 2007-08-08 858 { 15a0580ced081a David Brownell 2007-08-08 859 struct spi_device *spi = host->spi; 15a0580ced081a David Brownell 2007-08-08 860 struct device *dma_dev = host->dma_dev; 15a0580ced081a David Brownell 2007-08-08 861 struct spi_transfer *t; 9bd9c67ce7bf89 Andy Shevchenko 2021-12-06 862 enum dma_data_direction direction = mmc_get_dma_dir(data); 15a0580ced081a David Brownell 2007-08-08 863 struct scatterlist *sg; 15a0580ced081a David Brownell 2007-08-08 864 unsigned n_sg; 8eb6b82c80c8bd Andy Shevchenko 2021-12-06 865 bool multiple = (data->blocks > 1); 9bd9c67ce7bf89 Andy Shevchenko 2021-12-06 @866 const char *write_or_read = (direction == DMA_TO_DEVICE) ? "write" : "read"; 162350eb75fcb8 Matthew Fleming 2008-10-02 867 u32 clock_rate; 56e303ebeec7ef Wolfgang Muees 2009-04-07 868 unsigned long timeout; 15a0580ced081a David Brownell 2007-08-08 869 15a0580ced081a David Brownell 2007-08-08 870 mmc_spi_setup_data_message(host, multiple, direction); 15a0580ced081a David Brownell 2007-08-08 871 t = &host->t; 15a0580ced081a David Brownell 2007-08-08 872 162350eb75fcb8 Matthew Fleming 2008-10-02 873 if (t->speed_hz) 162350eb75fcb8 Matthew Fleming 2008-10-02 874 clock_rate = t->speed_hz; 162350eb75fcb8 Matthew Fleming 2008-10-02 875 else 162350eb75fcb8 Matthew Fleming 2008-10-02 876 clock_rate = spi->max_speed_hz; 162350eb75fcb8 Matthew Fleming 2008-10-02 877 81e41be92ad43b Tobias Schramm 2020-08-14 878 timeout = data->timeout_ns / 1000 + 56e303ebeec7ef Wolfgang Muees 2009-04-07 879 data->timeout_clks * 1000000 / clock_rate; 81e41be92ad43b Tobias Schramm 2020-08-14 880 timeout = usecs_to_jiffies((unsigned int)timeout) + 1; 162350eb75fcb8 Matthew Fleming 2008-10-02 881 15a0580ced081a David Brownell 2007-08-08 882 /* Handle scatterlist segments one at a time, with synch for 15a0580ced081a David Brownell 2007-08-08 883 * each 512-byte block 15a0580ced081a David Brownell 2007-08-08 884 */ b8deb11dbab03d Andy Shevchenko 2019-08-30 885 for_each_sg(data->sg, sg, data->sg_len, n_sg) { 15a0580ced081a David Brownell 2007-08-08 886 int status = 0; 15a0580ced081a David Brownell 2007-08-08 887 dma_addr_t dma_addr = 0; 15a0580ced081a David Brownell 2007-08-08 888 void *kmap_addr; 15a0580ced081a David Brownell 2007-08-08 889 unsigned length = sg->length; 15a0580ced081a David Brownell 2007-08-08 890 enum dma_data_direction dir = direction; 15a0580ced081a David Brownell 2007-08-08 891 15a0580ced081a David Brownell 2007-08-08 892 /* set up dma mapping for controller drivers that might 15a0580ced081a David Brownell 2007-08-08 893 * use DMA ... though they may fall back to PIO 15a0580ced081a David Brownell 2007-08-08 894 */ 15a0580ced081a David Brownell 2007-08-08 895 if (dma_dev) { 15a0580ced081a David Brownell 2007-08-08 896 /* never invalidate whole *shared* pages ... */ 15a0580ced081a David Brownell 2007-08-08 897 if ((sg->offset != 0 || length != PAGE_SIZE) 15a0580ced081a David Brownell 2007-08-08 898 && dir == DMA_FROM_DEVICE) 15a0580ced081a David Brownell 2007-08-08 899 dir = DMA_BIDIRECTIONAL; 15a0580ced081a David Brownell 2007-08-08 900 45711f1af6eff1 Jens Axboe 2007-10-22 901 dma_addr = dma_map_page(dma_dev, sg_page(sg), 0, 15a0580ced081a David Brownell 2007-08-08 902 PAGE_SIZE, dir); b00663124c76f6 Alexey Khoroshilov 2016-02-06 903 if (dma_mapping_error(dma_dev, dma_addr)) { b00663124c76f6 Alexey Khoroshilov 2016-02-06 904 data->error = -EFAULT; b00663124c76f6 Alexey Khoroshilov 2016-02-06 905 break; b00663124c76f6 Alexey Khoroshilov 2016-02-06 906 } 15a0580ced081a David Brownell 2007-08-08 907 if (direction == DMA_TO_DEVICE) 15a0580ced081a David Brownell 2007-08-08 908 t->tx_dma = dma_addr + sg->offset; 15a0580ced081a David Brownell 2007-08-08 909 else 15a0580ced081a David Brownell 2007-08-08 910 t->rx_dma = dma_addr + sg->offset; 15a0580ced081a David Brownell 2007-08-08 911 } 15a0580ced081a David Brownell 2007-08-08 912 15a0580ced081a David Brownell 2007-08-08 913 /* allow pio too; we don't allow highmem */ 45711f1af6eff1 Jens Axboe 2007-10-22 914 kmap_addr = kmap(sg_page(sg)); 15a0580ced081a David Brownell 2007-08-08 915 if (direction == DMA_TO_DEVICE) 15a0580ced081a David Brownell 2007-08-08 916 t->tx_buf = kmap_addr + sg->offset; 15a0580ced081a David Brownell 2007-08-08 917 else 15a0580ced081a David Brownell 2007-08-08 918 t->rx_buf = kmap_addr + sg->offset; 15a0580ced081a David Brownell 2007-08-08 919 15a0580ced081a David Brownell 2007-08-08 920 /* transfer each block, and update request status */ 15a0580ced081a David Brownell 2007-08-08 921 while (length) { 15a0580ced081a David Brownell 2007-08-08 922 t->len = min(length, blk_size); 15a0580ced081a David Brownell 2007-08-08 923 9bd9c67ce7bf89 Andy Shevchenko 2021-12-06 924 dev_dbg(&spi->dev, " %s block, %d bytes\n", write_or_read, t->len); 15a0580ced081a David Brownell 2007-08-08 925 15a0580ced081a David Brownell 2007-08-08 926 if (direction == DMA_TO_DEVICE) 162350eb75fcb8 Matthew Fleming 2008-10-02 927 status = mmc_spi_writeblock(host, t, timeout); 15a0580ced081a David Brownell 2007-08-08 928 else 162350eb75fcb8 Matthew Fleming 2008-10-02 929 status = mmc_spi_readblock(host, t, timeout); 15a0580ced081a David Brownell 2007-08-08 930 if (status < 0) 15a0580ced081a David Brownell 2007-08-08 931 break; 15a0580ced081a David Brownell 2007-08-08 932 15a0580ced081a David Brownell 2007-08-08 933 data->bytes_xfered += t->len; 15a0580ced081a David Brownell 2007-08-08 934 length -= t->len; 15a0580ced081a David Brownell 2007-08-08 935 15a0580ced081a David Brownell 2007-08-08 936 if (!multiple) 15a0580ced081a David Brownell 2007-08-08 937 break; 15a0580ced081a David Brownell 2007-08-08 938 } 15a0580ced081a David Brownell 2007-08-08 939 15a0580ced081a David Brownell 2007-08-08 940 /* discard mappings */ 15a0580ced081a David Brownell 2007-08-08 941 if (direction == DMA_FROM_DEVICE) 64a05fe645e27a Christoph Hellwig 2021-09-02 942 flush_dcache_page(sg_page(sg)); 45711f1af6eff1 Jens Axboe 2007-10-22 943 kunmap(sg_page(sg)); 15a0580ced081a David Brownell 2007-08-08 944 if (dma_dev) 15a0580ced081a David Brownell 2007-08-08 945 dma_unmap_page(dma_dev, dma_addr, PAGE_SIZE, dir); 15a0580ced081a David Brownell 2007-08-08 946 15a0580ced081a David Brownell 2007-08-08 947 if (status < 0) { 15a0580ced081a David Brownell 2007-08-08 948 data->error = status; 9bd9c67ce7bf89 Andy Shevchenko 2021-12-06 949 dev_dbg(&spi->dev, "%s status %d\n", write_or_read, status); 15a0580ced081a David Brownell 2007-08-08 950 break; 15a0580ced081a David Brownell 2007-08-08 951 } 15a0580ced081a David Brownell 2007-08-08 952 } 15a0580ced081a David Brownell 2007-08-08 953 15a0580ced081a David Brownell 2007-08-08 954 /* NOTE some docs describe an MMC-only SET_BLOCK_COUNT (CMD23) that 15a0580ced081a David Brownell 2007-08-08 955 * can be issued before multiblock writes. Unlike its more widely 15a0580ced081a David Brownell 2007-08-08 956 * documented analogue for SD cards (SET_WR_BLK_ERASE_COUNT, ACMD23), 15a0580ced081a David Brownell 2007-08-08 957 * that can affect the STOP_TRAN logic. Complete (and current) 15a0580ced081a David Brownell 2007-08-08 958 * MMC specs should sort that out before Linux starts using CMD23. 15a0580ced081a David Brownell 2007-08-08 959 */ 15a0580ced081a David Brownell 2007-08-08 960 if (direction == DMA_TO_DEVICE && multiple) { 15a0580ced081a David Brownell 2007-08-08 961 struct scratch *scratch = host->data; 15a0580ced081a David Brownell 2007-08-08 962 int tmp; 15a0580ced081a David Brownell 2007-08-08 963 const unsigned statlen = sizeof(scratch->status); 15a0580ced081a David Brownell 2007-08-08 964 91445d5eed6b19 Andy Shevchenko 2021-05-28 965 dev_dbg(&spi->dev, " STOP_TRAN\n"); 15a0580ced081a David Brownell 2007-08-08 966 15a0580ced081a David Brownell 2007-08-08 967 /* Tweak the per-block message we set up earlier by morphing 15a0580ced081a David Brownell 2007-08-08 968 * it to hold single buffer with the token followed by some 15a0580ced081a David Brownell 2007-08-08 969 * all-ones bytes ... skip N(BR) (0..1), scan the rest for 15a0580ced081a David Brownell 2007-08-08 970 * "not busy any longer" status, and leave chip selected. 15a0580ced081a David Brownell 2007-08-08 971 */ 15a0580ced081a David Brownell 2007-08-08 972 INIT_LIST_HEAD(&host->m.transfers); 15a0580ced081a David Brownell 2007-08-08 973 list_add(&host->early_status.transfer_list, 15a0580ced081a David Brownell 2007-08-08 974 &host->m.transfers); 15a0580ced081a David Brownell 2007-08-08 975 15a0580ced081a David Brownell 2007-08-08 976 memset(scratch->status, 0xff, statlen); 15a0580ced081a David Brownell 2007-08-08 977 scratch->status[0] = SPI_TOKEN_STOP_TRAN; 15a0580ced081a David Brownell 2007-08-08 978 15a0580ced081a David Brownell 2007-08-08 979 host->early_status.tx_buf = host->early_status.rx_buf; 15a0580ced081a David Brownell 2007-08-08 980 host->early_status.tx_dma = host->early_status.rx_dma; 15a0580ced081a David Brownell 2007-08-08 981 host->early_status.len = statlen; 15a0580ced081a David Brownell 2007-08-08 982 15a0580ced081a David Brownell 2007-08-08 983 if (host->dma_dev) 15a0580ced081a David Brownell 2007-08-08 984 dma_sync_single_for_device(host->dma_dev, 15a0580ced081a David Brownell 2007-08-08 985 host->data_dma, sizeof(*scratch), 15a0580ced081a David Brownell 2007-08-08 986 DMA_BIDIRECTIONAL); 15a0580ced081a David Brownell 2007-08-08 987 4751c1c74bc7b5 Ernst Schwab 2010-02-18 988 tmp = spi_sync_locked(spi, &host->m); 15a0580ced081a David Brownell 2007-08-08 989 15a0580ced081a David Brownell 2007-08-08 990 if (host->dma_dev) 15a0580ced081a David Brownell 2007-08-08 991 dma_sync_single_for_cpu(host->dma_dev, 15a0580ced081a David Brownell 2007-08-08 992 host->data_dma, sizeof(*scratch), 15a0580ced081a David Brownell 2007-08-08 993 DMA_BIDIRECTIONAL); 15a0580ced081a David Brownell 2007-08-08 994 15a0580ced081a David Brownell 2007-08-08 995 if (tmp < 0) { 15a0580ced081a David Brownell 2007-08-08 996 if (!data->error) 15a0580ced081a David Brownell 2007-08-08 997 data->error = tmp; 15a0580ced081a David Brownell 2007-08-08 998 return; 15a0580ced081a David Brownell 2007-08-08 999 } 15a0580ced081a David Brownell 2007-08-08 1000 15a0580ced081a David Brownell 2007-08-08 1001 /* Ideally we collected "not busy" status with one I/O, 15a0580ced081a David Brownell 2007-08-08 1002 * avoiding wasteful byte-at-a-time scanning... but more 15a0580ced081a David Brownell 2007-08-08 1003 * I/O is often needed. 15a0580ced081a David Brownell 2007-08-08 1004 */ 15a0580ced081a David Brownell 2007-08-08 1005 for (tmp = 2; tmp < statlen; tmp++) { 15a0580ced081a David Brownell 2007-08-08 1006 if (scratch->status[tmp] != 0) 15a0580ced081a David Brownell 2007-08-08 1007 return; 15a0580ced081a David Brownell 2007-08-08 1008 } 162350eb75fcb8 Matthew Fleming 2008-10-02 1009 tmp = mmc_spi_wait_unbusy(host, timeout); 15a0580ced081a David Brownell 2007-08-08 1010 if (tmp < 0 && !data->error) 15a0580ced081a David Brownell 2007-08-08 1011 data->error = tmp; 15a0580ced081a David Brownell 2007-08-08 1012 } 15a0580ced081a David Brownell 2007-08-08 1013 } 15a0580ced081a David Brownell 2007-08-08 1014 --- 0-DAY CI Kernel Test Service, Intel Corporation https://lists.01.org/hyperkitty/list/[email protected] _______________________________________________ kbuild mailing list -- [email protected] To unsubscribe send an email to [email protected]
