Message ID | 20240524182702.1317935-12-dave.stevenson@raspberrypi.com |
---|---|
State | New |
Headers | show |
Series | BCM2835 DMA mapping cleanups and fixes | expand |
On Fri, May 24, 2024 at 07:26:55PM +0100, Dave Stevenson wrote: > There is a need to account for dma-ranges and iommus in the > dma mapping process, and the public API for handling that is > dma_map_resource. what's means? > > Add support for mapping addresses to the DMA driver. > > Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com> > --- > drivers/dma/bcm2835-dma.c | 46 ++++++++++++++++++++++++++++++++++----- > 1 file changed, 41 insertions(+), 5 deletions(-) > > diff --git a/drivers/dma/bcm2835-dma.c b/drivers/dma/bcm2835-dma.c > index 9531c0b82071..e48008b06716 100644 > --- a/drivers/dma/bcm2835-dma.c > +++ b/drivers/dma/bcm2835-dma.c > @@ -67,6 +67,10 @@ struct bcm2835_cb_entry { > > struct bcm2835_dma_chan_map { > dma_addr_t addr; > + enum dma_data_direction dir; > + > + phys_addr_t slave_addr; > + unsigned int xfer_size; > }; > > struct bcm2835_chan { > @@ -294,12 +298,44 @@ static int bcm2835_dma_map_slave_addr(struct dma_chan *chan, > return 0; > } where umap function? I suppose you should unmap all when terminate chan or free chan by client driver. > > - /* > - * This path will be updated to handle new clients, but currently should > - * never be used. > - */ > + if (dev_size != DMA_SLAVE_BUSWIDTH_4_BYTES) > + return -EIO; > + > + /* Reuse current map if possible. */ > + if (dev_addr == map->slave_addr && > + dev_size == map->xfer_size && > + dev_dir == map->dir) > + return 0; > + > + /* Remove old mapping if present. */ > + if (map->xfer_size) { > + dev_dbg(chan->device->dev, "chan: unmap %zx@%pap to %pad dir: %s\n", > + dev_size, &dev_addr, &map->addr, > + dev_dir == DMA_TO_DEVICE ? "DMA_TO_DEVICE" : "DMA_FROM_DEVICE"); > + dma_unmap_resource(chan->device->dev, map->addr, > + map->xfer_size, map->dir, 0); > + } > + map->xfer_size = 0; > > - return -EINVAL; > + /* Create new slave address map. */ > + map->addr = dma_map_resource(chan->device->dev, dev_addr, dev_size, > + dev_dir, 0); > + > + if (dma_mapping_error(chan->device->dev, map->addr)) { > + dev_err(chan->device->dev, "chan: failed to map %zx@%pap", > + dev_size, &dev_addr); > + return -EIO; > + } > + > + dev_dbg(chan->device->dev, "chan: map %zx@%pap to %pad dir: %s\n", > + dev_size, &dev_addr, &map->addr, > + dev_dir == DMA_TO_DEVICE ? "DMA_TO_DEVICE" : "DMA_FROM_DEVICE"); > + > + map->slave_addr = dev_addr; > + map->xfer_size = dev_size; > + map->dir = dev_dir; > + > + return 0; > } > > static void bcm2835_dma_free_cb_chain(struct bcm2835_desc *desc) > -- > 2.34.1 >
diff --git a/drivers/dma/bcm2835-dma.c b/drivers/dma/bcm2835-dma.c index 9531c0b82071..e48008b06716 100644 --- a/drivers/dma/bcm2835-dma.c +++ b/drivers/dma/bcm2835-dma.c @@ -67,6 +67,10 @@ struct bcm2835_cb_entry { struct bcm2835_dma_chan_map { dma_addr_t addr; + enum dma_data_direction dir; + + phys_addr_t slave_addr; + unsigned int xfer_size; }; struct bcm2835_chan { @@ -294,12 +298,44 @@ static int bcm2835_dma_map_slave_addr(struct dma_chan *chan, return 0; } - /* - * This path will be updated to handle new clients, but currently should - * never be used. - */ + if (dev_size != DMA_SLAVE_BUSWIDTH_4_BYTES) + return -EIO; + + /* Reuse current map if possible. */ + if (dev_addr == map->slave_addr && + dev_size == map->xfer_size && + dev_dir == map->dir) + return 0; + + /* Remove old mapping if present. */ + if (map->xfer_size) { + dev_dbg(chan->device->dev, "chan: unmap %zx@%pap to %pad dir: %s\n", + dev_size, &dev_addr, &map->addr, + dev_dir == DMA_TO_DEVICE ? "DMA_TO_DEVICE" : "DMA_FROM_DEVICE"); + dma_unmap_resource(chan->device->dev, map->addr, + map->xfer_size, map->dir, 0); + } + map->xfer_size = 0; - return -EINVAL; + /* Create new slave address map. */ + map->addr = dma_map_resource(chan->device->dev, dev_addr, dev_size, + dev_dir, 0); + + if (dma_mapping_error(chan->device->dev, map->addr)) { + dev_err(chan->device->dev, "chan: failed to map %zx@%pap", + dev_size, &dev_addr); + return -EIO; + } + + dev_dbg(chan->device->dev, "chan: map %zx@%pap to %pad dir: %s\n", + dev_size, &dev_addr, &map->addr, + dev_dir == DMA_TO_DEVICE ? "DMA_TO_DEVICE" : "DMA_FROM_DEVICE"); + + map->slave_addr = dev_addr; + map->xfer_size = dev_size; + map->dir = dev_dir; + + return 0; } static void bcm2835_dma_free_cb_chain(struct bcm2835_desc *desc)
There is a need to account for dma-ranges and iommus in the dma mapping process, and the public API for handling that is dma_map_resource. Add support for mapping addresses to the DMA driver. Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com> --- drivers/dma/bcm2835-dma.c | 46 ++++++++++++++++++++++++++++++++++----- 1 file changed, 41 insertions(+), 5 deletions(-)