diff mbox series

[v3,5/6] dmaengine: dw-edma: add flags at struct dw_edma_chip

Message ID 20220307224750.18055-5-Frank.Li@nxp.com (mailing list archive)
State Changes Requested
Headers show
Series [v3,1/6] dmaengine: dw-edma: fix dw_edma_probe() can't be call globally | expand

Commit Message

Frank Li March 7, 2022, 10:47 p.m. UTC
Allow PCI EP probe DMA locally and prevent use of remote MSI
to remote PCI host.

Add option to force 32bit DBI register access even on
64-bit systems. i.MX8 hardware only allowed 32bit register
access.

Signed-off-by: Frank Li <Frank.Li@nxp.com>
---

Resend added dmaengine@vger.kernel.org

Change from v2 to v3
 - rework commit message
 - Change to DW_EDMA_CHIP_32BIT_DBI
 - using DW_EDMA_CHIP_LOCAL control msi
 - Apply Bjorn's comments, 
	if (!j) {
               control |= DW_EDMA_V0_LIE;
               if (!(chan->chip->flags & DW_EDMA_CHIP_LOCAL))
                               control |= DW_EDMA_V0_RIE;
        }

	if ((chan->chip->flags & DW_EDMA_CHIP_REG32BIT) ||
              !IS_ENABLED(CONFIG_64BIT)) {
          SET_CH_32(...);
          SET_CH_32(...);
       } else {
          SET_CH_64(...);
       }


Change from v1 to v2
- none

 drivers/dma/dw-edma/dw-edma-v0-core.c | 20 ++++++++++++--------
 include/linux/dma/edma.h              |  9 +++++++++
 2 files changed, 21 insertions(+), 8 deletions(-)

Comments

