Linux-ARM-Kernel Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v4 01/10] arm64: KVM: Use static keys for selecting the GIC backend
From: Vladimir Murzin @ 2016-09-14 15:20 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20160913092234.GA30056@cbox>

On 13/09/16 10:22, Christoffer Dall wrote:
> On Tue, Sep 13, 2016 at 10:11:10AM +0100, Marc Zyngier wrote:
>> On 13/09/16 09:20, Christoffer Dall wrote:
>>> On Mon, Sep 12, 2016 at 03:49:15PM +0100, Vladimir Murzin wrote:
>>>> Currently GIC backend is selected via alternative framework and this
>>>> is fine. We are going to introduce vgic-v3 to 32-bit world and there
>>>> we don't have patching framework in hand, so we can either check
>>>> support for GICv3 every time we need to choose which backend to use or
>>>> try to optimise it by using static keys. The later looks quite
>>>> promising because we can share logic involved in selecting GIC backend
>>>> between architectures if both uses static keys.
>>>>
>>>> This patch moves arm64 from alternative to static keys framework for
>>>> selecting GIC backend. For that we embed static key into vgic_global
>>>> and enable the key during vgic initialisation based on what has
>>>> already been exposed by the host GIC driver.
>>>>
>>>> Signed-off-by: Vladimir Murzin <vladimir.murzin@arm.com>
>>>> ---
>>>>  arch/arm64/kvm/hyp/switch.c   |   21 +++++++++++----------
>>>>  include/kvm/arm_vgic.h        |    4 ++++
>>>>  virt/kvm/arm/vgic/vgic-init.c |    4 ++++
>>>>  virt/kvm/arm/vgic/vgic.c      |    2 +-
>>>>  4 files changed, 20 insertions(+), 11 deletions(-)
>>>>
>>>> diff --git a/arch/arm64/kvm/hyp/switch.c b/arch/arm64/kvm/hyp/switch.c
>>>> index 5a84b45..d5c4cc5 100644
>>>> --- a/arch/arm64/kvm/hyp/switch.c
>>>> +++ b/arch/arm64/kvm/hyp/switch.c
>>>> @@ -16,6 +16,8 @@
>>>>   */
>>>>  
>>>>  #include <linux/types.h>
>>>> +#include <linux/jump_label.h>
>>>> +
>>>>  #include <asm/kvm_asm.h>
>>>>  #include <asm/kvm_hyp.h>
>>>>  
>>>> @@ -126,17 +128,13 @@ static void __hyp_text __deactivate_vm(struct kvm_vcpu *vcpu)
>>>>  	write_sysreg(0, vttbr_el2);
>>>>  }
>>>>  
>>>> -static hyp_alternate_select(__vgic_call_save_state,
>>>> -			    __vgic_v2_save_state, __vgic_v3_save_state,
>>>> -			    ARM64_HAS_SYSREG_GIC_CPUIF);
>>>> -
>>>> -static hyp_alternate_select(__vgic_call_restore_state,
>>>> -			    __vgic_v2_restore_state, __vgic_v3_restore_state,
>>>> -			    ARM64_HAS_SYSREG_GIC_CPUIF);
>>>> -
>>>>  static void __hyp_text __vgic_save_state(struct kvm_vcpu *vcpu)
>>>>  {
>>>> -	__vgic_call_save_state()(vcpu);
>>>> +	if (static_branch_unlikely(&kvm_vgic_global_state.gicv3_cpuif))
>>>
>>> It's a bit weird that we use _unlikely for GICv3 (at least if/when GICv3
>>> hardware becomes mainstream), but as we don't have another primitive for
>>> the 'default disabled' case, I suppose that's the best we can do.
>>
>> We could always revert the "likelihood" of that test once GICv3 has
>> conquered the world. Or start patching the 32bit kernel like we do for
>> 64bit...
>>
>>>
>>>> +		__vgic_v3_save_state(vcpu);
>>>> +	else
>>>> +		__vgic_v2_save_state(vcpu);
>>>> +
>>>>  	write_sysreg(read_sysreg(hcr_el2) & ~HCR_INT_OVERRIDE, hcr_el2);
>>>>  }
>>>>  
>>>> @@ -149,7 +147,10 @@ static void __hyp_text __vgic_restore_state(struct kvm_vcpu *vcpu)
>>>>  	val |= vcpu->arch.irq_lines;
>>>>  	write_sysreg(val, hcr_el2);
>>>>  
>>>> -	__vgic_call_restore_state()(vcpu);
>>>> +	if (static_branch_unlikely(&kvm_vgic_global_state.gicv3_cpuif))
>>>> +		__vgic_v3_restore_state(vcpu);
>>>> +	else
>>>> +		__vgic_v2_restore_state(vcpu);
>>>>  }
>>>>  
>>>>  static bool __hyp_text __true_value(void)
>>>> diff --git a/include/kvm/arm_vgic.h b/include/kvm/arm_vgic.h
>>>> index 19b698e..994665a 100644
>>>> --- a/include/kvm/arm_vgic.h
>>>> +++ b/include/kvm/arm_vgic.h
>>>> @@ -23,6 +23,7 @@
>>>>  #include <linux/types.h>
>>>>  #include <kvm/iodev.h>
>>>>  #include <linux/list.h>
>>>> +#include <linux/jump_label.h>
>>>>  
>>>>  #define VGIC_V3_MAX_CPUS	255
>>>>  #define VGIC_V2_MAX_CPUS	8
>>>> @@ -63,6 +64,9 @@ struct vgic_global {
>>>>  
>>>>  	/* Only needed for the legacy KVM_CREATE_IRQCHIP */
>>>>  	bool			can_emulate_gicv2;
>>>> +
>>>> +	/* GIC system register CPU interface */
>>>> +	struct static_key_false gicv3_cpuif;
>>>
>>> Documentation/static-keys.txt says that we are not supposed to use
>>> struct static_key_false directly.  This will obviously work quite
>>> nicely, but we could consider adding a pair of
>>> DECLARE_STATIC_KEY_TRUE/FALSE macros that don't have the assignments,
>>> but obviously this will need an ack from other maintainers.
>>>
>>> Thoughts?
>>
>> Grepping through the tree shows that we're not the only abusers of this
>> (dynamic debug is far worse!). Happy to write the additional macros and
>> submit them if nobody beats me to it.
>>
>>>
>>>
>>>>  };
>>>>  
>>>>  extern struct vgic_global kvm_vgic_global_state;
>>>> diff --git a/virt/kvm/arm/vgic/vgic-init.c b/virt/kvm/arm/vgic/vgic-init.c
>>>> index 83777c1..14d6718 100644
>>>> --- a/virt/kvm/arm/vgic/vgic-init.c
>>>> +++ b/virt/kvm/arm/vgic/vgic-init.c
>>>> @@ -405,6 +405,10 @@ int kvm_vgic_hyp_init(void)
>>>>  		break;
>>>>  	case GIC_V3:
>>>>  		ret = vgic_v3_probe(gic_kvm_info);
>>>> +		if (!ret) {
>>>> +			static_branch_enable(&kvm_vgic_global_state.gicv3_cpuif);
>>>> +			kvm_info("GIC system register CPU interface\n");
>>>
>>> nit: add enabled to the info message?
>>>
>>>> +		}
>>>>  		break;
>>>>  	default:
>>>>  		ret = -ENODEV;
>>>> diff --git a/virt/kvm/arm/vgic/vgic.c b/virt/kvm/arm/vgic/vgic.c
>>>> index e83b7fe..8a529a7 100644
>>>> --- a/virt/kvm/arm/vgic/vgic.c
>>>> +++ b/virt/kvm/arm/vgic/vgic.c
>>>> @@ -29,7 +29,7 @@
>>>>  #define DEBUG_SPINLOCK_BUG_ON(p)
>>>>  #endif
>>>>  
>>>> -struct vgic_global __section(.hyp.text) kvm_vgic_global_state;
>>>> +struct vgic_global __section(.hyp.text) kvm_vgic_global_state = {.gicv3_cpuif = STATIC_KEY_FALSE_INIT,};
>>>>  
>>>>  /*
>>>>   * Locking order is always:
>>>> -- 
>>>> 1.7.9.5
>>>>
>>>
>>> Overall this looks really nice, as long as we're clear on the static
>>> keys stuff.
>>
>> Indeed, we should get this sorted, though I'm not sure this should be a
>> blocker for this code.
>>
> Agreed, let's ship it!

To make it clear, should I respin with "enabled" into the info message
and macros for static keys?

Cheers
Vladimir

> -Christoffer
> 
> 

^ permalink raw reply

* [PATCH 2/2] dt-bindings: i2c-meson: add gxbb compatible string
From: Kevin Hilman @ 2016-09-14 15:19 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1473846557-18123-3-git-send-email-jbrunet@baylibre.com>

Jerome Brunet <jbrunet@baylibre.com> writes:

> From: Neil Armstrong <narmstrong@baylibre.com>
>
> Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
> Signed-off-by: Jerome Brunet <jbrunet@baylibre.com>

Acked-by: Kevin Hilman <khilman@baylibre.com>

> ---
>  Documentation/devicetree/bindings/i2c/i2c-meson.txt | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/Documentation/devicetree/bindings/i2c/i2c-meson.txt b/Documentation/devicetree/bindings/i2c/i2c-meson.txt
> index 682f9a6f766e..386357d1aab0 100644
> --- a/Documentation/devicetree/bindings/i2c/i2c-meson.txt
> +++ b/Documentation/devicetree/bindings/i2c/i2c-meson.txt
> @@ -1,7 +1,7 @@
>  Amlogic Meson I2C controller
>  
>  Required properties:
> - - compatible: must be "amlogic,meson6-i2c"
> + - compatible: must be "amlogic,meson6-i2c" or "amlogic,meson-gxbb-i2c"
>   - reg: physical address and length of the device registers
>   - interrupts: a single interrupt specifier
>   - clocks: clock for the device

^ permalink raw reply

* [PATCH 1/2] i2c: meson: add gxbb compatible string
From: Kevin Hilman @ 2016-09-14 15:19 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1473846557-18123-2-git-send-email-jbrunet@baylibre.com>

Jerome Brunet <jbrunet@baylibre.com> writes:

> From: Neil Armstrong <narmstrong@baylibre.com>
>
> Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
> Signed-off-by: Jerome Brunet <jbrunet@baylibre.com>

Acked-by: Kevin Hilman <khilman@baylibre.com>

> ---
>  drivers/i2c/busses/i2c-meson.c | 1 +
>  1 file changed, 1 insertion(+)
>
> diff --git a/drivers/i2c/busses/i2c-meson.c b/drivers/i2c/busses/i2c-meson.c
> index 76e28980904f..30977e31cd98 100644
> --- a/drivers/i2c/busses/i2c-meson.c
> +++ b/drivers/i2c/busses/i2c-meson.c
> @@ -473,6 +473,7 @@ static int meson_i2c_remove(struct platform_device *pdev)
>  
>  static const struct of_device_id meson_i2c_match[] = {
>  	{ .compatible = "amlogic,meson6-i2c" },
> +	{ .compatible = "amlogic,meson-gxbb-i2c" },
>  	{ },
>  };
>  MODULE_DEVICE_TABLE(of, meson_i2c_match);

^ permalink raw reply

* [PATCH] pintctrl: amlogic: gxbb: add i2c pins
From: Kevin Hilman @ 2016-09-14 15:18 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1473846328-17339-1-git-send-email-jbrunet@baylibre.com>

Jerome Brunet <jbrunet@baylibre.com> writes:

> Add EE domains pins for the i2c devices A,B,C
>
> Signed-off-by: Jerome Brunet <jbrunet@baylibre.com>

Acked-by: Kevin Hilman <khilman@baylibre.com>

^ permalink raw reply

* [GIT PULL] ARM: mvebu: dt64 for v4.9 (#1)
From: Arnd Bergmann @ 2016-09-14 15:17 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <87h99vzmhi.fsf@free-electrons.com>

On Sunday, September 4, 2016 5:57:29 PM CEST Gregory CLEMENT wrote:
> mvebu dt64 for 4.9 (part 1)
> 
> - add description for the new Armada 8040 dev board
> - add the PIC and PMU on Armada 7K/8K
> 
Pulled into next/dt64, thanks

	Arnd

^ permalink raw reply

* [RESEND][PATCH V7 0/5] perf: Driver specific configuration for PMU
From: Arnaldo Carvalho de Melo @ 2016-09-14 15:14 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <CANLsYkyqJvNUfJb4bMbUeNsSU+q+yK5W+RK+770TeUKuqQ2qOg@mail.gmail.com>

Em Wed, Sep 14, 2016 at 08:38:04AM -0600, Mathieu Poirier escreveu:
> On 13 September 2016 at 14:06, Arnaldo Carvalho de Melo <acme@kernel.org> wrote:
> > Em Tue, Sep 06, 2016 at 10:37:12AM -0600, Mathieu Poirier escreveu:
> >> Original blurb:
> >> ---------------
> >
> > So, I managed to apply "perf tools: add infrastructure for PMU specific
> > configuration", the first, as we discussed, needs splitting, some don't
> > apply due to the first not being applied, and one fails 'perf test
> > python', which I'll look at tomorrow.
> 
> I have a patchset where the first patch was split ready to go.  My
> plan was to wait for your comments but I can send it out right away if
> it makes it easier for you.  You can then make comments on that
> version if you need to - whichever makes your life easier.
> 
> What's this "perf test python" thing you're referring to?  With a
> little more information I can dig into it.

Well, just run:

  perf test

before sending any patches :-)

In this specific case, just run:

  perf test python

After a fresh build, and it should run that specific test, to see
details, use verbose mode:

  perf test -v python

What happened was that you added a call to a function that is not in the
list of objects linked for the python binding, that is at:

  tools/perf/util/python-ext-sources

Either we move this function to some file not in that list or if we drag
along what is needed to get the python binding without any missing
dependency.

I have to put together a tools/perf/Documentation/SubmittingPatches
file. :-\

There is also this:

  make -C tools/perf build-test

that I run before sending pull requests to Ingo, that can catch other
problems, and the usage of the docker build containers:

https://hub.docker.com/search/?q=acmel

But for now what would be really nice would be for you to do:

  perf test
  make -C tools/perf build-test

Before sending patchkits to me,

Thanks,

- Arnaldo
 
> Thanks,
> Mathieu
> 
> 
> >
> > - Arnaldo
> >
> >> This patchset adds the possiblity of specifying PMU driver configuration
> >> directly from the perf command line.  Anything that falls within the
> >> event specifiers '/.../' and that is preceded by the '@' symbol is
> >> treated as a configurable.  Two formats are supported, @cfg and
> >> @cfg=config.
> >>
> >> For example:
> >>
> >> perf record -e some_event/@cfg1/ ...
> >>
> >> or
> >>
> >> perf record -e some_event/@cfg2=config/ ...
> >>
> >> or
> >>
> >> perf record -e some_event/@cfg1, at cfg2=config/ ...
> >>
> >> The above are all valid configuration and will see the strings 'cfg1'
> >> and 'cfg2=config' sent to the PMU driver for parsing and interpretation
> >> using the existing ioctl() mechanism.
> >>
> >> The primary customers for this feature are the CoreSight drivers where
> >> the selection of a sink (where trace data is accumulated) needs to be
> >> done in a previous, and separated step, from the launching of the perf
> >> command.
> >>
> >> As such something that used to be a two-step process:
> >>
> >> # echo 1 > /sys/bus/coresight/devices/20070000.etr/enable_sink
> >> # perf record -e cs_etm//u --per-thread  uname
> >>
> >> is integrated in a single command:
> >>
> >> # perf record -e cs_etm/@20070000.etr/u --per-thread  uname
> >>
> >> Thanks,
> >> Mathieu
> >>
> >> Changes for V7:
> >> - Got rid of a miscellaneous debug message.
> >> - Rebased to v4.8-rc4
> >> - Added Jiri Olsa's Acked-by.
> >>
> >> Changes for V6:
> >> - Using sysFS rather than an ioctl() to communicate command line
> >>   parameters to the CoreSight PMU.
> >>
> >> Changes for V5:
> >> - Made commit log in 5/9 more descriptive.
> >> - Addressed missing return code in builtin-top.c.
> >> - Overhauled the kernel portion to do parsing in the core.
> >>
> >> Changes for V4:
> >> - Pushing PMU driver configuration for 'perf top'.
> >> - Rebased to the latest perf/core branch[1].
> >>
> >> Changes for V3:
> >> - Added comment for function drv_str() that explains the reason for
> >>   keeping the entire token intact.
> >> - Added driver config terms to the existing list of config terms.
> >> - Added documenation for driver specific configuration.
> >> - Pushing PMU driver configuration for 'perf stat' as well.
> >> - Preventing users from selecting a sink from sysFS _and_ perf.
> >>
> >> Changes for V2:
> >> - Rebased to [1] as per Jiri's request.
> >>
> >>
> >> Mathieu Poirier (5):
> >>   perf tools: making coresight PMU listable
> >>   perf tools: adding coresight etm PMU record capabilities
> >>   perf tools: add infrastructure for PMU specific configuration
> >>   perf tools: Pushing configuration down to PMU driver
> >>   perf tools: adding sink configuration for cs_etm PMU
> >>
> >>  MAINTAINERS                              |   5 +
> >>  tools/perf/Documentation/perf-record.txt |  12 +
> >>  tools/perf/Makefile.config               |  11 +-
> >>  tools/perf/arch/arm/util/Build           |   2 +
> >>  tools/perf/arch/arm/util/auxtrace.c      |  54 +++
> >>  tools/perf/arch/arm/util/cs-etm.c        | 615 +++++++++++++++++++++++++++++++
> >>  tools/perf/arch/arm/util/cs-etm.h        |  26 ++
> >>  tools/perf/arch/arm/util/pmu.c           |  37 ++
> >>  tools/perf/arch/arm64/util/Build         |   4 +
> >>  tools/perf/builtin-record.c              |   9 +
> >>  tools/perf/builtin-stat.c                |   8 +
> >>  tools/perf/builtin-top.c                 |  12 +
> >>  tools/perf/util/auxtrace.c               |   1 +
> >>  tools/perf/util/auxtrace.h               |   1 +
> >>  tools/perf/util/cs-etm.h                 |  74 ++++
> >>  tools/perf/util/evlist.c                 |  18 +
> >>  tools/perf/util/evlist.h                 |   3 +
> >>  tools/perf/util/evsel.c                  |  40 ++
> >>  tools/perf/util/evsel.h                  |   4 +
> >>  tools/perf/util/parse-events.c           |   7 +-
> >>  tools/perf/util/parse-events.h           |   1 +
> >>  tools/perf/util/parse-events.l           |  22 ++
> >>  tools/perf/util/parse-events.y           |  11 +
> >>  tools/perf/util/pmu.h                    |   2 +
> >>  24 files changed, 974 insertions(+), 5 deletions(-)
> >>  create mode 100644 tools/perf/arch/arm/util/auxtrace.c
> >>  create mode 100644 tools/perf/arch/arm/util/cs-etm.c
> >>  create mode 100644 tools/perf/arch/arm/util/cs-etm.h
> >>  create mode 100644 tools/perf/arch/arm/util/pmu.c
> >>  create mode 100644 tools/perf/util/cs-etm.h
> >>
> >> --
> >> 2.7.4

^ permalink raw reply

* [GIT PULL] Qualcomm ARM64 DT Updates for v4.9
From: Arnd Bergmann @ 2016-09-14 15:08 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1472875085-18017-1-git-send-email-andy.gross@linaro.org>

On Friday, September 2, 2016 10:58:05 PM CEST Andy Gross wrote:
> Qualcomm ARM64 Updates for v4.9
> 
> * Updates for MSM8916 including TSCR, SMSM/SMP2P, and MBA reserve
> * Update SCM node to denote being a reset-controller
> * Fix broken interrupt settings
> * Add TSENS nodes for MSM8916/MSM8996
> * Add DB820c support
> * Add MSM8916/APQ8016 display support
> 

Pulled into next/dt64, thanks!

	Arnd

^ permalink raw reply

* [GIT PULL] arm64: dts: hisilicon dts updates for v4.9
From: Arnd Bergmann @ 2016-09-14 15:06 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <57C95594.40105@hisilicon.com>

On Friday, September 2, 2016 11:33:56 AM CEST Wei Xu wrote:
> ARM64: DT: Hisilicon SoC DT updates for 4.9
> 
> - Set UART1 clock frequency to 150MHz for higher baud rates on hikey
> - Add display subsystem, HDMI and cma nodes on hikey to support display
> - Add syscon-reboot-mode support on hikey
> - Add pstore support on hikey
> - Add resets and sd-uhs-sdr property dwmmc ndoe on hikey
> - Remove hip05_hns.dtsi since it can not be built without mbigenv1
> - Update system controller bingding document for hip05 and hip06
> - Add xge and sas support on hip06
> 

Pulled into next/dt64, thanks!

	Arnd

^ permalink raw reply

* [PATCH V3 3/4] ARM64 LPC: support serial based on low-pin-count
From: zhichang.yuan @ 2016-09-14 15:04 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <4340181.AghlmQIy28@wuerfel>



On 2016/9/14 20:25, Arnd Bergmann wrote:
> On Wednesday, September 14, 2016 8:15:53 PM CEST Zhichang Yuan wrote:
>> From: "zhichang.yuan" <yuanzhichang@hisilicon.com>
>>
>> On Hip06 platform, a 16550 compatible UART is connected to low-pin-count and
>> controlled through the LPC I/O cycles. After registering the LPC uart specific
>> serial_in/serial_out to 8250 core driver, serial data can be read/written
>> through the LPC.
>>
>> Signed-off-by: zhichang.yuan <yuanzhichang@hisilicon.com>
>>
> 
> I still think this should be handled by 8250_of.c after the addition of
> support for IORESOURCE_IO.

The 8250_hisi_lpc.c support both ACPI and dts similar to 8250_dw :

+static struct platform_driver hs_lpc8250_driver = {
+	.driver = {
+		.name		= "hisi-lpc-uart",
+		.of_match_table	= hs8250_of_match,
+		.acpi_match_table = ACPI_PTR(hs8250_acpi_match),

So, I am a little confused why we need to support dts in 8250_of.c and support ACPI in another
driver file.

best,
Zhichang


> 
> 	Arnd
> 
> 
> .
> 

^ permalink raw reply

* [PATCH] of/platform: Initialise dev->fwnode appropriately
From: Robin Murphy @ 2016-09-14 15:01 UTC (permalink / raw)
  To: linux-arm-kernel

Whilst we're some of the way towards a universal firmware property
interface, drivers which deal with both OF and ACPI probing end up
having to do things like this:

    dev->of_node ? &dev->of_node->fwnode : dev->fwnode

This seems unnecessary, when the OF code could instead simply fill in
the device's fwnode when binding the of_node, and let the drivers use
dev->fwnode either way. Let's give it a go and see what falls out.

Signed-off-by: Robin Murphy <robin.murphy@arm.com>
---
 drivers/of/platform.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/of/platform.c b/drivers/of/platform.c
index f39ccd5aa701..f811d2796437 100644
--- a/drivers/of/platform.c
+++ b/drivers/of/platform.c
@@ -142,6 +142,7 @@ struct platform_device *of_device_alloc(struct device_node *np,
 	}
 
 	dev->dev.of_node = of_node_get(np);
+	dev->dev.fwnode = &np->fwnode;
 	dev->dev.parent = parent ? : &platform_bus;
 
 	if (bus_id)
@@ -241,6 +242,7 @@ static struct amba_device *of_amba_device_create(struct device_node *node,
 
 	/* setup generic device info */
 	dev->dev.of_node = of_node_get(node);
+	dev->dev.fwnode = &node->fwnode;
 	dev->dev.parent = parent ? : &platform_bus;
 	dev->dev.platform_data = platform_data;
 	if (bus_id)
-- 
2.8.1.dirty

^ permalink raw reply related

* [GIT PULL] arm64: X-Gene platforms DTS changes queued for 4.9 - part1
From: Arnd Bergmann @ 2016-09-14 14:59 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <CADaLNDkZdAipxx6cfLJ6yrzTrcLPS_Ciw8+T5EUFVcRRw+fjPw@mail.gmail.com>

On Friday, September 2, 2016 11:46:31 AM CEST Duc Dang wrote:
> Hi Arnd, Olof,
> 
> This is the first part of DTS changes for X-Gene platforms targeted for 4.9.
> 
> The changes include:
> + X-Gene Soc PMU support patch set from Tai Nguyen (v10 reviewed by
> Mark, DT binding document acked by Rob [1] and was suggested to merge
> via am-soc tree by Will [2])
> + Follow up patch to enable DT entry for SoC PMU on X-Gene v2
> + Correct PCIe legacy interrupt mode to level-active high
> + DTS entry for X-Gene hwmon (v4 acked by Guenter, DT binding document
> and driver is in linux-next now [3])
> 
> Regards,
> Duc Dang.

Sorry for the long delay, I've just now started looking at the dts changes
for arm64. The changes to arch/arm64/boot/dts look fine, but I don't
want to mix driver changes with dts changes, as we use separate
branches for those.

Please send this again as two pull requests, one for the dts changes, and
one for the rest (pmu driver, binding and MAINTAINERS file). Please
also include an explanation in the tag description about why this gets
merged through arm-soc. I see that Will suggested doing it that way,
but I don't see what the reason is. We normally don't touch that directory.

	Arnd

> 
> [1]: https://lkml.org/lkml/2016/7/15/563
> [2]: https://lkml.org/lkml/2016/7/20/224
> [3]: http://git.kernel.org/cgit/linux/kernel/git/next/linux-next.git/commit/?id=893485e74c37669aeecf0b648dbfbd8e2f0471c3
> ------
> 
> The following changes since commit 29b4817d4018df78086157ea3a55c1d9424a7cfc:
> 
>   Linux 4.8-rc1 (2016-08-07 18:18:00 -0700)
> 
> are available in the git repository at:
> 
>   https://github.com/AppliedMicro/xgene-next.git tags/xgene-dts-for-v4.9-part1
> 
> for you to fetch changes up to 1c983fc9369420748192712bde2429af3e580390:
> 
>   arm64: dts: apm: Add X-Gene SoC hwmon to device tree (2016-09-02
> 10:43:41 -0700)
> 
> ----------------------------------------------------------------
> X-Gene DTS changes queued for v4.9 - part 1
> 
> This patch set includes:
> + X-Gene v1 SoC Performance Monitoring Unit (PMU) support
> + DTS entry to enable SoC PMU for X-Gene v2 SoC
> + PCIe legacy interrupt polarity fix for X-Gene
> + X-Gene SoC hwmon DTS entry
> 

^ permalink raw reply

* [RESEND PATCH] arm64: kgdb: fix single stepping
From: Will Deacon @ 2016-09-14 14:58 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1429578793-3971-1-git-send-email-takahiro.akashi@linaro.org>

Hi Akashi,

On Tue, Apr 21, 2015 at 02:13:13AM +0100, AKASHI Takahiro wrote:
> Could you please review my patch below?
> See also arm64 maintainer's comment:
> http://lists.infradead.org/pipermail/linux-arm-kernel/2015-January/313712.html

-ETIMEDOUT waiting for the kdgb folk to comment. Ppeople have reported
that this patch is required for kgdb to work correctly on arm64, so I'm
happy to merge it.

However, as detailed in your comment log:

> This patch
> (1) moves kgdb_disable_single_step() from 'c' command handling to single
>     step handler.
>     This makes sure that single stepping gets effective at every 's' command.
>     Please note that, under the current implementation, single step bit in
>     spsr, which is cleared by the first single stepping, will not be set
>     again for the consecutive 's' commands because single step bit in mdscr
>     is still kept on (that is, kernel_active_single_step() in
>     kgdb_arch_handle_exception() is true).
> (2) re-implements kgdb_roundup_cpus() because the current implementation
>     enabled interrupts naively. See below.
> (3) removes 'enable_dbg' in el1_dbg.
>     Single step bit in mdscr is turned on in do_handle_exception()->
>     kgdb_handle_expection() before returning to debugged context, and if
>     debug exception is enabled in el1_dbg, we will see unexpected single-
>     stepping in el1_dbg.
>     Since v3.18, the following patch does the same:
>       commit 1059c6bf8534 ("arm64: debug: don't re-enable debug exceptions
>       on return from el1_dbg)
> (4) masks interrupts while single-stepping one instruction.
>     If an interrupt is caught during processing a single-stepping, debug
>     exception is unintentionally enabled by el1_irq's 'enable_dbg' before
>     returning to debugged context.
>     Thus, like in (2), we will see unexpected single-stepping in el1_irq.

this patch is doing *far* too much in one go. Could you please repost it
as a series of self-contained fixes with clear commit messages, so I can
queue them and cc stable where appropriate?

Thanks,

Will

^ permalink raw reply

* [PATCH v5 02/16] dt/bindings: Update binding for PM domain idle states
From: Lina Iyer @ 2016-09-14 14:55 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <87h99i6b5d.fsf@arm.com>

