Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > linux.kernel > #1684340 > unrolled thread
| Started by | Arnd Bergmann <arnd@arndb.de> |
|---|---|
| First post | 2017-07-10 17:20 +0200 |
| Last post | 2017-07-11 16:30 +0200 |
| Articles | 6 — 4 participants |
Back to article view | Back to linux.kernel
[PATCH] dpaa_eth: use correct device for DMA mapping API Arnd Bergmann <arnd@arndb.de> - 2017-07-10 17:20 +0200
Re: [PATCH] dpaa_eth: use correct device for DMA mapping API Geert Uytterhoeven <geert@linux-m68k.org> - 2017-07-10 17:40 +0200
Re: [PATCH] dpaa_eth: use correct device for DMA mapping API Robin Murphy <robin.murphy@arm.com> - 2017-07-10 18:00 +0200
RE: [PATCH] dpaa_eth: use correct device for DMA mapping API Madalin-cristian Bucur <madalin.bucur@nxp.com> - 2017-07-11 11:00 +0200
Re: [PATCH] dpaa_eth: use correct device for DMA mapping API Arnd Bergmann <arnd@arndb.de> - 2017-07-11 11:20 +0200
RE: [PATCH] dpaa_eth: use correct device for DMA mapping API Madalin-cristian Bucur <madalin.bucur@nxp.com> - 2017-07-11 16:30 +0200
| From | Arnd Bergmann <arnd@arndb.de> |
|---|---|
| Date | 2017-07-10 17:20 +0200 |
| Subject | [PATCH] dpaa_eth: use correct device for DMA mapping API |
| Message-ID | <u1IDE-6HQ-29@gated-at.bofh.it> |
Geert Uytterhoeven ran into a build error without CONFIG_HAS_DMA,
as a result of the driver calling set_dma_ops(). While we can
fix the build error in the dma-mapping implementation, there is
another problem in this driver:
The configuration for the DMA is done by the platform code,
looking up information about the system from the device tree.
This copies the information only in an incomplete way, setting
the dma_map_ops and forcing a specific mask, but ignoring all
settings regarding IOMMU, coherence etc.
A better way to avoid the problem is to only ever pass a device
into the dma_mapping implementation that has been setup by the
platform code. In this case, that is the parent device, so we
can get that pointer at probe time. Fortunately, we already have
a pointer in the device specific structure for that, so we only
need to modify that.
Fixes: fb52728a9294 ("dpaa_eth: reuse the dma_ops provided by the FMan MAC device")
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
---
Not tested, please see if this works before applying!
---
drivers/net/ethernet/freescale/dpaa/dpaa_eth.c | 11 ++---------
1 file changed, 2 insertions(+), 9 deletions(-)
diff --git a/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c b/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c
index 757b873735a5..f7b0b928cd53 100644
--- a/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c
+++ b/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c
@@ -2646,14 +2646,6 @@ static int dpaa_eth_probe(struct platform_device *pdev)
priv->buf_layout[RX].priv_data_size = DPAA_RX_PRIV_DATA_SIZE; /* Rx */
priv->buf_layout[TX].priv_data_size = DPAA_TX_PRIV_DATA_SIZE; /* Tx */
- /* device used for DMA mapping */
- set_dma_ops(dev, get_dma_ops(&pdev->dev));
- err = dma_coerce_mask_and_coherent(dev, DMA_BIT_MASK(40));
- if (err) {
- dev_err(dev, "dma_coerce_mask_and_coherent() failed\n");
- goto dev_mask_failed;
- }
-
/* bp init */
for (i = 0; i < DPAA_BPS_NUM; i++) {
int err;
@@ -2665,7 +2657,8 @@ static int dpaa_eth_probe(struct platform_device *pdev)
dpaa_bps[i]->raw_size = bpool_buffer_raw_size(i, DPAA_BPS_NUM);
/* avoid runtime computations by keeping the usable size here */
dpaa_bps[i]->size = dpaa_bp_size(dpaa_bps[i]->raw_size);
- dpaa_bps[i]->dev = dev;
+ /* DMA operations are done on the platform-provided device */
+ dpaa_bps[i]->dev = dev->parent;
err = dpaa_bp_alloc_pool(dpaa_bps[i]);
if (err < 0) {
--
2.9.0
[toc] | [next] | [standalone]
| From | Geert Uytterhoeven <geert@linux-m68k.org> |
|---|---|
| Date | 2017-07-10 17:40 +0200 |
| Message-ID | <u1IX0-6Op-27@gated-at.bofh.it> |
| In reply to | #1684340 |
Hi Arnd,
On Mon, Jul 10, 2017 at 5:14 PM, Arnd Bergmann <arnd@arndb.de> wrote:
> Geert Uytterhoeven ran into a build error without CONFIG_HAS_DMA,
> as a result of the driver calling set_dma_ops(). While we can
> fix the build error in the dma-mapping implementation, there is
> another problem in this driver:
>
> The configuration for the DMA is done by the platform code,
> looking up information about the system from the device tree.
> This copies the information only in an incomplete way, setting
> the dma_map_ops and forcing a specific mask, but ignoring all
> settings regarding IOMMU, coherence etc.
>
> A better way to avoid the problem is to only ever pass a device
> into the dma_mapping implementation that has been setup by the
> platform code. In this case, that is the parent device, so we
> can get that pointer at probe time. Fortunately, we already have
> a pointer in the device specific structure for that, so we only
> need to modify that.
Thank you, that looks like a much better solution!
> Fixes: fb52728a9294 ("dpaa_eth: reuse the dma_ops provided by the FMan MAC device")
> Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Acked-by: Geert Uytterhoeven <geert@linux-m68k.org>
> Not tested, please see if this works before applying!
Indeed, please test first.
Gr{oetje,eeting}s,
Geert
--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org
In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
-- Linus Torvalds
[toc] | [prev] | [next] | [standalone]
| From | Robin Murphy <robin.murphy@arm.com> |
|---|---|
| Date | 2017-07-10 18:00 +0200 |
| Message-ID | <u1Jgm-6Vr-13@gated-at.bofh.it> |
| In reply to | #1684340 |
On 10/07/17 16:14, Arnd Bergmann wrote:
> Geert Uytterhoeven ran into a build error without CONFIG_HAS_DMA,
> as a result of the driver calling set_dma_ops(). While we can
> fix the build error in the dma-mapping implementation, there is
> another problem in this driver:
>
> The configuration for the DMA is done by the platform code,
> looking up information about the system from the device tree.
> This copies the information only in an incomplete way, setting
> the dma_map_ops and forcing a specific mask, but ignoring all
> settings regarding IOMMU, coherence etc.
>
> A better way to avoid the problem is to only ever pass a device
> into the dma_mapping implementation that has been setup by the
> platform code. In this case, that is the parent device, so we
> can get that pointer at probe time. Fortunately, we already have
> a pointer in the device specific structure for that, so we only
> need to modify that.
>
> Fixes: fb52728a9294 ("dpaa_eth: reuse the dma_ops provided by the FMan MAC device")
> Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Acked-by: Robin Murphy <robin.murphy@arm.com>
Assuming all the DPAA subcomponents have the same DMA capabilities
(which to the best of my knowledge they probably do), this is a neater
approach than what I started a while back in the context of cleaning up
arch_setup_dma_ops() abuse. FWIW, that looked like this:
----->8-----
diff --git a/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c
b/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c
index e2ca107f9d94..8eef0db5db30 100644
--- a/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c
+++ b/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c
@@ -2539,10 +2539,9 @@ static int dpaa_eth_probe(struct platform_device
*pdev)
priv->buf_layout[TX].priv_data_size = DPAA_TX_PRIV_DATA_SIZE; /*
Tx */
/* device used for DMA mapping */
- arch_setup_dma_ops(dev, 0, 0, NULL, false);
- err = dma_coerce_mask_and_coherent(dev, DMA_BIT_MASK(40));
+ err = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(40));
if (err) {
- dev_err(dev, "dma_coerce_mask_and_coherent() failed\n");
+ dev_err(dev, "dma_set_mask_and_coherent() failed\n");
goto dev_mask_failed;
}
diff --git a/drivers/net/ethernet/freescale/fman/mac.c
b/drivers/net/ethernet/freescale/fman/mac.c
index 0b31f8502ada..c81efbfa99c2 100644
--- a/drivers/net/ethernet/freescale/fman/mac.c
+++ b/drivers/net/ethernet/freescale/fman/mac.c
@@ -627,6 +627,10 @@ static struct platform_device
*dpaa_eth_add_device(int fman_id,
if (ret)
goto err;
+ ret = of_dma_configure(&pdev->dev, node);
+ if (ret)
+ goto err;
+
ret = platform_device_add(pdev);
if (ret)
goto err;
-----8<-----
We might possibly need to revisit this if and when the question of IOMMU
support in the fsl-mc driver comes up (all this stuff is completely
paged out of my head at the moment, so I'm not certain), but for now I
don't see any reason no to go with your patch.
Robin.
> ---
> Not tested, please see if this works before applying!
> ---
> drivers/net/ethernet/freescale/dpaa/dpaa_eth.c | 11 ++---------
> 1 file changed, 2 insertions(+), 9 deletions(-)
>
> diff --git a/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c b/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c
> index 757b873735a5..f7b0b928cd53 100644
> --- a/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c
> +++ b/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c
> @@ -2646,14 +2646,6 @@ static int dpaa_eth_probe(struct platform_device *pdev)
> priv->buf_layout[RX].priv_data_size = DPAA_RX_PRIV_DATA_SIZE; /* Rx */
> priv->buf_layout[TX].priv_data_size = DPAA_TX_PRIV_DATA_SIZE; /* Tx */
>
> - /* device used for DMA mapping */
> - set_dma_ops(dev, get_dma_ops(&pdev->dev));
> - err = dma_coerce_mask_and_coherent(dev, DMA_BIT_MASK(40));
> - if (err) {
> - dev_err(dev, "dma_coerce_mask_and_coherent() failed\n");
> - goto dev_mask_failed;
> - }
> -
> /* bp init */
> for (i = 0; i < DPAA_BPS_NUM; i++) {
> int err;
> @@ -2665,7 +2657,8 @@ static int dpaa_eth_probe(struct platform_device *pdev)
> dpaa_bps[i]->raw_size = bpool_buffer_raw_size(i, DPAA_BPS_NUM);
> /* avoid runtime computations by keeping the usable size here */
> dpaa_bps[i]->size = dpaa_bp_size(dpaa_bps[i]->raw_size);
> - dpaa_bps[i]->dev = dev;
> + /* DMA operations are done on the platform-provided device */
> + dpaa_bps[i]->dev = dev->parent;
>
> err = dpaa_bp_alloc_pool(dpaa_bps[i]);
> if (err < 0) {
>
[toc] | [prev] | [next] | [standalone]
| From | Madalin-cristian Bucur <madalin.bucur@nxp.com> |
|---|---|
| Date | 2017-07-11 11:00 +0200 |
| Message-ID | <u1Zbt-8vM-39@gated-at.bofh.it> |
| In reply to | #1684340 |
> -----Original Message-----
> From: Arnd Bergmann [mailto:arnd@arndb.de]
> Sent: Monday, July 10, 2017 6:14 PM
> Subject: [PATCH] dpaa_eth: use correct device for DMA mapping API
>
> Geert Uytterhoeven ran into a build error without CONFIG_HAS_DMA,
> as a result of the driver calling set_dma_ops(). While we can
> fix the build error in the dma-mapping implementation, there is
> another problem in this driver:
>
> The configuration for the DMA is done by the platform code,
> looking up information about the system from the device tree.
> This copies the information only in an incomplete way, setting
> the dma_map_ops and forcing a specific mask, but ignoring all
> settings regarding IOMMU, coherence etc.
>
> A better way to avoid the problem is to only ever pass a device
> into the dma_mapping implementation that has been setup by the
> platform code. In this case, that is the parent device, so we
> can get that pointer at probe time. Fortunately, we already have
> a pointer in the device specific structure for that, so we only
> need to modify that.
>
> Fixes: fb52728a9294 ("dpaa_eth: reuse the dma_ops provided by the FMan MAC
> device")
> Signed-off-by: Arnd Bergmann <arnd@arndb.de>
> ---
> Not tested, please see if this works before applying!
> ---
> drivers/net/ethernet/freescale/dpaa/dpaa_eth.c | 11 ++---------
> 1 file changed, 2 insertions(+), 9 deletions(-)
>
> diff --git a/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c
> b/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c
> index 757b873735a5..f7b0b928cd53 100644
> --- a/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c
> +++ b/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c
> @@ -2646,14 +2646,6 @@ static int dpaa_eth_probe(struct platform_device
> *pdev)
> priv->buf_layout[RX].priv_data_size = DPAA_RX_PRIV_DATA_SIZE; /* Rx
> */
> priv->buf_layout[TX].priv_data_size = DPAA_TX_PRIV_DATA_SIZE; /* Tx
> */
>
> - /* device used for DMA mapping */
> - set_dma_ops(dev, get_dma_ops(&pdev->dev));
> - err = dma_coerce_mask_and_coherent(dev, DMA_BIT_MASK(40));
> - if (err) {
> - dev_err(dev, "dma_coerce_mask_and_coherent() failed\n");
> - goto dev_mask_failed;
> - }
> -
> /* bp init */
> for (i = 0; i < DPAA_BPS_NUM; i++) {
> int err;
> @@ -2665,7 +2657,8 @@ static int dpaa_eth_probe(struct platform_device
> *pdev)
> dpaa_bps[i]->raw_size = bpool_buffer_raw_size(i,
> DPAA_BPS_NUM);
> /* avoid runtime computations by keeping the usable size here
> */
> dpaa_bps[i]->size = dpaa_bp_size(dpaa_bps[i]->raw_size);
> - dpaa_bps[i]->dev = dev;
> + /* DMA operations are done on the platform-provided device */
> + dpaa_bps[i]->dev = dev->parent;
>
> err = dpaa_bp_alloc_pool(dpaa_bps[i]);
> if (err < 0) {
> --
> 2.9.0
Hi Arnd,
Thanks for looking into this, I've tested your fix, it seems to need more work:
[ 0.894968] platform: DMA map failed
[ 0.898627] platform: DMA map failed
[ 0.902288] platform: DMA map failed
[ 0.905947] platform: DMA map failed
[ 0.909606] platform: DMA map failed
[ 0.913265] platform: DMA map failed
You also missed this related change:
@@ -2806,7 +2799,6 @@ static int dpaa_eth_probe(struct platform_device *pdev)
dpaa_bps_free(priv);
bp_create_failed:
fq_probe_failed:
-dev_mask_failed:
mac_probe_failed:
dev_set_drvdata(dev, NULL);
free_netdev(net_dev);
I'll try to address your concern about performing the DMA mapping on a different
device than the one set up by the platform code.
Regards,
Madalin
[toc] | [prev] | [next] | [standalone]
| From | Arnd Bergmann <arnd@arndb.de> |
|---|---|
| Date | 2017-07-11 11:20 +0200 |
| Message-ID | <u1ZuP-pS-43@gated-at.bofh.it> |
| In reply to | #1684898 |
On Tue, Jul 11, 2017 at 10:50 AM, Madalin-cristian Bucur
<madalin.bucur@nxp.com> wrote:
> Hi Arnd,
>
> Thanks for looking into this, I've tested your fix, it seems to need more work:
>
> [ 0.894968] platform: DMA map failed
> [ 0.898627] platform: DMA map failed
> [ 0.902288] platform: DMA map failed
> [ 0.905947] platform: DMA map failed
> [ 0.909606] platform: DMA map failed
> [ 0.913265] platform: DMA map failed
I see: the assignment ended up after the first use, so ->dev was still
NULL here.
This should fix the problem you saw here:
diff --git a/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c
b/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c
index f7b0b928cd53..988c0212ce7e 100644
--- a/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c
+++ b/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c
@@ -2650,6 +2650,8 @@ static int dpaa_eth_probe(struct platform_device *pdev)
for (i = 0; i < DPAA_BPS_NUM; i++) {
int err;
+ /* DMA operations are done on the platform-provided device */
+ dpaa_bps[i]->dev = dev->parent;
dpaa_bps[i] = dpaa_bp_alloc(dev);
if (IS_ERR(dpaa_bps[i]))
return PTR_ERR(dpaa_bps[i]);
@@ -2657,8 +2659,6 @@ static int dpaa_eth_probe(struct platform_device *pdev)
dpaa_bps[i]->raw_size = bpool_buffer_raw_size(i, DPAA_BPS_NUM);
/* avoid runtime computations by keeping the usable size here */
dpaa_bps[i]->size = dpaa_bp_size(dpaa_bps[i]->raw_size);
- /* DMA operations are done on the platform-provided device */
- dpaa_bps[i]->dev = dev->parent;
err = dpaa_bp_alloc_pool(dpaa_bps[i]);
if (err < 0) {
> @@ -2806,7 +2799,6 @@ static int dpaa_eth_probe(struct platform_device *pdev)
> dpaa_bps_free(priv);
> bp_create_failed:
> fq_probe_failed:
> -dev_mask_failed:
> mac_probe_failed:
> dev_set_drvdata(dev, NULL);
> free_netdev(net_dev);
>
> I'll try to address your concern about performing the DMA mapping on a different
> device than the one set up by the platform code.
Thanks!
Arnd
[toc] | [prev] | [next] | [standalone]
| From | Madalin-cristian Bucur <madalin.bucur@nxp.com> |
|---|---|
| Date | 2017-07-11 16:30 +0200 |
| Message-ID | <u24kN-3rk-3@gated-at.bofh.it> |
| In reply to | #1684913 |
> -----Original Message-----
> From: arndbergmann@gmail.com [mailto:arndbergmann@gmail.com] On Behalf Of
> Arnd Bergmann
> Subject: Re: [PATCH] dpaa_eth: use correct device for DMA mapping API
>
> On Tue, Jul 11, 2017 at 10:50 AM, Madalin-cristian Bucur
> <madalin.bucur@nxp.com> wrote:
>
> > Hi Arnd,
> >
> > Thanks for looking into this, I've tested your fix, it seems to need
> more work:
> >
> > [ 0.894968] platform: DMA map failed
> > [ 0.898627] platform: DMA map failed
> > [ 0.902288] platform: DMA map failed
> > [ 0.905947] platform: DMA map failed
> > [ 0.909606] platform: DMA map failed
> > [ 0.913265] platform: DMA map failed
>
> I see: the assignment ended up after the first use, so ->dev was still
> NULL here.
>
> This should fix the problem you saw here:
>
> diff --git a/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c
> b/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c
> index f7b0b928cd53..988c0212ce7e 100644
> --- a/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c
> +++ b/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c
> @@ -2650,6 +2650,8 @@ static int dpaa_eth_probe(struct platform_device
> *pdev)
> for (i = 0; i < DPAA_BPS_NUM; i++) {
> int err;
>
> + /* DMA operations are done on the platform-provided device */
> + dpaa_bps[i]->dev = dev->parent;
> dpaa_bps[i] = dpaa_bp_alloc(dev);
Your new change de-references dpaa_bps[i] before it is set, this won't work either.
> if (IS_ERR(dpaa_bps[i]))
> return PTR_ERR(dpaa_bps[i]);
> @@ -2657,8 +2659,6 @@ static int dpaa_eth_probe(struct platform_device
> *pdev)
> dpaa_bps[i]->raw_size = bpool_buffer_raw_size(i, DPAA_BPS_NUM);
> /* avoid runtime computations by keeping the usable size here */
> dpaa_bps[i]->size = dpaa_bp_size(dpaa_bps[i]->raw_size);
> - /* DMA operations are done on the platform-provided device */
> - dpaa_bps[i]->dev = dev->parent;
>
> err = dpaa_bp_alloc_pool(dpaa_bps[i]);
> if (err < 0) {
>
> > @@ -2806,7 +2799,6 @@ static int dpaa_eth_probe(struct platform_device
> *pdev)
> > dpaa_bps_free(priv);
> > bp_create_failed:
> > fq_probe_failed:
> > -dev_mask_failed:
> > mac_probe_failed:
> > dev_set_drvdata(dev, NULL);
> > free_netdev(net_dev);
> >
> > I'll try to address your concern about performing the DMA mapping on a
> different
> > device than the one set up by the platform code.
>
> Thanks!
>
> Arnd
[toc] | [prev] | [standalone]
Back to top | Article view | linux.kernel
csiph-web