All of lore.kernel.org
 help / color / mirror / Atom feed
From: Arnd Bergmann <arnd@arndb.de>
To: Jonas Jensen <jonas.jensen@gmail.com>
Cc: linux-arm-kernel@lists.infradead.org,
	linux-kernel@vger.kernel.org, arm@kernel.org,
	vinod.koul@intel.com, djbw@fb.com, linux@arm.linux.org.uk
Subject: Re: [PATCH v4] dmaengine: Add MOXA ART DMA engine driver
Date: Mon, 29 Jul 2013 18:35:20 +0200	[thread overview]
Message-ID: <201307291835.21151.arnd@arndb.de> (raw)
In-Reply-To: <1375105442-14827-1-git-send-email-jonas.jensen@gmail.com>

On Monday 29 July 2013, Jonas Jensen wrote:

> diff --git a/Documentation/devicetree/bindings/dma/moxa,moxart-dma.txt b/Documentation/devicetree/bindings/dma/moxa,moxart-dma.txt
> new file mode 100644
> index 0000000..f18f0fb
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/dma/moxa,moxart-dma.txt
> @@ -0,0 +1,19 @@
> +MOXA ART DMA Controller
> +
> +See dma.txt first
> +
> +Required properties:
> +
> +- compatible : Must be "moxa,moxart-dma"
> +- reg : Should contain registers location and length
> +- interrupts : Should contain the interrupt number
> +- #dma-cells : see dma.txt, should be 1
> +
> +Example:
> +
> +	dma: dma@90500000 {
> +		compatible = "moxa,moxart-dma";
> +		reg = <0x90500000 0x1000>;
> +		interrupts = <24 0>;
> +		#dma-cells = <1>;
> +	};

The binding should really define what the one cell in the dma specifier refers
to. For all I can tell, it is a hardcoded channel number, and each channel
corresponds to exactly one slave request line.

> +static DEFINE_SPINLOCK(dma_lock);

Can't this be part of the device structure? You should not need a global lock here.

> +struct moxart_dma_container {
> +	int			ctlr;
> +	struct dma_device	dma_slave;
> +	struct moxart_dma_chan	slave_chans[APB_DMA_MAX_CHANNEL];
> +};
> +
> +struct moxart_dma_container *mdc;

Same here. Also, you should never have global identifiers with just three characters.
Most of your 'static' variables are already prefixed "moxart_".

