LinuxPPC-Dev Archive on lore.kernel.org
 help / color / mirror / Atom feed
* Re: [RFC] PPC: MPIC: necessary readback after EOI?
From: Segher Boessenkool @ 2015-01-08  0:49 UTC (permalink / raw)
  To: Benjamin Herrenschmidt; +Cc: linuxppc-dev, Purcareata Bogdan, linux-kernel
In-Reply-To: <1420641610.5830.29.camel@kernel.crashing.org>

On Wed, Jan 07, 2015 at 03:40:10PM +0100, Benjamin Herrenschmidt wrote:
> One way to work around the performance loss for you would be to add some
> DT property to indicate to the guest that the read isn't necessary.

Or KVM could use a virtual interrupt controller better suited to its
needs.


Segher

^ permalink raw reply

* [PATCH 2/3] module: remove mod arg from module_free, rename module_memfree().
From: Rusty Russell @ 2015-01-08  0:58 UTC (permalink / raw)
  To: linux-kernel
  Cc: linux-mips, Jesper Nilsson, x86, linux-cris-kernel, Rusty Russell,
	Alexei Starovoitov, Ralf Baechle, Anil S Keshavamurthy,
	Mikael Starvik, sparclinux, Chris Metcalf, netdev, Steven Rostedt,
	nios2-dev, Masami Hiramatsu, Ley Foon Tan, linuxppc-dev
In-Reply-To: <1420678687-30548-1-git-send-email-rusty@rustcorp.com.au>

Nothing needs the module pointer any more, and the next patch will
call it from RCU, where the module itself might no longer exist.
Removing the arg is the safest approach.

This just codifies the use of the module_alloc/module_free pattern
which ftrace and bpf use.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Cc: Mikael Starvik <starvik@axis.com>
Cc: Jesper Nilsson <jesper.nilsson@axis.com>
Cc: Ralf Baechle <ralf@linux-mips.org>
Cc: Ley Foon Tan <lftan@altera.com>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: Chris Metcalf <cmetcalf@ezchip.com>
Cc: Steven Rostedt <rostedt@goodmis.org>
Cc: x86@kernel.org
Cc: Alexei Starovoitov <ast@kernel.org>
Cc: Ananth N Mavinakayanahalli <ananth@in.ibm.com>
Cc: Anil S Keshavamurthy <anil.s.keshavamurthy@intel.com>
Cc: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
Cc: linux-cris-kernel@axis.com
Cc: linux-kernel@vger.kernel.org
Cc: linux-mips@linux-mips.org
Cc: nios2-dev@lists.rocketboards.org
Cc: linuxppc-dev@lists.ozlabs.org
Cc: sparclinux@vger.kernel.org
Cc: netdev@vger.kernel.org
---
 arch/cris/kernel/module.c       |  2 +-
 arch/mips/net/bpf_jit.c         |  2 +-
 arch/nios2/kernel/module.c      |  2 +-
 arch/powerpc/net/bpf_jit_comp.c |  2 +-
 arch/sparc/net/bpf_jit_comp.c   |  4 ++--
 arch/tile/kernel/module.c       |  2 +-
 arch/x86/kernel/ftrace.c        |  2 +-
 include/linux/moduleloader.h    |  2 +-
 kernel/bpf/core.c               |  2 +-
 kernel/kprobes.c                |  2 +-
 kernel/module.c                 | 14 +++++++-------
 11 files changed, 18 insertions(+), 18 deletions(-)

diff --git a/arch/cris/kernel/module.c b/arch/cris/kernel/module.c
index 51123f985eb5..af04cb6b6dc9 100644
--- a/arch/cris/kernel/module.c
+++ b/arch/cris/kernel/module.c
@@ -36,7 +36,7 @@ void *module_alloc(unsigned long size)
 }
 
 /* Free memory returned from module_alloc */
-void module_free(struct module *mod, void *module_region)
+void module_memfree(void *module_region)
 {
 	kfree(module_region);
 }
diff --git a/arch/mips/net/bpf_jit.c b/arch/mips/net/bpf_jit.c
index 9fd6834a2172..5d6139390bf8 100644
--- a/arch/mips/net/bpf_jit.c
+++ b/arch/mips/net/bpf_jit.c
@@ -1388,7 +1388,7 @@ out:
 void bpf_jit_free(struct bpf_prog *fp)
 {
 	if (fp->jited)
-		module_free(NULL, fp->bpf_func);
+		module_memfree(fp->bpf_func);
 
 	bpf_prog_unlock_free(fp);
 }
diff --git a/arch/nios2/kernel/module.c b/arch/nios2/kernel/module.c
index cc924a38f22a..e2e3f13f98d5 100644
--- a/arch/nios2/kernel/module.c
+++ b/arch/nios2/kernel/module.c
@@ -36,7 +36,7 @@ void *module_alloc(unsigned long size)
 }
 
 /* Free memory returned from module_alloc */
-void module_free(struct module *mod, void *module_region)
+void module_memfree(void *module_region)
 {
 	kfree(module_region);
 }
diff --git a/arch/powerpc/net/bpf_jit_comp.c b/arch/powerpc/net/bpf_jit_comp.c
index 1ca125b9c226..d1916b577f2c 100644
--- a/arch/powerpc/net/bpf_jit_comp.c
+++ b/arch/powerpc/net/bpf_jit_comp.c
@@ -699,7 +699,7 @@ out:
 void bpf_jit_free(struct bpf_prog *fp)
 {
 	if (fp->jited)
-		module_free(NULL, fp->bpf_func);
+		module_memfree(fp->bpf_func);
 
 	bpf_prog_unlock_free(fp);
 }
diff --git a/arch/sparc/net/bpf_jit_comp.c b/arch/sparc/net/bpf_jit_comp.c
index f33e7c7a3bf7..7931eeeb649a 100644
--- a/arch/sparc/net/bpf_jit_comp.c
+++ b/arch/sparc/net/bpf_jit_comp.c
@@ -776,7 +776,7 @@ cond_branch:			f_offset = addrs[i + filter[i].jf];
 				if (unlikely(proglen + ilen > oldproglen)) {
 					pr_err("bpb_jit_compile fatal error\n");
 					kfree(addrs);
-					module_free(NULL, image);
+					module_memfree(image);
 					return;
 				}
 				memcpy(image + proglen, temp, ilen);
@@ -822,7 +822,7 @@ out:
 void bpf_jit_free(struct bpf_prog *fp)
 {
 	if (fp->jited)
-		module_free(NULL, fp->bpf_func);
+		module_memfree(fp->bpf_func);
 
 	bpf_prog_unlock_free(fp);
 }
diff --git a/arch/tile/kernel/module.c b/arch/tile/kernel/module.c
index 62a597e810d6..2305084c9b93 100644
--- a/arch/tile/kernel/module.c
+++ b/arch/tile/kernel/module.c
@@ -74,7 +74,7 @@ error:
 
 
 /* Free memory returned from module_alloc */
-void module_free(struct module *mod, void *module_region)
+void module_memfree(void *module_region)
 {
 	vfree(module_region);
 
diff --git a/arch/x86/kernel/ftrace.c b/arch/x86/kernel/ftrace.c
index 2142376dc8c6..8b7b0a51e742 100644
--- a/arch/x86/kernel/ftrace.c
+++ b/arch/x86/kernel/ftrace.c
@@ -674,7 +674,7 @@ static inline void *alloc_tramp(unsigned long size)
 }
 static inline void tramp_free(void *tramp)
 {
-	module_free(NULL, tramp);
+	module_memfree(tramp);
 }
 #else
 /* Trampolines can only be created if modules are supported */
diff --git a/include/linux/moduleloader.h b/include/linux/moduleloader.h
index 054eac853090..f7556261fe3c 100644
--- a/include/linux/moduleloader.h
+++ b/include/linux/moduleloader.h
@@ -26,7 +26,7 @@ unsigned int arch_mod_section_prepend(struct module *mod, unsigned int section);
 void *module_alloc(unsigned long size);
 
 /* Free memory returned from module_alloc. */
-void module_free(struct module *mod, void *module_region);
+void module_memfree(void *module_region);
 
 /*
  * Apply the given relocation to the (simplified) ELF.  Return -error
diff --git a/kernel/bpf/core.c b/kernel/bpf/core.c
index d6594e457a25..a64e7a207d2b 100644
--- a/kernel/bpf/core.c
+++ b/kernel/bpf/core.c
@@ -163,7 +163,7 @@ bpf_jit_binary_alloc(unsigned int proglen, u8 **image_ptr,
 
 void bpf_jit_binary_free(struct bpf_binary_header *hdr)
 {
-	module_free(NULL, hdr);
+	module_memfree(hdr);
 }
 #endif /* CONFIG_BPF_JIT */
 
