This patch adds the num_channels_busy member to the dma structure which will be helpful in determining DMAC to be allocated to users based on the number of channels draining. This is help provide a primitive level of QoS and prevent DMAC overuse.
Signed-off-by: Ranjani Sridharan ranjani.sridharan@linux.intel.com --- src/drivers/dw-dma.c | 11 +++++++++++ src/drivers/hda-dma.c | 8 ++++++++ src/include/sof/dma.h | 2 ++ 3 files changed, 21 insertions(+)
diff --git a/src/drivers/dw-dma.c b/src/drivers/dw-dma.c index c064330..932874d 100644 --- a/src/drivers/dw-dma.c +++ b/src/drivers/dw-dma.c @@ -43,6 +43,7 @@ * used to construct the DMA configuration for the host client 1 above. */
+#include <sof/atomic.h> #include <sof/debug.h> #include <sof/sof.h> #include <sof/dma.h> @@ -309,6 +310,8 @@ static int dw_dma_channel_get(struct dma *dma, int req_chan)
p->chan[i].status = COMP_STATE_READY;
+ atomic_add(&dma->num_channels_busy, 1); + /* unmask block, transfer and error interrupts for channel */ dw_write(dma, DW_MASK_TFR, INT_UNMASK(i)); dw_write(dma, DW_MASK_BLOCK, INT_UNMASK(i)); @@ -347,6 +350,8 @@ static void dw_dma_channel_put_unlocked(struct dma *dma, int channel) p->chan[channel].status = COMP_STATE_INIT; p->chan[channel].cb = NULL; p->chan[channel].desc_count = 0; + + atomic_sub(&dma->num_channels_busy, 1); }
/* channel must not be running when this is called */ @@ -1033,6 +1038,9 @@ static int dw_dma_probe(struct dma *dma) interrupt_enable(dma_int[i]->irq); }
+ /* init number of channels draining */ + atomic_init(&dma->num_channels_busy, 0); + return 0; }
@@ -1170,6 +1178,9 @@ static int dw_dma_probe(struct dma *dma) interrupt_register(dma_irq(dma), dw_dma_irq_handler, dma); interrupt_enable(dma_irq(dma));
+ /* init number of channels draining */ + atomic_init(&dma->num_channels_busy, 0); + return 0; } #endif diff --git a/src/drivers/hda-dma.c b/src/drivers/hda-dma.c index 97ea0ef..3b72be4 100644 --- a/src/drivers/hda-dma.c +++ b/src/drivers/hda-dma.c @@ -29,6 +29,7 @@ * Liam Girdwood liam.r.girdwood@linux.intel.com */
+#include <sof/atomic.h> #include <stdint.h> #include <stddef.h> #include <errno.h> @@ -145,6 +146,8 @@ static int hda_dma_channel_get(struct dma *dma, int channel) if (p->chan[channel].status == COMP_STATE_INIT) { p->chan[channel].status = COMP_STATE_READY;
+ atomic_add(&dma->num_channels_busy, 1); + /* return channel */ spin_unlock_irq(&dma->lock, flags); return channel; @@ -173,6 +176,8 @@ static void hda_dma_channel_put(struct dma *dma, int channel) spin_lock_irq(&dma->lock, flags); hda_dma_channel_put_unlocked(dma, channel); spin_unlock_irq(&dma->lock, flags); + + atomic_sub(&dma->num_channels_busy, 1); }
static int hda_dma_start(struct dma *dma, int channel) @@ -400,6 +405,9 @@ static int hda_dma_probe(struct dma *dma) for (i = 0; i < HDA_DMA_MAX_CHANS; i++) hda_pdata->chan[i].status = COMP_STATE_INIT;
+ /* init number of channels draining */ + atomic_init(&dma->num_channels_busy, 0); + return 0; }
diff --git a/src/include/sof/dma.h b/src/include/sof/dma.h index 4bc178e..0babbd3 100644 --- a/src/include/sof/dma.h +++ b/src/include/sof/dma.h @@ -37,6 +37,7 @@ #include <sof/lock.h> #include <sof/sof.h> #include <sof/wait.h> +#include <arch/atomic.h>
/* types of DMA directions */ enum dma_copy_dir { @@ -145,6 +146,7 @@ struct dma { struct dma_plat_data plat_data; spinlock_t lock; const struct dma_ops *ops; + atomic_t num_channels_busy; /* number of channels draining */ void *private; };