diff options
Diffstat (limited to 'sound/synth/emux/soundfont.c')
| -rw-r--r-- | sound/synth/emux/soundfont.c | 320 |
1 files changed, 156 insertions, 164 deletions
diff --git a/sound/synth/emux/soundfont.c b/sound/synth/emux/soundfont.c index 31a4ea94830e..59f3b1b6df4a 100644 --- a/sound/synth/emux/soundfont.c +++ b/sound/synth/emux/soundfont.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0-or-later /* * Soundfont generic routines. * It is intended that these should be used by any driver that is willing @@ -5,20 +6,6 @@ * * Copyright (C) 1999 Steve Ratcliffe * Copyright (c) 1999-2000 Takashi Iwai <tiwai@suse.de> - * - * 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 */ /* * Deal with reading in of a soundfont. Code follows the OSS way @@ -51,7 +38,8 @@ static struct snd_sf_sample *sf_sample_new(struct snd_sf_list *sflist, static void sf_sample_delete(struct snd_sf_list *sflist, struct snd_soundfont *sf, struct snd_sf_sample *sp); static int load_map(struct snd_sf_list *sflist, const void __user *data, int count); -static int load_info(struct snd_sf_list *sflist, const void __user *data, long count); +static int load_info(struct snd_card *card, struct snd_sf_list *sflist, + const void __user *data, long count); static int remove_info(struct snd_sf_list *sflist, struct snd_soundfont *sf, int bank, int instr); static void init_voice_info(struct soundfont_voice_info *avp); @@ -73,47 +61,16 @@ static void snd_sf_init(struct snd_sf_list *sflist); static void snd_sf_clear(struct snd_sf_list *sflist); /* - * lock access to sflist - */ -static void -lock_preset(struct snd_sf_list *sflist) -{ - unsigned long flags; - mutex_lock(&sflist->presets_mutex); - spin_lock_irqsave(&sflist->lock, flags); - sflist->presets_locked = 1; - spin_unlock_irqrestore(&sflist->lock, flags); -} - - -/* - * remove lock - */ -static void -unlock_preset(struct snd_sf_list *sflist) -{ - unsigned long flags; - spin_lock_irqsave(&sflist->lock, flags); - sflist->presets_locked = 0; - spin_unlock_irqrestore(&sflist->lock, flags); - mutex_unlock(&sflist->presets_mutex); -} - - -/* * close the patch if the patch was opened by this client. */ int snd_soundfont_close_check(struct snd_sf_list *sflist, int client) { - unsigned long flags; - spin_lock_irqsave(&sflist->lock, flags); - if (sflist->open_client == client) { - spin_unlock_irqrestore(&sflist->lock, flags); - return close_patch(sflist); + scoped_guard(spinlock_irqsave, &sflist->lock) { + if (sflist->open_client != client) + return 0; } - spin_unlock_irqrestore(&sflist->lock, flags); - return 0; + return close_patch(sflist); } @@ -121,20 +78,20 @@ snd_soundfont_close_check(struct snd_sf_list *sflist, int client) * Deal with a soundfont patch. Any driver could use these routines * although it was designed for the AWE64. * - * The sample_write and callargs pararameters allow a callback into + * The sample_write and callargs parameters allow a callback into * the actual driver to write sample data to the board or whatever * it wants to do with it. */ int -snd_soundfont_load(struct snd_sf_list *sflist, const void __user *data, +snd_soundfont_load(struct snd_card *card, + struct snd_sf_list *sflist, const void __user *data, long count, int client) { struct soundfont_patch_info patch; - unsigned long flags; int rc; if (count < (long)sizeof(patch)) { - snd_printk(KERN_ERR "patch record too small %ld\n", count); + dev_err(card->dev, "patch record too small %ld\n", count); return -EINVAL; } if (copy_from_user(&patch, data, sizeof(patch))) @@ -144,40 +101,36 @@ snd_soundfont_load(struct snd_sf_list *sflist, const void __user *data, data += sizeof(patch); if (patch.key != SNDRV_OSS_SOUNDFONT_PATCH) { - snd_printk(KERN_ERR "The wrong kind of patch %x\n", patch.key); + dev_err(card->dev, "The wrong kind of patch %x\n", patch.key); return -EINVAL; } if (count < patch.len) { - snd_printk(KERN_ERR "Patch too short %ld, need %d\n", - count, patch.len); + dev_err(card->dev, "Patch too short %ld, need %d\n", + count, patch.len); return -EINVAL; } if (patch.len < 0) { - snd_printk(KERN_ERR "poor length %d\n", patch.len); + dev_err(card->dev, "poor length %d\n", patch.len); return -EINVAL; } if (patch.type == SNDRV_SFNT_OPEN_PATCH) { /* grab sflist to open */ - lock_preset(sflist); - rc = open_patch(sflist, data, count, client); - unlock_preset(sflist); - return rc; + guard(snd_soundfont_lock_preset)(sflist); + return open_patch(sflist, data, count, client); } /* check if other client already opened patch */ - spin_lock_irqsave(&sflist->lock, flags); - if (sflist->open_client != client) { - spin_unlock_irqrestore(&sflist->lock, flags); - return -EBUSY; + scoped_guard(spinlock_irqsave, &sflist->lock) { + if (sflist->open_client != client) + return -EBUSY; } - spin_unlock_irqrestore(&sflist->lock, flags); - lock_preset(sflist); + guard(snd_soundfont_lock_preset)(sflist); rc = -EINVAL; switch (patch.type) { case SNDRV_SFNT_LOAD_INFO: - rc = load_info(sflist, data, count); + rc = load_info(card, sflist, data, count); break; case SNDRV_SFNT_LOAD_DATA: rc = load_data(sflist, data, count); @@ -197,8 +150,8 @@ snd_soundfont_load(struct snd_sf_list *sflist, const void __user *data, case SNDRV_SFNT_REMOVE_INFO: /* patch must be opened */ if (!sflist->currsf) { - snd_printk(KERN_ERR "soundfont: remove_info: " - "patch not opened\n"); + dev_err(card->dev, + "soundfont: remove_info: patch not opened\n"); rc = -EINVAL; } else { int bank, instr; @@ -211,7 +164,6 @@ snd_soundfont_load(struct snd_sf_list *sflist, const void __user *data, } break; } - unlock_preset(sflist); return rc; } @@ -234,14 +186,11 @@ open_patch(struct snd_sf_list *sflist, const char __user *data, { struct soundfont_open_parm parm; struct snd_soundfont *sf; - unsigned long flags; - spin_lock_irqsave(&sflist->lock, flags); - if (sflist->open_client >= 0 || sflist->currsf) { - spin_unlock_irqrestore(&sflist->lock, flags); - return -EBUSY; + scoped_guard(spinlock_irqsave, &sflist->lock) { + if (sflist->open_client >= 0 || sflist->currsf) + return -EBUSY; } - spin_unlock_irqrestore(&sflist->lock, flags); if (copy_from_user(&parm, data, sizeof(parm))) return -EFAULT; @@ -255,10 +204,10 @@ open_patch(struct snd_sf_list *sflist, const char __user *data, return -ENOMEM; } - spin_lock_irqsave(&sflist->lock, flags); - sflist->open_client = client; - sflist->currsf = sf; - spin_unlock_irqrestore(&sflist->lock, flags); + scoped_guard(spinlock_irqsave, &sflist->lock) { + sflist->open_client = client; + sflist->currsf = sf; + } return 0; } @@ -316,12 +265,10 @@ is_identical_font(struct snd_soundfont *sf, int type, unsigned char *name) static int close_patch(struct snd_sf_list *sflist) { - unsigned long flags; - - spin_lock_irqsave(&sflist->lock, flags); - sflist->currsf = NULL; - sflist->open_client = -1; - spin_unlock_irqrestore(&sflist->lock, flags); + scoped_guard(spinlock_irqsave, &sflist->lock) { + sflist->currsf = NULL; + sflist->open_client = -1; + } rebuild_presets(sflist); @@ -362,7 +309,8 @@ sf_zone_new(struct snd_sf_list *sflist, struct snd_soundfont *sf) { struct snd_sf_zone *zp; - if ((zp = kzalloc(sizeof(*zp), GFP_KERNEL)) == NULL) + zp = kzalloc(sizeof(*zp), GFP_KERNEL); + if (!zp) return NULL; zp->next = sf->zones; sf->zones = zp; @@ -394,7 +342,8 @@ sf_sample_new(struct snd_sf_list *sflist, struct snd_soundfont *sf) { struct snd_sf_sample *sp; - if ((sp = kzalloc(sizeof(*sp), GFP_KERNEL)) == NULL) + sp = kzalloc(sizeof(*sp), GFP_KERNEL); + if (!sp) return NULL; sp->next = sf->samples; @@ -464,7 +413,8 @@ load_map(struct snd_sf_list *sflist, const void __user *data, int count) } /* create a new zone */ - if ((zp = sf_zone_new(sflist, sf)) == NULL) + zp = sf_zone_new(sflist, sf); + if (!zp) return -ENOMEM; zp->bank = map.map_bank; @@ -519,7 +469,8 @@ remove_info(struct snd_sf_list *sflist, struct snd_soundfont *sf, * open soundfont. */ static int -load_info(struct snd_sf_list *sflist, const void __user *data, long count) +load_info(struct snd_card *card, + struct snd_sf_list *sflist, const void __user *data, long count) { struct snd_soundfont *sf; struct snd_sf_zone *zone; @@ -527,14 +478,15 @@ load_info(struct snd_sf_list *sflist, const void __user *data, long count) int i; /* patch must be opened */ - if ((sf = sflist->currsf) == NULL) + sf = sflist->currsf; + if (!sf) return -EINVAL; if (is_special_type(sf->type)) return -EINVAL; if (count < (long)sizeof(hdr)) { - printk(KERN_ERR "Soundfont error: invalid patch zone length\n"); + dev_err(card->dev, "Soundfont error: invalid patch zone length\n"); return -EINVAL; } if (copy_from_user((char*)&hdr, data, sizeof(hdr))) @@ -544,15 +496,15 @@ load_info(struct snd_sf_list *sflist, const void __user *data, long count) count -= sizeof(hdr); if (hdr.nvoices <= 0 || hdr.nvoices >= 100) { - printk(KERN_ERR "Soundfont error: Illegal voice number %d\n", - hdr.nvoices); + dev_err(card->dev, "Soundfont error: Illegal voice number %d\n", + hdr.nvoices); return -EINVAL; } if (count < (long)sizeof(struct soundfont_voice_info) * hdr.nvoices) { - printk(KERN_ERR "Soundfont Error: " - "patch length(%ld) is smaller than nvoices(%d)\n", - count, hdr.nvoices); + dev_err(card->dev, + "Soundfont Error: patch length(%ld) is smaller than nvoices(%d)\n", + count, hdr.nvoices); return -EINVAL; } @@ -592,9 +544,9 @@ load_info(struct snd_sf_list *sflist, const void __user *data, long count) init_voice_parm(&tmpzone.v.parm); /* create a new zone */ - if ((zone = sf_zone_new(sflist, sf)) == NULL) { + zone = sf_zone_new(sflist, sf); + if (!zone) return -ENOMEM; - } /* copy the temporary data */ zone->bank = tmpzone.bank; @@ -698,6 +650,21 @@ find_sample(struct snd_soundfont *sf, int sample_id) } +static int +validate_sample_info(struct soundfont_sample_info *si) +{ + if (si->end < 0 || si->end > si->size) + return -EINVAL; + if (si->loopstart < 0 || si->loopstart > si->end) + return -EINVAL; + if (si->loopend < 0 || si->loopend > si->end) + return -EINVAL; + /* be sure loop points start < end */ + if (si->loopstart > si->loopend) + swap(si->loopstart, si->loopend); + return 0; +} + /* * Load sample information, this can include data to be loaded onto * the soundcard. It can also just be a pointer into soundcard ROM. @@ -710,21 +677,25 @@ load_data(struct snd_sf_list *sflist, const void __user *data, long count) struct snd_soundfont *sf; struct soundfont_sample_info sample_info; struct snd_sf_sample *sp; - long off; /* patch must be opened */ - if ((sf = sflist->currsf) == NULL) + sf = sflist->currsf; + if (!sf) return -EINVAL; if (is_special_type(sf->type)) return -EINVAL; + if (count < (long)sizeof(sample_info)) { + return -EINVAL; + } if (copy_from_user(&sample_info, data, sizeof(sample_info))) return -EFAULT; + data += sizeof(sample_info); + count -= sizeof(sample_info); - off = sizeof(sample_info); - - if (sample_info.size != (count-off)/2) + // SoundFont uses S16LE samples. + if (sample_info.size * 2 != count) return -EINVAL; /* Check for dup */ @@ -735,14 +706,30 @@ load_data(struct snd_sf_list *sflist, const void __user *data, long count) return -EINVAL; } + if (sample_info.size > 0) { + if (sample_info.start < 0) + return -EINVAL; + + // Here we "rebase out" the start address, because the + // real start is the start of the provided sample data. + sample_info.end -= sample_info.start; + sample_info.loopstart -= sample_info.start; + sample_info.loopend -= sample_info.start; + sample_info.start = 0; + + if (validate_sample_info(&sample_info) < 0) + return -EINVAL; + } + /* Allocate a new sample structure */ - if ((sp = sf_sample_new(sflist, sf)) == NULL) + sp = sf_sample_new(sflist, sf); + if (!sp) return -ENOMEM; sp->v = sample_info; sp->v.sf_id = sf->id; sp->v.dummy = 0; - sp->v.truesize = sp->v.size; + sp->v.truesize = 0; /* * If there is wave data then load it. @@ -751,7 +738,7 @@ load_data(struct snd_sf_list *sflist, const void __user *data, long count) int rc; rc = sflist->callback.sample_new (sflist->callback.private_data, sp, sflist->memhdr, - data + off, count - off); + data, count); if (rc < 0) { sf_sample_delete(sflist, sf, sp); return rc; @@ -764,7 +751,7 @@ load_data(struct snd_sf_list *sflist, const void __user *data, long count) /* log2_tbl[i] = log2(i+128) * 0x10000 */ -static int log_tbl[129] = { +static const int log_tbl[129] = { 0x70000, 0x702df, 0x705b9, 0x7088e, 0x70b5d, 0x70e26, 0x710eb, 0x713aa, 0x71663, 0x71918, 0x71bc8, 0x71e72, 0x72118, 0x723b9, 0x72655, 0x728ed, 0x72b80, 0x72e0e, 0x73098, 0x7331d, 0x7359e, 0x7381b, 0x73a93, 0x73d08, @@ -806,7 +793,7 @@ snd_sf_linear_to_log(unsigned int amount, int offset, int ratio) amount <<= 1; s = (amount >> 24) & 0x7f; low = (amount >> 16) & 0xff; - /* linear approxmimation by lower 8 bit */ + /* linear approximation by lower 8 bit */ v = (log_tbl[s + 1] * low + log_tbl[s] * (0x100 - low)) >> 8; v -= offset; v = (v * ratio) >> 16; @@ -856,6 +843,8 @@ calc_gus_envelope_time(int rate, int start, int end) int r, p, t; r = (3 - ((rate >> 6) & 3)) * 3; p = rate & 0x3f; + if (!p) + p = 1; t = end - start; if (t < 0) t = -t; if (13 > r) @@ -868,7 +857,7 @@ calc_gus_envelope_time(int rate, int start, int end) /* convert envelope time parameter to soundfont parameters */ /* attack & decay/release time table (msec) */ -static short attack_time_tbl[128] = { +static const short attack_time_tbl[128] = { 32767, 32767, 5989, 4235, 2994, 2518, 2117, 1780, 1497, 1373, 1259, 1154, 1058, 970, 890, 816, 707, 691, 662, 634, 607, 581, 557, 533, 510, 489, 468, 448, 429, 411, 393, 377, 361, 345, 331, 317, 303, 290, 278, 266, 255, 244, 234, 224, 214, 205, 196, 188, @@ -879,7 +868,7 @@ static short attack_time_tbl[128] = { 11, 11, 10, 10, 10, 9, 9, 8, 8, 8, 8, 7, 7, 7, 6, 0, }; -static short decay_time_tbl[128] = { +static const short decay_time_tbl[128] = { 32767, 32767, 22614, 15990, 11307, 9508, 7995, 6723, 5653, 5184, 4754, 4359, 3997, 3665, 3361, 3082, 2828, 2765, 2648, 2535, 2428, 2325, 2226, 2132, 2042, 1955, 1872, 1793, 1717, 1644, 1574, 1507, 1443, 1382, 1324, 1267, 1214, 1162, 1113, 1066, 978, 936, 897, 859, 822, 787, 754, 722, @@ -902,7 +891,7 @@ snd_sf_calc_parm_hold(int msec) /* search an index for specified time from given time table */ static int -calc_parm_search(int msec, short *table) +calc_parm_search(int msec, const short *table) { int left = 1, right = 127, mid; while (left < right) { @@ -946,8 +935,8 @@ int snd_sf_vol_table[128] = { /* load GUS patch */ static int -load_guspatch(struct snd_sf_list *sflist, const char __user *data, - long count, int client) +load_guspatch(struct snd_card *card, + struct snd_sf_list *sflist, const char __user *data, long count) { struct patch_info patch; struct snd_soundfont *sf; @@ -957,19 +946,22 @@ load_guspatch(struct snd_sf_list *sflist, const char __user *data, int rc; if (count < (long)sizeof(patch)) { - snd_printk(KERN_ERR "patch record too small %ld\n", count); + dev_err(card->dev, "patch record too small %ld\n", count); return -EINVAL; } if (copy_from_user(&patch, data, sizeof(patch))) return -EFAULT; - count -= sizeof(patch); data += sizeof(patch); + if ((patch.len << (patch.mode & WAVE_16_BITS ? 1 : 0)) != count) + return -EINVAL; + sf = newsf(sflist, SNDRV_SFNT_PAT_TYPE_GUS|SNDRV_SFNT_PAT_SHARED, NULL); if (sf == NULL) return -ENOMEM; - if ((smp = sf_sample_new(sflist, sf)) == NULL) + smp = sf_sample_new(sflist, sf); + if (!smp) return -ENOMEM; sample_id = sflist->sample_counter; smp->v.sample = sample_id; @@ -979,6 +971,11 @@ load_guspatch(struct snd_sf_list *sflist, const char __user *data, smp->v.loopend = patch.loop_end; smp->v.size = patch.len; + if (validate_sample_info(&smp->v) < 0) { + sf_sample_delete(sflist, sf, smp); + return -EINVAL; + } + /* set up mode flags */ smp->v.mode_flags = 0; if (!(patch.mode & WAVE_16_BITS)) @@ -1007,7 +1004,8 @@ load_guspatch(struct snd_sf_list *sflist, const char __user *data, smp->v.sf_id = sf->id; /* set up voice info */ - if ((zone = sf_zone_new(sflist, sf)) == NULL) { + zone = sf_zone_new(sflist, sf); + if (!zone) { sf_sample_delete(sflist, sf, smp); return -ENOMEM; } @@ -1015,7 +1013,7 @@ load_guspatch(struct snd_sf_list *sflist, const char __user *data, /* * load wave data */ - if (sflist->callback.sample_new) { + if (smp->v.size > 0) { rc = sflist->callback.sample_new (sflist->callback.private_data, smp, sflist->memhdr, data, count); @@ -1040,10 +1038,10 @@ load_guspatch(struct snd_sf_list *sflist, const char __user *data, /* panning position; -128 - 127 => 0-127 */ zone->v.pan = (patch.panning + 128) / 2; #if 0 - snd_printk(KERN_DEBUG - "gus: basefrq=%d (ofs=%d) root=%d,tune=%d, range:%d-%d\n", - (int)patch.base_freq, zone->v.rate_offset, - zone->v.root, zone->v.tune, zone->v.low, zone->v.high); + pr_debug( + "gus: basefrq=%d (ofs=%d) root=%d,tune=%d, range:%d-%d\n", + (int)patch.base_freq, zone->v.rate_offset, + zone->v.root, zone->v.tune, zone->v.low, zone->v.high); #endif /* detuning is ignored */ @@ -1075,12 +1073,12 @@ load_guspatch(struct snd_sf_list *sflist, const char __user *data, zone->v.parm.volrelease = 0x8000 | snd_sf_calc_parm_decay(release); zone->v.attenuation = calc_gus_attenuation(patch.env_offset[0]); #if 0 - snd_printk(KERN_DEBUG - "gus: atkhld=%x, dcysus=%x, volrel=%x, att=%d\n", - zone->v.parm.volatkhld, - zone->v.parm.voldcysus, - zone->v.parm.volrelease, - zone->v.attenuation); + dev_dbg(card->dev, + "gus: atkhld=%x, dcysus=%x, volrel=%x, att=%d\n", + zone->v.parm.volatkhld, + zone->v.parm.voldcysus, + zone->v.parm.volrelease, + zone->v.attenuation); #endif } @@ -1124,14 +1122,12 @@ load_guspatch(struct snd_sf_list *sflist, const char __user *data, /* load GUS patch */ int -snd_soundfont_load_guspatch(struct snd_sf_list *sflist, const char __user *data, - long count, int client) +snd_soundfont_load_guspatch(struct snd_card *card, + struct snd_sf_list *sflist, const char __user *data, + long count) { - int rc; - lock_preset(sflist); - rc = load_guspatch(sflist, data, count, client); - unlock_preset(sflist); - return rc; + guard(snd_soundfont_lock_preset)(sflist); + return load_guspatch(card, sflist, data, count); } @@ -1192,7 +1188,8 @@ add_preset(struct snd_sf_list *sflist, struct snd_sf_zone *cur) } /* prepend this zone */ - if ((index = get_index(cur->bank, cur->instr, cur->v.low)) < 0) + index = get_index(cur->bank, cur->instr, cur->v.low); + if (index < 0) return; cur->next_zone = zone; /* zone link */ cur->next_instr = sflist->presets[index]; /* preset table link */ @@ -1208,7 +1205,8 @@ delete_preset(struct snd_sf_list *sflist, struct snd_sf_zone *zp) int index; struct snd_sf_zone *p; - if ((index = get_index(zp->bank, zp->instr, zp->v.low)) < 0) + index = get_index(zp->bank, zp->instr, zp->v.low); + if (index < 0) return; for (p = sflist->presets[index]; p; p = p->next_instr) { while (p->next_instr == zp) { @@ -1235,17 +1233,14 @@ snd_soundfont_search_zone(struct snd_sf_list *sflist, int *notep, int vel, struct snd_sf_zone **table, int max_layers) { int nvoices; - unsigned long flags; /* this function is supposed to be called atomically, * so we check the lock. if it's busy, just returns 0 to * tell the caller the busy state */ - spin_lock_irqsave(&sflist->lock, flags); - if (sflist->presets_locked) { - spin_unlock_irqrestore(&sflist->lock, flags); + guard(spinlock_irqsave)(&sflist->lock); + if (sflist->presets_locked) return 0; - } nvoices = search_zones(sflist, notep, vel, preset, bank, table, max_layers, 0); if (! nvoices) { @@ -1254,7 +1249,6 @@ snd_soundfont_search_zone(struct snd_sf_list *sflist, int *notep, int vel, def_preset, def_bank, table, max_layers, 0); } - spin_unlock_irqrestore(&sflist->lock, flags); return nvoices; } @@ -1268,7 +1262,8 @@ search_first_zone(struct snd_sf_list *sflist, int bank, int preset, int key) int index; struct snd_sf_zone *zp; - if ((index = get_index(bank, preset, key)) < 0) + index = get_index(bank, preset, key); + if (index < 0) return NULL; for (zp = sflist->presets[index]; zp; zp = zp->next_instr) { if (zp->instr == preset && zp->bank == bank) @@ -1377,9 +1372,8 @@ snd_sf_clear(struct snd_sf_list *sflist) } for (sp = sf->samples; sp; sp = nextsp) { nextsp = sp->next; - if (sflist->callback.sample_free) - sflist->callback.sample_free(sflist->callback.private_data, - sp, sflist->memhdr); + sflist->callback.sample_free(sflist->callback.private_data, + sp, sflist->memhdr); kfree(sp); } kfree(sf); @@ -1397,7 +1391,8 @@ snd_sf_new(struct snd_sf_callback *callback, struct snd_util_memhdr *hdr) { struct snd_sf_list *sflist; - if ((sflist = kzalloc(sizeof(*sflist), GFP_KERNEL)) == NULL) + sflist = kzalloc(sizeof(*sflist), GFP_KERNEL); + if (!sflist) return NULL; mutex_init(&sflist->presets_mutex); @@ -1421,27 +1416,26 @@ snd_sf_free(struct snd_sf_list *sflist) if (sflist == NULL) return; - lock_preset(sflist); - if (sflist->callback.sample_reset) - sflist->callback.sample_reset(sflist->callback.private_data); - snd_sf_clear(sflist); - unlock_preset(sflist); + scoped_guard(snd_soundfont_lock_preset, sflist) { + if (sflist->callback.sample_reset) + sflist->callback.sample_reset(sflist->callback.private_data); + snd_sf_clear(sflist); + } kfree(sflist); } /* * Remove all samples - * The soundcard should be silet before calling this function. + * The soundcard should be silent before calling this function. */ int snd_soundfont_remove_samples(struct snd_sf_list *sflist) { - lock_preset(sflist); + guard(snd_soundfont_lock_preset)(sflist); if (sflist->callback.sample_reset) sflist->callback.sample_reset(sflist->callback.private_data); snd_sf_clear(sflist); - unlock_preset(sflist); return 0; } @@ -1457,7 +1451,7 @@ snd_soundfont_remove_unlocked(struct snd_sf_list *sflist) struct snd_sf_zone *zp, *nextzp; struct snd_sf_sample *sp, *nextsp; - lock_preset(sflist); + guard(snd_soundfont_lock_preset)(sflist); if (sflist->callback.sample_reset) sflist->callback.sample_reset(sflist->callback.private_data); @@ -1480,9 +1474,8 @@ snd_soundfont_remove_unlocked(struct snd_sf_list *sflist) nextsp = sp->next; sf->samples = nextsp; sflist->mem_used -= sp->v.truesize; - if (sflist->callback.sample_free) - sflist->callback.sample_free(sflist->callback.private_data, - sp, sflist->memhdr); + sflist->callback.sample_free(sflist->callback.private_data, + sp, sflist->memhdr); kfree(sp); } } @@ -1492,6 +1485,5 @@ snd_soundfont_remove_unlocked(struct snd_sf_list *sflist) rebuild_presets(sflist); - unlock_preset(sflist); return 0; } |
