diff options
Diffstat (limited to 'sound/core/timer.c')
| -rw-r--r-- | sound/core/timer.c | 77 |
1 files changed, 39 insertions, 38 deletions
diff --git a/sound/core/timer.c b/sound/core/timer.c index 2425b971b240..cdeeb639b675 100644 --- a/sound/core/timer.c +++ b/sound/core/timer.c | |||
| @@ -25,6 +25,7 @@ | |||
| 25 | #include <linux/smp_lock.h> | 25 | #include <linux/smp_lock.h> |
| 26 | #include <linux/slab.h> | 26 | #include <linux/slab.h> |
| 27 | #include <linux/time.h> | 27 | #include <linux/time.h> |
| 28 | #include <linux/mutex.h> | ||
| 28 | #include <linux/moduleparam.h> | 29 | #include <linux/moduleparam.h> |
| 29 | #include <linux/string.h> | 30 | #include <linux/string.h> |
| 30 | #include <sound/core.h> | 31 | #include <sound/core.h> |
| @@ -70,7 +71,7 @@ struct snd_timer_user { | |||
| 70 | struct timespec tstamp; /* trigger tstamp */ | 71 | struct timespec tstamp; /* trigger tstamp */ |
| 71 | wait_queue_head_t qchange_sleep; | 72 | wait_queue_head_t qchange_sleep; |
| 72 | struct fasync_struct *fasync; | 73 | struct fasync_struct *fasync; |
| 73 | struct semaphore tread_sem; | 74 | struct mutex tread_sem; |
| 74 | }; | 75 | }; |
| 75 | 76 | ||
| 76 | /* list of timers */ | 77 | /* list of timers */ |
| @@ -82,7 +83,7 @@ static LIST_HEAD(snd_timer_slave_list); | |||
| 82 | /* lock for slave active lists */ | 83 | /* lock for slave active lists */ |
| 83 | static DEFINE_SPINLOCK(slave_active_lock); | 84 | static DEFINE_SPINLOCK(slave_active_lock); |
| 84 | 85 | ||
| 85 | static DECLARE_MUTEX(register_mutex); | 86 | static DEFINE_MUTEX(register_mutex); |
| 86 | 87 | ||
| 87 | static int snd_timer_free(struct snd_timer *timer); | 88 | static int snd_timer_free(struct snd_timer *timer); |
| 88 | static int snd_timer_dev_free(struct snd_device *device); | 89 | static int snd_timer_dev_free(struct snd_device *device); |
| @@ -252,10 +253,10 @@ int snd_timer_open(struct snd_timer_instance **ti, | |||
| 252 | snd_printd("invalid slave class %i\n", tid->dev_sclass); | 253 | snd_printd("invalid slave class %i\n", tid->dev_sclass); |
| 253 | return -EINVAL; | 254 | return -EINVAL; |
| 254 | } | 255 | } |
| 255 | down(®ister_mutex); | 256 | mutex_lock(®ister_mutex); |
| 256 | timeri = snd_timer_instance_new(owner, NULL); | 257 | timeri = snd_timer_instance_new(owner, NULL); |
| 257 | if (!timeri) { | 258 | if (!timeri) { |
| 258 | up(®ister_mutex); | 259 | mutex_unlock(®ister_mutex); |
| 259 | return -ENOMEM; | 260 | return -ENOMEM; |
| 260 | } | 261 | } |
| 261 | timeri->slave_class = tid->dev_sclass; | 262 | timeri->slave_class = tid->dev_sclass; |
| @@ -263,37 +264,37 @@ int snd_timer_open(struct snd_timer_instance **ti, | |||
| 263 | timeri->flags |= SNDRV_TIMER_IFLG_SLAVE; | 264 | timeri->flags |= SNDRV_TIMER_IFLG_SLAVE; |
| 264 | list_add_tail(&timeri->open_list, &snd_timer_slave_list); | 265 | list_add_tail(&timeri->open_list, &snd_timer_slave_list); |
| 265 | snd_timer_check_slave(timeri); | 266 | snd_timer_check_slave(timeri); |
| 266 | up(®ister_mutex); | 267 | mutex_unlock(®ister_mutex); |
| 267 | *ti = timeri; | 268 | *ti = timeri; |
| 268 | return 0; | 269 | return 0; |
| 269 | } | 270 | } |
| 270 | 271 | ||
| 271 | /* open a master instance */ | 272 | /* open a master instance */ |
| 272 | down(®ister_mutex); | 273 | mutex_lock(®ister_mutex); |
| 273 | timer = snd_timer_find(tid); | 274 | timer = snd_timer_find(tid); |
| 274 | #ifdef CONFIG_KMOD | 275 | #ifdef CONFIG_KMOD |
| 275 | if (timer == NULL) { | 276 | if (timer == NULL) { |
| 276 | up(®ister_mutex); | 277 | mutex_unlock(®ister_mutex); |
| 277 | snd_timer_request(tid); | 278 | snd_timer_request(tid); |
| 278 | down(®ister_mutex); | 279 | mutex_lock(®ister_mutex); |
| 279 | timer = snd_timer_find(tid); | 280 | timer = snd_timer_find(tid); |
| 280 | } | 281 | } |
| 281 | #endif | 282 | #endif |
| 282 | if (!timer) { | 283 | if (!timer) { |
| 283 | up(®ister_mutex); | 284 | mutex_unlock(®ister_mutex); |
| 284 | return -ENODEV; | 285 | return -ENODEV; |
| 285 | } | 286 | } |
| 286 | if (!list_empty(&timer->open_list_head)) { | 287 | if (!list_empty(&timer->open_list_head)) { |
| 287 | timeri = list_entry(timer->open_list_head.next, | 288 | timeri = list_entry(timer->open_list_head.next, |
| 288 | struct snd_timer_instance, open_list); | 289 | struct snd_timer_instance, open_list); |
| 289 | if (timeri->flags & SNDRV_TIMER_IFLG_EXCLUSIVE) { | 290 | if (timeri->flags & SNDRV_TIMER_IFLG_EXCLUSIVE) { |
| 290 | up(®ister_mutex); | 291 | mutex_unlock(®ister_mutex); |
| 291 | return -EBUSY; | 292 | return -EBUSY; |
| 292 | } | 293 | } |
| 293 | } | 294 | } |
| 294 | timeri = snd_timer_instance_new(owner, timer); | 295 | timeri = snd_timer_instance_new(owner, timer); |
| 295 | if (!timeri) { | 296 | if (!timeri) { |
| 296 | up(®ister_mutex); | 297 | mutex_unlock(®ister_mutex); |
| 297 | return -ENOMEM; | 298 | return -ENOMEM; |
| 298 | } | 299 | } |
| 299 | timeri->slave_class = tid->dev_sclass; | 300 | timeri->slave_class = tid->dev_sclass; |
| @@ -302,7 +303,7 @@ int snd_timer_open(struct snd_timer_instance **ti, | |||
| 302 | timer->hw.open(timer); | 303 | timer->hw.open(timer); |
| 303 | list_add_tail(&timeri->open_list, &timer->open_list_head); | 304 | list_add_tail(&timeri->open_list, &timer->open_list_head); |
| 304 | snd_timer_check_master(timeri); | 305 | snd_timer_check_master(timeri); |
| 305 | up(®ister_mutex); | 306 | mutex_unlock(®ister_mutex); |
| 306 | *ti = timeri; | 307 | *ti = timeri; |
| 307 | return 0; | 308 | return 0; |
| 308 | } | 309 | } |
| @@ -333,9 +334,9 @@ int snd_timer_close(struct snd_timer_instance *timeri) | |||
| 333 | spin_lock_irq(&slave_active_lock); | 334 | spin_lock_irq(&slave_active_lock); |
| 334 | } | 335 | } |
| 335 | spin_unlock_irq(&slave_active_lock); | 336 | spin_unlock_irq(&slave_active_lock); |
| 336 | down(®ister_mutex); | 337 | mutex_lock(®ister_mutex); |
| 337 | list_del(&timeri->open_list); | 338 | list_del(&timeri->open_list); |
| 338 | up(®ister_mutex); | 339 | mutex_unlock(®ister_mutex); |
| 339 | } else { | 340 | } else { |
| 340 | timer = timeri->timer; | 341 | timer = timeri->timer; |
| 341 | /* wait, until the active callback is finished */ | 342 | /* wait, until the active callback is finished */ |
| @@ -346,7 +347,7 @@ int snd_timer_close(struct snd_timer_instance *timeri) | |||
| 346 | spin_lock_irq(&timer->lock); | 347 | spin_lock_irq(&timer->lock); |
| 347 | } | 348 | } |
| 348 | spin_unlock_irq(&timer->lock); | 349 | spin_unlock_irq(&timer->lock); |
| 349 | down(®ister_mutex); | 350 | mutex_lock(®ister_mutex); |
| 350 | list_del(&timeri->open_list); | 351 | list_del(&timeri->open_list); |
| 351 | if (timer && list_empty(&timer->open_list_head) && | 352 | if (timer && list_empty(&timer->open_list_head) && |
| 352 | timer->hw.close) | 353 | timer->hw.close) |
| @@ -362,7 +363,7 @@ int snd_timer_close(struct snd_timer_instance *timeri) | |||
| 362 | slave->timer = NULL; | 363 | slave->timer = NULL; |
| 363 | spin_unlock_irq(&slave_active_lock); | 364 | spin_unlock_irq(&slave_active_lock); |
| 364 | } | 365 | } |
| 365 | up(®ister_mutex); | 366 | mutex_unlock(®ister_mutex); |
| 366 | } | 367 | } |
| 367 | if (timeri->private_free) | 368 | if (timeri->private_free) |
| 368 | timeri->private_free(timeri); | 369 | timeri->private_free(timeri); |
| @@ -835,7 +836,7 @@ static int snd_timer_dev_register(struct snd_device *dev) | |||
| 835 | !timer->hw.resolution && timer->hw.c_resolution == NULL) | 836 | !timer->hw.resolution && timer->hw.c_resolution == NULL) |
| 836 | return -EINVAL; | 837 | return -EINVAL; |
| 837 | 838 | ||
| 838 | down(®ister_mutex); | 839 | mutex_lock(®ister_mutex); |
| 839 | list_for_each(p, &snd_timer_list) { | 840 | list_for_each(p, &snd_timer_list) { |
| 840 | timer1 = list_entry(p, struct snd_timer, device_list); | 841 | timer1 = list_entry(p, struct snd_timer, device_list); |
| 841 | if (timer1->tmr_class > timer->tmr_class) | 842 | if (timer1->tmr_class > timer->tmr_class) |
| @@ -857,11 +858,11 @@ static int snd_timer_dev_register(struct snd_device *dev) | |||
| 857 | if (timer1->tmr_subdevice < timer->tmr_subdevice) | 858 | if (timer1->tmr_subdevice < timer->tmr_subdevice) |
| 858 | continue; | 859 | continue; |
| 859 | /* conflicts.. */ | 860 | /* conflicts.. */ |
| 860 | up(®ister_mutex); | 861 | mutex_unlock(®ister_mutex); |
| 861 | return -EBUSY; | 862 | return -EBUSY; |
| 862 | } | 863 | } |
| 863 | list_add_tail(&timer->device_list, p); | 864 | list_add_tail(&timer->device_list, p); |
| 864 | up(®ister_mutex); | 865 | mutex_unlock(®ister_mutex); |
| 865 | return 0; | 866 | return 0; |
| 866 | } | 867 | } |
| 867 | 868 | ||
| @@ -871,7 +872,7 @@ static int snd_timer_unregister(struct snd_timer *timer) | |||
| 871 | struct snd_timer_instance *ti; | 872 | struct snd_timer_instance *ti; |
| 872 | 873 | ||
| 873 | snd_assert(timer != NULL, return -ENXIO); | 874 | snd_assert(timer != NULL, return -ENXIO); |
| 874 | down(®ister_mutex); | 875 | mutex_lock(®ister_mutex); |
| 875 | if (! list_empty(&timer->open_list_head)) { | 876 | if (! list_empty(&timer->open_list_head)) { |
| 876 | snd_printk(KERN_WARNING "timer 0x%lx is busy?\n", (long)timer); | 877 | snd_printk(KERN_WARNING "timer 0x%lx is busy?\n", (long)timer); |
| 877 | list_for_each_safe(p, n, &timer->open_list_head) { | 878 | list_for_each_safe(p, n, &timer->open_list_head) { |
| @@ -881,7 +882,7 @@ static int snd_timer_unregister(struct snd_timer *timer) | |||
| 881 | } | 882 | } |
| 882 | } | 883 | } |
| 883 | list_del(&timer->device_list); | 884 | list_del(&timer->device_list); |
| 884 | up(®ister_mutex); | 885 | mutex_unlock(®ister_mutex); |
| 885 | return snd_timer_free(timer); | 886 | return snd_timer_free(timer); |
| 886 | } | 887 | } |
| 887 | 888 | ||
| @@ -1065,7 +1066,7 @@ static void snd_timer_proc_read(struct snd_info_entry *entry, | |||
| 1065 | struct snd_timer_instance *ti; | 1066 | struct snd_timer_instance *ti; |
| 1066 | struct list_head *p, *q; | 1067 | struct list_head *p, *q; |
| 1067 | 1068 | ||
| 1068 | down(®ister_mutex); | 1069 | mutex_lock(®ister_mutex); |
| 1069 | list_for_each(p, &snd_timer_list) { | 1070 | list_for_each(p, &snd_timer_list) { |
| 1070 | timer = list_entry(p, struct snd_timer, device_list); | 1071 | timer = list_entry(p, struct snd_timer, device_list); |
| 1071 | switch (timer->tmr_class) { | 1072 | switch (timer->tmr_class) { |
| @@ -1105,7 +1106,7 @@ static void snd_timer_proc_read(struct snd_info_entry *entry, | |||
| 1105 | } | 1106 | } |
| 1106 | spin_unlock_irqrestore(&timer->lock, flags); | 1107 | spin_unlock_irqrestore(&timer->lock, flags); |
| 1107 | } | 1108 | } |
| 1108 | up(®ister_mutex); | 1109 | mutex_unlock(®ister_mutex); |
| 1109 | } | 1110 | } |
| 1110 | 1111 | ||
| 1111 | static struct snd_info_entry *snd_timer_proc_entry = NULL; | 1112 | static struct snd_info_entry *snd_timer_proc_entry = NULL; |
| @@ -1269,7 +1270,7 @@ static int snd_timer_user_open(struct inode *inode, struct file *file) | |||
| 1269 | return -ENOMEM; | 1270 | return -ENOMEM; |
| 1270 | spin_lock_init(&tu->qlock); | 1271 | spin_lock_init(&tu->qlock); |
| 1271 | init_waitqueue_head(&tu->qchange_sleep); | 1272 | init_waitqueue_head(&tu->qchange_sleep); |
| 1272 | init_MUTEX(&tu->tread_sem); | 1273 | mutex_init(&tu->tread_sem); |
| 1273 | tu->ticks = 1; | 1274 | tu->ticks = 1; |
| 1274 | tu->queue_size = 128; | 1275 | tu->queue_size = 128; |
| 1275 | tu->queue = kmalloc(tu->queue_size * sizeof(struct snd_timer_read), | 1276 | tu->queue = kmalloc(tu->queue_size * sizeof(struct snd_timer_read), |
| @@ -1325,7 +1326,7 @@ static int snd_timer_user_next_device(struct snd_timer_id __user *_tid) | |||
| 1325 | 1326 | ||
| 1326 | if (copy_from_user(&id, _tid, sizeof(id))) | 1327 | if (copy_from_user(&id, _tid, sizeof(id))) |
| 1327 | return -EFAULT; | 1328 | return -EFAULT; |
| 1328 | down(®ister_mutex); | 1329 | mutex_lock(®ister_mutex); |
| 1329 | if (id.dev_class < 0) { /* first item */ | 1330 | if (id.dev_class < 0) { /* first item */ |
| 1330 | if (list_empty(&snd_timer_list)) | 1331 | if (list_empty(&snd_timer_list)) |
| 1331 | snd_timer_user_zero_id(&id); | 1332 | snd_timer_user_zero_id(&id); |
| @@ -1407,7 +1408,7 @@ static int snd_timer_user_next_device(struct snd_timer_id __user *_tid) | |||
| 1407 | snd_timer_user_zero_id(&id); | 1408 | snd_timer_user_zero_id(&id); |
| 1408 | } | 1409 | } |
| 1409 | } | 1410 | } |
| 1410 | up(®ister_mutex); | 1411 | mutex_unlock(®ister_mutex); |
| 1411 | if (copy_to_user(_tid, &id, sizeof(*_tid))) | 1412 | if (copy_to_user(_tid, &id, sizeof(*_tid))) |
| 1412 | return -EFAULT; | 1413 | return -EFAULT; |
| 1413 | return 0; | 1414 | return 0; |
| @@ -1432,7 +1433,7 @@ static int snd_timer_user_ginfo(struct file *file, | |||
| 1432 | tid = ginfo->tid; | 1433 | tid = ginfo->tid; |
| 1433 | memset(ginfo, 0, sizeof(*ginfo)); | 1434 | memset(ginfo, 0, sizeof(*ginfo)); |
| 1434 | ginfo->tid = tid; | 1435 | ginfo->tid = tid; |
| 1435 | down(®ister_mutex); | 1436 | mutex_lock(®ister_mutex); |
| 1436 | t = snd_timer_find(&tid); | 1437 | t = snd_timer_find(&tid); |
| 1437 | if (t != NULL) { | 1438 | if (t != NULL) { |
| 1438 | ginfo->card = t->card ? t->card->number : -1; | 1439 | ginfo->card = t->card ? t->card->number : -1; |
| @@ -1451,7 +1452,7 @@ static int snd_timer_user_ginfo(struct file *file, | |||
| 1451 | } else { | 1452 | } else { |
| 1452 | err = -ENODEV; | 1453 | err = -ENODEV; |
| 1453 | } | 1454 | } |
| 1454 | up(®ister_mutex); | 1455 | mutex_unlock(®ister_mutex); |
| 1455 | if (err >= 0 && copy_to_user(_ginfo, ginfo, sizeof(*ginfo))) | 1456 | if (err >= 0 && copy_to_user(_ginfo, ginfo, sizeof(*ginfo))) |
| 1456 | err = -EFAULT; | 1457 | err = -EFAULT; |
| 1457 | kfree(ginfo); | 1458 | kfree(ginfo); |
| @@ -1467,7 +1468,7 @@ static int snd_timer_user_gparams(struct file *file, | |||
| 1467 | 1468 | ||
| 1468 | if (copy_from_user(&gparams, _gparams, sizeof(gparams))) | 1469 | if (copy_from_user(&gparams, _gparams, sizeof(gparams))) |
| 1469 | return -EFAULT; | 1470 | return -EFAULT; |
| 1470 | down(®ister_mutex); | 1471 | mutex_lock(®ister_mutex); |
| 1471 | t = snd_timer_find(&gparams.tid); | 1472 | t = snd_timer_find(&gparams.tid); |
| 1472 | if (!t) { | 1473 | if (!t) { |
| 1473 | err = -ENODEV; | 1474 | err = -ENODEV; |
| @@ -1483,7 +1484,7 @@ static int snd_timer_user_gparams(struct file *file, | |||
| 1483 | } | 1484 | } |
| 1484 | err = t->hw.set_period(t, gparams.period_num, gparams.period_den); | 1485 | err = t->hw.set_period(t, gparams.period_num, gparams.period_den); |
| 1485 | _error: | 1486 | _error: |
| 1486 | up(®ister_mutex); | 1487 | mutex_unlock(®ister_mutex); |
| 1487 | return err; | 1488 | return err; |
| 1488 | } | 1489 | } |
| 1489 | 1490 | ||
| @@ -1500,7 +1501,7 @@ static int snd_timer_user_gstatus(struct file *file, | |||
| 1500 | tid = gstatus.tid; | 1501 | tid = gstatus.tid; |
| 1501 | memset(&gstatus, 0, sizeof(gstatus)); | 1502 | memset(&gstatus, 0, sizeof(gstatus)); |
| 1502 | gstatus.tid = tid; | 1503 | gstatus.tid = tid; |
| 1503 | down(®ister_mutex); | 1504 | mutex_lock(®ister_mutex); |
| 1504 | t = snd_timer_find(&tid); | 1505 | t = snd_timer_find(&tid); |
| 1505 | if (t != NULL) { | 1506 | if (t != NULL) { |
| 1506 | if (t->hw.c_resolution) | 1507 | if (t->hw.c_resolution) |
| @@ -1517,7 +1518,7 @@ static int snd_timer_user_gstatus(struct file *file, | |||
| 1517 | } else { | 1518 | } else { |
| 1518 | err = -ENODEV; | 1519 | err = -ENODEV; |
| 1519 | } | 1520 | } |
| 1520 | up(®ister_mutex); | 1521 | mutex_unlock(®ister_mutex); |
| 1521 | if (err >= 0 && copy_to_user(_gstatus, &gstatus, sizeof(gstatus))) | 1522 | if (err >= 0 && copy_to_user(_gstatus, &gstatus, sizeof(gstatus))) |
| 1522 | err = -EFAULT; | 1523 | err = -EFAULT; |
| 1523 | return err; | 1524 | return err; |
| @@ -1532,7 +1533,7 @@ static int snd_timer_user_tselect(struct file *file, | |||
| 1532 | int err = 0; | 1533 | int err = 0; |
| 1533 | 1534 | ||
| 1534 | tu = file->private_data; | 1535 | tu = file->private_data; |
| 1535 | down(&tu->tread_sem); | 1536 | mutex_lock(&tu->tread_sem); |
| 1536 | if (tu->timeri) { | 1537 | if (tu->timeri) { |
| 1537 | snd_timer_close(tu->timeri); | 1538 | snd_timer_close(tu->timeri); |
| 1538 | tu->timeri = NULL; | 1539 | tu->timeri = NULL; |
| @@ -1576,7 +1577,7 @@ static int snd_timer_user_tselect(struct file *file, | |||
| 1576 | } | 1577 | } |
| 1577 | 1578 | ||
| 1578 | __err: | 1579 | __err: |
| 1579 | up(&tu->tread_sem); | 1580 | mutex_unlock(&tu->tread_sem); |
| 1580 | return err; | 1581 | return err; |
| 1581 | } | 1582 | } |
| 1582 | 1583 | ||
| @@ -1797,17 +1798,17 @@ static long snd_timer_user_ioctl(struct file *file, unsigned int cmd, | |||
| 1797 | { | 1798 | { |
| 1798 | int xarg; | 1799 | int xarg; |
| 1799 | 1800 | ||
| 1800 | down(&tu->tread_sem); | 1801 | mutex_lock(&tu->tread_sem); |
| 1801 | if (tu->timeri) { /* too late */ | 1802 | if (tu->timeri) { /* too late */ |
| 1802 | up(&tu->tread_sem); | 1803 | mutex_unlock(&tu->tread_sem); |
| 1803 | return -EBUSY; | 1804 | return -EBUSY; |
| 1804 | } | 1805 | } |
| 1805 | if (get_user(xarg, p)) { | 1806 | if (get_user(xarg, p)) { |
| 1806 | up(&tu->tread_sem); | 1807 | mutex_unlock(&tu->tread_sem); |
| 1807 | return -EFAULT; | 1808 | return -EFAULT; |
| 1808 | } | 1809 | } |
| 1809 | tu->tread = xarg ? 1 : 0; | 1810 | tu->tread = xarg ? 1 : 0; |
| 1810 | up(&tu->tread_sem); | 1811 | mutex_unlock(&tu->tread_sem); |
| 1811 | return 0; | 1812 | return 0; |
| 1812 | } | 1813 | } |
| 1813 | case SNDRV_TIMER_IOCTL_GINFO: | 1814 | case SNDRV_TIMER_IOCTL_GINFO: |
