3.8.13-rt11
Subsystems (5)
Dear RT Folks,
I'm pleased to announce the 3.8.13-rt11 release.
changes since v3.8.13-rt10:
- use wakeup_timer_waiters() in wake_up() so we do nothing on nort kernel. Sent by Zhao Hongjiang
- a fix for a cpu down problem. If kthread is pinned to the same CPU which is going down we will spin for ever and wait until kthread leaves the CPU. This does not trigger on v3.6-rt because the workqueue code there does not create a new process in the notfier callback. Reported by Qiang Huang.
- a check if we lose PF_THREAD_BOUND in the workqueue code. Shouldn't happen yet it seems it happens from time to time.
- save the cpu mask of the application which disables a CPU. Prior this change the application which put a CPU down was allowed to run on any CPU if it was restricted to a specifc one. Reported by Zhao Chenhui.
- the SLxB PowerPC, e500 problem is removed from the list without a change. The problem triggers even on a v3.6 non-RT kernel after 1-2 days of runtime on my MPC8572DS. I don't see any problem so far on MPC8536 which is mostly the same HW except it is UP but MPC8572DS crashes also in UP mode so I belive it is a HW problem.
Known issues:
- Steven reported a missing acpi from the v3.6 release.
- a "fix" for i915 leads to high latencies due to wbinvd(). Not sure what is the best thing to do here.
The delta patch against v3.8.13-rt10 is appended below and can be found here:
https://www.kernel.org/pub/linux/kernel/projects/rt/3.8/incr/patch-3.8.13-rt10-rt11.patch.xz
The RT patch against 3.8.11 can be found here:
https://www.kernel.org/pub/linux/kernel/projects/rt/3.8/patch-3.8.13-rt11.patch.xz
The split quilt queue is available at:
https://www.kernel.org/pub/linux/kernel/projects/rt/3.8/patches-3.8.13-rt11.tar.xz
Sebastian
kernel/cpu.c +26 -3
@@ -83,6 +83,7 @@ struct hotplug_pcp {int refcount;int grab_lock;struct completion synced; +struct completion unplug_wait;#ifdef CONFIG_PREEMPT_RT_FULL spinlock_t lock;#else
@@ -180,6 +181,7 @@ static int sync_unplug_thread(void *data) {struct hotplug_pcp *hp = data; +wait_for_completion (&hp->unplug_wait);preempt_disable (); hp->unplug = current;wait_for_pinned_cpus (hp);
@@ -245,6 +247,14 @@ static void __cpu_unplug_sync(struct hotplug_pcp *hp)wait_for_completion (&hp->synced); } +static void __cpu_unplug_wait (unsigned int cpu) +{ +struct hotplug_pcp *hp = &per_cpu (hotplug_pcp, cpu); + +complete (&hp->unplug_wait); +wait_for_completion (&hp->synced); +} +/* * Start the sync_unplug_thread on the target cpu and wait for it to * complete.
@@ -268,6 +278,7 @@ static int cpu_unplug_begin(unsigned int cpu)tell_sched_cpu_down_begin (cpu);init_completion (&hp->synced); +init_completion (&hp->unplug_wait); hp->sync_tsk =kthread_create (sync_unplug_thread, hp,"sync_unplug/%d" , cpu);if (IS_ERR (hp->sync_tsk)) {
@@ -283,8 +294,7 @@ static int cpu_unplug_begin(unsigned int cpu)* wait for tasks that are going to enter these sections and * we must not have them block. */ -__cpu_unplug_sync (hp); - +wake_up_process (hp->sync_tsk);return 0 ; }
@@ -535,6 +545,7 @@ static int __ref _cpu_down(unsigned int cpu, int tasks_frozen) .hcpu = hcpu, };cpumask_var_t cpumask; +cpumask_var_t cpumask_org;if (num_online_cpus () ==1 )return -EBUSY ;
@@ -545,6 +556,12 @@ static int __ref _cpu_down(unsigned int cpu, int tasks_frozen)/* Move the downtaker off the unplug cpu */ if (!alloc_cpumask_var (&cpumask,GFP_KERNEL ))return -ENOMEM ; +if (!alloc_cpumask_var (&cpumask_org,GFP_KERNEL )) { +free_cpumask_var (cpumask); +return -ENOMEM ; + } + +cpumask_copy (cpumask_org,tsk_cpus_allowed (current));cpumask_andnot (cpumask, cpu_online_mask,cpumask_of (cpu));set_cpus_allowed_ptr (current, cpumask);free_cpumask_var (cpumask);
@@ -553,7 +570,8 @@ static int __ref _cpu_down(unsigned int cpu, int tasks_frozen)if (mycpu == cpu) {printk (KERN_ERR "Yuck! Still on unplug CPU\n!" );migrate_enable (); -return -EBUSY ; + err = -EBUSY ; + goto restore_cpus; }cpu_hotplug_begin ();
@@ -571,6 +589,8 @@ static int __ref _cpu_down(unsigned int cpu, int tasks_frozen) __func__, cpu); goto out_release; } + +__cpu_unplug_wait (cpu);smpboot_park_threads (cpu);/* Notifiers are done. Don't let any more tasks pin this CPU. */
@@ -610,6 +630,9 @@ static int __ref _cpu_down(unsigned int cpu, int tasks_frozen)cpu_hotplug_done ();if (!err)cpu_notify_nofail (CPU_POST_DEAD | mod, hcpu); +restore_cpus: +set_cpus_allowed_ptr (current, cpumask_org); +free_cpumask_var (cpumask_org);return err; }
kernel/irq/manage.c +6 -5
@@ -849,9 +849,6 @@ static void irq_thread_dtor(struct callback_head *unused)static int irq_thread (void *data) {struct callback_head on_exit_work; -static const struct sched_param param = { - .sched_priority =MAX_USER_RT_PRIO /2 , - };struct irqaction *action = data;struct irq_desc *desc =irq_to_desc (action->irq); irqreturn_t (*handler_fn)(struct irq_desc *desc,
@@ -863,8 +860,6 @@ static int irq_thread(void *data)else handler_fn = irq_thread_fn; -sched_setscheduler (current,SCHED_FIFO , ¶m); -init_task_work (&on_exit_work, irq_thread_dtor);task_work_add (current, &on_exit_work, false);
@@ -965,6 +960,9 @@ __setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new)*/ if (new->thread_fn && !nested) {struct task_struct *t; +static const struct sched_param param = { + .sched_priority =MAX_USER_RT_PRIO /2 , + }; t =kthread_create (irq_thread, new,"irq/%d-%s" , irq, new->name);
@@ -972,6 +970,9 @@ __setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new) ret =PTR_ERR (t); goto out_mput; } + +sched_setscheduler (t,SCHED_FIFO , ¶m); +/* * We keep the reference to the task struct even if * the thread dies to avoid that the interrupt code
kernel/timer.c +6 -2
@@ -76,7 +76,9 @@ struct tvec_root {struct tvec_base {spinlock_t lock;struct timer_list *running_timer; +#ifdef CONFIG_PREEMPT_RT_FULL wait_queue_head_t wait_for_running_timer; +#endif unsigned long timer_jiffies;unsigned long next_timer;unsigned long active_timers;
@@ -982,7 +984,7 @@ static void wait_for_running_timer(struct timer_list *timer) base->running_timer != timer); } -# define wakeup_timer_waiters (b) wake_up(&(b)->wait_for_tunning_timer) +# define wakeup_timer_waiters (b) wake_up(&(b)->wait_for_running_timer)#else static inline void wait_for_running_timer (struct timer_list *timer) {
@@ -1236,7 +1238,7 @@ static inline void __run_timers(struct tvec_base *base) } } } -wake_up (&base->wait_for_running_timer); +wakeup_timer_waiters (base);spin_unlock_irq (&base->lock); }
@@ -1755,7 +1757,9 @@ static int __cpuinit init_timers_cpu(int cpu) }spin_lock_init (&base->lock); +#ifdef CONFIG_PREEMPT_RT_FULL init_waitqueue_head (&base->wait_for_running_timer); +#endif for (j =0 ; j <TVN_SIZE ; j++) {INIT_LIST_HEAD (base->tv5.vec + j);
kernel/workqueue.c +4 -1
@@ -1637,8 +1637,11 @@ __acquires(&gcwq->lock)* it races with cpu hotunplug operation. Verify * against GCWQ_DISASSOCIATED. */ -if (!(gcwq->flags &GCWQ_DISASSOCIATED )) +if (!(gcwq->flags &GCWQ_DISASSOCIATED )) {set_cpus_allowed_ptr (task,get_cpu_mask (gcwq->cpu)); +if (WARN_ON (!(task->flags &PF_THREAD_BOUND ))) + task->flags |=PF_THREAD_BOUND ; + }spin_lock_irq (&gcwq->lock);if (gcwq->flags &GCWQ_DISASSOCIATED )
localversion-rt +1 -1
@@ -1 +1 @@ --rt10 +-rt11
A message that is not in the archive (sent off-list or not yet received): [email protected]
PATCH 1/1 gpu: i915: allow the user not to do the wbinvd ("Was: Re: [ANNOUNCE] 3.8.13-rt11)
Quoted 1 line · * Carsten Emde | 2013-06-14 22:17:01 [+0200]:
Hi Sebastian,
Hi Carsten,
Quoted 8 lines
Quoted 2 lines
- a "fix" for i915 leads to high latencies due to
wbinvd(). Not sure what is the best thing to do here.Even if we do not yet know what is the best final solution to this problem, there is no doubt that, for the time being, the patch in question has to be reverted - the earlier the better. Please understand that this RT kernel release it totally unusable on a system that is equipped with one of several widely used Intel graphics boards. It simply is a waste of time.
Yes but reverting causes problems for others. Anyway, in order to make progress here and not break anything I include the patch below. So everyone who does not want the expensive sync can specify i915.do_wbinvd=no after they ensured that the same CPU is used for GPU related operations.
Subject: [PATCH] gpu: i915: allow the user not to do the wbinvd
The wbinvd() renders the system with i915 unusable on RT. Using this expensive instruction avoids GPU trouble according to
https://bugs.freedesktop.org/show_bug.cgi?id=62191
As a workaround for RT it is recommended to pin each GPU related process to the same CPU and then disable this instruction via the module paramter.
--- drivers/gpu/drm/i915/i915_gem.c | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-)
drivers/gpu/drm/i915/i915_gem.c +15 -2
@@ -35,6 +35,7 @@#include <linux/swap.h> #include <linux/pci.h> #include <linux/dma-buf.h> +#include <linux/module.h> static void i915_gem_object_flush_gtt_write_domain (struct drm_i915_gem_object *obj);static void i915_gem_object_flush_cpu_write_domain (struct drm_i915_gem_object *obj);
@@ -2656,6 +2657,10 @@ static inline int fence_number(struct drm_i915_private *dev_priv,return fence - dev_priv->fence_regs; } +static bool do_wbinvd = true; +module_param (do_wbinvd, bool,0644 ); +MODULE_PARM_DESC (do_wbinvd,"Do expensive synchronization. Say no after you pin each GPU process to the same CPU in order to lower the latency." ); +static void i915_gem_write_fence__ipi (void *data) {wbinvd ();
@@ -2679,8 +2684,16 @@ static void i915_gem_object_update_fence(struct drm_i915_gem_object *obj,* on each processor in order to manually flush all memory * transactions before updating the fence register. */ -if (HAS_LLC (obj->base.dev)) -on_each_cpu (i915_gem_write_fence__ipi,NULL ,1 ); +if (HAS_LLC (obj->base.dev)) { +if (do_wbinvd) { +#ifdef CONFIG_PREEMPT_RT_FULL +pr_err_once ("WARNING! The i915 invalidates all caches which increases the latency." ); +pr_err_once ("As a workaround use 'i915.do_wbinvd=no' and PIN each process doing " ); +pr_err_once ("any kind of GPU activity to the same CPU to avoid problems." ); +#endif +on_each_cpu (i915_gem_write_fence__ipi,NULL ,1 ); + } + }i915_gem_write_fence (dev, fence_reg, enable ? obj :NULL );if (enable) {
Signature · 1 line
1.8.3.1
Quoted 2 lines
-Carsten.
Sebastian