sound/pci/emu10k1/memory.c
Source file repositories/reference/linux-study-clean/sound/pci/emu10k1/memory.c
File Facts
- System
- Linux kernel
- Corpus path
sound/pci/emu10k1/memory.c- Extension
.c- Size
- 17104 bytes
- Lines
- 650
- Domain
- Driver Families
- Bucket
- sound/pci
- Inferred role
- Driver Families: exported/initcall integration point
- Status
- integration 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.
- 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.
- Exports symbols or registers init work; inspect boot/module ordering and who consumes the exported contract.
- Touches user memory; correctness depends on fault-safe copying and privilege boundary handling.
- Touches IRQ or DMA behavior; this matters for the representative real-device path.
- Allocates kernel memory; connect allocation flags and lifetime to context constraints.
- Defines or uses C structs; map object ownership, embedded links, reference counts, and lock ownership.
Dependency Surface
linux/pci.hlinux/gfp.hlinux/time.hlinux/mutex.hlinux/export.hsound/core.hsound/emu10k1.h
Detected Declarations
function Copyrightfunction set_silent_ptbfunction emu10k1_memblk_initfunction search_empty_map_areafunction list_for_eachfunction map_memblkfunction unmap_memblkfunction search_emptyfunction is_valid_pagefunction snd_emu10k1_memblk_mapfunction snd_emu10k1_alloc_pagesfunction snd_emu10k1_free_pagesfunction snd_emu10k1_detect_iommufunction pagesfunction snd_emu10k1_synth_freefunction get_single_page_rangefunction __synth_free_pagesfunction synth_alloc_pagesfunction synth_free_pagesfunction memsetfunction xor_rangefunction copy_from_userexport snd_emu10k1_memblk_mapexport snd_emu10k1_synth_allocexport snd_emu10k1_synth_freeexport snd_emu10k1_synth_memsetexport snd_emu10k1_synth_copy_from_user
Annotated Snippet
if (size == npages) {
*nextp = pos;
return page;
}
else if (size > max_size) {
/* we look for the maximum empty hole */
max_size = size;
candidate = pos;
found_page = page;
}
page = blk->mapped_page + blk->pages;
}
size = (emu->address_mode ? MAX_ALIGN_PAGES1 : MAX_ALIGN_PAGES0) - page;
if (size >= max_size) {
*nextp = pos;
return page;
}
*nextp = candidate;
return found_page;
}
/*
* map a memory block onto emu10k1's PTB
*
* call with memblk_lock held
*/
static int map_memblk(struct snd_emu10k1 *emu, struct snd_emu10k1_memblk *blk)
{
int page, pg;
struct list_head *next;
page = search_empty_map_area(emu, blk->pages, &next);
if (page < 0) /* not found */
return page;
if (page == 0) {
dev_err(emu->card->dev, "trying to map zero (reserved) page\n");
return -EINVAL;
}
/* insert this block in the proper position of mapped list */
list_add_tail(&blk->mapped_link, next);
/* append this as a newest block in order list */
list_add_tail(&blk->mapped_order_link, &emu->mapped_order_link_head);
blk->mapped_page = page;
/* fill PTB */
for (pg = blk->first_page; pg <= blk->last_page; pg++) {
set_ptb_entry(emu, page, emu->page_addr_table[pg]);
page++;
}
return 0;
}
/*
* unmap the block
* return the size of resultant empty pages
*
* call with memblk_lock held
*/
static int unmap_memblk(struct snd_emu10k1 *emu, struct snd_emu10k1_memblk *blk)
{
int start_page, end_page, mpage, pg;
struct list_head *p;
struct snd_emu10k1_memblk *q;
/* calculate the expected size of empty region */
p = blk->mapped_link.prev;
if (p != &emu->mapped_link_head) {
q = get_emu10k1_memblk(p, mapped_link);
start_page = q->mapped_page + q->pages;
} else {
start_page = 1;
}
p = blk->mapped_link.next;
if (p != &emu->mapped_link_head) {
q = get_emu10k1_memblk(p, mapped_link);
end_page = q->mapped_page;
} else {
end_page = (emu->address_mode ? MAX_ALIGN_PAGES1 : MAX_ALIGN_PAGES0);
}
/* remove links */
list_del(&blk->mapped_link);
list_del(&blk->mapped_order_link);
/* clear PTB */
mpage = blk->mapped_page;
for (pg = blk->first_page; pg <= blk->last_page; pg++) {
set_silent_ptb(emu, mpage);
mpage++;
}
blk->mapped_page = -1;
return end_page - start_page; /* return the new empty size */
Annotation
- Immediate include surface: `linux/pci.h`, `linux/gfp.h`, `linux/time.h`, `linux/mutex.h`, `linux/export.h`, `sound/core.h`, `sound/emu10k1.h`.
- Detected declarations: `function Copyright`, `function set_silent_ptb`, `function emu10k1_memblk_init`, `function search_empty_map_area`, `function list_for_each`, `function map_memblk`, `function unmap_memblk`, `function search_empty`, `function is_valid_page`, `function snd_emu10k1_memblk_map`.
- Atlas domain: Driver Families / sound/pci.
- Implementation status: integration implementation candidate.
- This snippet crosses the user/kernel memory boundary; validate fault handling and access checks before translating the pattern.
- IRQ or DMA behavior appears here, which is relevant to the selected PCIe/NVMe device path.
Implementation Notes
- This generated page is the file-by-file coverage layer; curated subsystem chapters should link here when they synthesize a multi-file control flow.
- Core OS pages should be promoted from atlas-only to deep-reviewed when they explain data structures, invariants, locking, lifecycle, and C implementation snippets.
- Driver-family pages are intentionally pattern-oriented unless they are part of the selected PCIe/NVMe representative device path.