[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>
This commit is contained in:
parent
2fd43d1159
commit
de24214d0c
|
@ -88,6 +88,7 @@ struct _snd_timer_hardware {
|
||||||
struct _snd_timer {
|
struct _snd_timer {
|
||||||
snd_timer_class_t tmr_class;
|
snd_timer_class_t tmr_class;
|
||||||
snd_card_t *card;
|
snd_card_t *card;
|
||||||
|
struct module *module;
|
||||||
int tmr_device;
|
int tmr_device;
|
||||||
int tmr_subdevice;
|
int tmr_subdevice;
|
||||||
char id[64];
|
char id[64];
|
||||||
|
|
|
@ -124,7 +124,8 @@ static int __init rtctimer_init(void)
|
||||||
|
|
||||||
if (rtctimer_freq < 2 || rtctimer_freq > 8192 ||
|
if (rtctimer_freq < 2 || rtctimer_freq > 8192 ||
|
||||||
(rtctimer_freq & (rtctimer_freq - 1)) != 0) {
|
(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;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -133,6 +134,7 @@ static int __init rtctimer_init(void)
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
|
timer->module = THIS_MODULE;
|
||||||
strcpy(timer->name, "RTC timer");
|
strcpy(timer->name, "RTC timer");
|
||||||
timer->hw = rtc_hw;
|
timer->hw = rtc_hw;
|
||||||
timer->hw.resolution = NANO_SEC / rtctimer_freq;
|
timer->hw.resolution = NANO_SEC / rtctimer_freq;
|
||||||
|
|
|
@ -113,7 +113,7 @@ static snd_timer_instance_t *snd_timer_instance_new(char *owner, snd_timer_t *ti
|
||||||
INIT_LIST_HEAD(&timeri->slave_active_head);
|
INIT_LIST_HEAD(&timeri->slave_active_head);
|
||||||
|
|
||||||
timeri->timer = timer;
|
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->owner);
|
||||||
kfree(timeri);
|
kfree(timeri);
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -363,8 +363,8 @@ int snd_timer_close(snd_timer_instance_t * timeri)
|
||||||
timeri->private_free(timeri);
|
timeri->private_free(timeri);
|
||||||
kfree(timeri->owner);
|
kfree(timeri->owner);
|
||||||
kfree(timeri);
|
kfree(timeri);
|
||||||
if (timer && timer->card)
|
if (timer)
|
||||||
module_put(timer->card->module);
|
module_put(timer->module);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -787,6 +787,7 @@ int snd_timer_new(snd_card_t *card, char *id, snd_timer_id_t *tid, snd_timer_t *
|
||||||
spin_lock_init(&timer->lock);
|
spin_lock_init(&timer->lock);
|
||||||
tasklet_init(&timer->task_queue, snd_timer_tasklet, (unsigned long)timer);
|
tasklet_init(&timer->task_queue, snd_timer_tasklet, (unsigned long)timer);
|
||||||
if (card != NULL) {
|
if (card != NULL) {
|
||||||
|
timer->module = card->module;
|
||||||
if ((err = snd_device_new(card, SNDRV_DEV_TIMER, timer, &ops)) < 0) {
|
if ((err = snd_device_new(card, SNDRV_DEV_TIMER, timer, &ops)) < 0) {
|
||||||
snd_timer_free(timer);
|
snd_timer_free(timer);
|
||||||
return err;
|
return err;
|
||||||
|
|
Loading…
Reference in New Issue