> +static int moxart_slave_config(struct dma_chan *chan,
> +			       struct dma_slave_config *cfg)
> +{
> +	struct moxart_dma_chan *mchan = to_moxart_dma_chan(chan);
> +	union moxart_dma_reg_cfg mcfg;
> +	unsigned long flags;
> +	unsigned int data_width, data_inc;
> +
> +	spin_lock_irqsave(&dma_lock, flags);
> +
> +	memcpy(&mchan->cfg, cfg, sizeof(mchan->cfg));
> +
> +	mcfg.ul = readl(&mchan->reg->cfg.ul);
> +	mcfg.bits.burst = APB_DMAB_BURST_MODE;
> +
> +	switch (mchan->cfg.src_addr_width) {
> +	case DMA_SLAVE_BUSWIDTH_1_BYTE:
> +		data_width = APB_DMAB_DATA_WIDTH_1;
> +		data_inc = APB_DMAB_DEST_INC_1_4;
> +		break;
> +	case DMA_SLAVE_BUSWIDTH_2_BYTES:
> +		data_width = APB_DMAB_DATA_WIDTH_2;
> +		data_inc = APB_DMAB_DEST_INC_2_8;
> +		break;
> +	default:
> +		data_width = APB_DMAB_DATA_WIDTH_4;
> +		data_inc = APB_DMAB_DEST_INC_4_16;
> +		break;
> +	}
> +
> +	if (mchan->cfg.direction == DMA_MEM_TO_DEV) {
> +		mcfg.bits.data_width = data_width;
> +		mcfg.bits.dest_sel = APB_DMAB_DEST_APB;
> +		mcfg.bits.dest_inc = APB_DMAB_DEST_INC_0;
> +		mcfg.bits.source_sel = APB_DMAB_SOURCE_AHB;
> +		mcfg.bits.source_inc = data_inc;
> +
> +		mcfg.bits.dest_req_no = mchan->cfg.slave_id;
> +		mcfg.bits.source_req_no = 0;

You must not override the "dest_req_no" and "dest_req_no" in moxart_slave_config
since they are already set by the ->xlate() function and the driver calling 
slave_config generally has no knowledge of what the slave id is.

> +static struct platform_driver moxart_driver;

Please reorder the symbols so you don't need the forward declaration.

> +bool moxart_filter_fn(struct dma_chan *chan, void *param)
> +{
> +	if (chan->device->dev->driver == &moxart_driver.driver) {

No need to check the driver. What you want to check instead is that
the *device* matches.

> +		struct moxart_dma_chan *mchan = to_moxart_dma_chan(chan);
> +		unsigned int ch_req = *(unsigned int *)param;
> +		dev_dbg(chan2dev(chan), "%s: mchan=%p ch_req=%d mchan->ch_num=%d\n",
> +			__func__, mchan, ch_req, mchan->ch_num);
> +		return ch_req == mchan->ch_num;
> +	} else {
> +		dev_dbg(chan2dev(chan), "%s: device not registered to this DMA engine\n",
> +			__func__);
> +		return false;
> +	}
> +}
> +EXPORT_SYMBOL(moxart_filter_fn);

Don't export the filter function. No slave driver should rely on this, since you
have DT probing.


> diff --git a/drivers/dma/moxart-dma.h b/drivers/dma/moxart-dma.h
> new file mode 100644
> index 0000000..a37b13f
> --- /dev/null
> +++ b/drivers/dma/moxart-dma.h

You don't need a separate file here, just move the contents into moxart-dma.c

> +union moxart_dma_reg_cfg {
> +
> +#define APB_DMA_ENABLE				BIT(0)
> +#define APB_DMA_FIN_INT_STS			BIT(1)
> +#define APB_DMA_FIN_INT_EN			BIT(2)
> +#define APB_DMA_BURST_MODE			BIT(3)
> +#define APB_DMA_ERR_INT_STS			BIT(4)
> +#define APB_DMA_ERR_INT_EN			BIT(5)
> +#define APB_DMA_SOURCE_AHB			BIT(6)
> +#define APB_DMA_SOURCE_APB			0
> +#define APB_DMA_DEST_AHB			BIT(7)
> +#define APB_DMA_DEST_APB			0
> +#define APB_DMA_SOURCE_INC_0			0
> +#define APB_DMA_SOURCE_INC_1_4			0x100
> +#define APB_DMA_SOURCE_INC_2_8			0x200
> +#define APB_DMA_SOURCE_INC_4_16			0x300
> +#define APB_DMA_SOURCE_DEC_1_4			0x500
> +#define APB_DMA_SOURCE_DEC_2_8			0x600
> +#define APB_DMA_SOURCE_DEC_4_16			0x700
> +#define APB_DMA_SOURCE_INC_MASK			0x700
> +#define APB_DMA_DEST_INC_0			0
> +#define APB_DMA_DEST_INC_1_4			0x1000
> +#define APB_DMA_DEST_INC_2_8			0x2000
> +#define APB_DMA_DEST_INC_4_16			0x3000
> +#define APB_DMA_DEST_DEC_1_4			0x5000
> +#define APB_DMA_DEST_DEC_2_8			0x6000
> +#define APB_DMA_DEST_DEC_4_16			0x7000
> +#define APB_DMA_DEST_INC_MASK			0x7000
> +#define APB_DMA_DEST_REQ_NO_MASK		0xf0000
> +#define APB_DMA_DATA_WIDTH_MASK			0x300000
> +#define APB_DMA_DATA_WIDTH_4			0
> +#define APB_DMA_DATA_WIDTH_2			0x100000
> +#define APB_DMA_DATA_WIDTH_1			0x200000
> +#define APB_DMA_SOURCE_REQ_NO_MASK		0xf000000
> +	unsigned int ul;
> +
> +	struct {
> +
> +#define APB_DMAB_ENABLE				1
> +		/* enable DMA */
> +		unsigned int enable:1;
> +
> +#define APB_DMAB_FIN_INT_STS			1
> +		/* finished interrupt status */
> +		unsigned int fin_int_sts:1;

The bit numbers don't actually match here if you build the kernel as
big-endian. You cannot use bitfields for hw data structures.

While you are here, get rid of the silly 'BIT' macro use as well.
Using hexadecimal literals is much clearer and you do that for
some fields anyway.

	Arnd

WARNING: multiple messages have this Message-ID (diff)
From: arnd@arndb.de (Arnd Bergmann)
To: linux-arm-kernel@lists.infradead.org
Subject: [PATCH v4] dmaengine: Add MOXA ART DMA engine driver
Date: Mon, 29 Jul 2013 18:35:20 +0200	[thread overview]
Message-ID: <201307291835.21151.arnd@arndb.de> (raw)
In-Reply-To: <1375105442-14827-1-git-send-email-jonas.jensen@gmail.com>

On Monday 29 July 2013, Jonas Jensen wrote:

> diff --git a/Documentation/devicetree/bindings/dma/moxa,moxart-dma.txt b/Documentation/devicetree/bindings/dma/moxa,moxart-dma.txt
> new file mode 100644
> index 0000000..f18f0fb
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/dma/moxa,moxart-dma.txt
> @@ -0,0 +1,19 @@
> +MOXA ART DMA Controller
> +
> +See dma.txt first
> +
> +Required properties:
> +
> +- compatible : Must be "moxa,moxart-dma"
> +- reg : Should contain registers location and length
> +- interrupts : Should contain the interrupt number
> +- #dma-cells : see dma.txt, should be 1
> +
> +Example:
> +
> +	dma: dma at 90500000 {
> +		compatible = "moxa,moxart-dma";
> +		reg = <0x90500000 0x1000>;
> +		interrupts = <24 0>;
> +		#dma-cells = <1>;
> +	};

The binding should really define what the one cell in the dma specifier refers
to. For all I can tell, it is a hardcoded channel number, and each channel
corresponds to exactly one slave request line.

> +static DEFINE_SPINLOCK(dma_lock);

Can't this be part of the device structure? You should not need a global lock here.

> +struct moxart_dma_container {
> +	int			ctlr;
> +	struct dma_device	dma_slave;
> +	struct moxart_dma_chan	slave_chans[APB_DMA_MAX_CHANNEL];
> +};
> +
> +struct moxart_dma_container *mdc;

Same here. Also, you should never have global identifiers with just three characters.
Most of your 'static' variables are already prefixed "moxart_".

> +static int moxart_slave_config(struct dma_chan *chan,
> +			       struct dma_slave_config *cfg)
> +{
> +	struct moxart_dma_chan *mchan = to_moxart_dma_chan(chan);
> +	union moxart_dma_reg_cfg mcfg;
> +	unsigned long flags;
> +	unsigned int data_width, data_inc;
> +
> +	spin_lock_irqsave(&dma_lock, flags);
> +
> +	memcpy(&mchan->cfg, cfg, sizeof(mchan->cfg));
> +
> +	mcfg.ul = readl(&mchan->reg->cfg.ul);
> +	mcfg.bits.burst = APB_DMAB_BURST_MODE;
> +
> +	switch (mchan->cfg.src_addr_width) {
> +	case DMA_SLAVE_BUSWIDTH_1_BYTE:
> +		data_width = APB_DMAB_DATA_WIDTH_1;
> +		data_inc = APB_DMAB_DEST_INC_1_4;
> +		break;
> +	case DMA_SLAVE_BUSWIDTH_2_BYTES:
> +		data_width = APB_DMAB_DATA_WIDTH_2;
> +		data_inc = APB_DMAB_DEST_INC_2_8;
> +		break;
> +	default:
> +		data_width = APB_DMAB_DATA_WIDTH_4;
> +		data_inc = APB_DMAB_DEST_INC_4_16;
> +		break;
> +	}
> +
> +	if (mchan->cfg.direction == DMA_MEM_TO_DEV) {
> +		mcfg.bits.data_width = data_width;
> +		mcfg.bits.dest_sel = APB_DMAB_DEST_APB;
> +		mcfg.bits.dest_inc = APB_DMAB_DEST_INC_0;
> +		mcfg.bits.source_sel = APB_DMAB_SOURCE_AHB;
> +		mcfg.bits.source_inc = data_inc;
> +
> +		mcfg.bits.dest_req_no = mchan->cfg.slave_id;
> +		mcfg.bits.source_req_no = 0;

You must not override the "dest_req_no" and "dest_req_no" in moxart_slave_config
since they are already set by the ->xlate() function and the driver calling 
slave_config generally has no knowledge of what the slave id is.

> +static struct platform_driver moxart_driver;

Please reorder the symbols so you don't need the forward declaration.

> +bool moxart_filter_fn(struct dma_chan *chan, void *param)
> +{
> +	if (chan->device->dev->driver == &moxart_driver.driver) {

No need to check the driver. What you want to check instead is that
the *device* matches.

> +		struct moxart_dma_chan *mchan = to_moxart_dma_chan(chan);
> +		unsigned int ch_req = *(unsigned int *)param;
> +		dev_dbg(chan2dev(chan), "%s: mchan=%p ch_req=%d mchan->ch_num=%d\n",
> +			__func__, mchan, ch_req, mchan->ch_num);
> +		return ch_req == mchan->ch_num;
> +	} else {
> +		dev_dbg(chan2dev(chan), "%s: device not registered to this DMA engine\n",
> +			__func__);
> +		return false;
> +	}
> +}
> +EXPORT_SYMBOL(moxart_filter_fn);

Don't export the filter function. No slave driver should rely on this, since you
have DT probing.


> diff --git a/drivers/dma/moxart-dma.h b/drivers/dma/moxart-dma.h
> new file mode 100644
> index 0000000..a37b13f
> --- /dev/null
> +++ b/drivers/dma/moxart-dma.h

You don't need a separate file here, just move the contents into moxart-dma.c

> +union moxart_dma_reg_cfg {
> +
> +#define APB_DMA_ENABLE				BIT(0)
> +#define APB_DMA_FIN_INT_STS			BIT(1)
> +#define APB_DMA_FIN_INT_EN			BIT(2)
> +#define APB_DMA_BURST_MODE			BIT(3)
> +#define APB_DMA_ERR_INT_STS			BIT(4)
> +#define APB_DMA_ERR_INT_EN			BIT(5)
> +#define APB_DMA_SOURCE_AHB			BIT(6)
> +#define APB_DMA_SOURCE_APB			0
> +#define APB_DMA_DEST_AHB			BIT(7)
> +#define APB_DMA_DEST_APB			0
> +#define APB_DMA_SOURCE_INC_0			0
> +#define APB_DMA_SOURCE_INC_1_4			0x100
> +#define APB_DMA_SOURCE_INC_2_8			0x200
> +#define APB_DMA_SOURCE_INC_4_16			0x300
> +#define APB_DMA_SOURCE_DEC_1_4			0x500
> +#define APB_DMA_SOURCE_DEC_2_8			0x600
> +#define APB_DMA_SOURCE_DEC_4_16			0x700
> +#define APB_DMA_SOURCE_INC_MASK			0x700
> +#define APB_DMA_DEST_INC_0			0
> +#define APB_DMA_DEST_INC_1_4			0x1000
> +#define APB_DMA_DEST_INC_2_8			0x2000
> +#define APB_DMA_DEST_INC_4_16			0x3000
> +#define APB_DMA_DEST_DEC_1_4			0x5000
> +#define APB_DMA_DEST_DEC_2_8			0x6000
> +#define APB_DMA_DEST_DEC_4_16			0x7000
> +#define APB_DMA_DEST_INC_MASK			0x7000
> +#define APB_DMA_DEST_REQ_NO_MASK		0xf0000
> +#define APB_DMA_DATA_WIDTH_MASK			0x300000
> +#define APB_DMA_DATA_WIDTH_4			0
> +#define APB_DMA_DATA_WIDTH_2			0x100000
> +#define APB_DMA_DATA_WIDTH_1			0x200000
> +#define APB_DMA_SOURCE_REQ_NO_MASK		0xf000000
> +	unsigned int ul;
> +
> +	struct {
> +
> +#define APB_DMAB_ENABLE				1
> +		/* enable DMA */
> +		unsigned int enable:1;
> +
> +#define APB_DMAB_FIN_INT_STS			1
> +		/* finished interrupt status */
> +		unsigned int fin_int_sts:1;

The bit numbers don't actually match here if you build the kernel as
big-endian. You cannot use bitfields for hw data structures.

While you are here, get rid of the silly 'BIT' macro use as well.
Using hexadecimal literals is much clearer and you do that for
some fields anyway.

	Arnd

  reply	other threads:[~2013-07-29 16:35 UTC|newest]

Thread overview: 80+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-07-10  8:51 [PATCH] dmaengine: Add MOXA ART DMA engine driver Jonas Jensen
2013-07-10  8:51 ` Jonas Jensen
2013-07-10  9:30 ` Russell King - ARM Linux
2013-07-10  9:30   ` Russell King - ARM Linux
2013-07-10  9:48   ` Jonas Jensen
2013-07-10  9:48     ` Jonas Jensen
2013-07-10 12:43 ` [PATCH v2] " Jonas Jensen
2013-07-10 12:43   ` Jonas Jensen
2013-07-17 10:06   ` [PATCH v3] " Jonas Jensen
2013-07-17 10:06     ` Jonas Jensen
2013-07-29 13:44     ` [PATCH v4] " Jonas Jensen
2013-07-29 13:44       ` Jonas Jensen
2013-07-29 16:35       ` Arnd Bergmann [this message]
2013-07-29 16:35         ` Arnd Bergmann
2013-08-02 12:28         ` Jonas Jensen
2013-08-02 12:28           ` Jonas Jensen
2013-08-02 19:28           ` Arnd Bergmann
2013-08-02 19:28             ` Arnd Bergmann
2013-08-02 12:03       ` [PATCH v5] " Jonas Jensen
2013-08-02 12:03         ` Jonas Jensen
2013-08-02 13:28         ` [PATCH v6] " Jonas Jensen
2013-08-02 13:28           ` Jonas Jensen
2013-08-02 13:51           ` Russell King - ARM Linux
2013-08-02 13:51             ` Russell King - ARM Linux
2013-08-02 14:09           ` Mark Rutland
2013-08-02 14:09             ` Mark Rutland
2013-08-05 14:37           ` [PATCH v7] " Jonas Jensen
2013-08-05 14:37             ` Jonas Jensen
2013-08-05 16:57             ` Mark Rutland
2013-08-05 16:57               ` Mark Rutland
2013-08-05 20:49             ` Arnd Bergmann
2013-08-05 20:49               ` Arnd Bergmann
2013-08-06 12:38             ` [PATCH v8] " Jonas Jensen
2013-08-06 12:38               ` Jonas Jensen
2013-08-06 18:42               ` Arnd Bergmann
2013-08-06 18:42                 ` Arnd Bergmann
2013-08-07 15:13               ` Mark Rutland
2013-08-07 15:13                 ` Mark Rutland
2013-10-07 13:42                 ` Jonas Jensen
2013-10-07 13:42                   ` Jonas Jensen
2013-10-07 13:13               ` [PATCH v9] " Jonas Jensen
2013-10-07 13:13                 ` Jonas Jensen
2013-10-07 14:10                 ` [PATCH v10] " Jonas Jensen
2013-10-07 14:10                   ` Jonas Jensen
2013-10-07 15:12                   ` Mark Rutland
2013-10-07 15:12                     ` Mark Rutland
2013-10-07 15:12                     ` Mark Rutland
2013-10-08  9:53                     ` Jonas Jensen
2013-10-08  9:53                       ` Jonas Jensen
2013-10-08  9:53                       ` Jonas Jensen
2013-10-08 12:55                       ` Mark Rutland
2013-10-08 12:55                         ` Mark Rutland
2013-10-08 12:55                         ` Mark Rutland
2013-10-08  8:42                   ` [PATCH v11] " Jonas Jensen
2013-10-08  8:42                     ` Jonas Jensen
2013-11-13 13:59                     ` Vinod Koul
2013-11-13 13:59                       ` Vinod Koul
2013-11-13 17:16                       ` Arnd Bergmann
2013-11-13 17:16                         ` Arnd Bergmann
2013-12-06 14:27                     ` [PATCH v12] " Jonas Jensen
2013-12-06 14:27                       ` Jonas Jensen
2013-12-11 15:13                       ` [PATCH v13] " Jonas Jensen
2013-12-11 15:13                         ` Jonas Jensen
2013-12-11 21:27                         ` Arnd Bergmann
2013-12-11 21:27                           ` Arnd Bergmann
2013-12-12  9:16                         ` Andy Shevchenko
2013-12-12  9:16                           ` Andy Shevchenko
2013-12-12 12:32                         ` [PATCH v14] " Jonas Jensen
2013-12-12 12:32                           ` Jonas Jensen
2013-12-13 16:02                           ` Lars-Peter Clausen
2013-12-13 16:02                             ` Lars-Peter Clausen
2013-12-16 10:24                           ` [PATCH v15] " Jonas Jensen
2013-12-16 10:24                             ` Jonas Jensen
2014-01-17  8:46                             ` [PATCH v16] " Jonas Jensen
2014-01-17  8:46                               ` Jonas Jensen
     [not found]                               ` <1389948365-13999-1-git-send-email-jonas.jensen-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
2014-01-17 13:29                                 ` Fwd: " Jonas Jensen
2014-01-17 14:42                               ` Arnd Bergmann
2014-01-17 14:42                                 ` Arnd Bergmann
2014-01-20  7:07                               ` Vinod Koul
2014-01-20  7:07                                 ` Vinod Koul

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=201307291835.21151.arnd@arndb.de \
    --to=arnd@arndb.de \
    --cc=arm@kernel.org \
    --cc=djbw@fb.com \
    --cc=jonas.jensen@gmail.com \
    --cc=linux-arm-kernel@lists.infradead.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux@arm.linux.org.uk \
    --cc=vinod.koul@intel.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.