Dear RT folks!

I'm pleased to announce the v3.18.9-rt4 patch set.

Changes since v3.18.9-rt3

- The patch "rwsem-rt: Do not allow readers to nest" has been reverted.
  This means cpufreq works again.

- A fix in sound/audio to not disable interrupts as part of the locking.
  (Mike Galbraith)

- A fix in NFS which caused " sleeping function called from invalid
  context" warnings (Mike Galbraith)

- Thermal wake ups on X86 are now handled defred into thread context
  (Daniel Wagner)

- A ifdefs in lockdep self-test to avoid long "defined but not used"
  compiler warnings (Josh Cartwright)

- Fixed dead-lock handling of the ww_mutex (Mike Galbraith)

- The primary handler of mmc/sdhci is moved into the threaded one to
  avoid taking sleeping locks in IRQ contet. (Reported by Michal Šmucr)

- The IRQ-work handling has been updated to get rid of the warning
  triggered in FULL_NO_HZ mode (Reported by Carsten Emde & Luis Claudio
  R. Goncalves)

- "rcu torture" now compiles if enabled (Luis Claudio R. Goncalves)

- "Simple work queue" now disables interrupts during list handling

- The MCE check now uses the "Simple work queue" instead of its own
  thread for defered work (Daniel Wagner)

Known issues:

      - bcache is disabled.

      - lazy preempt on x86_64 leads to a crash with some load.

      - CPU hotplug works in general. Steven's test script however
        deadlocks usually on the second invocation.

      - xor / raid_pq
        I had max latency jumping up to 67563us on one CPU while the next
        lower max was 58us. I tracked it down to module's init code of
        xor and raid_pq. Both disable preemption while measuring the
        measuring the performance of the individual implementation.


The delta patch against 3.18.9-rt3 is appended below and can be found here: 

   
https://www.kernel.org/pub/linux/kernel/projects/rt/3.18/incr/patch-3.18.9-rt3-rt4.patch.xz

The RT patch against 3.18.9 can be found here:

   
https://www.kernel.org/pub/linux/kernel/projects/rt/3.18/patch-3.18.9-rt4.patch.xz

The split quilt queue is available at:

   
https://www.kernel.org/pub/linux/kernel/projects/rt/3.18/patches-3.18.9-rt4.tar.xz

Sebastian

diff --git a/arch/x86/kernel/cpu/mcheck/mce.c b/arch/x86/kernel/cpu/mcheck/mce.c
index 718fc6cc6c64..d7f1c8316f94 100644
--- a/arch/x86/kernel/cpu/mcheck/mce.c
+++ b/arch/x86/kernel/cpu/mcheck/mce.c
@@ -18,7 +18,6 @@
 #include <linux/rcupdate.h>
 #include <linux/kobject.h>
 #include <linux/uaccess.h>
-#include <linux/kthread.h>
 #include <linux/kdebug.h>
 #include <linux/kernel.h>
 #include <linux/percpu.h>
@@ -43,6 +42,7 @@
 #include <linux/irq_work.h>
 #include <linux/export.h>
 #include <linux/jiffies.h>
+#include <linux/work-simple.h>
 
 #include <asm/processor.h>
 #include <asm/mce.h>
@@ -1364,7 +1364,7 @@ static void mce_do_trigger(struct work_struct *work)
 
 static DECLARE_WORK(mce_trigger_work, mce_do_trigger);
 
-static void __mce_notify_work(void)
+static void __mce_notify_work(struct swork_event *event)
 {
        /* Not more than two messages every minute */
        static DEFINE_RATELIMIT_STATE(ratelimit, 60*HZ, 2);
@@ -1385,43 +1385,31 @@ static void __mce_notify_work(void)
 }
 
 #ifdef CONFIG_PREEMPT_RT_FULL
