cregit-Linux how code gets into the kernel

Release 4.7 sound/isa/gus/gus_mem.c

Directory: sound/isa/gus
/*
 *  Copyright (c) by Jaroslav Kysela <perex@perex.cz>
 *  GUS's memory allocation routines / bottom layer
 *
 *
 *   This program is free software; you can redistribute it and/or modify
 *   it under the terms of the GNU General Public License as published by
 *   the Free Software Foundation; either version 2 of the License, or
 *   (at your option) any later version.
 *
 *   This program is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *   GNU General Public License for more details.
 *
 *   You should have received a copy of the GNU General Public License
 *   along with this program; if not, write to the Free Software
 *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
 *
 */

#include <linux/slab.h>
#include <linux/string.h>
#include <sound/core.h>
#include <sound/gus.h>
#include <sound/info.h>

#ifdef CONFIG_SND_DEBUG
static void snd_gf1_mem_info_read(struct snd_info_entry *entry, 
				  struct snd_info_buffer *buffer);
#endif


void snd_gf1_mem_lock(struct snd_gf1_mem * alloc, int xup) { if (!xup) { mutex_lock(&alloc->memory_mutex); } else { mutex_unlock(&alloc->memory_mutex); } }

Contributors

PersonTokensPropCommitsCommitProp
jaroslav kyselajaroslav kysela3589.74%133.33%
takashi iwaitakashi iwai25.13%133.33%
ingo molnaringo molnar25.13%133.33%
Total39100.00%3100.00%


static struct snd_gf1_mem_block *snd_gf1_mem_xalloc(struct snd_gf1_mem * alloc, struct snd_gf1_mem_block * block) { struct snd_gf1_mem_block *pblock, *nblock; nblock = kmalloc(sizeof(struct snd_gf1_mem_block), GFP_KERNEL); if (nblock == NULL) return NULL; *nblock = *block; pblock = alloc->first; while (pblock) { if (pblock->ptr > nblock->ptr) { nblock->prev = pblock->prev; nblock->next = pblock; pblock->prev = nblock; if (pblock == alloc->first) alloc->first = nblock; else nblock->prev->next = nblock; mutex_unlock(&alloc->memory_mutex); return NULL; } pblock = pblock->next; } nblock->next = NULL; if (alloc->last == NULL) { nblock->prev = NULL; alloc->first = alloc->last = nblock; } else { nblock->prev = alloc->last; alloc->last->next = nblock; alloc->last = nblock; } return nblock; }

Contributors

PersonTokensPropCommitsCommitProp
jaroslav kyselajaroslav kysela18593.43%120.00%
takashi iwaitakashi iwai105.05%120.00%
adrian bunkadrian bunk10.51%120.00%
ingo molnaringo molnar10.51%120.00%
al viroal viro10.51%120.00%
Total198100.00%5100.00%