diff --git a/kernel/kprobes.c b/kernel/kprobes.c
index 06f58309fed2..ee619929cf90 100644
--- a/kernel/kprobes.c
+++ b/kernel/kprobes.c
@@ -127,7 +127,7 @@ static void *alloc_insn_page(void)
 
 static void free_insn_page(void *page)
 {
-	module_free(NULL, page);
+	module_memfree(page);
 }
 
 struct kprobe_insn_cache kprobe_insn_slots = {
diff --git a/kernel/module.c b/kernel/module.c
index 68be0b1f9e7f..1f85fd5c89d3 100644
--- a/kernel/module.c
+++ b/kernel/module.c
@@ -1795,7 +1795,7 @@ static void unset_module_core_ro_nx(struct module *mod) { }
 static void unset_module_init_ro_nx(struct module *mod) { }
 #endif
 
-void __weak module_free(struct module *mod, void *module_region)
+void __weak module_memfree(void *module_region)
 {
 	vfree(module_region);
 }
@@ -1846,7 +1846,7 @@ static void free_module(struct module *mod)
 	/* This may be NULL, but that's OK */
 	unset_module_init_ro_nx(mod);
 	module_arch_freeing_init(mod);
-	module_free(mod, mod->module_init);
+	module_memfree(mod->module_init);
 	kfree(mod->args);
 	percpu_modfree(mod);
 
@@ -1855,7 +1855,7 @@ static void free_module(struct module *mod)
 
 	/* Finally, free the core (containing the module structure) */
 	unset_module_core_ro_nx(mod);
-	module_free(mod, mod->module_core);
+	module_memfree(mod->module_core);
 
 #ifdef CONFIG_MPU
 	update_protections(current->mm);
@@ -2790,7 +2790,7 @@ static int move_module(struct module *mod, struct load_info *info)
 		 */
 		kmemleak_ignore(ptr);
 		if (!ptr) {
-			module_free(mod, mod->module_core);
+			module_memfree(mod->module_core);
 			return -ENOMEM;
 		}
 		memset(ptr, 0, mod->init_size);
@@ -2936,8 +2936,8 @@ static void module_deallocate(struct module *mod, struct load_info *info)
 {
 	percpu_modfree(mod);
 	module_arch_freeing_init(mod);
-	module_free(mod, mod->module_init);
-	module_free(mod, mod->module_core);
+	module_memfree(mod->module_init);
+	module_memfree(mod->module_core);
 }
 
 int __weak module_finalize(const Elf_Ehdr *hdr,
@@ -3062,7 +3062,7 @@ static int do_init_module(struct module *mod)
 #endif
 	unset_module_init_ro_nx(mod);
 	module_arch_freeing_init(mod);
-	module_free(mod, mod->module_init);
+	module_memfree(mod->module_init);
 	mod->module_init = NULL;
 	mod->init_size = 0;
 	mod->init_ro_size = 0;
-- 
2.1.0

^ permalink raw reply related

* Re: [PATCH] [v3] power/fsl: add MDIO dt binding for FMan
From: Scott Wood @ 2015-01-08  1:12 UTC (permalink / raw)
  To: Emil Medve
  Cc: devicetree@vger.kernel.org, linuxppc-dev@lists.ozlabs.org,
	Xie Shaohui-B21989
In-Reply-To: <54AD8C8A.8070100@Freescale.com>

On Wed, 2015-01-07 at 13:44 -0600, Emil Medve wrote:
> Hello Scott,
> 
> 
> On 01/07/2015 12:05 PM, Scott Wood wrote:
> > On Tue, 2015-01-06 at 23:29 -0600, Xie Shaohui-B21989 wrote:
> >>>>> +- interrupts
> >>>>> +		Usage: optional
> >>>>> +		Value type: <prop-encoded-array>
> >>>>> +		Definition: Event interrupt of external MDIO controller.
> >>>>> +		1 Gb/s MDIO and 10 Gb/s MDIO has one interrupt respectively.
> >>>
> >>> I'm confused by "respectively" here.  Does fsl,fman-memac-mdio have two
> >>> interrupts (one for 1 Gb/s and one for 10 Gb/s)?
> >> [S.H] We use two MDIO controllers for external PHY management. One for 1 Gb/s,
> >> One for 10 Gb/s, and two MDIO interrupts connected to MPIC.
> > 
> > If there can be two interrupts you need to make that clear and specify
> > the order.
> > 
> > Is it possible for one MDIO controller to have an interrupt connected
> > but not the other, on the same system?  How would you represent that in
> > the device tree?  If there are two MDIO controllers why are they in the
> > same node?
> 
> Historically (FMan v2 and even before/legacy) we've had each MAC include
> an MDIO controller, but only one MDIO controller per MAC type/speed (1
> Gb/s vs 10 Gb/s) is pinned out and all the same speed PHY(s) are
> connected to the respective MDIO controllers. As such the first 1 Gb/s
> MAC/MDIO controller is used to manage all the 1 Gb/s PHY(s) and the
> first 10 Gb/s MAC/MDIO controller is used to manage all the 10 Gb/s
> PHY(s). Each MDIO controller has the ability to generate interrupts but
> only pinned out MDIO controllers are hooked up to the MPIC (as such the
> talk about two interrupts)
> 
> (Each MAC has also integrated a SERDES/TBI/"internal" PHY that is
> connected to the "local" MDIO controller)
> 
> As you can imagine this creates a number of problems in a partitioning
> scenario (and not just, imagine RCWs where the first MAC is not
> used/enabled). In order to help a bit (but not quite enough), in FMan
> v3, two additional MDIO controllers (one for 1 the Gb/s PHY(s) and one
> for 1 the 10 Gb/s PHY(s)) have been integrated that are not associated
> with any MAC and these are the pinned out MDIO controllers on such
> SoC(s) (chassis v2)

I'm happy to hear that.  Is that what is meant by "external" here?  I
thought it meant external to the SoC.  Is this the term used by hardware
documentation?  I'd have called it "independent" or similar.

> >>   Does "optional" mean it's used if and
> >>> only if external MDIO is used, or is it optional even with external MDIO?  I see
> >>> it's not present in the example -- do we not have a real example that has the
> >>> interrupt?
> >> [S.H] "optional" means it's available on hardware, but MDIO driver does not use interrupt. 
> >> So we don't have a real example.
> > 
> > <record type="broken">The device tree describes the hardware, not the
> > driver</record>
> 
> Anyway, only two MDIO nodes (out of 4 to 14) would have an interrupt
> property describing exactly one interrupt. What language should we use
> to convey this situation

So the answer is that there will not be more than one MDIO controller
per MDIO node, or more than one interrupt per MDIO node?  In that case
just get rid of the confusing "respectively" sentence -- and always
describe the interrupt if it exists in hardware.

-Scott

^ permalink raw reply

* [PATCH v7 1/4] tools/perf: support parsing parameterized events
From: Sukadev Bhattiprolu @ 2015-01-08  1:13 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo, Jiri Olsa, Michael Ellerman,
	Paul Mackerras
  Cc: peterz, linuxppc-dev, dev, linux-kernel
In-Reply-To: <1420679633-28856-1-git-send-email-sukadev@linux.vnet.ibm.com>

From: Cody P Schafer <cody@linux.vnet.ibm.com>

Enable event specification like:

	pmu/event_name,param1=0x1,param2=0x4/

Assuming that

	/sys/bus/event_source/devices/pmu/events/event_name

Contains something like

	param2=?,bar=1,param1=?

CC: Haren Myneni <hbabu@us.ibm.com>
CC: Cody P Schafer <dev@codyps.com>
Acked-by: Jiri Olsa <jolsa@kernel.org>
Signed-off-by: Sukadev Bhattiprolu <sukadev@linux.vnet.ibm.com>
Signed-off-by: Cody P Schafer <cody@linux.vnet.ibm.com>
---
Changelog[v6]:
	[Jiri Olsa] Add a check to make sure that sysfs entries have with
	parameters exactly match '=?'.

Changelog[v4]:
	[Jiri Olsa] Merge to recent perf-core and fix a small conflict.

Changelog[v3]:
	[Jiri Olsa] If the sysfs event file specifies 'param=val', make the
	usage 'hv_24x7/event,param=123/' rather than 'hv_24x7/event,val=123/'.

 tools/perf/util/parse-events.h |  1 +
 tools/perf/util/pmu.c          | 74 +++++++++++++++++++++++++++++++++++-------
 2 files changed, 64 insertions(+), 11 deletions(-)

diff --git a/tools/perf/util/parse-events.h b/tools/perf/util/parse-events.h
index db2cf78..ca226ce 100644
--- a/tools/perf/util/parse-events.h
+++ b/tools/perf/util/parse-events.h
@@ -71,6 +71,7 @@ struct parse_events_term {
 	int type_val;
 	int type_term;
 	struct list_head list;
+	bool used;
 };
 
 struct parse_events_evlist {
diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c
index 5c9c494..bfbecf7 100644
--- a/tools/perf/util/pmu.c
+++ b/tools/perf/util/pmu.c
@@ -551,31 +551,68 @@ static void pmu_format_value(unsigned long *format, __u64 value, __u64 *v,
 }
 
 /*
+ * Term is a string term, and might be a param-term. Try to look up it's value
+ * in the remaining terms.
+ * - We have a term like "base-or-format-term=param-term",
+ * - We need to find the value supplied for "param-term" (with param-term named
+ *   in a config string) later on in the term list.
+ */
+static int pmu_resolve_param_term(struct parse_events_term *term,
+				  struct list_head *head_terms,
+				  __u64 *value)
+{
+	struct parse_events_term *t;
+
+	list_for_each_entry(t, head_terms, list) {
+		if (t->type_val == PARSE_EVENTS__TERM_TYPE_NUM) {
+			if (!strcmp(t->config, term->config)) {
+				t->used = true;
+				*value = t->val.num;
+				return 0;
+			}
+		}
+	}
+
+	if (verbose)
+		printf("Required parameter '%s' not specified\n", term->config);
+
+	return -1;
+}
+
+/*
  * Setup one of config[12] attr members based on the
  * user input data - term parameter.
  */
 static int pmu_config_term(struct list_head *formats,
 			   struct perf_event_attr *attr,
 			   struct parse_events_term *term,
+			   struct list_head *head_terms,
 			   bool zero)
 {
 	struct perf_pmu_format *format;
 	__u64 *vp;
+	__u64 val;
+
+	/*
+	 * If this is a parameter we've already used for parameterized-eval,
+	 * skip it in normal eval.
+	 */
+	if (term->used)
+		return 0;
 
 	/*
-	 * Support only for hardcoded and numnerial terms.
 	 * Hardcoded terms should be already in, so nothing
 	 * to be done for them.
 	 */
 	if (parse_events__is_hardcoded_term(term))
 		return 0;
 
-	if (term->type_val != PARSE_EVENTS__TERM_TYPE_NUM)
-		return -EINVAL;
-
 	format = pmu_find_format(formats, term->config);
-	if (!format)
+	if (!format) {
+		if (verbose)
+			printf("Invalid event/parameter '%s'\n", term->config);
 		return -EINVAL;
+	}
 
 	switch (format->value) {
 	case PERF_PMU_FORMAT_VALUE_CONFIG:
@@ -592,11 +629,25 @@ static int pmu_config_term(struct list_head *formats,
 	}
 
 	/*
-	 * XXX If we ever decide to go with string values for
-	 * non-hardcoded terms, here's the place to translate
-	 * them into value.
+	 * Either directly use a numeric term, or try to translate string terms
+	 * using event parameters.
 	 */
-	pmu_format_value(format->bits, term->val.num, vp, zero);
+	if (term->type_val == PARSE_EVENTS__TERM_TYPE_NUM)
+		val = term->val.num;
+	else if (term->type_val == PARSE_EVENTS__TERM_TYPE_STR) {
+		if (strcmp(term->val.str, "?")) {
+			if (verbose)
+				pr_info("Invalid sysfs entry %s=%s\n",
+						term->config, term->val.str);
+			return -EINVAL;
+		}
+
+		if (pmu_resolve_param_term(term, head_terms, &val))
+			return -EINVAL;
+	} else
+		return -EINVAL;
+
+	pmu_format_value(format->bits, val, vp, zero);
 	return 0;
 }
 
@@ -607,9 +658,10 @@ int perf_pmu__config_terms(struct list_head *formats,
 {
 	struct parse_events_term *term;
 
-	list_for_each_entry(term, head_terms, list)
-		if (pmu_config_term(formats, attr, term, zero))
+	list_for_each_entry(term, head_terms, list) {
+		if (pmu_config_term(formats, attr, term, head_terms, zero))
 			return -EINVAL;
+	}
 
 	return 0;
 }
-- 
1.8.3.1

^ permalink raw reply related

* [PATCH v7 0/4] Add support for parametrized events
From: Sukadev Bhattiprolu @ 2015-01-08  1:13 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo, Jiri Olsa, Michael Ellerman,
	Paul Mackerras
  Cc: peterz, linuxppc-dev, dev, linux-kernel

Description of "event parameters" from the documentation patch:

    Event parameters are a basic way for partial events to be specified in
    sysfs with per-event names given to the fields that need to be filled in
    when using a particular event.

    It is intended for supporting cases where the single 'cpu' parameter is
    insufficient. For example, POWER 8 has events for physical
    sockets/cores/cpus that are accessible from with virtual machines. To
    keep using the single 'cpu' parameter we'd need to perform a mapping
    between Linux's cpus and the physical machine's cpus (in this case
    Linux is running under a hypervisor). This isn't possible because
    bindings between our cpus and physical cpus may not be fixed, and we
    probably won't have a "cpu" on each physical cpu.

Description of the sysfs contents when events are parameterized (copied from an
included patch):

	Examples:

		domain=0x1,offset=0x8,core=?

	In the case of the last example, a value replacing "?" would need
	to be provided by the user selecting the particular event. This is
	refered to as "event parameterization". All non-numerical values
	indicate an event parameter.

Notes on how perf-list displays parameterized events

	PARAMETERIZED EVENTS
	--------------------

	Some pmu events listed by 'perf list' will be displayed with '$xyz' in
	them. For example:

	  hv_24x7/HPM_THREAD_NAP_CCYC__PHYS_CORE,core=?/

	This means that when provided as an event, a value for ? must also
	be supplied. For example:

	  perf stat  -e \
	  	'hv_24x7/HPM_THREAD_NAP_CCYC__PHYS_CORE,core=2' ...

Changelog[v7]
	[Jiri Olsa] Nit: Add braces for clarity.
	[Jiri Olsa] Add a check to make sure that sysfs entries have with
	parameters exactly match '=?'.

Changelog[v6]

	[Jiri Olsa, Sukadev Bhattiprolu] Rather than display
	'starting_index=$core' in perf.list and sysfs and expect user to
	specify a value for 'starting_index', replace 'starting_index' with
	what it really means for the event. i.e for an event, if starting_index
	refers to 'core' then display 'core=?' in both perf list and sysfs (see
	examples above).

Changelog[v5]
	- [Jiri Olsa, Peter Zijlstra] Use '$arg' notation rather than ?
	  to indicate event parameters.

	- [Michael Ellerman] Separate the kernel and tool patches in the
	  patchset into different patchsets.

Changelog[v4]
	- [Jiri Olsa] Rebase to perf/core tree (fix small merge conflict)

Changelog[v3]
	- [Jiri Olsa] Changed the event parameters are specified. If
	  event file specifes 'param=val' make the usage 'param=123'
	  rather than 'val=123'. (patch 1,2/10)
	- Shortened event names using "PHYS" and "VCPU" (patch 4/10)
	- Print help message if invalid parameter is specified or required
	  parameter is missing.
	- Moved 3 patches that are unrelated to parametrized events into
	  a separate patchset.
	- Reordered patches so code changes come first.

Changelog[v2]
	- [Joe Perches, David Laight] Use beNN_to_cpu() instead of guessing
	  the size from type.
	- Use kmem_cache_free() to free page allocated with kmem_cache_alloc().
	- Rebase to recent kernel

Cody P Schafer (4):
  tools/perf: support parsing parameterized events
  tools/perf: extend format_alias() to include event parameters
  perf Documentation: add event parameters
  tools/perf: Document parameterized and symbolic events

 .../testing/sysfs-bus-event_source-devices-events  |  6 ++
 tools/perf/Documentation/perf-list.txt             | 13 +++
 tools/perf/Documentation/perf-record.txt           | 12 +++
 tools/perf/Documentation/perf-stat.txt             | 20 ++++-
 tools/perf/util/parse-events.h                     |  1 +
 tools/perf/util/pmu.c                              | 92 +++++++++++++++++++---
 6 files changed, 128 insertions(+), 16 deletions(-)

-- 
1.8.3.1

^ permalink raw reply

* [PATCH v7 2/4] tools/perf: extend format_alias() to include event parameters
From: Sukadev Bhattiprolu @ 2015-01-08  1:13 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo, Jiri Olsa, Michael Ellerman,
	Paul Mackerras
  Cc: peterz, linuxppc-dev, dev, linux-kernel
In-Reply-To: <1420679633-28856-1-git-send-email-sukadev@linux.vnet.ibm.com>

From: Cody P Schafer <cody@linux.vnet.ibm.com>

This causes `perf list pmu` to show parameters for parameterized events
like:

  pmu/event_name,param1=?,param2=?/ [Kernel PMU event]

An example:

  hv_24x7/HPM_TLBIE__PHYS_CORE,core=?/ [Kernel PMU event]

CC: Haren Myneni <hbabu@us.ibm.com>
CC: Cody P Schafer <dev@codyps.com>
Acked-by: Jiri Olsa <jolsa@kernel.org>
Signed-off-by: Cody P Schafer <cody@linux.vnet.ibm.com>
Signed-off-by: Sukadev Bhattiprolu <sukadev@linux.vnet.ibm.com>
---
Changelog[v7]
	[Jiri Olsa] Nit: Add braces for clarity.

Changelog[v6]
	[Jiri Olsa, Sukadev Bhattiprolu] Drop the '$' sign and go back to
	just printing whatevever sysfs provides (which is '=?') to identify
	required parameters. sysfs also now uses parameters like 'core'
	and 'vcpu' rather than 'starting_index'.

Changelog[v5]
	[Jiri Olsa, Peter Zijlstra] Use '$' to prefix parameterized events.

Changelog[v4]
	[Jiri Olsa] If the parameter for an event in sysfs is 'param=val',
	have perf-list show the event as 'param=?' rather than 'val=?'.

 tools/perf/util/pmu.c | 28 +++++++++++++++++++++++++++-
 1 file changed, 27 insertions(+), 1 deletion(-)

diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c
index bfbecf7..4841167 100644
--- a/tools/perf/util/pmu.c
+++ b/tools/perf/util/pmu.c
@@ -819,10 +819,36 @@ void perf_pmu__set_format(unsigned long *bits, long from, long to)
 		set_bit(b, bits);
 }
 
+static int sub_non_neg(int a, int b)
+{
+	if (b > a)
+		return 0;
+	return a - b;
+}
+
 static char *format_alias(char *buf, int len, struct perf_pmu *pmu,
 			  struct perf_pmu_alias *alias)
 {
-	snprintf(buf, len, "%s/%s/", pmu->name, alias->name);
+	struct parse_events_term *term;
+	int used = snprintf(buf, len, "%s/%s", pmu->name, alias->name);
+
+	list_for_each_entry(term, &alias->terms, list) {
+		if (term->type_val == PARSE_EVENTS__TERM_TYPE_STR)
+			used += snprintf(buf + used, sub_non_neg(len, used),
+					",%s=%s", term->config,
+					term->val.str);
+	}
+
+	if (sub_non_neg(len, used) > 0) {
+		buf[used] = '/';
+		used++;
+	}
+	if (sub_non_neg(len, used) > 0) {
+		buf[used] = '\0';
+		used++;
+	} else
+		buf[len - 1] = '\0';
+
 	return buf;
 }
 
-- 
1.8.3.1

^ permalink raw reply related

* [PATCH v7 3/4] perf Documentation: add event parameters
From: Sukadev Bhattiprolu @ 2015-01-08  1:13 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo, Jiri Olsa, Michael Ellerman,
	Paul Mackerras
  Cc: peterz, linuxppc-dev, dev, linux-kernel
In-Reply-To: <1420679633-28856-1-git-send-email-sukadev@linux.vnet.ibm.com>

From: Cody P Schafer <cody@linux.vnet.ibm.com>

Event parameters are a basic way for partial events to be specified in
sysfs with per-event names given to the fields that need to be filled in
when using a particular event.

It is intended for supporting cases where the single 'cpu' parameter is
insufficient. For example, POWER 8 has events for physical
sockets/cores/cpus that are accessible from with virtual machines. To
keep using the single 'cpu' parameter we'd need to perform a mapping
between Linux's cpus and the physical machine's cpus (in this case
Linux is running under a hypervisor). This isn't possible because
bindings between our cpus and physical cpus may not be fixed, and we
probably won't have a "cpu" on each physical cpu.

CC: Sukadev Bhattiprolu <sukadev@linux.vnet.ibm.com>
CC: Haren Myneni <hbabu@us.ibm.com>
CC: Cody P Schafer <dev@codyps.com>
Acked-by: Jiri Olsa <jolsa@kernel.org>
Signed-off-by: Cody P Schafer <cody@linux.vnet.ibm.com>
Signed-off-by: Sukadev Bhattiprolu <sukadev@linux.vnet.ibm.com>
---
Changelog[v6]
	Update event description to explain how required parameters
	are displayed.

 Documentation/ABI/testing/sysfs-bus-event_source-devices-events | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/Documentation/ABI/testing/sysfs-bus-event_source-devices-events b/Documentation/ABI/testing/sysfs-bus-event_source-devices-events
index 20979f8..505f080 100644
--- a/Documentation/ABI/testing/sysfs-bus-event_source-devices-events
+++ b/Documentation/ABI/testing/sysfs-bus-event_source-devices-events
@@ -52,12 +52,18 @@ Description:	Per-pmu performance monitoring events specific to the running syste
 			event=0x2abc
 			event=0x423,inv,cmask=0x3
 			domain=0x1,offset=0x8,starting_index=0xffff
+			domain=0x1,offset=0x8,core=?
 
 		Each of the assignments indicates a value to be assigned to a
 		particular set of bits (as defined by the format file
 		corresponding to the <term>) in the perf_event structure passed
 		to the perf_open syscall.
 
+		In the case of the last example, a value replacing "?" would
+		need to be provided by the user selecting the particular event.
+		This is referred to as "event parameterization". Event
+		parameters have the format 'param=?'.
+
 What: /sys/bus/event_source/devices/<pmu>/events/<event>.unit
 Date: 2014/02/24
 Contact:	Linux kernel mailing list <linux-kernel@vger.kernel.org>
-- 
1.8.3.1

^ permalink raw reply related

* [PATCH v7 4/4] tools/perf: Document parameterized and symbolic events
From: Sukadev Bhattiprolu @ 2015-01-08  1:13 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo, Jiri Olsa, Michael Ellerman,
	Paul Mackerras
  Cc: peterz, linuxppc-dev, dev, linux-kernel
In-Reply-To: <1420679633-28856-1-git-send-email-sukadev@linux.vnet.ibm.com>

From: Cody P Schafer <cody@linux.vnet.ibm.com>

CC: Haren Myneni <hbabu@us.ibm.com>
CC: Cody P Schafer <dev@codyps.com>
Acked-by: Jiri Olsa <jolsa@kernel.org>
Signed-off-by: Cody P Schafer <cody@linux.vnet.ibm.com>
Signed-off-by: Sukadev Bhattiprolu <sukadev@linux.vnet.ibm.com>
---
Changelog[v6]:
	- [Sukadev Bhattiprolu]: Update documentation of perf-list and
	  perf-record; Added documentation for perf-stat.
	- [Jiri Olsa] Fix some typos/formatting

 tools/perf/Documentation/perf-list.txt   | 13 +++++++++++++
 tools/perf/Documentation/perf-record.txt | 12 ++++++++++++
 tools/perf/Documentation/perf-stat.txt   | 20 ++++++++++++++++----
 3 files changed, 41 insertions(+), 4 deletions(-)

diff --git a/tools/perf/Documentation/perf-list.txt b/tools/perf/Documentation/perf-list.txt
index cbb4f74..3e2aec9 100644
--- a/tools/perf/Documentation/perf-list.txt
+++ b/tools/perf/Documentation/perf-list.txt
@@ -89,6 +89,19 @@ raw encoding of 0x1A8 can be used:
 You should refer to the processor specific documentation for getting these
 details. Some of them are referenced in the SEE ALSO section below.
 
+PARAMETERIZED EVENTS
+--------------------
+
+Some pmu events listed by 'perf-list' will be displayed with '?' in them. For
+example:
+
+  hv_gpci/dtbp_ptitc,phys_processor_idx=?/
+
+This means that when provided as an event, a value for '?' must
+also be supplied. For example:
+
+  perf stat -C 0 -e 'hv_gpci/dtbp_ptitc,phys_processor_idx=0x2/' ...
+
 OPTIONS
 -------
 
diff --git a/tools/perf/Documentation/perf-record.txt b/tools/perf/Documentation/perf-record.txt
index af9a54e..7d8df2e 100644
--- a/tools/perf/Documentation/perf-record.txt
+++ b/tools/perf/Documentation/perf-record.txt
@@ -33,6 +33,18 @@ OPTIONS
         - a raw PMU event (eventsel+umask) in the form of rNNN where NNN is a
 	  hexadecimal event descriptor.
 
+	- a symbolically formed PMU event like 'pmu/param1=0x3,param2/' where
+	  'param1', 'param2', etc are defined as formats for the PMU in
+	  /sys/bus/event_sources/devices/<pmu>/format/*.
+
+	- a symbolically formed event like 'pmu/config=M,config1=N,config3=K/'
+
+          where M, N, K are numbers (in decimal, hex, octal format). Acceptable
+          values for each of 'config', 'config1' and 'config2' are defined by
+          corresponding entries in /sys/bus/event_sources/devices/<pmu>/format/*
+          param1 and param2 are defined as formats for the PMU in:
+          /sys/bus/event_sources/devices/<pmu>/format/*
+
         - a hardware breakpoint event in the form of '\mem:addr[:access]'
           where addr is the address in memory you want to break in.
           Access is the memory access type (read, write, execute) it can
diff --git a/tools/perf/Documentation/perf-stat.txt b/tools/perf/Documentation/perf-stat.txt
index 29ee857..04e150d 100644
--- a/tools/perf/Documentation/perf-stat.txt
+++ b/tools/perf/Documentation/perf-stat.txt
@@ -25,10 +25,22 @@ OPTIONS
 
 -e::
 --event=::
-	Select the PMU event. Selection can be a symbolic event name
-	(use 'perf list' to list all events) or a raw PMU
-	event (eventsel+umask) in the form of rNNN where NNN is a
-	 hexadecimal event descriptor.
+	Select the PMU event. Selection can be:
+
+	- a symbolic event name (use 'perf list' to list all events)
+
+	- a raw PMU event (eventsel+umask) in the form of rNNN where NNN is a
+	  hexadecimal event descriptor.
+
+	- a symbolically formed event like 'pmu/param1=0x3,param2/' where
+	  param1 and param2 are defined as formats for the PMU in
+	  /sys/bus/event_sources/devices/<pmu>/format/*
+
+	- a symbolically formed event like 'pmu/config=M,config1=N,config2=K/'
+	  where M, N, K are numbers (in decimal, hex, octal format).
+	  Acceptable values for each of 'config', 'config1' and 'config2'
+	  parameters are defined by corresponding entries in
+	  /sys/bus/event_sources/devices/<pmu>/format/*
 
 -i::
 --no-inherit::
-- 
1.8.3.1

^ permalink raw reply related

* Re: [PATCH 2/3] module: remove mod arg from module_free, rename module_memfree().
From: Alexei Starovoitov @ 2015-01-08  1:17 UTC (permalink / raw)
  To: Rusty Russell
  Cc: linux-mips, Jesper Nilsson, linux-cris-kernel, x86@kernel.org,
	Anil S Keshavamurthy, linux-kernel@vger.kernel.org, Ralf Baechle,
	Alexei Starovoitov, Mikael Starvik, sparclinux, Chris Metcalf,
	netdev@vger.kernel.org, Steven Rostedt, nios2-dev,
	Masami Hiramatsu, Ley Foon Tan, linuxppc-dev

On Wed, Jan 7, 2015 at 4:58 PM, Rusty Russell <rusty@rustcorp.com.au> wrote:
> --- a/kernel/bpf/core.c
> +++ b/kernel/bpf/core.c
>  void bpf_jit_binary_free(struct bpf_binary_header *hdr)
>  {
> -       module_free(NULL, hdr);
> +       module_memfree(hdr);
>  }
...
> -void __weak module_free(struct module *mod, void *module_region)
> +void __weak module_memfree(void *module_region)
>  {
>         vfree(module_region);
>  }

Looks obviously correct.
Acked-by: Alexei Starovoitov <ast@kernel.org>

^ permalink raw reply

* Re: powerpc: refresh mpc85xx_defconfig using "make savedefconfig"
From: Michael Ellerman @ 2015-01-08  3:26 UTC (permalink / raw)
  To: Alessio Igor Bogani; +Cc: Scott Wood, linuxppc-dev
In-Reply-To: <CAPk1OjEfx=1yfb_GUnbdNsw9Y8QfJBeMEebSKiAqDcqwm+sLhA@mail.gmail.com>

On Wed, 2015-01-07 at 09:08 +0100, Alessio Igor Bogani wrote:
> Hi Michael,
> 
> On 5 December 2014 at 10:42, Michael Ellerman <mpe@ellerman.id.au> wrote:
> > On Fri, 2014-05-12 at 08:17:42 UTC, Alessio Igor Bogani wrote:
> >> Signed-off-by: Alessio Igor Bogani <alessio.bogani@elettra.eu>
> >> ---
> >>  arch/powerpc/configs/mpc85xx_defconfig | 57 +++++++---------------------------
> >>  1 file changed, 12 insertions(+), 45 deletions(-)
> >
> > Actually I was planning on doing this in bulk for all the powerpc defconfigs.
> >
> > Someone remind me to do it late next week once most of next has gone into
> > Linus' tree.
> 
> Is there any news about this?

Nope, other than I didn't get around to doing it :)

So Scott you may as well just merge this.

cheers

^ permalink raw reply

* RE: [PATCH] [v3] power/fsl: add MDIO dt binding for FMan
From: Shaohui Xie @ 2015-01-08  3:58 UTC (permalink / raw)
  To: Scott Wood, Emilian Medve
  Cc: devicetree@vger.kernel.org, linuxppc-dev@lists.ozlabs.org
In-Reply-To: <1420679558.4961.64.camel@freescale.com>

PiAtLS0tLU9yaWdpbmFsIE1lc3NhZ2UtLS0tLQ0KPiBGcm9tOiBXb29kIFNjb3R0LUIwNzQyMQ0K
PiBTZW50OiBUaHVyc2RheSwgSmFudWFyeSAwOCwgMjAxNSA5OjEzIEFNDQo+IFRvOiBNZWR2ZSBF
bWlsaWFuLUVNTUVEVkUxDQo+IENjOiBYaWUgU2hhb2h1aS1CMjE5ODk7IGxpbnV4cHBjLWRldkBs
aXN0cy5vemxhYnMub3JnOw0KPiBkZXZpY2V0cmVlQHZnZXIua2VybmVsLm9yZw0KPiBTdWJqZWN0
OiBSZTogW1BBVENIXSBbdjNdIHBvd2VyL2ZzbDogYWRkIE1ESU8gZHQgYmluZGluZyBmb3IgRk1h
bg0KPiANCj4gT24gV2VkLCAyMDE1LTAxLTA3IGF0IDEzOjQ0IC0wNjAwLCBFbWlsIE1lZHZlIHdy
b3RlOg0KPiA+IEhlbGxvIFNjb3R0LA0KPiA+DQo+ID4NCj4gPiBPbiAwMS8wNy8yMDE1IDEyOjA1
IFBNLCBTY290dCBXb29kIHdyb3RlOg0KPiA+ID4gT24gVHVlLCAyMDE1LTAxLTA2IGF0IDIzOjI5
IC0wNjAwLCBYaWUgU2hhb2h1aS1CMjE5ODkgd3JvdGU6DQo+ID4gPj4+Pj4gKy0gaW50ZXJydXB0
cw0KPiA+ID4+Pj4+ICsJCVVzYWdlOiBvcHRpb25hbA0KPiA+ID4+Pj4+ICsJCVZhbHVlIHR5cGU6
IDxwcm9wLWVuY29kZWQtYXJyYXk+DQo+ID4gPj4+Pj4gKwkJRGVmaW5pdGlvbjogRXZlbnQgaW50
ZXJydXB0IG9mIGV4dGVybmFsIE1ESU8gY29udHJvbGxlci4NCj4gPiA+Pj4+PiArCQkxIEdiL3Mg
TURJTyBhbmQgMTAgR2IvcyBNRElPIGhhcyBvbmUgaW50ZXJydXB0IHJlc3BlY3RpdmVseS4NCj4g
PiA+Pj4NCj4gPiA+Pj4gSSdtIGNvbmZ1c2VkIGJ5ICJyZXNwZWN0aXZlbHkiIGhlcmUuICBEb2Vz
IGZzbCxmbWFuLW1lbWFjLW1kaW8NCj4gPiA+Pj4gaGF2ZSB0d28gaW50ZXJydXB0cyAob25lIGZv
ciAxIEdiL3MgYW5kIG9uZSBmb3IgMTAgR2Ivcyk/DQo+ID4gPj4gW1MuSF0gV2UgdXNlIHR3byBN
RElPIGNvbnRyb2xsZXJzIGZvciBleHRlcm5hbCBQSFkgbWFuYWdlbWVudC4gT25lDQo+ID4gPj4g
Zm9yIDEgR2IvcywgT25lIGZvciAxMCBHYi9zLCBhbmQgdHdvIE1ESU8gaW50ZXJydXB0cyBjb25u
ZWN0ZWQgdG8gTVBJQy4NCj4gPiA+DQo+ID4gPiBJZiB0aGVyZSBjYW4gYmUgdHdvIGludGVycnVw
dHMgeW91IG5lZWQgdG8gbWFrZSB0aGF0IGNsZWFyIGFuZA0KPiA+ID4gc3BlY2lmeSB0aGUgb3Jk
ZXIuDQo+ID4gPg0KPiA+ID4gSXMgaXQgcG9zc2libGUgZm9yIG9uZSBNRElPIGNvbnRyb2xsZXIg
dG8gaGF2ZSBhbiBpbnRlcnJ1cHQNCj4gPiA+IGNvbm5lY3RlZCBidXQgbm90IHRoZSBvdGhlciwg
b24gdGhlIHNhbWUgc3lzdGVtPyAgSG93IHdvdWxkIHlvdQ0KPiA+ID4gcmVwcmVzZW50IHRoYXQg
aW4gdGhlIGRldmljZSB0cmVlPyAgSWYgdGhlcmUgYXJlIHR3byBNRElPDQo+ID4gPiBjb250cm9s
bGVycyB3aHkgYXJlIHRoZXkgaW4gdGhlIHNhbWUgbm9kZT8NCj4gPg0KPiA+IEhpc3RvcmljYWxs
eSAoRk1hbiB2MiBhbmQgZXZlbiBiZWZvcmUvbGVnYWN5KSB3ZSd2ZSBoYWQgZWFjaCBNQUMNCj4g
PiBpbmNsdWRlIGFuIE1ESU8gY29udHJvbGxlciwgYnV0IG9ubHkgb25lIE1ESU8gY29udHJvbGxl
ciBwZXIgTUFDDQo+ID4gdHlwZS9zcGVlZCAoMSBHYi9zIHZzIDEwIEdiL3MpIGlzIHBpbm5lZCBv
dXQgYW5kIGFsbCB0aGUgc2FtZSBzcGVlZA0KPiA+IFBIWShzKSBhcmUgY29ubmVjdGVkIHRvIHRo
ZSByZXNwZWN0aXZlIE1ESU8gY29udHJvbGxlcnMuIEFzIHN1Y2ggdGhlDQo+ID4gZmlyc3QgMSBH
Yi9zIE1BQy9NRElPIGNvbnRyb2xsZXIgaXMgdXNlZCB0byBtYW5hZ2UgYWxsIHRoZSAxIEdiL3MN
Cj4gPiBQSFkocykgYW5kIHRoZSBmaXJzdCAxMCBHYi9zIE1BQy9NRElPIGNvbnRyb2xsZXIgaXMg
dXNlZCB0byBtYW5hZ2UgYWxsDQo+ID4gdGhlIDEwIEdiL3MgUEhZKHMpLiBFYWNoIE1ESU8gY29u
dHJvbGxlciBoYXMgdGhlIGFiaWxpdHkgdG8gZ2VuZXJhdGUNCj4gPiBpbnRlcnJ1cHRzIGJ1dCBv
bmx5IHBpbm5lZCBvdXQgTURJTyBjb250cm9sbGVycyBhcmUgaG9va2VkIHVwIHRvIHRoZQ0KPiA+
IE1QSUMgKGFzIHN1Y2ggdGhlIHRhbGsgYWJvdXQgdHdvIGludGVycnVwdHMpDQo+ID4NCj4gPiAo
RWFjaCBNQUMgaGFzIGFsc28gaW50ZWdyYXRlZCBhIFNFUkRFUy9UQkkvImludGVybmFsIiBQSFkg
dGhhdCBpcw0KPiA+IGNvbm5lY3RlZCB0byB0aGUgImxvY2FsIiBNRElPIGNvbnRyb2xsZXIpDQo+
ID4NCj4gPiBBcyB5b3UgY2FuIGltYWdpbmUgdGhpcyBjcmVhdGVzIGEgbnVtYmVyIG9mIHByb2Js
ZW1zIGluIGEgcGFydGl0aW9uaW5nDQo+ID4gc2NlbmFyaW8gKGFuZCBub3QganVzdCwgaW1hZ2lu
ZSBSQ1dzIHdoZXJlIHRoZSBmaXJzdCBNQUMgaXMgbm90DQo+ID4gdXNlZC9lbmFibGVkKS4gSW4g
b3JkZXIgdG8gaGVscCBhIGJpdCAoYnV0IG5vdCBxdWl0ZSBlbm91Z2gpLCBpbiBGTWFuDQo+ID4g
djMsIHR3byBhZGRpdGlvbmFsIE1ESU8gY29udHJvbGxlcnMgKG9uZSBmb3IgMSB0aGUgR2IvcyBQ
SFkocykgYW5kIG9uZQ0KPiA+IGZvciAxIHRoZSAxMCBHYi9zIFBIWShzKSkgaGF2ZSBiZWVuIGlu
dGVncmF0ZWQgdGhhdCBhcmUgbm90IGFzc29jaWF0ZWQNCj4gPiB3aXRoIGFueSBNQUMgYW5kIHRo
ZXNlIGFyZSB0aGUgcGlubmVkIG91dCBNRElPIGNvbnRyb2xsZXJzIG9uIHN1Y2gNCj4gPiBTb0Mo
cykgKGNoYXNzaXMgdjIpDQo+IA0KPiBJJ20gaGFwcHkgdG8gaGVhciB0aGF0LiAgSXMgdGhhdCB3
aGF0IGlzIG1lYW50IGJ5ICJleHRlcm5hbCIgaGVyZT8gIEkgdGhvdWdodCBpdA0KPiBtZWFudCBl
eHRlcm5hbCB0byB0aGUgU29DLiAgSXMgdGhpcyB0aGUgdGVybSB1c2VkIGJ5IGhhcmR3YXJlIGRv
Y3VtZW50YXRpb24/DQpbUy5IXSBZZXMuICJleHRlcm5hbCIgJiAiaW50ZXJuYWwiIGFyZSB1c2Vk
IGJ5IGhhcmR3YXJlIGRvY3VtZW50YXRpb24uDQoNCj4gSSdkIGhhdmUgY2FsbGVkIGl0ICJpbmRl
cGVuZGVudCIgb3Igc2ltaWxhci4NCj4gDQo+ID4gPj4gICBEb2VzICJvcHRpb25hbCIgbWVhbiBp
dCdzIHVzZWQgaWYgYW5kDQo+ID4gPj4+IG9ubHkgaWYgZXh0ZXJuYWwgTURJTyBpcyB1c2VkLCBv
ciBpcyBpdCBvcHRpb25hbCBldmVuIHdpdGgNCj4gPiA+Pj4gZXh0ZXJuYWwgTURJTz8gIEkgc2Vl
IGl0J3Mgbm90IHByZXNlbnQgaW4gdGhlIGV4YW1wbGUgLS0gZG8gd2Ugbm90DQo+ID4gPj4+IGhh
dmUgYSByZWFsIGV4YW1wbGUgdGhhdCBoYXMgdGhlIGludGVycnVwdD8NCj4gPiA+PiBbUy5IXSAi
b3B0aW9uYWwiIG1lYW5zIGl0J3MgYXZhaWxhYmxlIG9uIGhhcmR3YXJlLCBidXQgTURJTyBkcml2
ZXIgZG9lcyBub3QNCj4gdXNlIGludGVycnVwdC4NCj4gPiA+PiBTbyB3ZSBkb24ndCBoYXZlIGEg
cmVhbCBleGFtcGxlLg0KPiA+ID4NCj4gPiA+IDxyZWNvcmQgdHlwZT0iYnJva2VuIj5UaGUgZGV2
aWNlIHRyZWUgZGVzY3JpYmVzIHRoZSBoYXJkd2FyZSwgbm90DQo+ID4gPiB0aGUgZHJpdmVyPC9y
ZWNvcmQ+DQo+ID4NCj4gPiBBbnl3YXksIG9ubHkgdHdvIE1ESU8gbm9kZXMgKG91dCBvZiA0IHRv
IDE0KSB3b3VsZCBoYXZlIGFuIGludGVycnVwdA0KPiA+IHByb3BlcnR5IGRlc2NyaWJpbmcgZXhh
Y3RseSBvbmUgaW50ZXJydXB0LiBXaGF0IGxhbmd1YWdlIHNob3VsZCB3ZSB1c2UNCj4gPiB0byBj
b252ZXkgdGhpcyBzaXR1YXRpb24NCj4gDQo+IFNvIHRoZSBhbnN3ZXIgaXMgdGhhdCB0aGVyZSB3
aWxsIG5vdCBiZSBtb3JlIHRoYW4gb25lIE1ESU8gY29udHJvbGxlciBwZXIgTURJTw0KPiBub2Rl
LCBvciBtb3JlIHRoYW4gb25lIGludGVycnVwdCBwZXIgTURJTyBub2RlPyANCltTLkhdIFllcywg
b25lIE1ESU8gY29udHJvbGxlciBwZXIgTURJTyBub2RlLCBhbmQgb25lIGludGVycnVwdCBwZXIg
ImV4dGVybmFsIg0KTURJTyBub2RlLg0KDQogSW4gdGhhdCBjYXNlIGp1c3QgZ2V0IHJpZCBvZg0K
PiB0aGUgY29uZnVzaW5nICJyZXNwZWN0aXZlbHkiIHNlbnRlbmNlIC0tIGFuZCBhbHdheXMgZGVz
Y3JpYmUgdGhlIGludGVycnVwdCBpZiBpdA0KPiBleGlzdHMgaW4gaGFyZHdhcmUuDQpbUy5IXSBP
Sy4NCg0KVGhhbmtzIQ0KU2hhb2h1aQ0K

^ permalink raw reply

* [PATCH] powerpc: Work around gcc bug in current_thread_info()
From: Michael Ellerman @ 2015-01-08  4:30 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: Anton Blanchard, agraf

In commit a3e5b356b3ab "powerpc: Don't use local named register variable
in current_thread_info" Anton changed the way we did current_thread_info()
to accommodate LLVM, and it was not meant to have any effect elsewhere.

Unfortunately it has exposed a gcc bug, where r1 gets copied into
another register and then gcc uses that register to restore the toc
after a function call, even when that register is volatile and has been
clobbered by the function call.

We could revert Anton's patch, but it's not clear the original code is
safe either, we may just have been lucky.

The cleanest solution is to just use the existing CURRENT_THREAD_INFO()
asm macro, and call it using inline asm.

Fixes: a3e5b356b3ab ("powerpc: Don't use local named register variable in current_thread_info")
Reported-by: Alexander Graf <agraf@suse.de>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
---
 arch/powerpc/include/asm/thread_info.h | 13 +++++++------
 1 file changed, 7 insertions(+), 6 deletions(-)

diff --git a/arch/powerpc/include/asm/thread_info.h b/arch/powerpc/include/asm/thread_info.h
index ebc4f165690a..cdafafe942e3 100644
--- a/arch/powerpc/include/asm/thread_info.h
+++ b/arch/powerpc/include/asm/thread_info.h
@@ -23,9 +23,9 @@
 #define THREAD_SIZE		(1 << THREAD_SHIFT)
 
 #ifdef CONFIG_PPC64
-#define CURRENT_THREAD_INFO(dest, sp)	clrrdi dest, sp, THREAD_SHIFT
+#define CURRENT_THREAD_INFO(dest, sp)	stringify_in_c(clrrdi dest, sp, THREAD_SHIFT)
 #else
-#define CURRENT_THREAD_INFO(dest, sp)	rlwinm dest, sp, 0, 0, 31-THREAD_SHIFT
+#define CURRENT_THREAD_INFO(dest, sp)	stringify_in_c(rlwinm dest, sp, 0, 0, 31-THREAD_SHIFT)
 #endif
 
 #ifndef __ASSEMBLY__
@@ -71,12 +71,13 @@ struct thread_info {
 #define THREAD_SIZE_ORDER	(THREAD_SHIFT - PAGE_SHIFT)
 
 /* how to get the thread information struct from C */
-register unsigned long __current_r1 asm("r1");
 static inline struct thread_info *current_thread_info(void)
 {
-	/* gcc4, at least, is smart enough to turn this into a single
-	 * rlwinm for ppc32 and clrrdi for ppc64 */
-	return (struct thread_info *)(__current_r1 & ~(THREAD_SIZE-1));
+	unsigned long val;
+
+	asm volatile(CURRENT_THREAD_INFO(%0,1) : "=r" (val));
+
+	return (struct thread_info *)val;
 }
 
 #endif /* __ASSEMBLY__ */
-- 
2.1.0

^ permalink raw reply related

* Re: [PATCH] powerpc/book3s: Fix the MCE code to use CONFIG_KVM_BOOK3S_HV_POSSIBLE
From: Mahesh Jagannath Salgaonkar @ 2015-01-08  5:28 UTC (permalink / raw)
  To: linuxppc-dev
In-Reply-To: <87iogjovit.fsf@linux.vnet.ibm.com>

On 01/07/2015 01:46 PM, Aneesh Kumar K.V wrote:
> Mahesh J Salgaonkar <mahesh@linux.vnet.ibm.com> writes:
> 
>> From: Mahesh Salgaonkar <mahesh@linux.vnet.ibm.com>
>>
>> commit id 9975f5e added new config variable CONFIG_KVM_BOOK3S_HV_POSSIBLE
>> that helps to select the relevant code in the kernel when HV and PR
>> bits are built as separate modules. As part of that commit, all the
>> instances of #ifdef CONFIG_KVM_BOOK3S_64_HV was replaced with
>> CONFIG_KVM_BOOK3S_HV_POSSIBLE. But the MCE code still depends on
>> CONFIG_KVM_BOOK3S_64_HV which is wrong. When HV bits are built as a
>> separate module the relevent MCE code gets excluded. This patch fixes
>> the MCE code to use CONFIG_KVM_BOOK3S_HV_POSSIBLE.
>>
>> Signed-off-by: Mahesh Salgaonkar <mahesh@linux.vnet.ibm.com>
>> ---
>>  arch/powerpc/kernel/exceptions-64s.S |    2 +-
>>  1 file changed, 1 insertion(+), 1 deletion(-)
>>
>> diff --git a/arch/powerpc/kernel/exceptions-64s.S b/arch/powerpc/kernel/exceptions-64s.S
>> index c2df815..7335857 100644
>> --- a/arch/powerpc/kernel/exceptions-64s.S
>> +++ b/arch/powerpc/kernel/exceptions-64s.S
>> @@ -1408,7 +1408,7 @@ machine_check_handle_early:
>>  	bne	9f			/* continue in V mode if we are. */
>>
>>  5:
>> -#ifdef CONFIG_KVM_BOOK3S_64_HV
>> +#ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE
>>  	/*
>>  	 * We are coming from kernel context. Check if we are coming from
>>  	 * guest. if yes, then we can continue. We will fall through
> 
> Do we also need to update the HSTATE_IN_GUEST check to avoid checking
> the PR guest mode ?ie, 

Not required. If we are coming from guest (HSTATE_IN_GUEST != 0) we fall
through do_kvm_200->kvmppc_interrupt and for PR guest it would lead us
to kvmppc_interrupt_pr which will inject MCE in PR guest.

Having said that I just realized that I should use #ifdef
CONFIG_KVM_BOOK3S_64_HANDLER instead. The check holds good for both HV
and PR guests.

Thanks,
-Mahesh.

> 
> 	lbz	r11,HSTATE_IN_GUEST(r13)
> 	cmpwi	r11,0			/* Check if coming from guest */
> 
> checking for 0 is what you want there ?
> 
> -aneesh
> 
> _______________________________________________
> Linuxppc-dev mailing list
> Linuxppc-dev@lists.ozlabs.org
> https://lists.ozlabs.org/listinfo/linuxppc-dev
> 

^ permalink raw reply

* [PATCH] powerpc/kernel: Avoid memory corruption at early stage
From: Gavin Shan @ 2015-01-08  5:40 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: Gavin Shan

When calling to early_setup(), we picks "boot_paca" up for the
master CPU and initialize that with initialise_paca(). At the
point, SLB shadow buffer isn't populated yet. Updating the SLB
shadow buffer should corrupt what we had in physical address 0
where the trap instruction is usually stored.

Signed-off-by: Gavin Shan <gwshan@linux.vnet.ibm.com>
---
 arch/powerpc/kernel/paca.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/arch/powerpc/kernel/paca.c b/arch/powerpc/kernel/paca.c
index d6e195e..048a6ee 100644
--- a/arch/powerpc/kernel/paca.c
+++ b/arch/powerpc/kernel/paca.c
@@ -115,6 +115,9 @@ static struct slb_shadow * __init init_slb_shadow(int cpu)
 {
 	struct slb_shadow *s = &slb_shadow[cpu];
 
+	if (!slb_shadow)
+		return NULL;
+
 	s->persistent = cpu_to_be32(SLB_NUM_BOLTED);
 	s->buffer_length = cpu_to_be32(sizeof(*s));
 
-- 
1.8.3.2

^ permalink raw reply related

* [PATCH] powerpc/kernel: Avoid initializing device-tree pointer twice
From: Gavin Shan @ 2015-01-08  5:41 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: Gavin Shan

As commit 50ba08f3 ("of/fdt: Don't clear initial_boot_params
if fdt_check_header() fails") does, the device-tree pointer
"initial_boot_params" is initialized by early_init_dt_verify(),
which is called by early_init_devtree(). So we needn't explicitly
initialize that again in early_init_devtree().

Signed-off-by: Gavin Shan <gwshan@linux.vnet.ibm.com>
---
 arch/powerpc/kernel/prom.c | 3 ---
 1 file changed, 3 deletions(-)

diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c
index 6a799b3..b8e15c6 100644
--- a/arch/powerpc/kernel/prom.c
+++ b/arch/powerpc/kernel/prom.c
@@ -652,9 +652,6 @@ void __init early_init_devtree(void *params)
 	if (!early_init_dt_verify(params))
 		panic("BUG: Failed verifying flat device tree, bad version?");
 
-	/* Setup flat device-tree pointer */
-	initial_boot_params = params;
-
 #ifdef CONFIG_PPC_RTAS
 	/* Some machines might need RTAS info for debugging, grab it now. */
 	of_scan_flat_dt(early_init_dt_scan_rtas, NULL);
-- 
1.8.3.2

^ permalink raw reply related

* [PATCH] powerpc/powernv: Don't alloc IRQ map if necessary
From: Gavin Shan @ 2015-01-08  5:42 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: Gavin Shan

On PowerNV platform, the OPAL interrupts are exported by firmware
through device-node property (/ibm,opal::opal-interrupts). Under
some extreme circumstances (e.g. simulator), we don't have this
property found from the device tree. For that case, we shouldn't
allocate the interrupt map. Otherwise, slab complains allocating
zero sized memory chunk.

Signed-off-by: Gavin Shan <gwshan@linux.vnet.ibm.com>
---
 arch/powerpc/platforms/powernv/opal.c | 13 ++++++++-----
 1 file changed, 8 insertions(+), 5 deletions(-)

diff --git a/arch/powerpc/platforms/powernv/opal.c b/arch/powerpc/platforms/powernv/opal.c
index f10b9ec..e61cefe 100644
--- a/arch/powerpc/platforms/powernv/opal.c
+++ b/arch/powerpc/platforms/powernv/opal.c
@@ -726,11 +726,14 @@ static int __init opal_init(void)
 
 	/* Find all OPAL interrupts and request them */
 	irqs = of_get_property(opal_node, "opal-interrupts", &irqlen);
+	opal_irq_count = irqs ? (irqlen / 4) : 0;
+	if (opal_irq_count)
+		opal_irqs = kzalloc(opal_irq_count * sizeof(unsigned int),
+				    GFP_KERNEL);
 	pr_debug("opal: Found %d interrupts reserved for OPAL\n",
-		 irqs ? (irqlen / 4) : 0);
-	opal_irq_count = irqlen / 4;
-	opal_irqs = kzalloc(opal_irq_count * sizeof(unsigned int), GFP_KERNEL);
-	for (i = 0; irqs && i < (irqlen / 4); i++, irqs++) {
+		 opal_irq_count);
+
+	for (i = 0; opal_irqs && i < opal_irq_count; i++, irqs++) {
 		unsigned int hwirq = be32_to_cpup(irqs);
 		unsigned int irq = irq_create_mapping(NULL, hwirq);
 		if (irq == NO_IRQ) {
@@ -775,7 +778,7 @@ void opal_shutdown(void)
 	long rc = OPAL_BUSY;
 
 	/* First free interrupts, which will also mask them */
-	for (i = 0; i < opal_irq_count; i++) {
+	for (i = 0; opal_irqs && i < opal_irq_count; i++) {
 		if (opal_irqs[i])
 			free_irq(opal_irqs[i], NULL);
 		opal_irqs[i] = 0;
-- 
1.8.3.2

^ permalink raw reply related

* Re: [PATCH 1/3] powerpc: Don't use local named register variable in current_thread_info
From: Alan Modra @ 2015-01-08  6:36 UTC (permalink / raw)
  To: Anton Blanchard
  Cc: Alexander Graf, ulrich.weigand, paulus, Scott Wood, linuxppc-dev
In-Reply-To: <20150107161247.55591e93@kryten>

On Wed, Jan 07, 2015 at 04:12:47PM +1100, Anton Blanchard wrote:
> Hi Alan,
> 
> > Right.  This is really an rs6000 backend bug.  We describe one of the
> > indirect calls that go wrong here as
> > 
> > (call_insn 108 107 109 13 (parallel [
> >             (set (reg:DI 3 3)
> >                 (call (mem:SI (reg:DI 288) [0 *_67 S4 A8])
> >                     (const_int 64 [0x40])))
> >             (use (mem:DI (plus:DI (reg/f:DI 287 [ ops_44(D)->update ])
> >                         (const_int 8 [0x8])) [0  S8 A8]))
> >             (set (reg:DI 2 2)
> >                 (mem/v/c:DI (plus:DI (reg/f:DI 1 1)
> >                         (const_int 40 [0x28])) [0  S8 A8]))
> >             (clobber (reg:DI 65 lr))
> >         ]) net/core/skbuff.c:2085 680 {*call_value_indirect_aixdi}
> > 	<notes and arg uses omitted for clarity>
> > )
> > 
> > Notice that the RTL contains a "parallel".  As you might guess, gcc
> > treats the vector of expressions inside the square brackets of the
> > parallel as happening "in parallel".  Meaning that as far as gcc is
> > concerned the toc restore part (third element) happens at the same
> > time as the call (first element).  So if gcc replaces (reg:DI 1) in
> > the toc restore with some other register known to have the same value
> > *before* the call, gcc's RTL analysis will conclude that such a
> > replacement is valid.
> 
> Thanks for looking into this. Does that mean we were just getting lucky
> with the previous version:
> 
> static inline struct thread_info *current_thread_info(void)
> {
>         register unsigned long sp asm("r1");
> 
>         return (struct thread_info *)(sp & ~(THREAD_SIZE-1));
> }

With both versions, the original rtl for current_thread_info consists
of two instructions, copy r1 to a pseudo reg, then the "and".  With
the above version, fwprop1 manages to combine this to a single "and"
insn.  When using a global reg var, fprop1 leaves the two
instructions, the copy causing the trouble in the following cprop1
pass.  So it's not that we are getting lucky in cprop1, but that
fwprop1 behaves differently with global vs. local registers.

-- 
Alan Modra
Australia Development Lab, IBM

^ permalink raw reply

* [PATCH RFT/RFC] powerpc: move cacheinfo sysfs to generic cacheinfo infrastructure
From: Sudeep Holla @ 2015-01-08  8:39 UTC (permalink / raw)
  To: linux-kernel, linuxppc-dev
  Cc: Anshuman Khandual, Paul Mackerras, Sudeep Holla

This patch removes the redundant sysfs cacheinfo code by reusing
the newly introduced generic cacheinfo infrastructure through the
commit 246246cbde5e ("drivers: base: support cpu cache information
interface to userspace via sysfs")

Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Michael Ellerman <mpe@ellerman.id.au>
Cc: Anshuman Khandual <khandual@linux.vnet.ibm.com>
Cc: linuxppc-dev@lists.ozlabs.org
---
 arch/powerpc/kernel/cacheinfo.c | 812 +++++-----------------------------------
 arch/powerpc/kernel/cacheinfo.h |   8 -
 arch/powerpc/kernel/sysfs.c     |  12 +-
 3 files changed, 90 insertions(+), 742 deletions(-)
 delete mode 100644 arch/powerpc/kernel/cacheinfo.h

Hi,

This patch is not tested. Last time Anshuman tested, he had seen issues.
The core driver has changed a lot after that. Since PPC depends a lot
on DT for cache information, there might be issues in the core later
which I could not identify with ARM/ARM64. It would be much appreciable
if someone help me in testing and fixing those so that PPC can migrate
to new/common cacheinfo infrastructure.

Regards,
Sudeep

diff --git a/arch/powerpc/kernel/cacheinfo.c b/arch/powerpc/kernel/cacheinfo.c
index 40198d50b4c2..6845eb7fcc18 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-*
@@ -92,231 +59,82 @@ static const struct cache_type_info cache_type_info[] = {
 	},
 };
 
-/* Cache object: each instance of this corresponds to a distinct cache
- * in the system.  There are separate objects for Harvard caches: one
- * each for instruction and data, and each refers to the same OF node.
- * The refcount of the OF node is elevated for the lifetime of the
- * cache object.  A cache object is released when its shared_cpu_map
- * is cleared (see cache_cpu_clear).
- *
- * A cache object is on two lists: an unsorted global list
- * (cache_list) of cache objects; and a singly-linked list
- * representing the local cache hierarchy, which is ordered by level
- * (e.g. L1d -> L1i -> L2 -> L3).
- */
-struct cache {
-	struct device_node *ofnode;    /* OF node for this cache, may be cpu */
-	struct cpumask shared_cpu_map; /* online CPUs using this cache */
-	int type;                      /* split cache disambiguation */
-	int level;                     /* level not explicit in device tree */
-	struct list_head list;         /* global list of cache objects */
-	struct cache *next_local;      /* next cache of >= level */
-};
-
-static DEFINE_PER_CPU(struct cache_dir *, cache_dir_pcpu);
-
-/* traversal/modification of this list occurs only at cpu hotplug time;
- * access is serialized by cpu hotplug locking
- */
-static LIST_HEAD(cache_list);
-
-static struct cache_index_dir *kobj_to_cache_index_dir(struct kobject *k)
-{
-	return container_of(k, struct cache_index_dir, kobj);
-}
-
-static const char *cache_type_string(const struct cache *cache)
+static inline int get_cacheinfo_idx(enum cache_type type)
 {
-	return cache_type_info[cache->type].name;
-}
-
-static void cache_init(struct cache *cache, int type, int level,
-		       struct device_node *ofnode)
-{
-	cache->type = type;
-	cache->level = level;
-	cache->ofnode = of_node_get(ofnode);
-	INIT_LIST_HEAD(&cache->list);
-	list_add(&cache->list, &cache_list);
-}
-
-static struct cache *new_cache(int type, int level, struct device_node *ofnode)
-{
-	struct cache *cache;
-
-	cache = kzalloc(sizeof(*cache), GFP_KERNEL);
-	if (cache)
-		cache_init(cache, type, level, ofnode);
-
-	return cache;
-}
-
-static void release_cache_debugcheck(struct cache *cache)
-{
-	struct cache *iter;
-
-	list_for_each_entry(iter, &cache_list, list)
-		WARN_ONCE(iter->next_local == cache,
-			  "cache for %s(%s) refers to cache for %s(%s)\n",
-			  iter->ofnode->full_name,
-			  cache_type_string(iter),
-			  cache->ofnode->full_name,
-			  cache_type_string(cache));
-}
-
-static void release_cache(struct cache *cache)
-{
-	if (!cache)
-		return;
-
-	pr_debug("freeing L%d %s cache for %s\n", cache->level,
-		 cache_type_string(cache), cache->ofnode->full_name);
-
-	release_cache_debugcheck(cache);
-	list_del(&cache->list);
-	of_node_put(cache->ofnode);
-	kfree(cache);
-}
-
-static void cache_cpu_set(struct cache *cache, int cpu)
-{
-	struct cache *next = cache;
-
-	while (next) {
-		WARN_ONCE(cpumask_test_cpu(cpu, &next->shared_cpu_map),
-			  "CPU %i already accounted in %s(%s)\n",
-			  cpu, next->ofnode->full_name,
-			  cache_type_string(next));
-		cpumask_set_cpu(cpu, &next->shared_cpu_map);
-		next = next->next_local;
-	}
+	if (type == CACHE_TYPE_UNIFIED)
+		return 0;
+	return type;
 }
 
-static int cache_size(const struct cache *cache, unsigned int *ret)
+static void cache_size(struct cacheinfo *this_leaf)
 {
 	const char *propname;
 	const __be32 *cache_size;
+	int ct_idx;
 
-	propname = cache_type_info[cache->type].size_prop;
+	ct_idx = get_cacheinfo_idx(this_leaf->type);
+	propname = cache_type_info[ct_idx].size_prop;
 
-	cache_size = of_get_property(cache->ofnode, propname, NULL);
+	cache_size = of_get_property(this_leaf->of_node, propname, NULL);
 	if (!cache_size)
-		return -ENODEV;
-
-	*ret = of_read_number(cache_size, 1);
-	return 0;
-}
-
-static int cache_size_kb(const struct cache *cache, unsigned int *ret)
-{
-	unsigned int size;
-
-	if (cache_size(cache, &size))
-		return -ENODEV;
-
-	*ret = size / 1024;
-	return 0;
+		this_leaf->size = 0;
+	else
+		this_leaf->size = of_read_number(cache_size, 1);
 }
 
 /* not cache_line_size() because that's a macro in include/linux/cache.h */
-static int cache_get_line_size(const struct cache *cache, unsigned int *ret)
+static void cache_get_line_size(struct cacheinfo *this_leaf)
 {
 	const __be32 *line_size;
-	int i, lim;
+	int i, lim, ct_idx;
 
-	lim = ARRAY_SIZE(cache_type_info[cache->type].line_size_props);
+	ct_idx = get_cacheinfo_idx(this_leaf->type);
+	lim = ARRAY_SIZE(cache_type_info[ct_idx].line_size_props);
 
 	for (i = 0; i < lim; i++) {
 		const char *propname;
 
-		propname = cache_type_info[cache->type].line_size_props[i];
-		line_size = of_get_property(cache->ofnode, propname, NULL);
+		propname = cache_type_info[ct_idx].line_size_props[i];
+		line_size = of_get_property(this_leaf->of_node, propname, NULL);
 		if (line_size)
 			break;
 	}
 
 	if (!line_size)
-		return -ENODEV;
-
-	*ret = of_read_number(line_size, 1);
-	return 0;
+		this_leaf->coherency_line_size = 0;
+	else
+		this_leaf->coherency_line_size = of_read_number(line_size, 1);
 }
 
-static int cache_nr_sets(const struct cache *cache, unsigned int *ret)
+static void cache_nr_sets(struct cacheinfo *this_leaf)
 {
 	const char *propname;
 	const __be32 *nr_sets;
+	int ct_idx;
 
-	propname = cache_type_info[cache->type].nr_sets_prop;
+	ct_idx = get_cacheinfo_idx(this_leaf->type);
+	propname = cache_type_info[ct_idx].nr_sets_prop;
 
-	nr_sets = of_get_property(cache->ofnode, propname, NULL);
+	nr_sets = of_get_property(this_leaf->of_node, propname, NULL);
 	if (!nr_sets)
-		return -ENODEV;
-
-	*ret = of_read_number(nr_sets, 1);
-	return 0;
+		this_leaf->number_of_sets = 0;
+	else
+		this_leaf->number_of_sets = of_read_number(nr_sets, 1);
 }
 
-static int cache_associativity(const struct cache *cache, unsigned int *ret)
+static void cache_associativity(struct cacheinfo *this_leaf)
 {
-	unsigned int line_size;
-	unsigned int nr_sets;
-	unsigned int size;
-
-	if (cache_nr_sets(cache, &nr_sets))
-		goto err;
+	unsigned int line_size = this_leaf->coherency_line_size;
+	unsigned int nr_sets = this_leaf->number_of_sets;
+	unsigned int size = this_leaf->size;
 
 	/* If the cache is fully associative, there is no need to
 	 * check the other properties.
 	 */
-	if (nr_sets == 1) {
-		*ret = 0;
-		return 0;
-	}
-
-	if (cache_get_line_size(cache, &line_size))
-		goto err;
-	if (cache_size(cache, &size))
-		goto err;
-
-	if (!(nr_sets > 0 && size > 0 && line_size > 0))
-		goto err;
-
-	*ret = (size / nr_sets) / line_size;
-	return 0;
-err:
-	return -ENODEV;
-}
-
-/* helper for dealing with split caches */
-static struct cache *cache_find_first_sibling(struct cache *cache)
-{
-	struct cache *iter;
-
-	if (cache->type == CACHE_TYPE_UNIFIED)
-		return cache;
-
-	list_for_each_entry(iter, &cache_list, list)
-		if (iter->ofnode == cache->ofnode && iter->next_local == cache)
-			return iter;
-
-	return cache;
-}
-
-/* return the first cache on a local list matching node */
-static struct cache *cache_lookup_by_node(const struct device_node *node)
-{
-	struct cache *cache = NULL;
-	struct cache *iter;
-
-	list_for_each_entry(iter, &cache_list, list) {
-		if (iter->ofnode != node)
-			continue;
-		cache = cache_find_first_sibling(iter);
-		break;
-	}
-
-	return cache;
+	if ((nr_sets == 1) || !(nr_sets > 0 && size > 0 && line_size > 0))
+		this_leaf->ways_of_associativity = 0;
+	else
+		this_leaf->ways_of_associativity = (size / nr_sets) / line_size;
 }
 
 static bool cache_node_is_unified(const struct device_node *np)
@@ -324,526 +142,74 @@ static bool cache_node_is_unified(const struct device_node *np)
 	return of_get_property(np, "cache-unified", NULL);
 }
 
-static struct cache *cache_do_one_devnode_unified(struct device_node *node,
-						  int level)
-{
-	struct cache *cache;
-
-	pr_debug("creating L%d ucache for %s\n", level, node->full_name);
-
-	cache = new_cache(CACHE_TYPE_UNIFIED, level, node);
-
-	return cache;
-}
-
-static struct cache *cache_do_one_devnode_split(struct device_node *node,
-						int level)
-{
-	struct cache *dcache, *icache;
-
-	pr_debug("creating L%d dcache and icache for %s\n", level,
-		 node->full_name);
-
-	dcache = new_cache(CACHE_TYPE_DATA, level, node);
-	icache = new_cache(CACHE_TYPE_INSTRUCTION, level, node);
-
-	if (!dcache || !icache)
-		goto err;
-
-	dcache->next_local = icache;
-
-	return dcache;
-err:
-	release_cache(dcache);
-	release_cache(icache);
-	return NULL;
-}
-
-static struct cache *cache_do_one_devnode(struct device_node *node, int level)
-{
-	struct cache *cache;
-
-	if (cache_node_is_unified(node))
-		cache = cache_do_one_devnode_unified(node, level);
-	else
-		cache = cache_do_one_devnode_split(node, level);
-
-	return cache;
-}
-
-static struct cache *cache_lookup_or_instantiate(struct device_node *node,
-						 int level)
-{
-	struct cache *cache;
-
-	cache = cache_lookup_by_node(node);
-
-	WARN_ONCE(cache && cache->level != level,
-		  "cache level mismatch on lookup (got %d, expected %d)\n",
-		  cache->level, level);
-
-	if (!cache)
-		cache = cache_do_one_devnode(node, level);
-
-	return cache;
-}
-
-static void link_cache_lists(struct cache *smaller, struct cache *bigger)
-{
-	while (smaller->next_local) {
-		if (smaller->next_local == bigger)
-			return; /* already linked */
-		smaller = smaller->next_local;
-	}
-
-	smaller->next_local = bigger;
-}
-
-static void do_subsidiary_caches_debugcheck(struct cache *cache)
-{
-	WARN_ON_ONCE(cache->level != 1);
-	WARN_ON_ONCE(strcmp(cache->ofnode->type, "cpu"));
-}
-
-static void do_subsidiary_caches(struct cache *cache)
-{
-	struct device_node *subcache_node;
-	int level = cache->level;
-
-	do_subsidiary_caches_debugcheck(cache);
-
-	while ((subcache_node = of_find_next_cache_node(cache->ofnode))) {
-		struct cache *subcache;
-
-		level++;
-		subcache = cache_lookup_or_instantiate(subcache_node, level);
-		of_node_put(subcache_node);
-		if (!subcache)
-			break;
-
-		link_cache_lists(cache, subcache);
-		cache = subcache;
-	}
-}
-
-static struct cache *cache_chain_instantiate(unsigned int cpu_id)
+static void ci_leaf_init(struct cacheinfo *this_leaf,
+			 enum cache_type type, unsigned int level)
 {
-	struct device_node *cpu_node;
-	struct cache *cpu_cache = NULL;
-
-	pr_debug("creating cache object(s) for CPU %i\n", cpu_id);
-
-	cpu_node = of_get_cpu_node(cpu_id, NULL);
-	WARN_ONCE(!cpu_node, "no OF node found for CPU %i\n", cpu_id);
-	if (!cpu_node)
-		goto out;
-
-	cpu_cache = cache_lookup_or_instantiate(cpu_node, 1);
-	if (!cpu_cache)
-		goto out;
-
-	do_subsidiary_caches(cpu_cache);
-
-	cache_cpu_set(cpu_cache, cpu_id);
-out:
-	of_node_put(cpu_node);
-
-	return cpu_cache;
+	this_leaf->level = level;
+	this_leaf->type = type;
+	cache_size(this_leaf);
+	cache_get_line_size(this_leaf);
+	cache_nr_sets(this_leaf);
+	cache_associativity(this_leaf);
 }
 
-static struct cache_dir *cacheinfo_create_cache_dir(unsigned int cpu_id)
+int init_cache_level(unsigned int cpu)
 {
-	struct cache_dir *cache_dir;
-	struct device *dev;
-	struct kobject *kobj = NULL;
-
-	dev = get_cpu_device(cpu_id);
-	WARN_ONCE(!dev, "no dev for CPU %i\n", cpu_id);
-	if (!dev)
-		goto err;
-
-	kobj = kobject_create_and_add("cache", &dev->kobj);
-	if (!kobj)
-		goto err;
-
-	cache_dir = kzalloc(sizeof(*cache_dir), GFP_KERNEL);
-	if (!cache_dir)
-		goto err;
-
-	cache_dir->kobj = kobj;
-
-	WARN_ON_ONCE(per_cpu(cache_dir_pcpu, cpu_id) != NULL);
-
-	per_cpu(cache_dir_pcpu, cpu_id) = cache_dir;
+	struct device_node *np;
+	struct device *cpu_dev = get_cpu_device(cpu);
+	struct cpu_cacheinfo *this_cpu_ci = get_cpu_cacheinfo(cpu);
+	unsigned int level = 0, leaves = 0;
 
-	return cache_dir;
-err:
-	kobject_put(kobj);
-	return NULL;
-}
-
-static void cache_index_release(struct kobject *kobj)
-{
-	struct cache_index_dir *index;
-
-	index = kobj_to_cache_index_dir(kobj);
-
-	pr_debug("freeing index directory for L%d %s cache\n",
-		 index->cache->level, cache_type_string(index->cache));
-
-	kfree(index);
-}
-
-static ssize_t cache_index_show(struct kobject *k, struct attribute *attr, char *buf)
-{
-	struct kobj_attribute *kobj_attr;
-
-	kobj_attr = container_of(attr, struct kobj_attribute, attr);
-
-	return kobj_attr->show(k, kobj_attr, buf);
-}
-
-static struct cache *index_kobj_to_cache(struct kobject *k)
-{
-	struct cache_index_dir *index;
-
-	index = kobj_to_cache_index_dir(k);
-
-	return index->cache;
-}
-
-static ssize_t size_show(struct kobject *k, struct kobj_attribute *attr, char *buf)
-{
-	unsigned int size_kb;
-	struct cache *cache;
-
-	cache = index_kobj_to_cache(k);
-
-	if (cache_size_kb(cache, &size_kb))
-		return -ENODEV;
-
-	return sprintf(buf, "%uK\n", size_kb);
-}
-
-static struct kobj_attribute cache_size_attr =
-	__ATTR(size, 0444, size_show, NULL);
-
-
-static ssize_t line_size_show(struct kobject *k, struct kobj_attribute *attr, char *buf)
-{
-	unsigned int line_size;
-	struct cache *cache;
-
-	cache = index_kobj_to_cache(k);
-
-	if (cache_get_line_size(cache, &line_size))
-		return -ENODEV;
-
-	return sprintf(buf, "%u\n", line_size);
-}
-
-static struct kobj_attribute cache_line_size_attr =
-	__ATTR(coherency_line_size, 0444, line_size_show, NULL);
-
-static ssize_t nr_sets_show(struct kobject *k, struct kobj_attribute *attr, char *buf)
-{
-	unsigned int nr_sets;
-	struct cache *cache;
-
-	cache = index_kobj_to_cache(k);
-
-	if (cache_nr_sets(cache, &nr_sets))
+	if (!cpu_dev) {
+		pr_err("No cpu device for CPU %d\n", cpu);
 		return -ENODEV;
-
-	return sprintf(buf, "%u\n", nr_sets);
-}
-
-static struct kobj_attribute cache_nr_sets_attr =
-	__ATTR(number_of_sets, 0444, nr_sets_show, NULL);
-
-static ssize_t associativity_show(struct kobject *k, struct kobj_attribute *attr, char *buf)
-{
-	unsigned int associativity;
-	struct cache *cache;
-
-	cache = index_kobj_to_cache(k);
-
-	if (cache_associativity(cache, &associativity))
-		return -ENODEV;
-
-	return sprintf(buf, "%u\n", associativity);
-}
-
-static struct kobj_attribute cache_assoc_attr =
-	__ATTR(ways_of_associativity, 0444, associativity_show, NULL);
-
-static ssize_t type_show(struct kobject *k, struct kobj_attribute *attr, char *buf)
-{
-	struct cache *cache;
-
-	cache = index_kobj_to_cache(k);
-
-	return sprintf(buf, "%s\n", cache_type_string(cache));
-}
-
-static struct kobj_attribute cache_type_attr =
-	__ATTR(type, 0444, type_show, NULL);
-
-static ssize_t level_show(struct kobject *k, struct kobj_attribute *attr, char *buf)
-{
-	struct cache_index_dir *index;
-	struct cache *cache;
-
-	index = kobj_to_cache_index_dir(k);
-	cache = index->cache;
-
-	return sprintf(buf, "%d\n", cache->level);
-}
-
-static struct kobj_attribute cache_level_attr =
-	__ATTR(level, 0444, level_show, NULL);
-
-static ssize_t shared_cpu_map_show(struct kobject *k, struct kobj_attribute *attr, char *buf)
-{
-	struct cache_index_dir *index;
-	struct cache *cache;
-	int len;
-	int n = 0;
-
-	index = kobj_to_cache_index_dir(k);
-	cache = index->cache;
-	len = PAGE_SIZE - 2;
-
-	if (len > 1) {
-		n = cpumask_scnprintf(buf, len, &cache->shared_cpu_map);
-		buf[n++] = '\n';
-		buf[n] = '\0';
 	}
-	return n;
-}
-
-static struct kobj_attribute cache_shared_cpu_map_attr =
-	__ATTR(shared_cpu_map, 0444, shared_cpu_map_show, NULL);
-
-/* Attributes which should always be created -- the kobject/sysfs core
- * does this automatically via kobj_type->default_attrs.  This is the
- * minimum data required to uniquely identify a cache.
- */
-static struct attribute *cache_index_default_attrs[] = {
-	&cache_type_attr.attr,
-	&cache_level_attr.attr,
-	&cache_shared_cpu_map_attr.attr,
-	NULL,
-};
-
-/* Attributes which should be created if the cache device node has the
- * right properties -- see cacheinfo_create_index_opt_attrs
- */
-static struct kobj_attribute *cache_index_opt_attrs[] = {
-	&cache_size_attr,
-	&cache_line_size_attr,
-	&cache_nr_sets_attr,
-	&cache_assoc_attr,
-};
-
-static const struct sysfs_ops cache_index_ops = {
-	.show = cache_index_show,
-};
-
-static struct kobj_type cache_index_type = {
-	.release = cache_index_release,
-	.sysfs_ops = &cache_index_ops,
-	.default_attrs = cache_index_default_attrs,
-};
-
-static void cacheinfo_create_index_opt_attrs(struct cache_index_dir *dir)
-{
-	const char *cache_name;
-	const char *cache_type;
-	struct cache *cache;
-	char *buf;
-	int i;
-
-	buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
-	if (!buf)
-		return;
-
-	cache = dir->cache;
-	cache_name = cache->ofnode->full_name;
-	cache_type = cache_type_string(cache);
-
-	/* We don't want to create an attribute that can't provide a
-	 * meaningful value.  Check the return value of each optional
-	 * attribute's ->show method before registering the
-	 * attribute.
-	 */
-	for (i = 0; i < ARRAY_SIZE(cache_index_opt_attrs); i++) {
-		struct kobj_attribute *attr;
-		ssize_t rc;
-
-		attr = cache_index_opt_attrs[i];
-
-		rc = attr->show(&dir->kobj, attr, buf);
-		if (rc <= 0) {
-			pr_debug("not creating %s attribute for "
-				 "%s(%s) (rc = %zd)\n",
-				 attr->attr.name, cache_name,
-				 cache_type, rc);
-			continue;
-		}
-		if (sysfs_create_file(&dir->kobj, &attr->attr))
-			pr_debug("could not create %s attribute for %s(%s)\n",
-				 attr->attr.name, cache_name, cache_type);
+	np = cpu_dev->of_node;
+	if (!np) {
+		pr_err("Failed to find cpu%d device node\n", cpu);
+		return -ENOENT;
 	}
 
-	kfree(buf);
-}
-
-static void cacheinfo_create_index_dir(struct cache *cache, int index,
-				       struct cache_dir *cache_dir)
-{
-	struct cache_index_dir *index_dir;
-	int rc;
-
-	index_dir = kzalloc(sizeof(*index_dir), GFP_KERNEL);
-	if (!index_dir)
-		goto err;
-
-	index_dir->cache = cache;
-
-	rc = kobject_init_and_add(&index_dir->kobj, &cache_index_type,
-				  cache_dir->kobj, "index%d", index);
-	if (rc)
-		goto err;
-
-	index_dir->next = cache_dir->index;
-	cache_dir->index = index_dir;
-
-	cacheinfo_create_index_opt_attrs(index_dir);
-
-	return;
-err:
-	kfree(index_dir);
-}
-
-static void cacheinfo_sysfs_populate(unsigned int cpu_id,
-				     struct cache *cache_list)
-{
-	struct cache_dir *cache_dir;
-	struct cache *cache;
-	int index = 0;
-
-	cache_dir = cacheinfo_create_cache_dir(cpu_id);
-	if (!cache_dir)
-		return;
-
-	cache = cache_list;
-	while (cache) {
-		cacheinfo_create_index_dir(cache, index, cache_dir);
-		index++;
-		cache = cache->next_local;
+	while (np) {
+		leaves += cache_node_is_unified(np) ? 1 : 2;
+		level++;
+		of_node_put(np);
+		np = of_find_next_cache_node(np);
 	}
-}
+	this_cpu_ci->num_levels = level;
+	this_cpu_ci->num_leaves = leaves;
 
-void cacheinfo_cpu_online(unsigned int cpu_id)
-{
-	struct cache *cache;
-
-	cache = cache_chain_instantiate(cpu_id);
-	if (!cache)
-		return;
-
-	cacheinfo_sysfs_populate(cpu_id, cache);
-}
-
-/* functions needed to remove cache entry for cpu offline or suspend/resume */
-
-#if (defined(CONFIG_PPC_PSERIES) && defined(CONFIG_SUSPEND)) || \
-    defined(CONFIG_HOTPLUG_CPU)
-
-static struct cache *cache_lookup_by_cpu(unsigned int cpu_id)
-{
-	struct device_node *cpu_node;
-	struct cache *cache;
-
-	cpu_node = of_get_cpu_node(cpu_id, NULL);
-	WARN_ONCE(!cpu_node, "no OF node found for CPU %i\n", cpu_id);
-	if (!cpu_node)
-		return NULL;
-
-	cache = cache_lookup_by_node(cpu_node);
-	of_node_put(cpu_node);
-
-	return cache;
+	return 0;
 }
 
-static void remove_index_dirs(struct cache_dir *cache_dir)
+int populate_cache_leaves(unsigned int cpu)
 {
-	struct cache_index_dir *index;
-
-	index = cache_dir->index;
+	struct cpu_cacheinfo *this_cpu_ci = get_cpu_cacheinfo(cpu);
+	struct cacheinfo *this_leaf = this_cpu_ci->info_list;
+	struct device *cpu_dev = get_cpu_device(cpu);
+	struct device_node *np;
+	unsigned int level, idx;
 
-	while (index) {
-		struct cache_index_dir *next;
-
-		next = index->next;
-		kobject_put(&index->kobj);
-		index = next;
+	np = of_node_get(cpu_dev->of_node);
+	if (!np) {
+		pr_err("Failed to find cpu%d device node\n", cpu);
+		return -ENOENT;
 	}
-}
-
-static void remove_cache_dir(struct cache_dir *cache_dir)
-{
-	remove_index_dirs(cache_dir);
 
-	/* Remove cache dir from sysfs */
-	kobject_del(cache_dir->kobj);
-
-	kobject_put(cache_dir->kobj);
-
-	kfree(cache_dir);
-}
-
-static void cache_cpu_clear(struct cache *cache, int cpu)
-{
-	while (cache) {
-		struct cache *next = cache->next_local;
-
-		WARN_ONCE(!cpumask_test_cpu(cpu, &cache->shared_cpu_map),
-			  "CPU %i not accounted in %s(%s)\n",
-			  cpu, cache->ofnode->full_name,
-			  cache_type_string(cache));
-
-		cpumask_clear_cpu(cpu, &cache->shared_cpu_map);
-
-		/* Release the cache object if all the cpus using it
-		 * are offline */
-		if (cpumask_empty(&cache->shared_cpu_map))
-			release_cache(cache);
-
-		cache = next;
+	for (idx = 0, level = 1; level <= this_cpu_ci->num_levels &&
+	     idx < this_cpu_ci->num_leaves; idx++, level++) {
+		if (!this_leaf)
+			return -EINVAL;
+
+		this_leaf->of_node = np;
+		if (cache_node_is_unified(np)) {
+			ci_leaf_init(this_leaf++, CACHE_TYPE_UNIFIED, level);
+		} else {
+			ci_leaf_init(this_leaf++, CACHE_TYPE_DATA, level);
+			ci_leaf_init(this_leaf++, CACHE_TYPE_INST, level);
+		}
+		np = of_find_next_cache_node(np);
 	}
+	return 0;
 }
 
-void cacheinfo_cpu_offline(unsigned int cpu_id)
-{
-	struct cache_dir *cache_dir;
-	struct cache *cache;
-
-	/* Prevent userspace from seeing inconsistent state - remove
-	 * the sysfs hierarchy first */
-	cache_dir = per_cpu(cache_dir_pcpu, cpu_id);
-
-	/* careful, sysfs population may have failed */
-	if (cache_dir)
-		remove_cache_dir(cache_dir);
-
-	per_cpu(cache_dir_pcpu, cpu_id) = NULL;
-
-	/* clear the CPU's bit in its cache chain, possibly freeing
-	 * cache objects */
-	cache = cache_lookup_by_cpu(cpu_id);
-	if (cache)
-		cache_cpu_clear(cache, cpu_id);
-}
-#endif /* (CONFIG_PPC_PSERIES && CONFIG_SUSPEND) || CONFIG_HOTPLUG_CPU */
diff --git a/arch/powerpc/kernel/cacheinfo.h b/arch/powerpc/kernel/cacheinfo.h
deleted file mode 100644
index a7b74d36acd7..000000000000
--- a/arch/powerpc/kernel/cacheinfo.h
+++ /dev/null
@@ -1,8 +0,0 @@
-#ifndef _PPC_CACHEINFO_H
-#define _PPC_CACHEINFO_H
-
-/* These are just hooks for sysfs.c to use. */
-extern void cacheinfo_cpu_online(unsigned int cpu_id);
-extern void cacheinfo_cpu_offline(unsigned int cpu_id);
-
-#endif /* _PPC_CACHEINFO_H */
diff --git a/arch/powerpc/kernel/sysfs.c b/arch/powerpc/kernel/sysfs.c
index fa1fd8a0c867..1a2ea4d64b28 100644
--- a/arch/powerpc/kernel/sysfs.c
+++ b/arch/powerpc/kernel/sysfs.c
@@ -19,8 +19,6 @@
 #include <asm/pmc.h>
 #include <asm/firmware.h>
 
-#include "cacheinfo.h"
-
 #ifdef CONFIG_PPC64
 #include <asm/paca.h>
 #include <asm/lppaca.h>
@@ -743,7 +741,6 @@ static void register_cpu_online(unsigned int cpu)
 		device_create_file(s, &dev_attr_altivec_idle_wait_time);
 	}
 #endif
-	cacheinfo_cpu_online(cpu);
 }
 
 #ifdef CONFIG_HOTPLUG_CPU
@@ -824,7 +821,6 @@ static void unregister_cpu_online(unsigned int cpu)
 		device_remove_file(s, &dev_attr_altivec_idle_wait_time);
 	}
 #endif
-	cacheinfo_cpu_offline(cpu);
 }
 
 #ifdef CONFIG_ARCH_CPU_PROBE_RELEASE
@@ -988,8 +984,7 @@ static int __init topology_init(void)
 	int cpu;
 
 	register_nodes();
-
-	cpu_notifier_register_begin();
+	register_cpu_notifier(&sysfs_cpu_nb);
 
 	for_each_possible_cpu(cpu) {
 		struct cpu *c = &per_cpu(cpu_devices, cpu);
@@ -1013,11 +1008,6 @@ static int __init topology_init(void)
 		if (cpu_online(cpu))
 			register_cpu_online(cpu);
 	}
-
-	__register_cpu_notifier(&sysfs_cpu_nb);
-
-	cpu_notifier_register_done();
-
 #ifdef CONFIG_PPC64
 	sysfs_create_dscr_default();
 #endif /* CONFIG_PPC64 */
-- 
1.9.1

^ permalink raw reply related

* Re: [PATCH] [v3] power/fsl: add MDIO dt binding for FMan
From: Emil Medve @ 2015-01-08  9:31 UTC (permalink / raw)
  To: Scott Wood
  Cc: devicetree@vger.kernel.org, linuxppc-dev@lists.ozlabs.org,
	Xie Shaohui-B21989
In-Reply-To: <1420679558.4961.64.camel@freescale.com>

Hello Scott,


On 01/07/2015 07:12 PM, Scott Wood wrote:
> On Wed, 2015-01-07 at 13:44 -0600, Emil Medve wrote:
>> Hello Scott,
>>
>>
>> On 01/07/2015 12:05 PM, Scott Wood wrote:
>>> On Tue, 2015-01-06 at 23:29 -0600, Xie Shaohui-B21989 wrote:
>>>>>>> +- interrupts
>>>>>>> +		Usage: optional
>>>>>>> +		Value type: <prop-encoded-array>
>>>>>>> +		Definition: Event interrupt of external MDIO controller.
>>>>>>> +		1 Gb/s MDIO and 10 Gb/s MDIO has one interrupt respectively.
>>>>>
>>>>> I'm confused by "respectively" here.  Does fsl,fman-memac-mdio have two
>>>>> interrupts (one for 1 Gb/s and one for 10 Gb/s)?
>>>> [S.H] We use two MDIO controllers for external PHY management. One for 1 Gb/s,
>>>> One for 10 Gb/s, and two MDIO interrupts connected to MPIC.
>>>
>>> If there can be two interrupts you need to make that clear and specify
>>> the order.
>>>
>>> Is it possible for one MDIO controller to have an interrupt connected
>>> but not the other, on the same system?  How would you represent that in
>>> the device tree?  If there are two MDIO controllers why are they in the
>>> same node?
>>
>> Historically (FMan v2 and even before/legacy) we've had each MAC include
>> an MDIO controller, but only one MDIO controller per MAC type/speed (1
>> Gb/s vs 10 Gb/s) is pinned out and all the same speed PHY(s) are
>> connected to the respective MDIO controllers. As such the first 1 Gb/s
>> MAC/MDIO controller is used to manage all the 1 Gb/s PHY(s) and the
>> first 10 Gb/s MAC/MDIO controller is used to manage all the 10 Gb/s
>> PHY(s). Each MDIO controller has the ability to generate interrupts but
>> only pinned out MDIO controllers are hooked up to the MPIC (as such the
>> talk about two interrupts)
>>
>> (Each MAC has also integrated a SERDES/TBI/"internal" PHY that is
>> connected to the "local" MDIO controller)
>>
>> As you can imagine this creates a number of problems in a partitioning
>> scenario (and not just, imagine RCWs where the first MAC is not
>> used/enabled). In order to help a bit (but not quite enough), in FMan
>> v3, two additional MDIO controllers (one for 1 the Gb/s PHY(s) and one
>> for 1 the 10 Gb/s PHY(s)) have been integrated that are not associated
>> with any MAC and these are the pinned out MDIO controllers on such
>> SoC(s) (chassis v2)
> 
> I'm happy to hear that.  Is that what is meant by "external" here?

"External" doesn't mean external to the MAC nodes. "External" doesn't
even properly apply to the MDIO controller(s) at all but to the PHY(s).

> I thought it meant external to the SoC.  Is this the term used by
> hardware documentation?

The documentation (mostly chip errata documents) refers to
external/internal MDIO accesses and as on FMan v3 external PHY accesses
are always made via these extra MDIO controllers (pinned oud) and the
internal SERDES PHY accesses are always made via the in-MAC MDIO
controllers some level of confusion is easy to be achieved. All the MDIO
controllers are identical whether they are in-MAC or standalone

> I'd have called it "independent" or similar.

To make things even more confusing, some documents call these extra MDIO
controllers "dedicated"


Cheers,


>>>>   Does "optional" mean it's used if and
>>>>> only if external MDIO is used, or is it optional even with external MDIO?  I see
>>>>> it's not present in the example -- do we not have a real example that has the
>>>>> interrupt?
>>>> [S.H] "optional" means it's available on hardware, but MDIO driver does not use interrupt. 
>>>> So we don't have a real example.
>>>
>>> <record type="broken">The device tree describes the hardware, not the
>>> driver</record>
>>
>> Anyway, only two MDIO nodes (out of 4 to 14) would have an interrupt
>> property describing exactly one interrupt. What language should we use
>> to convey this situation
> 
> So the answer is that there will not be more than one MDIO controller
> per MDIO node, or more than one interrupt per MDIO node?  In that case
> just get rid of the confusing "respectively" sentence -- and always
> describe the interrupt if it exists in hardware.
> 
> -Scott
> 
> 
> .
> 

^ permalink raw reply

* Re: [PATCH v7 0/4] Add support for parametrized events
From: Jiri Olsa @ 2015-01-08  9:54 UTC (permalink / raw)
  To: Sukadev Bhattiprolu
  Cc: peterz, linux-kernel, Arnaldo Carvalho de Melo, dev,
	Paul Mackerras, linuxppc-dev
In-Reply-To: <1420679633-28856-1-git-send-email-sukadev@linux.vnet.ibm.com>

On Wed, Jan 07, 2015 at 05:13:49PM -0800, Sukadev Bhattiprolu wrote:
> Description of "event parameters" from the documentation patch:
> 
>     Event parameters are a basic way for partial events to be specified in
>     sysfs with per-event names given to the fields that need to be filled in
>     when using a particular event.
> 
>     It is intended for supporting cases where the single 'cpu' parameter is
>     insufficient. For example, POWER 8 has events for physical
>     sockets/cores/cpus that are accessible from with virtual machines. To
>     keep using the single 'cpu' parameter we'd need to perform a mapping
>     between Linux's cpus and the physical machine's cpus (in this case
>     Linux is running under a hypervisor). This isn't possible because
>     bindings between our cpus and physical cpus may not be fixed, and we
>     probably won't have a "cpu" on each physical cpu.
> 
> Description of the sysfs contents when events are parameterized (copied from an
> included patch):
> 
> 	Examples:
> 
> 		domain=0x1,offset=0x8,core=?
> 
> 	In the case of the last example, a value replacing "?" would need
> 	to be provided by the user selecting the particular event. This is
> 	refered to as "event parameterization". All non-numerical values
> 	indicate an event parameter.
> 
> Notes on how perf-list displays parameterized events
> 
> 	PARAMETERIZED EVENTS
> 	--------------------
> 
> 	Some pmu events listed by 'perf list' will be displayed with '$xyz' in
> 	them. For example:
> 
> 	  hv_24x7/HPM_THREAD_NAP_CCYC__PHYS_CORE,core=?/
> 
> 	This means that when provided as an event, a value for ? must also
> 	be supplied. For example:
> 
> 	  perf stat  -e \
> 	  	'hv_24x7/HPM_THREAD_NAP_CCYC__PHYS_CORE,core=2' ...
> 
> Changelog[v7]
> 	[Jiri Olsa] Nit: Add braces for clarity.
> 	[Jiri Olsa] Add a check to make sure that sysfs entries have with
> 	parameters exactly match '=?'.

for the patchset:

Acked-by: Jiri Olsa <jolsa@kernel.org>

thanks,
jirka

^ permalink raw reply

* How to make use of SPE instructions?
From: Markus Stockhausen @ 2015-01-08  9:58 UTC (permalink / raw)
  To: linuxppc-dev@lists.ozlabs.org

[-- Attachment #1: Type: text/plain, Size: 839 bytes --]

Hello,

I developed a SHA224/256 kernel crypto module with SPE instructions.
The result looks quite promising (~ +50% speedup). Nevertheless the
flooding of kernel messages "SPE used in kernel" makes me feel 
uncomfortable.

My findings so far:

- I can configure the kernel with "SPE support". 
- arch/powerpc/kernel/head_fsl_booke.S suggests that the message is
  triggerd unconditionally whenwever we make use of SPE in kernel.
- There exists a function enable_kernel_spe() but I don't know how
  this could help me in my work.

I guess I need some kind of "brackets" around my coding to make sure 
the upper 32 bit of the registers are stored correctly during task switch. 
Or is the use of SPE instructions inside the kernel totally forbidden? Any 
expert with some helpful advise?

Thanks in advance.

Markus
=

[-- Attachment #2: InterScan_Disclaimer.txt --]
[-- Type: text/plain, Size: 1650 bytes --]

****************************************************************************
Diese E-Mail enthält vertrauliche und/oder rechtlich geschützte
Informationen. Wenn Sie nicht der richtige Adressat sind oder diese E-Mail
irrtümlich erhalten haben, informieren Sie bitte sofort den Absender und
vernichten Sie diese Mail. Das unerlaubte Kopieren sowie die unbefugte
Weitergabe dieser Mail ist nicht gestattet.

Über das Internet versandte E-Mails können unter fremden Namen erstellt oder
manipuliert werden. Deshalb ist diese als E-Mail verschickte Nachricht keine
rechtsverbindliche Willenserklärung.

Collogia
Unternehmensberatung AG
Ubierring 11
D-50678 Köln

Vorstand:
Kadir Akin
Dr. Michael Höhnerbach

Vorsitzender des Aufsichtsrates:
Hans Kristian Langva

Registergericht: Amtsgericht Köln
Registernummer: HRB 52 497

This e-mail may contain confidential and/or privileged information. If you
are not the intended recipient (or have received this e-mail in error)
please notify the sender immediately and destroy this e-mail. Any
unauthorized copying, disclosure or distribution of the material in this
e-mail is strictly forbidden.

e-mails sent over the internet may have been written under a wrong name or
been manipulated. That is why this message sent as an e-mail is not a
legally binding declaration of intention.

Collogia
Unternehmensberatung AG
Ubierring 11
D-50678 Köln

executive board:
Kadir Akin
Dr. Michael Höhnerbach

President of the supervisory board:
Hans Kristian Langva

Registry office: district court Cologne
Register number: HRB 52 497

****************************************************************************

^ permalink raw reply

* Re: [RFC] PPC: MPIC: necessary readback after EOI?
From: Benjamin Herrenschmidt @ 2015-01-08 19:17 UTC (permalink / raw)
  To: Scott Wood; +Cc: Purcareata Bogdan, linuxppc-dev, linux-kernel, Andreas Mohr
In-Reply-To: <1420650283.4961.52.camel@freescale.com>

On Wed, 2015-01-07 at 11:04 -0600, Scott Wood wrote:
> On Wed, 2015-01-07 at 15:44 +0100, Benjamin Herrenschmidt wrote:
> > On Mon, 2015-01-05 at 12:10 -0600, Scott Wood wrote:
> > > It would have been nice if a code comment explained why it was doing the
> > > readback...  I don't see any particular need to wait for EOI completion
> > > here (unlike when masking).
> > 
> > The EOI is what causes the MPIC to drop it's EE output to the CPU, if the
> > EOI is processed too slowly & asynchronously (posted write + 33Mhz MPIC)
> > we observe cases of spurrious interrupts. We had some macs basically getting
> > a spurrious irq for every MPIC interrupts...
> 
> Shouldn't reading INTACK be what causes the MPIC to drop its EE output?

Hrm, looks like I had too much wine or something, you are correct yes,
it's the intack, so my explanation is bogus.

So we are down to possibly delaying the raising back of the CPU priority
which is not a big deal indeed, we could probably get rid of the read
back.

Ben.

^ permalink raw reply

* [PATCH] cxl: remove redundant increment of hwirq
From: Colin King @ 2015-01-08 22:36 UTC (permalink / raw)
  To: Ian Munsie, Michael Neuling, linuxppc-dev; +Cc: linux-kernel

From: Colin Ian King <colin.king@canonical.com>

hwirq has not been initialized, however it is being incremented
and also not being referenced in a loop.  This error was detected with
cppcheck:

[drivers/misc/cxl/irq.c:439]: (error) Uninitialized variable: hwirq

Commit 80fa93fce37d ("cxl: Name interrupts in /proc/interrupt") 
introduced this error.

This is a simple fix that removes the redundant increment.

Signed-off-by: Colin Ian King <colin.king@canonical.com>
---
 drivers/misc/cxl/irq.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/misc/cxl/irq.c b/drivers/misc/cxl/irq.c
index c294925..68ab608 100644
--- a/drivers/misc/cxl/irq.c
+++ b/drivers/misc/cxl/irq.c
@@ -436,7 +436,7 @@ int afu_register_irqs(struct cxl_context *ctx, u32 count)
 	 */
 	INIT_LIST_HEAD(&ctx->irq_names);
 	for (r = 1; r < CXL_IRQ_RANGES; r++) {
-		for (i = 0; i < ctx->irqs.range[r]; hwirq++, i++) {
+		for (i = 0; i < ctx->irqs.range[r]; i++) {
 			irq_name = kmalloc(sizeof(struct cxl_irq_name),
 					   GFP_KERNEL);
 			if (!irq_name)
-- 
2.1.4

^ permalink raw reply related

* Re: [PATCH] cxl: remove redundant increment of hwirq
From: Michael Neuling @ 2015-01-08 22:42 UTC (permalink / raw)
  To: Colin King; +Cc: linuxppc-dev, Ian Munsie, linux-kernel
In-Reply-To: <1420756607-23459-1-git-send-email-colin.king@canonical.com>

On Thu, 2015-01-08 at 22:36 +0000, Colin King wrote:
> From: Colin Ian King <colin.king@canonical.com>
>=20
> hwirq has not been initialized, however it is being incremented
> and also not being referenced in a loop.  This error was detected with
> cppcheck:
>=20
> [drivers/misc/cxl/irq.c:439]: (error) Uninitialized variable: hwirq
>=20
> Commit 80fa93fce37d ("cxl: Name interrupts in /proc/interrupt")=20
> introduced this error.
>=20
> This is a simple fix that removes the redundant increment.
>=20
> Signed-off-by: Colin Ian King <colin.king@canonical.com>

Thanks.  Looks good.

Acked-By: Michael Neuling <mikey@neuling.org>

> ---
>  drivers/misc/cxl/irq.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
>=20
> diff --git a/drivers/misc/cxl/irq.c b/drivers/misc/cxl/irq.c
> index c294925..68ab608 100644
> --- a/drivers/misc/cxl/irq.c
> +++ b/drivers/misc/cxl/irq.c
> @@ -436,7 +436,7 @@ int afu_register_irqs(struct cxl_context *ctx, u32 co=
unt)
>  	 */
>  	INIT_LIST_HEAD(&ctx->irq_names);
>  	for (r =3D 1; r < CXL_IRQ_RANGES; r++) {
> -		for (i =3D 0; i < ctx->irqs.range[r]; hwirq++, i++) {
> +		for (i =3D 0; i < ctx->irqs.range[r]; i++) {
>  			irq_name =3D kmalloc(sizeof(struct cxl_irq_name),
>  					   GFP_KERNEL);
>  			if (!irq_name)

^ permalink raw reply

* [PATCH 1/2] powerpc: Add 64bit optimised memcmp
From: Anton Blanchard @ 2015-01-09  1:56 UTC (permalink / raw)
  To: benh, paulus, mpe; +Cc: linuxppc-dev

I noticed ksm spending quite a lot of time in memcmp on a large
KVM box. The current memcmp loop is very unoptimised - byte at a
time compares with no loop unrolling. We can do much much better.

Optimise the loop in a few ways:

- Unroll the byte at a time loop

- For large (at least 32 byte) comparisons that are also 8 byte
  aligned, use an unrolled modulo scheduled loop using 8 byte
  loads. This is similar to our glibc memcmp.

A simple microbenchmark testing 10000000 iterations of an 8192 byte
memcmp was used to measure the performance:

baseline:	29.93 s

modified:	 1.70 s

Just over 17x faster.

Signed-off-by: Anton Blanchard <anton@samba.org>
---
 arch/powerpc/lib/Makefile    |   3 +-
 arch/powerpc/lib/memcmp_64.S | 233 +++++++++++++++++++++++++++++++++++++++++++
 arch/powerpc/lib/string.S    |   2 +
 3 files changed, 237 insertions(+), 1 deletion(-)
 create mode 100644 arch/powerpc/lib/memcmp_64.S

diff --git a/arch/powerpc/lib/Makefile b/arch/powerpc/lib/Makefile
index 1b01159..5526156 100644
--- a/arch/powerpc/lib/Makefile
+++ b/arch/powerpc/lib/Makefile
@@ -15,7 +15,8 @@ obj-$(CONFIG_PPC32)	+= div64.o copy_32.o
 
 obj-$(CONFIG_PPC64)	+= copypage_64.o copyuser_64.o \
 			   usercopy_64.o mem_64.o hweight_64.o \
-			   copyuser_power7.o string_64.o copypage_power7.o
+			   copyuser_power7.o string_64.o copypage_power7.o \
+			   memcmp_64.o
 ifeq ($(CONFIG_GENERIC_CSUM),)
 obj-y			+= checksum_$(CONFIG_WORD_SIZE).o
 obj-$(CONFIG_PPC64)	+= checksum_wrappers_64.o
diff --git a/arch/powerpc/lib/memcmp_64.S b/arch/powerpc/lib/memcmp_64.S
new file mode 100644
index 0000000..d71880b
--- /dev/null
+++ b/arch/powerpc/lib/memcmp_64.S
@@ -0,0 +1,233 @@
+/*
+ * Author: Author: Anton Blanchard <anton@au.ibm.com>
+ * Copyright 2015 IBM Corporation.
+ *
+ * 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.
+ */
+#include <asm/ppc_asm.h>
+
+#define off8	r6
+#define off16	r7
+#define off24	r8
+
+#define rA	r9
+#define rB	r10
+#define rC	r11
+#define rD	r27
+#define rE	r28
+#define rF	r29
+#define rG	r30
+#define rH	r31
+
+#ifdef __LITTLE_ENDIAN__
+#define LD	ldbrx
+#else
+#define LD	ldx
+#endif
+
+_GLOBAL(memcmp)
+	cmpdi	cr1,r5,0
+
+	/* Use the short loop if both strings are not 8B aligned */
+	or	r6,r3,r4
+	rldicl.	r6,r6,0,(64-3)
+
+	/* Use the short loop if length is less than 32B */
+	cmpdi	cr5,r5,31
+
+	beq	cr1,.Lzero
+	bne	.Lshort
+	bgt	cr5,.Llong
+
+.Lshort:
+	mtctr	r5
+
+1:	lbz	rA,0(r3)
+	lbz	rB,0(r4)
+	subf.	rC,rB,rA
+	bne	.Lnon_zero
+	bdz	.Lzero
+
+	lbz	rA,1(r3)
+	lbz	rB,1(r4)
+	subf.	rC,rB,rA
+	bne	.Lnon_zero
+	bdz	.Lzero
+
+	lbz	rA,2(r3)
+	lbz	rB,2(r4)
+	subf.	rC,rB,rA
+	bne	.Lnon_zero
+	bdz	.Lzero
+
+	lbz	rA,3(r3)
+	lbz	rB,3(r4)
+	subf.	rC,rB,rA
+	bne	.Lnon_zero
+
+	addi	r3,r3,4
+	addi	r4,r4,4
+
+	bdnzt	eq,1b
+
+.Lzero:
+	li	r3,0
+	blr
+
+.Lnon_zero:
+	mr	r3,rC
+	blr
+
+.Llong:
+	li	off8,8
+	li	off16,16
+	li	off24,24
+
+	std	r31,-8(r1)
+	std	r30,-16(r1)
+	std	r29,-24(r1)
+	std	r28,-32(r1)
+	std	r27,-40(r1)
+
+	srdi	r0,r5,5
+	mtctr	r0
+	andi.	r5,r5,31
+
+	LD	rA,0,r3
+	LD	rB,0,r4
+
+	LD	rC,off8,r3
+	LD	rD,off8,r4
+
+	LD	rE,off16,r3
+	LD	rF,off16,r4
+
+	LD	rG,off24,r3
+	LD	rH,off24,r4
+	cmpld	cr0,rA,rB
+
+	addi	r3,r3,32
+	addi	r4,r4,32
+
+	bdz	.Lfirst32
+
+	LD	rA,0,r3
+	LD	rB,0,r4
+	cmpld	cr1,rC,rD
+
+	LD	rC,off8,r3
+	LD	rD,off8,r4
+	cmpld	cr5,rE,rF
+
+	LD	rE,off16,r3
+	LD	rF,off16,r4
+	cmpld	cr6,rG,rH
+	bne	cr0,.LcmpAB
+
+	LD	rG,off24,r3
+	LD	rH,off24,r4
+	cmpld	cr0,rA,rB
+	bne	cr1,.LcmpCD
+
+	addi	r3,r3,32
+	addi	r4,r4,32
+
+	bdz	.Lsecond32
+
+	.balign	16
+
+1:	LD	rA,0,r3
+	LD	rB,0,r4
+	cmpld	cr1,rC,rD
+	bne	cr5,.LcmpEF
+
+	LD	rC,off8,r3
+	LD	rD,off8,r4
+	cmpld	cr5,rE,rF
+	bne	cr6,.LcmpGH
+
+	LD	rE,off16,r3
+	LD	rF,off16,r4
+	cmpld	cr6,rG,rH
+	bne	cr0,.LcmpAB
+
+	LD	rG,off24,r3
+	LD	rH,off24,r4
+	cmpld	cr0,rA,rB
+	bne	cr1,.LcmpCD
+
+	addi	r3,r3,32
+	addi	r4,r4,32
+
+	bdnz	1b
+
+.Lsecond32:
+	cmpld	cr1,rC,rD
+	bne	cr5,.LcmpEF
+
+	cmpld	cr5,rE,rF
+	bne	cr6,.LcmpGH
+
+	cmpld	cr6,rG,rH
+	bne	cr0,.LcmpAB
+
+	bne	cr1,.LcmpCD
+	bne	cr5,.LcmpEF
+	bne	cr6,.LcmpGH
+
+.Ltail:
+	ld	r31,-8(r1)
+	ld	r30,-16(r1)
+	ld	r29,-24(r1)
+	ld	r28,-32(r1)
+	ld	r27,-40(r1)
+
+	cmpdi	r5,0
+	beq	.Lzero
+	b	.Lshort
+
+.Lfirst32:
+	cmpld	cr1,rC,rD
+	cmpld	cr5,rE,rF
+	cmpld	cr6,rG,rH
+
+	bne	cr0,.LcmpAB
+	bne	cr1,.LcmpCD
+	bne	cr5,.LcmpEF
+	bne	cr6,.LcmpGH
+
+	b	.Ltail
+
+.LcmpAB:
+	li	r3,1
+	bgt	cr0,.Lout
+	li	r3,-1
+	b	.Lout
+
+.LcmpCD:
+	li	r3,1
+	bgt	cr1,.Lout
+	li	r3,-1
+	b	.Lout
+
+.LcmpEF:
+	li	r3,1
+	bgt	cr5,.Lout
+	li	r3,-1
+	b	.Lout
+
+.LcmpGH:
+	li	r3,1
+	bgt	cr6,.Lout
+	li	r3,-1
+
+.Lout:
+	ld	r31,-8(r1)
+	ld	r30,-16(r1)
+	ld	r29,-24(r1)
+	ld	r28,-32(r1)
+	ld	r27,-40(r1)
+	blr
diff --git a/arch/powerpc/lib/string.S b/arch/powerpc/lib/string.S
index 1b5a0a0..c80fb49 100644
--- a/arch/powerpc/lib/string.S
+++ b/arch/powerpc/lib/string.S
@@ -93,6 +93,7 @@ _GLOBAL(strlen)
 	subf	r3,r3,r4
 	blr
 
+#ifdef CONFIG_PPC32
 _GLOBAL(memcmp)
 	PPC_LCMPI 0,r5,0
 	beq-	2f
@@ -106,6 +107,7 @@ _GLOBAL(memcmp)
 	blr
 2:	li	r3,0
 	blr
+#endif
 
 _GLOBAL(memchr)
 	PPC_LCMPI 0,r5,0
-- 
2.1.0

^ permalink raw reply related


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox