From: Frederic Weisbecker <frederic@kernel.org>
To: Christian Loehle <christian.loehle@arm.com>
Cc: LKML <linux-kernel@vger.kernel.org>,
Frederic Weisbecker <frederic@kernel.org>,
Anna-Maria Behnsen <anna-maria@linutronix.de>,
Sehee Jeong <sehee1.jeong@samsung.com>,
Thomas Gleixner <tglx@linutronix.de>,
Peter Zijlstra <peterz@infradead.org>
Subject: [PATCH 1/6] timers/migration: Revert per CPU capacity hierarchy
Date: Thu, 25 Jun 2026 18:41:09 +0200 [thread overview]
Message-ID: <20260625164114.51454-2-frederic@kernel.org> (raw)
In-Reply-To: <20260625164114.51454-1-frederic@kernel.org>
The per CPU-capacity hierarchies may not be the right answer to
solve timers migrating too often to high capacity CPUs. Revert that in
favour of later code that will gather groups per capacity under a common
root and prefer lower capacity groups as migrators.
Signed-off-by: Frederic Weisbecker <frederic@kernel.org>
---
include/trace/events/timer_migration.h | 24 +--
kernel/time/timer_migration.c | 241 ++++++-------------------
kernel/time/timer_migration.h | 18 --
scripts/timer_migration_tree.py | 50 ++---
4 files changed, 87 insertions(+), 246 deletions(-)
diff --git a/include/trace/events/timer_migration.h b/include/trace/events/timer_migration.h
index 0b135e9301b1..61171b13c687 100644
--- a/include/trace/events/timer_migration.h
+++ b/include/trace/events/timer_migration.h
@@ -33,16 +33,15 @@ TRACE_EVENT(tmigr_group_set,
TRACE_EVENT(tmigr_connect_child_parent,
- TP_PROTO(struct tmigr_hierarchy *hier, struct tmigr_group *child),
+ TP_PROTO(struct tmigr_group *child),
- TP_ARGS(hier, child),
+ TP_ARGS(child),
TP_STRUCT__entry(
__field( void *, child )
__field( void *, parent )
__field( unsigned int, lvl )
__field( unsigned int, numa_node )
- __field( unsigned int, capacity )
__field( unsigned int, num_children )
__field( u32, groupmask )
),
@@ -52,28 +51,26 @@ TRACE_EVENT(tmigr_connect_child_parent,
__entry->parent = child->parent;
__entry->lvl = child->parent->level;
__entry->numa_node = child->parent->numa_node;
- __entry->capacity = hier->capacity;
__entry->num_children = child->parent->num_children;
__entry->groupmask = child->groupmask;
),
- TP_printk("group=%p groupmask=%0x parent=%p lvl=%d numa=%d capacity=%d num_children=%d",
- __entry->child, __entry->groupmask, __entry->parent, __entry->lvl,
- __entry->numa_node, __entry->capacity, __entry->num_children)
+ TP_printk("group=%p groupmask=%0x parent=%p lvl=%d numa=%d num_children=%d",
+ __entry->child, __entry->groupmask, __entry->parent,
+ __entry->lvl, __entry->numa_node, __entry->num_children)
);
TRACE_EVENT(tmigr_connect_cpu_parent,
- TP_PROTO(struct tmigr_hierarchy *hier, struct tmigr_cpu *tmc),
+ TP_PROTO(struct tmigr_cpu *tmc),
- TP_ARGS(hier, tmc),
+ TP_ARGS(tmc),
TP_STRUCT__entry(
__field( void *, parent )
__field( unsigned int, cpu )
__field( unsigned int, lvl )
__field( unsigned int, numa_node )
- __field( unsigned int, capacity )
__field( unsigned int, num_children )
__field( u32, groupmask )
),
@@ -83,14 +80,13 @@ TRACE_EVENT(tmigr_connect_cpu_parent,
__entry->cpu = tmc->cpuevt.cpu;
__entry->lvl = tmc->tmgroup->level;
__entry->numa_node = tmc->tmgroup->numa_node;
- __entry->capacity = hier->capacity;
__entry->num_children = tmc->tmgroup->num_children;
__entry->groupmask = tmc->groupmask;
),
- TP_printk("cpu=%d groupmask=%0x parent=%p lvl=%d numa=%d capacity=%d num_children=%d",
- __entry->cpu, __entry->groupmask, __entry->parent, __entry->lvl,
- __entry->numa_node, __entry->capacity, __entry->num_children)
+ TP_printk("cpu=%d groupmask=%0x parent=%p lvl=%d numa=%d num_children=%d",
+ __entry->cpu, __entry->groupmask, __entry->parent,
+ __entry->lvl, __entry->numa_node, __entry->num_children)
);
DECLARE_EVENT_CLASS(tmigr_group_and_cpu,
diff --git a/kernel/time/timer_migration.c b/kernel/time/timer_migration.c
index 806c23cf71fc..52c15affdbff 100644
--- a/kernel/time/timer_migration.c
+++ b/kernel/time/timer_migration.c
@@ -102,7 +102,7 @@
* active CPU/group information atomic_try_cmpxchg() is used instead and only
* the per CPU tmigr_cpu->lock is held.
*
- * During the setup of groups, hier->level_list is required. It is protected by
+ * During the setup of groups tmigr_level_list is required. It is protected by
* @tmigr_mutex.
*
* When @timer_base->lock as well as tmigr related locks are required, the lock
@@ -416,12 +416,13 @@
*/
static DEFINE_MUTEX(tmigr_mutex);
-
-static LIST_HEAD(tmigr_hierarchy_list);
+static struct list_head *tmigr_level_list __read_mostly;
static unsigned int tmigr_hierarchy_levels __read_mostly;
static unsigned int tmigr_crossnode_level __read_mostly;
+static struct tmigr_group *tmigr_root;
+
static DEFINE_PER_CPU(struct tmigr_cpu, tmigr_cpu);
/*
@@ -1468,34 +1469,6 @@ static long tmigr_trigger_active(void *unused)
return 0;
}
-static unsigned int tmigr_get_capacity(int cpu)
-{
- /*
- * nohz_full CPUs need to make sure there is always an available (online)
- * and never idle migrator to handle all their global timers. That duty
- * is served by the timekeeper which then never stops its tick. But the
- * timekeeper must then belong to the same hierarchy as all the nohz_full
- * CPUs. Simply turn off capacity awareness when nohz_full is running.
- */
- if (tick_nohz_full_enabled() || !IS_ENABLED(CONFIG_BROKEN))
- return SCHED_CAPACITY_SCALE;
- else
- return arch_scale_cpu_capacity(cpu);
-}
-
-static struct tmigr_hierarchy *__tmigr_get_hierarchy(int cpu)
-{
- unsigned int capacity = tmigr_get_capacity(cpu);
- struct tmigr_hierarchy *iter;
-
- list_for_each_entry(iter, &tmigr_hierarchy_list, node) {
- if (iter->capacity == capacity)
- return iter;
- }
-
- return NULL;
-}
-
static int tmigr_clear_cpu_available(unsigned int cpu)
{
struct tmigr_cpu *tmc = this_cpu_ptr(&tmigr_cpu);
@@ -1520,21 +1493,8 @@ static int tmigr_clear_cpu_available(unsigned int cpu)
}
if (firstexp != KTIME_MAX) {
- struct tmigr_hierarchy *hier = __tmigr_get_hierarchy(cpu);
-
- if (WARN_ON_ONCE(!hier))
- return -EINVAL;
-
- migrator = cpumask_any_and(tmigr_available_cpumask, hier->cpumask);
- if (migrator < nr_cpu_ids) {
- work_on_cpu(migrator, tmigr_trigger_active, NULL);
- } else {
- /*
- * If deactivation returned an expiration, it belongs to an available
- * nohz CPU in the hierarchy.
- */
- WARN_ONCE(1, "Expected available CPU in the hierarchy\n");
- }
+ migrator = cpumask_any(tmigr_available_cpumask);
+ work_on_cpu(migrator, tmigr_trigger_active, NULL);
}
return 0;
@@ -1697,14 +1657,14 @@ static void tmigr_init_group(struct tmigr_group *group, unsigned int lvl,
group->groupevt.ignore = true;
}
-static struct tmigr_group *tmigr_get_group(struct tmigr_hierarchy *hier, int node, unsigned int lvl)
+static struct tmigr_group *tmigr_get_group(int node, unsigned int lvl)
{
struct tmigr_group *tmp, *group = NULL;
lockdep_assert_held(&tmigr_mutex);
/* Try to attach to an existing group first */
- list_for_each_entry(tmp, &hier->level_list[lvl], list) {
+ list_for_each_entry(tmp, &tmigr_level_list[lvl], list) {
/*
* If @lvl is below the cross NUMA node level, check whether
* this group belongs to the same NUMA node.
@@ -1738,14 +1698,14 @@ static struct tmigr_group *tmigr_get_group(struct tmigr_hierarchy *hier, int nod
tmigr_init_group(group, lvl, node);
/* Setup successful. Add it to the hierarchy */
- list_add(&group->list, &hier->level_list[lvl]);
+ list_add(&group->list, &tmigr_level_list[lvl]);
trace_tmigr_group_set(group);
return group;
}
-static bool tmigr_init_root(struct tmigr_hierarchy *hier, struct tmigr_group *group, bool activate)
+static bool tmigr_init_root(struct tmigr_group *group, bool activate)
{
- if (!group->parent && group != hier->root) {
+ if (!group->parent && group != tmigr_root) {
/*
* This is the new top-level, prepare its groupmask in advance
* to avoid accidents where yet another new top-level is
@@ -1761,10 +1721,11 @@ static bool tmigr_init_root(struct tmigr_hierarchy *hier, struct tmigr_group *gr
}
-static void tmigr_connect_child_parent(struct tmigr_hierarchy *hier, struct tmigr_group *child,
- struct tmigr_group *parent, bool activate)
+static void tmigr_connect_child_parent(struct tmigr_group *child,
+ struct tmigr_group *parent,
+ bool activate)
{
- if (tmigr_init_root(hier, parent, activate)) {
+ if (tmigr_init_root(parent, activate)) {
/*
* The previous top level had prepared its groupmask already,
* simply account it in advance as the first child. If some groups
@@ -1797,13 +1758,13 @@ static void tmigr_connect_child_parent(struct tmigr_hierarchy *hier, struct tmig
*/
smp_store_release(&child->parent, parent);
- trace_tmigr_connect_child_parent(hier, child);
+ trace_tmigr_connect_child_parent(child);
}
-static int tmigr_setup_groups(struct tmigr_hierarchy *hier, unsigned int cpu,
- unsigned int node, struct tmigr_group *start, bool activate)
+static int tmigr_setup_groups(unsigned int cpu, unsigned int node,
+ struct tmigr_group *start, bool activate)
{
- struct tmigr_group *root = hier->root, *group, *child, **stack;
+ struct tmigr_group *group, *child, **stack;
int i, top = 0, err = 0, start_lvl = 0;
bool root_mismatch = false;
@@ -1816,11 +1777,11 @@ static int tmigr_setup_groups(struct tmigr_hierarchy *hier, unsigned int cpu,
start_lvl = start->level + 1;
}
- if (root)
- root_mismatch = root->numa_node != node;
+ if (tmigr_root)
+ root_mismatch = tmigr_root->numa_node != node;
for (i = start_lvl; i < tmigr_hierarchy_levels; i++) {
- group = tmigr_get_group(hier, node, i);
+ group = tmigr_get_group(node, i);
if (IS_ERR(group)) {
err = PTR_ERR(group);
i--;
@@ -1842,7 +1803,7 @@ static int tmigr_setup_groups(struct tmigr_hierarchy *hier, unsigned int cpu,
if (group->parent)
break;
if ((!root_mismatch || i >= tmigr_crossnode_level) &&
- list_is_singular(&hier->level_list[i]))
+ list_is_singular(&tmigr_level_list[i]))
break;
}
@@ -1870,15 +1831,15 @@ static int tmigr_setup_groups(struct tmigr_hierarchy *hier, unsigned int cpu,
tmc->tmgroup = group;
tmc->groupmask = BIT(group->num_children++);
- tmigr_init_root(hier, group, activate);
+ tmigr_init_root(group, activate);
- trace_tmigr_connect_cpu_parent(hier, tmc);
+ trace_tmigr_connect_cpu_parent(tmc);
/* There are no children that need to be connected */
continue;
} else {
child = stack[i - 1];
- tmigr_connect_child_parent(hier, child, group, activate);
+ tmigr_connect_child_parent(child, group, activate);
}
}
@@ -1934,23 +1895,18 @@ static int tmigr_setup_groups(struct tmigr_hierarchy *hier, unsigned int cpu,
data.childmask = start->groupmask;
__walk_groups_from(tmigr_active_up, &data, start, start->parent);
}
- } else if (start) {
- union tmigr_state state;
-
- /* Remote activation assumes the whole target's hierarchy is inactive */
- state.state = atomic_read(&start->migr_state);
- WARN_ON_ONCE(state.active);
}
/* Root update */
- if (list_is_singular(&hier->level_list[top])) {
- group = list_first_entry(&hier->level_list[top], typeof(*group), list);
+ if (list_is_singular(&tmigr_level_list[top])) {
+ group = list_first_entry(&tmigr_level_list[top],
+ typeof(*group), list);
WARN_ON_ONCE(group->parent);
- if (root) {
+ if (tmigr_root) {
/* Old root should be the same or below */
- WARN_ON_ONCE(root->level > top);
+ WARN_ON_ONCE(tmigr_root->level > top);
}
- hier->root = group;
+ tmigr_root = group;
}
out:
kfree(stack);
@@ -1958,123 +1914,34 @@ static int tmigr_setup_groups(struct tmigr_hierarchy *hier, unsigned int cpu,
return err;
}
-static struct tmigr_hierarchy *tmigr_get_hierarchy(int cpu)
-{
- struct tmigr_hierarchy *hier;
-
- hier = __tmigr_get_hierarchy(cpu);
-
- if (hier)
- return hier;
-
- hier = kzalloc_flex(*hier, level_list, tmigr_hierarchy_levels);
- if (!hier)
- return ERR_PTR(-ENOMEM);
-
- hier->cpumask = kzalloc(cpumask_size(), GFP_KERNEL);
- if (!hier->cpumask) {
- kfree(hier);
- return ERR_PTR(-ENOMEM);
- }
-
- for (int i = 0; i < tmigr_hierarchy_levels; i++)
- INIT_LIST_HEAD(&hier->level_list[i]);
-
- hier->capacity = tmigr_get_capacity(cpu);
- list_add_tail(&hier->node, &tmigr_hierarchy_list);
-
- return hier;
-}
-
-static int tmigr_connect_old_root(struct tmigr_hierarchy *hier, int cpu,
- struct tmigr_group *old_root, bool activate)
-{
- /*
- * The target CPU must never do the prepare work, except
- * on early boot when the boot CPU is the target. Otherwise
- * it may spuriously activate the old top level group inside
- * the new one (nevertheless whether old top level group is
- * active or not) and/or release an uninitialized childmask.
- */
- WARN_ON_ONCE(cpu == smp_processor_id());
- if (activate) {
- /*
- * The current CPU is expected to be online in the hierarchy,
- * otherwise the old root may not be active as expected.
- */
- WARN_ON_ONCE(!__this_cpu_read(tmigr_cpu.available));
- }
-
- return tmigr_setup_groups(hier, -1, old_root->numa_node, old_root, activate);
-}
-
-static long connect_old_root_work(void *arg)
-{
- struct tmigr_group *old_root = arg;
- struct tmigr_hierarchy *hier;
- int cpu = smp_processor_id();
-
- hier = __tmigr_get_hierarchy(cpu);
- if (WARN_ON_ONCE(!hier))
- return -EINVAL;
-
- return tmigr_connect_old_root(hier, cpu, old_root, true);
-}
-
static int tmigr_add_cpu(unsigned int cpu)
{
- struct tmigr_hierarchy *hier;
- struct tmigr_group *old_root;
+ struct tmigr_group *old_root = tmigr_root;
int node = cpu_to_node(cpu);
int ret;
guard(mutex)(&tmigr_mutex);
- hier = tmigr_get_hierarchy(cpu);
- if (IS_ERR(hier))
- return PTR_ERR(hier);
-
- old_root = hier->root;
-
- ret = tmigr_setup_groups(hier, cpu, node, NULL, false);
-
- if (ret < 0)
- return ret;
+ ret = tmigr_setup_groups(cpu, node, NULL, false);
/* Root has changed? Connect the old one to the new */
- if (old_root && old_root != hier->root) {
- guard(migrate)();
-
- if (cpumask_test_cpu(smp_processor_id(), hier->cpumask)) {
- /*
- * If the target belong to the same hierarchy, the old root is expected
- * to be active. Link and propagate to the new root.
- */
- ret = tmigr_connect_old_root(hier, cpu, old_root, true);
- } else {
- int target = cpumask_first_and(hier->cpumask, tmigr_available_cpumask);
-
- if (target < nr_cpu_ids) {
- /*
- * If the target doesn't belong to the same hierarchy as the current
- * CPU, activate from a relevant one to make sure the old root is
- * active.
- */
- ret = work_on_cpu(target, connect_old_root_work, old_root);
- } else {
- /*
- * No other available CPUs in the remote hierarchy. Link the
- * old root remotely but don't propagate activation since the
- * old root is not expected to be active.
- */
- ret = tmigr_connect_old_root(hier, cpu, old_root, false);
- }
- }
+ if (ret >= 0 && old_root && old_root != tmigr_root) {
+ /*
+ * The target CPU must never do the prepare work, except
+ * on early boot when the boot CPU is the target. Otherwise
+ * it may spuriously activate the old top level group inside
+ * the new one (nevertheless whether old top level group is
+ * active or not) and/or release an uninitialized childmask.
+ */
+ WARN_ON_ONCE(cpu == raw_smp_processor_id());
+ /*
+ * The (likely) current CPU is expected to be online in the hierarchy,
+ * otherwise the old root may not be active as expected.
+ */
+ WARN_ON_ONCE(!per_cpu_ptr(&tmigr_cpu, raw_smp_processor_id())->available);
+ ret = tmigr_setup_groups(-1, old_root->numa_node, old_root, true);
}
- if (ret >= 0)
- cpumask_set_cpu(cpu, hier->cpumask);
-
return ret;
}
@@ -2107,7 +1974,7 @@ static int tmigr_cpu_prepare(unsigned int cpu)
static int __init tmigr_init(void)
{
- unsigned int cpulvl, nodelvl, cpus_per_node;
+ unsigned int cpulvl, nodelvl, cpus_per_node, i;
unsigned int nnodes = num_possible_nodes();
unsigned int ncpus = num_possible_cpus();
int ret = -ENOMEM;
@@ -2154,6 +2021,14 @@ static int __init tmigr_init(void)
*/
tmigr_crossnode_level = cpulvl;
+ tmigr_level_list = kzalloc_objs(struct list_head,
+ tmigr_hierarchy_levels);
+ if (!tmigr_level_list)
+ goto err;
+
+ for (i = 0; i < tmigr_hierarchy_levels; i++)
+ INIT_LIST_HEAD(&tmigr_level_list[i]);
+
pr_info("Timer migration: %d hierarchy levels; %d children per group;"
" %d crossnode level\n",
tmigr_hierarchy_levels, TMIGR_CHILDREN_PER_GROUP,
diff --git a/kernel/time/timer_migration.h b/kernel/time/timer_migration.h
index 31735dd52327..4c0073f3d321 100644
--- a/kernel/time/timer_migration.h
+++ b/kernel/time/timer_migration.h
@@ -5,24 +5,6 @@
/* Per group capacity. Must be a power of 2! */
#define TMIGR_CHILDREN_PER_GROUP 8
-/**
- * struct tmigr_hierarchy - a hierarchy associated to a given CPU capacity.
- * Homogeneous systems have only one hierarchy.
- * Heterogenous have one hierarchy per CPU capacity.
- * @cpumask: CPUs belonging to this hierarchy
- * @root: The current root of the hierarchy
- * @capacity: CPU capacity associated to this hierarchy
- * @node: Node in the global hierarchy list
- * @level_list: Per level lists of tmigr groups
- */
-struct tmigr_hierarchy {
- struct cpumask *cpumask;
- struct tmigr_group *root;
- unsigned long capacity;
- struct list_head node;
- struct list_head level_list[];
-};
-
/**
* struct tmigr_event - a timer event associated to a CPU
* @nextevt: The node to enqueue an event in the parent group queue
diff --git a/scripts/timer_migration_tree.py b/scripts/timer_migration_tree.py
index faac9de854bd..abb321b903c4 100755
--- a/scripts/timer_migration_tree.py
+++ b/scripts/timer_migration_tree.py
@@ -12,6 +12,7 @@ import re, sys
from ete3 import Tree
class Node:
+ node_list = { }
def __init__(self, group):
self.group = group
self.children = []
@@ -45,29 +46,21 @@ class Node:
parent_grp = "-"
return "Group: %s mask: %s parent: %s lvl: %d numa: %d num_children: %d" % (self.group, self.groupmask, parent_grp, self.lvl, self.numa, self.num_children)
-hierarchies = { }
-
-def get_hierarchy(capacity):
- if capacity not in hierarchies:
- hierarchies[capacity] = {}
- return hierarchies[capacity]
-
-def get_node(capacity, group):
- hier = get_hierarchy(capacity)
- if group in hier:
- return hier[group]
+def get_node(group):
+ if group in Node.node_list:
+ return Node.node_list[group]
else:
n = Node(group)
- hier[group] = n
+ Node.node_list[group] = n
return n
def tmigr_connect_cpu_parent(ts, line):
- s = re.search("tmigr_connect_cpu_parent: cpu=([0-9]+) groupmask=([0-9a-zA-Z]+) parent=([0-9a-zA-Z]+) lvl=([0-9]+) numa=([-]?[0-9]+) capacity=([-]?[0-9]+) num_children=([0-9]+)", line)
+ s = re.search("tmigr_connect_cpu_parent: cpu=([0-9]+) groupmask=([0-9a-zA-Z]+) parent=([0-9a-zA-Z]+) lvl=([0-9]+) numa=([-]?[0-9]+) num_children=([0-9]+)", line)
if s is None:
return False
- (cpu, groupmask, parent, lvl, numa, capacity, num_children) = (int(s.group(1)), s.group(2), s.group(3), int(s.group(4)), int(s.group(5)), int(s.group(6)), int(s.group(7)))
- n = get_node(capacity, cpu)
- p = get_node(capacity, parent)
+ (cpu, groupmask, parent, lvl, numa, num_children) = (int(s.group(1)), s.group(2), s.group(3), int(s.group(4)), int(s.group(5)), int(s.group(6)))
+ n = get_node(cpu)
+ p = get_node(parent)
n.set_parent(p)
n.set_groupmask(groupmask)
n.set_lvl(-1)
@@ -78,12 +71,12 @@ def tmigr_connect_cpu_parent(ts, line):
p.add_child(n)
def tmigr_connect_child_parent(ts, line):
- s = re.search("tmigr_connect_child_parent: group=([0-9a-zA-Z]+) groupmask=([0-9a-zA-Z]+) parent=([0-9a-zA-Z]+) lvl=([0-9]+) numa=([-]?[0-9]+) capacity=([-]?[0-9]+) num_children=([0-9]+)", line)
+ s = re.search("tmigr_connect_child_parent: group=([0-9a-zA-Z]+) groupmask=([0-9a-zA-Z]+) parent=([0-9a-zA-Z]+) lvl=([0-9]+) numa=([-]?[0-9]+) num_children=([0-9]+)", line)
if s is None:
return False
- (group, groupmask, parent, lvl, numa, capacity, num_children) = (s.group(1), s.group(2), s.group(3), int(s.group(4)), int(s.group(5)), int(s.group(6)), int(s.group(7)))
- n = get_node(capacity, group)
- p = get_node(capacity, parent)
+ (group, groupmask, parent, lvl, numa, num_children) = (s.group(1), s.group(2), s.group(3), int(s.group(4)), int(s.group(5)), int(s.group(6)))
+ n = get_node(group)
+ p = get_node(parent)
n.set_parent(p)
n.set_groupmask(groupmask)
p.set_lvl(lvl)
@@ -109,14 +102,9 @@ if __name__ == "__main__":
if tmigr_connect_child_parent(float(s.group(1)), s.group(2)):
continue
- for cap in hierarchies:
- h = hierarchies[cap]
- print("Tree for capacity %d" % cap)
- for k in h:
- n = h[k]
- while n.parent != None:
- n = n.parent
- root = Tree()
- populate(root, n)
- print(root.get_ascii(show_internal=True, attributes=["name", "numa", "lvl"]))
- break
+ group = list(Node.node_list.values())[0]
+ while group.parent != None:
+ group = group.parent
+ root = Tree()
+ populate(root, group)
+ print(root.get_ascii(show_internal=True, attributes=["name", "numa", "lvl"]))
--
2.53.0
next prev parent reply other threads:[~2026-06-25 16:41 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-06-25 16:41 [RFT][DONOTMERGE][PATCH 0/6] timers/migration: Prioritize lower capacity CPUs as migrators Frederic Weisbecker
2026-06-25 16:41 ` Frederic Weisbecker [this message]
2026-06-25 16:41 ` [PATCH 2/6] timers/migration: Defer initialization after capacity topology is setup Frederic Weisbecker
2026-06-25 16:41 ` [PATCH 3/6] sched/topology: Account asym capacities number Frederic Weisbecker
2026-06-25 16:41 ` [PATCH 4/6] timers/migration: Group CPUs per capacity Frederic Weisbecker
2026-06-25 16:41 ` [PATCH 5/6] timers/migration: Prefer lower capacity groups as migrators Frederic Weisbecker
2026-06-25 16:41 ` [PATCH 6/6] scripts/timer_migration_tree.py: Dump mask of each group Frederic Weisbecker
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260625164114.51454-2-frederic@kernel.org \
--to=frederic@kernel.org \
--cc=anna-maria@linutronix.de \
--cc=christian.loehle@arm.com \
--cc=linux-kernel@vger.kernel.org \
--cc=peterz@infradead.org \
--cc=sehee1.jeong@samsung.com \
--cc=tglx@linutronix.de \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox