mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-08-23 17:30:02 +00:00
timers: Remove delayed irqwork from alarmtimers implementation
Thomas asked about the delayed irq work in the alarmtimers code, and I realized that it was a legacy from when the alarmtimer base lock was a mutex (due to concerns that we'd be interacting with the RTC device, which is protected by mutexes). Since the alarmtimer base is now protected by a spinlock, we can simply execute alarmtimer functions directly from the hrtimer callback. Should any future alarmtimer functions sleep, they can simply manage scheduling any delayed work themselves. CC: Thomas Gleixner <tglx@linutronix.de> Signed-off-by: John Stultz <john.stultz@linaro.org>
This commit is contained in:
parent
180bf812ce
commit
7068b7a162
1 changed files with 9 additions and 23 deletions
|
@ -33,7 +33,6 @@
|
||||||
* @timer: hrtimer used to schedule events while running
|
* @timer: hrtimer used to schedule events while running
|
||||||
* @gettime: Function to read the time correlating to the base
|
* @gettime: Function to read the time correlating to the base
|
||||||
* @base_clockid: clockid for the base
|
* @base_clockid: clockid for the base
|
||||||
* @irqwork Delayed work structure for expiring timers
|
|
||||||
*/
|
*/
|
||||||
static struct alarm_base {
|
static struct alarm_base {
|
||||||
spinlock_t lock;
|
spinlock_t lock;
|
||||||
|
@ -41,7 +40,6 @@ static struct alarm_base {
|
||||||
struct hrtimer timer;
|
struct hrtimer timer;
|
||||||
ktime_t (*gettime)(void);
|
ktime_t (*gettime)(void);
|
||||||
clockid_t base_clockid;
|
clockid_t base_clockid;
|
||||||
struct work_struct irqwork;
|
|
||||||
} alarm_bases[ALARM_NUMTYPE];
|
} alarm_bases[ALARM_NUMTYPE];
|
||||||
|
|
||||||
/* rtc timer and device for setting alarm wakeups at suspend */
|
/* rtc timer and device for setting alarm wakeups at suspend */
|
||||||
|
@ -97,22 +95,23 @@ static void alarmtimer_remove(struct alarm_base *base, struct alarm *alarm)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* alarmtimer_do_work - Handles alarm being fired.
|
* alarmtimer_fired - Handles alarm hrtimer being fired.
|
||||||
* @work: pointer to workqueue being run
|
* @timer: pointer to hrtimer being run
|
||||||
*
|
*
|
||||||
* When a alarm timer fires, this runs through the timerqueue to
|
* When a alarm timer fires, this runs through the timerqueue to
|
||||||
* see which alarms expired, and runs those. If there are more alarm
|
* see which alarms expired, and runs those. If there are more alarm
|
||||||
* timers queued for the future, we set the hrtimer to fire when
|
* timers queued for the future, we set the hrtimer to fire when
|
||||||
* when the next future alarm timer expires.
|
* when the next future alarm timer expires.
|
||||||
*/
|
*/
|
||||||
static void alarmtimer_do_work(struct work_struct *work)
|
static enum hrtimer_restart alarmtimer_fired(struct hrtimer *timer)
|
||||||
{
|
{
|
||||||
struct alarm_base *base = container_of(work, struct alarm_base,
|
struct alarm_base *base = container_of(timer, struct alarm_base, timer);
|
||||||
irqwork);
|
|
||||||
struct timerqueue_node *next;
|
struct timerqueue_node *next;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
ktime_t now;
|
ktime_t now;
|
||||||
|
int ret = HRTIMER_NORESTART;
|
||||||
|
|
||||||
spin_lock_irqsave(&base->lock, flags);
|
spin_lock_irqsave(&base->lock, flags);
|
||||||
now = base->gettime();
|
now = base->gettime();
|
||||||
|
@ -140,25 +139,13 @@ static void alarmtimer_do_work(struct work_struct *work)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (next) {
|
if (next) {
|
||||||
hrtimer_start(&base->timer, next->expires,
|
hrtimer_set_expires(&base->timer, next->expires);
|
||||||
HRTIMER_MODE_ABS);
|
ret = HRTIMER_RESTART;
|
||||||
}
|
}
|
||||||
spin_unlock_irqrestore(&base->lock, flags);
|
spin_unlock_irqrestore(&base->lock, flags);
|
||||||
}
|
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
|
||||||
/**
|
|
||||||
* alarmtimer_fired - Handles alarm hrtimer being fired.
|
|
||||||
* @timer: pointer to hrtimer being run
|
|
||||||
*
|
|
||||||
* When a timer fires, this schedules the do_work function to
|
|
||||||
* be run.
|
|
||||||
*/
|
|
||||||
static enum hrtimer_restart alarmtimer_fired(struct hrtimer *timer)
|
|
||||||
{
|
|
||||||
struct alarm_base *base = container_of(timer, struct alarm_base, timer);
|
|
||||||
schedule_work(&base->irqwork);
|
|
||||||
return HRTIMER_NORESTART;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -636,7 +623,6 @@ static int __init alarmtimer_init(void)
|
||||||
alarm_bases[i].base_clockid,
|
alarm_bases[i].base_clockid,
|
||||||
HRTIMER_MODE_ABS);
|
HRTIMER_MODE_ABS);
|
||||||
alarm_bases[i].timer.function = alarmtimer_fired;
|
alarm_bases[i].timer.function = alarmtimer_fired;
|
||||||
INIT_WORK(&alarm_bases[i].irqwork, alarmtimer_do_work);
|
|
||||||
}
|
}
|
||||||
error = platform_driver_register(&alarmtimer_driver);
|
error = platform_driver_register(&alarmtimer_driver);
|
||||||
platform_device_register_simple("alarmtimer", -1, NULL, 0);
|
platform_device_register_simple("alarmtimer", -1, NULL, 0);
|
||||||
|
|
Loading…
Reference in a new issue