[v3,2/2] spi: dw: Add dma controller capability checks
Commit Message
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
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
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
@@ -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)
@@ -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;