diff mbox

[v2,03/15] dmaengine: Add no_wakeup parameter to dmaengine_prep_dma_cyclic()

Message ID 1347543485-339-4-git-send-email-peter.ujfalusi@ti.com (mailing list archive)
State New, archived
Headers show

Commit Message

Peter Ujfalusi Sept. 13, 2012, 1:37 p.m. UTC
The dmaengine_prep_dma_cyclic() function primarily used by audio for cyclic
transfer required by ALSA.
With this new parameter it is going to be possible to enable the
SNDRV_PCM_INFO_NO_PERIOD_WAKEUP mode on platforms where it is possible.
This patch only changes the public API first. Followup patch will change
the device_prep_dma_cyclic() callback parameters to pass this information
towards the dma drivers.

Signed-off-by: Peter Ujfalusi <peter.ujfalusi@ti.com>
CC: Lars-Peter Clausen <lars@metafoo.de>
---
 include/linux/dmaengine.h     | 3 ++-
 sound/soc/soc-dmaengine-pcm.c | 3 ++-
 2 files changed, 4 insertions(+), 2 deletions(-)

Comments

Lars-Peter Clausen Sept. 13, 2012, 3:27 p.m. UTC | #1
On 09/13/2012 03:37 PM, Peter Ujfalusi wrote:
> The dmaengine_prep_dma_cyclic() function primarily used by audio for cyclic
> transfer required by ALSA.
> With this new parameter it is going to be possible to enable the
> SNDRV_PCM_INFO_NO_PERIOD_WAKEUP mode on platforms where it is possible.
> This patch only changes the public API first. Followup patch will change
> the device_prep_dma_cyclic() callback parameters to pass this information
> towards the dma drivers.
> 

Hi,

Hm... Do you think it would work as well if we implement this by setting the
callback for the descriptor to NULL? If the callback is NULL there is
nothing to at the end of a transfer/period and the dma engine driver may
choose to disable interrupts. This would also benefit non cyclic transfers
where the callback is NULL and we do not need add the new parameter to
dmaengine_prep_dma_cyclic.

- Lars

> ---
>  include/linux/dmaengine.h     | 3 ++-
>  sound/soc/soc-dmaengine-pcm.c | 3 ++-
>  2 files changed, 4 insertions(+), 2 deletions(-)
> 
> diff --git a/include/linux/dmaengine.h b/include/linux/dmaengine.h
> index 9c02a45..990444b 100644
> --- a/include/linux/dmaengine.h
> +++ b/include/linux/dmaengine.h
> @@ -653,7 +653,8 @@ static inline struct dma_async_tx_descriptor *dmaengine_prep_rio_sg(
>  
>  static inline struct dma_async_tx_descriptor *dmaengine_prep_dma_cyclic(
>  		struct dma_chan *chan, dma_addr_t buf_addr, size_t buf_len,
> -		size_t period_len, enum dma_transfer_direction dir)
> +		size_t period_len, enum dma_transfer_direction dir,
> +		bool no_wakeup)
>  {
>  	return chan->device->device_prep_dma_cyclic(chan, buf_addr, buf_len,
>  						period_len, dir, NULL);
> diff --git a/sound/soc/soc-dmaengine-pcm.c b/sound/soc/soc-dmaengine-pcm.c
> index 5df529e..6b70adb 100644
> --- a/sound/soc/soc-dmaengine-pcm.c
> +++ b/sound/soc/soc-dmaengine-pcm.c
> @@ -147,7 +147,8 @@ static int dmaengine_pcm_prepare_and_submit(struct snd_pcm_substream *substream)
>  	desc = dmaengine_prep_dma_cyclic(chan,
>  		substream->runtime->dma_addr,
>  		snd_pcm_lib_buffer_bytes(substream),
> -		snd_pcm_lib_period_bytes(substream), direction);
> +		snd_pcm_lib_period_bytes(substream), direction,
> +		substream->runtime->no_period_wakeup);
>  
>  	if (!desc)
>  		return -ENOMEM;
Russell King - ARM Linux Sept. 13, 2012, 3:38 p.m. UTC | #2
On Thu, Sep 13, 2012 at 05:27:09PM +0200, Lars-Peter Clausen wrote:
> Hm... Do you think it would work as well if we implement this by setting the
> callback for the descriptor to NULL? If the callback is NULL there is
> nothing to at the end of a transfer/period and the dma engine driver may
> choose to disable interrupts. This would also benefit non cyclic transfers
> where the callback is NULL and we do not need add the new parameter to
> dmaengine_prep_dma_cyclic.

