sound/pci/trident/trident_memory.c

Source file repositories/reference/linux-study-clean/sound/pci/trident/trident_memory.c

File Facts

System
Linux kernel
Corpus path
sound/pci/trident/trident_memory.c
Extension
.c
Size
7958 bytes
Lines
270
Domain
Driver Families
Bucket
sound/pci
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

if (!is_valid_page(trident, addr)) {
			__snd_util_mem_free(hdr, blk);
			return NULL;
		}
		set_tlb_bus(trident, page, addr);
	}
	return blk;
}

/*
 * page allocation for DMA (contiguous version)
 */
static struct snd_util_memblk *
snd_trident_alloc_cont_pages(struct snd_trident *trident,
			     struct snd_pcm_substream *substream)
{
	struct snd_util_memhdr *hdr;
	struct snd_util_memblk *blk;
	int page;
	struct snd_pcm_runtime *runtime = substream->runtime;
	dma_addr_t addr;

	if (snd_BUG_ON(runtime->dma_bytes <= 0 ||
		       runtime->dma_bytes > SNDRV_TRIDENT_MAX_PAGES *
					SNDRV_TRIDENT_PAGE_SIZE))
		return NULL;
	hdr = trident->tlb.memhdr;
	if (snd_BUG_ON(!hdr))
		return NULL;

	guard(mutex)(&hdr->block_mutex);
	blk = search_empty(hdr, runtime->dma_bytes);
	if (blk == NULL)
		return NULL;
			   
	/* set TLB entries */
	addr = runtime->dma_addr;
	for (page = firstpg(blk); page <= lastpg(blk); page++,
	     addr += SNDRV_TRIDENT_PAGE_SIZE) {
		if (!is_valid_page(trident, addr)) {
			__snd_util_mem_free(hdr, blk);
			return NULL;
		}
		set_tlb_bus(trident, page, addr);
	}
	return blk;
}

/*
 * page allocation for DMA
 */
struct snd_util_memblk *
snd_trident_alloc_pages(struct snd_trident *trident,
			struct snd_pcm_substream *substream)
{
	if (snd_BUG_ON(!trident || !substream))
		return NULL;
	if (substream->dma_buffer.dev.type == SNDRV_DMA_TYPE_DEV_SG)
		return snd_trident_alloc_sg_pages(trident, substream);
	else
		return snd_trident_alloc_cont_pages(trident, substream);
}


/*
 * release DMA buffer from page table
 */
int snd_trident_free_pages(struct snd_trident *trident,
			   struct snd_util_memblk *blk)
{
	struct snd_util_memhdr *hdr;
	int page;

	if (snd_BUG_ON(!trident || !blk))
		return -EINVAL;

	hdr = trident->tlb.memhdr;
	guard(mutex)(&hdr->block_mutex);
	/* reset TLB entries */
	for (page = firstpg(blk); page <= lastpg(blk); page++)
		set_silent_tlb(trident, page);
	/* free memory block */
	__snd_util_mem_free(hdr, blk);
	return 0;
}

Annotation

Implementation Notes