Re: [RFC v3 2/3] kernel/time/clockevents: make setting of ->mult and ->mult_mono atomic
On Thu, Jul 21, 2016 at 12:24 PM, Nicolai Stangewrote: > John Stultz writes: > >> On Wed, Jul 13, 2016 at 6:00 AM, Nicolai Stange wrote: >>> In order to avoid races between setting a struct clock_event_device's >>> ->mult_mono in clockevents_update_freq() and yet to be implemented updates >>> triggered from the timekeeping core, the setting of ->mult and ->mult_mono >>> should be made atomic. >>> >>> Protect the update in clockevents_update_freq() by locking the >>> clockevents_lock spinlock. Frequency updates are expected to be done >>> seldomly and thus, taking this subsystem lock should not have any impact >>> on performance. >>> >>> Use a raw_spin_lock_irq_save()/raw_spin_unlock_irq_restore() pair for >>> locking/unlocking the clockevents_lock spinlock. >>> Purge the now redundant local_irq_save()/local_irq_restore() pair from >>> clockevents_update_freq(). Since the call to tick_broadcast_update_freq() >>> isn't done with interrupts disabled anymore, its >>> raw_spin_lock()/raw_spin_unlock() pair must be converted to >>> raw_spin_lock_irq_save()/raw_spin_unlock_irq_restore(). >>> >>> Signed-off-by: Nicolai Stange >>> --- >>> kernel/time/clockevents.c| 7 --- >>> kernel/time/tick-broadcast.c | 5 +++-- >>> 2 files changed, 7 insertions(+), 5 deletions(-) >>> >>> diff --git a/kernel/time/clockevents.c b/kernel/time/clockevents.c >>> index ba7fea4..ec01375 100644 >>> --- a/kernel/time/clockevents.c >>> +++ b/kernel/time/clockevents.c >>> @@ -589,11 +589,12 @@ int clockevents_update_freq(struct clock_event_device >>> *dev, u32 freq) >>> unsigned long flags; >>> int ret; >>> >>> - local_irq_save(flags); >>> ret = tick_broadcast_update_freq(dev, freq); >>> - if (ret == -ENODEV) >>> + if (ret == -ENODEV) { >>> + raw_spin_lock_irqsave(_lock, flags); >>> ret = __clockevents_update_freq(dev, freq); >>> - local_irq_restore(flags); >>> + raw_spin_unlock_irqrestore(_lock, flags); >>> + } >>> return ret; >>> } >>> >>> diff --git a/kernel/time/tick-broadcast.c b/kernel/time/tick-broadcast.c >>> index f6aae79..9c94c41 100644 >>> --- a/kernel/time/tick-broadcast.c >>> +++ b/kernel/time/tick-broadcast.c >>> @@ -125,11 +125,12 @@ int tick_is_broadcast_device(struct >>> clock_event_device *dev) >>> int tick_broadcast_update_freq(struct clock_event_device *dev, u32 freq) >>> { >>> int ret = -ENODEV; >>> + unsigned long flags; >>> >>> if (tick_is_broadcast_device(dev)) { >>> - raw_spin_lock(_broadcast_lock); >>> + raw_spin_lock_irqsave(_broadcast_lock, flags); >>> ret = __clockevents_update_freq(dev, freq); >>> - raw_spin_unlock(_broadcast_lock); >>> + raw_spin_unlock_irqrestore(_broadcast_lock, flags); >>> } >> >> >> So not necessarily part of your change, but this makes using >> tick_broadcast_update_freq() seem strange. >> >> We call it and if dev is a broadcast_device we call >> __clockevents_update_freq(), and if not, it fails and we then just >> call __clockevents_update_freq() again? > > Yes, but the first call is made under a different lock than the second > one. Ah. Thanks, that bit didn't stick out to me. -john
Re: [RFC v3 2/3] kernel/time/clockevents: make setting of ->mult and ->mult_mono atomic
On Thu, Jul 21, 2016 at 12:24 PM, Nicolai Stange wrote: > John Stultz writes: > >> On Wed, Jul 13, 2016 at 6:00 AM, Nicolai Stange wrote: >>> In order to avoid races between setting a struct clock_event_device's >>> ->mult_mono in clockevents_update_freq() and yet to be implemented updates >>> triggered from the timekeeping core, the setting of ->mult and ->mult_mono >>> should be made atomic. >>> >>> Protect the update in clockevents_update_freq() by locking the >>> clockevents_lock spinlock. Frequency updates are expected to be done >>> seldomly and thus, taking this subsystem lock should not have any impact >>> on performance. >>> >>> Use a raw_spin_lock_irq_save()/raw_spin_unlock_irq_restore() pair for >>> locking/unlocking the clockevents_lock spinlock. >>> Purge the now redundant local_irq_save()/local_irq_restore() pair from >>> clockevents_update_freq(). Since the call to tick_broadcast_update_freq() >>> isn't done with interrupts disabled anymore, its >>> raw_spin_lock()/raw_spin_unlock() pair must be converted to >>> raw_spin_lock_irq_save()/raw_spin_unlock_irq_restore(). >>> >>> Signed-off-by: Nicolai Stange >>> --- >>> kernel/time/clockevents.c| 7 --- >>> kernel/time/tick-broadcast.c | 5 +++-- >>> 2 files changed, 7 insertions(+), 5 deletions(-) >>> >>> diff --git a/kernel/time/clockevents.c b/kernel/time/clockevents.c >>> index ba7fea4..ec01375 100644 >>> --- a/kernel/time/clockevents.c >>> +++ b/kernel/time/clockevents.c >>> @@ -589,11 +589,12 @@ int clockevents_update_freq(struct clock_event_device >>> *dev, u32 freq) >>> unsigned long flags; >>> int ret; >>> >>> - local_irq_save(flags); >>> ret = tick_broadcast_update_freq(dev, freq); >>> - if (ret == -ENODEV) >>> + if (ret == -ENODEV) { >>> + raw_spin_lock_irqsave(_lock, flags); >>> ret = __clockevents_update_freq(dev, freq); >>> - local_irq_restore(flags); >>> + raw_spin_unlock_irqrestore(_lock, flags); >>> + } >>> return ret; >>> } >>> >>> diff --git a/kernel/time/tick-broadcast.c b/kernel/time/tick-broadcast.c >>> index f6aae79..9c94c41 100644 >>> --- a/kernel/time/tick-broadcast.c >>> +++ b/kernel/time/tick-broadcast.c >>> @@ -125,11 +125,12 @@ int tick_is_broadcast_device(struct >>> clock_event_device *dev) >>> int tick_broadcast_update_freq(struct clock_event_device *dev, u32 freq) >>> { >>> int ret = -ENODEV; >>> + unsigned long flags; >>> >>> if (tick_is_broadcast_device(dev)) { >>> - raw_spin_lock(_broadcast_lock); >>> + raw_spin_lock_irqsave(_broadcast_lock, flags); >>> ret = __clockevents_update_freq(dev, freq); >>> - raw_spin_unlock(_broadcast_lock); >>> + raw_spin_unlock_irqrestore(_broadcast_lock, flags); >>> } >> >> >> So not necessarily part of your change, but this makes using >> tick_broadcast_update_freq() seem strange. >> >> We call it and if dev is a broadcast_device we call >> __clockevents_update_freq(), and if not, it fails and we then just >> call __clockevents_update_freq() again? > > Yes, but the first call is made under a different lock than the second > one. Ah. Thanks, that bit didn't stick out to me. -john
Re: [RFC v3 2/3] kernel/time/clockevents: make setting of ->mult and ->mult_mono atomic
John Stultzwrites: > On Wed, Jul 13, 2016 at 6:00 AM, Nicolai Stange wrote: >> In order to avoid races between setting a struct clock_event_device's >> ->mult_mono in clockevents_update_freq() and yet to be implemented updates >> triggered from the timekeeping core, the setting of ->mult and ->mult_mono >> should be made atomic. >> >> Protect the update in clockevents_update_freq() by locking the >> clockevents_lock spinlock. Frequency updates are expected to be done >> seldomly and thus, taking this subsystem lock should not have any impact >> on performance. >> >> Use a raw_spin_lock_irq_save()/raw_spin_unlock_irq_restore() pair for >> locking/unlocking the clockevents_lock spinlock. >> Purge the now redundant local_irq_save()/local_irq_restore() pair from >> clockevents_update_freq(). Since the call to tick_broadcast_update_freq() >> isn't done with interrupts disabled anymore, its >> raw_spin_lock()/raw_spin_unlock() pair must be converted to >> raw_spin_lock_irq_save()/raw_spin_unlock_irq_restore(). >> >> Signed-off-by: Nicolai Stange >> --- >> kernel/time/clockevents.c| 7 --- >> kernel/time/tick-broadcast.c | 5 +++-- >> 2 files changed, 7 insertions(+), 5 deletions(-) >> >> diff --git a/kernel/time/clockevents.c b/kernel/time/clockevents.c >> index ba7fea4..ec01375 100644 >> --- a/kernel/time/clockevents.c >> +++ b/kernel/time/clockevents.c >> @@ -589,11 +589,12 @@ int clockevents_update_freq(struct clock_event_device >> *dev, u32 freq) >> unsigned long flags; >> int ret; >> >> - local_irq_save(flags); >> ret = tick_broadcast_update_freq(dev, freq); >> - if (ret == -ENODEV) >> + if (ret == -ENODEV) { >> + raw_spin_lock_irqsave(_lock, flags); >> ret = __clockevents_update_freq(dev, freq); >> - local_irq_restore(flags); >> + raw_spin_unlock_irqrestore(_lock, flags); >> + } >> return ret; >> } >> >> diff --git a/kernel/time/tick-broadcast.c b/kernel/time/tick-broadcast.c >> index f6aae79..9c94c41 100644 >> --- a/kernel/time/tick-broadcast.c >> +++ b/kernel/time/tick-broadcast.c >> @@ -125,11 +125,12 @@ int tick_is_broadcast_device(struct clock_event_device >> *dev) >> int tick_broadcast_update_freq(struct clock_event_device *dev, u32 freq) >> { >> int ret = -ENODEV; >> + unsigned long flags; >> >> if (tick_is_broadcast_device(dev)) { >> - raw_spin_lock(_broadcast_lock); >> + raw_spin_lock_irqsave(_broadcast_lock, flags); >> ret = __clockevents_update_freq(dev, freq); >> - raw_spin_unlock(_broadcast_lock); >> + raw_spin_unlock_irqrestore(_broadcast_lock, flags); >> } > > > So not necessarily part of your change, but this makes using > tick_broadcast_update_freq() seem strange. > > We call it and if dev is a broadcast_device we call > __clockevents_update_freq(), and if not, it fails and we then just > call __clockevents_update_freq() again? Yes, but the first call is made under a different lock than the second one. > > Why bother calling tick_broadcast_update_freq here, and instead just > call __clockevents_update_freq() directly the first time? Thanks, Nicolai
Re: [RFC v3 2/3] kernel/time/clockevents: make setting of ->mult and ->mult_mono atomic
John Stultz writes: > On Wed, Jul 13, 2016 at 6:00 AM, Nicolai Stange wrote: >> In order to avoid races between setting a struct clock_event_device's >> ->mult_mono in clockevents_update_freq() and yet to be implemented updates >> triggered from the timekeeping core, the setting of ->mult and ->mult_mono >> should be made atomic. >> >> Protect the update in clockevents_update_freq() by locking the >> clockevents_lock spinlock. Frequency updates are expected to be done >> seldomly and thus, taking this subsystem lock should not have any impact >> on performance. >> >> Use a raw_spin_lock_irq_save()/raw_spin_unlock_irq_restore() pair for >> locking/unlocking the clockevents_lock spinlock. >> Purge the now redundant local_irq_save()/local_irq_restore() pair from >> clockevents_update_freq(). Since the call to tick_broadcast_update_freq() >> isn't done with interrupts disabled anymore, its >> raw_spin_lock()/raw_spin_unlock() pair must be converted to >> raw_spin_lock_irq_save()/raw_spin_unlock_irq_restore(). >> >> Signed-off-by: Nicolai Stange >> --- >> kernel/time/clockevents.c| 7 --- >> kernel/time/tick-broadcast.c | 5 +++-- >> 2 files changed, 7 insertions(+), 5 deletions(-) >> >> diff --git a/kernel/time/clockevents.c b/kernel/time/clockevents.c >> index ba7fea4..ec01375 100644 >> --- a/kernel/time/clockevents.c >> +++ b/kernel/time/clockevents.c >> @@ -589,11 +589,12 @@ int clockevents_update_freq(struct clock_event_device >> *dev, u32 freq) >> unsigned long flags; >> int ret; >> >> - local_irq_save(flags); >> ret = tick_broadcast_update_freq(dev, freq); >> - if (ret == -ENODEV) >> + if (ret == -ENODEV) { >> + raw_spin_lock_irqsave(_lock, flags); >> ret = __clockevents_update_freq(dev, freq); >> - local_irq_restore(flags); >> + raw_spin_unlock_irqrestore(_lock, flags); >> + } >> return ret; >> } >> >> diff --git a/kernel/time/tick-broadcast.c b/kernel/time/tick-broadcast.c >> index f6aae79..9c94c41 100644 >> --- a/kernel/time/tick-broadcast.c >> +++ b/kernel/time/tick-broadcast.c >> @@ -125,11 +125,12 @@ int tick_is_broadcast_device(struct clock_event_device >> *dev) >> int tick_broadcast_update_freq(struct clock_event_device *dev, u32 freq) >> { >> int ret = -ENODEV; >> + unsigned long flags; >> >> if (tick_is_broadcast_device(dev)) { >> - raw_spin_lock(_broadcast_lock); >> + raw_spin_lock_irqsave(_broadcast_lock, flags); >> ret = __clockevents_update_freq(dev, freq); >> - raw_spin_unlock(_broadcast_lock); >> + raw_spin_unlock_irqrestore(_broadcast_lock, flags); >> } > > > So not necessarily part of your change, but this makes using > tick_broadcast_update_freq() seem strange. > > We call it and if dev is a broadcast_device we call > __clockevents_update_freq(), and if not, it fails and we then just > call __clockevents_update_freq() again? Yes, but the first call is made under a different lock than the second one. > > Why bother calling tick_broadcast_update_freq here, and instead just > call __clockevents_update_freq() directly the first time? Thanks, Nicolai
Re: [RFC v3 2/3] kernel/time/clockevents: make setting of ->mult and ->mult_mono atomic
On Wed, Jul 13, 2016 at 6:00 AM, Nicolai Stangewrote: > In order to avoid races between setting a struct clock_event_device's > ->mult_mono in clockevents_update_freq() and yet to be implemented updates > triggered from the timekeeping core, the setting of ->mult and ->mult_mono > should be made atomic. > > Protect the update in clockevents_update_freq() by locking the > clockevents_lock spinlock. Frequency updates are expected to be done > seldomly and thus, taking this subsystem lock should not have any impact > on performance. > > Use a raw_spin_lock_irq_save()/raw_spin_unlock_irq_restore() pair for > locking/unlocking the clockevents_lock spinlock. > Purge the now redundant local_irq_save()/local_irq_restore() pair from > clockevents_update_freq(). Since the call to tick_broadcast_update_freq() > isn't done with interrupts disabled anymore, its > raw_spin_lock()/raw_spin_unlock() pair must be converted to > raw_spin_lock_irq_save()/raw_spin_unlock_irq_restore(). > > Signed-off-by: Nicolai Stange > --- > kernel/time/clockevents.c| 7 --- > kernel/time/tick-broadcast.c | 5 +++-- > 2 files changed, 7 insertions(+), 5 deletions(-) > > diff --git a/kernel/time/clockevents.c b/kernel/time/clockevents.c > index ba7fea4..ec01375 100644 > --- a/kernel/time/clockevents.c > +++ b/kernel/time/clockevents.c > @@ -589,11 +589,12 @@ int clockevents_update_freq(struct clock_event_device > *dev, u32 freq) > unsigned long flags; > int ret; > > - local_irq_save(flags); > ret = tick_broadcast_update_freq(dev, freq); > - if (ret == -ENODEV) > + if (ret == -ENODEV) { > + raw_spin_lock_irqsave(_lock, flags); > ret = __clockevents_update_freq(dev, freq); > - local_irq_restore(flags); > + raw_spin_unlock_irqrestore(_lock, flags); > + } > return ret; > } > > diff --git a/kernel/time/tick-broadcast.c b/kernel/time/tick-broadcast.c > index f6aae79..9c94c41 100644 > --- a/kernel/time/tick-broadcast.c > +++ b/kernel/time/tick-broadcast.c > @@ -125,11 +125,12 @@ int tick_is_broadcast_device(struct clock_event_device > *dev) > int tick_broadcast_update_freq(struct clock_event_device *dev, u32 freq) > { > int ret = -ENODEV; > + unsigned long flags; > > if (tick_is_broadcast_device(dev)) { > - raw_spin_lock(_broadcast_lock); > + raw_spin_lock_irqsave(_broadcast_lock, flags); > ret = __clockevents_update_freq(dev, freq); > - raw_spin_unlock(_broadcast_lock); > + raw_spin_unlock_irqrestore(_broadcast_lock, flags); > } So not necessarily part of your change, but this makes using tick_broadcast_update_freq() seem strange. We call it and if dev is a broadcast_device we call __clockevents_update_freq(), and if not, it fails and we then just call __clockevents_update_freq() again? Why bother calling tick_broadcast_update_freq here, and instead just call __clockevents_update_freq() directly the first time? thanks -john
Re: [RFC v3 2/3] kernel/time/clockevents: make setting of ->mult and ->mult_mono atomic
On Wed, Jul 13, 2016 at 6:00 AM, Nicolai Stange wrote: > In order to avoid races between setting a struct clock_event_device's > ->mult_mono in clockevents_update_freq() and yet to be implemented updates > triggered from the timekeeping core, the setting of ->mult and ->mult_mono > should be made atomic. > > Protect the update in clockevents_update_freq() by locking the > clockevents_lock spinlock. Frequency updates are expected to be done > seldomly and thus, taking this subsystem lock should not have any impact > on performance. > > Use a raw_spin_lock_irq_save()/raw_spin_unlock_irq_restore() pair for > locking/unlocking the clockevents_lock spinlock. > Purge the now redundant local_irq_save()/local_irq_restore() pair from > clockevents_update_freq(). Since the call to tick_broadcast_update_freq() > isn't done with interrupts disabled anymore, its > raw_spin_lock()/raw_spin_unlock() pair must be converted to > raw_spin_lock_irq_save()/raw_spin_unlock_irq_restore(). > > Signed-off-by: Nicolai Stange > --- > kernel/time/clockevents.c| 7 --- > kernel/time/tick-broadcast.c | 5 +++-- > 2 files changed, 7 insertions(+), 5 deletions(-) > > diff --git a/kernel/time/clockevents.c b/kernel/time/clockevents.c > index ba7fea4..ec01375 100644 > --- a/kernel/time/clockevents.c > +++ b/kernel/time/clockevents.c > @@ -589,11 +589,12 @@ int clockevents_update_freq(struct clock_event_device > *dev, u32 freq) > unsigned long flags; > int ret; > > - local_irq_save(flags); > ret = tick_broadcast_update_freq(dev, freq); > - if (ret == -ENODEV) > + if (ret == -ENODEV) { > + raw_spin_lock_irqsave(_lock, flags); > ret = __clockevents_update_freq(dev, freq); > - local_irq_restore(flags); > + raw_spin_unlock_irqrestore(_lock, flags); > + } > return ret; > } > > diff --git a/kernel/time/tick-broadcast.c b/kernel/time/tick-broadcast.c > index f6aae79..9c94c41 100644 > --- a/kernel/time/tick-broadcast.c > +++ b/kernel/time/tick-broadcast.c > @@ -125,11 +125,12 @@ int tick_is_broadcast_device(struct clock_event_device > *dev) > int tick_broadcast_update_freq(struct clock_event_device *dev, u32 freq) > { > int ret = -ENODEV; > + unsigned long flags; > > if (tick_is_broadcast_device(dev)) { > - raw_spin_lock(_broadcast_lock); > + raw_spin_lock_irqsave(_broadcast_lock, flags); > ret = __clockevents_update_freq(dev, freq); > - raw_spin_unlock(_broadcast_lock); > + raw_spin_unlock_irqrestore(_broadcast_lock, flags); > } So not necessarily part of your change, but this makes using tick_broadcast_update_freq() seem strange. We call it and if dev is a broadcast_device we call __clockevents_update_freq(), and if not, it fails and we then just call __clockevents_update_freq() again? Why bother calling tick_broadcast_update_freq here, and instead just call __clockevents_update_freq() directly the first time? thanks -john
[RFC v3 2/3] kernel/time/clockevents: make setting of ->mult and ->mult_mono atomic
In order to avoid races between setting a struct clock_event_device's ->mult_mono in clockevents_update_freq() and yet to be implemented updates triggered from the timekeeping core, the setting of ->mult and ->mult_mono should be made atomic. Protect the update in clockevents_update_freq() by locking the clockevents_lock spinlock. Frequency updates are expected to be done seldomly and thus, taking this subsystem lock should not have any impact on performance. Use a raw_spin_lock_irq_save()/raw_spin_unlock_irq_restore() pair for locking/unlocking the clockevents_lock spinlock. Purge the now redundant local_irq_save()/local_irq_restore() pair from clockevents_update_freq(). Since the call to tick_broadcast_update_freq() isn't done with interrupts disabled anymore, its raw_spin_lock()/raw_spin_unlock() pair must be converted to raw_spin_lock_irq_save()/raw_spin_unlock_irq_restore(). Signed-off-by: Nicolai Stange--- kernel/time/clockevents.c| 7 --- kernel/time/tick-broadcast.c | 5 +++-- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/kernel/time/clockevents.c b/kernel/time/clockevents.c index ba7fea4..ec01375 100644 --- a/kernel/time/clockevents.c +++ b/kernel/time/clockevents.c @@ -589,11 +589,12 @@ int clockevents_update_freq(struct clock_event_device *dev, u32 freq) unsigned long flags; int ret; - local_irq_save(flags); ret = tick_broadcast_update_freq(dev, freq); - if (ret == -ENODEV) + if (ret == -ENODEV) { + raw_spin_lock_irqsave(_lock, flags); ret = __clockevents_update_freq(dev, freq); - local_irq_restore(flags); + raw_spin_unlock_irqrestore(_lock, flags); + } return ret; } diff --git a/kernel/time/tick-broadcast.c b/kernel/time/tick-broadcast.c index f6aae79..9c94c41 100644 --- a/kernel/time/tick-broadcast.c +++ b/kernel/time/tick-broadcast.c @@ -125,11 +125,12 @@ int tick_is_broadcast_device(struct clock_event_device *dev) int tick_broadcast_update_freq(struct clock_event_device *dev, u32 freq) { int ret = -ENODEV; + unsigned long flags; if (tick_is_broadcast_device(dev)) { - raw_spin_lock(_broadcast_lock); + raw_spin_lock_irqsave(_broadcast_lock, flags); ret = __clockevents_update_freq(dev, freq); - raw_spin_unlock(_broadcast_lock); + raw_spin_unlock_irqrestore(_broadcast_lock, flags); } return ret; } -- 2.9.0
[RFC v3 2/3] kernel/time/clockevents: make setting of ->mult and ->mult_mono atomic
In order to avoid races between setting a struct clock_event_device's ->mult_mono in clockevents_update_freq() and yet to be implemented updates triggered from the timekeeping core, the setting of ->mult and ->mult_mono should be made atomic. Protect the update in clockevents_update_freq() by locking the clockevents_lock spinlock. Frequency updates are expected to be done seldomly and thus, taking this subsystem lock should not have any impact on performance. Use a raw_spin_lock_irq_save()/raw_spin_unlock_irq_restore() pair for locking/unlocking the clockevents_lock spinlock. Purge the now redundant local_irq_save()/local_irq_restore() pair from clockevents_update_freq(). Since the call to tick_broadcast_update_freq() isn't done with interrupts disabled anymore, its raw_spin_lock()/raw_spin_unlock() pair must be converted to raw_spin_lock_irq_save()/raw_spin_unlock_irq_restore(). Signed-off-by: Nicolai Stange --- kernel/time/clockevents.c| 7 --- kernel/time/tick-broadcast.c | 5 +++-- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/kernel/time/clockevents.c b/kernel/time/clockevents.c index ba7fea4..ec01375 100644 --- a/kernel/time/clockevents.c +++ b/kernel/time/clockevents.c @@ -589,11 +589,12 @@ int clockevents_update_freq(struct clock_event_device *dev, u32 freq) unsigned long flags; int ret; - local_irq_save(flags); ret = tick_broadcast_update_freq(dev, freq); - if (ret == -ENODEV) + if (ret == -ENODEV) { + raw_spin_lock_irqsave(_lock, flags); ret = __clockevents_update_freq(dev, freq); - local_irq_restore(flags); + raw_spin_unlock_irqrestore(_lock, flags); + } return ret; } diff --git a/kernel/time/tick-broadcast.c b/kernel/time/tick-broadcast.c index f6aae79..9c94c41 100644 --- a/kernel/time/tick-broadcast.c +++ b/kernel/time/tick-broadcast.c @@ -125,11 +125,12 @@ int tick_is_broadcast_device(struct clock_event_device *dev) int tick_broadcast_update_freq(struct clock_event_device *dev, u32 freq) { int ret = -ENODEV; + unsigned long flags; if (tick_is_broadcast_device(dev)) { - raw_spin_lock(_broadcast_lock); + raw_spin_lock_irqsave(_broadcast_lock, flags); ret = __clockevents_update_freq(dev, freq); - raw_spin_unlock(_broadcast_lock); + raw_spin_unlock_irqrestore(_broadcast_lock, flags); } return ret; } -- 2.9.0