Message ID | 20221027052007.47403-2-sireeshkodali1@gmail.com (mailing list archive) |
---|---|
State | Not Applicable |
Headers | show |
Series | [v2,1/1] dmaengine: qcom: bam_dma: Add support for metadata | expand |
On 27-10-22, 10:50, Sireesh Kodali wrote: > From: Vladimir Lypak <vladimir.lypak@gmail.com> > > Add client metadata support for receiving information about transfers. > Only type of metadata implemented is amount of transferred bytes. This > can be used to know how much data is actually received if information > transferred doesn't contain header with size or is aggregated. > > Signed-off-by: Vladimir Lypak <vladimir.lypak@gmail.com> > Signed-off-by: Sireesh Kodali <sireeshkodali1@gmail.com> > --- > drivers/dma/qcom/bam_dma.c | 57 ++++++++++++++++++++++++++++++++ > include/linux/dma/qcom_bam_dma.h | 8 +++++ > 2 files changed, 65 insertions(+) > > diff --git a/drivers/dma/qcom/bam_dma.c b/drivers/dma/qcom/bam_dma.c > index 3135a3e4a167..264a9a2e199f 100644 > --- a/drivers/dma/qcom/bam_dma.c > +++ b/drivers/dma/qcom/bam_dma.c > @@ -30,6 +30,7 @@ > #include <linux/module.h> > #include <linux/interrupt.h> > #include <linux/dma-mapping.h> > +#include <linux/dma/qcom_bam_dma.h> > #include <linux/scatterlist.h> > #include <linux/device.h> > #include <linux/platform_device.h> > @@ -70,6 +71,7 @@ struct bam_async_desc { > u16 flags; > > struct bam_desc_hw *curr_desc; > + struct bam_dma_metadata *metadata; > > /* list node for the desc in the bam_chan list of descriptors */ > struct list_head desc_node; > @@ -418,6 +420,52 @@ static inline void __iomem *bam_addr(struct bam_device *bdev, u32 pipe, > r.ee_mult * bdev->ee; > } > > +/** > + * bam_update_metadata - update metadata buffer > + * @bchan: BAM channel to read metadata from > + * @async_desc: BAM async descriptior > + * > + * Updates metadata buffer (transfer size) based on values > + * read from FIFO descriptors at bchan->head > + */ > + > +static inline void bam_update_metadata(struct bam_chan *bchan, > + struct bam_async_desc *async_desc) > +{ > + unsigned int i, e, len = 0; > + struct bam_desc_hw *fifo; > + > + if (!async_desc->metadata) > + return; > + > + fifo = PTR_ALIGN(bchan->fifo_virt, sizeof(struct bam_desc_hw)); > + for (i = bchan->head, e = i + async_desc->xfer_len; i < e; i++) > + len += fifo[i % MAX_DESCRIPTORS].size; > + > + async_desc->metadata->xfer_len_bytes += len; > +} > + > +/** > + * bam_attach_metadata - attach metadata buffer to the async descriptor > + * @desc: async descriptor > + * @data: buffer pointer > + * @len: length of passed buffer > + */ > +static int bam_attach_metadata(struct dma_async_tx_descriptor *desc, void *data, > + size_t len) > +{ > + struct bam_async_desc *async_desc; > + > + if (!data || len != sizeof(struct bam_dma_metadata)) > + return -EINVAL; > + > + async_desc = container_of(desc, struct bam_async_desc, vd.tx); > + async_desc->metadata = data; > + async_desc->metadata->xfer_len_bytes = 0; > + > + return 0; > +} > + > /** > * bam_reset() - reset and initialize BAM registers > * @bdev: bam device > @@ -456,6 +504,10 @@ static void bam_reset(struct bam_device *bdev) > writel_relaxed(BAM_IRQ_MSK, bam_addr(bdev, 0, BAM_IRQ_SRCS_MSK_EE)); > } > > +static struct dma_descriptor_metadata_ops metadata_ops = { > + .attach = bam_attach_metadata, > +}; > + > /** > * bam_reset_channel - Reset individual BAM DMA channel > * @bchan: bam channel > @@ -714,6 +766,8 @@ static struct dma_async_tx_descriptor *bam_prep_slave_sg(struct dma_chan *chan, > } while (remainder > 0); > } > > + async_desc->vd.tx.metadata_ops = &metadata_ops; > + > return vchan_tx_prep(&bchan->vc, &async_desc->vd, flags); > } > > @@ -867,6 +921,8 @@ static u32 process_channel_irqs(struct bam_device *bdev) > if (avail < async_desc->xfer_len) > break; > > + bam_update_metadata(bchan, async_desc); > + > /* manage FIFO */ > bchan->head += async_desc->xfer_len; > bchan->head %= MAX_DESCRIPTORS; > @@ -1347,6 +1403,7 @@ static int bam_dma_probe(struct platform_device *pdev) > bdev->common.residue_granularity = DMA_RESIDUE_GRANULARITY_SEGMENT; > bdev->common.src_addr_widths = DMA_SLAVE_BUSWIDTH_4_BYTES; > bdev->common.dst_addr_widths = DMA_SLAVE_BUSWIDTH_4_BYTES; > + bdev->common.desc_metadata_modes = DESC_METADATA_CLIENT; > bdev->common.device_alloc_chan_resources = bam_alloc_chan; > bdev->common.device_free_chan_resources = bam_free_chan; > bdev->common.device_prep_slave_sg = bam_prep_slave_sg; > diff --git a/include/linux/dma/qcom_bam_dma.h b/include/linux/dma/qcom_bam_dma.h > index 68fc0e643b1b..8168b0573f45 100644 > --- a/include/linux/dma/qcom_bam_dma.h > +++ b/include/linux/dma/qcom_bam_dma.h > @@ -8,6 +8,14 @@ > > #include <asm/byteorder.h> > > +/* > + * This data type is used as client metadata buffer in bam driver. > + */ > +struct bam_dma_metadata { > + /* Actual number of bytes transferred by hardware */ > + size_t xfer_len_bytes; Pls implement dmaengine_result() and report that with proper residue set... Thanks
On Fri Nov 4, 2022 at 5:59 PM IST, Vinod Koul wrote: > On 27-10-22, 10:50, Sireesh Kodali wrote: > > From: Vladimir Lypak <vladimir.lypak@gmail.com> > > > > Add client metadata support for receiving information about transfers. > > Only type of metadata implemented is amount of transferred bytes. This > > can be used to know how much data is actually received if information > > transferred doesn't contain header with size or is aggregated. > > > > Signed-off-by: Vladimir Lypak <vladimir.lypak@gmail.com> > > Signed-off-by: Sireesh Kodali <sireeshkodali1@gmail.com> > > --- > > drivers/dma/qcom/bam_dma.c | 57 ++++++++++++++++++++++++++++++++ > > include/linux/dma/qcom_bam_dma.h | 8 +++++ > > 2 files changed, 65 insertions(+) > > > > diff --git a/drivers/dma/qcom/bam_dma.c b/drivers/dma/qcom/bam_dma.c > > index 3135a3e4a167..264a9a2e199f 100644 > > --- a/drivers/dma/qcom/bam_dma.c > > +++ b/drivers/dma/qcom/bam_dma.c > > @@ -30,6 +30,7 @@ > > #include <linux/module.h> > > #include <linux/interrupt.h> > > #include <linux/dma-mapping.h> > > +#include <linux/dma/qcom_bam_dma.h> > > #include <linux/scatterlist.h> > > #include <linux/device.h> > > #include <linux/platform_device.h> > > @@ -70,6 +71,7 @@ struct bam_async_desc { > > u16 flags; > > > > struct bam_desc_hw *curr_desc; > > + struct bam_dma_metadata *metadata; > > > > /* list node for the desc in the bam_chan list of descriptors */ > > struct list_head desc_node; > > @@ -418,6 +420,52 @@ static inline void __iomem *bam_addr(struct bam_device *bdev, u32 pipe, > > r.ee_mult * bdev->ee; > > } > > > > +/** > > + * bam_update_metadata - update metadata buffer > > + * @bchan: BAM channel to read metadata from > > + * @async_desc: BAM async descriptior > > + * > > + * Updates metadata buffer (transfer size) based on values > > + * read from FIFO descriptors at bchan->head > > + */ > > + > > +static inline void bam_update_metadata(struct bam_chan *bchan, > > + struct bam_async_desc *async_desc) > > +{ > > + unsigned int i, e, len = 0; > > + struct bam_desc_hw *fifo; > > + > > + if (!async_desc->metadata) > > + return; > > + > > + fifo = PTR_ALIGN(bchan->fifo_virt, sizeof(struct bam_desc_hw)); > > + for (i = bchan->head, e = i + async_desc->xfer_len; i < e; i++) > > + len += fifo[i % MAX_DESCRIPTORS].size; > > + > > + async_desc->metadata->xfer_len_bytes += len; > > +} > > + > > +/** > > + * bam_attach_metadata - attach metadata buffer to the async descriptor > > + * @desc: async descriptor > > + * @data: buffer pointer > > + * @len: length of passed buffer > > + */ > > +static int bam_attach_metadata(struct dma_async_tx_descriptor *desc, void *data, > > + size_t len) > > +{ > > + struct bam_async_desc *async_desc; > > + > > + if (!data || len != sizeof(struct bam_dma_metadata)) > > + return -EINVAL; > > + > > + async_desc = container_of(desc, struct bam_async_desc, vd.tx); > > + async_desc->metadata = data; > > + async_desc->metadata->xfer_len_bytes = 0; > > + > > + return 0; > > +} > > + > > /** > > * bam_reset() - reset and initialize BAM registers > > * @bdev: bam device > > @@ -456,6 +504,10 @@ static void bam_reset(struct bam_device *bdev) > > writel_relaxed(BAM_IRQ_MSK, bam_addr(bdev, 0, BAM_IRQ_SRCS_MSK_EE)); > > } > > > > +static struct dma_descriptor_metadata_ops metadata_ops = { > > + .attach = bam_attach_metadata, > > +}; > > + > > /** > > * bam_reset_channel - Reset individual BAM DMA channel > > * @bchan: bam channel > > @@ -714,6 +766,8 @@ static struct dma_async_tx_descriptor *bam_prep_slave_sg(struct dma_chan *chan, > > } while (remainder > 0); > > } > > > > + async_desc->vd.tx.metadata_ops = &metadata_ops; > > + > > return vchan_tx_prep(&bchan->vc, &async_desc->vd, flags); > > } > > > > @@ -867,6 +921,8 @@ static u32 process_channel_irqs(struct bam_device *bdev) > > if (avail < async_desc->xfer_len) > > break; > > > > + bam_update_metadata(bchan, async_desc); > > + > > /* manage FIFO */ > > bchan->head += async_desc->xfer_len; > > bchan->head %= MAX_DESCRIPTORS; > > @@ -1347,6 +1403,7 @@ static int bam_dma_probe(struct platform_device *pdev) > > bdev->common.residue_granularity = DMA_RESIDUE_GRANULARITY_SEGMENT; > > bdev->common.src_addr_widths = DMA_SLAVE_BUSWIDTH_4_BYTES; > > bdev->common.dst_addr_widths = DMA_SLAVE_BUSWIDTH_4_BYTES; > > + bdev->common.desc_metadata_modes = DESC_METADATA_CLIENT; > > bdev->common.device_alloc_chan_resources = bam_alloc_chan; > > bdev->common.device_free_chan_resources = bam_free_chan; > > bdev->common.device_prep_slave_sg = bam_prep_slave_sg; > > diff --git a/include/linux/dma/qcom_bam_dma.h b/include/linux/dma/qcom_bam_dma.h > > index 68fc0e643b1b..8168b0573f45 100644 > > --- a/include/linux/dma/qcom_bam_dma.h > > +++ b/include/linux/dma/qcom_bam_dma.h > > @@ -8,6 +8,14 @@ > > > > #include <asm/byteorder.h> > > > > +/* > > + * This data type is used as client metadata buffer in bam driver. > > + */ > > +struct bam_dma_metadata { > > + /* Actual number of bytes transferred by hardware */ > > + size_t xfer_len_bytes; > > Pls implement dmaengine_result() and report that with proper residue > set... Sure, I'll update the patch with this change Regards, Sireesh > > Thanks > > -- > ~Vinod
diff --git a/drivers/dma/qcom/bam_dma.c b/drivers/dma/qcom/bam_dma.c index 3135a3e4a167..264a9a2e199f 100644 --- a/drivers/dma/qcom/bam_dma.c +++ b/drivers/dma/qcom/bam_dma.c @@ -30,6 +30,7 @@ #include <linux/module.h> #include <linux/interrupt.h> #include <linux/dma-mapping.h> +#include <linux/dma/qcom_bam_dma.h> #include <linux/scatterlist.h> #include <linux/device.h> #include <linux/platform_device.h> @@ -70,6 +71,7 @@ struct bam_async_desc { u16 flags; struct bam_desc_hw *curr_desc; + struct bam_dma_metadata *metadata; /* list node for the desc in the bam_chan list of descriptors */ struct list_head desc_node; @@ -418,6 +420,52 @@ static inline void __iomem *bam_addr(struct bam_device *bdev, u32 pipe, r.ee_mult * bdev->ee; } +/** + * bam_update_metadata - update metadata buffer + * @bchan: BAM channel to read metadata from + * @async_desc: BAM async descriptior + * + * Updates metadata buffer (transfer size) based on values + * read from FIFO descriptors at bchan->head + */ + +static inline void bam_update_metadata(struct bam_chan *bchan, + struct bam_async_desc *async_desc) +{ + unsigned int i, e, len = 0; + struct bam_desc_hw *fifo; + + if (!async_desc->metadata) + return; + + fifo = PTR_ALIGN(bchan->fifo_virt, sizeof(struct bam_desc_hw)); + for (i = bchan->head, e = i + async_desc->xfer_len; i < e; i++) + len += fifo[i % MAX_DESCRIPTORS].size; + + async_desc->metadata->xfer_len_bytes += len; +} + +/** + * bam_attach_metadata - attach metadata buffer to the async descriptor + * @desc: async descriptor + * @data: buffer pointer + * @len: length of passed buffer + */ +static int bam_attach_metadata(struct dma_async_tx_descriptor *desc, void *data, + size_t len) +{ + struct bam_async_desc *async_desc; + + if (!data || len != sizeof(struct bam_dma_metadata)) + return -EINVAL; + + async_desc = container_of(desc, struct bam_async_desc, vd.tx); + async_desc->metadata = data; + async_desc->metadata->xfer_len_bytes = 0; + + return 0; +} + /** * bam_reset() - reset and initialize BAM registers * @bdev: bam device @@ -456,6 +504,10 @@ static void bam_reset(struct bam_device *bdev) writel_relaxed(BAM_IRQ_MSK, bam_addr(bdev, 0, BAM_IRQ_SRCS_MSK_EE)); } +static struct dma_descriptor_metadata_ops metadata_ops = { + .attach = bam_attach_metadata, +}; + /** * bam_reset_channel - Reset individual BAM DMA channel * @bchan: bam channel @@ -714,6 +766,8 @@ static struct dma_async_tx_descriptor *bam_prep_slave_sg(struct dma_chan *chan, } while (remainder > 0); } + async_desc->vd.tx.metadata_ops = &metadata_ops; + return vchan_tx_prep(&bchan->vc, &async_desc->vd, flags); } @@ -867,6 +921,8 @@ static u32 process_channel_irqs(struct bam_device *bdev) if (avail < async_desc->xfer_len) break; + bam_update_metadata(bchan, async_desc); + /* manage FIFO */ bchan->head += async_desc->xfer_len; bchan->head %= MAX_DESCRIPTORS; @@ -1347,6 +1403,7 @@ static int bam_dma_probe(struct platform_device *pdev) bdev->common.residue_granularity = DMA_RESIDUE_GRANULARITY_SEGMENT; bdev->common.src_addr_widths = DMA_SLAVE_BUSWIDTH_4_BYTES; bdev->common.dst_addr_widths = DMA_SLAVE_BUSWIDTH_4_BYTES; + bdev->common.desc_metadata_modes = DESC_METADATA_CLIENT; bdev->common.device_alloc_chan_resources = bam_alloc_chan; bdev->common.device_free_chan_resources = bam_free_chan; bdev->common.device_prep_slave_sg = bam_prep_slave_sg; diff --git a/include/linux/dma/qcom_bam_dma.h b/include/linux/dma/qcom_bam_dma.h index 68fc0e643b1b..8168b0573f45 100644 --- a/include/linux/dma/qcom_bam_dma.h +++ b/include/linux/dma/qcom_bam_dma.h @@ -8,6 +8,14 @@ #include <asm/byteorder.h> +/* + * This data type is used as client metadata buffer in bam driver. + */ +struct bam_dma_metadata { + /* Actual number of bytes transferred by hardware */ + size_t xfer_len_bytes; +}; + /* * This data type corresponds to the native Command Element * supported by BAM DMA Engine.