Actually, there's a way to do that already.  DMA_PREP_INTERRUPT.
Unfortunately, most DMA engine slave API users don't set it when they
setup their transfer:

 * @DMA_PREP_INTERRUPT - trigger an interrupt (callback) upon completion of
 *  this transaction

if we fixed that, then we could use the lack of it to avoid the interrupt.

However, cyclic transfers don't have the flags parameter used to pass this
bit.  Yet another bit of yucky inconsistent design in DMA engine land...
Vinod Koul Sept. 14, 2012, 3:26 a.m. UTC | #3
On Thu, 2012-09-13 at 17:27 +0200, Lars-Peter Clausen wrote:
> Hi,
> 
> Hm... Do you think it would work as well if we implement this by
> setting the
> callback for the descriptor to NULL? If the callback is NULL there is
> nothing to at the end of a transfer/period and the dma engine driver
> may
> choose to disable interrupts. This would also benefit non cyclic
> transfers
> where the callback is NULL and we do not need add the new parameter to
> dmaengine_prep_dma_cyclic.
That will work too.... BUT the idea of no_wake mode in ALSA is that we
should not have any interrupts, so anything which is going to cause
interrupts to AP in undesired. The interrupts still happen and it just
that dmaengine driver is not notifying client.
Vinod Koul Sept. 14, 2012, 3:27 a.m. UTC | #4
On Thu, 2012-09-13 at 16:38 +0100, Russell King - ARM Linux wrote:
> On Thu, Sep 13, 2012 at 05:27:09PM +0200, Lars-Peter Clausen wrote:
> > Hm... Do you think it would work as well if we implement this by setting the
> > callback for the descriptor to NULL? If the callback is NULL there is
> > nothing to at the end of a transfer/period and the dma engine driver may
> > choose to disable interrupts. This would also benefit non cyclic transfers
> > where the callback is NULL and we do not need add the new parameter to
> > dmaengine_prep_dma_cyclic.
> 
> Actually, there's a way to do that already.  DMA_PREP_INTERRUPT.
> Unfortunately, most DMA engine slave API users don't set it when they
> setup their transfer:
> 
>  * @DMA_PREP_INTERRUPT - trigger an interrupt (callback) upon completion of
>  *  this transaction
Looks like I have repeated the correct action!
> 
> if we fixed that, then we could use the lack of it to avoid the interrupt.
> 
> However, cyclic transfers don't have the flags parameter used to pass this
> bit.  Yet another bit of yucky inconsistent design in DMA engine land...
> 
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
Peter Ujfalusi Sept. 14, 2012, 7:12 a.m. UTC | #5
Hi,

On 09/13/2012 06:27 PM, Lars-Peter Clausen wrote:
> On 09/13/2012 03:37 PM, Peter Ujfalusi wrote:
>> The dmaengine_prep_dma_cyclic() function primarily used by audio for cyclic
>> transfer required by ALSA.
>> With this new parameter it is going to be possible to enable the
>> SNDRV_PCM_INFO_NO_PERIOD_WAKEUP mode on platforms where it is possible.
>> This patch only changes the public API first. Followup patch will change
>> the device_prep_dma_cyclic() callback parameters to pass this information
>> towards the dma drivers.
>>
> 
> Hi,
> 
> Hm... Do you think it would work as well if we implement this by setting the
> callback for the descriptor to NULL? If the callback is NULL there is
> nothing to at the end of a transfer/period and the dma engine driver may
> choose to disable interrupts. This would also benefit non cyclic transfers
> where the callback is NULL and we do not need add the new parameter to
> dmaengine_prep_dma_cyclic.

We could do that but dma drivers enable the interrupts within
dmaengine_prep_dma_cyclic() call, and we fill up the callback for
dmaengine_submit() dmaengine API call.
We need to tell the dma drivers in dmaengine_prep_dma_cyclic() to suppress the
interrupts.