-struct task_struct *mce_notify_helper;
-
-static int mce_notify_helper_thread(void *unused)
-{
-       while (1) {
-               set_current_state(TASK_INTERRUPTIBLE);
-               schedule();
-               if (kthread_should_stop())
-                       break;
-               __mce_notify_work();
-       }
-       return 0;
-}
+static bool notify_work_ready __read_mostly;
+static struct swork_event notify_work;
 
 static int mce_notify_work_init(void)
 {
-       mce_notify_helper = kthread_run(mce_notify_helper_thread, NULL,
-                                          "mce-notify");
-       if (!mce_notify_helper)
-               return -ENOMEM;
+       int err;
+
+       err = swork_get();
+       if (err)
+               return err;
 
+       INIT_SWORK(&notify_work, __mce_notify_work);
+       notify_work_ready = true;
        return 0;
 }
 
 static void mce_notify_work(void)
 {
-       if (WARN_ON_ONCE(!mce_notify_helper)) {
-               pr_info(HW_ERR "Machine check event before MCE init; 
ignored\n");
-               return;
-       }
-
-       wake_up_process(mce_notify_helper);
+       if (notify_work_ready)
+               swork_queue(&notify_work);
 }
 #else
 static void mce_notify_work(void)
 {
-       __mce_notify_work();
+       __mce_notify_work(NULL);
 }
 static inline int mce_notify_work_init(void) { return 0; }
 #endif
@@ -2497,6 +2485,10 @@ static __init int mcheck_init_device(void)
                goto err_out;
        }
 
+       err = mce_notify_work_init();
+       if (err)
+               goto err_out;
+
        if (!zalloc_cpumask_var(&mce_device_initialized, GFP_KERNEL)) {
                err = -ENOMEM;
                goto err_out;
@@ -2533,15 +2525,8 @@ static __init int mcheck_init_device(void)
        if (err)
                goto err_register;
 
-       err = mce_notify_work_init();
-       if (err)
-               goto err_notify;
-
        return 0;
 
-err_notify:
-       misc_deregister(&mce_chrdev_device);
-
 err_register:
        unregister_syscore_ops(&mce_syscore_ops);
 
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index 023c2010cd75..bcde53774bc9 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -2565,6 +2565,31 @@ static irqreturn_t sdhci_thread_irq(int irq, void 
*dev_id)
        return isr ? IRQ_HANDLED : IRQ_NONE;
 }
 
