diff options
Diffstat (limited to 'sound/core/timer.c')
-rw-r--r-- | sound/core/timer.c | 100 |
1 files changed, 65 insertions, 35 deletions
diff --git a/sound/core/timer.c b/sound/core/timer.c index fa762ca439be..b498e5482d77 100644 --- a/sound/core/timer.c +++ b/sound/core/timer.c | |||
@@ -69,6 +69,7 @@ typedef struct { | |||
69 | struct timespec tstamp; /* trigger tstamp */ | 69 | struct timespec tstamp; /* trigger tstamp */ |
70 | wait_queue_head_t qchange_sleep; | 70 | wait_queue_head_t qchange_sleep; |
71 | struct fasync_struct *fasync; | 71 | struct fasync_struct *fasync; |
72 | struct semaphore tread_sem; | ||
72 | } snd_timer_user_t; | 73 | } snd_timer_user_t; |
73 | 74 | ||
74 | /* list of timers */ | 75 | /* list of timers */ |
@@ -844,7 +845,7 @@ int snd_timer_dev_register(snd_device_t *dev) | |||
844 | return 0; | 845 | return 0; |
845 | } | 846 | } |
846 | 847 | ||
847 | int snd_timer_unregister(snd_timer_t *timer) | 848 | static int snd_timer_unregister(snd_timer_t *timer) |
848 | { | 849 | { |
849 | struct list_head *p, *n; | 850 | struct list_head *p, *n; |
850 | snd_timer_instance_t *ti; | 851 | snd_timer_instance_t *ti; |
@@ -945,11 +946,6 @@ struct snd_timer_system_private { | |||
945 | unsigned long correction; | 946 | unsigned long correction; |
946 | }; | 947 | }; |
947 | 948 | ||
948 | unsigned int snd_timer_system_resolution(void) | ||
949 | { | ||
950 | return 1000000000L / HZ; | ||
951 | } | ||
952 | |||
953 | static void snd_timer_s_function(unsigned long data) | 949 | static void snd_timer_s_function(unsigned long data) |
954 | { | 950 | { |
955 | snd_timer_t *timer = (snd_timer_t *)data; | 951 | snd_timer_t *timer = (snd_timer_t *)data; |
@@ -1208,6 +1204,7 @@ static int snd_timer_user_open(struct inode *inode, struct file *file) | |||
1208 | return -ENOMEM; | 1204 | return -ENOMEM; |
1209 | spin_lock_init(&tu->qlock); | 1205 | spin_lock_init(&tu->qlock); |
1210 | init_waitqueue_head(&tu->qchange_sleep); | 1206 | init_waitqueue_head(&tu->qchange_sleep); |
1207 | init_MUTEX(&tu->tread_sem); | ||
1211 | tu->ticks = 1; | 1208 | tu->ticks = 1; |
1212 | tu->queue_size = 128; | 1209 | tu->queue_size = 128; |
1213 | tu->queue = (snd_timer_read_t *)kmalloc(tu->queue_size * sizeof(snd_timer_read_t), GFP_KERNEL); | 1210 | tu->queue = (snd_timer_read_t *)kmalloc(tu->queue_size * sizeof(snd_timer_read_t), GFP_KERNEL); |
@@ -1454,46 +1451,51 @@ static int snd_timer_user_tselect(struct file *file, snd_timer_select_t __user * | |||
1454 | snd_timer_user_t *tu; | 1451 | snd_timer_user_t *tu; |
1455 | snd_timer_select_t tselect; | 1452 | snd_timer_select_t tselect; |
1456 | char str[32]; | 1453 | char str[32]; |
1457 | int err; | 1454 | int err = 0; |
1458 | 1455 | ||
1459 | tu = file->private_data; | 1456 | tu = file->private_data; |
1460 | if (tu->timeri) | 1457 | down(&tu->tread_sem); |
1458 | if (tu->timeri) { | ||
1461 | snd_timer_close(tu->timeri); | 1459 | snd_timer_close(tu->timeri); |
1462 | if (copy_from_user(&tselect, _tselect, sizeof(tselect))) | 1460 | tu->timeri = NULL; |
1463 | return -EFAULT; | 1461 | } |
1462 | if (copy_from_user(&tselect, _tselect, sizeof(tselect))) { | ||
1463 | err = -EFAULT; | ||
1464 | goto __err; | ||
1465 | } | ||
1464 | sprintf(str, "application %i", current->pid); | 1466 | sprintf(str, "application %i", current->pid); |
1465 | if (tselect.id.dev_class != SNDRV_TIMER_CLASS_SLAVE) | 1467 | if (tselect.id.dev_class != SNDRV_TIMER_CLASS_SLAVE) |
1466 | tselect.id.dev_sclass = SNDRV_TIMER_SCLASS_APPLICATION; | 1468 | tselect.id.dev_sclass = SNDRV_TIMER_SCLASS_APPLICATION; |
1467 | if ((err = snd_timer_open(&tu->timeri, str, &tselect.id, current->pid)) < 0) | 1469 | if ((err = snd_timer_open(&tu->timeri, str, &tselect.id, current->pid)) < 0) |
1468 | return err; | 1470 | goto __err; |
1469 | 1471 | ||
1470 | if (tu->queue) { | 1472 | kfree(tu->queue); |
1471 | kfree(tu->queue); | 1473 | tu->queue = NULL; |
1472 | tu->queue = NULL; | 1474 | kfree(tu->tqueue); |
1473 | } | 1475 | tu->tqueue = NULL; |
1474 | if (tu->tqueue) { | ||
1475 | kfree(tu->tqueue); | ||
1476 | tu->tqueue = NULL; | ||
1477 | } | ||
1478 | if (tu->tread) { | 1476 | if (tu->tread) { |
1479 | tu->tqueue = (snd_timer_tread_t *)kmalloc(tu->queue_size * sizeof(snd_timer_tread_t), GFP_KERNEL); | 1477 | tu->tqueue = (snd_timer_tread_t *)kmalloc(tu->queue_size * sizeof(snd_timer_tread_t), GFP_KERNEL); |
1480 | if (tu->tqueue == NULL) { | 1478 | if (tu->tqueue == NULL) |
1481 | snd_timer_close(tu->timeri); | 1479 | err = -ENOMEM; |
1482 | return -ENOMEM; | ||
1483 | } | ||
1484 | } else { | 1480 | } else { |
1485 | tu->queue = (snd_timer_read_t *)kmalloc(tu->queue_size * sizeof(snd_timer_read_t), GFP_KERNEL); | 1481 | tu->queue = (snd_timer_read_t *)kmalloc(tu->queue_size * sizeof(snd_timer_read_t), GFP_KERNEL); |
1486 | if (tu->queue == NULL) { | 1482 | if (tu->queue == NULL) |
1487 | snd_timer_close(tu->timeri); | 1483 | err = -ENOMEM; |
1488 | return -ENOMEM; | ||
1489 | } | ||
1490 | } | 1484 | } |
1491 | 1485 | ||
1492 | tu->timeri->flags |= SNDRV_TIMER_IFLG_FAST; | 1486 | if (err < 0) { |
1493 | tu->timeri->callback = tu->tread ? snd_timer_user_tinterrupt : snd_timer_user_interrupt; | 1487 | snd_timer_close(tu->timeri); |
1494 | tu->timeri->ccallback = snd_timer_user_ccallback; | 1488 | tu->timeri = NULL; |
1495 | tu->timeri->callback_data = (void *)tu; | 1489 | } else { |
1496 | return 0; | 1490 | tu->timeri->flags |= SNDRV_TIMER_IFLG_FAST; |
1491 | tu->timeri->callback = tu->tread ? snd_timer_user_tinterrupt : snd_timer_user_interrupt; | ||
1492 | tu->timeri->ccallback = snd_timer_user_ccallback; | ||
1493 | tu->timeri->callback_data = (void *)tu; | ||
1494 | } | ||
1495 | |||
1496 | __err: | ||
1497 | up(&tu->tread_sem); | ||
1498 | return err; | ||
1497 | } | 1499 | } |
1498 | 1500 | ||
1499 | static int snd_timer_user_info(struct file *file, snd_timer_info_t __user *_info) | 1501 | static int snd_timer_user_info(struct file *file, snd_timer_info_t __user *_info) |
@@ -1669,6 +1671,23 @@ static int snd_timer_user_continue(struct file *file) | |||
1669 | return (err = snd_timer_continue(tu->timeri)) < 0 ? err : 0; | 1671 | return (err = snd_timer_continue(tu->timeri)) < 0 ? err : 0; |
1670 | } | 1672 | } |
1671 | 1673 | ||
1674 | static int snd_timer_user_pause(struct file *file) | ||
1675 | { | ||
1676 | int err; | ||
1677 | snd_timer_user_t *tu; | ||
1678 | |||
1679 | tu = file->private_data; | ||
1680 | snd_assert(tu->timeri != NULL, return -ENXIO); | ||
1681 | return (err = snd_timer_pause(tu->timeri)) < 0 ? err : 0; | ||
1682 | } | ||
1683 | |||
1684 | enum { | ||
1685 | SNDRV_TIMER_IOCTL_START_OLD = _IO('T', 0x20), | ||
1686 | SNDRV_TIMER_IOCTL_STOP_OLD = _IO('T', 0x21), | ||
1687 | SNDRV_TIMER_IOCTL_CONTINUE_OLD = _IO('T', 0x22), | ||
1688 | SNDRV_TIMER_IOCTL_PAUSE_OLD = _IO('T', 0x23), | ||
1689 | }; | ||
1690 | |||
1672 | static long snd_timer_user_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | 1691 | static long snd_timer_user_ioctl(struct file *file, unsigned int cmd, unsigned long arg) |
1673 | { | 1692 | { |
1674 | snd_timer_user_t *tu; | 1693 | snd_timer_user_t *tu; |
@@ -1685,11 +1704,17 @@ static long snd_timer_user_ioctl(struct file *file, unsigned int cmd, unsigned l | |||
1685 | { | 1704 | { |
1686 | int xarg; | 1705 | int xarg; |
1687 | 1706 | ||
1688 | if (tu->timeri) /* too late */ | 1707 | down(&tu->tread_sem); |
1708 | if (tu->timeri) { /* too late */ | ||
1709 | up(&tu->tread_sem); | ||
1689 | return -EBUSY; | 1710 | return -EBUSY; |
1690 | if (get_user(xarg, p)) | 1711 | } |
1712 | if (get_user(xarg, p)) { | ||
1713 | up(&tu->tread_sem); | ||
1691 | return -EFAULT; | 1714 | return -EFAULT; |
1715 | } | ||
1692 | tu->tread = xarg ? 1 : 0; | 1716 | tu->tread = xarg ? 1 : 0; |
1717 | up(&tu->tread_sem); | ||
1693 | return 0; | 1718 | return 0; |
1694 | } | 1719 | } |
1695 | case SNDRV_TIMER_IOCTL_GINFO: | 1720 | case SNDRV_TIMER_IOCTL_GINFO: |
@@ -1707,11 +1732,17 @@ static long snd_timer_user_ioctl(struct file *file, unsigned int cmd, unsigned l | |||
1707 | case SNDRV_TIMER_IOCTL_STATUS: | 1732 | case SNDRV_TIMER_IOCTL_STATUS: |
1708 | return snd_timer_user_status(file, argp); | 1733 | return snd_timer_user_status(file, argp); |
1709 | case SNDRV_TIMER_IOCTL_START: | 1734 | case SNDRV_TIMER_IOCTL_START: |
1735 | case SNDRV_TIMER_IOCTL_START_OLD: | ||
1710 | return snd_timer_user_start(file); | 1736 | return snd_timer_user_start(file); |
1711 | case SNDRV_TIMER_IOCTL_STOP: | 1737 | case SNDRV_TIMER_IOCTL_STOP: |
1738 | case SNDRV_TIMER_IOCTL_STOP_OLD: | ||
1712 | return snd_timer_user_stop(file); | 1739 | return snd_timer_user_stop(file); |
1713 | case SNDRV_TIMER_IOCTL_CONTINUE: | 1740 | case SNDRV_TIMER_IOCTL_CONTINUE: |
1741 | case SNDRV_TIMER_IOCTL_CONTINUE_OLD: | ||
1714 | return snd_timer_user_continue(file); | 1742 | return snd_timer_user_continue(file); |
1743 | case SNDRV_TIMER_IOCTL_PAUSE: | ||
1744 | case SNDRV_TIMER_IOCTL_PAUSE_OLD: | ||
1745 | return snd_timer_user_pause(file); | ||
1715 | } | 1746 | } |
1716 | return -ENOTTY; | 1747 | return -ENOTTY; |
1717 | } | 1748 | } |
@@ -1898,4 +1929,3 @@ EXPORT_SYMBOL(snd_timer_global_free); | |||
1898 | EXPORT_SYMBOL(snd_timer_global_register); | 1929 | EXPORT_SYMBOL(snd_timer_global_register); |
1899 | EXPORT_SYMBOL(snd_timer_global_unregister); | 1930 | EXPORT_SYMBOL(snd_timer_global_unregister); |
1900 | EXPORT_SYMBOL(snd_timer_interrupt); | 1931 | EXPORT_SYMBOL(snd_timer_interrupt); |
1901 | EXPORT_SYMBOL(snd_timer_system_resolution); | ||