int snd_gf1_mem_xfree(struct snd_gf1_mem * alloc, struct snd_gf1_mem_block * block) { if (block->share) { /* ok.. shared block */ block->share--; mutex_unlock(&alloc->memory_mutex); return 0; } if (alloc->first == block) { alloc->first = block->next; if (block->next) block->next->prev = NULL; } else { block->prev->next = block->next; if (block->next) block->next->prev = block->prev; } if (alloc->last == block) { alloc->last = block->prev; if (block->prev) block->prev->next = NULL; } else { block->next->prev = block->prev; if (block->prev) block->prev->next = block->next; } kfree(block->name); kfree(block); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
jaroslav kyselajaroslav kysela17297.18%133.33%
takashi iwaitakashi iwai42.26%133.33%
ingo molnaringo molnar10.56%133.33%
Total177100.00%3100.00%


static struct snd_gf1_mem_block *snd_gf1_mem_look(struct snd_gf1_mem * alloc, unsigned int address) { struct snd_gf1_mem_block *block; for (block = alloc->first; block; block = block->next) { if (block->ptr == address) { return block; } } return NULL; }

Contributors

PersonTokensPropCommitsCommitProp
jaroslav kyselajaroslav kysela4987.50%133.33%
takashi iwaitakashi iwai610.71%133.33%
adrian bunkadrian bunk11.79%133.33%
Total56100.00%3100.00%


static struct snd_gf1_mem_block *snd_gf1_mem_share(struct snd_gf1_mem * alloc, unsigned int *share_id) { struct snd_gf1_mem_block *block; if (!share_id[0] && !share_id[1] && !share_id[2] && !share_id[3]) return NULL; for (block = alloc->first; block; block = block->next) if (!memcmp(share_id, block->share_id, sizeof(block->share_id))) return block; return NULL; }

Contributors

PersonTokensPropCommitsCommitProp
jaroslav kyselajaroslav kysela8490.32%125.00%
takashi iwaitakashi iwai66.45%125.00%
julia lawalljulia lawall22.15%125.00%
adrian bunkadrian bunk11.08%125.00%
Total93100.00%4100.00%


static int snd_gf1_mem_find(struct snd_gf1_mem * alloc, struct snd_gf1_mem_block * block, unsigned int size, int w_16, int align) { struct snd_gf1_bank_info *info = w_16 ? alloc->banks_16 : alloc->banks_8; unsigned int idx, boundary; int size1; struct snd_gf1_mem_block *pblock; unsigned int ptr1, ptr2; if (w_16 && align < 2) align = 2; block->flags = w_16 ? SNDRV_GF1_MEM_BLOCK_16BIT : 0; block->owner = SNDRV_GF1_MEM_OWNER_DRIVER; block->share = 0; block->share_id[0] = block->share_id[1] = block->share_id[2] = block->share_id[3] = 0; block->name = NULL; block->prev = block->next = NULL; for (pblock = alloc->first, idx = 0; pblock; pblock = pblock->next) { while (pblock->ptr >= (boundary = info[idx].address + info[idx].size)) idx++; while (pblock->ptr + pblock->size >= (boundary = info[idx].address + info[idx].size)) idx++; ptr2 = boundary; if (pblock->next) { if (pblock->ptr + pblock->size == pblock->next->ptr) continue; if (pblock->next->ptr < boundary) ptr2 = pblock->next->ptr; } ptr1 = ALIGN(pblock->ptr + pblock->size, align); if (ptr1 >= ptr2) continue; size1 = ptr2 - ptr1; if ((int)size <= size1) { block->ptr = ptr1; block->size = size; return 0; } } while (++idx < 4) { if (size <= info[idx].size) { /* I assume that bank address is already aligned.. */ block->ptr = info[idx].address; block->size = size; return 0; } } return -ENOMEM; }

Contributors

PersonTokensPropCommitsCommitProp
jaroslav kyselajaroslav kysela35596.21%250.00%
takashi iwaitakashi iwai82.17%125.00%
clemens ladischclemens ladisch61.63%125.00%
Total369100.00%4100.00%


struct snd_gf1_mem_block *snd_gf1_mem_alloc(struct snd_gf1_mem * alloc, int owner, char *name, int size, int w_16, int align, unsigned int *share_id) { struct snd_gf1_mem_block block, *nblock; snd_gf1_mem_lock(alloc, 0); if (share_id != NULL) { nblock = snd_gf1_mem_share(alloc, share_id); if (nblock != NULL) { if (size != (int)nblock->size) { /* TODO: remove in the future */ snd_printk(KERN_ERR "snd_gf1_mem_alloc - share: sizes differ\n"); goto __std; } nblock->share++; snd_gf1_mem_lock(alloc, 1); return NULL; } } __std: if (snd_gf1_mem_find(alloc, &block, size, w_16, align) < 0) { snd_gf1_mem_lock(alloc, 1); return NULL; } if (share_id != NULL) memcpy(&block.share_id, share_id, sizeof(block.share_id)); block.owner = owner; block.name = kstrdup(name, GFP_KERNEL); nblock = snd_gf1_mem_xalloc(alloc, &block); snd_gf1_mem_lock(alloc, 1); return nblock; }

Contributors

PersonTokensPropCommitsCommitProp
jaroslav kyselajaroslav kysela19496.04%240.00%
takashi iwaitakashi iwai73.47%240.00%
paulo marquespaulo marques10.50%120.00%
Total202100.00%5100.00%


int snd_gf1_mem_free(struct snd_gf1_mem * alloc, unsigned int address) { int result; struct snd_gf1_mem_block *block; snd_gf1_mem_lock(alloc, 0); if ((block = snd_gf1_mem_look(alloc, address)) != NULL) { result = snd_gf1_mem_xfree(alloc, block); snd_gf1_mem_lock(alloc, 1); return result; } snd_gf1_mem_lock(alloc, 1); return -EINVAL; }

Contributors

PersonTokensPropCommitsCommitProp
jaroslav kyselajaroslav kysela7294.74%150.00%
takashi iwaitakashi iwai45.26%150.00%
Total76100.00%2100.00%


int snd_gf1_mem_init(struct snd_gus_card * gus) { struct snd_gf1_mem *alloc; struct snd_gf1_mem_block block; #ifdef CONFIG_SND_DEBUG struct snd_info_entry *entry; #endif alloc = &gus->gf1.mem_alloc; mutex_init(&alloc->memory_mutex); alloc->first = alloc->last = NULL; if (!gus->gf1.memory) return 0; memset(&block, 0, sizeof(block)); block.owner = SNDRV_GF1_MEM_OWNER_DRIVER; if (gus->gf1.enh_mode) { block.ptr = 0; block.size = 1024; block.name = kstrdup("InterWave LFOs", GFP_KERNEL); if (snd_gf1_mem_xalloc(alloc, &block) == NULL) return -ENOMEM; } block.ptr = gus->gf1.default_voice_address; block.size = 4; block.name = kstrdup("Voice default (NULL's)", GFP_KERNEL); if (snd_gf1_mem_xalloc(alloc, &block) == NULL) return -ENOMEM; #ifdef CONFIG_SND_DEBUG if (! snd_card_proc_new(gus->card, "gusmem", &entry)) snd_info_set_text_ops(entry, gus, snd_gf1_mem_info_read); #endif return 0; }

Contributors

PersonTokensPropCommitsCommitProp
jaroslav kyselajaroslav kysela20094.79%240.00%
takashi iwaitakashi iwai83.79%120.00%
paulo marquespaulo marques20.95%120.00%
ingo molnaringo molnar10.47%120.00%
Total211100.00%5100.00%


int snd_gf1_mem_done(struct snd_gus_card * gus) { struct snd_gf1_mem *alloc; struct snd_gf1_mem_block *block, *nblock; alloc = &gus->gf1.mem_alloc; block = alloc->first; while (block) { nblock = block->next; snd_gf1_mem_xfree(alloc, block); block = nblock; } return 0; }

Contributors

PersonTokensPropCommitsCommitProp
jaroslav kyselajaroslav kysela5890.62%150.00%
takashi iwaitakashi iwai69.38%150.00%
Total64100.00%2100.00%

#ifdef CONFIG_SND_DEBUG
static void snd_gf1_mem_info_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer) { struct snd_gus_card *gus; struct snd_gf1_mem *alloc; struct snd_gf1_mem_block *block; unsigned int total, used; int i; gus = entry->private_data; alloc = &gus->gf1.mem_alloc; mutex_lock(&alloc->memory_mutex); snd_iprintf(buffer, "8-bit banks : \n "); for (i = 0; i < 4; i++) snd_iprintf(buffer, "0x%06x (%04ik)%s", alloc->banks_8[i].address, alloc->banks_8[i].size >> 10, i + 1 < 4 ? "," : ""); snd_iprintf(buffer, "\n" "16-bit banks : \n "); for (i = total = 0; i < 4; i++) { snd_iprintf(buffer, "0x%06x (%04ik)%s", alloc->banks_16[i].address, alloc->banks_16[i].size >> 10, i + 1 < 4 ? "," : ""); total += alloc->banks_16[i].size; } snd_iprintf(buffer, "\n"); used = 0; for (block = alloc->first, i = 0; block; block = block->next, i++) { used += block->size; snd_iprintf(buffer, "Block %i at 0x%lx onboard 0x%x size %i (0x%x):\n", i, (long) block, block->ptr, block->size, block->size); if (block->share || block->share_id[0] || block->share_id[1] || block->share_id[2] || block->share_id[3]) snd_iprintf(buffer, " Share : %i [id0 0x%x] [id1 0x%x] [id2 0x%x] [id3 0x%x]\n", block->share, block->share_id[0], block->share_id[1], block->share_id[2], block->share_id[3]); snd_iprintf(buffer, " Flags :%s\n", block->flags & SNDRV_GF1_MEM_BLOCK_16BIT ? " 16-bit" : ""); snd_iprintf(buffer, " Owner : "); switch (block->owner) { case SNDRV_GF1_MEM_OWNER_DRIVER: snd_iprintf(buffer, "driver - %s\n", block->name); break; case SNDRV_GF1_MEM_OWNER_WAVE_SIMPLE: snd_iprintf(buffer, "SIMPLE wave\n"); break; case SNDRV_GF1_MEM_OWNER_WAVE_GF1: snd_iprintf(buffer, "GF1 wave\n"); break; case SNDRV_GF1_MEM_OWNER_WAVE_IWFFFF: snd_iprintf(buffer, "IWFFFF wave\n"); break; default: snd_iprintf(buffer, "unknown\n"); } } snd_iprintf(buffer, " Total: memory = %i, used = %i, free = %i\n", total, used, total - used); mutex_unlock(&alloc->memory_mutex); #if 0 ultra_iprintf(buffer, " Verify: free = %i, max 8-bit block = %i, max 16-bit block = %i\n", ultra_memory_free_size(card, &card->gf1.mem_alloc), ultra_memory_free_block(card, &card->gf1.mem_alloc, 0), ultra_memory_free_block(card, &card->gf1.mem_alloc, 1)); #endif }

Contributors

PersonTokensPropCommitsCommitProp
jaroslav kyselajaroslav kysela43997.34%250.00%
takashi iwaitakashi iwai102.22%125.00%
ingo molnaringo molnar20.44%125.00%
Total451100.00%4100.00%

#endif

Overall Contributors

PersonTokensPropCommitsCommitProp
jaroslav kyselajaroslav kysela187794.94%642.86%
takashi iwaitakashi iwai753.79%214.29%
ingo molnaringo molnar70.35%17.14%
paulo marquespaulo marques60.30%17.14%
clemens ladischclemens ladisch60.30%17.14%
adrian bunkadrian bunk30.15%17.14%
julia lawalljulia lawall20.10%17.14%
al viroal viro10.05%17.14%
Total1977100.00%14100.00%
Directory: sound/isa/gus
Information contained on this website is for historical information purposes only and does not indicate or represent copyright ownership.
{% endraw %}