Message ID | 20170710151447.2814348-1-arnd@arndb.de |
---|---|
State | RFC, archived |
Delegated to: | David Miller |
Headers | show |
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
> -----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
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) {
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(-)