[ALSA] timers: add module refcounting for global timers
Modules: RTC timer driver,Timer Midlevel
Add a module pointer to the timer structure and use it for refcounting
instead of the card's module pointer to prevent the global timer
modules (rtctimer and hpetimer) from being removed while in use.
Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
diff --git a/include/sound/timer.h b/include/sound/timer.h
index 1898511..b55f38a 100644
--- a/include/sound/timer.h
+++ b/include/sound/timer.h
@@ -88,6 +88,7 @@
struct _snd_timer {
snd_timer_class_t tmr_class;
snd_card_t *card;
+ struct module *module;
int tmr_device;
int tmr_subdevice;
char id[64];
diff --git a/sound/core/rtctimer.c b/sound/core/rtctimer.c
index 8762ff8..c3c1856 100644
--- a/sound/core/rtctimer.c
+++ b/sound/core/rtctimer.c
@@ -124,7 +124,8 @@
if (rtctimer_freq < 2 || rtctimer_freq > 8192 ||
(rtctimer_freq & (rtctimer_freq - 1)) != 0) {
- snd_printk(KERN_ERR "rtctimer: invalid frequency %d\n", rtctimer_freq);
+ snd_printk(KERN_ERR "rtctimer: invalid frequency %d\n",
+ rtctimer_freq);
return -EINVAL;
}
@@ -133,6 +134,7 @@
if (err < 0)
return err;
+ timer->module = THIS_MODULE;
strcpy(timer->name, "RTC timer");
timer->hw = rtc_hw;
timer->hw.resolution = NANO_SEC / rtctimer_freq;
diff --git a/sound/core/timer.c b/sound/core/timer.c
index b02681e..c8496c7 100644
--- a/sound/core/timer.c
+++ b/sound/core/timer.c
@@ -113,7 +113,7 @@
INIT_LIST_HEAD(&timeri->slave_active_head);
timeri->timer = timer;
- if (timer && timer->card && !try_module_get(timer->card->module)) {
+ if (timer && !try_module_get(timer->module)) {
kfree(timeri->owner);
kfree(timeri);
return NULL;
@@ -363,8 +363,8 @@
timeri->private_free(timeri);
kfree(timeri->owner);
kfree(timeri);
- if (timer && timer->card)
- module_put(timer->card->module);
+ if (timer)
+ module_put(timer->module);
return 0;
}
@@ -787,6 +787,7 @@
spin_lock_init(&timer->lock);
tasklet_init(&timer->task_queue, snd_timer_tasklet, (unsigned long)timer);
if (card != NULL) {
+ timer->module = card->module;
if ((err = snd_device_new(card, SNDRV_DEV_TIMER, timer, &ops)) < 0) {
snd_timer_free(timer);
return err;