mbox series

[00/14] dma-jz4780 improvements

Message ID 20180703123214.23090-1-paul@crapouillou.net
Headers show
Series dma-jz4780 improvements | expand

Message

Paul Cercueil July 3, 2018, 12:32 p.m. UTC
Hi,

This set of patches by myself and Daniel extends the dma-jz4780 driver
to support other SoCs (JZ4770, JZ4740, JZ4725B).

Some fixes are also included, for proper residue reporting, which fixes
errors with ALSA.

Finally, the last two patches update the devicetree bindings for the
JZ4780 SoC and add a binding for the JZ4770 SoC.

This patchset was tested on JZ4780, JZ4770 and JZ4725B, but was not tested
on the JZ4740, so it would be fantastic if somebody could test it there.

Regards,
-Paul

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

Comments

Mathieu Malaterre July 3, 2018, 7:32 p.m. UTC | #1
On Tue, Jul 3, 2018 at 2:32 PM Paul Cercueil <paul@crapouillou.net> wrote:
>
> Hi,
>
> This set of patches by myself and Daniel extends the dma-jz4780 driver
> to support other SoCs (JZ4770, JZ4740, JZ4725B).
>
> Some fixes are also included, for proper residue reporting, which fixes
> errors with ALSA.
>
> Finally, the last two patches update the devicetree bindings for the
> JZ4780 SoC and add a binding for the JZ4770 SoC.
>
> This patchset was tested on JZ4780, JZ4770 and JZ4725B, but was not tested
> on the JZ4740, so it would be fantastic if somebody could test it there.

For the entire series, everything works as expected on JZ4780 (Creator
CI20), including reading from sdcard.

Tested-by: Mathieu Malaterre <malat@debian.org>

> Regards,
> -Paul
>
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
PrasannaKumar Muralidharan July 4, 2018, 4:28 p.m. UTC | #2
Hi Paul,

