Message ID | 1453384895-20395-4-git-send-email-niklas.soderlund+renesas@ragnatech.se (mailing list archive) |
---|---|
State | Superseded |
Delegated to: | Geert Uytterhoeven |
Headers | show |
Hi Niklas, [auto build test ERROR on renesas/next] [also build test ERROR on v4.4] [cannot apply to next-20160121] [if your patch is applied to the wrong git tree, please drop us a note to help improving the system] url: https://github.com/0day-ci/linux/commits/Niklas-S-derlund/dmaengine-rcar-dmac-add-iommu-support-for-slave-transfers/20160121-220503 base: https://git.kernel.org/pub/scm/linux/kernel/git/horms/renesas.git next config: m68k-allyesconfig (attached as .config) reproduce: wget https://git.kernel.org/cgit/linux/kernel/git/wfg/lkp-tests.git/plain/sbin/make.cross -O ~/bin/make.cross chmod +x ~/bin/make.cross # save the attached .config to linux build tree make.cross ARCH=m68k All errors (new ones prefixed by >>): drivers/dma/sh/rcar-dmac.c: In function '__rcar_dmac_device_config': >> drivers/dma/sh/rcar-dmac.c:1121:3: error: implicit declaration of function 'dma_unmap_page_attrs' [-Werror=implicit-function-declaration] dma_unmap_page_attrs(chan->device->dev, slave->slave_addr, ^ >> drivers/dma/sh/rcar-dmac.c:1132:3: error: implicit declaration of function 'dma_map_page_attrs' [-Werror=implicit-function-declaration] slave->slave_addr = dma_map_page_attrs(chan->device->dev, page, ^ cc1: some warnings being treated as errors vim +/dma_unmap_page_attrs +1121 drivers/dma/sh/rcar-dmac.c 1115 struct rcar_dmac_chan *rchan = to_rcar_dmac_chan(chan); 1116 struct page *page; 1117 size_t offset; 1118 1119 /* unmap old */ 1120 if (slave->slave_addr) { > 1121 dma_unmap_page_attrs(chan->device->dev, slave->slave_addr, 1122 slave->xfer_size, dir, attrs); 1123 slave->slave_addr = 0; 1124 slave->xfer_size = 0; 1125 } 1126 1127 /* map new */ 1128 if (addr) { 1129 /* phys_to_page not available on all platforms */ 1130 page = pfn_to_page(addr >> PAGE_SHIFT); 1131 offset = addr - page_to_phys(page); > 1132 slave->slave_addr = dma_map_page_attrs(chan->device->dev, page, 1133 offset, size, dir, attrs); 1134 1135 if (dma_mapping_error(chan->device->dev, slave->slave_addr)) { --- 0-DAY kernel test infrastructure Open Source Technology Center https://lists.01.org/pipermail/kbuild-all Intel Corporation
Hi Niklas, Thank you for the patch. On Thursday 21 January 2016 15:01:33 Niklas Söderlund wrote: > Enable slave transfers to devices behind IPMMU:s by mapping the slave > addresses using the dma-mapping API. > > Signed-off-by: Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se> > --- > drivers/dma/sh/rcar-dmac.c | 59 ++++++++++++++++++++++++++++++++++++++++---- > 1 file changed, 54 insertions(+), 5 deletions(-) > > diff --git a/drivers/dma/sh/rcar-dmac.c b/drivers/dma/sh/rcar-dmac.c > index 743873c..f3ec8a6 100644 > --- a/drivers/dma/sh/rcar-dmac.c > +++ b/drivers/dma/sh/rcar-dmac.c > @@ -1106,21 +1106,70 @@ rcar_dmac_prep_dma_cyclic(struct dma_chan *chan, > dma_addr_t buf_addr, return desc; > } > > +static int __rcar_dmac_device_config(struct dma_chan *chan, I'd call this rcar_dmac_set_slave_addr (or something similar) to make the purpose of the function more explicit. > + struct rcar_dmac_chan_slave *slave, > + phys_addr_t addr, size_t size, > + enum dma_data_direction dir, > + struct dma_attrs *attrs) > +{ > + struct rcar_dmac_chan *rchan = to_rcar_dmac_chan(chan); You can pass rchan to the function directly and avoid this cast. > + struct page *page; > + size_t offset; > + > + /* unmap old */ The drivers capitalizes the first word of each sentence in comments and ends the sentences with a full stop. Could you please use the same style for consistency. > + if (slave->slave_addr) { In theory 0 is a valid address. There's unfortunately no standard way to set an address to an invalid value that can be later checked (DMA_ERROR_CODE isn't defined on all architectures and dma_mapping_error() has no set counterpart). I would use xfer_size instead of slave_addr to check whether the page has been mapped. > + dma_unmap_page_attrs(chan->device->dev, slave->slave_addr, > + slave->xfer_size, dir, attrs); > + slave->slave_addr = 0; > + slave->xfer_size = 0; > + } > + > + /* map new */ > + if (addr) { > + /* phys_to_page not available on all platforms */ > + page = pfn_to_page(addr >> PAGE_SHIFT); > + offset = addr - page_to_phys(page); How about just offset = addr & ~PAGE_MASK; It seems simpler to me. > + slave->slave_addr = dma_map_page_attrs(chan->device->dev, page, I'm still worried about passing a page pointer computed from an address that has no associated page structure. This issue can probably be addressed separately from this series, but I'd like to see at least a comment that mentions the problem here. > + offset, size, dir, attrs); > + > + if (dma_mapping_error(chan->device->dev, slave->slave_addr)) { > + dev_err(chan->device->dev, > + "chan%u: failed to map %zx@%pap", > + rchan->index, size, &addr); > + return -EIO; > + } > + > + slave->xfer_size = size; > + } > + > + return 0; > + > +} > + > static int rcar_dmac_device_config(struct dma_chan *chan, > struct dma_slave_config *cfg) > { > struct rcar_dmac_chan *rchan = to_rcar_dmac_chan(chan); > + struct dma_attrs attrs; > + int ret; > > /* > * We could lock this, but you shouldn't be configuring the > * channel, while using it... > */ > - rchan->src.slave_addr = cfg->src_addr; > - rchan->dst.slave_addr = cfg->dst_addr; > - rchan->src.xfer_size = cfg->src_addr_width; > - rchan->dst.xfer_size = cfg->dst_addr_width; > > - return 0; > + init_dma_attrs(&attrs); > + dma_set_attr(DMA_ATTR_NO_KERNEL_MAPPING, &attrs); > + dma_set_attr(DMA_ATTR_SKIP_CPU_SYNC, &attrs); > + > + ret = __rcar_dmac_device_config(chan, &rchan->src, cfg->src_addr, You're passing a dma_addr_t while the function expects a phys_addr_t. As you mentioned in the cover letter this has been discussed before without reaching any clear conclusion, we need to come to an agreement. > + cfg->src_addr_width, DMA_FROM_DEVICE, &attrs); > + if (!ret) > + return ret; > + > + ret = __rcar_dmac_device_config(chan, &rchan->dst, cfg->dst_addr, > + cfg->dst_addr_width, DMA_TO_DEVICE, &attrs); > + return ret; > } > > static int rcar_dmac_chan_terminate_all(struct dma_chan *chan)
diff --git a/drivers/dma/sh/rcar-dmac.c b/drivers/dma/sh/rcar-dmac.c index 743873c..f3ec8a6 100644 --- a/drivers/dma/sh/rcar-dmac.c +++ b/drivers/dma/sh/rcar-dmac.c @@ -1106,21 +1106,70 @@ rcar_dmac_prep_dma_cyclic(struct dma_chan *chan, dma_addr_t buf_addr, return desc; } +static int __rcar_dmac_device_config(struct dma_chan *chan, + struct rcar_dmac_chan_slave *slave, + phys_addr_t addr, size_t size, + enum dma_data_direction dir, + struct dma_attrs *attrs) +{ + struct rcar_dmac_chan *rchan = to_rcar_dmac_chan(chan); + struct page *page; + size_t offset; + + /* unmap old */ + if (slave->slave_addr) { + dma_unmap_page_attrs(chan->device->dev, slave->slave_addr, + slave->xfer_size, dir, attrs); + slave->slave_addr = 0; + slave->xfer_size = 0; + } + + /* map new */ + if (addr) { + /* phys_to_page not available on all platforms */ + page = pfn_to_page(addr >> PAGE_SHIFT); + offset = addr - page_to_phys(page); + slave->slave_addr = dma_map_page_attrs(chan->device->dev, page, + offset, size, dir, attrs); + + if (dma_mapping_error(chan->device->dev, slave->slave_addr)) { + dev_err(chan->device->dev, + "chan%u: failed to map %zx@%pap", + rchan->index, size, &addr); + return -EIO; + } + + slave->xfer_size = size; + } + + return 0; + +} + static int rcar_dmac_device_config(struct dma_chan *chan, struct dma_slave_config *cfg) { struct rcar_dmac_chan *rchan = to_rcar_dmac_chan(chan); + struct dma_attrs attrs; + int ret; /* * We could lock this, but you shouldn't be configuring the * channel, while using it... */ - rchan->src.slave_addr = cfg->src_addr; - rchan->dst.slave_addr = cfg->dst_addr; - rchan->src.xfer_size = cfg->src_addr_width; - rchan->dst.xfer_size = cfg->dst_addr_width; - return 0; + init_dma_attrs(&attrs); + dma_set_attr(DMA_ATTR_NO_KERNEL_MAPPING, &attrs); + dma_set_attr(DMA_ATTR_SKIP_CPU_SYNC, &attrs); + + ret = __rcar_dmac_device_config(chan, &rchan->src, cfg->src_addr, + cfg->src_addr_width, DMA_FROM_DEVICE, &attrs); + if (!ret) + return ret; + + ret = __rcar_dmac_device_config(chan, &rchan->dst, cfg->dst_addr, + cfg->dst_addr_width, DMA_TO_DEVICE, &attrs); + return ret; } static int rcar_dmac_chan_terminate_all(struct dma_chan *chan)
Enable slave transfers to devices behind IPMMU:s by mapping the slave addresses using the dma-mapping API. Signed-off-by: Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se> --- drivers/dma/sh/rcar-dmac.c | 59 ++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 54 insertions(+), 5 deletions(-)