aboutsummaryrefslogtreecommitdiffstats
path: root/sound/core/timer.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/core/timer.c')
-rw-r--r--sound/core/timer.c125
1 files changed, 60 insertions, 65 deletions
diff --git a/sound/core/timer.c b/sound/core/timer.c
index 884c3066b028..a9b9a277e00c 100644
--- a/sound/core/timer.c
+++ b/sound/core/timer.c
@@ -319,6 +319,7 @@ int snd_timer_open(struct snd_timer_instance **ti,
319 *ti = timeri; 319 *ti = timeri;
320 return 0; 320 return 0;
321} 321}
322EXPORT_SYMBOL(snd_timer_open);
322 323
323/* 324/*
324 * close a timer instance 325 * close a timer instance
@@ -384,6 +385,7 @@ int snd_timer_close(struct snd_timer_instance *timeri)
384 mutex_unlock(&register_mutex); 385 mutex_unlock(&register_mutex);
385 return 0; 386 return 0;
386} 387}
388EXPORT_SYMBOL(snd_timer_close);
387 389
388unsigned long snd_timer_resolution(struct snd_timer_instance *timeri) 390unsigned long snd_timer_resolution(struct snd_timer_instance *timeri)
389{ 391{
@@ -398,6 +400,7 @@ unsigned long snd_timer_resolution(struct snd_timer_instance *timeri)
398 } 400 }
399 return 0; 401 return 0;
400} 402}
403EXPORT_SYMBOL(snd_timer_resolution);
401 404
402static void snd_timer_notify1(struct snd_timer_instance *ti, int event) 405static void snd_timer_notify1(struct snd_timer_instance *ti, int event)
403{ 406{
@@ -589,6 +592,7 @@ int snd_timer_start(struct snd_timer_instance *timeri, unsigned int ticks)
589 else 592 else
590 return snd_timer_start1(timeri, true, ticks); 593 return snd_timer_start1(timeri, true, ticks);
591} 594}
595EXPORT_SYMBOL(snd_timer_start);
592 596
593/* 597/*
594 * stop the timer instance. 598 * stop the timer instance.
@@ -602,6 +606,7 @@ int snd_timer_stop(struct snd_timer_instance *timeri)
602 else 606 else
603 return snd_timer_stop1(timeri, true); 607 return snd_timer_stop1(timeri, true);
604} 608}
609EXPORT_SYMBOL(snd_timer_stop);
605 610
606/* 611/*
607 * start again.. the tick is kept. 612 * start again.. the tick is kept.
@@ -617,6 +622,7 @@ int snd_timer_continue(struct snd_timer_instance *timeri)
617 else 622 else
618 return snd_timer_start1(timeri, false, 0); 623 return snd_timer_start1(timeri, false, 0);
619} 624}
625EXPORT_SYMBOL(snd_timer_continue);
620 626
621/* 627/*
622 * pause.. remember the ticks left 628 * pause.. remember the ticks left
@@ -628,6 +634,7 @@ int snd_timer_pause(struct snd_timer_instance * timeri)
628 else 634 else
629 return snd_timer_stop1(timeri, false); 635 return snd_timer_stop1(timeri, false);
630} 636}
637EXPORT_SYMBOL(snd_timer_pause);
631 638
632/* 639/*
633 * reschedule the timer 640 * reschedule the timer
@@ -809,6 +816,7 @@ void snd_timer_interrupt(struct snd_timer * timer, unsigned long ticks_left)
809 if (use_tasklet) 816 if (use_tasklet)
810 tasklet_schedule(&timer->task_queue); 817 tasklet_schedule(&timer->task_queue);
811} 818}
819EXPORT_SYMBOL(snd_timer_interrupt);
812 820
813/* 821/*
814 822
@@ -859,6 +867,7 @@ int snd_timer_new(struct snd_card *card, char *id, struct snd_timer_id *tid,
859 *rtimer = timer; 867 *rtimer = timer;
860 return 0; 868 return 0;
861} 869}
870EXPORT_SYMBOL(snd_timer_new);
862 871
863static int snd_timer_free(struct snd_timer *timer) 872static int snd_timer_free(struct snd_timer *timer)
864{ 873{
@@ -978,6 +987,7 @@ void snd_timer_notify(struct snd_timer *timer, int event, struct timespec *tstam
978 } 987 }
979 spin_unlock_irqrestore(&timer->lock, flags); 988 spin_unlock_irqrestore(&timer->lock, flags);
980} 989}
990EXPORT_SYMBOL(snd_timer_notify);
981 991
982/* 992/*
983 * exported functions for global timers 993 * exported functions for global timers
@@ -993,11 +1003,13 @@ int snd_timer_global_new(char *id, int device, struct snd_timer **rtimer)
993 tid.subdevice = 0; 1003 tid.subdevice = 0;
994 return snd_timer_new(NULL, id, &tid, rtimer); 1004 return snd_timer_new(NULL, id, &tid, rtimer);
995} 1005}
1006EXPORT_SYMBOL(snd_timer_global_new);
996 1007
997int snd_timer_global_free(struct snd_timer *timer) 1008int snd_timer_global_free(struct snd_timer *timer)
998{ 1009{
999 return snd_timer_free(timer); 1010 return snd_timer_free(timer);
1000} 1011}
1012EXPORT_SYMBOL(snd_timer_global_free);
1001 1013
1002int snd_timer_global_register(struct snd_timer *timer) 1014int snd_timer_global_register(struct snd_timer *timer)
1003{ 1015{
@@ -1007,6 +1019,7 @@ int snd_timer_global_register(struct snd_timer *timer)
1007 dev.device_data = timer; 1019 dev.device_data = timer;
1008 return snd_timer_dev_register(&dev); 1020 return snd_timer_dev_register(&dev);
1009} 1021}
1022EXPORT_SYMBOL(snd_timer_global_register);
1010 1023
1011/* 1024/*
1012 * System timer 1025 * System timer
@@ -1327,6 +1340,33 @@ static void snd_timer_user_tinterrupt(struct snd_timer_instance *timeri,
1327 wake_up(&tu->qchange_sleep); 1340 wake_up(&tu->qchange_sleep);
1328} 1341}
1329 1342
1343static int realloc_user_queue(struct snd_timer_user *tu, int size)
1344{
1345 struct snd_timer_read *queue = NULL;
1346 struct snd_timer_tread *tqueue = NULL;
1347
1348 if (tu->tread) {
1349 tqueue = kcalloc(size, sizeof(*tqueue), GFP_KERNEL);
1350 if (!tqueue)
1351 return -ENOMEM;
1352 } else {
1353 queue = kcalloc(size, sizeof(*queue), GFP_KERNEL);
1354 if (!queue)
1355 return -ENOMEM;
1356 }
1357
1358 spin_lock_irq(&tu->qlock);
1359 kfree(tu->queue);
1360 kfree(tu->tqueue);
1361 tu->queue_size = size;
1362 tu->queue = queue;
1363 tu->tqueue = tqueue;
1364 tu->qhead = tu->qtail = tu->qused = 0;
1365 spin_unlock_irq(&tu->qlock);
1366
1367 return 0;
1368}
1369
1330static int snd_timer_user_open(struct inode *inode, struct file *file) 1370static int snd_timer_user_open(struct inode *inode, struct file *file)
1331{ 1371{
1332 struct snd_timer_user *tu; 1372 struct snd_timer_user *tu;
@@ -1343,10 +1383,7 @@ static int snd_timer_user_open(struct inode *inode, struct file *file)
1343 init_waitqueue_head(&tu->qchange_sleep); 1383 init_waitqueue_head(&tu->qchange_sleep);
1344 mutex_init(&tu->ioctl_lock); 1384 mutex_init(&tu->ioctl_lock);
1345 tu->ticks = 1; 1385 tu->ticks = 1;
1346 tu->queue_size = 128; 1386 if (realloc_user_queue(tu, 128) < 0) {
1347 tu->queue = kmalloc(tu->queue_size * sizeof(struct snd_timer_read),
1348 GFP_KERNEL);
1349 if (tu->queue == NULL) {
1350 kfree(tu); 1387 kfree(tu);
1351 return -ENOMEM; 1388 return -ENOMEM;
1352 } 1389 }
@@ -1618,34 +1655,12 @@ static int snd_timer_user_tselect(struct file *file,
1618 if (err < 0) 1655 if (err < 0)
1619 goto __err; 1656 goto __err;
1620 1657
1621 tu->qhead = tu->qtail = tu->qused = 0; 1658 tu->timeri->flags |= SNDRV_TIMER_IFLG_FAST;
1622 kfree(tu->queue); 1659 tu->timeri->callback = tu->tread
1623 tu->queue = NULL;
1624 kfree(tu->tqueue);
1625 tu->tqueue = NULL;
1626 if (tu->tread) {
1627 tu->tqueue = kmalloc(tu->queue_size * sizeof(struct snd_timer_tread),
1628 GFP_KERNEL);
1629 if (tu->tqueue == NULL)
1630 err = -ENOMEM;
1631 } else {
1632 tu->queue = kmalloc(tu->queue_size * sizeof(struct snd_timer_read),
1633 GFP_KERNEL);
1634 if (tu->queue == NULL)
1635 err = -ENOMEM;
1636 }
1637
1638 if (err < 0) {
1639 snd_timer_close(tu->timeri);
1640 tu->timeri = NULL;
1641 } else {
1642 tu->timeri->flags |= SNDRV_TIMER_IFLG_FAST;
1643 tu->timeri->callback = tu->tread
1644 ? snd_timer_user_tinterrupt : snd_timer_user_interrupt; 1660 ? snd_timer_user_tinterrupt : snd_timer_user_interrupt;
1645 tu->timeri->ccallback = snd_timer_user_ccallback; 1661 tu->timeri->ccallback = snd_timer_user_ccallback;
1646 tu->timeri->callback_data = (void *)tu; 1662 tu->timeri->callback_data = (void *)tu;
1647 tu->timeri->disconnect = snd_timer_user_disconnect; 1663 tu->timeri->disconnect = snd_timer_user_disconnect;
1648 }
1649 1664
1650 __err: 1665 __err:
1651 return err; 1666 return err;
@@ -1687,8 +1702,6 @@ static int snd_timer_user_params(struct file *file,
1687 struct snd_timer_user *tu; 1702 struct snd_timer_user *tu;
1688 struct snd_timer_params params; 1703 struct snd_timer_params params;
1689 struct snd_timer *t; 1704 struct snd_timer *t;
1690 struct snd_timer_read *tr;
1691 struct snd_timer_tread *ttr;
1692 int err; 1705 int err;
1693 1706
1694 tu = file->private_data; 1707 tu = file->private_data;
@@ -1751,24 +1764,11 @@ static int snd_timer_user_params(struct file *file,
1751 spin_unlock_irq(&t->lock); 1764 spin_unlock_irq(&t->lock);
1752 if (params.queue_size > 0 && 1765 if (params.queue_size > 0 &&
1753 (unsigned int)tu->queue_size != params.queue_size) { 1766 (unsigned int)tu->queue_size != params.queue_size) {
1754 if (tu->tread) { 1767 err = realloc_user_queue(tu, params.queue_size);
1755 ttr = kmalloc(params.queue_size * sizeof(*ttr), 1768 if (err < 0)
1756 GFP_KERNEL); 1769 goto _end;
1757 if (ttr) {
1758 kfree(tu->tqueue);
1759 tu->queue_size = params.queue_size;
1760 tu->tqueue = ttr;
1761 }
1762 } else {
1763 tr = kmalloc(params.queue_size * sizeof(*tr),
1764 GFP_KERNEL);
1765 if (tr) {
1766 kfree(tu->queue);
1767 tu->queue_size = params.queue_size;
1768 tu->queue = tr;
1769 }
1770 }
1771 } 1770 }
1771 spin_lock_irq(&tu->qlock);
1772 tu->qhead = tu->qtail = tu->qused = 0; 1772 tu->qhead = tu->qtail = tu->qused = 0;
1773 if (tu->timeri->flags & SNDRV_TIMER_IFLG_EARLY_EVENT) { 1773 if (tu->timeri->flags & SNDRV_TIMER_IFLG_EARLY_EVENT) {
1774 if (tu->tread) { 1774 if (tu->tread) {
@@ -1789,6 +1789,7 @@ static int snd_timer_user_params(struct file *file,
1789 } 1789 }
1790 tu->filter = params.filter; 1790 tu->filter = params.filter;
1791 tu->ticks = params.ticks; 1791 tu->ticks = params.ticks;
1792 spin_unlock_irq(&tu->qlock);
1792 err = 0; 1793 err = 0;
1793 _end: 1794 _end:
1794 if (copy_to_user(_params, &params, sizeof(params))) 1795 if (copy_to_user(_params, &params, sizeof(params)))
@@ -1891,13 +1892,19 @@ static long __snd_timer_user_ioctl(struct file *file, unsigned int cmd,
1891 return snd_timer_user_next_device(argp); 1892 return snd_timer_user_next_device(argp);
1892 case SNDRV_TIMER_IOCTL_TREAD: 1893 case SNDRV_TIMER_IOCTL_TREAD:
1893 { 1894 {
1894 int xarg; 1895 int xarg, old_tread;
1895 1896
1896 if (tu->timeri) /* too late */ 1897 if (tu->timeri) /* too late */
1897 return -EBUSY; 1898 return -EBUSY;
1898 if (get_user(xarg, p)) 1899 if (get_user(xarg, p))
1899 return -EFAULT; 1900 return -EFAULT;
1901 old_tread = tu->tread;
1900 tu->tread = xarg ? 1 : 0; 1902 tu->tread = xarg ? 1 : 0;
1903 if (tu->tread != old_tread &&
1904 realloc_user_queue(tu, tu->queue_size) < 0) {
1905 tu->tread = old_tread;
1906 return -ENOMEM;
1907 }
1901 return 0; 1908 return 0;
1902 } 1909 }
1903 case SNDRV_TIMER_IOCTL_GINFO: 1910 case SNDRV_TIMER_IOCTL_GINFO:
@@ -2030,10 +2037,12 @@ static unsigned int snd_timer_user_poll(struct file *file, poll_table * wait)
2030 poll_wait(file, &tu->qchange_sleep, wait); 2037 poll_wait(file, &tu->qchange_sleep, wait);
2031 2038
2032 mask = 0; 2039 mask = 0;
2040 spin_lock_irq(&tu->qlock);
2033 if (tu->qused) 2041 if (tu->qused)
2034 mask |= POLLIN | POLLRDNORM; 2042 mask |= POLLIN | POLLRDNORM;
2035 if (tu->disconnected) 2043 if (tu->disconnected)
2036 mask |= POLLERR; 2044 mask |= POLLERR;
2045 spin_unlock_irq(&tu->qlock);
2037 2046
2038 return mask; 2047 return mask;
2039} 2048}
@@ -2117,17 +2126,3 @@ static void __exit alsa_timer_exit(void)
2117 2126
2118module_init(alsa_timer_init) 2127module_init(alsa_timer_init)
2119module_exit(alsa_timer_exit) 2128module_exit(alsa_timer_exit)
2120
2121EXPORT_SYMBOL(snd_timer_open);
2122EXPORT_SYMBOL(snd_timer_close);
2123EXPORT_SYMBOL(snd_timer_resolution);
2124EXPORT_SYMBOL(snd_timer_start);
2125EXPORT_SYMBOL(snd_timer_stop);
2126EXPORT_SYMBOL(snd_timer_continue);
2127EXPORT_SYMBOL(snd_timer_pause);
2128EXPORT_SYMBOL(snd_timer_new);
2129EXPORT_SYMBOL(snd_timer_notify);
2130EXPORT_SYMBOL(snd_timer_global_new);
2131EXPORT_SYMBOL(snd_timer_global_free);
2132EXPORT_SYMBOL(snd_timer_global_register);
2133EXPORT_SYMBOL(snd_timer_interrupt);