[alsa-devel] [PATCH] ASoC: omap-pcm: Lower the dma coherent mask to 32bits

Takashi Iwai tiwai at suse.de
Thu Dec 5 21:11:50 CET 2013


At Thu, 5 Dec 2013 19:28:53 +0000,
Russell King - ARM Linux wrote:
> 
> On Thu, Dec 05, 2013 at 05:33:46PM +0200, Peter Ujfalusi wrote:
> > I'm not that familiar with this part of the code (mm, dma-mapping) but so far
> > this is what I found:
> > 
> > ret = dma_coerce_mask_and_coherent(card->dev, DMA_BIT_MASK(64));
> > is successful, no failure to set the mask to 64.
> > 
> > later on when requesting the dma channel however:
> > arm_dma_alloc() -> get_coherent_dma_mask()  fails.
> > 
> > As far I can see we have different checks in case of
> > dma_coerce_mask_and_coherent() and arm_dma_alloc():
> > 
> > [1] dma_coerce_mask_and_coherent() -> dma_supported()
> > 
> >  	if (sizeof(mask) != sizeof(dma_addr_t) &&
> >  	    mask > (dma_addr_t)~0 &&
> >  	    dma_to_pfn(dev, ~0) > arm_dma_pfn_limit)  /* !!! */
> >  		return 0;
> > 
> > 
> > [2] arm_dma_alloc() -> get_coherent_dma_mask()
> > 
> >  	if (sizeof(mask) != sizeof(dma_addr_t) &&
> >  	    mask > (dma_addr_t)~0 &&
> >  	    dma_to_pfn(dev, ~0) > min(max_pfn, arm_dma_pfn_limit)) /* !!! */
> >  		return 0;
> > 
> > On omap4:
> > max_pfn: 0xc0000, arm_dma_pfn_limit: 0xfffff
> 
> Obviously, we should not be saying that the mask is okay, and then failing
> with that same mask.
> 
> I've thinking about what the right fix here is - it's been quite a while
> since I devised those tests and the knowledge I had back then has been
> swapped out...
> 
> The point of these tests are to deal with masks which are larger than
> dma_addr_t allows, and to only deny if we have sufficient system memory
> that we may overflow dma_addr_t.
> 
> So...
> 
> 	sizeof(u64) != sizeof(dma_addr_t)
> 
> detects when we have non-64 bit dma_addr_t.
> 
> 	mask > (dma_addr_t)~0
> 
> detects if the mask is larger than 4GiB.
> 
> 	dma_to_pfn(dev, ~0)
> 
> gives us the very last PFN which the bus associated with dev is able to
> address.  Hmm - so I got the test wrong on both twice - they should both
> be:
> 
>  	if (sizeof(mask) != sizeof(dma_addr_t) &&
>  	    mask > (dma_addr_t)~0 &&
>  	    dma_to_pfn(dev, ~0) < min(max_pfn, arm_dma_pfn_limit))
> 		return 0;
> 
> since we want to fail if we have _more_ memory than the bus will allow.
> Can you try the above in both locations please?

Does the check of dma_to_pfn(dev, ~0) is really necessary?
In get_coherent_dma_mask(), it checks further

		if (dma_to_pfn(dev, mask) < max_dma_pfn) {

and since mask > ~0, this check should suffice, I think.

And this made me wonder why can we simply use dma_supported() for the
check in get_coherent_dma_mask().  If the check in get_coherent_mask()
must be different, it'd be helpful if you comment on it there, too.


thanks,

Takashi


More information about the Alsa-devel mailing list