+#ifdef CONFIG_PREEMPT_RT_BASE
+static irqreturn_t sdhci_rt_irq(int irq, void *dev_id)
+{
+       irqreturn_t ret;
+
+       local_bh_disable();
+       ret = sdhci_irq(irq, dev_id);
+       local_bh_enable();
+       if (ret == IRQ_WAKE_THREAD)
+               ret = sdhci_thread_irq(irq, dev_id);
+       return ret;
+}
+#endif
+
+static int sdhci_req_irq(struct sdhci_host *host)
+{
+#ifdef CONFIG_PREEMPT_RT_BASE
+       return request_threaded_irq(host->irq, NULL, sdhci_rt_irq,
+                                   IRQF_SHARED, mmc_hostname(host->mmc), host);
+#else
+       return request_threaded_irq(host->irq, sdhci_irq, sdhci_thread_irq,
+                                   IRQF_SHARED, mmc_hostname(host->mmc), host);
+#endif
+}
+
 /*****************************************************************************\
  *                                                                           *
  * Suspend/resume                                                            *
@@ -2632,9 +2657,7 @@ int sdhci_resume_host(struct sdhci_host *host)
        }
 
        if (!device_may_wakeup(mmc_dev(host->mmc))) {
-               ret = request_threaded_irq(host->irq, sdhci_irq,
-                                          sdhci_thread_irq, IRQF_SHARED,
-                                          mmc_hostname(host->mmc), host);
+               ret = sdhci_req_irq(host);
                if (ret)
                        return ret;
        } else {
@@ -3253,8 +3276,7 @@ int sdhci_add_host(struct sdhci_host *host)
 
        sdhci_init(host, 0);
 
-       ret = request_threaded_irq(host->irq, sdhci_irq, sdhci_thread_irq,
-                                  IRQF_SHARED, mmc_hostname(mmc), host);
+       ret = sdhci_req_irq(host);
        if (ret) {
                pr_err("%s: Failed to request IRQ %d: %d\n",
                       mmc_hostname(mmc), host->irq, ret);
diff --git a/drivers/thermal/x86_pkg_temp_thermal.c 
b/drivers/thermal/x86_pkg_temp_thermal.c
index 9ea3d9d49ffc..e3c2663e0b1f 100644
--- a/drivers/thermal/x86_pkg_temp_thermal.c
+++ b/drivers/thermal/x86_pkg_temp_thermal.c
@@ -29,6 +29,7 @@
 #include <linux/pm.h>
 #include <linux/thermal.h>
 #include <linux/debugfs.h>
+#include <linux/work-simple.h>
 #include <asm/cpu_device_id.h>
 #include <asm/mce.h>
 
@@ -352,7 +353,7 @@ static void pkg_temp_thermal_threshold_work_fn(struct 
work_struct *work)
        }
 }
 
-static int pkg_temp_thermal_platform_thermal_notify(__u64 msr_val)
+static void platform_thermal_notify_work(struct swork_event *event)
 {
        unsigned long flags;
        int cpu = smp_processor_id();
@@ -369,7 +370,7 @@ static int pkg_temp_thermal_platform_thermal_notify(__u64 
msr_val)
                        pkg_work_scheduled[phy_id]) {
                disable_pkg_thres_interrupt();
                spin_unlock_irqrestore(&pkg_work_lock, flags);
-               return -EINVAL;
+               return;
        }
        pkg_work_scheduled[phy_id] = 1;
        spin_unlock_irqrestore(&pkg_work_lock, flags);
@@ -378,9 +379,48 @@ static int pkg_temp_thermal_platform_thermal_notify(__u64 
msr_val)
        schedule_delayed_work_on(cpu,
                                &per_cpu(pkg_temp_thermal_threshold_work, cpu),
                                msecs_to_jiffies(notify_delay_ms));
+}
+
+#ifdef CONFIG_PREEMPT_RT_FULL
+static struct swork_event notify_work;
+
+static int thermal_notify_work_init(void)
+{
+       int err;
+
+       err = swork_get();
+       if (err)
+               return err;
+
+       INIT_SWORK(&notify_work, platform_thermal_notify_work);
        return 0;
 }
 
+static void thermal_notify_work_cleanup(void)
+{
+       swork_put();
+}
+
+static int pkg_temp_thermal_platform_thermal_notify(__u64 msr_val)
+{
+       swork_queue(&notify_work);
+       return 0;
+}
+
+#else  /* !CONFIG_PREEMPT_RT_FULL */
+
+static int thermal_notify_work_init(void) { return 0; }
+
+static int thermal_notify_work_cleanup(void) {  }
+
+static int pkg_temp_thermal_platform_thermal_notify(__u64 msr_val)
+{
+       platform_thermal_notify_work(NULL);
+
+       return 0;
+}
+#endif /* CONFIG_PREEMPT_RT_FULL */
+
 static int find_siblings_cpu(int cpu)
 {
        int i;
@@ -584,6 +624,9 @@ static int __init pkg_temp_thermal_init(void)
        if (!x86_match_cpu(pkg_temp_thermal_ids))
                return -ENODEV;
 
+       if (!thermal_notify_work_init())
+               return -ENODEV;
+
        spin_lock_init(&pkg_work_lock);
        platform_thermal_package_notify =
                        pkg_temp_thermal_platform_thermal_notify;
@@ -608,7 +651,7 @@ static int __init pkg_temp_thermal_init(void)
        kfree(pkg_work_scheduled);
        platform_thermal_package_notify = NULL;
        platform_thermal_package_rate_control = NULL;
-
+       thermal_notify_work_cleanup();
        return -ENODEV;
 }
 
@@ -633,6 +676,7 @@ static void __exit pkg_temp_thermal_exit(void)
        mutex_unlock(&phy_dev_list_mutex);
        platform_thermal_package_notify = NULL;
        platform_thermal_package_rate_control = NULL;
+       thermal_notify_work_cleanup();
        for_each_online_cpu(i)
                cancel_delayed_work_sync(
                        &per_cpu(pkg_temp_thermal_threshold_work, i));
diff --git a/include/linux/rwsem_rt.h b/include/linux/rwsem_rt.h
index 0065b08fbb7a..924c2d274ab5 100644
--- a/include/linux/rwsem_rt.h
+++ b/include/linux/rwsem_rt.h
@@ -20,6 +20,7 @@
 
 struct rw_semaphore {
        struct rt_mutex         lock;
+       int                     read_depth;
 #ifdef CONFIG_DEBUG_LOCK_ALLOC
        struct lockdep_map      dep_map;
 #endif
diff --git a/kernel/irq_work.c b/kernel/irq_work.c
index 19c363a437bd..0c6491228b17 100644
--- a/kernel/irq_work.c
+++ b/kernel/irq_work.c
@@ -71,6 +71,8 @@ void __weak arch_irq_work_raise(void)
  */
 bool irq_work_queue_on(struct irq_work *work, int cpu)
 {
+       bool raise_irqwork;
+
        /* All work should have been flushed before going offline */
        WARN_ON_ONCE(cpu_is_offline(cpu));
 
@@ -81,7 +83,19 @@ bool irq_work_queue_on(struct irq_work *work, int cpu)
        if (!irq_work_claim(work))
                return false;
 
-       if (llist_add(&work->llnode, &per_cpu(raised_list, cpu)))
+#ifdef CONFIG_PREEMPT_RT_FULL
+       if (work->flags & IRQ_WORK_HARD_IRQ)
+               raise_irqwork = llist_add(&work->llnode,
+                                         &per_cpu(hirq_work_list, cpu));
+       else
+               raise_irqwork = llist_add(&work->llnode,
+                                         &per_cpu(lazy_list, cpu));
+#else
+               raise_irqwork = llist_add(&work->llnode,
+                                         &per_cpu(raised_list, cpu));
+#endif
+
+       if (raise_irqwork)
                arch_send_call_function_single_ipi(cpu);
 
        return true;
@@ -101,19 +115,14 @@ bool irq_work_queue(struct irq_work *work)
 
 #ifdef CONFIG_PREEMPT_RT_FULL
        if (work->flags & IRQ_WORK_HARD_IRQ) {
-               if (llist_add(&work->llnode, this_cpu_ptr(&hirq_work_list))) {
-                       if (work->flags & IRQ_WORK_LAZY) {
-                               if (tick_nohz_tick_stopped())
-                                       arch_irq_work_raise();
-                       } else {
-                               arch_irq_work_raise();
-                       }
-               }
-       /* If the work is "lazy", handle it from next tick if any */
-       } else if (work->flags & IRQ_WORK_LAZY) {
+               if (llist_add(&work->llnode, this_cpu_ptr(&hirq_work_list)))
+                       arch_irq_work_raise();
+       } else {
+               if (llist_add(&work->llnode, this_cpu_ptr(&lazy_list)))
+                       arch_irq_work_raise();
+       }
 #else
        if (work->flags & IRQ_WORK_LAZY) {
-#endif
                if (llist_add(&work->llnode, this_cpu_ptr(&lazy_list)) &&
                    tick_nohz_tick_stopped())
                        arch_irq_work_raise();
@@ -121,6 +130,7 @@ bool irq_work_queue(struct irq_work *work)
                if (llist_add(&work->llnode, this_cpu_ptr(&raised_list)))
                        arch_irq_work_raise();
        }
+#endif
 
        preempt_enable();
 
@@ -137,7 +147,8 @@ bool irq_work_needs_cpu(void)
 
        if (llist_empty(raised))
                if (llist_empty(lazy))
-                       return false;
+                       if (llist_empty(this_cpu_ptr(&hirq_work_list)))
+                               return false;
 
        /* All work should have been flushed before going offline */
        WARN_ON_ONCE(cpu_is_offline(smp_processor_id()));
diff --git a/kernel/locking/rt.c b/kernel/locking/rt.c
index eac2ddea9c45..73c55089fb93 100644
--- a/kernel/locking/rt.c
+++ b/kernel/locking/rt.c
@@ -322,7 +322,8 @@ EXPORT_SYMBOL(rt_up_write);
 void  rt_up_read(struct rw_semaphore *rwsem)
 {
        rwsem_release(&rwsem->dep_map, 1, _RET_IP_);
-       rt_mutex_unlock(&rwsem->lock);
+       if (--rwsem->read_depth == 0)
+               rt_mutex_unlock(&rwsem->lock);
 }
 EXPORT_SYMBOL(rt_up_read);
 
@@ -333,6 +334,7 @@ EXPORT_SYMBOL(rt_up_read);
 void  rt_downgrade_write(struct rw_semaphore *rwsem)
 {
        BUG_ON(rt_mutex_owner(&rwsem->lock) != current);
+       rwsem->read_depth = 1;
 }
 EXPORT_SYMBOL(rt_downgrade_write);
 
@@ -361,7 +363,7 @@ void  rt_down_write_nested(struct rw_semaphore *rwsem, int 
subclass)
 EXPORT_SYMBOL(rt_down_write_nested);
 
 void rt_down_write_nested_lock(struct rw_semaphore *rwsem,
-               struct lockdep_map *nest)
+                              struct lockdep_map *nest)
 {
        rwsem_acquire_nest(&rwsem->dep_map, 0, 0, nest, _RET_IP_);
        rt_mutex_lock(&rwsem->lock);
@@ -370,20 +372,36 @@ EXPORT_SYMBOL(rt_down_write_nested_lock);
 
 int  rt_down_read_trylock(struct rw_semaphore *rwsem)
 {
-       int ret;
+       struct rt_mutex *lock = &rwsem->lock;
+       int ret = 1;
 
-       ret = rt_mutex_trylock(&rwsem->lock);
-       if (ret)
-               rwsem_acquire(&rwsem->dep_map, 0, 1, _RET_IP_);
+       /*
+        * recursive read locks succeed when current owns the rwsem,
+        * but not when read_depth == 0 which means that the rwsem is
+        * write locked.
+        */
+       if (rt_mutex_owner(lock) != current)
+               ret = rt_mutex_trylock(&rwsem->lock);
+       else if (!rwsem->read_depth)
+               ret = 0;
 
+       if (ret) {
+               rwsem->read_depth++;
+               rwsem_acquire(&rwsem->dep_map, 0, 1, _RET_IP_);
+       }
        return ret;
 }
 EXPORT_SYMBOL(rt_down_read_trylock);
 
 static void __rt_down_read(struct rw_semaphore *rwsem, int subclass)
 {
-       rwsem_acquire(&rwsem->dep_map, subclass, 0, _RET_IP_);
-       rt_mutex_lock(&rwsem->lock);
+       struct rt_mutex *lock = &rwsem->lock;
+
+       rwsem_acquire_read(&rwsem->dep_map, subclass, 0, _RET_IP_);
+
+       if (rt_mutex_owner(lock) != current)
+               rt_mutex_lock(&rwsem->lock);
+       rwsem->read_depth++;
 }
 
 void  rt_down_read(struct rw_semaphore *rwsem)
@@ -408,6 +426,7 @@ void  __rt_rwsem_init(struct rw_semaphore *rwsem, const 
char *name,
        debug_check_no_locks_freed((void *)rwsem, sizeof(*rwsem));
        lockdep_init_map(&rwsem->dep_map, name, key, 0);
 #endif
+       rwsem->read_depth = 0;
        rwsem->lock.save_state = 0;
 }
 EXPORT_SYMBOL(__rt_rwsem_init);
diff --git a/kernel/locking/rtmutex.c b/kernel/locking/rtmutex.c
index e257819480a9..397373da53d2 100644
--- a/kernel/locking/rtmutex.c
+++ b/kernel/locking/rtmutex.c
@@ -1695,15 +1695,21 @@ rt_mutex_slowlock(struct rt_mutex *lock, int state,
        ret = task_blocks_on_rt_mutex(lock, &waiter, current, chwalk);
 
        if (likely(!ret))
-               ret = __rt_mutex_slowlock(lock, state, timeout, &waiter,
-                                         ww_ctx);
+               ret = __rt_mutex_slowlock(lock, state, timeout, &waiter, 
ww_ctx);
+       else if (ww_ctx) {
+               /* ww_mutex received EDEADLK, let it become EALREADY */
+               ret = __mutex_lock_check_stamp(lock, ww_ctx);
+               BUG_ON(!ret);
+       }
 
        set_current_state(TASK_RUNNING);
 
        if (unlikely(ret)) {
                if (rt_mutex_has_waiters(lock))
                        remove_waiter(lock, &waiter);
-               rt_mutex_handle_deadlock(ret, chwalk, &waiter);
+               /* ww_mutex want to report EDEADLK/EALREADY, let them */
+               if (!ww_ctx)
+                       rt_mutex_handle_deadlock(ret, chwalk, &waiter);
        } else if (ww_ctx) {
                ww_mutex_account_lock(lock, ww_ctx);
        }
@@ -2244,8 +2250,7 @@ __ww_mutex_lock_interruptible(struct ww_mutex *lock, 
struct ww_acquire_ctx *ww_c
        might_sleep();
 
        mutex_acquire_nest(&lock->base.dep_map, 0, 0, &ww_ctx->dep_map, 
_RET_IP_);
-       ret = rt_mutex_slowlock(&lock->base.lock, TASK_INTERRUPTIBLE, NULL,
-                               RT_MUTEX_FULL_CHAINWALK, ww_ctx);
+       ret = rt_mutex_slowlock(&lock->base.lock, TASK_INTERRUPTIBLE, NULL, 0, 
ww_ctx);
        if (ret)
                mutex_release(&lock->base.dep_map, 1, _RET_IP_);
        else if (!ret && ww_ctx->acquired > 1)
@@ -2263,8 +2268,7 @@ __ww_mutex_lock(struct ww_mutex *lock, struct 
ww_acquire_ctx *ww_ctx)
        might_sleep();
 
        mutex_acquire_nest(&lock->base.dep_map, 0, 0, &ww_ctx->dep_map, 
_RET_IP_);
-       ret = rt_mutex_slowlock(&lock->base.lock, TASK_UNINTERRUPTIBLE, NULL,
-                               RT_MUTEX_FULL_CHAINWALK, ww_ctx);
+       ret = rt_mutex_slowlock(&lock->base.lock, TASK_UNINTERRUPTIBLE, NULL, 
0, ww_ctx);
        if (ret)
                mutex_release(&lock->base.dep_map, 1, _RET_IP_);
        else if (!ret && ww_ctx->acquired > 1)
@@ -2276,11 +2280,13 @@ EXPORT_SYMBOL_GPL(__ww_mutex_lock);
 
 void __sched ww_mutex_unlock(struct ww_mutex *lock)
 {
+       int nest = !!lock->ctx;
+
        /*
         * The unlocking fastpath is the 0->1 transition from 'locked'
         * into 'unlocked' state:
         */
-       if (lock->ctx) {
+       if (nest) {
 #ifdef CONFIG_DEBUG_MUTEXES
                DEBUG_LOCKS_WARN_ON(!lock->ctx->acquired);
 #endif
@@ -2289,7 +2295,7 @@ void __sched ww_mutex_unlock(struct ww_mutex *lock)
                lock->ctx = NULL;
        }
 
-       mutex_release(&lock->base.dep_map, 1, _RET_IP_);
+       mutex_release(&lock->base.dep_map, nest, _RET_IP_);
        rt_mutex_unlock(&lock->base.lock);
 }
 EXPORT_SYMBOL(ww_mutex_unlock);
diff --git a/kernel/rcu/tree.c b/kernel/rcu/tree.c
index a4e9e258bfe8..6aae258f9f62 100644
--- a/kernel/rcu/tree.c
+++ b/kernel/rcu/tree.c
@@ -378,6 +378,12 @@ void rcu_bh_force_quiescent_state(void)
        force_quiescent_state(&rcu_bh_state);
 }
 EXPORT_SYMBOL_GPL(rcu_bh_force_quiescent_state);
+
+#else
+void rcu_force_quiescent_state(void)
+{
+}
+EXPORT_SYMBOL_GPL(rcu_force_quiescent_state);
 #endif
 
 /*
diff --git a/kernel/sched/work-simple.c b/kernel/sched/work-simple.c
index 0b2fa5ac88c8..c996f755dba6 100644
--- a/kernel/sched/work-simple.c
+++ b/kernel/sched/work-simple.c
@@ -33,9 +33,9 @@ static bool swork_readable(struct sworker *worker)
        if (kthread_should_stop())
                return true;
 
-       raw_spin_lock(&worker->lock);
+       raw_spin_lock_irq(&worker->lock);
        r = !list_empty(&worker->events);
-       raw_spin_unlock(&worker->lock);
+       raw_spin_unlock_irq(&worker->lock);
 
        return r;
 }
@@ -44,32 +44,28 @@ static int swork_kthread(void *arg)
 {
        struct sworker *worker = arg;
 
-       pr_info("swork_kthread enter\n");
-
        for (;;) {
                swait_event_interruptible(worker->wq,
                                        swork_readable(worker));
                if (kthread_should_stop())
                        break;
 
-               raw_spin_lock(&worker->lock);
+               raw_spin_lock_irq(&worker->lock);
                while (!list_empty(&worker->events)) {
                        struct swork_event *sev;
 
                        sev = list_first_entry(&worker->events,
                                        struct swork_event, item);
                        list_del(&sev->item);
-                       raw_spin_unlock(&worker->lock);
+                       raw_spin_unlock_irq(&worker->lock);
 
                        WARN_ON_ONCE(!test_and_clear_bit(SWORK_EVENT_PENDING,
                                                         &sev->flags));
                        sev->func(sev);
-                       raw_spin_lock(&worker->lock);
+                       raw_spin_lock_irq(&worker->lock);
                }
-               raw_spin_unlock(&worker->lock);
+               raw_spin_unlock_irq(&worker->lock);
        }
-
-       pr_info("swork_kthread exit\n");
        return 0;
 }
 
@@ -111,14 +107,14 @@ static void swork_destroy(struct sworker *worker)
  */
 bool swork_queue(struct swork_event *sev)
 {
+       unsigned long flags;
+
        if (test_and_set_bit(SWORK_EVENT_PENDING, &sev->flags))
                return false;
 
-       WARN_ON(irqs_disabled());
-
-       raw_spin_lock(&glob_worker->lock);
+       raw_spin_lock_irqsave(&glob_worker->lock, flags);
        list_add_tail(&sev->item, &glob_worker->events);
-       raw_spin_unlock(&glob_worker->lock);
+       raw_spin_unlock_irqrestore(&glob_worker->lock, flags);
 
        swait_wake(&glob_worker->wq);
        return true;
diff --git a/lib/locking-selftest.c b/lib/locking-selftest.c
index 19ae2366a7a9..b93a6103fa4d 100644
--- a/lib/locking-selftest.c
+++ b/lib/locking-selftest.c
@@ -590,6 +590,8 @@ GENERATE_TESTCASE(init_held_rsem)
 #include "locking-selftest-spin-hardirq.h"
 GENERATE_PERMUTATIONS_2_EVENTS(irqsafe1_hard_spin)
 
+#ifndef CONFIG_PREEMPT_RT_FULL
+
 #include "locking-selftest-rlock-hardirq.h"
 GENERATE_PERMUTATIONS_2_EVENTS(irqsafe1_hard_rlock)
 
@@ -605,9 +607,12 @@ GENERATE_PERMUTATIONS_2_EVENTS(irqsafe1_soft_rlock)
 #include "locking-selftest-wlock-softirq.h"
 GENERATE_PERMUTATIONS_2_EVENTS(irqsafe1_soft_wlock)
 
+#endif
+
 #undef E1
 #undef E2
 
+#ifndef CONFIG_PREEMPT_RT_FULL
 /*
  * Enabling hardirqs with a softirq-safe lock held:
  */
@@ -640,6 +645,8 @@ GENERATE_PERMUTATIONS_2_EVENTS(irqsafe2A_rlock)
 #undef E1
 #undef E2
 
+#endif
+
 /*
  * Enabling irqs with an irq-safe lock held:
  */
@@ -663,6 +670,8 @@ GENERATE_PERMUTATIONS_2_EVENTS(irqsafe2A_rlock)
 #include "locking-selftest-spin-hardirq.h"
 GENERATE_PERMUTATIONS_2_EVENTS(irqsafe2B_hard_spin)
 
+#ifndef CONFIG_PREEMPT_RT_FULL
+
 #include "locking-selftest-rlock-hardirq.h"
 GENERATE_PERMUTATIONS_2_EVENTS(irqsafe2B_hard_rlock)
 
@@ -678,6 +687,8 @@ GENERATE_PERMUTATIONS_2_EVENTS(irqsafe2B_soft_rlock)
 #include "locking-selftest-wlock-softirq.h"
 GENERATE_PERMUTATIONS_2_EVENTS(irqsafe2B_soft_wlock)
 
+#endif
+
 #undef E1
 #undef E2
 
@@ -709,6 +720,8 @@ GENERATE_PERMUTATIONS_2_EVENTS(irqsafe2B_soft_wlock)
 #include "locking-selftest-spin-hardirq.h"
 GENERATE_PERMUTATIONS_3_EVENTS(irqsafe3_hard_spin)
 
+#ifndef CONFIG_PREEMPT_RT_FULL
+
 #include "locking-selftest-rlock-hardirq.h"
 GENERATE_PERMUTATIONS_3_EVENTS(irqsafe3_hard_rlock)
 
@@ -724,6 +737,8 @@ GENERATE_PERMUTATIONS_3_EVENTS(irqsafe3_soft_rlock)
 #include "locking-selftest-wlock-softirq.h"
 GENERATE_PERMUTATIONS_3_EVENTS(irqsafe3_soft_wlock)
 
+#endif
+
 #undef E1
 #undef E2
 #undef E3
@@ -757,6 +772,8 @@ GENERATE_PERMUTATIONS_3_EVENTS(irqsafe3_soft_wlock)
 #include "locking-selftest-spin-hardirq.h"
 GENERATE_PERMUTATIONS_3_EVENTS(irqsafe4_hard_spin)
 
+#ifndef CONFIG_PREEMPT_RT_FULL
+
 #include "locking-selftest-rlock-hardirq.h"
 GENERATE_PERMUTATIONS_3_EVENTS(irqsafe4_hard_rlock)
 
@@ -772,10 +789,14 @@ GENERATE_PERMUTATIONS_3_EVENTS(irqsafe4_soft_rlock)
 #include "locking-selftest-wlock-softirq.h"
 GENERATE_PERMUTATIONS_3_EVENTS(irqsafe4_soft_wlock)
 
+#endif
+
 #undef E1
 #undef E2
 #undef E3
 
+#ifndef CONFIG_PREEMPT_RT_FULL
+
 /*
  * read-lock / write-lock irq inversion.
  *
@@ -838,6 +859,10 @@ GENERATE_PERMUTATIONS_3_EVENTS(irq_inversion_soft_wlock)
 #undef E2
 #undef E3
 
+#endif
+
+#ifndef CONFIG_PREEMPT_RT_FULL
+
 /*
  * read-lock / write-lock recursion that is actually safe.
  */
@@ -876,6 +901,8 @@ GENERATE_PERMUTATIONS_3_EVENTS(irq_read_recursion_soft)
 #undef E2
 #undef E3
 
+#endif
+
 /*
  * read-lock / write-lock recursion that is unsafe.
  */
diff --git a/localversion-rt b/localversion-rt
index 1445cd65885c..ad3da1bcab7e 100644
--- a/localversion-rt
+++ b/localversion-rt
@@ -1 +1 @@
--rt3
+-rt4
diff --git a/net/sunrpc/svc_xprt.c b/net/sunrpc/svc_xprt.c
index c179ca2a5aa4..ac93e74d5515 100644
--- a/net/sunrpc/svc_xprt.c
+++ b/net/sunrpc/svc_xprt.c
@@ -357,7 +357,7 @@ static void svc_xprt_do_enqueue(struct svc_xprt *xprt)
                return;
        }
 
-       cpu = get_cpu();
+       cpu = get_cpu_light();
        pool = svc_pool_for_cpu(xprt->xpt_server, cpu);
        spin_lock_bh(&pool->sp_lock);
 
@@ -390,7 +390,7 @@ static void svc_xprt_do_enqueue(struct svc_xprt *xprt)
        }
 
        spin_unlock_bh(&pool->sp_lock);
-       put_cpu();
+       put_cpu_light();
 }
 
 /*
diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c
index 166d59cdc86b..8854164197e5 100644
--- a/sound/core/pcm_native.c
+++ b/sound/core/pcm_native.c
@@ -104,7 +104,7 @@ EXPORT_SYMBOL_GPL(snd_pcm_stream_unlock);
 void snd_pcm_stream_lock_irq(struct snd_pcm_substream *substream)
 {
        if (!substream->pcm->nonatomic)
-               local_irq_disable();
+               local_irq_disable_nort();
        snd_pcm_stream_lock(substream);
 }
 EXPORT_SYMBOL_GPL(snd_pcm_stream_lock_irq);
@@ -113,7 +113,7 @@ void snd_pcm_stream_unlock_irq(struct snd_pcm_substream 
*substream)
 {
        snd_pcm_stream_unlock(substream);
        if (!substream->pcm->nonatomic)
-               local_irq_enable();
+               local_irq_enable_nort();
 }
 EXPORT_SYMBOL_GPL(snd_pcm_stream_unlock_irq);
 
@@ -121,7 +121,7 @@ unsigned long _snd_pcm_stream_lock_irqsave(struct 
snd_pcm_substream *substream)
 {
        unsigned long flags = 0;
        if (!substream->pcm->nonatomic)
-               local_irq_save(flags);
+               local_irq_save_nort(flags);
        snd_pcm_stream_lock(substream);
        return flags;
 }
@@ -132,7 +132,7 @@ void snd_pcm_stream_unlock_irqrestore(struct 
snd_pcm_substream *substream,
 {
        snd_pcm_stream_unlock(substream);
        if (!substream->pcm->nonatomic)
-               local_irq_restore(flags);
+               local_irq_restore_nort(flags);
 }
 EXPORT_SYMBOL_GPL(snd_pcm_stream_unlock_irqrestore);
 
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Reply via email to