Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > linux.kernel > #1724178 > unrolled thread

[PATCH 00/25] hrtimer: Provide softirq context hrtimers

Started byAnna-Maria Gleixner <anna-maria@linutronix.de>
First post2017-08-31 14:30 +0200
Last post2017-08-31 14:40 +0200
Articles 15 on this page of 35 — 8 participants

Back to article view | Back to linux.kernel


Contents

  [PATCH 00/25] hrtimer: Provide softirq context hrtimers Anna-Maria Gleixner <anna-maria@linutronix.de> - 2017-08-31 14:30 +0200
    [PATCH 07/25] hrtimer: Reduce conditional code (hres_active) Anna-Maria Gleixner <anna-maria@linutronix.de> - 2017-08-31 14:30 +0200
    [PATCH 05/25] hrtimer: Switch for loop to _ffs() evaluation Anna-Maria Gleixner <anna-maria@linutronix.de> - 2017-08-31 14:30 +0200
    [PATCH 24/25] net/cdc_ncm: Replace tasklet with softirq hrtimer Anna-Maria Gleixner <anna-maria@linutronix.de> - 2017-08-31 14:30 +0200
      Re: [PATCH 24/25] net/cdc_ncm: Replace tasklet with softirq hrtimer Greg Kroah-Hartman <gregkh@linuxfoundation.org> - 2017-08-31 15:40 +0200
      Re: [PATCH 24/25] net/cdc_ncm: Replace tasklet with softirq hrtimer Bjørn Mork <bjorn@mork.no> - 2017-08-31 16:00 +0200
        [PATCH 24/25 v2] net/cdc_ncm: Replace tasklet with softirq hrtimer Sebastian Andrzej Siewior <bigeasy@linutronix.de> - 2017-09-05 17:50 +0200
    [PATCH 23/25] ALSA/dummy: Replace tasklet with softirq hrtimer Anna-Maria Gleixner <anna-maria@linutronix.de> - 2017-08-31 14:30 +0200
      Re: [PATCH 23/25] ALSA/dummy: Replace tasklet with softirq hrtimer Takashi Iwai <tiwai@suse.de> - 2017-08-31 16:30 +0200
      Re: [PATCH 23/25] ALSA/dummy: Replace tasklet with softirq hrtimer Takashi Sakamoto <o-takashi@sakamocchi.jp> - 2017-08-31 16:30 +0200
      Re: [PATCH 23/25] ALSA/dummy: Replace tasklet with softirq hrtimer Takashi Iwai <tiwai@suse.de> - 2017-08-31 17:40 +0200
        Re: [PATCH 23/25] ALSA/dummy: Replace tasklet with softirq hrtimer Takashi Sakamoto <o-takashi@sakamocchi.jp> - 2017-09-01 12:30 +0200
          Re: [PATCH 23/25] ALSA/dummy: Replace tasklet with softirq hrtimer Takashi Iwai <tiwai@suse.de> - 2017-09-01 14:00 +0200
            Re: [PATCH 23/25] ALSA/dummy: Replace tasklet with softirq hrtimer Takashi Sakamoto <o-takashi@sakamocchi.jp> - 2017-09-02 03:30 +0200
              Re: [PATCH 23/25] ALSA/dummy: Replace tasklet with softirq hrtimer Takashi Sakamoto <o-takashi@sakamocchi.jp> - 2017-09-04 14:50 +0200
              [PATCH 23/25 v2] ALSA/dummy: Replace tasklet with softirq hrtimer Sebastian Andrzej Siewior <bigeasy@linutronix.de> - 2017-09-05 18:00 +0200
                Re: [PATCH 23/25 v2] ALSA/dummy: Replace tasklet with softirq hrtimer Takashi Iwai <tiwai@suse.de> - 2017-09-05 18:10 +0200
                Re: [PATCH 23/25 v2] ALSA/dummy: Replace tasklet with softirq hrtimer Takashi Sakamoto <o-takashi@sakamocchi.jp> - 2017-09-05 18:10 +0200
                  [PATCH 23/25 v3] ALSA/dummy: Replace tasklet with softirq hrtimer Sebastian Andrzej Siewior <bigeasy@linutronix.de> - 2017-09-05 18:20 +0200
                    Re: [PATCH 23/25 v3] ALSA/dummy: Replace tasklet with softirq hrtimer Takashi Sakamoto <o-takashi@sakamocchi.jp> - 2017-09-06 06:40 +0200
                      Re: [alsa-devel] [PATCH 23/25 v3] ALSA/dummy: Replace tasklet with     softirq hrtimer Takashi Iwai <tiwai@suse.de> - 2017-09-08 10:30 +0200
    [PATCH 22/25] softirq: Remove tasklet_hrtimer Anna-Maria Gleixner <anna-maria@linutronix.de> - 2017-08-31 14:30 +0200
    [PATCH 21/25] xfrm: Replace hrtimer tasklet with softirq hrtimer Anna-Maria Gleixner <anna-maria@linutronix.de> - 2017-08-31 14:30 +0200
    [PATCH 06/25] hrtimer: Store running timer in hrtimer_clock_base Anna-Maria Gleixner <anna-maria@linutronix.de> - 2017-08-31 14:30 +0200
    [PATCH 19/25] can/bcm: Replace hrtimer_tasklet with softirq based  hrtimer Anna-Maria Gleixner <anna-maria@linutronix.de> - 2017-08-31 14:30 +0200
      Re: [PATCH 19/25] can/bcm: Replace hrtimer_tasklet with softirq  based hrtimer Thomas Gleixner <tglx@linutronix.de> - 2017-09-01 18:00 +0200
        Re: [PATCH 19/25] can/bcm: Replace hrtimer_tasklet with softirq based  hrtimer Oliver Hartkopp <socketcan@hartkopp.net> - 2017-09-01 19:10 +0200
      Re: [PATCH 19/25] can/bcm: Replace hrtimer_tasklet with softirq based  hrtimer Oliver Hartkopp <socketcan@hartkopp.net> - 2017-09-01 18:00 +0200
      Re: [PATCH 19/25] can/bcm: Replace hrtimer_tasklet with softirq based  hrtimer Oliver Hartkopp <socketcan@hartkopp.net> - 2017-09-02 20:10 +0200
    [PATCH 10/25] hrtimer: Make handling of hrtimer reprogramming and  enqueuing not conditional Anna-Maria Gleixner <anna-maria@linutronix.de> - 2017-08-31 14:30 +0200
    [PATCH 14/25] hrtimer: Split out code from __hrtimer_get_next_event()  for reuse Anna-Maria Gleixner <anna-maria@linutronix.de> - 2017-08-31 14:30 +0200
    [PATCH 25/25] usb/gadget/NCM: Replace tasklet with softirq hrtimer Anna-Maria Gleixner <anna-maria@linutronix.de> - 2017-08-31 14:30 +0200
    [PATCH 03/25] hrtimer: Fix kerneldoc for struct hrtimer_cpu_base Anna-Maria Gleixner <anna-maria@linutronix.de> - 2017-08-31 14:30 +0200
    [PATCH 09/25] hrtimer: Reduce conditional code (hrtimer_reprogram()) Anna-Maria Gleixner <anna-maria@linutronix.de> - 2017-08-31 14:30 +0200
    Re: [PATCH 00/25] hrtimer: Provide softirq context hrtimers Anna-Maria Gleixner <anna-maria@linutronix.de> - 2017-08-31 14:40 +0200

Page 2 of 2 — ← Prev page 1 [2]


#1728687 — Re: [alsa-devel] [PATCH 23/25 v3] ALSA/dummy: Replace tasklet with softirq hrtimer

FromTakashi Iwai <tiwai@suse.de>
Date2017-09-08 10:30 +0200
SubjectRe: [alsa-devel] [PATCH 23/25 v3] ALSA/dummy: Replace tasklet with softirq hrtimer
Message-ID<unmPM-4eF-21@gated-at.bofh.it>
In reply to#1727151
On Wed, 06 Sep 2017 06:30:03 +0200,
Takashi Sakamoto wrote:
> 
> On Sep 6 2017 01:18, Sebastian Andrzej Siewior wrote:
> > From: Thomas Gleixner <tglx@linutronix.de>
> >
> > The tasklet is used to defer the execution of snd_pcm_period_elapsed() to
> > the softirq context. Using the CLOCK_MONOTONIC_SOFT base invokes the timer
> > callback in softirq context as well which renders the tasklet useless.
> >
> > Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
> > Signed-off-by: Anna-Maria Gleixner <anna-maria@linutronix.de>
> > Cc: Jaroslav Kysela <perex@perex.cz>
> > Cc: Takashi Iwai <tiwai@suse.com>
> > Cc: Takashi Sakamoto <o-takashi@sakamocchi.jp>
> > Cc: alsa-devel@alsa-project.org
> > [o-takashi: avoid stall due to a call of hrtimer_cancel() on a callback
> >              of hrtimer]
> > Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
> > Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
> > ---
> > On 2017-09-06 01:05:43 [+0900], Takashi Sakamoto wrote:
> >> As Iwai-san mentioned, in this function, .trigger can be called in two
> >> cases; XRUN occurs and draining is done. Thus, let you change the comment as
> >> 'In cases of XRUN and draining, this calls .trigger to stop PCM substream.'.
> >> I'm sorry to trouble you.
> >>
> >> snd_pcm_period_elapsed()
> >> ->snd_pcm_update_hw_ptr0()
> >>    ->snd_pcm_update_state()
> >>      ->snd_pcm_drain_done()
> >>        ...
> >>        ->.trigger(TRIGGER_STOP)
> >>      ->xrun()
> >>        ->snd_pcm_stop()
> >>          ...
> >>          ->.trigger(TRIGGER_STOP)
> >>
> >
> > I think you asked me just to update the comment. Did I do it right?
> >
> > v2…v3: updated the comment as per Takashi Sakamoto's suggestion.
> > v1…v2: merged Takashi Sakamoto fixup of the original patch into v2.
> >
> >   sound/drivers/dummy.c | 25 +++++++++++--------------
> >   1 file changed, 11 insertions(+), 14 deletions(-)
> 
> This Looks good to me. I did quick test and confirmed that it brings
> no stalls.
> 
> Tested-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>

I suppose you'd apply all together in some tree like tip or whatever?
In anyway, feel free to take my ack for this patch:
  Reviewed-by: Takashi Iwai <tiwai@suse.de>


Thanks!

Takashi

[toc] | [prev] | [next] | [standalone]


#1724183 — [PATCH 22/25] softirq: Remove tasklet_hrtimer

