Blame view
sound/core/init.c
25.8 KB
1a59d1b8e treewide: Replace... |
1 |
// SPDX-License-Identifier: GPL-2.0-or-later |
1da177e4c Linux-2.6.12-rc2 |
2 3 |
/* * Initialization routines |
c1017a4cd [ALSA] Changed Ja... |
4 |
* Copyright (c) by Jaroslav Kysela <perex@perex.cz> |
1da177e4c Linux-2.6.12-rc2 |
5 |
*/ |
1da177e4c Linux-2.6.12-rc2 |
6 7 |
#include <linux/init.h> #include <linux/sched.h> |
da155d5b4 sound: Add module... |
8 |
#include <linux/module.h> |
51990e825 device.h: cleanup... |
9 |
#include <linux/device.h> |
1da177e4c Linux-2.6.12-rc2 |
10 11 12 13 |
#include <linux/file.h> #include <linux/slab.h> #include <linux/time.h> #include <linux/ctype.h> |
1da177e4c Linux-2.6.12-rc2 |
14 |
#include <linux/pm.h> |
f24640648 ALSA: Use standar... |
15 |
#include <linux/completion.h> |
d052d1bef Create platform_d... |
16 |
|
1da177e4c Linux-2.6.12-rc2 |
17 18 19 |
#include <sound/core.h> #include <sound/control.h> #include <sound/info.h> |
82a783f4b ALSA: Remove stru... |
20 21 22 23 24 25 26 |
/* monitor files for graceful shutdown (hotplug) */ struct snd_monitor_file { struct file *file; const struct file_operations *disconnected_f_op; struct list_head shutdown_list; /* still need to shutdown */ struct list_head list; /* link of monitor files */ }; |
a9edfc602 [ALSA] Handle fil... |
27 28 |
static DEFINE_SPINLOCK(shutdown_lock); static LIST_HEAD(shutdown_files); |
9c2e08c59 [PATCH] mark stru... |
29 |
static const struct file_operations snd_shutdown_f_ops; |
1da177e4c Linux-2.6.12-rc2 |
30 |
|
7bb2491b3 ALSA: Add kconfig... |
31 32 |
/* locked for registering/using */ static DECLARE_BITMAP(snd_cards_lock, SNDRV_CARDS); |
f4fa96895 ALSA: core: Don't... |
33 |
static struct snd_card *snd_cards[SNDRV_CARDS]; |
c0d3fb39e [ALSA] Clean up E... |
34 |
|
746df9489 [ALSA] Fix rwlock... |
35 |
static DEFINE_MUTEX(snd_card_mutex); |
1da177e4c Linux-2.6.12-rc2 |
36 |
|
304cd07f9 [ALSA] Introduce ... |
37 38 39 |
static char *slots[SNDRV_CARDS]; module_param_array(slots, charp, NULL, 0444); MODULE_PARM_DESC(slots, "Module names assigned to the slots."); |
a93bbaa77 [ALSA] Improve th... |
40 |
/* return non-zero if the given index is reserved for the given |
304cd07f9 [ALSA] Introduce ... |
41 42 |
* module via slots option */ |
a93bbaa77 [ALSA] Improve th... |
43 |
static int module_slot_match(struct module *module, int idx) |
304cd07f9 [ALSA] Introduce ... |
44 |
{ |
a93bbaa77 [ALSA] Improve th... |
45 |
int match = 1; |
304cd07f9 [ALSA] Introduce ... |
46 |
#ifdef MODULE |
a93bbaa77 [ALSA] Improve th... |
47 |
const char *s1, *s2; |
60f6fef87 ALSA: Optimize mo... |
48 |
if (!module || !*module->name || !slots[idx]) |
304cd07f9 [ALSA] Introduce ... |
49 |
return 0; |
a93bbaa77 [ALSA] Improve th... |
50 51 52 53 54 55 56 |
s1 = module->name; s2 = slots[idx]; if (*s2 == '!') { match = 0; /* negative match */ s2++; } |
304cd07f9 [ALSA] Introduce ... |
57 58 59 60 61 62 63 64 65 66 67 |
/* compare module name strings * hyphens are handled as equivalent with underscore */ for (;;) { char c1 = *s1++; char c2 = *s2++; if (c1 == '-') c1 = '_'; if (c2 == '-') c2 = '_'; if (c1 != c2) |
a93bbaa77 [ALSA] Improve th... |
68 |
return !match; |
304cd07f9 [ALSA] Introduce ... |
69 70 71 |
if (!c1) break; } |
a93bbaa77 [ALSA] Improve th... |
72 73 |
#endif /* MODULE */ return match; |
304cd07f9 [ALSA] Introduce ... |
74 |
} |
8eeaa2f9e ALSA: Replace wit... |
75 |
#if IS_ENABLED(CONFIG_SND_MIXER_OSS) |
512bbd6a8 [ALSA] Remove xxx... |
76 |
int (*snd_mixer_oss_notify_callback)(struct snd_card *card, int free_flag); |
c0d3fb39e [ALSA] Clean up E... |
77 |
EXPORT_SYMBOL(snd_mixer_oss_notify_callback); |
1da177e4c Linux-2.6.12-rc2 |
78 |
#endif |
deb6596f1 ALSA: Refactor sl... |
79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 |
static int check_empty_slot(struct module *module, int slot) { return !slots[slot] || !*slots[slot]; } /* return an empty slot number (>= 0) found in the given bitmask @mask. * @mask == -1 == 0xffffffff means: take any free slot up to 32 * when no slot is available, return the original @mask as is. */ static int get_slot_from_bitmask(int mask, int (*check)(struct module *, int), struct module *module) { int slot; for (slot = 0; slot < SNDRV_CARDS; slot++) { if (slot < 32 && !(mask & (1U << slot))) continue; if (!test_bit(slot, snd_cards_lock)) { if (check(module, slot)) return slot; /* found */ } } return mask; /* unchanged */ } |
4b440be66 ALSA: Add a helpe... |
103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 |
/* the default release callback set in snd_device_initialize() below; * this is just NOP for now, as almost all jobs are already done in * dev_free callback of snd_device chain instead. */ static void default_release(struct device *dev) { } /** * snd_device_initialize - Initialize struct device for sound devices * @dev: device to initialize * @card: card to assign, optional */ void snd_device_initialize(struct device *dev, struct snd_card *card) { device_initialize(dev); if (card) dev->parent = &card->card_dev; dev->class = sound_class; dev->release = default_release; } EXPORT_SYMBOL_GPL(snd_device_initialize); |
8bfb181c1 ALSA: Embed card ... |
125 |
static int snd_card_do_free(struct snd_card *card); |
6bbc7fed8 ALSA: Add a helpe... |
126 |
static const struct attribute_group card_dev_attr_group; |
8bfb181c1 ALSA: Embed card ... |
127 128 129 130 131 |
static void release_card_device(struct device *dev) { snd_card_do_free(dev_to_snd_card(dev)); } |
1da177e4c Linux-2.6.12-rc2 |
132 |
/** |
393aa9c1c ALSA: Mandate to ... |
133 134 |
* snd_card_new - create and initialize a soundcard structure * @parent: the parent device object |
1da177e4c Linux-2.6.12-rc2 |
135 136 137 138 |
* @idx: card index (address) [0 ... (SNDRV_CARDS-1)] * @xid: card identification (ASCII string) * @module: top level module for locking * @extra_size: allocate this extra size after the main soundcard structure |
53fb1e635 ALSA: Introduce s... |
139 |
* @card_ret: the pointer to store the created card instance |
1da177e4c Linux-2.6.12-rc2 |
140 141 142 |
* * Creates and initializes a soundcard structure. * |
53fb1e635 ALSA: Introduce s... |
143 144 145 146 |
* The function allocates snd_card instance via kzalloc with the given * space for the driver to use freely. The allocated struct is stored * in the given card_ret pointer. * |
eb7c06e8e ALSA: add/change ... |
147 |
* Return: Zero if successful or a negative error code. |
1da177e4c Linux-2.6.12-rc2 |
148 |
*/ |
393aa9c1c ALSA: Mandate to ... |
149 |
int snd_card_new(struct device *parent, int idx, const char *xid, |
53fb1e635 ALSA: Introduce s... |
150 151 |
struct module *module, int extra_size, struct snd_card **card_ret) |
1da177e4c Linux-2.6.12-rc2 |
152 |
{ |
512bbd6a8 [ALSA] Remove xxx... |
153 |
struct snd_card *card; |
deb6596f1 ALSA: Refactor sl... |
154 |
int err; |
1da177e4c Linux-2.6.12-rc2 |
155 |
|
53fb1e635 ALSA: Introduce s... |
156 157 158 |
if (snd_BUG_ON(!card_ret)) return -EINVAL; *card_ret = NULL; |
1da177e4c Linux-2.6.12-rc2 |
159 160 |
if (extra_size < 0) extra_size = 0; |
ca2c09665 [ALSA] Replace wi... |
161 |
card = kzalloc(sizeof(*card) + extra_size, GFP_KERNEL); |
53fb1e635 ALSA: Introduce s... |
162 163 |
if (!card) return -ENOMEM; |
8bfb181c1 ALSA: Embed card ... |
164 165 |
if (extra_size > 0) card->private_data = (char *)card + sizeof(struct snd_card); |
10a8ebbb0 ALSA: Core - add ... |
166 |
if (xid) |
5fdc18d93 ALSA: Core - clea... |
167 |
strlcpy(card->id, xid, sizeof(card->id)); |
1da177e4c Linux-2.6.12-rc2 |
168 |
err = 0; |
746df9489 [ALSA] Fix rwlock... |
169 |
mutex_lock(&snd_card_mutex); |
deb6596f1 ALSA: Refactor sl... |
170 171 172 173 |
if (idx < 0) /* first check the matching module-name slot */ idx = get_slot_from_bitmask(idx, module_slot_match, module); if (idx < 0) /* if not matched, assign an empty slot */ idx = get_slot_from_bitmask(idx, check_empty_slot, module); |
a93bbaa77 [ALSA] Improve th... |
174 175 176 |
if (idx < 0) err = -ENODEV; else if (idx < snd_ecards_limit) { |
7bb2491b3 ALSA: Add kconfig... |
177 |
if (test_bit(idx, snd_cards_lock)) |
a93bbaa77 [ALSA] Improve th... |
178 179 180 181 |
err = -EBUSY; /* invalid */ } else if (idx >= SNDRV_CARDS) err = -ENODEV; if (err < 0) { |
746df9489 [ALSA] Fix rwlock... |
182 |
mutex_unlock(&snd_card_mutex); |
f2f9307a4 ALSA: core: Use s... |
183 184 |
dev_err(parent, "cannot find the slot for index %d (range 0-%i), error: %d ", |
5c33dd70b [ALSA] cleanup an... |
185 |
idx, snd_ecards_limit - 1, err); |
8bfb181c1 ALSA: Embed card ... |
186 187 |
kfree(card); return err; |
1da177e4c Linux-2.6.12-rc2 |
188 |
} |
7bb2491b3 ALSA: Add kconfig... |
189 |
set_bit(idx, snd_cards_lock); /* lock it */ |
a93bbaa77 [ALSA] Improve th... |
190 191 |
if (idx >= snd_ecards_limit) snd_ecards_limit = idx + 1; /* increase the limit */ |
746df9489 [ALSA] Fix rwlock... |
192 |
mutex_unlock(&snd_card_mutex); |
393aa9c1c ALSA: Mandate to ... |
193 |
card->dev = parent; |
1da177e4c Linux-2.6.12-rc2 |
194 |
card->number = idx; |
81033c6b5 ALSA: core: Warn ... |
195 196 |
#ifdef MODULE WARN_ON(!module); |
1da177e4c Linux-2.6.12-rc2 |
197 |
card->module = module; |
81033c6b5 ALSA: core: Warn ... |
198 |
#endif |
1da177e4c Linux-2.6.12-rc2 |
199 200 201 202 203 204 |
INIT_LIST_HEAD(&card->devices); init_rwsem(&card->controls_rwsem); rwlock_init(&card->ctl_files_rwlock); INIT_LIST_HEAD(&card->controls); INIT_LIST_HEAD(&card->ctl_files); spin_lock_init(&card->files_lock); |
118dd6bfe ALSA: Clean up sn... |
205 |
INIT_LIST_HEAD(&card->files_list); |
d4cfb30fc ALSA: pcm: Set pe... |
206 |
mutex_init(&card->memory_mutex); |
1da177e4c Linux-2.6.12-rc2 |
207 |
#ifdef CONFIG_PM |
1da177e4c Linux-2.6.12-rc2 |
208 209 |
init_waitqueue_head(&card->power_sleep); #endif |
c44027c89 ALSA: add snd_car... |
210 |
init_waitqueue_head(&card->remove_sleep); |
fabb26dcd ALSA: pcm: Add ca... |
211 |
card->sync_irq = -1; |
8bfb181c1 ALSA: Embed card ... |
212 213 214 215 216 |
device_initialize(&card->card_dev); card->card_dev.parent = parent; card->card_dev.class = sound_class; card->card_dev.release = release_card_device; |
6bbc7fed8 ALSA: Add a helpe... |
217 218 |
card->card_dev.groups = card->dev_groups; card->dev_groups[0] = &card_dev_attr_group; |
8bfb181c1 ALSA: Embed card ... |
219 220 221 |
err = kobject_set_name(&card->card_dev.kobj, "card%d", idx); if (err < 0) goto __error; |
de65360be ALSA: hda_intel: ... |
222 223 |
snprintf(card->irq_descr, sizeof(card->irq_descr), "%s:%s", dev_driver_string(card->dev), dev_name(&card->card_dev)); |
1da177e4c Linux-2.6.12-rc2 |
224 225 |
/* the control interface cannot be accessed from the user space until */ /* snd_cards_bitmask and snd_cards are set with snd_card_register */ |
53fb1e635 ALSA: Introduce s... |
226 227 |
err = snd_ctl_create(card); if (err < 0) { |
f2f9307a4 ALSA: core: Use s... |
228 229 |
dev_err(parent, "unable to register control minors "); |
1da177e4c Linux-2.6.12-rc2 |
230 231 |
goto __error; } |
53fb1e635 ALSA: Introduce s... |
232 233 |
err = snd_info_card_create(card); if (err < 0) { |
f2f9307a4 ALSA: core: Use s... |
234 235 |
dev_err(parent, "unable to create card info "); |
1da177e4c Linux-2.6.12-rc2 |
236 237 |
goto __error_ctl; } |
53fb1e635 ALSA: Introduce s... |
238 239 |
*card_ret = card; return 0; |
1da177e4c Linux-2.6.12-rc2 |
240 241 |
__error_ctl: |
289ca025e ALSA: Use priorit... |
242 |
snd_device_free_all(card); |
1da177e4c Linux-2.6.12-rc2 |
243 |
__error: |
8bfb181c1 ALSA: Embed card ... |
244 |
put_device(&card->card_dev); |
53fb1e635 ALSA: Introduce s... |
245 |
return err; |
1da177e4c Linux-2.6.12-rc2 |
246 |
} |
393aa9c1c ALSA: Mandate to ... |
247 |
EXPORT_SYMBOL(snd_card_new); |
c0d3fb39e [ALSA] Clean up E... |
248 |
|
f4fa96895 ALSA: core: Don't... |
249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 |
/** * snd_card_ref - Get the card object from the index * @idx: the card index * * Returns a card object corresponding to the given index or NULL if not found. * Release the object via snd_card_unref(). */ struct snd_card *snd_card_ref(int idx) { struct snd_card *card; mutex_lock(&snd_card_mutex); card = snd_cards[idx]; if (card) get_device(&card->card_dev); mutex_unlock(&snd_card_mutex); return card; } EXPORT_SYMBOL_GPL(snd_card_ref); |
746df9489 [ALSA] Fix rwlock... |
268 269 270 271 272 273 |
/* return non-zero if a card is already locked */ int snd_card_locked(int card) { int locked; mutex_lock(&snd_card_mutex); |
7bb2491b3 ALSA: Add kconfig... |
274 |
locked = test_bit(card, snd_cards_lock); |
746df9489 [ALSA] Fix rwlock... |
275 276 277 |
mutex_unlock(&snd_card_mutex); return locked; } |
b3b0abe11 [ALSA] return ENO... |
278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 |
static loff_t snd_disconnect_llseek(struct file *file, loff_t offset, int orig) { return -ENODEV; } static ssize_t snd_disconnect_read(struct file *file, char __user *buf, size_t count, loff_t *offset) { return -ENODEV; } static ssize_t snd_disconnect_write(struct file *file, const char __user *buf, size_t count, loff_t *offset) { return -ENODEV; } |
a9edfc602 [ALSA] Handle fil... |
294 295 296 297 298 299 300 301 |
static int snd_disconnect_release(struct inode *inode, struct file *file) { struct snd_monitor_file *df = NULL, *_df; spin_lock(&shutdown_lock); list_for_each_entry(_df, &shutdown_files, shutdown_list) { if (_df->file == file) { df = _df; |
118dd6bfe ALSA: Clean up sn... |
302 |
list_del_init(&df->shutdown_list); |
a9edfc602 [ALSA] Handle fil... |
303 304 305 306 |
break; } } spin_unlock(&shutdown_lock); |
233e70f42 saner FASYNC hand... |
307 308 309 |
if (likely(df)) { if ((file->f_flags & FASYNC) && df->disconnected_f_op->fasync) df->disconnected_f_op->fasync(-1, file, 0); |
a9edfc602 [ALSA] Handle fil... |
310 |
return df->disconnected_f_op->release(inode, file); |
233e70f42 saner FASYNC hand... |
311 |
} |
a9edfc602 [ALSA] Handle fil... |
312 |
|
9bf8e7dde [ALSA] sound: rep... |
313 |
panic("%s(%p, %p) failed!", __func__, inode, file); |
a9edfc602 [ALSA] Handle fil... |
314 |
} |
680ef72ab sound: annotate -... |
315 |
static __poll_t snd_disconnect_poll(struct file * file, poll_table * wait) |
1da177e4c Linux-2.6.12-rc2 |
316 |
{ |
a9a08845e vfs: do bulk POLL... |
317 |
return EPOLLERR | EPOLLNVAL; |
1da177e4c Linux-2.6.12-rc2 |
318 |
} |
b3b0abe11 [ALSA] return ENO... |
319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 |
static long snd_disconnect_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { return -ENODEV; } static int snd_disconnect_mmap(struct file *file, struct vm_area_struct *vma) { return -ENODEV; } static int snd_disconnect_fasync(int fd, struct file *file, int on) { return -ENODEV; } |
9c2e08c59 [PATCH] mark stru... |
334 |
static const struct file_operations snd_shutdown_f_ops = |
a9edfc602 [ALSA] Handle fil... |
335 336 337 338 339 340 341 342 343 344 345 346 347 348 |
{ .owner = THIS_MODULE, .llseek = snd_disconnect_llseek, .read = snd_disconnect_read, .write = snd_disconnect_write, .release = snd_disconnect_release, .poll = snd_disconnect_poll, .unlocked_ioctl = snd_disconnect_ioctl, #ifdef CONFIG_COMPAT .compat_ioctl = snd_disconnect_ioctl, #endif .mmap = snd_disconnect_mmap, .fasync = snd_disconnect_fasync }; |
1da177e4c Linux-2.6.12-rc2 |
349 350 351 352 353 354 |
/** * snd_card_disconnect - disconnect all APIs from the file-operations (user space) * @card: soundcard structure * * Disconnects all APIs from the file-operations (user space). * |
eb7c06e8e ALSA: add/change ... |
355 |
* Return: Zero, otherwise a negative error code. |
1da177e4c Linux-2.6.12-rc2 |
356 357 358 359 |
* * Note: The current implementation replaces all active file->f_op with special * dummy file operations (they do nothing except release). */ |
512bbd6a8 [ALSA] Remove xxx... |
360 |
int snd_card_disconnect(struct snd_card *card) |
1da177e4c Linux-2.6.12-rc2 |
361 362 |
{ struct snd_monitor_file *mfile; |
1da177e4c Linux-2.6.12-rc2 |
363 |
|
f18638dcf [ALSA] Clean up s... |
364 365 |
if (!card) return -EINVAL; |
1da177e4c Linux-2.6.12-rc2 |
366 367 368 369 370 371 372 |
spin_lock(&card->files_lock); if (card->shutdown) { spin_unlock(&card->files_lock); return 0; } card->shutdown = 1; spin_unlock(&card->files_lock); |
2a3f7221a ALSA: core: Fix c... |
373 |
/* replace file->f_op with special dummy operations */ |
1da177e4c Linux-2.6.12-rc2 |
374 |
spin_lock(&card->files_lock); |
118dd6bfe ALSA: Clean up sn... |
375 |
list_for_each_entry(mfile, &card->files_list, list) { |
1da177e4c Linux-2.6.12-rc2 |
376 377 |
/* it's critical part, use endless loop */ /* we have no room to fail */ |
a9edfc602 [ALSA] Handle fil... |
378 |
mfile->disconnected_f_op = mfile->file->f_op; |
1da177e4c Linux-2.6.12-rc2 |
379 |
|
a9edfc602 [ALSA] Handle fil... |
380 381 382 |
spin_lock(&shutdown_lock); list_add(&mfile->shutdown_list, &shutdown_files); spin_unlock(&shutdown_lock); |
1da177e4c Linux-2.6.12-rc2 |
383 |
|
a9edfc602 [ALSA] Handle fil... |
384 |
mfile->file->f_op = &snd_shutdown_f_ops; |
bc9abce0d [ALSA] fix compil... |
385 |
fops_get(mfile->file->f_op); |
1da177e4c Linux-2.6.12-rc2 |
386 387 |
} spin_unlock(&card->files_lock); |
2a3f7221a ALSA: core: Fix c... |
388 |
/* notify all connected devices about disconnection */ |
1da177e4c Linux-2.6.12-rc2 |
389 |
/* at this point, they cannot respond to any calls except release() */ |
8eeaa2f9e ALSA: Replace wit... |
390 |
#if IS_ENABLED(CONFIG_SND_MIXER_OSS) |
1da177e4c Linux-2.6.12-rc2 |
391 392 393 394 395 |
if (snd_mixer_oss_notify_callback) snd_mixer_oss_notify_callback(card, SND_MIXER_OSS_NOTIFY_DISCONNECT); #endif /* notify all devices that we are disconnected */ |
e086e3035 ALSA: core: Re-ad... |
396 |
snd_device_disconnect_all(card); |
1da177e4c Linux-2.6.12-rc2 |
397 |
|
746d4a02e [ALSA] Fix discon... |
398 |
snd_info_card_disconnect(card); |
8bfb181c1 ALSA: Embed card ... |
399 400 401 |
if (card->registered) { device_del(&card->card_dev); card->registered = false; |
73d38b13f [ALSA] Fix the ra... |
402 |
} |
2a3f7221a ALSA: core: Fix c... |
403 404 405 406 407 408 |
/* disable fops (user space) operations for ALSA API */ mutex_lock(&snd_card_mutex); snd_cards[card->number] = NULL; clear_bit(card->number, snd_cards_lock); mutex_unlock(&snd_card_mutex); |
f18638dcf [ALSA] Clean up s... |
409 410 411 |
#ifdef CONFIG_PM wake_up(&card->power_sleep); #endif |
1da177e4c Linux-2.6.12-rc2 |
412 413 |
return 0; } |
c0d3fb39e [ALSA] Clean up E... |
414 |
EXPORT_SYMBOL(snd_card_disconnect); |
c44027c89 ALSA: add snd_car... |
415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 |
/** * snd_card_disconnect_sync - disconnect card and wait until files get closed * @card: card object to disconnect * * This calls snd_card_disconnect() for disconnecting all belonging components * and waits until all pending files get closed. * It assures that all accesses from user-space finished so that the driver * can release its resources gracefully. */ void snd_card_disconnect_sync(struct snd_card *card) { int err; err = snd_card_disconnect(card); if (err < 0) { dev_err(card->dev, "snd_card_disconnect error (%d), skipping sync ", err); return; } spin_lock_irq(&card->files_lock); wait_event_lock_irq(card->remove_sleep, list_empty(&card->files_list), card->files_lock); spin_unlock_irq(&card->files_lock); } EXPORT_SYMBOL_GPL(snd_card_disconnect_sync); |
c461482c8 [ALSA] Unregister... |
444 |
static int snd_card_do_free(struct snd_card *card) |
1da177e4c Linux-2.6.12-rc2 |
445 |
{ |
8eeaa2f9e ALSA: Replace wit... |
446 |
#if IS_ENABLED(CONFIG_SND_MIXER_OSS) |
1da177e4c Linux-2.6.12-rc2 |
447 448 449 |
if (snd_mixer_oss_notify_callback) snd_mixer_oss_notify_callback(card, SND_MIXER_OSS_NOTIFY_FREE); #endif |
72620d604 ALSA: Clean up sn... |
450 |
snd_device_free_all(card); |
1da177e4c Linux-2.6.12-rc2 |
451 452 |
if (card->private_free) card->private_free(card); |
1da177e4c Linux-2.6.12-rc2 |
453 |
if (snd_info_card_free(card) < 0) { |
f2f9307a4 ALSA: core: Use s... |
454 455 |
dev_warn(card->dev, "unable to free card info "); |
1da177e4c Linux-2.6.12-rc2 |
456 457 |
/* Not fatal error */ } |
f24640648 ALSA: Use standar... |
458 459 |
if (card->release_completion) complete(card->release_completion); |
c461482c8 [ALSA] Unregister... |
460 461 462 |
kfree(card); return 0; } |
eb9c38d54 ALSA: doc: More k... |
463 464 465 466 467 468 469 470 471 |
/** * snd_card_free_when_closed - Disconnect the card, free it later eventually * @card: soundcard structure * * Unlike snd_card_free(), this function doesn't try to release the card * resource immediately, but tries to disconnect at first. When the card * is still in use, the function returns before freeing the resources. * The card resources will be freed when the refcount gets to zero. */ |
c461482c8 [ALSA] Unregister... |
472 473 |
int snd_card_free_when_closed(struct snd_card *card) { |
f24640648 ALSA: Use standar... |
474 475 |
int ret = snd_card_disconnect(card); if (ret) |
a0830dbd4 ALSA: Add a refer... |
476 |
return ret; |
f24640648 ALSA: Use standar... |
477 |
put_device(&card->card_dev); |
c461482c8 [ALSA] Unregister... |
478 479 |
return 0; } |
c461482c8 [ALSA] Unregister... |
480 |
EXPORT_SYMBOL(snd_card_free_when_closed); |
eb9c38d54 ALSA: doc: More k... |
481 482 483 484 485 486 487 488 489 490 491 492 493 |
/** * snd_card_free - frees given soundcard structure * @card: soundcard structure * * This function releases the soundcard structure and the all assigned * devices automatically. That is, you don't have to release the devices * by yourself. * * This function waits until the all resources are properly released. * * Return: Zero. Frees all associated devices and frees the control * interface associated to given soundcard. */ |
c461482c8 [ALSA] Unregister... |
494 495 |
int snd_card_free(struct snd_card *card) { |
bec206db9 ALSA: core: init:... |
496 |
DECLARE_COMPLETION_ONSTACK(released); |
f24640648 ALSA: Use standar... |
497 |
int ret; |
f24640648 ALSA: Use standar... |
498 499 |
card->release_completion = &released; ret = snd_card_free_when_closed(card); |
c461482c8 [ALSA] Unregister... |
500 501 |
if (ret) return ret; |
c461482c8 [ALSA] Unregister... |
502 |
/* wait, until all devices are ready for the free operation */ |
f24640648 ALSA: Use standar... |
503 |
wait_for_completion(&released); |
1da177e4c Linux-2.6.12-rc2 |
504 505 |
return 0; } |
c0d3fb39e [ALSA] Clean up E... |
506 |
EXPORT_SYMBOL(snd_card_free); |
e7df2a3ae ALSA: core - Refa... |
507 508 |
/* retrieve the last word of shortname or longname */ static const char *retrieve_id_from_card_name(const char *name) |
1da177e4c Linux-2.6.12-rc2 |
509 |
{ |
e7df2a3ae ALSA: core - Refa... |
510 511 512 513 514 515 |
const char *spos = name; while (*name) { if (isspace(*name) && isalnum(name[1])) spos = name + 1; name++; |
1da177e4c Linux-2.6.12-rc2 |
516 |
} |
e7df2a3ae ALSA: core - Refa... |
517 518 519 520 521 522 523 524 525 526 527 528 529 |
return spos; } /* return true if the given id string doesn't conflict any other card ids */ static bool card_id_ok(struct snd_card *card, const char *id) { int i; if (!snd_info_check_reserved_words(id)) return false; for (i = 0; i < snd_ecards_limit; i++) { if (snd_cards[i] && snd_cards[i] != card && !strcmp(snd_cards[i]->id, id)) return false; |
1da177e4c Linux-2.6.12-rc2 |
530 |
} |
e7df2a3ae ALSA: core - Refa... |
531 532 |
return true; } |
1da177e4c Linux-2.6.12-rc2 |
533 |
|
e7df2a3ae ALSA: core - Refa... |
534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 |
/* copy to card->id only with valid letters from nid */ static void copy_valid_id_string(struct snd_card *card, const char *src, const char *nid) { char *id = card->id; while (*nid && !isalnum(*nid)) nid++; if (isdigit(*nid)) *id++ = isalpha(*src) ? *src : 'D'; while (*nid && (size_t)(id - card->id) < sizeof(card->id) - 1) { if (isalnum(*nid)) *id++ = *nid; nid++; } *id = 0; } /* Set card->id from the given string * If the string conflicts with other ids, add a suffix to make it unique. */ static void snd_card_set_id_no_lock(struct snd_card *card, const char *src, const char *nid) { int len, loops; |
e7df2a3ae ALSA: core - Refa... |
559 560 |
bool is_default = false; char *id; |
1da177e4c Linux-2.6.12-rc2 |
561 |
|
e7df2a3ae ALSA: core - Refa... |
562 563 564 565 566 567 568 569 |
copy_valid_id_string(card, src, nid); id = card->id; again: /* use "Default" for obviously invalid strings * ("card" conflicts with proc directories) */ if (!*id || !strncmp(id, "card", 4)) { |
d8e4f9aed ALSA: core - Don'... |
570 |
strcpy(id, "Default"); |
e7df2a3ae ALSA: core - Refa... |
571 572 |
is_default = true; } |
1da177e4c Linux-2.6.12-rc2 |
573 |
|
8edbb198a ALSA: Fix the def... |
574 |
len = strlen(id); |
e7df2a3ae ALSA: core - Refa... |
575 |
for (loops = 0; loops < SNDRV_CARDS; loops++) { |
8edbb198a ALSA: Fix the def... |
576 577 578 |
char *spos; char sfxstr[5]; /* "_012" */ int sfxlen; |
e7df2a3ae ALSA: core - Refa... |
579 580 |
if (card_id_ok(card, id)) return; /* OK */ |
1da177e4c Linux-2.6.12-rc2 |
581 |
|
8edbb198a ALSA: Fix the def... |
582 583 584 585 586 587 588 589 |
/* Add _XYZ suffix */ sprintf(sfxstr, "_%X", loops + 1); sfxlen = strlen(sfxstr); if (len + sfxlen >= sizeof(card->id)) spos = id + sizeof(card->id) - sfxlen - 1; else spos = id + len; strcpy(spos, sfxstr); |
1da177e4c Linux-2.6.12-rc2 |
590 |
} |
e7df2a3ae ALSA: core - Refa... |
591 592 593 594 595 596 |
/* fallback to the default id */ if (!is_default) { *id = 0; goto again; } /* last resort... */ |
f2f9307a4 ALSA: core: Use s... |
597 598 |
dev_err(card->dev, "unable to set card id (%s) ", id); |
e7df2a3ae ALSA: core - Refa... |
599 |
if (card->proc_root->name) |
97f44f56c ALSA: Limit the f... |
600 |
strlcpy(card->id, card->proc_root->name, sizeof(card->id)); |
1da177e4c Linux-2.6.12-rc2 |
601 |
} |
872c78202 ALSA: Fix double ... |
602 603 604 605 606 607 608 609 610 611 |
/** * snd_card_set_id - set card identification name * @card: soundcard structure * @nid: new identification string * * This function sets the card identification and checks for name * collisions. */ void snd_card_set_id(struct snd_card *card, const char *nid) { |
5fdc18d93 ALSA: Core - clea... |
612 613 614 615 |
/* check if user specified own card->id */ if (card->id[0] != '\0') return; mutex_lock(&snd_card_mutex); |
e7df2a3ae ALSA: core - Refa... |
616 |
snd_card_set_id_no_lock(card, nid, nid); |
5fdc18d93 ALSA: Core - clea... |
617 |
mutex_unlock(&snd_card_mutex); |
872c78202 ALSA: Fix double ... |
618 |
} |
10a8ebbb0 ALSA: Core - add ... |
619 |
EXPORT_SYMBOL(snd_card_set_id); |
9fb6198e8 ALSA: add /sys/cl... |
620 621 622 623 |
static ssize_t card_id_show_attr(struct device *dev, struct device_attribute *attr, char *buf) { |
b203dbab0 ALSA: core: Fix m... |
624 |
struct snd_card *card = container_of(dev, struct snd_card, card_dev); |
ef21e1750 ALSA: Use scnprin... |
625 626 |
return scnprintf(buf, PAGE_SIZE, "%s ", card->id); |
9fb6198e8 ALSA: add /sys/cl... |
627 628 629 630 631 632 |
} static ssize_t card_id_store_attr(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { |
b203dbab0 ALSA: core: Fix m... |
633 |
struct snd_card *card = container_of(dev, struct snd_card, card_dev); |
9fb6198e8 ALSA: add /sys/cl... |
634 635 636 637 638 639 640 641 642 643 644 645 646 647 |
char buf1[sizeof(card->id)]; size_t copy = count > sizeof(card->id) - 1 ? sizeof(card->id) - 1 : count; size_t idx; int c; for (idx = 0; idx < copy; idx++) { c = buf[idx]; if (!isalnum(c) && c != '_' && c != '-') return -EINVAL; } memcpy(buf1, buf, copy); buf1[copy] = '\0'; mutex_lock(&snd_card_mutex); |
e7df2a3ae ALSA: core - Refa... |
648 |
if (!card_id_ok(NULL, buf1)) { |
9fb6198e8 ALSA: add /sys/cl... |
649 650 651 |
mutex_unlock(&snd_card_mutex); return -EEXIST; } |
9fb6198e8 ALSA: add /sys/cl... |
652 |
strcpy(card->id, buf1); |
c2eb9c4ea ALSA: when card i... |
653 |
snd_info_card_id_change(card); |
9fb6198e8 ALSA: add /sys/cl... |
654 655 656 657 |
mutex_unlock(&snd_card_mutex); return count; } |
6a73cf46c sound: Use octal ... |
658 |
static DEVICE_ATTR(id, 0644, card_id_show_attr, card_id_store_attr); |
9fb6198e8 ALSA: add /sys/cl... |
659 660 661 662 663 |
static ssize_t card_number_show_attr(struct device *dev, struct device_attribute *attr, char *buf) { |
b203dbab0 ALSA: core: Fix m... |
664 |
struct snd_card *card = container_of(dev, struct snd_card, card_dev); |
ef21e1750 ALSA: Use scnprin... |
665 666 |
return scnprintf(buf, PAGE_SIZE, "%i ", card->number); |
9fb6198e8 ALSA: add /sys/cl... |
667 |
} |
6a73cf46c sound: Use octal ... |
668 |
static DEVICE_ATTR(number, 0444, card_number_show_attr, NULL); |
34356dbdb ALSA: Use static ... |
669 670 671 672 673 674 |
static struct attribute *card_dev_attrs[] = { &dev_attr_id.attr, &dev_attr_number.attr, NULL }; |
6bbc7fed8 ALSA: Add a helpe... |
675 |
static const struct attribute_group card_dev_attr_group = { |
34356dbdb ALSA: Use static ... |
676 677 |
.attrs = card_dev_attrs, }; |
6bbc7fed8 ALSA: Add a helpe... |
678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 |
/** * snd_card_add_dev_attr - Append a new sysfs attribute group to card * @card: card instance * @group: attribute group to append */ int snd_card_add_dev_attr(struct snd_card *card, const struct attribute_group *group) { int i; /* loop for (arraysize-1) here to keep NULL at the last entry */ for (i = 0; i < ARRAY_SIZE(card->dev_groups) - 1; i++) { if (!card->dev_groups[i]) { card->dev_groups[i] = group; return 0; } } dev_err(card->dev, "Too many groups assigned "); return -ENOSPC; |
35f800141 ALSA: core: Follo... |
699 |
} |
6bbc7fed8 ALSA: Add a helpe... |
700 |
EXPORT_SYMBOL_GPL(snd_card_add_dev_attr); |
9fb6198e8 ALSA: add /sys/cl... |
701 |
|
1da177e4c Linux-2.6.12-rc2 |
702 703 704 705 706 707 708 709 710 |
/** * snd_card_register - register the soundcard * @card: soundcard structure * * This function registers all the devices assigned to the soundcard. * Until calling this, the ALSA control interface is blocked from the * external accesses. Thus, you should call this function at the end * of the initialization of the card. * |
eb7c06e8e ALSA: add/change ... |
711 |
* Return: Zero otherwise a negative error code if the registration failed. |
1da177e4c Linux-2.6.12-rc2 |
712 |
*/ |
512bbd6a8 [ALSA] Remove xxx... |
713 |
int snd_card_register(struct snd_card *card) |
1da177e4c Linux-2.6.12-rc2 |
714 715 |
{ int err; |
1da177e4c Linux-2.6.12-rc2 |
716 |
|
7eaa943c8 ALSA: Kill snd_as... |
717 718 |
if (snd_BUG_ON(!card)) return -EINVAL; |
39aba963d driver core: remo... |
719 |
|
8bfb181c1 ALSA: Embed card ... |
720 721 722 723 724 |
if (!card->registered) { err = device_add(&card->card_dev); if (err < 0) return err; card->registered = true; |
d80f19fab Driver core: conv... |
725 |
} |
39aba963d driver core: remo... |
726 |
|
1da177e4c Linux-2.6.12-rc2 |
727 728 |
if ((err = snd_device_register_all(card)) < 0) return err; |
746df9489 [ALSA] Fix rwlock... |
729 |
mutex_lock(&snd_card_mutex); |
1da177e4c Linux-2.6.12-rc2 |
730 731 |
if (snd_cards[card->number]) { /* already registered */ |
746df9489 [ALSA] Fix rwlock... |
732 |
mutex_unlock(&snd_card_mutex); |
2471b6c80 ALSA: info: Regis... |
733 |
return snd_info_card_register(card); /* register pending info */ |
1da177e4c Linux-2.6.12-rc2 |
734 |
} |
e7df2a3ae ALSA: core - Refa... |
735 736 737 738 739 740 741 742 743 744 745 746 |
if (*card->id) { /* make a unique id name from the given string */ char tmpid[sizeof(card->id)]; memcpy(tmpid, card->id, sizeof(card->id)); snd_card_set_id_no_lock(card, tmpid, tmpid); } else { /* create an id from either shortname or longname */ const char *src; src = *card->shortname ? card->shortname : card->longname; snd_card_set_id_no_lock(card, src, retrieve_id_from_card_name(src)); } |
1da177e4c Linux-2.6.12-rc2 |
747 |
snd_cards[card->number] = card; |
746df9489 [ALSA] Fix rwlock... |
748 |
mutex_unlock(&snd_card_mutex); |
29b2625ff ALSA: info: Move ... |
749 750 751 |
err = snd_info_card_register(card); if (err < 0) return err; |
8eeaa2f9e ALSA: Replace wit... |
752 |
#if IS_ENABLED(CONFIG_SND_MIXER_OSS) |
1da177e4c Linux-2.6.12-rc2 |
753 754 755 756 757 |
if (snd_mixer_oss_notify_callback) snd_mixer_oss_notify_callback(card, SND_MIXER_OSS_NOTIFY_REGISTER); #endif return 0; } |
c0d3fb39e [ALSA] Clean up E... |
758 |
EXPORT_SYMBOL(snd_card_register); |
cd6a65036 ALSA: replace CON... |
759 |
#ifdef CONFIG_SND_PROC_FS |
a381a7a66 [ALSA] Decentrali... |
760 761 |
static void snd_card_info_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer) |
1da177e4c Linux-2.6.12-rc2 |
762 763 |
{ int idx, count; |
512bbd6a8 [ALSA] Remove xxx... |
764 |
struct snd_card *card; |
1da177e4c Linux-2.6.12-rc2 |
765 766 |
for (idx = count = 0; idx < SNDRV_CARDS; idx++) { |
746df9489 [ALSA] Fix rwlock... |
767 |
mutex_lock(&snd_card_mutex); |
1da177e4c Linux-2.6.12-rc2 |
768 769 |
if ((card = snd_cards[idx]) != NULL) { count++; |
d001544de [ALSA] dynamic mi... |
770 771 |
snd_iprintf(buffer, "%2i [%-15s]: %s - %s ", |
1da177e4c Linux-2.6.12-rc2 |
772 773 774 775 |
idx, card->id, card->driver, card->shortname); |
d001544de [ALSA] dynamic mi... |
776 777 |
snd_iprintf(buffer, " %s ", |
1da177e4c Linux-2.6.12-rc2 |
778 779 |
card->longname); } |
746df9489 [ALSA] Fix rwlock... |
780 |
mutex_unlock(&snd_card_mutex); |
1da177e4c Linux-2.6.12-rc2 |
781 782 783 784 785 |
} if (!count) snd_iprintf(buffer, "--- no soundcards --- "); } |
e28563cce [ALSA] Optimize f... |
786 |
#ifdef CONFIG_SND_OSSEMUL |
512bbd6a8 [ALSA] Remove xxx... |
787 |
void snd_card_info_read_oss(struct snd_info_buffer *buffer) |
1da177e4c Linux-2.6.12-rc2 |
788 789 |
{ int idx, count; |
512bbd6a8 [ALSA] Remove xxx... |
790 |
struct snd_card *card; |
1da177e4c Linux-2.6.12-rc2 |
791 792 |
for (idx = count = 0; idx < SNDRV_CARDS; idx++) { |
746df9489 [ALSA] Fix rwlock... |
793 |
mutex_lock(&snd_card_mutex); |
1da177e4c Linux-2.6.12-rc2 |
794 795 796 797 798 |
if ((card = snd_cards[idx]) != NULL) { count++; snd_iprintf(buffer, "%s ", card->longname); } |
746df9489 [ALSA] Fix rwlock... |
799 |
mutex_unlock(&snd_card_mutex); |
1da177e4c Linux-2.6.12-rc2 |
800 801 802 803 804 805 806 807 808 809 |
} if (!count) { snd_iprintf(buffer, "--- no soundcards --- "); } } #endif #ifdef MODULE |
512bbd6a8 [ALSA] Remove xxx... |
810 811 |
static void snd_card_module_info_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer) |
1da177e4c Linux-2.6.12-rc2 |
812 813 |
{ int idx; |
512bbd6a8 [ALSA] Remove xxx... |
814 |
struct snd_card *card; |
1da177e4c Linux-2.6.12-rc2 |
815 816 |
for (idx = 0; idx < SNDRV_CARDS; idx++) { |
746df9489 [ALSA] Fix rwlock... |
817 |
mutex_lock(&snd_card_mutex); |
1da177e4c Linux-2.6.12-rc2 |
818 |
if ((card = snd_cards[idx]) != NULL) |
d001544de [ALSA] dynamic mi... |
819 820 821 |
snd_iprintf(buffer, "%2i %s ", idx, card->module->name); |
746df9489 [ALSA] Fix rwlock... |
822 |
mutex_unlock(&snd_card_mutex); |
1da177e4c Linux-2.6.12-rc2 |
823 824 825 826 827 828 |
} } #endif int __init snd_card_info_init(void) { |
512bbd6a8 [ALSA] Remove xxx... |
829 |
struct snd_info_entry *entry; |
1da177e4c Linux-2.6.12-rc2 |
830 831 |
entry = snd_info_create_module_entry(THIS_MODULE, "cards", NULL); |
7c22f1aaa [ALSA] Remove snd... |
832 833 |
if (! entry) return -ENOMEM; |
1da177e4c Linux-2.6.12-rc2 |
834 |
entry->c.text.read = snd_card_info_read; |
b591b6e9e ALSA: core: Don't... |
835 836 |
if (snd_info_register(entry) < 0) return -ENOMEM; /* freed in error path */ |
1da177e4c Linux-2.6.12-rc2 |
837 838 839 |
#ifdef MODULE entry = snd_info_create_module_entry(THIS_MODULE, "modules", NULL); |
b591b6e9e ALSA: core: Don't... |
840 841 842 843 844 |
if (!entry) return -ENOMEM; entry->c.text.read = snd_card_module_info_read; if (snd_info_register(entry) < 0) return -ENOMEM; /* freed in error path */ |
1da177e4c Linux-2.6.12-rc2 |
845 846 847 848 |
#endif return 0; } |
cd6a65036 ALSA: replace CON... |
849 |
#endif /* CONFIG_SND_PROC_FS */ |
e28563cce [ALSA] Optimize f... |
850 |
|
1da177e4c Linux-2.6.12-rc2 |
851 852 853 854 855 856 857 858 |
/** * snd_component_add - add a component string * @card: soundcard structure * @component: the component id string * * This function adds the component id string to the supported list. * The component can be referred from the alsa-lib. * |
eb7c06e8e ALSA: add/change ... |
859 |
* Return: Zero otherwise a negative error code. |
1da177e4c Linux-2.6.12-rc2 |
860 861 |
*/ |
512bbd6a8 [ALSA] Remove xxx... |
862 |
int snd_component_add(struct snd_card *card, const char *component) |
1da177e4c Linux-2.6.12-rc2 |
863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 |
{ char *ptr; int len = strlen(component); ptr = strstr(card->components, component); if (ptr != NULL) { if (ptr[len] == '\0' || ptr[len] == ' ') /* already there */ return 1; } if (strlen(card->components) + 1 + len + 1 > sizeof(card->components)) { snd_BUG(); return -ENOMEM; } if (card->components[0] != '\0') strcat(card->components, " "); strcat(card->components, component); return 0; } |
c0d3fb39e [ALSA] Clean up E... |
881 |
EXPORT_SYMBOL(snd_component_add); |
1da177e4c Linux-2.6.12-rc2 |
882 883 884 885 886 887 888 889 890 |
/** * snd_card_file_add - add the file to the file list of the card * @card: soundcard structure * @file: file pointer * * This function adds the file to the file linked-list of the card. * This linked-list is used to keep tracking the connection state, * and to avoid the release of busy resources by hotplug. * |
eb7c06e8e ALSA: add/change ... |
891 |
* Return: zero or a negative error code. |
1da177e4c Linux-2.6.12-rc2 |
892 |
*/ |
512bbd6a8 [ALSA] Remove xxx... |
893 |
int snd_card_file_add(struct snd_card *card, struct file *file) |
1da177e4c Linux-2.6.12-rc2 |
894 895 896 897 898 899 900 |
{ struct snd_monitor_file *mfile; mfile = kmalloc(sizeof(*mfile), GFP_KERNEL); if (mfile == NULL) return -ENOMEM; mfile->file = file; |
a9edfc602 [ALSA] Handle fil... |
901 |
mfile->disconnected_f_op = NULL; |
a45e3d6b1 ALSA: Fix yet ano... |
902 |
INIT_LIST_HEAD(&mfile->shutdown_list); |
1da177e4c Linux-2.6.12-rc2 |
903 904 905 906 907 908 |
spin_lock(&card->files_lock); if (card->shutdown) { spin_unlock(&card->files_lock); kfree(mfile); return -ENODEV; } |
118dd6bfe ALSA: Clean up sn... |
909 |
list_add(&mfile->list, &card->files_list); |
f24640648 ALSA: Use standar... |
910 |
get_device(&card->card_dev); |
1da177e4c Linux-2.6.12-rc2 |
911 912 913 |
spin_unlock(&card->files_lock); return 0; } |
c0d3fb39e [ALSA] Clean up E... |
914 |
EXPORT_SYMBOL(snd_card_file_add); |
1da177e4c Linux-2.6.12-rc2 |
915 916 917 918 919 920 921 |
/** * snd_card_file_remove - remove the file from the file list * @card: soundcard structure * @file: file pointer * * This function removes the file formerly added to the card via * snd_card_file_add() function. |
2b29b13c5 [ALSA] Deprecate ... |
922 923 924 |
* If all files are removed and snd_card_free_when_closed() was * called beforehand, it processes the pending release of * resources. |
1da177e4c Linux-2.6.12-rc2 |
925 |
* |
eb7c06e8e ALSA: add/change ... |
926 |
* Return: Zero or a negative error code. |
1da177e4c Linux-2.6.12-rc2 |
927 |
*/ |
512bbd6a8 [ALSA] Remove xxx... |
928 |
int snd_card_file_remove(struct snd_card *card, struct file *file) |
1da177e4c Linux-2.6.12-rc2 |
929 |
{ |
118dd6bfe ALSA: Clean up sn... |
930 |
struct snd_monitor_file *mfile, *found = NULL; |
1da177e4c Linux-2.6.12-rc2 |
931 932 |
spin_lock(&card->files_lock); |
118dd6bfe ALSA: Clean up sn... |
933 |
list_for_each_entry(mfile, &card->files_list, list) { |
1da177e4c Linux-2.6.12-rc2 |
934 |
if (mfile->file == file) { |
118dd6bfe ALSA: Clean up sn... |
935 |
list_del(&mfile->list); |
a45e3d6b1 ALSA: Fix yet ano... |
936 937 938 |
spin_lock(&shutdown_lock); list_del(&mfile->shutdown_list); spin_unlock(&shutdown_lock); |
118dd6bfe ALSA: Clean up sn... |
939 940 941 |
if (mfile->disconnected_f_op) fops_put(mfile->disconnected_f_op); found = mfile; |
1da177e4c Linux-2.6.12-rc2 |
942 943 |
break; } |
a9edfc602 [ALSA] Handle fil... |
944 |
} |
c44027c89 ALSA: add snd_car... |
945 946 |
if (list_empty(&card->files_list)) wake_up_all(&card->remove_sleep); |
c461482c8 [ALSA] Unregister... |
947 |
spin_unlock(&card->files_lock); |
118dd6bfe ALSA: Clean up sn... |
948 |
if (!found) { |
f2f9307a4 ALSA: core: Use s... |
949 950 |
dev_err(card->dev, "card file remove problem (%p) ", file); |
1da177e4c Linux-2.6.12-rc2 |
951 952 |
return -ENOENT; } |
118dd6bfe ALSA: Clean up sn... |
953 |
kfree(found); |
f24640648 ALSA: Use standar... |
954 |
put_device(&card->card_dev); |
1da177e4c Linux-2.6.12-rc2 |
955 956 |
return 0; } |
c0d3fb39e [ALSA] Clean up E... |
957 |
EXPORT_SYMBOL(snd_card_file_remove); |
1da177e4c Linux-2.6.12-rc2 |
958 959 960 961 962 |
#ifdef CONFIG_PM /** * snd_power_wait - wait until the power-state is changed. * @card: soundcard structure * @power_state: expected power state |
1da177e4c Linux-2.6.12-rc2 |
963 964 965 |
* * Waits until the power-state is changed. * |
eb7c06e8e ALSA: add/change ... |
966 |
* Return: Zero if successful, or a negative error code. |
1da177e4c Linux-2.6.12-rc2 |
967 |
*/ |
cbac4b0cb [ALSA] Cleanup un... |
968 |
int snd_power_wait(struct snd_card *card, unsigned int power_state) |
1da177e4c Linux-2.6.12-rc2 |
969 |
{ |
ac6424b98 sched/wait: Renam... |
970 |
wait_queue_entry_t wait; |
1da177e4c Linux-2.6.12-rc2 |
971 972 973 974 975 976 977 978 979 980 981 982 983 984 |
int result = 0; /* fastpath */ if (snd_power_get_state(card) == power_state) return 0; init_waitqueue_entry(&wait, current); add_wait_queue(&card->power_sleep, &wait); while (1) { if (card->shutdown) { result = -ENODEV; break; } if (snd_power_get_state(card) == power_state) break; |
1da177e4c Linux-2.6.12-rc2 |
985 |
set_current_state(TASK_UNINTERRUPTIBLE); |
1da177e4c Linux-2.6.12-rc2 |
986 |
schedule_timeout(30 * HZ); |
1da177e4c Linux-2.6.12-rc2 |
987 988 989 990 |
} remove_wait_queue(&card->power_sleep, &wait); return result; } |
c0d3fb39e [ALSA] Clean up E... |
991 |
EXPORT_SYMBOL(snd_power_wait); |
1da177e4c Linux-2.6.12-rc2 |
992 |
#endif /* CONFIG_PM */ |