Merge branch 'smp-hotplug-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip

Pull CPU hotplug updates from Thomas Gleixner:
 "Yet another batch of cpu hotplug core updates and conversions:

   - Provide core infrastructure for multi instance drivers so the
     drivers do not have to keep custom lists.

   - Convert custom lists to the new infrastructure. The block-mq custom
     list conversion comes through the block tree and makes the diffstat
     tip over to more lines removed than added.

   - Handle unbalanced hotplug enable/disable calls more gracefully.

   - Remove the obsolete CPU_STARTING/DYING notifier support.

   - Convert another batch of notifier users.

   The relayfs changes which conflicted with the conversion have been
   shipped to me by Andrew.

   The remaining lot is targeted for 4.10 so that we finally can remove
   the rest of the notifiers"

* 'smp-hotplug-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: (46 commits)
  cpufreq: Fix up conversion to hotplug state machine
  blk/mq: Reserve hotplug states for block multiqueue
  x86/apic/uv: Convert to hotplug state machine
  s390/mm/pfault: Convert to hotplug state machine
  mips/loongson/smp: Convert to hotplug state machine
  mips/octeon/smp: Convert to hotplug state machine
  fault-injection/cpu: Convert to hotplug state machine
  padata: Convert to hotplug state machine
  cpufreq: Convert to hotplug state machine
  ACPI/processor: Convert to hotplug state machine
  virtio scsi: Convert to hotplug state machine
  oprofile/timer: Convert to hotplug state machine
  block/softirq: Convert to hotplug state machine
  lib/irq_poll: Convert to hotplug state machine
  x86/microcode: Convert to hotplug state machine
  sh/SH-X3 SMP: Convert to hotplug state machine
  ia64/mca: Convert to hotplug state machine
  ARM/OMAP/wakeupgen: Convert to hotplug state machine
  ARM/shmobile: Convert to hotplug state machine
  arm64/FP/SIMD: Convert to hotplug state machine
  ...
This commit is contained in:
Linus Torvalds
2016-10-03 19:43:08 -07:00
50 changed files with 1461 additions and 1384 deletions

View File