FromAnna-Maria Gleixner <anna-maria@linutronix.de>
Date2017-08-31 14:30 +0200
Subject[PATCH 22/25] softirq: Remove tasklet_hrtimer
Message-ID<ukwLG-5Ay-59@gated-at.bofh.it>
In reply to#1724178
From: Thomas Gleixner <tglx@linutronix.de>

There are no more tasklet_hrtimer users of this interface.
Remove it.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Anna-Maria Gleixner <anna-maria@linutronix.de>
---
 include/linux/interrupt.h |   25 ----------------------
 kernel/softirq.c          |   51 ----------------------------------------------
 2 files changed, 76 deletions(-)

--- a/include/linux/interrupt.h
+++ b/include/linux/interrupt.h
@@ -631,31 +631,6 @@ extern void tasklet_kill_immediate(struc
 extern void tasklet_init(struct tasklet_struct *t,
 			 void (*func)(unsigned long), unsigned long data);
 
-struct tasklet_hrtimer {
-	struct hrtimer		timer;
-	struct tasklet_struct	tasklet;
-	enum hrtimer_restart	(*function)(struct hrtimer *);
-};
-
-extern void
-tasklet_hrtimer_init(struct tasklet_hrtimer *ttimer,
-		     enum hrtimer_restart (*function)(struct hrtimer *),
-		     clockid_t which_clock, enum hrtimer_mode mode);
-
-static inline
-void tasklet_hrtimer_start(struct tasklet_hrtimer *ttimer, ktime_t time,
-			   const enum hrtimer_mode mode)
-{
-	hrtimer_start(&ttimer->timer, time, mode);
-}
-
-static inline
-void tasklet_hrtimer_cancel(struct tasklet_hrtimer *ttimer)
-{
-	hrtimer_cancel(&ttimer->timer);
-	tasklet_kill(&ttimer->tasklet);
-}
-
 /*
  * Autoprobing for irqs:
  *
--- a/kernel/softirq.c
+++ b/kernel/softirq.c
@@ -594,57 +594,6 @@ void tasklet_kill(struct tasklet_struct
 }
 EXPORT_SYMBOL(tasklet_kill);
 
-/*
- * tasklet_hrtimer
- */
-
-/*
- * The trampoline is called when the hrtimer expires. It schedules a tasklet
- * to run __tasklet_hrtimer_trampoline() which in turn will call the intended
- * hrtimer callback, but from softirq context.
- */
-static enum hrtimer_restart __hrtimer_tasklet_trampoline(struct hrtimer *timer)
-{
-	struct tasklet_hrtimer *ttimer =
-		container_of(timer, struct tasklet_hrtimer, timer);
-
-	tasklet_hi_schedule(&ttimer->tasklet);
-	return HRTIMER_NORESTART;
-}
-
-/*
- * Helper function which calls the hrtimer callback from
- * tasklet/softirq context
- */
-static void __tasklet_hrtimer_trampoline(unsigned long data)
-{
-	struct tasklet_hrtimer *ttimer = (void *)data;
-	enum hrtimer_restart restart;
-
-	restart = ttimer->function(&ttimer->timer);
-	if (restart != HRTIMER_NORESTART)
-		hrtimer_restart(&ttimer->timer);
-}
-
-/**
- * tasklet_hrtimer_init - Init a tasklet/hrtimer combo for softirq callbacks
- * @ttimer:	 tasklet_hrtimer which is initialized
- * @function:	 hrtimer callback function which gets called from softirq context
- * @which_clock: clock id (CLOCK_MONOTONIC/CLOCK_REALTIME)
- * @mode:	 hrtimer mode (HRTIMER_MODE_ABS/HRTIMER_MODE_REL)
- */
-void tasklet_hrtimer_init(struct tasklet_hrtimer *ttimer,
-			  enum hrtimer_restart (*function)(struct hrtimer *),
-			  clockid_t which_clock, enum hrtimer_mode mode)
-{
-	hrtimer_init(&ttimer->timer, which_clock, mode);
-	ttimer->timer.function = __hrtimer_tasklet_trampoline;
-	tasklet_init(&ttimer->tasklet, __tasklet_hrtimer_trampoline,
-		     (unsigned long)ttimer);
-	ttimer->function = function;
-}
-EXPORT_SYMBOL_GPL(tasklet_hrtimer_init);
-
 void __init softirq_init(void)
 {
 	int cpu;

[toc] | [prev] | [next] | [standalone]


#1724184 — [PATCH 21/25] xfrm: Replace hrtimer tasklet with softirq hrtimer

FromAnna-Maria Gleixner <anna-maria@linutronix.de>
Date2017-08-31 14:30 +0200
Subject[PATCH 21/25] xfrm: Replace hrtimer tasklet with softirq hrtimer
Message-ID<ukwLG-5Ay-63@gated-at.bofh.it>
In reply to#1724178
From: Thomas Gleixner <tglx@linutronix.de>

Switch the timer to CLOCK_MONOTONIC_SOFT, which executed the timer
callback in softirq context and remove the hrtimer_tasklet.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Anna-Maria Gleixner <anna-maria@linutronix.de>
Cc: Steffen Klassert <steffen.klassert@secunet.com>
Cc: Herbert Xu <herbert@gondor.apana.org.au>
Cc: "David S. Miller" <davem@davemloft.net>
Cc: netdev@vger.kernel.org

---
 include/net/xfrm.h    |    2 +-
 net/xfrm/xfrm_state.c |   29 +++++++++++++++++------------
 2 files changed, 18 insertions(+), 13 deletions(-)

--- a/include/net/xfrm.h
+++ b/include/net/xfrm.h
@@ -213,7 +213,7 @@ struct xfrm_state {
 	struct xfrm_stats	stats;
 
 	struct xfrm_lifetime_cur curlft;
-	struct tasklet_hrtimer	mtimer;
+	struct hrtimer		mtimer;
 
 	struct xfrm_state_offload xso;
 
--- a/net/xfrm/xfrm_state.c
+++ b/net/xfrm/xfrm_state.c
@@ -418,7 +418,7 @@ static void xfrm_put_mode(struct xfrm_mo
 
 static void xfrm_state_gc_destroy(struct xfrm_state *x)
 {
-	tasklet_hrtimer_cancel(&x->mtimer);
+	hrtimer_cancel(&x->mtimer);
 	del_timer_sync(&x->rtimer);
 	kfree(x->aead);
 	kfree(x->aalg);
@@ -463,8 +463,8 @@ static void xfrm_state_gc_task(struct wo
 
 static enum hrtimer_restart xfrm_timer_handler(struct hrtimer *me)
 {
-	struct tasklet_hrtimer *thr = container_of(me, struct tasklet_hrtimer, timer);
-	struct xfrm_state *x = container_of(thr, struct xfrm_state, mtimer);
+	struct xfrm_state *x = container_of(me, struct xfrm_state, mtimer);
+	enum hrtimer_restart ret = HRTIMER_NORESTART;
 	unsigned long now = get_seconds();
 	long next = LONG_MAX;
 	int warn = 0;
@@ -528,7 +528,8 @@ static enum hrtimer_restart xfrm_timer_h
 		km_state_expired(x, 0, 0);
 resched:
 	if (next != LONG_MAX) {
-		tasklet_hrtimer_start(&x->mtimer, ktime_set(next, 0), HRTIMER_MODE_REL);
+		hrtimer_forward_now(&x->mtimer, ktime_set(next, 0));
+		ret = HRTIMER_RESTART;
 	}
 
 	goto out;
@@ -545,7 +546,7 @@ static enum hrtimer_restart xfrm_timer_h
 
 out:
 	spin_unlock(&x->lock);
-	return HRTIMER_NORESTART;
+	return ret;
 }
 
 static void xfrm_replay_timer_handler(unsigned long data);
@@ -564,8 +565,8 @@ struct xfrm_state *xfrm_state_alloc(stru
 		INIT_HLIST_NODE(&x->bydst);
 		INIT_HLIST_NODE(&x->bysrc);
 		INIT_HLIST_NODE(&x->byspi);
-		tasklet_hrtimer_init(&x->mtimer, xfrm_timer_handler,
-					CLOCK_BOOTTIME, HRTIMER_MODE_ABS);
+		hrtimer_init(&x->mtimer, CLOCK_BOOTTIME_SOFT, HRTIMER_MODE_ABS);
+		x->mtimer.function = xfrm_timer_handler;
 		setup_timer(&x->rtimer, xfrm_replay_timer_handler,
 				(unsigned long)x);
 		x->curlft.add_time = get_seconds();
@@ -1021,7 +1022,9 @@ xfrm_state_find(const xfrm_address_t *da
 				hlist_add_head_rcu(&x->byspi, net->xfrm.state_byspi + h);
 			}
 			x->lft.hard_add_expires_seconds = net->xfrm.sysctl_acq_expires;
-			tasklet_hrtimer_start(&x->mtimer, ktime_set(net->xfrm.sysctl_acq_expires, 0), HRTIMER_MODE_REL);
+			hrtimer_start(&x->mtimer,
+				      ktime_set(net->xfrm.sysctl_acq_expires, 0),
+				      HRTIMER_MODE_REL);
 			net->xfrm.state_num++;
 			xfrm_hash_grow_check(net, x->bydst.next != NULL);
 			spin_unlock_bh(&net->xfrm.xfrm_state_lock);
@@ -1132,7 +1135,7 @@ static void __xfrm_state_insert(struct x
 		hlist_add_head_rcu(&x->byspi, net->xfrm.state_byspi + h);
 	}
 
-	tasklet_hrtimer_start(&x->mtimer, ktime_set(1, 0), HRTIMER_MODE_REL);
+	hrtimer_start(&x->mtimer, ktime_set(1, 0), HRTIMER_MODE_REL);
 	if (x->replay_maxage)
 		mod_timer(&x->rtimer, jiffies + x->replay_maxage);
 
@@ -1236,7 +1239,9 @@ static struct xfrm_state *__find_acq_cor
 		x->mark.m = m->m;
 		x->lft.hard_add_expires_seconds = net->xfrm.sysctl_acq_expires;
 		xfrm_state_hold(x);
-		tasklet_hrtimer_start(&x->mtimer, ktime_set(net->xfrm.sysctl_acq_expires, 0), HRTIMER_MODE_REL);
+		hrtimer_start(&x->mtimer,
+			      ktime_set(net->xfrm.sysctl_acq_expires, 0),
+			      HRTIMER_MODE_REL);
 		list_add(&x->km.all, &net->xfrm.state_all);
 		hlist_add_head_rcu(&x->bydst, net->xfrm.state_bydst + h);
 		h = xfrm_src_hash(net, daddr, saddr, family);
@@ -1535,7 +1540,7 @@ int xfrm_state_update(struct xfrm_state
 		memcpy(&x1->lft, &x->lft, sizeof(x1->lft));
 		x1->km.dying = 0;
 
-		tasklet_hrtimer_start(&x1->mtimer, ktime_set(1, 0), HRTIMER_MODE_REL);
+		hrtimer_start(&x1->mtimer, ktime_set(1, 0), HRTIMER_MODE_REL);
 		if (x1->curlft.use_time)
 			xfrm_state_check_expire(x1);
 
@@ -1559,7 +1564,7 @@ int xfrm_state_check_expire(struct xfrm_
 	if (x->curlft.bytes >= x->lft.hard_byte_limit ||
 	    x->curlft.packets >= x->lft.hard_packet_limit) {
 		x->km.state = XFRM_STATE_EXPIRED;
-		tasklet_hrtimer_start(&x->mtimer, 0, HRTIMER_MODE_REL);
+		hrtimer_start(&x->mtimer, 0, HRTIMER_MODE_REL);
 		return -EINVAL;
 	}
 

[toc] | [prev] | [next] | [standalone]


#1724185 — [PATCH 06/25] hrtimer: Store running timer in hrtimer_clock_base

FromAnna-Maria Gleixner <anna-maria@linutronix.de>
Date2017-08-31 14:30 +0200
Subject[PATCH 06/25] hrtimer: Store running timer in hrtimer_clock_base
Message-ID<ukwLG-5Ay-55@gated-at.bofh.it>
In reply to#1724178
From: Anna-Maria Gleixner <anna-maria@linutronix.de>

The pointer to the currently running timer is stored in hrtimer_cpu_base
before the base lock is dropped and the callback is invoked.

This results in two levels of indirections and the upcoming support for
softirq based hrtimer requires splitting the "running" storage into soft
and hard irq context expiry.

Storing both in the cpu base would require conditionals in all code paths
accessing that information.

It's possible to have a per clock base sequence count and running pointer
without changing the semantics of the related mechanisms because the timer
base pointer cannot be changed while a timer is running the callback.

Unfortunately this makes cpu_clock base larger than 32 bytes on 32bit
kernels. Instead of having huge gaps due to alignment, remove the alignment
and let the compiler pack cpu base for 32bit. The resulting cache access
patterns are fortunately not really different from the current
behaviour. On 64bit kernels the 64byte alignment stays and the behaviour is
unchanged.

Signed-off-by: Anna-Maria Gleixner <anna-maria@linutronix.de>
---
 include/linux/hrtimer.h |   20 +++++++++-----------
 kernel/time/hrtimer.c   |   28 +++++++++++++---------------
 2 files changed, 22 insertions(+), 26 deletions(-)

--- a/include/linux/hrtimer.h
+++ b/include/linux/hrtimer.h
@@ -112,9 +112,9 @@ struct hrtimer_sleeper {
 };
 
 #ifdef CONFIG_64BIT
-# define HRTIMER_CLOCK_BASE_ALIGN	64
+# define __hrtimer_clock_base_align	____cacheline_aligned
 #else
-# define HRTIMER_CLOCK_BASE_ALIGN	32
+# define __hrtimer_clock_base_align
 #endif
 
 /**
@@ -123,18 +123,22 @@ struct hrtimer_sleeper {
  * @index:		clock type index for per_cpu support when moving a
  *			timer to a base on another cpu.
  * @clockid:		clock id for per_cpu support
+ * @seq:		seqcount around __run_hrtimer
+ * @running:		pointer to the currently running hrtimer
  * @active:		red black tree root node for the active timers
  * @get_time:		function to retrieve the current time of the clock
  * @offset:		offset of this clock to the monotonic base
  */
 struct hrtimer_clock_base {
 	struct hrtimer_cpu_base	*cpu_base;
-	int			index;
+	unsigned int		index;
 	clockid_t		clockid;
+	seqcount_t		seq;
+	struct hrtimer		*running;
 	struct timerqueue_head	active;
 	ktime_t			(*get_time)(void);
 	ktime_t			offset;
-} __attribute__((__aligned__(HRTIMER_CLOCK_BASE_ALIGN)));
+} __hrtimer_clock_base_align;
 
 enum  hrtimer_base_type {
 	HRTIMER_BASE_MONOTONIC,
@@ -148,8 +152,6 @@ enum  hrtimer_base_type {
  * struct hrtimer_cpu_base - the per cpu clock bases
  * @lock:		lock protecting the base and associated clock bases
  *			and timers
- * @seq:		seqcount around __run_hrtimer
- * @running:		pointer to the currently running hrtimer
  * @cpu:		cpu number
  * @active_bases:	Bitfield to mark bases with active timers
  * @clock_was_set_seq:	Sequence counter of clock was set events
@@ -173,8 +175,6 @@ enum  hrtimer_base_type {
  */
 struct hrtimer_cpu_base {
 	raw_spinlock_t			lock;
-	seqcount_t			seq;
-	struct hrtimer			*running;
 	unsigned int			cpu;
 	unsigned int			active_bases;
 	unsigned int			clock_was_set_seq;
@@ -196,8 +196,6 @@ struct hrtimer_cpu_base {
 
 static inline void hrtimer_set_expires(struct hrtimer *timer, ktime_t time)
 {
-	BUILD_BUG_ON(sizeof(struct hrtimer_clock_base) > HRTIMER_CLOCK_BASE_ALIGN);
-
 	timer->node.expires = time;
 	timer->_softexpires = time;
 }
@@ -422,7 +420,7 @@ static inline int hrtimer_is_queued(stru
  */
 static inline int hrtimer_callback_running(struct hrtimer *timer)
 {
-	return timer->base->cpu_base->running == timer;
+	return timer->base->running == timer;
 }
 
 /* Forward a hrtimer so it expires after now: */
--- a/kernel/time/hrtimer.c
+++ b/kernel/time/hrtimer.c
@@ -70,7 +70,6 @@
 DEFINE_PER_CPU(struct hrtimer_cpu_base, hrtimer_bases) =
 {
 	.lock = __RAW_SPIN_LOCK_UNLOCKED(hrtimer_bases.lock),
-	.seq = SEQCNT_ZERO(hrtimer_bases.seq),
 	.clock_base =
 	{
 		{
@@ -118,7 +117,6 @@ static const int hrtimer_clock_to_base_t
  * timer->base->cpu_base
  */
 static struct hrtimer_cpu_base migration_cpu_base = {
-	.seq = SEQCNT_ZERO(migration_cpu_base),
 	.clock_base = { { .cpu_base = &migration_cpu_base, }, },
 };
 
@@ -1136,19 +1134,19 @@ EXPORT_SYMBOL_GPL(hrtimer_init);
  */
 bool hrtimer_active(const struct hrtimer *timer)
 {
-	struct hrtimer_cpu_base *cpu_base;
+	struct hrtimer_clock_base *base;
 	unsigned int seq;
 
 	do {
-		cpu_base = READ_ONCE(timer->base->cpu_base);
-		seq = raw_read_seqcount_begin(&cpu_base->seq);
+		base = READ_ONCE(timer->base);
+		seq = raw_read_seqcount_begin(&base->seq);
 
 		if (timer->state != HRTIMER_STATE_INACTIVE ||
-		    cpu_base->running == timer)
+		    base->running == timer)
 			return true;
 
-	} while (read_seqcount_retry(&cpu_base->seq, seq) ||
-		 cpu_base != READ_ONCE(timer->base->cpu_base));
+	} while (read_seqcount_retry(&base->seq, seq) ||
+		 base != READ_ONCE(timer->base));
 
 	return false;
 }
@@ -1182,16 +1180,16 @@ static void __run_hrtimer(struct hrtimer
 	lockdep_assert_held(&cpu_base->lock);
 
 	debug_deactivate(timer);
-	cpu_base->running = timer;
+	base->running = timer;
 
 	/*
 	 * Separate the ->running assignment from the ->state assignment.
 	 *
 	 * As with a regular write barrier, this ensures the read side in
-	 * hrtimer_active() cannot observe cpu_base->running == NULL &&
+	 * hrtimer_active() cannot observe base->running == NULL &&
 	 * timer->state == INACTIVE.
 	 */
-	raw_write_seqcount_barrier(&cpu_base->seq);
+	raw_write_seqcount_barrier(&base->seq);
 
 	__remove_hrtimer(timer, base, HRTIMER_STATE_INACTIVE, 0);
 	fn = timer->function;
@@ -1232,13 +1230,13 @@ static void __run_hrtimer(struct hrtimer
 	 * Separate the ->running assignment from the ->state assignment.
 	 *
 	 * As with a regular write barrier, this ensures the read side in
-	 * hrtimer_active() cannot observe cpu_base->running == NULL &&
+	 * hrtimer_active() cannot observe base->running.timer == NULL &&
 	 * timer->state == INACTIVE.
 	 */
-	raw_write_seqcount_barrier(&cpu_base->seq);
+	raw_write_seqcount_barrier(&base->seq);
 
-	WARN_ON_ONCE(cpu_base->running != timer);
-	cpu_base->running = NULL;
+	WARN_ON_ONCE(base->running != timer);
+	base->running = NULL;
 }
 
 static void __hrtimer_run_queues(struct hrtimer_cpu_base *cpu_base, ktime_t now)

[toc] | [prev] | [next] | [standalone]


#1724186 — [PATCH 19/25] can/bcm: Replace hrtimer_tasklet with softirq based hrtimer

FromAnna-Maria Gleixner <anna-maria@linutronix.de>
Date2017-08-31 14:30 +0200
Subject[PATCH 19/25] can/bcm: Replace hrtimer_tasklet with softirq based hrtimer
Message-ID<ukwLG-5Ay-57@gated-at.bofh.it>
In reply to#1724178
From: Thomas Gleixner <tglx@linutronix.de>

Switch the timer to CLOCK_MONOTONIC_SOFT, which executed the timer
callback in softirq context and remove the hrtimer_tasklet.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Anna-Maria Gleixner <anna-maria@linutronix.de>
Cc: Oliver Hartkopp <socketcan@hartkopp.net>
Cc: Marc Kleine-Budde <mkl@pengutronix.de>
Cc: linux-can@vger.kernel.org
---
 net/can/bcm.c |  150 ++++++++++++++++++----------------------------------------
 1 file changed, 49 insertions(+), 101 deletions(-)

--- a/net/can/bcm.c
+++ b/net/can/bcm.c
@@ -102,7 +102,6 @@ struct bcm_op {
 	unsigned long frames_abs, frames_filtered;
 	struct bcm_timeval ival1, ival2;
 	struct hrtimer timer, thrtimer;
-	struct tasklet_struct tsklet, thrtsklet;
 	ktime_t rx_stamp, kt_ival1, kt_ival2, kt_lastmsg;
 	int rx_ifindex;
 	int cfsiz;
@@ -364,25 +363,34 @@ static void bcm_send_to_user(struct bcm_
 	}
 }
 
-static void bcm_tx_start_timer(struct bcm_op *op)
+static bool bcm_tx_set_expiry(struct bcm_op *op, struct hrtimer *hrt)
 {
+	ktime_t ival;
+
 	if (op->kt_ival1 && op->count)
-		hrtimer_start(&op->timer,
-			      ktime_add(ktime_get(), op->kt_ival1),
-			      HRTIMER_MODE_ABS);
+		ival = op->kt_ival1;
 	else if (op->kt_ival2)
-		hrtimer_start(&op->timer,
-			      ktime_add(ktime_get(), op->kt_ival2),
-			      HRTIMER_MODE_ABS);
+		ival = op->kt_ival2;
+	else
+		return false;
+
+	hrtimer_set_expires(hrt, ktime_add(ktime_get(), ival));
+	return true;
 }
 
-static void bcm_tx_timeout_tsklet(unsigned long data)
+static void bcm_tx_start_timer(struct bcm_op *op)
 {
-	struct bcm_op *op = (struct bcm_op *)data;
+	if (bcm_tx_set_expiry(op, &op->timer))
+		hrtimer_start_expires(&op->timer, HRTIMER_MODE_ABS);
+}
+
+/* bcm_tx_timeout_handler - performs cyclic CAN frame transmissions */
+static enum hrtimer_restart bcm_tx_timeout_handler(struct hrtimer *hrtimer)
+{
+	struct bcm_op *op = container_of(hrtimer, struct bcm_op, timer);
 	struct bcm_msg_head msg_head;
 
 	if (op->kt_ival1 && (op->count > 0)) {
-
 		op->count--;
 		if (!op->count && (op->flags & TX_COUNTEVT)) {
 
@@ -399,22 +407,12 @@ static void bcm_tx_timeout_tsklet(unsign
 		}
 		bcm_can_tx(op);
 
-	} else if (op->kt_ival2)
+	} else if (op->kt_ival2) {
 		bcm_can_tx(op);
+	}
 
-	bcm_tx_start_timer(op);
-}
-
-/*
- * bcm_tx_timeout_handler - performs cyclic CAN frame transmissions
- */
-static enum hrtimer_restart bcm_tx_timeout_handler(struct hrtimer *hrtimer)
-{
-	struct bcm_op *op = container_of(hrtimer, struct bcm_op, timer);
-
-	tasklet_schedule(&op->tsklet);
-
-	return HRTIMER_NORESTART;
+	return bcm_tx_set_expiry(op, &op->timer) ?
+		HRTIMER_RESTART : HRTIMER_NORESTART;
 }
 
 /*
@@ -542,11 +540,18 @@ static void bcm_rx_starttimer(struct bcm
 		hrtimer_start(&op->timer, op->kt_ival1, HRTIMER_MODE_REL);
 }
 
-static void bcm_rx_timeout_tsklet(unsigned long data)
+/* bcm_rx_timeout_handler - when the (cyclic) CAN frame reception timed out */
+static enum hrtimer_restart bcm_rx_timeout_handler(struct hrtimer *hrtimer)
 {
-	struct bcm_op *op = (struct bcm_op *)data;
+	struct bcm_op *op = container_of(hrtimer, struct bcm_op, timer);
 	struct bcm_msg_head msg_head;
 
+	/* if user wants to be informed, when cyclic CAN-Messages come back */
+	if ((op->flags & RX_ANNOUNCE_RESUME) && op->last_frames) {
+		/* clear received CAN frames to indicate 'nothing received' */
+		memset(op->last_frames, 0, op->nframes * op->cfsiz);
+	}
+
 	/* create notification to user */
 	msg_head.opcode  = RX_TIMEOUT;
 	msg_head.flags   = op->flags;
@@ -557,25 +562,6 @@ static void bcm_rx_timeout_tsklet(unsign
 	msg_head.nframes = 0;
 
 	bcm_send_to_user(op, &msg_head, NULL, 0);
-}
-
-/*
- * bcm_rx_timeout_handler - when the (cyclic) CAN frame reception timed out
- */
-static enum hrtimer_restart bcm_rx_timeout_handler(struct hrtimer *hrtimer)
-{
-	struct bcm_op *op = container_of(hrtimer, struct bcm_op, timer);
-
-	/* schedule before NET_RX_SOFTIRQ */
-	tasklet_hi_schedule(&op->tsklet);
-
-	/* no restart of the timer is done here! */
-
-	/* if user wants to be informed, when cyclic CAN-Messages come back */
-	if ((op->flags & RX_ANNOUNCE_RESUME) && op->last_frames) {
-		/* clear received CAN frames to indicate 'nothing received' */
-		memset(op->last_frames, 0, op->nframes * op->cfsiz);
-	}
 
 	return HRTIMER_NORESTART;
 }
@@ -583,14 +569,12 @@ static enum hrtimer_restart bcm_rx_timeo
 /*
  * bcm_rx_do_flush - helper for bcm_rx_thr_flush
  */
-static inline int bcm_rx_do_flush(struct bcm_op *op, int update,
-				  unsigned int index)
+static inline int bcm_rx_do_flush(struct bcm_op *op, unsigned int index)
 {
 	struct canfd_frame *lcf = op->last_frames + op->cfsiz * index;
 
 	if ((op->last_frames) && (lcf->flags & RX_THR)) {
-		if (update)
-			bcm_rx_changed(op, lcf);
+		bcm_rx_changed(op, lcf);
 		return 1;
 	}
 	return 0;
@@ -598,11 +582,8 @@ static inline int bcm_rx_do_flush(struct
 
 /*
  * bcm_rx_thr_flush - Check for throttled data and send it to the userspace
- *
- * update == 0 : just check if throttled data is available  (any irq context)
- * update == 1 : check and send throttled data to userspace (soft_irq context)
  */
-static int bcm_rx_thr_flush(struct bcm_op *op, int update)
+static int bcm_rx_thr_flush(struct bcm_op *op)
 {
 	int updated = 0;
 
@@ -611,24 +592,16 @@ static int bcm_rx_thr_flush(struct bcm_o
 
 		/* for MUX filter we start at index 1 */
 		for (i = 1; i < op->nframes; i++)
-			updated += bcm_rx_do_flush(op, update, i);
+			updated += bcm_rx_do_flush(op, i);
 
 	} else {
 		/* for RX_FILTER_ID and simple filter */
-		updated += bcm_rx_do_flush(op, update, 0);
+		updated += bcm_rx_do_flush(op, 0);
 	}
 
 	return updated;
 }
 
-static void bcm_rx_thr_tsklet(unsigned long data)
-{
-	struct bcm_op *op = (struct bcm_op *)data;
-
-	/* push the changed data to the userspace */
-	bcm_rx_thr_flush(op, 1);
-}
-
 /*
  * bcm_rx_thr_handler - the time for blocked content updates is over now:
  *                      Check for throttled data and send it to the userspace
@@ -637,9 +610,7 @@ static enum hrtimer_restart bcm_rx_thr_h
 {
 	struct bcm_op *op = container_of(hrtimer, struct bcm_op, thrtimer);
 
-	tasklet_schedule(&op->thrtsklet);
-
-	if (bcm_rx_thr_flush(op, 0)) {
+	if (bcm_rx_thr_flush(op)) {
 		hrtimer_forward(hrtimer, ktime_get(), op->kt_ival2);
 		return HRTIMER_RESTART;
 	} else {
@@ -735,23 +706,8 @@ static struct bcm_op *bcm_find_op(struct
 
 static void bcm_remove_op(struct bcm_op *op)
 {
-	if (op->tsklet.func) {
-		while (test_bit(TASKLET_STATE_SCHED, &op->tsklet.state) ||
-		       test_bit(TASKLET_STATE_RUN, &op->tsklet.state) ||
-		       hrtimer_active(&op->timer)) {
-			hrtimer_cancel(&op->timer);
-			tasklet_kill(&op->tsklet);
-		}
-	}
-
-	if (op->thrtsklet.func) {
-		while (test_bit(TASKLET_STATE_SCHED, &op->thrtsklet.state) ||
-		       test_bit(TASKLET_STATE_RUN, &op->thrtsklet.state) ||
-		       hrtimer_active(&op->thrtimer)) {
-			hrtimer_cancel(&op->thrtimer);
-			tasklet_kill(&op->thrtsklet);
-		}
-	}
+	hrtimer_cancel(&op->timer);
+	hrtimer_cancel(&op->thrtimer);
 
 	if ((op->frames) && (op->frames != &op->sframe))
 		kfree(op->frames);
@@ -979,15 +935,13 @@ static int bcm_tx_setup(struct bcm_msg_h
 		op->ifindex = ifindex;
 
 		/* initialize uninitialized (kzalloc) structure */
-		hrtimer_init(&op->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
+		hrtimer_init(&op->timer, CLOCK_MONOTONIC_SOFT,
+			     HRTIMER_MODE_REL);
 		op->timer.function = bcm_tx_timeout_handler;
 
-		/* initialize tasklet for tx countevent notification */
-		tasklet_init(&op->tsklet, bcm_tx_timeout_tsklet,
-			     (unsigned long) op);
-
 		/* currently unused in tx_ops */
-		hrtimer_init(&op->thrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
+		hrtimer_init(&op->thrtimer, CLOCK_MONOTONIC_SOFT,
+			     HRTIMER_MODE_REL);
 
 		/* add this bcm_op to the list of the tx_ops */
 		list_add(&op->list, &bo->tx_ops);
@@ -1150,20 +1104,14 @@ static int bcm_rx_setup(struct bcm_msg_h
 		op->rx_ifindex = ifindex;
 
 		/* initialize uninitialized (kzalloc) structure */
-		hrtimer_init(&op->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
+		hrtimer_init(&op->timer, CLOCK_MONOTONIC_SOFT,
+			     HRTIMER_MODE_REL);
 		op->timer.function = bcm_rx_timeout_handler;
 
-		/* initialize tasklet for rx timeout notification */
-		tasklet_init(&op->tsklet, bcm_rx_timeout_tsklet,
-			     (unsigned long) op);
-
-		hrtimer_init(&op->thrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
+		hrtimer_init(&op->thrtimer, CLOCK_MONOTONIC_SOFT,
+			     HRTIMER_MODE_REL);
 		op->thrtimer.function = bcm_rx_thr_handler;
 
-		/* initialize tasklet for rx throttle handling */
-		tasklet_init(&op->thrtsklet, bcm_rx_thr_tsklet,
-			     (unsigned long) op);
-
 		/* add this bcm_op to the list of the rx_ops */
 		list_add(&op->list, &bo->rx_ops);
 
@@ -1209,7 +1157,7 @@ static int bcm_rx_setup(struct bcm_msg_h
 			 */
 			op->kt_lastmsg = 0;
 			hrtimer_cancel(&op->thrtimer);
-			bcm_rx_thr_flush(op, 1);
+			bcm_rx_thr_flush(op);
 		}
 
 		if ((op->flags & STARTTIMER) && op->kt_ival1)

[toc] | [prev] | [next] | [standalone]


#1725182 — Re: [PATCH 19/25] can/bcm: Replace hrtimer_tasklet with softirq based hrtimer

FromThomas Gleixner <tglx@linutronix.de>
Date2017-09-01 18:00 +0200
SubjectRe: [PATCH 19/25] can/bcm: Replace hrtimer_tasklet with softirq based hrtimer
Message-ID<ukWwp-759-1@gated-at.bofh.it>
In reply to#1724186
On Fri, 1 Sep 2017, Oliver Hartkopp wrote:

> Hi Anna-Maria & Thomas,
> 
> thanks for the effort!
> 
> I'm really happy that the hrtimer becomes softirq capable as it basically
> reverts this ugly commit from January 2009:
> 
> https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit?id=6e5c172cf7ca1ab878cc6a6a4c1d52fef60f3ee0
> 
> From the first look the changes seem to be correct.
> 
> I'll pick the entire patchset for a test and give a Acked|Tested-by then.
> 
> Best regards,
> Oliver
> 
> ps.
> 
> On 08/31/2017 02:23 PM, Anna-Maria Gleixner wrote:
> 
> (nothing here!)
> 
> Please send patches inline and not as attachments. Tnx!

PS:

Content-Type: text/plain; charset=UTF-8
Content-Disposition: inline;
 filename=canbcm_Replace_hrtimer_tasklet_with_softirq_based_hrtimer.patch

Please get a proper mail client, which actually parses the
Content-Disposition tag correcly

Thanks,

	tglx

[toc] | [prev] | [next] | [standalone]


#1725237 — Re: [PATCH 19/25] can/bcm: Replace hrtimer_tasklet with softirq based hrtimer

FromOliver Hartkopp <socketcan@hartkopp.net>
Date2017-09-01 19:10 +0200
SubjectRe: [PATCH 19/25] can/bcm: Replace hrtimer_tasklet with softirq based hrtimer
Message-ID<ukXCa-81A-11@gated-at.bofh.it>
In reply to#1725182
On 09/01/2017 05:56 PM, Thomas Gleixner wrote:
> On Fri, 1 Sep 2017, Oliver Hartkopp wrote:

>>
>> On 08/31/2017 02:23 PM, Anna-Maria Gleixner wrote:
>>
>> (nothing here!)
>>
>> Please send patches inline and not as attachments. Tnx!
> 
> PS:
> 
> Content-Type: text/plain; charset=UTF-8
> Content-Disposition: inline;
>   filename=canbcm_Replace_hrtimer_tasklet_with_softirq_based_hrtimer.patch
> 
> Please get a proper mail client, which actually parses the
> Content-Disposition tag correcly
> 

Aah!

Setting

	mail.reply_quote_inline = true

in the config editor fixes that issue when replying a quilt post with 
Thunderbird.

Tnx!

Best,
Oliver

[toc] | [prev] | [next] | [standalone]


#1725188 — Re: [PATCH 19/25] can/bcm: Replace hrtimer_tasklet with softirq based hrtimer

FromOliver Hartkopp <socketcan@hartkopp.net>
Date2017-09-01 18:00 +0200
SubjectRe: [PATCH 19/25] can/bcm: Replace hrtimer_tasklet with softirq based hrtimer
Message-ID<ukWwp-759-3@gated-at.bofh.it>
In reply to#1724186
Hi Anna-Maria & Thomas,

thanks for the effort!

I'm really happy that the hrtimer becomes softirq capable as it 
basically reverts this ugly commit from January 2009:

https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit?id=6e5c172cf7ca1ab878cc6a6a4c1d52fef60f3ee0

 From the first look the changes seem to be correct.

I'll pick the entire patchset for a test and give a Acked|Tested-by then.

Best regards,
Oliver

ps.

On 08/31/2017 02:23 PM, Anna-Maria Gleixner wrote:

(nothing here!)

Please send patches inline and not as attachments. Tnx!

[toc] | [prev] | [next] | [standalone]


#1725545 — Re: [PATCH 19/25] can/bcm: Replace hrtimer_tasklet with softirq based hrtimer

FromOliver Hartkopp <socketcan@hartkopp.net>
Date2017-09-02 20:10 +0200
SubjectRe: [PATCH 19/25] can/bcm: Replace hrtimer_tasklet with softirq based hrtimer
Message-ID<ull1M-6fs-3@gated-at.bofh.it>
In reply to#1724186
On 08/31/2017 02:23 PM, Anna-Maria Gleixner wrote:
> From: Thomas Gleixner <tglx@linutronix.de>
> 
> Switch the timer to CLOCK_MONOTONIC_SOFT, which executed the timer
> callback in softirq context and remove the hrtimer_tasklet.
> 
> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
> Signed-off-by: Anna-Maria Gleixner <anna-maria@linutronix.de>
> Cc: Oliver Hartkopp <socketcan@hartkopp.net>

Acked-by: Oliver Hartkopp <socketcan@hartkopp.net>

Thanks,
Oliver

> Cc: Marc Kleine-Budde <mkl@pengutronix.de>
> Cc: linux-can@vger.kernel.org
> ---
>   net/can/bcm.c |  150 ++++++++++++++++++----------------------------------------
>   1 file changed, 49 insertions(+), 101 deletions(-)
> 
> --- a/net/can/bcm.c
> +++ b/net/can/bcm.c
> @@ -102,7 +102,6 @@ struct bcm_op {
>   	unsigned long frames_abs, frames_filtered;
>   	struct bcm_timeval ival1, ival2;
>   	struct hrtimer timer, thrtimer;
> -	struct tasklet_struct tsklet, thrtsklet;
>   	ktime_t rx_stamp, kt_ival1, kt_ival2, kt_lastmsg;
>   	int rx_ifindex;
>   	int cfsiz;
> @@ -364,25 +363,34 @@ static void bcm_send_to_user(struct bcm_
>   	}
>   }
>   
> -static void bcm_tx_start_timer(struct bcm_op *op)
> +static bool bcm_tx_set_expiry(struct bcm_op *op, struct hrtimer *hrt)
>   {
> +	ktime_t ival;
> +
>   	if (op->kt_ival1 && op->count)
> -		hrtimer_start(&op->timer,
> -			      ktime_add(ktime_get(), op->kt_ival1),
> -			      HRTIMER_MODE_ABS);
> +		ival = op->kt_ival1;
>   	else if (op->kt_ival2)
> -		hrtimer_start(&op->timer,
> -			      ktime_add(ktime_get(), op->kt_ival2),
> -			      HRTIMER_MODE_ABS);
> +		ival = op->kt_ival2;
> +	else
> +		return false;
> +
> +	hrtimer_set_expires(hrt, ktime_add(ktime_get(), ival));
> +	return true;
>   }
>   
> -static void bcm_tx_timeout_tsklet(unsigned long data)
> +static void bcm_tx_start_timer(struct bcm_op *op)
>   {
> -	struct bcm_op *op = (struct bcm_op *)data;
> +	if (bcm_tx_set_expiry(op, &op->timer))
> +		hrtimer_start_expires(&op->timer, HRTIMER_MODE_ABS);
> +}
> +
> +/* bcm_tx_timeout_handler - performs cyclic CAN frame transmissions */
> +static enum hrtimer_restart bcm_tx_timeout_handler(struct hrtimer *hrtimer)
> +{
> +	struct bcm_op *op = container_of(hrtimer, struct bcm_op, timer);
>   	struct bcm_msg_head msg_head;
>   
>   	if (op->kt_ival1 && (op->count > 0)) {
> -
>   		op->count--;
>   		if (!op->count && (op->flags & TX_COUNTEVT)) {
>   
> @@ -399,22 +407,12 @@ static void bcm_tx_timeout_tsklet(unsign
>   		}
>   		bcm_can_tx(op);
>   
> -	} else if (op->kt_ival2)
> +	} else if (op->kt_ival2) {
>   		bcm_can_tx(op);
> +	}
>   
> -	bcm_tx_start_timer(op);
> -}
> -
> -/*
> - * bcm_tx_timeout_handler - performs cyclic CAN frame transmissions
> - */
> -static enum hrtimer_restart bcm_tx_timeout_handler(struct hrtimer *hrtimer)
> -{
> -	struct bcm_op *op = container_of(hrtimer, struct bcm_op, timer);
> -
> -	tasklet_schedule(&op->tsklet);
> -
> -	return HRTIMER_NORESTART;
> +	return bcm_tx_set_expiry(op, &op->timer) ?
> +		HRTIMER_RESTART : HRTIMER_NORESTART;
>   }
>   
>   /*
> @@ -542,11 +540,18 @@ static void bcm_rx_starttimer(struct bcm
>   		hrtimer_start(&op->timer, op->kt_ival1, HRTIMER_MODE_REL);
>   }
>   
> -static void bcm_rx_timeout_tsklet(unsigned long data)
> +/* bcm_rx_timeout_handler - when the (cyclic) CAN frame reception timed out */
> +static enum hrtimer_restart bcm_rx_timeout_handler(struct hrtimer *hrtimer)
>   {
> -	struct bcm_op *op = (struct bcm_op *)data;
> +	struct bcm_op *op = container_of(hrtimer, struct bcm_op, timer);
>   	struct bcm_msg_head msg_head;
>   
> +	/* if user wants to be informed, when cyclic CAN-Messages come back */
> +	if ((op->flags & RX_ANNOUNCE_RESUME) && op->last_frames) {
> +		/* clear received CAN frames to indicate 'nothing received' */
> +		memset(op->last_frames, 0, op->nframes * op->cfsiz);
> +	}
> +
>   	/* create notification to user */
>   	msg_head.opcode  = RX_TIMEOUT;
>   	msg_head.flags   = op->flags;
> @@ -557,25 +562,6 @@ static void bcm_rx_timeout_tsklet(unsign
>   	msg_head.nframes = 0;
>   
>   	bcm_send_to_user(op, &msg_head, NULL, 0);
> -}
> -
> -/*
> - * bcm_rx_timeout_handler - when the (cyclic) CAN frame reception timed out
> - */
> -static enum hrtimer_restart bcm_rx_timeout_handler(struct hrtimer *hrtimer)
> -{
> -	struct bcm_op *op = container_of(hrtimer, struct bcm_op, timer);
> -
> -	/* schedule before NET_RX_SOFTIRQ */
> -	tasklet_hi_schedule(&op->tsklet);
> -
> -	/* no restart of the timer is done here! */
> -
> -	/* if user wants to be informed, when cyclic CAN-Messages come back */
> -	if ((op->flags & RX_ANNOUNCE_RESUME) && op->last_frames) {
> -		/* clear received CAN frames to indicate 'nothing received' */
> -		memset(op->last_frames, 0, op->nframes * op->cfsiz);
> -	}
>   
>   	return HRTIMER_NORESTART;
>   }
> @@ -583,14 +569,12 @@ static enum hrtimer_restart bcm_rx_timeo
>   /*
>    * bcm_rx_do_flush - helper for bcm_rx_thr_flush
>    */
> -static inline int bcm_rx_do_flush(struct bcm_op *op, int update,
> -				  unsigned int index)
> +static inline int bcm_rx_do_flush(struct bcm_op *op, unsigned int index)
>   {
>   	struct canfd_frame *lcf = op->last_frames + op->cfsiz * index;
>   
>   	if ((op->last_frames) && (lcf->flags & RX_THR)) {
> -		if (update)
> -			bcm_rx_changed(op, lcf);
> +		bcm_rx_changed(op, lcf);
>   		return 1;
>   	}
>   	return 0;
> @@ -598,11 +582,8 @@ static inline int bcm_rx_do_flush(struct
>   
>   /*
>    * bcm_rx_thr_flush - Check for throttled data and send it to the userspace
> - *
> - * update == 0 : just check if throttled data is available  (any irq context)
> - * update == 1 : check and send throttled data to userspace (soft_irq context)
>    */
> -static int bcm_rx_thr_flush(struct bcm_op *op, int update)
> +static int bcm_rx_thr_flush(struct bcm_op *op)
>   {
>   	int updated = 0;
>   
> @@ -611,24 +592,16 @@ static int bcm_rx_thr_flush(struct bcm_o
>   
>   		/* for MUX filter we start at index 1 */
>   		for (i = 1; i < op->nframes; i++)
> -			updated += bcm_rx_do_flush(op, update, i);
> +			updated += bcm_rx_do_flush(op, i);
>   
>   	} else {
>   		/* for RX_FILTER_ID and simple filter */
> -		updated += bcm_rx_do_flush(op, update, 0);
> +		updated += bcm_rx_do_flush(op, 0);
>   	}
>   
>   	return updated;
>   }
>   
> -static void bcm_rx_thr_tsklet(unsigned long data)
> -{
> -	struct bcm_op *op = (struct bcm_op *)data;
> -
> -	/* push the changed data to the userspace */
> -	bcm_rx_thr_flush(op, 1);
> -}
> -
>   /*
>    * bcm_rx_thr_handler - the time for blocked content updates is over now:
>    *                      Check for throttled data and send it to the userspace
> @@ -637,9 +610,7 @@ static enum hrtimer_restart bcm_rx_thr_h
>   {
>   	struct bcm_op *op = container_of(hrtimer, struct bcm_op, thrtimer);
>   
> -	tasklet_schedule(&op->thrtsklet);
> -
> -	if (bcm_rx_thr_flush(op, 0)) {
> +	if (bcm_rx_thr_flush(op)) {
>   		hrtimer_forward(hrtimer, ktime_get(), op->kt_ival2);
>   		return HRTIMER_RESTART;
>   	} else {
> @@ -735,23 +706,8 @@ static struct bcm_op *bcm_find_op(struct
>   
>   static void bcm_remove_op(struct bcm_op *op)
>   {
> -	if (op->tsklet.func) {
> -		while (test_bit(TASKLET_STATE_SCHED, &op->tsklet.state) ||
> -		       test_bit(TASKLET_STATE_RUN, &op->tsklet.state) ||
> -		       hrtimer_active(&op->timer)) {
> -			hrtimer_cancel(&op->timer);
> -			tasklet_kill(&op->tsklet);
> -		}
> -	}
> -
> -	if (op->thrtsklet.func) {
> -		while (test_bit(TASKLET_STATE_SCHED, &op->thrtsklet.state) ||
> -		       test_bit(TASKLET_STATE_RUN, &op->thrtsklet.state) ||
> -		       hrtimer_active(&op->thrtimer)) {
> -			hrtimer_cancel(&op->thrtimer);
> -			tasklet_kill(&op->thrtsklet);
> -		}
> -	}
> +	hrtimer_cancel(&op->timer);
> +	hrtimer_cancel(&op->thrtimer);
>   
>   	if ((op->frames) && (op->frames != &op->sframe))
>   		kfree(op->frames);
> @@ -979,15 +935,13 @@ static int bcm_tx_setup(struct bcm_msg_h
>   		op->ifindex = ifindex;
>   
>   		/* initialize uninitialized (kzalloc) structure */
> -		hrtimer_init(&op->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
> +		hrtimer_init(&op->timer, CLOCK_MONOTONIC_SOFT,
> +			     HRTIMER_MODE_REL);
>   		op->timer.function = bcm_tx_timeout_handler;
>   
> -		/* initialize tasklet for tx countevent notification */
> -		tasklet_init(&op->tsklet, bcm_tx_timeout_tsklet,
> -			     (unsigned long) op);
> -
>   		/* currently unused in tx_ops */
> -		hrtimer_init(&op->thrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
> +		hrtimer_init(&op->thrtimer, CLOCK_MONOTONIC_SOFT,
> +			     HRTIMER_MODE_REL);
>   
>   		/* add this bcm_op to the list of the tx_ops */
>   		list_add(&op->list, &bo->tx_ops);
> @@ -1150,20 +1104,14 @@ static int bcm_rx_setup(struct bcm_msg_h
>   		op->rx_ifindex = ifindex;
>   
>   		/* initialize uninitialized (kzalloc) structure */
> -		hrtimer_init(&op->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
> +		hrtimer_init(&op->timer, CLOCK_MONOTONIC_SOFT,
> +			     HRTIMER_MODE_REL);
>   		op->timer.function = bcm_rx_timeout_handler;
>   
> -		/* initialize tasklet for rx timeout notification */
> -		tasklet_init(&op->tsklet, bcm_rx_timeout_tsklet,
> -			     (unsigned long) op);
> -
> -		hrtimer_init(&op->thrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
> +		hrtimer_init(&op->thrtimer, CLOCK_MONOTONIC_SOFT,
> +			     HRTIMER_MODE_REL);
>   		op->thrtimer.function = bcm_rx_thr_handler;
>   
> -		/* initialize tasklet for rx throttle handling */
> -		tasklet_init(&op->thrtsklet, bcm_rx_thr_tsklet,
> -			     (unsigned long) op);
> -
>   		/* add this bcm_op to the list of the rx_ops */
>   		list_add(&op->list, &bo->rx_ops);
>   
> @@ -1209,7 +1157,7 @@ static int bcm_rx_setup(struct bcm_msg_h
>   			 */
>   			op->kt_lastmsg = 0;
>   			hrtimer_cancel(&op->thrtimer);
> -			bcm_rx_thr_flush(op, 1);
> +			bcm_rx_thr_flush(op);
>   		}
>   
>   		if ((op->flags & STARTTIMER) && op->kt_ival1)
> 
> 

[toc] | [prev] | [next] | [standalone]


#1724187 — [PATCH 10/25] hrtimer: Make handling of hrtimer reprogramming and enqueuing not conditional

FromAnna-Maria Gleixner <anna-maria@linutronix.de>
Date2017-08-31 14:30 +0200
Subject[PATCH 10/25] hrtimer: Make handling of hrtimer reprogramming and enqueuing not conditional
Message-ID<ukwLG-5Ay-65@gated-at.bofh.it>
In reply to#1724178
The hrtimer_reprogramming, remote timer enqueuing and handling of the
hrtimer_cpu_base struct member expires_next depend on the active high
resolution timers. This makes the code harder to understand.

To simplify the code, the hrtimer reprogramming is now executed
independently except for the real reprogramming part. The expires_next
stores now the first enqueued timer. Due to the adaption of the
check_target function, remote enqueuing is now only possible when the
expiry time is after the currently first expiry time independent of the
active high resolution timers.

Signed-off-by: Anna-Maria Gleixner <anna-maria@linutronix.de>
---
 kernel/time/hrtimer.c |   31 ++++++++++++-------------------
 1 file changed, 12 insertions(+), 19 deletions(-)

--- a/kernel/time/hrtimer.c
+++ b/kernel/time/hrtimer.c
@@ -154,10 +154,11 @@ struct hrtimer_clock_base *lock_hrtimer_
 }
 
 /*
- * With high resolution timers enabled we do not migrate the timer
- * when it is expiring before the next event on the target cpu because
- * we cannot reprogram the target cpu hardware and we would cause it
- * to fire late.
+ * We do not migrate the timer when it is expiring before the next
+ * event on the target cpu. When high resolution is enabled, we cannot
+ * reprogram the target cpu hardware and we would cause it to fire
+ * late. To keep it simple, we handle the high resolution enabled and
+ * disabled case similar.
  *
  * Called with cpu_base->lock of target cpu held.
  */
@@ -166,9 +167,6 @@ hrtimer_check_target(struct hrtimer *tim
 {
 	ktime_t expires;
 
-	if (!new_base->cpu_base->hres_active)
-		return 0;
-
 	expires = ktime_sub(hrtimer_get_expires(timer), new_base->offset);
 	return expires <= new_base->cpu_base->expires_next;
 }
@@ -689,21 +687,24 @@ static void hrtimer_reprogram(struct hrt
 
 	/* Update the pointer to the next expiring timer */
 	hrtimer_update_next_timer(cpu_base, timer);
+	cpu_base->expires_next = expires;
 
 	/*
+	 * If hres is not active, hardware does not have to be
+	 * programmed yet.
+	 *
 	 * If a hang was detected in the last timer interrupt then we
 	 * do not schedule a timer which is earlier than the expiry
 	 * which we enforced in the hang detection. We want the system
 	 * to make progress.
 	 */
-	if (cpu_base->hang_detected)
+	if (!__hrtimer_hres_active(cpu_base) || cpu_base->hang_detected)
 		return;
 
 	/*
 	 * Program the timer hardware. We enforce the expiry for
 	 * events which are already in the past.
 	 */
-	cpu_base->expires_next = expires;
 	tick_program_event(expires, 1);
 }
 
@@ -943,16 +944,8 @@ void hrtimer_start_range_ns(struct hrtim
 	if (!leftmost)
 		goto unlock;
 
-	if (!hrtimer_is_hres_active(timer)) {
-		/*
-		 * Kick to reschedule the next tick to handle the new timer
-		 * on dynticks target.
-		 */
-		if (new_base->cpu_base->nohz_active)
-			wake_up_nohz_cpu(new_base->cpu_base->cpu);
-	} else {
-		hrtimer_reprogram(timer, new_base);
-	}
+	hrtimer_reprogram(timer, new_base);
+
 unlock:
 	unlock_hrtimer_base(timer, &flags);
 }

[toc] | [prev] | [next] | [standalone]


#1724188 — [PATCH 14/25] hrtimer: Split out code from __hrtimer_get_next_event() for reuse

FromAnna-Maria Gleixner <anna-maria@linutronix.de>
Date2017-08-31 14:30 +0200
Subject[PATCH 14/25] hrtimer: Split out code from __hrtimer_get_next_event() for reuse
Message-ID<ukwLG-5Ay-61@gated-at.bofh.it>
In reply to#1724178
From: Anna-Maria Gleixner <anna-maria@linutronix.de>

Preparatory patch for softirq based hrtimers. No functional change.

Signed-off-by: Anna-Maria Gleixner <anna-maria@linutronix.de>
---
 kernel/time/hrtimer.c |   20 ++++++++++++++++----
 1 file changed, 16 insertions(+), 4 deletions(-)

--- a/kernel/time/hrtimer.c
+++ b/kernel/time/hrtimer.c
@@ -454,12 +454,12 @@ static inline void hrtimer_update_next_t
 }
 
 #if defined(CONFIG_NO_HZ_COMMON) || defined(CONFIG_HIGH_RES_TIMERS)
-static ktime_t __hrtimer_get_next_event(struct hrtimer_cpu_base *cpu_base)
+static ktime_t __hrtimer_next_event_base(struct hrtimer_cpu_base *cpu_base,
+					 unsigned int active,
+					 ktime_t expires_next)
 {
-	unsigned int active = cpu_base->active_bases;
-	ktime_t expires, expires_next = KTIME_MAX;
+	ktime_t expires;
 
-	hrtimer_update_next_timer(cpu_base, NULL);
 	while (active) {
 		unsigned int id = __ffs(active);
 		struct hrtimer_clock_base *base;
@@ -486,6 +486,18 @@ static ktime_t __hrtimer_get_next_event(
 		expires_next = 0;
 	return expires_next;
 }
+
+static ktime_t __hrtimer_get_next_event(struct hrtimer_cpu_base *cpu_base)
+{
+	unsigned int active = cpu_base->active_bases;
+	ktime_t expires_next = KTIME_MAX;
+
+	hrtimer_update_next_timer(cpu_base, NULL);
+
+	expires_next = __hrtimer_next_event_base(cpu_base, active, expires_next);
+
+	return expires_next;
+}
 #endif
 
 static inline ktime_t hrtimer_update_base(struct hrtimer_cpu_base *base)

[toc] | [prev] | [next] | [standalone]


#1724189 — [PATCH 25/25] usb/gadget/NCM: Replace tasklet with softirq hrtimer

FromAnna-Maria Gleixner <anna-maria@linutronix.de>
Date2017-08-31 14:30 +0200
Subject[PATCH 25/25] usb/gadget/NCM: Replace tasklet with softirq hrtimer
Message-ID<ukwLG-5Ay-67@gated-at.bofh.it>
In reply to#1724178
From: Thomas Gleixner <tglx@linutronix.de>

The tx_tasklet tasklet is used in invoke the hrtimer (task_timer) in
softirq context. This can be also achieved without the tasklet but with
CLOCK_MONOTONIC_SOFT as hrtimer base.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Anna-Maria Gleixner <anna-maria@linutronix.de>
Cc: Felipe Balbi <balbi@kernel.org>
Cc: linux-usb@vger.kernel.org
---
 drivers/usb/gadget/function/f_ncm.c |   28 ++++++----------------------
 1 file changed, 6 insertions(+), 22 deletions(-)

--- a/drivers/usb/gadget/function/f_ncm.c
+++ b/drivers/usb/gadget/function/f_ncm.c
@@ -77,9 +77,7 @@ struct f_ncm {
 	struct sk_buff			*skb_tx_ndp;
 	u16				ndp_dgram_count;
 	bool				timer_force_tx;
-	struct tasklet_struct		tx_tasklet;
 	struct hrtimer			task_timer;
-
 	bool				timer_stopping;
 };
 
@@ -1154,17 +1152,15 @@ static struct sk_buff *ncm_wrap_ntb(stru
 }
 
 /*
- * This transmits the NTB if there are frames waiting.
+ * The transmit should only be run if no skb data has been sent
+ * for a certain duration.
  */
-static void ncm_tx_tasklet(unsigned long data)
+static enum hrtimer_restart ncm_tx_timeout(struct hrtimer *data)
 {
-	struct f_ncm	*ncm = (void *)data;
-
-	if (ncm->timer_stopping)
-		return;
+	struct f_ncm *ncm = container_of(data, struct f_ncm, task_timer);
 
 	/* Only send if data is available. */
-	if (ncm->skb_tx_data) {
+	if (!ncm->timer_stopping && ncm->skb_tx_data) {
 		ncm->timer_force_tx = true;
 
 		/* XXX This allowance of a NULL skb argument to ndo_start_xmit
@@ -1177,16 +1173,6 @@ static void ncm_tx_tasklet(unsigned long
 
 		ncm->timer_force_tx = false;
 	}
-}
-
-/*
- * The transmit should only be run if no skb data has been sent
- * for a certain duration.
- */
-static enum hrtimer_restart ncm_tx_timeout(struct hrtimer *data)
-{
-	struct f_ncm *ncm = container_of(data, struct f_ncm, task_timer);
-	tasklet_schedule(&ncm->tx_tasklet);
 	return HRTIMER_NORESTART;
 }
 
@@ -1519,8 +1505,7 @@ static int ncm_bind(struct usb_configura
 	ncm->port.open = ncm_open;
 	ncm->port.close = ncm_close;
 
-	tasklet_init(&ncm->tx_tasklet, ncm_tx_tasklet, (unsigned long) ncm);
-	hrtimer_init(&ncm->task_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
+	hrtimer_init(&ncm->task_timer, CLOCK_MONOTONIC_SOFT, HRTIMER_MODE_REL);
 	ncm->task_timer.function = ncm_tx_timeout;
 
 	DBG(cdev, "CDC Network: %s speed IN/%s OUT/%s NOTIFY/%s\n",
@@ -1629,7 +1614,6 @@ static void ncm_unbind(struct usb_config
 	DBG(c->cdev, "ncm unbind\n");
 
 	hrtimer_cancel(&ncm->task_timer);
-	tasklet_kill(&ncm->tx_tasklet);
 
 	ncm_string_defs[0].id = 0;
 	usb_free_all_descriptors(f);

[toc] | [prev] | [next] | [standalone]


#1724190 — [PATCH 03/25] hrtimer: Fix kerneldoc for struct hrtimer_cpu_base

FromAnna-Maria Gleixner <anna-maria@linutronix.de>
Date2017-08-31 14:30 +0200
Subject[PATCH 03/25] hrtimer: Fix kerneldoc for struct hrtimer_cpu_base
Message-ID<ukwLG-5Ay-69@gated-at.bofh.it>
In reply to#1724178
From: Anna-Maria Gleixner <anna-maria@linutronix.de>

The sequence '/**' marks the start of a struct description. Add the
missing second asterisk. While at it adapt the ordering of the struct
members to the struct definition and document the purpose of
expires_next more precisely.

Signed-off-by: Anna-Maria Gleixner <anna-maria@linutronix.de>
---
 include/linux/hrtimer.h |    8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

--- a/include/linux/hrtimer.h
+++ b/include/linux/hrtimer.h
@@ -144,7 +144,7 @@ enum  hrtimer_base_type {
 	HRTIMER_MAX_CLOCK_BASES,
 };
 
-/*
+/**
  * struct hrtimer_cpu_base - the per cpu clock bases
  * @lock:		lock protecting the base and associated clock bases
  *			and timers
@@ -155,12 +155,12 @@ enum  hrtimer_base_type {
  * @clock_was_set_seq:	Sequence counter of clock was set events
  * @migration_enabled:	The migration of hrtimers to other cpus is enabled
  * @nohz_active:	The nohz functionality is enabled
- * @expires_next:	absolute time of the next event which was scheduled
- *			via clock_set_next_event()
- * @next_timer:		Pointer to the first expiring timer
  * @in_hrtirq:		hrtimer_interrupt() is currently executing
  * @hres_active:	State of high resolution mode
  * @hang_detected:	The last hrtimer interrupt detected a hang
+ * @expires_next:	absolute time of the next event, is required for remote
+ *			hrtimer enqueue
+ * @next_timer:		Pointer to the first expiring timer
  * @nr_events:		Total number of hrtimer interrupt events
  * @nr_retries:		Total number of hrtimer interrupt retries
  * @nr_hangs:		Total number of hrtimer interrupt hangs

[toc] | [prev] | [next] | [standalone]


#1724191 — [PATCH 09/25] hrtimer: Reduce conditional code (hrtimer_reprogram())

FromAnna-Maria Gleixner <anna-maria@linutronix.de>
Date2017-08-31 14:30 +0200
Subject[PATCH 09/25] hrtimer: Reduce conditional code (hrtimer_reprogram())
Message-ID<ukwLG-5Ay-71@gated-at.bofh.it>
In reply to#1724178
The hrtimer_reprogram() is currently required only when
CONFIG_HIGH_RES_TIMERS is set. Additional bitfields of hrtimer_cpu_base
struct are high resolution timer specific as well.

To simplify the hrtimer code, the behaviour of CONFIG_HIGH_RES_TIMERS and
!CONFIG_HIGH_RES_TIMERS should be similar. As preparation for this, the
function hrtimer_reprogram() and required hrtimer_cpu_base struct members
are moved outside the conditional area.

Signed-off-by: Anna-Maria Gleixner <anna-maria@linutronix.de>
---
 include/linux/hrtimer.h |    6 +-
 kernel/time/hrtimer.c   |  131 +++++++++++++++++++++++-------------------------
 2 files changed, 66 insertions(+), 71 deletions(-)

--- a/include/linux/hrtimer.h
+++ b/include/linux/hrtimer.h
@@ -180,10 +180,10 @@ struct hrtimer_cpu_base {
 	unsigned int			clock_was_set_seq;
 	bool				migration_enabled;
 	bool				nohz_active;
-	unsigned int			hres_active	: 1;
-#ifdef CONFIG_HIGH_RES_TIMERS
-	unsigned int			in_hrtirq	: 1,
+	unsigned int			hres_active	: 1,
+					in_hrtirq	: 1,
 					hang_detected	: 1;
+#ifdef CONFIG_HIGH_RES_TIMERS
 	unsigned int			nr_events;
 	unsigned int			nr_retries;
 	unsigned int			nr_hangs;
--- a/kernel/time/hrtimer.c
+++ b/kernel/time/hrtimer.c
@@ -449,13 +449,13 @@ static inline void debug_deactivate(stru
 	trace_hrtimer_cancel(timer);
 }
 
-#if defined(CONFIG_NO_HZ_COMMON) || defined(CONFIG_HIGH_RES_TIMERS)
 static inline void hrtimer_update_next_timer(struct hrtimer_cpu_base *cpu_base,
 					     struct hrtimer *timer)
 {
 	cpu_base->next_timer = timer;
 }
 
+#if defined(CONFIG_NO_HZ_COMMON) || defined(CONFIG_HIGH_RES_TIMERS)
 static ktime_t __hrtimer_get_next_event(struct hrtimer_cpu_base *cpu_base)
 {
 	unsigned int active = cpu_base->active_bases;
@@ -582,68 +582,6 @@ hrtimer_force_reprogram(struct hrtimer_c
 }
 
 /*
- * When a timer is enqueued and expires earlier than the already enqueued
- * timers, we have to check, whether it expires earlier than the timer for
- * which the clock event device was armed.
- *
- * Called with interrupts disabled and base->cpu_base.lock held
- */
-static void hrtimer_reprogram(struct hrtimer *timer,
-			      struct hrtimer_clock_base *base)
-{
-	struct hrtimer_cpu_base *cpu_base = this_cpu_ptr(&hrtimer_bases);
-	ktime_t expires = ktime_sub(hrtimer_get_expires(timer), base->offset);
-
-	WARN_ON_ONCE(hrtimer_get_expires_tv64(timer) < 0);
-
-	/*
-	 * If the timer is not on the current cpu, we cannot reprogram
-	 * the other cpus clock event device.
-	 */
-	if (base->cpu_base != cpu_base)
-		return;
-
-	/*
-	 * If the hrtimer interrupt is running, then it will
-	 * reevaluate the clock bases and reprogram the clock event
-	 * device. The callbacks are always executed in hard interrupt
-	 * context so we don't need an extra check for a running
-	 * callback.
-	 */
-	if (cpu_base->in_hrtirq)
-		return;
-
-	/*
-	 * CLOCK_REALTIME timer might be requested with an absolute
-	 * expiry time which is less than base->offset. Set it to 0.
-	 */
-	if (expires < 0)
-		expires = 0;
-
-	if (expires >= cpu_base->expires_next)
-		return;
-
-	/* Update the pointer to the next expiring timer */
-	hrtimer_update_next_timer(cpu_base, timer);
-
-	/*
-	 * If a hang was detected in the last timer interrupt then we
-	 * do not schedule a timer which is earlier than the expiry
-	 * which we enforced in the hang detection. We want the system
-	 * to make progress.
-	 */
-	if (cpu_base->hang_detected)
-		return;
-
-	/*
-	 * Program the timer hardware. We enforce the expiry for
-	 * events which are already in the past.
-	 */
-	cpu_base->expires_next = expires;
-	tick_program_event(expires, 1);
-}
-
-/*
  * Retrigger next event is called after clock was set
  *
  * Called with interrupts disabled via on_each_cpu()
@@ -703,16 +641,73 @@ static inline int hrtimer_is_hres_enable
 static inline void hrtimer_switch_to_hres(void) { }
 static inline void
 hrtimer_force_reprogram(struct hrtimer_cpu_base *base, int skip_equal) { }
-static inline int hrtimer_reprogram(struct hrtimer *timer,
-				    struct hrtimer_clock_base *base)
-{
-	return 0;
-}
 static inline void retrigger_next_event(void *arg) { }
 
 #endif /* CONFIG_HIGH_RES_TIMERS */
 
 /*
+ * When a timer is enqueued and expires earlier than the already enqueued
+ * timers, we have to check, whether it expires earlier than the timer for
+ * which the clock event device was armed.
+ *
+ * Called with interrupts disabled and base->cpu_base.lock held
+ */
+static void hrtimer_reprogram(struct hrtimer *timer,
+			      struct hrtimer_clock_base *base)
+{
+	struct hrtimer_cpu_base *cpu_base = this_cpu_ptr(&hrtimer_bases);
+	ktime_t expires = ktime_sub(hrtimer_get_expires(timer), base->offset);
+
+	WARN_ON_ONCE(hrtimer_get_expires_tv64(timer) < 0);
+
+	/*
+	 * If the timer is not on the current cpu, we cannot reprogram
+	 * the other cpus clock event device.
+	 */
+	if (base->cpu_base != cpu_base)
+		return;
+
+	/*
+	 * If the hrtimer interrupt is running, then it will
+	 * reevaluate the clock bases and reprogram the clock event
+	 * device. The callbacks are always executed in hard interrupt
+	 * context so we don't need an extra check for a running
+	 * callback.
+	 */
+	if (cpu_base->in_hrtirq)
+		return;
+
+	/*
+	 * CLOCK_REALTIME timer might be requested with an absolute
+	 * expiry time which is less than base->offset. Set it to 0.
+	 */
+	if (expires < 0)
+		expires = 0;
+
+	if (expires >= cpu_base->expires_next)
+		return;
+
+	/* Update the pointer to the next expiring timer */
+	hrtimer_update_next_timer(cpu_base, timer);
+
+	/*
+	 * If a hang was detected in the last timer interrupt then we
+	 * do not schedule a timer which is earlier than the expiry
+	 * which we enforced in the hang detection. We want the system
+	 * to make progress.
+	 */
+	if (cpu_base->hang_detected)
+		return;
+
+	/*
+	 * Program the timer hardware. We enforce the expiry for
+	 * events which are already in the past.
+	 */
+	cpu_base->expires_next = expires;
+	tick_program_event(expires, 1);
+}
+
+/*
  * Clock realtime was set
  *
  * Change the offset of the realtime clock vs. the monotonic

[toc] | [prev] | [next] | [standalone]


#1724193

FromAnna-Maria Gleixner <anna-maria@linutronix.de>
Date2017-08-31 14:40 +0200
Message-ID<ukwVk-5Dr-21@gated-at.bofh.it>
In reply to#1724178
I'm sorry for the typo in the email address!

    Anna-Maria

On Thu, 31 Aug 2017, Anna-Maria Gleixner wrote:

> There are quite some places in the kernel which use a combination of
> hrtimers and tasklets to make use of the precise expiry of hrtimers, which
> schedule a tasklet to bring the actual function into softirq context.
> 
> This was introduced when the previous hrtimer softirq code was
> removed. That code was implemented by expiring the timer in hard irq
> context and then deferring the execution of the callback into softirq
> context. That caused a lot of pointless shuffling between the rbtree and a
> linked list.
> 
> In recent discussions it turned out that more potential users of hrtimers
> in softirq context might come up. Aside of that the RT patches need this
> functionality as well to defer hrtimers into softirq context if their
> callbacks are not interrupt safe on RT.
> 
> This series implements a new approach by adding SOFT_* clock ids and
> instead of doing the list shuffle, timers started with these clock ids are
> put into separate soft expiry hrtimer queues. These queues are evaluated
> only when the hardirq context detects that the first expiring timer in the
> softirq queues has expired. That makes the overhead in the hardirq context
> minimal.
> 
> The series reworks the code to reuse as much as possible from the existing
> facilities for the new softirq hrtimers and integrates them with all
> flavours of hrtimers (HIGH_RES=y/n - NOHZ=y/n).
> 
> To achieve this quite some of the conditionals in the existing code are
> removed for the price of adding some pointless data and state tracking to
> the HIGH_RES=n case. That's minimal, but well worth it as it increases the
> readability and maintainability of the code.
> 
> The first part of the series implements the new functionality and the
> second part converts the hrtimer/tasklet users to make use of it and
> removes struct hrtimer_tasklet and the surrounding helper functions.
> 
> This series is available from git as well:
> 
>     git://git.kernel.org/pub/scm/linux/kernel/git/bigeasy/linux-hrtimer.git soft_hrtimer
>     https://git.kernel.org/bigeasy/linux-hrtimer/h/soft_hrtimer
> 
> 
> Thanks,
> 
> 	Anna-Maria
> 
> ---
>  drivers/net/usb/cdc_ncm.c             |   37 +-
>  drivers/net/wireless/mac80211_hwsim.c |   44 +-
>  drivers/usb/gadget/function/f_ncm.c   |   28 -
>  include/linux/hrtimer.h               |   76 ++---
>  include/linux/interrupt.h             |   25 -
>  include/linux/usb/cdc_ncm.h           |    2 
>  include/net/xfrm.h                    |    2 
>  kernel/softirq.c                      |   51 ---
>  kernel/time/hrtimer.c                 |  513 +++++++++++++++++++++-------------
>  net/can/bcm.c                         |  150 +++------
>  net/xfrm/xfrm_state.c                 |   29 +
>  sound/drivers/dummy.c                 |   16 -
>  12 files changed, 484 insertions(+), 489 deletions(-)
> 
> 

[toc] | [prev] | [standalone]


Page 2 of 2 — ← Prev page 1 [2]

Back to top | Article view | linux.kernel


csiph-web