2022-10-27 05:32:46

by Sireesh Kodali

[permalink] [raw]
Subject: [PATCH v2 0/1] dmaengine: qcom: Add support for metadata in bam_dma

IPA v2.x uses BAM to send and receive IP packets, to and from the AP.
However, unlike its predecessor BAM-DMUX, it doesn't send information
about the packet length. To find the length of the packet, one must
instead read the bam_desc metadata. This patch adds support for sending
the size metadata over the dmaengine metadata api. Currently only the
dma size is stored in the metadata. Only client-side metadata is
supported for now, because host-side metadata doesn't make sense for
IPA, where more than one DMA descriptors could be waiting to be acked
and processed.

Changes since v1:
* Rebased onto 6.0 kernel
* Patch redone by Vladimir

Vladimir Lypak (1):
dmaengine: qcom: bam_dma: Add support for metadata

drivers/dma/qcom/bam_dma.c | 57 ++++++++++++++++++++++++++++++++
include/linux/dma/qcom_bam_dma.h | 8 +++++
2 files changed, 65 insertions(+)

--
2.38.1



2022-10-27 05:45:04

by Sireesh Kodali

[permalink] [raw]
Subject: [PATCH v2 1/1] dmaengine: qcom: bam_dma: Add support for metadata

From: Vladimir Lypak <[email protected]>

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 <[email protected]>
Signed-off-by: Sireesh Kodali <[email protected]>
---
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;
+};
+
/*
* This data type corresponds to the native Command Element
* supported by BAM DMA Engine.
--
2.38.1


2022-11-04 13:24:29

by Vinod Koul

[permalink] [raw]
Subject: Re: [PATCH v2 1/1] dmaengine: qcom: bam_dma: Add support for metadata

On 27-10-22, 10:50, Sireesh Kodali wrote:
> From: Vladimir Lypak <[email protected]>
>
> 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 <[email protected]>
> Signed-off-by: Sireesh Kodali <[email protected]>
> ---
> 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

--
~Vinod

2022-11-11 05:21:22

by Sireesh Kodali

[permalink] [raw]
Subject: Re: [PATCH v2 1/1] dmaengine: qcom: bam_dma: Add support for metadata

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 <[email protected]>
> >
> > 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 <[email protected]>
> > Signed-off-by: Sireesh Kodali <[email protected]>
> > ---
> > 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