[v3,2/2] spi: dw: Add dma controller capability checks

Message ID 20230326173511.710749-3-joychakr@google.com
State New
Headers
Series spi: dw: DW SPI DMA Driver updates |

Commit Message

Joy Chakraborty March 26, 2023, 5:35 p.m. UTC
  Check capabilities of DMA controller during init to make sure it is
capable of handling MEM2DEV for tx channel, DEV2MEM for rx channel
and store addr_width capabilities to check per transfer to make sure the
bits/word requirement can be met for that transfer.

Signed-off-by: Joy Chakraborty <joychakr@google.com>
---
 drivers/spi/spi-dw-dma.c | 54 ++++++++++++++++++++++++++++++++--------
 drivers/spi/spi-dw.h     |  1 +
 2 files changed, 44 insertions(+), 11 deletions(-)
  

Comments

kernel test robot March 26, 2023, 11:28 p.m. UTC | #1
Hi Joy,

Thank you for the patch! Perhaps something to improve:

[auto build test WARNING on broonie-spi/for-next]
[also build test WARNING on linus/master v6.3-rc4 next-20230324]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Joy-Chakraborty/spi-dw-Add-32-bpw-support-to-DW-DMA-Controller/20230327-013645
base:   https://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi.git for-next
patch link:    https://lore.kernel.org/r/20230326173511.710749-3-joychakr%40google.com
patch subject: [PATCH v3 2/2] spi: dw: Add dma controller capability checks
config: arc-randconfig-s041-20230326 (https://download.01.org/0day-ci/archive/20230327/202303270715.w9sMJhIh-lkp@intel.com/config)
compiler: arceb-elf-gcc (GCC) 12.1.0
reproduce:
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # apt-get install sparse
        # sparse version: v0.6.4-39-gce1a6720-dirty
        # https://github.com/intel-lab-lkp/linux/commit/9962c1acd23cb0766a09948c1bee4f29950b8a96
        git remote add linux-review https://github.com/intel-lab-lkp/linux
        git fetch --no-tags linux-review Joy-Chakraborty/spi-dw-Add-32-bpw-support-to-DW-DMA-Controller/20230327-013645
        git checkout 9962c1acd23cb0766a09948c1bee4f29950b8a96
        # save the config file
        mkdir build_dir && cp config build_dir/.config
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-12.1.0 make.cross C=1 CF='-fdiagnostic-prefix -D__CHECK_ENDIAN__' O=build_dir ARCH=arc olddefconfig
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-12.1.0 make.cross C=1 CF='-fdiagnostic-prefix -D__CHECK_ENDIAN__' O=build_dir ARCH=arc SHELL=/bin/bash drivers/spi/

If you fix the issue, kindly add following tag where applicable
| Reported-by: kernel test robot <lkp@intel.com>
| Link: https://lore.kernel.org/oe-kbuild-all/202303270715.w9sMJhIh-lkp@intel.com/

sparse warnings: (new ones prefixed by >>)
>> drivers/spi/spi-dw-dma.c:241:56: sparse: sparse: marked inline, but without a definition

vim +241 drivers/spi/spi-dw-dma.c

f89a6d8f43ebe9 drivers/spi/spi-dw-mid.c Andy Shevchenko 2015-03-09  240  
57784411728ff4 drivers/spi/spi-dw-dma.c Serge Semin     2020-05-29 @241  static enum dma_slave_buswidth dw_spi_dma_convert_width(u8 n_bytes)
57784411728ff4 drivers/spi/spi-dw-dma.c Serge Semin     2020-05-29  242  {
80de96dae70648 drivers/spi/spi-dw-dma.c Joy Chakraborty 2023-03-26  243  	switch (n_bytes) {
80de96dae70648 drivers/spi/spi-dw-dma.c Joy Chakraborty 2023-03-26  244  	case 1:
e31abce778bc05 drivers/spi/spi-dw-mid.c Andy Shevchenko 2015-03-09  245  		return DMA_SLAVE_BUSWIDTH_1_BYTE;
80de96dae70648 drivers/spi/spi-dw-dma.c Joy Chakraborty 2023-03-26  246  	case 2:
e31abce778bc05 drivers/spi/spi-dw-mid.c Andy Shevchenko 2015-03-09  247  		return DMA_SLAVE_BUSWIDTH_2_BYTES;
80de96dae70648 drivers/spi/spi-dw-dma.c Joy Chakraborty 2023-03-26  248  	case 3:
80de96dae70648 drivers/spi/spi-dw-dma.c Joy Chakraborty 2023-03-26  249  	case 4:
80de96dae70648 drivers/spi/spi-dw-dma.c Joy Chakraborty 2023-03-26  250  		return DMA_SLAVE_BUSWIDTH_4_BYTES;
80de96dae70648 drivers/spi/spi-dw-dma.c Joy Chakraborty 2023-03-26  251  	default:
e31abce778bc05 drivers/spi/spi-dw-mid.c Andy Shevchenko 2015-03-09  252  		return DMA_SLAVE_BUSWIDTH_UNDEFINED;
e31abce778bc05 drivers/spi/spi-dw-mid.c Andy Shevchenko 2015-03-09  253  	}
80de96dae70648 drivers/spi/spi-dw-dma.c Joy Chakraborty 2023-03-26  254  }
e31abce778bc05 drivers/spi/spi-dw-mid.c Andy Shevchenko 2015-03-09  255
  
Joy Chakraborty March 27, 2023, 4:03 a.m. UTC | #2
Hi Serge(y)

On Mon, Mar 27, 2023 at 4:59 AM kernel test robot <lkp@intel.com> wrote:
>
> Hi Joy,
>
> Thank you for the patch! Perhaps something to improve:
>
> [auto build test WARNING on broonie-spi/for-next]
> [also build test WARNING on linus/master v6.3-rc4 next-20230324]
> [If your patch is applied to the wrong git tree, kindly drop us a note.
> And when submitting patch, we suggest to use '--base' as documented in
> https://git-scm.com/docs/git-format-patch#_base_tree_information]
>
> url:    https://github.com/intel-lab-lkp/linux/commits/Joy-Chakraborty/spi-dw-Add-32-bpw-support-to-DW-DMA-Controller/20230327-013645
> base:   https://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi.git for-next
> patch link:    https://lore.kernel.org/r/20230326173511.710749-3-joychakr%40google.com
> patch subject: [PATCH v3 2/2] spi: dw: Add dma controller capability checks
> config: arc-randconfig-s041-20230326 (https://download.01.org/0day-ci/archive/20230327/202303270715.w9sMJhIh-lkp@intel.com/config)
> compiler: arceb-elf-gcc (GCC) 12.1.0
> reproduce:
>         wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
>         chmod +x ~/bin/make.cross
>         # apt-get install sparse
>         # sparse version: v0.6.4-39-gce1a6720-dirty
>         # https://github.com/intel-lab-lkp/linux/commit/9962c1acd23cb0766a09948c1bee4f29950b8a96
>         git remote add linux-review https://github.com/intel-lab-lkp/linux
>         git fetch --no-tags linux-review Joy-Chakraborty/spi-dw-Add-32-bpw-support-to-DW-DMA-Controller/20230327-013645
>         git checkout 9962c1acd23cb0766a09948c1bee4f29950b8a96
>         # save the config file
>         mkdir build_dir && cp config build_dir/.config
>         COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-12.1.0 make.cross C=1 CF='-fdiagnostic-prefix -D__CHECK_ENDIAN__' O=build_dir ARCH=arc olddefconfig
>         COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-12.1.0 make.cross C=1 CF='-fdiagnostic-prefix -D__CHECK_ENDIAN__' O=build_dir ARCH=arc SHELL=/bin/bash drivers/spi/
>
> If you fix the issue, kindly add following tag where applicable
> | Reported-by: kernel test robot <lkp@intel.com>
> | Link: https://lore.kernel.org/oe-kbuild-all/202303270715.w9sMJhIh-lkp@intel.com/
>
> sparse warnings: (new ones prefixed by >>)
> >> drivers/spi/spi-dw-dma.c:241:56: sparse: sparse: marked inline, but without a definition
>
> vim +241 drivers/spi/spi-dw-dma.c

Indeed I have marked it inline in the function prototype.
Removing the same and sending a V4 patch.

>
> f89a6d8f43ebe9 drivers/spi/spi-dw-mid.c Andy Shevchenko 2015-03-09  240
> 57784411728ff4 drivers/spi/spi-dw-dma.c Serge Semin     2020-05-29 @241  static enum dma_slave_buswidth dw_spi_dma_convert_width(u8 n_bytes)
> 57784411728ff4 drivers/spi/spi-dw-dma.c Serge Semin     2020-05-29  242  {
> 80de96dae70648 drivers/spi/spi-dw-dma.c Joy Chakraborty 2023-03-26  243         switch (n_bytes) {
> 80de96dae70648 drivers/spi/spi-dw-dma.c Joy Chakraborty 2023-03-26  244         case 1:
> e31abce778bc05 drivers/spi/spi-dw-mid.c Andy Shevchenko 2015-03-09  245                 return DMA_SLAVE_BUSWIDTH_1_BYTE;
> 80de96dae70648 drivers/spi/spi-dw-dma.c Joy Chakraborty 2023-03-26  246         case 2:
> e31abce778bc05 drivers/spi/spi-dw-mid.c Andy Shevchenko 2015-03-09  247                 return DMA_SLAVE_BUSWIDTH_2_BYTES;
> 80de96dae70648 drivers/spi/spi-dw-dma.c Joy Chakraborty 2023-03-26  248         case 3:
> 80de96dae70648 drivers/spi/spi-dw-dma.c Joy Chakraborty 2023-03-26  249         case 4:
> 80de96dae70648 drivers/spi/spi-dw-dma.c Joy Chakraborty 2023-03-26  250                 return DMA_SLAVE_BUSWIDTH_4_BYTES;
> 80de96dae70648 drivers/spi/spi-dw-dma.c Joy Chakraborty 2023-03-26  251         default:
> e31abce778bc05 drivers/spi/spi-dw-mid.c Andy Shevchenko 2015-03-09  252                 return DMA_SLAVE_BUSWIDTH_UNDEFINED;
> e31abce778bc05 drivers/spi/spi-dw-mid.c Andy Shevchenko 2015-03-09  253         }
> 80de96dae70648 drivers/spi/spi-dw-dma.c Joy Chakraborty 2023-03-26  254  }
> e31abce778bc05 drivers/spi/spi-dw-mid.c Andy Shevchenko 2015-03-09  255
>
> --
> 0-DAY CI Kernel Test Service
> https://github.com/intel/lkp-tests

Thanks
Joy
  

Patch

diff --git a/drivers/spi/spi-dw-dma.c b/drivers/spi/spi-dw-dma.c
index b3a88bb75907..5a642ec9c269 100644
--- a/drivers/spi/spi-dw-dma.c
+++ b/drivers/spi/spi-dw-dma.c
@@ -23,6 +23,8 @@ 
 #define DW_SPI_TX_BUSY		1
 #define DW_SPI_TX_BURST_LEVEL	16
 
+static inline enum dma_slave_buswidth dw_spi_dma_convert_width(u8 n_bytes);
+
 static bool dw_spi_dma_chan_filter(struct dma_chan *chan, void *param)
 {
 	struct dw_dma_slave *s = param;
@@ -72,12 +74,15 @@  static void dw_spi_dma_maxburst_init(struct dw_spi *dws)
 	dw_writel(dws, DW_SPI_DMATDLR, dws->txburst);
 }
 
-static void dw_spi_dma_sg_burst_init(struct dw_spi *dws)
+static int dw_spi_dma_caps_init(struct dw_spi *dws)
 {
+	int ret;
 	struct dma_slave_caps tx = {0}, rx = {0};
 
-	dma_get_slave_caps(dws->txchan, &tx);
-	dma_get_slave_caps(dws->rxchan, &rx);
+	ret = dma_get_slave_caps(dws->txchan, &tx);
+	ret |= dma_get_slave_caps(dws->rxchan, &rx);
+	if (ret)
+		return ret;
 
 	if (tx.max_sg_burst > 0 && rx.max_sg_burst > 0)
 		dws->dma_sg_burst = min(tx.max_sg_burst, rx.max_sg_burst);
@@ -87,6 +92,18 @@  static void dw_spi_dma_sg_burst_init(struct dw_spi *dws)
 		dws->dma_sg_burst = rx.max_sg_burst;
 	else
 		dws->dma_sg_burst = 0;
+
+	/*
+	 * Assuming both channels belong to the same DMA controller hence the
+	 * address width capabilities most likely would be the same.
+	 */
+	dws->dma_addr_widths = tx.dst_addr_widths & rx.src_addr_widths;
+
+	if (!(tx.directions & BIT(DMA_MEM_TO_DEV) &&
+	      rx.directions & BIT(DMA_DEV_TO_MEM)))
+		return -ENXIO;
+
+	return 0;
 }
 
 static int dw_spi_dma_init_mfld(struct device *dev, struct dw_spi *dws)
@@ -95,6 +112,7 @@  static int dw_spi_dma_init_mfld(struct device *dev, struct dw_spi *dws)
 	struct dw_dma_slave dma_rx = { .src_id = 0 }, *rx = &dma_rx;
 	struct pci_dev *dma_dev;
 	dma_cap_mask_t mask;
+	int ret = -EBUSY;
 
 	/*
 	 * Get pci device for DMA controller, currently it could only
@@ -124,20 +142,24 @@  static int dw_spi_dma_init_mfld(struct device *dev, struct dw_spi *dws)
 
 	init_completion(&dws->dma_completion);
 
-	dw_spi_dma_maxburst_init(dws);
+	ret = dw_spi_dma_caps_init(dws);
+	if (ret)
+		goto free_txchan;
 
-	dw_spi_dma_sg_burst_init(dws);
+	dw_spi_dma_maxburst_init(dws);
 
 	pci_dev_put(dma_dev);
 
 	return 0;
-
+free_txchan:
+	dma_release_channel(dws->txchan);
+	dws->txchan = NULL;
 free_rxchan:
 	dma_release_channel(dws->rxchan);
 	dws->rxchan = NULL;
 err_exit:
 	pci_dev_put(dma_dev);
-	return -EBUSY;
+	return ret;
 }
 
 static int dw_spi_dma_init_generic(struct device *dev, struct dw_spi *dws)
@@ -163,12 +185,16 @@  static int dw_spi_dma_init_generic(struct device *dev, struct dw_spi *dws)
 
 	init_completion(&dws->dma_completion);
 
-	dw_spi_dma_maxburst_init(dws);
+	ret = dw_spi_dma_caps_init(dws);
+	if (ret)
+		goto free_txchan;
 
-	dw_spi_dma_sg_burst_init(dws);
+	dw_spi_dma_maxburst_init(dws);
 
 	return 0;
-
+free_txchan:
+	dma_release_channel(dws->txchan);
+	dws->txchan = NULL;
 free_rxchan:
 	dma_release_channel(dws->rxchan);
 	dws->rxchan = NULL;
@@ -202,8 +228,14 @@  static bool dw_spi_can_dma(struct spi_controller *master,
 			   struct spi_device *spi, struct spi_transfer *xfer)
 {
 	struct dw_spi *dws = spi_controller_get_devdata(master);
+	enum dma_slave_buswidth dma_bus_width;
+
+	if (xfer->len <= dws->fifo_len)
+		return false;
+
+	dma_bus_width = dw_spi_dma_convert_width(dws->n_bytes);
 
-	return xfer->len > dws->fifo_len;
+	return dws->dma_addr_widths & BIT(dma_bus_width);
 }
 
 static enum dma_slave_buswidth dw_spi_dma_convert_width(u8 n_bytes)
diff --git a/drivers/spi/spi-dw.h b/drivers/spi/spi-dw.h
index 9e8eb2b52d5c..3962e6dcf880 100644
--- a/drivers/spi/spi-dw.h
+++ b/drivers/spi/spi-dw.h
@@ -190,6 +190,7 @@  struct dw_spi {
 	struct dma_chan		*rxchan;
 	u32			rxburst;
 	u32			dma_sg_burst;
+	u32			dma_addr_widths;
 	unsigned long		dma_chan_busy;
 	dma_addr_t		dma_addr; /* phy address of the Data register */
 	const struct dw_spi_dma_ops *dma_ops;