summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--patches/0001-genirq-Provide-generic_handle_irq_safe.patch59
-rw-r--r--patches/0001-kernel-fork-Redo-ifdefs-around-task-s-handling.patch162
-rw-r--r--patches/0001-mm-memcg-Revert-mm-memcg-optimize-user-context-objec.patch247
-rw-r--r--patches/0001-net-dev-Remove-preempt_disable-and-get_cpu-in-netif_.patch64
-rw-r--r--patches/0001-printk-add-infrastucture-for-atomic-consoles.patch (renamed from patches/0014-printk-add-infrastucture-for-atomic-consoles.patch)219
-rw-r--r--patches/0001-printk-rename-cpulock-functions.patch33
-rw-r--r--patches/0001-random-use-computational-hash-for-entropy-extraction.patch498
-rw-r--r--patches/0001-sched-Fix-missing-prototype-warnings.patch141
-rw-r--r--patches/0002-i2c-core-Use-generic_handle_irq_safe-in-i2c_handle_s.patch39
-rw-r--r--patches/0002-kernel-fork-Duplicate-task_struct-before-stack-alloc.patch51
-rw-r--r--patches/0002-mm-memcg-Disable-threshold-event-handlers-on-PREEMPT.patch91
-rw-r--r--patches/0002-net-dev-Make-rps_lock-disable-interrupts.patch203
-rw-r--r--patches/0002-printk-cpu-sync-always-disable-interrupts.patch9
-rw-r--r--patches/0002-random-remove-batched-entropy-locking.patch150
-rw-r--r--patches/0002-serial-8250-implement-write_atomic.patch927
-rw-r--r--patches/0002-smp-Rename-flush_smp_call_function_from_idle.patch125
-rw-r--r--patches/0003-drm-i915-Use-preempt_disable-enable_rt-where-recomme.patch4
-rw-r--r--patches/0003-i2c-cht-wc-Use-generic_handle_irq_safe.patch36
-rw-r--r--patches/0003-kernel-fork-IA64-Provide-a-alloc_thread_stack_node-f.patch69
-rw-r--r--patches/0003-mm-memcg-Protect-per-CPU-counter-by-disabling-preemp.patch121
-rw-r--r--patches/0003-net-dev-Makes-sure-netif_rx-can-be-invoked-in-any-co.patch412
-rw-r--r--patches/0003-printk-add-missing-memory-barrier-to-wake_up_klogd.patch88
-rw-r--r--patches/0003-printk-avoid-preempt_disable-for-PREEMPT_RT.patch (renamed from patches/0016-printk-avoid-preempt_disable-for-PREEMPT_RT.patch)59
-rw-r--r--patches/0003-printk-use-percpu-flag-instead-of-cpu_online.patch50
-rw-r--r--patches/0003-random-fix-locking-in-crng_fast_load.patch37
-rw-r--r--patches/0003-smp-Make-softirq-handling-RT-safe-in-flush_smp_call_.patch106
-rw-r--r--patches/0004-drm-i915-Don-t-disable-interrupts-on-PREEMPT_RT-duri.patch8
-rw-r--r--patches/0004-kernel-fork-Don-t-assign-the-stack-pointer-in-dup_ta.patch150
-rw-r--r--patches/0004-misc-hi6421-spmi-pmic-Use-generic_handle_irq_safe.patch42
-rw-r--r--patches/0004-mm-memcg-Opencode-the-inner-part-of-obj_cgroup_uncha.patch75
-rw-r--r--patches/0004-printk-wake-up-all-waiters.patch26
-rw-r--r--patches/0004-random-defer-fast-pool-mixing-to-worker.patch177
-rw-r--r--patches/0005-drm-i915-Don-t-check-for-atomic-context-on-PREEMPT_R.patch2
-rw-r--r--patches/0005-kernel-fork-Move-memcg_charge_kernel_stack-into-CONF.patch123
-rw-r--r--patches/0005-mfd-ezx-pcap-Use-generic_handle_irq_safe.patch31
-rw-r--r--patches/0005-mm-memcg-Protect-memcg_stock-with-a-local_lock_t.patch233
-rw-r--r--patches/0005-printk-wake-waiters-for-safe-and-NMI-contexts.patch85
-rw-r--r--patches/0005-random-clear-fast-pool-crng-and-batches-in-cpuhp-bri.patch247
-rw-r--r--patches/0006-kernel-fork-Move-task-stack-account-to-do_exit.patch164
-rw-r--r--patches/0006-mm-memcg-Disable-migration-instead-of-preemption-in-.patch50
-rw-r--r--patches/0006-net-usb-lan78xx-Use-generic_handle_irq_safe.patch30
-rw-r--r--patches/0006-printk-get-caller_id-timestamp-after-migration-disab.patch (renamed from patches/0004-printk-get-caller_id-timestamp-after-migration-disab.patch)15
-rw-r--r--patches/0007-kernel-fork-Only-cache-the-VMAP-stack-in-finish_task.patch146
-rw-r--r--patches/0007-mm-memcg-Add-missing-counter-index-which-are-not-upd.patch38
-rw-r--r--patches/0007-printk-call-boot_delay_msec-in-printk_delay.patch (renamed from patches/0005-printk-call-boot_delay_msec-in-printk_delay.patch)11
-rw-r--r--patches/0007-staging-greybus-gpio-Use-generic_handle_irq_safe.patch30
-rw-r--r--patches/0008-kernel-fork-Use-IS_ENABLED-in-account_kernel_stack.patch40
-rw-r--r--patches/0008-mm-memcg-Add-a-comment-regarding-the-release-obj.patch25
-rw-r--r--patches/0008-printk-add-con_printk-macro-for-console-details.patch54
-rw-r--r--patches/0009-drm-i915-gt-Use-spin_lock_irq-instead-of-local_irq_d.patch12
-rw-r--r--patches/0009-printk-refactor-and-rework-printing-logic.patch (renamed from patches/0006-printk-refactor-and-rework-printing-logic.patch)253
-rw-r--r--patches/0010-drm-i915-Drop-the-irqs_disabled-check.patch4
-rw-r--r--patches/0010-printk-add-kthread-console-printers.patch285
-rw-r--r--patches/0010-printk-move-buffer-definitions-into-console_emit_nex.patch (renamed from patches/0007-printk-move-buffer-definitions-into-console_emit_nex.patch)41
-rw-r--r--patches/0011-printk-add-pr_flush.patch (renamed from patches/0008-printk-add-pr_flush.patch)110
-rw-r--r--patches/0011-printk-reimplement-console_lock-for-proper-kthread-s.patch480
-rw-r--r--patches/0012-printk-add-functions-to-prefer-direct-printing.patch (renamed from patches/0009-printk-add-functions-to-allow-direct-printing.patch)242
-rw-r--r--patches/0013-console-introduce-CON_MIGHT_SLEEP-for-vt.patch54
-rw-r--r--patches/0013-printk-add-kthread-console-printers.patch529
-rw-r--r--patches/0014-printk-extend-console_lock-for-proper-kthread-suppor.patch695
-rw-r--r--patches/0015-printk-remove-console_locked.patch (renamed from patches/0012-printk-remove-console_locked.patch)67
-rw-r--r--patches/0015-serial-8250-implement-write_atomic.patch492
-rw-r--r--patches/ARM64__Allow_to_enable_RT.patch2
-rw-r--r--patches/ARM__Allow_to_enable_RT.patch6
-rw-r--r--patches/Add_localversion_for_-RT_release.patch2
-rw-r--r--patches/KVM__arm_arm64__downgrade_preempt_disabled_region_to_migrate_disable.patch10
-rw-r--r--patches/POWERPC__Allow_to_enable_RT.patch4
-rw-r--r--patches/arch_arm64__Add_lazy_preempt_support.patch8
-rw-r--r--patches/arm64-signal-Use-ARCH_RT_DELAYS_SIGNAL_SEND.patch4
-rw-r--r--patches/arm64-sve-Delay-freeing-memory-in-fpsimd_flush_threa.patch4
-rw-r--r--patches/arm__Add_support_for_lazy_preemption.patch26
-rw-r--r--patches/block_mq__do_not_invoke_preempt_disable.patch2
-rw-r--r--patches/cgroup__use_irqsave_in_cgroup_rstat_flush_locked.patch49
-rw-r--r--patches/drivers_block_zram__Replace_bit_spinlocks_with_rtmutex_for_-rt.patch6
-rw-r--r--patches/drm-i915-Depend-on-PREEMPT_RT.patch28
-rw-r--r--patches/fs-namespace-Boost-the-mount_lock.lock-owner-instead.patch57
-rw-r--r--patches/fs_dcache__disable_preemption_on_i_dir_seqs_write_side.patch4
-rw-r--r--patches/fs_dcache__use_swait_queue_instead_of_waitqueue.patch16
-rw-r--r--patches/irq_poll-Use-raise_softirq_irqoff-in-cpu_dead-notifi.patch35
-rw-r--r--patches/jump-label__disable_if_stop_machine_is_used.patch2
-rw-r--r--patches/lib-irq_poll-Prevent-softirq-pending-leak-in-irq_pol.patch49
-rw-r--r--patches/locking-Enable-RT_MUTEXES-by-default-on-PREEMPT_RT.patch27
-rw-r--r--patches/locking-local_lock-Make-the-empty-local_lock_-functi.patch41
-rw-r--r--patches/mm-memcg-Only-perform-the-debug-checks-on-PREEMPT_RT.patch28
-rw-r--r--patches/mm__workingset__replace_IRQ-off_check_with_a_lockdep_assert..patch45
-rw-r--r--patches/mm_vmalloc__Another_preempt_disable_region_which_sucks.patch6
-rw-r--r--patches/net-Correct-wrong-BH-disable-in-hard-interrupt.patch62
-rw-r--r--patches/net-Use-this_cpu_inc-to-increment-net-core_stats.patch132
-rw-r--r--patches/powerpc__Add_support_for_lazy_preemption.patch6
-rw-r--r--patches/powerpc_kvm__Disable_in-kernel_MPIC_emulation_for_PREEMPT_RT.patch2
-rw-r--r--patches/printk-defer_console_output-use-atomic-update.patch50
-rw-r--r--patches/ptrace-fix-ptrace-vs-tasklist_lock-race-on-PREEMPT_R.patch10
-rw-r--r--patches/random-Move-crng_fast_load-to-the-worker.patch72
-rw-r--r--patches/sched__Add_support_for_lazy_preemption.patch63
-rw-r--r--patches/scsi_fcoe__Make_RT_aware..patch8
-rw-r--r--patches/series99
-rw-r--r--patches/signal__Revert_ptrace_preempt_magic.patch2
-rw-r--r--patches/signal_x86__Delay_calling_signals_in_atomic.patch20
-rw-r--r--patches/smp_wake_ksoftirqd_on_preempt_rt_instead_do_softirq.patch67
-rw-r--r--patches/softirq-Disable-softirq-stacks-on-PREEMPT_RT.patch28
-rw-r--r--patches/softirq-Use-a-dedicated-thread-for-timer-wakeups.patch10
-rw-r--r--patches/softirq__Check_preemption_after_reenabling_interrupts.patch10
-rw-r--r--patches/sunrpc__Make_svc_xprt_do_enqueue_use_get_cpu_light.patch6
-rw-r--r--patches/sysfs__Add__sys_kernel_realtime_entry.patch4
-rw-r--r--patches/tcp-Don-t-acquire-inet_listen_hashbucket-lock-with-d.patch160
-rw-r--r--patches/tty_serial_omap__Make_the_locking_RT_aware.patch4
-rw-r--r--patches/virt-acrn-Remove-unsued-acrn_irqfds_mutex.patch25
-rw-r--r--patches/x86-kvm-Require-const-tsc-for-RT.patch32
-rw-r--r--patches/x86__Enable_RT_also_on_32bit.patch2
-rw-r--r--patches/x86__Support_for_lazy_preemption.patch4
-rw-r--r--patches/x86_entry__Use_should_resched_in_idtentry_exit_cond_resched.patch2
111 files changed, 3730 insertions, 6677 deletions
diff --git a/patches/0001-genirq-Provide-generic_handle_irq_safe.patch b/patches/0001-genirq-Provide-generic_handle_irq_safe.patch
deleted file mode 100644
index 305398f17f68..000000000000
--- a/patches/0001-genirq-Provide-generic_handle_irq_safe.patch
+++ /dev/null
@@ -1,59 +0,0 @@
-From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
-Date: Fri, 11 Feb 2022 19:14:54 +0100
-Subject: [PATCH 1/7] genirq: Provide generic_handle_irq_safe().
-
-Provide generic_handle_irq_safe() which can used from any context.
-
-Suggested-by: Thomas Gleixner <tglx@linutronix.de>
-Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
-Reviewed-by: Hans de Goede <hdegoede@redhat.com>
-Reviewed-by: Oleksandr Natalenko <oleksandr@natalenko.name>
-Reviewed-by: Wolfram Sang <wsa+renesas@sang-engineering.com>
-Link: https://lore.kernel.org/r/20220211181500.1856198-2-bigeasy@linutronix.de
----
- include/linux/irqdesc.h | 1 +
- kernel/irq/irqdesc.c | 23 +++++++++++++++++++++++
- 2 files changed, 24 insertions(+)
-
---- a/include/linux/irqdesc.h
-+++ b/include/linux/irqdesc.h
-@@ -160,6 +160,7 @@ static inline void generic_handle_irq_de
-
- int handle_irq_desc(struct irq_desc *desc);
- int generic_handle_irq(unsigned int irq);
-+int generic_handle_irq_safe(unsigned int irq);
-
- #ifdef CONFIG_IRQ_DOMAIN
- /*
---- a/kernel/irq/irqdesc.c
-+++ b/kernel/irq/irqdesc.c
-@@ -662,6 +662,29 @@ int generic_handle_irq(unsigned int irq)
- }
- EXPORT_SYMBOL_GPL(generic_handle_irq);
-
-+/**
-+ * generic_handle_irq_safe - Invoke the handler for a particular irq from any
-+ * context.
-+ * @irq: The irq number to handle
-+ *
-+ * Returns: 0 on success, a negative value on error.
-+ *
-+ * This function can be called from any context (IRQ or process context). It
-+ * will report an error if not invoked from IRQ context and the irq has been
-+ * marked to enforce IRQ-context only.
-+ */
-+int generic_handle_irq_safe(unsigned int irq)
-+{
-+ unsigned long flags;
-+ int ret;
-+
-+ local_irq_save(flags);
-+ ret = handle_irq_desc(irq_to_desc(irq));
-+ local_irq_restore(flags);
-+ return ret;
-+}
-+EXPORT_SYMBOL_GPL(generic_handle_irq_safe);
-+
- #ifdef CONFIG_IRQ_DOMAIN
- /**
- * generic_handle_domain_irq - Invoke the handler for a HW irq belonging
diff --git a/patches/0001-kernel-fork-Redo-ifdefs-around-task-s-handling.patch b/patches/0001-kernel-fork-Redo-ifdefs-around-task-s-handling.patch
deleted file mode 100644
index 4acb42fefc9a..000000000000
--- a/patches/0001-kernel-fork-Redo-ifdefs-around-task-s-handling.patch
+++ /dev/null
@@ -1,162 +0,0 @@
-From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
-Date: Thu, 17 Feb 2022 11:23:59 +0100
-Subject: [PATCH 1/8] kernel/fork: Redo ifdefs around task's handling.
-
-The use of ifdef CONFIG_VMAP_STACK is confusing in terms what is
-actually happenning and what can happen.
-For instance from reading free_thread_stack() it appears that in the
-CONFIG_VMAP_STACK case we may receive a non-NULL vm pointer but it may
-also be NULL in which case __free_pages() is used to free the stack.
-This is however not the case because in the VMAP case a non-NULL pointer
-is always returned here.
-Since it looks like this might happen, the compiler creates the correct
-dead code with the invocation to __free_pages() and everything around
-it. Twice.
-
-Add spaces between the ifdef and the identifer to recognize the ifdef
-level that we are currently in.
-Add the current identifer as a comment behind #else and #endif.
-Move the code within free_thread_stack() and alloc_thread_stack_node()
-into the relavant ifdef block.
-
-Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
-Acked-by: Andy Lutomirski <luto@kernel.org>
-Link: https://lore.kernel.org/r/20220217102406.3697941-2-bigeasy@linutronix.de
----
- kernel/fork.c | 74 ++++++++++++++++++++++++++++++----------------------------
- 1 file changed, 39 insertions(+), 35 deletions(-)
-
---- a/kernel/fork.c
-+++ b/kernel/fork.c
-@@ -185,7 +185,7 @@ static inline void free_task_struct(stru
- */
- # if THREAD_SIZE >= PAGE_SIZE || defined(CONFIG_VMAP_STACK)
-
--#ifdef CONFIG_VMAP_STACK
-+# ifdef CONFIG_VMAP_STACK
- /*
- * vmalloc() is a bit slow, and calling vfree() enough times will force a TLB
- * flush. Try to minimize the number of calls by caching stacks.
-@@ -210,11 +210,9 @@ static int free_vm_stack_cache(unsigned
-
- return 0;
- }
--#endif
-
- static unsigned long *alloc_thread_stack_node(struct task_struct *tsk, int node)
- {
--#ifdef CONFIG_VMAP_STACK
- void *stack;
- int i;
-
-@@ -258,45 +256,53 @@ static unsigned long *alloc_thread_stack
- tsk->stack = stack;
- }
- return stack;
--#else
-- struct page *page = alloc_pages_node(node, THREADINFO_GFP,
-- THREAD_SIZE_ORDER);
--
-- if (likely(page)) {
-- tsk->stack = kasan_reset_tag(page_address(page));
-- return tsk->stack;
-- }
-- return NULL;
--#endif
- }
-
--static inline void free_thread_stack(struct task_struct *tsk)
-+static void free_thread_stack(struct task_struct *tsk)
- {
--#ifdef CONFIG_VMAP_STACK
- struct vm_struct *vm = task_stack_vm_area(tsk);
-+ int i;
-
-- if (vm) {
-- int i;
-+ for (i = 0; i < THREAD_SIZE / PAGE_SIZE; i++)
-+ memcg_kmem_uncharge_page(vm->pages[i], 0);
-
-- for (i = 0; i < THREAD_SIZE / PAGE_SIZE; i++)
-- memcg_kmem_uncharge_page(vm->pages[i], 0);
-+ for (i = 0; i < NR_CACHED_STACKS; i++) {
-+ if (this_cpu_cmpxchg(cached_stacks[i], NULL,
-+ tsk->stack_vm_area) != NULL)
-+ continue;
-+
-+ tsk->stack = NULL;
-+ tsk->stack_vm_area = NULL;
-+ return;
-+ }
-+ vfree_atomic(tsk->stack);
-+ tsk->stack = NULL;
-+ tsk->stack_vm_area = NULL;
-+}
-
-- for (i = 0; i < NR_CACHED_STACKS; i++) {
-- if (this_cpu_cmpxchg(cached_stacks[i],
-- NULL, tsk->stack_vm_area) != NULL)
-- continue;
-+# else /* !CONFIG_VMAP_STACK */
-
-- return;
-- }
-+static unsigned long *alloc_thread_stack_node(struct task_struct *tsk, int node)
-+{
-+ struct page *page = alloc_pages_node(node, THREADINFO_GFP,
-+ THREAD_SIZE_ORDER);
-
-- vfree_atomic(tsk->stack);
-- return;
-+ if (likely(page)) {
-+ tsk->stack = kasan_reset_tag(page_address(page));
-+ return tsk->stack;
- }
--#endif
-+ return NULL;
-+}
-
-+static void free_thread_stack(struct task_struct *tsk)
-+{
- __free_pages(virt_to_page(tsk->stack), THREAD_SIZE_ORDER);
-+ tsk->stack = NULL;
- }
--# else
-+
-+# endif /* CONFIG_VMAP_STACK */
-+# else /* !(THREAD_SIZE >= PAGE_SIZE || defined(CONFIG_VMAP_STACK)) */
-+
- static struct kmem_cache *thread_stack_cache;
-
- static unsigned long *alloc_thread_stack_node(struct task_struct *tsk,
-@@ -312,6 +318,7 @@ static unsigned long *alloc_thread_stack
- static void free_thread_stack(struct task_struct *tsk)
- {
- kmem_cache_free(thread_stack_cache, tsk->stack);
-+ tsk->stack = NULL;
- }
-
- void thread_stack_cache_init(void)
-@@ -321,8 +328,9 @@ void thread_stack_cache_init(void)
- THREAD_SIZE, NULL);
- BUG_ON(thread_stack_cache == NULL);
- }
--# endif
--#endif
-+
-+# endif /* THREAD_SIZE >= PAGE_SIZE || defined(CONFIG_VMAP_STACK) */
-+#endif /* !CONFIG_ARCH_THREAD_STACK_ALLOCATOR */
-
- /* SLAB cache for signal_struct structures (tsk->signal) */
- static struct kmem_cache *signal_cachep;
-@@ -432,10 +440,6 @@ static void release_task_stack(struct ta
-
- account_kernel_stack(tsk, -1);
- free_thread_stack(tsk);
-- tsk->stack = NULL;
--#ifdef CONFIG_VMAP_STACK
-- tsk->stack_vm_area = NULL;
--#endif
- }
-
- #ifdef CONFIG_THREAD_INFO_IN_TASK
diff --git a/patches/0001-mm-memcg-Revert-mm-memcg-optimize-user-context-objec.patch b/patches/0001-mm-memcg-Revert-mm-memcg-optimize-user-context-objec.patch
deleted file mode 100644
index f95f8a5c4f68..000000000000
--- a/patches/0001-mm-memcg-Revert-mm-memcg-optimize-user-context-objec.patch
+++ /dev/null
@@ -1,247 +0,0 @@
-From: Michal Hocko <mhocko@suse.com>
-Date: Thu, 17 Feb 2022 10:47:58 +0100
-Subject: [PATCH 1/8] mm/memcg: Revert ("mm/memcg: optimize user context object
- stock access")
-
-The optimisation is based on a micro benchmark where local_irq_save() is
-more expensive than a preempt_disable(). There is no evidence that it is
-visible in a real-world workload and there are CPUs where the opposite is
-true (local_irq_save() is cheaper than preempt_disable()).
-
-Based on micro benchmarks, the optimisation makes sense on PREEMPT_NONE
-where preempt_disable() is optimized away. There is no improvement with
-PREEMPT_DYNAMIC since the preemption counter is always available.
-
-The optimization makes also the PREEMPT_RT integration more complicated
-since most of the assumption are not true on PREEMPT_RT.
-
-Revert the optimisation since it complicates the PREEMPT_RT integration
-and the improvement is hardly visible.
-
-[ bigeasy: Patch body around Michal's diff ]
-
-Link: https://lore.kernel.org/all/YgOGkXXCrD%2F1k+p4@dhcp22.suse.cz
-Link: https://lkml.kernel.org/r/YdX+INO9gQje6d0S@linutronix.de
-Signed-off-by: Michal Hocko <mhocko@suse.com>
-Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
-Acked-by: Roman Gushchin <guro@fb.com>
-Acked-by: Johannes Weiner <hannes@cmpxchg.org>
-Reviewed-by: Shakeel Butt <shakeelb@google.com>
-Acked-by: Michal Hocko <mhocko@suse.com>
----
- mm/memcontrol.c | 94 ++++++++++++++++----------------------------------------
- 1 file changed, 27 insertions(+), 67 deletions(-)
-
---- a/mm/memcontrol.c
-+++ b/mm/memcontrol.c
-@@ -2085,23 +2085,17 @@ void unlock_page_memcg(struct page *page
- folio_memcg_unlock(page_folio(page));
- }
-
--struct obj_stock {
-+struct memcg_stock_pcp {
-+ struct mem_cgroup *cached; /* this never be root cgroup */
-+ unsigned int nr_pages;
-+
- #ifdef CONFIG_MEMCG_KMEM
- struct obj_cgroup *cached_objcg;
- struct pglist_data *cached_pgdat;
- unsigned int nr_bytes;
- int nr_slab_reclaimable_b;
- int nr_slab_unreclaimable_b;
--#else
-- int dummy[0];
- #endif
--};
--
--struct memcg_stock_pcp {
-- struct mem_cgroup *cached; /* this never be root cgroup */
-- unsigned int nr_pages;
-- struct obj_stock task_obj;
-- struct obj_stock irq_obj;
-
- struct work_struct work;
- unsigned long flags;
-@@ -2111,12 +2105,12 @@ static DEFINE_PER_CPU(struct memcg_stock
- static DEFINE_MUTEX(percpu_charge_mutex);
-
- #ifdef CONFIG_MEMCG_KMEM
--static void drain_obj_stock(struct obj_stock *stock);
-+static void drain_obj_stock(struct memcg_stock_pcp *stock);
- static bool obj_stock_flush_required(struct memcg_stock_pcp *stock,
- struct mem_cgroup *root_memcg);
-
- #else
--static inline void drain_obj_stock(struct obj_stock *stock)
-+static inline void drain_obj_stock(struct memcg_stock_pcp *stock)
- {
- }
- static bool obj_stock_flush_required(struct memcg_stock_pcp *stock,
-@@ -2193,9 +2187,7 @@ static void drain_local_stock(struct wor
- local_irq_save(flags);
-
- stock = this_cpu_ptr(&memcg_stock);
-- drain_obj_stock(&stock->irq_obj);
-- if (in_task())
-- drain_obj_stock(&stock->task_obj);
-+ drain_obj_stock(stock);
- drain_stock(stock);
- clear_bit(FLUSHING_CACHED_CHARGE, &stock->flags);
-
-@@ -2771,41 +2763,6 @@ static struct mem_cgroup *get_mem_cgroup
- #define OBJCGS_CLEAR_MASK (__GFP_DMA | __GFP_RECLAIMABLE | __GFP_ACCOUNT)
-
- /*
-- * Most kmem_cache_alloc() calls are from user context. The irq disable/enable
-- * sequence used in this case to access content from object stock is slow.
-- * To optimize for user context access, there are now two object stocks for
-- * task context and interrupt context access respectively.
-- *
-- * The task context object stock can be accessed by disabling preemption only
-- * which is cheap in non-preempt kernel. The interrupt context object stock
-- * can only be accessed after disabling interrupt. User context code can
-- * access interrupt object stock, but not vice versa.
-- */
--static inline struct obj_stock *get_obj_stock(unsigned long *pflags)
--{
-- struct memcg_stock_pcp *stock;
--
-- if (likely(in_task())) {
-- *pflags = 0UL;
-- preempt_disable();
-- stock = this_cpu_ptr(&memcg_stock);
-- return &stock->task_obj;
-- }
--
-- local_irq_save(*pflags);
-- stock = this_cpu_ptr(&memcg_stock);
-- return &stock->irq_obj;
--}
--
--static inline void put_obj_stock(unsigned long flags)
--{
-- if (likely(in_task()))
-- preempt_enable();
-- else
-- local_irq_restore(flags);
--}
--
--/*
- * mod_objcg_mlstate() may be called with irq enabled, so
- * mod_memcg_lruvec_state() should be used.
- */
-@@ -3075,10 +3032,13 @@ void __memcg_kmem_uncharge_page(struct p
- void mod_objcg_state(struct obj_cgroup *objcg, struct pglist_data *pgdat,
- enum node_stat_item idx, int nr)
- {
-+ struct memcg_stock_pcp *stock;
- unsigned long flags;
-- struct obj_stock *stock = get_obj_stock(&flags);
- int *bytes;
-
-+ local_irq_save(flags);
-+ stock = this_cpu_ptr(&memcg_stock);
-+
- /*
- * Save vmstat data in stock and skip vmstat array update unless
- * accumulating over a page of vmstat data or when pgdat or idx
-@@ -3129,26 +3089,29 @@ void mod_objcg_state(struct obj_cgroup *
- if (nr)
- mod_objcg_mlstate(objcg, pgdat, idx, nr);
-
-- put_obj_stock(flags);
-+ local_irq_restore(flags);
- }
-
- static bool consume_obj_stock(struct obj_cgroup *objcg, unsigned int nr_bytes)
- {
-+ struct memcg_stock_pcp *stock;
- unsigned long flags;
-- struct obj_stock *stock = get_obj_stock(&flags);
- bool ret = false;
-
-+ local_irq_save(flags);
-+
-+ stock = this_cpu_ptr(&memcg_stock);
- if (objcg == stock->cached_objcg && stock->nr_bytes >= nr_bytes) {
- stock->nr_bytes -= nr_bytes;
- ret = true;
- }
-
-- put_obj_stock(flags);
-+ local_irq_restore(flags);
-
- return ret;
- }
-
--static void drain_obj_stock(struct obj_stock *stock)
-+static void drain_obj_stock(struct memcg_stock_pcp *stock)
- {
- struct obj_cgroup *old = stock->cached_objcg;
-
-@@ -3204,13 +3167,8 @@ static bool obj_stock_flush_required(str
- {
- struct mem_cgroup *memcg;
-
-- if (in_task() && stock->task_obj.cached_objcg) {
-- memcg = obj_cgroup_memcg(stock->task_obj.cached_objcg);
-- if (memcg && mem_cgroup_is_descendant(memcg, root_memcg))
-- return true;
-- }
-- if (stock->irq_obj.cached_objcg) {
-- memcg = obj_cgroup_memcg(stock->irq_obj.cached_objcg);
-+ if (stock->cached_objcg) {
-+ memcg = obj_cgroup_memcg(stock->cached_objcg);
- if (memcg && mem_cgroup_is_descendant(memcg, root_memcg))
- return true;
- }
-@@ -3221,10 +3179,13 @@ static bool obj_stock_flush_required(str
- static void refill_obj_stock(struct obj_cgroup *objcg, unsigned int nr_bytes,
- bool allow_uncharge)
- {
-+ struct memcg_stock_pcp *stock;
- unsigned long flags;
-- struct obj_stock *stock = get_obj_stock(&flags);
- unsigned int nr_pages = 0;
-
-+ local_irq_save(flags);
-+
-+ stock = this_cpu_ptr(&memcg_stock);
- if (stock->cached_objcg != objcg) { /* reset if necessary */
- drain_obj_stock(stock);
- obj_cgroup_get(objcg);
-@@ -3240,7 +3201,7 @@ static void refill_obj_stock(struct obj_
- stock->nr_bytes &= (PAGE_SIZE - 1);
- }
-
-- put_obj_stock(flags);
-+ local_irq_restore(flags);
-
- if (nr_pages)
- obj_cgroup_uncharge_pages(objcg, nr_pages);
-@@ -6821,7 +6782,6 @@ static void uncharge_folio(struct folio
- long nr_pages;
- struct mem_cgroup *memcg;
- struct obj_cgroup *objcg;
-- bool use_objcg = folio_memcg_kmem(folio);
-
- VM_BUG_ON_FOLIO(folio_test_lru(folio), folio);
-
-@@ -6830,7 +6790,7 @@ static void uncharge_folio(struct folio
- * folio memcg or objcg at this point, we have fully
- * exclusive access to the folio.
- */
-- if (use_objcg) {
-+ if (folio_memcg_kmem(folio)) {
- objcg = __folio_objcg(folio);
- /*
- * This get matches the put at the end of the function and
-@@ -6858,7 +6818,7 @@ static void uncharge_folio(struct folio
-
- nr_pages = folio_nr_pages(folio);
-
-- if (use_objcg) {
-+ if (folio_memcg_kmem(folio)) {
- ug->nr_memory += nr_pages;
- ug->nr_kmem += nr_pages;
-
diff --git a/patches/0001-net-dev-Remove-preempt_disable-and-get_cpu-in-netif_.patch b/patches/0001-net-dev-Remove-preempt_disable-and-get_cpu-in-netif_.patch
deleted file mode 100644
index 9893806a2398..000000000000
--- a/patches/0001-net-dev-Remove-preempt_disable-and-get_cpu-in-netif_.patch
+++ /dev/null
@@ -1,64 +0,0 @@
-From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
-Date: Wed, 15 Dec 2021 09:40:00 +0100
-Subject: [PATCH 1/3] net: dev: Remove preempt_disable() and get_cpu() in
- netif_rx_internal().
-
-The preempt_disable() () section was introduced in commit
- cece1945bffcf ("net: disable preemption before call smp_processor_id()")
-
-and adds it in case this function is invoked from preemtible context and
-because get_cpu() later on as been added.
-
-The get_cpu() usage was added in commit
- b0e28f1effd1d ("net: netif_rx() must disable preemption")
-
-because ip_dev_loopback_xmit() invoked netif_rx() with enabled preemption
-causing a warning in smp_processor_id(). The function netif_rx() should
-only be invoked from an interrupt context which implies disabled
-preemption. The commit
- e30b38c298b55 ("ip: Fix ip_dev_loopback_xmit()")
-
-was addressing this and replaced netif_rx() with in netif_rx_ni() in
-ip_dev_loopback_xmit().
-
-Based on the discussion on the list, the former patch (b0e28f1effd1d)
-should not have been applied only the latter (e30b38c298b55).
-
-Remove get_cpu() and preempt_disable() since the function is supposed to
-be invoked from context with stable per-CPU pointers. Bottom halves have
-to be disabled at this point because the function may raise softirqs
-which need to be processed.
-
-Link: https://lkml.kernel.org/r/20100415.013347.98375530.davem@davemloft.net
-Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
-Reviewed-by: Eric Dumazet <edumazet@google.com>
----
- net/core/dev.c | 5 +----
- 1 file changed, 1 insertion(+), 4 deletions(-)
-
---- a/net/core/dev.c
-+++ b/net/core/dev.c
-@@ -4796,7 +4796,6 @@ static int netif_rx_internal(struct sk_b
- struct rps_dev_flow voidflow, *rflow = &voidflow;
- int cpu;
-
-- preempt_disable();
- rcu_read_lock();
-
- cpu = get_rps_cpu(skb->dev, skb, &rflow);
-@@ -4806,14 +4805,12 @@ static int netif_rx_internal(struct sk_b
- ret = enqueue_to_backlog(skb, cpu, &rflow->last_qtail);
-
- rcu_read_unlock();
-- preempt_enable();
- } else
- #endif
- {
- unsigned int qtail;
-
-- ret = enqueue_to_backlog(skb, get_cpu(), &qtail);
-- put_cpu();
-+ ret = enqueue_to_backlog(skb, smp_processor_id(), &qtail);
- }
- return ret;
- }
diff --git a/patches/0014-printk-add-infrastucture-for-atomic-consoles.patch b/patches/0001-printk-add-infrastucture-for-atomic-consoles.patch
index 155fe3b30261..790faebfa9b7 100644
--- a/patches/0014-printk-add-infrastucture-for-atomic-consoles.patch
+++ b/patches/0001-printk-add-infrastucture-for-atomic-consoles.patch
@@ -1,6 +1,6 @@
From: John Ogness <john.ogness@linutronix.de>
Date: Fri, 4 Feb 2022 16:01:17 +0106
-Subject: [PATCH 14/16] printk: add infrastucture for atomic consoles
+Subject: [PATCH 1/3] printk: add infrastucture for atomic consoles
Many times it is not possible to see the console output on
panic because printing threads cannot be scheduled and/or the
@@ -28,14 +28,14 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
include/linux/console.h | 16 ++
init/Kconfig | 4
kernel/panic.c | 6
- kernel/printk/printk.c | 291 +++++++++++++++++++++++++++++++++++++++++++-----
- 4 files changed, 288 insertions(+), 29 deletions(-)
+ kernel/printk/printk.c | 297 +++++++++++++++++++++++++++++++++++++++++++-----
+ 4 files changed, 293 insertions(+), 30 deletions(-)
--- a/include/linux/console.h
+++ b/include/linux/console.h
-@@ -140,9 +140,19 @@ static inline int con_debug_leave(void)
- #define CON_PAUSED (128) /* Sleep while console is locked */
- #define CON_MIGHT_SLEEP (256) /* Can only be called from sleepable context */
+@@ -139,9 +139,19 @@ static inline int con_debug_leave(void)
+ #define CON_EXTENDED (64) /* Use the extended output format a la /dev/kmsg */
+ #define CON_THD_BLOCKED (128) /* Thread blocked because console is locked */
+#ifdef CONFIG_HAVE_ATOMIC_CONSOLE
+struct console_atomic_data {
@@ -53,7 +53,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
int (*read)(struct console *, char *, unsigned);
struct tty_driver *(*device)(struct console *, int *);
void (*unblank)(void);
-@@ -155,7 +165,10 @@ struct console {
+@@ -154,7 +164,10 @@ struct console {
uint ispeed;
uint ospeed;
u64 seq;
@@ -65,7 +65,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
struct task_struct *thread;
/*
-@@ -185,6 +198,7 @@ extern int console_set_on_cmdline;
+@@ -184,6 +197,7 @@ extern int console_set_on_cmdline;
extern struct console *early_console;
enum con_flush_mode {
@@ -75,7 +75,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
};
--- a/init/Kconfig
+++ b/init/Kconfig
-@@ -1541,6 +1541,10 @@ config PRINTK
+@@ -1545,6 +1545,10 @@ config PRINTK
very difficult to diagnose system problems, saying N here is
strongly discouraged.
@@ -88,7 +88,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
default y
--- a/kernel/panic.c
+++ b/kernel/panic.c
-@@ -216,7 +216,6 @@ void panic(const char *fmt, ...)
+@@ -233,7 +233,6 @@ void panic(const char *fmt, ...)
panic_smp_self_stop();
console_verbose();
@@ -96,7 +96,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
va_start(args, fmt);
len = vscnprintf(buf, sizeof(buf), fmt, args);
va_end(args);
-@@ -233,6 +232,11 @@ void panic(const char *fmt, ...)
+@@ -250,6 +249,11 @@ void panic(const char *fmt, ...)
dump_stack();
#endif
@@ -118,7 +118,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
#include <linux/sched/clock.h>
#include <linux/sched/debug.h>
#include <linux/sched/task_stack.h>
-@@ -1968,21 +1969,30 @@ static int console_trylock_spinning(void
+@@ -2035,21 +2036,30 @@ static int console_trylock_spinning(void
* dropped, a dropped message will be written out first.
*/
static void call_console_driver(struct console *con, const char *text, size_t len,
@@ -155,7 +155,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
}
/*
-@@ -2325,6 +2335,76 @@ asmlinkage __visible int _printk(const c
+@@ -2401,6 +2411,76 @@ asmlinkage __visible int _printk(const c
}
EXPORT_SYMBOL(_printk);
@@ -229,10 +229,10 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+}
+#endif /* CONFIG_HAVE_ATOMIC_CONSOLE */
+
- static void start_printk_kthread(struct console *con);
+ static bool __pr_flush(struct console *con, int timeout_ms, bool reset_on_progress);
- #else /* CONFIG_PRINTK */
-@@ -2337,6 +2417,8 @@ static void start_printk_kthread(struct
+ static void printk_start_kthread(struct console *con);
+@@ -2415,6 +2495,8 @@ static void printk_start_kthread(struct
#define prb_first_valid_seq(rb) 0
#define prb_next_seq(rb) 0
@@ -241,7 +241,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
static u64 syslog_seq;
static size_t record_print_text(const struct printk_record *r,
-@@ -2355,7 +2437,7 @@ static ssize_t msg_print_ext_body(char *
+@@ -2433,7 +2515,7 @@ static ssize_t msg_print_ext_body(char *
static void console_lock_spinning_enable(void) { }
static int console_lock_spinning_disable_and_check(void) { return 0; }
static void call_console_driver(struct console *con, const char *text, size_t len,
@@ -250,16 +250,13 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
{
}
static bool suppress_message_printing(int level) { return false; }
-@@ -2666,13 +2748,23 @@ EXPORT_SYMBOL(is_console_locked);
+@@ -2790,10 +2872,20 @@ static inline bool __console_is_usable(s
*
- * Requires the console_lock.
+ * Requires holding the console_lock or con->lock.
*/
-static inline bool console_is_usable(struct console *con)
+static inline bool console_is_usable(struct console *con, bool atomic_printing)
{
- if (!(con->flags & CON_ENABLED))
- return false;
-
- if (!con->write)
+ if (atomic_printing) {
+#ifdef CONFIG_HAVE_ATOMIC_CONSOLE
@@ -274,9 +271,9 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+ return false;
+ }
- /*
- * Console drivers may assume that per-cpu resources have been
-@@ -2704,6 +2796,66 @@ static void __console_unlock(void)
+ return __console_is_usable(con->flags);
+ }
+@@ -2818,6 +2910,66 @@ static void __console_unlock(void)
up_console_sem();
}
@@ -343,27 +340,27 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
/*
* Print one record for the given console. The record printed is whatever
* record is the next available record for the given console.
-@@ -2716,6 +2868,8 @@ static void __console_unlock(void)
+@@ -2830,6 +2982,8 @@ static void __console_unlock(void)
* If dropped messages should be printed, @dropped_text is a buffer of size
* DROPPED_TEXT_MAX. Otherwise @dropped_text must be NULL.
*
+ * @atomic_printing specifies if atomic printing should be used.
+ *
- * Requires the console_lock.
- *
- * Returns false if the given console has no next record to print, otherwise
-@@ -2727,7 +2881,8 @@ static void __console_unlock(void)
- * to disable allowing the console_lock to be taken over by a printk waiter.
+ * @handover will be set to true if a printk waiter has taken over the
+ * console_lock, in which case the caller is no longer holding the
+ * console_lock. Otherwise it is set to false. A NULL pointer may be provided
+@@ -2841,7 +2995,8 @@ static void __console_unlock(void)
+ * Requires the console_lock if @handover is non-NULL.
*/
- static bool console_emit_next_record(struct console *con, char *text, char *ext_text,
-- char *dropped_text, bool *handover)
-+ char *dropped_text, bool atomic_printing,
-+ bool *handover)
+ static bool __console_emit_next_record(struct console *con, char *text, char *ext_text,
+- char *dropped_text, bool *handover)
++ char *dropped_text, bool atomic_printing,
++ bool *handover)
{
+ static atomic_t panic_console_dropped = ATOMIC_INIT(0);
struct printk_info info;
- struct printk_record r;
-@@ -2735,23 +2890,27 @@ static bool console_emit_next_record(str
- bool allow_handover;
+@@ -2849,18 +3004,22 @@ static bool __console_emit_next_record(s
+ unsigned long flags;
char *write_text;
size_t len;
+ u64 seq;
@@ -386,7 +383,10 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+ atomic_long_add((unsigned long)(r.info->seq - seq), &con->dropped);
+ write_console_seq(con, r.info->seq, atomic_printing);
+ seq = r.info->seq;
- }
+ if (panic_in_progress() &&
+ atomic_fetch_inc_relaxed(&panic_console_dropped) > 10) {
+ suppress_panic_printk = 1;
+@@ -2870,7 +3029,7 @@ static bool __console_emit_next_record(s
/* Skip record that has level above the console loglevel. */
if (suppress_message_printing(r.info->level)) {
@@ -395,47 +395,44 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
goto skip;
}
-@@ -2784,10 +2943,10 @@ static bool console_emit_next_record(str
+@@ -2902,9 +3061,9 @@ static bool __console_emit_next_record(s
+ stop_critical_timings();
}
- stop_critical_timings(); /* don't trace print latency */
- call_console_driver(con, write_text, len, dropped_text);
+ call_console_driver(con, write_text, len, dropped_text, atomic_printing);
- start_critical_timings();
- con->seq++;
+ write_console_seq(con, seq + 1, atomic_printing);
- if (allow_handover) {
- *handover = console_lock_spinning_disable_and_check();
-@@ -2835,7 +2994,7 @@ static bool console_flush_all(bool do_co
+ if (handover) {
+ start_critical_timings();
+@@ -2936,7 +3095,7 @@ static bool console_emit_next_record_tra
+ handover = NULL;
+ }
+
+- return __console_emit_next_record(con, text, ext_text, dropped_text, handover);
++ return __console_emit_next_record(con, text, ext_text, dropped_text, false, handover);
+ }
+
+ /*
+@@ -2984,7 +3143,7 @@ static bool console_flush_all(bool do_co
for_each_console(con) {
bool progress;
- if (!console_is_usable(con))
+ if (!console_is_usable(con, false))
continue;
- if ((con->flags & CON_MIGHT_SLEEP) && !do_cond_resched)
- continue;
-@@ -2845,11 +3004,11 @@ static bool console_flush_all(bool do_co
- /* Extended consoles do not print "dropped messages". */
- progress = console_emit_next_record(con, &text[0],
- &ext_text[0], NULL,
-- handover);
-+ false, handover);
- } else {
- progress = console_emit_next_record(con, &text[0],
- NULL, &dropped_text[0],
-- handover);
-+ false, handover);
- }
- if (*handover)
- return true;
-@@ -2870,6 +3029,67 @@ static bool console_flush_all(bool do_co
+ any_usable = true;
+
+@@ -3019,6 +3178,70 @@ static bool console_flush_all(bool do_co
return any_usable;
}
+#ifdef CONFIG_HAVE_ATOMIC_CONSOLE
++static bool console_emit_next_record(struct console *con, char *text, char *ext_text,
++ char *dropped_text, bool atomic_printing);
++
+static void atomic_console_flush_all(void)
+{
+ bool any_usable = false;
@@ -470,13 +467,13 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+ &con->atomic_data->text[index],
+ &con->atomic_data->ext_text[index],
+ NULL,
-+ true, NULL);
++ true);
+ } else {
+ progress = console_emit_next_record(con,
+ &con->atomic_data->text[index],
+ NULL,
+ &con->atomic_data->dropped_text[index],
-+ true, NULL);
++ true);
+ }
+
+ if (!progress)
@@ -499,7 +496,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
/**
* console_unlock - unlock the console system
*
-@@ -2983,6 +3203,11 @@ void console_unblank(void)
+@@ -3134,6 +3357,11 @@ void console_unblank(void)
*/
void console_flush_on_panic(enum con_flush_mode mode)
{
@@ -511,7 +508,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
/*
* If someone else is holding the console lock, trylock will fail
* and may_schedule may be set. Ignore and proceed to unlock so
-@@ -2999,7 +3224,7 @@ void console_flush_on_panic(enum con_flu
+@@ -3150,7 +3378,7 @@ void console_flush_on_panic(enum con_flu
seq = prb_first_valid_seq(prb);
for_each_console(c)
@@ -520,16 +517,19 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
}
console_unlock();
}
-@@ -3240,16 +3465,19 @@ void register_console(struct console *ne
- if (consoles_paused)
- newcon->flags |= CON_PAUSED;
+@@ -3396,19 +3624,22 @@ void register_console(struct console *ne
+ if (newcon->flags & CON_EXTENDED)
+ nr_ext_console_drivers++;
- newcon->dropped = 0;
+ atomic_long_set(&newcon->dropped, 0);
+ newcon->thread = NULL;
+ newcon->flags |= CON_THD_BLOCKED;
+ mutex_init(&newcon->lock);
+#ifdef CONFIG_HAVE_ATOMIC_CONSOLE
+ newcon->atomic_data = NULL;
+#endif
- mutex_init(&newcon->lock);
+
if (newcon->flags & CON_PRINTBUFFER) {
/* Get a consistent copy of @syslog_seq. */
mutex_lock(&syslog_lock);
@@ -541,10 +541,10 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
- newcon->seq = prb_next_seq(prb);
+ write_console_seq(newcon, prb_next_seq(prb), false);
}
- if (kthreads_started)
- start_printk_kthread(newcon);
-@@ -3331,6 +3559,10 @@ int unregister_console(struct console *c
- console_unlock();
+
+ if (printk_kthreads_available)
+@@ -3497,6 +3728,10 @@ int unregister_console(struct console *c
+
console_sysfs_notify();
+#ifdef CONFIG_HAVE_ATOMIC_CONSOLE
@@ -554,18 +554,31 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
if (console->exit)
res = console->exit(console);
-@@ -3465,7 +3697,7 @@ bool pr_flush(int timeout_ms, bool reset
-
- console_lock();
- for_each_console(con) {
-- if (!console_is_usable(con))
-+ if (!console_is_usable(con, false))
+@@ -3626,7 +3861,7 @@ static bool __pr_flush(struct console *c
+ for_each_console(c) {
+ if (con && con != c)
+ continue;
+- if (!console_is_usable(c))
++ if (!console_is_usable(c, false))
continue;
- printk_seq = con->seq;
+ printk_seq = c->seq;
if (printk_seq < seq)
-@@ -3533,6 +3765,11 @@ static int printk_kthread_func(void *dat
- (con->flags & CON_BOOT) ? "boot" : "",
- con->name, con->index);
+@@ -3708,9 +3943,10 @@ static void printk_fallback_preferred_di
+ * See __console_emit_next_record() for argument and return details.
+ */
+ static bool console_emit_next_record(struct console *con, char *text, char *ext_text,
+- char *dropped_text)
++ char *dropped_text, bool atomic_printing)
+ {
+- return __console_emit_next_record(con, text, ext_text, dropped_text, NULL);
++ return __console_emit_next_record(con, text, ext_text, dropped_text,
++ atomic_printing, NULL);
+ }
+
+ static bool printer_should_wake(struct console *con, u64 seq)
+@@ -3748,6 +3984,11 @@ static int printk_kthread_func(void *dat
+ char *text;
+ int error;
+#ifdef CONFIG_HAVE_ATOMIC_CONSOLE
+ if (con->write_atomic)
@@ -573,23 +586,23 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+#endif
+
text = kmalloc(CONSOLE_LOG_MAX, GFP_KERNEL);
- if (!text)
- goto out;
-@@ -3561,7 +3798,7 @@ static int printk_kthread_func(void *dat
- if (error)
- break;
-
-- if (!console_is_usable(con)) {
-+ if (!console_is_usable(con, false)) {
- mutex_unlock(&con->lock);
- break;
- }
-@@ -3581,7 +3818,7 @@ static int printk_kthread_func(void *dat
- */
- console_may_schedule = 0;
- progress = console_emit_next_record(con, text, ext_text,
-- dropped_text, NULL);
-+ dropped_text, false, NULL);
-
- seq = con->seq;
+ if (!text) {
+ con_printk(KERN_ERR, con, "failed to allocate text buffer\n");
+@@ -3797,7 +4038,7 @@ static int printk_kthread_func(void *dat
+ if (error)
+ continue;
+
+- if (!console_is_usable(con)) {
++ if (!console_is_usable(con, false)) {
+ mutex_unlock(&con->lock);
+ continue;
+ }
+@@ -3817,7 +4058,7 @@ static int printk_kthread_func(void *dat
+ * which can conditionally invoke cond_resched().
+ */
+ console_may_schedule = 0;
+- console_emit_next_record(con, text, ext_text, dropped_text);
++ console_emit_next_record(con, text, ext_text, dropped_text, false);
+
+ seq = con->seq;
diff --git a/patches/0001-printk-rename-cpulock-functions.patch b/patches/0001-printk-rename-cpulock-functions.patch
index b65342bd5fe3..88c05b2c1f13 100644
--- a/patches/0001-printk-rename-cpulock-functions.patch
+++ b/patches/0001-printk-rename-cpulock-functions.patch
@@ -1,6 +1,6 @@
From: John Ogness <john.ogness@linutronix.de>
-Date: Mon, 7 Feb 2022 15:53:38 +0106
-Subject: [PATCH 01/16] printk: rename cpulock functions
+Date: Wed, 20 Apr 2022 01:52:23 +0206
+Subject: [PATCH 01/15] printk: rename cpulock functions
Since the printk cpulock is CPU-reentrant and since it is used
in all contexts, its usage must be carefully considered and
@@ -11,18 +11,23 @@ cpu_sync. The main functions then become:
printk_cpu_sync_get_irqsave(flags);
printk_cpu_sync_put_irqrestore(flags);
+Add extra notes of caution in the function description to help
+developers understand the requirements for correct usage.
+
Signed-off-by: John Ogness <john.ogness@linutronix.de>
+Reviewed-by: Petr Mladek <pmladek@suse.com>
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Link: https://lore.kernel.org/r/20220419234637.357112-2-john.ogness@linutronix.de
---
- include/linux/printk.h | 42 ++++++++++++++--------------
+ include/linux/printk.h | 54 ++++++++++++++++++++++---------------
kernel/printk/printk.c | 71 ++++++++++++++++++++++++-------------------------
lib/dump_stack.c | 4 +-
lib/nmi_backtrace.c | 4 +-
- 4 files changed, 61 insertions(+), 60 deletions(-)
+ 4 files changed, 73 insertions(+), 60 deletions(-)
--- a/include/linux/printk.h
+++ b/include/linux/printk.h
-@@ -277,43 +277,43 @@ static inline void printk_trigger_flush(
+@@ -277,43 +277,55 @@ static inline void printk_trigger_flush(
#endif
#ifdef CONFIG_SMP
@@ -44,6 +49,18 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
*
* If the lock is owned by another CPU, spin until it becomes available.
* Interrupts are restored while spinning.
++ *
++ * CAUTION: This function must be used carefully. It does not behave like a
++ * typical lock. Here are important things to watch out for...
++ *
++ * * This function is reentrant on the same CPU. Therefore the calling
++ * code must not assume exclusive access to data if code accessing the
++ * data can run reentrant or within NMI context on the same CPU.
++ *
++ * * If there exists usage of this function from NMI context, it becomes
++ * unsafe to perform any type of locking or spinning to wait for other
++ * CPUs after calling this function from any context. This includes
++ * using spinlocks or any other busy-waiting synchronization methods.
*/
-#define printk_cpu_lock_irqsave(flags) \
- for (;;) { \
@@ -89,7 +106,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
--- a/kernel/printk/printk.c
+++ b/kernel/printk/printk.c
-@@ -3600,26 +3600,26 @@ EXPORT_SYMBOL_GPL(kmsg_dump_rewind);
+@@ -3667,26 +3667,26 @@ EXPORT_SYMBOL_GPL(kmsg_dump_rewind);
#endif
#ifdef CONFIG_SMP
@@ -125,7 +142,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
*
* If no processor has the lock, the calling processor takes the lock and
* becomes the owner. If the calling processor is already the owner of the
-@@ -3628,7 +3628,7 @@ EXPORT_SYMBOL(__printk_wait_on_cpu_lock)
+@@ -3695,7 +3695,7 @@ EXPORT_SYMBOL(__printk_wait_on_cpu_lock)
* Context: Any context. Expects interrupts to be disabled.
* Return: 1 on success, otherwise 0.
*/
@@ -134,7 +151,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
{
int cpu;
int old;
-@@ -3638,79 +3638,80 @@ int __printk_cpu_trylock(void)
+@@ -3705,79 +3705,80 @@ int __printk_cpu_trylock(void)
/*
* Guarantee loads and stores from this CPU when it is the lock owner
* are _not_ visible to the previous lock owner. This pairs with
diff --git a/patches/0001-random-use-computational-hash-for-entropy-extraction.patch b/patches/0001-random-use-computational-hash-for-entropy-extraction.patch
deleted file mode 100644
index 144904e02cfb..000000000000
--- a/patches/0001-random-use-computational-hash-for-entropy-extraction.patch
+++ /dev/null
@@ -1,498 +0,0 @@
-From: "Jason A. Donenfeld" <Jason@zx2c4.com>
-Date: Sun, 16 Jan 2022 14:23:10 +0100
-Subject: [PATCH 1/5] random: use computational hash for entropy extraction
-
-The current 4096-bit LFSR used for entropy collection had a few
-desirable attributes for the context in which it was created. For
-example, the state was huge, which meant that /dev/random would be able
-to output quite a bit of accumulated entropy before blocking. It was
-also, in its time, quite fast at accumulating entropy byte-by-byte,
-which matters given the varying contexts in which mix_pool_bytes() is
-called. And its diffusion was relatively high, which meant that changes
-would ripple across several words of state rather quickly.
-
-However, it also suffers from a few security vulnerabilities. In
-particular, inputs learned by an attacker can be undone, but more over,
-if the state of the pool leaks, its contents can be controlled and
-entirely zeroed out. I've demonstrated this attack with this SMT2
-script, <https://xn--4db.cc/5o9xO8pb>, which Boolector/CaDiCal solves in
-a matter of seconds on a single core of my laptop, resulting in little
-proof of concept C demonstrators such as <https://xn--4db.cc/jCkvvIaH/c>.
-
-For basically all recent formal models of RNGs, these attacks represent
-a significant cryptographic flaw. But how does this manifest
-practically? If an attacker has access to the system to such a degree
-that he can learn the internal state of the RNG, arguably there are
-other lower hanging vulnerabilities -- side-channel, infoleak, or
-otherwise -- that might have higher priority. On the other hand, seed
-files are frequently used on systems that have a hard time generating
-much entropy on their own, and these seed files, being files, often leak
-or are duplicated and distributed accidentally, or are even seeded over
-the Internet intentionally, where their contents might be recorded or
-tampered with. Seen this way, an otherwise quasi-implausible
-vulnerability is a bit more practical than initially thought.
-
-Another aspect of the current mix_pool_bytes() function is that, while
-its performance was arguably competitive for the time in which it was
-created, it's no longer considered so. This patch improves performance
-significantly: on a high-end CPU, an i7-11850H, it improves performance
-of mix_pool_bytes() by 225%, and on a low-end CPU, a Cortex-A7, it
-improves performance by 103%.
-
-This commit replaces the LFSR of mix_pool_bytes() with a straight-
-forward cryptographic hash function, BLAKE2s, which is already in use
-for pool extraction. Universal hashing with a secret seed was considered
-too, something along the lines of <https://eprint.iacr.org/2013/338>,
-but the requirement for a secret seed makes for a chicken & egg problem.
-Instead we go with a formally proven scheme using a computational hash
-function, described in sections 5.1, 6.4, and B.1.8 of
-<https://eprint.iacr.org/2019/198>.
-
-BLAKE2s outputs 256 bits, which should give us an appropriate amount of
-min-entropy accumulation, and a wide enough margin of collision
-resistance against active attacks. mix_pool_bytes() becomes a simple
-call to blake2s_update(), for accumulation, while the extraction step
-becomes a blake2s_final() to generate a seed, with which we can then do
-a HKDF-like or BLAKE2X-like expansion, the first part of which we fold
-back as an init key for subsequent blake2s_update()s, and the rest we
-produce to the caller. This then is provided to our CRNG like usual. In
-that expansion step, we make opportunistic use of 32 bytes of RDRAND
-output, just as before. We also always reseed the crng with 32 bytes,
-unconditionally, or not at all, rather than sometimes with 16 as before,
-as we don't win anything by limiting beyond the 16 byte threshold.
-
-Going for a hash function as an entropy collector is a conservative,
-proven approach. The result of all this is a much simpler and much less
-bespoke construction than what's there now, which not only plugs a
-vulnerability but also improves performance considerably.
-
-[ bigeasy: commit 107307cbac3871a1b26088d4865de57ae9b50032 from
- git.kernel.org/pub/scm/linux/kernel/git/crng/random.git ]
-
-Cc: Theodore Ts'o <tytso@mit.edu>
-Cc: Dominik Brodowski <linux@dominikbrodowski.net>
-Reviewed-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-Reviewed-by: Jean-Philippe Aumasson <jeanphilippe.aumasson@gmail.com>
-Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
-Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
----
- drivers/char/random.c | 304 +++++++++-----------------------------------------
- 1 file changed, 55 insertions(+), 249 deletions(-)
-
---- a/drivers/char/random.c
-+++ b/drivers/char/random.c
-@@ -42,61 +42,6 @@
- */
-
- /*
-- * (now, with legal B.S. out of the way.....)
-- *
-- * This routine gathers environmental noise from device drivers, etc.,
-- * and returns good random numbers, suitable for cryptographic use.
-- * Besides the obvious cryptographic uses, these numbers are also good
-- * for seeding TCP sequence numbers, and other places where it is
-- * desirable to have numbers which are not only random, but hard to
-- * predict by an attacker.
-- *
-- * Theory of operation
-- * ===================
-- *
-- * Computers are very predictable devices. Hence it is extremely hard
-- * to produce truly random numbers on a computer --- as opposed to
-- * pseudo-random numbers, which can easily generated by using a
-- * algorithm. Unfortunately, it is very easy for attackers to guess
-- * the sequence of pseudo-random number generators, and for some
-- * applications this is not acceptable. So instead, we must try to
-- * gather "environmental noise" from the computer's environment, which
-- * must be hard for outside attackers to observe, and use that to
-- * generate random numbers. In a Unix environment, this is best done
-- * from inside the kernel.
-- *
-- * Sources of randomness from the environment include inter-keyboard
-- * timings, inter-interrupt timings from some interrupts, and other
-- * events which are both (a) non-deterministic and (b) hard for an
-- * outside observer to measure. Randomness from these sources are
-- * added to an "entropy pool", which is mixed using a CRC-like function.
-- * This is not cryptographically strong, but it is adequate assuming
-- * the randomness is not chosen maliciously, and it is fast enough that
-- * the overhead of doing it on every interrupt is very reasonable.
-- * As random bytes are mixed into the entropy pool, the routines keep
-- * an *estimate* of how many bits of randomness have been stored into
-- * the random number generator's internal state.
-- *
-- * When random bytes are desired, they are obtained by taking the BLAKE2s
-- * hash of the contents of the "entropy pool". The BLAKE2s hash avoids
-- * exposing the internal state of the entropy pool. It is believed to
-- * be computationally infeasible to derive any useful information
-- * about the input of BLAKE2s from its output. Even if it is possible to
-- * analyze BLAKE2s in some clever way, as long as the amount of data
-- * returned from the generator is less than the inherent entropy in
-- * the pool, the output data is totally unpredictable. For this
-- * reason, the routine decreases its internal estimate of how many
-- * bits of "true randomness" are contained in the entropy pool as it
-- * outputs random numbers.
-- *
-- * If this estimate goes to zero, the routine can still generate
-- * random numbers; however, an attacker may (at least in theory) be
-- * able to infer the future output of the generator from prior
-- * outputs. This requires successful cryptanalysis of BLAKE2s, which is
-- * not believed to be feasible, but there is a remote possibility.
-- * Nonetheless, these numbers should be useful for the vast majority
-- * of purposes.
-- *
- * Exported interfaces ---- output
- * ===============================
- *
-@@ -298,23 +243,6 @@
- *
- * mknod /dev/random c 1 8
- * mknod /dev/urandom c 1 9
-- *
-- * Acknowledgements:
-- * =================
-- *
-- * Ideas for constructing this random number generator were derived
-- * from Pretty Good Privacy's random number generator, and from private
-- * discussions with Phil Karn. Colin Plumb provided a faster random
-- * number generator, which speed up the mixing function of the entropy
-- * pool, taken from PGPfone. Dale Worley has also contributed many
-- * useful ideas and suggestions to improve this driver.
-- *
-- * Any flaws in the design are solely my responsibility, and should
-- * not be attributed to the Phil, Colin, or any of authors of PGP.
-- *
-- * Further background information on this topic may be obtained from
-- * RFC 1750, "Randomness Recommendations for Security", by Donald
-- * Eastlake, Steve Crocker, and Jeff Schiller.
- */
-
- #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-@@ -358,79 +286,15 @@
-
- /* #define ADD_INTERRUPT_BENCH */
-
--/*
-- * If the entropy count falls under this number of bits, then we
-- * should wake up processes which are selecting or polling on write
-- * access to /dev/random.
-- */
--static int random_write_wakeup_bits = 28 * (1 << 5);
--
--/*
-- * Originally, we used a primitive polynomial of degree .poolwords
-- * over GF(2). The taps for various sizes are defined below. They
-- * were chosen to be evenly spaced except for the last tap, which is 1
-- * to get the twisting happening as fast as possible.
-- *
-- * For the purposes of better mixing, we use the CRC-32 polynomial as
-- * well to make a (modified) twisted Generalized Feedback Shift
-- * Register. (See M. Matsumoto & Y. Kurita, 1992. Twisted GFSR
-- * generators. ACM Transactions on Modeling and Computer Simulation
-- * 2(3):179-194. Also see M. Matsumoto & Y. Kurita, 1994. Twisted
-- * GFSR generators II. ACM Transactions on Modeling and Computer
-- * Simulation 4:254-266)
-- *
-- * Thanks to Colin Plumb for suggesting this.
-- *
-- * The mixing operation is much less sensitive than the output hash,
-- * where we use BLAKE2s. All that we want of mixing operation is that
-- * it be a good non-cryptographic hash; i.e. it not produce collisions
-- * when fed "random" data of the sort we expect to see. As long as
-- * the pool state differs for different inputs, we have preserved the
-- * input entropy and done a good job. The fact that an intelligent
-- * attacker can construct inputs that will produce controlled
-- * alterations to the pool's state is not important because we don't
-- * consider such inputs to contribute any randomness. The only
-- * property we need with respect to them is that the attacker can't
-- * increase his/her knowledge of the pool's state. Since all
-- * additions are reversible (knowing the final state and the input,
-- * you can reconstruct the initial state), if an attacker has any
-- * uncertainty about the initial state, he/she can only shuffle that
-- * uncertainty about, but never cause any collisions (which would
-- * decrease the uncertainty).
-- *
-- * Our mixing functions were analyzed by Lacharme, Roeck, Strubel, and
-- * Videau in their paper, "The Linux Pseudorandom Number Generator
-- * Revisited" (see: http://eprint.iacr.org/2012/251.pdf). In their
-- * paper, they point out that we are not using a true Twisted GFSR,
-- * since Matsumoto & Kurita used a trinomial feedback polynomial (that
-- * is, with only three taps, instead of the six that we are using).
-- * As a result, the resulting polynomial is neither primitive nor
-- * irreducible, and hence does not have a maximal period over
-- * GF(2**32). They suggest a slight change to the generator
-- * polynomial which improves the resulting TGFSR polynomial to be
-- * irreducible, which we have made here.
-- */
- enum poolinfo {
-- POOL_WORDS = 128,
-- POOL_WORDMASK = POOL_WORDS - 1,
-- POOL_BYTES = POOL_WORDS * sizeof(u32),
-- POOL_BITS = POOL_BYTES * 8,
-+ POOL_BITS = BLAKE2S_HASH_SIZE * 8,
- POOL_BITSHIFT = ilog2(POOL_BITS),
-
- /* To allow fractional bits to be tracked, the entropy_count field is
- * denominated in units of 1/8th bits. */
- POOL_ENTROPY_SHIFT = 3,
- #define POOL_ENTROPY_BITS() (input_pool.entropy_count >> POOL_ENTROPY_SHIFT)
-- POOL_FRACBITS = POOL_BITS << POOL_ENTROPY_SHIFT,
--
-- /* x^128 + x^104 + x^76 + x^51 +x^25 + x + 1 */
-- POOL_TAP1 = 104,
-- POOL_TAP2 = 76,
-- POOL_TAP3 = 51,
-- POOL_TAP4 = 25,
-- POOL_TAP5 = 1,
--
-- EXTRACT_SIZE = BLAKE2S_HASH_SIZE / 2
-+ POOL_FRACBITS = POOL_BITS << POOL_ENTROPY_SHIFT
- };
-
- /*
-@@ -438,6 +302,12 @@ enum poolinfo {
- */
- static DECLARE_WAIT_QUEUE_HEAD(random_write_wait);
- static struct fasync_struct *fasync;
-+/*
-+ * If the entropy count falls under this number of bits, then we
-+ * should wake up processes which are selecting or polling on write
-+ * access to /dev/random.
-+ */
-+static int random_write_wakeup_bits = POOL_BITS * 3 / 4;
-
- static DEFINE_SPINLOCK(random_ready_list_lock);
- static LIST_HEAD(random_ready_list);
-@@ -493,73 +363,31 @@ MODULE_PARM_DESC(ratelimit_disable, "Dis
- *
- **********************************************************************/
-
--static u32 input_pool_data[POOL_WORDS] __latent_entropy;
--
- static struct {
-+ struct blake2s_state hash;
- spinlock_t lock;
-- u16 add_ptr;
-- u16 input_rotate;
- int entropy_count;
- } input_pool = {
-+ .hash.h = { BLAKE2S_IV0 ^ (0x01010000 | BLAKE2S_HASH_SIZE),
-+ BLAKE2S_IV1, BLAKE2S_IV2, BLAKE2S_IV3, BLAKE2S_IV4,
-+ BLAKE2S_IV5, BLAKE2S_IV6, BLAKE2S_IV7 },
-+ .hash.outlen = BLAKE2S_HASH_SIZE,
- .lock = __SPIN_LOCK_UNLOCKED(input_pool.lock),
- };
-
--static ssize_t extract_entropy(void *buf, size_t nbytes, int min);
--static ssize_t _extract_entropy(void *buf, size_t nbytes);
-+static bool extract_entropy(void *buf, size_t nbytes, int min);
-+static void _extract_entropy(void *buf, size_t nbytes);
-
- static void crng_reseed(struct crng_state *crng, bool use_input_pool);
-
--static const u32 twist_table[8] = {
-- 0x00000000, 0x3b6e20c8, 0x76dc4190, 0x4db26158,
-- 0xedb88320, 0xd6d6a3e8, 0x9b64c2b0, 0xa00ae278 };
--
- /*
- * This function adds bytes into the entropy "pool". It does not
- * update the entropy estimate. The caller should call
- * credit_entropy_bits if this is appropriate.
-- *
-- * The pool is stirred with a primitive polynomial of the appropriate
-- * degree, and then twisted. We twist by three bits at a time because
-- * it's cheap to do so and helps slightly in the expected case where
-- * the entropy is concentrated in the low-order bits.
- */
- static void _mix_pool_bytes(const void *in, int nbytes)
- {
-- unsigned long i;
-- int input_rotate;
-- const u8 *bytes = in;
-- u32 w;
--
-- input_rotate = input_pool.input_rotate;
-- i = input_pool.add_ptr;
--
-- /* mix one byte at a time to simplify size handling and churn faster */
-- while (nbytes--) {
-- w = rol32(*bytes++, input_rotate);
-- i = (i - 1) & POOL_WORDMASK;
--
-- /* XOR in the various taps */
-- w ^= input_pool_data[i];
-- w ^= input_pool_data[(i + POOL_TAP1) & POOL_WORDMASK];
-- w ^= input_pool_data[(i + POOL_TAP2) & POOL_WORDMASK];
-- w ^= input_pool_data[(i + POOL_TAP3) & POOL_WORDMASK];
-- w ^= input_pool_data[(i + POOL_TAP4) & POOL_WORDMASK];
-- w ^= input_pool_data[(i + POOL_TAP5) & POOL_WORDMASK];
--
-- /* Mix the result back in with a twist */
-- input_pool_data[i] = (w >> 3) ^ twist_table[w & 7];
--
-- /*
-- * Normally, we add 7 bits of rotation to the pool.
-- * At the beginning of the pool, add an extra 7 bits
-- * rotation, so that successive passes spread the
-- * input bits across the pool evenly.
-- */
-- input_rotate = (input_rotate + (i ? 7 : 14)) & 31;
-- }
--
-- input_pool.input_rotate = input_rotate;
-- input_pool.add_ptr = i;
-+ blake2s_update(&input_pool.hash, in, nbytes);
- }
-
- static void __mix_pool_bytes(const void *in, int nbytes)
-@@ -953,15 +781,14 @@ static int crng_slow_load(const u8 *cp,
- static void crng_reseed(struct crng_state *crng, bool use_input_pool)
- {
- unsigned long flags;
-- int i, num;
-+ int i;
- union {
- u8 block[CHACHA_BLOCK_SIZE];
- u32 key[8];
- } buf;
-
- if (use_input_pool) {
-- num = extract_entropy(&buf, 32, 16);
-- if (num == 0)
-+ if (!extract_entropy(&buf, 32, 16))
- return;
- } else {
- _extract_crng(&primary_crng, buf.block);
-@@ -1329,74 +1156,48 @@ static size_t account(size_t nbytes, int
- }
-
- /*
-- * This function does the actual extraction for extract_entropy.
-- *
-- * Note: we assume that .poolwords is a multiple of 16 words.
-+ * This is an HKDF-like construction for using the hashed collected entropy
-+ * as a PRF key, that's then expanded block-by-block.
- */
--static void extract_buf(u8 *out)
-+static void _extract_entropy(void *buf, size_t nbytes)
- {
-- struct blake2s_state state __aligned(__alignof__(unsigned long));
-- u8 hash[BLAKE2S_HASH_SIZE];
-- unsigned long *salt;
- unsigned long flags;
--
-- blake2s_init(&state, sizeof(hash));
--
-- /*
-- * If we have an architectural hardware random number
-- * generator, use it for BLAKE2's salt & personal fields.
-- */
-- for (salt = (unsigned long *)&state.h[4];
-- salt < (unsigned long *)&state.h[8]; ++salt) {
-- unsigned long v;
-- if (!arch_get_random_long(&v))
-- break;
-- *salt ^= v;
-+ u8 seed[BLAKE2S_HASH_SIZE], next_key[BLAKE2S_HASH_SIZE];
-+ struct {
-+ unsigned long rdrand[32 / sizeof(long)];
-+ size_t counter;
-+ } block;
-+ size_t i;
-+
-+ for (i = 0; i < ARRAY_SIZE(block.rdrand); ++i) {
-+ if (!arch_get_random_long(&block.rdrand[i]))
-+ block.rdrand[i] = random_get_entropy();
- }
-
-- /* Generate a hash across the pool */
- spin_lock_irqsave(&input_pool.lock, flags);
-- blake2s_update(&state, (const u8 *)input_pool_data, POOL_BYTES);
-- blake2s_final(&state, hash); /* final zeros out state */
-
-- /*
-- * We mix the hash back into the pool to prevent backtracking
-- * attacks (where the attacker knows the state of the pool
-- * plus the current outputs, and attempts to find previous
-- * outputs), unless the hash function can be inverted. By
-- * mixing at least a hash worth of hash data back, we make
-- * brute-forcing the feedback as hard as brute-forcing the
-- * hash.
-- */
-- __mix_pool_bytes(hash, sizeof(hash));
-- spin_unlock_irqrestore(&input_pool.lock, flags);
-+ /* seed = HASHPRF(last_key, entropy_input) */
-+ blake2s_final(&input_pool.hash, seed);
-
-- /* Note that EXTRACT_SIZE is half of hash size here, because above
-- * we've dumped the full length back into mixer. By reducing the
-- * amount that we emit, we retain a level of forward secrecy.
-- */
-- memcpy(out, hash, EXTRACT_SIZE);
-- memzero_explicit(hash, sizeof(hash));
--}
-+ /* next_key = HASHPRF(key, RDRAND || 0) */
-+ block.counter = 0;
-+ blake2s(next_key, (u8 *)&block, seed, sizeof(next_key), sizeof(block), sizeof(seed));
-+ blake2s_init_key(&input_pool.hash, BLAKE2S_HASH_SIZE, next_key, sizeof(next_key));
-
--static ssize_t _extract_entropy(void *buf, size_t nbytes)
--{
-- ssize_t ret = 0, i;
-- u8 tmp[EXTRACT_SIZE];
-+ spin_unlock_irqrestore(&input_pool.lock, flags);
-+ memzero_explicit(next_key, sizeof(next_key));
-
- while (nbytes) {
-- extract_buf(tmp);
-- i = min_t(int, nbytes, EXTRACT_SIZE);
-- memcpy(buf, tmp, i);
-+ i = min_t(size_t, nbytes, BLAKE2S_HASH_SIZE);
-+ /* output = HASHPRF(key, RDRAND || ++counter) */
-+ ++block.counter;
-+ blake2s(buf, (u8 *)&block, seed, i, sizeof(block), sizeof(seed));
- nbytes -= i;
- buf += i;
-- ret += i;
- }
-
-- /* Wipe data just returned from memory */
-- memzero_explicit(tmp, sizeof(tmp));
--
-- return ret;
-+ memzero_explicit(seed, sizeof(seed));
-+ memzero_explicit(&block, sizeof(block));
- }
-
- /*
-@@ -1404,13 +1205,18 @@ static ssize_t _extract_entropy(void *bu
- * returns it in a buffer.
- *
- * The min parameter specifies the minimum amount we can pull before
-- * failing to avoid races that defeat catastrophic reseeding.
-+ * failing to avoid races that defeat catastrophic reseeding. If we
-+ * have less than min entropy available, we return false and buf is
-+ * not filled.
- */
--static ssize_t extract_entropy(void *buf, size_t nbytes, int min)
-+static bool extract_entropy(void *buf, size_t nbytes, int min)
- {
- trace_extract_entropy(nbytes, POOL_ENTROPY_BITS(), _RET_IP_);
-- nbytes = account(nbytes, min);
-- return _extract_entropy(buf, nbytes);
-+ if (account(nbytes, min)) {
-+ _extract_entropy(buf, nbytes);
-+ return true;
-+ }
-+ return false;
- }
-
- #define warn_unseeded_randomness(previous) \
-@@ -1674,7 +1480,7 @@ static void __init init_std_data(void)
- unsigned long rv;
-
- mix_pool_bytes(&now, sizeof(now));
-- for (i = POOL_BYTES; i > 0; i -= sizeof(rv)) {
-+ for (i = BLAKE2S_BLOCK_SIZE; i > 0; i -= sizeof(rv)) {
- if (!arch_get_random_seed_long(&rv) &&
- !arch_get_random_long(&rv))
- rv = random_get_entropy();
diff --git a/patches/0001-sched-Fix-missing-prototype-warnings.patch b/patches/0001-sched-Fix-missing-prototype-warnings.patch
new file mode 100644
index 000000000000..25995095d3aa
--- /dev/null
+++ b/patches/0001-sched-Fix-missing-prototype-warnings.patch
@@ -0,0 +1,141 @@
+From: Thomas Gleixner <tglx@linutronix.de>
+Date: Wed, 13 Apr 2022 15:31:02 +0200
+Subject: [PATCH 1/3] sched: Fix missing prototype warnings
+
+A W=1 build emits more than a dozen missing prototype warnings related to
+scheduler and scheduler specific includes.
+
+Reported-by: kernel test robot <lkp@intel.com>
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Link: https://lore.kernel.org/r/20220413133024.249118058@linutronix.de
+---
+ include/linux/sched.h | 2 ++
+ kernel/sched/build_policy.c | 2 ++
+ kernel/sched/build_utility.c | 1 +
+ kernel/sched/core.c | 3 +++
+ kernel/sched/deadline.c | 2 --
+ kernel/sched/fair.c | 1 +
+ kernel/sched/sched.h | 8 ++------
+ kernel/sched/smp.h | 6 ++++++
+ kernel/stop_machine.c | 2 --
+ 9 files changed, 17 insertions(+), 10 deletions(-)
+
+--- a/include/linux/sched.h
++++ b/include/linux/sched.h
+@@ -2364,4 +2364,6 @@ static inline void sched_core_free(struc
+ static inline void sched_core_fork(struct task_struct *p) { }
+ #endif
+
++extern void sched_set_stop_task(int cpu, struct task_struct *stop);
++
+ #endif
+--- a/kernel/sched/build_policy.c
++++ b/kernel/sched/build_policy.c
+@@ -15,6 +15,7 @@
+ /* Headers: */
+ #include <linux/sched/clock.h>
+ #include <linux/sched/cputime.h>
++#include <linux/sched/hotplug.h>
+ #include <linux/sched/posix-timers.h>
+ #include <linux/sched/rt.h>
+
+@@ -31,6 +32,7 @@
+ #include <uapi/linux/sched/types.h>
+
+ #include "sched.h"
++#include "smp.h"
+
+ #include "autogroup.h"
+ #include "stats.h"
+--- a/kernel/sched/build_utility.c
++++ b/kernel/sched/build_utility.c
+@@ -14,6 +14,7 @@
+ #include <linux/sched/debug.h>
+ #include <linux/sched/isolation.h>
+ #include <linux/sched/loadavg.h>
++#include <linux/sched/nohz.h>
+ #include <linux/sched/mm.h>
+ #include <linux/sched/rseq_api.h>
+ #include <linux/sched/task_stack.h>
+--- a/kernel/sched/core.c
++++ b/kernel/sched/core.c
+@@ -26,7 +26,10 @@
+ #include <linux/topology.h>
+ #include <linux/sched/clock.h>
+ #include <linux/sched/cond_resched.h>
++#include <linux/sched/cputime.h>
+ #include <linux/sched/debug.h>
++#include <linux/sched/hotplug.h>
++#include <linux/sched/init.h>
+ #include <linux/sched/isolation.h>
+ #include <linux/sched/loadavg.h>
+ #include <linux/sched/mm.h>
+--- a/kernel/sched/deadline.c
++++ b/kernel/sched/deadline.c
+@@ -1220,8 +1220,6 @@ int dl_runtime_exceeded(struct sched_dl_
+ return (dl_se->runtime <= 0);
+ }
+
+-extern bool sched_rt_bandwidth_account(struct rt_rq *rt_rq);
+-
+ /*
+ * This function implements the GRUB accounting rule:
+ * according to the GRUB reclaiming algorithm, the runtime is
+--- a/kernel/sched/fair.c
++++ b/kernel/sched/fair.c
+@@ -36,6 +36,7 @@
+ #include <linux/sched/cond_resched.h>
+ #include <linux/sched/cputime.h>
+ #include <linux/sched/isolation.h>
++#include <linux/sched/nohz.h>
+
+ #include <linux/cpuidle.h>
+ #include <linux/interrupt.h>
+--- a/kernel/sched/sched.h
++++ b/kernel/sched/sched.h
+@@ -1827,12 +1827,7 @@ static inline void dirty_sched_domain_sy
+ #endif
+
+ extern int sched_update_scaling(void);
+-
+-extern void flush_smp_call_function_from_idle(void);
+-
+-#else /* !CONFIG_SMP: */
+-static inline void flush_smp_call_function_from_idle(void) { }
+-#endif
++#endif /* CONFIG_SMP */
+
+ #include "stats.h"
+
+@@ -2309,6 +2304,7 @@ extern void resched_cpu(int cpu);
+
+ extern struct rt_bandwidth def_rt_bandwidth;
+ extern void init_rt_bandwidth(struct rt_bandwidth *rt_b, u64 period, u64 runtime);
++extern bool sched_rt_bandwidth_account(struct rt_rq *rt_rq);
+
+ extern void init_dl_bandwidth(struct dl_bandwidth *dl_b, u64 period, u64 runtime);
+ extern void init_dl_task_timer(struct sched_dl_entity *dl_se);
+--- a/kernel/sched/smp.h
++++ b/kernel/sched/smp.h
+@@ -7,3 +7,9 @@
+ extern void sched_ttwu_pending(void *arg);
+
+ extern void send_call_function_single_ipi(int cpu);
++
++#ifdef CONFIG_SMP
++extern void flush_smp_call_function_from_idle(void);
++#else
++static inline void flush_smp_call_function_from_idle(void) { }
++#endif
+--- a/kernel/stop_machine.c
++++ b/kernel/stop_machine.c
+@@ -535,8 +535,6 @@ void stop_machine_park(int cpu)
+ kthread_park(stopper->thread);
+ }
+
+-extern void sched_set_stop_task(int cpu, struct task_struct *stop);
+-
+ static void cpu_stop_create(unsigned int cpu)
+ {
+ sched_set_stop_task(cpu, per_cpu(cpu_stopper.thread, cpu));
diff --git a/patches/0002-i2c-core-Use-generic_handle_irq_safe-in-i2c_handle_s.patch b/patches/0002-i2c-core-Use-generic_handle_irq_safe-in-i2c_handle_s.patch
deleted file mode 100644
index f9711eb71860..000000000000
--- a/patches/0002-i2c-core-Use-generic_handle_irq_safe-in-i2c_handle_s.patch
+++ /dev/null
@@ -1,39 +0,0 @@
-From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
-Date: Fri, 11 Feb 2022 19:14:55 +0100
-Subject: [PATCH 2/7] i2c: core: Use generic_handle_irq_safe() in
- i2c_handle_smbus_host_notify().
-
-The i2c-i801 driver invokes i2c_handle_smbus_host_notify() from his
-interrupt service routine. On PREEMPT_RT i2c-i801's handler is forced
-threaded with enabled interrupts which leads to a warning by
-handle_irq_event_percpu() assuming that irq_default_primary_handler()
-enabled interrupts.
-
-i2c-i801's interrupt handler can't be made non-threaded because the
-interrupt line is shared with other devices.
-
-Use generic_handle_irq_safe() which can invoked with disabled and enabled
-interrupts.
-
-Reported-by: Michael Below <below@judiz.de>
-Link: https://bugs.debian.org/1002537
-Cc: Salvatore Bonaccorso <carnil@debian.org>
-Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
-Reviewed-by: Oleksandr Natalenko <oleksandr@natalenko.name>
-Acked-by: Wolfram Sang <wsa@kernel.org>
-Link: https://lore.kernel.org/r/20220211181500.1856198-3-bigeasy@linutronix.de
----
- drivers/i2c/i2c-core-base.c | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
---- a/drivers/i2c/i2c-core-base.c
-+++ b/drivers/i2c/i2c-core-base.c
-@@ -1424,7 +1424,7 @@ int i2c_handle_smbus_host_notify(struct
- if (irq <= 0)
- return -ENXIO;
-
-- generic_handle_irq(irq);
-+ generic_handle_irq_safe(irq);
-
- return 0;
- }
diff --git a/patches/0002-kernel-fork-Duplicate-task_struct-before-stack-alloc.patch b/patches/0002-kernel-fork-Duplicate-task_struct-before-stack-alloc.patch
deleted file mode 100644
index c99f1d144187..000000000000
--- a/patches/0002-kernel-fork-Duplicate-task_struct-before-stack-alloc.patch
+++ /dev/null
@@ -1,51 +0,0 @@
-From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
-Date: Thu, 17 Feb 2022 11:24:00 +0100
-Subject: [PATCH 2/8] kernel/fork: Duplicate task_struct before stack
- allocation.
-
-alloc_thread_stack_node() already populates the task_struct::stack
-member except on IA64. The stack pointer is saved and populated again
-because IA64 needs it and arch_dup_task_struct() overwrites it.
-
-Allocate thread's stack after task_struct has been duplicated as a
-preparation.
-
-Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
-Acked-by: Andy Lutomirski <luto@kernel.org>
-Link: https://lore.kernel.org/r/20220217102406.3697941-3-bigeasy@linutronix.de
----
- kernel/fork.c | 9 ++++-----
- 1 file changed, 4 insertions(+), 5 deletions(-)
-
---- a/kernel/fork.c
-+++ b/kernel/fork.c
-@@ -888,6 +888,10 @@ static struct task_struct *dup_task_stru
- if (!tsk)
- return NULL;
-
-+ err = arch_dup_task_struct(tsk, orig);
-+ if (err)
-+ goto free_tsk;
-+
- stack = alloc_thread_stack_node(tsk, node);
- if (!stack)
- goto free_tsk;
-@@ -897,8 +901,6 @@ static struct task_struct *dup_task_stru
-
- stack_vm_area = task_stack_vm_area(tsk);
-
-- err = arch_dup_task_struct(tsk, orig);
--
- /*
- * arch_dup_task_struct() clobbers the stack-related fields. Make
- * sure they're properly initialized before using any stack-related
-@@ -912,9 +914,6 @@ static struct task_struct *dup_task_stru
- refcount_set(&tsk->stack_refcount, 1);
- #endif
-
-- if (err)
-- goto free_stack;
--
- err = scs_prepare(tsk, node);
- if (err)
- goto free_stack;
diff --git a/patches/0002-mm-memcg-Disable-threshold-event-handlers-on-PREEMPT.patch b/patches/0002-mm-memcg-Disable-threshold-event-handlers-on-PREEMPT.patch
deleted file mode 100644
index 041388fc5aff..000000000000
--- a/patches/0002-mm-memcg-Disable-threshold-event-handlers-on-PREEMPT.patch
+++ /dev/null
@@ -1,91 +0,0 @@
-From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
-Date: Thu, 17 Feb 2022 10:47:59 +0100
-Subject: [PATCH 2/8] mm/memcg: Disable threshold event handlers on PREEMPT_RT
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-During the integration of PREEMPT_RT support, the code flow around
-memcg_check_events() resulted in `twisted code'. Moving the code around
-and avoiding then would then lead to an additional local-irq-save
-section within memcg_check_events(). While looking better, it adds a
-local-irq-save section to code flow which is usually within an
-local-irq-off block on non-PREEMPT_RT configurations.
-
-The threshold event handler is a deprecated memcg v1 feature. Instead of
-trying to get it to work under PREEMPT_RT just disable it. There should
-be no users on PREEMPT_RT. From that perspective it makes even less
-sense to get it to work under PREEMPT_RT while having zero users.
-
-Make memory.soft_limit_in_bytes and cgroup.event_control return
--EOPNOTSUPP on PREEMPT_RT. Make an empty memcg_check_events() and
-memcg_write_event_control() which return only -EOPNOTSUPP on PREEMPT_RT.
-Document that the two knobs are disabled on PREEMPT_RT.
-
-Suggested-by: Michal Hocko <mhocko@kernel.org>
-Suggested-by: Michal Koutný <mkoutny@suse.com>
-Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
-Acked-by: Roman Gushchin <guro@fb.com>
-Acked-by: Johannes Weiner <hannes@cmpxchg.org>
-Reviewed-by: Shakeel Butt <shakeelb@google.com>
-Acked-by: Michal Hocko <mhocko@suse.com>
----
- Documentation/admin-guide/cgroup-v1/memory.rst | 2 ++
- mm/memcontrol.c | 14 ++++++++++++--
- 2 files changed, 14 insertions(+), 2 deletions(-)
-
---- a/Documentation/admin-guide/cgroup-v1/memory.rst
-+++ b/Documentation/admin-guide/cgroup-v1/memory.rst
-@@ -64,6 +64,7 @@ Brief summary of control files.
- threads
- cgroup.procs show list of processes
- cgroup.event_control an interface for event_fd()
-+ This knob is not available on CONFIG_PREEMPT_RT systems.
- memory.usage_in_bytes show current usage for memory
- (See 5.5 for details)
- memory.memsw.usage_in_bytes show current usage for memory+Swap
-@@ -75,6 +76,7 @@ Brief summary of control files.
- memory.max_usage_in_bytes show max memory usage recorded
- memory.memsw.max_usage_in_bytes show max memory+Swap usage recorded
- memory.soft_limit_in_bytes set/show soft limit of memory usage
-+ This knob is not available on CONFIG_PREEMPT_RT systems.
- memory.stat show various statistics
- memory.use_hierarchy set/show hierarchical account enabled
- This knob is deprecated and shouldn't be
---- a/mm/memcontrol.c
-+++ b/mm/memcontrol.c
-@@ -858,6 +858,9 @@ static bool mem_cgroup_event_ratelimit(s
- */
- static void memcg_check_events(struct mem_cgroup *memcg, int nid)
- {
-+ if (IS_ENABLED(CONFIG_PREEMPT_RT))
-+ return;
-+
- /* threshold event is triggered in finer grain than soft limit */
- if (unlikely(mem_cgroup_event_ratelimit(memcg,
- MEM_CGROUP_TARGET_THRESH))) {
-@@ -3724,8 +3727,12 @@ static ssize_t mem_cgroup_write(struct k
- }
- break;
- case RES_SOFT_LIMIT:
-- memcg->soft_limit = nr_pages;
-- ret = 0;
-+ if (IS_ENABLED(CONFIG_PREEMPT_RT)) {
-+ ret = -EOPNOTSUPP;
-+ } else {
-+ memcg->soft_limit = nr_pages;
-+ ret = 0;
-+ }
- break;
- }
- return ret ?: nbytes;
-@@ -4701,6 +4708,9 @@ static ssize_t memcg_write_event_control
- char *endp;
- int ret;
-
-+ if (IS_ENABLED(CONFIG_PREEMPT_RT))
-+ return -EOPNOTSUPP;
-+
- buf = strstrip(buf);
-
- efd = simple_strtoul(buf, &endp, 10);
diff --git a/patches/0002-net-dev-Make-rps_lock-disable-interrupts.patch b/patches/0002-net-dev-Make-rps_lock-disable-interrupts.patch
deleted file mode 100644
index 311f2134985b..000000000000
--- a/patches/0002-net-dev-Make-rps_lock-disable-interrupts.patch
+++ /dev/null
@@ -1,203 +0,0 @@
-From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
-Date: Sat, 12 Feb 2022 00:38:39 +0100
-Subject: [PATCH 2/3] net: dev: Make rps_lock() disable interrupts.
-
-Disabling interrupts and in the RPS case locking input_pkt_queue is
-split into local_irq_disable() and optional spin_lock().
-
-This breaks on PREEMPT_RT because the spinlock_t typed lock can not be
-acquired with disabled interrupts.
-The sections in which the lock is acquired is usually short in a sense that it
-is not causing long und unbounded latiencies. One exception is the
-skb_flow_limit() invocation which may invoke a BPF program (and may
-require sleeping locks).
-
-By moving local_irq_disable() + spin_lock() into rps_lock(), we can keep
-interrupts disabled on !PREEMPT_RT and enabled on PREEMPT_RT kernels.
-Without RPS on a PREEMPT_RT kernel, the needed synchronisation happens
-as part of local_bh_disable() on the local CPU.
-____napi_schedule() is only invoked if sd is from the local CPU. Replace
-it with __napi_schedule_irqoff() which already disables interrupts on
-PREEMPT_RT as needed. Move this call to rps_ipi_queued() and rename the
-function to napi_schedule_rps as suggested by Jakub.
-
-Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
-Reviewed-by: Jakub Kicinski <kuba@kernel.org>
-Signed-off-by: David S. Miller <davem@davemloft.net>
-Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
----
- net/core/dev.c | 76 +++++++++++++++++++++++++++++++--------------------------
- 1 file changed, 42 insertions(+), 34 deletions(-)
-
---- a/net/core/dev.c
-+++ b/net/core/dev.c
-@@ -216,18 +216,38 @@ static inline struct hlist_head *dev_ind
- return &net->dev_index_head[ifindex & (NETDEV_HASHENTRIES - 1)];
- }
-
--static inline void rps_lock(struct softnet_data *sd)
-+static inline void rps_lock_irqsave(struct softnet_data *sd,
-+ unsigned long *flags)
- {
--#ifdef CONFIG_RPS
-- spin_lock(&sd->input_pkt_queue.lock);
--#endif
-+ if (IS_ENABLED(CONFIG_RPS))
-+ spin_lock_irqsave(&sd->input_pkt_queue.lock, *flags);
-+ else if (!IS_ENABLED(CONFIG_PREEMPT_RT))
-+ local_irq_save(*flags);
- }
-
--static inline void rps_unlock(struct softnet_data *sd)
-+static inline void rps_lock_irq_disable(struct softnet_data *sd)
- {
--#ifdef CONFIG_RPS
-- spin_unlock(&sd->input_pkt_queue.lock);
--#endif
-+ if (IS_ENABLED(CONFIG_RPS))
-+ spin_lock_irq(&sd->input_pkt_queue.lock);
-+ else if (!IS_ENABLED(CONFIG_PREEMPT_RT))
-+ local_irq_disable();
-+}
-+
-+static inline void rps_unlock_irq_restore(struct softnet_data *sd,
-+ unsigned long *flags)
-+{
-+ if (IS_ENABLED(CONFIG_RPS))
-+ spin_unlock_irqrestore(&sd->input_pkt_queue.lock, *flags);
-+ else if (!IS_ENABLED(CONFIG_PREEMPT_RT))
-+ local_irq_restore(*flags);
-+}
-+
-+static inline void rps_unlock_irq_enable(struct softnet_data *sd)
-+{
-+ if (IS_ENABLED(CONFIG_RPS))
-+ spin_unlock_irq(&sd->input_pkt_queue.lock);
-+ else if (!IS_ENABLED(CONFIG_PREEMPT_RT))
-+ local_irq_enable();
- }
-
- static struct netdev_name_node *netdev_name_node_alloc(struct net_device *dev,
-@@ -4456,11 +4476,11 @@ static void rps_trigger_softirq(void *da
- * If yes, queue it to our IPI list and return 1
- * If no, return 0
- */
--static int rps_ipi_queued(struct softnet_data *sd)
-+static int napi_schedule_rps(struct softnet_data *sd)
- {
--#ifdef CONFIG_RPS
- struct softnet_data *mysd = this_cpu_ptr(&softnet_data);
-
-+#ifdef CONFIG_RPS
- if (sd != mysd) {
- sd->rps_ipi_next = mysd->rps_ipi_list;
- mysd->rps_ipi_list = sd;
-@@ -4469,6 +4489,7 @@ static int rps_ipi_queued(struct softnet
- return 1;
- }
- #endif /* CONFIG_RPS */
-+ __napi_schedule_irqoff(&mysd->backlog);
- return 0;
- }
-
-@@ -4525,9 +4546,7 @@ static int enqueue_to_backlog(struct sk_
-
- sd = &per_cpu(softnet_data, cpu);
-
-- local_irq_save(flags);
--
-- rps_lock(sd);
-+ rps_lock_irqsave(sd, &flags);
- if (!netif_running(skb->dev))
- goto drop;
- qlen = skb_queue_len(&sd->input_pkt_queue);
-@@ -4536,26 +4555,21 @@ static int enqueue_to_backlog(struct sk_
- enqueue:
- __skb_queue_tail(&sd->input_pkt_queue, skb);
- input_queue_tail_incr_save(sd, qtail);
-- rps_unlock(sd);
-- local_irq_restore(flags);
-+ rps_unlock_irq_restore(sd, &flags);
- return NET_RX_SUCCESS;
- }
-
- /* Schedule NAPI for backlog device
- * We can use non atomic operation since we own the queue lock
- */
-- if (!__test_and_set_bit(NAPI_STATE_SCHED, &sd->backlog.state)) {
-- if (!rps_ipi_queued(sd))
-- ____napi_schedule(sd, &sd->backlog);
-- }
-+ if (!__test_and_set_bit(NAPI_STATE_SCHED, &sd->backlog.state))
-+ napi_schedule_rps(sd);
- goto enqueue;
- }
-
- drop:
- sd->dropped++;
-- rps_unlock(sd);
--
-- local_irq_restore(flags);
-+ rps_unlock_irq_restore(sd, &flags);
-
- atomic_long_inc(&skb->dev->rx_dropped);
- kfree_skb(skb);
-@@ -5647,8 +5661,7 @@ static void flush_backlog(struct work_st
- local_bh_disable();
- sd = this_cpu_ptr(&softnet_data);
-
-- local_irq_disable();
-- rps_lock(sd);
-+ rps_lock_irq_disable(sd);
- skb_queue_walk_safe(&sd->input_pkt_queue, skb, tmp) {
- if (skb->dev->reg_state == NETREG_UNREGISTERING) {
- __skb_unlink(skb, &sd->input_pkt_queue);
-@@ -5656,8 +5669,7 @@ static void flush_backlog(struct work_st
- input_queue_head_incr(sd);
- }
- }
-- rps_unlock(sd);
-- local_irq_enable();
-+ rps_unlock_irq_enable(sd);
-
- skb_queue_walk_safe(&sd->process_queue, skb, tmp) {
- if (skb->dev->reg_state == NETREG_UNREGISTERING) {
-@@ -5675,16 +5687,14 @@ static bool flush_required(int cpu)
- struct softnet_data *sd = &per_cpu(softnet_data, cpu);
- bool do_flush;
-
-- local_irq_disable();
-- rps_lock(sd);
-+ rps_lock_irq_disable(sd);
-
- /* as insertion into process_queue happens with the rps lock held,
- * process_queue access may race only with dequeue
- */
- do_flush = !skb_queue_empty(&sd->input_pkt_queue) ||
- !skb_queue_empty_lockless(&sd->process_queue);
-- rps_unlock(sd);
-- local_irq_enable();
-+ rps_unlock_irq_enable(sd);
-
- return do_flush;
- #endif
-@@ -5799,8 +5809,7 @@ static int process_backlog(struct napi_s
-
- }
-
-- local_irq_disable();
-- rps_lock(sd);
-+ rps_lock_irq_disable(sd);
- if (skb_queue_empty(&sd->input_pkt_queue)) {
- /*
- * Inline a custom version of __napi_complete().
-@@ -5816,8 +5825,7 @@ static int process_backlog(struct napi_s
- skb_queue_splice_tail_init(&sd->input_pkt_queue,
- &sd->process_queue);
- }
-- rps_unlock(sd);
-- local_irq_enable();
-+ rps_unlock_irq_enable(sd);
- }
-
- return work;
diff --git a/patches/0002-printk-cpu-sync-always-disable-interrupts.patch b/patches/0002-printk-cpu-sync-always-disable-interrupts.patch
index 5a43c7a7ff8c..79b7662a92d0 100644
--- a/patches/0002-printk-cpu-sync-always-disable-interrupts.patch
+++ b/patches/0002-printk-cpu-sync-always-disable-interrupts.patch
@@ -1,13 +1,16 @@
From: John Ogness <john.ogness@linutronix.de>
-Date: Mon, 7 Feb 2022 15:53:41 +0106
-Subject: [PATCH 02/16] printk: cpu sync always disable interrupts
+Date: Wed, 20 Apr 2022 01:52:24 +0206
+Subject: [PATCH 02/15] printk: cpu sync always disable interrupts
The CPU sync functions are a NOP for !CONFIG_SMP. But for
!CONFIG_SMP they still need to disable interrupts in order to
preserve context within the CPU sync sections.
Signed-off-by: John Ogness <john.ogness@linutronix.de>
+Reviewed-by: Petr Mladek <pmladek@suse.com>
+Reviewed-by: Sergey Senozhatsky <senozhatsky@chromium.org>
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Link: https://lore.kernel.org/r/20220419234637.357112-3-john.ogness@linutronix.de
---
include/linux/printk.h | 18 +++++++++---------
1 file changed, 9 insertions(+), 9 deletions(-)
@@ -33,7 +36,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
* @flags: Stack-allocated storage for saving local interrupt state,
* to be passed to printk_cpu_sync_put_irqrestore().
*
-@@ -310,13 +317,6 @@ extern void __printk_cpu_sync_put(void);
+@@ -322,13 +329,6 @@ extern void __printk_cpu_sync_put(void);
local_irq_restore(flags); \
} while (0)
diff --git a/patches/0002-random-remove-batched-entropy-locking.patch b/patches/0002-random-remove-batched-entropy-locking.patch
deleted file mode 100644
index 231e71d04f13..000000000000
--- a/patches/0002-random-remove-batched-entropy-locking.patch
+++ /dev/null
@@ -1,150 +0,0 @@
-From: "Jason A. Donenfeld" <Jason@zx2c4.com>
-Date: Fri, 28 Jan 2022 23:29:45 +0100
-Subject: [PATCH 2/5] random: remove batched entropy locking
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-Rather than use spinlocks to protect batched entropy, we can instead
-disable interrupts locally, since we're dealing with per-cpu data, and
-manage resets with a basic generation counter. At the same time, we
-can't quite do this on PREEMPT_RT, where we still want spinlocks-as-
-mutexes semantics. So we use a local_lock_t, which provides the right
-behavior for each. Because this is a per-cpu lock, that generation
-counter is still doing the necessary CPU-to-CPU communication.
-
-This should improve performance a bit. It will also fix the linked splat
-that Jonathan received with a PROVE_RAW_LOCK_NESTING=y.
-
-Reviewed-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
-Reviewed-by: Dominik Brodowski <linux@dominikbrodowski.net>
-Suggested-by: Andy Lutomirski <luto@kernel.org>
-Reported-by: Jonathan Neuschäfer <j.neuschaefer@gmx.net>
-Tested-by: Jonathan Neuschäfer <j.neuschaefer@gmx.net>
-Link: https://lore.kernel.org/lkml/YfMa0QgsjCVdRAvJ@latitude/
-Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
-Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
----
- drivers/char/random.c | 55 +++++++++++++++++++++++++-------------------------
- 1 file changed, 28 insertions(+), 27 deletions(-)
-
---- a/drivers/char/random.c
-+++ b/drivers/char/random.c
-@@ -1876,13 +1876,16 @@ static int __init random_sysctls_init(vo
- device_initcall(random_sysctls_init);
- #endif /* CONFIG_SYSCTL */
-
-+static atomic_t batch_generation = ATOMIC_INIT(0);
-+
- struct batched_entropy {
- union {
- u64 entropy_u64[CHACHA_BLOCK_SIZE / sizeof(u64)];
- u32 entropy_u32[CHACHA_BLOCK_SIZE / sizeof(u32)];
- };
-+ local_lock_t lock;
- unsigned int position;
-- spinlock_t batch_lock;
-+ int generation;
- };
-
- /*
-@@ -1894,7 +1897,7 @@ struct batched_entropy {
- * point prior.
- */
- static DEFINE_PER_CPU(struct batched_entropy, batched_entropy_u64) = {
-- .batch_lock = __SPIN_LOCK_UNLOCKED(batched_entropy_u64.lock),
-+ .lock = INIT_LOCAL_LOCK(batched_entropy_u64.lock)
- };
-
- u64 get_random_u64(void)
-@@ -1903,67 +1906,65 @@ u64 get_random_u64(void)
- unsigned long flags;
- struct batched_entropy *batch;
- static void *previous;
-+ int next_gen;
-
- warn_unseeded_randomness(&previous);
-
-+ local_lock_irqsave(&batched_entropy_u64.lock, flags);
- batch = raw_cpu_ptr(&batched_entropy_u64);
-- spin_lock_irqsave(&batch->batch_lock, flags);
-- if (batch->position % ARRAY_SIZE(batch->entropy_u64) == 0) {
-+
-+ next_gen = atomic_read(&batch_generation);
-+ if (batch->position % ARRAY_SIZE(batch->entropy_u64) == 0 ||
-+ next_gen != batch->generation) {
- extract_crng((u8 *)batch->entropy_u64);
- batch->position = 0;
-+ batch->generation = next_gen;
- }
-+
- ret = batch->entropy_u64[batch->position++];
-- spin_unlock_irqrestore(&batch->batch_lock, flags);
-+ local_unlock_irqrestore(&batched_entropy_u64.lock, flags);
- return ret;
- }
- EXPORT_SYMBOL(get_random_u64);
-
- static DEFINE_PER_CPU(struct batched_entropy, batched_entropy_u32) = {
-- .batch_lock = __SPIN_LOCK_UNLOCKED(batched_entropy_u32.lock),
-+ .lock = INIT_LOCAL_LOCK(batched_entropy_u32.lock)
- };
-+
- u32 get_random_u32(void)
- {
- u32 ret;
- unsigned long flags;
- struct batched_entropy *batch;
- static void *previous;
-+ int next_gen;
-
- warn_unseeded_randomness(&previous);
-
-+ local_lock_irqsave(&batched_entropy_u32.lock, flags);
- batch = raw_cpu_ptr(&batched_entropy_u32);
-- spin_lock_irqsave(&batch->batch_lock, flags);
-- if (batch->position % ARRAY_SIZE(batch->entropy_u32) == 0) {
-+
-+ next_gen = atomic_read(&batch_generation);
-+ if (batch->position % ARRAY_SIZE(batch->entropy_u32) == 0 ||
-+ next_gen != batch->generation) {
- extract_crng((u8 *)batch->entropy_u32);
- batch->position = 0;
-+ batch->generation = next_gen;
- }
-+
- ret = batch->entropy_u32[batch->position++];
-- spin_unlock_irqrestore(&batch->batch_lock, flags);
-+ local_unlock_irqrestore(&batched_entropy_u32.lock, flags);
- return ret;
- }
- EXPORT_SYMBOL(get_random_u32);
-
- /* It's important to invalidate all potential batched entropy that might
- * be stored before the crng is initialized, which we can do lazily by
-- * simply resetting the counter to zero so that it's re-extracted on the
-- * next usage. */
-+ * bumping the generation counter.
-+ */
- static void invalidate_batched_entropy(void)
- {
-- int cpu;
-- unsigned long flags;
--
-- for_each_possible_cpu(cpu) {
-- struct batched_entropy *batched_entropy;
--
-- batched_entropy = per_cpu_ptr(&batched_entropy_u32, cpu);
-- spin_lock_irqsave(&batched_entropy->batch_lock, flags);
-- batched_entropy->position = 0;
-- spin_unlock(&batched_entropy->batch_lock);
--
-- batched_entropy = per_cpu_ptr(&batched_entropy_u64, cpu);
-- spin_lock(&batched_entropy->batch_lock);
-- batched_entropy->position = 0;
-- spin_unlock_irqrestore(&batched_entropy->batch_lock, flags);
-- }
-+ atomic_inc(&batch_generation);
- }
-
- /**
diff --git a/patches/0002-serial-8250-implement-write_atomic.patch b/patches/0002-serial-8250-implement-write_atomic.patch
new file mode 100644
index 000000000000..5d89cfe3b30b
--- /dev/null
+++ b/patches/0002-serial-8250-implement-write_atomic.patch
@@ -0,0 +1,927 @@
+From: John Ogness <john.ogness@linutronix.de>
+Date: Fri, 4 Feb 2022 16:01:17 +0106
+Subject: [PATCH 2/3] serial: 8250: implement write_atomic
+
+Implement a non-sleeping NMI-safe write_atomic() console function in
+order to support atomic console printing during a panic.
+
+Trasmitting data requires disabling interrupts. Since write_atomic()
+can be called from any context, it may be called while another CPU
+is executing in console code. In order to maintain the correct state
+of the IER register, use the global cpu_sync to synchronize all
+access to the IER register. This synchronization is only necessary
+for serial ports that are being used as consoles.
+
+The global cpu_sync is also used to synchronize between the write()
+and write_atomic() callbacks. write() synchronizes per character,
+write_atomic() synchronizes per line.
+
+Signed-off-by: John Ogness <john.ogness@linutronix.de>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+---
+ drivers/tty/serial/8250/8250.h | 66 +++++++++++-
+ drivers/tty/serial/8250/8250_aspeed_vuart.c | 2
+ drivers/tty/serial/8250/8250_bcm7271.c | 21 +++
+ drivers/tty/serial/8250/8250_core.c | 24 ++++
+ drivers/tty/serial/8250/8250_exar.c | 4
+ drivers/tty/serial/8250/8250_fsl.c | 3
+ drivers/tty/serial/8250/8250_ingenic.c | 3
+ drivers/tty/serial/8250/8250_mtk.c | 32 +++++
+ drivers/tty/serial/8250/8250_omap.c | 20 +--
+ drivers/tty/serial/8250/8250_port.c | 152 +++++++++++++++++++---------
+ drivers/tty/serial/8250/Kconfig | 1
+ include/linux/serial_8250.h | 5
+ 12 files changed, 268 insertions(+), 65 deletions(-)
+
+--- a/drivers/tty/serial/8250/8250.h
++++ b/drivers/tty/serial/8250/8250.h
+@@ -132,12 +132,74 @@ static inline void serial_dl_write(struc
+ up->dl_write(up, value);
+ }
+
++static inline int serial8250_in_IER(struct uart_8250_port *up)
++{
++ struct uart_port *port = &up->port;
++ unsigned long flags;
++ bool is_console;
++ int ier;
++
++ is_console = uart_console(port);
++
++ if (is_console)
++ printk_cpu_sync_get_irqsave(flags);
++
++ ier = serial_in(up, UART_IER);
++
++ if (is_console)
++ printk_cpu_sync_put_irqrestore(flags);
++
++ return ier;
++}
++
++static inline void serial8250_set_IER(struct uart_8250_port *up, int ier)
++{
++ struct uart_port *port = &up->port;
++ unsigned long flags;
++ bool is_console;
++
++ is_console = uart_console(port);
++
++ if (is_console)
++ printk_cpu_sync_get_irqsave(flags);
++
++ serial_out(up, UART_IER, ier);
++
++ if (is_console)
++ printk_cpu_sync_put_irqrestore(flags);
++}
++
++static inline int serial8250_clear_IER(struct uart_8250_port *up)
++{
++ struct uart_port *port = &up->port;
++ unsigned int clearval = 0;
++ unsigned long flags;
++ bool is_console;
++ int prior;
++
++ is_console = uart_console(port);
++
++ if (up->capabilities & UART_CAP_UUE)
++ clearval = UART_IER_UUE;
++
++ if (is_console)
++ printk_cpu_sync_get_irqsave(flags);
++
++ prior = serial_in(up, UART_IER);
++ serial_out(up, UART_IER, clearval);
++
++ if (is_console)
++ printk_cpu_sync_put_irqrestore(flags);
++
++ return prior;
++}
++
+ static inline bool serial8250_set_THRI(struct uart_8250_port *up)
+ {
+ if (up->ier & UART_IER_THRI)
+ return false;
+ up->ier |= UART_IER_THRI;
+- serial_out(up, UART_IER, up->ier);
++ serial8250_set_IER(up, up->ier);
+ return true;
+ }
+
+@@ -146,7 +208,7 @@ static inline bool serial8250_clear_THRI
+ if (!(up->ier & UART_IER_THRI))
+ return false;
+ up->ier &= ~UART_IER_THRI;
+- serial_out(up, UART_IER, up->ier);
++ serial8250_set_IER(up, up->ier);
+ return true;
+ }
+
+--- a/drivers/tty/serial/8250/8250_aspeed_vuart.c
++++ b/drivers/tty/serial/8250/8250_aspeed_vuart.c
+@@ -278,7 +278,7 @@ static void __aspeed_vuart_set_throttle(
+ up->ier &= ~irqs;
+ if (!throttle)
+ up->ier |= irqs;
+- serial_out(up, UART_IER, up->ier);
++ serial8250_set_IER(up, up->ier);
+ }
+ static void aspeed_vuart_set_throttle(struct uart_port *port, bool throttle)
+ {
+--- a/drivers/tty/serial/8250/8250_bcm7271.c
++++ b/drivers/tty/serial/8250/8250_bcm7271.c
+@@ -609,7 +609,7 @@ static int brcmuart_startup(struct uart_
+ * will handle this.
+ */
+ up->ier &= ~UART_IER_RDI;
+- serial_port_out(port, UART_IER, up->ier);
++ serial8250_set_IER(up, up->ier);
+
+ priv->tx_running = false;
+ priv->dma.rx_dma = NULL;
+@@ -775,10 +775,12 @@ static int brcmuart_handle_irq(struct ua
+ unsigned int iir = serial_port_in(p, UART_IIR);
+ struct brcmuart_priv *priv = p->private_data;
+ struct uart_8250_port *up = up_to_u8250p(p);
++ unsigned long cs_flags;
+ unsigned int status;
+ unsigned long flags;
+ unsigned int ier;
+ unsigned int mcr;
++ bool is_console;
+ int handled = 0;
+
+ /*
+@@ -789,6 +791,10 @@ static int brcmuart_handle_irq(struct ua
+ spin_lock_irqsave(&p->lock, flags);
+ status = serial_port_in(p, UART_LSR);
+ if ((status & UART_LSR_DR) == 0) {
++ is_console = uart_console(p);
++
++ if (is_console)
++ printk_cpu_sync_get_irqsave(cs_flags);
+
+ ier = serial_port_in(p, UART_IER);
+ /*
+@@ -809,6 +815,9 @@ static int brcmuart_handle_irq(struct ua
+ serial_port_in(p, UART_RX);
+ }
+
++ if (is_console)
++ printk_cpu_sync_put_irqrestore(cs_flags);
++
+ handled = 1;
+ }
+ spin_unlock_irqrestore(&p->lock, flags);
+@@ -823,8 +832,10 @@ static enum hrtimer_restart brcmuart_hrt
+ struct brcmuart_priv *priv = container_of(t, struct brcmuart_priv, hrt);
+ struct uart_port *p = priv->up;
+ struct uart_8250_port *up = up_to_u8250p(p);
++ unsigned long cs_flags;
+ unsigned int status;
+ unsigned long flags;
++ bool is_console;
+
+ if (priv->shutdown)
+ return HRTIMER_NORESTART;
+@@ -846,12 +857,20 @@ static enum hrtimer_restart brcmuart_hrt
+ /* re-enable receive unless upper layer has disabled it */
+ if ((up->ier & (UART_IER_RLSI | UART_IER_RDI)) ==
+ (UART_IER_RLSI | UART_IER_RDI)) {
++ is_console = uart_console(p);
++
++ if (is_console)
++ printk_cpu_sync_get_irqsave(cs_flags);
++
+ status = serial_port_in(p, UART_IER);
+ status |= (UART_IER_RLSI | UART_IER_RDI);
+ serial_port_out(p, UART_IER, status);
+ status = serial_port_in(p, UART_MCR);
+ status |= UART_MCR_RTS;
+ serial_port_out(p, UART_MCR, status);
++
++ if (is_console)
++ printk_cpu_sync_put_irqrestore(cs_flags);
+ }
+ spin_unlock_irqrestore(&p->lock, flags);
+ return HRTIMER_NORESTART;
+--- a/drivers/tty/serial/8250/8250_core.c
++++ b/drivers/tty/serial/8250/8250_core.c
+@@ -255,8 +255,11 @@ static void serial8250_timeout(struct ti
+ static void serial8250_backup_timeout(struct timer_list *t)
+ {
+ struct uart_8250_port *up = from_timer(up, t, timer);
++ struct uart_port *port = &up->port;
+ unsigned int iir, ier = 0, lsr;
++ unsigned long cs_flags;
+ unsigned long flags;
++ bool is_console;
+
+ spin_lock_irqsave(&up->port.lock, flags);
+
+@@ -265,8 +268,16 @@ static void serial8250_backup_timeout(st
+ * based handler.
+ */
+ if (up->port.irq) {
++ is_console = uart_console(port);
++
++ if (is_console)
++ printk_cpu_sync_get_irqsave(cs_flags);
++
+ ier = serial_in(up, UART_IER);
+ serial_out(up, UART_IER, 0);
++
++ if (is_console)
++ printk_cpu_sync_put_irqrestore(cs_flags);
+ }
+
+ iir = serial_in(up, UART_IIR);
+@@ -290,7 +301,7 @@ static void serial8250_backup_timeout(st
+ serial8250_tx_chars(up);
+
+ if (up->port.irq)
+- serial_out(up, UART_IER, ier);
++ serial8250_set_IER(up, ier);
+
+ spin_unlock_irqrestore(&up->port.lock, flags);
+
+@@ -567,6 +578,14 @@ serial8250_register_ports(struct uart_dr
+
+ #ifdef CONFIG_SERIAL_8250_CONSOLE
+
++static void univ8250_console_write_atomic(struct console *co, const char *s,
++ unsigned int count)
++{
++ struct uart_8250_port *up = &serial8250_ports[co->index];
++
++ serial8250_console_write_atomic(up, s, count);
++}
++
+ static void univ8250_console_write(struct console *co, const char *s,
+ unsigned int count)
+ {
+@@ -660,6 +679,7 @@ static int univ8250_console_match(struct
+
+ static struct console univ8250_console = {
+ .name = "ttyS",
++ .write_atomic = univ8250_console_write_atomic,
+ .write = univ8250_console_write,
+ .device = uart_console_device,
+ .setup = univ8250_console_setup,
+@@ -953,7 +973,7 @@ static void serial_8250_overrun_backoff_
+ spin_lock_irqsave(&port->lock, flags);
+ up->ier |= UART_IER_RLSI | UART_IER_RDI;
+ up->port.read_status_mask |= UART_LSR_DR;
+- serial_out(up, UART_IER, up->ier);
++ serial8250_set_IER(up, up->ier);
+ spin_unlock_irqrestore(&port->lock, flags);
+ }
+
+--- a/drivers/tty/serial/8250/8250_exar.c
++++ b/drivers/tty/serial/8250/8250_exar.c
+@@ -177,6 +177,8 @@ static void xr17v35x_set_divisor(struct
+
+ static int xr17v35x_startup(struct uart_port *port)
+ {
++ struct uart_8250_port *up = up_to_u8250p(port);
++
+ /*
+ * First enable access to IER [7:5], ISR [5:4], FCR [5:4],
+ * MCR [7:5] and MSR [7:0]
+@@ -187,7 +189,7 @@ static int xr17v35x_startup(struct uart_
+ * Make sure all interrups are masked until initialization is
+ * complete and the FIFOs are cleared
+ */
+- serial_port_out(port, UART_IER, 0);
++ serial8250_set_IER(up, 0);
+
+ return serial8250_do_startup(port);
+ }
+--- a/drivers/tty/serial/8250/8250_fsl.c
++++ b/drivers/tty/serial/8250/8250_fsl.c
+@@ -58,7 +58,8 @@ int fsl8250_handle_irq(struct uart_port
+ if ((orig_lsr & UART_LSR_OE) && (up->overrun_backoff_time_ms > 0)) {
+ unsigned long delay;
+
+- up->ier = port->serial_in(port, UART_IER);
++ up->ier = serial8250_in_IER(up);
++
+ if (up->ier & (UART_IER_RLSI | UART_IER_RDI)) {
+ port->ops->stop_rx(port);
+ } else {
+--- a/drivers/tty/serial/8250/8250_ingenic.c
++++ b/drivers/tty/serial/8250/8250_ingenic.c
+@@ -146,6 +146,7 @@ OF_EARLYCON_DECLARE(x1000_uart, "ingenic
+
+ static void ingenic_uart_serial_out(struct uart_port *p, int offset, int value)
+ {
++ struct uart_8250_port *up = up_to_u8250p(p);
+ int ier;
+
+ switch (offset) {
+@@ -167,7 +168,7 @@ static void ingenic_uart_serial_out(stru
+ * If we have enabled modem status IRQs we should enable
+ * modem mode.
+ */
+- ier = p->serial_in(p, UART_IER);
++ ier = serial8250_in_IER(up);
+
+ if (ier & UART_IER_MSI)
+ value |= UART_MCR_MDCE | UART_MCR_FCM;
+--- a/drivers/tty/serial/8250/8250_mtk.c
++++ b/drivers/tty/serial/8250/8250_mtk.c
+@@ -218,12 +218,40 @@ static void mtk8250_shutdown(struct uart
+
+ static void mtk8250_disable_intrs(struct uart_8250_port *up, int mask)
+ {
+- serial_out(up, UART_IER, serial_in(up, UART_IER) & (~mask));
++ struct uart_port *port = &up->port;
++ unsigned long flags;
++ bool is_console;
++ int ier;
++
++ is_console = uart_console(port);
++
++ if (is_console)
++ printk_cpu_sync_get_irqsave(flags);
++
++ ier = serial_in(up, UART_IER);
++ serial_out(up, UART_IER, ier & (~mask));
++
++ if (is_console)
++ printk_cpu_sync_put_irqrestore(flags);
+ }
+
+ static void mtk8250_enable_intrs(struct uart_8250_port *up, int mask)
+ {
+- serial_out(up, UART_IER, serial_in(up, UART_IER) | mask);
++ struct uart_port *port = &up->port;
++ unsigned long flags;
++ bool is_console;
++ int ier;
++
++ is_console = uart_console(port);
++
++ if (is_console)
++ printk_cpu_sync_get_irqsave(flags);
++
++ ier = serial_in(up, UART_IER);
++ serial_out(up, UART_IER, ier | mask);
++
++ if (is_console)
++ printk_cpu_sync_put_irqrestore(flags);
+ }
+
+ static void mtk8250_set_flow_ctrl(struct uart_8250_port *up, int mode)
+--- a/drivers/tty/serial/8250/8250_omap.c
++++ b/drivers/tty/serial/8250/8250_omap.c
+@@ -325,7 +325,7 @@ static void omap8250_restore_regs(struct
+
+ /* drop TCR + TLR access, we setup XON/XOFF later */
+ serial8250_out_MCR(up, up->mcr);
+- serial_out(up, UART_IER, up->ier);
++ serial8250_set_IER(up, up->ier);
+
+ serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
+ serial_dl_write(up, priv->quot);
+@@ -512,7 +512,7 @@ static void omap_8250_pm(struct uart_por
+ serial_out(up, UART_EFR, efr | UART_EFR_ECB);
+ serial_out(up, UART_LCR, 0);
+
+- serial_out(up, UART_IER, (state != 0) ? UART_IERX_SLEEP : 0);
++ serial8250_set_IER(up, (state != 0) ? UART_IERX_SLEEP : 0);
+ serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
+ serial_out(up, UART_EFR, efr);
+ serial_out(up, UART_LCR, 0);
+@@ -633,7 +633,7 @@ static irqreturn_t omap8250_irq(int irq,
+ if ((lsr & UART_LSR_OE) && up->overrun_backoff_time_ms > 0) {
+ unsigned long delay;
+
+- up->ier = port->serial_in(port, UART_IER);
++ up->ier = serial8250_in_IER(up);
+ if (up->ier & (UART_IER_RLSI | UART_IER_RDI)) {
+ port->ops->stop_rx(port);
+ } else {
+@@ -693,7 +693,7 @@ static int omap_8250_startup(struct uart
+ goto err;
+
+ up->ier = UART_IER_RLSI | UART_IER_RDI;
+- serial_out(up, UART_IER, up->ier);
++ serial8250_set_IER(up, up->ier);
+
+ #ifdef CONFIG_PM
+ up->capabilities |= UART_CAP_RPM;
+@@ -734,7 +734,7 @@ static void omap_8250_shutdown(struct ua
+ serial_out(up, UART_OMAP_EFR2, 0x0);
+
+ up->ier = 0;
+- serial_out(up, UART_IER, 0);
++ serial8250_set_IER(up, 0);
+
+ if (up->dma)
+ serial8250_release_dma(up);
+@@ -782,7 +782,7 @@ static void omap_8250_unthrottle(struct
+ up->dma->rx_dma(up);
+ up->ier |= UART_IER_RLSI | UART_IER_RDI;
+ port->read_status_mask |= UART_LSR_DR;
+- serial_out(up, UART_IER, up->ier);
++ serial8250_set_IER(up, up->ier);
+ spin_unlock_irqrestore(&port->lock, flags);
+
+ pm_runtime_mark_last_busy(port->dev);
+@@ -873,7 +873,7 @@ static void __dma_rx_complete(void *para
+ __dma_rx_do_complete(p);
+ if (!priv->throttled) {
+ p->ier |= UART_IER_RLSI | UART_IER_RDI;
+- serial_out(p, UART_IER, p->ier);
++ serial8250_set_IER(p, p->ier);
+ if (!(priv->habit & UART_HAS_EFR2))
+ omap_8250_rx_dma(p);
+ }
+@@ -930,7 +930,7 @@ static int omap_8250_rx_dma(struct uart_
+ * callback to run.
+ */
+ p->ier &= ~(UART_IER_RLSI | UART_IER_RDI);
+- serial_out(p, UART_IER, p->ier);
++ serial8250_set_IER(p, p->ier);
+ }
+ goto out;
+ }
+@@ -1146,12 +1146,12 @@ static void am654_8250_handle_rx_dma(str
+ * periodic timeouts, re-enable interrupts.
+ */
+ up->ier &= ~(UART_IER_RLSI | UART_IER_RDI);
+- serial_out(up, UART_IER, up->ier);
++ serial8250_set_IER(up, up->ier);
+ omap_8250_rx_dma_flush(up);
+ serial_in(up, UART_IIR);
+ serial_out(up, UART_OMAP_EFR2, 0x0);
+ up->ier |= UART_IER_RLSI | UART_IER_RDI;
+- serial_out(up, UART_IER, up->ier);
++ serial8250_set_IER(up, up->ier);
+ }
+ }
+
+--- a/drivers/tty/serial/8250/8250_port.c
++++ b/drivers/tty/serial/8250/8250_port.c
+@@ -770,7 +770,7 @@ static void serial8250_set_sleep(struct
+ serial_out(p, UART_EFR, UART_EFR_ECB);
+ serial_out(p, UART_LCR, 0);
+ }
+- serial_out(p, UART_IER, sleep ? UART_IERX_SLEEP : 0);
++ serial8250_set_IER(p, sleep ? UART_IERX_SLEEP : 0);
+ if (p->capabilities & UART_CAP_EFR) {
+ serial_out(p, UART_LCR, UART_LCR_CONF_MODE_B);
+ serial_out(p, UART_EFR, efr);
+@@ -1044,8 +1044,11 @@ static int broken_efr(struct uart_8250_p
+ */
+ static void autoconfig_16550a(struct uart_8250_port *up)
+ {
++ struct uart_port *port = &up->port;
+ unsigned char status1, status2;
+ unsigned int iersave;
++ unsigned long flags;
++ bool is_console;
+
+ up->port.type = PORT_16550A;
+ up->capabilities |= UART_CAP_FIFO;
+@@ -1156,6 +1159,11 @@ static void autoconfig_16550a(struct uar
+ return;
+ }
+
++ is_console = uart_console(port);
++
++ if (is_console)
++ printk_cpu_sync_get_irqsave(flags);
++
+ /*
+ * Try writing and reading the UART_IER_UUE bit (b6).
+ * If it works, this is probably one of the Xscale platform's
+@@ -1191,6 +1199,9 @@ static void autoconfig_16550a(struct uar
+ }
+ serial_out(up, UART_IER, iersave);
+
++ if (is_console)
++ printk_cpu_sync_put_irqrestore(flags);
++
+ /*
+ * We distinguish between 16550A and U6 16550A by counting
+ * how many bytes are in the FIFO.
+@@ -1215,6 +1226,7 @@ static void autoconfig(struct uart_8250_
+ struct uart_port *port = &up->port;
+ unsigned long flags;
+ unsigned int old_capabilities;
++ bool is_console;
+
+ if (!port->iobase && !port->mapbase && !port->membase)
+ return;
+@@ -1232,6 +1244,13 @@ static void autoconfig(struct uart_8250_
+ up->bugs = 0;
+
+ if (!(port->flags & UPF_BUGGY_UART)) {
++ unsigned long cs_flags;
++
++ is_console = uart_console(port);
++
++ if (is_console)
++ printk_cpu_sync_get_irqsave(cs_flags);
++
+ /*
+ * Do a simple existence test first; if we fail this,
+ * there's no point trying anything else.
+@@ -1261,6 +1280,10 @@ static void autoconfig(struct uart_8250_
+ #endif
+ scratch3 = serial_in(up, UART_IER) & 0x0f;
+ serial_out(up, UART_IER, scratch);
++
++ if (is_console)
++ printk_cpu_sync_put_irqrestore(cs_flags);
++
+ if (scratch2 != 0 || scratch3 != 0x0F) {
+ /*
+ * We failed; there's nothing here
+@@ -1358,10 +1381,7 @@ static void autoconfig(struct uart_8250_
+ serial8250_out_MCR(up, save_mcr);
+ serial8250_clear_fifos(up);
+ serial_in(up, UART_RX);
+- if (up->capabilities & UART_CAP_UUE)
+- serial_out(up, UART_IER, UART_IER_UUE);
+- else
+- serial_out(up, UART_IER, 0);
++ serial8250_clear_IER(up);
+
+ out_unlock:
+ spin_unlock_irqrestore(&port->lock, flags);
+@@ -1387,7 +1407,9 @@ static void autoconfig_irq(struct uart_8
+ unsigned char save_mcr, save_ier;
+ unsigned char save_ICP = 0;
+ unsigned int ICP = 0;
++ unsigned long flags;
+ unsigned long irqs;
++ bool is_console;
+ int irq;
+
+ if (port->flags & UPF_FOURPORT) {
+@@ -1397,8 +1419,12 @@ static void autoconfig_irq(struct uart_8
+ inb_p(ICP);
+ }
+
+- if (uart_console(port))
++ is_console = uart_console(port);
++
++ if (is_console) {
+ console_lock();
++ printk_cpu_sync_get_irqsave(flags);
++ }
+
+ /* forget possible initially masked and pending IRQ */
+ probe_irq_off(probe_irq_on());
+@@ -1430,8 +1456,10 @@ static void autoconfig_irq(struct uart_8
+ if (port->flags & UPF_FOURPORT)
+ outb_p(save_ICP, ICP);
+
+- if (uart_console(port))
++ if (is_console) {
++ printk_cpu_sync_put_irqrestore(flags);
+ console_unlock();
++ }
+
+ port->irq = (irq > 0) ? irq : 0;
+ }
+@@ -1444,7 +1472,7 @@ static void serial8250_stop_rx(struct ua
+
+ up->ier &= ~(UART_IER_RLSI | UART_IER_RDI);
+ up->port.read_status_mask &= ~UART_LSR_DR;
+- serial_port_out(port, UART_IER, up->ier);
++ serial8250_set_IER(up, up->ier);
+
+ serial8250_rpm_put(up);
+ }
+@@ -1474,7 +1502,7 @@ void serial8250_em485_stop_tx(struct uar
+ serial8250_clear_and_reinit_fifos(p);
+
+ p->ier |= UART_IER_RLSI | UART_IER_RDI;
+- serial_port_out(&p->port, UART_IER, p->ier);
++ serial8250_set_IER(p, p->ier);
+ }
+ }
+ EXPORT_SYMBOL_GPL(serial8250_em485_stop_tx);
+@@ -1711,7 +1739,7 @@ static void serial8250_disable_ms(struct
+ mctrl_gpio_disable_ms(up->gpios);
+
+ up->ier &= ~UART_IER_MSI;
+- serial_port_out(port, UART_IER, up->ier);
++ serial8250_set_IER(up, up->ier);
+ }
+
+ static void serial8250_enable_ms(struct uart_port *port)
+@@ -1727,7 +1755,7 @@ static void serial8250_enable_ms(struct
+ up->ier |= UART_IER_MSI;
+
+ serial8250_rpm_get(up);
+- serial_port_out(port, UART_IER, up->ier);
++ serial8250_set_IER(up, up->ier);
+ serial8250_rpm_put(up);
+ }
+
+@@ -2146,14 +2174,7 @@ static void serial8250_put_poll_char(str
+ struct uart_8250_port *up = up_to_u8250p(port);
+
+ serial8250_rpm_get(up);
+- /*
+- * First save the IER then disable the interrupts
+- */
+- ier = serial_port_in(port, UART_IER);
+- if (up->capabilities & UART_CAP_UUE)
+- serial_port_out(port, UART_IER, UART_IER_UUE);
+- else
+- serial_port_out(port, UART_IER, 0);
++ ier = serial8250_clear_IER(up);
+
+ wait_for_xmitr(up, BOTH_EMPTY);
+ /*
+@@ -2166,7 +2187,7 @@ static void serial8250_put_poll_char(str
+ * and restore the IER
+ */
+ wait_for_xmitr(up, BOTH_EMPTY);
+- serial_port_out(port, UART_IER, ier);
++ serial8250_set_IER(up, ier);
+ serial8250_rpm_put(up);
+ }
+
+@@ -2175,8 +2196,10 @@ static void serial8250_put_poll_char(str
+ int serial8250_do_startup(struct uart_port *port)
+ {
+ struct uart_8250_port *up = up_to_u8250p(port);
++ unsigned long cs_flags;
+ unsigned long flags;
+ unsigned char lsr, iir;
++ bool is_console;
+ int retval;
+
+ if (!port->fifosize)
+@@ -2196,7 +2219,7 @@ int serial8250_do_startup(struct uart_po
+ up->acr = 0;
+ serial_port_out(port, UART_LCR, UART_LCR_CONF_MODE_B);
+ serial_port_out(port, UART_EFR, UART_EFR_ECB);
+- serial_port_out(port, UART_IER, 0);
++ serial8250_set_IER(up, 0);
+ serial_port_out(port, UART_LCR, 0);
+ serial_icr_write(up, UART_CSR, 0); /* Reset the UART */
+ serial_port_out(port, UART_LCR, UART_LCR_CONF_MODE_B);
+@@ -2206,7 +2229,7 @@ int serial8250_do_startup(struct uart_po
+
+ if (port->type == PORT_DA830) {
+ /* Reset the port */
+- serial_port_out(port, UART_IER, 0);
++ serial8250_set_IER(up, 0);
+ serial_port_out(port, UART_DA830_PWREMU_MGMT, 0);
+ mdelay(10);
+
+@@ -2301,6 +2324,8 @@ int serial8250_do_startup(struct uart_po
+ if (port->irq && (up->port.flags & UPF_SHARE_IRQ))
+ up->port.irqflags |= IRQF_SHARED;
+
++ is_console = uart_console(port);
++
+ if (port->irq && !(up->port.flags & UPF_NO_THRE_TEST)) {
+ unsigned char iir1;
+
+@@ -2317,6 +2342,9 @@ int serial8250_do_startup(struct uart_po
+ */
+ spin_lock_irqsave(&port->lock, flags);
+
++ if (is_console)
++ printk_cpu_sync_get_irqsave(cs_flags);
++
+ wait_for_xmitr(up, UART_LSR_THRE);
+ serial_port_out_sync(port, UART_IER, UART_IER_THRI);
+ udelay(1); /* allow THRE to set */
+@@ -2327,6 +2355,9 @@ int serial8250_do_startup(struct uart_po
+ iir = serial_port_in(port, UART_IIR);
+ serial_port_out(port, UART_IER, 0);
+
++ if (is_console)
++ printk_cpu_sync_put_irqrestore(cs_flags);
++
+ spin_unlock_irqrestore(&port->lock, flags);
+
+ if (port->irqflags & IRQF_SHARED)
+@@ -2383,10 +2414,14 @@ int serial8250_do_startup(struct uart_po
+ * Do a quick test to see if we receive an interrupt when we enable
+ * the TX irq.
+ */
++ if (is_console)
++ printk_cpu_sync_get_irqsave(cs_flags);
+ serial_port_out(port, UART_IER, UART_IER_THRI);
+ lsr = serial_port_in(port, UART_LSR);
+ iir = serial_port_in(port, UART_IIR);
+ serial_port_out(port, UART_IER, 0);
++ if (is_console)
++ printk_cpu_sync_put_irqrestore(cs_flags);
+
+ if (lsr & UART_LSR_TEMT && iir & UART_IIR_NO_INT) {
+ if (!(up->bugs & UART_BUG_TXEN)) {
+@@ -2418,7 +2453,7 @@ int serial8250_do_startup(struct uart_po
+ if (up->dma) {
+ const char *msg = NULL;
+
+- if (uart_console(port))
++ if (is_console)
+ msg = "forbid DMA for kernel console";
+ else if (serial8250_request_dma(up))
+ msg = "failed to request DMA";
+@@ -2469,7 +2504,7 @@ void serial8250_do_shutdown(struct uart_
+ */
+ spin_lock_irqsave(&port->lock, flags);
+ up->ier = 0;
+- serial_port_out(port, UART_IER, 0);
++ serial8250_set_IER(up, 0);
+ spin_unlock_irqrestore(&port->lock, flags);
+
+ synchronize_irq(port->irq);
+@@ -2837,7 +2872,7 @@ serial8250_do_set_termios(struct uart_po
+ if (up->capabilities & UART_CAP_RTOIE)
+ up->ier |= UART_IER_RTOIE;
+
+- serial_port_out(port, UART_IER, up->ier);
++ serial8250_set_IER(up, up->ier);
+
+ if (up->capabilities & UART_CAP_EFR) {
+ unsigned char efr = 0;
+@@ -3303,7 +3338,7 @@ EXPORT_SYMBOL_GPL(serial8250_set_default
+
+ #ifdef CONFIG_SERIAL_8250_CONSOLE
+
+-static void serial8250_console_putchar(struct uart_port *port, unsigned char ch)
++static void serial8250_console_putchar_locked(struct uart_port *port, unsigned char ch)
+ {
+ struct uart_8250_port *up = up_to_u8250p(port);
+
+@@ -3311,6 +3346,18 @@ static void serial8250_console_putchar(s
+ serial_port_out(port, UART_TX, ch);
+ }
+
++static void serial8250_console_putchar(struct uart_port *port, unsigned char ch)
++{
++ struct uart_8250_port *up = up_to_u8250p(port);
++ unsigned long flags;
++
++ wait_for_xmitr(up, UART_LSR_THRE);
++
++ printk_cpu_sync_get_irqsave(flags);
++ serial8250_console_putchar_locked(port, ch);
++ printk_cpu_sync_put_irqrestore(flags);
++}
++
+ /*
+ * Restore serial console when h/w power-off detected
+ */
+@@ -3332,6 +3379,32 @@ static void serial8250_console_restore(s
+ serial8250_out_MCR(up, UART_MCR_DTR | UART_MCR_RTS);
+ }
+
++void serial8250_console_write_atomic(struct uart_8250_port *up,
++ const char *s, unsigned int count)
++{
++ struct uart_port *port = &up->port;
++ unsigned long flags;
++ unsigned int ier;
++
++ printk_cpu_sync_get_irqsave(flags);
++
++ touch_nmi_watchdog();
++
++ ier = serial8250_clear_IER(up);
++
++ if (atomic_fetch_inc(&up->console_printing)) {
++ uart_console_write(port, "\n", 1,
++ serial8250_console_putchar_locked);
++ }
++ uart_console_write(port, s, count, serial8250_console_putchar_locked);
++ atomic_dec(&up->console_printing);
++
++ wait_for_xmitr(up, BOTH_EMPTY);
++ serial8250_set_IER(up, ier);
++
++ printk_cpu_sync_put_irqrestore(flags);
++}
++
+ /*
+ * Print a string to the serial port trying not to disturb
+ * any possible real use of the port...
+@@ -3348,24 +3421,12 @@ void serial8250_console_write(struct uar
+ struct uart_port *port = &up->port;
+ unsigned long flags;
+ unsigned int ier;
+- int locked = 1;
+
+ touch_nmi_watchdog();
+
+- if (oops_in_progress)
+- locked = spin_trylock_irqsave(&port->lock, flags);
+- else
+- spin_lock_irqsave(&port->lock, flags);
+-
+- /*
+- * First save the IER then disable the interrupts
+- */
+- ier = serial_port_in(port, UART_IER);
++ spin_lock_irqsave(&port->lock, flags);
+
+- if (up->capabilities & UART_CAP_UUE)
+- serial_port_out(port, UART_IER, UART_IER_UUE);
+- else
+- serial_port_out(port, UART_IER, 0);
++ ier = serial8250_clear_IER(up);
+
+ /* check scratch reg to see if port powered off during system sleep */
+ if (up->canary && (up->canary != serial_port_in(port, UART_SCR))) {
+@@ -3379,7 +3440,9 @@ void serial8250_console_write(struct uar
+ mdelay(port->rs485.delay_rts_before_send);
+ }
+
++ atomic_inc(&up->console_printing);
+ uart_console_write(port, s, count, serial8250_console_putchar);
++ atomic_dec(&up->console_printing);
+
+ /*
+ * Finally, wait for transmitter to become empty
+@@ -3392,8 +3455,7 @@ void serial8250_console_write(struct uar
+ if (em485->tx_stopped)
+ up->rs485_stop_tx(up);
+ }
+-
+- serial_port_out(port, UART_IER, ier);
++ serial8250_set_IER(up, ier);
+
+ /*
+ * The receive handling will happen properly because the
+@@ -3405,8 +3467,7 @@ void serial8250_console_write(struct uar
+ if (up->msr_saved_flags)
+ serial8250_modem_status(up);
+
+- if (locked)
+- spin_unlock_irqrestore(&port->lock, flags);
++ spin_unlock_irqrestore(&port->lock, flags);
+ }
+
+ static unsigned int probe_baud(struct uart_port *port)
+@@ -3426,6 +3487,7 @@ static unsigned int probe_baud(struct ua
+
+ int serial8250_console_setup(struct uart_port *port, char *options, bool probe)
+ {
++ struct uart_8250_port *up = up_to_u8250p(port);
+ int baud = 9600;
+ int bits = 8;
+ int parity = 'n';
+@@ -3435,6 +3497,8 @@ int serial8250_console_setup(struct uart
+ if (!port->iobase && !port->membase)
+ return -ENODEV;
+
++ atomic_set(&up->console_printing, 0);
++
+ if (options)
+ uart_parse_options(options, &baud, &parity, &bits, &flow);
+ else if (probe)
+--- a/drivers/tty/serial/8250/Kconfig
++++ b/drivers/tty/serial/8250/Kconfig
+@@ -9,6 +9,7 @@ config SERIAL_8250
+ depends on !S390
+ select SERIAL_CORE
+ select SERIAL_MCTRL_GPIO if GPIOLIB
++ select HAVE_ATOMIC_CONSOLE
+ help
+ This selects whether you want to include the driver for the standard
+ serial ports. The standard answer is Y. People who might say N
+--- a/include/linux/serial_8250.h
++++ b/include/linux/serial_8250.h
+@@ -7,6 +7,7 @@
+ #ifndef _LINUX_SERIAL_8250_H
+ #define _LINUX_SERIAL_8250_H
+
++#include <linux/atomic.h>
+ #include <linux/serial_core.h>
+ #include <linux/serial_reg.h>
+ #include <linux/platform_device.h>
+@@ -123,6 +124,8 @@ struct uart_8250_port {
+ #define MSR_SAVE_FLAGS UART_MSR_ANY_DELTA
+ unsigned char msr_saved_flags;
+
++ atomic_t console_printing;
++
+ struct uart_8250_dma *dma;
+ const struct uart_8250_ops *ops;
+
+@@ -178,6 +181,8 @@ void serial8250_init_port(struct uart_82
+ void serial8250_set_defaults(struct uart_8250_port *up);
+ void serial8250_console_write(struct uart_8250_port *up, const char *s,
+ unsigned int count);
++void serial8250_console_write_atomic(struct uart_8250_port *up, const char *s,
++ unsigned int count);
+ int serial8250_console_setup(struct uart_port *port, char *options, bool probe);
+ int serial8250_console_exit(struct uart_port *port);
+
diff --git a/patches/0002-smp-Rename-flush_smp_call_function_from_idle.patch b/patches/0002-smp-Rename-flush_smp_call_function_from_idle.patch
new file mode 100644
index 000000000000..de9f037a3f19
--- /dev/null
+++ b/patches/0002-smp-Rename-flush_smp_call_function_from_idle.patch
@@ -0,0 +1,125 @@
+From: Thomas Gleixner <tglx@linutronix.de>
+Date: Wed, 13 Apr 2022 15:31:03 +0200
+Subject: [PATCH 2/3] smp: Rename flush_smp_call_function_from_idle()
+
+This is invoked from the stopper thread too, which is definitely not idle.
+Rename it to flush_smp_call_function_queue() and fixup the callers.
+
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Link: https://lore.kernel.org/r/20220413133024.305001096@linutronix.de
+---
+ kernel/sched/core.c | 2 +-
+ kernel/sched/idle.c | 2 +-
+ kernel/sched/smp.h | 4 ++--
+ kernel/smp.c | 27 ++++++++++++++++++++-------
+ 4 files changed, 24 insertions(+), 11 deletions(-)
+
+--- a/kernel/sched/core.c
++++ b/kernel/sched/core.c
+@@ -2411,7 +2411,7 @@ static int migration_cpu_stop(void *data
+ * __migrate_task() such that we will not miss enforcing cpus_ptr
+ * during wakeups, see set_cpus_allowed_ptr()'s TASK_WAKING test.
+ */
+- flush_smp_call_function_from_idle();
++ flush_smp_call_function_queue();
+
+ raw_spin_lock(&p->pi_lock);
+ rq_lock(rq, &rf);
+--- a/kernel/sched/idle.c
++++ b/kernel/sched/idle.c
+@@ -327,7 +327,7 @@ static void do_idle(void)
+ * RCU relies on this call to be done outside of an RCU read-side
+ * critical section.
+ */
+- flush_smp_call_function_from_idle();
++ flush_smp_call_function_queue();
+ schedule_idle();
+
+ if (unlikely(klp_patch_pending(current)))
+--- a/kernel/sched/smp.h
++++ b/kernel/sched/smp.h
+@@ -9,7 +9,7 @@ extern void sched_ttwu_pending(void *arg
+ extern void send_call_function_single_ipi(int cpu);
+
+ #ifdef CONFIG_SMP
+-extern void flush_smp_call_function_from_idle(void);
++extern void flush_smp_call_function_queue(void);
+ #else
+-static inline void flush_smp_call_function_from_idle(void) { }
++static inline void flush_smp_call_function_queue(void) { }
+ #endif
+--- a/kernel/smp.c
++++ b/kernel/smp.c
+@@ -96,7 +96,7 @@ static DEFINE_PER_CPU_ALIGNED(struct cal
+
+ static DEFINE_PER_CPU_SHARED_ALIGNED(struct llist_head, call_single_queue);
+
+-static void flush_smp_call_function_queue(bool warn_cpu_offline);
++static void __flush_smp_call_function_queue(bool warn_cpu_offline);
+
+ int smpcfd_prepare_cpu(unsigned int cpu)
+ {
+@@ -141,7 +141,7 @@ int smpcfd_dying_cpu(unsigned int cpu)
+ * ensure that the outgoing CPU doesn't go offline with work
+ * still pending.
+ */
+- flush_smp_call_function_queue(false);
++ __flush_smp_call_function_queue(false);
+ irq_work_run();
+ return 0;
+ }
+@@ -541,11 +541,11 @@ void generic_smp_call_function_single_in
+ {
+ cfd_seq_store(this_cpu_ptr(&cfd_seq_local)->gotipi, CFD_SEQ_NOCPU,
+ smp_processor_id(), CFD_SEQ_GOTIPI);
+- flush_smp_call_function_queue(true);
++ __flush_smp_call_function_queue(true);
+ }
+
+ /**
+- * flush_smp_call_function_queue - Flush pending smp-call-function callbacks
++ * __flush_smp_call_function_queue - Flush pending smp-call-function callbacks
+ *
+ * @warn_cpu_offline: If set to 'true', warn if callbacks were queued on an
+ * offline CPU. Skip this check if set to 'false'.
+@@ -558,7 +558,7 @@ void generic_smp_call_function_single_in
+ * Loop through the call_single_queue and run all the queued callbacks.
+ * Must be called with interrupts disabled.
+ */
+-static void flush_smp_call_function_queue(bool warn_cpu_offline)
++static void __flush_smp_call_function_queue(bool warn_cpu_offline)
+ {
+ call_single_data_t *csd, *csd_next;
+ struct llist_node *entry, *prev;
+@@ -681,7 +681,20 @@ static void flush_smp_call_function_queu
+ smp_processor_id(), CFD_SEQ_HDLEND);
+ }
+
+-void flush_smp_call_function_from_idle(void)
++
++/**
++ * flush_smp_call_function_queue - Flush pending smp-call-function callbacks
++ * from task context (idle, migration thread)
++ *
++ * When TIF_POLLING_NRFLAG is supported and a CPU is in idle and has it
++ * set, then remote CPUs can avoid sending IPIs and wake the idle CPU by
++ * setting TIF_NEED_RESCHED. The idle task on the woken up CPU has to
++ * handle queued SMP function calls before scheduling.
++ *
++ * The migration thread has to ensure that an eventually pending wakeup has
++ * been handled before it migrates a task.
++ */
++void flush_smp_call_function_queue(void)
+ {
+ unsigned long flags;
+
+@@ -691,7 +704,7 @@ void flush_smp_call_function_from_idle(v
+ cfd_seq_store(this_cpu_ptr(&cfd_seq_local)->idle, CFD_SEQ_NOCPU,
+ smp_processor_id(), CFD_SEQ_IDLE);
+ local_irq_save(flags);
+- flush_smp_call_function_queue(true);
++ __flush_smp_call_function_queue(true);
+ if (local_softirq_pending())
+ do_softirq();
+
diff --git a/patches/0003-drm-i915-Use-preempt_disable-enable_rt-where-recomme.patch b/patches/0003-drm-i915-Use-preempt_disable-enable_rt-where-recomme.patch
index 1d2fecd82e55..468f188595f7 100644
--- a/patches/0003-drm-i915-Use-preempt_disable-enable_rt-where-recomme.patch
+++ b/patches/0003-drm-i915-Use-preempt_disable-enable_rt-where-recomme.patch
@@ -33,7 +33,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
-@@ -916,7 +916,8 @@ static bool i915_get_crtc_scanoutpos(str
+@@ -917,7 +917,8 @@ static bool i915_get_crtc_scanoutpos(str
*/
spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
@@ -43,7 +43,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
/* Get optional system timestamp before query. */
if (stime)
-@@ -980,7 +981,8 @@ static bool i915_get_crtc_scanoutpos(str
+@@ -981,7 +982,8 @@ static bool i915_get_crtc_scanoutpos(str
if (etime)
*etime = ktime_get();
diff --git a/patches/0003-i2c-cht-wc-Use-generic_handle_irq_safe.patch b/patches/0003-i2c-cht-wc-Use-generic_handle_irq_safe.patch
deleted file mode 100644
index 8d90fd0b1468..000000000000
--- a/patches/0003-i2c-cht-wc-Use-generic_handle_irq_safe.patch
+++ /dev/null
@@ -1,36 +0,0 @@
-From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
-Date: Fri, 11 Feb 2022 19:14:56 +0100
-Subject: [PATCH 3/7] i2c: cht-wc: Use generic_handle_irq_safe().
-
-Instead of manually disabling interrupts before invoking use
-generic_handle_irq_safe() which can be invoked with enabled and disabled
-interrupts.
-
-Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
-Reviewed-by: Hans de Goede <hdegoede@redhat.com>
-Acked-by: Wolfram Sang <wsa@kernel.org>
-Link: https://lore.kernel.org/r/20220211181500.1856198-4-bigeasy@linutronix.de
----
- drivers/i2c/busses/i2c-cht-wc.c | 11 ++---------
- 1 file changed, 2 insertions(+), 9 deletions(-)
-
---- a/drivers/i2c/busses/i2c-cht-wc.c
-+++ b/drivers/i2c/busses/i2c-cht-wc.c
-@@ -99,15 +99,8 @@ static irqreturn_t cht_wc_i2c_adap_threa
- * interrupt handler as well, so running the client irq handler from
- * this thread will cause things to lock up.
- */
-- if (reg & CHT_WC_EXTCHGRIRQ_CLIENT_IRQ) {
-- /*
-- * generic_handle_irq expects local IRQs to be disabled
-- * as normally it is called from interrupt context.
-- */
-- local_irq_disable();
-- generic_handle_irq(adap->client_irq);
-- local_irq_enable();
-- }
-+ if (reg & CHT_WC_EXTCHGRIRQ_CLIENT_IRQ)
-+ generic_handle_irq_safe(adap->client_irq);
-
- return IRQ_HANDLED;
- }
diff --git a/patches/0003-kernel-fork-IA64-Provide-a-alloc_thread_stack_node-f.patch b/patches/0003-kernel-fork-IA64-Provide-a-alloc_thread_stack_node-f.patch
deleted file mode 100644
index 30846acb5aae..000000000000
--- a/patches/0003-kernel-fork-IA64-Provide-a-alloc_thread_stack_node-f.patch
+++ /dev/null
@@ -1,69 +0,0 @@
-From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
-Date: Thu, 17 Feb 2022 11:24:01 +0100
-Subject: [PATCH 3/8] kernel/fork, IA64: Provide a alloc_thread_stack_node()
- for IA64.
-
-Provide a generic alloc_thread_stack_node() for IA64/
-CONFIG_ARCH_THREAD_STACK_ALLOCATOR which returns stack pointer and sets
-task_struct::stack so it behaves exactly like the other implementations.
-
-Rename IA64's alloc_thread_stack_node() and add the generic version to
-the fork code so it is in one place _and_ to drastically lower chances
-of fat fingering the IA64 code.
-Do the same for free_thread_stack().
-
-Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
-Acked-by: Andy Lutomirski <luto@kernel.org>
-Link: https://lore.kernel.org/r/20220217102406.3697941-4-bigeasy@linutronix.de
----
- arch/ia64/include/asm/thread_info.h | 6 +++---
- kernel/fork.c | 17 +++++++++++++++++
- 2 files changed, 20 insertions(+), 3 deletions(-)
-
---- a/arch/ia64/include/asm/thread_info.h
-+++ b/arch/ia64/include/asm/thread_info.h
-@@ -55,15 +55,15 @@ struct thread_info {
- #ifndef ASM_OFFSETS_C
- /* how to get the thread information struct from C */
- #define current_thread_info() ((struct thread_info *) ((char *) current + IA64_TASK_SIZE))
--#define alloc_thread_stack_node(tsk, node) \
-+#define arch_alloc_thread_stack_node(tsk, node) \
- ((unsigned long *) ((char *) (tsk) + IA64_TASK_SIZE))
- #define task_thread_info(tsk) ((struct thread_info *) ((char *) (tsk) + IA64_TASK_SIZE))
- #else
- #define current_thread_info() ((struct thread_info *) 0)
--#define alloc_thread_stack_node(tsk, node) ((unsigned long *) 0)
-+#define arch_alloc_thread_stack_node(tsk, node) ((unsigned long *) 0)
- #define task_thread_info(tsk) ((struct thread_info *) 0)
- #endif
--#define free_thread_stack(tsk) /* nothing */
-+#define arch_free_thread_stack(tsk) /* nothing */
- #define task_stack_page(tsk) ((void *)(tsk))
-
- #define __HAVE_THREAD_FUNCTIONS
---- a/kernel/fork.c
-+++ b/kernel/fork.c
-@@ -330,6 +330,23 @@ void thread_stack_cache_init(void)
- }
-
- # endif /* THREAD_SIZE >= PAGE_SIZE || defined(CONFIG_VMAP_STACK) */
-+#else /* CONFIG_ARCH_THREAD_STACK_ALLOCATOR */
-+
-+static unsigned long *alloc_thread_stack_node(struct task_struct *tsk, int node)
-+{
-+ unsigned long *stack;
-+
-+ stack = arch_alloc_thread_stack_node(tsk, node);
-+ tsk->stack = stack;
-+ return stack;
-+}
-+
-+static void free_thread_stack(struct task_struct *tsk)
-+{
-+ arch_free_thread_stack(tsk);
-+ tsk->stack = NULL;
-+}
-+
- #endif /* !CONFIG_ARCH_THREAD_STACK_ALLOCATOR */
-
- /* SLAB cache for signal_struct structures (tsk->signal) */
diff --git a/patches/0003-mm-memcg-Protect-per-CPU-counter-by-disabling-preemp.patch b/patches/0003-mm-memcg-Protect-per-CPU-counter-by-disabling-preemp.patch
deleted file mode 100644
index 53b6073fa36a..000000000000
--- a/patches/0003-mm-memcg-Protect-per-CPU-counter-by-disabling-preemp.patch
+++ /dev/null
@@ -1,121 +0,0 @@
-From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
-Date: Thu, 17 Feb 2022 10:48:00 +0100
-Subject: [PATCH 3/8] mm/memcg: Protect per-CPU counter by disabling preemption
- on PREEMPT_RT where needed.
-
-The per-CPU counter are modified with the non-atomic modifier. The
-consistency is ensured by disabling interrupts for the update.
-On non PREEMPT_RT configuration this works because acquiring a
-spinlock_t typed lock with the _irq() suffix disables interrupts. On
-PREEMPT_RT configurations the RMW operation can be interrupted.
-
-Another problem is that mem_cgroup_swapout() expects to be invoked with
-disabled interrupts because the caller has to acquire a spinlock_t which
-is acquired with disabled interrupts. Since spinlock_t never disables
-interrupts on PREEMPT_RT the interrupts are never disabled at this
-point.
-
-The code is never called from in_irq() context on PREEMPT_RT therefore
-disabling preemption during the update is sufficient on PREEMPT_RT.
-The sections which explicitly disable interrupts can remain on
-PREEMPT_RT because the sections remain short and they don't involve
-sleeping locks (memcg_check_events() is doing nothing on PREEMPT_RT).
-
-Disable preemption during update of the per-CPU variables which do not
-explicitly disable interrupts.
-
-Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
-Acked-by: Roman Gushchin <guro@fb.com>
----
- mm/memcontrol.c | 49 ++++++++++++++++++++++++++++++++++++++++++++++++-
- 1 file changed, 48 insertions(+), 1 deletion(-)
-
---- a/mm/memcontrol.c
-+++ b/mm/memcontrol.c
-@@ -629,6 +629,35 @@ static DEFINE_SPINLOCK(stats_flush_lock)
- static DEFINE_PER_CPU(unsigned int, stats_updates);
- static atomic_t stats_flush_threshold = ATOMIC_INIT(0);
-
-+/*
-+ * Accessors to ensure that preemption is disabled on PREEMPT_RT because it can
-+ * not rely on this as part of an acquired spinlock_t lock. These functions are
-+ * never used in hardirq context on PREEMPT_RT and therefore disabling preemtion
-+ * is sufficient.
-+ */
-+static void memcg_stats_lock(void)
-+{
-+#ifdef CONFIG_PREEMPT_RT
-+ preempt_disable();
-+#else
-+ VM_BUG_ON(!irqs_disabled());
-+#endif
-+}
-+
-+static void __memcg_stats_lock(void)
-+{
-+#ifdef CONFIG_PREEMPT_RT
-+ preempt_disable();
-+#endif
-+}
-+
-+static void memcg_stats_unlock(void)
-+{
-+#ifdef CONFIG_PREEMPT_RT
-+ preempt_enable();
-+#endif
-+}
-+
- static inline void memcg_rstat_updated(struct mem_cgroup *memcg, int val)
- {
- unsigned int x;
-@@ -705,6 +734,20 @@ void __mod_memcg_lruvec_state(struct lru
- pn = container_of(lruvec, struct mem_cgroup_per_node, lruvec);
- memcg = pn->memcg;
-
-+ /*
-+ * The caller from rmap relay on disabled preemption becase they never
-+ * update their counter from in-interrupt context. For these two
-+ * counters we check that the update is never performed from an
-+ * interrupt context while other caller need to have disabled interrupt.
-+ */
-+ __memcg_stats_lock();
-+ if (IS_ENABLED(CONFIG_DEBUG_VM)) {
-+ if (idx == NR_ANON_MAPPED || idx == NR_FILE_MAPPED)
-+ WARN_ON_ONCE(!in_task());
-+ else
-+ WARN_ON_ONCE(!irqs_disabled());
-+ }
-+
- /* Update memcg */
- __this_cpu_add(memcg->vmstats_percpu->state[idx], val);
-
-@@ -712,6 +755,7 @@ void __mod_memcg_lruvec_state(struct lru
- __this_cpu_add(pn->lruvec_stats_percpu->state[idx], val);
-
- memcg_rstat_updated(memcg, val);
-+ memcg_stats_unlock();
- }
-
- /**
-@@ -794,8 +838,10 @@ void __count_memcg_events(struct mem_cgr
- if (mem_cgroup_disabled())
- return;
-
-+ memcg_stats_lock();
- __this_cpu_add(memcg->vmstats_percpu->events[idx], count);
- memcg_rstat_updated(memcg, count);
-+ memcg_stats_unlock();
- }
-
- static unsigned long memcg_events(struct mem_cgroup *memcg, int event)
-@@ -7149,8 +7195,9 @@ void mem_cgroup_swapout(struct page *pag
- * important here to have the interrupts disabled because it is the
- * only synchronisation we have for updating the per-CPU variables.
- */
-- VM_BUG_ON(!irqs_disabled());
-+ memcg_stats_lock();
- mem_cgroup_charge_statistics(memcg, -nr_entries);
-+ memcg_stats_unlock();
- memcg_check_events(memcg, page_to_nid(page));
-
- css_put(&memcg->css);
diff --git a/patches/0003-net-dev-Makes-sure-netif_rx-can-be-invoked-in-any-co.patch b/patches/0003-net-dev-Makes-sure-netif_rx-can-be-invoked-in-any-co.patch
deleted file mode 100644
index 9a7c8539d577..000000000000
--- a/patches/0003-net-dev-Makes-sure-netif_rx-can-be-invoked-in-any-co.patch
+++ /dev/null
@@ -1,412 +0,0 @@
-From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
-Date: Sat, 12 Feb 2022 00:38:38 +0100
-Subject: [PATCH 3/3] net: dev: Makes sure netif_rx() can be invoked in any
- context.
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-Dave suggested a while ago (eleven years by now) "Let's make netif_rx()
-work in all contexts and get rid of netif_rx_ni()". Eric agreed and
-pointed out that modern devices should use netif_receive_skb() to avoid
-the overhead.
-In the meantime someone added another variant, netif_rx_any_context(),
-which behaves as suggested.
-
-netif_rx() must be invoked with disabled bottom halves to ensure that
-pending softirqs, which were raised within the function, are handled.
-netif_rx_ni() can be invoked only from process context (bottom halves
-must be enabled) because the function handles pending softirqs without
-checking if bottom halves were disabled or not.
-netif_rx_any_context() invokes on the former functions by checking
-in_interrupts().
-
-netif_rx() could be taught to handle both cases (disabled and enabled
-bottom halves) by simply disabling bottom halves while invoking
-netif_rx_internal(). The local_bh_enable() invocation will then invoke
-pending softirqs only if the BH-disable counter drops to zero.
-
-Eric is concerned about the overhead of BH-disable+enable especially in
-regard to the loopback driver. As critical as this driver is, it will
-receive a shortcut to avoid the additional overhead which is not needed.
-
-Add a local_bh_disable() section in netif_rx() to ensure softirqs are
-handled if needed.
-Provide __netif_rx() which does not disable BH and has a lockdep assert
-to ensure that interrupts are disabled. Use this shortcut in the
-loopback driver and in drivers/net/*.c.
-Make netif_rx_ni() and netif_rx_any_context() invoke netif_rx() so they
-can be removed once they are no more users left.
-
-Link: https://lkml.kernel.org/r/20100415.020246.218622820.davem@davemloft.net
-Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
-Reviewed-by: Eric Dumazet <edumazet@google.com>
-Reviewed-by: Toke Høiland-Jørgensen <toke@redhat.com>
-Signed-off-by: David S. Miller <davem@davemloft.net>
-Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
----
- drivers/net/amt.c | 4 +-
- drivers/net/geneve.c | 4 +-
- drivers/net/gtp.c | 2 -
- drivers/net/loopback.c | 4 +-
- drivers/net/macsec.c | 6 ++--
- drivers/net/macvlan.c | 4 +-
- drivers/net/mhi_net.c | 2 -
- drivers/net/ntb_netdev.c | 2 -
- drivers/net/rionet.c | 2 -
- drivers/net/sb1000.c | 2 -
- drivers/net/veth.c | 2 -
- drivers/net/vrf.c | 2 -
- drivers/net/vxlan.c | 2 -
- include/linux/netdevice.h | 14 ++++++++-
- include/trace/events/net.h | 14 ---------
- net/core/dev.c | 67 +++++++++++++++++++--------------------------
- 16 files changed, 60 insertions(+), 73 deletions(-)
-
---- a/drivers/net/amt.c
-+++ b/drivers/net/amt.c
-@@ -2373,7 +2373,7 @@ static bool amt_membership_query_handler
- skb->pkt_type = PACKET_MULTICAST;
- skb->ip_summed = CHECKSUM_NONE;
- len = skb->len;
-- if (netif_rx(skb) == NET_RX_SUCCESS) {
-+ if (__netif_rx(skb) == NET_RX_SUCCESS) {
- amt_update_gw_status(amt, AMT_STATUS_RECEIVED_QUERY, true);
- dev_sw_netstats_rx_add(amt->dev, len);
- } else {
-@@ -2470,7 +2470,7 @@ static bool amt_update_handler(struct am
- skb->pkt_type = PACKET_MULTICAST;
- skb->ip_summed = CHECKSUM_NONE;
- len = skb->len;
-- if (netif_rx(skb) == NET_RX_SUCCESS) {
-+ if (__netif_rx(skb) == NET_RX_SUCCESS) {
- amt_update_relay_status(tunnel, AMT_STATUS_RECEIVED_UPDATE,
- true);
- dev_sw_netstats_rx_add(amt->dev, len);
---- a/drivers/net/geneve.c
-+++ b/drivers/net/geneve.c
-@@ -925,7 +925,7 @@ static int geneve_xmit_skb(struct sk_buf
- }
-
- skb->protocol = eth_type_trans(skb, geneve->dev);
-- netif_rx(skb);
-+ __netif_rx(skb);
- dst_release(&rt->dst);
- return -EMSGSIZE;
- }
-@@ -1021,7 +1021,7 @@ static int geneve6_xmit_skb(struct sk_bu
- }
-
- skb->protocol = eth_type_trans(skb, geneve->dev);
-- netif_rx(skb);
-+ __netif_rx(skb);
- dst_release(dst);
- return -EMSGSIZE;
- }
---- a/drivers/net/gtp.c
-+++ b/drivers/net/gtp.c
-@@ -207,7 +207,7 @@ static int gtp_rx(struct pdp_ctx *pctx,
-
- dev_sw_netstats_rx_add(pctx->dev, skb->len);
-
-- netif_rx(skb);
-+ __netif_rx(skb);
- return 0;
-
- err:
---- a/drivers/net/loopback.c
-+++ b/drivers/net/loopback.c
-@@ -78,7 +78,7 @@ static netdev_tx_t loopback_xmit(struct
-
- skb_orphan(skb);
-
-- /* Before queueing this packet to netif_rx(),
-+ /* Before queueing this packet to __netif_rx(),
- * make sure dst is refcounted.
- */
- skb_dst_force(skb);
-@@ -86,7 +86,7 @@ static netdev_tx_t loopback_xmit(struct
- skb->protocol = eth_type_trans(skb, dev);
-
- len = skb->len;
-- if (likely(netif_rx(skb) == NET_RX_SUCCESS))
-+ if (likely(__netif_rx(skb) == NET_RX_SUCCESS))
- dev_lstats_add(dev, len);
-
- return NETDEV_TX_OK;
---- a/drivers/net/macsec.c
-+++ b/drivers/net/macsec.c
-@@ -1033,7 +1033,7 @@ static enum rx_handler_result handle_not
- else
- nskb->pkt_type = PACKET_MULTICAST;
-
-- netif_rx(nskb);
-+ __netif_rx(nskb);
- }
- continue;
- }
-@@ -1056,7 +1056,7 @@ static enum rx_handler_result handle_not
-
- nskb->dev = ndev;
-
-- if (netif_rx(nskb) == NET_RX_SUCCESS) {
-+ if (__netif_rx(nskb) == NET_RX_SUCCESS) {
- u64_stats_update_begin(&secy_stats->syncp);
- secy_stats->stats.InPktsUntagged++;
- u64_stats_update_end(&secy_stats->syncp);
-@@ -1288,7 +1288,7 @@ static rx_handler_result_t macsec_handle
-
- macsec_reset_skb(nskb, macsec->secy.netdev);
-
-- ret = netif_rx(nskb);
-+ ret = __netif_rx(nskb);
- if (ret == NET_RX_SUCCESS) {
- u64_stats_update_begin(&secy_stats->syncp);
- secy_stats->stats.InPktsUnknownSCI++;
---- a/drivers/net/macvlan.c
-+++ b/drivers/net/macvlan.c
-@@ -410,7 +410,7 @@ static void macvlan_forward_source_one(s
- if (ether_addr_equal_64bits(eth_hdr(skb)->h_dest, dev->dev_addr))
- nskb->pkt_type = PACKET_HOST;
-
-- ret = netif_rx(nskb);
-+ ret = __netif_rx(nskb);
- macvlan_count_rx(vlan, len, ret == NET_RX_SUCCESS, false);
- }
-
-@@ -468,7 +468,7 @@ static rx_handler_result_t macvlan_handl
- /* forward to original port. */
- vlan = src;
- ret = macvlan_broadcast_one(skb, vlan, eth, 0) ?:
-- netif_rx(skb);
-+ __netif_rx(skb);
- handle_res = RX_HANDLER_CONSUMED;
- goto out;
- }
---- a/drivers/net/mhi_net.c
-+++ b/drivers/net/mhi_net.c
-@@ -225,7 +225,7 @@ static void mhi_net_dl_callback(struct m
- u64_stats_inc(&mhi_netdev->stats.rx_packets);
- u64_stats_add(&mhi_netdev->stats.rx_bytes, skb->len);
- u64_stats_update_end(&mhi_netdev->stats.rx_syncp);
-- netif_rx(skb);
-+ __netif_rx(skb);
- }
-
- /* Refill if RX buffers queue becomes low */
---- a/drivers/net/ntb_netdev.c
-+++ b/drivers/net/ntb_netdev.c
-@@ -119,7 +119,7 @@ static void ntb_netdev_rx_handler(struct
- skb->protocol = eth_type_trans(skb, ndev);
- skb->ip_summed = CHECKSUM_NONE;
-
-- if (netif_rx(skb) == NET_RX_DROP) {
-+ if (__netif_rx(skb) == NET_RX_DROP) {
- ndev->stats.rx_errors++;
- ndev->stats.rx_dropped++;
- } else {
---- a/drivers/net/rionet.c
-+++ b/drivers/net/rionet.c
-@@ -109,7 +109,7 @@ static int rionet_rx_clean(struct net_de
- skb_put(rnet->rx_skb[i], RIO_MAX_MSG_SIZE);
- rnet->rx_skb[i]->protocol =
- eth_type_trans(rnet->rx_skb[i], ndev);
-- error = netif_rx(rnet->rx_skb[i]);
-+ error = __netif_rx(rnet->rx_skb[i]);
-
- if (error == NET_RX_DROP) {
- ndev->stats.rx_dropped++;
---- a/drivers/net/sb1000.c
-+++ b/drivers/net/sb1000.c
-@@ -872,7 +872,7 @@ printk("cm0: IP identification: %02x%02x
-
- /* datagram completed: send to upper level */
- skb_trim(skb, dlen);
-- netif_rx(skb);
-+ __netif_rx(skb);
- stats->rx_bytes+=dlen;
- stats->rx_packets++;
- lp->rx_skb[ns] = NULL;
---- a/drivers/net/veth.c
-+++ b/drivers/net/veth.c
-@@ -287,7 +287,7 @@ static int veth_forward_skb(struct net_d
- {
- return __dev_forward_skb(dev, skb) ?: xdp ?
- veth_xdp_rx(rq, skb) :
-- netif_rx(skb);
-+ __netif_rx(skb);
- }
-
- /* return true if the specified skb has chances of GRO aggregation
---- a/drivers/net/vrf.c
-+++ b/drivers/net/vrf.c
-@@ -418,7 +418,7 @@ static int vrf_local_xmit(struct sk_buff
-
- skb->protocol = eth_type_trans(skb, dev);
-
-- if (likely(netif_rx(skb) == NET_RX_SUCCESS))
-+ if (likely(__netif_rx(skb) == NET_RX_SUCCESS))
- vrf_rx_stats(dev, len);
- else
- this_cpu_inc(dev->dstats->rx_drps);
---- a/drivers/net/vxlan.c
-+++ b/drivers/net/vxlan.c
-@@ -2541,7 +2541,7 @@ static void vxlan_encap_bypass(struct sk
- tx_stats->tx_bytes += len;
- u64_stats_update_end(&tx_stats->syncp);
-
-- if (netif_rx(skb) == NET_RX_SUCCESS) {
-+ if (__netif_rx(skb) == NET_RX_SUCCESS) {
- u64_stats_update_begin(&rx_stats->syncp);
- rx_stats->rx_packets++;
- rx_stats->rx_bytes += len;
---- a/include/linux/netdevice.h
-+++ b/include/linux/netdevice.h
-@@ -3669,8 +3669,18 @@ u32 bpf_prog_run_generic_xdp(struct sk_b
- void generic_xdp_tx(struct sk_buff *skb, struct bpf_prog *xdp_prog);
- int do_xdp_generic(struct bpf_prog *xdp_prog, struct sk_buff *skb);
- int netif_rx(struct sk_buff *skb);
--int netif_rx_ni(struct sk_buff *skb);
--int netif_rx_any_context(struct sk_buff *skb);
-+int __netif_rx(struct sk_buff *skb);
-+
-+static inline int netif_rx_ni(struct sk_buff *skb)
-+{
-+ return netif_rx(skb);
-+}
-+
-+static inline int netif_rx_any_context(struct sk_buff *skb)
-+{
-+ return netif_rx(skb);
-+}
-+
- int netif_receive_skb(struct sk_buff *skb);
- int netif_receive_skb_core(struct sk_buff *skb);
- void netif_receive_skb_list_internal(struct list_head *head);
---- a/include/trace/events/net.h
-+++ b/include/trace/events/net.h
-@@ -260,13 +260,6 @@ DEFINE_EVENT(net_dev_rx_verbose_template
- TP_ARGS(skb)
- );
-
--DEFINE_EVENT(net_dev_rx_verbose_template, netif_rx_ni_entry,
--
-- TP_PROTO(const struct sk_buff *skb),
--
-- TP_ARGS(skb)
--);
--
- DECLARE_EVENT_CLASS(net_dev_rx_exit_template,
-
- TP_PROTO(int ret),
-@@ -309,13 +302,6 @@ DEFINE_EVENT(net_dev_rx_exit_template, n
-
- TP_PROTO(int ret),
-
-- TP_ARGS(ret)
--);
--
--DEFINE_EVENT(net_dev_rx_exit_template, netif_rx_ni_exit,
--
-- TP_PROTO(int ret),
--
- TP_ARGS(ret)
- );
-
---- a/net/core/dev.c
-+++ b/net/core/dev.c
-@@ -4830,65 +4830,56 @@ static int netif_rx_internal(struct sk_b
- }
-
- /**
-+ * __netif_rx - Slightly optimized version of netif_rx
-+ * @skb: buffer to post
-+ *
-+ * This behaves as netif_rx except that it does not disable bottom halves.
-+ * As a result this function may only be invoked from the interrupt context
-+ * (either hard or soft interrupt).
-+ */
-+int __netif_rx(struct sk_buff *skb)
-+{
-+ int ret;
-+
-+ lockdep_assert_once(hardirq_count() | softirq_count());
-+
-+ trace_netif_rx_entry(skb);
-+ ret = netif_rx_internal(skb);
-+ trace_netif_rx_exit(ret);
-+ return ret;
-+}
-+EXPORT_SYMBOL(__netif_rx);
-+
-+/**
- * netif_rx - post buffer to the network code
- * @skb: buffer to post
- *
- * This function receives a packet from a device driver and queues it for
-- * the upper (protocol) levels to process. It always succeeds. The buffer
-- * may be dropped during processing for congestion control or by the
-- * protocol layers.
-+ * the upper (protocol) levels to process via the backlog NAPI device. It
-+ * always succeeds. The buffer may be dropped during processing for
-+ * congestion control or by the protocol layers.
-+ * The network buffer is passed via the backlog NAPI device. Modern NIC
-+ * driver should use NAPI and GRO.
-+ * This function can used from any context.
- *
- * return values:
- * NET_RX_SUCCESS (no congestion)
- * NET_RX_DROP (packet was dropped)
- *
- */
--
- int netif_rx(struct sk_buff *skb)
- {
- int ret;
-
-+ local_bh_disable();
- trace_netif_rx_entry(skb);
--
- ret = netif_rx_internal(skb);
- trace_netif_rx_exit(ret);
--
-+ local_bh_enable();
- return ret;
- }
- EXPORT_SYMBOL(netif_rx);
-
--int netif_rx_ni(struct sk_buff *skb)
--{
-- int err;
--
-- trace_netif_rx_ni_entry(skb);
--
-- preempt_disable();
-- err = netif_rx_internal(skb);
-- if (local_softirq_pending())
-- do_softirq();
-- preempt_enable();
-- trace_netif_rx_ni_exit(err);
--
-- return err;
--}
--EXPORT_SYMBOL(netif_rx_ni);
--
--int netif_rx_any_context(struct sk_buff *skb)
--{
-- /*
-- * If invoked from contexts which do not invoke bottom half
-- * processing either at return from interrupt or when softrqs are
-- * reenabled, use netif_rx_ni() which invokes bottomhalf processing
-- * directly.
-- */
-- if (in_interrupt())
-- return netif_rx(skb);
-- else
-- return netif_rx_ni(skb);
--}
--EXPORT_SYMBOL(netif_rx_any_context);
--
- static __latent_entropy void net_tx_action(struct softirq_action *h)
- {
- struct softnet_data *sd = this_cpu_ptr(&softnet_data);
diff --git a/patches/0003-printk-add-missing-memory-barrier-to-wake_up_klogd.patch b/patches/0003-printk-add-missing-memory-barrier-to-wake_up_klogd.patch
new file mode 100644
index 000000000000..f284c6344df1
--- /dev/null
+++ b/patches/0003-printk-add-missing-memory-barrier-to-wake_up_klogd.patch
@@ -0,0 +1,88 @@
+From: John Ogness <john.ogness@linutronix.de>
+Date: Wed, 20 Apr 2022 01:52:25 +0206
+Subject: [PATCH 03/15] printk: add missing memory barrier to wake_up_klogd()
+
+It is important that any new records are visible to preparing
+waiters before the waker checks if the wait queue is empty.
+Otherwise it is possible that:
+
+- there are new records available
+- the waker sees an empty wait queue and does not wake
+- the preparing waiter sees no new records and begins to wait
+
+This is exactly the problem that the function description of
+waitqueue_active() warns about.
+
+Use wq_has_sleeper() instead of waitqueue_active() because it
+includes the necessary full memory barrier.
+
+Signed-off-by: John Ogness <john.ogness@linutronix.de>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Link: https://lore.kernel.org/r/20220419234637.357112-4-john.ogness@linutronix.de
+---
+ kernel/printk/printk.c | 39 ++++++++++++++++++++++++++++++++++++---
+ 1 file changed, 36 insertions(+), 3 deletions(-)
+
+--- a/kernel/printk/printk.c
++++ b/kernel/printk/printk.c
+@@ -746,8 +746,19 @@ static ssize_t devkmsg_read(struct file
+ goto out;
+ }
+
++ /*
++ * Guarantee this task is visible on the waitqueue before
++ * checking the wake condition.
++ *
++ * The full memory barrier within set_current_state() of
++ * prepare_to_wait_event() pairs with the full memory barrier
++ * within wq_has_sleeper().
++ *
++ * This pairs with wake_up_klogd:A.
++ */
+ ret = wait_event_interruptible(log_wait,
+- prb_read_valid(prb, atomic64_read(&user->seq), r));
++ prb_read_valid(prb,
++ atomic64_read(&user->seq), r)); /* LMM(devkmsg_read:A) */
+ if (ret)
+ goto out;
+ }
+@@ -1513,7 +1524,18 @@ static int syslog_print(char __user *buf
+ seq = syslog_seq;
+
+ mutex_unlock(&syslog_lock);
+- len = wait_event_interruptible(log_wait, prb_read_valid(prb, seq, NULL));
++ /*
++ * Guarantee this task is visible on the waitqueue before
++ * checking the wake condition.
++ *
++ * The full memory barrier within set_current_state() of
++ * prepare_to_wait_event() pairs with the full memory barrier
++ * within wq_has_sleeper().
++ *
++ * This pairs with wake_up_klogd:A.
++ */
++ len = wait_event_interruptible(log_wait,
++ prb_read_valid(prb, seq, NULL)); /* LMM(syslog_print:A) */
+ mutex_lock(&syslog_lock);
+
+ if (len)
+@@ -3316,7 +3338,18 @@ void wake_up_klogd(void)
+ return;
+
+ preempt_disable();
+- if (waitqueue_active(&log_wait)) {
++ /*
++ * Guarantee any new records can be seen by tasks preparing to wait
++ * before this context checks if the wait queue is empty.
++ *
++ * The full memory barrier within wq_has_sleeper() pairs with the full
++ * memory barrier within set_current_state() of
++ * prepare_to_wait_event(), which is called after ___wait_event() adds
++ * the waiter but before it has checked the wait condition.
++ *
++ * This pairs with devkmsg_read:A and syslog_print:A.
++ */
++ if (wq_has_sleeper(&log_wait)) { /* LMM(wake_up_klogd:A) */
+ this_cpu_or(printk_pending, PRINTK_PENDING_WAKEUP);
+ irq_work_queue(this_cpu_ptr(&wake_up_klogd_work));
+ }
diff --git a/patches/0016-printk-avoid-preempt_disable-for-PREEMPT_RT.patch b/patches/0003-printk-avoid-preempt_disable-for-PREEMPT_RT.patch
index 7fcd95e13dee..d85419106920 100644
--- a/patches/0016-printk-avoid-preempt_disable-for-PREEMPT_RT.patch
+++ b/patches/0003-printk-avoid-preempt_disable-for-PREEMPT_RT.patch
@@ -1,6 +1,6 @@
From: John Ogness <john.ogness@linutronix.de>
Date: Fri, 4 Feb 2022 16:01:17 +0106
-Subject: [PATCH 16/16] printk: avoid preempt_disable() for PREEMPT_RT
+Subject: [PATCH 3/3] printk: avoid preempt_disable() for PREEMPT_RT
During non-normal operation, printk() calls will attempt to
write the messages directly to the consoles. This involves
@@ -23,13 +23,14 @@ non-panic dumps, the risks of delayed print output for these
scenarios will be accepted under PREEMPT_RT.
Signed-off-by: John Ogness <john.ogness@linutronix.de>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
---
- kernel/printk/printk.c | 29 ++++++++++++++++++++++++-----
- 1 file changed, 24 insertions(+), 5 deletions(-)
+ kernel/printk/printk.c | 21 ++++++++++++++++++++-
+ 1 file changed, 20 insertions(+), 1 deletion(-)
--- a/kernel/printk/printk.c
+++ b/kernel/printk/printk.c
-@@ -1899,6 +1899,7 @@ static int console_lock_spinning_disable
+@@ -1956,6 +1956,7 @@ static int console_lock_spinning_disable
return 1;
}
@@ -37,7 +38,7 @@ Signed-off-by: John Ogness <john.ogness@linutronix.de>
/**
* console_trylock_spinning - try to get console_lock by busy waiting
*
-@@ -1962,6 +1963,7 @@ static int console_trylock_spinning(void
+@@ -2029,6 +2030,7 @@ static int console_trylock_spinning(void
return 1;
}
@@ -45,13 +46,10 @@ Signed-off-by: John Ogness <john.ogness@linutronix.de>
/*
* Call the specified console driver, asking it to write out the specified
-@@ -2296,19 +2298,31 @@ asmlinkage int vprintk_emit(int facility
+@@ -2368,6 +2370,18 @@ asmlinkage int vprintk_emit(int facility
+
/* If called from the scheduler, we can not call up(). */
if (!in_sched && allow_direct_printing()) {
- /*
-+ * Try to acquire and then immediately release the console
-+ * semaphore. The release will print out buffers.
-+ */
+#if IS_ENABLED(CONFIG_PREEMPT_RT)
+ /*
+ * Use the non-spinning trylock since PREEMPT_RT does not
@@ -64,17 +62,10 @@ Signed-off-by: John Ogness <john.ogness@linutronix.de>
+ if (preemptible() && console_trylock())
+ console_unlock();
+#else
-+ /*
- * Disable preemption to avoid being preempted while holding
- * console_sem which would prevent anyone from printing to
- * console
- */
- preempt_disable();
-- /*
-- * Try to acquire and then immediately release the console
-- * semaphore. The release will print out buffers and wake up
-- * /dev/kmsg and syslog() users.
-- */
+ /*
+ * The caller may be holding system-critical or
+ * timing-sensitive locks. Disable preemption during direct
+@@ -2385,6 +2399,7 @@ asmlinkage int vprintk_emit(int facility
if (console_trylock_spinning())
console_unlock();
preempt_enable();
@@ -82,17 +73,17 @@ Signed-off-by: John Ogness <john.ogness@linutronix.de>
}
wake_up_klogd();
-@@ -2924,8 +2938,13 @@ static bool console_emit_next_record(str
- len = record_print_text(&r, console_msg_format & MSG_FORMAT_SYSLOG, printk_time);
+@@ -3089,8 +3104,12 @@ static bool console_emit_next_record_tra
+ /*
+ * Handovers are only supported if threaded printers are atomically
+ * blocked. The context taking over the console_lock may be atomic.
++ *
++ * PREEMPT_RT also does not support handovers because the spinning
++ * waiter can cause large latencies.
+ */
+- if (!console_kthreads_atomically_blocked()) {
++ if (!console_kthreads_atomically_blocked() ||
++ IS_ENABLED(CONFIG_PREEMPT_RT)) {
+ *handover = false;
+ handover = NULL;
}
-
-+#if IS_ENABLED(CONFIG_PREEMPT_RT)
-+ /* PREEMPT_RT does not support console lock handovers. */
-+ allow_handover = false;
-+#else
- /* Handovers may only happen between trylock contexts. */
- allow_handover = (handover && atomic_read(&console_lock_count) == -1);
-+#endif
-
- if (allow_handover) {
- /*
diff --git a/patches/0003-printk-use-percpu-flag-instead-of-cpu_online.patch b/patches/0003-printk-use-percpu-flag-instead-of-cpu_online.patch
deleted file mode 100644
index b0aa5173df4d..000000000000
--- a/patches/0003-printk-use-percpu-flag-instead-of-cpu_online.patch
+++ /dev/null
@@ -1,50 +0,0 @@
-From: John Ogness <john.ogness@linutronix.de>
-Date: Mon, 7 Feb 2022 15:53:45 +0106
-Subject: [PATCH 03/16] printk: use percpu flag instead of cpu_online()
-
-The CON_ANYTIME console flag is used to label consoles that will
-work correctly before percpu resources are allocated. To check
-the condition, cpu_online(raw_smp_processor_id()) was used.
-However, this is odd because CPUs can go offline at a later point.
-Also, the function is forced to use the raw_ variant because
-migration is not disabled.
-
-Since commit ab6f762f0f53 ("printk: queue wake_up_klogd irq_work
-only if per-CPU areas are ready") there is a variable to identify
-if percpu resources have been allocated. Use that variable instead
-of cpu_online(raw_smp_processor_id()).
-
-Signed-off-by: John Ogness <john.ogness@linutronix.de>
-Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
----
- include/linux/console.h | 2 +-
- kernel/printk/printk.c | 4 ++--
- 2 files changed, 3 insertions(+), 3 deletions(-)
-
---- a/include/linux/console.h
-+++ b/include/linux/console.h
-@@ -133,7 +133,7 @@ static inline int con_debug_leave(void)
- #define CON_CONSDEV (2) /* Preferred console, /dev/console */
- #define CON_ENABLED (4)
- #define CON_BOOT (8)
--#define CON_ANYTIME (16) /* Safe to call when cpu is offline */
-+#define CON_ANYTIME (16) /* Safe to call before per-cpu resources ready */
- #define CON_BRL (32) /* Used for a braille device */
- #define CON_EXTENDED (64) /* Use the extended output format a la /dev/kmsg */
-
---- a/kernel/printk/printk.c
-+++ b/kernel/printk/printk.c
-@@ -2578,11 +2578,11 @@ static int have_callable_console(void)
- *
- * Console drivers may assume that per-cpu resources have been allocated. So
- * unless they're explicitly marked as being able to cope (CON_ANYTIME) don't
-- * call them until this CPU is officially up.
-+ * call them until per-cpu resources have been allocated.
- */
- static inline int can_use_console(void)
- {
-- return cpu_online(raw_smp_processor_id()) || have_callable_console();
-+ return (printk_percpu_data_ready() || have_callable_console());
- }
-
- /**
diff --git a/patches/0003-random-fix-locking-in-crng_fast_load.patch b/patches/0003-random-fix-locking-in-crng_fast_load.patch
deleted file mode 100644
index 6016efc84758..000000000000
--- a/patches/0003-random-fix-locking-in-crng_fast_load.patch
+++ /dev/null
@@ -1,37 +0,0 @@
-From: Dominik Brodowski <linux@dominikbrodowski.net>
-Date: Sat, 5 Feb 2022 11:34:57 +0100
-Subject: [PATCH 3/5] random: fix locking in crng_fast_load()
-
-crng_init is protected by primary_crng->lock, so keep holding that lock
-when incrementing crng_init from 0 to 1 in crng_fast_load(). The call to
-pr_notice() can wait until the lock is released; this code path cannot
-be reached twice, as crng_fast_load() aborts early if crng_init > 0.
-
-Signed-off-by: Dominik Brodowski <linux@dominikbrodowski.net>
-[Jason: Note - this is only possible now that invalidate_batched_
- entropy() is a simple atomic_inc(), so this must be ordered after that,
- even though it appears on first glance as independent.]
-Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
-Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
----
- drivers/char/random.c | 5 +++--
- 1 file changed, 3 insertions(+), 2 deletions(-)
-
---- a/drivers/char/random.c
-+++ b/drivers/char/random.c
-@@ -724,12 +724,13 @@ static size_t crng_fast_load(const u8 *c
- p[crng_init_cnt % CHACHA_KEY_SIZE] ^= *cp;
- cp++; crng_init_cnt++; len--; ret++;
- }
-- spin_unlock_irqrestore(&primary_crng.lock, flags);
- if (crng_init_cnt >= CRNG_INIT_CNT_THRESH) {
- invalidate_batched_entropy();
- crng_init = 1;
-- pr_notice("fast init done\n");
- }
-+ spin_unlock_irqrestore(&primary_crng.lock, flags);
-+ if (crng_init == 1)
-+ pr_notice("fast init done\n");
- return ret;
- }
-
diff --git a/patches/0003-smp-Make-softirq-handling-RT-safe-in-flush_smp_call_.patch b/patches/0003-smp-Make-softirq-handling-RT-safe-in-flush_smp_call_.patch
new file mode 100644
index 000000000000..f0aaf37a3623
--- /dev/null
+++ b/patches/0003-smp-Make-softirq-handling-RT-safe-in-flush_smp_call_.patch
@@ -0,0 +1,106 @@
+From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Date: Wed, 13 Apr 2022 15:31:05 +0200
+Subject: [PATCH 3/3] smp: Make softirq handling RT safe in
+ flush_smp_call_function_queue()
+
+flush_smp_call_function_queue() invokes do_softirq() which is not available
+on PREEMPT_RT. flush_smp_call_function_queue() is invoked from the idle
+task and the migration task with preemption or interrupts disabled.
+
+So RT kernels cannot process soft interrupts in that context as that has to
+acquire 'sleeping spinlocks' which is not possible with preemption or
+interrupts disabled and forbidden from the idle task anyway.
+
+The currently known SMP function call which raises a soft interrupt is in
+the block layer, but this functionality is not enabled on RT kernels due to
+latency and performance reasons.
+
+RT could wake up ksoftirqd unconditionally, but this wants to be avoided if
+there were soft interrupts pending already when this is invoked in the
+context of the migration task. The migration task might have preempted a
+threaded interrupt handler which raised a soft interrupt, but did not reach
+the local_bh_enable() to process it. The "running" ksoftirqd might prevent
+the handling in the interrupt thread context which is causing latency
+issues.
+
+Add a new function which handles this case explicitely for RT and falls
+back to do_softirq() on !RT kernels. In the RT case this warns when one of
+the flushed SMP function calls raised a soft interrupt so this can be
+investigated.
+
+[ tglx: Moved the RT part out of SMP code ]
+
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Link: https://lore.kernel.org/r/YgKgL6aPj8aBES6G@linutronix.de
+Link: https://lore.kernel.org/r/20220413133024.356509586@linutronix.de
+---
+ include/linux/interrupt.h | 9 +++++++++
+ kernel/smp.c | 5 ++++-
+ kernel/softirq.c | 13 +++++++++++++
+ 3 files changed, 26 insertions(+), 1 deletion(-)
+
+--- a/include/linux/interrupt.h
++++ b/include/linux/interrupt.h
+@@ -607,6 +607,15 @@ struct softirq_action
+ asmlinkage void do_softirq(void);
+ asmlinkage void __do_softirq(void);
+
++#ifdef CONFIG_PREEMPT_RT
++extern void do_softirq_post_smp_call_flush(unsigned int was_pending);
++#else
++static inline void do_softirq_post_smp_call_flush(unsigned int unused)
++{
++ do_softirq();
++}
++#endif
++
+ extern void open_softirq(int nr, void (*action)(struct softirq_action *));
+ extern void softirq_init(void);
+ extern void __raise_softirq_irqoff(unsigned int nr);
+--- a/kernel/smp.c
++++ b/kernel/smp.c
+@@ -696,6 +696,7 @@ static void __flush_smp_call_function_qu
+ */
+ void flush_smp_call_function_queue(void)
+ {
++ unsigned int was_pending;
+ unsigned long flags;
+
+ if (llist_empty(this_cpu_ptr(&call_single_queue)))
+@@ -704,9 +705,11 @@ void flush_smp_call_function_queue(void)
+ cfd_seq_store(this_cpu_ptr(&cfd_seq_local)->idle, CFD_SEQ_NOCPU,
+ smp_processor_id(), CFD_SEQ_IDLE);
+ local_irq_save(flags);
++ /* Get the already pending soft interrupts for RT enabled kernels */
++ was_pending = local_softirq_pending();
+ __flush_smp_call_function_queue(true);
+ if (local_softirq_pending())
+- do_softirq();
++ do_softirq_post_smp_call_flush(was_pending);
+
+ local_irq_restore(flags);
+ }
+--- a/kernel/softirq.c
++++ b/kernel/softirq.c
+@@ -294,6 +294,19 @@ static inline void invoke_softirq(void)
+ wakeup_softirqd();
+ }
+
++/*
++ * flush_smp_call_function_queue() can raise a soft interrupt in a function
++ * call. On RT kernels this is undesired and the only known functionality
++ * in the block layer which does this is disabled on RT. If soft interrupts
++ * get raised which haven't been raised before the flush, warn so it can be
++ * investigated.
++ */
++void do_softirq_post_smp_call_flush(unsigned int was_pending)
++{
++ if (WARN_ON_ONCE(was_pending != local_softirq_pending()))
++ invoke_softirq();
++}
++
+ #else /* CONFIG_PREEMPT_RT */
+
+ /*
diff --git a/patches/0004-drm-i915-Don-t-disable-interrupts-on-PREEMPT_RT-duri.patch b/patches/0004-drm-i915-Don-t-disable-interrupts-on-PREEMPT_RT-duri.patch
index 9cc17b2707d8..682209bf95f6 100644
--- a/patches/0004-drm-i915-Don-t-disable-interrupts-on-PREEMPT_RT-duri.patch
+++ b/patches/0004-drm-i915-Don-t-disable-interrupts-on-PREEMPT_RT-duri.patch
@@ -36,7 +36,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
--- a/drivers/gpu/drm/i915/display/intel_crtc.c
+++ b/drivers/gpu/drm/i915/display/intel_crtc.c
-@@ -517,7 +517,8 @@ void intel_pipe_update_start(struct inte
+@@ -518,7 +518,8 @@ void intel_pipe_update_start(struct inte
*/
intel_psr_wait_for_idle(new_crtc_state);
@@ -46,7 +46,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
crtc->debug.min_vbl = min;
crtc->debug.max_vbl = max;
-@@ -542,11 +543,13 @@ void intel_pipe_update_start(struct inte
+@@ -543,11 +544,13 @@ void intel_pipe_update_start(struct inte
break;
}
@@ -62,7 +62,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
}
finish_wait(wq, &wait);
-@@ -579,7 +582,8 @@ void intel_pipe_update_start(struct inte
+@@ -580,7 +583,8 @@ void intel_pipe_update_start(struct inte
return;
irq_disable:
@@ -72,7 +72,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
}
#if IS_ENABLED(CONFIG_DRM_I915_DEBUG_VBLANK_EVADE)
-@@ -678,7 +682,8 @@ void intel_pipe_update_end(struct intel_
+@@ -679,7 +683,8 @@ void intel_pipe_update_end(struct intel_
*/
intel_vrr_send_push(new_crtc_state);
diff --git a/patches/0004-kernel-fork-Don-t-assign-the-stack-pointer-in-dup_ta.patch b/patches/0004-kernel-fork-Don-t-assign-the-stack-pointer-in-dup_ta.patch
deleted file mode 100644
index d36deb2ca4dc..000000000000
--- a/patches/0004-kernel-fork-Don-t-assign-the-stack-pointer-in-dup_ta.patch
+++ /dev/null
@@ -1,150 +0,0 @@
-From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
-Date: Thu, 17 Feb 2022 11:24:02 +0100
-Subject: [PATCH 4/8] kernel/fork: Don't assign the stack pointer in
- dup_task_struct().
-
-All four versions of alloc_thread_stack_node() assign now
-task_struct::stack in case the allocation was successful.
-
-Let alloc_thread_stack_node() return an error code instead of the stack
-pointer and remove the stack assignment in dup_task_struct().
-
-Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
-Acked-by: Andy Lutomirski <luto@kernel.org>
-Link: https://lore.kernel.org/r/20220217102406.3697941-5-bigeasy@linutronix.de
----
- kernel/fork.c | 47 ++++++++++++++++-------------------------------
- 1 file changed, 16 insertions(+), 31 deletions(-)
-
---- a/kernel/fork.c
-+++ b/kernel/fork.c
-@@ -211,7 +211,7 @@ static int free_vm_stack_cache(unsigned
- return 0;
- }
-
--static unsigned long *alloc_thread_stack_node(struct task_struct *tsk, int node)
-+static int alloc_thread_stack_node(struct task_struct *tsk, int node)
- {
- void *stack;
- int i;
-@@ -232,7 +232,7 @@ static unsigned long *alloc_thread_stack
-
- tsk->stack_vm_area = s;
- tsk->stack = s->addr;
-- return s->addr;
-+ return 0;
- }
-
- /*
-@@ -245,17 +245,16 @@ static unsigned long *alloc_thread_stack
- THREADINFO_GFP & ~__GFP_ACCOUNT,
- PAGE_KERNEL,
- 0, node, __builtin_return_address(0));
--
-+ if (!stack)
-+ return -ENOMEM;
- /*
- * We can't call find_vm_area() in interrupt context, and
- * free_thread_stack() can be called in interrupt context,
- * so cache the vm_struct.
- */
-- if (stack) {
-- tsk->stack_vm_area = find_vm_area(stack);
-- tsk->stack = stack;
-- }
-- return stack;
-+ tsk->stack_vm_area = find_vm_area(stack);
-+ tsk->stack = stack;
-+ return 0;
- }
-
- static void free_thread_stack(struct task_struct *tsk)
-@@ -282,16 +281,16 @@ static void free_thread_stack(struct tas
-
- # else /* !CONFIG_VMAP_STACK */
-
--static unsigned long *alloc_thread_stack_node(struct task_struct *tsk, int node)
-+static int alloc_thread_stack_node(struct task_struct *tsk, int node)
- {
- struct page *page = alloc_pages_node(node, THREADINFO_GFP,
- THREAD_SIZE_ORDER);
-
- if (likely(page)) {
- tsk->stack = kasan_reset_tag(page_address(page));
-- return tsk->stack;
-+ return 0;
- }
-- return NULL;
-+ return -ENOMEM;
- }
-
- static void free_thread_stack(struct task_struct *tsk)
-@@ -305,14 +304,13 @@ static void free_thread_stack(struct tas
-
- static struct kmem_cache *thread_stack_cache;
-
--static unsigned long *alloc_thread_stack_node(struct task_struct *tsk,
-- int node)
-+static int alloc_thread_stack_node(struct task_struct *tsk, int node)
- {
- unsigned long *stack;
- stack = kmem_cache_alloc_node(thread_stack_cache, THREADINFO_GFP, node);
- stack = kasan_reset_tag(stack);
- tsk->stack = stack;
-- return stack;
-+ return stack ? 0 : -ENOMEM;
- }
-
- static void free_thread_stack(struct task_struct *tsk)
-@@ -332,13 +330,13 @@ void thread_stack_cache_init(void)
- # endif /* THREAD_SIZE >= PAGE_SIZE || defined(CONFIG_VMAP_STACK) */
- #else /* CONFIG_ARCH_THREAD_STACK_ALLOCATOR */
-
--static unsigned long *alloc_thread_stack_node(struct task_struct *tsk, int node)
-+static int alloc_thread_stack_node(struct task_struct *tsk, int node)
- {
- unsigned long *stack;
-
- stack = arch_alloc_thread_stack_node(tsk, node);
- tsk->stack = stack;
-- return stack;
-+ return stack ? 0 : -ENOMEM;
- }
-
- static void free_thread_stack(struct task_struct *tsk)
-@@ -895,8 +893,6 @@ void set_task_stack_end_magic(struct tas
- static struct task_struct *dup_task_struct(struct task_struct *orig, int node)
- {
- struct task_struct *tsk;
-- unsigned long *stack;
-- struct vm_struct *stack_vm_area __maybe_unused;
- int err;
-
- if (node == NUMA_NO_NODE)
-@@ -909,24 +905,13 @@ static struct task_struct *dup_task_stru
- if (err)
- goto free_tsk;
-
-- stack = alloc_thread_stack_node(tsk, node);
-- if (!stack)
-+ err = alloc_thread_stack_node(tsk, node);
-+ if (err)
- goto free_tsk;
-
- if (memcg_charge_kernel_stack(tsk))
- goto free_stack;
-
-- stack_vm_area = task_stack_vm_area(tsk);
--
-- /*
-- * arch_dup_task_struct() clobbers the stack-related fields. Make
-- * sure they're properly initialized before using any stack-related
-- * functions again.
-- */
-- tsk->stack = stack;
--#ifdef CONFIG_VMAP_STACK
-- tsk->stack_vm_area = stack_vm_area;
--#endif
- #ifdef CONFIG_THREAD_INFO_IN_TASK
- refcount_set(&tsk->stack_refcount, 1);
- #endif
diff --git a/patches/0004-misc-hi6421-spmi-pmic-Use-generic_handle_irq_safe.patch b/patches/0004-misc-hi6421-spmi-pmic-Use-generic_handle_irq_safe.patch
deleted file mode 100644
index e2b51bde32ba..000000000000
--- a/patches/0004-misc-hi6421-spmi-pmic-Use-generic_handle_irq_safe.patch
+++ /dev/null
@@ -1,42 +0,0 @@
-From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
-Date: Fri, 11 Feb 2022 19:14:57 +0100
-Subject: [PATCH 4/7] misc: hi6421-spmi-pmic: Use generic_handle_irq_safe().
-
-generic_handle_irq() is invoked from a regular interrupt service
-routine. This handler will become a forced-threaded handler on
-PREEMPT_RT and will be invoked with enabled interrupts. The
-generic_handle_irq() must be invoked with disabled interrupts in order
-to avoid deadlocks.
-
-Instead of manually disabling interrupts before invoking use
-generic_handle_irq_safe() which can be invoked with enabled and disabled
-interrupts.
-
-Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
-Link: https://lore.kernel.org/r/20220211181500.1856198-5-bigeasy@linutronix.de
----
- drivers/misc/hi6421v600-irq.c | 6 +++---
- 1 file changed, 3 insertions(+), 3 deletions(-)
-
---- a/drivers/misc/hi6421v600-irq.c
-+++ b/drivers/misc/hi6421v600-irq.c
-@@ -117,8 +117,8 @@ static irqreturn_t hi6421v600_irq_handle
- * If both powerkey down and up IRQs are received,
- * handle them at the right order
- */
-- generic_handle_irq(priv->irqs[POWERKEY_DOWN]);
-- generic_handle_irq(priv->irqs[POWERKEY_UP]);
-+ generic_handle_irq_safe(priv->irqs[POWERKEY_DOWN]);
-+ generic_handle_irq_safe(priv->irqs[POWERKEY_UP]);
- pending &= ~HISI_IRQ_POWERKEY_UP_DOWN;
- }
-
-@@ -126,7 +126,7 @@ static irqreturn_t hi6421v600_irq_handle
- continue;
-
- for_each_set_bit(offset, &pending, BITS_PER_BYTE) {
-- generic_handle_irq(priv->irqs[offset + i * BITS_PER_BYTE]);
-+ generic_handle_irq_safe(priv->irqs[offset + i * BITS_PER_BYTE]);
- }
- }
-
diff --git a/patches/0004-mm-memcg-Opencode-the-inner-part-of-obj_cgroup_uncha.patch b/patches/0004-mm-memcg-Opencode-the-inner-part-of-obj_cgroup_uncha.patch
deleted file mode 100644
index 1b53e598011b..000000000000
--- a/patches/0004-mm-memcg-Opencode-the-inner-part-of-obj_cgroup_uncha.patch
+++ /dev/null
@@ -1,75 +0,0 @@
-From: Johannes Weiner <hannes@cmpxchg.org>
-Date: Thu, 17 Feb 2022 10:48:01 +0100
-Subject: [PATCH 4/8] mm/memcg: Opencode the inner part of
- obj_cgroup_uncharge_pages() in drain_obj_stock()
-
-Provide the inner part of refill_stock() as __refill_stock() without
-disabling interrupts. This eases the integration of local_lock_t where
-recursive locking must be avoided.
-Open code obj_cgroup_uncharge_pages() in drain_obj_stock() and use
-__refill_stock(). The caller of drain_obj_stock() already disables
-interrupts.
-
-[bigeasy: Patch body around Johannes' diff ]
-
-Signed-off-by: Johannes Weiner <hannes@cmpxchg.org>
-Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
-Reviewed-by: Shakeel Butt <shakeelb@google.com>
-Reviewed-by: Roman Gushchin <guro@fb.com>
-Acked-by: Michal Hocko <mhocko@suse.com>
----
- mm/memcontrol.c | 26 ++++++++++++++++++++------
- 1 file changed, 20 insertions(+), 6 deletions(-)
-
---- a/mm/memcontrol.c
-+++ b/mm/memcontrol.c
-@@ -2247,12 +2247,9 @@ static void drain_local_stock(struct wor
- * Cache charges(val) to local per_cpu area.
- * This will be consumed by consume_stock() function, later.
- */
--static void refill_stock(struct mem_cgroup *memcg, unsigned int nr_pages)
-+static void __refill_stock(struct mem_cgroup *memcg, unsigned int nr_pages)
- {
- struct memcg_stock_pcp *stock;
-- unsigned long flags;
--
-- local_irq_save(flags);
-
- stock = this_cpu_ptr(&memcg_stock);
- if (stock->cached != memcg) { /* reset if necessary */
-@@ -2264,7 +2261,14 @@ static void refill_stock(struct mem_cgro
-
- if (stock->nr_pages > MEMCG_CHARGE_BATCH)
- drain_stock(stock);
-+}
-
-+static void refill_stock(struct mem_cgroup *memcg, unsigned int nr_pages)
-+{
-+ unsigned long flags;
-+
-+ local_irq_save(flags);
-+ __refill_stock(memcg, nr_pages);
- local_irq_restore(flags);
- }
-
-@@ -3171,8 +3175,18 @@ static void drain_obj_stock(struct memcg
- unsigned int nr_pages = stock->nr_bytes >> PAGE_SHIFT;
- unsigned int nr_bytes = stock->nr_bytes & (PAGE_SIZE - 1);
-
-- if (nr_pages)
-- obj_cgroup_uncharge_pages(old, nr_pages);
-+ if (nr_pages) {
-+ struct mem_cgroup *memcg;
-+
-+ memcg = get_mem_cgroup_from_objcg(old);
-+
-+ if (!cgroup_subsys_on_dfl(memory_cgrp_subsys))
-+ page_counter_uncharge(&memcg->kmem, nr_pages);
-+
-+ __refill_stock(memcg, nr_pages);
-+
-+ css_put(&memcg->css);
-+ }
-
- /*
- * The leftover is flushed to the centralized per-memcg value.
diff --git a/patches/0004-printk-wake-up-all-waiters.patch b/patches/0004-printk-wake-up-all-waiters.patch
new file mode 100644
index 000000000000..640a0ba4c84e
--- /dev/null
+++ b/patches/0004-printk-wake-up-all-waiters.patch
@@ -0,0 +1,26 @@
+From: John Ogness <john.ogness@linutronix.de>
+Date: Wed, 20 Apr 2022 01:52:26 +0206
+Subject: [PATCH 04/15] printk: wake up all waiters
+
+There can be multiple tasks waiting for new records. They should
+all be woken. Use wake_up_interruptible_all() instead of
+wake_up_interruptible().
+
+Signed-off-by: John Ogness <john.ogness@linutronix.de>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Link: https://lore.kernel.org/r/20220419234637.357112-5-john.ogness@linutronix.de
+---
+ kernel/printk/printk.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/kernel/printk/printk.c
++++ b/kernel/printk/printk.c
+@@ -3326,7 +3326,7 @@ static void wake_up_klogd_work_func(stru
+ }
+
+ if (pending & PRINTK_PENDING_WAKEUP)
+- wake_up_interruptible(&log_wait);
++ wake_up_interruptible_all(&log_wait);
+ }
+
+ static DEFINE_PER_CPU(struct irq_work, wake_up_klogd_work) =
diff --git a/patches/0004-random-defer-fast-pool-mixing-to-worker.patch b/patches/0004-random-defer-fast-pool-mixing-to-worker.patch
deleted file mode 100644
index b7482f5c948b..000000000000
--- a/patches/0004-random-defer-fast-pool-mixing-to-worker.patch
+++ /dev/null
@@ -1,177 +0,0 @@
-From: "Jason A. Donenfeld" <Jason@zx2c4.com>
-Date: Fri, 4 Feb 2022 16:15:46 +0100
-Subject: [PATCH 4/5] random: defer fast pool mixing to worker
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-On PREEMPT_RT, it's problematic to take spinlocks from hard irq
-handlers. We can fix this by deferring to a workqueue the dumping of
-the fast pool into the input pool.
-
-We accomplish this with some careful rules on fast_pool->count:
-
- - When it's incremented to >= 64, we schedule the work.
- - If the top bit is set, we never schedule the work, even if >= 64.
- - The worker is responsible for setting it back to 0 when it's done.
-
-There are two small issues around using workqueues for this purpose that
-we work around.
-
-The first issue is that mix_interrupt_randomness() might be migrated to
-another CPU during CPU hotplug. This issue is rectified by checking that
-it hasn't been migrated (after disabling irqs). If it has been migrated,
-then we set the count to zero, so that when the CPU comes online again,
-it can requeue the work. As part of this, we switch to using an
-atomic_t, so that the increment in the irq handler doesn't wipe out the
-zeroing if the CPU comes back online while this worker is running.
-
-The second issue is that, though relatively minor in effect, we probably
-want to make sure we get a consistent view of the pool onto the stack,
-in case it's interrupted by an irq while reading. To do this, we don't
-reenable irqs until after the copy. There are only 18 instructions
-between the cli and sti, so this is a pretty tiny window.
-
-Cc: Thomas Gleixner <tglx@linutronix.de>
-Cc: Peter Zijlstra <peterz@infradead.org>
-Cc: Theodore Ts'o <tytso@mit.edu>
-Cc: Jonathan Neuschäfer <j.neuschaefer@gmx.net>
-Acked-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
-Reviewed-by: Sultan Alsawaf <sultan@kerneltoast.com>
-Reviewed-by: Dominik Brodowski <linux@dominikbrodowski.net>
-Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
-Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
----
- drivers/char/random.c | 70 +++++++++++++++++++++++++++++++++++---------------
- 1 file changed, 50 insertions(+), 20 deletions(-)
-
---- a/drivers/char/random.c
-+++ b/drivers/char/random.c
-@@ -390,12 +390,6 @@ static void _mix_pool_bytes(const void *
- blake2s_update(&input_pool.hash, in, nbytes);
- }
-
--static void __mix_pool_bytes(const void *in, int nbytes)
--{
-- trace_mix_pool_bytes_nolock(nbytes, _RET_IP_);
-- _mix_pool_bytes(in, nbytes);
--}
--
- static void mix_pool_bytes(const void *in, int nbytes)
- {
- unsigned long flags;
-@@ -408,9 +402,10 @@ static void mix_pool_bytes(const void *i
-
- struct fast_pool {
- u32 pool[4];
-+ struct work_struct mix;
- unsigned long last;
-+ atomic_t count;
- u16 reg_idx;
-- u8 count;
- };
-
- /*
-@@ -441,7 +436,6 @@ static void fast_mix(struct fast_pool *f
-
- f->pool[0] = a; f->pool[1] = b;
- f->pool[2] = c; f->pool[3] = d;
-- f->count++;
- }
-
- static void process_random_ready_list(void)
-@@ -1048,14 +1042,51 @@ static u32 get_reg(struct fast_pool *f,
- return *ptr;
- }
-
-+static void mix_interrupt_randomness(struct work_struct *work)
-+{
-+ struct fast_pool *fast_pool = container_of(work, struct fast_pool, mix);
-+ u32 pool[4];
-+
-+ /* Check to see if we're running on the wrong CPU due to hotplug. */
-+ local_irq_disable();
-+ if (fast_pool != this_cpu_ptr(&irq_randomness)) {
-+ local_irq_enable();
-+ /*
-+ * If we are unlucky enough to have been moved to another CPU,
-+ * during CPU hotplug while the CPU was shutdown then we set
-+ * our count to zero atomically so that when the CPU comes
-+ * back online, it can enqueue work again. The _release here
-+ * pairs with the atomic_inc_return_acquire in
-+ * add_interrupt_randomness().
-+ */
-+ atomic_set_release(&fast_pool->count, 0);
-+ return;
-+ }
-+
-+ /*
-+ * Copy the pool to the stack so that the mixer always has a
-+ * consistent view, before we reenable irqs again.
-+ */
-+ memcpy(pool, fast_pool->pool, sizeof(pool));
-+ atomic_set(&fast_pool->count, 0);
-+ fast_pool->last = jiffies;
-+ local_irq_enable();
-+
-+ mix_pool_bytes(pool, sizeof(pool));
-+ credit_entropy_bits(1);
-+ memzero_explicit(pool, sizeof(pool));
-+}
-+
- void add_interrupt_randomness(int irq)
- {
-+ enum { MIX_INFLIGHT = 1U << 31 };
- struct fast_pool *fast_pool = this_cpu_ptr(&irq_randomness);
- struct pt_regs *regs = get_irq_regs();
- unsigned long now = jiffies;
- cycles_t cycles = random_get_entropy();
- u32 c_high, j_high;
- u64 ip;
-+ unsigned int new_count;
-
- if (cycles == 0)
- cycles = get_reg(fast_pool, regs);
-@@ -1069,31 +1100,30 @@ void add_interrupt_randomness(int irq)
- (sizeof(ip) > 4) ? ip >> 32 : get_reg(fast_pool, regs);
-
- fast_mix(fast_pool);
-+ /* The _acquire here pairs with the atomic_set_release in mix_interrupt_randomness(). */
-+ new_count = (unsigned int)atomic_inc_return_acquire(&fast_pool->count);
-+
- add_interrupt_bench(cycles);
-
- if (unlikely(crng_init == 0)) {
-- if ((fast_pool->count >= 64) &&
-+ if ((new_count >= 64) &&
- crng_fast_load((u8 *)fast_pool->pool, sizeof(fast_pool->pool)) > 0) {
-- fast_pool->count = 0;
-+ atomic_set(&fast_pool->count, 0);
- fast_pool->last = now;
- }
- return;
- }
-
-- if ((fast_pool->count < 64) && !time_after(now, fast_pool->last + HZ))
-+ if (new_count & MIX_INFLIGHT)
- return;
-
-- if (!spin_trylock(&input_pool.lock))
-+ if ((new_count < 64) && !time_after(now, fast_pool->last + HZ))
- return;
-
-- fast_pool->last = now;
-- __mix_pool_bytes(&fast_pool->pool, sizeof(fast_pool->pool));
-- spin_unlock(&input_pool.lock);
--
-- fast_pool->count = 0;
--
-- /* award one bit for the contents of the fast pool */
-- credit_entropy_bits(1);
-+ if (unlikely(!fast_pool->mix.func))
-+ INIT_WORK(&fast_pool->mix, mix_interrupt_randomness);
-+ atomic_or(MIX_INFLIGHT, &fast_pool->count);
-+ queue_work_on(raw_smp_processor_id(), system_highpri_wq, &fast_pool->mix);
- }
- EXPORT_SYMBOL_GPL(add_interrupt_randomness);
-
diff --git a/patches/0005-drm-i915-Don-t-check-for-atomic-context-on-PREEMPT_R.patch b/patches/0005-drm-i915-Don-t-check-for-atomic-context-on-PREEMPT_R.patch
index 723c24bb124b..f8c949d0d686 100644
--- a/patches/0005-drm-i915-Don-t-check-for-atomic-context-on-PREEMPT_R.patch
+++ b/patches/0005-drm-i915-Don-t-check-for-atomic-context-on-PREEMPT_R.patch
@@ -18,7 +18,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
--- a/drivers/gpu/drm/i915/i915_utils.h
+++ b/drivers/gpu/drm/i915/i915_utils.h
-@@ -344,7 +344,7 @@ wait_remaining_ms_from_jiffies(unsigned
+@@ -329,7 +329,7 @@ wait_remaining_ms_from_jiffies(unsigned
#define wait_for(COND, MS) _wait_for((COND), (MS) * 1000, 10, 1000)
/* If CONFIG_PREEMPT_COUNT is disabled, in_atomic() always reports false. */
diff --git a/patches/0005-kernel-fork-Move-memcg_charge_kernel_stack-into-CONF.patch b/patches/0005-kernel-fork-Move-memcg_charge_kernel_stack-into-CONF.patch
deleted file mode 100644
index b2e7fa2ec309..000000000000
--- a/patches/0005-kernel-fork-Move-memcg_charge_kernel_stack-into-CONF.patch
+++ /dev/null
@@ -1,123 +0,0 @@
-From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
-Date: Thu, 17 Feb 2022 11:24:03 +0100
-Subject: [PATCH 5/8] kernel/fork: Move memcg_charge_kernel_stack() into
- CONFIG_VMAP_STACK.
-
-memcg_charge_kernel_stack() is only used in the CONFIG_VMAP_STACK case.
-
-Move memcg_charge_kernel_stack() into the CONFIG_VMAP_STACK block and
-invoke it from within alloc_thread_stack_node().
-
-Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
-Acked-by: Andy Lutomirski <luto@kernel.org>
-Link: https://lore.kernel.org/r/20220217102406.3697941-6-bigeasy@linutronix.de
----
- kernel/fork.c | 69 ++++++++++++++++++++++++++++++----------------------------
- 1 file changed, 36 insertions(+), 33 deletions(-)
-
---- a/kernel/fork.c
-+++ b/kernel/fork.c
-@@ -211,6 +211,32 @@ static int free_vm_stack_cache(unsigned
- return 0;
- }
-
-+static int memcg_charge_kernel_stack(struct task_struct *tsk)
-+{
-+ struct vm_struct *vm = task_stack_vm_area(tsk);
-+ int i;
-+ int ret;
-+
-+ BUILD_BUG_ON(IS_ENABLED(CONFIG_VMAP_STACK) && PAGE_SIZE % 1024 != 0);
-+ BUG_ON(vm->nr_pages != THREAD_SIZE / PAGE_SIZE);
-+
-+ for (i = 0; i < THREAD_SIZE / PAGE_SIZE; i++) {
-+ ret = memcg_kmem_charge_page(vm->pages[i], GFP_KERNEL, 0);
-+ if (ret)
-+ goto err;
-+ }
-+ return 0;
-+err:
-+ /*
-+ * If memcg_kmem_charge_page() fails, page's memory cgroup pointer is
-+ * NULL, and memcg_kmem_uncharge_page() in free_thread_stack() will
-+ * ignore this page.
-+ */
-+ for (i = 0; i < THREAD_SIZE / PAGE_SIZE; i++)
-+ memcg_kmem_uncharge_page(vm->pages[i], 0);
-+ return ret;
-+}
-+
- static int alloc_thread_stack_node(struct task_struct *tsk, int node)
- {
- void *stack;
-@@ -230,6 +256,11 @@ static int alloc_thread_stack_node(struc
- /* Clear stale pointers from reused stack. */
- memset(s->addr, 0, THREAD_SIZE);
-
-+ if (memcg_charge_kernel_stack(tsk)) {
-+ vfree(s->addr);
-+ return -ENOMEM;
-+ }
-+
- tsk->stack_vm_area = s;
- tsk->stack = s->addr;
- return 0;
-@@ -247,6 +278,11 @@ static int alloc_thread_stack_node(struc
- 0, node, __builtin_return_address(0));
- if (!stack)
- return -ENOMEM;
-+
-+ if (memcg_charge_kernel_stack(tsk)) {
-+ vfree(stack);
-+ return -ENOMEM;
-+ }
- /*
- * We can't call find_vm_area() in interrupt context, and
- * free_thread_stack() can be called in interrupt context,
-@@ -418,36 +454,6 @@ static void account_kernel_stack(struct
- }
- }
-
--static int memcg_charge_kernel_stack(struct task_struct *tsk)
--{
--#ifdef CONFIG_VMAP_STACK
-- struct vm_struct *vm = task_stack_vm_area(tsk);
-- int ret;
--
-- BUILD_BUG_ON(IS_ENABLED(CONFIG_VMAP_STACK) && PAGE_SIZE % 1024 != 0);
--
-- if (vm) {
-- int i;
--
-- BUG_ON(vm->nr_pages != THREAD_SIZE / PAGE_SIZE);
--
-- for (i = 0; i < THREAD_SIZE / PAGE_SIZE; i++) {
-- /*
-- * If memcg_kmem_charge_page() fails, page's
-- * memory cgroup pointer is NULL, and
-- * memcg_kmem_uncharge_page() in free_thread_stack()
-- * will ignore this page.
-- */
-- ret = memcg_kmem_charge_page(vm->pages[i], GFP_KERNEL,
-- 0);
-- if (ret)
-- return ret;
-- }
-- }
--#endif
-- return 0;
--}
--
- static void release_task_stack(struct task_struct *tsk)
- {
- if (WARN_ON(READ_ONCE(tsk->__state) != TASK_DEAD))
-@@ -909,9 +915,6 @@ static struct task_struct *dup_task_stru
- if (err)
- goto free_tsk;
-
-- if (memcg_charge_kernel_stack(tsk))
-- goto free_stack;
--
- #ifdef CONFIG_THREAD_INFO_IN_TASK
- refcount_set(&tsk->stack_refcount, 1);
- #endif
diff --git a/patches/0005-mfd-ezx-pcap-Use-generic_handle_irq_safe.patch b/patches/0005-mfd-ezx-pcap-Use-generic_handle_irq_safe.patch
deleted file mode 100644
index 838e5df787cd..000000000000
--- a/patches/0005-mfd-ezx-pcap-Use-generic_handle_irq_safe.patch
+++ /dev/null
@@ -1,31 +0,0 @@
-From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
-Date: Fri, 11 Feb 2022 19:14:58 +0100
-Subject: [PATCH 5/7] mfd: ezx-pcap: Use generic_handle_irq_safe().
-
-Instead of manually disabling interrupts before invoking use
-generic_handle_irq_safe() which can be invoked with enabled and disabled
-interrupts.
-
-Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
-Link: https://lore.kernel.org/r/20220211181500.1856198-6-bigeasy@linutronix.de
----
- drivers/mfd/ezx-pcap.c | 4 +---
- 1 file changed, 1 insertion(+), 3 deletions(-)
-
---- a/drivers/mfd/ezx-pcap.c
-+++ b/drivers/mfd/ezx-pcap.c
-@@ -193,13 +193,11 @@ static void pcap_isr_work(struct work_st
- ezx_pcap_write(pcap, PCAP_REG_MSR, isr | msr);
- ezx_pcap_write(pcap, PCAP_REG_ISR, isr);
-
-- local_irq_disable();
- service = isr & ~msr;
- for (irq = pcap->irq_base; service; service >>= 1, irq++) {
- if (service & 1)
-- generic_handle_irq(irq);
-+ generic_handle_irq_safe(irq);
- }
-- local_irq_enable();
- ezx_pcap_write(pcap, PCAP_REG_MSR, pcap->msr);
- } while (gpio_get_value(pdata->gpio));
- }
diff --git a/patches/0005-mm-memcg-Protect-memcg_stock-with-a-local_lock_t.patch b/patches/0005-mm-memcg-Protect-memcg_stock-with-a-local_lock_t.patch
deleted file mode 100644
index f5942fd16d55..000000000000
--- a/patches/0005-mm-memcg-Protect-memcg_stock-with-a-local_lock_t.patch
+++ /dev/null
@@ -1,233 +0,0 @@
-From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
-Date: Thu, 17 Feb 2022 10:48:02 +0100
-Subject: [PATCH 5/8] mm/memcg: Protect memcg_stock with a local_lock_t
-
-The members of the per-CPU structure memcg_stock_pcp are protected by
-disabling interrupts. This is not working on PREEMPT_RT because it
-creates atomic context in which actions are performed which require
-preemptible context. One example is obj_cgroup_release().
-
-The IRQ-disable sections can be replaced with local_lock_t which
-preserves the explicit disabling of interrupts while keeps the code
-preemptible on PREEMPT_RT.
-
-drain_obj_stock() drops a reference on obj_cgroup which leads to an invocation
-of obj_cgroup_release() if it is the last object. This in turn leads to
-recursive locking of the local_lock_t. To avoid this, obj_cgroup_release() is
-invoked outside of the locked section.
-
-obj_cgroup_uncharge_pages() can be invoked with the local_lock_t acquired and
-without it. This will lead later to a recursion in refill_stock(). To
-avoid the locking recursion provide obj_cgroup_uncharge_pages_locked()
-which uses the locked version of refill_stock().
-
-- Replace disabling interrupts for memcg_stock with a local_lock_t.
-
-- Let drain_obj_stock() return the old struct obj_cgroup which is passed
- to obj_cgroup_put() outside of the locked section.
-
-- Provide obj_cgroup_uncharge_pages_locked() which uses the locked
- version of refill_stock() to avoid recursive locking in
- drain_obj_stock().
-
-Link: https://lkml.kernel.org/r/20220209014709.GA26885@xsang-OptiPlex-9020
-Reported-by: kernel test robot <oliver.sang@intel.com>
-Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
----
- mm/memcontrol.c | 55 ++++++++++++++++++++++++++++++++++---------------------
- 1 file changed, 34 insertions(+), 21 deletions(-)
-
---- a/mm/memcontrol.c
-+++ b/mm/memcontrol.c
-@@ -2135,6 +2135,7 @@ void unlock_page_memcg(struct page *page
- }
-
- struct memcg_stock_pcp {
-+ local_lock_t stock_lock;
- struct mem_cgroup *cached; /* this never be root cgroup */
- unsigned int nr_pages;
-
-@@ -2150,17 +2151,20 @@ struct memcg_stock_pcp {
- unsigned long flags;
- #define FLUSHING_CACHED_CHARGE 0
- };
--static DEFINE_PER_CPU(struct memcg_stock_pcp, memcg_stock);
-+static DEFINE_PER_CPU(struct memcg_stock_pcp, memcg_stock) = {
-+ .stock_lock = INIT_LOCAL_LOCK(stock_lock),
-+};
- static DEFINE_MUTEX(percpu_charge_mutex);
-
- #ifdef CONFIG_MEMCG_KMEM
--static void drain_obj_stock(struct memcg_stock_pcp *stock);
-+static struct obj_cgroup *drain_obj_stock(struct memcg_stock_pcp *stock);
- static bool obj_stock_flush_required(struct memcg_stock_pcp *stock,
- struct mem_cgroup *root_memcg);
-
- #else
--static inline void drain_obj_stock(struct memcg_stock_pcp *stock)
-+static inline struct obj_cgroup *drain_obj_stock(struct memcg_stock_pcp *stock)
- {
-+ return NULL;
- }
- static bool obj_stock_flush_required(struct memcg_stock_pcp *stock,
- struct mem_cgroup *root_memcg)
-@@ -2189,7 +2193,7 @@ static bool consume_stock(struct mem_cgr
- if (nr_pages > MEMCG_CHARGE_BATCH)
- return ret;
-
-- local_irq_save(flags);
-+ local_lock_irqsave(&memcg_stock.stock_lock, flags);
-
- stock = this_cpu_ptr(&memcg_stock);
- if (memcg == stock->cached && stock->nr_pages >= nr_pages) {
-@@ -2197,7 +2201,7 @@ static bool consume_stock(struct mem_cgr
- ret = true;
- }
-
-- local_irq_restore(flags);
-+ local_unlock_irqrestore(&memcg_stock.stock_lock, flags);
-
- return ret;
- }
-@@ -2226,6 +2230,7 @@ static void drain_stock(struct memcg_sto
- static void drain_local_stock(struct work_struct *dummy)
- {
- struct memcg_stock_pcp *stock;
-+ struct obj_cgroup *old = NULL;
- unsigned long flags;
-
- /*
-@@ -2233,14 +2238,16 @@ static void drain_local_stock(struct wor
- * drain_stock races is that we always operate on local CPU stock
- * here with IRQ disabled
- */
-- local_irq_save(flags);
-+ local_lock_irqsave(&memcg_stock.stock_lock, flags);
-
- stock = this_cpu_ptr(&memcg_stock);
-- drain_obj_stock(stock);
-+ old = drain_obj_stock(stock);
- drain_stock(stock);
- clear_bit(FLUSHING_CACHED_CHARGE, &stock->flags);
-
-- local_irq_restore(flags);
-+ local_unlock_irqrestore(&memcg_stock.stock_lock, flags);
-+ if (old)
-+ obj_cgroup_put(old);
- }
-
- /*
-@@ -2267,9 +2274,9 @@ static void refill_stock(struct mem_cgro
- {
- unsigned long flags;
-
-- local_irq_save(flags);
-+ local_lock_irqsave(&memcg_stock.stock_lock, flags);
- __refill_stock(memcg, nr_pages);
-- local_irq_restore(flags);
-+ local_unlock_irqrestore(&memcg_stock.stock_lock, flags);
- }
-
- /*
-@@ -3086,10 +3093,11 @@ void mod_objcg_state(struct obj_cgroup *
- enum node_stat_item idx, int nr)
- {
- struct memcg_stock_pcp *stock;
-+ struct obj_cgroup *old = NULL;
- unsigned long flags;
- int *bytes;
-
-- local_irq_save(flags);
-+ local_lock_irqsave(&memcg_stock.stock_lock, flags);
- stock = this_cpu_ptr(&memcg_stock);
-
- /*
-@@ -3098,7 +3106,7 @@ void mod_objcg_state(struct obj_cgroup *
- * changes.
- */
- if (stock->cached_objcg != objcg) {
-- drain_obj_stock(stock);
-+ old = drain_obj_stock(stock);
- obj_cgroup_get(objcg);
- stock->nr_bytes = atomic_read(&objcg->nr_charged_bytes)
- ? atomic_xchg(&objcg->nr_charged_bytes, 0) : 0;
-@@ -3142,7 +3150,9 @@ void mod_objcg_state(struct obj_cgroup *
- if (nr)
- mod_objcg_mlstate(objcg, pgdat, idx, nr);
-
-- local_irq_restore(flags);
-+ local_unlock_irqrestore(&memcg_stock.stock_lock, flags);
-+ if (old)
-+ obj_cgroup_put(old);
- }
-
- static bool consume_obj_stock(struct obj_cgroup *objcg, unsigned int nr_bytes)
-@@ -3151,7 +3161,7 @@ static bool consume_obj_stock(struct obj
- unsigned long flags;
- bool ret = false;
-
-- local_irq_save(flags);
-+ local_lock_irqsave(&memcg_stock.stock_lock, flags);
-
- stock = this_cpu_ptr(&memcg_stock);
- if (objcg == stock->cached_objcg && stock->nr_bytes >= nr_bytes) {
-@@ -3159,17 +3169,17 @@ static bool consume_obj_stock(struct obj
- ret = true;
- }
-
-- local_irq_restore(flags);
-+ local_unlock_irqrestore(&memcg_stock.stock_lock, flags);
-
- return ret;
- }
-
--static void drain_obj_stock(struct memcg_stock_pcp *stock)
-+static struct obj_cgroup *drain_obj_stock(struct memcg_stock_pcp *stock)
- {
- struct obj_cgroup *old = stock->cached_objcg;
-
- if (!old)
-- return;
-+ return NULL;
-
- if (stock->nr_bytes) {
- unsigned int nr_pages = stock->nr_bytes >> PAGE_SHIFT;
-@@ -3221,8 +3231,8 @@ static void drain_obj_stock(struct memcg
- stock->cached_pgdat = NULL;
- }
-
-- obj_cgroup_put(old);
- stock->cached_objcg = NULL;
-+ return old;
- }
-
- static bool obj_stock_flush_required(struct memcg_stock_pcp *stock,
-@@ -3243,14 +3253,15 @@ static void refill_obj_stock(struct obj_
- bool allow_uncharge)
- {
- struct memcg_stock_pcp *stock;
-+ struct obj_cgroup *old = NULL;
- unsigned long flags;
- unsigned int nr_pages = 0;
-
-- local_irq_save(flags);
-+ local_lock_irqsave(&memcg_stock.stock_lock, flags);
-
- stock = this_cpu_ptr(&memcg_stock);
- if (stock->cached_objcg != objcg) { /* reset if necessary */
-- drain_obj_stock(stock);
-+ old = drain_obj_stock(stock);
- obj_cgroup_get(objcg);
- stock->cached_objcg = objcg;
- stock->nr_bytes = atomic_read(&objcg->nr_charged_bytes)
-@@ -3264,7 +3275,9 @@ static void refill_obj_stock(struct obj_
- stock->nr_bytes &= (PAGE_SIZE - 1);
- }
-
-- local_irq_restore(flags);
-+ local_unlock_irqrestore(&memcg_stock.stock_lock, flags);
-+ if (old)
-+ obj_cgroup_put(old);
-
- if (nr_pages)
- obj_cgroup_uncharge_pages(objcg, nr_pages);
diff --git a/patches/0005-printk-wake-waiters-for-safe-and-NMI-contexts.patch b/patches/0005-printk-wake-waiters-for-safe-and-NMI-contexts.patch
new file mode 100644
index 000000000000..357164da0fd7
--- /dev/null
+++ b/patches/0005-printk-wake-waiters-for-safe-and-NMI-contexts.patch
@@ -0,0 +1,85 @@
+From: John Ogness <john.ogness@linutronix.de>
+Date: Wed, 20 Apr 2022 01:52:27 +0206
+Subject: [PATCH 05/15] printk: wake waiters for safe and NMI contexts
+
+When printk() is called from safe or NMI contexts, it will directly
+store the record (vprintk_store()) and then defer the console output.
+However, defer_console_output() only causes console printing and does
+not wake any waiters of new records.
+
+Wake waiters from defer_console_output() so that they also are aware
+of the new records from safe and NMI contexts.
+
+Fixes: 03fc7f9c99c1 ("printk/nmi: Prevent deadlock when accessing the main log buffer in NMI")
+Signed-off-by: John Ogness <john.ogness@linutronix.de>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Link: https://lore.kernel.org/r/20220419234637.357112-6-john.ogness@linutronix.de
+---
+ kernel/printk/printk.c | 28 ++++++++++++++++------------
+ 1 file changed, 16 insertions(+), 12 deletions(-)
+
+--- a/kernel/printk/printk.c
++++ b/kernel/printk/printk.c
+@@ -754,7 +754,7 @@ static ssize_t devkmsg_read(struct file
+ * prepare_to_wait_event() pairs with the full memory barrier
+ * within wq_has_sleeper().
+ *
+- * This pairs with wake_up_klogd:A.
++ * This pairs with __wake_up_klogd:A.
+ */
+ ret = wait_event_interruptible(log_wait,
+ prb_read_valid(prb,
+@@ -1532,7 +1532,7 @@ static int syslog_print(char __user *buf
+ * prepare_to_wait_event() pairs with the full memory barrier
+ * within wq_has_sleeper().
+ *
+- * This pairs with wake_up_klogd:A.
++ * This pairs with __wake_up_klogd:A.
+ */
+ len = wait_event_interruptible(log_wait,
+ prb_read_valid(prb, seq, NULL)); /* LMM(syslog_print:A) */
+@@ -3332,7 +3332,7 @@ static void wake_up_klogd_work_func(stru
+ static DEFINE_PER_CPU(struct irq_work, wake_up_klogd_work) =
+ IRQ_WORK_INIT_LAZY(wake_up_klogd_work_func);
+
+-void wake_up_klogd(void)
++static void __wake_up_klogd(int val)
+ {
+ if (!printk_percpu_data_ready())
+ return;
+@@ -3349,22 +3349,26 @@ void wake_up_klogd(void)
+ *
+ * This pairs with devkmsg_read:A and syslog_print:A.
+ */
+- if (wq_has_sleeper(&log_wait)) { /* LMM(wake_up_klogd:A) */
+- this_cpu_or(printk_pending, PRINTK_PENDING_WAKEUP);
++ if (wq_has_sleeper(&log_wait) || /* LMM(__wake_up_klogd:A) */
++ (val & PRINTK_PENDING_OUTPUT)) {
++ this_cpu_or(printk_pending, val);
+ irq_work_queue(this_cpu_ptr(&wake_up_klogd_work));
+ }
+ preempt_enable();
+ }
+
+-void defer_console_output(void)
++void wake_up_klogd(void)
+ {
+- if (!printk_percpu_data_ready())
+- return;
++ __wake_up_klogd(PRINTK_PENDING_WAKEUP);
++}
+
+- preempt_disable();
+- this_cpu_or(printk_pending, PRINTK_PENDING_OUTPUT);
+- irq_work_queue(this_cpu_ptr(&wake_up_klogd_work));
+- preempt_enable();
++void defer_console_output(void)
++{
++ /*
++ * New messages may have been added directly to the ringbuffer
++ * using vprintk_store(), so wake any waiters as well.
++ */
++ __wake_up_klogd(PRINTK_PENDING_WAKEUP | PRINTK_PENDING_OUTPUT);
+ }
+
+ void printk_trigger_flush(void)
diff --git a/patches/0005-random-clear-fast-pool-crng-and-batches-in-cpuhp-bri.patch b/patches/0005-random-clear-fast-pool-crng-and-batches-in-cpuhp-bri.patch
deleted file mode 100644
index 378cbd3da92d..000000000000
--- a/patches/0005-random-clear-fast-pool-crng-and-batches-in-cpuhp-bri.patch
+++ /dev/null
@@ -1,247 +0,0 @@
-From: "Jason A. Donenfeld" <Jason@zx2c4.com>
-Date: Sun, 13 Feb 2022 22:48:04 +0100
-Subject: [PATCH 5/5] random: clear fast pool, crng, and batches in cpuhp bring
- up
-
-For the irq randomness fast pool, rather than having to use expensive
-atomics, which were visibly the most expensive thing in the entire irq
-handler, simply take care of the extreme edge case of resetting count to
-zero in the cpuhp online handler, just after workqueues have been
-reenabled. This simplifies the code a bit and lets us use vanilla
-variables rather than atomics, and performance should be improved.
-
-As well, very early on when the CPU comes up, while interrupts are still
-disabled, we clear out the per-cpu crng and its batches, so that it
-always starts with fresh randomness.
-
-Cc: Thomas Gleixner <tglx@linutronix.de>
-Cc: Peter Zijlstra <peterz@infradead.org>
-Cc: Theodore Ts'o <tytso@mit.edu>
-Cc: Sultan Alsawaf <sultan@kerneltoast.com>
-Cc: Dominik Brodowski <linux@dominikbrodowski.net>
-Acked-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
-Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
-Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
----
- drivers/char/random.c | 65 +++++++++++++++++++++++++++++++-----------
- include/linux/cpuhotplug.h | 2 +
- include/linux/random.h | 5 +++
- include/trace/events/random.h | 6 ---
- kernel/cpu.c | 11 +++++++
- 5 files changed, 66 insertions(+), 23 deletions(-)
-
---- a/drivers/char/random.c
-+++ b/drivers/char/random.c
-@@ -404,7 +404,7 @@ struct fast_pool {
- u32 pool[4];
- struct work_struct mix;
- unsigned long last;
-- atomic_t count;
-+ unsigned int count;
- u16 reg_idx;
- };
-
-@@ -1006,6 +1006,29 @@ EXPORT_SYMBOL_GPL(add_input_randomness);
-
- static DEFINE_PER_CPU(struct fast_pool, irq_randomness);
-
-+#ifdef CONFIG_SMP
-+/*
-+ * This function is called when the CPU has just come online, with
-+ * entry CPUHP_AP_RANDOM_ONLINE, just after CPUHP_AP_WORKQUEUE_ONLINE.
-+ */
-+int random_online_cpu(unsigned int cpu)
-+{
-+ /*
-+ * During CPU shutdown and before CPU onlining, add_interrupt_
-+ * randomness() may schedule mix_interrupt_randomness(), and
-+ * set the MIX_INFLIGHT flag. However, because the worker can
-+ * be scheduled on a different CPU during this period, that
-+ * flag will never be cleared. For that reason, we zero out
-+ * the flag here, which runs just after workqueues are onlined
-+ * for the CPU again. This also has the effect of setting the
-+ * irq randomness count to zero so that new accumulated irqs
-+ * are fresh.
-+ */
-+ per_cpu_ptr(&irq_randomness, cpu)->count = 0;
-+ return 0;
-+}
-+#endif
-+
- #ifdef ADD_INTERRUPT_BENCH
- static unsigned long avg_cycles, avg_deviation;
-
-@@ -1051,15 +1074,6 @@ static void mix_interrupt_randomness(str
- local_irq_disable();
- if (fast_pool != this_cpu_ptr(&irq_randomness)) {
- local_irq_enable();
-- /*
-- * If we are unlucky enough to have been moved to another CPU,
-- * during CPU hotplug while the CPU was shutdown then we set
-- * our count to zero atomically so that when the CPU comes
-- * back online, it can enqueue work again. The _release here
-- * pairs with the atomic_inc_return_acquire in
-- * add_interrupt_randomness().
-- */
-- atomic_set_release(&fast_pool->count, 0);
- return;
- }
-
-@@ -1068,7 +1082,7 @@ static void mix_interrupt_randomness(str
- * consistent view, before we reenable irqs again.
- */
- memcpy(pool, fast_pool->pool, sizeof(pool));
-- atomic_set(&fast_pool->count, 0);
-+ fast_pool->count = 0;
- fast_pool->last = jiffies;
- local_irq_enable();
-
-@@ -1100,15 +1114,14 @@ void add_interrupt_randomness(int irq)
- (sizeof(ip) > 4) ? ip >> 32 : get_reg(fast_pool, regs);
-
- fast_mix(fast_pool);
-- /* The _acquire here pairs with the atomic_set_release in mix_interrupt_randomness(). */
-- new_count = (unsigned int)atomic_inc_return_acquire(&fast_pool->count);
-+ new_count = ++fast_pool->count;
-
- add_interrupt_bench(cycles);
-
- if (unlikely(crng_init == 0)) {
- if ((new_count >= 64) &&
- crng_fast_load((u8 *)fast_pool->pool, sizeof(fast_pool->pool)) > 0) {
-- atomic_set(&fast_pool->count, 0);
-+ fast_pool->count = 0;
- fast_pool->last = now;
- }
- return;
-@@ -1122,7 +1135,7 @@ void add_interrupt_randomness(int irq)
-
- if (unlikely(!fast_pool->mix.func))
- INIT_WORK(&fast_pool->mix, mix_interrupt_randomness);
-- atomic_or(MIX_INFLIGHT, &fast_pool->count);
-+ fast_pool->count |= MIX_INFLIGHT;
- queue_work_on(raw_smp_processor_id(), system_highpri_wq, &fast_pool->mix);
- }
- EXPORT_SYMBOL_GPL(add_interrupt_randomness);
-@@ -1945,7 +1958,7 @@ u64 get_random_u64(void)
- batch = raw_cpu_ptr(&batched_entropy_u64);
-
- next_gen = atomic_read(&batch_generation);
-- if (batch->position % ARRAY_SIZE(batch->entropy_u64) == 0 ||
-+ if (batch->position >= ARRAY_SIZE(batch->entropy_u64) ||
- next_gen != batch->generation) {
- extract_crng((u8 *)batch->entropy_u64);
- batch->position = 0;
-@@ -1976,7 +1989,7 @@ u32 get_random_u32(void)
- batch = raw_cpu_ptr(&batched_entropy_u32);
-
- next_gen = atomic_read(&batch_generation);
-- if (batch->position % ARRAY_SIZE(batch->entropy_u32) == 0 ||
-+ if (batch->position >= ARRAY_SIZE(batch->entropy_u32) ||
- next_gen != batch->generation) {
- extract_crng((u8 *)batch->entropy_u32);
- batch->position = 0;
-@@ -1989,6 +2002,24 @@ u32 get_random_u32(void)
- }
- EXPORT_SYMBOL(get_random_u32);
-
-+#ifdef CONFIG_SMP
-+/*
-+ * This function is called when the CPU is coming up, with entry
-+ * CPUHP_RANDOM_PREPARE, which comes before CPUHP_WORKQUEUE_PREP.
-+ */
-+int random_prepare_cpu(unsigned int cpu)
-+{
-+ /*
-+ * When the cpu comes back online, immediately invalidate both
-+ * the per-cpu crng and all batches, so that we serve fresh
-+ * randomness.
-+ */
-+ per_cpu_ptr(&batched_entropy_u32, cpu)->position = UINT_MAX;
-+ per_cpu_ptr(&batched_entropy_u64, cpu)->position = UINT_MAX;
-+ return 0;
-+}
-+#endif
-+
- /* It's important to invalidate all potential batched entropy that might
- * be stored before the crng is initialized, which we can do lazily by
- * bumping the generation counter.
---- a/include/linux/cpuhotplug.h
-+++ b/include/linux/cpuhotplug.h
-@@ -100,6 +100,7 @@ enum cpuhp_state {
- CPUHP_AP_ARM_CACHE_B15_RAC_DEAD,
- CPUHP_PADATA_DEAD,
- CPUHP_AP_DTPM_CPU_DEAD,
-+ CPUHP_RANDOM_PREPARE,
- CPUHP_WORKQUEUE_PREP,
- CPUHP_POWER_NUMA_PREPARE,
- CPUHP_HRTIMERS_PREPARE,
-@@ -240,6 +241,7 @@ enum cpuhp_state {
- CPUHP_AP_PERF_CSKY_ONLINE,
- CPUHP_AP_WATCHDOG_ONLINE,
- CPUHP_AP_WORKQUEUE_ONLINE,
-+ CPUHP_AP_RANDOM_ONLINE,
- CPUHP_AP_RCUTREE_ONLINE,
- CPUHP_AP_BASE_CACHEINFO_ONLINE,
- CPUHP_AP_ONLINE_DYN,
---- a/include/linux/random.h
-+++ b/include/linux/random.h
-@@ -158,4 +158,9 @@ static inline bool __init arch_get_rando
- }
- #endif
-
-+#ifdef CONFIG_SMP
-+extern int random_prepare_cpu(unsigned int cpu);
-+extern int random_online_cpu(unsigned int cpu);
-+#endif
-+
- #endif /* _LINUX_RANDOM_H */
---- a/include/trace/events/random.h
-+++ b/include/trace/events/random.h
-@@ -52,12 +52,6 @@ DEFINE_EVENT(random__mix_pool_bytes, mix
- TP_ARGS(bytes, IP)
- );
-
--DEFINE_EVENT(random__mix_pool_bytes, mix_pool_bytes_nolock,
-- TP_PROTO(int bytes, unsigned long IP),
--
-- TP_ARGS(bytes, IP)
--);
--
- TRACE_EVENT(credit_entropy_bits,
- TP_PROTO(int bits, int entropy_count, unsigned long IP),
-
---- a/kernel/cpu.c
-+++ b/kernel/cpu.c
-@@ -34,6 +34,7 @@
- #include <linux/scs.h>
- #include <linux/percpu-rwsem.h>
- #include <linux/cpuset.h>
-+#include <linux/random.h>
-
- #include <trace/events/power.h>
- #define CREATE_TRACE_POINTS
-@@ -1659,6 +1660,11 @@ static struct cpuhp_step cpuhp_hp_states
- .startup.single = perf_event_init_cpu,
- .teardown.single = perf_event_exit_cpu,
- },
-+ [CPUHP_RANDOM_PREPARE] = {
-+ .name = "random:prepare",
-+ .startup.single = random_prepare_cpu,
-+ .teardown.single = NULL,
-+ },
- [CPUHP_WORKQUEUE_PREP] = {
- .name = "workqueue:prepare",
- .startup.single = workqueue_prepare_cpu,
-@@ -1782,6 +1788,11 @@ static struct cpuhp_step cpuhp_hp_states
- .startup.single = workqueue_online_cpu,
- .teardown.single = workqueue_offline_cpu,
- },
-+ [CPUHP_AP_RANDOM_ONLINE] = {
-+ .name = "random:online",
-+ .startup.single = random_online_cpu,
-+ .teardown.single = NULL,
-+ },
- [CPUHP_AP_RCUTREE_ONLINE] = {
- .name = "RCU/tree:online",
- .startup.single = rcutree_online_cpu,
diff --git a/patches/0006-kernel-fork-Move-task-stack-account-to-do_exit.patch b/patches/0006-kernel-fork-Move-task-stack-account-to-do_exit.patch
deleted file mode 100644
index 871caa52934c..000000000000
--- a/patches/0006-kernel-fork-Move-task-stack-account-to-do_exit.patch
+++ /dev/null
@@ -1,164 +0,0 @@
-From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
-Date: Thu, 17 Feb 2022 11:24:04 +0100
-Subject: [PATCH 6/8] kernel/fork: Move task stack account to do_exit().
-
-There is no need to perform the stack accounting of the outgoing task in
-its final schedule() invocation which happens with disabled preemption.
-The task is leaving, the resources will be freed and the accounting can
-happen in do_exit() before the actual schedule invocation which
-frees the stack memory.
-
-Move the accounting of the stack memory from release_task_stack() to
-exit_task_stack_account() which then can be invoked from do_exit().
-
-Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
-Acked-by: Andy Lutomirski <luto@kernel.org>
-Link: https://lore.kernel.org/r/20220217102406.3697941-7-bigeasy@linutronix.de
----
- include/linux/sched/task_stack.h | 2 ++
- kernel/exit.c | 1 +
- kernel/fork.c | 35 +++++++++++++++++++++++------------
- 3 files changed, 26 insertions(+), 12 deletions(-)
-
---- a/include/linux/sched/task_stack.h
-+++ b/include/linux/sched/task_stack.h
-@@ -79,6 +79,8 @@ static inline void *try_get_task_stack(s
- static inline void put_task_stack(struct task_struct *tsk) {}
- #endif
-
-+void exit_task_stack_account(struct task_struct *tsk);
-+
- #define task_stack_end_corrupted(task) \
- (*(end_of_stack(task)) != STACK_END_MAGIC)
-
---- a/kernel/exit.c
-+++ b/kernel/exit.c
-@@ -845,6 +845,7 @@ void __noreturn do_exit(long code)
- put_page(tsk->task_frag.page);
-
- validate_creds_for_do_exit(tsk);
-+ exit_task_stack_account(tsk);
-
- check_stack_usage();
- preempt_disable();
---- a/kernel/fork.c
-+++ b/kernel/fork.c
-@@ -211,9 +211,8 @@ static int free_vm_stack_cache(unsigned
- return 0;
- }
-
--static int memcg_charge_kernel_stack(struct task_struct *tsk)
-+static int memcg_charge_kernel_stack(struct vm_struct *vm)
- {
-- struct vm_struct *vm = task_stack_vm_area(tsk);
- int i;
- int ret;
-
-@@ -239,6 +238,7 @@ static int memcg_charge_kernel_stack(str
-
- static int alloc_thread_stack_node(struct task_struct *tsk, int node)
- {
-+ struct vm_struct *vm;
- void *stack;
- int i;
-
-@@ -256,7 +256,7 @@ static int alloc_thread_stack_node(struc
- /* Clear stale pointers from reused stack. */
- memset(s->addr, 0, THREAD_SIZE);
-
-- if (memcg_charge_kernel_stack(tsk)) {
-+ if (memcg_charge_kernel_stack(s)) {
- vfree(s->addr);
- return -ENOMEM;
- }
-@@ -279,7 +279,8 @@ static int alloc_thread_stack_node(struc
- if (!stack)
- return -ENOMEM;
-
-- if (memcg_charge_kernel_stack(tsk)) {
-+ vm = find_vm_area(stack);
-+ if (memcg_charge_kernel_stack(vm)) {
- vfree(stack);
- return -ENOMEM;
- }
-@@ -288,19 +289,15 @@ static int alloc_thread_stack_node(struc
- * free_thread_stack() can be called in interrupt context,
- * so cache the vm_struct.
- */
-- tsk->stack_vm_area = find_vm_area(stack);
-+ tsk->stack_vm_area = vm;
- tsk->stack = stack;
- return 0;
- }
-
- static void free_thread_stack(struct task_struct *tsk)
- {
-- struct vm_struct *vm = task_stack_vm_area(tsk);
- int i;
-
-- for (i = 0; i < THREAD_SIZE / PAGE_SIZE; i++)
-- memcg_kmem_uncharge_page(vm->pages[i], 0);
--
- for (i = 0; i < NR_CACHED_STACKS; i++) {
- if (this_cpu_cmpxchg(cached_stacks[i], NULL,
- tsk->stack_vm_area) != NULL)
-@@ -454,12 +451,25 @@ static void account_kernel_stack(struct
- }
- }
-
-+void exit_task_stack_account(struct task_struct *tsk)
-+{
-+ account_kernel_stack(tsk, -1);
-+
-+ if (IS_ENABLED(CONFIG_VMAP_STACK)) {
-+ struct vm_struct *vm;
-+ int i;
-+
-+ vm = task_stack_vm_area(tsk);
-+ for (i = 0; i < THREAD_SIZE / PAGE_SIZE; i++)
-+ memcg_kmem_uncharge_page(vm->pages[i], 0);
-+ }
-+}
-+
- static void release_task_stack(struct task_struct *tsk)
- {
- if (WARN_ON(READ_ONCE(tsk->__state) != TASK_DEAD))
- return; /* Better to leak the stack than to free prematurely */
-
-- account_kernel_stack(tsk, -1);
- free_thread_stack(tsk);
- }
-
-@@ -918,6 +928,7 @@ static struct task_struct *dup_task_stru
- #ifdef CONFIG_THREAD_INFO_IN_TASK
- refcount_set(&tsk->stack_refcount, 1);
- #endif
-+ account_kernel_stack(tsk, 1);
-
- err = scs_prepare(tsk, node);
- if (err)
-@@ -961,8 +972,6 @@ static struct task_struct *dup_task_stru
- tsk->wake_q.next = NULL;
- tsk->worker_private = NULL;
-
-- account_kernel_stack(tsk, 1);
--
- kcov_task_init(tsk);
- kmap_local_fork(tsk);
-
-@@ -981,6 +990,7 @@ static struct task_struct *dup_task_stru
- return tsk;
-
- free_stack:
-+ exit_task_stack_account(tsk);
- free_thread_stack(tsk);
- free_tsk:
- free_task_struct(tsk);
-@@ -2459,6 +2469,7 @@ static __latent_entropy struct task_stru
- exit_creds(p);
- bad_fork_free:
- WRITE_ONCE(p->__state, TASK_DEAD);
-+ exit_task_stack_account(p);
- put_task_stack(p);
- delayed_free_task(p);
- fork_out:
diff --git a/patches/0006-mm-memcg-Disable-migration-instead-of-preemption-in-.patch b/patches/0006-mm-memcg-Disable-migration-instead-of-preemption-in-.patch
deleted file mode 100644
index d2ded6766944..000000000000
--- a/patches/0006-mm-memcg-Disable-migration-instead-of-preemption-in-.patch
+++ /dev/null
@@ -1,50 +0,0 @@
-From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
-Date: Mon, 21 Feb 2022 18:49:33 +0100
-Subject: [PATCH 6/8] mm/memcg: Disable migration instead of preemption in
- drain_all_stock().
-
-Before the for-each-CPU loop, preemption is disabled so that so that
-drain_local_stock() can be invoked directly instead of scheduling a
-worker. Ensuring that drain_local_stock() completed on the local CPU is
-not correctness problem. It _could_ be that the charging path will be
-forced to reclaim memory because cached charges are still waiting for
-their draining.
-
-Disabling preemption before invoking drain_local_stock() is problematic
-on PREEMPT_RT due to the sleeping locks involved. To ensure that no CPU
-migrations happens across for_each_online_cpu() it is enouhg to use
-migrate_disable() which disables migration and keeps context preemptible
-to a sleeping lock can be acquired.
-A race with CPU hotplug is not a problem because pcp data is not going away.
-In the worst case we just schedule draining of an empty stock.
-
-Use migrate_disable() instead of get_cpu() around the
-for_each_online_cpu() loop.
-
-Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
-Acked-by: Michal Hocko <mhocko@suse.com>
----
- mm/memcontrol.c | 5 +++--
- 1 file changed, 3 insertions(+), 2 deletions(-)
-
---- a/mm/memcontrol.c
-+++ b/mm/memcontrol.c
-@@ -2296,7 +2296,8 @@ static void drain_all_stock(struct mem_c
- * as well as workers from this path always operate on the local
- * per-cpu data. CPU up doesn't touch memcg_stock at all.
- */
-- curcpu = get_cpu();
-+ migrate_disable();
-+ curcpu = smp_processor_id();
- for_each_online_cpu(cpu) {
- struct memcg_stock_pcp *stock = &per_cpu(memcg_stock, cpu);
- struct mem_cgroup *memcg;
-@@ -2319,7 +2320,7 @@ static void drain_all_stock(struct mem_c
- schedule_work_on(cpu, &stock->work);
- }
- }
-- put_cpu();
-+ migrate_enable();
- mutex_unlock(&percpu_charge_mutex);
- }
-
diff --git a/patches/0006-net-usb-lan78xx-Use-generic_handle_irq_safe.patch b/patches/0006-net-usb-lan78xx-Use-generic_handle_irq_safe.patch
deleted file mode 100644
index af61c2e98c15..000000000000
--- a/patches/0006-net-usb-lan78xx-Use-generic_handle_irq_safe.patch
+++ /dev/null
@@ -1,30 +0,0 @@
-From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
-Date: Fri, 11 Feb 2022 19:14:59 +0100
-Subject: [PATCH 6/7] net: usb: lan78xx: Use generic_handle_irq_safe().
-
-Instead of manually disabling interrupts before invoking use
-generic_handle_irq_safe() which can be invoked with enabled and disabled
-interrupts.
-
-Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
-Link: https://lore.kernel.org/r/20220211181500.1856198-7-bigeasy@linutronix.de
----
- drivers/net/usb/lan78xx.c | 7 ++-----
- 1 file changed, 2 insertions(+), 5 deletions(-)
-
---- a/drivers/net/usb/lan78xx.c
-+++ b/drivers/net/usb/lan78xx.c
-@@ -1537,11 +1537,8 @@ static void lan78xx_status(struct lan78x
- netif_dbg(dev, link, dev->net, "PHY INTR: 0x%08x\n", intdata);
- lan78xx_defer_kevent(dev, EVENT_LINK_RESET);
-
-- if (dev->domain_data.phyirq > 0) {
-- local_irq_disable();
-- generic_handle_irq(dev->domain_data.phyirq);
-- local_irq_enable();
-- }
-+ if (dev->domain_data.phyirq > 0)
-+ generic_handle_irq_safe(dev->domain_data.phyirq);
- } else {
- netdev_warn(dev->net,
- "unexpected interrupt: 0x%08x\n", intdata);
diff --git a/patches/0004-printk-get-caller_id-timestamp-after-migration-disab.patch b/patches/0006-printk-get-caller_id-timestamp-after-migration-disab.patch
index 2f24c819cc68..1ef9f1a3dff8 100644
--- a/patches/0004-printk-get-caller_id-timestamp-after-migration-disab.patch
+++ b/patches/0006-printk-get-caller_id-timestamp-after-migration-disab.patch
@@ -1,6 +1,6 @@
From: John Ogness <john.ogness@linutronix.de>
-Date: Mon, 7 Feb 2022 15:53:48 +0106
-Subject: [PATCH 04/16] printk: get caller_id/timestamp after migration disable
+Date: Wed, 20 Apr 2022 01:52:28 +0206
+Subject: [PATCH 06/15] printk: get caller_id/timestamp after migration disable
Currently the local CPU timestamp and caller_id for the record are
collected while migration is enabled. Since this information is
@@ -11,14 +11,17 @@ anyway, so just move the information collection to after the
migration disabling.
Signed-off-by: John Ogness <john.ogness@linutronix.de>
+Reviewed-by: Sergey Senozhatsky <senozhatsky@chromium.org>
+Reviewed-by: Petr Mladek <pmladek@suse.com>
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Link: https://lore.kernel.org/r/20220419234637.357112-7-john.ogness@linutronix.de
---
kernel/printk/printk.c | 10 ++++++----
1 file changed, 6 insertions(+), 4 deletions(-)
--- a/kernel/printk/printk.c
+++ b/kernel/printk/printk.c
-@@ -2018,7 +2018,7 @@ static inline void printk_delay(void)
+@@ -2063,7 +2063,7 @@ static inline void printk_delay(void)
static inline u32 printk_caller_id(void)
{
return in_task() ? task_pid_nr(current) :
@@ -27,7 +30,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
}
/**
-@@ -2100,7 +2100,6 @@ int vprintk_store(int facility, int leve
+@@ -2145,7 +2145,6 @@ int vprintk_store(int facility, int leve
const struct dev_printk_info *dev_info,
const char *fmt, va_list args)
{
@@ -35,7 +38,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
struct prb_reserved_entry e;
enum printk_info_flags flags = 0;
struct printk_record r;
-@@ -2110,10 +2109,14 @@ int vprintk_store(int facility, int leve
+@@ -2155,10 +2154,14 @@ int vprintk_store(int facility, int leve
u8 *recursion_ptr;
u16 reserve_size;
va_list args2;
@@ -50,7 +53,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
/*
* Since the duration of printk() can vary depending on the message
* and state of the ringbuffer, grab the timestamp now so that it is
-@@ -2122,8 +2125,7 @@ int vprintk_store(int facility, int leve
+@@ -2167,8 +2170,7 @@ int vprintk_store(int facility, int leve
*/
ts_nsec = local_clock();
diff --git a/patches/0007-kernel-fork-Only-cache-the-VMAP-stack-in-finish_task.patch b/patches/0007-kernel-fork-Only-cache-the-VMAP-stack-in-finish_task.patch
deleted file mode 100644
index eac69a199032..000000000000
--- a/patches/0007-kernel-fork-Only-cache-the-VMAP-stack-in-finish_task.patch
+++ /dev/null
@@ -1,146 +0,0 @@
-From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
-Date: Thu, 17 Feb 2022 11:24:05 +0100
-Subject: [PATCH 7/8] kernel/fork: Only cache the VMAP stack in
- finish_task_switch().
-
-The task stack could be deallocated later. For fork()/exec() kind of
-workloads (say a shell script executing several commands) it is
-important that the stack is released in finish_task_switch() so that in
-VMAP_STACK case it can be cached and reused in the new task.
-
-For PREEMPT_RT it would be good if the wake-up in vfree_atomic() could
-be avoided in the scheduling path. Far worse are the other
-free_thread_stack() implementations which invoke __free_pages()/
-kmem_cache_free() with disabled preemption.
-
-Cache the stack in free_thread_stack() in the VMAP_STACK case and
-RCU-delay the free path otherwise. Free the stack in the RCU callback.
-In the VMAP_STACK case this is another opportunity to fill the cache.
-
-Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
-Acked-by: Andy Lutomirski <luto@kernel.org>
-Link: https://lore.kernel.org/r/20220217102406.3697941-8-bigeasy@linutronix.de
----
- kernel/fork.c | 76 ++++++++++++++++++++++++++++++++++++++++++++++++----------
- 1 file changed, 63 insertions(+), 13 deletions(-)
-
---- a/kernel/fork.c
-+++ b/kernel/fork.c
-@@ -193,6 +193,41 @@ static inline void free_task_struct(stru
- #define NR_CACHED_STACKS 2
- static DEFINE_PER_CPU(struct vm_struct *, cached_stacks[NR_CACHED_STACKS]);
-
-+struct vm_stack {
-+ struct rcu_head rcu;
-+ struct vm_struct *stack_vm_area;
-+};
-+
-+static bool try_release_thread_stack_to_cache(struct vm_struct *vm)
-+{
-+ unsigned int i;
-+
-+ for (i = 0; i < NR_CACHED_STACKS; i++) {
-+ if (this_cpu_cmpxchg(cached_stacks[i], NULL, vm) != NULL)
-+ continue;
-+ return true;
-+ }
-+ return false;
-+}
-+
-+static void thread_stack_free_rcu(struct rcu_head *rh)
-+{
-+ struct vm_stack *vm_stack = container_of(rh, struct vm_stack, rcu);
-+
-+ if (try_release_thread_stack_to_cache(vm_stack->stack_vm_area))
-+ return;
-+
-+ vfree(vm_stack);
-+}
-+
-+static void thread_stack_delayed_free(struct task_struct *tsk)
-+{
-+ struct vm_stack *vm_stack = tsk->stack;
-+
-+ vm_stack->stack_vm_area = tsk->stack_vm_area;
-+ call_rcu(&vm_stack->rcu, thread_stack_free_rcu);
-+}
-+
- static int free_vm_stack_cache(unsigned int cpu)
- {
- struct vm_struct **cached_vm_stacks = per_cpu_ptr(cached_stacks, cpu);
-@@ -296,24 +331,27 @@ static int alloc_thread_stack_node(struc
-
- static void free_thread_stack(struct task_struct *tsk)
- {
-- int i;
-+ if (!try_release_thread_stack_to_cache(tsk->stack_vm_area))
-+ thread_stack_delayed_free(tsk);
-
-- for (i = 0; i < NR_CACHED_STACKS; i++) {
-- if (this_cpu_cmpxchg(cached_stacks[i], NULL,
-- tsk->stack_vm_area) != NULL)
-- continue;
--
-- tsk->stack = NULL;
-- tsk->stack_vm_area = NULL;
-- return;
-- }
-- vfree_atomic(tsk->stack);
- tsk->stack = NULL;
- tsk->stack_vm_area = NULL;
- }
-
- # else /* !CONFIG_VMAP_STACK */
-
-+static void thread_stack_free_rcu(struct rcu_head *rh)
-+{
-+ __free_pages(virt_to_page(rh), THREAD_SIZE_ORDER);
-+}
-+
-+static void thread_stack_delayed_free(struct task_struct *tsk)
-+{
-+ struct rcu_head *rh = tsk->stack;
-+
-+ call_rcu(rh, thread_stack_free_rcu);
-+}
-+
- static int alloc_thread_stack_node(struct task_struct *tsk, int node)
- {
- struct page *page = alloc_pages_node(node, THREADINFO_GFP,
-@@ -328,7 +366,7 @@ static int alloc_thread_stack_node(struc
-
- static void free_thread_stack(struct task_struct *tsk)
- {
-- __free_pages(virt_to_page(tsk->stack), THREAD_SIZE_ORDER);
-+ thread_stack_delayed_free(tsk);
- tsk->stack = NULL;
- }
-
-@@ -337,6 +375,18 @@ static void free_thread_stack(struct tas
-
- static struct kmem_cache *thread_stack_cache;
-
-+static void thread_stack_free_rcu(struct rcu_head *rh)
-+{
-+ kmem_cache_free(thread_stack_cache, rh);
-+}
-+
-+static void thread_stack_delayed_free(struct task_struct *tsk)
-+{
-+ struct rcu_head *rh = tsk->stack;
-+
-+ call_rcu(rh, thread_stack_free_rcu);
-+}
-+
- static int alloc_thread_stack_node(struct task_struct *tsk, int node)
- {
- unsigned long *stack;
-@@ -348,7 +398,7 @@ static int alloc_thread_stack_node(struc
-
- static void free_thread_stack(struct task_struct *tsk)
- {
-- kmem_cache_free(thread_stack_cache, tsk->stack);
-+ thread_stack_delayed_free(tsk);
- tsk->stack = NULL;
- }
-
diff --git a/patches/0007-mm-memcg-Add-missing-counter-index-which-are-not-upd.patch b/patches/0007-mm-memcg-Add-missing-counter-index-which-are-not-upd.patch
deleted file mode 100644
index 9135de742148..000000000000
--- a/patches/0007-mm-memcg-Add-missing-counter-index-which-are-not-upd.patch
+++ /dev/null
@@ -1,38 +0,0 @@
-From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
-Date: Fri, 25 Feb 2022 10:37:56 +0100
-Subject: [PATCH 7/8] mm/memcg: Add missing counter index which are not update
- in interrupt.
-
-Shakeel Butt reported that I missed a few counters which are not updated
-in-interrupt context and therefore disabling preemption is fine.
-
-Please fold into:
- "Protect per-CPU counter by disabling preemption on PREEMPT_RT"
-
-Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
----
- mm/memcontrol.c | 11 +++++++++--
- 1 file changed, 9 insertions(+), 2 deletions(-)
-
---- a/mm/memcontrol.c
-+++ b/mm/memcontrol.c
-@@ -742,10 +742,17 @@ void __mod_memcg_lruvec_state(struct lru
- */
- __memcg_stats_lock();
- if (IS_ENABLED(CONFIG_DEBUG_VM)) {
-- if (idx == NR_ANON_MAPPED || idx == NR_FILE_MAPPED)
-+ switch (idx) {
-+ case NR_ANON_MAPPED:
-+ case NR_FILE_MAPPED:
-+ case NR_ANON_THPS:
-+ case NR_SHMEM_PMDMAPPED:
-+ case NR_FILE_PMDMAPPED:
- WARN_ON_ONCE(!in_task());
-- else
-+ break;
-+ default:
- WARN_ON_ONCE(!irqs_disabled());
-+ }
- }
-
- /* Update memcg */
diff --git a/patches/0005-printk-call-boot_delay_msec-in-printk_delay.patch b/patches/0007-printk-call-boot_delay_msec-in-printk_delay.patch
index 0e58681b35ff..ce20eb0bc3fe 100644
--- a/patches/0005-printk-call-boot_delay_msec-in-printk_delay.patch
+++ b/patches/0007-printk-call-boot_delay_msec-in-printk_delay.patch
@@ -1,19 +1,22 @@
From: John Ogness <john.ogness@linutronix.de>
-Date: Mon, 7 Feb 2022 15:53:51 +0106
-Subject: [PATCH 05/16] printk: call boot_delay_msec() in printk_delay()
+Date: Wed, 20 Apr 2022 01:52:29 +0206
+Subject: [PATCH 07/15] printk: call boot_delay_msec() in printk_delay()
boot_delay_msec() is always called immediately before printk_delay()
so just call it from within printk_delay().
Signed-off-by: John Ogness <john.ogness@linutronix.de>
+Reviewed-by: Sergey Senozhatsky <senozhatsky@chromium.org>
+Reviewed-by: Petr Mladek <pmladek@suse.com>
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Link: https://lore.kernel.org/r/20220419234637.357112-8-john.ogness@linutronix.de
---
kernel/printk/printk.c | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
--- a/kernel/printk/printk.c
+++ b/kernel/printk/printk.c
-@@ -2003,8 +2003,10 @@ static u8 *__printk_recursion_counter(vo
+@@ -2048,8 +2048,10 @@ static u8 *__printk_recursion_counter(vo
int printk_delay_msec __read_mostly;
@@ -25,7 +28,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
if (unlikely(printk_delay_msec)) {
int m = printk_delay_msec;
-@@ -2225,8 +2227,7 @@ asmlinkage int vprintk_emit(int facility
+@@ -2274,8 +2276,7 @@ asmlinkage int vprintk_emit(int facility
in_sched = true;
}
diff --git a/patches/0007-staging-greybus-gpio-Use-generic_handle_irq_safe.patch b/patches/0007-staging-greybus-gpio-Use-generic_handle_irq_safe.patch
deleted file mode 100644
index 79f383a351fb..000000000000
--- a/patches/0007-staging-greybus-gpio-Use-generic_handle_irq_safe.patch
+++ /dev/null
@@ -1,30 +0,0 @@
-From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
-Date: Fri, 11 Feb 2022 19:15:00 +0100
-Subject: [PATCH 7/7] staging: greybus: gpio: Use generic_handle_irq_safe().
-
-Instead of manually disabling interrupts before invoking use
-generic_handle_irq_safe() which can be invoked with enabled and disabled
-interrupts.
-
-Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
-Acked-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-Acked-by: Johan Hovold <johan@kernel.org>
-Link: https://lore.kernel.org/r/20220211181500.1856198-8-bigeasy@linutronix.de
----
- drivers/staging/greybus/gpio.c | 5 +----
- 1 file changed, 1 insertion(+), 4 deletions(-)
-
---- a/drivers/staging/greybus/gpio.c
-+++ b/drivers/staging/greybus/gpio.c
-@@ -391,10 +391,7 @@ static int gb_gpio_request_handler(struc
- return -EINVAL;
- }
-
-- local_irq_disable();
-- ret = generic_handle_irq(irq);
-- local_irq_enable();
--
-+ ret = generic_handle_irq_safe(irq);
- if (ret)
- dev_err(dev, "failed to invoke irq handler\n");
-
diff --git a/patches/0008-kernel-fork-Use-IS_ENABLED-in-account_kernel_stack.patch b/patches/0008-kernel-fork-Use-IS_ENABLED-in-account_kernel_stack.patch
deleted file mode 100644
index 97e8743bdeb0..000000000000
--- a/patches/0008-kernel-fork-Use-IS_ENABLED-in-account_kernel_stack.patch
+++ /dev/null
@@ -1,40 +0,0 @@
-From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
-Date: Thu, 17 Feb 2022 11:24:06 +0100
-Subject: [PATCH 8/8] kernel/fork: Use IS_ENABLED() in account_kernel_stack().
-
-Not strickly needed but checking CONFIG_VMAP_STACK instead of
-task_stack_vm_area()' result allows the compiler the remove the else
-path in the CONFIG_VMAP_STACK case where the pointer can't be NULL.
-
-Check for CONFIG_VMAP_STACK in order to use the proper path.
-
-Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
-Acked-by: Andy Lutomirski <luto@kernel.org>
-Link: https://lore.kernel.org/r/20220217102406.3697941-9-bigeasy@linutronix.de
----
- kernel/fork.c | 8 ++++----
- 1 file changed, 4 insertions(+), 4 deletions(-)
-
---- a/kernel/fork.c
-+++ b/kernel/fork.c
-@@ -485,16 +485,16 @@ void vm_area_free(struct vm_area_struct
-
- static void account_kernel_stack(struct task_struct *tsk, int account)
- {
-- void *stack = task_stack_page(tsk);
-- struct vm_struct *vm = task_stack_vm_area(tsk);
--
-- if (vm) {
-+ if (IS_ENABLED(CONFIG_VMAP_STACK)) {
-+ struct vm_struct *vm = task_stack_vm_area(tsk);
- int i;
-
- for (i = 0; i < THREAD_SIZE / PAGE_SIZE; i++)
- mod_lruvec_page_state(vm->pages[i], NR_KERNEL_STACK_KB,
- account * (PAGE_SIZE / 1024));
- } else {
-+ void *stack = task_stack_page(tsk);
-+
- /* All stack pages are in the same node. */
- mod_lruvec_kmem_state(stack, NR_KERNEL_STACK_KB,
- account * (THREAD_SIZE / 1024));
diff --git a/patches/0008-mm-memcg-Add-a-comment-regarding-the-release-obj.patch b/patches/0008-mm-memcg-Add-a-comment-regarding-the-release-obj.patch
deleted file mode 100644
index 22ac20853d03..000000000000
--- a/patches/0008-mm-memcg-Add-a-comment-regarding-the-release-obj.patch
+++ /dev/null
@@ -1,25 +0,0 @@
-From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
-Date: Fri, 25 Feb 2022 16:04:51 +0100
-Subject: [PATCH 8/8] mm/memcg: Add a comment regarding the release `obj'.
-
-Please fold into
- mm/memcg: Protect memcg_stock with a local_lock_t
-
-Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
----
- mm/memcontrol.c | 4 ++++
- 1 file changed, 4 insertions(+)
-
---- a/mm/memcontrol.c
-+++ b/mm/memcontrol.c
-@@ -3240,6 +3240,10 @@ static struct obj_cgroup *drain_obj_stoc
- }
-
- stock->cached_objcg = NULL;
-+ /*
-+ * The `old' objects needs to be released by the caller via
-+ * obj_cgroup_put() outside of memcg_stock_pcp::stock_lock.
-+ */
- return old;
- }
-
diff --git a/patches/0008-printk-add-con_printk-macro-for-console-details.patch b/patches/0008-printk-add-con_printk-macro-for-console-details.patch
new file mode 100644
index 000000000000..8ef4569e0731
--- /dev/null
+++ b/patches/0008-printk-add-con_printk-macro-for-console-details.patch
@@ -0,0 +1,54 @@
+From: John Ogness <john.ogness@linutronix.de>
+Date: Wed, 20 Apr 2022 01:52:30 +0206
+Subject: [PATCH 08/15] printk: add con_printk() macro for console details
+
+It is useful to generate log messages that include details about
+the related console. Rather than duplicate the code to assemble
+the details, put that code into a macro con_printk().
+
+Once console printers become threaded, this macro will find more
+users.
+
+Signed-off-by: John Ogness <john.ogness@linutronix.de>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Link: https://lore.kernel.org/r/20220419234637.357112-9-john.ogness@linutronix.de
+---
+ kernel/printk/printk.c | 13 +++++++------
+ 1 file changed, 7 insertions(+), 6 deletions(-)
+
+--- a/kernel/printk/printk.c
++++ b/kernel/printk/printk.c
+@@ -3015,6 +3015,11 @@ static void try_enable_default_console(s
+ newcon->flags |= CON_CONSDEV;
+ }
+
++#define con_printk(lvl, con, fmt, ...) \
++ printk(lvl pr_fmt("%sconsole [%s%d] " fmt), \
++ (con->flags & CON_BOOT) ? "boot" : "", \
++ con->name, con->index, ##__VA_ARGS__)
++
+ /*
+ * The console driver calls this routine during kernel initialization
+ * to register the console printing procedure with printk() and to
+@@ -3153,9 +3158,7 @@ void register_console(struct console *ne
+ * users know there might be something in the kernel's log buffer that
+ * went to the bootconsole (that they do not see on the real console)
+ */
+- pr_info("%sconsole [%s%d] enabled\n",
+- (newcon->flags & CON_BOOT) ? "boot" : "" ,
+- newcon->name, newcon->index);
++ con_printk(KERN_INFO, newcon, "enabled\n");
+ if (bootcon_enabled &&
+ ((newcon->flags & (CON_CONSDEV | CON_BOOT)) == CON_CONSDEV) &&
+ !keep_bootcon) {
+@@ -3174,9 +3177,7 @@ int unregister_console(struct console *c
+ struct console *con;
+ int res;
+
+- pr_info("%sconsole [%s%d] disabled\n",
+- (console->flags & CON_BOOT) ? "boot" : "" ,
+- console->name, console->index);
++ con_printk(KERN_INFO, console, "disabled\n");
+
+ res = _braille_unregister_console(console);
+ if (res < 0)
diff --git a/patches/0009-drm-i915-gt-Use-spin_lock_irq-instead-of-local_irq_d.patch b/patches/0009-drm-i915-gt-Use-spin_lock_irq-instead-of-local_irq_d.patch
index 9f71e539caba..d1db49f55add 100644
--- a/patches/0009-drm-i915-gt-Use-spin_lock_irq-instead-of-local_irq_d.patch
+++ b/patches/0009-drm-i915-gt-Use-spin_lock_irq-instead-of-local_irq_d.patch
@@ -27,7 +27,7 @@ Reviewed-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
--- a/drivers/gpu/drm/i915/gt/intel_execlists_submission.c
+++ b/drivers/gpu/drm/i915/gt/intel_execlists_submission.c
-@@ -1284,7 +1284,7 @@ static void execlists_dequeue(struct int
+@@ -1290,7 +1290,7 @@ static void execlists_dequeue(struct int
* and context switches) submission.
*/
@@ -36,7 +36,7 @@ Reviewed-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
/*
* If the queue is higher priority than the last
-@@ -1384,7 +1384,7 @@ static void execlists_dequeue(struct int
+@@ -1390,7 +1390,7 @@ static void execlists_dequeue(struct int
* Even if ELSP[1] is occupied and not worthy
* of timeslices, our queue might be.
*/
@@ -45,7 +45,7 @@ Reviewed-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
return;
}
}
-@@ -1410,7 +1410,7 @@ static void execlists_dequeue(struct int
+@@ -1416,7 +1416,7 @@ static void execlists_dequeue(struct int
if (last && !can_merge_rq(last, rq)) {
spin_unlock(&ve->base.sched_engine->lock);
@@ -54,7 +54,7 @@ Reviewed-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
return; /* leave this for another sibling */
}
-@@ -1572,7 +1572,7 @@ static void execlists_dequeue(struct int
+@@ -1578,7 +1578,7 @@ static void execlists_dequeue(struct int
*/
sched_engine->queue_priority_hint = queue_prio(sched_engine);
i915_sched_engine_reset_on_empty(sched_engine);
@@ -63,7 +63,7 @@ Reviewed-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
/*
* We can skip poking the HW if we ended up with exactly the same set
-@@ -1598,13 +1598,6 @@ static void execlists_dequeue(struct int
+@@ -1604,13 +1604,6 @@ static void execlists_dequeue(struct int
}
}
@@ -77,7 +77,7 @@ Reviewed-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
static void clear_ports(struct i915_request **ports, int count)
{
memset_p((void **)ports, NULL, count);
-@@ -2425,7 +2418,7 @@ static void execlists_submission_tasklet
+@@ -2431,7 +2424,7 @@ static void execlists_submission_tasklet
}
if (!engine->execlists.pending[0]) {
diff --git a/patches/0006-printk-refactor-and-rework-printing-logic.patch b/patches/0009-printk-refactor-and-rework-printing-logic.patch
index 2204201ea6b2..6e3d8b8400de 100644
--- a/patches/0006-printk-refactor-and-rework-printing-logic.patch
+++ b/patches/0009-printk-refactor-and-rework-printing-logic.patch
@@ -1,28 +1,37 @@
From: John Ogness <john.ogness@linutronix.de>
-Date: Mon, 7 Feb 2022 15:54:14 +0106
-Subject: [PATCH 06/16] printk: refactor and rework printing logic
+Date: Wed, 20 Apr 2022 01:52:31 +0206
+Subject: [PATCH 09/15] printk: refactor and rework printing logic
-Refactor/rework printing logic in order to prepare for moving to threaded
-console printing.
+Refactor/rework printing logic in order to prepare for moving to
+threaded console printing.
-- Move @console_seq into struct console so that the current "position" of
- each console can be tracked individually.
+- Move @console_seq into struct console so that the current
+ "position" of each console can be tracked individually.
-- Move @console_dropped into struct console so that the current drop count
- of each console can be tracked individually.
+- Move @console_dropped into struct console so that the current drop
+ count of each console can be tracked individually.
-- Modify printing logic so that each console independently loads, prepares,
- prints, and delays its next record.
+- Modify printing logic so that each console independently loads,
+ prepares, and prints its next record.
-- Remove exclusive_console logic. Since console positions are handled
- independently, replaying past records occurs naturally.
+- Remove exclusive_console logic. Since console positions are
+ handled independently, replaying past records occurs naturally.
+
+- Update the comments explaining why preemption is disabled while
+ printing from printk() context.
+
+With these changes, there is a change in behavior: the console
+replaying the log (formerly exclusive console) will no longer block
+other consoles. New messages appear on the other consoles while the
+newly added console is still replaying.
Signed-off-by: John Ogness <john.ogness@linutronix.de>
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Link: https://lore.kernel.org/r/20220419234637.357112-10-john.ogness@linutronix.de
---
include/linux/console.h | 2
- kernel/printk/printk.c | 388 ++++++++++++++++++++++++------------------------
- 2 files changed, 198 insertions(+), 192 deletions(-)
+ kernel/printk/printk.c | 441 ++++++++++++++++++++++++------------------------
+ 2 files changed, 230 insertions(+), 213 deletions(-)
--- a/include/linux/console.h
+++ b/include/linux/console.h
@@ -37,7 +46,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
};
--- a/kernel/printk/printk.c
+++ b/kernel/printk/printk.c
-@@ -268,11 +268,6 @@ static void __up_console_sem(unsigned lo
+@@ -281,11 +281,6 @@ static bool panic_in_progress(void)
static int console_locked, console_suspended;
/*
@@ -49,7 +58,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
* Array of consoles built from command line options (console=)
*/
-@@ -361,12 +356,6 @@ static u64 syslog_seq;
+@@ -374,12 +369,6 @@ static u64 syslog_seq;
static size_t syslog_partial;
static bool syslog_time;
@@ -62,7 +71,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
struct latched_seq {
seqcount_latch_t latch;
u64 val[2];
-@@ -1888,47 +1877,26 @@ static int console_trylock_spinning(void
+@@ -1933,47 +1922,26 @@ static int console_trylock_spinning(void
}
/*
@@ -120,16 +129,31 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
}
/*
-@@ -2227,8 +2195,6 @@ asmlinkage int vprintk_emit(int facility
- in_sched = true;
- }
-
-- printk_delay(level);
--
- printed_len = vprintk_store(facility, level, dev_info, fmt, args);
-
+@@ -2283,15 +2251,18 @@ asmlinkage int vprintk_emit(int facility
/* If called from the scheduler, we can not call up(). */
-@@ -2280,11 +2246,9 @@ EXPORT_SYMBOL(_printk);
+ if (!in_sched) {
+ /*
+- * Disable preemption to avoid being preempted while holding
+- * console_sem which would prevent anyone from printing to
+- * console
++ * The caller may be holding system-critical or
++ * timing-sensitive locks. Disable preemption during
++ * printing of all remaining records to all consoles so that
++ * this context can return as soon as possible. Hopefully
++ * another printk() caller will take over the printing.
+ */
+ preempt_disable();
+ /*
+ * Try to acquire and then immediately release the console
+- * semaphore. The release will print out buffers and wake up
+- * /dev/kmsg and syslog() users.
++ * semaphore. The release will print out buffers. With the
++ * spinning variant, this context tries to take over the
++ * printing from another printing context.
+ */
+ if (console_trylock_spinning())
+ console_unlock();
+@@ -2329,11 +2300,9 @@ EXPORT_SYMBOL(_printk);
#define prb_read_valid(rb, seq, r) false
#define prb_first_valid_seq(rb) 0
@@ -142,51 +166,63 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
static size_t record_print_text(const struct printk_record *r,
bool syslog, bool time)
-@@ -2301,9 +2265,9 @@ static ssize_t msg_print_ext_body(char *
+@@ -2350,8 +2319,7 @@ static ssize_t msg_print_ext_body(char *
struct dev_printk_info *dev_info) { return 0; }
static void console_lock_spinning_enable(void) { }
static int console_lock_spinning_disable_and_check(void) { return 0; }
-static void call_console_drivers(const char *ext_text, size_t ext_len,
- const char *text, size_t len) {}
-+static void call_console_driver(struct console *con, const char *text, size_t len) {}
++static void call_console_driver(struct console *con, const char *text, size_t len) { }
static bool suppress_message_printing(int level) { return false; }
-+static void printk_delay(int level) {}
#endif /* CONFIG_PRINTK */
-
-@@ -2561,31 +2525,167 @@ int is_console_locked(void)
+@@ -2622,22 +2590,6 @@ int is_console_locked(void)
EXPORT_SYMBOL(is_console_locked);
/*
- * Check if we have any console that is capable of printing while cpu is
- * booting or shutting down. Requires console_sem.
+- */
+-static int have_callable_console(void)
+-{
+- struct console *con;
+-
+- for_each_console(con)
+- if ((con->flags & CON_ENABLED) &&
+- (con->flags & CON_ANYTIME))
+- return 1;
+-
+- return 0;
+-}
+-
+-/*
+ * Return true when this CPU should unlock console_sem without pushing all
+ * messages to the console. This reduces the chance that the console is
+ * locked when the panic CPU tries to use it.
+@@ -2657,15 +2609,182 @@ static bool abandon_console_lock_in_pani
+ }
+
+ /*
+- * Can we actually use the console at this time on this cpu?
+ * Check if the given console is currently capable and allowed to print
+ * records.
+ *
+ * Requires the console_lock.
- */
--static int have_callable_console(void)
++ */
+static inline bool console_is_usable(struct console *con)
- {
-- struct console *con;
++{
+ if (!(con->flags & CON_ENABLED))
+ return false;
-
-- for_each_console(con)
-- if ((con->flags & CON_ENABLED) &&
-- (con->flags & CON_ANYTIME))
-- return 1;
++
+ if (!con->write)
+ return false;
-
-- return 0;
++
+ /*
+ * Console drivers may assume that per-cpu resources have been
+ * allocated. So unless they're explicitly marked as being able to
-+ * cope (CON_ANYTIME) don't call them until per-cpu resources have
-+ * been allocated.
++ * cope (CON_ANYTIME) don't call them until this CPU is officially up.
+ */
-+ if (!printk_percpu_data_ready() &&
++ if (!cpu_online(raw_smp_processor_id()) &&
+ !(con->flags & CON_ANYTIME))
+ return false;
+
@@ -197,31 +233,26 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+{
+ console_locked = 0;
+ up_console_sem();
- }
-
- /*
-- * Can we actually use the console at this time on this cpu?
++}
++
++/*
+ * Print one record for the given console. The record printed is whatever
+ * record is the next available record for the given console.
+ *
-+ * Requires the console_lock.
- *
-- * Console drivers may assume that per-cpu resources have been allocated. So
-- * unless they're explicitly marked as being able to cope (CON_ANYTIME) don't
-- * call them until per-cpu resources have been allocated.
-+ * Returns false if the given console has no next record to print, otherwise
-+ * true.
-+ *
+ * @handover will be set to true if a printk waiter has taken over the
+ * console_lock, in which case the caller is no longer holding the
+ * console_lock. Otherwise it is set to false.
- */
--static inline int can_use_console(void)
++ *
++ * Returns false if the given console has no next record to print, otherwise
++ * true.
++ *
++ * Requires the console_lock.
++ */
+static bool console_emit_next_record(struct console *con, bool *handover)
- {
-- return (printk_percpu_data_ready() || have_callable_console());
++{
+ static char ext_text[CONSOLE_EXT_LOG_MAX];
+ static char text[CONSOLE_LOG_MAX];
++ static int panic_console_dropped;
+ struct printk_info info;
+ struct printk_record r;
+ unsigned long flags;
@@ -238,6 +269,10 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+ if (con->seq != r.info->seq) {
+ con->dropped += r.info->seq - con->seq;
+ con->seq = r.info->seq;
++ if (panic_in_progress() && panic_console_dropped++ > 10) {
++ suppress_panic_printk = 1;
++ pr_warn_once("Too many dropped messages. Suppress messages on non-panic CPUs to prevent livelock.\n");
++ }
+ }
+
+ /* Skip record that has level above the console loglevel. */
@@ -277,8 +312,6 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+
+ *handover = console_lock_spinning_disable_and_check();
+ printk_safe_exit_irqrestore(flags);
-+
-+ printk_delay(r.info->level);
+skip:
+ return true;
+}
@@ -286,19 +319,33 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+/*
+ * Print out all remaining records to all consoles.
+ *
-+ * Requires the console_lock.
-+ *
-+ * Returns true if a console was available for flushing, otherwise false.
-+ *
-+ * @next_seq is set to the highest sequence number of all of the consoles that
-+ * were flushed.
++ * @do_cond_resched is set by the caller. It can be true only in schedulable
++ * context.
+ *
++ * @next_seq is set to the sequence number after the last available record.
++ * The value is valid only when this function returns true. It means that all
++ * usable consoles are completely flushed.
+ *
+- * Console drivers may assume that per-cpu resources have been allocated. So
+- * unless they're explicitly marked as being able to cope (CON_ANYTIME) don't
+- * call them until this CPU is officially up.
+ * @handover will be set to true if a printk waiter has taken over the
+ * console_lock, in which case the caller is no longer holding the
+ * console_lock. Otherwise it is set to false.
-+ */
++ *
++ * Returns true when there was at least one usable console and all messages
++ * were flushed to all usable consoles. A returned false informs the caller
++ * that everything was not flushed (either there were no usable consoles or
++ * another context has taken over printing or it is a panic situation and this
++ * is not the panic CPU). Regardless the reason, the caller should assume it
++ * is not useful to immediately try again.
++ *
++ * Requires the console_lock.
+ */
+-static inline int can_use_console(void)
+static bool console_flush_all(bool do_cond_resched, u64 *next_seq, bool *handover)
-+{
+ {
+- return cpu_online(raw_smp_processor_id()) || have_callable_console();
+ bool any_usable = false;
+ struct console *con;
+ bool any_progress;
@@ -318,9 +365,9 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+
+ progress = console_emit_next_record(con, handover);
+ if (*handover)
-+ return true;
++ return false;
+
-+ /* Track the highest seq flushed. */
++ /* Track the next of the highest seq flushed. */
+ if (con->seq > *next_seq)
+ *next_seq = con->seq;
+
@@ -328,6 +375,10 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+ continue;
+ any_progress = true;
+
++ /* Allow panic_cpu to take over the consoles safely. */
++ if (abandon_console_lock_in_panic())
++ return false;
++
+ if (do_cond_resched)
+ cond_resched();
+ }
@@ -337,12 +388,19 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
}
/**
-@@ -2604,21 +2704,16 @@ static inline int can_use_console(void)
+@@ -2678,28 +2797,20 @@ static inline int can_use_console(void)
+ * by printk(). If this is the case, console_unlock(); emits
+ * the output prior to releasing the lock.
+ *
+- * If there is output waiting, we wake /dev/kmsg and syslog() users.
+- *
+ * console_unlock(); may be called from any context.
*/
void console_unlock(void)
{
- static char ext_text[CONSOLE_EXT_LOG_MAX];
- static char text[CONSOLE_LOG_MAX];
+- static int panic_console_dropped;
- unsigned long flags;
- bool do_cond_resched, retry;
- struct printk_info info;
@@ -363,7 +421,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
/*
* Console drivers are called with interrupts disabled, so
* @console_may_schedule should be cleared before; however, we may
-@@ -2627,117 +2722,31 @@ void console_unlock(void)
+@@ -2708,125 +2819,34 @@ void console_unlock(void)
* between lines if allowable. Not doing so can cause a very long
* scheduling stall on a slow console leading to RCU stall and
* softlockup warnings which exacerbate the issue with more
@@ -378,7 +436,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
do_cond_resched = console_may_schedule;
-again:
- console_may_schedule = 0;
--
+
- /*
- * We released the console_sem lock, so we need to recheck if
- * cpu is online and (if not) is there at least one CON_ANYTIME
@@ -389,23 +447,23 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
- up_console_sem();
- return;
- }
-
+-
- for (;;) {
- size_t ext_len = 0;
- int handover;
- size_t len;
-+ do {
-+ console_may_schedule = 0;
-
+-
-skip:
- if (!prb_read_valid(prb, console_seq, &r))
-+ flushed = console_flush_all(do_cond_resched, &next_seq, &handover);
-+ if (handover)
- break;
-
+- break;
+-
- if (console_seq != r.info->seq) {
- console_dropped += r.info->seq - console_seq;
- console_seq = r.info->seq;
+- if (panic_in_progress() && panic_console_dropped++ > 10) {
+- suppress_panic_printk = 1;
+- pr_warn_once("Too many dropped messages. Suppress messages on non-panic CPUs to prevent livelock.\n");
+- }
- }
-
- if (suppress_message_printing(r.info->level)) {
@@ -417,18 +475,26 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
- console_seq++;
- goto skip;
- }
--
++ do {
++ console_may_schedule = 0;
+
- /* Output to all consoles once old messages replayed. */
- if (unlikely(exclusive_console &&
- console_seq >= exclusive_console_stop_seq)) {
- exclusive_console = NULL;
- }
-+ __console_unlock();
++ flushed = console_flush_all(do_cond_resched, &next_seq, &handover);
++ if (!handover)
++ __console_unlock();
-- /*
+ /*
- * Handle extended console text first because later
- * record_print_text() will modify the record buffer in-place.
-- */
++ * Abort if there was a failure to flush all messages to all
++ * usable consoles. Either it is not possible to flush (in
++ * which case it would be an infinite loop of retrying) or
++ * another context has taken over printing.
+ */
- if (nr_ext_console_drivers) {
- ext_len = info_print_ext_header(ext_text,
- sizeof(ext_text),
@@ -443,7 +509,6 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
- console_msg_format & MSG_FORMAT_SYSLOG,
- printk_time);
- console_seq++;
-+ /* Were there any consoles available for flushing? */
+ if (!flushed)
+ break;
@@ -473,6 +538,10 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
- if (handover)
- return;
-
+- /* Allow panic_cpu to take over the consoles safely */
+- if (abandon_console_lock_in_panic())
+- break;
+-
- if (do_cond_resched)
- cond_resched();
- }
@@ -490,13 +559,13 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
- * flush, no worries.
- */
- retry = prb_read_valid(prb, next_seq, NULL);
-- if (retry && console_trylock())
+- if (retry && !abandon_console_lock_in_panic() && console_trylock())
- goto again;
+ } while (prb_read_valid(prb, next_seq, NULL) && console_trylock());
}
EXPORT_SYMBOL(console_unlock);
-@@ -2797,8 +2806,14 @@ void console_flush_on_panic(enum con_flu
+@@ -2886,8 +2906,14 @@ void console_flush_on_panic(enum con_flu
console_trylock();
console_may_schedule = 0;
@@ -513,7 +582,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
console_unlock();
}
-@@ -3033,26 +3048,15 @@ void register_console(struct console *ne
+@@ -3127,26 +3153,15 @@ void register_console(struct console *ne
if (newcon->flags & CON_EXTENDED)
nr_ext_console_drivers++;
diff --git a/patches/0010-drm-i915-Drop-the-irqs_disabled-check.patch b/patches/0010-drm-i915-Drop-the-irqs_disabled-check.patch
index 6d411b56cb55..86486cce7a16 100644
--- a/patches/0010-drm-i915-Drop-the-irqs_disabled-check.patch
+++ b/patches/0010-drm-i915-Drop-the-irqs_disabled-check.patch
@@ -20,7 +20,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
--- a/drivers/gpu/drm/i915/i915_request.c
+++ b/drivers/gpu/drm/i915/i915_request.c
-@@ -583,7 +583,6 @@ bool __i915_request_submit(struct i915_r
+@@ -587,7 +587,6 @@ bool __i915_request_submit(struct i915_r
RQ_TRACE(request, "\n");
@@ -28,7 +28,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
lockdep_assert_held(&engine->sched_engine->lock);
/*
-@@ -692,7 +691,6 @@ void __i915_request_unsubmit(struct i915
+@@ -696,7 +695,6 @@ void __i915_request_unsubmit(struct i915
*/
RQ_TRACE(request, "\n");
diff --git a/patches/0010-printk-add-kthread-console-printers.patch b/patches/0010-printk-add-kthread-console-printers.patch
deleted file mode 100644
index ad8b57cad2df..000000000000
--- a/patches/0010-printk-add-kthread-console-printers.patch
+++ /dev/null
@@ -1,285 +0,0 @@
-From: John Ogness <john.ogness@linutronix.de>
-Date: Mon, 7 Feb 2022 15:54:42 +0106
-Subject: [PATCH 10/16] printk: add kthread console printers
-
-Create a kthread for each console to perform console printing. During
-normal operation (@system_state == SYSTEM_RUNNING), the kthread
-printers are responsible for all printing on their respective
-consoles.
-
-During non-normal operation, console printing is done as it has been:
-within the context of the printk caller or within irq work triggered
-by the printk caller.
-
-Console printers synchronize against each other and against console
-lockers by taking the console lock for each message that is printed.
-
-Signed-off-by: John Ogness <john.ogness@linutronix.de>
----
- include/linux/console.h | 2
- kernel/printk/printk.c | 159 +++++++++++++++++++++++++++++++++++++++++++++++-
- 2 files changed, 159 insertions(+), 2 deletions(-)
-
---- a/include/linux/console.h
-+++ b/include/linux/console.h
-@@ -153,6 +153,8 @@ struct console {
- uint ospeed;
- u64 seq;
- unsigned long dropped;
-+ struct task_struct *thread;
-+
- void *data;
- struct console *next;
- };
---- a/kernel/printk/printk.c
-+++ b/kernel/printk/printk.c
-@@ -348,6 +348,13 @@ static int console_msg_format = MSG_FORM
- /* syslog_lock protects syslog_* variables and write access to clear_seq. */
- static DEFINE_MUTEX(syslog_lock);
-
-+/*
-+ * A flag to signify if printk_late_init() has already started the kthread
-+ * printers. If true, any later registered consoles must start their own
-+ * kthread directly. The flag is write protected by the console_lock.
-+ */
-+static bool kthreads_started;
-+
- #ifdef CONFIG_PRINTK
- static atomic_t printk_direct = ATOMIC_INIT(0);
-
-@@ -374,6 +381,14 @@ void printk_direct_exit(void)
- atomic_dec(&printk_direct);
- }
-
-+static inline bool allow_direct_printing(void)
-+{
-+ return (!kthreads_started ||
-+ system_state != SYSTEM_RUNNING ||
-+ oops_in_progress ||
-+ atomic_read(&printk_direct));
-+}
-+
- DECLARE_WAIT_QUEUE_HEAD(log_wait);
- /* All 3 protected by @syslog_lock. */
- /* the next printk record to read by syslog(READ) or /proc/kmsg */
-@@ -2226,7 +2241,7 @@ asmlinkage int vprintk_emit(int facility
- printed_len = vprintk_store(facility, level, dev_info, fmt, args);
-
- /* If called from the scheduler, we can not call up(). */
-- if (!in_sched) {
-+ if (!in_sched && allow_direct_printing()) {
- /*
- * Disable preemption to avoid being preempted while holding
- * console_sem which would prevent anyone from printing to
-@@ -2267,6 +2282,8 @@ asmlinkage __visible int _printk(const c
- }
- EXPORT_SYMBOL(_printk);
-
-+static void start_printk_kthread(struct console *con);
-+
- #else /* CONFIG_PRINTK */
-
- #define CONSOLE_LOG_MAX 0
-@@ -2300,6 +2317,8 @@ static void call_console_driver(struct c
- }
- static bool suppress_message_printing(int level) { return false; }
- static void printk_delay(int level) {}
-+static void start_printk_kthread(struct console *con) {}
-+static bool allow_direct_printing(void) { return true; }
-
- #endif /* CONFIG_PRINTK */
-
-@@ -2488,6 +2507,10 @@ void resume_console(void)
- down_console_sem();
- console_suspended = 0;
- console_unlock();
-+
-+ /* Wake the kthread printers. */
-+ wake_up_klogd();
-+
- pr_flush(1000, true);
- }
-
-@@ -2703,6 +2726,10 @@ static bool console_flush_all(bool do_co
- *handover = false;
-
- do {
-+ /* Let the kthread printers do the work if they can. */
-+ if (!allow_direct_printing())
-+ break;
-+
- any_progress = false;
-
- for_each_console(con) {
-@@ -2911,6 +2938,10 @@ void console_start(struct console *conso
- console_lock();
- console->flags |= CON_ENABLED;
- console_unlock();
-+
-+ /* Wake the kthread printers. */
-+ wake_up_klogd();
-+
- pr_flush(1000, true);
- }
- EXPORT_SYMBOL(console_start);
-@@ -3115,6 +3146,8 @@ void register_console(struct console *ne
- /* Begin with next message. */
- newcon->seq = prb_next_seq(prb);
- }
-+ if (kthreads_started)
-+ start_printk_kthread(newcon);
- console_unlock();
- console_sysfs_notify();
-
-@@ -3171,6 +3204,11 @@ int unregister_console(struct console *c
- }
- }
-
-+ if (console->thread) {
-+ kthread_stop(console->thread);
-+ console->thread = NULL;
-+ }
-+
- if (res)
- goto out_disable_unlock;
-
-@@ -3277,6 +3315,13 @@ static int __init printk_late_init(void)
- console_cpu_notify, NULL);
- WARN_ON(ret < 0);
- printk_sysctl_init();
-+
-+ console_lock();
-+ for_each_console(con)
-+ start_printk_kthread(con);
-+ kthreads_started = true;
-+ console_unlock();
-+
- return 0;
- }
- late_initcall(printk_late_init);
-@@ -3347,6 +3392,116 @@ bool pr_flush(int timeout_ms, bool reset
- }
- EXPORT_SYMBOL(pr_flush);
-
-+static bool printer_should_wake(struct console *con, u64 seq)
-+{
-+ short flags;
-+
-+ if (kthread_should_stop())
-+ return true;
-+
-+ if (console_suspended)
-+ return false;
-+
-+ /*
-+ * This is an unsafe read to con->flags, but false positives
-+ * are not an issue as long as they are rare.
-+ */
-+ flags = data_race(READ_ONCE(con->flags));
-+ if (!(flags & CON_ENABLED))
-+ return false;
-+
-+ return prb_read_valid(prb, seq, NULL);
-+}
-+
-+static int printk_kthread_func(void *data)
-+{
-+ struct console *con = data;
-+ char *dropped_text = NULL;
-+ char *ext_text = NULL;
-+ bool progress;
-+ bool handover;
-+ u64 seq = 0;
-+ char *text;
-+ int error;
-+
-+ pr_info("%sconsole [%s%d]: printing thread started\n",
-+ (con->flags & CON_BOOT) ? "boot" : "",
-+ con->name, con->index);
-+
-+ text = kmalloc(CONSOLE_LOG_MAX, GFP_KERNEL);
-+ if (!text)
-+ goto out;
-+
-+ if (con->flags & CON_EXTENDED) {
-+ ext_text = kmalloc(CONSOLE_EXT_LOG_MAX, GFP_KERNEL);
-+ if (!ext_text)
-+ goto out;
-+ } else {
-+ dropped_text = kmalloc(DROPPED_TEXT_MAX, GFP_KERNEL);
-+ if (!dropped_text)
-+ goto out;
-+ }
-+
-+ for (;;) {
-+ error = wait_event_interruptible(log_wait, printer_should_wake(con, seq));
-+
-+ if (kthread_should_stop())
-+ break;
-+
-+ if (error)
-+ continue;
-+
-+ do {
-+ console_lock();
-+ if (console_suspended) {
-+ console_unlock();
-+ break;
-+ }
-+
-+ /*
-+ * Even though the printk kthread is always preemptible, it is
-+ * still not allowed to call cond_resched() from within
-+ * console drivers. The task may become non-preemptible in the
-+ * console driver call chain. For example, vt_console_print()
-+ * takes a spinlock and then can call into fbcon_redraw(),
-+ * which can conditionally invoke cond_resched().
-+ */
-+ console_may_schedule = 0;
-+ progress = console_emit_next_record(con, text, ext_text,
-+ dropped_text, &handover);
-+ if (handover)
-+ break;
-+
-+ seq = con->seq;
-+
-+ /* Unlock console without invoking direct printing. */
-+ __console_unlock();
-+ } while (progress);
-+ }
-+out:
-+ kfree(dropped_text);
-+ kfree(ext_text);
-+ kfree(text);
-+ pr_info("%sconsole [%s%d]: printing thread stopped\n",
-+ (con->flags & CON_BOOT) ? "boot" : "",
-+ con->name, con->index);
-+ return 0;
-+}
-+
-+/* Must be called within console_lock(). */
-+static void start_printk_kthread(struct console *con)
-+{
-+ con->thread = kthread_run(printk_kthread_func, con,
-+ "pr/%s%d", con->name, con->index);
-+ if (IS_ERR(con->thread)) {
-+ con->thread = NULL;
-+ pr_err("%sconsole [%s%d]: unable to start printing thread\n",
-+ (con->flags & CON_BOOT) ? "boot" : "",
-+ con->name, con->index);
-+ return;
-+ }
-+}
-+
- /*
- * Delayed printk version, for scheduler-internal messages:
- */
-@@ -3373,7 +3528,7 @@ static void wake_up_klogd_work_func(stru
- }
-
- if (pending & PRINTK_PENDING_WAKEUP)
-- wake_up_interruptible(&log_wait);
-+ wake_up_interruptible_all(&log_wait);
- }
-
- static DEFINE_PER_CPU(struct irq_work, wake_up_klogd_work) =
diff --git a/patches/0007-printk-move-buffer-definitions-into-console_emit_nex.patch b/patches/0010-printk-move-buffer-definitions-into-console_emit_nex.patch
index d083e0c61dd7..56b3e26672b8 100644
--- a/patches/0007-printk-move-buffer-definitions-into-console_emit_nex.patch
+++ b/patches/0010-printk-move-buffer-definitions-into-console_emit_nex.patch
@@ -1,6 +1,6 @@
From: John Ogness <john.ogness@linutronix.de>
-Date: Mon, 7 Feb 2022 15:54:22 +0106
-Subject: [PATCH 07/16] printk: move buffer definitions into
+Date: Wed, 20 Apr 2022 01:52:32 +0206
+Subject: [PATCH 10/15] printk: move buffer definitions into
console_emit_next_record() caller
Extended consoles print extended messages and do not print messages about
@@ -24,14 +24,16 @@ With this change, buffer definition/allocation/specification is separated
from the code that does the various types of string printing.
Signed-off-by: John Ogness <john.ogness@linutronix.de>
+Reviewed-by: Petr Mladek <pmladek@suse.com>
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Link: https://lore.kernel.org/r/20220419234637.357112-11-john.ogness@linutronix.de
---
kernel/printk/printk.c | 60 +++++++++++++++++++++++++++++++++++--------------
1 file changed, 43 insertions(+), 17 deletions(-)
--- a/kernel/printk/printk.c
+++ b/kernel/printk/printk.c
-@@ -381,6 +381,9 @@ static struct latched_seq clear_seq = {
+@@ -394,6 +394,9 @@ static struct latched_seq clear_seq = {
/* the maximum size of a formatted record (i.e. with prefix added per line) */
#define CONSOLE_LOG_MAX 1024
@@ -41,7 +43,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
/* the maximum size allowed to be reserved for a record */
#define LOG_LINE_MAX (CONSOLE_LOG_MAX - PREFIX_MAX)
-@@ -1878,18 +1881,18 @@ static int console_trylock_spinning(void
+@@ -1923,18 +1926,18 @@ static int console_trylock_spinning(void
/*
* Call the specified console driver, asking it to write out the specified
@@ -65,7 +67,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
"** %lu printk messages dropped **\n",
con->dropped);
con->dropped = 0;
-@@ -2242,6 +2245,7 @@ EXPORT_SYMBOL(_printk);
+@@ -2296,6 +2299,7 @@ EXPORT_SYMBOL(_printk);
#else /* CONFIG_PRINTK */
#define CONSOLE_LOG_MAX 0
@@ -73,19 +75,19 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
#define printk_time false
#define prb_read_valid(rb, seq, r) false
-@@ -2265,7 +2269,10 @@ static ssize_t msg_print_ext_body(char *
+@@ -2319,7 +2323,10 @@ static ssize_t msg_print_ext_body(char *
struct dev_printk_info *dev_info) { return 0; }
static void console_lock_spinning_enable(void) { }
static int console_lock_spinning_disable_and_check(void) { return 0; }
--static void call_console_driver(struct console *con, const char *text, size_t len) {}
+-static void call_console_driver(struct console *con, const char *text, size_t len) { }
+static void call_console_driver(struct console *con, const char *text, size_t len,
+ char *dropped_text)
+{
+}
static bool suppress_message_printing(int level) { return false; }
- static void printk_delay(int level) {}
-@@ -2561,6 +2568,14 @@ static void __console_unlock(void)
+ #endif /* CONFIG_PRINTK */
+@@ -2644,6 +2651,14 @@ static void __console_unlock(void)
* Print one record for the given console. The record printed is whatever
* record is the next available record for the given console.
*
@@ -97,12 +99,12 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+ * If dropped messages should be printed, @dropped_text is a buffer of size
+ * DROPPED_TEXT_MAX. Otherwise @dropped_text must be NULL.
+ *
- * Requires the console_lock.
- *
- * Returns false if the given console has no next record to print, otherwise
-@@ -2570,17 +2585,16 @@ static void __console_unlock(void)
+ * @handover will be set to true if a printk waiter has taken over the
* console_lock, in which case the caller is no longer holding the
* console_lock. Otherwise it is set to false.
+@@ -2653,10 +2668,9 @@ static void __console_unlock(void)
+ *
+ * Requires the console_lock.
*/
-static bool console_emit_next_record(struct console *con, bool *handover)
+static bool console_emit_next_record(struct console *con, char *text, char *ext_text,
@@ -110,9 +112,10 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
{
- static char ext_text[CONSOLE_EXT_LOG_MAX];
- static char text[CONSOLE_LOG_MAX];
+ static int panic_console_dropped;
struct printk_info info;
struct printk_record r;
- unsigned long flags;
+@@ -2664,7 +2678,7 @@ static bool console_emit_next_record(str
char *write_text;
size_t len;
@@ -121,7 +124,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
*handover = false;
-@@ -2598,13 +2612,13 @@ static bool console_emit_next_record(str
+@@ -2686,13 +2700,13 @@ static bool console_emit_next_record(str
goto skip;
}
@@ -140,7 +143,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
len = record_print_text(&r, console_msg_format & MSG_FORMAT_SYSLOG, printk_time);
}
-@@ -2622,7 +2636,7 @@ static bool console_emit_next_record(str
+@@ -2710,7 +2724,7 @@ static bool console_emit_next_record(str
console_lock_spinning_enable();
stop_critical_timings(); /* don't trace print latency */
@@ -149,7 +152,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
start_critical_timings();
con->seq++;
-@@ -2651,6 +2665,9 @@ static bool console_emit_next_record(str
+@@ -2746,6 +2760,9 @@ static bool console_emit_next_record(str
*/
static bool console_flush_all(bool do_cond_resched, u64 *next_seq, bool *handover)
{
@@ -159,7 +162,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
bool any_usable = false;
struct console *con;
bool any_progress;
-@@ -2668,7 +2685,16 @@ static bool console_flush_all(bool do_co
+@@ -2763,7 +2780,16 @@ static bool console_flush_all(bool do_co
continue;
any_usable = true;
@@ -175,5 +178,5 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+ handover);
+ }
if (*handover)
- return true;
+ return false;
diff --git a/patches/0008-printk-add-pr_flush.patch b/patches/0011-printk-add-pr_flush.patch
index ffdc30eada19..042c619867ee 100644
--- a/patches/0008-printk-add-pr_flush.patch
+++ b/patches/0011-printk-add-pr_flush.patch
@@ -1,9 +1,9 @@
From: John Ogness <john.ogness@linutronix.de>
-Date: Mon, 7 Feb 2022 15:54:26 +0106
-Subject: [PATCH 08/16] printk: add pr_flush()
+Date: Wed, 20 Apr 2022 01:52:33 +0206
+Subject: [PATCH 11/15] printk: add pr_flush()
-Provide a might-sleep function to allow waiting for threaded console
-printers to catch up to the latest logged message.
+Provide a might-sleep function to allow waiting for console printers
+to catch up to the latest logged message.
Use pr_flush() whenever it is desirable to get buffered messages
printed before continuing: suspend_console(), resume_console(),
@@ -11,10 +11,11 @@ console_stop(), console_start(), console_unblank().
Signed-off-by: John Ogness <john.ogness@linutronix.de>
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Link: https://lore.kernel.org/r/20220419234637.357112-12-john.ogness@linutronix.de
---
include/linux/printk.h | 7 ++++
- kernel/printk/printk.c | 73 ++++++++++++++++++++++++++++++++++++++++++++++++-
- 2 files changed, 79 insertions(+), 1 deletion(-)
+ kernel/printk/printk.c | 83 +++++++++++++++++++++++++++++++++++++++++++++++++
+ 2 files changed, 90 insertions(+)
--- a/include/linux/printk.h
+++ b/include/linux/printk.h
@@ -41,7 +42,24 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
return 0;
--- a/kernel/printk/printk.c
+++ b/kernel/printk/printk.c
-@@ -2450,6 +2450,7 @@ void suspend_console(void)
+@@ -2296,6 +2296,8 @@ asmlinkage __visible int _printk(const c
+ }
+ EXPORT_SYMBOL(_printk);
+
++static bool __pr_flush(struct console *con, int timeout_ms, bool reset_on_progress);
++
+ #else /* CONFIG_PRINTK */
+
+ #define CONSOLE_LOG_MAX 0
+@@ -2328,6 +2330,7 @@ static void call_console_driver(struct c
+ {
+ }
+ static bool suppress_message_printing(int level) { return false; }
++static bool __pr_flush(struct console *con, int timeout_ms, bool reset_on_progress) { return true; }
+
+ #endif /* CONFIG_PRINTK */
+
+@@ -2515,6 +2518,7 @@ void suspend_console(void)
if (!console_suspend_enabled)
return;
pr_info("Suspending console(s) (use no_console_suspend to debug)\n");
@@ -49,7 +67,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
console_lock();
console_suspended = 1;
up_console_sem();
-@@ -2462,6 +2463,7 @@ void resume_console(void)
+@@ -2527,6 +2531,7 @@ void resume_console(void)
down_console_sem();
console_suspended = 0;
console_unlock();
@@ -57,57 +75,41 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
}
/**
-@@ -2803,8 +2805,10 @@ void console_unblank(void)
- if (oops_in_progress) {
- if (down_trylock_console_sem() != 0)
- return;
-- } else
-+ } else {
+@@ -2912,6 +2917,9 @@ void console_unblank(void)
+ if ((c->flags & CON_ENABLED) && c->unblank)
+ c->unblank();
+ console_unlock();
++
++ if (!oops_in_progress)
+ pr_flush(1000, true);
- console_lock();
-+ }
+ }
- console_locked = 1;
- console_may_schedule = 0;
-@@ -2870,6 +2874,7 @@ struct tty_driver *console_device(int *i
+ /**
+@@ -2970,6 +2978,7 @@ struct tty_driver *console_device(int *i
*/
void console_stop(struct console *console)
{
-+ pr_flush(1000, true);
++ __pr_flush(console, 1000, true);
console_lock();
console->flags &= ~CON_ENABLED;
console_unlock();
-@@ -2881,6 +2886,7 @@ void console_start(struct console *conso
+@@ -2981,6 +2990,7 @@ void console_start(struct console *conso
console_lock();
console->flags |= CON_ENABLED;
console_unlock();
-+ pr_flush(1000, true);
++ __pr_flush(console, 1000, true);
}
EXPORT_SYMBOL(console_start);
-@@ -3251,6 +3257,71 @@ static int __init printk_late_init(void)
+@@ -3352,6 +3362,79 @@ static int __init printk_late_init(void)
late_initcall(printk_late_init);
#if defined CONFIG_PRINTK
-+/**
-+ * pr_flush() - Wait for printing threads to catch up.
-+ *
-+ * @timeout_ms: The maximum time (in ms) to wait.
-+ * @reset_on_progress: Reset the timeout if forward progress is seen.
-+ *
-+ * A value of 0 for @timeout_ms means no waiting will occur. A value of -1
-+ * represents infinite waiting.
-+ *
-+ * If @reset_on_progress is true, the timeout will be reset whenever any
-+ * printer has been seen to make some forward progress.
-+ *
-+ * Context: Process context. May sleep while acquiring console lock.
-+ * Return: true if all enabled printers are caught up.
-+ */
-+bool pr_flush(int timeout_ms, bool reset_on_progress)
++/* If @con is specified, only wait for that console. Otherwise wait for all. */
++static bool __pr_flush(struct console *con, int timeout_ms, bool reset_on_progress)
+{
+ int remaining = timeout_ms;
-+ struct console *con;
++ struct console *c;
+ u64 last_diff = 0;
+ u64 printk_seq;
+ u64 diff;
@@ -121,10 +123,12 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+ diff = 0;
+
+ console_lock();
-+ for_each_console(con) {
-+ if (!console_is_usable(con))
++ for_each_console(c) {
++ if (con && con != c)
++ continue;
++ if (!console_is_usable(c))
+ continue;
-+ printk_seq = con->seq;
++ printk_seq = c->seq;
+ if (printk_seq < seq)
+ diff += seq - printk_seq;
+ }
@@ -152,6 +156,26 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+
+ return (diff == 0);
+}
++
++/**
++ * pr_flush() - Wait for printing threads to catch up.
++ *
++ * @timeout_ms: The maximum time (in ms) to wait.
++ * @reset_on_progress: Reset the timeout if forward progress is seen.
++ *
++ * A value of 0 for @timeout_ms means no waiting will occur. A value of -1
++ * represents infinite waiting.
++ *
++ * If @reset_on_progress is true, the timeout will be reset whenever any
++ * printer has been seen to make some forward progress.
++ *
++ * Context: Process context. May sleep while acquiring console lock.
++ * Return: true if all enabled printers are caught up.
++ */
++bool pr_flush(int timeout_ms, bool reset_on_progress)
++{
++ return __pr_flush(NULL, timeout_ms, reset_on_progress);
++}
+EXPORT_SYMBOL(pr_flush);
+
/*
diff --git a/patches/0011-printk-reimplement-console_lock-for-proper-kthread-s.patch b/patches/0011-printk-reimplement-console_lock-for-proper-kthread-s.patch
deleted file mode 100644
index 4b57e7153c5d..000000000000
--- a/patches/0011-printk-reimplement-console_lock-for-proper-kthread-s.patch
+++ /dev/null
@@ -1,480 +0,0 @@
-From: John Ogness <john.ogness@linutronix.de>
-Date: Mon, 7 Feb 2022 15:54:47 +0106
-Subject: [PATCH 11/16] printk: reimplement console_lock for proper kthread
- support
-
-With non-threaded console printers preemption is disabled while
-holding the console lock in order to avoid the situation where the
-console printer is scheduled away and no other task can lock the
-console (for printing or otherwise). Disabling preemption is
-necessary because the console lock is implemented purely as a
-semaphore, which has no owner.
-
-Like non-threaded console printers, kthread printers use the
-console lock to synchronize during printing. However, since they
-use console_lock() instead of a best-effort console_trylock(), it
-is not possible to disable preemption upon locking. Therefore an
-alternative for synchronizing and avoiding the above mentioned
-situation is needed.
-
-The kthread printers do not need to synchronize against each other,
-but they do need to synchronize against console_lock() callers. To
-provide this synchronization, introduce a per-console mutex. The
-mutex is taken by the kthread printer during printing and is also
-taken by console_lock() callers. Since mutexes have owners, when
-calling console_lock(), the scheduler is able to schedule any
-kthread printers that may have been preempted while printing.
-
-Rather than console_lock() callers holding the per-console mutex
-for the duration of the console lock, the per-console mutex is only
-taken in order to set a new CON_PAUSED flag, which is checked by
-the kthread printers. This avoids any issues due to nested locking
-between the various per-console mutexes.
-
-The kthread printers must also synchronize against console_trylock()
-callers. Since console_trylock() is non-blocking, a global atomic
-counter will be used to identify if any kthread printers are active.
-The kthread printers will also check the atomic counter to identify
-if the console has been locked by another task via
-console_trylock().
-
-A locking overview for console_lock(), console_trylock(), and the
-kthread printers is as follows (pseudo code):
-
-console_lock()
-{
- down(&console_sem);
- for_each_console(con) {
- mutex_lock(&con->lock);
- con->flags |= CON_PAUSED;
- mutex_unlock(&con->lock);
- }
- /* console lock acquired */
-}
-
-console_trylock()
-{
- if (down_trylock(&console_sem) == 0) {
- if (atomic_cmpxchg(&console_lock_count, 0, -1) == 0) {
- /* console lock acquired */
- }
- }
-}
-
-threaded_printer()
-{
- mutex_lock(&con->lock);
- if (!(con->flags & CON_PAUSED)) {
- if (atomic_inc_unless_negative(&console_lock_count)) {
- /* console locking now blocked */
-
- con->write();
- atomic_dec(&console_lock_count);
- }
- }
- mutex_unlock(&con->lock);
-}
-
-Also note that the console owner and waiter logic now only applies
-between contexts that have both taken the console lock via
-console_trylock(). This is for 2 reasons:
-
-1. Contexts that have taken the console lock via console_lock()
- require a sleepable context when unlocking to unpause the kthread
- printers. But a waiter context has used console_trylock() and
- may not be sleepable.
-
-2. The kthread printers no longer acquire the console lock, so it is
- not possible to handover the console lock.
-
-This also has implications for console_unlock(), which attempts a
-console_trylock() before returning. Introduce
-console_trylock_sched() to allow console_unlock() to specify if it
-is in a sleepable context.
-
-Signed-off-by: John Ogness <john.ogness@linutronix.de>
-Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
----
- include/linux/console.h | 15 +++
- kernel/printk/printk.c | 190 ++++++++++++++++++++++++++++++++++++++----------
- 2 files changed, 166 insertions(+), 39 deletions(-)
-
---- a/include/linux/console.h
-+++ b/include/linux/console.h
-@@ -16,6 +16,7 @@
-
- #include <linux/atomic.h>
- #include <linux/types.h>
-+#include <linux/mutex.h>
-
- struct vc_data;
- struct console_font_op;
-@@ -136,6 +137,7 @@ static inline int con_debug_leave(void)
- #define CON_ANYTIME (16) /* Safe to call before per-cpu resources ready */
- #define CON_BRL (32) /* Used for a braille device */
- #define CON_EXTENDED (64) /* Use the extended output format a la /dev/kmsg */
-+#define CON_PAUSED (128) /* Sleep while console is locked */
-
- struct console {
- char name[16];
-@@ -155,6 +157,19 @@ struct console {
- unsigned long dropped;
- struct task_struct *thread;
-
-+ /*
-+ * The per-console lock is used by printing kthreads to synchronize
-+ * this console with callers of console_lock(). This is necessary in
-+ * order to allow printing kthreads to run in parallel to each other,
-+ * while each safely accessing their own @flags and synchronizing
-+ * against direct printing via console_lock/console_unlock.
-+ *
-+ * Note: For synchronizing against direct printing via
-+ * console_trylock/console_unlock, see the static global
-+ * variable @console_lock_count.
-+ */
-+ struct mutex lock;
-+
- void *data;
- struct console *next;
- };
---- a/kernel/printk/printk.c
-+++ b/kernel/printk/printk.c
-@@ -216,6 +216,26 @@ int devkmsg_sysctl_set_loglvl(struct ctl
- static int nr_ext_console_drivers;
-
- /*
-+ * Used to synchronize printing kthreads against direct printing via
-+ * console_trylock/console_unlock.
-+ *
-+ * Values:
-+ * -1 = console locked (via trylock), kthreads will not print
-+ * 0 = no kthread printing, console not locked (via trylock)
-+ * >0 = kthread(s) actively printing
-+ *
-+ * Note: For synchronizing against direct printing via
-+ * console_lock/console_unlock, see the @lock variable in
-+ * struct console.
-+ */
-+static atomic_t console_lock_count = ATOMIC_INIT(0);
-+
-+#define console_excl_trylock() (atomic_cmpxchg(&console_lock_count, 0, -1) == 0)
-+#define console_excl_unlock() atomic_cmpxchg(&console_lock_count, -1, 0)
-+#define console_printer_tryenter() atomic_inc_unless_negative(&console_lock_count)
-+#define console_printer_exit() atomic_dec(&console_lock_count)
-+
-+/*
- * Helper macros to handle lockdep when locking/unlocking console_sem. We use
- * macros instead of functions so that _RET_IP_ contains useful information.
- */
-@@ -258,6 +278,37 @@ static void __up_console_sem(unsigned lo
- #define up_console_sem() __up_console_sem(_RET_IP_)
-
- /*
-+ * Tracks whether kthread printers are all paused. A value of true implies
-+ * that the console is locked via console_lock() or the console is suspended.
-+ * Reading and writing to this variable requires holding @console_sem.
-+ */
-+static bool consoles_paused;
-+
-+/*
-+ * Pause or unpause all kthread printers.
-+ *
-+ * Requires the console_lock.
-+ */
-+static void __pause_all_consoles(bool do_pause)
-+{
-+ struct console *con;
-+
-+ for_each_console(con) {
-+ mutex_lock(&con->lock);
-+ if (do_pause)
-+ con->flags |= CON_PAUSED;
-+ else
-+ con->flags &= ~CON_PAUSED;
-+ mutex_unlock(&con->lock);
-+ }
-+
-+ consoles_paused = do_pause;
-+}
-+
-+#define pause_all_consoles() __pause_all_consoles(true)
-+#define unpause_all_consoles() __pause_all_consoles(false)
-+
-+/*
- * This is used for debugging the mess that is the VT code by
- * keeping track if we have the console semaphore held. It's
- * definitely not the perfect debug tool (we don't know if _WE_
-@@ -2507,10 +2558,6 @@ void resume_console(void)
- down_console_sem();
- console_suspended = 0;
- console_unlock();
--
-- /* Wake the kthread printers. */
-- wake_up_klogd();
--
- pr_flush(1000, true);
- }
-
-@@ -2548,6 +2595,7 @@ void console_lock(void)
- down_console_sem();
- if (console_suspended)
- return;
-+ pause_all_consoles();
- console_locked = 1;
- console_may_schedule = 1;
- }
-@@ -2569,15 +2617,45 @@ int console_trylock(void)
- up_console_sem();
- return 0;
- }
-+ if (!console_excl_trylock()) {
-+ up_console_sem();
-+ return 0;
-+ }
- console_locked = 1;
- console_may_schedule = 0;
- return 1;
- }
- EXPORT_SYMBOL(console_trylock);
-
-+/*
-+ * A variant of console_trylock() that allows specifying if the context may
-+ * sleep. If yes, a trylock on @console_sem is attempted and if successful,
-+ * the threaded printers are paused. This is important to ensure that
-+ * sleepable contexts do not become involved in console_lock handovers and
-+ * will call cond_resched() during the printing loop.
-+ */
-+static int console_trylock_sched(bool may_schedule)
-+{
-+ if (!may_schedule)
-+ return console_trylock();
-+
-+ might_sleep();
-+
-+ if (down_trylock_console_sem())
-+ return 0;
-+ if (console_suspended) {
-+ up_console_sem();
-+ return 0;
-+ }
-+ pause_all_consoles();
-+ console_locked = 1;
-+ console_may_schedule = 1;
-+ return 1;
-+}
-+
- int is_console_locked(void)
- {
-- return console_locked;
-+ return (console_locked || atomic_read(&console_lock_count));
- }
- EXPORT_SYMBOL(is_console_locked);
-
-@@ -2611,6 +2689,19 @@ static inline bool console_is_usable(str
- static void __console_unlock(void)
- {
- console_locked = 0;
-+
-+ /*
-+ * Depending on whether console_lock() or console_trylock() was used,
-+ * appropriately allow the kthread printers to continue.
-+ */
-+ if (consoles_paused)
-+ unpause_all_consoles();
-+ else
-+ console_excl_unlock();
-+
-+ /* Wake the kthread printers. */
-+ wake_up_klogd();
-+
- up_console_sem();
- }
-
-@@ -2633,7 +2724,8 @@ static void __console_unlock(void)
- *
- * @handover will be set to true if a printk waiter has taken over the
- * console_lock, in which case the caller is no longer holding the
-- * console_lock. Otherwise it is set to false.
-+ * console_lock. Otherwise it is set to false. A NULL pointer may be provided
-+ * to disable allowing the console_lock to be taken over by a printk waiter.
- */
- static bool console_emit_next_record(struct console *con, char *text, char *ext_text,
- char *dropped_text, bool *handover)
-@@ -2641,12 +2733,14 @@ static bool console_emit_next_record(str
- struct printk_info info;
- struct printk_record r;
- unsigned long flags;
-+ bool allow_handover;
- char *write_text;
- size_t len;
-
- prb_rec_init_rd(&r, &info, text, CONSOLE_LOG_MAX);
-
-- *handover = false;
-+ if (handover)
-+ *handover = false;
-
- if (!prb_read_valid(prb, con->seq, &r))
- return false;
-@@ -2672,18 +2766,23 @@ static bool console_emit_next_record(str
- len = record_print_text(&r, console_msg_format & MSG_FORMAT_SYSLOG, printk_time);
- }
-
-- /*
-- * While actively printing out messages, if another printk()
-- * were to occur on another CPU, it may wait for this one to
-- * finish. This task can not be preempted if there is a
-- * waiter waiting to take over.
-- *
-- * Interrupts are disabled because the hand over to a waiter
-- * must not be interrupted until the hand over is completed
-- * (@console_waiter is cleared).
-- */
-- printk_safe_enter_irqsave(flags);
-- console_lock_spinning_enable();
-+ /* Handovers may only happen between trylock contexts. */
-+ allow_handover = (handover && atomic_read(&console_lock_count) == -1);
-+
-+ if (allow_handover) {
-+ /*
-+ * While actively printing out messages, if another printk()
-+ * were to occur on another CPU, it may wait for this one to
-+ * finish. This task can not be preempted if there is a
-+ * waiter waiting to take over.
-+ *
-+ * Interrupts are disabled because the hand over to a waiter
-+ * must not be interrupted until the hand over is completed
-+ * (@console_waiter is cleared).
-+ */
-+ printk_safe_enter_irqsave(flags);
-+ console_lock_spinning_enable();
-+ }
-
- stop_critical_timings(); /* don't trace print latency */
- call_console_driver(con, write_text, len, dropped_text);
-@@ -2691,8 +2790,10 @@ static bool console_emit_next_record(str
-
- con->seq++;
-
-- *handover = console_lock_spinning_disable_and_check();
-- printk_safe_exit_irqrestore(flags);
-+ if (allow_handover) {
-+ *handover = console_lock_spinning_disable_and_check();
-+ printk_safe_exit_irqrestore(flags);
-+ }
-
- printk_delay(r.info->level);
- skip:
-@@ -2826,7 +2927,7 @@ void console_unlock(void)
- * Re-check if there is a new record to flush. If the trylock
- * fails, another context is already handling the printing.
- */
-- } while (prb_read_valid(prb, next_seq, NULL) && console_trylock());
-+ } while (prb_read_valid(prb, next_seq, NULL) && console_trylock_sched(do_cond_resched));
- }
- EXPORT_SYMBOL(console_unlock);
-
-@@ -2857,6 +2958,10 @@ void console_unblank(void)
- if (oops_in_progress) {
- if (down_trylock_console_sem() != 0)
- return;
-+ if (!console_excl_trylock()) {
-+ up_console_sem();
-+ return;
-+ }
- } else {
- pr_flush(1000, true);
- console_lock();
-@@ -2938,10 +3043,6 @@ void console_start(struct console *conso
- console_lock();
- console->flags |= CON_ENABLED;
- console_unlock();
--
-- /* Wake the kthread printers. */
-- wake_up_klogd();
--
- pr_flush(1000, true);
- }
- EXPORT_SYMBOL(console_start);
-@@ -3136,7 +3237,11 @@ void register_console(struct console *ne
- if (newcon->flags & CON_EXTENDED)
- nr_ext_console_drivers++;
-
-+ if (consoles_paused)
-+ newcon->flags |= CON_PAUSED;
-+
- newcon->dropped = 0;
-+ mutex_init(&newcon->lock);
- if (newcon->flags & CON_PRINTBUFFER) {
- /* Get a consistent copy of @syslog_seq. */
- mutex_lock(&syslog_lock);
-@@ -3399,16 +3504,17 @@ static bool printer_should_wake(struct c
- if (kthread_should_stop())
- return true;
-
-- if (console_suspended)
-- return false;
--
- /*
- * This is an unsafe read to con->flags, but false positives
- * are not an issue as long as they are rare.
- */
- flags = data_race(READ_ONCE(con->flags));
-- if (!(flags & CON_ENABLED))
-+
-+ if (!(flags & CON_ENABLED) ||
-+ (flags & CON_PAUSED) ||
-+ atomic_read(&console_lock_count) == -1) {
- return false;
-+ }
-
- return prb_read_valid(prb, seq, NULL);
- }
-@@ -3419,7 +3525,6 @@ static int printk_kthread_func(void *dat
- char *dropped_text = NULL;
- char *ext_text = NULL;
- bool progress;
-- bool handover;
- u64 seq = 0;
- char *text;
- int error;
-@@ -3452,9 +3557,17 @@ static int printk_kthread_func(void *dat
- continue;
-
- do {
-- console_lock();
-- if (console_suspended) {
-- console_unlock();
-+ error = mutex_lock_interruptible(&con->lock);
-+ if (error)
-+ break;
-+
-+ if (!console_is_usable(con)) {
-+ mutex_unlock(&con->lock);
-+ break;
-+ }
-+
-+ if ((con->flags & CON_PAUSED) || !console_printer_tryenter()) {
-+ mutex_unlock(&con->lock);
- break;
- }
-
-@@ -3468,14 +3581,13 @@ static int printk_kthread_func(void *dat
- */
- console_may_schedule = 0;
- progress = console_emit_next_record(con, text, ext_text,
-- dropped_text, &handover);
-- if (handover)
-- break;
-+ dropped_text, NULL);
-
- seq = con->seq;
-
-- /* Unlock console without invoking direct printing. */
-- __console_unlock();
-+ console_printer_exit();
-+
-+ mutex_unlock(&con->lock);
- } while (progress);
- }
- out:
diff --git a/patches/0009-printk-add-functions-to-allow-direct-printing.patch b/patches/0012-printk-add-functions-to-prefer-direct-printing.patch
index dddee01b1439..2533e3afa26f 100644
--- a/patches/0009-printk-add-functions-to-allow-direct-printing.patch
+++ b/patches/0012-printk-add-functions-to-prefer-direct-printing.patch
@@ -1,62 +1,87 @@
From: John Ogness <john.ogness@linutronix.de>
-Date: Mon, 7 Feb 2022 15:54:30 +0106
-Subject: [PATCH 09/16] printk: add functions to allow direct printing
+Date: Wed, 20 Apr 2022 01:52:34 +0206
+Subject: [PATCH 12/15] printk: add functions to prefer direct printing
-Once kthread printing is introduced, console printing will no longer
+Once kthread printing is available, console printing will no longer
occur in the context of the printk caller. However, there are some
special contexts where it is desirable for the printk caller to
directly print out kernel messages. Using pr_flush() to wait for
threaded printers is only possible if the caller is in a sleepable
context and the kthreads are active. That is not always the case.
-Introduce printk_direct_enter() and printk_direct_exit() functions
-to explicitly (and globally) activate/deactivate direct console
-printing.
+Introduce printk_prefer_direct_enter() and printk_prefer_direct_exit()
+functions to explicitly (and globally) activate/deactivate preferred
+direct console printing. The term "direct console printing" refers to
+printing to all enabled consoles from the context of the printk
+caller. The term "prefer" is used because this type of printing is
+only best effort. If the console is currently locked or other
+printers are already actively printing, the printk caller will need
+to rely on the other contexts to handle the printing.
+
+This preferred direct printing is how all printing has been handled
+until now (unless it was explicitly deferred).
+
+When kthread printing is introduced, there may be some unanticipated
+problems due to kthreads being unable to flush important messages.
+In order to minimize such risks, preferred direct printing is
+activated for the primary important messages when the system
+experiences general types of major errors. These are:
-Activate direct printing for:
- - sysrq
- emergency reboot/shutdown
- cpu and rcu stalls
- hard and soft lockups
- hung tasks
- - stack dumps
+ - warn
+ - sysrq
+
+Note that since kthread printing does not yet exist, no behavior
+changes result from this commit. This is only implementing the
+counter and marking the various places where preferred direct
+printing is active.
Signed-off-by: John Ogness <john.ogness@linutronix.de>
+Reviewed-by: Petr Mladek <pmladek@suse.com>
+Acked-by: Paul E. McKenney <paulmck@kernel.org> # for RCU
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Link: https://lore.kernel.org/r/20220419234637.357112-13-john.ogness@linutronix.de
---
drivers/tty/sysrq.c | 2 ++
include/linux/printk.h | 11 +++++++++++
kernel/hung_task.c | 11 ++++++++++-
- kernel/printk/printk.c | 39 ++++++++++++++++++++++++++++++++++++++-
+ kernel/panic.c | 4 ++++
+ kernel/printk/printk.c | 28 ++++++++++++++++++++++++++++
kernel/rcu/tree_stall.h | 2 ++
kernel/reboot.c | 14 +++++++++++++-
kernel/watchdog.c | 4 ++++
kernel/watchdog_hld.c | 4 ++++
- lib/dump_stack.c | 2 ++
- lib/nmi_backtrace.c | 2 ++
- 10 files changed, 88 insertions(+), 3 deletions(-)
+ 9 files changed, 78 insertions(+), 2 deletions(-)
--- a/drivers/tty/sysrq.c
+++ b/drivers/tty/sysrq.c
-@@ -594,9 +594,11 @@ void __handle_sysrq(int key, bool check_
- * should not) and is the invoked operation enabled?
- */
- if (!check_mask || sysrq_on_mask(op_p->enable_mask)) {
-+ printk_direct_enter();
- pr_info("%s\n", op_p->action_msg);
- console_loglevel = orig_log_level;
- op_p->handler(key);
-+ printk_direct_exit();
- } else {
- pr_info("This sysrq operation is disabled.\n");
- console_loglevel = orig_log_level;
+@@ -578,6 +578,7 @@ void __handle_sysrq(int key, bool check_
+
+ rcu_sysrq_start();
+ rcu_read_lock();
++ printk_prefer_direct_enter();
+ /*
+ * Raise the apparent loglevel to maximum so that the sysrq header
+ * is shown to provide the user with positive feedback. We do not
+@@ -619,6 +620,7 @@ void __handle_sysrq(int key, bool check_
+ pr_cont("\n");
+ console_loglevel = orig_log_level;
+ }
++ printk_prefer_direct_exit();
+ rcu_read_unlock();
+ rcu_sysrq_end();
+
--- a/include/linux/printk.h
+++ b/include/linux/printk.h
@@ -170,6 +170,9 @@ extern void __printk_safe_exit(void);
#define printk_deferred_enter __printk_safe_enter
#define printk_deferred_exit __printk_safe_exit
-+extern void printk_direct_enter(void);
-+extern void printk_direct_exit(void);
++extern void printk_prefer_direct_enter(void);
++extern void printk_prefer_direct_exit(void);
+
extern bool pr_flush(int timeout_ms, bool reset_on_progress);
@@ -65,11 +90,11 @@ Signed-off-by: John Ogness <john.ogness@linutronix.de>
{
}
-+static inline void printk_direct_enter(void)
++static inline void printk_prefer_direct_enter(void)
+{
+}
+
-+static inline void printk_direct_exit(void)
++static inline void printk_prefer_direct_exit(void)
+{
+}
+
@@ -82,7 +107,7 @@ Signed-off-by: John Ogness <john.ogness@linutronix.de>
* complain:
*/
if (sysctl_hung_task_warnings) {
-+ printk_direct_enter();
++ printk_prefer_direct_enter();
+
if (sysctl_hung_task_warnings > 0)
sysctl_hung_task_warnings--;
@@ -92,7 +117,7 @@ Signed-off-by: John Ogness <john.ogness@linutronix.de>
if (sysctl_hung_task_all_cpu_backtrace)
hung_task_show_all_bt = true;
+
-+ printk_direct_exit();
++ printk_prefer_direct_exit();
}
touch_nmi_watchdog();
@@ -102,110 +127,91 @@ Signed-off-by: John Ogness <john.ogness@linutronix.de>
rcu_read_unlock();
- if (hung_task_show_lock)
+ if (hung_task_show_lock) {
-+ printk_direct_enter();
++ printk_prefer_direct_enter();
debug_show_all_locks();
-+ printk_direct_exit();
++ printk_prefer_direct_exit();
+ }
if (hung_task_show_all_bt) {
hung_task_show_all_bt = false;
-+ printk_direct_enter();
++ printk_prefer_direct_enter();
trigger_all_cpu_backtrace();
-+ printk_direct_exit();
++ printk_prefer_direct_exit();
}
if (hung_task_call_panic)
+--- a/kernel/panic.c
++++ b/kernel/panic.c
+@@ -579,6 +579,8 @@ void __warn(const char *file, int line,
+ {
+ disable_trace_on_warning();
+
++ printk_prefer_direct_enter();
++
+ if (file)
+ pr_warn("WARNING: CPU: %d PID: %d at %s:%d %pS\n",
+ raw_smp_processor_id(), current->pid, file, line,
+@@ -608,6 +610,8 @@ void __warn(const char *file, int line,
+
+ /* Just a warning, don't kill lockdep. */
+ add_taint(taint, LOCKDEP_STILL_OK);
++
++ printk_prefer_direct_exit();
+ }
+
+ #ifndef __WARN_FLAGS
--- a/kernel/printk/printk.c
+++ b/kernel/printk/printk.c
-@@ -349,6 +349,31 @@ static int console_msg_format = MSG_FORM
+@@ -362,6 +362,34 @@ static int console_msg_format = MSG_FORM
static DEFINE_MUTEX(syslog_lock);
#ifdef CONFIG_PRINTK
-+static atomic_t printk_direct = ATOMIC_INIT(0);
++static atomic_t printk_prefer_direct = ATOMIC_INIT(0);
+
+/**
-+ * printk_direct_enter - cause console printing to occur in the context of
-+ * printk() callers
++ * printk_prefer_direct_enter - cause printk() calls to attempt direct
++ * printing to all enabled consoles
++ *
++ * Since it is not possible to call into the console printing code from any
++ * context, there is no guarantee that direct printing will occur.
+ *
+ * This globally effects all printk() callers.
+ *
+ * Context: Any context.
+ */
-+void printk_direct_enter(void)
++void printk_prefer_direct_enter(void)
+{
-+ atomic_inc(&printk_direct);
++ atomic_inc(&printk_prefer_direct);
+}
+
+/**
-+ * printk_direct_exit - restore console printing behavior from direct
++ * printk_prefer_direct_exit - restore printk() behavior
+ *
+ * Context: Any context.
+ */
-+void printk_direct_exit(void)
++void printk_prefer_direct_exit(void)
+{
-+ atomic_dec(&printk_direct);
++ WARN_ON(atomic_dec_if_positive(&printk_prefer_direct) < 0);
+}
+
DECLARE_WAIT_QUEUE_HEAD(log_wait);
/* All 3 protected by @syslog_lock. */
/* the next printk record to read by syslog(READ) or /proc/kmsg */
-@@ -3327,6 +3352,7 @@ EXPORT_SYMBOL(pr_flush);
- */
- #define PRINTK_PENDING_WAKEUP 0x01
- #define PRINTK_PENDING_OUTPUT 0x02
-+#define PRINTK_DIRECT_OUTPUT 0x04
-
- static DEFINE_PER_CPU(int, printk_pending);
-
-@@ -3335,9 +3361,15 @@ static void wake_up_klogd_work_func(stru
- int pending = __this_cpu_xchg(printk_pending, 0);
-
- if (pending & PRINTK_PENDING_OUTPUT) {
-+ if (pending & PRINTK_DIRECT_OUTPUT)
-+ printk_direct_enter();
-+
- /* If trylock fails, someone else is doing the printing */
- if (console_trylock())
- console_unlock();
-+
-+ if (pending & PRINTK_DIRECT_OUTPUT)
-+ printk_direct_exit();
- }
-
- if (pending & PRINTK_PENDING_WAKEUP)
-@@ -3362,11 +3394,16 @@ void wake_up_klogd(void)
-
- void defer_console_output(void)
- {
-+ int val = PRINTK_PENDING_OUTPUT;
-+
- if (!printk_percpu_data_ready())
- return;
-
-+ if (atomic_read(&printk_direct))
-+ val |= PRINTK_DIRECT_OUTPUT;
-+
- preempt_disable();
-- this_cpu_or(printk_pending, PRINTK_PENDING_OUTPUT);
-+ this_cpu_or(printk_pending, val);
- irq_work_queue(this_cpu_ptr(&wake_up_klogd_work));
- preempt_enable();
- }
--- a/kernel/rcu/tree_stall.h
+++ b/kernel/rcu/tree_stall.h
-@@ -587,6 +587,7 @@ static void print_cpu_stall(unsigned lon
+@@ -619,6 +619,7 @@ static void print_cpu_stall(unsigned lon
* See Documentation/RCU/stallwarn.rst for info on how to debug
* RCU CPU stall warnings.
*/
-+ printk_direct_enter();
++ printk_prefer_direct_enter();
trace_rcu_stall_warning(rcu_state.name, TPS("SelfDetected"));
pr_err("INFO: %s self-detected stall on CPU\n", rcu_state.name);
raw_spin_lock_irqsave_rcu_node(rdp->mynode, flags);
-@@ -621,6 +622,7 @@ static void print_cpu_stall(unsigned lon
+@@ -656,6 +657,7 @@ static void print_cpu_stall(unsigned lon
*/
set_tsk_need_resched(current);
set_preempt_need_resched();
-+ printk_direct_exit();
++ printk_prefer_direct_exit();
}
static void check_cpu_stall(struct rcu_data *rdp)
@@ -215,11 +221,11 @@ Signed-off-by: John Ogness <john.ogness@linutronix.de>
ret = run_cmd(reboot_cmd);
if (ret) {
-+ printk_direct_enter();
++ printk_prefer_direct_enter();
pr_warn("Failed to start orderly reboot: forcing the issue\n");
emergency_sync();
kernel_restart(NULL);
-+ printk_direct_exit();
++ printk_prefer_direct_exit();
}
return ret;
@@ -227,7 +233,7 @@ Signed-off-by: John Ogness <john.ogness@linutronix.de>
ret = run_cmd(poweroff_cmd);
if (ret && force) {
-+ printk_direct_enter();
++ printk_prefer_direct_enter();
pr_warn("Failed to start orderly shutdown: forcing the issue\n");
/*
@@ -235,7 +241,7 @@ Signed-off-by: John Ogness <john.ogness@linutronix.de>
*/
emergency_sync();
kernel_power_off();
-+ printk_direct_exit();
++ printk_prefer_direct_exit();
}
return ret;
@@ -243,7 +249,7 @@ Signed-off-by: John Ogness <john.ogness@linutronix.de>
*/
static void hw_failure_emergency_poweroff_func(struct work_struct *work)
{
-+ printk_direct_enter();
++ printk_prefer_direct_enter();
+
/*
* We have reached here after the emergency shutdown waiting period has
@@ -253,7 +259,7 @@ Signed-off-by: John Ogness <john.ogness@linutronix.de>
pr_emerg("Hardware protection shutdown failed. Trying emergency restart\n");
emergency_restart();
+
-+ printk_direct_exit();
++ printk_prefer_direct_exit();
}
static DECLARE_DELAYED_WORK(hw_failure_emergency_poweroff_work,
@@ -261,7 +267,7 @@ Signed-off-by: John Ogness <john.ogness@linutronix.de>
{
static atomic_t allow_proceed = ATOMIC_INIT(1);
-+ printk_direct_enter();
++ printk_prefer_direct_enter();
+
pr_emerg("HARDWARE PROTECTION shutdown (%s)\n", reason);
@@ -277,7 +283,7 @@ Signed-off-by: John Ogness <john.ogness@linutronix.de>
hw_failure_emergency_poweroff(ms_until_forced);
orderly_poweroff(true);
+out:
-+ printk_direct_exit();
++ printk_prefer_direct_exit();
}
EXPORT_SYMBOL_GPL(hw_protection_shutdown);
@@ -287,7 +293,7 @@ Signed-off-by: John Ogness <john.ogness@linutronix.de>
/* Start period for the next softlockup warning. */
update_report_ts();
-+ printk_direct_enter();
++ printk_prefer_direct_enter();
+
pr_emerg("BUG: soft lockup - CPU#%d stuck for %us! [%s:%d]\n",
smp_processor_id(), duration,
@@ -297,7 +303,7 @@ Signed-off-by: John Ogness <john.ogness@linutronix.de>
if (softlockup_panic)
panic("softlockup: hung tasks");
+
-+ printk_direct_exit();
++ printk_prefer_direct_exit();
}
return HRTIMER_RESTART;
@@ -307,7 +313,7 @@ Signed-off-by: John Ogness <john.ogness@linutronix.de>
if (__this_cpu_read(hard_watchdog_warn) == true)
return;
-+ printk_direct_enter();
++ printk_prefer_direct_enter();
+
pr_emerg("Watchdog detected hard LOCKUP on cpu %d\n",
this_cpu);
@@ -316,40 +322,8 @@ Signed-off-by: John Ogness <john.ogness@linutronix.de>
if (hardlockup_panic)
nmi_panic(regs, "Hard LOCKUP");
-+ printk_direct_exit();
++ printk_prefer_direct_exit();
+
__this_cpu_write(hard_watchdog_warn, true);
return;
}
---- a/lib/dump_stack.c
-+++ b/lib/dump_stack.c
-@@ -102,9 +102,11 @@ asmlinkage __visible void dump_stack_lvl
- * Permit this cpu to perform nested stack dumps while serialising
- * against other CPUs
- */
-+ printk_direct_enter();
- printk_cpu_sync_get_irqsave(flags);
- __dump_stack(log_lvl);
- printk_cpu_sync_put_irqrestore(flags);
-+ printk_direct_exit();
- }
- EXPORT_SYMBOL(dump_stack_lvl);
-
---- a/lib/nmi_backtrace.c
-+++ b/lib/nmi_backtrace.c
-@@ -99,6 +99,7 @@ bool nmi_cpu_backtrace(struct pt_regs *r
- * Allow nested NMI backtraces while serializing
- * against other CPUs.
- */
-+ printk_direct_enter();
- printk_cpu_sync_get_irqsave(flags);
- if (!READ_ONCE(backtrace_idle) && regs && cpu_in_idle(instruction_pointer(regs))) {
- pr_warn("NMI backtrace for cpu %d skipped: idling at %pS\n",
-@@ -111,6 +112,7 @@ bool nmi_cpu_backtrace(struct pt_regs *r
- dump_stack();
- }
- printk_cpu_sync_put_irqrestore(flags);
-+ printk_direct_exit();
- cpumask_clear_cpu(cpu, to_cpumask(backtrace_mask));
- return true;
- }
diff --git a/patches/0013-console-introduce-CON_MIGHT_SLEEP-for-vt.patch b/patches/0013-console-introduce-CON_MIGHT_SLEEP-for-vt.patch
deleted file mode 100644
index 4d14b008d00c..000000000000
--- a/patches/0013-console-introduce-CON_MIGHT_SLEEP-for-vt.patch
+++ /dev/null
@@ -1,54 +0,0 @@
-From: John Ogness <john.ogness@linutronix.de>
-Date: Mon, 7 Feb 2022 15:54:58 +0106
-Subject: [PATCH 13/16] console: introduce CON_MIGHT_SLEEP for vt
-
-Deadlocks and the framebuffer console have been a recurring issue
-that is getting worse. Daniel Vetter suggested [0] that
-fbcon->write() should no longer be called from an atomic context.
-
-Introduce a new console flag CON_MIGHT_SLEEP for a console driver to
-specify that it is only called from sleepable contexts. Set the
-fbcon to use this new flag.
-
-[0] https://lore.kernel.org/all/YYuS1uNhxWOEX1Ci@phenom.ffwll.local
-
-Signed-off-by: John Ogness <john.ogness@linutronix.de>
-Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
----
- drivers/tty/vt/vt.c | 2 +-
- include/linux/console.h | 1 +
- kernel/printk/printk.c | 2 ++
- 3 files changed, 4 insertions(+), 1 deletion(-)
-
---- a/drivers/tty/vt/vt.c
-+++ b/drivers/tty/vt/vt.c
-@@ -3161,7 +3161,7 @@ static struct console vt_console_driver
- .write = vt_console_print,
- .device = vt_console_device,
- .unblank = unblank_screen,
-- .flags = CON_PRINTBUFFER,
-+ .flags = CON_PRINTBUFFER|CON_MIGHT_SLEEP,
- .index = -1,
- };
- #endif
---- a/include/linux/console.h
-+++ b/include/linux/console.h
-@@ -138,6 +138,7 @@ static inline int con_debug_leave(void)
- #define CON_BRL (32) /* Used for a braille device */
- #define CON_EXTENDED (64) /* Use the extended output format a la /dev/kmsg */
- #define CON_PAUSED (128) /* Sleep while console is locked */
-+#define CON_MIGHT_SLEEP (256) /* Can only be called from sleepable context */
-
- struct console {
- char name[16];
---- a/kernel/printk/printk.c
-+++ b/kernel/printk/printk.c
-@@ -2837,6 +2837,8 @@ static bool console_flush_all(bool do_co
-
- if (!console_is_usable(con))
- continue;
-+ if ((con->flags & CON_MIGHT_SLEEP) && !do_cond_resched)
-+ continue;
- any_usable = true;
-
- if (con->flags & CON_EXTENDED) {
diff --git a/patches/0013-printk-add-kthread-console-printers.patch b/patches/0013-printk-add-kthread-console-printers.patch
new file mode 100644
index 000000000000..8e813ebc60a7
--- /dev/null
+++ b/patches/0013-printk-add-kthread-console-printers.patch
@@ -0,0 +1,529 @@
+From: John Ogness <john.ogness@linutronix.de>
+Date: Wed, 20 Apr 2022 01:52:35 +0206
+Subject: [PATCH 13/15] printk: add kthread console printers
+
+Create a kthread for each console to perform console printing. During
+normal operation (@system_state == SYSTEM_RUNNING), the kthread
+printers are responsible for all printing on their respective
+consoles.
+
+During non-normal operation, console printing is done as it has been:
+within the context of the printk caller or within irqwork triggered
+by the printk caller, referred to as direct printing.
+
+Since threaded console printers are responsible for all printing
+during normal operation, this also includes messages generated via
+deferred printk calls. If direct printing is in effect during a
+deferred printk call, the queued irqwork will perform the direct
+printing. To make it clear that this is the only time that the
+irqwork will perform direct printing, rename the flag
+PRINTK_PENDING_OUTPUT to PRINTK_PENDING_DIRECT_OUTPUT.
+
+Threaded console printers synchronize against each other and against
+console lockers by taking the console lock for each message that is
+printed.
+
+Note that the kthread printers do not care about direct printing.
+They will always try to print if new records are available. They can
+be blocked by direct printing, but will be woken again once direct
+printing is finished.
+
+Console unregistration is a bit tricky because the associated
+kthread printer cannot be stopped while the console lock is held.
+A policy is implemented that states: whichever task clears
+con->thread (under the console lock) is responsible for stopping
+the kthread. unregister_console() will clear con->thread while
+the console lock is held and then stop the kthread after releasing
+the console lock.
+
+For consoles that have implemented the exit() callback, the kthread
+is stopped before exit() is called.
+
+Signed-off-by: John Ogness <john.ogness@linutronix.de>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Link: https://lore.kernel.org/r/20220419234637.357112-14-john.ogness@linutronix.de
+---
+ include/linux/console.h | 2
+ kernel/printk/printk.c | 303 ++++++++++++++++++++++++++++++++++++++++++++----
+ 2 files changed, 283 insertions(+), 22 deletions(-)
+
+--- a/include/linux/console.h
++++ b/include/linux/console.h
+@@ -153,6 +153,8 @@ struct console {
+ uint ospeed;
+ u64 seq;
+ unsigned long dropped;
++ struct task_struct *thread;
++
+ void *data;
+ struct console *next;
+ };
+--- a/kernel/printk/printk.c
++++ b/kernel/printk/printk.c
+@@ -361,6 +361,13 @@ static int console_msg_format = MSG_FORM
+ /* syslog_lock protects syslog_* variables and write access to clear_seq. */
+ static DEFINE_MUTEX(syslog_lock);
+
++/*
++ * A flag to signify if printk_activate_kthreads() has already started the
++ * kthread printers. If true, any later registered consoles must start their
++ * own kthread directly. The flag is write protected by the console_lock.
++ */
++static bool printk_kthreads_available;
++
+ #ifdef CONFIG_PRINTK
+ static atomic_t printk_prefer_direct = ATOMIC_INIT(0);
+
+@@ -390,6 +397,14 @@ void printk_prefer_direct_exit(void)
+ WARN_ON(atomic_dec_if_positive(&printk_prefer_direct) < 0);
+ }
+
++static inline bool allow_direct_printing(void)
++{
++ return (!printk_kthreads_available ||
++ system_state > SYSTEM_RUNNING ||
++ oops_in_progress ||
++ atomic_read(&printk_prefer_direct));
++}
++
+ DECLARE_WAIT_QUEUE_HEAD(log_wait);
+ /* All 3 protected by @syslog_lock. */
+ /* the next printk record to read by syslog(READ) or /proc/kmsg */
+@@ -2280,10 +2295,10 @@ asmlinkage int vprintk_emit(int facility
+ printed_len = vprintk_store(facility, level, dev_info, fmt, args);
+
+ /* If called from the scheduler, we can not call up(). */
+- if (!in_sched) {
++ if (!in_sched && allow_direct_printing()) {
+ /*
+ * The caller may be holding system-critical or
+- * timing-sensitive locks. Disable preemption during
++ * timing-sensitive locks. Disable preemption during direct
+ * printing of all remaining records to all consoles so that
+ * this context can return as soon as possible. Hopefully
+ * another printk() caller will take over the printing.
+@@ -2326,6 +2341,8 @@ EXPORT_SYMBOL(_printk);
+
+ static bool __pr_flush(struct console *con, int timeout_ms, bool reset_on_progress);
+
++static void printk_start_kthread(struct console *con);
++
+ #else /* CONFIG_PRINTK */
+
+ #define CONSOLE_LOG_MAX 0
+@@ -2359,6 +2376,8 @@ static void call_console_driver(struct c
+ }
+ static bool suppress_message_printing(int level) { return false; }
+ static bool __pr_flush(struct console *con, int timeout_ms, bool reset_on_progress) { return true; }
++static void printk_start_kthread(struct console *con) { }
++static bool allow_direct_printing(void) { return true; }
+
+ #endif /* CONFIG_PRINTK */
+
+@@ -2559,6 +2578,13 @@ void resume_console(void)
+ down_console_sem();
+ console_suspended = 0;
+ console_unlock();
++
++ /*
++ * While suspended, new records may have been added to the
++ * ringbuffer. Wake up the kthread printers to print them.
++ */
++ wake_up_klogd();
++
+ pr_flush(1000, true);
+ }
+
+@@ -2577,6 +2603,9 @@ static int console_cpu_notify(unsigned i
+ /* If trylock fails, someone else is doing the printing */
+ if (console_trylock())
+ console_unlock();
++
++ /* Wake kthread printers. Some may have become usable. */
++ wake_up_klogd();
+ }
+ return 0;
+ }
+@@ -2648,18 +2677,9 @@ static bool abandon_console_lock_in_pani
+ return atomic_read(&panic_cpu) != raw_smp_processor_id();
+ }
+
+-/*
+- * Check if the given console is currently capable and allowed to print
+- * records.
+- *
+- * Requires the console_lock.
+- */
+-static inline bool console_is_usable(struct console *con)
++static inline bool __console_is_usable(short flags)
+ {
+- if (!(con->flags & CON_ENABLED))
+- return false;
+-
+- if (!con->write)
++ if (!(flags & CON_ENABLED))
+ return false;
+
+ /*
+@@ -2668,12 +2688,26 @@ static inline bool console_is_usable(str
+ * cope (CON_ANYTIME) don't call them until this CPU is officially up.
+ */
+ if (!cpu_online(raw_smp_processor_id()) &&
+- !(con->flags & CON_ANYTIME))
++ !(flags & CON_ANYTIME))
+ return false;
+
+ return true;
+ }
+
++/*
++ * Check if the given console is currently capable and allowed to print
++ * records.
++ *
++ * Requires the console_lock.
++ */
++static inline bool console_is_usable(struct console *con)
++{
++ if (!con->write)
++ return false;
++
++ return __console_is_usable(con->flags);
++}
++
+ static void __console_unlock(void)
+ {
+ console_locked = 0;
+@@ -2786,8 +2820,8 @@ static bool console_emit_next_record(str
+ * were flushed to all usable consoles. A returned false informs the caller
+ * that everything was not flushed (either there were no usable consoles or
+ * another context has taken over printing or it is a panic situation and this
+- * is not the panic CPU). Regardless the reason, the caller should assume it
+- * is not useful to immediately try again.
++ * is not the panic CPU or direct printing is not preferred). Regardless the
++ * reason, the caller should assume it is not useful to immediately try again.
+ *
+ * Requires the console_lock.
+ */
+@@ -2804,6 +2838,10 @@ static bool console_flush_all(bool do_co
+ *handover = false;
+
+ do {
++ /* Let the kthread printers do the work if they can. */
++ if (!allow_direct_printing())
++ return false;
++
+ any_progress = false;
+
+ for_each_console(con) {
+@@ -3018,6 +3056,10 @@ void console_start(struct console *conso
+ console_lock();
+ console->flags |= CON_ENABLED;
+ console_unlock();
++
++ /* Wake the newly enabled kthread printer. */
++ wake_up_klogd();
++
+ __pr_flush(console, 1000, true);
+ }
+ EXPORT_SYMBOL(console_start);
+@@ -3218,6 +3260,8 @@ void register_console(struct console *ne
+ nr_ext_console_drivers++;
+
+ newcon->dropped = 0;
++ newcon->thread = NULL;
++
+ if (newcon->flags & CON_PRINTBUFFER) {
+ /* Get a consistent copy of @syslog_seq. */
+ mutex_lock(&syslog_lock);
+@@ -3227,6 +3271,10 @@ void register_console(struct console *ne
+ /* Begin with next message. */
+ newcon->seq = prb_next_seq(prb);
+ }
++
++ if (printk_kthreads_available)
++ printk_start_kthread(newcon);
++
+ console_unlock();
+ console_sysfs_notify();
+
+@@ -3253,6 +3301,7 @@ EXPORT_SYMBOL(register_console);
+
+ int unregister_console(struct console *console)
+ {
++ struct task_struct *thd;
+ struct console *con;
+ int res;
+
+@@ -3293,7 +3342,20 @@ int unregister_console(struct console *c
+ console_drivers->flags |= CON_CONSDEV;
+
+ console->flags &= ~CON_ENABLED;
++
++ /*
++ * console->thread can only be cleared under the console lock. But
++ * stopping the thread must be done without the console lock. The
++ * task that clears @thread is the task that stops the kthread.
++ */
++ thd = console->thread;
++ console->thread = NULL;
++
+ console_unlock();
++
++ if (thd)
++ kthread_stop(thd);
++
+ console_sysfs_notify();
+
+ if (console->exit)
+@@ -3389,6 +3451,20 @@ static int __init printk_late_init(void)
+ }
+ late_initcall(printk_late_init);
+
++static int __init printk_activate_kthreads(void)
++{
++ struct console *con;
++
++ console_lock();
++ printk_kthreads_available = true;
++ for_each_console(con)
++ printk_start_kthread(con);
++ console_unlock();
++
++ return 0;
++}
++early_initcall(printk_activate_kthreads);
++
+ #if defined CONFIG_PRINTK
+ /* If @con is specified, only wait for that console. Otherwise wait for all. */
+ static bool __pr_flush(struct console *con, int timeout_ms, bool reset_on_progress)
+@@ -3463,11 +3539,180 @@ bool pr_flush(int timeout_ms, bool reset
+ }
+ EXPORT_SYMBOL(pr_flush);
+
++static void __printk_fallback_preferred_direct(void)
++{
++ printk_prefer_direct_enter();
++ pr_err("falling back to preferred direct printing\n");
++ printk_kthreads_available = false;
++}
++
++/*
++ * Enter preferred direct printing, but never exit. Mark console threads as
++ * unavailable. The system is then forever in preferred direct printing and
++ * any printing threads will exit.
++ *
++ * Must *not* be called under console_lock. Use
++ * __printk_fallback_preferred_direct() if already holding console_lock.
++ */
++static void printk_fallback_preferred_direct(void)
++{
++ console_lock();
++ __printk_fallback_preferred_direct();
++ console_unlock();
++}
++
++static bool printer_should_wake(struct console *con, u64 seq)
++{
++ short flags;
++
++ if (kthread_should_stop() || !printk_kthreads_available)
++ return true;
++
++ if (console_suspended)
++ return false;
++
++ /*
++ * This is an unsafe read from con->flags, but a false positive is
++ * not a problem. Worst case it would allow the printer to wake up
++ * although it is disabled. But the printer will notice that when
++ * attempting to print and instead go back to sleep.
++ */
++ flags = data_race(READ_ONCE(con->flags));
++
++ if (!__console_is_usable(flags))
++ return false;
++
++ return prb_read_valid(prb, seq, NULL);
++}
++
++static int printk_kthread_func(void *data)
++{
++ struct console *con = data;
++ char *dropped_text = NULL;
++ char *ext_text = NULL;
++ bool handover;
++ u64 seq = 0;
++ char *text;
++ int error;
++
++ text = kmalloc(CONSOLE_LOG_MAX, GFP_KERNEL);
++ if (!text) {
++ con_printk(KERN_ERR, con, "failed to allocate text buffer\n");
++ printk_fallback_preferred_direct();
++ goto out;
++ }
++
++ if (con->flags & CON_EXTENDED) {
++ ext_text = kmalloc(CONSOLE_EXT_LOG_MAX, GFP_KERNEL);
++ if (!ext_text) {
++ con_printk(KERN_ERR, con, "failed to allocate ext_text buffer\n");
++ printk_fallback_preferred_direct();
++ goto out;
++ }
++ } else {
++ dropped_text = kmalloc(DROPPED_TEXT_MAX, GFP_KERNEL);
++ if (!dropped_text) {
++ con_printk(KERN_ERR, con, "failed to allocate dropped_text buffer\n");
++ printk_fallback_preferred_direct();
++ goto out;
++ }
++ }
++
++ con_printk(KERN_INFO, con, "printing thread started\n");
++
++ for (;;) {
++ /*
++ * Guarantee this task is visible on the waitqueue before
++ * checking the wake condition.
++ *
++ * The full memory barrier within set_current_state() of
++ * prepare_to_wait_event() pairs with the full memory barrier
++ * within wq_has_sleeper().
++ *
++ * This pairs with __wake_up_klogd:A.
++ */
++ error = wait_event_interruptible(log_wait,
++ printer_should_wake(con, seq)); /* LMM(printk_kthread_func:A) */
++
++ if (kthread_should_stop() || !printk_kthreads_available)
++ break;
++
++ if (error)
++ continue;
++
++ console_lock();
++
++ if (console_suspended) {
++ up_console_sem();
++ continue;
++ }
++
++ if (!console_is_usable(con)) {
++ __console_unlock();
++ continue;
++ }
++
++ /*
++ * Even though the printk kthread is always preemptible, it is
++ * still not allowed to call cond_resched() from within
++ * console drivers. The task may become non-preemptible in the
++ * console driver call chain. For example, vt_console_print()
++ * takes a spinlock and then can call into fbcon_redraw(),
++ * which can conditionally invoke cond_resched().
++ */
++ console_may_schedule = 0;
++ console_emit_next_record(con, text, ext_text, dropped_text, &handover);
++ if (handover)
++ continue;
++
++ seq = con->seq;
++
++ __console_unlock();
++ }
++
++ con_printk(KERN_INFO, con, "printing thread stopped\n");
++out:
++ kfree(dropped_text);
++ kfree(ext_text);
++ kfree(text);
++
++ console_lock();
++ /*
++ * If this kthread is being stopped by another task, con->thread will
++ * already be NULL. That is fine. The important thing is that it is
++ * NULL after the kthread exits.
++ */
++ con->thread = NULL;
++ console_unlock();
++
++ return 0;
++}
++
++/* Must be called under console_lock. */
++static void printk_start_kthread(struct console *con)
++{
++ /*
++ * Do not start a kthread if there is no write() callback. The
++ * kthreads assume the write() callback exists.
++ */
++ if (!con->write)
++ return;
++
++ con->thread = kthread_run(printk_kthread_func, con,
++ "pr/%s%d", con->name, con->index);
++ if (IS_ERR(con->thread)) {
++ con->thread = NULL;
++ con_printk(KERN_ERR, con, "unable to start printing thread\n");
++ __printk_fallback_preferred_direct();
++ return;
++ }
++}
++
+ /*
+ * Delayed printk version, for scheduler-internal messages:
+ */
+-#define PRINTK_PENDING_WAKEUP 0x01
+-#define PRINTK_PENDING_OUTPUT 0x02
++#define PRINTK_PENDING_WAKEUP 0x01
++#define PRINTK_PENDING_DIRECT_OUTPUT 0x02
+
+ static DEFINE_PER_CPU(int, printk_pending);
+
+@@ -3475,10 +3720,14 @@ static void wake_up_klogd_work_func(stru
+ {
+ int pending = this_cpu_xchg(printk_pending, 0);
+
+- if (pending & PRINTK_PENDING_OUTPUT) {
++ if (pending & PRINTK_PENDING_DIRECT_OUTPUT) {
++ printk_prefer_direct_enter();
++
+ /* If trylock fails, someone else is doing the printing */
+ if (console_trylock())
+ console_unlock();
++
++ printk_prefer_direct_exit();
+ }
+
+ if (pending & PRINTK_PENDING_WAKEUP)
+@@ -3503,10 +3752,11 @@ static void __wake_up_klogd(int val)
+ * prepare_to_wait_event(), which is called after ___wait_event() adds
+ * the waiter but before it has checked the wait condition.
+ *
+- * This pairs with devkmsg_read:A and syslog_print:A.
++ * This pairs with devkmsg_read:A, syslog_print:A, and
++ * printk_kthread_func:A.
+ */
+ if (wq_has_sleeper(&log_wait) || /* LMM(__wake_up_klogd:A) */
+- (val & PRINTK_PENDING_OUTPUT)) {
++ (val & PRINTK_PENDING_DIRECT_OUTPUT)) {
+ this_cpu_or(printk_pending, val);
+ irq_work_queue(this_cpu_ptr(&wake_up_klogd_work));
+ }
+@@ -3524,7 +3774,16 @@ void defer_console_output(void)
+ * New messages may have been added directly to the ringbuffer
+ * using vprintk_store(), so wake any waiters as well.
+ */
+- __wake_up_klogd(PRINTK_PENDING_WAKEUP | PRINTK_PENDING_OUTPUT);
++ int val = PRINTK_PENDING_WAKEUP;
++
++ /*
++ * If console deferring was called with preferred direct printing,
++ * make the irqwork perform the direct printing.
++ */
++ if (atomic_read(&printk_prefer_direct))
++ val |= PRINTK_PENDING_DIRECT_OUTPUT;
++
++ __wake_up_klogd(val);
+ }
+
+ void printk_trigger_flush(void)
diff --git a/patches/0014-printk-extend-console_lock-for-proper-kthread-suppor.patch b/patches/0014-printk-extend-console_lock-for-proper-kthread-suppor.patch
new file mode 100644
index 000000000000..cd47ef70bc95
--- /dev/null
+++ b/patches/0014-printk-extend-console_lock-for-proper-kthread-suppor.patch
@@ -0,0 +1,695 @@
+From: John Ogness <john.ogness@linutronix.de>
+Date: Wed, 20 Apr 2022 01:52:36 +0206
+Subject: [PATCH 14/15] printk: extend console_lock for proper kthread support
+
+Currently threaded console printers synchronize against each
+other using console_lock(). However, different console drivers
+are unrelated and do not require any synchronization between
+each other. Removing the synchronization between the threaded
+console printers will allow each console to print at its own
+speed.
+
+But the threaded consoles printers do still need to synchronize
+against console_lock() callers. Introduce a per-console mutex
+and a new console flag CON_THD_BLOCKED to provide this
+synchronization.
+
+console_lock() is modified so that it must acquire the mutex
+of each console in order to set the CON_THD_BLOCKED flag.
+Console printing threads will acquire their mutex while
+printing a record. If CON_THD_BLOCKED was set, the thread will
+go back to sleep instead of printing.
+
+The reason for the CON_THD_BLOCKED flag is so that
+console_lock() callers do not need to acquire multiple console
+mutexes simultaneously, which would introduce unnecessary
+complexity due to nested mutex locking.
+
+The per-console mutex is also used to synchronize setting and
+checking the CON_ENABLED flag. A new console_lock() variant is
+introduced, console_lock_single_hold(), that allows acquiring
+@console_sem but only locking (and holding) the mutex of a
+single console. This allows safely enabling and disabling
+consoles without disturbing the other kthread printers. The
+mutex and @console_sem are released with
+console_unlock_single_release().
+
+Console unregistering now uses console_lock_single_hold() to
+stop the kthread. Thus con->thread is now synchronized by
+the per-console mutex. This allows consoles to be unregistered
+without disturbing the other kthread printers.
+
+Threaded console printers also need to synchronize against
+console_trylock() callers. Since console_trylock() may be
+called from any context, the per-console mutex cannot be used
+for this synchronization. (mutex_trylock() cannot be called
+from atomic contexts.) Introduce a global atomic counter to
+identify if any threaded printers are active. The threaded
+printers will also check the atomic counter to identify if the
+console has been locked by another task via console_trylock().
+
+Note that @console_sem is still used to provide synchronization
+between console_lock() and console_trylock() callers.
+
+A locking overview for console_lock(), console_trylock(), and the
+threaded printers is as follows (pseudo code):
+
+console_lock()
+{
+ down(&console_sem);
+ for_each_console(con) {
+ mutex_lock(&con->lock);
+ con->flags |= CON_THD_BLOCKED;
+ mutex_unlock(&con->lock);
+ }
+ /* console_lock acquired */
+}
+
+console_trylock()
+{
+ if (down_trylock(&console_sem) == 0) {
+ if (atomic_cmpxchg(&console_kthreads_active, 0, -1) == 0) {
+ /* console_lock acquired */
+ }
+ }
+}
+
+threaded_printer()
+{
+ mutex_lock(&con->lock);
+ if (!(con->flags & CON_THD_BLOCKED)) {
+ /* console_lock() callers blocked */
+
+ if (atomic_inc_unless_negative(&console_kthreads_active)) {
+ /* console_trylock() callers blocked */
+
+ con->write();
+
+ atomic_dec(&console_lock_count);
+ }
+ }
+ mutex_unlock(&con->lock);
+}
+
+The console owner and waiter logic now only applies between contexts
+that have taken the console_lock via console_trylock(). Threaded
+printers never take the console_lock, so they do not have a
+console_lock to handover. Tasks that have used console_lock() will
+block the threaded printers using a mutex and if the console_lock
+is handed over to an atomic context, it would be unable to unblock
+the threaded printers. However, the console_trylock() case is
+really the only scenario that is interesting for handovers anyway.
+
+@panic_console_dropped must change to atomic_t since it is no longer
+protected exclusively by the console_lock.
+
+Since threaded printers remain asleep if they see that the console
+is locked, they now must be explicitly woken in __console_unlock().
+This means wake_up_klogd() calls following a console_unlock() are
+no longer necessary and are removed.
+
+Also note that threaded printers no longer need to check
+@console_suspended. The check for the CON_THD_BLOCKED flag
+implicitly covers the suspended console case.
+
+Signed-off-by: John Ogness <john.ogness@linutronix.de>
+Reported-by: kernel test robot <lkp@intel.com>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Link: https://lore.kernel.org/r/20220419234637.357112-15-john.ogness@linutronix.de
+---
+ include/linux/console.h | 15 ++
+ kernel/printk/printk.c | 295 ++++++++++++++++++++++++++++++++++++------------
+ 2 files changed, 242 insertions(+), 68 deletions(-)
+
+--- a/include/linux/console.h
++++ b/include/linux/console.h
+@@ -16,6 +16,7 @@
+
+ #include <linux/atomic.h>
+ #include <linux/types.h>
++#include <linux/mutex.h>
+
+ struct vc_data;
+ struct console_font_op;
+@@ -136,6 +137,7 @@ static inline int con_debug_leave(void)
+ #define CON_ANYTIME (16) /* Safe to call when cpu is offline */
+ #define CON_BRL (32) /* Used for a braille device */
+ #define CON_EXTENDED (64) /* Use the extended output format a la /dev/kmsg */
++#define CON_THD_BLOCKED (128) /* Thread blocked because console is locked */
+
+ struct console {
+ char name[16];
+@@ -155,6 +157,19 @@ struct console {
+ unsigned long dropped;
+ struct task_struct *thread;
+
++ /*
++ * The per-console lock is used by printing kthreads to synchronize
++ * this console with callers of console_lock(). This is necessary in
++ * order to allow printing kthreads to run in parallel to each other,
++ * while each safely accessing their own @flags and synchronizing
++ * against direct printing via console_lock/console_unlock.
++ *
++ * Note: For synchronizing against direct printing via
++ * console_trylock/console_unlock, see the static global
++ * variable @console_kthreads_active.
++ */
++ struct mutex lock;
++
+ void *data;
+ struct console *next;
+ };
+--- a/kernel/printk/printk.c
++++ b/kernel/printk/printk.c
+@@ -224,6 +224,33 @@ int devkmsg_sysctl_set_loglvl(struct ctl
+ static int nr_ext_console_drivers;
+
+ /*
++ * Used to synchronize printing kthreads against direct printing via
++ * console_trylock/console_unlock.
++ *
++ * Values:
++ * -1 = console kthreads atomically blocked (via global trylock)
++ * 0 = no kthread printing, console not locked (via trylock)
++ * >0 = kthread(s) actively printing
++ *
++ * Note: For synchronizing against direct printing via
++ * console_lock/console_unlock, see the @lock variable in
++ * struct console.
++ */
++static atomic_t console_kthreads_active = ATOMIC_INIT(0);
++
++#define console_kthreads_atomic_tryblock() \
++ (atomic_cmpxchg(&console_kthreads_active, 0, -1) == 0)
++#define console_kthreads_atomic_unblock() \
++ atomic_cmpxchg(&console_kthreads_active, -1, 0)
++#define console_kthreads_atomically_blocked() \
++ (atomic_read(&console_kthreads_active) == -1)
++
++#define console_kthread_printing_tryenter() \
++ atomic_inc_unless_negative(&console_kthreads_active)
++#define console_kthread_printing_exit() \
++ atomic_dec(&console_kthreads_active)
++
++/*
+ * Helper macros to handle lockdep when locking/unlocking console_sem. We use
+ * macros instead of functions so that _RET_IP_ contains useful information.
+ */
+@@ -271,6 +298,49 @@ static bool panic_in_progress(void)
+ }
+
+ /*
++ * Tracks whether kthread printers are all blocked. A value of true implies
++ * that the console is locked via console_lock() or the console is suspended.
++ * Reading and writing to this variable requires holding @console_sem.
++ */
++static bool console_kthreads_blocked;
++
++/*
++ * Block all kthread printers from a schedulable context.
++ *
++ * Requires holding @console_sem.
++ */
++static void console_kthreads_block(void)
++{
++ struct console *con;
++
++ for_each_console(con) {
++ mutex_lock(&con->lock);
++ con->flags |= CON_THD_BLOCKED;
++ mutex_unlock(&con->lock);
++ }
++
++ console_kthreads_blocked = true;
++}
++
++/*
++ * Unblock all kthread printers from a schedulable context.
++ *
++ * Requires holding @console_sem.
++ */
++static void console_kthreads_unblock(void)
++{
++ struct console *con;
++
++ for_each_console(con) {
++ mutex_lock(&con->lock);
++ con->flags &= ~CON_THD_BLOCKED;
++ mutex_unlock(&con->lock);
++ }
++
++ console_kthreads_blocked = false;
++}
++
++/*
+ * This is used for debugging the mess that is the VT code by
+ * keeping track if we have the console semaphore held. It's
+ * definitely not the perfect debug tool (we don't know if _WE_
+@@ -2578,13 +2648,6 @@ void resume_console(void)
+ down_console_sem();
+ console_suspended = 0;
+ console_unlock();
+-
+- /*
+- * While suspended, new records may have been added to the
+- * ringbuffer. Wake up the kthread printers to print them.
+- */
+- wake_up_klogd();
+-
+ pr_flush(1000, true);
+ }
+
+@@ -2603,9 +2666,10 @@ static int console_cpu_notify(unsigned i
+ /* If trylock fails, someone else is doing the printing */
+ if (console_trylock())
+ console_unlock();
+-
+- /* Wake kthread printers. Some may have become usable. */
+- wake_up_klogd();
++ else {
++ /* Some kthread printers may have become usable. */
++ wake_up_klogd();
++ }
+ }
+ return 0;
+ }
+@@ -2625,11 +2689,33 @@ void console_lock(void)
+ down_console_sem();
+ if (console_suspended)
+ return;
++ console_kthreads_block();
+ console_locked = 1;
+ console_may_schedule = 1;
+ }
+ EXPORT_SYMBOL(console_lock);
+
++/*
++ * Lock the console_lock, but rather than blocking all the kthread printers,
++ * lock a specified kthread printer and hold the lock. This is useful if
++ * console flags for a particular console need to be updated.
++ */
++static void console_lock_single_hold(struct console *con)
++{
++ might_sleep();
++ down_console_sem();
++ mutex_lock(&con->lock);
++ console_locked = 1;
++ console_may_schedule = 1;
++}
++
++static void console_unlock_single_release(struct console *con)
++{
++ console_locked = 0;
++ mutex_unlock(&con->lock);
++ up_console_sem();
++}
++
+ /**
+ * console_trylock - try to lock the console system for exclusive use.
+ *
+@@ -2646,6 +2732,10 @@ int console_trylock(void)
+ up_console_sem();
+ return 0;
+ }
++ if (!console_kthreads_atomic_tryblock()) {
++ up_console_sem();
++ return 0;
++ }
+ console_locked = 1;
+ console_may_schedule = 0;
+ return 1;
+@@ -2654,7 +2744,7 @@ EXPORT_SYMBOL(console_trylock);
+
+ int is_console_locked(void)
+ {
+- return console_locked;
++ return (console_locked || atomic_read(&console_kthreads_active));
+ }
+ EXPORT_SYMBOL(is_console_locked);
+
+@@ -2698,7 +2788,7 @@ static inline bool __console_is_usable(s
+ * Check if the given console is currently capable and allowed to print
+ * records.
+ *
+- * Requires the console_lock.
++ * Requires holding the console_lock or con->lock.
+ */
+ static inline bool console_is_usable(struct console *con)
+ {
+@@ -2711,6 +2801,22 @@ static inline bool console_is_usable(str
+ static void __console_unlock(void)
+ {
+ console_locked = 0;
++
++ /*
++ * Depending on whether console_lock() or console_trylock() was used,
++ * appropriately allow the kthread printers to continue.
++ */
++ if (console_kthreads_blocked)
++ console_kthreads_unblock();
++ else
++ console_kthreads_atomic_unblock();
++
++ /*
++ * New records may have arrived while the console was locked.
++ * Wake the kthread printers to print them.
++ */
++ wake_up_klogd();
++
+ up_console_sem();
+ }
+
+@@ -2728,17 +2834,18 @@ static void __console_unlock(void)
+ *
+ * @handover will be set to true if a printk waiter has taken over the
+ * console_lock, in which case the caller is no longer holding the
+- * console_lock. Otherwise it is set to false.
++ * console_lock. Otherwise it is set to false. A NULL pointer may be provided
++ * to disable allowing the console_lock to be taken over by a printk waiter.
+ *
+ * Returns false if the given console has no next record to print, otherwise
+ * true.
+ *
+- * Requires the console_lock.
++ * Requires the console_lock if @handover is non-NULL.
+ */
+-static bool console_emit_next_record(struct console *con, char *text, char *ext_text,
+- char *dropped_text, bool *handover)
++static bool __console_emit_next_record(struct console *con, char *text, char *ext_text,
++ char *dropped_text, bool *handover)
+ {
+- static int panic_console_dropped;
++ static atomic_t panic_console_dropped = ATOMIC_INIT(0);
+ struct printk_info info;
+ struct printk_record r;
+ unsigned long flags;
+@@ -2747,7 +2854,8 @@ static bool console_emit_next_record(str
+
+ prb_rec_init_rd(&r, &info, text, CONSOLE_LOG_MAX);
+
+- *handover = false;
++ if (handover)
++ *handover = false;
+
+ if (!prb_read_valid(prb, con->seq, &r))
+ return false;
+@@ -2755,7 +2863,8 @@ static bool console_emit_next_record(str
+ if (con->seq != r.info->seq) {
+ con->dropped += r.info->seq - con->seq;
+ con->seq = r.info->seq;
+- if (panic_in_progress() && panic_console_dropped++ > 10) {
++ if (panic_in_progress() &&
++ atomic_fetch_inc_relaxed(&panic_console_dropped) > 10) {
+ suppress_panic_printk = 1;
+ pr_warn_once("Too many dropped messages. Suppress messages on non-panic CPUs to prevent livelock.\n");
+ }
+@@ -2777,32 +2886,62 @@ static bool console_emit_next_record(str
+ len = record_print_text(&r, console_msg_format & MSG_FORMAT_SYSLOG, printk_time);
+ }
+
+- /*
+- * While actively printing out messages, if another printk()
+- * were to occur on another CPU, it may wait for this one to
+- * finish. This task can not be preempted if there is a
+- * waiter waiting to take over.
+- *
+- * Interrupts are disabled because the hand over to a waiter
+- * must not be interrupted until the hand over is completed
+- * (@console_waiter is cleared).
+- */
+- printk_safe_enter_irqsave(flags);
+- console_lock_spinning_enable();
++ if (handover) {
++ /*
++ * While actively printing out messages, if another printk()
++ * were to occur on another CPU, it may wait for this one to
++ * finish. This task can not be preempted if there is a
++ * waiter waiting to take over.
++ *
++ * Interrupts are disabled because the hand over to a waiter
++ * must not be interrupted until the hand over is completed
++ * (@console_waiter is cleared).
++ */
++ printk_safe_enter_irqsave(flags);
++ console_lock_spinning_enable();
++
++ /* don't trace irqsoff print latency */
++ stop_critical_timings();
++ }
+
+- stop_critical_timings(); /* don't trace print latency */
+ call_console_driver(con, write_text, len, dropped_text);
+- start_critical_timings();
+
+ con->seq++;
+
+- *handover = console_lock_spinning_disable_and_check();
+- printk_safe_exit_irqrestore(flags);
++ if (handover) {
++ start_critical_timings();
++ *handover = console_lock_spinning_disable_and_check();
++ printk_safe_exit_irqrestore(flags);
++ }
+ skip:
+ return true;
+ }
+
+ /*
++ * Print a record for a given console, but allow another printk() caller to
++ * take over the console_lock and continue printing.
++ *
++ * Requires the console_lock, but depending on @handover after the call, the
++ * caller may no longer have the console_lock.
++ *
++ * See __console_emit_next_record() for argument and return details.
++ */
++static bool console_emit_next_record_transferable(struct console *con, char *text, char *ext_text,
++ char *dropped_text, bool *handover)
++{
++ /*
++ * Handovers are only supported if threaded printers are atomically
++ * blocked. The context taking over the console_lock may be atomic.
++ */
++ if (!console_kthreads_atomically_blocked()) {
++ *handover = false;
++ handover = NULL;
++ }
++
++ return __console_emit_next_record(con, text, ext_text, dropped_text, handover);
++}
++
++/*
+ * Print out all remaining records to all consoles.
+ *
+ * @do_cond_resched is set by the caller. It can be true only in schedulable
+@@ -2853,13 +2992,11 @@ static bool console_flush_all(bool do_co
+
+ if (con->flags & CON_EXTENDED) {
+ /* Extended consoles do not print "dropped messages". */
+- progress = console_emit_next_record(con, &text[0],
+- &ext_text[0], NULL,
+- handover);
++ progress = console_emit_next_record_transferable(con, &text[0],
++ &ext_text[0], NULL, handover);
+ } else {
+- progress = console_emit_next_record(con, &text[0],
+- NULL, &dropped_text[0],
+- handover);
++ progress = console_emit_next_record_transferable(con, &text[0],
++ NULL, &dropped_text[0], handover);
+ }
+ if (*handover)
+ return false;
+@@ -2974,6 +3111,10 @@ void console_unblank(void)
+ if (oops_in_progress) {
+ if (down_trylock_console_sem() != 0)
+ return;
++ if (!console_kthreads_atomic_tryblock()) {
++ up_console_sem();
++ return;
++ }
+ } else
+ console_lock();
+
+@@ -3045,21 +3186,20 @@ struct tty_driver *console_device(int *i
+ void console_stop(struct console *console)
+ {
+ __pr_flush(console, 1000, true);
+- console_lock();
++ console_lock_single_hold(console);
+ console->flags &= ~CON_ENABLED;
+- console_unlock();
++ console_unlock_single_release(console);
+ }
+ EXPORT_SYMBOL(console_stop);
+
++
+ void console_start(struct console *console)
+ {
+- console_lock();
++ console_lock_single_hold(console);
+ console->flags |= CON_ENABLED;
+- console_unlock();
+-
++ console_unlock_single_release(console);
+ /* Wake the newly enabled kthread printer. */
+ wake_up_klogd();
+-
+ __pr_flush(console, 1000, true);
+ }
+ EXPORT_SYMBOL(console_start);
+@@ -3261,6 +3401,8 @@ void register_console(struct console *ne
+
+ newcon->dropped = 0;
+ newcon->thread = NULL;
++ newcon->flags |= CON_THD_BLOCKED;
++ mutex_init(&newcon->lock);
+
+ if (newcon->flags & CON_PRINTBUFFER) {
+ /* Get a consistent copy of @syslog_seq. */
+@@ -3314,7 +3456,7 @@ int unregister_console(struct console *c
+ return 0;
+
+ res = -ENODEV;
+- console_lock();
++ console_lock_single_hold(console);
+ if (console_drivers == console) {
+ console_drivers=console->next;
+ res = 0;
+@@ -3344,14 +3486,14 @@ int unregister_console(struct console *c
+ console->flags &= ~CON_ENABLED;
+
+ /*
+- * console->thread can only be cleared under the console lock. But
+- * stopping the thread must be done without the console lock. The
+- * task that clears @thread is the task that stops the kthread.
++ * console->thread can only be cleared while holding con->lock. But
++ * stopping the thread must be done without con->lock. The task that
++ * clears @thread is the task that stops the kthread.
+ */
+ thd = console->thread;
+ console->thread = NULL;
+
+- console_unlock();
++ console_unlock_single_release(console);
+
+ if (thd)
+ kthread_stop(thd);
+@@ -3365,7 +3507,7 @@ int unregister_console(struct console *c
+
+ out_disable_unlock:
+ console->flags &= ~CON_ENABLED;
+- console_unlock();
++ console_unlock_single_release(console);
+
+ return res;
+ }
+@@ -3561,6 +3703,19 @@ static void printk_fallback_preferred_di
+ console_unlock();
+ }
+
++/*
++ * Print a record for a given console, not allowing another printk() caller
++ * to take over. This is appropriate for contexts that do not have the
++ * console_lock.
++ *
++ * See __console_emit_next_record() for argument and return details.
++ */
++static bool console_emit_next_record(struct console *con, char *text, char *ext_text,
++ char *dropped_text)
++{
++ return __console_emit_next_record(con, text, ext_text, dropped_text, NULL);
++}
++
+ static bool printer_should_wake(struct console *con, u64 seq)
+ {
+ short flags;
+@@ -3568,9 +3723,6 @@ static bool printer_should_wake(struct c
+ if (kthread_should_stop() || !printk_kthreads_available)
+ return true;
+
+- if (console_suspended)
+- return false;
+-
+ /*
+ * This is an unsafe read from con->flags, but a false positive is
+ * not a problem. Worst case it would allow the printer to wake up
+@@ -3582,6 +3734,11 @@ static bool printer_should_wake(struct c
+ if (!__console_is_usable(flags))
+ return false;
+
++ if ((flags & CON_THD_BLOCKED) ||
++ console_kthreads_atomically_blocked()) {
++ return false;
++ }
++
+ return prb_read_valid(prb, seq, NULL);
+ }
+
+@@ -3590,7 +3747,6 @@ static int printk_kthread_func(void *dat
+ struct console *con = data;
+ char *dropped_text = NULL;
+ char *ext_text = NULL;
+- bool handover;
+ u64 seq = 0;
+ char *text;
+ int error;
+@@ -3640,15 +3796,18 @@ static int printk_kthread_func(void *dat
+ if (error)
+ continue;
+
+- console_lock();
++ error = mutex_lock_interruptible(&con->lock);
++ if (error)
++ continue;
+
+- if (console_suspended) {
+- up_console_sem();
++ if (!console_is_usable(con)) {
++ mutex_unlock(&con->lock);
+ continue;
+ }
+
+- if (!console_is_usable(con)) {
+- __console_unlock();
++ if ((con->flags & CON_THD_BLOCKED) ||
++ !console_kthread_printing_tryenter()) {
++ mutex_unlock(&con->lock);
+ continue;
+ }
+
+@@ -3661,13 +3820,13 @@ static int printk_kthread_func(void *dat
+ * which can conditionally invoke cond_resched().
+ */
+ console_may_schedule = 0;
+- console_emit_next_record(con, text, ext_text, dropped_text, &handover);
+- if (handover)
+- continue;
++ console_emit_next_record(con, text, ext_text, dropped_text);
+
+ seq = con->seq;
+
+- __console_unlock();
++ console_kthread_printing_exit();
++
++ mutex_unlock(&con->lock);
+ }
+
+ con_printk(KERN_INFO, con, "printing thread stopped\n");
+@@ -3676,14 +3835,14 @@ static int printk_kthread_func(void *dat
+ kfree(ext_text);
+ kfree(text);
+
+- console_lock();
++ mutex_lock(&con->lock);
+ /*
+ * If this kthread is being stopped by another task, con->thread will
+ * already be NULL. That is fine. The important thing is that it is
+ * NULL after the kthread exits.
+ */
+ con->thread = NULL;
+- console_unlock();
++ mutex_unlock(&con->lock);
+
+ return 0;
+ }
diff --git a/patches/0012-printk-remove-console_locked.patch b/patches/0015-printk-remove-console_locked.patch
index af56470ce706..fa4d4d21ccbc 100644
--- a/patches/0012-printk-remove-console_locked.patch
+++ b/patches/0015-printk-remove-console_locked.patch
@@ -1,28 +1,30 @@
From: John Ogness <john.ogness@linutronix.de>
-Date: Mon, 7 Feb 2022 15:54:54 +0106
-Subject: [PATCH 12/16] printk: remove @console_locked
+Date: Wed, 20 Apr 2022 01:52:37 +0206
+Subject: [PATCH 15/15] printk: remove @console_locked
-The static global variable @console_locked is used to help debug VT
-code to make sure that certain code paths are running with the
-console_lock held. However, this information is also available with
-the static global variable @consoles_paused (for locking via
-console_lock()), and the static global variable @console_lock_count
-(for locking via console_trylock()).
+The static global variable @console_locked is used to help debug
+VT code to make sure that certain code paths are running with
+the console_lock held. However, this information is also available
+with the static global variable @console_kthreads_blocked (for
+locking via console_lock()), and the static global variable
+@console_kthreads_active (for locking via console_trylock()).
Remove @console_locked and update is_console_locked() to use the
alternative variables.
Signed-off-by: John Ogness <john.ogness@linutronix.de>
+Reviewed-by: Petr Mladek <pmladek@suse.com>
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Link: https://lore.kernel.org/r/20220419234637.357112-16-john.ogness@linutronix.de
---
- kernel/printk/printk.c | 30 ++++++++++++++----------------
- 1 file changed, 14 insertions(+), 16 deletions(-)
+ kernel/printk/printk.c | 31 ++++++++++++++-----------------
+ 1 file changed, 14 insertions(+), 17 deletions(-)
--- a/kernel/printk/printk.c
+++ b/kernel/printk/printk.c
-@@ -308,15 +308,7 @@ static void __pause_all_consoles(bool do
- #define pause_all_consoles() __pause_all_consoles(true)
- #define unpause_all_consoles() __pause_all_consoles(false)
+@@ -340,15 +340,7 @@ static void console_kthreads_unblock(voi
+ console_kthreads_blocked = false;
+ }
-/*
- * This is used for debugging the mess that is the VT code by
@@ -37,30 +39,37 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
/*
* Array of consoles built from command line options (console=)
-@@ -2596,7 +2588,6 @@ void console_lock(void)
+@@ -2690,7 +2682,6 @@ void console_lock(void)
if (console_suspended)
return;
- pause_all_consoles();
+ console_kthreads_block();
- console_locked = 1;
console_may_schedule = 1;
}
EXPORT_SYMBOL(console_lock);
-@@ -2621,7 +2612,6 @@ int console_trylock(void)
- up_console_sem();
- return 0;
- }
+@@ -2705,13 +2696,11 @@ static void console_lock_single_hold(str
+ might_sleep();
+ down_console_sem();
+ mutex_lock(&con->lock);
- console_locked = 1;
- console_may_schedule = 0;
- return 1;
+ console_may_schedule = 1;
}
-@@ -2648,14 +2638,25 @@ static int console_trylock_sched(bool ma
+
+ static void console_unlock_single_release(struct console *con)
+ {
+- console_locked = 0;
+ mutex_unlock(&con->lock);
+ up_console_sem();
+ }
+@@ -2736,15 +2725,26 @@ int console_trylock(void)
+ up_console_sem();
return 0;
}
- pause_all_consoles();
- console_locked = 1;
- console_may_schedule = 1;
+ console_may_schedule = 0;
return 1;
}
+ EXPORT_SYMBOL(console_trylock);
+/*
+ * This is used to help to make sure that certain paths within the VT code are
@@ -76,12 +85,12 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+ */
int is_console_locked(void)
{
-- return (console_locked || atomic_read(&console_lock_count));
-+ return (consoles_paused || atomic_read(&console_lock_count));
+- return (console_locked || atomic_read(&console_kthreads_active));
++ return (console_kthreads_blocked || atomic_read(&console_kthreads_active));
}
EXPORT_SYMBOL(is_console_locked);
-@@ -2688,8 +2689,6 @@ static inline bool console_is_usable(str
+@@ -2800,8 +2800,6 @@ static inline bool console_is_usable(str
static void __console_unlock(void)
{
@@ -90,9 +99,9 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
/*
* Depending on whether console_lock() or console_trylock() was used,
* appropriately allow the kthread printers to continue.
-@@ -2967,7 +2966,6 @@ void console_unblank(void)
+@@ -3118,7 +3116,6 @@ void console_unblank(void)
+ } else
console_lock();
- }
- console_locked = 1;
console_may_schedule = 0;
diff --git a/patches/0015-serial-8250-implement-write_atomic.patch b/patches/0015-serial-8250-implement-write_atomic.patch
deleted file mode 100644
index 9193ef05bf2e..000000000000
--- a/patches/0015-serial-8250-implement-write_atomic.patch
+++ /dev/null
@@ -1,492 +0,0 @@
-From: John Ogness <john.ogness@linutronix.de>
-Date: Fri, 4 Feb 2022 16:01:17 +0106
-Subject: [PATCH 15/16] serial: 8250: implement write_atomic
-
-Implement a non-sleeping NMI-safe write_atomic() console function in
-order to support atomic console printing during a panic.
-
-Since interrupts need to be disabled during transmit, all usage of
-the IER register is wrapped with access functions that use the
-printk_cpu_sync_get_irqsave() function to synchronize register access
-while tracking the state of the interrupts. This is necessary because
-write_atomic() can be called from an NMI context that has preempted
-write_atomic().
-
-Signed-off-by: John Ogness <john.ogness@linutronix.de>
-Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
----
- drivers/tty/serial/8250/8250.h | 47 ++++++++++++++++
- drivers/tty/serial/8250/8250_core.c | 17 ++++--
- drivers/tty/serial/8250/8250_fsl.c | 9 +++
- drivers/tty/serial/8250/8250_ingenic.c | 7 ++
- drivers/tty/serial/8250/8250_mtk.c | 29 +++++++++-
- drivers/tty/serial/8250/8250_port.c | 92 ++++++++++++++++++++-------------
- drivers/tty/serial/8250/Kconfig | 1
- include/linux/serial_8250.h | 5 +
- 8 files changed, 163 insertions(+), 44 deletions(-)
-
---- a/drivers/tty/serial/8250/8250.h
-+++ b/drivers/tty/serial/8250/8250.h
-@@ -132,12 +132,55 @@ static inline void serial_dl_write(struc
- up->dl_write(up, value);
- }
-
-+static inline void serial8250_set_IER(struct uart_8250_port *up,
-+ unsigned char ier)
-+{
-+ struct uart_port *port = &up->port;
-+ unsigned long flags;
-+ bool is_console;
-+
-+ is_console = uart_console(port);
-+
-+ if (is_console)
-+ printk_cpu_sync_get_irqsave(flags);
-+
-+ serial_out(up, UART_IER, ier);
-+
-+ if (is_console)
-+ printk_cpu_sync_put_irqrestore(flags);
-+}
-+
-+static inline unsigned char serial8250_clear_IER(struct uart_8250_port *up)
-+{
-+ struct uart_port *port = &up->port;
-+ unsigned int clearval = 0;
-+ unsigned long flags;
-+ unsigned int prior;
-+ bool is_console;
-+
-+ is_console = uart_console(port);
-+
-+ if (up->capabilities & UART_CAP_UUE)
-+ clearval = UART_IER_UUE;
-+
-+ if (is_console)
-+ printk_cpu_sync_get_irqsave(flags);
-+
-+ prior = serial_port_in(port, UART_IER);
-+ serial_port_out(port, UART_IER, clearval);
-+
-+ if (is_console)
-+ printk_cpu_sync_put_irqrestore(flags);
-+
-+ return prior;
-+}
-+
- static inline bool serial8250_set_THRI(struct uart_8250_port *up)
- {
- if (up->ier & UART_IER_THRI)
- return false;
- up->ier |= UART_IER_THRI;
-- serial_out(up, UART_IER, up->ier);
-+ serial8250_set_IER(up, up->ier);
- return true;
- }
-
-@@ -146,7 +189,7 @@ static inline bool serial8250_clear_THRI
- if (!(up->ier & UART_IER_THRI))
- return false;
- up->ier &= ~UART_IER_THRI;
-- serial_out(up, UART_IER, up->ier);
-+ serial8250_set_IER(up, up->ier);
- return true;
- }
-
---- a/drivers/tty/serial/8250/8250_core.c
-+++ b/drivers/tty/serial/8250/8250_core.c
-@@ -264,10 +264,8 @@ static void serial8250_backup_timeout(st
- * Must disable interrupts or else we risk racing with the interrupt
- * based handler.
- */
-- if (up->port.irq) {
-- ier = serial_in(up, UART_IER);
-- serial_out(up, UART_IER, 0);
-- }
-+ if (up->port.irq)
-+ ier = serial8250_clear_IER(up);
-
- iir = serial_in(up, UART_IIR);
-
-@@ -290,7 +288,7 @@ static void serial8250_backup_timeout(st
- serial8250_tx_chars(up);
-
- if (up->port.irq)
-- serial_out(up, UART_IER, ier);
-+ serial8250_set_IER(up, ier);
-
- spin_unlock_irqrestore(&up->port.lock, flags);
-
-@@ -567,6 +565,14 @@ serial8250_register_ports(struct uart_dr
-
- #ifdef CONFIG_SERIAL_8250_CONSOLE
-
-+static void univ8250_console_write_atomic(struct console *co, const char *s,
-+ unsigned int count)
-+{
-+ struct uart_8250_port *up = &serial8250_ports[co->index];
-+
-+ serial8250_console_write_atomic(up, s, count);
-+}
-+
- static void univ8250_console_write(struct console *co, const char *s,
- unsigned int count)
- {
-@@ -660,6 +666,7 @@ static int univ8250_console_match(struct
-
- static struct console univ8250_console = {
- .name = "ttyS",
-+ .write_atomic = univ8250_console_write_atomic,
- .write = univ8250_console_write,
- .device = uart_console_device,
- .setup = univ8250_console_setup,
---- a/drivers/tty/serial/8250/8250_fsl.c
-+++ b/drivers/tty/serial/8250/8250_fsl.c
-@@ -56,9 +56,18 @@ int fsl8250_handle_irq(struct uart_port
-
- /* Stop processing interrupts on input overrun */
- if ((orig_lsr & UART_LSR_OE) && (up->overrun_backoff_time_ms > 0)) {
-+ unsigned long flags;
- unsigned long delay;
-+ bool is_console;
-
-+ is_console = uart_console(port);
-+
-+ if (is_console)
-+ printk_cpu_sync_get_irqsave(flags);
- up->ier = port->serial_in(port, UART_IER);
-+ if (is_console)
-+ printk_cpu_sync_put_irqrestore(flags);
-+
- if (up->ier & (UART_IER_RLSI | UART_IER_RDI)) {
- port->ops->stop_rx(port);
- } else {
---- a/drivers/tty/serial/8250/8250_ingenic.c
-+++ b/drivers/tty/serial/8250/8250_ingenic.c
-@@ -146,6 +146,8 @@ OF_EARLYCON_DECLARE(x1000_uart, "ingenic
-
- static void ingenic_uart_serial_out(struct uart_port *p, int offset, int value)
- {
-+ unsigned long flags;
-+ bool is_console;
- int ier;
-
- switch (offset) {
-@@ -167,7 +169,12 @@ static void ingenic_uart_serial_out(stru
- * If we have enabled modem status IRQs we should enable
- * modem mode.
- */
-+ is_console = uart_console(p);
-+ if (is_console)
-+ printk_cpu_sync_get_irqsave(flags);
- ier = p->serial_in(p, UART_IER);
-+ if (is_console)
-+ printk_cpu_sync_put_irqrestore(flags);
-
- if (ier & UART_IER_MSI)
- value |= UART_MCR_MDCE | UART_MCR_FCM;
---- a/drivers/tty/serial/8250/8250_mtk.c
-+++ b/drivers/tty/serial/8250/8250_mtk.c
-@@ -218,12 +218,37 @@ static void mtk8250_shutdown(struct uart
-
- static void mtk8250_disable_intrs(struct uart_8250_port *up, int mask)
- {
-- serial_out(up, UART_IER, serial_in(up, UART_IER) & (~mask));
-+ struct uart_port *port = &up->port;
-+ unsigned long flags;
-+ unsigned int ier;
-+ bool is_console;
-+
-+ is_console = uart_console(port);
-+
-+ if (is_console)
-+ printk_cpu_sync_get_irqsave(flags);
-+
-+ ier = serial_in(up, UART_IER);
-+ serial_out(up, UART_IER, ier & (~mask));
-+
-+ if (is_console)
-+ printk_cpu_sync_put_irqrestore(flags);
- }
-
- static void mtk8250_enable_intrs(struct uart_8250_port *up, int mask)
- {
-- serial_out(up, UART_IER, serial_in(up, UART_IER) | mask);
-+ struct uart_port *port = &up->port;
-+ unsigned long flags;
-+ unsigned int ier;
-+
-+ if (uart_console(port))
-+ printk_cpu_sync_get_irqsave(flags);
-+
-+ ier = serial_in(up, UART_IER);
-+ serial_out(up, UART_IER, ier | mask);
-+
-+ if (uart_console(port))
-+ printk_cpu_sync_put_irqrestore(flags);
- }
-
- static void mtk8250_set_flow_ctrl(struct uart_8250_port *up, int mode)
---- a/drivers/tty/serial/8250/8250_port.c
-+++ b/drivers/tty/serial/8250/8250_port.c
-@@ -762,7 +762,7 @@ static void serial8250_set_sleep(struct
- serial_out(p, UART_EFR, UART_EFR_ECB);
- serial_out(p, UART_LCR, 0);
- }
-- serial_out(p, UART_IER, sleep ? UART_IERX_SLEEP : 0);
-+ serial8250_set_IER(p, sleep ? UART_IERX_SLEEP : 0);
- if (p->capabilities & UART_CAP_EFR) {
- serial_out(p, UART_LCR, UART_LCR_CONF_MODE_B);
- serial_out(p, UART_EFR, efr);
-@@ -1436,7 +1436,7 @@ static void serial8250_stop_rx(struct ua
-
- up->ier &= ~(UART_IER_RLSI | UART_IER_RDI);
- up->port.read_status_mask &= ~UART_LSR_DR;
-- serial_port_out(port, UART_IER, up->ier);
-+ serial8250_set_IER(up, up->ier);
-
- serial8250_rpm_put(up);
- }
-@@ -1466,7 +1466,7 @@ void serial8250_em485_stop_tx(struct uar
- serial8250_clear_and_reinit_fifos(p);
-
- p->ier |= UART_IER_RLSI | UART_IER_RDI;
-- serial_port_out(&p->port, UART_IER, p->ier);
-+ serial8250_set_IER(p, p->ier);
- }
- }
- EXPORT_SYMBOL_GPL(serial8250_em485_stop_tx);
-@@ -1688,7 +1688,7 @@ static void serial8250_disable_ms(struct
- mctrl_gpio_disable_ms(up->gpios);
-
- up->ier &= ~UART_IER_MSI;
-- serial_port_out(port, UART_IER, up->ier);
-+ serial8250_set_IER(up, up->ier);
- }
-
- static void serial8250_enable_ms(struct uart_port *port)
-@@ -1704,7 +1704,7 @@ static void serial8250_enable_ms(struct
- up->ier |= UART_IER_MSI;
-
- serial8250_rpm_get(up);
-- serial_port_out(port, UART_IER, up->ier);
-+ serial8250_set_IER(up, up->ier);
- serial8250_rpm_put(up);
- }
-
-@@ -2125,14 +2125,7 @@ static void serial8250_put_poll_char(str
- struct uart_8250_port *up = up_to_u8250p(port);
-
- serial8250_rpm_get(up);
-- /*
-- * First save the IER then disable the interrupts
-- */
-- ier = serial_port_in(port, UART_IER);
-- if (up->capabilities & UART_CAP_UUE)
-- serial_port_out(port, UART_IER, UART_IER_UUE);
-- else
-- serial_port_out(port, UART_IER, 0);
-+ ier = serial8250_clear_IER(up);
-
- wait_for_xmitr(up, BOTH_EMPTY);
- /*
-@@ -2145,7 +2138,7 @@ static void serial8250_put_poll_char(str
- * and restore the IER
- */
- wait_for_xmitr(up, BOTH_EMPTY);
-- serial_port_out(port, UART_IER, ier);
-+ serial8250_set_IER(up, ier);
- serial8250_rpm_put(up);
- }
-
-@@ -2448,7 +2441,7 @@ void serial8250_do_shutdown(struct uart_
- */
- spin_lock_irqsave(&port->lock, flags);
- up->ier = 0;
-- serial_port_out(port, UART_IER, 0);
-+ serial8250_set_IER(up, 0);
- spin_unlock_irqrestore(&port->lock, flags);
-
- synchronize_irq(port->irq);
-@@ -2830,7 +2823,7 @@ serial8250_do_set_termios(struct uart_po
- if (up->capabilities & UART_CAP_RTOIE)
- up->ier |= UART_IER_RTOIE;
-
-- serial_port_out(port, UART_IER, up->ier);
-+ serial8250_set_IER(up, up->ier);
-
- if (up->capabilities & UART_CAP_EFR) {
- unsigned char efr = 0;
-@@ -3296,7 +3289,7 @@ EXPORT_SYMBOL_GPL(serial8250_set_default
-
- #ifdef CONFIG_SERIAL_8250_CONSOLE
-
--static void serial8250_console_putchar(struct uart_port *port, int ch)
-+static void serial8250_console_putchar_locked(struct uart_port *port, int ch)
- {
- struct uart_8250_port *up = up_to_u8250p(port);
-
-@@ -3304,6 +3297,18 @@ static void serial8250_console_putchar(s
- serial_port_out(port, UART_TX, ch);
- }
-
-+static void serial8250_console_putchar(struct uart_port *port, int ch)
-+{
-+ struct uart_8250_port *up = up_to_u8250p(port);
-+ unsigned long flags;
-+
-+ wait_for_xmitr(up, UART_LSR_THRE);
-+
-+ printk_cpu_sync_get_irqsave(flags);
-+ serial8250_console_putchar_locked(port, ch);
-+ printk_cpu_sync_put_irqrestore(flags);
-+}
-+
- /*
- * Restore serial console when h/w power-off detected
- */
-@@ -3325,6 +3330,32 @@ static void serial8250_console_restore(s
- serial8250_out_MCR(up, UART_MCR_DTR | UART_MCR_RTS);
- }
-
-+void serial8250_console_write_atomic(struct uart_8250_port *up,
-+ const char *s, unsigned int count)
-+{
-+ struct uart_port *port = &up->port;
-+ unsigned long flags;
-+ unsigned int ier;
-+
-+ printk_cpu_sync_get_irqsave(flags);
-+
-+ touch_nmi_watchdog();
-+
-+ ier = serial8250_clear_IER(up);
-+
-+ if (atomic_fetch_inc(&up->console_printing)) {
-+ uart_console_write(port, "\n", 1,
-+ serial8250_console_putchar_locked);
-+ }
-+ uart_console_write(port, s, count, serial8250_console_putchar_locked);
-+ atomic_dec(&up->console_printing);
-+
-+ wait_for_xmitr(up, BOTH_EMPTY);
-+ serial8250_set_IER(up, ier);
-+
-+ printk_cpu_sync_put_irqrestore(flags);
-+}
-+
- /*
- * Print a string to the serial port trying not to disturb
- * any possible real use of the port...
-@@ -3341,24 +3372,12 @@ void serial8250_console_write(struct uar
- struct uart_port *port = &up->port;
- unsigned long flags;
- unsigned int ier;
-- int locked = 1;
-
- touch_nmi_watchdog();
-
-- if (oops_in_progress)
-- locked = spin_trylock_irqsave(&port->lock, flags);
-- else
-- spin_lock_irqsave(&port->lock, flags);
--
-- /*
-- * First save the IER then disable the interrupts
-- */
-- ier = serial_port_in(port, UART_IER);
-+ spin_lock_irqsave(&port->lock, flags);
-
-- if (up->capabilities & UART_CAP_UUE)
-- serial_port_out(port, UART_IER, UART_IER_UUE);
-- else
-- serial_port_out(port, UART_IER, 0);
-+ ier = serial8250_clear_IER(up);
-
- /* check scratch reg to see if port powered off during system sleep */
- if (up->canary && (up->canary != serial_port_in(port, UART_SCR))) {
-@@ -3372,7 +3391,9 @@ void serial8250_console_write(struct uar
- mdelay(port->rs485.delay_rts_before_send);
- }
-
-+ atomic_inc(&up->console_printing);
- uart_console_write(port, s, count, serial8250_console_putchar);
-+ atomic_dec(&up->console_printing);
-
- /*
- * Finally, wait for transmitter to become empty
-@@ -3385,8 +3406,7 @@ void serial8250_console_write(struct uar
- if (em485->tx_stopped)
- up->rs485_stop_tx(up);
- }
--
-- serial_port_out(port, UART_IER, ier);
-+ serial8250_set_IER(up, ier);
-
- /*
- * The receive handling will happen properly because the
-@@ -3398,8 +3418,7 @@ void serial8250_console_write(struct uar
- if (up->msr_saved_flags)
- serial8250_modem_status(up);
-
-- if (locked)
-- spin_unlock_irqrestore(&port->lock, flags);
-+ spin_unlock_irqrestore(&port->lock, flags);
- }
-
- static unsigned int probe_baud(struct uart_port *port)
-@@ -3419,6 +3438,7 @@ static unsigned int probe_baud(struct ua
-
- int serial8250_console_setup(struct uart_port *port, char *options, bool probe)
- {
-+ struct uart_8250_port *up = up_to_u8250p(port);
- int baud = 9600;
- int bits = 8;
- int parity = 'n';
-@@ -3428,6 +3448,8 @@ int serial8250_console_setup(struct uart
- if (!port->iobase && !port->membase)
- return -ENODEV;
-
-+ atomic_set(&up->console_printing, 0);
-+
- if (options)
- uart_parse_options(options, &baud, &parity, &bits, &flow);
- else if (probe)
---- a/drivers/tty/serial/8250/Kconfig
-+++ b/drivers/tty/serial/8250/Kconfig
-@@ -9,6 +9,7 @@ config SERIAL_8250
- depends on !S390
- select SERIAL_CORE
- select SERIAL_MCTRL_GPIO if GPIOLIB
-+ select HAVE_ATOMIC_CONSOLE
- help
- This selects whether you want to include the driver for the standard
- serial ports. The standard answer is Y. People who might say N
---- a/include/linux/serial_8250.h
-+++ b/include/linux/serial_8250.h
-@@ -7,6 +7,7 @@
- #ifndef _LINUX_SERIAL_8250_H
- #define _LINUX_SERIAL_8250_H
-
-+#include <linux/atomic.h>
- #include <linux/serial_core.h>
- #include <linux/serial_reg.h>
- #include <linux/platform_device.h>
-@@ -123,6 +124,8 @@ struct uart_8250_port {
- #define MSR_SAVE_FLAGS UART_MSR_ANY_DELTA
- unsigned char msr_saved_flags;
-
-+ atomic_t console_printing;
-+
- struct uart_8250_dma *dma;
- const struct uart_8250_ops *ops;
-
-@@ -178,6 +181,8 @@ void serial8250_init_port(struct uart_82
- void serial8250_set_defaults(struct uart_8250_port *up);
- void serial8250_console_write(struct uart_8250_port *up, const char *s,
- unsigned int count);
-+void serial8250_console_write_atomic(struct uart_8250_port *up, const char *s,
-+ unsigned int count);
- int serial8250_console_setup(struct uart_port *port, char *options, bool probe);
- int serial8250_console_exit(struct uart_port *port);
-
diff --git a/patches/ARM64__Allow_to_enable_RT.patch b/patches/ARM64__Allow_to_enable_RT.patch
index 1ebbea855d4c..fd03bece904c 100644
--- a/patches/ARM64__Allow_to_enable_RT.patch
+++ b/patches/ARM64__Allow_to_enable_RT.patch
@@ -16,7 +16,7 @@ Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
-@@ -89,6 +89,7 @@ config ARM64
+@@ -91,6 +91,7 @@ config ARM64
select ARCH_SUPPORTS_ATOMIC_RMW
select ARCH_SUPPORTS_INT128 if CC_HAS_INT128
select ARCH_SUPPORTS_NUMA_BALANCING
diff --git a/patches/ARM__Allow_to_enable_RT.patch b/patches/ARM__Allow_to_enable_RT.patch
index ad7dffb7b4cb..fd6296d4cdbe 100644
--- a/patches/ARM__Allow_to_enable_RT.patch
+++ b/patches/ARM__Allow_to_enable_RT.patch
@@ -16,7 +16,7 @@ Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
-@@ -33,6 +33,7 @@ config ARM
+@@ -34,6 +34,7 @@ config ARM
select ARCH_OPTIONAL_KERNEL_RWX_DEFAULT if CPU_V7
select ARCH_SUPPORTS_ATOMIC_RMW
select ARCH_SUPPORTS_HUGETLBFS if ARM_LPAE
@@ -24,11 +24,11 @@ Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
select ARCH_USE_BUILTIN_BSWAP
select ARCH_USE_CMPXCHG_LOCKREF
select ARCH_USE_MEMTEST
-@@ -126,6 +127,7 @@ config ARM
+@@ -129,6 +130,7 @@ config ARM
select OLD_SIGSUSPEND3
select PCI_SYSCALL if PCI
select PERF_USE_VMALLOC
+ select HAVE_POSIX_CPU_TIMERS_TASK_WORK if !KVM
select RTC_LIB
select SYS_SUPPORTS_APM_EMULATION
- select THREAD_INFO_IN_TASK if CURRENT_POINTER_IN_TPIDRURO
+ select THREAD_INFO_IN_TASK
diff --git a/patches/Add_localversion_for_-RT_release.patch b/patches/Add_localversion_for_-RT_release.patch
index efeddd431fc4..0e6dbb0e3c10 100644
--- a/patches/Add_localversion_for_-RT_release.patch
+++ b/patches/Add_localversion_for_-RT_release.patch
@@ -15,4 +15,4 @@ Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
--- /dev/null
+++ b/localversion-rt
@@ -0,0 +1 @@
-+-rt17
++-rt1
diff --git a/patches/KVM__arm_arm64__downgrade_preempt_disabled_region_to_migrate_disable.patch b/patches/KVM__arm_arm64__downgrade_preempt_disabled_region_to_migrate_disable.patch
index bb18775b7325..846c95920b28 100644
--- a/patches/KVM__arm_arm64__downgrade_preempt_disabled_region_to_migrate_disable.patch
+++ b/patches/KVM__arm_arm64__downgrade_preempt_disabled_region_to_migrate_disable.patch
@@ -27,16 +27,16 @@ Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
--- a/arch/arm64/kvm/arm.c
+++ b/arch/arm64/kvm/arm.c
-@@ -864,7 +864,7 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_v
+@@ -798,7 +798,7 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_v
* involves poking the GIC, which must be done in a
* non-preemptible context.
*/
- preempt_disable();
+ migrate_disable();
- kvm_pmu_flush_hwstate(vcpu);
-
-@@ -888,7 +888,7 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_v
+ /*
+ * The VMID allocator only tracks active VMIDs per
+@@ -831,7 +831,7 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_v
kvm_timer_sync_user(vcpu);
kvm_vgic_sync_hwstate(vcpu);
local_irq_enable();
@@ -45,7 +45,7 @@ Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
continue;
}
-@@ -958,7 +958,7 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_v
+@@ -903,7 +903,7 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_v
/* Exit types that need handling before we can be preempted */
handle_exit_early(vcpu, ret);
diff --git a/patches/POWERPC__Allow_to_enable_RT.patch b/patches/POWERPC__Allow_to_enable_RT.patch
index e2e298e764ce..5bedabc2150c 100644
--- a/patches/POWERPC__Allow_to_enable_RT.patch
+++ b/patches/POWERPC__Allow_to_enable_RT.patch
@@ -16,7 +16,7 @@ Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
-@@ -144,6 +144,7 @@ config PPC
+@@ -149,6 +149,7 @@ config PPC
select ARCH_STACKWALK
select ARCH_SUPPORTS_ATOMIC_RMW
select ARCH_SUPPORTS_DEBUG_PAGEALLOC if PPC_BOOK3S || PPC_8xx || 40x
@@ -24,7 +24,7 @@ Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
select ARCH_USE_BUILTIN_BSWAP
select ARCH_USE_CMPXCHG_LOCKREF if PPC64
select ARCH_USE_MEMTEST
-@@ -213,6 +214,7 @@ config PPC
+@@ -220,6 +221,7 @@ config PPC
select HAVE_IOREMAP_PROT
select HAVE_IRQ_EXIT_ON_IRQ_STACK
select HAVE_IRQ_TIME_ACCOUNTING
diff --git a/patches/arch_arm64__Add_lazy_preempt_support.patch b/patches/arch_arm64__Add_lazy_preempt_support.patch
index 37250a72d887..5cb73f4f6bc0 100644
--- a/patches/arch_arm64__Add_lazy_preempt_support.patch
+++ b/patches/arch_arm64__Add_lazy_preempt_support.patch
@@ -25,9 +25,9 @@ Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
-@@ -193,6 +193,7 @@ config ARM64
- select HAVE_PERF_REGS
+@@ -196,6 +196,7 @@ config ARM64
select HAVE_PERF_USER_STACK_DUMP
+ select HAVE_PREEMPT_DYNAMIC_KEY
select HAVE_REGS_AND_STACK_ACCESS_API
+ select HAVE_PREEMPT_LAZY
select HAVE_POSIX_CPU_TIMERS_TASK_WORK
@@ -35,7 +35,7 @@ Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
select MMU_GATHER_RCU_TABLE_FREE
--- a/arch/arm64/include/asm/preempt.h
+++ b/arch/arm64/include/asm/preempt.h
-@@ -70,13 +70,36 @@ static inline bool __preempt_count_dec_a
+@@ -71,13 +71,36 @@ static inline bool __preempt_count_dec_a
* interrupt occurring between the non-atomic READ_ONCE/WRITE_ONCE
* pair.
*/
@@ -124,7 +124,7 @@ Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
#endif
--- a/arch/arm64/kernel/signal.c
+++ b/arch/arm64/kernel/signal.c
-@@ -920,7 +920,7 @@ static void do_signal(struct pt_regs *re
+@@ -921,7 +921,7 @@ static void do_signal(struct pt_regs *re
void do_notify_resume(struct pt_regs *regs, unsigned long thread_flags)
{
do {
diff --git a/patches/arm64-signal-Use-ARCH_RT_DELAYS_SIGNAL_SEND.patch b/patches/arm64-signal-Use-ARCH_RT_DELAYS_SIGNAL_SEND.patch
index b42e7cb1c9e3..d96f4f6462dc 100644
--- a/patches/arm64-signal-Use-ARCH_RT_DELAYS_SIGNAL_SEND.patch
+++ b/patches/arm64-signal-Use-ARCH_RT_DELAYS_SIGNAL_SEND.patch
@@ -19,7 +19,7 @@ Link: https://lore.kernel.org/r/20211012084421.35136-1-zhe.he@windriver.com
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
-@@ -96,6 +96,7 @@ config ARM64
+@@ -98,6 +98,7 @@ config ARM64
select ARCH_WANT_HUGE_PMD_SHARE if ARM64_4K_PAGES || (ARM64_16K_PAGES && !ARM64_VA_BITS_36)
select ARCH_WANT_LD_ORPHAN_WARN
select ARCH_WANTS_NO_INSTR
@@ -29,7 +29,7 @@ Link: https://lore.kernel.org/r/20211012084421.35136-1-zhe.he@windriver.com
select ARM_ARCH_TIMER
--- a/arch/arm64/kernel/signal.c
+++ b/arch/arm64/kernel/signal.c
-@@ -928,6 +928,14 @@ void do_notify_resume(struct pt_regs *re
+@@ -929,6 +929,14 @@ void do_notify_resume(struct pt_regs *re
} else {
local_daif_restore(DAIF_PROCCTX);
diff --git a/patches/arm64-sve-Delay-freeing-memory-in-fpsimd_flush_threa.patch b/patches/arm64-sve-Delay-freeing-memory-in-fpsimd_flush_threa.patch
index e5fddb7cfa22..995147c9595e 100644
--- a/patches/arm64-sve-Delay-freeing-memory-in-fpsimd_flush_threa.patch
+++ b/patches/arm64-sve-Delay-freeing-memory-in-fpsimd_flush_threa.patch
@@ -14,7 +14,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
--- a/arch/arm64/kernel/fpsimd.c
+++ b/arch/arm64/kernel/fpsimd.c
-@@ -1135,6 +1135,8 @@ static void fpsimd_flush_thread_vl(enum
+@@ -1141,6 +1141,8 @@ static void fpsimd_flush_thread_vl(enum
void fpsimd_flush_thread(void)
{
@@ -23,7 +23,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
if (!system_supports_fpsimd())
return;
-@@ -1146,11 +1148,16 @@ void fpsimd_flush_thread(void)
+@@ -1152,11 +1154,16 @@ void fpsimd_flush_thread(void)
if (system_supports_sve()) {
clear_thread_flag(TIF_SVE);
diff --git a/patches/arm__Add_support_for_lazy_preemption.patch b/patches/arm__Add_support_for_lazy_preemption.patch
index 8ceccc1acaf0..75c7f1f824e3 100644
--- a/patches/arm__Add_support_for_lazy_preemption.patch
+++ b/patches/arm__Add_support_for_lazy_preemption.patch
@@ -19,7 +19,7 @@ Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
-@@ -110,6 +110,7 @@ config ARM
+@@ -113,6 +113,7 @@ config ARM
select HAVE_PERF_EVENTS
select HAVE_PERF_REGS
select HAVE_PERF_USER_STACK_DUMP
@@ -29,15 +29,15 @@ Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
select HAVE_RSEQ
--- a/arch/arm/include/asm/thread_info.h
+++ b/arch/arm/include/asm/thread_info.h
-@@ -54,6 +54,7 @@ struct cpu_context_save {
+@@ -62,6 +62,7 @@ struct cpu_context_save {
struct thread_info {
unsigned long flags; /* low level flags */
int preempt_count; /* 0 => preemptable, <0 => bug */
+ int preempt_lazy_count; /* 0 => preemptable, <0 => bug */
- #ifndef CONFIG_THREAD_INFO_IN_TASK
- struct task_struct *task; /* main task structure */
- #endif
-@@ -152,6 +153,7 @@ extern int vfp_restore_user_hwstate(stru
+ __u32 cpu; /* cpu */
+ __u32 cpu_domain; /* cpu domain */
+ struct cpu_context_save cpu_context; /* cpu context */
+@@ -133,6 +134,7 @@ extern int vfp_restore_user_hwstate(stru
#define TIF_SYSCALL_TRACEPOINT 6 /* syscall tracepoint instrumentation */
#define TIF_SECCOMP 7 /* seccomp syscall filtering active */
#define TIF_NOTIFY_SIGNAL 8 /* signal notifications exist */
@@ -45,7 +45,7 @@ Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
#define TIF_USING_IWMMXT 17
#define TIF_MEMDIE 18 /* is terminating due to OOM killer */
-@@ -166,6 +168,7 @@ extern int vfp_restore_user_hwstate(stru
+@@ -147,6 +149,7 @@ extern int vfp_restore_user_hwstate(stru
#define _TIF_SYSCALL_TRACEPOINT (1 << TIF_SYSCALL_TRACEPOINT)
#define _TIF_SECCOMP (1 << TIF_SECCOMP)
#define _TIF_NOTIFY_SIGNAL (1 << TIF_NOTIFY_SIGNAL)
@@ -53,7 +53,7 @@ Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
#define _TIF_USING_IWMMXT (1 << TIF_USING_IWMMXT)
/* Checks for any syscall work in entry-common.S */
-@@ -175,7 +178,8 @@ extern int vfp_restore_user_hwstate(stru
+@@ -156,7 +159,8 @@ extern int vfp_restore_user_hwstate(stru
/*
* Change these and you break ASM code in entry-common.S
*/
@@ -70,12 +70,12 @@ Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
DEFINE(TI_FLAGS, offsetof(struct thread_info, flags));
DEFINE(TI_PREEMPT, offsetof(struct thread_info, preempt_count));
+ DEFINE(TI_PREEMPT_LAZY, offsetof(struct thread_info, preempt_lazy_count));
- #ifndef CONFIG_THREAD_INFO_IN_TASK
- DEFINE(TI_TASK, offsetof(struct thread_info, task));
- #endif
+ DEFINE(TI_CPU, offsetof(struct thread_info, cpu));
+ DEFINE(TI_CPU_DOMAIN, offsetof(struct thread_info, cpu_domain));
+ DEFINE(TI_CPU_SAVE, offsetof(struct thread_info, cpu_context));
--- a/arch/arm/kernel/entry-armv.S
+++ b/arch/arm/kernel/entry-armv.S
-@@ -203,11 +203,18 @@ ENDPROC(__dabt_svc)
+@@ -224,11 +224,18 @@ ENDPROC(__dabt_svc)
#ifdef CONFIG_PREEMPTION
ldr r8, [tsk, #TI_PREEMPT] @ get preempt count
@@ -96,7 +96,7 @@ Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
#endif
svc_exit r5, irq = 1 @ return from exception
-@@ -222,8 +229,14 @@ ENDPROC(__irq_svc)
+@@ -243,8 +250,14 @@ ENDPROC(__irq_svc)
1: bl preempt_schedule_irq @ irq en/disable is done inside
ldr r0, [tsk, #TI_FLAGS] @ get new tasks TI_FLAGS
tst r0, #_TIF_NEED_RESCHED
diff --git a/patches/block_mq__do_not_invoke_preempt_disable.patch b/patches/block_mq__do_not_invoke_preempt_disable.patch
index c862f3bd5a28..dae42f07f446 100644
--- a/patches/block_mq__do_not_invoke_preempt_disable.patch
+++ b/patches/block_mq__do_not_invoke_preempt_disable.patch
@@ -18,7 +18,7 @@ Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
--- a/block/blk-mq.c
+++ b/block/blk-mq.c
-@@ -2044,14 +2044,14 @@ static void __blk_mq_delay_run_hw_queue(
+@@ -2053,14 +2053,14 @@ static void __blk_mq_delay_run_hw_queue(
return;
if (!async && !(hctx->flags & BLK_MQ_F_BLOCKING)) {
diff --git a/patches/cgroup__use_irqsave_in_cgroup_rstat_flush_locked.patch b/patches/cgroup__use_irqsave_in_cgroup_rstat_flush_locked.patch
deleted file mode 100644
index 62402d218f3f..000000000000
--- a/patches/cgroup__use_irqsave_in_cgroup_rstat_flush_locked.patch
+++ /dev/null
@@ -1,49 +0,0 @@
-Subject: cgroup: use irqsave in cgroup_rstat_flush_locked()
-From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
-Date: Tue Jul 3 18:19:48 2018 +0200
-
-From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
-
-All callers of cgroup_rstat_flush_locked() acquire cgroup_rstat_lock
-either with spin_lock_irq() or spin_lock_irqsave().
-cgroup_rstat_flush_locked() itself acquires cgroup_rstat_cpu_lock which
-is a raw_spin_lock. This lock is also acquired in cgroup_rstat_updated()
-in IRQ context and therefore requires _irqsave() locking suffix in
-cgroup_rstat_flush_locked().
-Since there is no difference between spin_lock_t and raw_spin_lock_t
-on !RT lockdep does not complain here. On RT lockdep complains because
-the interrupts were not disabled here and a deadlock is possible.
-
-Acquire the raw_spin_lock_t with disabled interrupts.
-
-Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
-Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
-Link: https://www.spinics.net/lists/cgroups/msg23051.html
-
-
----
- kernel/cgroup/rstat.c | 5 +++--
- 1 file changed, 3 insertions(+), 2 deletions(-)
----
---- a/kernel/cgroup/rstat.c
-+++ b/kernel/cgroup/rstat.c
-@@ -153,8 +153,9 @@ static void cgroup_rstat_flush_locked(st
- raw_spinlock_t *cpu_lock = per_cpu_ptr(&cgroup_rstat_cpu_lock,
- cpu);
- struct cgroup *pos = NULL;
-+ unsigned long flags;
-
-- raw_spin_lock(cpu_lock);
-+ raw_spin_lock_irqsave(cpu_lock, flags);
- while ((pos = cgroup_rstat_cpu_pop_updated(pos, cgrp, cpu))) {
- struct cgroup_subsys_state *css;
-
-@@ -166,7 +167,7 @@ static void cgroup_rstat_flush_locked(st
- css->ss->css_rstat_flush(css, cpu);
- rcu_read_unlock();
- }
-- raw_spin_unlock(cpu_lock);
-+ raw_spin_unlock_irqrestore(cpu_lock, flags);
-
- /* if @may_sleep, play nice and yield if necessary */
- if (may_sleep && (need_resched() ||
diff --git a/patches/drivers_block_zram__Replace_bit_spinlocks_with_rtmutex_for_-rt.patch b/patches/drivers_block_zram__Replace_bit_spinlocks_with_rtmutex_for_-rt.patch
index 2dd9a5d4284a..38d74ba73010 100644
--- a/patches/drivers_block_zram__Replace_bit_spinlocks_with_rtmutex_for_-rt.patch
+++ b/patches/drivers_block_zram__Replace_bit_spinlocks_with_rtmutex_for_-rt.patch
@@ -19,7 +19,7 @@ Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
--- a/drivers/block/zram/zram_drv.c
+++ b/drivers/block/zram/zram_drv.c
-@@ -59,6 +59,40 @@ static void zram_free_page(struct zram *
+@@ -58,6 +58,40 @@ static void zram_free_page(struct zram *
static int zram_bvec_read(struct zram *zram, struct bio_vec *bvec,
u32 index, int offset, struct bio *bio);
@@ -60,7 +60,7 @@ Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
static int zram_slot_trylock(struct zram *zram, u32 index)
{
-@@ -74,6 +108,7 @@ static void zram_slot_unlock(struct zram
+@@ -73,6 +107,7 @@ static void zram_slot_unlock(struct zram
{
bit_spin_unlock(ZRAM_LOCK, &zram->table[index].flags);
}
@@ -68,7 +68,7 @@ Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
static inline bool init_done(struct zram *zram)
{
-@@ -1199,6 +1234,7 @@ static bool zram_meta_alloc(struct zram
+@@ -1194,6 +1229,7 @@ static bool zram_meta_alloc(struct zram
if (!huge_class_size)
huge_class_size = zs_huge_class_size(zram->mem_pool);
diff --git a/patches/drm-i915-Depend-on-PREEMPT_RT.patch b/patches/drm-i915-Depend-on-PREEMPT_RT.patch
deleted file mode 100644
index faef6c8477ad..000000000000
--- a/patches/drm-i915-Depend-on-PREEMPT_RT.patch
+++ /dev/null
@@ -1,28 +0,0 @@
-From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
-Date: Mon, 14 Feb 2022 19:59:08 +0100
-Subject: [PATCH] drm/i915: Depend on !PREEMPT_RT.
-
-There are a few sections in the driver which are not compatible with
-PREEMPT_RT. They trigger warnings and can lead to deadlocks at runtime.
-
-Disable the i915 driver on a PREEMPT_RT enabled kernel. This way
-PREEMPT_RT itself can be enabled without needing to address the i915
-issues first. The RT related patches are still in RT queue and will be
-handled later.
-
-Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
-Link: https://lore.kernel.org/r/YgqmfKhwU5spS069@linutronix.de
----
- drivers/gpu/drm/i915/Kconfig | 1 +
- 1 file changed, 1 insertion(+)
-
---- a/drivers/gpu/drm/i915/Kconfig
-+++ b/drivers/gpu/drm/i915/Kconfig
-@@ -3,6 +3,7 @@ config DRM_I915
- tristate "Intel 8xx/9xx/G3x/G4x/HD Graphics"
- depends on DRM
- depends on X86 && PCI
-+ depends on !PREEMPT_RT
- select INTEL_GTT
- select INTERVAL_TREE
- # we need shmfs for the swappable backing store, and in particular
diff --git a/patches/fs-namespace-Boost-the-mount_lock.lock-owner-instead.patch b/patches/fs-namespace-Boost-the-mount_lock.lock-owner-instead.patch
deleted file mode 100644
index 80eeb49697aa..000000000000
--- a/patches/fs-namespace-Boost-the-mount_lock.lock-owner-instead.patch
+++ /dev/null
@@ -1,57 +0,0 @@
-From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
-Date: Mon, 25 Oct 2021 16:49:35 +0200
-Subject: [PATCH] fs/namespace: Boost the mount_lock.lock owner instead of
- spinning on PREEMPT_RT.
-
-The MNT_WRITE_HOLD flag is used to hold back any new writers while the
-mount point is about to be made read-only. __mnt_want_write() then loops
-with disabled preemption until this flag disappears. Callers of
-mnt_hold_writers() (which sets the flag) hold the spinlock_t of
-mount_lock (seqlock_t) which disables preemption on !PREEMPT_RT and
-ensures the task is not scheduled away so that the spinning side spins
-for a long time.
-
-On PREEMPT_RT the spinlock_t does not disable preemption and so it is
-possible that the task setting MNT_WRITE_HOLD is preempted by task with
-higher priority which then spins infinitely waiting for MNT_WRITE_HOLD
-to get removed.
-
-Acquire mount_lock::lock which is held by setter of MNT_WRITE_HOLD. This
-will PI-boost the owner and wait until the lock is dropped and which
-means that MNT_WRITE_HOLD is cleared again.
-
-Link: https://lkml.kernel.org/r/20211025152218.opvcqfku2lhqvp4o@linutronix.de
-Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
----
- fs/namespace.c | 20 ++++++++++++++++++--
- 1 file changed, 18 insertions(+), 2 deletions(-)
-
---- a/fs/namespace.c
-+++ b/fs/namespace.c
-@@ -344,8 +344,24 @@ int __mnt_want_write(struct vfsmount *m)
- * incremented count after it has set MNT_WRITE_HOLD.
- */
- smp_mb();
-- while (READ_ONCE(mnt->mnt.mnt_flags) & MNT_WRITE_HOLD)
-- cpu_relax();
-+ might_lock(&mount_lock.lock);
-+ while (READ_ONCE(mnt->mnt.mnt_flags) & MNT_WRITE_HOLD) {
-+ if (!IS_ENABLED(CONFIG_PREEMPT_RT)) {
-+ cpu_relax();
-+ } else {
-+ /*
-+ * This prevents priority inversion, if the task
-+ * setting MNT_WRITE_HOLD got preempted on a remote
-+ * CPU, and it prevents life lock if the task setting
-+ * MNT_WRITE_HOLD has a lower priority and is bound to
-+ * the same CPU as the task that is spinning here.
-+ */
-+ preempt_enable();
-+ lock_mount_hash();
-+ unlock_mount_hash();
-+ preempt_disable();
-+ }
-+ }
- /*
- * After the slowpath clears MNT_WRITE_HOLD, mnt_is_readonly will
- * be set to match its requirements. So we must not load that until
diff --git a/patches/fs_dcache__disable_preemption_on_i_dir_seqs_write_side.patch b/patches/fs_dcache__disable_preemption_on_i_dir_seqs_write_side.patch
index 2064e56012fa..f834249ca308 100644
--- a/patches/fs_dcache__disable_preemption_on_i_dir_seqs_write_side.patch
+++ b/patches/fs_dcache__disable_preemption_on_i_dir_seqs_write_side.patch
@@ -38,7 +38,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
---
--- a/fs/dcache.c
+++ b/fs/dcache.c
-@@ -2562,7 +2562,13 @@ EXPORT_SYMBOL(d_rehash);
+@@ -2563,7 +2563,13 @@ EXPORT_SYMBOL(d_rehash);
static inline unsigned start_dir_add(struct inode *dir)
{
@@ -53,7 +53,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
for (;;) {
unsigned n = dir->i_dir_seq;
if (!(n & 1) && cmpxchg(&dir->i_dir_seq, n, n + 1) == n)
-@@ -2574,6 +2580,8 @@ static inline unsigned start_dir_add(str
+@@ -2575,6 +2581,8 @@ static inline unsigned start_dir_add(str
static inline void end_dir_add(struct inode *dir, unsigned n)
{
smp_store_release(&dir->i_dir_seq, n + 2);
diff --git a/patches/fs_dcache__use_swait_queue_instead_of_waitqueue.patch b/patches/fs_dcache__use_swait_queue_instead_of_waitqueue.patch
index f632d54f4d28..5c73ee04b554 100644
--- a/patches/fs_dcache__use_swait_queue_instead_of_waitqueue.patch
+++ b/patches/fs_dcache__use_swait_queue_instead_of_waitqueue.patch
@@ -50,7 +50,7 @@ Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
--- a/fs/dcache.c
+++ b/fs/dcache.c
-@@ -2578,21 +2578,24 @@ static inline void end_dir_add(struct in
+@@ -2579,21 +2579,24 @@ static inline void end_dir_add(struct in
static void d_wait_lookup(struct dentry *dentry)
{
@@ -86,7 +86,7 @@ Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
{
unsigned int hash = name->hash;
struct hlist_bl_head *b = in_lookup_hash(parent, hash);
-@@ -2707,7 +2710,7 @@ void __d_lookup_done(struct dentry *dent
+@@ -2708,7 +2711,7 @@ void __d_lookup_done(struct dentry *dent
hlist_bl_lock(b);
dentry->d_flags &= ~DCACHE_PAR_LOOKUP;
__hlist_bl_del(&dentry->d_u.d_in_lookup_hash);
@@ -128,7 +128,7 @@ Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
return ERR_PTR(-ENOENT);
--- a/fs/nfs/dir.c
+++ b/fs/nfs/dir.c
-@@ -641,7 +641,7 @@ void nfs_prime_dcache(struct dentry *par
+@@ -721,7 +721,7 @@ void nfs_prime_dcache(struct dentry *par
unsigned long dir_verifier)
{
struct qstr filename = QSTR_INIT(entry->name, entry->len);
@@ -137,7 +137,7 @@ Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
struct dentry *dentry;
struct dentry *alias;
struct inode *inode;
-@@ -1895,7 +1895,7 @@ int nfs_atomic_open(struct inode *dir, s
+@@ -2020,7 +2020,7 @@ int nfs_atomic_open(struct inode *dir, s
struct file *file, unsigned open_flags,
umode_t mode)
{
@@ -168,7 +168,7 @@ Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
spin_lock(&dentry->d_lock);
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
-@@ -96,6 +96,7 @@
+@@ -95,6 +95,7 @@
#include <linux/posix-timers.h>
#include <linux/time_namespace.h>
#include <linux/resctrl.h>
@@ -176,7 +176,7 @@ Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
#include <linux/cn_proc.h>
#include <trace/events/oom.h>
#include "internal.h"
-@@ -2045,7 +2046,7 @@ bool proc_fill_cache(struct file *file,
+@@ -2044,7 +2045,7 @@ bool proc_fill_cache(struct file *file,
child = d_hash_and_lookup(dir, &qname);
if (!child) {
@@ -218,7 +218,7 @@ Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
extern struct dentry * d_exact_alias(struct dentry *, struct inode *);
--- a/include/linux/nfs_xdr.h
+++ b/include/linux/nfs_xdr.h
-@@ -1686,7 +1686,7 @@ struct nfs_unlinkdata {
+@@ -1685,7 +1685,7 @@ struct nfs_unlinkdata {
struct nfs_removeargs args;
struct nfs_removeres res;
struct dentry *dentry;
@@ -229,7 +229,7 @@ Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
long timeout;
--- a/kernel/sched/swait.c
+++ b/kernel/sched/swait.c
-@@ -64,6 +64,7 @@ void swake_up_all(struct swait_queue_hea
+@@ -63,6 +63,7 @@ void swake_up_all(struct swait_queue_hea
struct swait_queue *curr;
LIST_HEAD(tmp);
diff --git a/patches/irq_poll-Use-raise_softirq_irqoff-in-cpu_dead-notifi.patch b/patches/irq_poll-Use-raise_softirq_irqoff-in-cpu_dead-notifi.patch
deleted file mode 100644
index 4d94fe3915e6..000000000000
--- a/patches/irq_poll-Use-raise_softirq_irqoff-in-cpu_dead-notifi.patch
+++ /dev/null
@@ -1,35 +0,0 @@
-From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
-Date: Thu, 2 Apr 2020 21:16:30 +0200
-Subject: [PATCH] irq_poll: Add local_bh_disable() in cpu_dead notifier
-
-__raise_softirq_irqoff() adds a bit to the pending sofirq mask and this
-is it. The softirq won't be handled in a deterministic way but randomly
-when an interrupt fires and handles the softirq in its irq_exit() routine or
-if something randomly checks and handles pending softirqs in the call
-chain before the CPU goes idle.
-
-Add a local_bh_disable/enable() around the IRQ-off section which will
-handle pending softirqs.
-
-Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
-Link: https://lore.kernel.org/all/YgJ%2FXWVxxWDVBBVA@linutronix.de
----
- lib/irq_poll.c | 2 ++
- 1 file changed, 2 insertions(+)
-
---- a/lib/irq_poll.c
-+++ b/lib/irq_poll.c
-@@ -191,11 +191,13 @@ static int irq_poll_cpu_dead(unsigned in
- * If a CPU goes away, splice its entries to the current CPU
- * and trigger a run of the softirq
- */
-+ local_bh_disable();
- local_irq_disable();
- list_splice_init(&per_cpu(blk_cpu_iopoll, cpu),
- this_cpu_ptr(&blk_cpu_iopoll));
- __raise_softirq_irqoff(IRQ_POLL_SOFTIRQ);
- local_irq_enable();
-+ local_bh_enable();
-
- return 0;
- }
diff --git a/patches/jump-label__disable_if_stop_machine_is_used.patch b/patches/jump-label__disable_if_stop_machine_is_used.patch
index 894c5d3538e4..b1e6f1ffaf4f 100644
--- a/patches/jump-label__disable_if_stop_machine_is_used.patch
+++ b/patches/jump-label__disable_if_stop_machine_is_used.patch
@@ -29,7 +29,7 @@ Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
-@@ -68,7 +68,7 @@ config ARM
+@@ -71,7 +71,7 @@ config ARM
select HARDIRQS_SW_RESEND
select HAVE_ARCH_AUDITSYSCALL if AEABI && !OABI_COMPAT
select HAVE_ARCH_BITREVERSE if (CPU_32v7M || CPU_32v7) && !CPU_32v6
diff --git a/patches/lib-irq_poll-Prevent-softirq-pending-leak-in-irq_pol.patch b/patches/lib-irq_poll-Prevent-softirq-pending-leak-in-irq_pol.patch
new file mode 100644
index 000000000000..08bf96b04bb2
--- /dev/null
+++ b/patches/lib-irq_poll-Prevent-softirq-pending-leak-in-irq_pol.patch
@@ -0,0 +1,49 @@
+From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Date: Sun, 10 Apr 2022 14:49:36 +0200
+Subject: [PATCH] lib/irq_poll: Prevent softirq pending leak in
+ irq_poll_cpu_dead()
+
+irq_poll_cpu_dead() pulls the blk_cpu_iopoll backlog from the dead CPU and
+raises the POLL softirq with __raise_softirq_irqoff() on the CPU it is
+running on. That just sets the bit in the pending softirq mask.
+
+This means the handling of the softirq is delayed until the next interrupt
+or a local_bh_disable/enable() pair. As a consequence the CPU on which this
+code runs can reach idle with the POLL softirq pending, which triggers a
+warning in the NOHZ idle code.
+
+Add a local_bh_disable/enable() pair around the interrupts disabled section
+in irq_poll_cpu_dead(). local_bh_enable will handle the pending softirq.
+
+[tglx: Massaged changelog and comment]
+
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Link: https://lore.kernel.org/r/87k0bxgl27.ffs@tglx
+---
+ lib/irq_poll.c | 8 ++++++--
+ 1 file changed, 6 insertions(+), 2 deletions(-)
+
+--- a/lib/irq_poll.c
++++ b/lib/irq_poll.c
+@@ -188,14 +188,18 @@ EXPORT_SYMBOL(irq_poll_init);
+ static int irq_poll_cpu_dead(unsigned int cpu)
+ {
+ /*
+- * If a CPU goes away, splice its entries to the current CPU
+- * and trigger a run of the softirq
++ * If a CPU goes away, splice its entries to the current CPU and
++ * set the POLL softirq bit. The local_bh_disable()/enable() pair
++ * ensures that it is handled. Otherwise the current CPU could
++ * reach idle with the POLL softirq pending.
+ */
++ local_bh_disable();
+ local_irq_disable();
+ list_splice_init(&per_cpu(blk_cpu_iopoll, cpu),
+ this_cpu_ptr(&blk_cpu_iopoll));
+ __raise_softirq_irqoff(IRQ_POLL_SOFTIRQ);
+ local_irq_enable();
++ local_bh_enable();
+
+ return 0;
+ }
diff --git a/patches/locking-Enable-RT_MUTEXES-by-default-on-PREEMPT_RT.patch b/patches/locking-Enable-RT_MUTEXES-by-default-on-PREEMPT_RT.patch
deleted file mode 100644
index d3b374583bc6..000000000000
--- a/patches/locking-Enable-RT_MUTEXES-by-default-on-PREEMPT_RT.patch
+++ /dev/null
@@ -1,27 +0,0 @@
-From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
-Date: Wed, 26 Jan 2022 15:31:20 +0100
-Subject: [PATCH] locking: Enable RT_MUTEXES by default on PREEMPT_RT.
-
-The CONFIG_RT_MUTEXES option is enabled by CONFIG_FUTEX and CONFIG_I2C.
-If both are disabled then CONFIG_PREEMPT_RT builds fail to compile.
-It is not possible to have a PREEMPT_RT kernel without RT_MUTEX support
-because RT_MUTEX based locking is always used.
-
-Enable CONFIG_RT_MUTEXES by default on PREEMPT_RT builds.
-
-Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
-Link: https://lkml.kernel.org/r/YgKmhjkcuqWXdUjQ@linutronix.de
----
- init/Kconfig | 1 +
- 1 file changed, 1 insertion(+)
-
---- a/init/Kconfig
-+++ b/init/Kconfig
-@@ -2058,6 +2058,7 @@ source "arch/Kconfig"
-
- config RT_MUTEXES
- bool
-+ default y if PREEMPT_RT
-
- config BASE_SMALL
- int
diff --git a/patches/locking-local_lock-Make-the-empty-local_lock_-functi.patch b/patches/locking-local_lock-Make-the-empty-local_lock_-functi.patch
deleted file mode 100644
index e13835bb9ea5..000000000000
--- a/patches/locking-local_lock-Make-the-empty-local_lock_-functi.patch
+++ /dev/null
@@ -1,41 +0,0 @@
-From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
-Date: Wed, 5 Jan 2022 10:53:55 +0100
-Subject: [PATCH] locking/local_lock: Make the empty local_lock_*() function a
- macro.
-
-It has been said that local_lock() does not add any overhead compared to
-preempt_disable() in a !LOCKDEP configuration. A micro benchmark showed
-an unexpected result which can be reduced to the fact that local_lock()
-was not entirely optimized away.
-In the !LOCKDEP configuration local_lock_acquire() is an empty static
-inline function. On x86 the this_cpu_ptr() argument of that function is
-fully evaluated leading to an additional mov+add instructions which are
-not needed and not used.
-
-Replace the static inline function with a macro. The typecheck() macro
-ensures that the argument is of proper type while the resulting
-disassembly shows no traces of this_cpu_ptr().
-
-Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
-Reviewed-by: Waiman Long <longman@redhat.com>
-Reviewed-by: Davidlohr Bueso <dbueso@suse.de>
-Link: https://lkml.kernel.org/r/YgKjciR60fZft2l4@linutronix.de
----
- include/linux/local_lock_internal.h | 6 +++---
- 1 file changed, 3 insertions(+), 3 deletions(-)
-
---- a/include/linux/local_lock_internal.h
-+++ b/include/linux/local_lock_internal.h
-@@ -44,9 +44,9 @@ static inline void local_lock_debug_init
- }
- #else /* CONFIG_DEBUG_LOCK_ALLOC */
- # define LOCAL_LOCK_DEBUG_INIT(lockname)
--static inline void local_lock_acquire(local_lock_t *l) { }
--static inline void local_lock_release(local_lock_t *l) { }
--static inline void local_lock_debug_init(local_lock_t *l) { }
-+# define local_lock_acquire(__ll) do { typecheck(local_lock_t *, __ll); } while (0)
-+# define local_lock_release(__ll) do { typecheck(local_lock_t *, __ll); } while (0)
-+# define local_lock_debug_init(__ll) do { typecheck(local_lock_t *, __ll); } while (0)
- #endif /* !CONFIG_DEBUG_LOCK_ALLOC */
-
- #define INIT_LOCAL_LOCK(lockname) { LOCAL_LOCK_DEBUG_INIT(lockname) }
diff --git a/patches/mm-memcg-Only-perform-the-debug-checks-on-PREEMPT_RT.patch b/patches/mm-memcg-Only-perform-the-debug-checks-on-PREEMPT_RT.patch
deleted file mode 100644
index d25583a8d142..000000000000
--- a/patches/mm-memcg-Only-perform-the-debug-checks-on-PREEMPT_RT.patch
+++ /dev/null
@@ -1,28 +0,0 @@
-From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
-Date: Fri, 25 Feb 2022 23:50:41 +0100
-Subject: [PATCH] mm/memcg: Only perform the debug checks on !PREEMPT_RT
-
-On PREEMPT_RT interrupts and preemption is always enabled. The locking
-function __memcg_stats_lock() always disabled preemptions. The recently
-added checks need to performed only on !PREEMPT_RT where preemption and
-disabled interrupts are used.
-
-Please fold into:
- "Protect per-CPU counter by disabling preemption on PREEMPT_RT"
-
-Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
----
- mm/memcontrol.c | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
---- a/mm/memcontrol.c
-+++ b/mm/memcontrol.c
-@@ -741,7 +741,7 @@ void __mod_memcg_lruvec_state(struct lru
- * interrupt context while other caller need to have disabled interrupt.
- */
- __memcg_stats_lock();
-- if (IS_ENABLED(CONFIG_DEBUG_VM)) {
-+ if (IS_ENABLED(CONFIG_DEBUG_VM) && !IS_ENABLED(CONFIG_PREEMPT_RT)) {
- switch (idx) {
- case NR_ANON_MAPPED:
- case NR_FILE_MAPPED:
diff --git a/patches/mm__workingset__replace_IRQ-off_check_with_a_lockdep_assert..patch b/patches/mm__workingset__replace_IRQ-off_check_with_a_lockdep_assert..patch
deleted file mode 100644
index d5712d8b1841..000000000000
--- a/patches/mm__workingset__replace_IRQ-off_check_with_a_lockdep_assert..patch
+++ /dev/null
@@ -1,45 +0,0 @@
-Subject: mm: workingset: replace IRQ-off check with a lockdep assert.
-From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
-Date: Mon Feb 11 10:40:46 2019 +0100
-
-From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
-
-Commit
-
- 68d48e6a2df57 ("mm: workingset: add vmstat counter for shadow nodes")
-
-introduced an IRQ-off check to ensure that a lock is held which also
-disabled interrupts. This does not work the same way on -RT because none
-of the locks, that are held, disable interrupts.
-Replace this check with a lockdep assert which ensures that the lock is
-held.
-
-Cc: Peter Zijlstra <peterz@infradead.org>
-Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
-Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
-Link: https://lkml.kernel.org/r/20190211113829.sqf6bdi4c4cdd3rp@linutronix.de
----
- mm/workingset.c | 5 ++++-
- 1 file changed, 4 insertions(+), 1 deletion(-)
----
---- a/mm/workingset.c
-+++ b/mm/workingset.c
-@@ -433,6 +433,8 @@ static struct list_lru shadow_nodes;
-
- void workingset_update_node(struct xa_node *node)
- {
-+ struct address_space *mapping;
-+
- /*
- * Track non-empty nodes that contain only shadow entries;
- * unlink those that contain pages or are being freed.
-@@ -441,7 +443,8 @@ void workingset_update_node(struct xa_no
- * already where they should be. The list_empty() test is safe
- * as node->private_list is protected by the i_pages lock.
- */
-- VM_WARN_ON_ONCE(!irqs_disabled()); /* For __inc_lruvec_page_state */
-+ mapping = container_of(node->array, struct address_space, i_pages);
-+ lockdep_assert_held(&mapping->i_pages.xa_lock);
-
- if (node->count && node->count == node->nr_values) {
- if (list_empty(&node->private_list)) {
diff --git a/patches/mm_vmalloc__Another_preempt_disable_region_which_sucks.patch b/patches/mm_vmalloc__Another_preempt_disable_region_which_sucks.patch
index e303949d2625..27f66c0a898d 100644
--- a/patches/mm_vmalloc__Another_preempt_disable_region_which_sucks.patch
+++ b/patches/mm_vmalloc__Another_preempt_disable_region_which_sucks.patch
@@ -14,7 +14,7 @@ Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
--- a/mm/vmalloc.c
+++ b/mm/vmalloc.c
-@@ -1924,11 +1924,12 @@ static void *new_vmap_block(unsigned int
+@@ -1938,11 +1938,12 @@ static void *new_vmap_block(unsigned int
return ERR_PTR(err);
}
@@ -29,7 +29,7 @@ Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
return vaddr;
}
-@@ -2007,7 +2008,8 @@ static void *vb_alloc(unsigned long size
+@@ -2021,7 +2022,8 @@ static void *vb_alloc(unsigned long size
order = get_order(size);
rcu_read_lock();
@@ -39,7 +39,7 @@ Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
list_for_each_entry_rcu(vb, &vbq->free, free_list) {
unsigned long pages_off;
-@@ -2030,7 +2032,7 @@ static void *vb_alloc(unsigned long size
+@@ -2044,7 +2046,7 @@ static void *vb_alloc(unsigned long size
break;
}
diff --git a/patches/net-Correct-wrong-BH-disable-in-hard-interrupt.patch b/patches/net-Correct-wrong-BH-disable-in-hard-interrupt.patch
deleted file mode 100644
index c0b6134950c6..000000000000
--- a/patches/net-Correct-wrong-BH-disable-in-hard-interrupt.patch
+++ /dev/null
@@ -1,62 +0,0 @@
-From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
-Date: Wed, 16 Feb 2022 18:50:46 +0100
-Subject: [PATCH] net: Correct wrong BH disable in hard-interrupt.
-
-I missed the obvious case where netif_ix() is invoked from hard-IRQ
-context.
-
-Disabling bottom halves is only needed in process context. This ensures
-that the code remains on the current CPU and that the soft-interrupts
-are processed at local_bh_enable() time.
-In hard- and soft-interrupt context this is already the case and the
-soft-interrupts will be processed once the context is left (at irq-exit
-time).
-
-Disable bottom halves if neither hard-interrupts nor soft-interrupts are
-disabled. Update the kernel-doc, mention that interrupts must be enabled
-if invoked from process context.
-
-Fixes: baebdf48c3600 ("net: dev: Makes sure netif_rx() can be invoked in any context.")
-Reported-by: Marek Szyprowski <m.szyprowski@samsung.com>
-Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
-Tested-by: Marek Szyprowski <m.szyprowski@samsung.com>
-Tested-by: Geert Uytterhoeven <geert@linux-m68k.org>
-Link: https://lore.kernel.org/r/Yg05duINKBqvnxUc@linutronix.de
-Signed-off-by: Jakub Kicinski <kuba@kernel.org>
-Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
----
- net/core/dev.c | 11 ++++++++---
- 1 file changed, 8 insertions(+), 3 deletions(-)
-
---- a/net/core/dev.c
-+++ b/net/core/dev.c
-@@ -4860,7 +4860,9 @@ EXPORT_SYMBOL(__netif_rx);
- * congestion control or by the protocol layers.
- * The network buffer is passed via the backlog NAPI device. Modern NIC
- * driver should use NAPI and GRO.
-- * This function can used from any context.
-+ * This function can used from interrupt and from process context. The
-+ * caller from process context must not disable interrupts before invoking
-+ * this function.
- *
- * return values:
- * NET_RX_SUCCESS (no congestion)
-@@ -4869,13 +4871,16 @@ EXPORT_SYMBOL(__netif_rx);
- */
- int netif_rx(struct sk_buff *skb)
- {
-+ bool need_bh_off = !(hardirq_count() | softirq_count());
- int ret;
-
-- local_bh_disable();
-+ if (need_bh_off)
-+ local_bh_disable();
- trace_netif_rx_entry(skb);
- ret = netif_rx_internal(skb);
- trace_netif_rx_exit(ret);
-- local_bh_enable();
-+ if (need_bh_off)
-+ local_bh_enable();
- return ret;
- }
- EXPORT_SYMBOL(netif_rx);
diff --git a/patches/net-Use-this_cpu_inc-to-increment-net-core_stats.patch b/patches/net-Use-this_cpu_inc-to-increment-net-core_stats.patch
new file mode 100644
index 000000000000..43c8c67f9679
--- /dev/null
+++ b/patches/net-Use-this_cpu_inc-to-increment-net-core_stats.patch
@@ -0,0 +1,132 @@
+From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Date: Thu, 21 Apr 2022 13:20:32 +0200
+Subject: [PATCH] net: Use this_cpu_inc() to increment net->core_stats
+
+The macro dev_core_stats_##FIELD##_inc() disables preemption and invokes
+netdev_core_stats_alloc() to return a per-CPU pointer.
+netdev_core_stats_alloc() will allocate memory on its first invocation
+which breaks on PREEMPT_RT because it requires non-atomic context for
+memory allocation.
+
+This can be avoided by enabling preemption in netdev_core_stats_alloc()
+assuming the caller always disables preemption.
+
+It might be better to replace local_inc() with this_cpu_inc() now that
+dev_core_stats_##FIELD##_inc() gained a preempt-disable section and does
+not rely on already disabled preemption. This results in less
+instructions on x86-64:
+local_inc:
+| incl %gs:__preempt_count(%rip) # __preempt_count
+| movq 488(%rdi), %rax # _1->core_stats, _22
+| testq %rax, %rax # _22
+| je .L585 #,
+| add %gs:this_cpu_off(%rip), %rax # this_cpu_off, tcp_ptr__
+| .L586:
+| testq %rax, %rax # _27
+| je .L587 #,
+| incq (%rax) # _6->a.counter
+| .L587:
+| decl %gs:__preempt_count(%rip) # __preempt_count
+
+this_cpu_inc(), this patch:
+| movq 488(%rdi), %rax # _1->core_stats, _5
+| testq %rax, %rax # _5
+| je .L591 #,
+| .L585:
+| incq %gs:(%rax) # _18->rx_dropped
+
+Use unsigned long as type for the counter. Use this_cpu_inc() to
+increment the counter. Use a plain read of the counter.
+
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+---
+ include/linux/netdevice.h | 17 +++++++----------
+ net/core/dev.c | 14 +++++---------
+ 2 files changed, 12 insertions(+), 19 deletions(-)
+
+--- a/include/linux/netdevice.h
++++ b/include/linux/netdevice.h
+@@ -199,10 +199,10 @@ struct net_device_stats {
+ * Try to fit them in a single cache line, for dev_get_stats() sake.
+ */
+ struct net_device_core_stats {
+- local_t rx_dropped;
+- local_t tx_dropped;
+- local_t rx_nohandler;
+-} __aligned(4 * sizeof(local_t));
++ unsigned long rx_dropped;
++ unsigned long tx_dropped;
++ unsigned long rx_nohandler;
++} __aligned(4 * sizeof(unsigned long));
+
+ #include <linux/cache.h>
+ #include <linux/skbuff.h>
+@@ -3843,7 +3843,7 @@ static __always_inline bool __is_skb_for
+ return false;
+ }
+
+-struct net_device_core_stats *netdev_core_stats_alloc(struct net_device *dev);
++struct net_device_core_stats __percpu *netdev_core_stats_alloc(struct net_device *dev);
+
+ static inline struct net_device_core_stats *dev_core_stats(struct net_device *dev)
+ {
+@@ -3851,7 +3851,7 @@ static inline struct net_device_core_sta
+ struct net_device_core_stats __percpu *p = READ_ONCE(dev->core_stats);
+
+ if (likely(p))
+- return this_cpu_ptr(p);
++ return p;
+
+ return netdev_core_stats_alloc(dev);
+ }
+@@ -3861,12 +3861,9 @@ static inline void dev_core_stats_##FIEL
+ { \
+ struct net_device_core_stats *p; \
+ \
+- preempt_disable(); \
+ p = dev_core_stats(dev); \
+- \
+ if (p) \
+- local_inc(&p->FIELD); \
+- preempt_enable(); \
++ this_cpu_inc(p->FIELD); \
+ }
+ DEV_CORE_STATS_INC(rx_dropped)
+ DEV_CORE_STATS_INC(tx_dropped)
+--- a/net/core/dev.c
++++ b/net/core/dev.c
+@@ -10304,7 +10304,7 @@ void netdev_stats_to_stats64(struct rtnl
+ }
+ EXPORT_SYMBOL(netdev_stats_to_stats64);
+
+-struct net_device_core_stats *netdev_core_stats_alloc(struct net_device *dev)
++struct net_device_core_stats __percpu *netdev_core_stats_alloc(struct net_device *dev)
+ {
+ struct net_device_core_stats __percpu *p;
+
+@@ -10315,11 +10315,7 @@ struct net_device_core_stats *netdev_cor
+ free_percpu(p);
+
+ /* This READ_ONCE() pairs with the cmpxchg() above */
+- p = READ_ONCE(dev->core_stats);
+- if (!p)
+- return NULL;
+-
+- return this_cpu_ptr(p);
++ return READ_ONCE(dev->core_stats);
+ }
+ EXPORT_SYMBOL(netdev_core_stats_alloc);
+
+@@ -10356,9 +10352,9 @@ struct rtnl_link_stats64 *dev_get_stats(
+
+ for_each_possible_cpu(i) {
+ core_stats = per_cpu_ptr(p, i);
+- storage->rx_dropped += local_read(&core_stats->rx_dropped);
+- storage->tx_dropped += local_read(&core_stats->tx_dropped);
+- storage->rx_nohandler += local_read(&core_stats->rx_nohandler);
++ storage->rx_dropped += core_stats->rx_dropped;
++ storage->tx_dropped += core_stats->tx_dropped;
++ storage->rx_nohandler += core_stats->rx_nohandler;
+ }
+ }
+ return storage;
diff --git a/patches/powerpc__Add_support_for_lazy_preemption.patch b/patches/powerpc__Add_support_for_lazy_preemption.patch
index 30e15bde0cf4..50b7a014196f 100644
--- a/patches/powerpc__Add_support_for_lazy_preemption.patch
+++ b/patches/powerpc__Add_support_for_lazy_preemption.patch
@@ -17,7 +17,7 @@ Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
-@@ -229,6 +229,7 @@ config PPC
+@@ -236,6 +236,7 @@ config PPC
select HAVE_PERF_EVENTS_NMI if PPC64
select HAVE_PERF_REGS
select HAVE_PERF_USER_STACK_DUMP
@@ -83,7 +83,7 @@ Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
/* Don't move TLF_NAPPING without adjusting the code in entry_32.S */
--- a/arch/powerpc/kernel/interrupt.c
+++ b/arch/powerpc/kernel/interrupt.c
-@@ -346,7 +346,7 @@ interrupt_exit_user_prepare_main(unsigne
+@@ -345,7 +345,7 @@ interrupt_exit_user_prepare_main(unsigne
ti_flags = read_thread_flags();
while (unlikely(ti_flags & (_TIF_USER_WORK_MASK & ~_TIF_RESTORE_TM))) {
local_irq_enable();
@@ -92,7 +92,7 @@ Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
schedule();
} else {
/*
-@@ -550,11 +550,15 @@ notrace unsigned long interrupt_exit_ker
+@@ -549,11 +549,15 @@ notrace unsigned long interrupt_exit_ker
/* Returning to a kernel context with local irqs enabled. */
WARN_ON_ONCE(!(regs->msr & MSR_EE));
again:
diff --git a/patches/powerpc_kvm__Disable_in-kernel_MPIC_emulation_for_PREEMPT_RT.patch b/patches/powerpc_kvm__Disable_in-kernel_MPIC_emulation_for_PREEMPT_RT.patch
index 6d52dda6a7bb..7574b97de0d0 100644
--- a/patches/powerpc_kvm__Disable_in-kernel_MPIC_emulation_for_PREEMPT_RT.patch
+++ b/patches/powerpc_kvm__Disable_in-kernel_MPIC_emulation_for_PREEMPT_RT.patch
@@ -32,7 +32,7 @@ Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
--- a/arch/powerpc/kvm/Kconfig
+++ b/arch/powerpc/kvm/Kconfig
-@@ -195,6 +195,7 @@ config KVM_E500MC
+@@ -204,6 +204,7 @@ config KVM_E500MC
config KVM_MPIC
bool "KVM in-kernel MPIC emulation"
depends on KVM && E500
diff --git a/patches/printk-defer_console_output-use-atomic-update.patch b/patches/printk-defer_console_output-use-atomic-update.patch
deleted file mode 100644
index af1f8e1250d2..000000000000
--- a/patches/printk-defer_console_output-use-atomic-update.patch
+++ /dev/null
@@ -1,50 +0,0 @@
-From: John Ogness <john.ogness@linutronix.de>
-Date: Mon, 7 Feb 2022 10:52:20 +0106
-Subject: [PATCH] printk: defer_console_output: use atomic update
-
-The per-cpu @printk_pending variable can be updated from
-sleepable contexts, such as:
-
- get_random_bytes()
- warn_unseeded_randomness()
- printk_deferred()
- defer_console_output()
-
-and can be updated from interrupt contexts, such as:
-
- handle_irq_event_percpu()
- __irq_wake_thread()
- wake_up_process()
- try_to_wake_up()
- select_task_rq()
- select_fallback_rq()
- printk_deferred()
- defer_console_output()
-
-and can be updated from NMI contexts, such as:
-
- vprintk()
- if (in_nmi()) defer_console_output()
-
-Therefore this_cpu_or(), the atomic variant of __this_cpu_or(),
-should be used to update the variable.
-
-Reported-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
-Reviewed-by: Sergey Senozhatsky <senozhatsky@chromium.org>
-Signed-off-by: John Ogness <john.ogness@linutronix.de>
-Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
----
- kernel/printk/printk.c | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
---- a/kernel/printk/printk.c
-+++ b/kernel/printk/printk.c
-@@ -3262,7 +3262,7 @@ void defer_console_output(void)
- return;
-
- preempt_disable();
-- __this_cpu_or(printk_pending, PRINTK_PENDING_OUTPUT);
-+ this_cpu_or(printk_pending, PRINTK_PENDING_OUTPUT);
- irq_work_queue(this_cpu_ptr(&wake_up_klogd_work));
- preempt_enable();
- }
diff --git a/patches/ptrace-fix-ptrace-vs-tasklist_lock-race-on-PREEMPT_R.patch b/patches/ptrace-fix-ptrace-vs-tasklist_lock-race-on-PREEMPT_R.patch
index 6dc5ace22489..16f6dbca472b 100644
--- a/patches/ptrace-fix-ptrace-vs-tasklist_lock-race-on-PREEMPT_R.patch
+++ b/patches/ptrace-fix-ptrace-vs-tasklist_lock-race-on-PREEMPT_R.patch
@@ -55,7 +55,7 @@ Link: https://lore.kernel.org/r/YkW55u6u2fo5QmV7@linutronix.de
/*
* Special states are those that do not use the normal wait-loop pattern. See
* the comment with set_special_state().
-@@ -2009,6 +2005,130 @@ static inline int test_tsk_need_resched(
+@@ -2027,6 +2023,130 @@ static inline int test_tsk_need_resched(
return unlikely(test_tsk_thread_flag(tsk,TIF_NEED_RESCHED));
}
@@ -236,7 +236,7 @@ Link: https://lore.kernel.org/r/YkW55u6u2fo5QmV7@linutronix.de
--- a/kernel/sched/core.c
+++ b/kernel/sched/core.c
-@@ -3219,6 +3219,8 @@ unsigned long wait_task_inactive(struct
+@@ -3287,6 +3287,8 @@ unsigned long wait_task_inactive(struct
struct rq *rq;
for (;;) {
@@ -245,7 +245,7 @@ Link: https://lore.kernel.org/r/YkW55u6u2fo5QmV7@linutronix.de
/*
* We do the initial early heuristics without holding
* any task-queue locks at all. We'll only try to get
-@@ -3239,7 +3241,8 @@ unsigned long wait_task_inactive(struct
+@@ -3307,7 +3309,8 @@ unsigned long wait_task_inactive(struct
* is actually now running somewhere else!
*/
while (task_running(rq, p)) {
@@ -255,7 +255,7 @@ Link: https://lore.kernel.org/r/YkW55u6u2fo5QmV7@linutronix.de
return 0;
cpu_relax();
}
-@@ -3254,7 +3257,9 @@ unsigned long wait_task_inactive(struct
+@@ -3322,7 +3325,9 @@ unsigned long wait_task_inactive(struct
running = task_running(rq, p);
queued = task_on_rq_queued(p);
ncsw = 0;
@@ -266,7 +266,7 @@ Link: https://lore.kernel.org/r/YkW55u6u2fo5QmV7@linutronix.de
ncsw = p->nvcsw | LONG_MIN; /* sets MSB */
task_rq_unlock(rq, p, &rf);
-@@ -3284,7 +3289,7 @@ unsigned long wait_task_inactive(struct
+@@ -3352,7 +3357,7 @@ unsigned long wait_task_inactive(struct
* running right now), it's preempted, and we should
* yield - it could be a while.
*/
diff --git a/patches/random-Move-crng_fast_load-to-the-worker.patch b/patches/random-Move-crng_fast_load-to-the-worker.patch
deleted file mode 100644
index a6629fd6393c..000000000000
--- a/patches/random-Move-crng_fast_load-to-the-worker.patch
+++ /dev/null
@@ -1,72 +0,0 @@
-From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
-Date: Thu, 10 Feb 2022 18:22:05 +0100
-Subject: [PATCH] random: Move crng_fast_load() to the worker.
-
-crng_fast_load() is invoked from hard IRQ context and acquires a
-spinlock_t via a trylock. If the lock is locked in hard IRQ context then
-the following locking attempt (on another CPU) will PI-boost the wrong
-task.
-
-Move the crng_fast_load() invocation into the worker.
-
-Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
----
- drivers/char/random.c | 33 ++++++++++++++++++++++++++-------
- 1 file changed, 26 insertions(+), 7 deletions(-)
-
---- a/drivers/char/random.c
-+++ b/drivers/char/random.c
-@@ -707,8 +707,7 @@ static size_t crng_fast_load(const u8 *c
- u8 *p;
- size_t ret = 0;
-
-- if (!spin_trylock_irqsave(&primary_crng.lock, flags))
-- return 0;
-+ spin_lock_irqsave(&primary_crng.lock, flags);
- if (crng_init != 0) {
- spin_unlock_irqrestore(&primary_crng.lock, flags);
- return 0;
-@@ -1086,6 +1085,19 @@ static void mix_interrupt_randomness(str
- fast_pool->last = jiffies;
- local_irq_enable();
-
-+ if (unlikely(crng_init == 0)) {
-+ size_t ret;
-+
-+ ret = crng_fast_load((u8 *)fast_pool->pool, sizeof(fast_pool->pool));
-+ if (ret) {
-+ local_irq_disable();
-+ WRITE_ONCE(fast_pool->count, 0);
-+ fast_pool->last = jiffies;
-+ local_irq_enable();
-+ return;
-+ }
-+ }
-+
- mix_pool_bytes(pool, sizeof(pool));
- credit_entropy_bits(1);
- memzero_explicit(pool, sizeof(pool));
-@@ -1119,11 +1131,18 @@ void add_interrupt_randomness(int irq)
- add_interrupt_bench(cycles);
-
- if (unlikely(crng_init == 0)) {
-- if ((new_count >= 64) &&
-- crng_fast_load((u8 *)fast_pool->pool, sizeof(fast_pool->pool)) > 0) {
-- fast_pool->count = 0;
-- fast_pool->last = now;
-- }
-+ if (new_count & MIX_INFLIGHT)
-+ return;
-+
-+ if (new_count < 64)
-+ return;
-+
-+ if (unlikely(!fast_pool->mix.func))
-+ INIT_WORK(&fast_pool->mix, mix_interrupt_randomness);
-+
-+ fast_pool->count |= MIX_INFLIGHT;
-+ queue_work_on(raw_smp_processor_id(), system_highpri_wq, &fast_pool->mix);
-+
- return;
- }
-
diff --git a/patches/sched__Add_support_for_lazy_preemption.patch b/patches/sched__Add_support_for_lazy_preemption.patch
index 03fda81885f9..4ae70ed48047 100644
--- a/patches/sched__Add_support_for_lazy_preemption.patch
+++ b/patches/sched__Add_support_for_lazy_preemption.patch
@@ -57,18 +57,18 @@ Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
include/linux/preempt.h | 54 +++++++++++++++++++++++++++--
- include/linux/sched.h | 37 +++++++++++++++++++
+ include/linux/sched.h | 37 ++++++++++++++++++++
include/linux/thread_info.h | 12 +++++-
include/linux/trace_events.h | 10 ++++-
kernel/Kconfig.preempt | 6 +++
- kernel/sched/core.c | 80 +++++++++++++++++++++++++++++++++++++++++--
+ kernel/sched/core.c | 79 ++++++++++++++++++++++++++++++++++++++++++-
kernel/sched/fair.c | 16 ++++----
kernel/sched/features.h | 3 +
kernel/sched/sched.h | 9 ++++
- kernel/trace/trace.c | 50 ++++++++++++++++----------
+ kernel/trace/trace.c | 50 ++++++++++++++++-----------
kernel/trace/trace_events.c | 1
kernel/trace/trace_output.c | 18 ++++++++-
- 12 files changed, 260 insertions(+), 36 deletions(-)
+ 12 files changed, 260 insertions(+), 35 deletions(-)
---
--- a/include/linux/preempt.h
+++ b/include/linux/preempt.h
@@ -177,7 +177,7 @@ Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
-@@ -2005,6 +2005,43 @@ static inline int test_tsk_need_resched(
+@@ -2023,6 +2023,43 @@ static inline int test_tsk_need_resched(
return unlikely(test_tsk_thread_flag(tsk,TIF_NEED_RESCHED));
}
@@ -244,7 +244,7 @@ Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
static inline int arch_within_stack_frames(const void * const stack,
--- a/include/linux/trace_events.h
+++ b/include/linux/trace_events.h
-@@ -69,6 +69,7 @@ struct trace_entry {
+@@ -70,6 +70,7 @@ struct trace_entry {
unsigned char flags;
unsigned char preempt_count;
int pid;
@@ -252,7 +252,7 @@ Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
};
#define TRACE_EVENT_TYPE_MAX \
-@@ -157,9 +158,10 @@ static inline void tracing_generic_entry
+@@ -158,9 +159,10 @@ static inline void tracing_generic_entry
unsigned int trace_ctx)
{
entry->preempt_count = trace_ctx & 0xff;
@@ -264,7 +264,7 @@ Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
}
unsigned int tracing_gen_ctx_irq_test(unsigned int irqs_status);
-@@ -170,7 +172,13 @@ enum trace_flag_type {
+@@ -171,7 +173,13 @@ enum trace_flag_type {
TRACE_FLAG_NEED_RESCHED = 0x04,
TRACE_FLAG_HARDIRQ = 0x08,
TRACE_FLAG_SOFTIRQ = 0x10,
@@ -294,7 +294,7 @@ Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
--- a/kernel/sched/core.c
+++ b/kernel/sched/core.c
-@@ -997,6 +997,46 @@ void resched_curr(struct rq *rq)
+@@ -1065,6 +1065,46 @@ void resched_curr(struct rq *rq)
trace_sched_wake_idle_without_ipi(cpu);
}
@@ -341,7 +341,7 @@ Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
void resched_cpu(int cpu)
{
struct rq *rq = cpu_rq(cpu);
-@@ -2171,6 +2211,7 @@ void migrate_disable(void)
+@@ -2239,6 +2279,7 @@ void migrate_disable(void)
preempt_disable();
this_rq()->nr_pinned++;
p->migration_disabled = 1;
@@ -349,7 +349,7 @@ Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
preempt_enable();
}
EXPORT_SYMBOL_GPL(migrate_disable);
-@@ -2202,6 +2243,7 @@ void migrate_enable(void)
+@@ -2270,6 +2311,7 @@ void migrate_enable(void)
barrier();
p->migration_disabled = 0;
this_rq()->nr_pinned--;
@@ -357,7 +357,7 @@ Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
preempt_enable();
}
EXPORT_SYMBOL_GPL(migrate_enable);
-@@ -4434,6 +4476,9 @@ int sched_fork(unsigned long clone_flags
+@@ -4519,6 +4561,9 @@ int sched_fork(unsigned long clone_flags
p->on_cpu = 0;
#endif
init_task_preempt_count(p);
@@ -367,7 +367,7 @@ Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
#ifdef CONFIG_SMP
plist_node_init(&p->pushable_tasks, MAX_PRIO);
RB_CLEAR_NODE(&p->pushable_dl_tasks);
-@@ -6268,6 +6313,7 @@ static void __sched notrace __schedule(u
+@@ -6359,6 +6404,7 @@ static void __sched notrace __schedule(u
next = pick_next_task(rq, prev, &rf);
clear_tsk_need_resched(prev);
@@ -375,7 +375,7 @@ Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
clear_preempt_need_resched();
#ifdef CONFIG_SCHED_DEBUG
rq->last_seen_need_resched_ns = 0;
-@@ -6479,6 +6525,30 @@ static void __sched notrace preempt_sche
+@@ -6569,6 +6615,30 @@ static void __sched notrace preempt_sche
} while (need_resched());
}
@@ -406,17 +406,16 @@ Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
#ifdef CONFIG_PREEMPTION
/*
* This is the entry point to schedule() from in-kernel preemption
-@@ -6492,7 +6562,8 @@ asmlinkage __visible void __sched notrac
+@@ -6582,6 +6652,8 @@ asmlinkage __visible void __sched notrac
*/
if (likely(!preemptible()))
return;
--
+ if (!preemptible_lazy())
+ return;
preempt_schedule_common();
}
NOKPROBE_SYMBOL(preempt_schedule);
-@@ -6525,6 +6596,9 @@ asmlinkage __visible void __sched notrac
+@@ -6629,6 +6701,9 @@ asmlinkage __visible void __sched notrac
if (likely(!preemptible()))
return;
@@ -426,7 +425,7 @@ Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
do {
/*
* Because the function tracer can trace preempt_count_sub()
-@@ -8691,7 +8765,9 @@ void __init init_idle(struct task_struct
+@@ -8845,7 +8920,9 @@ void __init init_idle(struct task_struct
/* Set the preempt count _outside_ the spinlocks! */
init_idle_preempt_count(idle, cpu);
@@ -439,7 +438,7 @@ Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
*/
--- a/kernel/sched/fair.c
+++ b/kernel/sched/fair.c
-@@ -4427,7 +4427,7 @@ check_preempt_tick(struct cfs_rq *cfs_rq
+@@ -4481,7 +4481,7 @@ check_preempt_tick(struct cfs_rq *cfs_rq
ideal_runtime = sched_slice(cfs_rq, curr);
delta_exec = curr->sum_exec_runtime - curr->prev_sum_exec_runtime;
if (delta_exec > ideal_runtime) {
@@ -448,7 +447,7 @@ Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
/*
* The current task ran long enough, ensure it doesn't get
* re-elected due to buddy favours.
-@@ -4451,7 +4451,7 @@ check_preempt_tick(struct cfs_rq *cfs_rq
+@@ -4505,7 +4505,7 @@ check_preempt_tick(struct cfs_rq *cfs_rq
return;
if (delta > ideal_runtime)
@@ -457,7 +456,7 @@ Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
}
static void
-@@ -4597,7 +4597,7 @@ entity_tick(struct cfs_rq *cfs_rq, struc
+@@ -4651,7 +4651,7 @@ entity_tick(struct cfs_rq *cfs_rq, struc
* validating it and just reschedule.
*/
if (queued) {
@@ -466,7 +465,7 @@ Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
return;
}
/*
-@@ -4746,7 +4746,7 @@ static void __account_cfs_rq_runtime(str
+@@ -4800,7 +4800,7 @@ static void __account_cfs_rq_runtime(str
* hierarchy can be throttled
*/
if (!assign_cfs_rq_runtime(cfs_rq) && likely(cfs_rq->curr))
@@ -475,7 +474,7 @@ Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
}
static __always_inline
-@@ -5509,7 +5509,7 @@ static void hrtick_start_fair(struct rq
+@@ -5563,7 +5563,7 @@ static void hrtick_start_fair(struct rq
if (delta < 0) {
if (task_current(rq, p))
@@ -484,7 +483,7 @@ Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
return;
}
hrtick_start(rq, delta);
-@@ -7159,7 +7159,7 @@ static void check_preempt_wakeup(struct
+@@ -7213,7 +7213,7 @@ static void check_preempt_wakeup(struct
return;
preempt:
@@ -493,7 +492,7 @@ Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
/*
* Only set the backward buddy when the current task is still
* on the rq. This can happen when a wakeup gets interleaved
-@@ -11196,7 +11196,7 @@ static void task_fork_fair(struct task_s
+@@ -11251,7 +11251,7 @@ static void task_fork_fair(struct task_s
* 'current' within the tree based on its new key value.
*/
swap(curr->vruntime, se->vruntime);
@@ -502,7 +501,7 @@ Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
}
se->vruntime -= cfs_rq->min_vruntime;
-@@ -11223,7 +11223,7 @@ prio_changed_fair(struct rq *rq, struct
+@@ -11278,7 +11278,7 @@ prio_changed_fair(struct rq *rq, struct
*/
if (task_current(rq, p)) {
if (p->prio > oldprio)
@@ -525,7 +524,7 @@ Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
/*
--- a/kernel/sched/sched.h
+++ b/kernel/sched/sched.h
-@@ -2328,6 +2328,15 @@ extern void reweight_task(struct task_st
+@@ -2302,6 +2302,15 @@ extern void reweight_task(struct task_st
extern void resched_curr(struct rq *rq);
extern void resched_cpu(int cpu);
@@ -540,10 +539,10 @@ Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+
extern struct rt_bandwidth def_rt_bandwidth;
extern void init_rt_bandwidth(struct rt_bandwidth *rt_b, u64 period, u64 runtime);
-
+ extern bool sched_rt_bandwidth_account(struct rt_rq *rt_rq);
--- a/kernel/trace/trace.c
+++ b/kernel/trace/trace.c
-@@ -2612,11 +2612,19 @@ unsigned int tracing_gen_ctx_irq_test(un
+@@ -2622,11 +2622,19 @@ unsigned int tracing_gen_ctx_irq_test(un
if (softirq_count() >> (SOFTIRQ_SHIFT + 1))
trace_flags |= TRACE_FLAG_BH_OFF;
@@ -565,7 +564,7 @@ Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
(min_t(unsigned int, migration_disable_value(), 0xf)) << 4;
}
-@@ -4197,15 +4205,17 @@ unsigned long trace_total_entries(struct
+@@ -4212,15 +4220,17 @@ unsigned long trace_total_entries(struct
static void print_lat_help_header(struct seq_file *m)
{
@@ -592,7 +591,7 @@ Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
}
static void print_event_info(struct array_buffer *buf, struct seq_file *m)
-@@ -4239,14 +4249,16 @@ static void print_func_help_header_irq(s
+@@ -4254,14 +4264,16 @@ static void print_func_help_header_irq(s
print_event_info(buf, m);
@@ -619,7 +618,7 @@ Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
void
--- a/kernel/trace/trace_events.c
+++ b/kernel/trace/trace_events.c
-@@ -184,6 +184,7 @@ static int trace_define_common_fields(vo
+@@ -192,6 +192,7 @@ static int trace_define_common_fields(vo
/* Holds both preempt_count and migrate_disable */
__common_field(unsigned char, preempt_count);
__common_field(int, pid);
diff --git a/patches/scsi_fcoe__Make_RT_aware..patch b/patches/scsi_fcoe__Make_RT_aware..patch
index d9a53ac77c5d..3d310be4aa97 100644
--- a/patches/scsi_fcoe__Make_RT_aware..patch
+++ b/patches/scsi_fcoe__Make_RT_aware..patch
@@ -18,7 +18,7 @@ Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
--- a/drivers/scsi/fcoe/fcoe.c
+++ b/drivers/scsi/fcoe/fcoe.c
-@@ -1450,11 +1450,11 @@ static int fcoe_rcv(struct sk_buff *skb,
+@@ -1451,11 +1451,11 @@ static int fcoe_rcv(struct sk_buff *skb,
static int fcoe_alloc_paged_crc_eof(struct sk_buff *skb, int tlen)
{
struct fcoe_percpu_s *fps;
@@ -33,7 +33,7 @@ Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
return rc;
}
-@@ -1639,11 +1639,11 @@ static inline int fcoe_filter_frames(str
+@@ -1640,11 +1640,11 @@ static inline int fcoe_filter_frames(str
return 0;
}
@@ -47,7 +47,7 @@ Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
return -EINVAL;
}
-@@ -1684,7 +1684,7 @@ static void fcoe_recv_frame(struct sk_bu
+@@ -1685,7 +1685,7 @@ static void fcoe_recv_frame(struct sk_bu
*/
hp = (struct fcoe_hdr *) skb_network_header(skb);
@@ -56,7 +56,7 @@ Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
if (unlikely(FC_FCOE_DECAPS_VER(hp) != FC_FCOE_VER)) {
if (stats->ErrorFrames < 5)
printk(KERN_WARNING "fcoe: FCoE version "
-@@ -1716,13 +1716,13 @@ static void fcoe_recv_frame(struct sk_bu
+@@ -1717,13 +1717,13 @@ static void fcoe_recv_frame(struct sk_bu
goto drop;
if (!fcoe_filter_frames(lport, fp)) {
diff --git a/patches/series b/patches/series
index 0220b2fadf6b..00fe288c17ad 100644
--- a/patches/series
+++ b/patches/series
@@ -3,98 +3,46 @@
###########################################################################
# John's printk queue
###########################################################################
-printk-defer_console_output-use-atomic-update.patch
0001-printk-rename-cpulock-functions.patch
0002-printk-cpu-sync-always-disable-interrupts.patch
-0003-printk-use-percpu-flag-instead-of-cpu_online.patch
-0004-printk-get-caller_id-timestamp-after-migration-disab.patch
-0005-printk-call-boot_delay_msec-in-printk_delay.patch
-0006-printk-refactor-and-rework-printing-logic.patch
-0007-printk-move-buffer-definitions-into-console_emit_nex.patch
-0008-printk-add-pr_flush.patch
-0009-printk-add-functions-to-allow-direct-printing.patch
-0010-printk-add-kthread-console-printers.patch
-0011-printk-reimplement-console_lock-for-proper-kthread-s.patch
-0012-printk-remove-console_locked.patch
-0013-console-introduce-CON_MIGHT_SLEEP-for-vt.patch
-0014-printk-add-infrastucture-for-atomic-consoles.patch
-0015-serial-8250-implement-write_atomic.patch
-0016-printk-avoid-preempt_disable-for-PREEMPT_RT.patch
+0003-printk-add-missing-memory-barrier-to-wake_up_klogd.patch
+0004-printk-wake-up-all-waiters.patch
+0005-printk-wake-waiters-for-safe-and-NMI-contexts.patch
+0006-printk-get-caller_id-timestamp-after-migration-disab.patch
+0007-printk-call-boot_delay_msec-in-printk_delay.patch
+0008-printk-add-con_printk-macro-for-console-details.patch
+0009-printk-refactor-and-rework-printing-logic.patch
+0010-printk-move-buffer-definitions-into-console_emit_nex.patch
+0011-printk-add-pr_flush.patch
+0012-printk-add-functions-to-prefer-direct-printing.patch
+0013-printk-add-kthread-console-printers.patch
+0014-printk-extend-console_lock-for-proper-kthread-suppor.patch
+0015-printk-remove-console_locked.patch
+#
+0001-printk-add-infrastucture-for-atomic-consoles.patch
+0002-serial-8250-implement-write_atomic.patch
+0003-printk-avoid-preempt_disable-for-PREEMPT_RT.patch
###########################################################################
# Posted and applied
###########################################################################
-# Slipped, waiting for 5.18
-fs-namespace-Boost-the-mount_lock.lock-owner-instead.patch
# in -tip or traveling to -tip.
-locking-local_lock-Make-the-empty-local_lock_-functi.patch
-locking-Enable-RT_MUTEXES-by-default-on-PREEMPT_RT.patch
-irq_poll-Use-raise_softirq_irqoff-in-cpu_dead-notifi.patch
-smp_wake_ksoftirqd_on_preempt_rt_instead_do_softirq.patch
+lib-irq_poll-Prevent-softirq-pending-leak-in-irq_pol.patch
signal_x86__Delay_calling_signals_in_atomic.patch
-# misc
-drm-i915-Depend-on-PREEMPT_RT.patch
-cgroup__use_irqsave_in_cgroup_rstat_flush_locked.patch
-mm__workingset__replace_IRQ-off_check_with_a_lockdep_assert..patch
-
-# Random, backports from git.kernel.org/pub/scm/linux/kernel/git/crng/random.git
-# stashed for 5.18
-0001-random-use-computational-hash-for-entropy-extraction.patch
-0002-random-remove-batched-entropy-locking.patch
-0003-random-fix-locking-in-crng_fast_load.patch
-0004-random-defer-fast-pool-mixing-to-worker.patch
-0005-random-clear-fast-pool-crng-and-batches-in-cpuhp-bri.patch
-# Minimal duct tape for the v5.17. Jason has
-# "random: do crng pre-init loading in worker rather than irq"
-# queued.
-random-Move-crng_fast_load-to-the-worker.patch
-
-# sched/fork, expecting in 5.18
-tcp-Don-t-acquire-inet_listen_hashbucket-lock-with-d.patch
-0001-kernel-fork-Redo-ifdefs-around-task-s-handling.patch
-0002-kernel-fork-Duplicate-task_struct-before-stack-alloc.patch
-0003-kernel-fork-IA64-Provide-a-alloc_thread_stack_node-f.patch
-0004-kernel-fork-Don-t-assign-the-stack-pointer-in-dup_ta.patch
-0005-kernel-fork-Move-memcg_charge_kernel_stack-into-CONF.patch
-0006-kernel-fork-Move-task-stack-account-to-do_exit.patch
-0007-kernel-fork-Only-cache-the-VMAP-stack-in-finish_task.patch
-0008-kernel-fork-Use-IS_ENABLED-in-account_kernel_stack.patch
-
-# In net-next
-0001-net-dev-Remove-preempt_disable-and-get_cpu-in-netif_.patch
-0002-net-dev-Make-rps_lock-disable-interrupts.patch
-0003-net-dev-Makes-sure-netif_rx-can-be-invoked-in-any-co.patch
-net-Correct-wrong-BH-disable-in-hard-interrupt.patch
-
-# These genirq should arrive in 5.18 on way or another.
-0001-genirq-Provide-generic_handle_irq_safe.patch
-0002-i2c-core-Use-generic_handle_irq_safe-in-i2c_handle_s.patch
-0003-i2c-cht-wc-Use-generic_handle_irq_safe.patch
-0004-misc-hi6421-spmi-pmic-Use-generic_handle_irq_safe.patch
-0005-mfd-ezx-pcap-Use-generic_handle_irq_safe.patch
-0006-net-usb-lan78xx-Use-generic_handle_irq_safe.patch
-0007-staging-greybus-gpio-Use-generic_handle_irq_safe.patch
-
-# cgroup, in -mm, 5.18 should work.
-0001-mm-memcg-Revert-mm-memcg-optimize-user-context-objec.patch
-0002-mm-memcg-Disable-threshold-event-handlers-on-PREEMPT.patch
-0003-mm-memcg-Protect-per-CPU-counter-by-disabling-preemp.patch
-0004-mm-memcg-Opencode-the-inner-part-of-obj_cgroup_uncha.patch
-0005-mm-memcg-Protect-memcg_stock-with-a-local_lock_t.patch
-0006-mm-memcg-Disable-migration-instead-of-preemption-in-.patch
-0007-mm-memcg-Add-missing-counter-index-which-are-not-upd.patch
-0008-mm-memcg-Add-a-comment-regarding-the-release-obj.patch
-mm-memcg-Only-perform-the-debug-checks-on-PREEMPT_RT.patch
+# v5, fixed 3/3 of smp: Make softirq handling RT friendly
+0001-sched-Fix-missing-prototype-warnings.patch
+0002-smp-Rename-flush_smp_call_function_from_idle.patch
+0003-smp-Make-softirq-handling-RT-safe-in-flush_smp_call_.patch
###########################################################################
# Posted
###########################################################################
-x86-kvm-Require-const-tsc-for-RT.patch
ptrace-fix-ptrace-vs-tasklist_lock-race-on-PREEMPT_R.patch
rcu-tasks-Use-rcuwait-for-the-rcu_tasks_kthread.patch
rcu-tasks-Use-schedule_hrtimeout_range-while-waiting.patch
+net-Use-this_cpu_inc-to-increment-net-core_stats.patch
###########################################################################
# Post
@@ -137,7 +85,6 @@ x86__Enable_RT_also_on_32bit.patch
# For later, not essencial
###########################################################################
softirq-Use-a-dedicated-thread-for-timer-wakeups.patch
-virt-acrn-Remove-unsued-acrn_irqfds_mutex.patch
tpm_tis__fix_stall_after_iowrites.patch
drivers_block_zram__Replace_bit_spinlocks_with_rtmutex_for_-rt.patch
generic-softirq-Disable-softirq-stacks-on-PREEMPT_RT.patch
diff --git a/patches/signal__Revert_ptrace_preempt_magic.patch b/patches/signal__Revert_ptrace_preempt_magic.patch
index 38b67d2b8d67..071a4dded2bc 100644
--- a/patches/signal__Revert_ptrace_preempt_magic.patch
+++ b/patches/signal__Revert_ptrace_preempt_magic.patch
@@ -17,7 +17,7 @@ Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
--- a/kernel/signal.c
+++ b/kernel/signal.c
-@@ -2316,16 +2316,8 @@ static void ptrace_stop(int exit_code, i
+@@ -2320,16 +2320,8 @@ static int ptrace_stop(int exit_code, in
if (gstop_done && ptrace_reparented(current))
do_notify_parent_cldstop(current, false, why);
diff --git a/patches/signal_x86__Delay_calling_signals_in_atomic.patch b/patches/signal_x86__Delay_calling_signals_in_atomic.patch
index f9d4d186ea3c..960d657dee5b 100644
--- a/patches/signal_x86__Delay_calling_signals_in_atomic.patch
+++ b/patches/signal_x86__Delay_calling_signals_in_atomic.patch
@@ -42,8 +42,8 @@ Link: https://lore.kernel.org/r/Ygq5aBB/qMQw6aP5@linutronix.de
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
-@@ -120,6 +120,7 @@ config X86
- select ARCH_WANTS_NO_INSTR
+@@ -122,6 +122,7 @@ config X86
+ select ARCH_WANT_GENERAL_HUGETLB
select ARCH_WANT_HUGE_PMD_SHARE
select ARCH_WANT_LD_ORPHAN_WARN
+ select ARCH_WANTS_RT_DELAYED_SIGNALS
@@ -52,7 +52,7 @@ Link: https://lore.kernel.org/r/Ygq5aBB/qMQw6aP5@linutronix.de
select BUILDTIME_TABLE_SORT
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
-@@ -1087,6 +1087,9 @@ struct task_struct {
+@@ -1090,6 +1090,9 @@ struct task_struct {
/* Restored if set_restore_sigmask() was used: */
sigset_t saved_sigmask;
struct sigpending pending;
@@ -64,7 +64,7 @@ Link: https://lore.kernel.org/r/Ygq5aBB/qMQw6aP5@linutronix.de
unsigned int sas_ss_flags;
--- a/kernel/Kconfig.preempt
+++ b/kernel/Kconfig.preempt
-@@ -132,4 +132,14 @@ config SCHED_CORE
+@@ -133,4 +133,14 @@ config SCHED_CORE
which is the likely usage by Linux distributions, there should
be no measurable impact on performance.
@@ -81,8 +81,8 @@ Link: https://lore.kernel.org/r/Ygq5aBB/qMQw6aP5@linutronix.de
+ def_bool PREEMPT_RT && ARCH_WANTS_RT_DELAYED_SIGNALS
--- a/kernel/entry/common.c
+++ b/kernel/entry/common.c
-@@ -148,6 +148,18 @@ static void handle_signal_work(struct pt
- arch_do_signal_or_restart(regs, ti_work & _TIF_SIGPENDING);
+@@ -139,6 +139,18 @@ void noinstr exit_to_user_mode(void)
+ __exit_to_user_mode();
}
+#ifdef CONFIG_RT_DELAYED_SIGNALS
@@ -97,10 +97,10 @@ Link: https://lore.kernel.org/r/Ygq5aBB/qMQw6aP5@linutronix.de
+static inline void raise_delayed_signal(void) { }
+#endif
+
- static unsigned long exit_to_user_mode_loop(struct pt_regs *regs,
- unsigned long ti_work)
- {
-@@ -162,6 +174,8 @@ static unsigned long exit_to_user_mode_l
+ /* Workaround to allow gradual conversion of architecture code */
+ void __weak arch_do_signal_or_restart(struct pt_regs *regs) { }
+
+@@ -156,6 +168,8 @@ static unsigned long exit_to_user_mode_l
if (ti_work & _TIF_NEED_RESCHED)
schedule();
diff --git a/patches/smp_wake_ksoftirqd_on_preempt_rt_instead_do_softirq.patch b/patches/smp_wake_ksoftirqd_on_preempt_rt_instead_do_softirq.patch
deleted file mode 100644
index 5d420eafab2d..000000000000
--- a/patches/smp_wake_ksoftirqd_on_preempt_rt_instead_do_softirq.patch
+++ /dev/null
@@ -1,67 +0,0 @@
-From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
-Subject: smp: Wake ksoftirqd on PREEMPT_RT instead do_softirq().
-Date: Mon, 27 Sep 2021 09:38:14 +0200
-
-The softirq implementation on PREEMPT_RT does not provide do_softirq(). The
-softirq can not be handled directly here because migration_cpu_stop() is
-invoked with disabled preemption/ interrupts.
-
-A known user of scheduling softirqs from a remote function call is the block
-layer. It won't happen on PREEMPT_RT because it doesn't make sense for
-latency/ performance reasons and is disabled. Nevertheless this should
-be handled in case of a new user pops up rather than simply ignoring it.
-
-Waking ksoftirqd unconditionally can be problematic if softirqs were already
-pending but not yet handled. This can happen since the migration thread
-is running at a high priority and able to preempt a threaded-interrupt.
-The woken-up ksoftirqd would catch-up all pending (and later raised)
-softirqs which is not desired on PREEMPT_RT since it is no longer
-handled where it has been originally raised. This in turn delays the
-actual processing until a SCHED_OTHER task can run.
-
-Wake the softirq thread on PREEMPT_RT if a remote function call raised
-softirqs. Add warning in this case since this condition is not desired.
-
-Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
-Link: https://lkml.kernel.org/r/YgKgL6aPj8aBES6G@linutronix.de
----
-v2…v3:
- - Only wake ksoftirqd if the softirqs were raised wthin
- flush_smp_call_function_queue().
- - Add a warning in the wake case.
-v1…v2: Drop an empty line.
-
- kernel/smp.c | 21 ++++++++++++++++++---
- 1 file changed, 18 insertions(+), 3 deletions(-)
----
---- a/kernel/smp.c
-+++ b/kernel/smp.c
-@@ -691,10 +691,25 @@ void flush_smp_call_function_from_idle(v
- cfd_seq_store(this_cpu_ptr(&cfd_seq_local)->idle, CFD_SEQ_NOCPU,
- smp_processor_id(), CFD_SEQ_IDLE);
- local_irq_save(flags);
-- flush_smp_call_function_queue(true);
-- if (local_softirq_pending())
-- do_softirq();
-+ if (!IS_ENABLED(CONFIG_PREEMPT_RT)) {
-+ flush_smp_call_function_queue(true);
-+ if (local_softirq_pending())
-+ do_softirq();
-+ } else {
-+ unsigned int pending_prev;
-+ unsigned int pending_post;
-
-+ pending_prev = local_softirq_pending();
-+ flush_smp_call_function_queue(true);
-+ pending_post = local_softirq_pending();
-+
-+ if (WARN_ON_ONCE(!pending_prev && pending_post)) {
-+ struct task_struct *ksoftirqd = this_cpu_ksoftirqd();
-+
-+ if (ksoftirqd && !task_is_running(ksoftirqd))
-+ wake_up_process(ksoftirqd);
-+ }
-+ }
- local_irq_restore(flags);
- }
-
diff --git a/patches/softirq-Disable-softirq-stacks-on-PREEMPT_RT.patch b/patches/softirq-Disable-softirq-stacks-on-PREEMPT_RT.patch
index e5614969ebcc..4554b698dee9 100644
--- a/patches/softirq-Disable-softirq-stacks-on-PREEMPT_RT.patch
+++ b/patches/softirq-Disable-softirq-stacks-on-PREEMPT_RT.patch
@@ -13,14 +13,34 @@ ensure that do_softirq_own_stack() is not used which is not expected.
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
---
+ arch/arm/kernel/irq.c | 3 ++-
arch/powerpc/kernel/irq.c | 4 ++++
arch/sh/kernel/irq.c | 2 ++
arch/sparc/kernel/irq_64.c | 2 ++
- 3 files changed, 8 insertions(+)
+ 4 files changed, 10 insertions(+), 1 deletion(-)
+--- a/arch/arm/kernel/irq.c
++++ b/arch/arm/kernel/irq.c
+@@ -70,6 +70,7 @@ static void __init init_irq_stacks(void)
+ }
+ }
+
++#ifndef CONFIG_PREEMPT_RT
+ static void ____do_softirq(void *arg)
+ {
+ __do_softirq();
+@@ -80,7 +81,7 @@ void do_softirq_own_stack(void)
+ call_with_stack(____do_softirq, NULL,
+ __this_cpu_read(irq_stack_ptr));
+ }
+-
++#endif
+ #endif
+
+ int arch_show_interrupts(struct seq_file *p, int prec)
--- a/arch/powerpc/kernel/irq.c
+++ b/arch/powerpc/kernel/irq.c
-@@ -690,6 +690,7 @@ static inline void check_stack_overflow(
+@@ -689,6 +689,7 @@ static inline void check_stack_overflow(
}
}
@@ -28,7 +48,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
static __always_inline void call_do_softirq(const void *sp)
{
/* Temporarily switch r1 to sp, call __do_softirq() then restore r1. */
-@@ -708,6 +709,7 @@ static __always_inline void call_do_soft
+@@ -707,6 +708,7 @@ static __always_inline void call_do_soft
"r11", "r12"
);
}
@@ -36,7 +56,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
static __always_inline void call_do_irq(struct pt_regs *regs, void *sp)
{
-@@ -821,10 +823,12 @@ void *mcheckirq_ctx[NR_CPUS] __read_most
+@@ -820,10 +822,12 @@ void *mcheckirq_ctx[NR_CPUS] __read_most
void *softirq_ctx[NR_CPUS] __read_mostly;
void *hardirq_ctx[NR_CPUS] __read_mostly;
diff --git a/patches/softirq-Use-a-dedicated-thread-for-timer-wakeups.patch b/patches/softirq-Use-a-dedicated-thread-for-timer-wakeups.patch
index 9a8405ae4dea..8baa5030f95f 100644
--- a/patches/softirq-Use-a-dedicated-thread-for-timer-wakeups.patch
+++ b/patches/softirq-Use-a-dedicated-thread-for-timer-wakeups.patch
@@ -45,7 +45,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
--- a/include/linux/interrupt.h
+++ b/include/linux/interrupt.h
-@@ -605,6 +605,22 @@ extern void __raise_softirq_irqoff(unsig
+@@ -623,6 +623,22 @@ extern void __raise_softirq_irqoff(unsig
extern void raise_softirq_irqoff(unsigned int nr);
extern void raise_softirq(unsigned int nr);
@@ -70,7 +70,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
static inline struct task_struct *this_cpu_ksoftirqd(void)
--- a/kernel/softirq.c
+++ b/kernel/softirq.c
-@@ -624,6 +624,22 @@ static inline void tick_irq_exit(void)
+@@ -637,6 +637,22 @@ static inline void tick_irq_exit(void)
#endif
}
@@ -93,7 +93,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
static inline void __irq_exit_rcu(void)
{
#ifndef __ARCH_IRQ_EXIT_IRQS_DISABLED
-@@ -635,6 +651,8 @@ static inline void __irq_exit_rcu(void)
+@@ -648,6 +664,8 @@ static inline void __irq_exit_rcu(void)
preempt_count_sub(HARDIRQ_OFFSET);
if (!in_interrupt() && local_softirq_pending())
invoke_softirq();
@@ -102,7 +102,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
tick_irq_exit();
}
-@@ -963,11 +981,69 @@ static struct smp_hotplug_thread softirq
+@@ -976,11 +994,69 @@ static struct smp_hotplug_thread softirq
.thread_comm = "ksoftirqd/%u",
};
@@ -194,7 +194,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
__hrtimer_run_queues(cpu_base, now, flags, HRTIMER_ACTIVE_HARD);
--- a/kernel/time/timer.c
+++ b/kernel/time/timer.c
-@@ -1766,7 +1766,7 @@ static void run_local_timers(void)
+@@ -1769,7 +1769,7 @@ static void run_local_timers(void)
if (time_before(jiffies, base->next_expiry))
return;
}
diff --git a/patches/softirq__Check_preemption_after_reenabling_interrupts.patch b/patches/softirq__Check_preemption_after_reenabling_interrupts.patch
index 529fbe6e45e6..40c978498691 100644
--- a/patches/softirq__Check_preemption_after_reenabling_interrupts.patch
+++ b/patches/softirq__Check_preemption_after_reenabling_interrupts.patch
@@ -47,7 +47,7 @@ Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
#endif /* CONFIG_PREEMPT_COUNT */
--- a/net/core/dev.c
+++ b/net/core/dev.c
-@@ -2985,6 +2985,7 @@ static void __netif_reschedule(struct Qd
+@@ -3024,6 +3024,7 @@ static void __netif_reschedule(struct Qd
sd->output_queue_tailp = &q->next_sched;
raise_softirq_irqoff(NET_TX_SOFTIRQ);
local_irq_restore(flags);
@@ -55,7 +55,7 @@ Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
}
void __netif_schedule(struct Qdisc *q)
-@@ -3047,6 +3048,7 @@ void __dev_kfree_skb_irq(struct sk_buff
+@@ -3086,6 +3087,7 @@ void __dev_kfree_skb_irq(struct sk_buff
__this_cpu_write(softnet_data.completion_queue, skb);
raise_softirq_irqoff(NET_TX_SOFTIRQ);
local_irq_restore(flags);
@@ -63,7 +63,7 @@ Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
}
EXPORT_SYMBOL(__dev_kfree_skb_irq);
-@@ -5760,12 +5762,14 @@ static void net_rps_action_and_irq_enabl
+@@ -5807,12 +5809,14 @@ static void net_rps_action_and_irq_enabl
sd->rps_ipi_list = NULL;
local_irq_enable();
@@ -78,7 +78,7 @@ Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
}
static bool sd_has_rps_ipi_waiting(struct softnet_data *sd)
-@@ -5841,6 +5845,7 @@ void __napi_schedule(struct napi_struct
+@@ -5888,6 +5892,7 @@ void __napi_schedule(struct napi_struct
local_irq_save(flags);
____napi_schedule(this_cpu_ptr(&softnet_data), n);
local_irq_restore(flags);
@@ -86,7 +86,7 @@ Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
}
EXPORT_SYMBOL(__napi_schedule);
-@@ -10665,6 +10670,7 @@ static int dev_cpu_dead(unsigned int old
+@@ -10996,6 +11001,7 @@ static int dev_cpu_dead(unsigned int old
raise_softirq_irqoff(NET_TX_SOFTIRQ);
local_irq_enable();
diff --git a/patches/sunrpc__Make_svc_xprt_do_enqueue_use_get_cpu_light.patch b/patches/sunrpc__Make_svc_xprt_do_enqueue_use_get_cpu_light.patch
index e6718bb2b85f..ecb0053bb318 100644
--- a/patches/sunrpc__Make_svc_xprt_do_enqueue_use_get_cpu_light.patch
+++ b/patches/sunrpc__Make_svc_xprt_do_enqueue_use_get_cpu_light.patch
@@ -38,7 +38,7 @@ Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
--- a/net/sunrpc/svc_xprt.c
+++ b/net/sunrpc/svc_xprt.c
-@@ -440,7 +440,7 @@ void svc_xprt_do_enqueue(struct svc_xprt
+@@ -461,7 +461,7 @@ void svc_xprt_enqueue(struct svc_xprt *x
if (test_and_set_bit(XPT_BUSY, &xprt->xpt_flags))
return;
@@ -47,7 +47,7 @@ Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
pool = svc_pool_for_cpu(xprt->xpt_server, cpu);
atomic_long_inc(&pool->sp_stats.packets);
-@@ -464,7 +464,7 @@ void svc_xprt_do_enqueue(struct svc_xprt
+@@ -485,7 +485,7 @@ void svc_xprt_enqueue(struct svc_xprt *x
rqstp = NULL;
out_unlock:
rcu_read_unlock();
@@ -55,4 +55,4 @@ Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+ put_cpu_light();
trace_svc_xprt_enqueue(xprt, rqstp);
}
- EXPORT_SYMBOL_GPL(svc_xprt_do_enqueue);
+ EXPORT_SYMBOL_GPL(svc_xprt_enqueue);
diff --git a/patches/sysfs__Add__sys_kernel_realtime_entry.patch b/patches/sysfs__Add__sys_kernel_realtime_entry.patch
index 8a7384813434..7fd249eadabf 100644
--- a/patches/sysfs__Add__sys_kernel_realtime_entry.patch
+++ b/patches/sysfs__Add__sys_kernel_realtime_entry.patch
@@ -24,7 +24,7 @@ Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
--- a/kernel/ksysfs.c
+++ b/kernel/ksysfs.c
-@@ -138,6 +138,15 @@ KERNEL_ATTR_RO(vmcoreinfo);
+@@ -137,6 +137,15 @@ KERNEL_ATTR_RO(vmcoreinfo);
#endif /* CONFIG_CRASH_CORE */
@@ -40,7 +40,7 @@ Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
/* whether file capabilities are enabled */
static ssize_t fscaps_show(struct kobject *kobj,
struct kobj_attribute *attr, char *buf)
-@@ -229,6 +238,9 @@ static struct attribute * kernel_attrs[]
+@@ -228,6 +237,9 @@ static struct attribute * kernel_attrs[]
&rcu_expedited_attr.attr,
&rcu_normal_attr.attr,
#endif
diff --git a/patches/tcp-Don-t-acquire-inet_listen_hashbucket-lock-with-d.patch b/patches/tcp-Don-t-acquire-inet_listen_hashbucket-lock-with-d.patch
deleted file mode 100644
index d11df4740e5a..000000000000
--- a/patches/tcp-Don-t-acquire-inet_listen_hashbucket-lock-with-d.patch
+++ /dev/null
@@ -1,160 +0,0 @@
-From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
-Date: Tue, 30 Nov 2021 12:48:08 +0100
-Subject: [PATCH] tcp: Don't acquire inet_listen_hashbucket::lock with disabled
- BH.
-
-Commit
- 9652dc2eb9e40 ("tcp: relax listening_hash operations")
-
-removed the need to disable bottom half while acquiring
-listening_hash.lock. There are still two callers left which disable
-bottom half before the lock is acquired.
-
-On PREEMPT_RT the softirqs are preemptible and local_bh_disable() acts
-as a lock to ensure that resources, that are protected by disabling
-bottom halves, remain protected.
-This leads to a circular locking dependency if the lock acquired with
-disabled bottom halves is also acquired with enabled bottom halves
-followed by disabling bottom halves. This is the reverse locking order.
-It has been observed with inet_listen_hashbucket::lock:
-
-local_bh_disable() + spin_lock(&ilb->lock):
- inet_listen()
- inet_csk_listen_start()
- sk->sk_prot->hash() := inet_hash()
- local_bh_disable()
- __inet_hash()
- spin_lock(&ilb->lock);
- acquire(&ilb->lock);
-
-Reverse order: spin_lock(&ilb2->lock) + local_bh_disable():
- tcp_seq_next()
- listening_get_next()
- spin_lock(&ilb2->lock);
- acquire(&ilb2->lock);
-
- tcp4_seq_show()
- get_tcp4_sock()
- sock_i_ino()
- read_lock_bh(&sk->sk_callback_lock);
- acquire(softirq_ctrl) // <---- whoops
- acquire(&sk->sk_callback_lock)
-
-Drop local_bh_disable() around __inet_hash() which acquires
-listening_hash->lock. Split inet_unhash() and acquire the
-listen_hashbucket lock without disabling bottom halves; the inet_ehash
-lock with disabled bottom halves.
-
-Reported-by: Mike Galbraith <efault@gmx.de>
-Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
-Link: https://lkml.kernel.org/r/12d6f9879a97cd56c09fb53dee343cbb14f7f1f7.camel@gmx.de
-Link: https://lkml.kernel.org/r/X9CheYjuXWc75Spa@hirez.programming.kicks-ass.net
-Link: https://lkml.kernel.org/r/YgKh9fbQ2dcBu3e1@linutronix.de
----
- net/ipv4/inet_hashtables.c | 53 ++++++++++++++++++++++++++------------------
- net/ipv6/inet6_hashtables.c | 5 ----
- 2 files changed, 33 insertions(+), 25 deletions(-)
-
---- a/net/ipv4/inet_hashtables.c
-+++ b/net/ipv4/inet_hashtables.c
-@@ -637,7 +637,9 @@ int __inet_hash(struct sock *sk, struct
- int err = 0;
-
- if (sk->sk_state != TCP_LISTEN) {
-+ local_bh_disable();
- inet_ehash_nolisten(sk, osk, NULL);
-+ local_bh_enable();
- return 0;
- }
- WARN_ON(!sk_unhashed(sk));
-@@ -669,45 +671,54 @@ int inet_hash(struct sock *sk)
- {
- int err = 0;
-
-- if (sk->sk_state != TCP_CLOSE) {
-- local_bh_disable();
-+ if (sk->sk_state != TCP_CLOSE)
- err = __inet_hash(sk, NULL);
-- local_bh_enable();
-- }
-
- return err;
- }
- EXPORT_SYMBOL_GPL(inet_hash);
-
--void inet_unhash(struct sock *sk)
-+static void __inet_unhash(struct sock *sk, struct inet_listen_hashbucket *ilb)
- {
-- struct inet_hashinfo *hashinfo = sk->sk_prot->h.hashinfo;
-- struct inet_listen_hashbucket *ilb = NULL;
-- spinlock_t *lock;
--
- if (sk_unhashed(sk))
- return;
-
-- if (sk->sk_state == TCP_LISTEN) {
-- ilb = &hashinfo->listening_hash[inet_sk_listen_hashfn(sk)];
-- lock = &ilb->lock;
-- } else {
-- lock = inet_ehash_lockp(hashinfo, sk->sk_hash);
-- }
-- spin_lock_bh(lock);
-- if (sk_unhashed(sk))
-- goto unlock;
--
- if (rcu_access_pointer(sk->sk_reuseport_cb))
- reuseport_stop_listen_sock(sk);
- if (ilb) {
-+ struct inet_hashinfo *hashinfo = sk->sk_prot->h.hashinfo;
-+
- inet_unhash2(hashinfo, sk);
- ilb->count--;
- }
- __sk_nulls_del_node_init_rcu(sk);
- sock_prot_inuse_add(sock_net(sk), sk->sk_prot, -1);
--unlock:
-- spin_unlock_bh(lock);
-+}
-+
-+void inet_unhash(struct sock *sk)
-+{
-+ struct inet_hashinfo *hashinfo = sk->sk_prot->h.hashinfo;
-+
-+ if (sk_unhashed(sk))
-+ return;
-+
-+ if (sk->sk_state == TCP_LISTEN) {
-+ struct inet_listen_hashbucket *ilb;
-+
-+ ilb = &hashinfo->listening_hash[inet_sk_listen_hashfn(sk)];
-+ /* Don't disable bottom halves while acquiring the lock to
-+ * avoid circular locking dependency on PREEMPT_RT.
-+ */
-+ spin_lock(&ilb->lock);
-+ __inet_unhash(sk, ilb);
-+ spin_unlock(&ilb->lock);
-+ } else {
-+ spinlock_t *lock = inet_ehash_lockp(hashinfo, sk->sk_hash);
-+
-+ spin_lock_bh(lock);
-+ __inet_unhash(sk, NULL);
-+ spin_unlock_bh(lock);
-+ }
- }
- EXPORT_SYMBOL_GPL(inet_unhash);
-
---- a/net/ipv6/inet6_hashtables.c
-+++ b/net/ipv6/inet6_hashtables.c
-@@ -333,11 +333,8 @@ int inet6_hash(struct sock *sk)
- {
- int err = 0;
-
-- if (sk->sk_state != TCP_CLOSE) {
-- local_bh_disable();
-+ if (sk->sk_state != TCP_CLOSE)
- err = __inet_hash(sk, NULL);
-- local_bh_enable();
-- }
-
- return err;
- }
diff --git a/patches/tty_serial_omap__Make_the_locking_RT_aware.patch b/patches/tty_serial_omap__Make_the_locking_RT_aware.patch
index 263e41d07452..0170136bc1c2 100644
--- a/patches/tty_serial_omap__Make_the_locking_RT_aware.patch
+++ b/patches/tty_serial_omap__Make_the_locking_RT_aware.patch
@@ -17,7 +17,7 @@ Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
--- a/drivers/tty/serial/omap-serial.c
+++ b/drivers/tty/serial/omap-serial.c
-@@ -1255,13 +1255,10 @@ serial_omap_console_write(struct console
+@@ -1241,13 +1241,10 @@ serial_omap_console_write(struct console
unsigned int ier;
int locked = 1;
@@ -34,7 +34,7 @@ Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
/*
* First save the IER then disable the interrupts
-@@ -1288,8 +1285,7 @@ serial_omap_console_write(struct console
+@@ -1274,8 +1271,7 @@ serial_omap_console_write(struct console
check_modem_status(up);
if (locked)
diff --git a/patches/virt-acrn-Remove-unsued-acrn_irqfds_mutex.patch b/patches/virt-acrn-Remove-unsued-acrn_irqfds_mutex.patch
deleted file mode 100644
index 12805701bc21..000000000000
--- a/patches/virt-acrn-Remove-unsued-acrn_irqfds_mutex.patch
+++ /dev/null
@@ -1,25 +0,0 @@
-From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
-Date: Thu, 9 Sep 2021 10:15:30 +0200
-Subject: [PATCH] virt: acrn: Remove unsued acrn_irqfds_mutex.
-
-acrn_irqfds_mutex is not used, never was.
-
-Remove acrn_irqfds_mutex.
-
-Fixes: aa3b483ff1d71 ("virt: acrn: Introduce irqfd")
-Cc: Fei Li <fei1.li@intel.com>
-Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
----
- drivers/virt/acrn/irqfd.c | 1 -
- 1 file changed, 1 deletion(-)
-
---- a/drivers/virt/acrn/irqfd.c
-+++ b/drivers/virt/acrn/irqfd.c
-@@ -17,7 +17,6 @@
- #include "acrn_drv.h"
-
- static LIST_HEAD(acrn_irqfd_clients);
--static DEFINE_MUTEX(acrn_irqfds_mutex);
-
- /**
- * struct hsm_irqfd - Properties of HSM irqfd
diff --git a/patches/x86-kvm-Require-const-tsc-for-RT.patch b/patches/x86-kvm-Require-const-tsc-for-RT.patch
deleted file mode 100644
index bfa429253a61..000000000000
--- a/patches/x86-kvm-Require-const-tsc-for-RT.patch
+++ /dev/null
@@ -1,32 +0,0 @@
-From: Thomas Gleixner <tglx@linutronix.de>
-Date: Sun, 6 Nov 2011 12:26:18 +0100
-Subject: [PATCH] x86: kvm Require const tsc for RT
-
-Non constant TSC is a nightmare on bare metal already, but with
-virtualization it becomes a complete disaster because the workarounds
-are horrible latency wise. That's also a preliminary for running RT in
-a guest on top of a RT host.
-
-Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
-Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
-Acked-by: Paolo Bonzini <pbonzini@redhat.com>
-Link: https://lore.kernel.org/r/Yh5eJSG19S2sjZfy@linutronix.de
----
- arch/x86/kvm/x86.c | 6 ++++++
- 1 file changed, 6 insertions(+)
-
---- a/arch/x86/kvm/x86.c
-+++ b/arch/x86/kvm/x86.c
-@@ -8826,6 +8826,12 @@ int kvm_arch_init(void *opaque)
- goto out;
- }
-
-+ if (IS_ENABLED(CONFIG_PREEMPT_RT) && !boot_cpu_has(X86_FEATURE_CONSTANT_TSC)) {
-+ pr_err("RT requires X86_FEATURE_CONSTANT_TSC\n");
-+ r = -EOPNOTSUPP;
-+ goto out;
-+ }
-+
- r = -ENOMEM;
-
- x86_emulator_cache = kvm_alloc_emulator_cache();
diff --git a/patches/x86__Enable_RT_also_on_32bit.patch b/patches/x86__Enable_RT_also_on_32bit.patch
index f52dde183193..3f4b61ab22c8 100644
--- a/patches/x86__Enable_RT_also_on_32bit.patch
+++ b/patches/x86__Enable_RT_also_on_32bit.patch
@@ -22,7 +22,7 @@ Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
select ARCH_USE_CMPXCHG_LOCKREF
select HAVE_ARCH_SOFT_DIRTY
select MODULES_USE_ELF_RELA
-@@ -110,6 +109,7 @@ config X86
+@@ -111,6 +110,7 @@ config X86
select ARCH_SUPPORTS_KMAP_LOCAL_FORCE_MAP if NR_CPUS <= 4096
select ARCH_SUPPORTS_LTO_CLANG
select ARCH_SUPPORTS_LTO_CLANG_THIN
diff --git a/patches/x86__Support_for_lazy_preemption.patch b/patches/x86__Support_for_lazy_preemption.patch
index b594f3e6c057..49ee7bea7da5 100644
--- a/patches/x86__Support_for_lazy_preemption.patch
+++ b/patches/x86__Support_for_lazy_preemption.patch
@@ -19,7 +19,7 @@ Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
-@@ -237,6 +237,7 @@ config X86
+@@ -241,6 +241,7 @@ config X86
select HAVE_PCI
select HAVE_PERF_REGS
select HAVE_PERF_USER_STACK_DUMP
@@ -136,7 +136,7 @@ Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
/**
--- a/kernel/entry/common.c
+++ b/kernel/entry/common.c
-@@ -171,7 +171,7 @@ static unsigned long exit_to_user_mode_l
+@@ -165,7 +165,7 @@ static unsigned long exit_to_user_mode_l
local_irq_enable_exit_to_user(ti_work);
diff --git a/patches/x86_entry__Use_should_resched_in_idtentry_exit_cond_resched.patch b/patches/x86_entry__Use_should_resched_in_idtentry_exit_cond_resched.patch
index 89ba39cc46b1..c0f85a307273 100644
--- a/patches/x86_entry__Use_should_resched_in_idtentry_exit_cond_resched.patch
+++ b/patches/x86_entry__Use_should_resched_in_idtentry_exit_cond_resched.patch
@@ -21,7 +21,7 @@ Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
--- a/kernel/entry/common.c
+++ b/kernel/entry/common.c
-@@ -401,7 +401,7 @@ void irqentry_exit_cond_resched(void)
+@@ -395,7 +395,7 @@ void raw_irqentry_exit_cond_resched(void
rcu_irq_exit_check_preempt();
if (IS_ENABLED(CONFIG_DEBUG_ENTRY))
WARN_ON_ONCE(!on_thread_stack());