On Thu, 1 Jul 2010, Rafael J. Wysocki wrote: > I invented a slightly different version in the meantime, which is appended > as a patch on top of the original one (I don't want to modify the original > patch, since it's been reviewed already by several people and went to my > linux-next branch). > /** > - * pm_wakeup_work_fn - Deferred closing of a wakeup event. > + * pm_wakeup_timer_fn - Deferred closing of a wakeup event. > * > * Execute pm_relax() for a wakeup event detected in the past and free the > * work item object used for queuing up the work. > */ > -static void pm_wakeup_work_fn(struct work_struct *work) > +static void pm_wakeup_timer_fn(unsigned long data) > { > - struct delayed_work *dwork = to_delayed_work(work); > + unsigned long flags; > > - pm_relax(); > - kfree(dwork); > + spin_lock_irqsave(&events_lock, flags); > + if (events_timer_expires && time_after(jiffies, events_timer_expires)) { Should be time_after_eq. > + events_in_progress -= delayed_count; > + event_count += delayed_count; > + delayed_count = 0; > + events_timer_expires = 0; > + } > + spin_unlock_irqrestore(&events_lock, flags); > } > > /** > @@ -132,19 +145,31 @@ static void pm_wakeup_work_fn(struct wor > void pm_wakeup_event(struct device *dev, unsigned int msec) > { > unsigned long flags; > - struct delayed_work *dwork; > - > - dwork = msec ? kzalloc(sizeof(*dwork), GFP_ATOMIC) : NULL; > > spin_lock_irqsave(&events_lock, flags); > if (dev) > dev->power.wakeup_count++; > > - if (dwork) { > - INIT_DELAYED_WORK(dwork, pm_wakeup_work_fn); > - schedule_delayed_work(dwork, msecs_to_jiffies(msec)); > + if (msec) { > + ktime_t kt; > + struct timespec ts; > + unsigned long expires; > + > + kt = ktime_get(); > + kt = ktime_add_ns(kt, msec * NSEC_PER_MSEC); > + ts = ktime_to_timespec(kt); > + expires = timespec_to_jiffies(&ts); Is this somehow better than jiffies + msecs_to_jiffies(msec)? > + if (!expires) > + expires = 1; > + > + if (!events_timer_expires > + || time_after(expires, events_timer_expires)) { > + mod_timer(&events_timer, expires); > + events_timer_expires = expires; > + } > > events_in_progress++; > + delayed_count++; > } else { > event_count++; > } Alan Stern _______________________________________________ linux-pm mailing list linux-pm@xxxxxxxxxxxxxxxxxxxxxxxxxx https://lists.linux-foundation.org/mailman/listinfo/linux-pm