On Wed, Sep 14 2016 at 04:18 -0600, Brendan Jackman wrote:
>
>On Tue, Sep 13 2016 at 20:38, Lina Iyer wrote:
>> On Tue, Sep 13 2016 at 11:50 -0600, Brendan Jackman wrote:
>>>
>>>On Mon, Sep 12 2016 at 18:09, Sudeep Holla wrote:
>>>> On 12/09/16 17:16, Lina Iyer wrote:
>>>>> On Mon, Sep 12 2016 at 09:19 -0600, Brendan Jackman wrote:
>>>>>>
>>>>>> Hi Lina,
>>>>>>
>>>>>> Sorry for the delay here, Sudeep and I were both been on holiday last
>>>>>> week.
>>>>>>
>>>>>> On Fri, Sep 02 2016 at 21:16, Lina Iyer wrote:
>>>>>>> On Fri, Sep 02 2016 at 07:21 -0700, Sudeep Holla wrote:
>>>>>> [...]
>>>>>>>> This version is *not very descriptive*. Also the discussion we had
>>>>>>>> on v3
>>>>>>>> version has not yet concluded IMO. So can I take that we agreed on what
>>>>>>>> was proposed there or not ?
>>>>>>>>
>>>>>>> Sorry, this example is not very descriptive. Pls. check the 8916 dtsi
>>>>>>> for the new changes in the following patches. Let me know if that makes
>>>>>>> sense.
>>>>
>>>> Please add all possible use-cases in the bindings. Though one can refer
>>>> the usage examples, it might not cover all usage descriptions. It helps
>>>> preventing people from defining their own when they don't see examples.
>>>> Again DT bindings are like specifications, it should be descriptive
>>>> especially this kind of generic ones.
>>>>
>>>>>>
>>>>>> The not-yet-concluded discussion Sudeep is referring to is at [1].
>>>>>>
>>>>>> In that thread we initially proposed the idea of, instead of splitting
>>>>>> state phandles between cpu-idle-states and domain-idle-states, putting
>>>>>> CPUs in their own domains and using domain-idle-states for _all_
>>>>>> phandles, deprecating cpu-idle-states. I've brought this up in other
>>>>>> threads [2] but discussion keeps petering out, and neither this example
>>>>>> nor the 8916 dtsi in this patch series reflect the idea.
>>>>>>
>>>>> Brendan, while your idea is good and will work for CPUs, I do not expect
>>>>> other domains and possibly CPU domains on some architectures to follow
>>>>> this model. There is nothing that prevents you from doing this today,
>>>
>>>As I understand it your opposition to this approach is this:
>>>
>>>There may be devices/CPUs which have idle states which do not constitute
>>>"power off". If we put those  devices in their own power domain for the
>>>purpose of putting their (non-power-off) idle state phandles in
>>>domain-idle-states, we are "lying" because no true power domain exists
>>>there.
>>>
>>>Am I correct that that's your opposition?
>>>
>>>If so, it seems we essentially disagree on the definition of a power
>>>domain, i.e. you define it as a set of devices that are powered on/off
>>>together while I define it as a set of devices whose power states
>>>(including idle states, not just on/off) are tied together. I said
>>>something similar on another thread [1] which died out.
>>>
>>>Do you agree that this is basically where we disagree, or am I missing
>>>something else?
>>>
>>>[2] http://www.spinics.net/lists/devicetree/msg141050.html
>>>
>> Yes, you are right, I disagree with the definition of a domain around a
>> device.
>OK, great.
>> However, as long as you don't force SoC's to define devices in
>> the CPU PM domain to have their own virtual domains, I have no problem.
>> You are welcome to define it the way you want for Juno or any other
>> platform.
>I don't think that's true; the bindings have to work the same way for
>all platforms. If for Juno we put CPU idle state phandles in a
>domain-idle-states property for per-CPU domains then, with the current
>implementation, the CPU-level idle states would be duplicated between
>cpuidle and the CPU PM domains.

We don't have the code today. Your patches would add the functionality
of parsing domain idle states and attaching them to cpu-idle-states if
the firmware support and the mode is Platform-coordinated. And that
functionality is an easy addition. Nobody is making this change to
platforms with PC to use the CPU PM domains yet. 

What you are referring to is just a convergence PC and OSI to use
the same domain hierarchy. This definition is not impacted by your 
desire. I have my own doubts of defining PC domains this way, but I
would leave that to you to submit the relevant RFC and bring forth the
discussion. (Per DT, the definition of PC domain states is already
immutable from how it is defined today in DT. You have to be careful in
breaking it up.)

>> I don't want that to be the forced and expected out of all
>> SoCs. All I am saying here is that the current implementation would
>> handle your case as well.
>
>The current implementation certainly does cover the work I want to
>do. The suggestion of per-device power domains for devices/CPUs with
>their own idle states is simply intended to minimise the binding design,
>since we'd no longer need cpu-idle-states or device-idle-states
>(the latter was proposed elsewhere).
>
>I am fine with the bindings as they are implemented currently so long
>as:
>
>- The binding doc makes clear how idle state phandles should be split
>  between cpu-idle-states and domain-idle-states. It should make it
>  obvious that no phandle should ever appear in both properties. It
>  would even be worth briefly going over the backward-compatibility
>  implications (e.g. what happens with old-kernel/new-DT and
>  new-kernel/old-DT combos if a platform has OSI and PC support and we
>  move cluster-level idle state phandles out of cpu-idle-states and into
>  domai-idle-states).
>
Since, I have been only defining OSI initiated PM domains, this is not a
problem. I have clearly distinguished the explanation to be OSI
specific, for now.

>- We have a reason against the definition of power domains as "a set of
>  devices bound by a common power (including idle) state", since that
>  definition would simplify the bindings. In my view, "nobody thinks
>  that's what a power domain is" _is_ a compelling reason, so if others
>  on the list get involved I'm convinced. I think I speak for Sudeep
>  here too.
>

Look outside the context of the CPU - a generic PM domain is collective
of generic devices that share the same power island. A PM Domain may
also have other domains as sub-domains as well. So it is exactly that.
A CPU is just a specialized device.

Hope this helps.

Thanks,
Lina

^ permalink raw reply

* [GIT PULL 3/4] arm64: dts: exynos: DeviceTree ARM64 for v4.9
From: Arnd Bergmann @ 2016-09-14 14:52 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1472548739-20050-4-git-send-email-k.kozlowski@samsung.com>

On Tuesday, August 30, 2016 11:18:58 AM CEST Krzysztof Kozlowski wrote:
> This is an old one. It was ready for v4.8 but then Marc Zynger posted
> some conflicting change so I postponed it. Marc's patch didn't get in,
> so there is no reason to wait.
> 
> No conflict expected yet, but if you apply Marc's "arm64: dts: Fix
> broken architected timer interrupt trigger" then proper resolution would be:
> 
> arch/arm64/boot/dts/exynos/exynos7.dtsi:
> 
> +                       interrupts = <GIC_PPI 13
> +                                       (GIC_CPU_MASK_SIMPLE(8) | IRQ_TYPE_LEVEL_LOW)>,
> +                                    <GIC_PPI 14
> +                                       (GIC_CPU_MASK_SIMPLE(8) | IRQ_TYPE_LEVEL_LOW)>,
> +                                    <GIC_PPI 11
> +                                       (GIC_CPU_MASK_SIMPLE(8) | IRQ_TYPE_LEVEL_LOW)>,
> +                                    <GIC_PPI 10
> +                                       (GIC_CPU_MASK_SIMPLE(8) | IRQ_TYPE_LEVEL_LOW)>;
> 
> 
> Best regards,
> Krzysztof
> 
> The following changes since commit 29b4817d4018df78086157ea3a55c1d9424a7cfc:
> 
>   Linux 4.8-rc1 (2016-08-07 18:18:00 -0700)
> 
> are available in the git repository at:
> 
>   git://git.kernel.org/pub/scm/linux/kernel/git/krzk/linux.git tags/samsung-dt64-4.9
> 
> for you to fetch changes up to 36d1c9cd07cd6a065f1dde3cbbfe3a9867d693a4:
> 
>   arm64: dts: exynos: Use human-friendly symbols for timer interrupt flags (2016-08-10 11:09:46 +0200)
> 

Pulled into next/dt64, thanks!

	Arnd

^ permalink raw reply

* [PATCH V3 2/4] ARM64 LPC: LPC driver implementation on Hip06
From: zhichang.yuan @ 2016-09-14 14:50 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <5140357.dcW9ibtZJ6@wuerfel>



On 2016/9/14 20:33, Arnd Bergmann wrote:
> On Wednesday, September 14, 2016 8:15:52 PM CEST Zhichang Yuan wrote:
> 
>> +Required properties:
>> +- compatible: should be "hisilicon,low-pin-count"
>> +- #address-cells: must be 2 which stick to the ISA/EISA binding doc.
>> +- #size-cells: must be 1 which stick to the ISA/EISA binding doc.
>> +- reg: base address and length of the register set for the device.
>> +- ranges: define a 1:1 mapping between the I/O space of the child device and
>> +	  the parent.
> 
> Do we still need the "ranges" here? The property in your example seems
> wrong.

I think "ranges" is needed.
without this, of_translate_address --> __of_translate_address --> of_translate_one will fail when translating the child's IO resource.

> 
>> +	ranges = <0x01 0xe4 0x0 0xe4 0x1000>;
> 
> You translate I/O port 0x00e4 through 0x10e4 to CPU address 0x0e4?
The hip06 LPC is defined as isa type.
So, 0x01 0xe4 is the local IO address of 0xe4. With this ranges, 0xe4 of child will be 1:1 mapped as 0xe4.
It means no translation.