Note: First I was trying this to be done in hw_params() time via the
dmaengine_slave_config() call, but substream->runtime->no_period_wakeup is not
configured in there. It is set for _prepare() and _trigger().

As Vinod and Russell suggested I will modify the dmaengine_prep_dma_cyclic()
API to pass flags as well instead of the no_wakeup parameter.

> 
> - Lars
> 
>> ---
>>  include/linux/dmaengine.h     | 3 ++-
>>  sound/soc/soc-dmaengine-pcm.c | 3 ++-
>>  2 files changed, 4 insertions(+), 2 deletions(-)
>>
>> diff --git a/include/linux/dmaengine.h b/include/linux/dmaengine.h
>> index 9c02a45..990444b 100644
>> --- a/include/linux/dmaengine.h
>> +++ b/include/linux/dmaengine.h
>> @@ -653,7 +653,8 @@ static inline struct dma_async_tx_descriptor *dmaengine_prep_rio_sg(
>>  
>>  static inline struct dma_async_tx_descriptor *dmaengine_prep_dma_cyclic(
>>  		struct dma_chan *chan, dma_addr_t buf_addr, size_t buf_len,
>> -		size_t period_len, enum dma_transfer_direction dir)
>> +		size_t period_len, enum dma_transfer_direction dir,
>> +		bool no_wakeup)
>>  {
>>  	return chan->device->device_prep_dma_cyclic(chan, buf_addr, buf_len,
>>  						period_len, dir, NULL);
>> diff --git a/sound/soc/soc-dmaengine-pcm.c b/sound/soc/soc-dmaengine-pcm.c
>> index 5df529e..6b70adb 100644
>> --- a/sound/soc/soc-dmaengine-pcm.c
>> +++ b/sound/soc/soc-dmaengine-pcm.c
>> @@ -147,7 +147,8 @@ static int dmaengine_pcm_prepare_and_submit(struct snd_pcm_substream *substream)
>>  	desc = dmaengine_prep_dma_cyclic(chan,
>>  		substream->runtime->dma_addr,
>>  		snd_pcm_lib_buffer_bytes(substream),
>> -		snd_pcm_lib_period_bytes(substream), direction);
>> +		snd_pcm_lib_period_bytes(substream), direction,
>> +		substream->runtime->no_period_wakeup);
>>  
>>  	if (!desc)
>>  		return -ENOMEM;
>
Peter Ujfalusi Sept. 14, 2012, 7:15 a.m. UTC | #6
On 09/13/2012 06:38 PM, Russell King - ARM Linux wrote:
> On Thu, Sep 13, 2012 at 05:27:09PM +0200, Lars-Peter Clausen wrote:
>> Hm... Do you think it would work as well if we implement this by setting the
>> callback for the descriptor to NULL? If the callback is NULL there is
>> nothing to at the end of a transfer/period and the dma engine driver may
>> choose to disable interrupts. This would also benefit non cyclic transfers
>> where the callback is NULL and we do not need add the new parameter to
>> dmaengine_prep_dma_cyclic.
> 
> Actually, there's a way to do that already.  DMA_PREP_INTERRUPT.
> Unfortunately, most DMA engine slave API users don't set it when they
> setup their transfer:
> 
>  * @DMA_PREP_INTERRUPT - trigger an interrupt (callback) upon completion of
>  *  this transaction

As I mentioned already to Vinod: the description of this flag is close enough
for our needs (other than the notion of 'this transaction' is not really
correct for cyclic mode).
I will resend the series to add the flags as new parameter instead of the
no_wakeup.

> 
> if we fixed that, then we could use the lack of it to avoid the interrupt.
> 
> However, cyclic transfers don't have the flags parameter used to pass this
> bit.  Yet another bit of yucky inconsistent design in DMA engine land...
>
Peter Ujfalusi Sept. 14, 2012, 7:18 a.m. UTC | #7
On 09/14/2012 06:26 AM, Vinod Koul wrote:
> On Thu, 2012-09-13 at 17:27 +0200, Lars-Peter Clausen wrote:
>> Hi,
>>
>> Hm... Do you think it would work as well if we implement this by
>> setting the
>> callback for the descriptor to NULL? If the callback is NULL there is
>> nothing to at the end of a transfer/period and the dma engine driver
>> may
>> choose to disable interrupts. This would also benefit non cyclic
>> transfers
>> where the callback is NULL and we do not need add the new parameter to
>> dmaengine_prep_dma_cyclic.
> That will work too.... BUT the idea of no_wake mode in ALSA is that we
> should not have any interrupts, so anything which is going to cause
> interrupts to AP in undesired. The interrupts still happen and it just
> that dmaengine driver is not notifying client.

Yes, this is correct. We could go and hack around later if the callback is not
present and modify the irq requests for the platform but it is really not
elegant way of dealing with the issue IMHO.
Lars-Peter Clausen Sept. 14, 2012, 8:13 a.m. UTC | #8
On 09/14/2012 05:26 AM, Vinod Koul wrote:
> On Thu, 2012-09-13 at 17:27 +0200, Lars-Peter Clausen wrote:
>> Hi,
>>
>> Hm... Do you think it would work as well if we implement this by
>> setting the
>> callback for the descriptor to NULL? If the callback is NULL there is
>> nothing to at the end of a transfer/period and the dma engine driver
>> may
>> choose to disable interrupts. This would also benefit non cyclic
>> transfers
>> where the callback is NULL and we do not need add the new parameter to
>> dmaengine_prep_dma_cyclic.
> That will work too.... BUT the idea of no_wake mode in ALSA is that we
> should not have any interrupts, so anything which is going to cause
> interrupts to AP in undesired. The interrupts still happen and it just
> that dmaengine driver is not notifying client.

Well, the idea was that the driver would disable interrupts if there is no
callback to call, since there would be nothing to do in the interrupt
handler anyway. But I guess the flags approach should work fine as well.
Vinod Koul Sept. 14, 2012, 8:50 a.m. UTC | #9
On Fri, 2012-09-14 at 10:13 +0200, Lars-Peter Clausen wrote:
> On 09/14/2012 05:26 AM, Vinod Koul wrote:
> > On Thu, 2012-09-13 at 17:27 +0200, Lars-Peter Clausen wrote:
> >> Hi,
> >>
> >> Hm... Do you think it would work as well if we implement this by
> >> setting the
> >> callback for the descriptor to NULL? If the callback is NULL there is
> >> nothing to at the end of a transfer/period and the dma engine driver
> >> may
> >> choose to disable interrupts. This would also benefit non cyclic
> >> transfers
> >> where the callback is NULL and we do not need add the new parameter to
> >> dmaengine_prep_dma_cyclic.
> > That will work too.... BUT the idea of no_wake mode in ALSA is that we
> > should not have any interrupts, so anything which is going to cause
> > interrupts to AP in undesired. The interrupts still happen and it just
> > that dmaengine driver is not notifying client.
> 
> Well, the idea was that the driver would disable interrupts if there is no
> callback to call, since there would be nothing to do in the interrupt
> handler anyway. But I guess the flags approach should work fine as well.
Yes we _could_ do that, but this relies on dmaengine driver to have this
implicit understanding. Anyone using dmaengine library in ASoC may or
may not be aware of this, so i would consider it hackish.

Using this flag explicitly makes everyone aware what the intended
behaviour is.
Peter Ujfalusi Sept. 14, 2012, 9:28 a.m. UTC | #10
Hi,

On 09/14/2012 11:50 AM, Vinod Koul wrote:
>> Well, the idea was that the driver would disable interrupts if there is no
>> callback to call, since there would be nothing to do in the interrupt
>> handler anyway. But I guess the flags approach should work fine as well.
> Yes we _could_ do that, but this relies on dmaengine driver to have this
> implicit understanding. Anyone using dmaengine library in ASoC may or
> may not be aware of this, so i would consider it hackish.
> 
> Using this flag explicitly makes everyone aware what the intended
> behaviour is.

I'm not sure about which flags should ASoC set for the two case we are going
to have. I think it should be something like this:

unsigned long flags = DMA_CTRL_ACK;

if (!substream->runtime->no_period_wakeup)
	flags |= DMA_PREP_INTERRUPT;

I'm not 100% sure of the role of DMA_CTRL_ACK in this case. Or should we only
handle the DMA_PREP_INTERRUPT flag, like this:

unsigned long flags = 0;

if (!substream->runtime->no_period_wakeup)
	flags |= DMA_PREP_INTERRUPT;


What do you think?
Vinod Koul Sept. 14, 2012, 9:38 a.m. UTC | #11
On Fri, 2012-09-14 at 12:28 +0300, Peter Ujfalusi wrote:
> Hi,
> 
> On 09/14/2012 11:50 AM, Vinod Koul wrote:
> >> Well, the idea was that the driver would disable interrupts if there is no
> >> callback to call, since there would be nothing to do in the interrupt
> >> handler anyway. But I guess the flags approach should work fine as well.
> > Yes we _could_ do that, but this relies on dmaengine driver to have this
> > implicit understanding. Anyone using dmaengine library in ASoC may or
> > may not be aware of this, so i would consider it hackish.
> > 
> > Using this flag explicitly makes everyone aware what the intended
> > behaviour is.
> 
> I'm not sure about which flags should ASoC set for the two case we are going
> to have. I think it should be something like this:
> 
> unsigned long flags = DMA_CTRL_ACK;
usage of ACK flag is mostly async_tx thingy, we can skip it for slave.
> 
> if (!substream->runtime->no_period_wakeup)
> 	flags |= DMA_PREP_INTERRUPT;
> I'm not 100% sure of the role of DMA_CTRL_ACK in this case. Or should we only
> handle the DMA_PREP_INTERRUPT flag, like this:
> 
> unsigned long flags = 0;
> 
> if (!substream->runtime->no_period_wakeup)
> 	flags |= DMA_PREP_INTERRUPT;
> 
> 
> What do you think?
Looks fine.
Russell King - ARM Linux Sept. 14, 2012, 10:01 a.m. UTC | #12
On Fri, Sep 14, 2012 at 12:28:28PM +0300, Peter Ujfalusi wrote:
> I'm not sure about which flags should ASoC set for the two case we are going
> to have. I think it should be something like this:
> 
> unsigned long flags = DMA_CTRL_ACK;
> 
> if (!substream->runtime->no_period_wakeup)
> 	flags |= DMA_PREP_INTERRUPT;

That looks about right.  I would encourage DMA_CTRL_ACK to always be set
for slave stuff, because it will (according to my understanding of it)
make the behaviour no different from the async_tx stuff... which is
important when support for that stuff gets added.

We could, of course, set DMA_CTRL_ACK in the slave APIs beneath the
user, but the user has access to tx->flags between the prepare and
submit calls...  And doing it in the submit callback will force DMA
engine drivers to have two separate submission paths (as tx'es can't
be acked at submission time.)
diff mbox

Patch

diff --git a/include/linux/dmaengine.h b/include/linux/dmaengine.h
index 9c02a45..990444b 100644
--- a/include/linux/dmaengine.h
+++ b/include/linux/dmaengine.h
@@ -653,7 +653,8 @@  static inline struct dma_async_tx_descriptor *dmaengine_prep_rio_sg(
 
 static inline struct dma_async_tx_descriptor *dmaengine_prep_dma_cyclic(
 		struct dma_chan *chan, dma_addr_t buf_addr, size_t buf_len,
-		size_t period_len, enum dma_transfer_direction dir)
+		size_t period_len, enum dma_transfer_direction dir,
+		bool no_wakeup)
 {
 	return chan->device->device_prep_dma_cyclic(chan, buf_addr, buf_len,
 						period_len, dir, NULL);
diff --git a/sound/soc/soc-dmaengine-pcm.c b/sound/soc/soc-dmaengine-pcm.c
index 5df529e..6b70adb 100644
--- a/sound/soc/soc-dmaengine-pcm.c
+++ b/sound/soc/soc-dmaengine-pcm.c
@@ -147,7 +147,8 @@  static int dmaengine_pcm_prepare_and_submit(struct snd_pcm_substream *substream)
 	desc = dmaengine_prep_dma_cyclic(chan,
 		substream->runtime->dma_addr,
 		snd_pcm_lib_buffer_bytes(substream),
-		snd_pcm_lib_period_bytes(substream), direction);
+		snd_pcm_lib_period_bytes(substream), direction,
+		substream->runtime->no_period_wakeup);
 
 	if (!desc)
 		return -ENOMEM;