Manivannan Sadhasivam March 10, 2022, 7:44 a.m. UTC | #1
On Mon, Mar 07, 2022 at 04:47:49PM -0600, Frank Li wrote:
> Allow PCI EP probe DMA locally and prevent use of remote MSI
> to remote PCI host.
> 
> Add option to force 32bit DBI register access even on
> 64-bit systems. i.MX8 hardware only allowed 32bit register
> access.
> 
> Signed-off-by: Frank Li <Frank.Li@nxp.com>
> ---
> 
> Resend added dmaengine@vger.kernel.org
> 
> Change from v2 to v3
>  - rework commit message
>  - Change to DW_EDMA_CHIP_32BIT_DBI
>  - using DW_EDMA_CHIP_LOCAL control msi
>  - Apply Bjorn's comments, 
> 	if (!j) {
>                control |= DW_EDMA_V0_LIE;
>                if (!(chan->chip->flags & DW_EDMA_CHIP_LOCAL))
>                                control |= DW_EDMA_V0_RIE;
>         }
> 
> 	if ((chan->chip->flags & DW_EDMA_CHIP_REG32BIT) ||
>               !IS_ENABLED(CONFIG_64BIT)) {
>           SET_CH_32(...);
>           SET_CH_32(...);
>        } else {
>           SET_CH_64(...);
>        }
> 
> 
> Change from v1 to v2
> - none
> 
>  drivers/dma/dw-edma/dw-edma-v0-core.c | 20 ++++++++++++--------
>  include/linux/dma/edma.h              |  9 +++++++++
>  2 files changed, 21 insertions(+), 8 deletions(-)
> 
> diff --git a/drivers/dma/dw-edma/dw-edma-v0-core.c b/drivers/dma/dw-edma/dw-edma-v0-core.c
> index 6e2f83e31a03a..081cd7997348d 100644
> --- a/drivers/dma/dw-edma/dw-edma-v0-core.c
> +++ b/drivers/dma/dw-edma/dw-edma-v0-core.c
> @@ -307,6 +307,7 @@ u32 dw_edma_v0_core_status_abort_int(struct dw_edma_chip *chip, enum dw_edma_dir
>  static void dw_edma_v0_core_write_chunk(struct dw_edma_chunk *chunk)
>  {
>  	struct dw_edma_burst *child;
> +	struct dw_edma_chan *chan = chunk->chan;
>  	struct dw_edma_v0_lli __iomem *lli;
>  	struct dw_edma_v0_llp __iomem *llp;
>  	u32 control = 0, i = 0;
> @@ -320,9 +321,11 @@ static void dw_edma_v0_core_write_chunk(struct dw_edma_chunk *chunk)
>  	j = chunk->bursts_alloc;
>  	list_for_each_entry(child, &chunk->burst->list, list) {
>  		j--;
> -		if (!j)
> -			control |= (DW_EDMA_V0_LIE | DW_EDMA_V0_RIE);
> -
> +		if (!j) {
> +			control |= DW_EDMA_V0_LIE;
> +			if (!(chan->chip->flags & DW_EDMA_CHIP_LOCAL))
> +				control |= DW_EDMA_V0_RIE;
> +		}
>  		/* Channel control */
>  		SET_LL_32(&lli[i].control, control);
>  		/* Transfer size */
> @@ -420,15 +423,16 @@ void dw_edma_v0_core_start(struct dw_edma_chunk *chunk, bool first)
>  		SET_CH_32(chip, chan->dir, chan->id, ch_control1,
>  			  (DW_EDMA_V0_CCS | DW_EDMA_V0_LLE));
>  		/* Linked list */
> -		#ifdef CONFIG_64BIT
> -			SET_CH_64(chip, chan->dir, chan->id, llp.reg,
> -				  chunk->ll_region.paddr);
> -		#else /* CONFIG_64BIT */
> +		if ((chan->chip->flags & DW_EDMA_CHIP_32BIT_DBI) ||
> +		    !IS_ENABLED(CONFIG_64BIT)) {
>  			SET_CH_32(chip, chan->dir, chan->id, llp.lsb,
>  				  lower_32_bits(chunk->ll_region.paddr));
>  			SET_CH_32(chip, chan->dir, chan->id, llp.msb,
>  				  upper_32_bits(chunk->ll_region.paddr));
> -		#endif /* CONFIG_64BIT */
> +		} else {
> +			SET_CH_64(chip, chan->dir, chan->id, llp.reg,
> +				  chunk->ll_region.paddr);
> +		}
>  	}
>  	/* Doorbell */
>  	SET_RW_32(chip, chan->dir, doorbell,
> diff --git a/include/linux/dma/edma.h b/include/linux/dma/edma.h
> index fcfbc0f47f83d..4321f6378ef66 100644
> --- a/include/linux/dma/edma.h
> +++ b/include/linux/dma/edma.h
> @@ -33,6 +33,12 @@ enum dw_edma_map_format {
>  	EDMA_MF_HDMA_COMPAT = 0x5
>  };
>  
> +/* Probe EDMA engine locally and prevent generate MSI to host side*/
> +#define DW_EDMA_CHIP_LOCAL	BIT(0)
> +
> +/* Only support 32bit DBI register access */
> +#define DW_EDMA_CHIP_32BIT_DBI	BIT(1)
> +

How about using an enum for defining the flags? This would help us organize the
flags in a more coherent way and also will give the benefit of kdoc.

/**
 * enum dw_edma_chip_flags - Flags specific to an eDMA chip
 * @DW_EDMA_CHIP_LOCAL:		eDMA is used locally by an endpoint
 * @DW_EDMA_CHIP_32BIT_DBI:	eDMA only supports 32bit DBI access
 */
enum dw_edma_chip_flags {
	DW_EDMA_CHIP_LOCAL = BIT(0),
	DW_EDMA_CHIP_32BIT_DBI = BIT(1),
};

>  /**
>   * struct dw_edma_chip - representation of DesignWare eDMA controller hardware
>   * @dev:		 struct device of the eDMA controller
> @@ -40,6 +46,8 @@ enum dw_edma_map_format {
>   * @nr_irqs:		 total dma irq number
>   * reg64bit		 if support 64bit write to register
>   * @ops			 DMA channel to IRQ number mapping
> + * @flags		 - DW_EDMA_CHIP_LOCAL
> + *			 - DW_EDMA_CHIP_32BIT_DBI

No need to mention the flags here if you use the enum I suggested above.

>   * @wr_ch_cnt		 DMA write channel number
>   * @rd_ch_cnt		 DMA read channel number
>   * @rg_region		 DMA register region
> @@ -53,6 +61,7 @@ struct dw_edma_chip {
>  	int			id;
>  	int			nr_irqs;
>  	const struct dw_edma_core_ops   *ops;
> +	u32			flags;

	enum dw_edma_chip_flags	flags;

Thanks,
Mani

>  
>  	void __iomem		*reg_base;
>  
> -- 
> 2.24.0.rc1
>
Manivannan Sadhasivam March 10, 2022, 7:55 a.m. UTC | #2
Subject could be:

dmaengine: dw-edma: Add support for chip specific flags

On Mon, Mar 07, 2022 at 04:47:49PM -0600, Frank Li wrote:
> Allow PCI EP probe DMA locally and prevent use of remote MSI
> to remote PCI host.
> 
> Add option to force 32bit DBI register access even on
> 64-bit systems. i.MX8 hardware only allowed 32bit register
> access.
> 

Add a "flags" field to the "struct dw_edma_chip" so that the controller drivers
can pass flags that are relevant to the platform. Currently 2 flags are
defined:

1. DW_EDMA_CHIP_LOCAL - Used by the controller drivers accessing eDMA locally.
Local eDMA access doesn't require generating MSIs to the remote.

2. DW_EDMA_CHIP_32BIT_DBI - Used by the controller drivers like i.MX8 that
allows only 32bit access to the DBI region.

Thanks,
Mani

> Signed-off-by: Frank Li <Frank.Li@nxp.com>
> ---
> 
> Resend added dmaengine@vger.kernel.org
> 
> Change from v2 to v3
>  - rework commit message
>  - Change to DW_EDMA_CHIP_32BIT_DBI
>  - using DW_EDMA_CHIP_LOCAL control msi
>  - Apply Bjorn's comments, 
> 	if (!j) {
>                control |= DW_EDMA_V0_LIE;
>                if (!(chan->chip->flags & DW_EDMA_CHIP_LOCAL))
>                                control |= DW_EDMA_V0_RIE;
>         }
> 
> 	if ((chan->chip->flags & DW_EDMA_CHIP_REG32BIT) ||
>               !IS_ENABLED(CONFIG_64BIT)) {
>           SET_CH_32(...);
>           SET_CH_32(...);
>        } else {
>           SET_CH_64(...);
>        }
> 
> 
> Change from v1 to v2
> - none
> 
>  drivers/dma/dw-edma/dw-edma-v0-core.c | 20 ++++++++++++--------
>  include/linux/dma/edma.h              |  9 +++++++++
>  2 files changed, 21 insertions(+), 8 deletions(-)
> 
> diff --git a/drivers/dma/dw-edma/dw-edma-v0-core.c b/drivers/dma/dw-edma/dw-edma-v0-core.c
> index 6e2f83e31a03a..081cd7997348d 100644
> --- a/drivers/dma/dw-edma/dw-edma-v0-core.c
> +++ b/drivers/dma/dw-edma/dw-edma-v0-core.c
> @@ -307,6 +307,7 @@ u32 dw_edma_v0_core_status_abort_int(struct dw_edma_chip *chip, enum dw_edma_dir
>  static void dw_edma_v0_core_write_chunk(struct dw_edma_chunk *chunk)
>  {
>  	struct dw_edma_burst *child;
> +	struct dw_edma_chan *chan = chunk->chan;
>  	struct dw_edma_v0_lli __iomem *lli;
>  	struct dw_edma_v0_llp __iomem *llp;
>  	u32 control = 0, i = 0;
> @@ -320,9 +321,11 @@ static void dw_edma_v0_core_write_chunk(struct dw_edma_chunk *chunk)
>  	j = chunk->bursts_alloc;
>  	list_for_each_entry(child, &chunk->burst->list, list) {
>  		j--;
> -		if (!j)
> -			control |= (DW_EDMA_V0_LIE | DW_EDMA_V0_RIE);
> -
> +		if (!j) {
> +			control |= DW_EDMA_V0_LIE;
> +			if (!(chan->chip->flags & DW_EDMA_CHIP_LOCAL))
> +				control |= DW_EDMA_V0_RIE;
> +		}
>  		/* Channel control */
>  		SET_LL_32(&lli[i].control, control);
>  		/* Transfer size */
> @@ -420,15 +423,16 @@ void dw_edma_v0_core_start(struct dw_edma_chunk *chunk, bool first)
>  		SET_CH_32(chip, chan->dir, chan->id, ch_control1,
>  			  (DW_EDMA_V0_CCS | DW_EDMA_V0_LLE));
>  		/* Linked list */
> -		#ifdef CONFIG_64BIT
> -			SET_CH_64(chip, chan->dir, chan->id, llp.reg,
> -				  chunk->ll_region.paddr);
> -		#else /* CONFIG_64BIT */
> +		if ((chan->chip->flags & DW_EDMA_CHIP_32BIT_DBI) ||
> +		    !IS_ENABLED(CONFIG_64BIT)) {
>  			SET_CH_32(chip, chan->dir, chan->id, llp.lsb,
>  				  lower_32_bits(chunk->ll_region.paddr));
>  			SET_CH_32(chip, chan->dir, chan->id, llp.msb,
>  				  upper_32_bits(chunk->ll_region.paddr));
> -		#endif /* CONFIG_64BIT */
> +		} else {
> +			SET_CH_64(chip, chan->dir, chan->id, llp.reg,
> +				  chunk->ll_region.paddr);
> +		}
>  	}
>  	/* Doorbell */
>  	SET_RW_32(chip, chan->dir, doorbell,
> diff --git a/include/linux/dma/edma.h b/include/linux/dma/edma.h
> index fcfbc0f47f83d..4321f6378ef66 100644
> --- a/include/linux/dma/edma.h
> +++ b/include/linux/dma/edma.h
> @@ -33,6 +33,12 @@ enum dw_edma_map_format {
>  	EDMA_MF_HDMA_COMPAT = 0x5
>  };
>  
> +/* Probe EDMA engine locally and prevent generate MSI to host side*/
> +#define DW_EDMA_CHIP_LOCAL	BIT(0)
> +
> +/* Only support 32bit DBI register access */
> +#define DW_EDMA_CHIP_32BIT_DBI	BIT(1)
> +
>  /**
>   * struct dw_edma_chip - representation of DesignWare eDMA controller hardware
>   * @dev:		 struct device of the eDMA controller
> @@ -40,6 +46,8 @@ enum dw_edma_map_format {
>   * @nr_irqs:		 total dma irq number
>   * reg64bit		 if support 64bit write to register
>   * @ops			 DMA channel to IRQ number mapping
> + * @flags		 - DW_EDMA_CHIP_LOCAL
> + *			 - DW_EDMA_CHIP_32BIT_DBI
>   * @wr_ch_cnt		 DMA write channel number
>   * @rd_ch_cnt		 DMA read channel number
>   * @rg_region		 DMA register region
> @@ -53,6 +61,7 @@ struct dw_edma_chip {
>  	int			id;
>  	int			nr_irqs;
>  	const struct dw_edma_core_ops   *ops;
> +	u32			flags;
>  
>  	void __iomem		*reg_base;
>  
> -- 
> 2.24.0.rc1
>
Zhi Li March 10, 2022, 5 p.m. UTC | #3
On Thu, Mar 10, 2022 at 1:44 AM Manivannan Sadhasivam
<manivannan.sadhasivam@linaro.org> wrote:
>
> On Mon, Mar 07, 2022 at 04:47:49PM -0600, Frank Li wrote:
> > Allow PCI EP probe DMA locally and prevent use of remote MSI
> > to remote PCI host.
> >
> > Add option to force 32bit DBI register access even on
> > 64-bit systems. i.MX8 hardware only allowed 32bit register
> > access.
> >
> > Signed-off-by: Frank Li <Frank.Li@nxp.com>
> > ---
> >
> > Resend added dmaengine@vger.kernel.org
> >
> > Change from v2 to v3
> >  - rework commit message
> >  - Change to DW_EDMA_CHIP_32BIT_DBI
> >  - using DW_EDMA_CHIP_LOCAL control msi
> >  - Apply Bjorn's comments,
> >       if (!j) {
> >                control |= DW_EDMA_V0_LIE;
> >                if (!(chan->chip->flags & DW_EDMA_CHIP_LOCAL))
> >                                control |= DW_EDMA_V0_RIE;
> >         }
> >
> >       if ((chan->chip->flags & DW_EDMA_CHIP_REG32BIT) ||
> >               !IS_ENABLED(CONFIG_64BIT)) {
> >           SET_CH_32(...);
> >           SET_CH_32(...);
> >        } else {
> >           SET_CH_64(...);
> >        }
> >
> >
> > Change from v1 to v2
> > - none
> >
> >  drivers/dma/dw-edma/dw-edma-v0-core.c | 20 ++++++++++++--------
> >  include/linux/dma/edma.h              |  9 +++++++++
> >  2 files changed, 21 insertions(+), 8 deletions(-)
> >
> > diff --git a/drivers/dma/dw-edma/dw-edma-v0-core.c b/drivers/dma/dw-edma/dw-edma-v0-core.c
> > index 6e2f83e31a03a..081cd7997348d 100644
> > --- a/drivers/dma/dw-edma/dw-edma-v0-core.c
> > +++ b/drivers/dma/dw-edma/dw-edma-v0-core.c
> > @@ -307,6 +307,7 @@ u32 dw_edma_v0_core_status_abort_int(struct dw_edma_chip *chip, enum dw_edma_dir
> >  static void dw_edma_v0_core_write_chunk(struct dw_edma_chunk *chunk)
> >  {
> >       struct dw_edma_burst *child;
> > +     struct dw_edma_chan *chan = chunk->chan;
> >       struct dw_edma_v0_lli __iomem *lli;
> >       struct dw_edma_v0_llp __iomem *llp;
> >       u32 control = 0, i = 0;
> > @@ -320,9 +321,11 @@ static void dw_edma_v0_core_write_chunk(struct dw_edma_chunk *chunk)
> >       j = chunk->bursts_alloc;
> >       list_for_each_entry(child, &chunk->burst->list, list) {
> >               j--;
> > -             if (!j)
> > -                     control |= (DW_EDMA_V0_LIE | DW_EDMA_V0_RIE);
> > -
> > +             if (!j) {
> > +                     control |= DW_EDMA_V0_LIE;
> > +                     if (!(chan->chip->flags & DW_EDMA_CHIP_LOCAL))
> > +                             control |= DW_EDMA_V0_RIE;
> > +             }
> >               /* Channel control */
> >               SET_LL_32(&lli[i].control, control);
> >               /* Transfer size */
> > @@ -420,15 +423,16 @@ void dw_edma_v0_core_start(struct dw_edma_chunk *chunk, bool first)
> >               SET_CH_32(chip, chan->dir, chan->id, ch_control1,
> >                         (DW_EDMA_V0_CCS | DW_EDMA_V0_LLE));
> >               /* Linked list */
> > -             #ifdef CONFIG_64BIT
> > -                     SET_CH_64(chip, chan->dir, chan->id, llp.reg,
> > -                               chunk->ll_region.paddr);
> > -             #else /* CONFIG_64BIT */
> > +             if ((chan->chip->flags & DW_EDMA_CHIP_32BIT_DBI) ||
> > +                 !IS_ENABLED(CONFIG_64BIT)) {
> >                       SET_CH_32(chip, chan->dir, chan->id, llp.lsb,
> >                                 lower_32_bits(chunk->ll_region.paddr));
> >                       SET_CH_32(chip, chan->dir, chan->id, llp.msb,
> >                                 upper_32_bits(chunk->ll_region.paddr));
> > -             #endif /* CONFIG_64BIT */
> > +             } else {
> > +                     SET_CH_64(chip, chan->dir, chan->id, llp.reg,
> > +                               chunk->ll_region.paddr);
> > +             }
> >       }
> >       /* Doorbell */
> >       SET_RW_32(chip, chan->dir, doorbell,
> > diff --git a/include/linux/dma/edma.h b/include/linux/dma/edma.h
> > index fcfbc0f47f83d..4321f6378ef66 100644
> > --- a/include/linux/dma/edma.h
> > +++ b/include/linux/dma/edma.h
> > @@ -33,6 +33,12 @@ enum dw_edma_map_format {
> >       EDMA_MF_HDMA_COMPAT = 0x5
> >  };
> >
> > +/* Probe EDMA engine locally and prevent generate MSI to host side*/
> > +#define DW_EDMA_CHIP_LOCAL   BIT(0)
> > +
> > +/* Only support 32bit DBI register access */
> > +#define DW_EDMA_CHIP_32BIT_DBI       BIT(1)
> > +
>
> How about using an enum for defining the flags? This would help us organize the
> flags in a more coherent way and also will give the benefit of kdoc.

Did you see other linux code use enum as bitmask?
According to my understanding, enum just chooses values in a list.

>
> /**
>  * enum dw_edma_chip_flags - Flags specific to an eDMA chip
>  * @DW_EDMA_CHIP_LOCAL:         eDMA is used locally by an endpoint
>  * @DW_EDMA_CHIP_32BIT_DBI:     eDMA only supports 32bit DBI access
>  */
> enum dw_edma_chip_flags {
>         DW_EDMA_CHIP_LOCAL = BIT(0),
>         DW_EDMA_CHIP_32BIT_DBI = BIT(1),
> };
>
> >  /**
> >   * struct dw_edma_chip - representation of DesignWare eDMA controller hardware
> >   * @dev:              struct device of the eDMA controller
> > @@ -40,6 +46,8 @@ enum dw_edma_map_format {
> >   * @nr_irqs:          total dma irq number
> >   * reg64bit           if support 64bit write to register
> >   * @ops                       DMA channel to IRQ number mapping
> > + * @flags             - DW_EDMA_CHIP_LOCAL
> > + *                    - DW_EDMA_CHIP_32BIT_DBI
>
> No need to mention the flags here if you use the enum I suggested above.
>
> >   * @wr_ch_cnt                 DMA write channel number
> >   * @rd_ch_cnt                 DMA read channel number
> >   * @rg_region                 DMA register region
> > @@ -53,6 +61,7 @@ struct dw_edma_chip {
> >       int                     id;
> >       int                     nr_irqs;
> >       const struct dw_edma_core_ops   *ops;
> > +     u32                     flags;
>
>         enum dw_edma_chip_flags flags;
>
> Thanks,
> Mani
>
> >
> >       void __iomem            *reg_base;
> >
> > --
> > 2.24.0.rc1
> >
Zhi Li March 18, 2022, 6:40 p.m. UTC | #4
On Thu, Mar 10, 2022 at 11:00 AM Zhi Li <lznuaa@gmail.com> wrote:
>
> On Thu, Mar 10, 2022 at 1:44 AM Manivannan Sadhasivam
> <manivannan.sadhasivam@linaro.org> wrote:
> >
> > On Mon, Mar 07, 2022 at 04:47:49PM -0600, Frank Li wrote:
> > > Allow PCI EP probe DMA locally and prevent use of remote MSI
> > > to remote PCI host.
> > >
> > > Add option to force 32bit DBI register access even on
> > > 64-bit systems. i.MX8 hardware only allowed 32bit register
> > > access.
> > >
> > > Signed-off-by: Frank Li <Frank.Li@nxp.com>
> > > ---
> > >
> > > Resend added dmaengine@vger.kernel.org
> > >
> > > Change from v2 to v3
> > >  - rework commit message
> > >  - Change to DW_EDMA_CHIP_32BIT_DBI
> > >  - using DW_EDMA_CHIP_LOCAL control msi
> > >  - Apply Bjorn's comments,
> > >       if (!j) {
> > >                control |= DW_EDMA_V0_LIE;
> > >                if (!(chan->chip->flags & DW_EDMA_CHIP_LOCAL))
> > >                                control |= DW_EDMA_V0_RIE;
> > >         }
> > >
> > >       if ((chan->chip->flags & DW_EDMA_CHIP_REG32BIT) ||
> > >               !IS_ENABLED(CONFIG_64BIT)) {
> > >           SET_CH_32(...);
> > >           SET_CH_32(...);
> > >        } else {
> > >           SET_CH_64(...);
> > >        }
> > >
> > >
> > > Change from v1 to v2
> > > - none
> > >
> > >  drivers/dma/dw-edma/dw-edma-v0-core.c | 20 ++++++++++++--------
> > >  include/linux/dma/edma.h              |  9 +++++++++
> > >  2 files changed, 21 insertions(+), 8 deletions(-)
> > >
> > > diff --git a/drivers/dma/dw-edma/dw-edma-v0-core.c b/drivers/dma/dw-edma/dw-edma-v0-core.c
> > > index 6e2f83e31a03a..081cd7997348d 100644
> > > --- a/drivers/dma/dw-edma/dw-edma-v0-core.c
> > > +++ b/drivers/dma/dw-edma/dw-edma-v0-core.c
> > > @@ -307,6 +307,7 @@ u32 dw_edma_v0_core_status_abort_int(struct dw_edma_chip *chip, enum dw_edma_dir
> > >  static void dw_edma_v0_core_write_chunk(struct dw_edma_chunk *chunk)
> > >  {
> > >       struct dw_edma_burst *child;
> > > +     struct dw_edma_chan *chan = chunk->chan;
> > >       struct dw_edma_v0_lli __iomem *lli;
> > >       struct dw_edma_v0_llp __iomem *llp;
> > >       u32 control = 0, i = 0;
> > > @@ -320,9 +321,11 @@ static void dw_edma_v0_core_write_chunk(struct dw_edma_chunk *chunk)
> > >       j = chunk->bursts_alloc;
> > >       list_for_each_entry(child, &chunk->burst->list, list) {
> > >               j--;
> > > -             if (!j)
> > > -                     control |= (DW_EDMA_V0_LIE | DW_EDMA_V0_RIE);
> > > -
> > > +             if (!j) {
> > > +                     control |= DW_EDMA_V0_LIE;
> > > +                     if (!(chan->chip->flags & DW_EDMA_CHIP_LOCAL))
> > > +                             control |= DW_EDMA_V0_RIE;
> > > +             }
> > >               /* Channel control */
> > >               SET_LL_32(&lli[i].control, control);
> > >               /* Transfer size */
> > > @@ -420,15 +423,16 @@ void dw_edma_v0_core_start(struct dw_edma_chunk *chunk, bool first)
> > >               SET_CH_32(chip, chan->dir, chan->id, ch_control1,
> > >                         (DW_EDMA_V0_CCS | DW_EDMA_V0_LLE));
> > >               /* Linked list */
> > > -             #ifdef CONFIG_64BIT
> > > -                     SET_CH_64(chip, chan->dir, chan->id, llp.reg,
> > > -                               chunk->ll_region.paddr);
> > > -             #else /* CONFIG_64BIT */
> > > +             if ((chan->chip->flags & DW_EDMA_CHIP_32BIT_DBI) ||
> > > +                 !IS_ENABLED(CONFIG_64BIT)) {
> > >                       SET_CH_32(chip, chan->dir, chan->id, llp.lsb,
> > >                                 lower_32_bits(chunk->ll_region.paddr));
> > >                       SET_CH_32(chip, chan->dir, chan->id, llp.msb,
> > >                                 upper_32_bits(chunk->ll_region.paddr));
> > > -             #endif /* CONFIG_64BIT */
> > > +             } else {
> > > +                     SET_CH_64(chip, chan->dir, chan->id, llp.reg,
> > > +                               chunk->ll_region.paddr);
> > > +             }
> > >       }
> > >       /* Doorbell */
> > >       SET_RW_32(chip, chan->dir, doorbell,
> > > diff --git a/include/linux/dma/edma.h b/include/linux/dma/edma.h
> > > index fcfbc0f47f83d..4321f6378ef66 100644
> > > --- a/include/linux/dma/edma.h
> > > +++ b/include/linux/dma/edma.h
> > > @@ -33,6 +33,12 @@ enum dw_edma_map_format {
> > >       EDMA_MF_HDMA_COMPAT = 0x5
> > >  };
> > >
> > > +/* Probe EDMA engine locally and prevent generate MSI to host side*/
> > > +#define DW_EDMA_CHIP_LOCAL   BIT(0)
> > > +
> > > +/* Only support 32bit DBI register access */
> > > +#define DW_EDMA_CHIP_32BIT_DBI       BIT(1)
> > > +
> >
> > How about using an enum for defining the flags? This would help us organize the
> > flags in a more coherent way and also will give the benefit of kdoc.
>
> Did you see other linux code use enum as bitmask?
> According to my understanding, enum just chooses values in a list.

Do you agree that using define because it will be used as bitmask?

best regards
Frank Li

>
> >
> > /**
> >  * enum dw_edma_chip_flags - Flags specific to an eDMA chip
> >  * @DW_EDMA_CHIP_LOCAL:         eDMA is used locally by an endpoint
> >  * @DW_EDMA_CHIP_32BIT_DBI:     eDMA only supports 32bit DBI access
> >  */
> > enum dw_edma_chip_flags {
> >         DW_EDMA_CHIP_LOCAL = BIT(0),
> >         DW_EDMA_CHIP_32BIT_DBI = BIT(1),
> > };
> >
> > >  /**
> > >   * struct dw_edma_chip - representation of DesignWare eDMA controller hardware
> > >   * @dev:              struct device of the eDMA controller
> > > @@ -40,6 +46,8 @@ enum dw_edma_map_format {
> > >   * @nr_irqs:          total dma irq number
> > >   * reg64bit           if support 64bit write to register
> > >   * @ops                       DMA channel to IRQ number mapping
> > > + * @flags             - DW_EDMA_CHIP_LOCAL
> > > + *                    - DW_EDMA_CHIP_32BIT_DBI
> >
> > No need to mention the flags here if you use the enum I suggested above.
> >
> > >   * @wr_ch_cnt                 DMA write channel number
> > >   * @rd_ch_cnt                 DMA read channel number
> > >   * @rg_region                 DMA register region
> > > @@ -53,6 +61,7 @@ struct dw_edma_chip {
> > >       int                     id;
> > >       int                     nr_irqs;
> > >       const struct dw_edma_core_ops   *ops;
> > > +     u32                     flags;
> >
> >         enum dw_edma_chip_flags flags;
> >
> > Thanks,
> > Mani
> >
> > >
> > >       void __iomem            *reg_base;
> > >
> > > --
> > > 2.24.0.rc1
> > >
Manivannan Sadhasivam March 18, 2022, 7:28 p.m. UTC | #5
On Fri, Mar 18, 2022 at 01:40:44PM -0500, Zhi Li wrote:
> On Thu, Mar 10, 2022 at 11:00 AM Zhi Li <lznuaa@gmail.com> wrote:
> >
> > On Thu, Mar 10, 2022 at 1:44 AM Manivannan Sadhasivam
> > <manivannan.sadhasivam@linaro.org> wrote:
> > >
> > > On Mon, Mar 07, 2022 at 04:47:49PM -0600, Frank Li wrote:
> > > > Allow PCI EP probe DMA locally and prevent use of remote MSI
> > > > to remote PCI host.
> > > >
> > > > Add option to force 32bit DBI register access even on
> > > > 64-bit systems. i.MX8 hardware only allowed 32bit register
> > > > access.
> > > >
> > > > Signed-off-by: Frank Li <Frank.Li@nxp.com>
> > > > ---
> > > >
> > > > Resend added dmaengine@vger.kernel.org
> > > >
> > > > Change from v2 to v3
> > > >  - rework commit message
> > > >  - Change to DW_EDMA_CHIP_32BIT_DBI
> > > >  - using DW_EDMA_CHIP_LOCAL control msi
> > > >  - Apply Bjorn's comments,
> > > >       if (!j) {
> > > >                control |= DW_EDMA_V0_LIE;
> > > >                if (!(chan->chip->flags & DW_EDMA_CHIP_LOCAL))
> > > >                                control |= DW_EDMA_V0_RIE;
> > > >         }
> > > >
> > > >       if ((chan->chip->flags & DW_EDMA_CHIP_REG32BIT) ||
> > > >               !IS_ENABLED(CONFIG_64BIT)) {
> > > >           SET_CH_32(...);
> > > >           SET_CH_32(...);
> > > >        } else {
> > > >           SET_CH_64(...);
> > > >        }
> > > >
> > > >
> > > > Change from v1 to v2
> > > > - none
> > > >
> > > >  drivers/dma/dw-edma/dw-edma-v0-core.c | 20 ++++++++++++--------
> > > >  include/linux/dma/edma.h              |  9 +++++++++
> > > >  2 files changed, 21 insertions(+), 8 deletions(-)
> > > >
> > > > diff --git a/drivers/dma/dw-edma/dw-edma-v0-core.c b/drivers/dma/dw-edma/dw-edma-v0-core.c
> > > > index 6e2f83e31a03a..081cd7997348d 100644
> > > > --- a/drivers/dma/dw-edma/dw-edma-v0-core.c
> > > > +++ b/drivers/dma/dw-edma/dw-edma-v0-core.c
> > > > @@ -307,6 +307,7 @@ u32 dw_edma_v0_core_status_abort_int(struct dw_edma_chip *chip, enum dw_edma_dir
> > > >  static void dw_edma_v0_core_write_chunk(struct dw_edma_chunk *chunk)
> > > >  {
> > > >       struct dw_edma_burst *child;
> > > > +     struct dw_edma_chan *chan = chunk->chan;
> > > >       struct dw_edma_v0_lli __iomem *lli;
> > > >       struct dw_edma_v0_llp __iomem *llp;
> > > >       u32 control = 0, i = 0;
> > > > @@ -320,9 +321,11 @@ static void dw_edma_v0_core_write_chunk(struct dw_edma_chunk *chunk)
> > > >       j = chunk->bursts_alloc;
> > > >       list_for_each_entry(child, &chunk->burst->list, list) {
> > > >               j--;
> > > > -             if (!j)
> > > > -                     control |= (DW_EDMA_V0_LIE | DW_EDMA_V0_RIE);
> > > > -
> > > > +             if (!j) {
> > > > +                     control |= DW_EDMA_V0_LIE;
> > > > +                     if (!(chan->chip->flags & DW_EDMA_CHIP_LOCAL))
> > > > +                             control |= DW_EDMA_V0_RIE;
> > > > +             }
> > > >               /* Channel control */
> > > >               SET_LL_32(&lli[i].control, control);
> > > >               /* Transfer size */
> > > > @@ -420,15 +423,16 @@ void dw_edma_v0_core_start(struct dw_edma_chunk *chunk, bool first)
> > > >               SET_CH_32(chip, chan->dir, chan->id, ch_control1,
> > > >                         (DW_EDMA_V0_CCS | DW_EDMA_V0_LLE));
> > > >               /* Linked list */
> > > > -             #ifdef CONFIG_64BIT
> > > > -                     SET_CH_64(chip, chan->dir, chan->id, llp.reg,
> > > > -                               chunk->ll_region.paddr);
> > > > -             #else /* CONFIG_64BIT */
> > > > +             if ((chan->chip->flags & DW_EDMA_CHIP_32BIT_DBI) ||
> > > > +                 !IS_ENABLED(CONFIG_64BIT)) {
> > > >                       SET_CH_32(chip, chan->dir, chan->id, llp.lsb,
> > > >                                 lower_32_bits(chunk->ll_region.paddr));
> > > >                       SET_CH_32(chip, chan->dir, chan->id, llp.msb,
> > > >                                 upper_32_bits(chunk->ll_region.paddr));
> > > > -             #endif /* CONFIG_64BIT */
> > > > +             } else {
> > > > +                     SET_CH_64(chip, chan->dir, chan->id, llp.reg,
> > > > +                               chunk->ll_region.paddr);
> > > > +             }
> > > >       }
> > > >       /* Doorbell */
> > > >       SET_RW_32(chip, chan->dir, doorbell,
> > > > diff --git a/include/linux/dma/edma.h b/include/linux/dma/edma.h
> > > > index fcfbc0f47f83d..4321f6378ef66 100644
> > > > --- a/include/linux/dma/edma.h
> > > > +++ b/include/linux/dma/edma.h
> > > > @@ -33,6 +33,12 @@ enum dw_edma_map_format {
> > > >       EDMA_MF_HDMA_COMPAT = 0x5
> > > >  };
> > > >
> > > > +/* Probe EDMA engine locally and prevent generate MSI to host side*/
> > > > +#define DW_EDMA_CHIP_LOCAL   BIT(0)
> > > > +
> > > > +/* Only support 32bit DBI register access */
> > > > +#define DW_EDMA_CHIP_32BIT_DBI       BIT(1)
> > > > +
> > >
> > > How about using an enum for defining the flags? This would help us organize the
> > > flags in a more coherent way and also will give the benefit of kdoc.
> >
> > Did you see other linux code use enum as bitmask?
> > According to my understanding, enum just chooses values in a list.
>

There are lot of places it is used:

$ grep -r "= BIT(.*)," include/
 
> Do you agree that using define because it will be used as bitmask?
> 

As I said, using enum helps in organizing the flags and it also provides kdoc.
I'd prefer to go with it.

Thanks,
Mani

> best regards
> Frank Li
> 
> >
> > >
> > > /**
> > >  * enum dw_edma_chip_flags - Flags specific to an eDMA chip
> > >  * @DW_EDMA_CHIP_LOCAL:         eDMA is used locally by an endpoint
> > >  * @DW_EDMA_CHIP_32BIT_DBI:     eDMA only supports 32bit DBI access
> > >  */
> > > enum dw_edma_chip_flags {
> > >         DW_EDMA_CHIP_LOCAL = BIT(0),
> > >         DW_EDMA_CHIP_32BIT_DBI = BIT(1),
> > > };
> > >
> > > >  /**
> > > >   * struct dw_edma_chip - representation of DesignWare eDMA controller hardware
> > > >   * @dev:              struct device of the eDMA controller
> > > > @@ -40,6 +46,8 @@ enum dw_edma_map_format {
> > > >   * @nr_irqs:          total dma irq number
> > > >   * reg64bit           if support 64bit write to register
> > > >   * @ops                       DMA channel to IRQ number mapping
> > > > + * @flags             - DW_EDMA_CHIP_LOCAL
> > > > + *                    - DW_EDMA_CHIP_32BIT_DBI
> > >
> > > No need to mention the flags here if you use the enum I suggested above.
> > >
> > > >   * @wr_ch_cnt                 DMA write channel number
> > > >   * @rd_ch_cnt                 DMA read channel number
> > > >   * @rg_region                 DMA register region
> > > > @@ -53,6 +61,7 @@ struct dw_edma_chip {
> > > >       int                     id;
> > > >       int                     nr_irqs;
> > > >       const struct dw_edma_core_ops   *ops;
> > > > +     u32                     flags;
> > >
> > >         enum dw_edma_chip_flags flags;
> > >
> > > Thanks,
> > > Mani
> > >
> > > >
> > > >       void __iomem            *reg_base;
> > > >
> > > > --
> > > > 2.24.0.rc1
> > > >
diff mbox series

Patch

diff --git a/drivers/dma/dw-edma/dw-edma-v0-core.c b/drivers/dma/dw-edma/dw-edma-v0-core.c
index 6e2f83e31a03a..081cd7997348d 100644
--- a/drivers/dma/dw-edma/dw-edma-v0-core.c
+++ b/drivers/dma/dw-edma/dw-edma-v0-core.c
@@ -307,6 +307,7 @@  u32 dw_edma_v0_core_status_abort_int(struct dw_edma_chip *chip, enum dw_edma_dir
 static void dw_edma_v0_core_write_chunk(struct dw_edma_chunk *chunk)
 {
 	struct dw_edma_burst *child;
+	struct dw_edma_chan *chan = chunk->chan;
 	struct dw_edma_v0_lli __iomem *lli;
 	struct dw_edma_v0_llp __iomem *llp;
 	u32 control = 0, i = 0;
@@ -320,9 +321,11 @@  static void dw_edma_v0_core_write_chunk(struct dw_edma_chunk *chunk)
 	j = chunk->bursts_alloc;
 	list_for_each_entry(child, &chunk->burst->list, list) {
 		j--;
-		if (!j)
-			control |= (DW_EDMA_V0_LIE | DW_EDMA_V0_RIE);
-
+		if (!j) {
+			control |= DW_EDMA_V0_LIE;
+			if (!(chan->chip->flags & DW_EDMA_CHIP_LOCAL))
+				control |= DW_EDMA_V0_RIE;
+		}
 		/* Channel control */
 		SET_LL_32(&lli[i].control, control);
 		/* Transfer size */
@@ -420,15 +423,16 @@  void dw_edma_v0_core_start(struct dw_edma_chunk *chunk, bool first)
 		SET_CH_32(chip, chan->dir, chan->id, ch_control1,
 			  (DW_EDMA_V0_CCS | DW_EDMA_V0_LLE));
 		/* Linked list */
-		#ifdef CONFIG_64BIT
-			SET_CH_64(chip, chan->dir, chan->id, llp.reg,
-				  chunk->ll_region.paddr);
-		#else /* CONFIG_64BIT */
+		if ((chan->chip->flags & DW_EDMA_CHIP_32BIT_DBI) ||
+		    !IS_ENABLED(CONFIG_64BIT)) {
 			SET_CH_32(chip, chan->dir, chan->id, llp.lsb,
 				  lower_32_bits(chunk->ll_region.paddr));
 			SET_CH_32(chip, chan->dir, chan->id, llp.msb,
 				  upper_32_bits(chunk->ll_region.paddr));
-		#endif /* CONFIG_64BIT */
+		} else {
+			SET_CH_64(chip, chan->dir, chan->id, llp.reg,
+				  chunk->ll_region.paddr);
+		}
 	}
 	/* Doorbell */
 	SET_RW_32(chip, chan->dir, doorbell,
diff --git a/include/linux/dma/edma.h b/include/linux/dma/edma.h
index fcfbc0f47f83d..4321f6378ef66 100644
--- a/include/linux/dma/edma.h
+++ b/include/linux/dma/edma.h
@@ -33,6 +33,12 @@  enum dw_edma_map_format {
 	EDMA_MF_HDMA_COMPAT = 0x5
 };
 
+/* Probe EDMA engine locally and prevent generate MSI to host side*/
+#define DW_EDMA_CHIP_LOCAL	BIT(0)
+
+/* Only support 32bit DBI register access */
+#define DW_EDMA_CHIP_32BIT_DBI	BIT(1)
+
 /**
  * struct dw_edma_chip - representation of DesignWare eDMA controller hardware
  * @dev:		 struct device of the eDMA controller
@@ -40,6 +46,8 @@  enum dw_edma_map_format {
  * @nr_irqs:		 total dma irq number
  * reg64bit		 if support 64bit write to register
  * @ops			 DMA channel to IRQ number mapping
+ * @flags		 - DW_EDMA_CHIP_LOCAL
+ *			 - DW_EDMA_CHIP_32BIT_DBI
  * @wr_ch_cnt		 DMA write channel number
  * @rd_ch_cnt		 DMA read channel number
  * @rg_region		 DMA register region
@@ -53,6 +61,7 @@  struct dw_edma_chip {
 	int			id;
 	int			nr_irqs;
 	const struct dw_edma_core_ops   *ops;
+	u32			flags;
 
 	void __iomem		*reg_base;