> 
>> +/**
>> + * hisilpc_children_map_sysio - setup the mapping between system Io and
>> + *			physical IO
>> + *
>> + * @child: the device whose IO is handling
>> + * @data: some device specific data. For ACPI device, should be NULL.
>> + *
>> + * Returns >=0 means the mapping is successfully created;
>> + * others mean some failures.
>> + */
>> +static int hisilpc_children_map_sysio(struct device * child, void * data)
>> +{
>> +	struct resource *iores;
>> +	unsigned long cpuio;
>> +	struct extio_ops *opsnode;
>> +	int ret;
>> +	struct hisilpc_dev *lpcdev;
>> +
>> +	if (!child || !child->parent)
>> +		return -EINVAL;
>> +
>> +	iores = platform_get_resource_byname(to_platform_device(child),
>> +					IORESOURCE_IO, "dev_io");
>> +	if (!iores)
>> +		return -ENODEV;
>> +
>> +	/*
>> +	 * can not use devm_kzalloc to allocate slab for child before its driver
>> +	 * start probing. Here allocate the slab with the name of parent.
>> +	 */
>> +	opsnode = devm_kzalloc(child->parent, sizeof(*opsnode), GFP_KERNEL);
>> +	if (!opsnode)
>> +		return -ENOMEM;
>> +
>> +	cpuio = data ? *((unsigned long *)data) : 0;
>> +
>> +	opsnode->start = iores->start;
>> +	opsnode->end = iores->end;
>> +	opsnode->ptoffset = cpuio ? (cpuio - iores->start) : 0;
>> +
>> +	dev_info(child, "map sys port[%lx - %lx] offset=0x%lx",
>> +				(unsigned long)iores->start,
>> +				(unsigned long)iores->end,
>> +				opsnode->ptoffset);
>> +
>> +	opsnode->pfin = hisilpc_comm_inb;
>> +	opsnode->pfout = hisilpc_comm_outb;
>> +
>> +	lpcdev = platform_get_drvdata(to_platform_device(child->parent));
>> +	opsnode->devpara = lpcdev;
>> +
>> +	/* only apply indirect-IO to ipmi child device */
> 
> I don't get this part. The bus driver should not care what its
> children are, just register and PIO ranges that the bus can handle
> in theory, i.e. from 0x000 to 0xfff.

Just as we discussed in V2, the legacy PIO range is specific to some device, such as for ipmi bt, 0xe4 - 0xe7 will be populated.
I don't want to occupy a larger PIO range in which only small part PIOs are used by our LPC. At this moment, two PIO ranges are using
through the device property configuration, 0xe4-0xe7, 0x2f8-0x2ff.
If we configure 0-0x1000 for the LPC to cover those two ranges, most PIO are wasted and other PIO device on other buses lose the chance to use the PIO below 0x1000.
Otherwise, PIO conflict will happen. So, My idea is only occupied the PIO ranges which are really needed for the children.

And there are probably multiple child devices under LPC, the global arm64_extio_ops only can cover one PIO range. It is fortunate only ipmi driver can not support I/O
operation registering, serial driver has serial_in/serial_out to be registered. So, only the PIO range for ipmi device is stored in arm64_extio_ops and the indirect-IO
works well for ipmi device.

If we think it is nearly no chance that LPC PIO range conflict with other buses, we can allocate 0xe4 - 0x2ff to LPC and store it to arm64_extio_ops. In this case,
the special processing for ipmi device is not needed.

Best,
Zhichang

> 
> 	Arnd
> 
> 
> .
> 

^ permalink raw reply

* [PATCH 1/1 v6] ARM: imx: Added perf functionality to mmdc driver
From: Frank Li @ 2016-09-14 14:48 UTC (permalink / raw)
  To: linux-arm-kernel

From: Zhengyu Shen <zhengyu.shen@nxp.com>

MMDC is a multi-mode DDR controller that supports DDR3/DDR3L x16/x32/x64
and LPDDR2 two channel x16/x32 memory types. MMDC is configurable, high
performance, and optimized. MMDC is present on i.MX6 Quad and i.MX6
QuadPlus devices, but this driver only supports i.MX6 Quad at the moment.
MMDC provides registers for performance counters which read via this
driver to help debug memory throughput and similar issues.

$ perf stat -a -e mmdc/busy-cycles/,mmdc/read-accesses/,mmdc/read-bytes/,mmdc/total-cycles/,mmdc/write-accesses/,mmdc/write-bytes/ dd if=/dev/zero of=/dev/null bs=1M count=5000
Performance counter stats for 'dd if=/dev/zero of=/dev/null bs=1M count=5000':

         898021787      mmdc/busy-cycles/
          14819600      mmdc/read-accesses/
            471.30 MB   mmdc/read-bytes/
        2815419216      mmdc/total-cycles/
          13367354      mmdc/write-accesses/
            427.76 MB   mmdc/write-bytes/

       5.334757334 seconds time elapsed

Signed-off-by: Zhengyu Shen <zhengyu.shen@nxp.com>
Signed-off-by: Frank Li <frank.li@nxp.com>
---
Changes from v5 to v6
    Improve group event error handle

Changes from v4 to v5
    Remove mmdc_pmu:irq
    remove static variable cpuhp_mmdc_pmu
    remove spin_lock
    check is_sampling_event(event)
    remove unnecessary cast
    use hw_perf_event::prev_count

Changes from v3 to v4:
    Tested and fixed crash relating to removing events with perf fuzzer
    Adjusted formatting
    Moved all perf event code under CONFIG_PERF_EVENTS
        Switched cpuhp_setup_state to cpuhp_setup_state_nocalls

Changes from v2 to v3:
    Use WARN_ONCE instead of returning generic error values
    Replace CPU Notifiers with newer state machine hotplug
    Added additional checks on event_init for grouping and sampling
    Remove useless mmdc_enable_profiling function
    Added comments
    Moved start index of events from 0x01 to 0x00
    Added a counter to pmu_mmdc to only stop hrtimer after all events are finished
    Replace readl_relaxed and writel_relaxed with readl and writel
    Removed duplicate update function
    Used devm_kasprintf when naming mmdcs probed

Changes from v1 to v2:
    Added cpumask and migration handling support to driver
    Validated event during event_init
    Added code to properly stop counters
    Used perf_invalid_context instead of perf_sw_context
    Added hrtimer to poll for overflow
    Added better description
    Added support for multiple mmdcs


 arch/arm/mach-imx/mmdc.c | 463 ++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 461 insertions(+), 2 deletions(-)

diff --git a/arch/arm/mach-imx/mmdc.c b/arch/arm/mach-imx/mmdc.c
index db9621c..bd53b8e 100644
--- a/arch/arm/mach-imx/mmdc.c
+++ b/arch/arm/mach-imx/mmdc.c
@@ -1,5 +1,5 @@
 /*
- * Copyright 2011 Freescale Semiconductor, Inc.
+ * Copyright 2011,2016 Freescale Semiconductor, Inc.
  * Copyright 2011 Linaro Ltd.
  *
  * The code contained herein is licensed under the GNU General Public
@@ -10,12 +10,16 @@
  * http://www.gnu.org/copyleft/gpl.html
  */
 
+#include <linux/hrtimer.h>
 #include <linux/init.h>
+#include <linux/interrupt.h>
 #include <linux/io.h>
 #include <linux/module.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
 #include <linux/of_device.h>
+#include <linux/perf_event.h>
+#include <linux/slab.h>
 
 #include "common.h"
 
@@ -27,8 +31,462 @@
 #define BM_MMDC_MDMISC_DDR_TYPE	0x18
 #define BP_MMDC_MDMISC_DDR_TYPE	0x3
 
+#define TOTAL_CYCLES		0x0
+#define BUSY_CYCLES		0x1
+#define READ_ACCESSES		0x2
+#define WRITE_ACCESSES		0x3
+#define READ_BYTES		0x4
+#define WRITE_BYTES		0x5
+
+/* Enables, resets, freezes, overflow profiling*/
+#define DBG_DIS			0x0
+#define DBG_EN			0x1
+#define DBG_RST			0x2
+#define PRF_FRZ			0x4
+#define CYC_OVF			0x8
+
+#define MMDC_MADPCR0	0x410
+#define MMDC_MADPSR0	0x418
+#define MMDC_MADPSR1	0x41C
+#define MMDC_MADPSR2	0x420
+#define MMDC_MADPSR3	0x424
+#define MMDC_MADPSR4	0x428
+#define MMDC_MADPSR5	0x42C
+
+#define MMDC_NUM_COUNTERS	6
+
+#define to_mmdc_pmu(p) container_of(p, struct mmdc_pmu, pmu)
+
 static int ddr_type;
 
+#ifdef CONFIG_PERF_EVENTS
+
+static DEFINE_IDA(mmdc_ida);
+
+PMU_EVENT_ATTR_STRING(total-cycles, mmdc_total_cycles, "event=0x00")
+PMU_EVENT_ATTR_STRING(busy-cycles, mmdc_busy_cycles, "event=0x01")
+PMU_EVENT_ATTR_STRING(read-accesses, mmdc_read_accesses, "event=0x02")
+PMU_EVENT_ATTR_STRING(write-accesses, mmdc_write_accesses, "config=0x03")
+PMU_EVENT_ATTR_STRING(read-bytes, mmdc_read_bytes, "event=0x04")
+PMU_EVENT_ATTR_STRING(read-bytes.unit, mmdc_read_bytes_unit, "MB");
+PMU_EVENT_ATTR_STRING(read-bytes.scale, mmdc_read_bytes_scale, "0.000001");
+PMU_EVENT_ATTR_STRING(write-bytes, mmdc_write_bytes, "event=0x05")
+PMU_EVENT_ATTR_STRING(write-bytes.unit, mmdc_write_bytes_unit, "MB");
+PMU_EVENT_ATTR_STRING(write-bytes.scale, mmdc_write_bytes_scale, "0.000001");
+
+struct mmdc_pmu {
+	struct pmu pmu;
+	void __iomem *mmdc_base;
+	cpumask_t cpu;
+	struct hrtimer hrtimer;
+	unsigned int active_events;
+	struct device *dev;
+	struct perf_event *mmdc_events[MMDC_NUM_COUNTERS];
+	struct hlist_node node;
+};
+
+static struct mmdc_pmu *cpuhp_mmdc_pmu;
+
+/*
+ * Polling period is set to one second, overflow of total-cycles (the fastest
+ * increasing counter) takes ten seconds so one second is safe
+ */
+static unsigned int mmdc_poll_period_us = 1000000;
+
+module_param_named(pmu_poll_period_us, mmdc_poll_period_us, uint,
+		S_IRUGO | S_IWUSR);
+
+static ktime_t mmdc_timer_period(void)
+{
+	return ns_to_ktime((u64)mmdc_poll_period_us * 1000);
+}
+
+static ssize_t mmdc_cpumask_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct mmdc_pmu *pmu_mmdc = dev_get_drvdata(dev);
+
+	return cpumap_print_to_pagebuf(true, buf, &pmu_mmdc->cpu);
+}
+
+static struct device_attribute mmdc_cpumask_attr =
+__ATTR(cpumask, S_IRUGO, mmdc_cpumask_show, NULL);
+
+static struct attribute *mmdc_cpumask_attrs[] = {
+	&mmdc_cpumask_attr.attr,
+	NULL,
+};
+
+static struct attribute_group mmdc_cpumask_attr_group = {
+	.attrs = mmdc_cpumask_attrs,
+};
+
+static struct attribute *mmdc_events_attrs[] = {
+	&mmdc_total_cycles.attr.attr,
+	&mmdc_busy_cycles.attr.attr,
+	&mmdc_read_accesses.attr.attr,
+	&mmdc_write_accesses.attr.attr,
+	&mmdc_read_bytes.attr.attr,
+	&mmdc_read_bytes_unit.attr.attr,
+	&mmdc_read_bytes_scale.attr.attr,
+	&mmdc_write_bytes.attr.attr,
+	&mmdc_write_bytes_unit.attr.attr,
+	&mmdc_write_bytes_scale.attr.attr,
+	NULL,
+};
+
+static struct attribute_group mmdc_events_attr_group = {
+	.name = "events",
+	.attrs = mmdc_events_attrs,
+};
+
+PMU_FORMAT_ATTR(event, "config:0-63");
+static struct attribute *mmdc_format_attrs[] = {
+	&format_attr_event.attr,
+	NULL,
+};
+
+static struct attribute_group mmdc_format_attr_group = {
+	.name = "format",
+	.attrs = mmdc_format_attrs,
+};
+
+static const struct attribute_group *attr_groups[] = {
+	&mmdc_events_attr_group,
+	&mmdc_format_attr_group,
+	&mmdc_cpumask_attr_group,
+	NULL,
+};
+
+static u32 mmdc_read_counter(struct mmdc_pmu *pmu_mmdc, int cfg)
+{
+	void __iomem *mmdc_base, *reg;
+
+	mmdc_base = pmu_mmdc->mmdc_base;
+
+	switch (cfg) {
+	case TOTAL_CYCLES:
+		reg = mmdc_base + MMDC_MADPSR0;
+		break;
+	case BUSY_CYCLES:
+		reg = mmdc_base + MMDC_MADPSR1;
+		break;
+	case READ_ACCESSES:
+		reg = mmdc_base + MMDC_MADPSR2;
+		break;
+	case WRITE_ACCESSES:
+		reg = mmdc_base + MMDC_MADPSR3;
+		break;
+	case READ_BYTES:
+		reg = mmdc_base + MMDC_MADPSR4;
+		break;
+	case WRITE_BYTES:
+		reg = mmdc_base + MMDC_MADPSR5;
+		break;
+	default:
+		return WARN_ONCE(1,
+			"invalid configuration %d for mmdc counter", cfg);
+	}
+	return readl(reg);
+}
+
+static int mmdc_pmu_offline_cpu(unsigned int cpu, struct hlist_node *node)
+{
+	struct mmdc_pmu *pmu_mmdc = hlist_entry_safe(node, struct mmdc_pmu, node);
+	int target;
+
+	if (!cpumask_test_and_clear_cpu(cpu, &pmu_mmdc->cpu))
+		return 0;
+
+	target = cpumask_any_but(cpu_online_mask, cpu);
+	if (target >= nr_cpu_ids)
+		return 0;
+
+	perf_pmu_migrate_context(&pmu_mmdc->pmu, cpu, target);
+	cpumask_set_cpu(target, &pmu_mmdc->cpu);
+
+	return 0;
+}
+
+static bool mmdc_pmu_group_is_valid(struct perf_event *event)
+{
+	struct pmu *pmu = event->pmu;
+	struct perf_event *leader = event->group_leader;
+	struct perf_event *sibling;
+
+	int cfg = leader->attr.config;
+	int counter_mask = 0;
+
+	if (cfg < 0 || cfg >= MMDC_NUM_COUNTERS)
+		return false;
+
+	if (leader->pmu == pmu)
+		counter_mask |= 1 << cfg;
+	else if (!is_software_event(leader))
+		return false;
+
+	list_for_each_entry(sibling, &leader->sibling_list, group_entry) {
+		if (sibling->pmu == pmu) {
+			cfg = sibling->attr.config;
+			if (cfg < 0 || cfg >= MMDC_NUM_COUNTERS)
+				return false;
+			counter_mask |= 1 << cfg;
+		} else if (!is_software_event(sibling)) {
+			return false;
+		}
+	}
+
+	if (event == leader)
+		return true;
+
+	cfg = event->attr.config;
+	if (cfg < 0 || cfg >= MMDC_NUM_COUNTERS)
+		return false;
+
+	return !(counter_mask & (1 << cfg));
+}
+
+static int mmdc_event_init(struct perf_event *event)
+{
+	struct mmdc_pmu *pmu_mmdc = to_mmdc_pmu(event->pmu);
+	int cfg = event->attr.config;
+
+	if (event->attr.type != event->pmu->type)
+		return -ENOENT;
+
+	if (is_sampling_event(event) || event->attach_state & PERF_ATTACH_TASK)
+		return -EOPNOTSUPP;
+
+	if (event->cpu < 0) {
+		dev_warn(pmu_mmdc->dev, "Can't provide per-task data!\n");
+		return -EOPNOTSUPP;
+	}
+
+	if (event->attr.exclude_user		||
+			event->attr.exclude_kernel	||
+			event->attr.exclude_hv		||
+			event->attr.exclude_idle	||
+			event->attr.exclude_host	||
+			event->attr.exclude_guest	||
+			event->attr.sample_period)
+		return -EINVAL;
+
+	if (cfg < 0 || cfg >= MMDC_NUM_COUNTERS)
+		return -EINVAL;
+
+	if (!mmdc_pmu_group_is_valid(event))
+		return -EINVAL;
+
+	event->cpu = cpumask_first(&pmu_mmdc->cpu);
+	return 0;
+}
+
+static void mmdc_event_update(struct perf_event *event)
+{
+	struct mmdc_pmu *pmu_mmdc = to_mmdc_pmu(event->pmu);
+	struct hw_perf_event *hwc = &event->hw;
+	u64 delta, prev_raw_count, new_raw_count;
+
+	do {
+		prev_raw_count = local64_read(&hwc->prev_count);
+		new_raw_count = mmdc_read_counter(pmu_mmdc,
+						  event->attr.config);
+	} while (local64_cmpxchg(&hwc->prev_count, prev_raw_count,
+		new_raw_count) != prev_raw_count);
+
+	delta = (new_raw_count - prev_raw_count) & 0xFFFFFFFF;
+
+	local64_add(delta, &event->count);
+}
+
+static void mmdc_event_start(struct perf_event *event, int flags)
+{
+	struct mmdc_pmu *pmu_mmdc = to_mmdc_pmu(event->pmu);
+	struct hw_perf_event *hwc = &event->hw;
+	void __iomem *mmdc_base, *reg;
+
+	mmdc_base = pmu_mmdc->mmdc_base;
+	reg = mmdc_base + MMDC_MADPCR0;
+
+	/*
+	 * hrtimer is required because mmdc does not provide an interrupt so
+	 * polling is necessary
+	 */
+	hrtimer_start(&pmu_mmdc->hrtimer, mmdc_timer_period(),
+			HRTIMER_MODE_REL_PINNED);
+
+	local64_set(&hwc->prev_count, 0);
+
+	writel(DBG_RST, reg);
+	writel(DBG_EN, reg);
+}
+
+static int mmdc_event_add(struct perf_event *event, int flags)
+{
+	struct mmdc_pmu *pmu_mmdc = to_mmdc_pmu(event->pmu);
+	struct hw_perf_event *hwc = &event->hw;
+
+	int cfg = event->attr.config;
+
+	if (WARN_ONCE((cfg < 0 || cfg >= MMDC_NUM_COUNTERS),
+				"invalid configuration %d for mmdc", cfg))
+		return -1;
+
+	if (flags & PERF_EF_START)
+		mmdc_event_start(event, flags);
+
+	pmu_mmdc->mmdc_events[cfg] = event;
+	pmu_mmdc->active_events++;
+
+	local64_set(&hwc->prev_count, mmdc_read_counter(pmu_mmdc, cfg));
+
+	return 0;
+}
+
+static void mmdc_event_stop(struct perf_event *event, int flags)
+{
+	struct mmdc_pmu *pmu_mmdc = to_mmdc_pmu(event->pmu);
+	void __iomem *mmdc_base, *reg;
+	int cfg = (int)event->attr.config;
+
+	mmdc_base = pmu_mmdc->mmdc_base;
+	reg = mmdc_base + MMDC_MADPCR0;
+
+	if (WARN_ONCE((cfg < 0 || cfg >= MMDC_NUM_COUNTERS),
+				"invalid configuration %d for mmdc counter", cfg))
+		return;
+
+	writel(PRF_FRZ, reg);
+	mmdc_event_update(event);
+}
+
+static void mmdc_event_del(struct perf_event *event, int flags)
+{
+	struct mmdc_pmu *pmu_mmdc = to_mmdc_pmu(event->pmu);
+	int cfg = event->attr.config;
+
+	pmu_mmdc->mmdc_events[cfg] = NULL;
+	pmu_mmdc->active_events--;
+
+	if (pmu_mmdc->active_events <= 0)
+		hrtimer_cancel(&pmu_mmdc->hrtimer);
+
+	mmdc_event_stop(event, PERF_EF_UPDATE);
+}
+
+static void mmdc_overflow_handler(struct mmdc_pmu *pmu_mmdc)
+{
+	int i;
+
+	for (i = 0; i < MMDC_NUM_COUNTERS; i++) {
+		struct perf_event *event = pmu_mmdc->mmdc_events[i];
+
+		if (event)
+			mmdc_event_update(event);
+	}
+}
+
+static enum hrtimer_restart mmdc_timer_handler(struct hrtimer *hrtimer)
+{
+	struct mmdc_pmu *pmu_mmdc = container_of(hrtimer, struct mmdc_pmu,
+			hrtimer);
+
+	mmdc_overflow_handler(pmu_mmdc);
+	hrtimer_forward_now(hrtimer, mmdc_timer_period());
+
+	return HRTIMER_RESTART;
+}
+
+static int mmdc_pmu_init(struct mmdc_pmu *pmu_mmdc,
+		void __iomem *mmdc_base, struct device *dev)
+{
+	int mmdc_num;
+
+	*pmu_mmdc = (struct mmdc_pmu) {
+		.pmu = (struct pmu) {
+			.task_ctx_nr    = perf_invalid_context,
+			.attr_groups    = attr_groups,
+			.event_init     = mmdc_event_init,
+			.add            = mmdc_event_add,
+			.del            = mmdc_event_del,
+			.start          = mmdc_event_start,
+			.stop           = mmdc_event_stop,
+			.read           = mmdc_event_update,
+		},
+		.mmdc_base = mmdc_base,
+		.dev = dev,
+		.active_events = 0,
+	};
+
+	mmdc_num = ida_simple_get(&mmdc_ida, 0, 0, GFP_KERNEL);
+
+	return mmdc_num;
+}
+
+static int imx_mmdc_remove(struct platform_device *pdev)
+{
+	struct mmdc_pmu *pmu_mmdc = platform_get_drvdata(pdev);
+
+	perf_pmu_unregister(&pmu_mmdc->pmu);
+	cpuhp_remove_state_nocalls(CPUHP_ONLINE);
+	cpuhp_mmdc_pmu = NULL;
+	kfree(pmu_mmdc);
+	return 0;
+}
+
+static int imx_mmdc_perf_init(struct platform_device *pdev, void __iomem *mmdc_base)
+{
+	struct mmdc_pmu *pmu_mmdc;
+	char *name;
+	int mmdc_num;
+	int ret;
+
+	pmu_mmdc = kzalloc(sizeof(*pmu_mmdc), GFP_KERNEL);
+	if (!pmu_mmdc) {
+		pr_err("failed to allocate PMU device!\n");
+		return -ENOMEM;
+	}
+
+	mmdc_num = mmdc_pmu_init(pmu_mmdc, mmdc_base, &pdev->dev);
+	if (mmdc_num == 0)
+		name = "mmdc";
+	else
+		name = devm_kasprintf(&pdev->dev,
+				GFP_KERNEL, "mmdc%d", mmdc_num);
+
+	hrtimer_init(&pmu_mmdc->hrtimer, CLOCK_MONOTONIC,
+			HRTIMER_MODE_REL);
+	pmu_mmdc->hrtimer.function = mmdc_timer_handler;
+
+	cpuhp_state_add_instance_nocalls(CPUHP_ONLINE,
+					 &pmu_mmdc->node);
+	cpumask_set_cpu(smp_processor_id(), &pmu_mmdc->cpu);
+	ret = cpuhp_setup_state_multi(CPUHP_AP_NOTIFY_ONLINE,
+				      "MMDC_ONLINE", NULL,
+				      mmdc_pmu_offline_cpu);
+	if (ret) {
+		pr_err("cpuhp_setup_state_multi failure\n");
+		goto pmu_register_err;
+	}
+
+	ret = perf_pmu_register(&(pmu_mmdc->pmu), name, -1);
+	platform_set_drvdata(pdev, pmu_mmdc);
+	if (ret)
+		goto pmu_register_err;
+	return 0;
+
+pmu_register_err:
+	pr_warn("MMDC Perf PMU failed (%d), disabled\n", ret);
+	hrtimer_cancel(&pmu_mmdc->hrtimer);
+	kfree(pmu_mmdc);
+	return ret;
+}
+
+#else
+#define imx_mmdc_remove NULL
+#define imx_mmdc_perf_init(pdev, mmdc_base) 0
+#endif
+
 static int imx_mmdc_probe(struct platform_device *pdev)
 {
 	struct device_node *np = pdev->dev.of_node;
@@ -62,7 +520,7 @@ static int imx_mmdc_probe(struct platform_device *pdev)
 		return -EBUSY;
 	}
 