On 3 July 2018 at 18:02, Paul Cercueil <paul@crapouillou.net> wrote:
> As part of the work to support various other Ingenic JZ47xx SoC versions,
> which don't feature the same number of DMA channels per core, we now
> deduce the number of DMA channels available from the devicetree
> compatible string.
>
> Signed-off-by: Paul Cercueil <paul@crapouillou.net>
> ---
>  drivers/dma/dma-jz4780.c | 53 +++++++++++++++++++++++++++++-----------
>  1 file changed, 39 insertions(+), 14 deletions(-)
>
> diff --git a/drivers/dma/dma-jz4780.c b/drivers/dma/dma-jz4780.c
> index 85820a2d69d4..b40f491f0367 100644
> --- a/drivers/dma/dma-jz4780.c
> +++ b/drivers/dma/dma-jz4780.c
> @@ -16,6 +16,7 @@
>  #include <linux/interrupt.h>
>  #include <linux/module.h>
>  #include <linux/of.h>
> +#include <linux/of_device.h>
>  #include <linux/of_dma.h>
>  #include <linux/platform_device.h>
>  #include <linux/slab.h>
> @@ -23,8 +24,6 @@
>  #include "dmaengine.h"
>  #include "virt-dma.h"
>
> -#define JZ_DMA_NR_CHANNELS     32
> -
>  /* Global registers. */
>  #define JZ_DMA_REG_DMAC                0x1000
>  #define JZ_DMA_REG_DIRQP       0x1004
> @@ -135,14 +134,20 @@ struct jz4780_dma_chan {
>         unsigned int curr_hwdesc;
>  };
>
> +enum jz_version {
> +       ID_JZ4780,
> +};
> +
>  struct jz4780_dma_dev {
>         struct dma_device dma_device;
>         void __iomem *base;
>         struct clk *clk;
>         unsigned int irq;
> +       unsigned int nb_channels;
> +       enum jz_version version;
>
>         uint32_t chan_reserved;
> -       struct jz4780_dma_chan chan[JZ_DMA_NR_CHANNELS];
> +       struct jz4780_dma_chan chan[];

Looks like a variable length array in struct. I think there is some
effort to remove the usage of VLA. Can you revisit this? I may be
wrong, please feel free to correct.

>  };
>
>  struct jz4780_dma_filter_data {
> @@ -648,7 +653,7 @@ static irqreturn_t jz4780_dma_irq_handler(int irq, void *data)
>
>         pending = jz4780_dma_readl(jzdma, JZ_DMA_REG_DIRQP);
>
> -       for (i = 0; i < JZ_DMA_NR_CHANNELS; i++) {
> +       for (i = 0; i < jzdma->nb_channels; i++) {
>                 if (!(pending & (1<<i)))
>                         continue;
>
> @@ -728,7 +733,7 @@ static struct dma_chan *jz4780_of_dma_xlate(struct of_phandle_args *dma_spec,
>         data.channel = dma_spec->args[1];
>
>         if (data.channel > -1) {
> -               if (data.channel >= JZ_DMA_NR_CHANNELS) {
> +               if (data.channel >= jzdma->nb_channels) {
>                         dev_err(jzdma->dma_device.dev,
>                                 "device requested non-existent channel %u\n",
>                                 data.channel);
> @@ -752,19 +757,45 @@ static struct dma_chan *jz4780_of_dma_xlate(struct of_phandle_args *dma_spec,
>         }
>  }
>
> +static const unsigned int jz4780_dma_nb_channels[] = {
> +       [ID_JZ4780] = 32,
> +};
> +
> +static const struct of_device_id jz4780_dma_dt_match[] = {
> +       { .compatible = "ingenic,jz4780-dma", .data = (void *)ID_JZ4780 },
> +       {},
> +};
> +MODULE_DEVICE_TABLE(of, jz4780_dma_dt_match);
> +
>  static int jz4780_dma_probe(struct platform_device *pdev)
>  {
>         struct device *dev = &pdev->dev;
> +       const struct of_device_id *of_id = of_match_device(
> +                       jz4780_dma_dt_match, dev);
>         struct jz4780_dma_dev *jzdma;
>         struct jz4780_dma_chan *jzchan;
>         struct dma_device *dd;
>         struct resource *res;
> +       enum jz_version version;
> +       unsigned int nb_channels;
>         int i, ret;
>
> -       jzdma = devm_kzalloc(dev, sizeof(*jzdma), GFP_KERNEL);
> +       if (of_id)
> +               version = (enum jz_version)of_id->data;
> +       else
> +               version = ID_JZ4780; /* Default when not probed from DT */
> +
> +       nb_channels = jz4780_dma_nb_channels[version];
> +
> +       jzdma = devm_kzalloc(dev, sizeof(*jzdma)
> +                               + sizeof(*jzdma->chan) * nb_channels,
> +                               GFP_KERNEL);
>         if (!jzdma)
>                 return -ENOMEM;
>
> +       jzdma->nb_channels = nb_channels;
> +       jzdma->version = version;
> +
>         platform_set_drvdata(pdev, jzdma);
>
>         res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> @@ -839,7 +870,7 @@ static int jz4780_dma_probe(struct platform_device *pdev)
>
>         INIT_LIST_HEAD(&dd->channels);
>
> -       for (i = 0; i < JZ_DMA_NR_CHANNELS; i++) {
> +       for (i = 0; i < jzdma->nb_channels; i++) {
>                 jzchan = &jzdma->chan[i];
>                 jzchan->id = i;
>
> @@ -884,19 +915,13 @@ static int jz4780_dma_remove(struct platform_device *pdev)
>
>         free_irq(jzdma->irq, jzdma);
>
> -       for (i = 0; i < JZ_DMA_NR_CHANNELS; i++)
> +       for (i = 0; i < jzdma->nb_channels; i++)
>                 tasklet_kill(&jzdma->chan[i].vchan.task);
>
>         dma_async_device_unregister(&jzdma->dma_device);
>         return 0;
>  }
>
> -static const struct of_device_id jz4780_dma_dt_match[] = {
> -       { .compatible = "ingenic,jz4780-dma", .data = NULL },
> -       {},
> -};
> -MODULE_DEVICE_TABLE(of, jz4780_dma_dt_match);
> -
>  static struct platform_driver jz4780_dma_driver = {
>         .probe          = jz4780_dma_probe,
>         .remove         = jz4780_dma_remove,
> --
> 2.18.0
>
>
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
PrasannaKumar Muralidharan July 4, 2018, 4:40 p.m. UTC | #3
Hi Paul,

On 3 July 2018 at 18:02, Paul Cercueil <paul@crapouillou.net> wrote:
> The only information we use in the 8-word version of the hardware DMA
> descriptor that is not present in the 4-word version is the transfer
> type, aka. the ID of the source or recipient device.
>
> Since the transfer type will never change for a DMA channel in use,
> we can just set it once for all in the corresponding DMA register
> before starting any transfer.
>
> This has several benefits:
>
> * the driver will handle twice as many hardware DMA descriptors;
>
> * the driver is closer to support the JZ4740, which only supports 4-word
>   hardware DMA descriptors;
>
> * the JZ4770 SoC needs the transfer type to be set in the corresponding
>   DMA register anyway, even if 8-word descriptors are in use.
>
> Signed-off-by: Paul Cercueil <paul@crapouillou.net>
> ---
>  drivers/dma/dma-jz4780.c | 21 +++++++++------------
>  1 file changed, 9 insertions(+), 12 deletions(-)
>
> diff --git a/drivers/dma/dma-jz4780.c b/drivers/dma/dma-jz4780.c
> index 4d234caf5d62..cd2cd70fd843 100644
> --- a/drivers/dma/dma-jz4780.c
> +++ b/drivers/dma/dma-jz4780.c
> @@ -93,17 +93,12 @@
>   * @dtc: transfer count (number of blocks of the transfer size specified in DCM
>   * to transfer) in the low 24 bits, offset of the next descriptor from the
>   * descriptor base address in the upper 8 bits.
> - * @sd: target/source stride difference (in stride transfer mode).
> - * @drt: request type
>   */
>  struct jz4780_dma_hwdesc {
>         uint32_t dcm;
>         uint32_t dsa;
>         uint32_t dta;
>         uint32_t dtc;
> -       uint32_t sd;
> -       uint32_t drt;
> -       uint32_t reserved[2];
>  };
>
>  /* Size of allocations for hardware descriptor blocks. */
> @@ -280,7 +275,6 @@ static int jz4780_dma_setup_hwdesc(struct jz4780_dma_chan *jzchan,
>                 desc->dcm = JZ_DMA_DCM_SAI;
>                 desc->dsa = addr;
>                 desc->dta = config->dst_addr;
> -               desc->drt = jzchan->transfer_type;
>
>                 width = config->dst_addr_width;
>                 maxburst = config->dst_maxburst;
> @@ -288,7 +282,6 @@ static int jz4780_dma_setup_hwdesc(struct jz4780_dma_chan *jzchan,
>                 desc->dcm = JZ_DMA_DCM_DAI;
>                 desc->dsa = config->src_addr;
>                 desc->dta = addr;
> -               desc->drt = jzchan->transfer_type;
>
>                 width = config->src_addr_width;
>                 maxburst = config->src_maxburst;
> @@ -433,9 +426,10 @@ static struct dma_async_tx_descriptor *jz4780_dma_prep_dma_memcpy(
>         tsz = jz4780_dma_transfer_size(dest | src | len,
>                                        &jzchan->transfer_shift);
>
> +       jzchan->transfer_type = JZ_DMA_DRT_AUTO;
> +
>         desc->desc[0].dsa = src;
>         desc->desc[0].dta = dest;
> -       desc->desc[0].drt = JZ_DMA_DRT_AUTO;
>         desc->desc[0].dcm = JZ_DMA_DCM_TIE | JZ_DMA_DCM_SAI | JZ_DMA_DCM_DAI |
>                             tsz << JZ_DMA_DCM_TSZ_SHIFT |
>                             JZ_DMA_WIDTH_32_BIT << JZ_DMA_DCM_SP_SHIFT |
> @@ -490,9 +484,12 @@ static void jz4780_dma_begin(struct jz4780_dma_chan *jzchan)
>                         (jzchan->curr_hwdesc + 1) % jzchan->desc->count;
>         }
>
> -       /* Use 8-word descriptors. */
> -       jz4780_dma_chn_writel(jzdma, jzchan->id,
> -                             JZ_DMA_REG_DCS, JZ_DMA_DCS_DES8);
> +       /* Use 4-word descriptors. */
> +       jz4780_dma_chn_writel(jzdma, jzchan->id, JZ_DMA_REG_DCS, 0);
> +
> +       /* Set transfer type. */
> +       jz4780_dma_chn_writel(jzdma, jzchan->id, JZ_DMA_REG_DRT,
> +                             jzchan->transfer_type);
>
>         /* Write descriptor address and initiate descriptor fetch. */
>         desc_phys = jzchan->desc->desc_phys +
> @@ -502,7 +499,7 @@ static void jz4780_dma_begin(struct jz4780_dma_chan *jzchan)
>
>         /* Enable the channel. */
>         jz4780_dma_chn_writel(jzdma, jzchan->id, JZ_DMA_REG_DCS,
> -                             JZ_DMA_DCS_DES8 | JZ_DMA_DCS_CTE);
> +                             JZ_DMA_DCS_CTE);
>  }
>
>  static void jz4780_dma_issue_pending(struct dma_chan *chan)
> --
> 2.18.0
>
>

Patch looks good to me.
Reviewed-by: PrasannaKumar Muralidharan <prasannatsmkumar@gmail.com>

Regards,
PrasannaKumar
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
PrasannaKumar Muralidharan July 4, 2018, 5 p.m. UTC | #4
On 3 July 2018 at 18:02, Paul Cercueil <paul@crapouillou.net> wrote:
> With the fast DMA bit set, the DMA will transfer twice as much data
> per clock period to the AIC, so there is little point not to set it.
>
> Signed-off-by: Paul Cercueil <paul@crapouillou.net>
> ---
>  drivers/dma/dma-jz4780.c | 5 +++--
>  1 file changed, 3 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/dma/dma-jz4780.c b/drivers/dma/dma-jz4780.c
> index 922e4031e70e..7ee2c121948f 100644
> --- a/drivers/dma/dma-jz4780.c
> +++ b/drivers/dma/dma-jz4780.c
> @@ -52,6 +52,7 @@
>  #define JZ_DMA_DMAC_DMAE       BIT(0)
>  #define JZ_DMA_DMAC_AR         BIT(2)
>  #define JZ_DMA_DMAC_HLT                BIT(3)
> +#define JZ_DMA_DMAC_FAIC       BIT(27)
>  #define JZ_DMA_DMAC_FMSC       BIT(31)
>
>  #define JZ_DMA_DRT_AUTO                0x8
> @@ -929,8 +930,8 @@ static int jz4780_dma_probe(struct platform_device *pdev)
>          * Also set the FMSC bit - it increases MSC performance, so it makes
>          * little sense not to enable it.
>          */
> -       jz4780_dma_ctrl_writel(jzdma, JZ_DMA_REG_DMAC,
> -                         JZ_DMA_DMAC_DMAE | JZ_DMA_DMAC_FMSC);
> +       jz4780_dma_ctrl_writel(jzdma, JZ_DMA_REG_DMAC, JZ_DMA_DMAC_DMAE |
> +                              JZ_DMA_DMAC_FAIC | JZ_DMA_DMAC_FMSC);
>
>         if (jzdma->version == ID_JZ4780)
>                 jz4780_dma_ctrl_writel(jzdma, JZ_DMA_REG_DMACP, 0);
> --
> 2.18.0
>
>

Reviewed-by: PrasannaKumar Muralidharan <prasannatsmkumar@gmail.com>.
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Paul Cercueil July 5, 2018, 6:26 p.m. UTC | #5
Hi PrasannaKumar,

> Hi Paul,
> 
> On 3 July 2018 at 18:02, Paul Cercueil <paul@crapouillou.net> wrote:
>>  As part of the work to support various other Ingenic JZ47xx SoC 
>> versions,
>>  which don't feature the same number of DMA channels per core, we now
>>  deduce the number of DMA channels available from the devicetree
>>  compatible string.
>> 
>>  Signed-off-by: Paul Cercueil <paul@crapouillou.net>
>>  ---
>>   drivers/dma/dma-jz4780.c | 53 
>> +++++++++++++++++++++++++++++-----------
>>   1 file changed, 39 insertions(+), 14 deletions(-)
>> 
>>  diff --git a/drivers/dma/dma-jz4780.c b/drivers/dma/dma-jz4780.c
>>  index 85820a2d69d4..b40f491f0367 100644
>>  --- a/drivers/dma/dma-jz4780.c
>>  +++ b/drivers/dma/dma-jz4780.c
>>  @@ -16,6 +16,7 @@
>>   #include <linux/interrupt.h>
>>   #include <linux/module.h>
>>   #include <linux/of.h>
>>  +#include <linux/of_device.h>
>>   #include <linux/of_dma.h>
>>   #include <linux/platform_device.h>
>>   #include <linux/slab.h>
>>  @@ -23,8 +24,6 @@
>>   #include "dmaengine.h"
>>   #include "virt-dma.h"
>> 
>>  -#define JZ_DMA_NR_CHANNELS     32
>>  -
>>   /* Global registers. */
>>   #define JZ_DMA_REG_DMAC                0x1000
>>   #define JZ_DMA_REG_DIRQP       0x1004
>>  @@ -135,14 +134,20 @@ struct jz4780_dma_chan {
>>          unsigned int curr_hwdesc;
>>   };
>> 
>>  +enum jz_version {
>>  +       ID_JZ4780,
>>  +};
>>  +
>>   struct jz4780_dma_dev {
>>          struct dma_device dma_device;
>>          void __iomem *base;
>>          struct clk *clk;
>>          unsigned int irq;
>>  +       unsigned int nb_channels;
>>  +       enum jz_version version;
>> 
>>          uint32_t chan_reserved;
>>  -       struct jz4780_dma_chan chan[JZ_DMA_NR_CHANNELS];
>>  +       struct jz4780_dma_chan chan[];
> 
> Looks like a variable length array in struct. I think there is some
> effort to remove the usage of VLA. Can you revisit this? I may be
> wrong, please feel free to correct.

Are you sure? It's the first time I hear about it.
Could anybody confirm?

>>   };
>> 
>>   struct jz4780_dma_filter_data {
>>  @@ -648,7 +653,7 @@ static irqreturn_t jz4780_dma_irq_handler(int 
>> irq, void *data)
>> 
>>          pending = jz4780_dma_readl(jzdma, JZ_DMA_REG_DIRQP);
>> 
>>  -       for (i = 0; i < JZ_DMA_NR_CHANNELS; i++) {
>>  +       for (i = 0; i < jzdma->nb_channels; i++) {
>>                  if (!(pending & (1<<i)))
>>                          continue;
>> 
>>  @@ -728,7 +733,7 @@ static struct dma_chan 
>> *jz4780_of_dma_xlate(struct of_phandle_args *dma_spec,
>>          data.channel = dma_spec->args[1];
>> 
>>          if (data.channel > -1) {
>>  -               if (data.channel >= JZ_DMA_NR_CHANNELS) {
>>  +               if (data.channel >= jzdma->nb_channels) {
>>                          dev_err(jzdma->dma_device.dev,
>>                                  "device requested non-existent 
>> channel %u\n",
>>                                  data.channel);
>>  @@ -752,19 +757,45 @@ static struct dma_chan 
>> *jz4780_of_dma_xlate(struct of_phandle_args *dma_spec,
>>          }
>>   }
>> 
>>  +static const unsigned int jz4780_dma_nb_channels[] = {
>>  +       [ID_JZ4780] = 32,
>>  +};
>>  +
>>  +static const struct of_device_id jz4780_dma_dt_match[] = {
>>  +       { .compatible = "ingenic,jz4780-dma", .data = (void 
>> *)ID_JZ4780 },
>>  +       {},
>>  +};
>>  +MODULE_DEVICE_TABLE(of, jz4780_dma_dt_match);
>>  +
>>   static int jz4780_dma_probe(struct platform_device *pdev)
>>   {
>>          struct device *dev = &pdev->dev;
>>  +       const struct of_device_id *of_id = of_match_device(
>>  +                       jz4780_dma_dt_match, dev);
>>          struct jz4780_dma_dev *jzdma;
>>          struct jz4780_dma_chan *jzchan;
>>          struct dma_device *dd;
>>          struct resource *res;
>>  +       enum jz_version version;
>>  +       unsigned int nb_channels;
>>          int i, ret;
>> 
>>  -       jzdma = devm_kzalloc(dev, sizeof(*jzdma), GFP_KERNEL);
>>  +       if (of_id)
>>  +               version = (enum jz_version)of_id->data;
>>  +       else
>>  +               version = ID_JZ4780; /* Default when not probed 
>> from DT */
>>  +
>>  +       nb_channels = jz4780_dma_nb_channels[version];
>>  +
>>  +       jzdma = devm_kzalloc(dev, sizeof(*jzdma)
>>  +                               + sizeof(*jzdma->chan) * 
>> nb_channels,
>>  +                               GFP_KERNEL);
>>          if (!jzdma)
>>                  return -ENOMEM;
>> 
>>  +       jzdma->nb_channels = nb_channels;
>>  +       jzdma->version = version;
>>  +
>>          platform_set_drvdata(pdev, jzdma);
>> 
>>          res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
>>  @@ -839,7 +870,7 @@ static int jz4780_dma_probe(struct 
>> platform_device *pdev)
>> 
>>          INIT_LIST_HEAD(&dd->channels);
>> 
>>  -       for (i = 0; i < JZ_DMA_NR_CHANNELS; i++) {
>>  +       for (i = 0; i < jzdma->nb_channels; i++) {
>>                  jzchan = &jzdma->chan[i];
>>                  jzchan->id = i;
>> 
>>  @@ -884,19 +915,13 @@ static int jz4780_dma_remove(struct 
>> platform_device *pdev)
>> 
>>          free_irq(jzdma->irq, jzdma);
>> 
>>  -       for (i = 0; i < JZ_DMA_NR_CHANNELS; i++)
>>  +       for (i = 0; i < jzdma->nb_channels; i++)
>>                  tasklet_kill(&jzdma->chan[i].vchan.task);
>> 
>>          dma_async_device_unregister(&jzdma->dma_device);
>>          return 0;
>>   }
>> 
>>  -static const struct of_device_id jz4780_dma_dt_match[] = {
>>  -       { .compatible = "ingenic,jz4780-dma", .data = NULL },
>>  -       {},
>>  -};
>>  -MODULE_DEVICE_TABLE(of, jz4780_dma_dt_match);
>>  -
>>   static struct platform_driver jz4780_dma_driver = {
>>          .probe          = jz4780_dma_probe,
>>          .remove         = jz4780_dma_remove,
>>  --
>>  2.18.0
>> 
>> 

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
PrasannaKumar Muralidharan July 7, 2018, 7:34 a.m. UTC | #6
On 5 July 2018 at 23:56, Paul Cercueil <paul@crapouillou.net> wrote:
> Hi PrasannaKumar,
>
>
>> Hi Paul,
>>
>> On 3 July 2018 at 18:02, Paul Cercueil <paul@crapouillou.net> wrote:
>>>
>>>  As part of the work to support various other Ingenic JZ47xx SoC
>>> versions,
>>>  which don't feature the same number of DMA channels per core, we now
>>>  deduce the number of DMA channels available from the devicetree
>>>  compatible string.
>>>
>>>  Signed-off-by: Paul Cercueil <paul@crapouillou.net>
>>>  ---
>>>   drivers/dma/dma-jz4780.c | 53 +++++++++++++++++++++++++++++-----------
>>>   1 file changed, 39 insertions(+), 14 deletions(-)
>>>
>>>  diff --git a/drivers/dma/dma-jz4780.c b/drivers/dma/dma-jz4780.c
>>>  index 85820a2d69d4..b40f491f0367 100644
>>>  --- a/drivers/dma/dma-jz4780.c
>>>  +++ b/drivers/dma/dma-jz4780.c
>>>  @@ -16,6 +16,7 @@
>>>   #include <linux/interrupt.h>
>>>   #include <linux/module.h>
>>>   #include <linux/of.h>
>>>  +#include <linux/of_device.h>
>>>   #include <linux/of_dma.h>
>>>   #include <linux/platform_device.h>
>>>   #include <linux/slab.h>
>>>  @@ -23,8 +24,6 @@
>>>   #include "dmaengine.h"
>>>   #include "virt-dma.h"
>>>
>>>  -#define JZ_DMA_NR_CHANNELS     32
>>>  -
>>>   /* Global registers. */
>>>   #define JZ_DMA_REG_DMAC                0x1000
>>>   #define JZ_DMA_REG_DIRQP       0x1004
>>>  @@ -135,14 +134,20 @@ struct jz4780_dma_chan {
>>>          unsigned int curr_hwdesc;
>>>   };
>>>
>>>  +enum jz_version {
>>>  +       ID_JZ4780,
>>>  +};
>>>  +
>>>   struct jz4780_dma_dev {
>>>          struct dma_device dma_device;
>>>          void __iomem *base;
>>>          struct clk *clk;
>>>          unsigned int irq;
>>>  +       unsigned int nb_channels;
>>>  +       enum jz_version version;
>>>
>>>          uint32_t chan_reserved;
>>>  -       struct jz4780_dma_chan chan[JZ_DMA_NR_CHANNELS];
>>>  +       struct jz4780_dma_chan chan[];
>>
>>
>> Looks like a variable length array in struct. I think there is some
>> effort to remove the usage of VLA. Can you revisit this? I may be
>> wrong, please feel free to correct.
>
>
> Are you sure? It's the first time I hear about it.
> Could anybody confirm?

Please see [1] for info.

Variable Length Arrays in struct is expressly forbidden in C99, C11.
Clang does not support it. To make kernel compile with Clang few
people are trying to remove/reduce VLAIS usage.

1. https://blog.linuxplumbersconf.org/2013/ocw/system/presentations/1221/original/VLAIS.pdf
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Paul Cercueil July 7, 2018, 11:01 a.m. UTC | #7
Le sam. 7 juil. 2018 à 9:34, PrasannaKumar Muralidharan 
<prasannatsmkumar@gmail.com> a écrit :
> On 5 July 2018 at 23:56, Paul Cercueil <paul@crapouillou.net> wrote:
>>  Hi PrasannaKumar,
>> 
>> 
>>>  Hi Paul,
>>> 
>>>  On 3 July 2018 at 18:02, Paul Cercueil <paul@crapouillou.net> 
>>> wrote:
>>>> 
>>>>   As part of the work to support various other Ingenic JZ47xx SoC
>>>>  versions,
>>>>   which don't feature the same number of DMA channels per core, we 
>>>> now
>>>>   deduce the number of DMA channels available from the devicetree
>>>>   compatible string.
>>>> 
>>>>   Signed-off-by: Paul Cercueil <paul@crapouillou.net>
>>>>   ---
>>>>    drivers/dma/dma-jz4780.c | 53 
>>>> +++++++++++++++++++++++++++++-----------
>>>>    1 file changed, 39 insertions(+), 14 deletions(-)
>>>> 
>>>>   diff --git a/drivers/dma/dma-jz4780.c b/drivers/dma/dma-jz4780.c
>>>>   index 85820a2d69d4..b40f491f0367 100644
>>>>   --- a/drivers/dma/dma-jz4780.c
>>>>   +++ b/drivers/dma/dma-jz4780.c
>>>>   @@ -16,6 +16,7 @@
>>>>    #include <linux/interrupt.h>
>>>>    #include <linux/module.h>
>>>>    #include <linux/of.h>
>>>>   +#include <linux/of_device.h>
>>>>    #include <linux/of_dma.h>
>>>>    #include <linux/platform_device.h>
>>>>    #include <linux/slab.h>
>>>>   @@ -23,8 +24,6 @@
>>>>    #include "dmaengine.h"
>>>>    #include "virt-dma.h"
>>>> 
>>>>   -#define JZ_DMA_NR_CHANNELS     32
>>>>   -
>>>>    /* Global registers. */
>>>>    #define JZ_DMA_REG_DMAC                0x1000
>>>>    #define JZ_DMA_REG_DIRQP       0x1004
>>>>   @@ -135,14 +134,20 @@ struct jz4780_dma_chan {
>>>>           unsigned int curr_hwdesc;
>>>>    };
>>>> 
>>>>   +enum jz_version {
>>>>   +       ID_JZ4780,
>>>>   +};
>>>>   +
>>>>    struct jz4780_dma_dev {
>>>>           struct dma_device dma_device;
>>>>           void __iomem *base;
>>>>           struct clk *clk;
>>>>           unsigned int irq;
>>>>   +       unsigned int nb_channels;
>>>>   +       enum jz_version version;
>>>> 
>>>>           uint32_t chan_reserved;
>>>>   -       struct jz4780_dma_chan chan[JZ_DMA_NR_CHANNELS];
>>>>   +       struct jz4780_dma_chan chan[];
>>> 
>>> 
>>>  Looks like a variable length array in struct. I think there is some
>>>  effort to remove the usage of VLA. Can you revisit this? I may be
>>>  wrong, please feel free to correct.
>> 
>> 
>>  Are you sure? It's the first time I hear about it.
>>  Could anybody confirm?
> 
> Please see [1] for info.
> 
> Variable Length Arrays in struct is expressly forbidden in C99, C11.
> Clang does not support it. To make kernel compile with Clang few
> people are trying to remove/reduce VLAIS usage.
> 
> 1. 
> https://blog.linuxplumbersconf.org/2013/ocw/system/presentations/1221/original/VLAIS.pdf

I read it, and my structure is not a VLAIS; my "chan" array is a 
flexible
array, its sizeof() is 0, so the sizeof() of the structure is constant.

See page 6 of the PDF, about alternatives to VLAIS:
"If possible use a flexible array member and move the array to the end 
of
the struct"
Which is what I am doing here.

-Paul

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Vinod Koul July 9, 2018, 4:59 p.m. UTC | #8
On 03-07-18, 14:32, Paul Cercueil wrote:

>  struct jz4780_dma_dev {
>  	struct dma_device dma_device;
>  	void __iomem *base;
>  	struct clk *clk;
>  	unsigned int irq;
> +	unsigned int nb_channels;
> +	enum jz_version version;
>  
>  	uint32_t chan_reserved;
> -	struct jz4780_dma_chan chan[JZ_DMA_NR_CHANNELS];
> +	struct jz4780_dma_chan chan[];

why array, why not channel pointer?

> +static const unsigned int jz4780_dma_nb_channels[] = {
> +	[ID_JZ4780] = 32,
> +};
> +
> +static const struct of_device_id jz4780_dma_dt_match[] = {
> +	{ .compatible = "ingenic,jz4780-dma", .data = (void *)ID_JZ4780 },
> +	{},
> +};

Looking at description I was hoping that channels would be in DT,
channels is hardware information, so should come from DT rather than
coding the kernel...

> -	jzdma = devm_kzalloc(dev, sizeof(*jzdma), GFP_KERNEL);
> +	if (of_id)
> +		version = (enum jz_version)of_id->data;
> +	else
> +		version = ID_JZ4780; /* Default when not probed from DT */

where else would it be probed from.... ?
Vinod Koul July 11, 2018, 12:14 p.m. UTC | #9
Hi Paul,

On 10-07-18, 17:29, Paul Cercueil wrote:
> > >  +static const unsigned int jz4780_dma_nb_channels[] = {
> > >  +	[ID_JZ4780] = 32,
> > >  +};
> > >  +
> > >  +static const struct of_device_id jz4780_dma_dt_match[] = {
> > >  +	{ .compatible = "ingenic,jz4780-dma", .data = (void *)ID_JZ4780 },
> > >  +	{},
> > >  +};
> > 
> > Looking at description I was hoping that channels would be in DT,
> > channels is hardware information, so should come from DT rather than
> > coding the kernel...
> 
> I had a talk with Linus Walleij (GPIO maintainer) about that:
> http://lkml.iu.edu/hypermail/linux/kernel/1701.3/05422.html
> 
> And I agree with him, we shouldn't have in devicetree what we can deduce
> from the compatible string. But there doesn't seem to be an enforced
> policy about it.

Looking at this, yes that can be done as you have implemented but adding
new compatible and tables every time seems not so great to me.

If DT can describe these hardware features then driver can take action generically
and we avoid these tables and skip some patches here..

> 
> @Rob, what do you think?

Rob what is the recommendation here?

> 
> > >  -	jzdma = devm_kzalloc(dev, sizeof(*jzdma), GFP_KERNEL);
> > >  +	if (of_id)
> > >  +		version = (enum jz_version)of_id->data;
> > >  +	else
> > >  +		version = ID_JZ4780; /* Default when not probed from DT */
> > 
> > where else would it be probed from.... ?
> 
> Platform, MFD driver, etc. But not likely to happen.
> I can remove these lines if you want.

Lets add when we land support for those.