Commit 6a9f264c authored by Samuel Ortiz's avatar Samuel Ortiz Committed by Juha Yrjola

IDLETIMER: We shouldn't sleep in the timer routine

Currently, IDLETIMER timer routine calls kobject_uevent, which might sleep.
Since we are in interrupt context, we now schedule a work when the timer
expires. This calls sysfs_notify() for notifying userspace.
Signed-off-by: default avatarSamuel Ortiz <samuel.ortiz@solidboot.com>
Signed-off-by: default avatarJuha Yrjola <juha.yrjola@solidboot.com>
parent af2ee19e
...@@ -43,6 +43,7 @@ struct utimer_t { ...@@ -43,6 +43,7 @@ struct utimer_t {
char name[IFNAMSIZ]; char name[IFNAMSIZ];
struct list_head entry; struct list_head entry;
struct timer_list timer; struct timer_list timer;
struct work_struct work;
}; };
static LIST_HEAD(active_utimer_head); static LIST_HEAD(active_utimer_head);
...@@ -58,23 +59,31 @@ static void utimer_delete(struct utimer_t *timer) ...@@ -58,23 +59,31 @@ static void utimer_delete(struct utimer_t *timer)
kfree(timer); kfree(timer);
} }
static void utimer_expired(unsigned long data) static void utimer_work(void * data)
{ {
struct utimer_t *timer = (struct utimer_t *) data; struct utimer_t *timer = (struct utimer_t *) data;
struct net_device *netdev; struct net_device *netdev;
DEBUGP("Timer '%s' expired\n", timer->name);
netdev = dev_get_by_name(timer->name); netdev = dev_get_by_name(timer->name);
if (netdev != NULL) {
sysfs_notify(&netdev->class_dev.kobj, NULL,
"idletimer");
dev_put(netdev);
}
}
static void utimer_expired(unsigned long data)
{
struct utimer_t *timer = (struct utimer_t *) data;
DEBUGP("Timer '%s' expired\n", timer->name);
spin_lock_bh(&list_lock); spin_lock_bh(&list_lock);
utimer_delete(timer); utimer_delete(timer);
spin_unlock_bh(&list_lock); spin_unlock_bh(&list_lock);
if (netdev != NULL) { schedule_work(&timer->work);
kobject_uevent(&netdev->class_dev.kobj,
KOBJ_CHANGE);
dev_put(netdev);
}
} }
static struct utimer_t *utimer_create(const char *name) static struct utimer_t *utimer_create(const char *name)
...@@ -92,6 +101,8 @@ static struct utimer_t *utimer_create(const char *name) ...@@ -92,6 +101,8 @@ static struct utimer_t *utimer_create(const char *name)
timer->timer.function = utimer_expired; timer->timer.function = utimer_expired;
timer->timer.data = (unsigned long) timer; timer->timer.data = (unsigned long) timer;
INIT_WORK(&timer->work, utimer_work, timer);
DEBUGP("Created timer '%s'\n", timer->name); DEBUGP("Created timer '%s'\n", timer->name);
return timer; return timer;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment