* [PATCH v2 2/6] powernv:cpufreq: Create a powernv_cpu_to_core_mask() helper.
From: Gautham R. Shenoy @ 2014-03-10 11:10 UTC (permalink / raw)
To: linuxppc-dev; +Cc: srivatsa.bhat, Gautham R. Shenoy
In-Reply-To: <1394449861-8688-1-git-send-email-ego@linux.vnet.ibm.com>
From: "Srivatsa S. Bhat" <srivatsa.bhat@linux.vnet.ibm.com>
Create a helper method that computes the cpumask corresponding to the
thread-siblings of a cpu. Use this for initializing the policy->cpus
mask for a given cpu.
(Original code written by Srivatsa S. Bhat. Gautham moved this to a
helper function!)
Signed-off-by: Srivatsa S. Bhat <srivatsa.bhat@linux.vnet.ibm.com>
Signed-off-by: Gautham R. Shenoy <ego@linux.vnet.ibm.com>
---
drivers/cpufreq/powernv-cpufreq.c | 24 ++++++++++++++++++------
1 file changed, 18 insertions(+), 6 deletions(-)
diff --git a/drivers/cpufreq/powernv-cpufreq.c b/drivers/cpufreq/powernv-cpufreq.c
index ab1551f..4cad727 100644
--- a/drivers/cpufreq/powernv-cpufreq.c
+++ b/drivers/cpufreq/powernv-cpufreq.c
@@ -115,6 +115,23 @@ static struct freq_attr *powernv_cpu_freq_attr[] = {
/* Helper routines */
+/**
+ * Sets the bits corresponding to the thread-siblings of cpu in its core
+ * in 'cpus'.
+ */
+static void powernv_cpu_to_core_mask(unsigned int cpu, cpumask_var_t cpus)
+{
+ int base, i;
+
+ base = cpu_first_thread_sibling(cpu);
+
+ for (i = 0; i < threads_per_core; i++) {
+ cpumask_set_cpu(base + i, cpus);
+ }
+
+ return;
+}
+
/* Access helpers to power mgt SPR */
static inline unsigned long get_pmspr(unsigned long sprn)
@@ -180,13 +197,8 @@ static int powernv_set_freq(cpumask_var_t cpus, unsigned int new_index)
static int powernv_cpufreq_cpu_init(struct cpufreq_policy *policy)
{
- int base, i;
-
#ifdef CONFIG_SMP
- base = cpu_first_thread_sibling(policy->cpu);
-
- for (i = 0; i < threads_per_core; i++)
- cpumask_set_cpu(base + i, policy->cpus);
+ powernv_cpu_to_core_mask(policy->cpu, policy->cpus);
#endif
policy->cpuinfo.transition_latency = 25000;
--
1.8.3.1
^ permalink raw reply related
* [PATCH v2 3/6] powernv, cpufreq:Add per-core locking to serialize frequency transitions
From: Gautham R. Shenoy @ 2014-03-10 11:10 UTC (permalink / raw)
To: linuxppc-dev; +Cc: srivatsa.bhat, Gautham R. Shenoy
In-Reply-To: <1394449861-8688-1-git-send-email-ego@linux.vnet.ibm.com>
From: "Srivatsa S. Bhat" <srivatsa.bhat@linux.vnet.ibm.com>
On POWER systems, the CPU frequency is controlled at a core-level and
hence we need to serialize so that only one of the threads in the core
switches the core's frequency at a time.
Using a global mutex lock would needlessly serialize _all_ frequency
transitions in the system (across all cores). So introduce per-core
locking to enable finer-grained synchronization and thereby enhance
the speed and responsiveness of the cpufreq driver to varying workload
demands.
The design of per-core locking is very simple and straight-forward: we
first define a Per-CPU lock and use the ones that belongs to the first
thread sibling of the core.
cpu_first_thread_sibling() macro is used to find the *common* lock for
all thread siblings belonging to a core.
Signed-off-by: Srivatsa S. Bhat <srivatsa.bhat@linux.vnet.ibm.com>
Signed-off-by: Vaidyanathan Srinivasan <svaidy@linux.vnet.ibm.com>
Signed-off-by: Gautham R. Shenoy <ego@linux.vnet.ibm.com>
---
drivers/cpufreq/powernv-cpufreq.c | 21 ++++++++++++++++-----
1 file changed, 16 insertions(+), 5 deletions(-)
diff --git a/drivers/cpufreq/powernv-cpufreq.c b/drivers/cpufreq/powernv-cpufreq.c
index 4cad727..4c2e8ca 100644
--- a/drivers/cpufreq/powernv-cpufreq.c
+++ b/drivers/cpufreq/powernv-cpufreq.c
@@ -24,8 +24,15 @@
#include <linux/of.h>
#include <asm/cputhreads.h>
-/* FIXME: Make this per-core */
-static DEFINE_MUTEX(freq_switch_mutex);
+/* Per-Core locking for frequency transitions */
+static DEFINE_PER_CPU(struct mutex, freq_switch_lock);
+
+#define lock_core_freq(cpu) \
+ mutex_lock(&per_cpu(freq_switch_lock,\
+ cpu_first_thread_sibling(cpu)));
+#define unlock_core_freq(cpu) \
+ mutex_unlock(&per_cpu(freq_switch_lock,\
+ cpu_first_thread_sibling(cpu)));
#define POWERNV_MAX_PSTATES 256
@@ -233,7 +240,7 @@ static int powernv_cpufreq_target(struct cpufreq_policy *policy,
freqs.new = powernv_freqs[new_index].frequency;
freqs.cpu = policy->cpu;
- mutex_lock(&freq_switch_mutex);
+ lock_core_freq(policy->cpu);
cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE);
pr_debug("setting frequency for cpu %d to %d kHz index %d pstate %d",
@@ -245,7 +252,7 @@ static int powernv_cpufreq_target(struct cpufreq_policy *policy,
rc = powernv_set_freq(policy->cpus, new_index);
cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE);
- mutex_unlock(&freq_switch_mutex);
+ unlock_core_freq(policy->cpu);
return rc;
}
@@ -262,7 +269,7 @@ static struct cpufreq_driver powernv_cpufreq_driver = {
static int __init powernv_cpufreq_init(void)
{
- int rc = 0;
+ int cpu, rc = 0;
/* Discover pstates from device tree and init */
@@ -272,6 +279,10 @@ static int __init powernv_cpufreq_init(void)
pr_info("powernv-cpufreq disabled\n");
return rc;
}
+ /* Init per-core mutex */
+ for_each_possible_cpu(cpu) {
+ mutex_init(&per_cpu(freq_switch_lock, cpu));
+ }
rc = cpufreq_register_driver(&powernv_cpufreq_driver);
return rc;
--
1.8.3.1
^ permalink raw reply related
* [PATCH v2 5/6] powernv:cpufreq: Export nominal frequency via sysfs.
From: Gautham R. Shenoy @ 2014-03-10 11:11 UTC (permalink / raw)
To: linuxppc-dev; +Cc: srivatsa.bhat, Gautham R. Shenoy
In-Reply-To: <1394449861-8688-1-git-send-email-ego@linux.vnet.ibm.com>
From: "Gautham R. Shenoy" <ego@linux.vnet.ibm.com>
Create a driver attribute named cpuinfo_nominal_freq which
creates a sysfs read-only file named cpuinfo_nominal_freq. Export
the frequency corresponding to the nominal_pstate through this
interface.
Nominal frequency is the highest non-turbo frequency for the
platform. This is generally used for setting governor policies from
user space for optimal energy efficiency.
Signed-off-by: Gautham R. Shenoy <ego@linux.vnet.ibm.com>
---
drivers/cpufreq/powernv-cpufreq.c | 22 ++++++++++++++++++++++
1 file changed, 22 insertions(+)
diff --git a/drivers/cpufreq/powernv-cpufreq.c b/drivers/cpufreq/powernv-cpufreq.c
index 0ecd163..183bbc4 100644
--- a/drivers/cpufreq/powernv-cpufreq.c
+++ b/drivers/cpufreq/powernv-cpufreq.c
@@ -142,8 +142,30 @@ static unsigned int pstate_id_to_freq(int pstate_id)
return powernv_freqs[i].frequency;
}
+/**
+ * show_cpuinfo_nominal_freq - Show the nominal CPU frequency as indicated by
+ * the firmware
+ */
+static ssize_t show_cpuinfo_nominal_freq(struct cpufreq_policy *policy,
+ char *buf)
+{
+ int nominal_freq;
+ nominal_freq = pstate_id_to_freq(powernv_pstate_info.pstate_nominal_id);
+ return sprintf(buf, "%u\n", nominal_freq);
+}
+
+
+struct freq_attr cpufreq_freq_attr_cpuinfo_nominal_freq = {
+ .attr = { .name = "cpuinfo_nominal_freq",
+ .mode = 0444,
+ },
+ .show = show_cpuinfo_nominal_freq,
+};
+
+
static struct freq_attr *powernv_cpu_freq_attr[] = {
&cpufreq_freq_attr_scaling_available_freqs,
+ &cpufreq_freq_attr_cpuinfo_nominal_freq,
NULL,
};
--
1.8.3.1
^ permalink raw reply related
* [PATCH v2 1/6] powernv: cpufreq driver for powernv platform
From: Gautham R. Shenoy @ 2014-03-10 11:10 UTC (permalink / raw)
To: linuxppc-dev; +Cc: Anton Blanchard, srivatsa.bhat, Gautham R. Shenoy
In-Reply-To: <1394449861-8688-1-git-send-email-ego@linux.vnet.ibm.com>
From: Vaidyanathan Srinivasan <svaidy@linux.vnet.ibm.com>
Backend driver to dynamically set voltage and frequency on
IBM POWER non-virtualized platforms. Power management SPRs
are used to set the required PState.
This driver works in conjunction with cpufreq governors
like 'ondemand' to provide a demand based frequency and
voltage setting on IBM POWER non-virtualized platforms.
PState table is obtained from OPAL v3 firmware through device
tree.
powernv_cpufreq back-end driver would parse the relevant device-tree
nodes and initialise the cpufreq subsystem on powernv platform.
Signed-off-by: Vaidyanathan Srinivasan <svaidy@linux.vnet.ibm.com>
Signed-off-by: Srivatsa S. Bhat <srivatsa.bhat@linux.vnet.ibm.com>
Signed-off-by: Anton Blanchard <anton@samba.org>
Signed-off-by: Gautham R. Shenoy <ego@linux.vnet.ibm.com>
---
arch/powerpc/include/asm/reg.h | 4 +
arch/powerpc/platforms/powernv/Kconfig | 1 +
drivers/cpufreq/Kconfig | 1 +
drivers/cpufreq/Kconfig.powerpc | 13 ++
drivers/cpufreq/Makefile | 1 +
drivers/cpufreq/powernv-cpufreq.c | 277 +++++++++++++++++++++++++++++++++
6 files changed, 297 insertions(+)
create mode 100644 drivers/cpufreq/powernv-cpufreq.c
diff --git a/arch/powerpc/include/asm/reg.h b/arch/powerpc/include/asm/reg.h
index 90c06ec..84f92ca 100644
--- a/arch/powerpc/include/asm/reg.h
+++ b/arch/powerpc/include/asm/reg.h
@@ -271,6 +271,10 @@
#define SPRN_HSRR1 0x13B /* Hypervisor Save/Restore 1 */
#define SPRN_IC 0x350 /* Virtual Instruction Count */
#define SPRN_VTB 0x351 /* Virtual Time Base */
+#define SPRN_PMICR 0x354 /* Power Management Idle Control Reg */
+#define SPRN_PMSR 0x355 /* Power Management Status Reg */
+#define SPRN_PMCR 0x374 /* Power Management Control Register */
+
/* HFSCR and FSCR bit numbers are the same */
#define FSCR_TAR_LG 8 /* Enable Target Address Register */
#define FSCR_EBB_LG 7 /* Enable Event Based Branching */
diff --git a/arch/powerpc/platforms/powernv/Kconfig b/arch/powerpc/platforms/powernv/Kconfig
index 895e8a2..1fe12b1 100644
--- a/arch/powerpc/platforms/powernv/Kconfig
+++ b/arch/powerpc/platforms/powernv/Kconfig
@@ -11,6 +11,7 @@ config PPC_POWERNV
select PPC_UDBG_16550
select PPC_SCOM
select ARCH_RANDOM
+ select CPU_FREQ
default y
config PPC_POWERNV_RTAS
diff --git a/drivers/cpufreq/Kconfig b/drivers/cpufreq/Kconfig
index 4b029c0..4ba1632 100644
--- a/drivers/cpufreq/Kconfig
+++ b/drivers/cpufreq/Kconfig
@@ -48,6 +48,7 @@ config CPU_FREQ_STAT_DETAILS
choice
prompt "Default CPUFreq governor"
default CPU_FREQ_DEFAULT_GOV_USERSPACE if ARM_SA1100_CPUFREQ || ARM_SA1110_CPUFREQ
+ default CPU_FREQ_DEFAULT_GOV_ONDEMAND if POWERNV_CPUFREQ
default CPU_FREQ_DEFAULT_GOV_PERFORMANCE
help
This option sets which CPUFreq governor shall be loaded at
diff --git a/drivers/cpufreq/Kconfig.powerpc b/drivers/cpufreq/Kconfig.powerpc
index ca0021a..93f8689 100644
--- a/drivers/cpufreq/Kconfig.powerpc
+++ b/drivers/cpufreq/Kconfig.powerpc
@@ -54,3 +54,16 @@ config PPC_PASEMI_CPUFREQ
help
This adds the support for frequency switching on PA Semi
PWRficient processors.
+
+config POWERNV_CPUFREQ
+ tristate "CPU frequency scaling for IBM POWERNV platform"
+ depends on PPC_POWERNV
+ select CPU_FREQ_GOV_PERFORMANCE
+ select CPU_FREQ_GOV_POWERSAVE
+ select CPU_FREQ_GOV_USERSPACE
+ select CPU_FREQ_GOV_ONDEMAND
+ select CPU_FREQ_GOV_CONSERVATIVE
+ default y
+ help
+ This adds support for CPU frequency switching on IBM POWERNV
+ platform
diff --git a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile
index 7494565..0dbb963 100644
--- a/drivers/cpufreq/Makefile
+++ b/drivers/cpufreq/Makefile
@@ -86,6 +86,7 @@ obj-$(CONFIG_PPC_CORENET_CPUFREQ) += ppc-corenet-cpufreq.o
obj-$(CONFIG_CPU_FREQ_PMAC) += pmac32-cpufreq.o
obj-$(CONFIG_CPU_FREQ_PMAC64) += pmac64-cpufreq.o
obj-$(CONFIG_PPC_PASEMI_CPUFREQ) += pasemi-cpufreq.o
+obj-$(CONFIG_POWERNV_CPUFREQ) += powernv-cpufreq.o
##################################################################################
# Other platform drivers
diff --git a/drivers/cpufreq/powernv-cpufreq.c b/drivers/cpufreq/powernv-cpufreq.c
new file mode 100644
index 0000000..ab1551f
--- /dev/null
+++ b/drivers/cpufreq/powernv-cpufreq.c
@@ -0,0 +1,277 @@
+/*
+ * POWERNV cpufreq driver for the IBM POWER processors
+ *
+ * (C) Copyright IBM 2014
+ *
+ * Author: Vaidyanathan Srinivasan <svaidy at linux.vnet.ibm.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#define pr_fmt(fmt) "powernv-cpufreq: " fmt
+
+#include <linux/module.h>
+#include <linux/cpufreq.h>
+#include <linux/of.h>
+#include <asm/cputhreads.h>
+
+/* FIXME: Make this per-core */
+static DEFINE_MUTEX(freq_switch_mutex);
+
+#define POWERNV_MAX_PSTATES 256
+
+static struct cpufreq_frequency_table powernv_freqs[POWERNV_MAX_PSTATES+1];
+static int powernv_pstate_ids[POWERNV_MAX_PSTATES+1];
+
+/*
+ * Initialize the freq table based on data obtained
+ * from the firmware passed via device-tree
+ */
+
+static int init_powernv_pstates(void)
+{
+ struct device_node *power_mgt;
+ int nr_pstates = 0;
+ int pstate_min, pstate_max, pstate_nominal;
+ const __be32 *pstate_ids, *pstate_freqs;
+ int i;
+ u32 len_ids, len_freqs;
+
+ power_mgt = of_find_node_by_path("/ibm,opal/power-mgt");
+ if (!power_mgt) {
+ pr_warn("power-mgt node not found\n");
+ return -ENODEV;
+ }
+
+ if (of_property_read_u32(power_mgt, "ibm,pstate-min", &pstate_min)) {
+ pr_warn("ibm,pstate-min node not found\n");
+ return -ENODEV;
+ }
+
+ if (of_property_read_u32(power_mgt, "ibm,pstate-max", &pstate_max)) {
+ pr_warn("ibm,pstate-max node not found\n");
+ return -ENODEV;
+ }
+
+ if (of_property_read_u32(power_mgt, "ibm,pstate-nominal",
+ &pstate_nominal)) {
+ pr_warn("ibm,pstate-nominal not found\n");
+ return -ENODEV;
+ }
+ pr_info("cpufreq pstate min %d nominal %d max %d\n", pstate_min,
+ pstate_nominal, pstate_max);
+
+ pstate_ids = of_get_property(power_mgt, "ibm,pstate-ids", &len_ids);
+ if (!pstate_ids) {
+ pr_warn("ibm,pstate-ids not found\n");
+ return -ENODEV;
+ }
+
+ pstate_freqs = of_get_property(power_mgt, "ibm,pstate-frequencies-mhz",
+ &len_freqs);
+ if (!pstate_freqs) {
+ pr_warn("ibm,pstate-frequencies-mhz not found\n");
+ return -ENODEV;
+ }
+
+ WARN_ON(len_ids != len_freqs);
+ nr_pstates = min(len_ids, len_freqs) / sizeof(u32);
+ WARN_ON(!nr_pstates);
+
+ pr_debug("NR PStates %d\n", nr_pstates);
+ for (i = 0; i < nr_pstates; i++) {
+ u32 id = be32_to_cpu(pstate_ids[i]);
+ u32 freq = be32_to_cpu(pstate_freqs[i]);
+
+ pr_debug("PState id %d freq %d MHz\n", id, freq);
+ powernv_freqs[i].driver_data = i;
+ powernv_freqs[i].frequency = freq * 1000; /* kHz */
+ powernv_pstate_ids[i] = id;
+ }
+ /* End of list marker entry */
+ powernv_freqs[i].driver_data = 0;
+ powernv_freqs[i].frequency = CPUFREQ_TABLE_END;
+
+ /* Print frequency table */
+ for (i = 0; powernv_freqs[i].frequency != CPUFREQ_TABLE_END; i++)
+ pr_debug("%d: %d\n", i, powernv_freqs[i].frequency);
+
+ return 0;
+}
+
+static struct freq_attr *powernv_cpu_freq_attr[] = {
+ &cpufreq_freq_attr_scaling_available_freqs,
+ NULL,
+};
+
+/* Helper routines */
+
+/* Access helpers to power mgt SPR */
+
+static inline unsigned long get_pmspr(unsigned long sprn)
+{
+ switch (sprn) {
+ case SPRN_PMCR:
+ return mfspr(SPRN_PMCR);
+
+ case SPRN_PMICR:
+ return mfspr(SPRN_PMICR);
+
+ case SPRN_PMSR:
+ return mfspr(SPRN_PMSR);
+ }
+ BUG();
+}
+
+static inline void set_pmspr(unsigned long sprn, unsigned long val)
+{
+ switch (sprn) {
+ case SPRN_PMCR:
+ mtspr(SPRN_PMCR, val);
+ return;
+
+ case SPRN_PMICR:
+ mtspr(SPRN_PMICR, val);
+ return;
+
+ case SPRN_PMSR:
+ mtspr(SPRN_PMSR, val);
+ return;
+ }
+ BUG();
+}
+
+static void set_pstate(void *pstate)
+{
+ unsigned long val;
+ unsigned long pstate_ul = *(unsigned long *) pstate;
+
+ val = get_pmspr(SPRN_PMCR);
+ val = val & 0x0000ffffffffffffULL;
+ /* Set both global(bits 56..63) and local(bits 48..55) PStates */
+ val = val | (pstate_ul << 56) | (pstate_ul << 48);
+ pr_debug("Setting cpu %d pmcr to %016lX\n", smp_processor_id(), val);
+ set_pmspr(SPRN_PMCR, val);
+}
+
+static int powernv_set_freq(cpumask_var_t cpus, unsigned int new_index)
+{
+ unsigned long val = (unsigned long) powernv_pstate_ids[new_index];
+
+ /*
+ * Use smp_call_function to send IPI and execute the
+ * mtspr on target cpu. We could do that without IPI
+ * if current CPU is within policy->cpus (core)
+ */
+
+ val = val & 0xFF;
+ smp_call_function_any(cpus, set_pstate, &val, 1);
+ return 0;
+}
+
+static int powernv_cpufreq_cpu_init(struct cpufreq_policy *policy)
+{
+ int base, i;
+
+#ifdef CONFIG_SMP
+ base = cpu_first_thread_sibling(policy->cpu);
+
+ for (i = 0; i < threads_per_core; i++)
+ cpumask_set_cpu(base + i, policy->cpus);
+#endif
+ policy->cpuinfo.transition_latency = 25000;
+
+ policy->cur = powernv_freqs[0].frequency;
+ cpufreq_frequency_table_get_attr(powernv_freqs, policy->cpu);
+ return cpufreq_frequency_table_cpuinfo(policy, powernv_freqs);
+}
+
+static int powernv_cpufreq_cpu_exit(struct cpufreq_policy *policy)
+{
+ cpufreq_frequency_table_put_attr(policy->cpu);
+ return 0;
+}
+
+static int powernv_cpufreq_verify(struct cpufreq_policy *policy)
+{
+ return cpufreq_frequency_table_verify(policy, powernv_freqs);
+}
+
+static int powernv_cpufreq_target(struct cpufreq_policy *policy,
+ unsigned int target_freq,
+ unsigned int relation)
+{
+ int rc;
+ struct cpufreq_freqs freqs;
+ unsigned int new_index;
+
+ cpufreq_frequency_table_target(policy, powernv_freqs, target_freq,
+ relation, &new_index);
+
+ freqs.old = policy->cur;
+ freqs.new = powernv_freqs[new_index].frequency;
+ freqs.cpu = policy->cpu;
+
+ mutex_lock(&freq_switch_mutex);
+ cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE);
+
+ pr_debug("setting frequency for cpu %d to %d kHz index %d pstate %d",
+ policy->cpu,
+ powernv_freqs[new_index].frequency,
+ new_index,
+ powernv_pstate_ids[new_index]);
+
+ rc = powernv_set_freq(policy->cpus, new_index);
+
+ cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE);
+ mutex_unlock(&freq_switch_mutex);
+
+ return rc;
+}
+
+static struct cpufreq_driver powernv_cpufreq_driver = {
+ .verify = powernv_cpufreq_verify,
+ .target = powernv_cpufreq_target,
+ .init = powernv_cpufreq_cpu_init,
+ .exit = powernv_cpufreq_cpu_exit,
+ .name = "powernv-cpufreq",
+ .flags = CPUFREQ_CONST_LOOPS,
+ .attr = powernv_cpu_freq_attr,
+};
+
+static int __init powernv_cpufreq_init(void)
+{
+ int rc = 0;
+
+ /* Discover pstates from device tree and init */
+
+ rc = init_powernv_pstates();
+
+ if (rc) {
+ pr_info("powernv-cpufreq disabled\n");
+ return rc;
+ }
+
+ rc = cpufreq_register_driver(&powernv_cpufreq_driver);
+ return rc;
+}
+
+static void __exit powernv_cpufreq_exit(void)
+{
+ cpufreq_unregister_driver(&powernv_cpufreq_driver);
+}
+
+module_init(powernv_cpufreq_init);
+module_exit(powernv_cpufreq_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Vaidyanathan Srinivasan <svaidy at linux.vnet.ibm.com>");
--
1.8.3.1
^ permalink raw reply related
* [PATCH v2 0/6] powernv:cpufreq: Dynamic cpu-frequency scaling
From: Gautham R. Shenoy @ 2014-03-10 11:10 UTC (permalink / raw)
To: linuxppc-dev; +Cc: srivatsa.bhat, Gautham R. Shenoy
From: "Gautham R. Shenoy" <ego@linux.vnet.ibm.com>
Hi,
This is the v2 of the consolidated patchset consisting
patches for enabling cpufreq on IBM POWERNV platforms
along with some enhancements.
The v1 of these patches have been previously
submitted on linuxppc-dev [1][2].
- This patchset contains code for the platform driver to support CPU
frequency scaling on IBM POWERNV platforms.
- In addition to the standard control and status files exposed by the
cpufreq core, the patchset exposes the nominal frequency through the
file named "cpuinfo_nominal_freq".
The patchset is based against commit c3bebc71c4bcdafa24b506adf0c1de3c1f77e2e0
of the mainline tree.
[1]: https://lists.ozlabs.org/pipermail/linuxppc-dev/2014-February/115244.html
[2]: https://lists.ozlabs.org/pipermail/linuxppc-dev/2014-March/115703.html
Gautham R. Shenoy (3):
powernv:cpufreq: Create pstate_id_to_freq() helper
powernv:cpufreq: Export nominal frequency via sysfs.
powernv:cpufreq: Implement the driver->get() method
Srivatsa S. Bhat (2):
powernv:cpufreq: Create a powernv_cpu_to_core_mask() helper.
powernv,cpufreq:Add per-core locking to serialize frequency
transitions
Vaidyanathan Srinivasan (1):
powernv: cpufreq driver for powernv platform
arch/powerpc/include/asm/reg.h | 4 +
arch/powerpc/platforms/powernv/Kconfig | 1 +
drivers/cpufreq/Kconfig | 1 +
drivers/cpufreq/Kconfig.powerpc | 13 ++
drivers/cpufreq/Makefile | 1 +
drivers/cpufreq/powernv-cpufreq.c | 397 +++++++++++++++++++++++++++++++++
6 files changed, 417 insertions(+)
create mode 100644 drivers/cpufreq/powernv-cpufreq.c
--
1.8.3.1
^ permalink raw reply
* Re: [PATCH 1/2] Revert "KVM: PPC: Book3S HV: Add new state for transactional memory"
From: Paolo Bonzini @ 2014-03-10 10:51 UTC (permalink / raw)
To: Paul Mackerras, Aneesh Kumar K.V, Scott Wood
Cc: linuxppc-dev, agraf, kvm-ppc, kvm
In-Reply-To: <20140310105028.GA5934@iris.ozlabs.ibm.com>
Il 10/03/2014 11:50, Paul Mackerras ha scritto:
> We can either do this revert, or apply a patch removing the extra
> hunk, but one or the other should go in for 3.14 since it's quite
> broken as it is (that is, HV-mode KVM on powerpc is broken).
>
> Paolo, do you have a preference about revert vs. fix? Are you happy
> to take what Aneesh sent (in which case please add my acked-by and
> perhaps edit the commentary to say how the problem arose), or do you
> want a freshly-prepared patch, and if so against which branch?
I prefer a fix.
Paolo
^ permalink raw reply
* Re: [PATCH 1/2] Revert "KVM: PPC: Book3S HV: Add new state for transactional memory"
From: Paul Mackerras @ 2014-03-10 10:50 UTC (permalink / raw)
To: Aneesh Kumar K.V, Paolo Bonzini, Scott Wood
Cc: linuxppc-dev, agraf, kvm-ppc, kvm
In-Reply-To: <1394102170-22126-1-git-send-email-aneesh.kumar@linux.vnet.ibm.com>
On Thu, Mar 06, 2014 at 04:06:09PM +0530, Aneesh Kumar K.V wrote:
> From: "Aneesh Kumar K.V" <aneesh.kumar@linux.vnet.ibm.com>
>
> This reverts commit 7b490411c37f7ab7965cbdfe5e3ec28eadb6db5b which cause
> the below crash in the host.
OK, I understand now what happened, which is this: when I sent out
that patch, I inadvertently included a hunk of extra code as a result
of not cleaning up a rebase properly. The next patch in the series
removed the extraneous hunk, but Alex didn't apply the next patch.
We can either do this revert, or apply a patch removing the extra
hunk, but one or the other should go in for 3.14 since it's quite
broken as it is (that is, HV-mode KVM on powerpc is broken).
Paolo, do you have a preference about revert vs. fix? Are you happy
to take what Aneesh sent (in which case please add my acked-by and
perhaps edit the commentary to say how the problem arose), or do you
want a freshly-prepared patch, and if so against which branch?
Thanks,
Paul.
^ permalink raw reply
* RE: rfc: checkpatch logical line continuations (was IBM Akebono: Add support for a new PHY interface to the IBM emac driver)
From: David Laight @ 2014-03-10 9:53 UTC (permalink / raw)
To: 'josh@joshtriplett.org', Joe Perches
Cc: Randy Dunlap, devicetree@vger.kernel.org, Dan Carpenter,
alistair@popple.id.au, linux-kernel@vger.kernel.org,
netdev@vger.kernel.org, Andrew Morton,
linuxppc-dev@lists.ozlabs.org, David Miller
In-Reply-To: <20140307213017.GA18769@cloud>
From: josh@joshtriplett.org
> On Fri, Mar 07, 2014 at 01:02:44PM -0800, Joe Perches wrote:
> > On Fri, 2014-03-07 at 15:41 -0500, David Miller wrote:
> > > From: Alistair Popple <alistair@popple.id.au>
> > > Date: Thu, 6 Mar 2014 14:52:25 +1100
> > >
> > > > + out_be32(dev->reg, in_be32(dev->reg) | WKUP_ETH_RGMIIEN
> > > > + | WKUP_ETH_TX_OE | WKUP_ETH_RX_IE);
> > >
> > > When an expression spans multiple lines, the lines should end with
> > > operators rather than begin with them.
> >
> > That's not in CodingStyle currently.
>=20
> It's also not even remotely consistent across existing kernel code, and
> it isn't obvious that there's a general developer consensus on the
> "right" way to write it.
My personal preference (which counts for nothing here) is to put
the operators at the start of the continuation like in order to
make it more obvious that it is a continuation.
The netdev rules are particularly problematical for code like:
if (tst(foo, foo2, foo3, ...) && ....... &&
tst2(......) && tst3()) {
baz(....);
where a scan read of the LHS gives the wrong logic.
At least we don't have a coding style that allows very long lnes
an puts } and { on their own lines - leading to:
...
}
while (foo(...) && bar(...) && ..... /* very long line falls off sc=
reen */
{
int x;
Is that the top or bottom of a loop?
David
^ permalink raw reply
* Re: [PATCH] eeh_pseries: Missing break?
From: Gavin Shan @ 2014-03-08 16:37 UTC (permalink / raw)
To: Joe Perches; +Cc: linuxppc-dev, Gavin Shan, linux-kernel
In-Reply-To: <1394296003.6972.26.camel@joe-AO722>
On Sat, Mar 08, 2014 at 08:26:43AM -0800, Joe Perches wrote:
>On Sun, 2014-03-09 at 00:16 +0800, Gavin Shan wrote:
>> On Fri, Mar 07, 2014 at 04:31:32PM -0800, Joe Perches wrote:
.../...
>English usages of "double negatives" are different
>than other languages. "it wasn't unintentional"
>means the same thing as "it was intentional".
>
Sorry, typo :)
>> Could you have better commit log
>> and subject, then repost it?
>>
.../...
>From my perspective, you should write up a commit
>message of your own choice (I wouldn't use "we",
>but the rest seems OK) and add a Reported-by:
>
>All I did was notice it and bring it to your
>attention.
>
Ok. I will post it. Thanks!
Thanks,
Gavin
>> >---
>> >diff --git a/arch/powerpc/platforms/pseries/eeh_pseries.c b/arch/powerpc/platforms/pseries/eeh_pseries.c
>> >index 8a8f047..83da53f 100644
>> >--- a/arch/powerpc/platforms/pseries/eeh_pseries.c
>> >+++ b/arch/powerpc/platforms/pseries/eeh_pseries.c
>> >@@ -460,14 +460,15 @@ static int pseries_eeh_get_state(struct eeh_pe *pe, int *state)
>> > case 5:
>> > if (rets[2]) {
>> > if (state) *state = rets[2];
>> > result = EEH_STATE_UNAVAILABLE;
>> > } else {
>> > result = EEH_STATE_NOT_SUPPORT;
>> > }
>> >+ break;
>> > default:
>> > result = EEH_STATE_NOT_SUPPORT;
>> > }
>> > } else {
>> > result = EEH_STATE_NOT_SUPPORT;
>> > }
>> >
>>
>> Thanks,
>> Gavin
>>
>
>
>
^ permalink raw reply
* Re: [PATCH] eeh_pseries: Missing break?
From: Joe Perches @ 2014-03-08 16:26 UTC (permalink / raw)
To: Gavin Shan; +Cc: linuxppc-dev, linux-kernel
In-Reply-To: <20140308161647.GA24296@shangw.(null)>
On Sun, 2014-03-09 at 00:16 +0800, Gavin Shan wrote:
> On Fri, Mar 07, 2014 at 04:31:32PM -0800, Joe Perches wrote:
> >Looks like this is unintentional as the
> >result = EEH_STATE_UNAVAILABLE is being
> >overwritten by EEH_STATE_NOT_SUPPORT in the
> >fallthrough to the default case.
>
> Thanks, Joe. It wasn't unintentional.
Hi Gavin.
English usages of "double negatives" are different
than other languages. "it wasn't unintentional"
means the same thing as "it was intentional".
> Could you have better commit log
> and subject, then repost it?
>
> The format looks like:
>
> ---
>
> powerpc/eeh: Fix overwritten PE state
>
> In pseries_eeh_get_state(), we always have EEH_STATE_UNAVAILABLE
> overwritten by EEH_STATE_NOT_SUPPORT because of the missed "break"
> the patch fixes the issue.
>
> Signed-off-by: Joe Perches <joe@perches.com>
>From my perspective, you should write up a commit
message of your own choice (I wouldn't use "we",
but the rest seems OK) and add a Reported-by:
All I did was notice it and bring it to your
attention.
> ---
>
> With the better commit log/subject, please have:
>
> Acked-by: Gavin Shan <shangw@linux.vnet.ibm.com>
>
> >---
> >diff --git a/arch/powerpc/platforms/pseries/eeh_pseries.c b/arch/powerpc/platforms/pseries/eeh_pseries.c
> >index 8a8f047..83da53f 100644
> >--- a/arch/powerpc/platforms/pseries/eeh_pseries.c
> >+++ b/arch/powerpc/platforms/pseries/eeh_pseries.c
> >@@ -460,14 +460,15 @@ static int pseries_eeh_get_state(struct eeh_pe *pe, int *state)
> > case 5:
> > if (rets[2]) {
> > if (state) *state = rets[2];
> > result = EEH_STATE_UNAVAILABLE;
> > } else {
> > result = EEH_STATE_NOT_SUPPORT;
> > }
> >+ break;
> > default:
> > result = EEH_STATE_NOT_SUPPORT;
> > }
> > } else {
> > result = EEH_STATE_NOT_SUPPORT;
> > }
> >
>
> Thanks,
> Gavin
>
^ permalink raw reply
* Re: [PATCH] eeh_pseries: Missing break?
From: Gavin Shan @ 2014-03-08 16:16 UTC (permalink / raw)
To: Joe Perches; +Cc: linuxppc-dev, Gavin Shan, linux-kernel
In-Reply-To: <1394238692.16156.115.camel@joe-AO722>
On Fri, Mar 07, 2014 at 04:31:32PM -0800, Joe Perches wrote:
>Looks like this is unintentional as the
>result = EEH_STATE_UNAVAILABLE is being
>overwritten by EEH_STATE_NOT_SUPPORT in the
>fallthrough to the default case.
Thanks, Joe. It wasn't unintentional. Could you have better commit log
and subject, then repost it?
The format looks like:
---
powerpc/eeh: Fix overwritten PE state
In pseries_eeh_get_state(), we always have EEH_STATE_UNAVAILABLE
overwritten by EEH_STATE_NOT_SUPPORT because of the missed "break"
the patch fixes the issue.
Signed-off-by: Joe Perches <joe@perches.com>
---
With the better commit log/subject, please have:
Acked-by: Gavin Shan <shangw@linux.vnet.ibm.com>
>---
>diff --git a/arch/powerpc/platforms/pseries/eeh_pseries.c b/arch/powerpc/platforms/pseries/eeh_pseries.c
>index 8a8f047..83da53f 100644
>--- a/arch/powerpc/platforms/pseries/eeh_pseries.c
>+++ b/arch/powerpc/platforms/pseries/eeh_pseries.c
>@@ -460,14 +460,15 @@ static int pseries_eeh_get_state(struct eeh_pe *pe, int *state)
> case 5:
> if (rets[2]) {
> if (state) *state = rets[2];
> result = EEH_STATE_UNAVAILABLE;
> } else {
> result = EEH_STATE_NOT_SUPPORT;
> }
>+ break;
> default:
> result = EEH_STATE_NOT_SUPPORT;
> }
> } else {
> result = EEH_STATE_NOT_SUPPORT;
> }
>
Thanks,
Gavin
^ permalink raw reply
* [PATCH] eeh_pseries: Missing break?
From: Joe Perches @ 2014-03-08 0:31 UTC (permalink / raw)
To: Gavin Shan; +Cc: linuxppc-dev, linux-kernel
Looks like this is unintentional as the
result = EEH_STATE_UNAVAILABLE is being
overwritten by EEH_STATE_NOT_SUPPORT in the
fallthrough to the default case.
---
diff --git a/arch/powerpc/platforms/pseries/eeh_pseries.c b/arch/powerpc/platforms/pseries/eeh_pseries.c
index 8a8f047..83da53f 100644
--- a/arch/powerpc/platforms/pseries/eeh_pseries.c
+++ b/arch/powerpc/platforms/pseries/eeh_pseries.c
@@ -460,14 +460,15 @@ static int pseries_eeh_get_state(struct eeh_pe *pe, int *state)
case 5:
if (rets[2]) {
if (state) *state = rets[2];
result = EEH_STATE_UNAVAILABLE;
} else {
result = EEH_STATE_NOT_SUPPORT;
}
+ break;
default:
result = EEH_STATE_NOT_SUPPORT;
}
} else {
result = EEH_STATE_NOT_SUPPORT;
}
^ permalink raw reply related
* Re: rfc: checkpatch logical line continuations (was IBM Akebono: Add support for a new PHY interface to the IBM emac driver)
From: Joe Perches @ 2014-03-07 23:15 UTC (permalink / raw)
To: Dan Carpenter
Cc: Randy Dunlap, devicetree, Dan Carpenter, alistair, josh,
linux-kernel, netdev, Andrew Morton, linuxppc-dev, David Miller
In-Reply-To: <20140307230420.GH29018@mwanda>
On Sat, 2014-03-08 at 02:04 +0300, Dan Carpenter wrote:
> On Fri, Mar 07, 2014 at 01:30:17PM -0800, josh@joshtriplett.org wrote:
> > On Fri, Mar 07, 2014 at 01:02:44PM -0800, Joe Perches wrote:
> > > On Fri, 2014-03-07 at 15:41 -0500, David Miller wrote:
> > > > From: Alistair Popple <alistair@popple.id.au>
> > > > Date: Thu, 6 Mar 2014 14:52:25 +1100
> > > >
> > > > > + out_be32(dev->reg, in_be32(dev->reg) | WKUP_ETH_RGMIIEN
> > > > > + | WKUP_ETH_TX_OE | WKUP_ETH_RX_IE);
> > > >
> > > > When an expression spans multiple lines, the lines should end with
> > > > operators rather than begin with them.
> > >
> > > That's not in CodingStyle currently.
> >
> > It's also not even remotely consistent across existing kernel code, and
> > it isn't obvious that there's a general developer consensus on the
> > "right" way to write it.
> >
>
> We just had this discussion in staging and Greg modified the patch to
> put the operator at the end.
>
> https://lkml.org/lkml/2014/2/25/125
I remember and it's the reason I bring it up in a
more public way.
> It's like logical && and || operators which go at the end these days.
> I don't really want to have a lot of checkpatch churn to convert
> everything...
Nor I really. I simply would like a tool that lets
more core maintainers like David M avoid sending out
"do this, not that" type emails about patches.
I don't mind adding style checking that emits something
for patches and is quieter when scanning files.
^ permalink raw reply
* Re: rfc: checkpatch logical line continuations (was IBM Akebono: Add support for a new PHY interface to the IBM emac driver)
From: Dan Carpenter @ 2014-03-07 23:04 UTC (permalink / raw)
To: josh
Cc: Randy Dunlap, devicetree, Dan Carpenter, alistair, linux-kernel,
netdev, Joe Perches, Andrew Morton, linuxppc-dev, David Miller
In-Reply-To: <20140307213017.GA18769@cloud>
On Fri, Mar 07, 2014 at 01:30:17PM -0800, josh@joshtriplett.org wrote:
> On Fri, Mar 07, 2014 at 01:02:44PM -0800, Joe Perches wrote:
> > On Fri, 2014-03-07 at 15:41 -0500, David Miller wrote:
> > > From: Alistair Popple <alistair@popple.id.au>
> > > Date: Thu, 6 Mar 2014 14:52:25 +1100
> > >
> > > > + out_be32(dev->reg, in_be32(dev->reg) | WKUP_ETH_RGMIIEN
> > > > + | WKUP_ETH_TX_OE | WKUP_ETH_RX_IE);
> > >
> > > When an expression spans multiple lines, the lines should end with
> > > operators rather than begin with them.
> >
> > That's not in CodingStyle currently.
>
> It's also not even remotely consistent across existing kernel code, and
> it isn't obvious that there's a general developer consensus on the
> "right" way to write it.
>
We just had this discussion in staging and Greg modified the patch to
put the operator at the end.
https://lkml.org/lkml/2014/2/25/125
It's like logical && and || operators which go at the end these days.
I don't really want to have a lot of checkpatch churn to convert
everything...
regards,
dan carpenter
^ permalink raw reply
* Re: rfc: checkpatch logical line continuations (was IBM Akebono: Add support for a new PHY interface to the IBM emac driver)
From: josh @ 2014-03-07 21:30 UTC (permalink / raw)
To: Joe Perches
Cc: Randy Dunlap, devicetree, Dan Carpenter, alistair, linux-kernel,
netdev, Andrew Morton, linuxppc-dev, David Miller
In-Reply-To: <1394226164.16156.96.camel@joe-AO722>
On Fri, Mar 07, 2014 at 01:02:44PM -0800, Joe Perches wrote:
> On Fri, 2014-03-07 at 15:41 -0500, David Miller wrote:
> > From: Alistair Popple <alistair@popple.id.au>
> > Date: Thu, 6 Mar 2014 14:52:25 +1100
> >
> > > + out_be32(dev->reg, in_be32(dev->reg) | WKUP_ETH_RGMIIEN
> > > + | WKUP_ETH_TX_OE | WKUP_ETH_RX_IE);
> >
> > When an expression spans multiple lines, the lines should end with
> > operators rather than begin with them.
>
> That's not in CodingStyle currently.
It's also not even remotely consistent across existing kernel code, and
it isn't obvious that there's a general developer consensus on the
"right" way to write it.
> Right now, checkpatch emits a --strict only warning on "&&" or "||"
> at the beginning of line but that could be changed to any "$Operators"
>
> our $Arithmetic = qr{\+|-|\*|\/|%};
> our $Operators = qr{
> <=|>=|==|!=|
> =>|->|<<|>>|<|>|!|~|
> &&|\|\||,|\^|\+\+|--|&|\||$Arithmetic
> }x;
>
> The ones that likely have a too high false positive rates
> are the negation "!" and bitwise "~".
I don't think warning about operators at start of line seems like a good
idea at all. There are plenty of cases where putting the operator at
the start of the line will produce a better result. (I'd actually
suggest that in *most* cases.)
> Also, using perl, it's hard to distinguish between a
> logical "&" and the address-of "&" as well as the
> multiplication "*" and indirection "*" so maybe those
> should be excluded too.
>
> And I think it should only be added as a --strict test.
Agreed, if even that.
- Josh Triplett
^ permalink raw reply
* Re: rfc: checkpatch logical line continuations (was IBM Akebono: Add support for a new PHY interface to the IBM emac driver)
From: Joe Perches @ 2014-03-07 21:45 UTC (permalink / raw)
To: josh
Cc: devicetree, Dan Carpenter, alistair, Randy Dunlap, linux-kernel,
netdev, Andrew Morton, linuxppc-dev, David Miller
In-Reply-To: <20140307213017.GA18769@cloud>
On Fri, 2014-03-07 at 13:30 -0800, josh@joshtriplett.org wrote:
> On Fri, Mar 07, 2014 at 01:02:44PM -0800, Joe Perches wrote:
> > On Fri, 2014-03-07 at 15:41 -0500, David Miller wrote:
> > > From: Alistair Popple <alistair@popple.id.au>
> > > Date: Thu, 6 Mar 2014 14:52:25 +1100
> > >
> > > > + out_be32(dev->reg, in_be32(dev->reg) | WKUP_ETH_RGMIIEN
> > > > + | WKUP_ETH_TX_OE | WKUP_ETH_RX_IE);
> > >
> > > When an expression spans multiple lines, the lines should end with
> > > operators rather than begin with them.
> >
> > That's not in CodingStyle currently.
>
> It's also not even remotely consistent across existing kernel code, and
> it isn't obvious that there's a general developer consensus on the
> "right" way to write it.
I agree with that. Stuff that's not in CodingStyle generally
doesn't have a developer consensus.
> > Right now, checkpatch emits a --strict only warning on "&&" or "||"
> > at the beginning of line but that could be changed to any "$Operators"
> >
> > our $Arithmetic = qr{\+|-|\*|\/|%};
> > our $Operators = qr{
> > <=|>=|==|!=|
> > =>|->|<<|>>|<|>|!|~|
> > &&|\|\||,|\^|\+\+|--|&|\||$Arithmetic
> > }x;
> >
> > The ones that likely have a too high false positive rates
> > are the negation "!" and bitwise "~".
>
> I don't think warning about operators at start of line seems like a good
> idea at all. There are plenty of cases where putting the operator at
> the start of the line will produce a better result. (I'd actually
> suggest that in *most* cases.)
>
> > Also, using perl, it's hard to distinguish between a
> > logical "&" and the address-of "&" as well as the
> > multiplication "*" and indirection "*" so maybe those
> > should be excluded too.
> >
> > And I think it should only be added as a --strict test.
>
> Agreed, if even that.
And probably made specific to net/ and drivers/net like
a few other comment style tests until such time as a
consensus exists.
^ permalink raw reply
* Re: rfc: checkpatch logical line continuations
From: David Miller @ 2014-03-07 21:23 UTC (permalink / raw)
To: joe
Cc: randy.dunlap, devicetree, error27, alistair, linux-kernel, josh,
netdev, akpm, linuxppc-dev
In-Reply-To: <1394226164.16156.96.camel@joe-AO722>
From: Joe Perches <joe@perches.com>
Date: Fri, 07 Mar 2014 13:02:44 -0800
> Right now, checkpatch emits a --strict only warning on "&&" or "||"
> at the beginning of line but that could be changed to any "$Operators"
>
> our $Arithmetic = qr{\+|-|\*|\/|%};
> our $Operators = qr{
> <=|>=|==|!=|
> =>|->|<<|>>|<|>|!|~|
> &&|\|\||,|\^|\+\+|--|&|\||$Arithmetic
> }x;
>
> The ones that likely have a too high false positive rates
> are the negation "!" and bitwise "~".
Unary operators at the beginning of a line are perfectly fine,
it's the other ones that are the problem.
^ permalink raw reply
* [git pull] Please pull powerpc.git merge branch
From: Benjamin Herrenschmidt @ 2014-03-07 21:04 UTC (permalink / raw)
To: Linus Torvalds; +Cc: linuxppc-dev, Linux Kernel list
Hi Linus !
Here are a couple of powerpc fixes for 3.14. One is (another !) nasty TM
problem, we can crash the kernel by forking inside a transaction. The
other one is a simple fix for an alignment issue which can hurt in LE
mode.
Cheers,
Ben.
The following changes since commit e0cf957614976896111e676e5134ac98ee227d3d:
powerpc/powernv: Fix indirect XSCOM unmangling (2014-02-28 19:15:49 +1100)
are available in the git repository at:
git://git.kernel.org/pub/scm/linux/kernel/git/benh/powerpc.git merge
for you to fetch changes up to a5b2cf5b1af424ee3dd9e3ce6d5cea18cb927e67:
powerpc: Align p_dyn, p_rela and p_st symbols (2014-03-07 13:50:19 +1100)
----------------------------------------------------------------
Anton Blanchard (1):
powerpc: Align p_dyn, p_rela and p_st symbols
Michael Neuling (1):
powerpc/tm: Fix crash when forking inside a transaction
arch/powerpc/kernel/process.c | 9 +++++++++
arch/powerpc/kernel/reloc_64.S | 1 +
2 files changed, 10 insertions(+)
^ permalink raw reply
* rfc: checkpatch logical line continuations (was IBM Akebono: Add support for a new PHY interface to the IBM emac driver)
From: Joe Perches @ 2014-03-07 21:02 UTC (permalink / raw)
To: David Miller
Cc: Randy Dunlap, devicetree, Dan Carpenter, alistair, linux-kernel,
Josh Triplett, netdev, Andrew Morton, linuxppc-dev
In-Reply-To: <20140307.154142.488351276799532264.davem@davemloft.net>
(added some cc's)
On Fri, 2014-03-07 at 15:41 -0500, David Miller wrote:
> From: Alistair Popple <alistair@popple.id.au>
> Date: Thu, 6 Mar 2014 14:52:25 +1100
>
> > + out_be32(dev->reg, in_be32(dev->reg) | WKUP_ETH_RGMIIEN
> > + | WKUP_ETH_TX_OE | WKUP_ETH_RX_IE);
>
> When an expression spans multiple lines, the lines should end with
> operators rather than begin with them.
That's not in CodingStyle currently.
Right now, checkpatch emits a --strict only warning on "&&" or "||"
at the beginning of line but that could be changed to any "$Operators"
our $Arithmetic = qr{\+|-|\*|\/|%};
our $Operators = qr{
<=|>=|==|!=|
=>|->|<<|>>|<|>|!|~|
&&|\|\||,|\^|\+\+|--|&|\||$Arithmetic
}x;
The ones that likely have a too high false positive rates
are the negation "!" and bitwise "~".
Also, using perl, it's hard to distinguish between a
logical "&" and the address-of "&" as well as the
multiplication "*" and indirection "*" so maybe those
should be excluded too.
And I think it should only be added as a --strict test.
^ permalink raw reply
* Re: [PATCH 2/5] IBM Akebono: Add support for a new PHY interface to the IBM emac driver
From: David Miller @ 2014-03-07 20:41 UTC (permalink / raw)
To: alistair; +Cc: netdev, linuxppc-dev, linux-kernel, devicetree
In-Reply-To: <1394077948-8395-3-git-send-email-alistair@popple.id.au>
From: Alistair Popple <alistair@popple.id.au>
Date: Thu, 6 Mar 2014 14:52:25 +1100
> + out_be32(dev->reg, in_be32(dev->reg) | WKUP_ETH_RGMIIEN
> + | WKUP_ETH_TX_OE | WKUP_ETH_RX_IE);
When an expression spans multiple lines, the lines should end with
operators rather than begin with them.
Also, it would be easier to read this call if parenthesis were put
around the third argument and then indented to match, f.e.:
out_be32(dev->reg, (in_be32(dev->reg) | WKUP_ETH_RGMIIEN |
WKUP_ETH_TX_OE | WKUP_ETH_RX_IE));
^ permalink raw reply
* Re: [PATCH v2 14/52] powerpc, sysfs: Fix CPU hotplug callback registration
From: Gautham R Shenoy @ 2014-03-07 6:21 UTC (permalink / raw)
To: Benjamin Herrenschmidt
Cc: linux-arch, ego, walken, linux, akpm, Wang Dongsheng, peterz,
rusty, rjw, oleg, linux-kernel, Olof Johansson,
Madhavan Srinivasan, paulus, Srivatsa S. Bhat, tj, tglx, paulmck,
linuxppc-dev, mingo
In-Reply-To: <1394161051.26321.71.camel@pasglop>
Hello Ben,
On Fri, Mar 07, 2014 at 01:57:31PM +1100, Benjamin Herrenschmidt wrote:
> On Fri, 2014-02-14 at 13:22 +0530, Srivatsa S. Bhat wrote:
> > Subsystems that want to register CPU hotplug callbacks, as well as perform
> > initialization for the CPUs that are already online, often do it as shown
> > below:
> >
> > get_online_cpus();
> >
> > for_each_online_cpu(cpu)
> > init_cpu(cpu);
> >
> > register_cpu_notifier(&foobar_cpu_notifier);
> >
> > put_online_cpus();
>
> This patch breaks a good half of my test configs with:
>
> /home/benh/linux-powerpc-test/arch/powerpc/kernel/sysfs.c: In function 'topology_init':
> /home/benh/linux-powerpc-test/arch/powerpc/kernel/sysfs.c:979:2: error: implicit declaration of function 'cpu_notifier_register_begin' [-Werror=implicit-function-declaration]
> /home/benh/linux-powerpc-test/arch/powerpc/kernel/sysfs.c:1004:2: error: implicit declaration of function '__register_cpu_notifier' [-Werror=implicit-function-declaration]
> /home/benh/linux-powerpc-test/arch/powerpc/kernel/sysfs.c:1006:2: error: implicit declaration of function 'cpu_notifier_register_done' [-Werror=implicit-function-declaration]
> cc1: all warnings being treated as errors
> make[2]: *** [arch/powerpc/kernel/sysfs.o] Error 1
> make[2]: *** Waiting for unfinished jobs....
This patch depends on
"[PATCH v2 02/52] CPU hotplug: Provide lockless versions of callback registration functions"
of the series (Can be found here: https://lkml.org/lkml/2014/2/14/59).
This particular patch defines 'cpu_notifier_register_begin',
'__register_cpu_notifier', and 'cpu_notifier_register_done' in the
cpu-hotplug core. Are you seeing the build breakage with this patch on
?
--
Thanks and Regards
gautham.
^ permalink raw reply
* Re: [PATCH RFC/RFT v3 6/9] powerpc: move cacheinfo sysfs to generic cacheinfo infrastructure
From: Anshuman Khandual @ 2014-03-07 6:14 UTC (permalink / raw)
To: Sudeep Holla; +Cc: linuxppc-dev, Paul Mackerras, linux-kernel
In-Reply-To: <531945D1.7010503@linux.vnet.ibm.com>
On 03/07/2014 09:36 AM, Anshuman Khandual wrote:
> On 02/19/2014 09:36 PM, Sudeep Holla wrote:
>> From: Sudeep Holla <sudeep.holla@arm.com>
>>
>> This patch removes the redundant sysfs cacheinfo code by making use of
>> the newly introduced generic cacheinfo infrastructure.
>>
>> Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>
>> Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
>> Cc: Paul Mackerras <paulus@samba.org>
>> Cc: linuxppc-dev@lists.ozlabs.org
>> ---
>> arch/powerpc/kernel/cacheinfo.c | 831 ++++++----------------------------------
>> arch/powerpc/kernel/cacheinfo.h | 8 -
>> arch/powerpc/kernel/sysfs.c | 4 -
>> 3 files changed, 109 insertions(+), 734 deletions(-)
>> delete mode 100644 arch/powerpc/kernel/cacheinfo.h
>>
>> diff --git a/arch/powerpc/kernel/cacheinfo.c b/arch/powerpc/kernel/cacheinfo.c
>> index 2912b87..05b7580 100644
>> --- a/arch/powerpc/kernel/cacheinfo.c
>> +++ b/arch/powerpc/kernel/cacheinfo.c
>> @@ -10,38 +10,10 @@
>> * 2 as published by the Free Software Foundation.
>> */
>>
>> +#include <linux/cacheinfo.h>
>> #include <linux/cpu.h>
>> -#include <linux/cpumask.h>
>> #include <linux/kernel.h>
>> -#include <linux/kobject.h>
>> -#include <linux/list.h>
>> -#include <linux/notifier.h>
>> #include <linux/of.h>
>> -#include <linux/percpu.h>
>> -#include <linux/slab.h>
>> -#include <asm/prom.h>
>> -
>> -#include "cacheinfo.h"
>> -
>> -/* per-cpu object for tracking:
>> - * - a "cache" kobject for the top-level directory
>> - * - a list of "index" objects representing the cpu's local cache hierarchy
>> - */
>> -struct cache_dir {
>> - struct kobject *kobj; /* bare (not embedded) kobject for cache
>> - * directory */
>> - struct cache_index_dir *index; /* list of index objects */
>> -};
>> -
>> -/* "index" object: each cpu's cache directory has an index
>> - * subdirectory corresponding to a cache object associated with the
>> - * cpu. This object's lifetime is managed via the embedded kobject.
>> - */
>> -struct cache_index_dir {
>> - struct kobject kobj;
>> - struct cache_index_dir *next; /* next index in parent directory */
>> - struct cache *cache;
>> -};
>>
>> /* Template for determining which OF properties to query for a given
>> * cache type */
>> @@ -60,11 +32,6 @@ struct cache_type_info {
>> const char *nr_sets_prop;
>> };
>>
>> -/* These are used to index the cache_type_info array. */
>> -#define CACHE_TYPE_UNIFIED 0
>> -#define CACHE_TYPE_INSTRUCTION 1
>> -#define CACHE_TYPE_DATA 2
>> -
>> static const struct cache_type_info cache_type_info[] = {
>> {
>> /* PowerPC Processor binding says the [di]-cache-*
>> @@ -77,246 +44,115 @@ static const struct cache_type_info cache_type_info[] = {
>> .nr_sets_prop = "d-cache-sets",
>> },
>> {
>> - .name = "Instruction",
>> - .size_prop = "i-cache-size",
>> - .line_size_props = { "i-cache-line-size",
>> - "i-cache-block-size", },
>> - .nr_sets_prop = "i-cache-sets",
>> - },
>> - {
>> .name = "Data",
>> .size_prop = "d-cache-size",
>> .line_size_props = { "d-cache-line-size",
>> "d-cache-block-size", },
>> .nr_sets_prop = "d-cache-sets",
>> },
>> + {
>> + .name = "Instruction",
>> + .size_prop = "i-cache-size",
>> + .line_size_props = { "i-cache-line-size",
>> + "i-cache-block-size", },
>> + .nr_sets_prop = "i-cache-sets",
>> + },
>> };
>
>
> Hey Sudeep,
>
> After applying this patch, the cache_type_info array looks like this.
>
> static const struct cache_type_info cache_type_info[] = {
> {
> /*
> * PowerPC Processor binding says the [di]-cache-*
> * must be equal on unified caches, so just use
> * d-cache properties.
> */
> .name = "Unified",
> .size_prop = "d-cache-size",
> .line_size_props = { "d-cache-line-size",
> "d-cache-block-size", },
> .nr_sets_prop = "d-cache-sets",
> },
> {
> .name = "Data",
> .size_prop = "d-cache-size",
> .line_size_props = { "d-cache-line-size",
> "d-cache-block-size", },
> .nr_sets_prop = "d-cache-sets",
> },
> {
> .name = "Instruction",
> .size_prop = "i-cache-size",
> .line_size_props = { "i-cache-line-size",
> "i-cache-block-size", },
> .nr_sets_prop = "i-cache-sets",
> },
> };
>
> and this function computes the the array index for any given cache type
> define for PowerPC.
>
> static inline int get_cacheinfo_idx(enum cache_type type)
> {
> if (type == CACHE_TYPE_UNIFIED)
> return 0;
> else
> return type;
> }
>
> These types are define in include/linux/cacheinfo.h as
>
> enum cache_type {
> CACHE_TYPE_NOCACHE = 0,
> CACHE_TYPE_INST = BIT(0), ---> 1
> CACHE_TYPE_DATA = BIT(1), ---> 2
> CACHE_TYPE_SEPARATE = CACHE_TYPE_INST | CACHE_TYPE_DATA,
> CACHE_TYPE_UNIFIED = BIT(2),
> };
>
> When it is UNIFIED we return index 0, which is correct. But the index
> for instruction and data cache seems to be swapped which wrong. This
> will fetch invalid properties for any given cache type.
>
> I have done some initial review and testing for this patch's impact on
> PowerPC (ppc64 POWER specifically). I am trying to do some code clean-up
> and re-arrangements. Will post out soon. Thanks !
It does not work correctly on POWER.
The new patchset adds some more attributes for every cache entry apart from
what we used to have on PowerPC before. From the ABI perspective, the old ones
should reflect the correct value in the same manner as before. Looks like
the generic code will make any attribute as "Unknown" if the arch code does
not populate them in the respective callback.
Here are some problems found on a POWER7 system
(1) L1 instruction cache (cpu<N>/cache/index1/)
====== Before patch ======
coherency_line_size: 128
level: 1
shared_cpu_map: 00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,
00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,
00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,
00000000,00000000,00000000,00000000,00000f00
size: 32K
type: Instruction
===== After patch ========
coherency_line_size: Unknown ----> Wrong
level: 1
shared_cpu_map: 00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,
00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,
00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,
00000000,00000000,00000000,00000000,00ffffff ----> Wrong
size: 0K ----> Wrong
type: Instruction
(2) L3 cache (cpu<N>/cache/index3/)
====== Before patch ======
number_of_sets: 1
size: 4096K
ways_of_associativity: 0
===== After patch ========
number_of_sets: 1
size: 4096K
ways_of_associativity: Unknown ----> Wrong
Need to revisit this implementation on PowerPC and figure out the cause of these problems.
^ permalink raw reply
* [PATCH 2/2] powerpc/powernv: hwmon driver for power values, fan rpm and temperature
From: Neelesh Gupta @ 2014-03-07 5:33 UTC (permalink / raw)
To: linuxppc-dev; +Cc: sbhat
In-Reply-To: <20140307053236.3547.55729.stgit@neelegup-tp-t420.in.ibm.com>
From: Shivaprasad G Bhat <sbhat@linux.vnet.ibm.com>
This patch adds basic kernel enablement for reading power values, fan
speed rpm and temperature values on powernv platforms which will
be exported to user space through sysfs interface.
Signed-off-by: Shivaprasad G Bhat <sbhat@linux.vnet.ibm.com>
Signed-off-by: Neelesh Gupta <neelegup@linux.vnet.ibm.com>
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---
drivers/hwmon/Kconfig | 8 +
drivers/hwmon/Makefile | 1
drivers/hwmon/ibmpowernv.c | 529 ++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 538 insertions(+)
create mode 100644 drivers/hwmon/ibmpowernv.c
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
index 5ce43d8..ad4cdcb 100644
--- a/drivers/hwmon/Kconfig
+++ b/drivers/hwmon/Kconfig
@@ -557,6 +557,14 @@ config SENSORS_IBMPEX
This driver can also be built as a module. If so, the module
will be called ibmpex.
+config SENSORS_IBMPOWERNV
+ tristate "IBM PowerNv Platform temperature/power/fan sensor"
+ depends on PPC_POWERNV
+ default y
+ help
+ If you say yes here you get support for the temperature/fan/power
+ sensors on your platform.
+
config SENSORS_IIO_HWMON
tristate "Hwmon driver that uses channels specified via iio maps"
depends on IIO
diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile
index ec7cde0..807e172 100644
--- a/drivers/hwmon/Makefile
+++ b/drivers/hwmon/Makefile
@@ -70,6 +70,7 @@ obj-$(CONFIG_SENSORS_ULTRA45) += ultra45_env.o
obj-$(CONFIG_SENSORS_I5K_AMB) += i5k_amb.o
obj-$(CONFIG_SENSORS_IBMAEM) += ibmaem.o
obj-$(CONFIG_SENSORS_IBMPEX) += ibmpex.o
+obj-$(CONFIG_SENSORS_IBMPOWERNV)+= ibmpowernv.o
obj-$(CONFIG_SENSORS_IIO_HWMON) += iio_hwmon.o
obj-$(CONFIG_SENSORS_INA209) += ina209.o
obj-$(CONFIG_SENSORS_INA2XX) += ina2xx.o
diff --git a/drivers/hwmon/ibmpowernv.c b/drivers/hwmon/ibmpowernv.c
new file mode 100644
index 0000000..b7b1297
--- /dev/null
+++ b/drivers/hwmon/ibmpowernv.c
@@ -0,0 +1,529 @@
+/*
+ * hwmon driver for temperature/power/fan on IBM PowerNV platform
+ * Copyright (C) 2013 IBM
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/hwmon.h>
+#include <linux/hwmon-sysfs.h>
+#include <linux/of.h>
+#include <linux/slab.h>
+
+#include <linux/jiffies.h>
+#include <linux/platform_device.h>
+#include <asm/opal.h>
+#include <linux/err.h>
+
+MODULE_DESCRIPTION("IBM PowerNV Platform power/temp/fan sensor hwmon module");
+MODULE_LICENSE("GPL");
+
+#define MAX_ATTR_LENGTH 32
+
+/* Device tree sensor name prefixes. The device tree has the names in the
+ * format "cooling-fan#2-faulted" where the "cooling-fan" is the sensor type,
+ * 2 is the sensor count, and "faulted" is the sensor data attribute type.
+ */
+#define DT_FAULT_ATTR_SUFFIX "faulted"
+#define DT_DATA_ATTR_SUFFIX "data"
+#define DT_THRESHOLD_ATTR_SUFFIX "thrs"
+
+enum sensors {
+ FAN,
+ TEMPERATURE,
+ POWERSUPPLY,
+ POWER,
+ MAX_SENSOR_TYPE,
+};
+
+enum attributes {
+ INPUT,
+ MINIMUM,
+ MAXIMUM,
+ FAULT,
+ MAX_ATTR_TYPES
+};
+
+static struct sensor_name {
+ char *name;
+ char *compaible;
+} sensor_names[] = {
+ {"fan-sensor", "ibm,opal-sensor-cooling-fan"},
+ {"amb-temp-sensor", "ibm,opal-sensor-amb-temp"},
+ {"power-sensor", "ibm,opal-sensor-power-supply"},
+ {"power", "ibm,opal-sensor-power"}
+};
+
+static const char * const attribute_type_table[] = {
+ "input",
+ "min",
+ "max",
+ "fault",
+ NULL
+};
+
+struct pdev_entry {
+ struct list_head list;
+ struct platform_device *pdev;
+ enum sensors type;
+};
+
+static LIST_HEAD(pdev_list);
+
+/* The sensors are categorised on type.
+ *
+ * The sensors of same type are categorised under a common platform device.
+ * So, The pdev is shared by all sensors of same type.
+ * Ex : temp1_input, temp1_max, temp2_input,temp2_max all share same platform
+ * device.
+ *
+ * "sensor_data" is the Platform device specific data.
+ * There is one hwmon_device instance for all the sensors of same type.
+ * This also holds the list of all sensors with same type but different
+ * attribute and index.
+ */
+struct sensor_specific_data {
+ u32 sensor_id; /* The hex value as in the device tree */
+ u32 sensor_index; /* The sensor instance index */
+ struct sensor_device_attribute sd_attr;
+ enum attributes attr_type;
+ char attr_name[64];
+};
+
+struct sensor_data {
+ struct device *hwmon_dev;
+ struct list_head sensor_list;
+ struct device_attribute name_attr;
+};
+
+struct sensor_entry {
+ struct list_head list;
+ struct sensor_specific_data *sensor_data;
+};
+
+static struct platform_device *powernv_sensor_get_pdev(enum sensors type)
+{
+ struct pdev_entry *p;
+ list_for_each_entry(p, &pdev_list, list)
+ if (p->type == type)
+ return p->pdev;
+
+ return NULL;
+}
+
+static struct sensor_specific_data *powernv_sensor_get_sensor_data(
+ struct sensor_data *pdata,
+ int index, enum attributes attr_type)
+{
+ struct sensor_entry *p;
+ list_for_each_entry(p, &pdata->sensor_list, list)
+ if ((p->sensor_data->sensor_index == index) &&
+ (attr_type == p->sensor_data->attr_type))
+ return p->sensor_data;
+
+ return NULL;
+}
+
+static ssize_t show_name(struct device *dev,
+ struct device_attribute *devattr, char *buf)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+
+ return sprintf(buf, "%s\n", pdev->name);
+}
+
+/* Note: Data from the sensors for each sensor type needs to be converted to
+ * the dimension appropriate.
+ */
+static ssize_t show_sensor(struct device *dev,
+ struct device_attribute *devattr, char *buf)
+{
+ struct sensor_device_attribute *sd_attr = to_sensor_dev_attr(devattr);
+ struct platform_device *pdev = to_platform_device(dev);
+ struct sensor_data *pdata = platform_get_drvdata(pdev);
+ struct sensor_specific_data *tdata = NULL;
+ enum sensors sensor_type = pdev->id;
+ u32 x = -1;
+ int ret;
+
+ if (sd_attr && sd_attr->dev_attr.attr.name) {
+ char *pos = strchr(sd_attr->dev_attr.attr.name, '_');
+ int i;
+
+ for (i = 0; i < MAX_ATTR_TYPES; i++) {
+ if (strcmp(pos+1, attribute_type_table[i]) == 0) {
+ tdata = powernv_sensor_get_sensor_data(pdata,
+ sd_attr->index, i);
+ break;
+ }
+ }
+ }
+
+ if (tdata) {
+ ret = opal_get_sensor_data(tdata->sensor_id, &x);
+ if (ret)
+ x = -1;
+ }
+
+ if (sensor_type == TEMPERATURE && x > 0) {
+ /* Temperature comes in Degrees and convert it to
+ * milli-degrees.
+ */
+ x = x*1000;
+ } else if (sensor_type == POWER && x > 0) {
+ /* Power value comes in watts, convert to micro-watts */
+ x = x * 1000000;
+ }
+
+ return sprintf(buf, "%d\n", x);
+}
+
+static u32 get_sensor_index_from_name(const char *name)
+{
+ char *hash_position = strchr(name, '#');
+ u32 index = 0, copy_length;
+ char newbuf[8];
+
+ if (hash_position) {
+ copy_length = strchr(hash_position, '-') - hash_position - 1;
+ if (copy_length < sizeof(newbuf)) {
+ strncpy(newbuf, hash_position + 1, copy_length);
+ sscanf(newbuf, "%d", &index);
+ }
+ }
+
+ return index;
+}
+
+static inline void get_sensor_suffix_from_name(const char *name, char *suffix)
+{
+ char *dash_position = strrchr(name, '-');
+ if (dash_position)
+ strncpy(suffix, dash_position+1, MAX_ATTR_LENGTH);
+ else
+ strcpy(suffix,"");
+}
+
+static int get_sensor_attr_properties(const char *sensor_name,
+ enum sensors sensor_type, enum attributes *attr_type,
+ u32 *sensor_index)
+{
+ char suffix[MAX_ATTR_LENGTH];
+
+ *attr_type = MAX_ATTR_TYPES;
+ *sensor_index = get_sensor_index_from_name(sensor_name);
+ if (*sensor_index == 0)
+ return -EINVAL;
+
+ get_sensor_suffix_from_name(sensor_name, suffix);
+ if (strcmp(suffix, "") == 0)
+ return -EINVAL;
+
+ if (strcmp(suffix, DT_FAULT_ATTR_SUFFIX) == 0)
+ *attr_type = FAULT;
+ else if (strcmp(suffix, DT_DATA_ATTR_SUFFIX) == 0)
+ *attr_type = INPUT;
+ else if ((sensor_type == TEMPERATURE) &&
+ (strcmp(suffix, DT_THRESHOLD_ATTR_SUFFIX) == 0))
+ *attr_type = MAXIMUM;
+ else if ((sensor_type == FAN) &&
+ (strcmp(suffix, DT_THRESHOLD_ATTR_SUFFIX) == 0))
+ *attr_type = MINIMUM;
+ else
+ return -ENOENT;
+
+ if (((sensor_type == FAN) && ((*attr_type == INPUT) ||
+ (*attr_type == MINIMUM)))
+ || ((sensor_type == TEMPERATURE) && ((*attr_type == INPUT) ||
+ (*attr_type == MAXIMUM)))
+ || ((sensor_type == POWER) && ((*attr_type == INPUT))))
+ return 0;
+
+ return -ENOENT;
+}
+
+static int create_sensor_attr(struct sensor_specific_data *tdata,
+ struct device *dev, enum sensors sensor_type,
+ enum attributes attr_type)
+{
+ int err = 0;
+ char temp_file_prefix[50];
+ static const char *const file_name_format = "%s%d_%s";
+
+ tdata->attr_type = attr_type;
+
+ if (sensor_type == FAN)
+ strcpy(temp_file_prefix, "fan");
+ else if (sensor_type == TEMPERATURE)
+ strcpy(temp_file_prefix, "temp");
+ else if (sensor_type == POWERSUPPLY)
+ strcpy(temp_file_prefix, "powersupply");
+ else if (sensor_type == POWER)
+ strcpy(temp_file_prefix, "power");
+
+ snprintf(tdata->attr_name, sizeof(tdata->attr_name), file_name_format,
+ temp_file_prefix, tdata->sensor_index,
+ attribute_type_table[tdata->attr_type]);
+
+ sysfs_attr_init(&tdata->sd_attr.dev_attr.attr);
+ tdata->sd_attr.dev_attr.attr.name = tdata->attr_name;
+ tdata->sd_attr.dev_attr.attr.mode = S_IRUGO;
+ tdata->sd_attr.dev_attr.show = show_sensor;
+
+ tdata->sd_attr.index = tdata->sensor_index;
+ err = device_create_file(dev, &tdata->sd_attr.dev_attr);
+
+ return err;
+}
+
+static int create_name_attr(struct sensor_data *pdata,
+ struct device *dev)
+{
+ sysfs_attr_init(&pdata->name_attr.attr);
+ pdata->name_attr.attr.name = "name";
+ pdata->name_attr.attr.mode = S_IRUGO;
+ pdata->name_attr.show = show_name;
+ return device_create_file(dev, &pdata->name_attr);
+}
+
+static int create_platform_device(enum sensors sensor_type,
+ struct platform_device **pdev)
+{
+ struct pdev_entry *pdev_entry = NULL;
+ int err;
+
+ *pdev = platform_device_alloc(sensor_names[sensor_type].name,
+ sensor_type);
+ if (!*pdev) {
+ pr_err("Device allocation failed\n");
+ err = -ENOMEM;
+ goto exit;
+ }
+
+ pdev_entry = kzalloc(sizeof(struct pdev_entry), GFP_KERNEL);
+ if (!pdev_entry) {
+ pr_err("Device allocation failed\n");
+ err = -ENOMEM;
+ goto exit_device_put;
+ }
+
+ err = platform_device_add(*pdev);
+ if (err) {
+ pr_err("Device addition failed (%d)\n", err);
+ goto exit_device_free;
+ }
+
+ pdev_entry->pdev = *pdev;
+ pdev_entry->type = (*pdev)->id;
+
+ list_add_tail(&pdev_entry->list, &pdev_list);
+
+ return 0;
+exit_device_free:
+ kfree(pdev_entry);
+exit_device_put:
+ platform_device_put(*pdev);
+exit:
+ return err;
+}
+
+static int create_sensor_data(struct platform_device *pdev)
+{
+ struct sensor_data *pdata = NULL;
+ int err = 0;
+
+ pdata = kzalloc(sizeof(struct sensor_data), GFP_KERNEL);
+ if (!pdata) {
+ err = -ENOMEM;
+ goto exit;
+ }
+
+ err = create_name_attr(pdata, &pdev->dev);
+ if (err)
+ goto exit_free;
+
+ pdata->hwmon_dev = hwmon_device_register(&pdev->dev);
+ if (IS_ERR(pdata->hwmon_dev)) {
+ err = PTR_ERR(pdata->hwmon_dev);
+ dev_err(&pdev->dev, "Class registration failed (%d)\n",
+ err);
+ goto exit_name;
+ }
+
+ INIT_LIST_HEAD(&pdata->sensor_list);
+ platform_set_drvdata(pdev, pdata);
+
+ return 0;
+
+exit_name:
+ device_remove_file(&pdev->dev, &pdata->name_attr);
+exit_free:
+ kfree(pdata);
+exit:
+ return err;
+}
+
+static void delete_sensor_attr(struct sensor_data *pdata)
+{
+ struct sensor_entry *s, *l;
+
+ list_for_each_entry_safe(s, l, &pdata->sensor_list, list) {
+ struct sensor_specific_data *tdata = s->sensor_data;
+ kfree(tdata);
+ list_del(&s->list);
+ kfree(s);
+ }
+}
+
+static int powernv_sensor_init(u32 sensor_id, const struct device_node *np,
+ enum sensors sensor_type, enum attributes attr_type,
+ u32 sensor_index)
+{
+ struct platform_device *pdev = powernv_sensor_get_pdev(sensor_type);
+ struct sensor_specific_data *tdata;
+ struct sensor_entry *sensor_entry;
+ struct sensor_data *pdata;
+ int err = 0;
+
+ if (!pdev) {
+ err = create_platform_device(sensor_type, &pdev);
+ if (err)
+ goto exit;
+
+ err = create_sensor_data(pdev);
+ if (err)
+ goto exit;
+ }
+
+ pdata = platform_get_drvdata(pdev);
+ if (!pdata) {
+ err = -ENOMEM;
+ goto exit;
+ }
+
+ tdata = kzalloc(sizeof(struct sensor_specific_data), GFP_KERNEL);
+ if (!tdata) {
+ err = -ENOMEM;
+ goto exit;
+ }
+
+ tdata->sensor_id = sensor_id;
+ tdata->sensor_index = sensor_index;
+
+ err = create_sensor_attr(tdata, &pdev->dev, sensor_type, attr_type);
+ if (err)
+ goto exit_free;
+
+ sensor_entry = kzalloc(sizeof(struct sensor_entry), GFP_KERNEL);
+ if (!sensor_entry) {
+ err = -ENOMEM;
+ goto exit_attr;
+ }
+
+ sensor_entry->sensor_data = tdata;
+
+ list_add_tail(&sensor_entry->list, &pdata->sensor_list);
+
+ return 0;
+exit_attr:
+ device_remove_file(&pdev->dev, &tdata->sd_attr.dev_attr);
+exit_free:
+ kfree(tdata);
+exit:
+ return err;
+}
+
+static void delete_unregister_sensors(void)
+{
+ struct pdev_entry *p, *n;
+
+ list_for_each_entry_safe(p, n, &pdev_list, list) {
+ struct sensor_data *pdata = platform_get_drvdata(p->pdev);
+ if (pdata) {
+ delete_sensor_attr(pdata);
+
+ hwmon_device_unregister(pdata->hwmon_dev);
+ kfree(pdata);
+ }
+ platform_device_unregister(p->pdev);
+ list_del(&p->list);
+ kfree(p);
+ }
+}
+
+static int __init powernv_hwmon_init(void)
+{
+ struct device_node *opal, *np = NULL;
+ enum attributes attr_type;
+ enum sensors type;
+ const u32 *sensor_id;
+ u32 sensor_index;
+ int err;
+
+ opal = of_find_node_by_path("/ibm,opal/sensors");
+ if (!opal) {
+ pr_err("%s: Opal 'sensors' node not found\n", __func__);
+ return -ENXIO;
+ }
+
+ for_each_child_of_node(opal, np) {
+ if (np->name == NULL)
+ continue;
+
+ for (type = 0; type < MAX_SENSOR_TYPE; type++)
+ if (of_device_is_compatible(np,
+ sensor_names[type].compaible))
+ break;
+
+ if (type == MAX_SENSOR_TYPE)
+ continue;
+
+ if (get_sensor_attr_properties(np->name, type, &attr_type,
+ &sensor_index))
+ continue;
+
+ sensor_id = of_get_property(np, "sensor-id", NULL);
+ if (!sensor_id) {
+ pr_info("%s: %s doesn't have sensor-id\n", __func__,
+ np->name);
+ continue;
+ }
+
+ err = powernv_sensor_init(*sensor_id, np, type, attr_type,
+ sensor_index);
+ if (err) {
+ of_node_put(opal);
+ goto exit;
+ }
+ }
+ of_node_put(opal);
+
+ return 0;
+exit:
+ delete_unregister_sensors();
+ return err;
+
+}
+
+static void powernv_hwmon_exit(void)
+{
+ delete_unregister_sensors();
+}
+
+module_init(powernv_hwmon_init);
+module_exit(powernv_hwmon_exit);
^ permalink raw reply related
* [PATCH 1/2] powerpc/powernv: Enable fetching of platform sensor data
From: Neelesh Gupta @ 2014-03-07 5:33 UTC (permalink / raw)
To: linuxppc-dev; +Cc: sbhat
In-Reply-To: <20140307053236.3547.55729.stgit@neelegup-tp-t420.in.ibm.com>
This patch enables fetching of various platform sensor data through
OPAL and expects a sensor handle from the driver to pass to OPAL.
Signed-off-by: Neelesh Gupta <neelegup@linux.vnet.ibm.com>
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---
arch/powerpc/include/asm/opal.h | 4 ++
arch/powerpc/platforms/powernv/Makefile | 2 -
arch/powerpc/platforms/powernv/opal-sensor.c | 64 ++++++++++++++++++++++++
arch/powerpc/platforms/powernv/opal-wrappers.S | 1
4 files changed, 70 insertions(+), 1 deletion(-)
create mode 100644 arch/powerpc/platforms/powernv/opal-sensor.c
diff --git a/arch/powerpc/include/asm/opal.h b/arch/powerpc/include/asm/opal.h
index 60b3edc..a1cc4dd 100644
--- a/arch/powerpc/include/asm/opal.h
+++ b/arch/powerpc/include/asm/opal.h
@@ -159,6 +159,7 @@ extern int opal_enter_rtas(struct rtas_args *args,
#define OPAL_GET_MSG 85
#define OPAL_CHECK_ASYNC_COMPLETION 86
#define OPAL_SYNC_HOST_REBOOT 87
+#define OPAL_SENSOR_READ 88
#define OPAL_GET_PARAM 89
#define OPAL_SET_PARAM 90
@@ -847,6 +848,8 @@ int64_t opal_get_param(uint64_t token, uint32_t param_id, uint64_t buffer,
size_t length);
int64_t opal_set_param(uint64_t token, uint32_t param_id, uint64_t buffer,
size_t length);
+int64_t opal_sensor_read(uint32_t sensor_hndl, int token,
+ uint32_t *sensor_data);
/* Internal functions */
extern int early_init_dt_scan_opal(unsigned long node, const char *uname, int depth, void *data);
@@ -875,6 +878,7 @@ extern int opal_async_get_token_interruptible(void);
extern int __opal_async_release_token(int token);
extern int opal_async_release_token(int token);
extern int opal_async_wait_response(uint64_t token, struct opal_msg *msg);
+extern int opal_get_sensor_data(u32 sensor_hndl, u32 *sensor_data);
extern void hvc_opal_init_early(void);
diff --git a/arch/powerpc/platforms/powernv/Makefile b/arch/powerpc/platforms/powernv/Makefile
index e6166d3..00ae938 100644
--- a/arch/powerpc/platforms/powernv/Makefile
+++ b/arch/powerpc/platforms/powernv/Makefile
@@ -1,6 +1,6 @@
obj-y += setup.o opal-takeover.o opal-wrappers.o opal.o opal-async.o
obj-y += opal-rtc.o opal-nvram.o opal-lpc.o opal-flash.o opal-sysparam.o
-obj-y += rng.o
+obj-y += rng.o opal-sensor.o
obj-$(CONFIG_SMP) += smp.o
obj-$(CONFIG_PCI) += pci.o pci-p5ioc2.o pci-ioda.o
diff --git a/arch/powerpc/platforms/powernv/opal-sensor.c b/arch/powerpc/platforms/powernv/opal-sensor.c
new file mode 100644
index 0000000..663cc9c
--- /dev/null
+++ b/arch/powerpc/platforms/powernv/opal-sensor.c
@@ -0,0 +1,64 @@
+/*
+ * PowerNV sensor code
+ *
+ * Copyright (C) 2013 IBM
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <linux/delay.h>
+#include <linux/mutex.h>
+#include <asm/opal.h>
+
+static DEFINE_MUTEX(opal_sensor_mutex);
+
+/*
+ * This will return sensor information to driver based on the requested sensor
+ * handle. A handle is an opaque id for the powernv, read by the driver from the
+ * device tree..
+ */
+int opal_get_sensor_data(u32 sensor_hndl, u32 *sensor_data)
+{
+ int ret, token;
+ struct opal_msg msg;
+
+ token = opal_async_get_token_interruptible();
+ if (token < 0) {
+ pr_err("%s: Couldn't get the token, returning\n", __func__);
+ ret = token;
+ goto out;
+ }
+
+ mutex_lock(&opal_sensor_mutex);
+ ret = opal_sensor_read(sensor_hndl, token, sensor_data);
+ if (ret != OPAL_ASYNC_COMPLETION)
+ goto out_token;
+
+ ret = opal_async_wait_response(token, &msg);
+ if (ret) {
+ pr_err("%s: Failed to wait for the async response, %d\n",
+ __func__, ret);
+ goto out_token;
+ }
+
+ ret = msg.params[1];
+
+out_token:
+ mutex_unlock(&opal_sensor_mutex);
+ opal_async_release_token(token);
+out:
+ return ret;
+}
+EXPORT_SYMBOL_GPL(opal_get_sensor_data);
diff --git a/arch/powerpc/platforms/powernv/opal-wrappers.S b/arch/powerpc/platforms/powernv/opal-wrappers.S
index 0afdeca..4279e30 100644
--- a/arch/powerpc/platforms/powernv/opal-wrappers.S
+++ b/arch/powerpc/platforms/powernv/opal-wrappers.S
@@ -129,5 +129,6 @@ OPAL_CALL(opal_update_flash, OPAL_FLASH_UPDATE);
OPAL_CALL(opal_get_msg, OPAL_GET_MSG);
OPAL_CALL(opal_check_completion, OPAL_CHECK_ASYNC_COMPLETION);
OPAL_CALL(opal_sync_host_reboot, OPAL_SYNC_HOST_REBOOT);
+OPAL_CALL(opal_sensor_read, OPAL_SENSOR_READ);
OPAL_CALL(opal_get_param, OPAL_GET_PARAM);
OPAL_CALL(opal_set_param, OPAL_SET_PARAM);
^ permalink raw reply related
* [PATCH 0/2] Enable powernv based platform sensors
From: Neelesh Gupta @ 2014-03-07 5:33 UTC (permalink / raw)
To: linuxppc-dev; +Cc: sbhat
This patchset contains the enablement code to expose platform sensor data
on powernv platform. First patch fetches the sensor data from the firmware
and second patch being an hwmon driver, enables the sysfs interfaces.
---
Neelesh Gupta (1):
powerpc/powernv: Enable fetching of platform sensor data
Shivaprasad G Bhat (1):
powerpc/powernv: hwmon driver for power values, fan rpm and temperature
arch/powerpc/include/asm/opal.h | 4
arch/powerpc/platforms/powernv/Makefile | 2
arch/powerpc/platforms/powernv/opal-sensor.c | 64 +++
arch/powerpc/platforms/powernv/opal-wrappers.S | 1
drivers/hwmon/Kconfig | 8
drivers/hwmon/Makefile | 1
drivers/hwmon/ibmpowernv.c | 529 ++++++++++++++++++++++++
7 files changed, 608 insertions(+), 1 deletion(-)
create mode 100644 arch/powerpc/platforms/powernv/opal-sensor.c
create mode 100644 drivers/hwmon/ibmpowernv.c
--
Signature
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox