summaryrefslogtreecommitdiffstats
path: root/drivers/bus
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2016-10-03 22:43:08 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2016-10-03 22:43:08 -0400
commit597f03f9d133e9837d00965016170271d4f87dcf (patch)
tree33bdb5c1104d5b466387f4ae98748c5f4ddd29bb /drivers/bus
parent999dcbe2414e15e19cdc1f91497d01f262c6e1cf (diff)
parent0bf71e4d02ffec8ab9a6adecca61d3eed74fc99d (diff)
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 ...
Diffstat (limited to 'drivers/bus')
-rw-r--r--drivers/bus/arm-cci.c45
-rw-r--r--drivers/bus/arm-ccn.c54
-rw-r--r--drivers/bus/mips_cdmm.c70
3 files changed, 51 insertions, 118 deletions
diff --git a/drivers/bus/arm-cci.c b/drivers/bus/arm-cci.c
index ffa7c9dcbd7a..890082315054 100644
--- a/drivers/bus/arm-cci.c
+++ b/drivers/bus/arm-cci.c
@@ -144,15 +144,12 @@ struct cci_pmu {
144 int num_cntrs; 144 int num_cntrs;
145 atomic_t active_events; 145 atomic_t active_events;
146 struct mutex reserve_mutex; 146 struct mutex reserve_mutex;
147 struct list_head entry; 147 struct hlist_node node;
148 cpumask_t cpus; 148 cpumask_t cpus;
149}; 149};
150 150
151#define to_cci_pmu(c) (container_of(c, struct cci_pmu, pmu)) 151#define to_cci_pmu(c) (container_of(c, struct cci_pmu, pmu))
152 152
153static DEFINE_MUTEX(cci_pmu_mutex);
154static LIST_HEAD(cci_pmu_list);
155
156enum cci_models { 153enum cci_models {
157#ifdef CONFIG_ARM_CCI400_PMU 154#ifdef CONFIG_ARM_CCI400_PMU
158 CCI400_R0, 155 CCI400_R0,
@@ -1506,25 +1503,21 @@ static int cci_pmu_init(struct cci_pmu *cci_pmu, struct platform_device *pdev)
1506 return perf_pmu_register(&cci_pmu->pmu, name, -1); 1503 return perf_pmu_register(&cci_pmu->pmu, name, -1);
1507} 1504}
1508 1505
1509static int cci_pmu_offline_cpu(unsigned int cpu) 1506static int cci_pmu_offline_cpu(unsigned int cpu, struct hlist_node *node)
1510{ 1507{
1511 struct cci_pmu *cci_pmu; 1508 struct cci_pmu *cci_pmu = hlist_entry_safe(node, struct cci_pmu, node);
1512 unsigned int target; 1509 unsigned int target;
1513 1510
1514 mutex_lock(&cci_pmu_mutex); 1511 if (!cpumask_test_and_clear_cpu(cpu, &cci_pmu->cpus))
1515 list_for_each_entry(cci_pmu, &cci_pmu_list, entry) { 1512 return 0;
1516 if (!cpumask_test_and_clear_cpu(cpu, &cci_pmu->cpus)) 1513 target = cpumask_any_but(cpu_online_mask, cpu);
1517 continue; 1514 if (target >= nr_cpu_ids)
1518 target = cpumask_any_but(cpu_online_mask, cpu); 1515 return 0;
1519 if (target >= nr_cpu_ids) 1516 /*
1520 continue; 1517 * TODO: migrate context once core races on event->ctx have
1521 /* 1518 * been fixed.
1522 * TODO: migrate context once core races on event->ctx have 1519 */
1523 * been fixed. 1520 cpumask_set_cpu(target, &cci_pmu->cpus);
1524 */
1525 cpumask_set_cpu(target, &cci_pmu->cpus);
1526 }
1527 mutex_unlock(&cci_pmu_mutex);
1528 return 0; 1521 return 0;
1529} 1522}
1530 1523
@@ -1768,10 +1761,8 @@ static int cci_pmu_probe(struct platform_device *pdev)
1768 if (ret) 1761 if (ret)
1769 return ret; 1762 return ret;
1770 1763
1771 mutex_lock(&cci_pmu_mutex); 1764 cpuhp_state_add_instance_nocalls(CPUHP_AP_PERF_ARM_CCI_ONLINE,
1772 list_add(&cci_pmu->entry, &cci_pmu_list); 1765 &cci_pmu->node);
1773 mutex_unlock(&cci_pmu_mutex);
1774
1775 pr_info("ARM %s PMU driver probed", cci_pmu->model->name); 1766 pr_info("ARM %s PMU driver probed", cci_pmu->model->name);
1776 return 0; 1767 return 0;
1777} 1768}
@@ -1804,9 +1795,9 @@ static int __init cci_platform_init(void)
1804{ 1795{
1805 int ret; 1796 int ret;
1806 1797
1807 ret = cpuhp_setup_state_nocalls(CPUHP_AP_PERF_ARM_CCI_ONLINE, 1798 ret = cpuhp_setup_state_multi(CPUHP_AP_PERF_ARM_CCI_ONLINE,
1808 "AP_PERF_ARM_CCI_ONLINE", NULL, 1799 "AP_PERF_ARM_CCI_ONLINE", NULL,
1809 cci_pmu_offline_cpu); 1800 cci_pmu_offline_cpu);
1810 if (ret) 1801 if (ret)
1811 return ret; 1802 return ret;
1812 1803
diff --git a/drivers/bus/arm-ccn.c b/drivers/bus/arm-ccn.c
index 884c0305e290..d1074d9b38ba 100644
--- a/drivers/bus/arm-ccn.c
+++ b/drivers/bus/arm-ccn.c
@@ -167,7 +167,7 @@ struct arm_ccn_dt {
167 struct hrtimer hrtimer; 167 struct hrtimer hrtimer;
168 168
169 cpumask_t cpu; 169 cpumask_t cpu;
170 struct list_head entry; 170 struct hlist_node node;
171 171
172 struct pmu pmu; 172 struct pmu pmu;
173}; 173};
@@ -190,9 +190,6 @@ struct arm_ccn {
190 int mn_id; 190 int mn_id;
191}; 191};
192 192
193static DEFINE_MUTEX(arm_ccn_mutex);
194static LIST_HEAD(arm_ccn_list);
195
196static int arm_ccn_node_to_xp(int node) 193static int arm_ccn_node_to_xp(int node)
197{ 194{
198 return node / CCN_NUM_XP_PORTS; 195 return node / CCN_NUM_XP_PORTS;
@@ -1214,30 +1211,24 @@ static enum hrtimer_restart arm_ccn_pmu_timer_handler(struct hrtimer *hrtimer)
1214} 1211}
1215 1212
1216 1213
1217static int arm_ccn_pmu_offline_cpu(unsigned int cpu) 1214static int arm_ccn_pmu_offline_cpu(unsigned int cpu, struct hlist_node *node)
1218{ 1215{
1219 struct arm_ccn_dt *dt; 1216 struct arm_ccn_dt *dt = hlist_entry_safe(node, struct arm_ccn_dt, node);
1217 struct arm_ccn *ccn = container_of(dt, struct arm_ccn, dt);
1220 unsigned int target; 1218 unsigned int target;
1221 1219
1222 mutex_lock(&arm_ccn_mutex); 1220 if (!cpumask_test_and_clear_cpu(cpu, &dt->cpu))
1223 list_for_each_entry(dt, &arm_ccn_list, entry) { 1221 return 0;
1224 struct arm_ccn *ccn = container_of(dt, struct arm_ccn, dt); 1222 target = cpumask_any_but(cpu_online_mask, cpu);
1225 1223 if (target >= nr_cpu_ids)
1226 if (!cpumask_test_and_clear_cpu(cpu, &dt->cpu)) 1224 return 0;
1227 continue; 1225 perf_pmu_migrate_context(&dt->pmu, cpu, target);
1228 target = cpumask_any_but(cpu_online_mask, cpu); 1226 cpumask_set_cpu(target, &dt->cpu);
1229 if (target >= nr_cpu_ids) 1227 if (ccn->irq)
1230 continue; 1228 WARN_ON(irq_set_affinity_hint(ccn->irq, &dt->cpu) != 0);
1231 perf_pmu_migrate_context(&dt->pmu, cpu, target);
1232 cpumask_set_cpu(target, &dt->cpu);
1233 if (ccn->irq)
1234 WARN_ON(irq_set_affinity_hint(ccn->irq, &dt->cpu) != 0);
1235 }
1236 mutex_unlock(&arm_ccn_mutex);
1237 return 0; 1229 return 0;
1238} 1230}
1239 1231
1240
1241static DEFINE_IDA(arm_ccn_pmu_ida); 1232static DEFINE_IDA(arm_ccn_pmu_ida);
1242 1233
1243static int arm_ccn_pmu_init(struct arm_ccn *ccn) 1234static int arm_ccn_pmu_init(struct arm_ccn *ccn)
@@ -1321,9 +1312,8 @@ static int arm_ccn_pmu_init(struct arm_ccn *ccn)
1321 if (err) 1312 if (err)
1322 goto error_pmu_register; 1313 goto error_pmu_register;
1323 1314
1324 mutex_lock(&arm_ccn_mutex); 1315 cpuhp_state_add_instance_nocalls(CPUHP_AP_PERF_ARM_CCN_ONLINE,
1325 list_add(&ccn->dt.entry, &arm_ccn_list); 1316 &ccn->dt.node);
1326 mutex_unlock(&arm_ccn_mutex);
1327 return 0; 1317 return 0;
1328 1318
1329error_pmu_register: 1319error_pmu_register:
@@ -1339,10 +1329,8 @@ static void arm_ccn_pmu_cleanup(struct arm_ccn *ccn)
1339{ 1329{
1340 int i; 1330 int i;
1341 1331
1342 mutex_lock(&arm_ccn_mutex); 1332 cpuhp_state_remove_instance_nocalls(CPUHP_AP_PERF_ARM_CCN_ONLINE,
1343 list_del(&ccn->dt.entry); 1333 &ccn->dt.node);
1344 mutex_unlock(&arm_ccn_mutex);
1345
1346 if (ccn->irq) 1334 if (ccn->irq)
1347 irq_set_affinity_hint(ccn->irq, NULL); 1335 irq_set_affinity_hint(ccn->irq, NULL);
1348 for (i = 0; i < ccn->num_xps; i++) 1336 for (i = 0; i < ccn->num_xps; i++)
@@ -1573,9 +1561,9 @@ static int __init arm_ccn_init(void)
1573{ 1561{
1574 int i, ret; 1562 int i, ret;
1575 1563
1576 ret = cpuhp_setup_state_nocalls(CPUHP_AP_PERF_ARM_CCN_ONLINE, 1564 ret = cpuhp_setup_state_multi(CPUHP_AP_PERF_ARM_CCN_ONLINE,
1577 "AP_PERF_ARM_CCN_ONLINE", NULL, 1565 "AP_PERF_ARM_CCN_ONLINE", NULL,
1578 arm_ccn_pmu_offline_cpu); 1566 arm_ccn_pmu_offline_cpu);
1579 if (ret) 1567 if (ret)
1580 return ret; 1568 return ret;
1581 1569
@@ -1587,7 +1575,7 @@ static int __init arm_ccn_init(void)
1587 1575
1588static void __exit arm_ccn_exit(void) 1576static void __exit arm_ccn_exit(void)
1589{ 1577{
1590 cpuhp_remove_state_nocalls(CPUHP_AP_PERF_ARM_CCN_ONLINE); 1578 cpuhp_remove_multi_state(CPUHP_AP_PERF_ARM_CCN_ONLINE);
1591 platform_driver_unregister(&arm_ccn_driver); 1579 platform_driver_unregister(&arm_ccn_driver);
1592} 1580}
1593 1581
diff --git a/drivers/bus/mips_cdmm.c b/drivers/bus/mips_cdmm.c
index cad49bc38b3e..1b14256376d2 100644
--- a/drivers/bus/mips_cdmm.c
+++ b/drivers/bus/mips_cdmm.c
@@ -596,19 +596,20 @@ BUILD_PERDEV_HELPER(cpu_down) /* int mips_cdmm_cpu_down_helper(...) */
596BUILD_PERDEV_HELPER(cpu_up) /* int mips_cdmm_cpu_up_helper(...) */ 596BUILD_PERDEV_HELPER(cpu_up) /* int mips_cdmm_cpu_up_helper(...) */
597 597
598/** 598/**
599 * mips_cdmm_bus_down() - Tear down the CDMM bus. 599 * mips_cdmm_cpu_down_prep() - Callback for CPUHP DOWN_PREP:
600 * @data: Pointer to unsigned int CPU number. 600 * Tear down the CDMM bus.
601 * @cpu: unsigned int CPU number.
601 * 602 *
602 * This function is executed on the hotplugged CPU and calls the CDMM 603 * This function is executed on the hotplugged CPU and calls the CDMM
603 * driver cpu_down callback for all devices on that CPU. 604 * driver cpu_down callback for all devices on that CPU.
604 */ 605 */
605static long mips_cdmm_bus_down(void *data) 606static int mips_cdmm_cpu_down_prep(unsigned int cpu)
606{ 607{
607 struct mips_cdmm_bus *bus; 608 struct mips_cdmm_bus *bus;
608 long ret; 609 long ret;
609 610
610 /* Inform all the devices on the bus */ 611 /* Inform all the devices on the bus */
611 ret = bus_for_each_dev(&mips_cdmm_bustype, NULL, data, 612 ret = bus_for_each_dev(&mips_cdmm_bustype, NULL, &cpu,
612 mips_cdmm_cpu_down_helper); 613 mips_cdmm_cpu_down_helper);
613 614
614 /* 615 /*
@@ -623,8 +624,8 @@ static long mips_cdmm_bus_down(void *data)
623} 624}
624 625
625/** 626/**
626 * mips_cdmm_bus_up() - Bring up the CDMM bus. 627 * mips_cdmm_cpu_online() - Callback for CPUHP ONLINE: Bring up the CDMM bus.
627 * @data: Pointer to unsigned int CPU number. 628 * @cpu: unsigned int CPU number.
628 * 629 *
629 * This work_on_cpu callback function is executed on a given CPU to discover 630 * This work_on_cpu callback function is executed on a given CPU to discover
630 * CDMM devices on that CPU, or to call the CDMM driver cpu_up callback for all 631 * CDMM devices on that CPU, or to call the CDMM driver cpu_up callback for all
@@ -634,7 +635,7 @@ static long mips_cdmm_bus_down(void *data)
634 * initialisation. When CPUs are brought online the function is 635 * initialisation. When CPUs are brought online the function is
635 * invoked directly on the hotplugged CPU. 636 * invoked directly on the hotplugged CPU.
636 */ 637 */
637static long mips_cdmm_bus_up(void *data) 638static int mips_cdmm_cpu_online(unsigned int cpu)
638{ 639{
639 struct mips_cdmm_bus *bus; 640 struct mips_cdmm_bus *bus;
640 long ret; 641 long ret;
@@ -651,51 +652,13 @@ static long mips_cdmm_bus_up(void *data)
651 mips_cdmm_bus_discover(bus); 652 mips_cdmm_bus_discover(bus);
652 else 653 else
653 /* Inform all the devices on the bus */ 654 /* Inform all the devices on the bus */
654 ret = bus_for_each_dev(&mips_cdmm_bustype, NULL, data, 655 ret = bus_for_each_dev(&mips_cdmm_bustype, NULL, &cpu,
655 mips_cdmm_cpu_up_helper); 656 mips_cdmm_cpu_up_helper);
656 657
657 return ret; 658 return ret;
658} 659}
659 660
660/** 661/**
661 * mips_cdmm_cpu_notify() - Take action when a CPU is going online or offline.
662 * @nb: CPU notifier block .
663 * @action: Event that has taken place (CPU_*).
664 * @data: CPU number.
665 *
666 * This notifier is used to keep the CDMM buses updated as CPUs are offlined and
667 * onlined. When CPUs go offline or come back online, so does their CDMM bus, so
668 * devices must be informed. Also when CPUs come online for the first time the
669 * devices on the CDMM bus need discovering.
670 *
671 * Returns: NOTIFY_OK if event was used.
672 * NOTIFY_DONE if we didn't care.
673 */
674static int mips_cdmm_cpu_notify(struct notifier_block *nb,
675 unsigned long action, void *data)
676{
677 unsigned int cpu = (unsigned int)data;
678
679 switch (action & ~CPU_TASKS_FROZEN) {
680 case CPU_ONLINE:
681 case CPU_DOWN_FAILED:
682 mips_cdmm_bus_up(&cpu);
683 break;
684 case CPU_DOWN_PREPARE:
685 mips_cdmm_bus_down(&cpu);
686 break;
687 default:
688 return NOTIFY_DONE;
689 }
690
691 return NOTIFY_OK;
692}
693
694static struct notifier_block mips_cdmm_cpu_nb = {
695 .notifier_call = mips_cdmm_cpu_notify,
696};
697
698/**
699 * mips_cdmm_init() - Initialise CDMM bus. 662 * mips_cdmm_init() - Initialise CDMM bus.
700 * 663 *
701 * Initialise CDMM bus, discover CDMM devices for online CPUs, and arrange for 664 * Initialise CDMM bus, discover CDMM devices for online CPUs, and arrange for
@@ -703,7 +666,6 @@ static struct notifier_block mips_cdmm_cpu_nb = {
703 */ 666 */
704static int __init mips_cdmm_init(void) 667static int __init mips_cdmm_init(void)
705{ 668{
706 unsigned int cpu;
707 int ret; 669 int ret;
708 670
709 /* Register the bus */ 671 /* Register the bus */
@@ -712,19 +674,11 @@ static int __init mips_cdmm_init(void)
712 return ret; 674 return ret;
713 675
714 /* We want to be notified about new CPUs */ 676 /* We want to be notified about new CPUs */
715 ret = register_cpu_notifier(&mips_cdmm_cpu_nb); 677 ret = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "bus/cdmm:online",
716 if (ret) { 678 mips_cdmm_cpu_online, mips_cdmm_cpu_down_prep);
679 if (ret < 0)
717 pr_warn("cdmm: Failed to register CPU notifier\n"); 680 pr_warn("cdmm: Failed to register CPU notifier\n");
718 goto out;
719 }
720
721 /* Discover devices on CDMM of online CPUs */
722 for_each_online_cpu(cpu)
723 work_on_cpu(cpu, mips_cdmm_bus_up, &cpu);
724 681
725 return 0;
726out:
727 bus_unregister(&mips_cdmm_bustype);
728 return ret; 682 return ret;
729} 683}
730subsys_initcall(mips_cdmm_init); 684subsys_initcall(mips_cdmm_init);