At Thu, 14 Feb 2013 18:26:53 +0100, Adrian Knoth wrote:
On 02/14/2013 06:14 PM, Takashi Iwai wrote:
/* allocate level buffer */ err = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV_SG, snd_dma_pci_data(hdspm->pci), MADIFX_LEVEL_BUFFER_SIZE, &hdspm->dmaLevelBuffer); if (err < 0) { /* error */ [..] }
hdspm->level_buffer = snd_sgbuf_get_ptr(&(hdspm->dmaLevelBuffer), 0);
hdspm->level_buffer = (u32*)hdspm.dmaLevelBuffer.area;
Looks good, TNX.
This used to work on my development machine (kernel 3.6.x), but now a kernel 3.2.0 user reports a NULL pointer dereference of hdspm->level_buffer, so apparently, snd_sgbuf_get_ptr() returned NULL for him.
What's level_buffer?
The card does hardware metering and stores RMS/peak values in a DMA buffer. I want to later pass this to userspace to show signal levels, either via memcpy()ing the DMA buffer or maybe via mmap(). But since I no longer have access to such a card, work on this is on halt atm.
Is a SG-buffer for the audio stream?
The audio buffers use
snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV_SG, snd_dma_pci_data(hdspm->pci),
so they're SG, yes.
But isn't the level meter buffer a single page? If the buffer is only for peak meters, it can't be that big even for multi-channel cards. If so, SNDRV_DMA_TYPE_DEV_SG is utterly nonsense. Otherwise, if it's a SG buffer, you'll have to some code to set up TLB in anyway.
Takashi