@@ -749,65 +749,52 @@ static void cpuidle_coupled_allow_idle(struct cpuidle_coupled *coupled)
put_cpu();
}
/**
* cpuidle_coupled_cpu_notify - notifier called during hotplug transitions
* @nb: notifier block
* @action: hotplug transition
* @hcpu: target cpu number
*
* Called when a cpu is brought on or offline using hotplug. Updates the
* coupled cpu set appropriately
*/
static int cpuidle_coupled_cpu_notify(struct notifier_block *nb,
unsigned long action, void *hcpu)
static int coupled_cpu_online(unsigned int cpu)
{
int cpu = (unsigned long)hcpu;
struct cpuidle_device *dev;
switch (action & ~CPU_TASKS_FROZEN) {
case CPU_UP_PREPARE:
case CPU_DOWN_PREPARE:
case CPU_ONLINE:
case CPU_DEAD:
case CPU_UP_CANCELED:
case CPU_DOWN_FAILED:
break;
default:
return NOTIFY_OK;
}
mutex_lock(&cpuidle_lock);
dev = per_cpu(cpuidle_devices, cpu);
if (!dev || !dev->coupled)
goto out;
switch (action & ~CPU_TASKS_FROZEN) {
case CPU_UP_PREPARE:
case CPU_DOWN_PREPARE:
cpuidle_coupled_prevent_idle(dev->coupled);
break;
case CPU_ONLINE:
case CPU_DEAD:
if (dev && dev->coupled) {
cpuidle_coupled_update_online_cpus(dev->coupled);
/* Fall through */
case CPU_UP_CANCELED:
case CPU_DOWN_FAILED:
cpuidle_coupled_allow_idle(dev->coupled);
break;
}
out:
mutex_unlock(&cpuidle_lock);
return NOTIFY_OK;
return 0;
}
static struct notifier_block cpuidle_coupled_cpu_notifier = {
.notifier_call = cpuidle_coupled_cpu_notify,
};
static int coupled_cpu_up_prepare(unsigned int cpu)
{
struct cpuidle_device *dev;
mutex_lock(&cpuidle_lock);
dev = per_cpu(cpuidle_devices, cpu);
if (dev && dev->coupled)
cpuidle_coupled_prevent_idle(dev->coupled);
mutex_unlock(&cpuidle_lock);
return 0;
}
static int __init cpuidle_coupled_init(void)
{
return register_cpu_notifier(&cpuidle_coupled_cpu_notifier);
int ret;
ret = cpuhp_setup_state_nocalls(CPUHP_CPUIDLE_COUPLED_PREPARE,
"cpuidle/coupled:prepare",
coupled_cpu_up_prepare,
coupled_cpu_online);
if (ret)
return ret;
ret = cpuhp_setup_state_nocalls(CPUHP_AP_ONLINE_DYN,
"cpuidle/coupled:online",
coupled_cpu_online,
coupled_cpu_up_prepare);
if (ret < 0)
cpuhp_remove_state_nocalls(CPUHP_CPUIDLE_COUPLED_PREPARE);
return ret;
}
core_initcall(cpuidle_coupled_init);

View File

@@ -119,39 +119,29 @@ static struct cpuidle_state powernv_states[CPUIDLE_STATE_MAX] = {
.enter = snooze_loop },
};
static int powernv_cpuidle_add_cpu_notifier(struct notifier_block *n,
unsigned long action, void *hcpu)
static int powernv_cpuidle_cpu_online(unsigned int cpu)
{
int hotcpu = (unsigned long)hcpu;
struct cpuidle_device *dev =
per_cpu(cpuidle_devices, hotcpu);
struct cpuidle_device *dev = per_cpu(cpuidle_devices, cpu);
if (dev && cpuidle_get_driver()) {
switch (action) {
case CPU_ONLINE:
case CPU_ONLINE_FROZEN:
cpuidle_pause_and_lock();
cpuidle_enable_device(dev);
cpuidle_resume_and_unlock();
break;
case CPU_DEAD:
case CPU_DEAD_FROZEN:
cpuidle_pause_and_lock();
cpuidle_disable_device(dev);
cpuidle_resume_and_unlock();
break;
default:
return NOTIFY_DONE;
}
cpuidle_pause_and_lock();
cpuidle_enable_device(dev);
cpuidle_resume_and_unlock();
}
return NOTIFY_OK;
return 0;
}
static struct notifier_block setup_hotplug_notifier = {
.notifier_call = powernv_cpuidle_add_cpu_notifier,
};
static int powernv_cpuidle_cpu_dead(unsigned int cpu)
{
struct cpuidle_device *dev = per_cpu(cpuidle_devices, cpu);
if (dev && cpuidle_get_driver()) {
cpuidle_pause_and_lock();
cpuidle_disable_device(dev);
cpuidle_resume_and_unlock();
}
return 0;
}
/*
* powernv_cpuidle_driver_init()
@@ -355,7 +345,14 @@ static int __init powernv_processor_idle_init(void)
return retval;
}
register_cpu_notifier(&setup_hotplug_notifier);
retval = cpuhp_setup_state_nocalls(CPUHP_AP_ONLINE_DYN,
"cpuidle/powernv:online",
powernv_cpuidle_cpu_online, NULL);
WARN_ON(retval < 0);
retval = cpuhp_setup_state_nocalls(CPUHP_CPUIDLE_DEAD,
"cpuidle/powernv:dead", NULL,
powernv_cpuidle_cpu_dead);
WARN_ON(retval < 0);
printk(KERN_DEBUG "powernv_idle_driver registered\n");
return 0;
}

View File

@@ -171,39 +171,29 @@ static struct cpuidle_state shared_states[] = {
.enter = &shared_cede_loop },
};
static int pseries_cpuidle_add_cpu_notifier(struct notifier_block *n,
unsigned long action, void *hcpu)
static int pseries_cpuidle_cpu_online(unsigned int cpu)
{
int hotcpu = (unsigned long)hcpu;
struct cpuidle_device *dev =
per_cpu(cpuidle_devices, hotcpu);
struct cpuidle_device *dev = per_cpu(cpuidle_devices, cpu);
if (dev && cpuidle_get_driver()) {
switch (action) {
case CPU_ONLINE:
case CPU_ONLINE_FROZEN:
cpuidle_pause_and_lock();
cpuidle_enable_device(dev);
cpuidle_resume_and_unlock();
break;
case CPU_DEAD:
case CPU_DEAD_FROZEN:
cpuidle_pause_and_lock();
cpuidle_disable_device(dev);
cpuidle_resume_and_unlock();
break;
default:
return NOTIFY_DONE;
}
cpuidle_pause_and_lock();
cpuidle_enable_device(dev);
cpuidle_resume_and_unlock();
}
return NOTIFY_OK;
return 0;
}
static struct notifier_block setup_hotplug_notifier = {
.notifier_call = pseries_cpuidle_add_cpu_notifier,
};
static int pseries_cpuidle_cpu_dead(unsigned int cpu)
{
struct cpuidle_device *dev = per_cpu(cpuidle_devices, cpu);
if (dev && cpuidle_get_driver()) {
cpuidle_pause_and_lock();
cpuidle_disable_device(dev);
cpuidle_resume_and_unlock();
}
return 0;
}
/*
* pseries_cpuidle_driver_init()
@@ -273,7 +263,14 @@ static int __init pseries_processor_idle_init(void)
return retval;
}
register_cpu_notifier(&setup_hotplug_notifier);
retval = cpuhp_setup_state_nocalls(CPUHP_AP_ONLINE_DYN,
"cpuidle/pseries:online",
pseries_cpuidle_cpu_online, NULL);
WARN_ON(retval < 0);
retval = cpuhp_setup_state_nocalls(CPUHP_CPUIDLE_DEAD,
"cpuidle/pseries:DEAD", NULL,
pseries_cpuidle_cpu_dead);
WARN_ON(retval < 0);
printk(KERN_DEBUG "pseries_idle_driver registered\n");
return 0;
}