Merge branch 'timers-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel...
authorLinus Torvalds <torvalds@linux-foundation.org>
Tue, 30 Jan 2018 00:50:58 +0000 (16:50 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Tue, 30 Jan 2018 00:50:58 +0000 (16:50 -0800)
Pull timer updates from Thomas Gleixner:
 "The timer departement presents:

   - A rather large rework of the hrtimer infrastructure which
     introduces softirq based hrtimers to replace the spread of
     hrtimer/tasklet combos which force the actual callback execution
     into softirq context. The approach is completely different from the
     initial implementation which you cursed at 10 years ago rightfully.

     The softirq based timers have their own queues and there is no
     nasty indirection and list reshuffling in the hard interrupt
     anymore. This comes with conversion of some of the hrtimer/tasklet
     users, the rest and the final removal of that horrible interface
     will come towards the end of the merge window or go through the
     relevant maintainer trees.

     Note: The top commit merged the last minute bugfix for the 10 years
     old CPU hotplug bug as I wanted to make sure that I fatfinger the
     merge conflict resolution myself.

   - The overhaul of the STM32 clocksource/clockevents driver

   - A new driver for the Spreadtrum SC9860 timer

   - A new driver dor the Actions Semi S700 timer

   - The usual set of fixes and updates all over the place"

* 'timers-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: (53 commits)
  usb/gadget/NCM: Replace tasklet with softirq hrtimer
  ALSA/dummy: Replace tasklet with softirq hrtimer
  hrtimer: Implement SOFT/HARD clock base selection
  hrtimer: Implement support for softirq based hrtimers
  hrtimer: Prepare handling of hard and softirq based hrtimers
  hrtimer: Add clock bases and hrtimer mode for softirq context
  hrtimer: Use irqsave/irqrestore around __run_hrtimer()
  hrtimer: Factor out __hrtimer_next_event_base()
  hrtimer: Factor out __hrtimer_start_range_ns()
  hrtimer: Remove the 'base' parameter from hrtimer_reprogram()
  hrtimer: Make remote enqueue decision less restrictive
  hrtimer: Unify remote enqueue handling
  hrtimer: Unify hrtimer removal handling
  hrtimer: Make hrtimer_force_reprogramm() unconditionally available
  hrtimer: Make hrtimer_reprogramm() unconditional
  hrtimer: Make hrtimer_cpu_base.next_timer handling unconditional
  hrtimer: Make the remote enqueue check unconditional
  hrtimer: Use accesor functions instead of direct access
  hrtimer: Make the hrtimer_cpu_base::hres_active field unconditional, to simplify the code
  hrtimer: Make room in 'struct hrtimer_cpu_base'
  ...

1  2 
sound/drivers/dummy.c

diff --combined sound/drivers/dummy.c
index 69db45bc0197e398ce298ed2c7d9f71b0539f9fb,6ad2ff57833d6ad28d62f6c865c8c58abb726109..8fb9a54fe8ba879857ce61ec25d5d2408c9a21ad
@@@ -375,17 -375,9 +375,9 @@@ struct dummy_hrtimer_pcm 
        ktime_t period_time;
        atomic_t running;
        struct hrtimer timer;
-       struct tasklet_struct tasklet;
        struct snd_pcm_substream *substream;
  };
  
- static void dummy_hrtimer_pcm_elapsed(unsigned long priv)
- {
-       struct dummy_hrtimer_pcm *dpcm = (struct dummy_hrtimer_pcm *)priv;
-       if (atomic_read(&dpcm->running))
-               snd_pcm_period_elapsed(dpcm->substream);
- }
  static enum hrtimer_restart dummy_hrtimer_callback(struct hrtimer *timer)
  {
        struct dummy_hrtimer_pcm *dpcm;
        dpcm = container_of(timer, struct dummy_hrtimer_pcm, timer);
        if (!atomic_read(&dpcm->running))
                return HRTIMER_NORESTART;
-       tasklet_schedule(&dpcm->tasklet);
+       /*
+        * In cases of XRUN and draining, this calls .trigger to stop PCM
+        * substream.
+        */
+       snd_pcm_period_elapsed(dpcm->substream);
+       if (!atomic_read(&dpcm->running))
+               return HRTIMER_NORESTART;
        hrtimer_forward_now(timer, dpcm->period_time);
        return HRTIMER_RESTART;
  }
@@@ -403,7 -402,7 +402,7 @@@ static int dummy_hrtimer_start(struct s
        struct dummy_hrtimer_pcm *dpcm = substream->runtime->private_data;
  
        dpcm->base_time = hrtimer_cb_get_time(&dpcm->timer);
-       hrtimer_start(&dpcm->timer, dpcm->period_time, HRTIMER_MODE_REL);
+       hrtimer_start(&dpcm->timer, dpcm->period_time, HRTIMER_MODE_REL_SOFT);
        atomic_set(&dpcm->running, 1);
        return 0;
  }
@@@ -413,14 -412,14 +412,14 @@@ static int dummy_hrtimer_stop(struct sn
        struct dummy_hrtimer_pcm *dpcm = substream->runtime->private_data;
  
        atomic_set(&dpcm->running, 0);
-       hrtimer_cancel(&dpcm->timer);
+       if (!hrtimer_callback_running(&dpcm->timer))
+               hrtimer_cancel(&dpcm->timer);
        return 0;
  }
  
  static inline void dummy_hrtimer_sync(struct dummy_hrtimer_pcm *dpcm)
  {
        hrtimer_cancel(&dpcm->timer);
-       tasklet_kill(&dpcm->tasklet);
  }
  
  static snd_pcm_uframes_t
@@@ -465,12 -464,10 +464,10 @@@ static int dummy_hrtimer_create(struct 
        if (!dpcm)
                return -ENOMEM;
        substream->runtime->private_data = dpcm;
-       hrtimer_init(&dpcm->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
+       hrtimer_init(&dpcm->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL_SOFT);
        dpcm->timer.function = dummy_hrtimer_callback;
        dpcm->substream = substream;
        atomic_set(&dpcm->running, 0);
-       tasklet_init(&dpcm->tasklet, dummy_hrtimer_pcm_elapsed,
-                    (unsigned long)dpcm);
        return 0;
  }
  
@@@ -830,7 -827,7 +827,7 @@@ static int snd_dummy_capsrc_put(struct 
  static int snd_dummy_iobox_info(struct snd_kcontrol *kcontrol,
                                struct snd_ctl_elem_info *info)
  {
 -      const char *const names[] = { "None", "CD Player" };
 +      static const char *const names[] = { "None", "CD Player" };
  
        return snd_ctl_enum_info(info, 1, 2, names);
  }