-	return 0;
+	return imx_mmdc_perf_init(pdev, mmdc_base);
 }
 
 int imx_mmdc_get_ddr_type(void)
@@ -81,6 +539,7 @@ static struct platform_driver imx_mmdc_driver = {
 		.of_match_table = imx_mmdc_dt_ids,
 	},
 	.probe		= imx_mmdc_probe,
+	.remove		= imx_mmdc_remove,
 };
 
 static int __init imx_mmdc_init(void)
-- 
2.5.2

^ permalink raw reply related

* [PATCH 4/4] ARM: orion5x: remove extraneous NO_IRQ
From: Gregory CLEMENT @ 2016-09-14 14:38 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20160906140623.2853066-4-arnd@arndb.de>

Hi Arnd,
 
 On mar., sept. 06 2016, Arnd Bergmann <arnd@arndb.de> wrote:

> rd88f6183ap-ge passes NO_IRQ as the interrupt line for its m25p80
> NOR flash. However, this device never uses an interrupt and the
> driver doesn't care, so we can simply remove the deprecated constant
> here.
>
> Signed-off-by: Arnd Bergmann <arnd@arndb.de>

Applied on mvebu/soc with Reviewed-by tag from Andrew Lunn

Thanks,

Gregory

> ---
>  arch/arm/mach-orion5x/rd88f6183ap-ge-setup.c | 1 -
>  1 file changed, 1 deletion(-)
>
> diff --git a/arch/arm/mach-orion5x/rd88f6183ap-ge-setup.c b/arch/arm/mach-orion5x/rd88f6183ap-ge-setup.c
> index 4bf80dd5478c..8ffaead76771 100644
> --- a/arch/arm/mach-orion5x/rd88f6183ap-ge-setup.c
> +++ b/arch/arm/mach-orion5x/rd88f6183ap-ge-setup.c
> @@ -71,7 +71,6 @@ static struct spi_board_info __initdata rd88f6183ap_ge_spi_slave_info[] = {
>  	{
>  		.modalias	= "m25p80",
>  		.platform_data	= &rd88f6183ap_ge_spi_slave_data,
> -		.irq		= NO_IRQ,
>  		.max_speed_hz	= 20000000,
>  		.bus_num	= 0,
>  		.chip_select	= 0,
> -- 
> 2.9.0
>

-- 
Gregory Clement, Free Electrons
Kernel, drivers, real-time and embedded Linux
development, consulting, training and support.
http://free-electrons.com

^ permalink raw reply

* [RESEND][PATCH V7 0/5] perf: Driver specific configuration for PMU
From: Mathieu Poirier @ 2016-09-14 14:38 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20160913200614.GB10582@kernel.org>

On 13 September 2016 at 14:06, Arnaldo Carvalho de Melo <acme@kernel.org> wrote:
> Em Tue, Sep 06, 2016 at 10:37:12AM -0600, Mathieu Poirier escreveu:
>> Original blurb:
>> ---------------
>
> So, I managed to apply "perf tools: add infrastructure for PMU specific
> configuration", the first, as we discussed, needs splitting, some don't
> apply due to the first not being applied, and one fails 'perf test
> python', which I'll look at tomorrow.

I have a patchset where the first patch was split ready to go.  My
plan was to wait for your comments but I can send it out right away if
it makes it easier for you.  You can then make comments on that
version if you need to - whichever makes your life easier.

What's this "perf test python" thing you're referring to?  With a
little more information I can dig into it.

Thanks,
Mathieu


>
> - Arnaldo
>
>> This patchset adds the possiblity of specifying PMU driver configuration
>> directly from the perf command line.  Anything that falls within the
>> event specifiers '/.../' and that is preceded by the '@' symbol is
>> treated as a configurable.  Two formats are supported, @cfg and
>> @cfg=config.
>>
>> For example:
>>
>> perf record -e some_event/@cfg1/ ...
>>
>> or
>>
>> perf record -e some_event/@cfg2=config/ ...
>>
>> or
>>
>> perf record -e some_event/@cfg1, at cfg2=config/ ...
>>
>> The above are all valid configuration and will see the strings 'cfg1'
>> and 'cfg2=config' sent to the PMU driver for parsing and interpretation
>> using the existing ioctl() mechanism.
>>
>> The primary customers for this feature are the CoreSight drivers where
>> the selection of a sink (where trace data is accumulated) needs to be
>> done in a previous, and separated step, from the launching of the perf
>> command.
>>
>> As such something that used to be a two-step process:
>>
>> # echo 1 > /sys/bus/coresight/devices/20070000.etr/enable_sink
>> # perf record -e cs_etm//u --per-thread  uname
>>
>> is integrated in a single command:
>>
>> # perf record -e cs_etm/@20070000.etr/u --per-thread  uname
>>
>> Thanks,
>> Mathieu
>>
>> Changes for V7:
>> - Got rid of a miscellaneous debug message.
>> - Rebased to v4.8-rc4
>> - Added Jiri Olsa's Acked-by.
>>
>> Changes for V6:
>> - Using sysFS rather than an ioctl() to communicate command line
>>   parameters to the CoreSight PMU.
>>
>> Changes for V5:
>> - Made commit log in 5/9 more descriptive.
>> - Addressed missing return code in builtin-top.c.
>> - Overhauled the kernel portion to do parsing in the core.
>>
>> Changes for V4:
>> - Pushing PMU driver configuration for 'perf top'.
>> - Rebased to the latest perf/core branch[1].
>>
>> Changes for V3:
>> - Added comment for function drv_str() that explains the reason for
>>   keeping the entire token intact.
>> - Added driver config terms to the existing list of config terms.
>> - Added documenation for driver specific configuration.
>> - Pushing PMU driver configuration for 'perf stat' as well.
>> - Preventing users from selecting a sink from sysFS _and_ perf.
>>
>> Changes for V2:
>> - Rebased to [1] as per Jiri's request.
>>
>>
>> Mathieu Poirier (5):
>>   perf tools: making coresight PMU listable
>>   perf tools: adding coresight etm PMU record capabilities
>>   perf tools: add infrastructure for PMU specific configuration
>>   perf tools: Pushing configuration down to PMU driver
>>   perf tools: adding sink configuration for cs_etm PMU
>>
>>  MAINTAINERS                              |   5 +
>>  tools/perf/Documentation/perf-record.txt |  12 +
>>  tools/perf/Makefile.config               |  11 +-
>>  tools/perf/arch/arm/util/Build           |   2 +
>>  tools/perf/arch/arm/util/auxtrace.c      |  54 +++
>>  tools/perf/arch/arm/util/cs-etm.c        | 615 +++++++++++++++++++++++++++++++
>>  tools/perf/arch/arm/util/cs-etm.h        |  26 ++
>>  tools/perf/arch/arm/util/pmu.c           |  37 ++
>>  tools/perf/arch/arm64/util/Build         |   4 +
>>  tools/perf/builtin-record.c              |   9 +
>>  tools/perf/builtin-stat.c                |   8 +
>>  tools/perf/builtin-top.c                 |  12 +
>>  tools/perf/util/auxtrace.c               |   1 +
>>  tools/perf/util/auxtrace.h               |   1 +
>>  tools/perf/util/cs-etm.h                 |  74 ++++
>>  tools/perf/util/evlist.c                 |  18 +
>>  tools/perf/util/evlist.h                 |   3 +
>>  tools/perf/util/evsel.c                  |  40 ++
>>  tools/perf/util/evsel.h                  |   4 +
>>  tools/perf/util/parse-events.c           |   7 +-
>>  tools/perf/util/parse-events.h           |   1 +
>>  tools/perf/util/parse-events.l           |  22 ++
>>  tools/perf/util/parse-events.y           |  11 +
>>  tools/perf/util/pmu.h                    |   2 +
>>  24 files changed, 974 insertions(+), 5 deletions(-)
>>  create mode 100644 tools/perf/arch/arm/util/auxtrace.c
>>  create mode 100644 tools/perf/arch/arm/util/cs-etm.c
>>  create mode 100644 tools/perf/arch/arm/util/cs-etm.h
>>  create mode 100644 tools/perf/arch/arm/util/pmu.c
>>  create mode 100644 tools/perf/util/cs-etm.h
>>
>> --
>> 2.7.4

^ permalink raw reply

* [PATCH 3/4] ARM: orion5x: avoid NO_IRQ in orion_ge00_switch_init
From: Gregory CLEMENT @ 2016-09-14 14:37 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <3683516.te4PblbMyt@wuerfel>

Hi Arnd,
 
 On jeu., sept. 08 2016, Arnd Bergmann <arnd@arndb.de> wrote:

> On Wednesday, September 7, 2016 4:03:16 AM CEST Andrew Lunn wrote:
>> On Tue, Sep 06, 2016 at 04:06:22PM +0200, Arnd Bergmann wrote:
>> > As of commit 5be9fc23cdb4 ("ARM: orion5x: fix legacy orion5x IRQ numbers"),
>> > IRQ zero is no longer a valid interrupt on Orion5x, so we can use the
>> > normal convention of using '0' to indicate an invalid interrupt, rather
>> > than the deprecated NO_IRQ constant
>> > 
>> > My first approach was to pass a pointer to the resource into
>> > orion_ge00_switch_init(), but it seemed to just add complexity
>> > for no good.
>> 
>> Hi Arnd
>> 
>> You can simply this. DSA has never as far as i remember used an
>> interrupt passed via platform data. Two boards do seem to pass an
>> interrupt via a GPIO line, but it has never been used.
>> 
>> So if you want, you could strip all this interrupt code out.
>> 
>> There might be some patches coming soon which does add interrupt
>> support to DSA, but it will only be via device tree, since i don't
>> have a platform which is capable of using platform data for DSA.
>
> Ok, good idea!
>
> This is what I came up with, let me know if I should repost the
> whole series with this.
>
> 	Arnd
>
> From 75669f969287e9479f280642d251c1bac68f8d7c Mon Sep 17 00:00:00 2001
> From: Arnd Bergmann <arnd@arndb.de>
> Date: Mon, 5 Sep 2016 16:18:45 +0200
> Subject: [PATCH] ARM: orion: simplify orion_ge00_switch_init
>
> One of the last users of NO_IRQ on ARM is the switch initialization
> code on orion5x, which sometimes passes a GPIO based IRQ number.
>
> However, the driver doesn't actually use this number, and according
> to Andrew Lunn never will do it for non-DT based machines, so
> we can simply drop the irq argument.
>
> Simplifying it further, we can also drop the static platform_device
> and instead call platform_device_register_data(), which in turn
> lets us mark the platform_data structures as __initdata and slightly
> reduce the memory consumption.
>
> Signed-off-by: Arnd Bergmann <arnd@arndb.de>


I applied this version f the patch on mvebu/soc

Thanks,

Gregory

>
> diff --git a/arch/arm/mach-orion5x/common.c b/arch/arm/mach-orion5x/common.c
> index 058994e99570..04910764c385 100644
> --- a/arch/arm/mach-orion5x/common.c
> +++ b/arch/arm/mach-orion5x/common.c
> @@ -105,9 +105,9 @@ void __init orion5x_eth_init(struct mv643xx_eth_platform_data *eth_data)
>  /*****************************************************************************
>   * Ethernet switch
>   ****************************************************************************/
> -void __init orion5x_eth_switch_init(struct dsa_platform_data *d, int irq)
> +void __init orion5x_eth_switch_init(struct dsa_platform_data *d)
>  {
> -	orion_ge00_switch_init(d, irq);
> +	orion_ge00_switch_init(d);
>  }
>  
>  
> diff --git a/arch/arm/mach-orion5x/common.h b/arch/arm/mach-orion5x/common.h
> index cd0389c6e822..8a4115bd441d 100644
> --- a/arch/arm/mach-orion5x/common.h
> +++ b/arch/arm/mach-orion5x/common.h
> @@ -41,7 +41,7 @@ void orion5x_setup_wins(void);
>  void orion5x_ehci0_init(void);
>  void orion5x_ehci1_init(void);
>  void orion5x_eth_init(struct mv643xx_eth_platform_data *eth_data);
> -void orion5x_eth_switch_init(struct dsa_platform_data *d, int irq);
> +void orion5x_eth_switch_init(struct dsa_platform_data *d);
>  void orion5x_i2c_init(void);
>  void orion5x_sata_init(struct mv_sata_platform_data *sata_data);
>  void orion5x_spi_init(void);
> diff --git a/arch/arm/mach-orion5x/rd88f5181l-fxo-setup.c b/arch/arm/mach-orion5x/rd88f5181l-fxo-setup.c
> index c742e7b40b0d..dccadf68ea2b 100644
> --- a/arch/arm/mach-orion5x/rd88f5181l-fxo-setup.c
> +++ b/arch/arm/mach-orion5x/rd88f5181l-fxo-setup.c
> @@ -101,7 +101,7 @@ static struct dsa_chip_data rd88f5181l_fxo_switch_chip_data = {
>  	.port_names[7]	= "lan3",
>  };
>  
> -static struct dsa_platform_data rd88f5181l_fxo_switch_plat_data = {
> +static struct dsa_platform_data __initdata rd88f5181l_fxo_switch_plat_data = {
>  	.nr_chips	= 1,
>  	.chip		= &rd88f5181l_fxo_switch_chip_data,
>  };
> @@ -120,7 +120,7 @@ static void __init rd88f5181l_fxo_init(void)
>  	 */
>  	orion5x_ehci0_init();
>  	orion5x_eth_init(&rd88f5181l_fxo_eth_data);
> -	orion5x_eth_switch_init(&rd88f5181l_fxo_switch_plat_data, NO_IRQ);
> +	orion5x_eth_switch_init(&rd88f5181l_fxo_switch_plat_data);
>  	orion5x_uart0_init();
>  
>  	mvebu_mbus_add_window_by_id(ORION_MBUS_DEVBUS_BOOT_TARGET,
> diff --git a/arch/arm/mach-orion5x/rd88f5181l-ge-setup.c b/arch/arm/mach-orion5x/rd88f5181l-ge-setup.c
> index 7e977b794b0c..affe5ec825de 100644
> --- a/arch/arm/mach-orion5x/rd88f5181l-ge-setup.c
> +++ b/arch/arm/mach-orion5x/rd88f5181l-ge-setup.c
> @@ -102,7 +102,7 @@ static struct dsa_chip_data rd88f5181l_ge_switch_chip_data = {
>  	.port_names[7]	= "lan3",
>  };
>  
> -static struct dsa_platform_data rd88f5181l_ge_switch_plat_data = {
> +static struct dsa_platform_data __initdata rd88f5181l_ge_switch_plat_data = {
>  	.nr_chips	= 1,
>  	.chip		= &rd88f5181l_ge_switch_chip_data,
>  };
> @@ -125,8 +125,7 @@ static void __init rd88f5181l_ge_init(void)
>  	 */
>  	orion5x_ehci0_init();
>  	orion5x_eth_init(&rd88f5181l_ge_eth_data);
> -	orion5x_eth_switch_init(&rd88f5181l_ge_switch_plat_data,
> -				gpio_to_irq(8));
> +	orion5x_eth_switch_init(&rd88f5181l_ge_switch_plat_data);
>  	orion5x_i2c_init();
>  	orion5x_uart0_init();
>  
> diff --git a/arch/arm/mach-orion5x/rd88f6183ap-ge-setup.c b/arch/arm/mach-orion5x/rd88f6183ap-ge-setup.c
> index 8ffaead76771..67ee8571b03c 100644
> --- a/arch/arm/mach-orion5x/rd88f6183ap-ge-setup.c
> +++ b/arch/arm/mach-orion5x/rd88f6183ap-ge-setup.c
> @@ -40,7 +40,7 @@ static struct dsa_chip_data rd88f6183ap_ge_switch_chip_data = {
>  	.port_names[5]	= "cpu",
>  };
>  
> -static struct dsa_platform_data rd88f6183ap_ge_switch_plat_data = {
> +static struct dsa_platform_data __initdata rd88f6183ap_ge_switch_plat_data = {
>  	.nr_chips	= 1,
>  	.chip		= &rd88f6183ap_ge_switch_chip_data,
>  };
> @@ -89,8 +89,7 @@ static void __init rd88f6183ap_ge_init(void)
>  	 */
>  	orion5x_ehci0_init();
>  	orion5x_eth_init(&rd88f6183ap_ge_eth_data);
> -	orion5x_eth_switch_init(&rd88f6183ap_ge_switch_plat_data,
> -				gpio_to_irq(3));
> +	orion5x_eth_switch_init(&rd88f6183ap_ge_switch_plat_data);
>  	spi_register_board_info(rd88f6183ap_ge_spi_slave_info,
>  				ARRAY_SIZE(rd88f6183ap_ge_spi_slave_info));
>  	orion5x_spi_init();
> diff --git a/arch/arm/mach-orion5x/wnr854t-setup.c b/arch/arm/mach-orion5x/wnr854t-setup.c
> index 4e1e5c8f6111..4dbcdbe1de7c 100644
> --- a/arch/arm/mach-orion5x/wnr854t-setup.c
> +++ b/arch/arm/mach-orion5x/wnr854t-setup.c
> @@ -106,7 +106,7 @@ static struct dsa_chip_data wnr854t_switch_chip_data = {
>  	.port_names[7] = "lan2",
>  };
>  
> -static struct dsa_platform_data wnr854t_switch_plat_data = {
> +static struct dsa_platform_data __initdata wnr854t_switch_plat_data = {
>  	.nr_chips	= 1,
>  	.chip		= &wnr854t_switch_chip_data,
>  };
> @@ -124,7 +124,7 @@ static void __init wnr854t_init(void)
>  	 * Configure peripherals.
>  	 */
>  	orion5x_eth_init(&wnr854t_eth_data);
> -	orion5x_eth_switch_init(&wnr854t_switch_plat_data, NO_IRQ);
> +	orion5x_eth_switch_init(&wnr854t_switch_plat_data);
>  	orion5x_uart0_init();
>  
>  	mvebu_mbus_add_window_by_id(ORION_MBUS_DEVBUS_BOOT_TARGET,
> diff --git a/arch/arm/mach-orion5x/wrt350n-v2-setup.c b/arch/arm/mach-orion5x/wrt350n-v2-setup.c
> index 61e9027ef224..a6a8c4648d74 100644
> --- a/arch/arm/mach-orion5x/wrt350n-v2-setup.c
> +++ b/arch/arm/mach-orion5x/wrt350n-v2-setup.c
> @@ -191,7 +191,7 @@ static struct dsa_chip_data wrt350n_v2_switch_chip_data = {
>  	.port_names[7]	= "lan4",
>  };
>  
> -static struct dsa_platform_data wrt350n_v2_switch_plat_data = {
> +static struct dsa_platform_data __initdata wrt350n_v2_switch_plat_data = {
>  	.nr_chips	= 1,
>  	.chip		= &wrt350n_v2_switch_chip_data,
>  };
> @@ -210,7 +210,7 @@ static void __init wrt350n_v2_init(void)
>  	 */
>  	orion5x_ehci0_init();
>  	orion5x_eth_init(&wrt350n_v2_eth_data);
> -	orion5x_eth_switch_init(&wrt350n_v2_switch_plat_data, NO_IRQ);
> +	orion5x_eth_switch_init(&wrt350n_v2_switch_plat_data);
>  	orion5x_uart0_init();
>  
>  	mvebu_mbus_add_window_by_id(ORION_MBUS_DEVBUS_BOOT_TARGET,
> diff --git a/arch/arm/plat-orion/common.c b/arch/arm/plat-orion/common.c
> index 7b9b70785a54..272f49b2c68f 100644
> --- a/arch/arm/plat-orion/common.c
> +++ b/arch/arm/plat-orion/common.c
> @@ -470,37 +470,15 @@ void __init orion_ge11_init(struct mv643xx_eth_platform_data *eth_data,
>  /*****************************************************************************
>   * Ethernet switch
>   ****************************************************************************/
> -static struct resource orion_switch_resources[] = {
> -	{
> -		.start	= 0,
> -		.end	= 0,
> -		.flags	= IORESOURCE_IRQ,
> -	},
> -};
> -
> -static struct platform_device orion_switch_device = {
> -	.name		= "dsa",
> -	.id		= 0,
> -	.num_resources	= 0,
> -	.resource	= orion_switch_resources,
> -};
> -
> -void __init orion_ge00_switch_init(struct dsa_platform_data *d, int irq)
> +void __init orion_ge00_switch_init(struct dsa_platform_data *d)
>  {
>  	int i;
>  
> -	if (irq != NO_IRQ) {
> -		orion_switch_resources[0].start = irq;
> -		orion_switch_resources[0].end = irq;
> -		orion_switch_device.num_resources = 1;
> -	}
> -
>  	d->netdev = &orion_ge00.dev;
>  	for (i = 0; i < d->nr_chips; i++)
>  		d->chip[i].host_dev = &orion_ge_mvmdio.dev;
> -	orion_switch_device.dev.platform_data = d;
>  
> -	platform_device_register(&orion_switch_device);
> +	platform_device_register_data(NULL, "dsa", 0, d, sizeof(d));
>  }
>  
>  /*****************************************************************************
> diff --git a/arch/arm/plat-orion/include/plat/common.h b/arch/arm/plat-orion/include/plat/common.h
> index 8519727faa5e..9347f3c58a6d 100644
> --- a/arch/arm/plat-orion/include/plat/common.h
> +++ b/arch/arm/plat-orion/include/plat/common.h
> @@ -57,8 +57,7 @@ void __init orion_ge11_init(struct mv643xx_eth_platform_data *eth_data,
>  			    unsigned long mapbase,
>  			    unsigned long irq);
>  
> -void __init orion_ge00_switch_init(struct dsa_platform_data *d,
> -				   int irq);
> +void __init orion_ge00_switch_init(struct dsa_platform_data *d);
>  
>  void __init orion_i2c_init(unsigned long mapbase,
>  			   unsigned long irq,
>

-- 
Gregory Clement, Free Electrons
Kernel, drivers, real-time and embedded Linux
development, consulting, training and support.
http://free-electrons.com

^ permalink raw reply

* [PATCH 2/4] ARM: mvebu/orion: remove NO_IRQ check from device init
From: Gregory CLEMENT @ 2016-09-14 14:37 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20160906140623.2853066-2-arnd@arndb.de>

Hi Arnd,
 
 On mar., sept. 06 2016, Arnd Bergmann <arnd@arndb.de> wrote:

> For most devices, we know in advance whether they have an
> interrupt line or not, so we can avoid passing NO_IRQ and
> instead split fill_resources() into two interfaces, with
> only the new fill_resources_irq() function taking an irq
> argument, which it then can use unconditionally.
>
> Signed-off-by: Arnd Bergmann <arnd@arndb.de>

Applied on mvebu/soc

Thanks,

Gregory
> ---
>  arch/arm/plat-orion/common.c | 52 ++++++++++++++++++++++++--------------------
>  1 file changed, 29 insertions(+), 23 deletions(-)
>
> diff --git a/arch/arm/plat-orion/common.c b/arch/arm/plat-orion/common.c
> index 7757f71fe709..7b9b70785a54 100644
> --- a/arch/arm/plat-orion/common.c
> +++ b/arch/arm/plat-orion/common.c
> @@ -52,21 +52,27 @@ void __init orion_clkdev_init(struct clk *tclk)
>  static void fill_resources(struct platform_device *device,
>  			   struct resource *resources,
>  			   resource_size_t mapbase,
> -			   resource_size_t size,
> -			   unsigned int irq)
> +			   resource_size_t size)
>  {
>  	device->resource = resources;
>  	device->num_resources = 1;
>  	resources[0].flags = IORESOURCE_MEM;
>  	resources[0].start = mapbase;
>  	resources[0].end = mapbase + size;
> +}
>  
> -	if (irq != NO_IRQ) {
> -		device->num_resources++;
> -		resources[1].flags = IORESOURCE_IRQ;
> -		resources[1].start = irq;
> -		resources[1].end = irq;
> -	}
> +static void fill_resources_irq(struct platform_device *device,
> +			       struct resource *resources,
> +			       resource_size_t mapbase,
> +			       resource_size_t size,
> +			       unsigned int irq)
> +{
> +	fill_resources(device, resources, mapbase, size);
> +
> +	device->num_resources++;
> +	resources[1].flags = IORESOURCE_IRQ;
> +	resources[1].start = irq;
> +	resources[1].end = irq;
>  }
>  
>  /*****************************************************************************
> @@ -93,7 +99,7 @@ static void __init uart_complete(
>  	data->uartclk = uart_get_clk_rate(clk);
>  	orion_uart->dev.platform_data = data;
>  
> -	fill_resources(orion_uart, resources, mapbase, 0xff, irq);
> +	fill_resources_irq(orion_uart, resources, mapbase, 0xff, irq);
>  	platform_device_register(orion_uart);
>  }
>  
> @@ -305,8 +311,8 @@ void __init orion_ge00_init(struct mv643xx_eth_platform_data *eth_data,
>  			    unsigned int tx_csum_limit)
>  {
>  	fill_resources(&orion_ge00_shared, orion_ge00_shared_resources,
> -		       mapbase + 0x2000, SZ_16K - 1, NO_IRQ);
> -	fill_resources(&orion_ge_mvmdio, orion_ge_mvmdio_resources,
> +		       mapbase + 0x2000, SZ_16K - 1);
> +	fill_resources_irq(&orion_ge_mvmdio, orion_ge_mvmdio_resources,
>  			mapbase + 0x2004, 0x84 - 1, irq_err);
>  	orion_ge00_shared_data.tx_csum_limit = tx_csum_limit;
>  	ge_complete(&orion_ge00_shared_data,
> @@ -357,7 +363,7 @@ void __init orion_ge01_init(struct mv643xx_eth_platform_data *eth_data,
>  			    unsigned int tx_csum_limit)
>  {
>  	fill_resources(&orion_ge01_shared, orion_ge01_shared_resources,
> -		       mapbase + 0x2000, SZ_16K - 1, NO_IRQ);
> +		       mapbase + 0x2000, SZ_16K - 1);
>  	orion_ge01_shared_data.tx_csum_limit = tx_csum_limit;
>  	ge_complete(&orion_ge01_shared_data,
>  		    orion_ge01_resources, irq, &orion_ge01_shared,
> @@ -406,7 +412,7 @@ void __init orion_ge10_init(struct mv643xx_eth_platform_data *eth_data,
>  			    unsigned long irq)
>  {
>  	fill_resources(&orion_ge10_shared, orion_ge10_shared_resources,
> -		       mapbase + 0x2000, SZ_16K - 1, NO_IRQ);
> +		       mapbase + 0x2000, SZ_16K - 1);
>  	ge_complete(&orion_ge10_shared_data,
>  		    orion_ge10_resources, irq, &orion_ge10_shared,
>  		    NULL,
> @@ -454,7 +460,7 @@ void __init orion_ge11_init(struct mv643xx_eth_platform_data *eth_data,
>  			    unsigned long irq)
>  {
>  	fill_resources(&orion_ge11_shared, orion_ge11_shared_resources,
> -		       mapbase + 0x2000, SZ_16K - 1, NO_IRQ);
> +		       mapbase + 0x2000, SZ_16K - 1);
>  	ge_complete(&orion_ge11_shared_data,
>  		    orion_ge11_resources, irq, &orion_ge11_shared,
>  		    NULL,
> @@ -535,7 +541,7 @@ void __init orion_i2c_init(unsigned long mapbase,
>  			   unsigned long freq_m)
>  {
>  	orion_i2c_pdata.freq_m = freq_m;
> -	fill_resources(&orion_i2c, orion_i2c_resources, mapbase,
> +	fill_resources_irq(&orion_i2c, orion_i2c_resources, mapbase,
>  		       SZ_32 - 1, irq);
>  	platform_device_register(&orion_i2c);
>  }
> @@ -545,7 +551,7 @@ void __init orion_i2c_1_init(unsigned long mapbase,
>  			     unsigned long freq_m)
>  {
>  	orion_i2c_1_pdata.freq_m = freq_m;
> -	fill_resources(&orion_i2c_1, orion_i2c_1_resources, mapbase,
> +	fill_resources_irq(&orion_i2c_1, orion_i2c_1_resources, mapbase,
>  		       SZ_32 - 1, irq);
>  	platform_device_register(&orion_i2c_1);
>  }
> @@ -573,14 +579,14 @@ static struct platform_device orion_spi_1 = {
>  void __init orion_spi_init(unsigned long mapbase)
>  {
>  	fill_resources(&orion_spi, &orion_spi_resources,
> -		       mapbase, SZ_512 - 1, NO_IRQ);
> +		       mapbase, SZ_512 - 1);
>  	platform_device_register(&orion_spi);
>  }
>  
>  void __init orion_spi_1_init(unsigned long mapbase)
>  {
>  	fill_resources(&orion_spi_1, &orion_spi_1_resources,
> -		       mapbase, SZ_512 - 1, NO_IRQ);
> +		       mapbase, SZ_512 - 1);
>  	platform_device_register(&orion_spi_1);
>  }
>  
> @@ -738,7 +744,7 @@ void __init orion_ehci_init(unsigned long mapbase,
>  			    enum orion_ehci_phy_ver phy_version)
>  {
>  	orion_ehci_data.phy_version = phy_version;
> -	fill_resources(&orion_ehci, orion_ehci_resources, mapbase, SZ_4K - 1,
> +	fill_resources_irq(&orion_ehci, orion_ehci_resources, mapbase, SZ_4K - 1,
>  		       irq);
>  
>  	platform_device_register(&orion_ehci);
> @@ -762,7 +768,7 @@ static struct platform_device orion_ehci_1 = {
>  void __init orion_ehci_1_init(unsigned long mapbase,
>  			      unsigned long irq)
>  {
> -	fill_resources(&orion_ehci_1, orion_ehci_1_resources,
> +	fill_resources_irq(&orion_ehci_1, orion_ehci_1_resources,
>  		       mapbase, SZ_4K - 1, irq);
>  
>  	platform_device_register(&orion_ehci_1);
> @@ -786,7 +792,7 @@ static struct platform_device orion_ehci_2 = {
>  void __init orion_ehci_2_init(unsigned long mapbase,
>  			      unsigned long irq)
>  {
> -	fill_resources(&orion_ehci_2, orion_ehci_2_resources,
> +	fill_resources_irq(&orion_ehci_2, orion_ehci_2_resources,
>  		       mapbase, SZ_4K - 1, irq);
>  
>  	platform_device_register(&orion_ehci_2);
> @@ -816,7 +822,7 @@ void __init orion_sata_init(struct mv_sata_platform_data *sata_data,
>  			    unsigned long irq)
>  {
>  	orion_sata.dev.platform_data = sata_data;
> -	fill_resources(&orion_sata, orion_sata_resources,
> +	fill_resources_irq(&orion_sata, orion_sata_resources,
>  		       mapbase, 0x5000 - 1, irq);
>  
>  	platform_device_register(&orion_sata);
> @@ -846,7 +852,7 @@ void __init orion_crypto_init(unsigned long mapbase,
>  			      unsigned long sram_size,
>  			      unsigned long irq)
>  {
> -	fill_resources(&orion_crypto, orion_crypto_resources,
> +	fill_resources_irq(&orion_crypto, orion_crypto_resources,
>  		       mapbase, 0xffff, irq);
>  	orion_crypto.num_resources = 3;
>  	orion_crypto_resources[2].start = srambase;
> -- 
> 2.9.0
>

-- 
Gregory Clement, Free Electrons
Kernel, drivers, real-time and embedded Linux
development, consulting, training and support.
http://free-electrons.com

^ permalink raw reply

* [PATCH 1/4] ARM: mv78xx0: simplify ethernet device creation
From: Gregory CLEMENT @ 2016-09-14 14:37 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20160906140623.2853066-1-arnd@arndb.de>

Hi Arnd,
 
 On mar., sept. 06 2016, Arnd Bergmann <arnd@arndb.de> wrote:

> Out of the four ethernet devices on mv78xx0, only the first one
> has an error interrupt line, for the other ones we pass NO_IRQ
> and then ignore the argument.
>
> In order to get closer to complete remove of NO_IRQ, this simply
> drops the unused function arguments.
>
> Signed-off-by: Arnd Bergmann <arnd@arndb.de>

Applied on mvebu/soc with Reviewed-by tag from  Andrew Lunn

Thanks,

Gregory

> ---
>  arch/arm/mach-mv78xx0/common.c            | 9 ++-------
>  arch/arm/plat-orion/common.c              | 7 ++-----
>  arch/arm/plat-orion/include/plat/common.h | 7 ++-----
>  3 files changed, 6 insertions(+), 17 deletions(-)
>
> diff --git a/arch/arm/mach-mv78xx0/common.c b/arch/arm/mach-mv78xx0/common.c
> index 6af5430d0d97..f72e1e9f5fc5 100644
> --- a/arch/arm/mach-mv78xx0/common.c
> +++ b/arch/arm/mach-mv78xx0/common.c
> @@ -219,7 +219,6 @@ void __init mv78xx0_ge01_init(struct mv643xx_eth_platform_data *eth_data)
>  {
>  	orion_ge01_init(eth_data,
>  			GE01_PHYS_BASE, IRQ_MV78XX0_GE01_SUM,
> -			NO_IRQ,
>  			MV643XX_TX_CSUM_DEFAULT_LIMIT);
>  }
>  
> @@ -242,9 +241,7 @@ void __init mv78xx0_ge10_init(struct mv643xx_eth_platform_data *eth_data)
>  		eth_data->duplex = DUPLEX_FULL;
>  	}
>  
> -	orion_ge10_init(eth_data,
> -			GE10_PHYS_BASE, IRQ_MV78XX0_GE10_SUM,
> -			NO_IRQ);
> +	orion_ge10_init(eth_data, GE10_PHYS_BASE, IRQ_MV78XX0_GE10_SUM);
>  }
>  
>  
> @@ -266,9 +263,7 @@ void __init mv78xx0_ge11_init(struct mv643xx_eth_platform_data *eth_data)
>  		eth_data->duplex = DUPLEX_FULL;
>  	}
>  
> -	orion_ge11_init(eth_data,
> -			GE11_PHYS_BASE, IRQ_MV78XX0_GE11_SUM,
> -			NO_IRQ);
> +	orion_ge11_init(eth_data, GE11_PHYS_BASE, IRQ_MV78XX0_GE11_SUM);
>  }
>  
>  /*****************************************************************************
> diff --git a/arch/arm/plat-orion/common.c b/arch/arm/plat-orion/common.c
> index 78c8bf4043c0..7757f71fe709 100644
> --- a/arch/arm/plat-orion/common.c
> +++ b/arch/arm/plat-orion/common.c
> @@ -354,7 +354,6 @@ static struct platform_device orion_ge01 = {
>  void __init orion_ge01_init(struct mv643xx_eth_platform_data *eth_data,
>  			    unsigned long mapbase,
>  			    unsigned long irq,
> -			    unsigned long irq_err,
>  			    unsigned int tx_csum_limit)
>  {
>  	fill_resources(&orion_ge01_shared, orion_ge01_shared_resources,
> @@ -404,8 +403,7 @@ static struct platform_device orion_ge10 = {
>  
>  void __init orion_ge10_init(struct mv643xx_eth_platform_data *eth_data,
>  			    unsigned long mapbase,
> -			    unsigned long irq,
> -			    unsigned long irq_err)
> +			    unsigned long irq)
>  {
>  	fill_resources(&orion_ge10_shared, orion_ge10_shared_resources,
>  		       mapbase + 0x2000, SZ_16K - 1, NO_IRQ);
> @@ -453,8 +451,7 @@ static struct platform_device orion_ge11 = {
>  
>  void __init orion_ge11_init(struct mv643xx_eth_platform_data *eth_data,
>  			    unsigned long mapbase,
> -			    unsigned long irq,
> -			    unsigned long irq_err)
> +			    unsigned long irq)
>  {
>  	fill_resources(&orion_ge11_shared, orion_ge11_shared_resources,
>  		       mapbase + 0x2000, SZ_16K - 1, NO_IRQ);
> diff --git a/arch/arm/plat-orion/include/plat/common.h b/arch/arm/plat-orion/include/plat/common.h
> index 9e6d76ad48a9..8519727faa5e 100644
> --- a/arch/arm/plat-orion/include/plat/common.h
> +++ b/arch/arm/plat-orion/include/plat/common.h
> @@ -47,18 +47,15 @@ void __init orion_ge00_init(struct mv643xx_eth_platform_data *eth_data,
>  void __init orion_ge01_init(struct mv643xx_eth_platform_data *eth_data,
>  			    unsigned long mapbase,
>  			    unsigned long irq,
> -			    unsigned long irq_err,
>  			    unsigned int tx_csum_limit);
>  
>  void __init orion_ge10_init(struct mv643xx_eth_platform_data *eth_data,
>  			    unsigned long mapbase,
> -			    unsigned long irq,
> -			    unsigned long irq_err);
> +			    unsigned long irq);
>  
>  void __init orion_ge11_init(struct mv643xx_eth_platform_data *eth_data,
>  			    unsigned long mapbase,
> -			    unsigned long irq,
> -			    unsigned long irq_err);
> +			    unsigned long irq);
>  
>  void __init orion_ge00_switch_init(struct dsa_platform_data *d,
>  				   int irq);
> -- 
> 2.9.0
>

-- 
Gregory Clement, Free Electrons
Kernel, drivers, real-time and embedded Linux
development, consulting, training and support.
http://free-electrons.com

^ permalink raw reply

* [PATCH v7.1 19/22] iommu/arm-smmu: Wire up generic configuration support
From: Robin Murphy @ 2016-09-14 14:26 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <228dc6c675f10ae7481640d4ef2f4960c170621f.1473695704.git.robin.murphy@arm.com>

With everything else now in place, fill in an of_xlate callback and the
appropriate registration to plumb into the generic configuration
machinery, and watch everything just work.

Signed-off-by: Robin Murphy <robin.murphy@arm.com>

---

- Don't pull in of_platform.h for no reason (was an old leftover)
- Don't spam deprecated binding message when multiple SMMUs are using it

---
 drivers/iommu/arm-smmu.c | 168 ++++++++++++++++++++++++++++++-----------------
 1 file changed, 108 insertions(+), 60 deletions(-)

diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c
index 9dbb6a37e625..fd6cc19c4ced 100644
--- a/drivers/iommu/arm-smmu.c
+++ b/drivers/iommu/arm-smmu.c
@@ -418,6 +418,8 @@ struct arm_smmu_option_prop {
 
 static atomic_t cavium_smmu_context_count = ATOMIC_INIT(0);
 
+static bool using_legacy_binding, using_generic_binding;
+
 static struct arm_smmu_option_prop arm_smmu_options[] = {
 	{ ARM_SMMU_OPT_SECURE_CFG_ACCESS, "calxeda,smmu-secure-config-access" },
 	{ 0, NULL},
@@ -817,12 +819,6 @@ static int arm_smmu_init_domain_context(struct iommu_domain *domain,
 	if (smmu_domain->smmu)
 		goto out_unlock;
 
-	/* We're bypassing these SIDs, so don't allocate an actual context */
-	if (domain->type == IOMMU_DOMAIN_DMA) {
-		smmu_domain->smmu = smmu;
-		goto out_unlock;
-	}
-
 	/*
 	 * Mapping the requested stage onto what we support is surprisingly
 	 * complicated, mainly because the spec allows S1+S2 SMMUs without
@@ -981,7 +977,7 @@ static void arm_smmu_destroy_domain_context(struct iommu_domain *domain)
 	void __iomem *cb_base;
 	int irq;
 
-	if (!smmu || domain->type == IOMMU_DOMAIN_DMA)
+	if (!smmu)
 		return;
 
 	/*
@@ -1015,8 +1011,8 @@ static struct iommu_domain *arm_smmu_domain_alloc(unsigned type)
 	if (!smmu_domain)
 		return NULL;
 
-	if (type == IOMMU_DOMAIN_DMA &&
-	    iommu_get_dma_cookie(&smmu_domain->domain)) {
+	if (type == IOMMU_DOMAIN_DMA && (using_legacy_binding ||
+	    iommu_get_dma_cookie(&smmu_domain->domain))) {
 		kfree(smmu_domain);
 		return NULL;
 	}
@@ -1133,19 +1129,22 @@ static int arm_smmu_master_alloc_smes(struct device *dev)
 	mutex_lock(&smmu->stream_map_mutex);
 	/* Figure out a viable stream map entry allocation */
 	for_each_cfg_sme(fwspec, i, idx) {
+		u16 sid = fwspec->ids[i];
+		u16 mask = fwspec->ids[i] >> SMR_MASK_SHIFT;
+
 		if (idx != INVALID_SMENDX) {
 			ret = -EEXIST;
 			goto out_err;
 		}
 
-		ret = arm_smmu_find_sme(smmu, fwspec->ids[i], 0);
+		ret = arm_smmu_find_sme(smmu, sid, mask);
 		if (ret < 0)
 			goto out_err;
 
 		idx = ret;
 		if (smrs && smmu->s2crs[idx].count == 0) {
-			smrs[idx].id = fwspec->ids[i];
-			smrs[idx].mask = 0; /* We don't currently share SMRs */
+			smrs[idx].id = sid;
+			smrs[idx].mask = mask;
 			smrs[idx].valid = true;
 		}
 		smmu->s2crs[idx].count++;
@@ -1203,15 +1202,6 @@ static int arm_smmu_domain_add_master(struct arm_smmu_domain *smmu_domain,
 	u8 cbndx = smmu_domain->cfg.cbndx;
 	int i, idx;
 
-	/*
-	 * FIXME: This won't be needed once we have IOMMU-backed DMA ops
-	 * for all devices behind the SMMU. Note that we need to take
-	 * care configuring SMRs for devices both a platform_device and
-	 * and a PCI device (i.e. a PCI host controller)
-	 */
-	if (smmu_domain->domain.type == IOMMU_DOMAIN_DMA)
-		type = S2CR_TYPE_BYPASS;
-
 	for_each_cfg_sme(fwspec, i, idx) {
 		if (type == s2cr[idx].type && cbndx == s2cr[idx].cbndx)
 			continue;
@@ -1373,25 +1363,50 @@ static bool arm_smmu_capable(enum iommu_cap cap)
 	}
 }
 
+static int arm_smmu_match_node(struct device *dev, void *data)
+{
+	return dev->of_node == data;
+}
+
+static struct arm_smmu_device *arm_smmu_get_by_node(struct device_node *np)
+{
+	struct device *dev = driver_find_device(&arm_smmu_driver.driver, NULL,
+						np, arm_smmu_match_node);
+	put_device(dev);
+	return dev ? dev_get_drvdata(dev) : NULL;
+}
+
 static int arm_smmu_add_device(struct device *dev)
 {
 	struct arm_smmu_device *smmu;
 	struct arm_smmu_master_cfg *cfg;
-	struct iommu_fwspec *fwspec;
+	struct iommu_fwspec *fwspec = dev->iommu_fwspec;
 	int i, ret;
 
-	ret = arm_smmu_register_legacy_master(dev, &smmu);
-	fwspec = dev->iommu_fwspec;
-	if (ret)
-		goto out_free;
+	if (using_legacy_binding) {
+		ret = arm_smmu_register_legacy_master(dev, &smmu);
+		fwspec = dev->iommu_fwspec;
+		if (ret)
+			goto out_free;
+	} else if (fwspec) {
+		smmu = arm_smmu_get_by_node(to_of_node(fwspec->iommu_fwnode));
+	} else {
+		return -ENODEV;
+	}
 
 	ret = -EINVAL;
 	for (i = 0; i < fwspec->num_ids; i++) {
 		u16 sid = fwspec->ids[i];
+		u16 mask = fwspec->ids[i] >> SMR_MASK_SHIFT;
 
 		if (sid & ~smmu->streamid_mask) {
 			dev_err(dev, "stream ID 0x%x out of range for SMMU (0x%x)\n",
-				sid, cfg->smmu->streamid_mask);
+				sid, smmu->streamid_mask);
+			goto out_free;
+		}
+		if (mask & ~smmu->smr_mask_mask) {
+			dev_err(dev, "SMR mask 0x%x out of range for SMMU (0x%x)\n",
+				sid, smmu->smr_mask_mask);
 			goto out_free;
 		}
 	}
@@ -1503,6 +1518,19 @@ out_unlock:
 	return ret;
 }
 
+static int arm_smmu_of_xlate(struct device *dev, struct of_phandle_args *args)
+{
+	u32 fwid = 0;
+
+	if (args->args_count > 0)
+		fwid |= (u16)args->args[0];
+
+	if (args->args_count > 1)
+		fwid |= (u16)args->args[1] << SMR_MASK_SHIFT;
+
+	return iommu_fwspec_add_ids(dev, &fwid, 1);
+}
+
 static struct iommu_ops arm_smmu_ops = {
 	.capable		= arm_smmu_capable,
 	.domain_alloc		= arm_smmu_domain_alloc,
@@ -1517,6 +1545,7 @@ static struct iommu_ops arm_smmu_ops = {
 	.device_group		= arm_smmu_device_group,
 	.domain_get_attr	= arm_smmu_domain_get_attr,
 	.domain_set_attr	= arm_smmu_domain_set_attr,
+	.of_xlate		= arm_smmu_of_xlate,
 	.pgsize_bitmap		= -1UL, /* Restricted during device attach */
 };
 
@@ -1870,6 +1899,19 @@ static int arm_smmu_device_dt_probe(struct platform_device *pdev)
 	struct arm_smmu_device *smmu;
 	struct device *dev = &pdev->dev;
 	int num_irqs, i, err;
+	bool legacy_binding;
+
+	legacy_binding = of_find_property(dev->of_node, "mmu-masters", NULL);
+	if (legacy_binding && !using_generic_binding) {
+		if (!using_legacy_binding)
+			pr_notice("deprecated \"mmu-masters\" DT property in use; DMA API support unavailable\n");
+		using_legacy_binding = true;
+	} else if (!legacy_binding && !using_legacy_binding) {
+		using_generic_binding = true;
+	} else {
+		dev_err(dev, "not probing due to mismatched DT properties\n");
+		return -ENODEV;
+	}
 
 	smmu = devm_kzalloc(dev, sizeof(*smmu), GFP_KERNEL);
 	if (!smmu) {
@@ -1954,6 +1996,20 @@ static int arm_smmu_device_dt_probe(struct platform_device *pdev)
 	of_iommu_set_ops(dev->of_node, &arm_smmu_ops);
 	platform_set_drvdata(pdev, smmu);
 	arm_smmu_device_reset(smmu);
+
+	/* Oh, for a proper bus abstraction */
+	if (!iommu_present(&platform_bus_type))
+		bus_set_iommu(&platform_bus_type, &arm_smmu_ops);
+#ifdef CONFIG_ARM_AMBA
+	if (!iommu_present(&amba_bustype))
+		bus_set_iommu(&amba_bustype, &arm_smmu_ops);
+#endif
+#ifdef CONFIG_PCI
+	if (!iommu_present(&pci_bus_type)) {
+		pci_request_acs();
+		bus_set_iommu(&pci_bus_type, &arm_smmu_ops);
+	}
+#endif
 	return 0;
 }
 
@@ -1983,41 +2039,14 @@ static struct platform_driver arm_smmu_driver = {
 
 static int __init arm_smmu_init(void)
 {
-	struct device_node *np;
-	int ret;
+	static bool registered;
+	int ret = 0;
 
-	/*
-	 * Play nice with systems that don't have an ARM SMMU by checking that
-	 * an ARM SMMU exists in the system before proceeding with the driver
-	 * and IOMMU bus operation registration.
-	 */
-	np = of_find_matching_node(NULL, arm_smmu_of_match);
-	if (!np)
-		return 0;
-
-	of_node_put(np);
-
-	ret = platform_driver_register(&arm_smmu_driver);
-	if (ret)
-		return ret;
-
-	/* Oh, for a proper bus abstraction */
-	if (!iommu_present(&platform_bus_type))
-		bus_set_iommu(&platform_bus_type, &arm_smmu_ops);
-
-#ifdef CONFIG_ARM_AMBA
-	if (!iommu_present(&amba_bustype))
-		bus_set_iommu(&amba_bustype, &arm_smmu_ops);
-#endif
-
-#ifdef CONFIG_PCI
-	if (!iommu_present(&pci_bus_type)) {
-		pci_request_acs();
-		bus_set_iommu(&pci_bus_type, &arm_smmu_ops);
+	if (!registered) {
+		ret = platform_driver_register(&arm_smmu_driver);
+		registered = !ret;
 	}
-#endif
-
-	return 0;
+	return ret;
 }
 
 static void __exit arm_smmu_exit(void)
@@ -2028,6 +2057,25 @@ static void __exit arm_smmu_exit(void)
 subsys_initcall(arm_smmu_init);
 module_exit(arm_smmu_exit);
 
+static int __init arm_smmu_of_init(struct device_node *np)
+{
+	int ret = arm_smmu_init();
+
+	if (ret)
+		return ret;
+
+	if (!of_platform_device_create(np, NULL, platform_bus_type.dev_root))
+		return -ENODEV;
+
+	return 0;
+}
+IOMMU_OF_DECLARE(arm_smmuv1, "arm,smmu-v1", arm_smmu_of_init);
+IOMMU_OF_DECLARE(arm_smmuv2, "arm,smmu-v2", arm_smmu_of_init);
+IOMMU_OF_DECLARE(arm_mmu400, "arm,mmu-400", arm_smmu_of_init);
+IOMMU_OF_DECLARE(arm_mmu401, "arm,mmu-401", arm_smmu_of_init);
+IOMMU_OF_DECLARE(arm_mmu500, "arm,mmu-500", arm_smmu_of_init);
+IOMMU_OF_DECLARE(cavium_smmuv2, "cavium,smmu-v2", arm_smmu_of_init);
+
 MODULE_DESCRIPTION("IOMMU API for ARM architected SMMU implementations");
 MODULE_AUTHOR("Will Deacon <will.deacon@arm.com>");
 MODULE_LICENSE("GPL v2");
-- 
2.8.1.dirty

^ permalink raw reply related

* [PATCH] dt-binding: mrvl-gpio: remove orion-gpio description
From: Gregory CLEMENT @ 2016-09-14 14:25 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20160905192813.GB2719@lunn.ch>

Hi Baruch, Andrew,
 
 On lun., sept. 05 2016, Andrew Lunn <andrew@lunn.ch> wrote:

> On Mon, Sep 05, 2016 at 10:00:10PM +0300, Baruch Siach wrote:
>> The Orion GPIO controller binding description in mrvl-gpio.txt is obsolete, and
>> duplicates the description in gpio-mvebu.txt.
>> 
>> Signed-off-by: Baruch Siach <baruch@tkos.co.il>
>
> Reviewed-by: Andrew Lunn <andrew@lunn.ch>

Applied on mvebu/dt

Thanks,

Gregory
>
>     Andrew

-- 
Gregory Clement, Free Electrons
Kernel, drivers, real-time and embedded Linux
development, consulting, training and support.
http://free-electrons.com

^ permalink raw reply

* [PATCH V3 1/4] ARM64 LPC: Indirect ISA port IO introduced
From: Arnd Bergmann @ 2016-09-14 14:23 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <57D95BBC.9030405@hisilicon.com>

On Wednesday, September 14, 2016 10:16:28 PM CEST zhichang.yuan wrote:
> > 
> > No need to guard includes with an #ifdef.
> If remove #ifdef here, extio.h should not contain any function external declarations whose definitions are in
> extio.c compiled only when CONFIG_ARM64_INDIRECT_PIO is yes.
 
There is no problem with making declarations visible for functions that
are not part of the kernel, we do that all the time.

> >> +#define BUILDS_RW(bwl, type)                                                \
> >> +static inline void reads##bwl(const volatile void __iomem *addr,    \
> >> +                            void *buffer, unsigned int count)       \
> >> +{                                                                   \
> >> +    if (count) {                                                    \
> >> +            type *buf = buffer;                                     \
> >> +                                                                    \
> >> +            do {                                                    \
> >> +                    type x = __raw_read##bwl(addr);                 \
> >> +                    *buf++ = x;                                     \
> >> +            } while (--count);                                      \
> >> +    }                                                               \
> >> +}                                                                   \
> >> +                                                                    \
> >> +static inline void writes##bwl(volatile void __iomem *addr,         \
> >> +                            const void *buffer, unsigned int count) \
> >> +{                                                                   \
> >> +    if (count) {                                                    \
> >> +            const type *buf = buffer;                               \
> >> +                                                                    \
> >> +            do {                                                    \
> >> +                    __raw_write##bwl(*buf++, addr);                 \
> >> +            } while (--count);                                      \
> >> +    }                                                               \
> >> +}
> >> +
> >> +BUILDS_RW(b, u8)
> > 
> > Why is this in here?
> the readsb/writesb are defined in asm-generic/io.h which is included later, but the redefined insb/outsb need
> to call them. Without these readsb/writesb definition before insb/outsb redefined, compile error occur.
> 
> It seems that copy all the definitions of "asm-generic/io.h" is not a good idea, so I move the definitions of
> those function needed here....
> 
> Ok. I think your idea below defining in(s)/out(s) in a c file can solve this issue.
> 
> #ifdef CONFIG_ARM64_INDIRECT_PIO
> #define inb inb
> extern u8 inb(unsigned long addr);
> 
> #define outb outb
> extern void outb(u8 value, unsigned long addr);
> 
> #define insb insb
> extern void insb(unsigned long addr, void *buffer, unsigned int count);
> 
> #define outsb outsb
> extern void outsb(unsigned long addr, const void *buffer, unsigned int count);
> #endif
> 
> and definitions of all these functions are in extio.c :
> 
> u8 inb(unsigned long addr)
> {
>         if (!arm64_extio_ops || arm64_extio_ops->start > addr ||
>                         arm64_extio_ops->end < addr)
>                 return readb(PCI_IOBASE + addr);
>         else
>                 return arm64_extio_ops->pfin ?
>                         arm64_extio_ops->pfin(arm64_extio_ops->devpara,
>                                 addr + arm64_extio_ops->ptoffset, NULL,
>                                 sizeof(u8), 1) : -1;
> }
> .....

Yes, sounds good.

> >> @@ -149,6 +185,60 @@ static inline u64 __raw_readq(const volatile void __iomem *addr)
> >>  #define IO_SPACE_LIMIT              (PCI_IO_SIZE - 1)
> >>  #define PCI_IOBASE          ((void __iomem *)PCI_IO_START)
> >>  
> >> +
> >> +/*
> >> + * redefine the in(s)b/out(s)b for indirect-IO.
> >> + */
> >> +#define inb inb
> >> +static inline u8 inb(unsigned long addr)
> >> +{
> >> +#ifdef CONFIG_ARM64_INDIRECT_PIO
> >> +    if (arm64_extio_ops && arm64_extio_ops->start <= addr &&
> >> +                    addr <= arm64_extio_ops->end)
> >> +            return extio_inb(addr);
> >> +#endif
> >> +    return readb(PCI_IOBASE + addr);
> >> +}
> >> +
> > 
> > Looks ok, but you only seem to do this for the 8-bit
> > accessors, when it should be done for 16-bit and 32-bit
> > ones as well for consistency.
> Hip06 LPC only support 8-bit I/O operations on the designated port.

That is an interesting limitation. Maybe still call the extio operations
and have them do WARN_ON_ONCE() instead?

If you get a driver that calls inw/outw on the range that is owned
by the LPC bus, you otherwise get an unhandled page fault in kernel
space, which is not as nice.

> >> diff --git a/drivers/bus/extio.c b/drivers/bus/extio.c
> >> new file mode 100644
> >> index 0000000..1e7a9c5
> >> --- /dev/null
> >> +++ b/drivers/bus/extio.c
> >> @@ -0,0 +1,66 @@
> > 
> > This is in a globally visible directory
> > 
> >> +
> >> +struct extio_ops *arm64_extio_ops;
> > 
> > But the identifier uses an architecture specific prefix. Either
> > move the whole file into arch/arm64, or make the naming so that
> > it can be used for everything.
> 
> I perfer to move the whole file into arch/arm64, extio.h will be moved to arch/arm64/include/asm;

Ok, that simplifies it a lot, you can just do everything in asm/io.h then.

	Arnd

^ permalink raw reply

* [PATCH 2/2] arm64: dts: marvell: enable MSI for PCIe on Armada 7K/8K
From: Gregory CLEMENT @ 2016-09-14 14:21 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1472744484-19132-3-git-send-email-thomas.petazzoni@free-electrons.com>

Hi Thomas,
 
 On jeu., sept. 01 2016, Thomas Petazzoni <thomas.petazzoni@free-electrons.com> wrote:

> This commit adds a reference to the appropriate MSI controller in the
> description of the PCIe controllers on Marvel Armada 7K and 8K
> platforms.

Applied on mvebu/dt64

Thanks,

Gregory

>
> Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
> ---
>  arch/arm64/boot/dts/marvell/armada-cp110-master.dtsi | 3 +++
>  arch/arm64/boot/dts/marvell/armada-cp110-slave.dtsi  | 3 +++
>  2 files changed, 6 insertions(+)
>
> diff --git a/arch/arm64/boot/dts/marvell/armada-cp110-master.dtsi b/arch/arm64/boot/dts/marvell/armada-cp110-master.dtsi
> index ceb83b0..ff469e1 100644
> --- a/arch/arm64/boot/dts/marvell/armada-cp110-master.dtsi
> +++ b/arch/arm64/boot/dts/marvell/armada-cp110-master.dtsi
> @@ -177,6 +177,7 @@
>  			#interrupt-cells = <1>;
>  			device_type = "pci";
>  			dma-coherent;
> +			msi-parent = <&gic_v2m0>;
>  
>  			bus-range = <0 0xff>;
>  			ranges =
> @@ -202,6 +203,7 @@
>  			#interrupt-cells = <1>;
>  			device_type = "pci";
>  			dma-coherent;
> +			msi-parent = <&gic_v2m0>;
>  
>  			bus-range = <0 0xff>;
>  			ranges =
> @@ -228,6 +230,7 @@
>  			#interrupt-cells = <1>;
>  			device_type = "pci";
>  			dma-coherent;
> +			msi-parent = <&gic_v2m0>;
>  
>  			bus-range = <0 0xff>;
>  			ranges =
> diff --git a/arch/arm64/boot/dts/marvell/armada-cp110-slave.dtsi b/arch/arm64/boot/dts/marvell/armada-cp110-slave.dtsi
> index 2d863f2..43cecf0 100644
> --- a/arch/arm64/boot/dts/marvell/armada-cp110-slave.dtsi
> +++ b/arch/arm64/boot/dts/marvell/armada-cp110-slave.dtsi
> @@ -177,6 +177,7 @@
>  			#interrupt-cells = <1>;
>  			device_type = "pci";
>  			dma-coherent;
> +			msi-parent = <&gic_v2m0>;
>  
>  			bus-range = <0 0xff>;
>  			ranges =
> @@ -202,6 +203,7 @@
>  			#interrupt-cells = <1>;
>  			device_type = "pci";
>  			dma-coherent;
> +			msi-parent = <&gic_v2m0>;
>  
>  			bus-range = <0 0xff>;
>  			ranges =
> @@ -228,6 +230,7 @@
>  			#interrupt-cells = <1>;
>  			device_type = "pci";
>  			dma-coherent;
> +			msi-parent = <&gic_v2m0>;
>  
>  			bus-range = <0 0xff>;
>  			ranges =
> -- 
> 2.7.4
>

-- 
Gregory Clement, Free Electrons
Kernel, drivers, real-time and embedded Linux
development, consulting, training and support.
http://free-electrons.com

^ permalink raw reply


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