Linux-ARM-Kernel Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 1/2] ABI: rtc-ab8500: fix rtc_calibration documentation
From: Mauro Carvalho Chehab @ 2016-10-29 10:10 UTC (permalink / raw)
  To: linux-arm-kernel

The "What:" field at the ABI should describe the location of
the ABI, e. g. the position under a mounted sysfs.

Fix it.

Cc: Mark Godfrey <mark.godfrey@stericsson.com>
Cc: Linus Walleij <linus.walleij@linaro.org>
Cc: Alessandro Zummo <a.zummo@towertech.it>
Cc: Alexandre Belloni <alexandre.belloni@free-electrons.com>
Cc: linux-arm-kernel at lists.infradead.org
Cc: rtc-linux at googlegroups.com
Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
---
 .../ABI/testing/sysfs-class-rtc-rtc0-device-rtc_calibration          | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/Documentation/ABI/testing/sysfs-class-rtc-rtc0-device-rtc_calibration b/Documentation/ABI/testing/sysfs-class-rtc-rtc0-device-rtc_calibration
index 4cf1e72222d9..ec950c93e5c6 100644
--- a/Documentation/ABI/testing/sysfs-class-rtc-rtc0-device-rtc_calibration
+++ b/Documentation/ABI/testing/sysfs-class-rtc-rtc0-device-rtc_calibration
@@ -1,8 +1,9 @@
-What:           Attribute for calibrating ST-Ericsson AB8500 Real Time Clock
+What:           /sys/class/rtc/rtc0/device/rtc_calibration
 Date:           Oct 2011
 KernelVersion:  3.0
 Contact:        Mark Godfrey <mark.godfrey@stericsson.com>
-Description:    The rtc_calibration attribute allows the userspace to
+Description:    Attribute for calibrating ST-Ericsson AB8500 Real Time Clock
+		The rtc_calibration attribute allows the userspace to
                 calibrate the AB8500.s 32KHz Real Time Clock.
                 Every 60 seconds the AB8500 will correct the RTC's value
                 by adding to it the value of this attribute.
-- 
2.7.4

^ permalink raw reply related

* [PATCH 1/2] ABI: rtc-ab8500: fix rtc_calibration documentation
From: Linus Walleij @ 2016-10-29 10:22 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <364a36215c44e0c2785911e9d9259cd866283cb9.1477735797.git.mchehab@s-opensource.com>

On Sat, Oct 29, 2016 at 12:10 PM, Mauro Carvalho Chehab
<mchehab@s-opensource.com> wrote:

> The "What:" field at the ABI should describe the location of
> the ABI, e. g. the position under a mounted sysfs.
>
> Fix it.
>
> Cc: Mark Godfrey <mark.godfrey@stericsson.com>
> Cc: Linus Walleij <linus.walleij@linaro.org>
> Cc: Alessandro Zummo <a.zummo@towertech.it>
> Cc: Alexandre Belloni <alexandre.belloni@free-electrons.com>
> Cc: linux-arm-kernel at lists.infradead.org
> Cc: rtc-linux at googlegroups.com
> Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>

Acked-by: Linus Walleij <linus.walleij@linaro.org>

Yours,
Linus Walleij

^ permalink raw reply

* [PATCH] drm/sun4i: Add a few formats
From: Chen-Yu Tsai @ 2016-10-29 10:25 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20161027143505.rblgbz5uqjynrtjk@lukather>

On Thu, Oct 27, 2016 at 10:35 PM, Maxime Ripard
<maxime.ripard@free-electrons.com> wrote:
> Hi,
>
> On Tue, Oct 25, 2016 at 08:42:26AM +0800, Chen-Yu Tsai wrote:
>> On Mon, Oct 24, 2016 at 10:40 PM, Maxime Ripard
>> <maxime.ripard@free-electrons.com> wrote:
>> > Hi,
>> >
>> > On Fri, Oct 21, 2016 at 11:15:32AM +0800, Chen-Yu Tsai wrote:
>> >> On Tue, Oct 18, 2016 at 4:46 PM, Maxime Ripard
>> >> <maxime.ripard@free-electrons.com> wrote:
>> >> > The planes can do more than what was previously exposed. Add support for
>> >> > them.
>> >> >
>> >> > Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
>> >> > ---
>> >> >  drivers/gpu/drm/sun4i/sun4i_backend.c | 20 ++++++++++++++++++++
>> >> >  drivers/gpu/drm/sun4i/sun4i_layer.c   |  6 ++++++
>> >> >  2 files changed, 26 insertions(+)
>> >> >
>> >> > diff --git a/drivers/gpu/drm/sun4i/sun4i_backend.c b/drivers/gpu/drm/sun4i/sun4i_backend.c
>> >> > index afb7ddf660ef..b184a476a480 100644
>> >> > --- a/drivers/gpu/drm/sun4i/sun4i_backend.c
>> >> > +++ b/drivers/gpu/drm/sun4i/sun4i_backend.c
>> >> > @@ -96,6 +96,22 @@ static int sun4i_backend_drm_format_to_layer(struct drm_plane *plane,
>> >> >                 *mode = SUN4I_BACKEND_LAY_FBFMT_ARGB8888;
>> >> >                 break;
>> >> >
>> >> > +       case DRM_FORMAT_ARGB4444:
>> >> > +               *mode = SUN4I_BACKEND_LAY_FBFMT_ARGB4444;
>> >> > +               break;
>> >> > +
>> >> > +       case DRM_FORMAT_ARGB1555:
>> >> > +               *mode = SUN4I_BACKEND_LAY_FBFMT_ARGB1555;
>> >> > +               break;
>> >> > +
>> >> > +       case DRM_FORMAT_RGBA5551:
>> >> > +               *mode = SUN4I_BACKEND_LAY_FBFMT_RGBA5551;
>> >> > +               break;
>> >> > +
>> >> > +       case DRM_FORMAT_RGBA4444:
>> >> > +               *mode = SUN4I_BACKEND_LAY_FBFMT_RGBA4444;
>> >>
>> >> The A20 manual only lists ARGB4444, not RGBA4444. There might be
>> >> some discrepancy here. We can deal with them
>> >
>> > Hmm, yes, that's weird. But I guess this would be part of porting it
>> > to the A20.
>> >
>> >> Also there are some more formats missing from the list, could you
>> >> add them as well?
>> >
>> > Which one do you refer to?
>>
>> RGB556 and RGB655.
>
> These formats are not supported by Linux yet though.

I see. Sorry for the noise.

Acked-by: Chen-Yu Tsai <wens@csie.org>

>
> Thanks,
> Maxime
>
> --
> Maxime Ripard, Free Electrons
> Embedded Linux and Kernel engineering
> http://free-electrons.com

^ permalink raw reply

* [PATCH v3 0/2] ARM: dts: sun6i: hummingbird-a31: Enable display output through VGA bridge
From: Chen-Yu Tsai @ 2016-10-29 11:06 UTC (permalink / raw)
  To: linux-arm-kernel

Hi,

This is v3 of my sun6i DRM/KMS display enablement series. Most of the
patches in v2 were merged, leaving only the dumb-vga-dac patch and the
hummingbird-a31 VGA output patch.

A few things were changed, mainly the DAC enable method from a GPIO
to a regulator supply.

Changes since v2:

  - Changed the enable-gpio of dumb-vga-dac to vdd-supply regulator.
    This better matches the hardware that I have: the DAC has a fixed
    regulator dropping the voltage from the board-wide 5V to 3.3V the
    DAC uses. The regulator is controlled through a GPIO pin.

  - Renamed the node of the VGA connector from "vga" to "vga-connector".

  - Renamed the node of the VGA DAC from "bridge" to "vga-dac".


Regards
ChenYu


Chen-Yu Tsai (2):
  drm/bridge: dumb-vga-dac: Support a VDD regulator supply
  ARM: dts: sun6i: hummingbird-a31: Enable display output through VGA
    bridge

 .../bindings/display/bridge/dumb-vga-dac.txt       |  2 +
 arch/arm/boot/dts/sun6i-a31-hummingbird.dts        | 76 ++++++++++++++++++++++
 drivers/gpu/drm/bridge/dumb-vga-dac.c              | 35 ++++++++++
 3 files changed, 113 insertions(+)

-- 
2.9.3

^ permalink raw reply

* [PATCH v3 1/2] drm/bridge: dumb-vga-dac: Support a VDD regulator supply
From: Chen-Yu Tsai @ 2016-10-29 11:06 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20161029110611.28951-1-wens@csie.org>

Some dumb VGA DACs are active components which require external power.
Add support for specifying a regulator as its power supply.

Signed-off-by: Chen-Yu Tsai <wens@csie.org>
---
 .../bindings/display/bridge/dumb-vga-dac.txt       |  2 ++
 drivers/gpu/drm/bridge/dumb-vga-dac.c              | 35 ++++++++++++++++++++++
 2 files changed, 37 insertions(+)

diff --git a/Documentation/devicetree/bindings/display/bridge/dumb-vga-dac.txt b/Documentation/devicetree/bindings/display/bridge/dumb-vga-dac.txt
index 003bc246a270..164cbb15f04c 100644
--- a/Documentation/devicetree/bindings/display/bridge/dumb-vga-dac.txt
+++ b/Documentation/devicetree/bindings/display/bridge/dumb-vga-dac.txt
@@ -16,6 +16,8 @@ graph bindings specified in Documentation/devicetree/bindings/graph.txt.
 - Video port 0 for RGB input
 - Video port 1 for VGA output
 
+Optional properties:
+- vdd-supply: Power supply for DAC
 
 Example
 -------
diff --git a/drivers/gpu/drm/bridge/dumb-vga-dac.c b/drivers/gpu/drm/bridge/dumb-vga-dac.c
index afec232185a7..59781e031220 100644
--- a/drivers/gpu/drm/bridge/dumb-vga-dac.c
+++ b/drivers/gpu/drm/bridge/dumb-vga-dac.c
@@ -12,6 +12,7 @@
 
 #include <linux/module.h>
 #include <linux/of_graph.h>
+#include <linux/regulator/consumer.h>
 
 #include <drm/drmP.h>
 #include <drm/drm_atomic_helper.h>
@@ -23,6 +24,7 @@ struct dumb_vga {
 	struct drm_connector	connector;
 
 	struct i2c_adapter	*ddc;
+	struct regulator	*vdd;
 };
 
 static inline struct dumb_vga *
@@ -124,8 +126,33 @@ static int dumb_vga_attach(struct drm_bridge *bridge)
 	return 0;
 }
 
+static void dumb_vga_enable(struct drm_bridge *bridge)
+{
+	struct dumb_vga *vga = drm_bridge_to_dumb_vga(bridge);
+	int ret;
+
+	if (!IS_ERR(vga->vdd)) {
+		ret = regulator_enable(vga->vdd);
+
+		if (ret) {
+			DRM_ERROR("Failed to enable vdd regulator: %d\n", ret);
+			return;
+		}
+	}
+}
+
+static void dumb_vga_disable(struct drm_bridge *bridge)
+{
+	struct dumb_vga *vga = drm_bridge_to_dumb_vga(bridge);
+
+	if (!IS_ERR(vga->vdd))
+		regulator_disable(vga->vdd);
+}
+
 static const struct drm_bridge_funcs dumb_vga_bridge_funcs = {
 	.attach		= dumb_vga_attach,
+	.enable		= dumb_vga_enable,
+	.disable	= dumb_vga_disable,
 };
 
 static struct i2c_adapter *dumb_vga_retrieve_ddc(struct device *dev)
@@ -169,6 +196,14 @@ static int dumb_vga_probe(struct platform_device *pdev)
 		return -ENOMEM;
 	platform_set_drvdata(pdev, vga);
 
+	vga->vdd = devm_regulator_get_optional(&pdev->dev, "vdd");
+	if (IS_ERR(vga->vdd)) {
+		ret = PTR_ERR(vga->vdd);
+		if (ret == -EPROBE_DEFER)
+			return -EPROBE_DEFER;
+		dev_dbg(&pdev->dev, "No vdd regulator found: %d\n", ret);
+	}
+
 	vga->ddc = dumb_vga_retrieve_ddc(&pdev->dev);
 	if (IS_ERR(vga->ddc)) {
 		if (PTR_ERR(vga->ddc) == -ENODEV) {
-- 
2.9.3

^ permalink raw reply related

* [PATCH v3 2/2] ARM: dts: sun6i: hummingbird-a31: Enable display output through VGA bridge
From: Chen-Yu Tsai @ 2016-10-29 11:06 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20161029110611.28951-1-wens@csie.org>

The Hummingbird A31 board has a VGA DAC which converts RGB output
from the LCD interface to VGA analog signals.

Add nodes for the VGA DAC, its power supply, and enable this part
of the display pipeline.

Signed-off-by: Chen-Yu Tsai <wens@csie.org>
---
 arch/arm/boot/dts/sun6i-a31-hummingbird.dts | 76 +++++++++++++++++++++++++++++
 1 file changed, 76 insertions(+)

diff --git a/arch/arm/boot/dts/sun6i-a31-hummingbird.dts b/arch/arm/boot/dts/sun6i-a31-hummingbird.dts
index 9a74637f677f..1ab28b2108fe 100644
--- a/arch/arm/boot/dts/sun6i-a31-hummingbird.dts
+++ b/arch/arm/boot/dts/sun6i-a31-hummingbird.dts
@@ -63,6 +63,62 @@
 		stdout-path = "serial0:115200n8";
 	};
 
+	vga-connector {
+		compatible = "vga-connector";
+
+		port {
+			vga_con_in: endpoint {
+				remote-endpoint = <&vga_dac_out>;
+			};
+		};
+	};
+
+	vga-dac {
+		compatible = "dumb-vga-dac";
+		vdd-supply = <&reg_vga_3v3>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		ports {
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			port at 0 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				reg = <0>;
+
+				vga_dac_in: endpoint at 0 {
+					reg = <0>;
+					remote-endpoint = <&tcon0_out_vga>;
+				};
+			};
+
+			port at 1 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				reg = <1>;
+
+				vga_dac_out: endpoint at 0 {
+					reg = <0>;
+					remote-endpoint = <&vga_con_in>;
+				};
+			};
+		};
+	};
+
+	reg_vga_3v3: vga_3v3_regulator {
+		compatible = "regulator-fixed";
+		pinctrl-names = "default";
+		pinctrl-0 = <&vga_3v3_enable_pin_hummingbird>;
+		regulator-name = "vga-3v3";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+		regulator-boot-on;
+		enable-active-high;
+		gpio = <&pio 7 25 GPIO_ACTIVE_HIGH>; /* PH25 */
+	};
+
 	wifi_pwrseq: wifi_pwrseq {
 		compatible = "mmc-pwrseq-simple";
 		reset-gpios = <&pio 6 10 GPIO_ACTIVE_LOW>; /* PG10 */
@@ -166,6 +222,13 @@
 		allwinner,pull = <SUN4I_PINCTRL_PULL_UP>;
 	};
 
+	vga_3v3_enable_pin_hummingbird: vga_3v3_enable_pin {
+		allwinner,pins = "PH25";
+		allwinner,function = "gpio_out";
+		allwinner,drive = <SUN4I_PINCTRL_10_MA>;
+		allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
+	};
+
 	wifi_reset_pin_hummingbird: wifi_reset_pin at 0 {
 		allwinner,pins = "PG10";
 		allwinner,function = "gpio_out";
@@ -245,6 +308,19 @@
 	status = "okay";
 };
 
+&tcon0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&lcd0_rgb888_pins>;
+	status = "okay";
+};
+
+&tcon0_out {
+	tcon0_out_vga: endpoint at 0 {
+		reg = <0>;
+		remote-endpoint = <&vga_dac_in>;
+	};
+};
+
 &uart0 {
 	pinctrl-names = "default";
 	pinctrl-0 = <&uart0_pins_a>;
-- 
2.9.3

^ permalink raw reply related

* [PATCH] ARM: BCM5301X: Add back handler ignoring external imprecise aborts
From: Rafał Miłecki @ 2016-10-29 11:12 UTC (permalink / raw)
  To: linux-arm-kernel

From: Rafa? Mi?ecki <rafal@milecki.pl>

Since early BCM5301X days we got abort handler that was removed by
commit 937b12306ea79 ("ARM: BCM5301X: remove workaround imprecise abort
fault handler"). It assumed we need to deal only with pending aborts
left by the bootloader. Unfortunately this isn't true for BCM5301X.

When probing PCI config space (device enumeration) it is expected to
have master aborts on the PCI bus. Most bridges don't forward (or they
allow disabling it) these errors onto the AXI/AMBA bus but not the
Northstar (BCM5301X) one.

iProc PCIe controller on Northstar seems to be some older one, without
a control register for errors forwarding. It means we need to workaround
this at platform level. All newer platforms are not affected by this
issue.

Signed-off-by: Rafa? Mi?ecki <rafal@milecki.pl>
---
 arch/arm/mach-bcm/bcm_5301x.c | 28 ++++++++++++++++++++++++++++
 1 file changed, 28 insertions(+)

diff --git a/arch/arm/mach-bcm/bcm_5301x.c b/arch/arm/mach-bcm/bcm_5301x.c
index c8830a2..fe067f6 100644
--- a/arch/arm/mach-bcm/bcm_5301x.c
+++ b/arch/arm/mach-bcm/bcm_5301x.c
@@ -9,14 +9,42 @@
 #include <asm/hardware/cache-l2x0.h>
 
 #include <asm/mach/arch.h>
+#include <asm/siginfo.h>
+#include <asm/signal.h>
+
+#define FSR_EXTERNAL		(1 << 12)
+#define FSR_READ		(0 << 10)
+#define FSR_IMPRECISE		0x0406
 
 static const char *const bcm5301x_dt_compat[] __initconst = {
 	"brcm,bcm4708",
 	NULL,
 };
 
+static int bcm5301x_abort_handler(unsigned long addr, unsigned int fsr,
+				  struct pt_regs *regs)
+{
+	/*
+	 * We want to ignore aborts forwarded from the PCIe bus that are
+	 * expected and shouldn't really be passed by the PCIe controller.
+	 * The biggest disadvantage is the same FSR code may be reported when
+	 * reading non-existing APB register and we shouldn't ignore that.
+	 */
+	if (fsr == (FSR_EXTERNAL | FSR_READ | FSR_IMPRECISE))
+		return 0;
+
+	return 1;
+}
+
+static void __init bcm5301x_init_early(void)
+{
+	hook_fault_code(16 + 6, bcm5301x_abort_handler, SIGBUS, BUS_OBJERR,
+			"imprecise external abort");
+}
+
 DT_MACHINE_START(BCM5301X, "BCM5301X")
 	.l2c_aux_val	= 0,
 	.l2c_aux_mask	= ~0,
 	.dt_compat	= bcm5301x_dt_compat,
+	.init_early	= bcm5301x_init_early,
 MACHINE_END
-- 
2.9.3

^ permalink raw reply related

* [PATCH] KVM: arm/arm64: vgic: Prevent VGIC_ADDR_TO_INTID from emiting divisions
From: Marc Zyngier @ 2016-10-29 11:19 UTC (permalink / raw)
  To: linux-arm-kernel

Using non-constant number of bits for VGIC_ADDR_TO_INTID() leads
to gcc 6.1 emiting calls to __aeabi_uldivmod, which the kernel
does not implement.

As we really don't want to implement complex division in the kernel,
the only other option is to prove to the compiler that there is only
a few values that are possible for the number of bits per IRQ, and
that they are all power of 2.

We turn the VGIC_ADDR_TO_INTID macro into a switch that looks for
the supported set of values (1, 2, 8, 64), and perform the computation
accordingly. When "bits" is a constant, the compiler optimizes
away the other cases. If not, we end-up with a small number of cases
that GCC optimises reasonably well. Out of range values are detected
both at build time (constants) and at run time (variables).

Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
This should be applied *before* Andre's patch fixing out of bound SPIs.

 virt/kvm/arm/vgic/vgic-mmio.h | 33 ++++++++++++++++++++++++++++++++-
 1 file changed, 32 insertions(+), 1 deletion(-)

diff --git a/virt/kvm/arm/vgic/vgic-mmio.h b/virt/kvm/arm/vgic/vgic-mmio.h
index 4c34d39..a457282 100644
--- a/virt/kvm/arm/vgic/vgic-mmio.h
+++ b/virt/kvm/arm/vgic/vgic-mmio.h
@@ -57,10 +57,41 @@ extern struct kvm_io_device_ops kvm_io_gic_ops;
  * multiplication with the inverted fraction, and scale up both the
  * numerator and denominator with 8 to support at most 64 bits per IRQ:
  */
-#define VGIC_ADDR_TO_INTID(addr, bits)  (((addr) & VGIC_ADDR_IRQ_MASK(bits)) * \
+#define __VGIC_ADDR_INTID(addr, bits)  (((addr) & VGIC_ADDR_IRQ_MASK(bits)) * \
 					64 / (bits) / 8)
 
 /*
+ * Perform the same computation, but also handle non-constant number
+ * of bits. We only care about the few cases that are required by
+ * GICv2/v3.
+ */
+#define VGIC_ADDR_TO_INTID(addr, bits)				\
+	({							\
+		u32 __v;					\
+		switch((bits)) {				\
+		case 1:						\
+			__v = __VGIC_ADDR_INTID((addr), 1);	\
+			break;					\
+		case 2:						\
+			__v = __VGIC_ADDR_INTID((addr), 2);	\
+			break;					\
+		case 8:						\
+			__v = __VGIC_ADDR_INTID((addr), 8);	\
+			break;					\
+		case 64:					\
+			__v = __VGIC_ADDR_INTID((addr), 64);	\
+			break;					\
+		default:					\
+			if (__builtin_constant_p((bits)))	\
+				BUILD_BUG();			\
+			else					\
+				BUG();				\
+		}						\
+								\
+		__v;						\
+	})
+
+/*
  * Some VGIC registers store per-IRQ information, with a different number
  * of bits per IRQ. For those registers this macro is used.
  * The _WITH_LENGTH version instantiates registers with a fixed length
-- 
2.9.3

^ permalink raw reply related

* [Bug] ARM: mxs: STI: console can't wake up from freeze
From: Stefan Wahren @ 2016-10-29 11:44 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20161023133134.GI1041@n2100.armlinux.org.uk>

Hi Russell,

> Russell King - ARM Linux <linux@armlinux.org.uk> hat am 23. Oktober 2016 um
> 15:31 geschrieben:
> 
> 
> On Sun, Oct 23, 2016 at 11:19:26AM +0200, Stefan Wahren wrote:
> > Hi,
> > 
> > i'm faced with the issue that on i.MX28 the console is unable to wake up
> > from
> > freeze ( suspend to idle). I tested it with Linux 4.9-rc1, 4.8 and 3.18 (
> > cmdline has
> > no_console_suspend=1 ) and also with a i.MX23 with the same result. The
> > suspend
> > seems to work, but there is no reaction to the console after the freeze
> > except
> > an hung task warning after some time:
> 
> I bet if you remove "no_console_suspend" (it's not =1) then it'll work.

unfortunately not:

Setting: no_console_suspend not in cmdline, Debug UART wakeup source enabled

echo mem > /sys/power/state

Result: Able to wakeup via Debug UART
Expected result: Able to wakeup via Debug UART

---

Setting: no_console_suspend not in cmdline, Debug UART wakeup source enabled

echo freeze > /sys/power/state

Result: Unable to wakeup via Debug UART (no hung task warning)
Expected result: Able to wakeup via Debug UART

---

Setting: no_console_suspend in cmdline, Debug UART as wakeup source enabled

echo mem > /sys/power/state

Result: Able to wakeup via Debug UART
Expected result: Able to wakeup via Debug UART

---

Setting: no_console_suspend in cmdline, Debug UART as wake source enabled

echo freeze > /sys/power/state

Result: Unable to wakeup via Debug UART (hung task warning after some minutes)
Expected result: Able to wakeup Debug via UART

---

Setting: no_console_suspend in cmdline, Debug UART as wake source disabled

echo mem > /sys/power/state

Result: Able to wakeup via Debug UART
Expected result: Able to wakeup via Debug UART

---

Setting: no_console_suspend in cmdline, Debug UART as wake source disabled

echo freeze > /sys/power/state

Result: Unable to wakeup via UART (hung task warning after some minutes)
Expected result: Able to wakeup via Debug UART

---

Here some more relevant information about the setup:

The console is operating on Debug UART which is a ARM PL011. The following
kernel configs are set:

CONFIG_PM_SLEEP=y
CONFIG_SUSPEND=y
CONFIG_SUSPEND_FREEZER=y
CONFIG_PM=y

^ permalink raw reply

* [PATCH v4 0/5] Cavium ThunderX uncore PMU support
From: Jan Glauber @ 2016-10-29 11:55 UTC (permalink / raw)
  To: linux-arm-kernel

As discussed, changed perf_sw_context -> perf_invalid_context.

Not changed:
- Stick to NUMA node ID to detect the socket a device belongs to but made
  uncore depend on CONFIG_NUMA.
- Stick to initcall for uncore framework because it is easier to do the
  scanning for the same type of PCI devices, also I don't know if the PCI layer
  would allow for several drivers to register for the same device ID.

Patches are against 4.9.0-rc2.

Changes to v3:
- use perf_invalid_context

Changes to v2:
- Embedded struct pmu and killed uncore->type
- Simplified add functions
- Unified functions where possible into a common implementation
- Use arrays to translate non-contiguous counter addresses to event_id's
  visible to the user
- Sorted includes
- Got rid of division for previous counter values
- Removed unneeded WARN_ONs
- Use sizeof(*ptr)
- Use bool for event_valid return
- Fixed HES_STOPPED logic
- Added some design notes and improved (hopefully) comments
- Removed pass1 counter support for now
- Merged EVENT_ATTR and EVENT_PTR defines into one (unreadable) thing
- Use pmu_enable|disable to start|stop the OCX TLK counter set
- Moved cpumask into thunder_uncore struct
- Switched to new cpuhp stuff. I still don't care about the CPU location
  used to access an uncore device, it may cross the CCPI and
  we'll pay a performance penalty. We might optimize this later, for now
  I feel it is not worth the time optimizing it.

--------------------------

Jan Glauber (5):
  arm64: perf: Basic uncore counter support for Cavium ThunderX SOC
  arm64: perf: Cavium ThunderX L2C TAD uncore support
  arm64: perf: Cavium ThunderX L2C CBC uncore support
  arm64: perf: Cavium ThunderX LMC uncore support
  arm64: perf: Cavium ThunderX OCX TLK uncore support

 drivers/perf/Kconfig                        |  13 +
 drivers/perf/Makefile                       |   1 +
 drivers/perf/uncore/Makefile                |   5 +
 drivers/perf/uncore/uncore_cavium.c         | 355 ++++++++++++++++++++++++++
 drivers/perf/uncore/uncore_cavium.h         |  75 ++++++
 drivers/perf/uncore/uncore_cavium_l2c_cbc.c | 148 +++++++++++
 drivers/perf/uncore/uncore_cavium_l2c_tad.c | 379 ++++++++++++++++++++++++++++
 drivers/perf/uncore/uncore_cavium_lmc.c     | 118 +++++++++
 drivers/perf/uncore/uncore_cavium_ocx_tlk.c | 344 +++++++++++++++++++++++++
 include/linux/cpuhotplug.h                  |   1 +
 10 files changed, 1439 insertions(+)
 create mode 100644 drivers/perf/uncore/Makefile
 create mode 100644 drivers/perf/uncore/uncore_cavium.c
 create mode 100644 drivers/perf/uncore/uncore_cavium.h
 create mode 100644 drivers/perf/uncore/uncore_cavium_l2c_cbc.c
 create mode 100644 drivers/perf/uncore/uncore_cavium_l2c_tad.c
 create mode 100644 drivers/perf/uncore/uncore_cavium_lmc.c
 create mode 100644 drivers/perf/uncore/uncore_cavium_ocx_tlk.c

-- 
2.9.0.rc0.21.g7777322

^ permalink raw reply

* [PATCH v4 1/5] arm64: perf: Basic uncore counter support for Cavium ThunderX SOC
From: Jan Glauber @ 2016-10-29 11:55 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <cover.1477741719.git.jglauber@cavium.com>

Provide "uncore" facilities for different non-CPU performance
counter units.

The uncore PMUs can be found under /sys/bus/event_source/devices.
All counters are exported via sysfs in the corresponding events
files under the PMU directory so the perf tool can list the event names.

There are some points that are special in this implementation:

1) The PMU detection relies on PCI device detection. If a
   matching PCI device is found the PMU is created. The code can deal
   with multiple units of the same type, e.g. more than one memory
   controller.

2) Counters are summarized across different units of the same type
   on one NUMA node but not across NUMA nodes.
   For instance L2C TAD 0..7 are presented as a single counter
   (adding the values from TAD 0 to 7). Although losing the ability
   to read a single value the merged values are easier to use.

3) The counters are not CPU related. A random CPU is picked regardless
   of the NUMA node. There is a small performance penalty for accessing
   counters on a remote note but reading a performance counter is a
   slow operation anyway.

Signed-off-by: Jan Glauber <jglauber@cavium.com>
---
 drivers/perf/Kconfig                |  13 ++
 drivers/perf/Makefile               |   1 +
 drivers/perf/uncore/Makefile        |   1 +
 drivers/perf/uncore/uncore_cavium.c | 351 ++++++++++++++++++++++++++++++++++++
 drivers/perf/uncore/uncore_cavium.h |  71 ++++++++
 include/linux/cpuhotplug.h          |   1 +
 6 files changed, 438 insertions(+)
 create mode 100644 drivers/perf/uncore/Makefile
 create mode 100644 drivers/perf/uncore/uncore_cavium.c
 create mode 100644 drivers/perf/uncore/uncore_cavium.h

diff --git a/drivers/perf/Kconfig b/drivers/perf/Kconfig
index 4d5c5f9..3266c87 100644
--- a/drivers/perf/Kconfig
+++ b/drivers/perf/Kconfig
@@ -19,4 +19,17 @@ config XGENE_PMU
         help
           Say y if you want to use APM X-Gene SoC performance monitors.
 
+config UNCORE_PMU
+	bool
+
+config UNCORE_PMU_CAVIUM
+	depends on PERF_EVENTS && NUMA && ARM64
+	bool "Cavium uncore PMU support"
+	select UNCORE_PMU
+	default y
+	help
+	  Say y if you want to access performance counters of subsystems
+	  on a Cavium SOC like cache controller, memory controller or
+	  processor interconnect.
+
 endmenu
diff --git a/drivers/perf/Makefile b/drivers/perf/Makefile
index b116e98..d6c02c9 100644
--- a/drivers/perf/Makefile
+++ b/drivers/perf/Makefile
@@ -1,2 +1,3 @@
 obj-$(CONFIG_ARM_PMU) += arm_pmu.o
 obj-$(CONFIG_XGENE_PMU) += xgene_pmu.o
+obj-y += uncore/
diff --git a/drivers/perf/uncore/Makefile b/drivers/perf/uncore/Makefile
new file mode 100644
index 0000000..6130e18
--- /dev/null
+++ b/drivers/perf/uncore/Makefile
@@ -0,0 +1 @@
+obj-$(CONFIG_UNCORE_PMU_CAVIUM) += uncore_cavium.o
diff --git a/drivers/perf/uncore/uncore_cavium.c b/drivers/perf/uncore/uncore_cavium.c
new file mode 100644
index 0000000..a7b4277
--- /dev/null
+++ b/drivers/perf/uncore/uncore_cavium.c
@@ -0,0 +1,351 @@
+/*
+ * Cavium Thunder uncore PMU support.
+ *
+ * Copyright (C) 2015,2016 Cavium Inc.
+ * Author: Jan Glauber <jan.glauber@cavium.com>
+ */
+
+#include <linux/cpufeature.h>
+#include <linux/numa.h>
+#include <linux/slab.h>
+
+#include "uncore_cavium.h"
+
+/*
+ * Some notes about the various counters supported by this "uncore" PMU
+ * and the design:
+ *
+ * All counters are 64 bit long.
+ * There are no overflow interrupts.
+ * Counters are summarized per node/socket.
+ * Most devices appear as separate PCI devices per socket with the exception
+ * of OCX TLK which appears as one PCI device per socket and contains several
+ * units with counters that are merged.
+ * Some counters are selected via a control register (L2C TAD) and read by
+ * a number of counter registers, others (L2C CBC, LMC & OCX TLK) have
+ * one dedicated counter per event.
+ * Some counters are not stoppable (L2C CBC & LMC).
+ * Some counters are read-only (LMC).
+ * All counters belong to PCI devices, the devices may have additional
+ * drivers but we assume we are the only user of the counter registers.
+ * We map the whole PCI BAR so we must be careful to forbid access to
+ * addresses that contain neither counters nor counter control registers.
+ */
+
+void thunder_uncore_read(struct perf_event *event)
+{
+	struct thunder_uncore *uncore = to_uncore(event->pmu);
+	struct hw_perf_event *hwc = &event->hw;
+	struct thunder_uncore_node *node;
+	struct thunder_uncore_unit *unit;
+	u64 prev, delta, new = 0;
+
+	node = get_node(hwc->config, uncore);
+
+	/* read counter values from all units on the node */
+	list_for_each_entry(unit, &node->unit_list, entry)
+		new += readq(hwc->event_base + unit->map);
+
+	prev = local64_read(&hwc->prev_count);
+	local64_set(&hwc->prev_count, new);
+	delta = new - prev;
+	local64_add(delta, &event->count);
+}
+
+int thunder_uncore_add(struct perf_event *event, int flags, u64 config_base,
+		       u64 event_base)
+{
+	struct thunder_uncore *uncore = to_uncore(event->pmu);
+	struct hw_perf_event *hwc = &event->hw;
+	struct thunder_uncore_node *node;
+	int id;
+
+	node = get_node(hwc->config, uncore);
+	id = get_id(hwc->config);
+
+	if (!cmpxchg(&node->events[id], NULL, event))
+		hwc->idx = id;
+
+	if (hwc->idx == -1)
+		return -EBUSY;
+
+	hwc->config_base = config_base;
+	hwc->event_base = event_base;
+	hwc->state = PERF_HES_UPTODATE | PERF_HES_STOPPED;
+
+	if (flags & PERF_EF_START)
+		uncore->pmu.start(event, PERF_EF_RELOAD);
+
+	return 0;
+}
+
+void thunder_uncore_del(struct perf_event *event, int flags)
+{
+	struct thunder_uncore *uncore = to_uncore(event->pmu);
+	struct hw_perf_event *hwc = &event->hw;
+	struct thunder_uncore_node *node;
+	int i;
+
+	event->pmu->stop(event, PERF_EF_UPDATE);
+
+	/*
+	 * For programmable counters we need to check where we installed it.
+	 * To keep this function generic always test the more complicated
+	 * case (free running counters won't need the loop).
+	 */
+	node = get_node(hwc->config, uncore);
+	for (i = 0; i < node->num_counters; i++) {
+		if (cmpxchg(&node->events[i], event, NULL) == event)
+			break;
+	}
+	hwc->idx = -1;
+}
+
+void thunder_uncore_start(struct perf_event *event, int flags)
+{
+	struct thunder_uncore *uncore = to_uncore(event->pmu);
+	struct hw_perf_event *hwc = &event->hw;
+	struct thunder_uncore_node *node;
+	struct thunder_uncore_unit *unit;
+	u64 new = 0;
+
+	/* read counter values from all units on the node */
+	node = get_node(hwc->config, uncore);
+	list_for_each_entry(unit, &node->unit_list, entry)
+		new += readq(hwc->event_base + unit->map);
+	local64_set(&hwc->prev_count, new);
+
+	hwc->state = 0;
+	perf_event_update_userpage(event);
+}
+
+void thunder_uncore_stop(struct perf_event *event, int flags)
+{
+	struct hw_perf_event *hwc = &event->hw;
+
+	hwc->state |= PERF_HES_STOPPED;
+
+	if ((flags & PERF_EF_UPDATE) && !(hwc->state & PERF_HES_UPTODATE)) {
+		thunder_uncore_read(event);
+		hwc->state |= PERF_HES_UPTODATE;
+	}
+}
+
+int thunder_uncore_event_init(struct perf_event *event)
+{
+	struct hw_perf_event *hwc = &event->hw;
+	struct thunder_uncore_node *node;
+	struct thunder_uncore *uncore;
+
+	if (event->attr.type != event->pmu->type)
+		return -ENOENT;
+
+	/* we do not support sampling */
+	if (is_sampling_event(event))
+		return -EINVAL;
+
+	/* counters do not have these bits */
+	if (event->attr.exclude_user	||
+	    event->attr.exclude_kernel	||
+	    event->attr.exclude_host	||
+	    event->attr.exclude_guest	||
+	    event->attr.exclude_hv	||
+	    event->attr.exclude_idle)
+		return -EINVAL;
+
+	uncore = to_uncore(event->pmu);
+	if (!uncore)
+		return -ENODEV;
+	if (!uncore->event_valid(event->attr.config & UNCORE_EVENT_ID_MASK))
+		return -EINVAL;
+
+	/* check NUMA node */
+	node = get_node(event->attr.config, uncore);
+	if (!node) {
+		pr_debug("Invalid NUMA node selected\n");
+		return -EINVAL;
+	}
+
+	hwc->config = event->attr.config;
+	hwc->idx = -1;
+	return 0;
+}
+
+static ssize_t thunder_uncore_attr_show_cpumask(struct device *dev,
+						struct device_attribute *attr,
+						char *buf)
+{
+	struct pmu *pmu = dev_get_drvdata(dev);
+	struct thunder_uncore *uncore =
+		container_of(pmu, struct thunder_uncore, pmu);
+
+	return cpumap_print_to_pagebuf(true, buf, &uncore->active_mask);
+}
+static DEVICE_ATTR(cpumask, S_IRUGO, thunder_uncore_attr_show_cpumask, NULL);
+
+static struct attribute *thunder_uncore_attrs[] = {
+	&dev_attr_cpumask.attr,
+	NULL,
+};
+
+struct attribute_group thunder_uncore_attr_group = {
+	.attrs = thunder_uncore_attrs,
+};
+
+ssize_t thunder_events_sysfs_show(struct device *dev,
+				  struct device_attribute *attr,
+				  char *page)
+{
+	struct perf_pmu_events_attr *pmu_attr =
+		container_of(attr, struct perf_pmu_events_attr, attr);
+
+	if (pmu_attr->event_str)
+		return sprintf(page, "%s", pmu_attr->event_str);
+
+	return 0;
+}
+
+/* node attribute depending on number of NUMA nodes */
+static ssize_t node_show(struct device *dev, struct device_attribute *attr,
+			 char *page)
+{
+	if (NODES_SHIFT)
+		return sprintf(page, "config:16-%d\n", 16 + NODES_SHIFT - 1);
+	else
+		return sprintf(page, "config:16\n");
+}
+
+struct device_attribute format_attr_node = __ATTR_RO(node);
+
+/*
+ * Thunder uncore events are independent from CPUs. Provide a cpumask
+ * nevertheless to prevent perf from adding the event per-cpu and just
+ * set the mask to one online CPU. Use the same cpumask for all uncore
+ * devices.
+ *
+ * There is a performance penalty for accessing a device from a CPU on
+ * another socket, but we do not care (yet).
+ */
+static int thunder_uncore_offline_cpu(unsigned int old_cpu, struct hlist_node *node)
+{
+	struct thunder_uncore *uncore = hlist_entry_safe(node, struct thunder_uncore, node);
+	int new_cpu;
+
+	if (!cpumask_test_and_clear_cpu(old_cpu, &uncore->active_mask))
+		return 0;
+	new_cpu = cpumask_any_but(cpu_online_mask, old_cpu);
+	if (new_cpu >= nr_cpu_ids)
+		return 0;
+	perf_pmu_migrate_context(&uncore->pmu, old_cpu, new_cpu);
+	cpumask_set_cpu(new_cpu, &uncore->active_mask);
+	return 0;
+}
+
+static struct thunder_uncore_node * __init alloc_node(struct thunder_uncore *uncore,
+						      int node_id, int counters)
+{
+	struct thunder_uncore_node *node;
+
+	node = kzalloc(sizeof(*node), GFP_KERNEL);
+	if (!node)
+		return NULL;
+	node->num_counters = counters;
+	INIT_LIST_HEAD(&node->unit_list);
+	return node;
+}
+
+int __init thunder_uncore_setup(struct thunder_uncore *uncore, int device_id,
+				struct pmu *pmu, int counters)
+{
+	unsigned int vendor_id = PCI_VENDOR_ID_CAVIUM;
+	struct thunder_uncore_unit  *unit, *tmp;
+	struct thunder_uncore_node *node;
+	struct pci_dev *pdev = NULL;
+	int ret, node_id, found = 0;
+
+	/* detect PCI devices */
+	while ((pdev = pci_get_device(vendor_id, device_id, pdev))) {
+		if (!pdev)
+			break;
+
+		node_id = dev_to_node(&pdev->dev);
+
+		/* allocate node if necessary */
+		if (!uncore->nodes[node_id])
+			uncore->nodes[node_id] = alloc_node(uncore, node_id, counters);
+
+		node = uncore->nodes[node_id];
+		if (!node) {
+			ret = -ENOMEM;
+			goto fail;
+		}
+
+		unit = kzalloc(sizeof(*unit), GFP_KERNEL);
+		if (!unit) {
+			ret = -ENOMEM;
+			goto fail;
+		}
+
+		unit->pdev = pdev;
+		unit->map = ioremap(pci_resource_start(pdev, 0),
+				    pci_resource_len(pdev, 0));
+		list_add(&unit->entry, &node->unit_list);
+		node->nr_units++;
+		found++;
+	}
+
+	if (!found)
+		return -ENODEV;
+
+	cpuhp_state_add_instance_nocalls(CPUHP_AP_UNCORE_CAVIUM_ONLINE,
+                                         &uncore->node);
+
+	/*
+	 * perf PMU is CPU dependent in difference to our uncore devices.
+	 * Just pick a CPU and migrate away if it goes offline.
+	 */
+	cpumask_set_cpu(smp_processor_id(), &uncore->active_mask);
+
+	uncore->pmu = *pmu;
+	ret = perf_pmu_register(&uncore->pmu, uncore->pmu.name, -1);
+	if (ret)
+		goto fail;
+
+	return 0;
+
+fail:
+	node_id = 0;
+	while (uncore->nodes[node_id]) {
+		node = uncore->nodes[node_id];
+
+		list_for_each_entry_safe(unit, tmp, &node->unit_list, entry) {
+			if (unit->pdev) {
+				if (unit->map)
+					iounmap(unit->map);
+				pci_dev_put(unit->pdev);
+			}
+			kfree(unit);
+		}
+		kfree(uncore->nodes[node_id]);
+		node_id++;
+	}
+	return ret;
+}
+
+static int __init thunder_uncore_init(void)
+{
+	unsigned long implementor = read_cpuid_implementor();
+	int ret;
+
+	if (implementor != ARM_CPU_IMP_CAVIUM)
+		return -ENODEV;
+
+	ret = cpuhp_setup_state_multi(CPUHP_AP_UNCORE_CAVIUM_ONLINE,
+				      "AP_PERF_UNCORE_CAVIUM_ONLINE", NULL,
+				      thunder_uncore_offline_cpu);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+late_initcall(thunder_uncore_init);
diff --git a/drivers/perf/uncore/uncore_cavium.h b/drivers/perf/uncore/uncore_cavium.h
new file mode 100644
index 0000000..b5d64b5
--- /dev/null
+++ b/drivers/perf/uncore/uncore_cavium.h
@@ -0,0 +1,71 @@
+#include <linux/io.h>
+#include <linux/list.h>
+#include <linux/pci.h>
+#include <linux/perf_event.h>
+
+#undef pr_fmt
+#define pr_fmt(fmt)     "thunderx_uncore: " fmt
+
+#define to_uncore(x) container_of((x), struct thunder_uncore, pmu)
+
+#define UNCORE_EVENT_ID_MASK		0xffff
+#define UNCORE_EVENT_ID_SHIFT		16
+
+/* maximum number of parallel hardware counters for all uncore parts */
+#define MAX_COUNTERS			64
+
+struct thunder_uncore_unit {
+	struct list_head entry;
+	void __iomem *map;
+	struct pci_dev *pdev;
+};
+
+struct thunder_uncore_node {
+	int nr_units;
+	int num_counters;
+	struct list_head unit_list;
+	struct perf_event *events[MAX_COUNTERS];
+};
+
+/* generic uncore struct for different pmu types */
+struct thunder_uncore {
+	struct pmu pmu;
+	bool (*event_valid)(u64);
+	struct hlist_node node;
+	struct thunder_uncore_node *nodes[MAX_NUMNODES];
+	cpumask_t active_mask;
+};
+
+#define UC_EVENT_ENTRY(_name, _id)							\
+	&((struct perf_pmu_events_attr[]) {						\
+		{									\
+			__ATTR(_name, S_IRUGO, thunder_events_sysfs_show, NULL),	\
+			0,								\
+			"event=" __stringify(_id),					\
+		}									\
+	})[0].attr.attr
+
+static inline struct thunder_uncore_node *get_node(u64 config,
+				   struct thunder_uncore *uncore)
+{
+	return uncore->nodes[config >> UNCORE_EVENT_ID_SHIFT];
+}
+
+#define get_id(config) (config & UNCORE_EVENT_ID_MASK)
+
+extern struct attribute_group thunder_uncore_attr_group;
+extern struct device_attribute format_attr_node;
+
+/* Prototypes */
+void thunder_uncore_read(struct perf_event *event);
+int thunder_uncore_add(struct perf_event *event, int flags, u64 config_base,
+		       u64 event_base);
+void thunder_uncore_del(struct perf_event *event, int flags);
+void thunder_uncore_start(struct perf_event *event, int flags);
+void thunder_uncore_stop(struct perf_event *event, int flags);
+int thunder_uncore_event_init(struct perf_event *event);
+int thunder_uncore_setup(struct thunder_uncore *uncore, int id,
+			 struct pmu *pmu, int counters);
+ssize_t thunder_events_sysfs_show(struct device *dev,
+				  struct device_attribute *attr,
+				  char *page);
diff --git a/include/linux/cpuhotplug.h b/include/linux/cpuhotplug.h
index afe641c..973f2bb 100644
--- a/include/linux/cpuhotplug.h
+++ b/include/linux/cpuhotplug.h
@@ -118,6 +118,7 @@ enum cpuhp_state {
 	CPUHP_AP_PERF_ARM_CCI_ONLINE,
 	CPUHP_AP_PERF_ARM_CCN_ONLINE,
 	CPUHP_AP_PERF_ARM_L2X0_ONLINE,
+	CPUHP_AP_UNCORE_CAVIUM_ONLINE,
 	CPUHP_AP_WORKQUEUE_ONLINE,
 	CPUHP_AP_RCUTREE_ONLINE,
 	CPUHP_AP_NOTIFY_ONLINE,
-- 
2.9.0.rc0.21.g7777322

^ permalink raw reply related

* [PATCH v4 2/5] arm64: perf: Cavium ThunderX L2C TAD uncore support
From: Jan Glauber @ 2016-10-29 11:55 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <cover.1477741719.git.jglauber@cavium.com>

Support counters of the L2 Cache tag and data units.

Signed-off-by: Jan Glauber <jglauber@cavium.com>
---
 drivers/perf/uncore/Makefile                |   3 +-
 drivers/perf/uncore/uncore_cavium.c         |   1 +
 drivers/perf/uncore/uncore_cavium.h         |   1 +
 drivers/perf/uncore/uncore_cavium_l2c_tad.c | 379 ++++++++++++++++++++++++++++
 4 files changed, 383 insertions(+), 1 deletion(-)
 create mode 100644 drivers/perf/uncore/uncore_cavium_l2c_tad.c

diff --git a/drivers/perf/uncore/Makefile b/drivers/perf/uncore/Makefile
index 6130e18..90850a2 100644
--- a/drivers/perf/uncore/Makefile
+++ b/drivers/perf/uncore/Makefile
@@ -1 +1,2 @@
-obj-$(CONFIG_UNCORE_PMU_CAVIUM) += uncore_cavium.o
+obj-$(CONFIG_UNCORE_PMU_CAVIUM) += uncore_cavium.o		\
+				   uncore_cavium_l2c_tad.o
diff --git a/drivers/perf/uncore/uncore_cavium.c b/drivers/perf/uncore/uncore_cavium.c
index a7b4277..15e1aec 100644
--- a/drivers/perf/uncore/uncore_cavium.c
+++ b/drivers/perf/uncore/uncore_cavium.c
@@ -346,6 +346,7 @@ static int __init thunder_uncore_init(void)
 	if (ret)
 		return ret;
 
+	thunder_uncore_l2c_tad_setup();
 	return 0;
 }
 late_initcall(thunder_uncore_init);
diff --git a/drivers/perf/uncore/uncore_cavium.h b/drivers/perf/uncore/uncore_cavium.h
index b5d64b5..70a8214 100644
--- a/drivers/perf/uncore/uncore_cavium.h
+++ b/drivers/perf/uncore/uncore_cavium.h
@@ -69,3 +69,4 @@ int thunder_uncore_setup(struct thunder_uncore *uncore, int id,
 ssize_t thunder_events_sysfs_show(struct device *dev,
 				  struct device_attribute *attr,
 				  char *page);
+int thunder_uncore_l2c_tad_setup(void);
diff --git a/drivers/perf/uncore/uncore_cavium_l2c_tad.c b/drivers/perf/uncore/uncore_cavium_l2c_tad.c
new file mode 100644
index 0000000..b97ba33
--- /dev/null
+++ b/drivers/perf/uncore/uncore_cavium_l2c_tad.c
@@ -0,0 +1,379 @@
+/*
+ * Cavium Thunder uncore PMU support,
+ * L2 Cache tag-and-data-units (L2C TAD) counters.
+ *
+ * Copyright 2016 Cavium Inc.
+ * Author: Jan Glauber <jan.glauber@cavium.com>
+ */
+
+#include <linux/perf_event.h>
+#include <linux/slab.h>
+
+#include "uncore_cavium.h"
+
+struct thunder_uncore *thunder_uncore_l2c_tad;
+
+#define L2C_TAD_NR_COUNTERS             4
+#define L2C_TAD_PRF_OFFSET		0x10000
+#define L2C_TAD_PFC_OFFSET		0x10100
+
+/*
+ * Counters are selected via L2C_TAD(x)_PRF:
+ *
+ *   63					    32
+ *   +---------------------------------------+
+ *   |  Reserved			     |
+ *   +---------------------------------------+
+ *   | CNT3SEL | CNT2SEL | CNT1SEL | CNT0SEL |
+ *   +---------------------------------------+
+ *   31       24	16	  8	     0
+ *
+ * config_base contains the offset of the selected CNTxSEL in the mapped BAR.
+ *
+ * Counters are read via L2C_TAD(x)_PFC(0..3).
+ * event_base contains the associated address to read the counter.
+ */
+
+/* L2C TAD event list */
+#define L2C_TAD_EVENTS_DISABLED			0x00
+#define L2C_TAD_EVENT_L2T_HIT			0x01
+#define L2C_TAD_EVENT_L2T_MISS			0x02
+#define L2C_TAD_EVENT_L2T_NOALLOC		0x03
+#define L2C_TAD_EVENT_L2_VIC			0x04
+#define L2C_TAD_EVENT_SC_FAIL			0x05
+#define L2C_TAD_EVENT_SC_PASS			0x06
+#define L2C_TAD_EVENT_LFB_OCC			0x07
+#define L2C_TAD_EVENT_WAIT_LFB			0x08
+#define L2C_TAD_EVENT_WAIT_VAB			0x09
+#define L2C_TAD_EVENT_OPEN_CCPI			0x0a
+#define L2C_TAD_EVENT_LOOKUP			0x40
+#define L2C_TAD_EVENT_LOOKUP_XMC_LCL		0x41
+#define L2C_TAD_EVENT_LOOKUP_XMC_RMT		0x42
+#define L2C_TAD_EVENT_LOOKUP_MIB		0x43
+#define L2C_TAD_EVENT_LOOKUP_ALL		0x44
+#define L2C_TAD_EVENT_TAG_ALC_HIT		0x48
+#define L2C_TAD_EVENT_TAG_ALC_MISS		0x49
+#define L2C_TAD_EVENT_TAG_ALC_NALC		0x4a
+#define L2C_TAD_EVENT_TAG_NALC_HIT		0x4b
+#define L2C_TAD_EVENT_TAG_NALC_MISS		0x4c
+#define L2C_TAD_EVENT_LMC_WR			0x4e
+#define L2C_TAD_EVENT_LMC_SBLKDTY		0x4f
+#define L2C_TAD_EVENT_TAG_ALC_RTG_HIT		0x50
+#define L2C_TAD_EVENT_TAG_ALC_RTG_HITE		0x51
+#define L2C_TAD_EVENT_TAG_ALC_RTG_HITS		0x52
+#define L2C_TAD_EVENT_TAG_ALC_RTG_MISS		0x53
+#define L2C_TAD_EVENT_TAG_NALC_RTG_HIT		0x54
+#define L2C_TAD_EVENT_TAG_NALC_RTG_MISS		0x55
+#define L2C_TAD_EVENT_TAG_NALC_RTG_HITE		0x56
+#define L2C_TAD_EVENT_TAG_NALC_RTG_HITS		0x57
+#define L2C_TAD_EVENT_TAG_ALC_LCL_EVICT		0x58
+#define L2C_TAD_EVENT_TAG_ALC_LCL_CLNVIC	0x59
+#define L2C_TAD_EVENT_TAG_ALC_LCL_DTYVIC	0x5a
+#define L2C_TAD_EVENT_TAG_ALC_RMT_EVICT		0x5b
+#define L2C_TAD_EVENT_TAG_ALC_RMT_VIC		0x5c
+#define L2C_TAD_EVENT_RTG_ALC			0x5d
+#define L2C_TAD_EVENT_RTG_ALC_HIT		0x5e
+#define L2C_TAD_EVENT_RTG_ALC_HITWB		0x5f
+#define L2C_TAD_EVENT_STC_TOTAL			0x60
+#define L2C_TAD_EVENT_STC_TOTAL_FAIL		0x61
+#define L2C_TAD_EVENT_STC_RMT			0x62
+#define L2C_TAD_EVENT_STC_RMT_FAIL		0x63
+#define L2C_TAD_EVENT_STC_LCL			0x64
+#define L2C_TAD_EVENT_STC_LCL_FAIL		0x65
+#define L2C_TAD_EVENT_OCI_RTG_WAIT		0x68
+#define L2C_TAD_EVENT_OCI_FWD_CYC_HIT		0x69
+#define L2C_TAD_EVENT_OCI_FWD_RACE		0x6a
+#define L2C_TAD_EVENT_OCI_HAKS			0x6b
+#define L2C_TAD_EVENT_OCI_FLDX_TAG_E_NODAT	0x6c
+#define L2C_TAD_EVENT_OCI_FLDX_TAG_E_DAT	0x6d
+#define L2C_TAD_EVENT_OCI_RLDD			0x6e
+#define L2C_TAD_EVENT_OCI_RLDD_PEMD		0x6f
+#define L2C_TAD_EVENT_OCI_RRQ_DAT_CNT		0x70
+#define L2C_TAD_EVENT_OCI_RRQ_DAT_DMASK		0x71
+#define L2C_TAD_EVENT_OCI_RSP_DAT_CNT		0x72
+#define L2C_TAD_EVENT_OCI_RSP_DAT_DMASK		0x73
+#define L2C_TAD_EVENT_OCI_RSP_DAT_VICD_CNT	0x74
+#define L2C_TAD_EVENT_OCI_RSP_DAT_VICD_DMASK	0x75
+#define L2C_TAD_EVENT_OCI_RTG_ALC_EVICT		0x76
+#define L2C_TAD_EVENT_OCI_RTG_ALC_VIC		0x77
+#define L2C_TAD_EVENT_QD0_IDX			0x80
+#define L2C_TAD_EVENT_QD0_RDAT			0x81
+#define L2C_TAD_EVENT_QD0_BNKS			0x82
+#define L2C_TAD_EVENT_QD0_WDAT			0x83
+#define L2C_TAD_EVENT_QD1_IDX			0x90
+#define L2C_TAD_EVENT_QD1_RDAT			0x91
+#define L2C_TAD_EVENT_QD1_BNKS			0x92
+#define L2C_TAD_EVENT_QD1_WDAT			0x93
+#define L2C_TAD_EVENT_QD2_IDX			0xa0
+#define L2C_TAD_EVENT_QD2_RDAT			0xa1
+#define L2C_TAD_EVENT_QD2_BNKS			0xa2
+#define L2C_TAD_EVENT_QD2_WDAT			0xa3
+#define L2C_TAD_EVENT_QD3_IDX			0xb0
+#define L2C_TAD_EVENT_QD3_RDAT			0xb1
+#define L2C_TAD_EVENT_QD3_BNKS			0xb2
+#define L2C_TAD_EVENT_QD3_WDAT			0xb3
+#define L2C_TAD_EVENT_QD4_IDX			0xc0
+#define L2C_TAD_EVENT_QD4_RDAT			0xc1
+#define L2C_TAD_EVENT_QD4_BNKS			0xc2
+#define L2C_TAD_EVENT_QD4_WDAT			0xc3
+#define L2C_TAD_EVENT_QD5_IDX			0xd0
+#define L2C_TAD_EVENT_QD5_RDAT			0xd1
+#define L2C_TAD_EVENT_QD5_BNKS			0xd2
+#define L2C_TAD_EVENT_QD5_WDAT			0xd3
+#define L2C_TAD_EVENT_QD6_IDX			0xe0
+#define L2C_TAD_EVENT_QD6_RDAT			0xe1
+#define L2C_TAD_EVENT_QD6_BNKS			0xe2
+#define L2C_TAD_EVENT_QD6_WDAT			0xe3
+#define L2C_TAD_EVENT_QD7_IDX			0xf0
+#define L2C_TAD_EVENT_QD7_RDAT			0xf1
+#define L2C_TAD_EVENT_QD7_BNKS			0xf2
+#define L2C_TAD_EVENT_QD7_WDAT			0xf3
+
+static void thunder_uncore_start_l2c_tad(struct perf_event *event, int flags)
+{
+	struct thunder_uncore *uncore = to_uncore(event->pmu);
+	struct hw_perf_event *hwc = &event->hw;
+	struct thunder_uncore_node *node;
+	struct thunder_uncore_unit *unit;
+	int id;
+
+	node = get_node(hwc->config, uncore);
+	id = get_id(hwc->config);
+
+	/* reset counter values to zero */
+	if (flags & PERF_EF_RELOAD)
+		list_for_each_entry(unit, &node->unit_list, entry)
+			writeq(0, hwc->event_base + unit->map);
+
+	/* start counters on all units on the node */
+	list_for_each_entry(unit, &node->unit_list, entry)
+		writeb(id, hwc->config_base + unit->map);
+
+	hwc->state = 0;
+	perf_event_update_userpage(event);
+}
+
+static void thunder_uncore_stop_l2c_tad(struct perf_event *event, int flags)
+{
+	struct thunder_uncore *uncore = to_uncore(event->pmu);
+	struct hw_perf_event *hwc = &event->hw;
+	struct thunder_uncore_node *node;
+	struct thunder_uncore_unit *unit;
+
+	node = get_node(hwc->config, uncore);
+
+	/* disable counters for all units on the node */
+	list_for_each_entry(unit, &node->unit_list, entry)
+		writeb(L2C_TAD_EVENTS_DISABLED, hwc->config_base + unit->map);
+	hwc->state |= PERF_HES_STOPPED;
+
+	if ((flags & PERF_EF_UPDATE) && !(hwc->state & PERF_HES_UPTODATE)) {
+		thunder_uncore_read(event);
+		hwc->state |= PERF_HES_UPTODATE;
+	}
+}
+
+static int thunder_uncore_add_l2c_tad(struct perf_event *event, int flags)
+{
+	struct thunder_uncore *uncore = to_uncore(event->pmu);
+	struct hw_perf_event *hwc = &event->hw;
+	struct thunder_uncore_node *node;
+	int i;
+
+	node = get_node(hwc->config, uncore);
+
+	/* take the first available counter */
+	for (i = 0; i < node->num_counters; i++) {
+		if (!cmpxchg(&node->events[i], NULL, event)) {
+			hwc->idx = i;
+			break;
+		}
+	}
+
+	if (hwc->idx == -1)
+		return -EBUSY;
+
+	/* see comment at beginning of file */
+	hwc->config_base = L2C_TAD_PRF_OFFSET + hwc->idx;
+	hwc->event_base = L2C_TAD_PFC_OFFSET + hwc->idx * sizeof(u64);
+
+	hwc->state = PERF_HES_UPTODATE | PERF_HES_STOPPED;
+	if (flags & PERF_EF_START)
+		thunder_uncore_start(event, PERF_EF_RELOAD);
+	return 0;
+}
+
+PMU_FORMAT_ATTR(event, "config:0-7");
+
+static struct attribute *thunder_l2c_tad_format_attr[] = {
+	&format_attr_event.attr,
+	&format_attr_node.attr,
+	NULL,
+};
+
+static struct attribute_group thunder_l2c_tad_format_group = {
+	.name = "format",
+	.attrs = thunder_l2c_tad_format_attr,
+};
+
+static struct attribute *thunder_l2c_tad_events_attr[] = {
+	UC_EVENT_ENTRY(l2t_hit,			L2C_TAD_EVENT_L2T_HIT),
+	UC_EVENT_ENTRY(l2t_miss,		L2C_TAD_EVENT_L2T_MISS),
+	UC_EVENT_ENTRY(l2t_noalloc,		L2C_TAD_EVENT_L2T_NOALLOC),
+	UC_EVENT_ENTRY(l2_vic,			L2C_TAD_EVENT_L2_VIC),
+	UC_EVENT_ENTRY(sc_fail,			L2C_TAD_EVENT_SC_FAIL),
+	UC_EVENT_ENTRY(sc_pass,			L2C_TAD_EVENT_SC_PASS),
+	UC_EVENT_ENTRY(lfb_occ,			L2C_TAD_EVENT_LFB_OCC),
+	UC_EVENT_ENTRY(wait_lfb,		L2C_TAD_EVENT_WAIT_LFB),
+	UC_EVENT_ENTRY(wait_vab,		L2C_TAD_EVENT_WAIT_VAB),
+	UC_EVENT_ENTRY(open_ccpi,		L2C_TAD_EVENT_OPEN_CCPI),
+	UC_EVENT_ENTRY(lookup,			L2C_TAD_EVENT_LOOKUP),
+	UC_EVENT_ENTRY(lookup_xmc_lcl,		L2C_TAD_EVENT_LOOKUP_XMC_LCL),
+	UC_EVENT_ENTRY(lookup_xmc_rmt,		L2C_TAD_EVENT_LOOKUP_XMC_RMT),
+	UC_EVENT_ENTRY(lookup_mib,		L2C_TAD_EVENT_LOOKUP_MIB),
+	UC_EVENT_ENTRY(lookup_all,		L2C_TAD_EVENT_LOOKUP_ALL),
+	UC_EVENT_ENTRY(tag_alc_hit,		L2C_TAD_EVENT_TAG_ALC_HIT),
+	UC_EVENT_ENTRY(tag_alc_miss,		L2C_TAD_EVENT_TAG_ALC_MISS),
+	UC_EVENT_ENTRY(tag_alc_nalc,		L2C_TAD_EVENT_TAG_ALC_NALC),
+	UC_EVENT_ENTRY(tag_nalc_hit,		L2C_TAD_EVENT_TAG_NALC_HIT),
+	UC_EVENT_ENTRY(tag_nalc_miss,		L2C_TAD_EVENT_TAG_NALC_MISS),
+	UC_EVENT_ENTRY(lmc_wr,			L2C_TAD_EVENT_LMC_WR),
+	UC_EVENT_ENTRY(lmc_sblkdty,		L2C_TAD_EVENT_LMC_SBLKDTY),
+	UC_EVENT_ENTRY(tag_alc_rtg_hit,		L2C_TAD_EVENT_TAG_ALC_RTG_HIT),
+	UC_EVENT_ENTRY(tag_alc_rtg_hite,	L2C_TAD_EVENT_TAG_ALC_RTG_HITE),
+	UC_EVENT_ENTRY(tag_alc_rtg_hits,	L2C_TAD_EVENT_TAG_ALC_RTG_HITS),
+	UC_EVENT_ENTRY(tag_alc_rtg_miss,	L2C_TAD_EVENT_TAG_ALC_RTG_MISS),
+	UC_EVENT_ENTRY(tag_alc_nalc_rtg_hit,	L2C_TAD_EVENT_TAG_NALC_RTG_HIT),
+	UC_EVENT_ENTRY(tag_nalc_rtg_miss,	L2C_TAD_EVENT_TAG_NALC_RTG_MISS),
+	UC_EVENT_ENTRY(tag_nalc_rtg_hite,	L2C_TAD_EVENT_TAG_NALC_RTG_HITE),
+	UC_EVENT_ENTRY(tag_nalc_rtg_hits,	L2C_TAD_EVENT_TAG_NALC_RTG_HITS),
+	UC_EVENT_ENTRY(tag_alc_lcl_evict,	L2C_TAD_EVENT_TAG_ALC_LCL_EVICT),
+	UC_EVENT_ENTRY(tag_alc_lcl_clnvic,	L2C_TAD_EVENT_TAG_ALC_LCL_CLNVIC),
+	UC_EVENT_ENTRY(tag_alc_lcl_dtyvic,	L2C_TAD_EVENT_TAG_ALC_LCL_DTYVIC),
+	UC_EVENT_ENTRY(tag_alc_rmt_evict,	L2C_TAD_EVENT_TAG_ALC_RMT_EVICT),
+	UC_EVENT_ENTRY(tag_alc_rmt_vic,		L2C_TAD_EVENT_TAG_ALC_RMT_VIC),
+	UC_EVENT_ENTRY(rtg_alc,			L2C_TAD_EVENT_RTG_ALC),
+	UC_EVENT_ENTRY(rtg_alc_hit,		L2C_TAD_EVENT_RTG_ALC_HIT),
+	UC_EVENT_ENTRY(rtg_alc_hitwb,		L2C_TAD_EVENT_RTG_ALC_HITWB),
+	UC_EVENT_ENTRY(stc_total,		L2C_TAD_EVENT_STC_TOTAL),
+	UC_EVENT_ENTRY(stc_total_fail,		L2C_TAD_EVENT_STC_TOTAL_FAIL),
+	UC_EVENT_ENTRY(stc_rmt,			L2C_TAD_EVENT_STC_RMT),
+	UC_EVENT_ENTRY(stc_rmt_fail,		L2C_TAD_EVENT_STC_RMT_FAIL),
+	UC_EVENT_ENTRY(stc_lcl,			L2C_TAD_EVENT_STC_LCL),
+	UC_EVENT_ENTRY(stc_lcl_fail,		L2C_TAD_EVENT_STC_LCL_FAIL),
+	UC_EVENT_ENTRY(oci_rtg_wait,		L2C_TAD_EVENT_OCI_RTG_WAIT),
+	UC_EVENT_ENTRY(oci_fwd_cyc_hit,		L2C_TAD_EVENT_OCI_FWD_CYC_HIT),
+	UC_EVENT_ENTRY(oci_fwd_race,		L2C_TAD_EVENT_OCI_FWD_RACE),
+	UC_EVENT_ENTRY(oci_haks,		L2C_TAD_EVENT_OCI_HAKS),
+	UC_EVENT_ENTRY(oci_fldx_tag_e_nodat,	L2C_TAD_EVENT_OCI_FLDX_TAG_E_NODAT),
+	UC_EVENT_ENTRY(oci_fldx_tag_e_dat,	L2C_TAD_EVENT_OCI_FLDX_TAG_E_DAT),
+	UC_EVENT_ENTRY(oci_rldd,		L2C_TAD_EVENT_OCI_RLDD),
+	UC_EVENT_ENTRY(oci_rldd_pemd,		L2C_TAD_EVENT_OCI_RLDD_PEMD),
+	UC_EVENT_ENTRY(oci_rrq_dat_cnt,		L2C_TAD_EVENT_OCI_RRQ_DAT_CNT),
+	UC_EVENT_ENTRY(oci_rrq_dat_dmask,	L2C_TAD_EVENT_OCI_RRQ_DAT_DMASK),
+	UC_EVENT_ENTRY(oci_rsp_dat_cnt,		L2C_TAD_EVENT_OCI_RSP_DAT_CNT),
+	UC_EVENT_ENTRY(oci_rsp_dat_dmaks,	L2C_TAD_EVENT_OCI_RSP_DAT_DMASK),
+	UC_EVENT_ENTRY(oci_rsp_dat_vicd_cnt,	L2C_TAD_EVENT_OCI_RSP_DAT_VICD_CNT),
+	UC_EVENT_ENTRY(oci_rsp_dat_vicd_dmask,	L2C_TAD_EVENT_OCI_RSP_DAT_VICD_DMASK),
+	UC_EVENT_ENTRY(oci_rtg_alc_evict,	L2C_TAD_EVENT_OCI_RTG_ALC_EVICT),
+	UC_EVENT_ENTRY(oci_rtg_alc_vic,		L2C_TAD_EVENT_OCI_RTG_ALC_VIC),
+	UC_EVENT_ENTRY(qd0_idx,			L2C_TAD_EVENT_QD0_IDX),
+	UC_EVENT_ENTRY(qd0_rdat,		L2C_TAD_EVENT_QD0_RDAT),
+	UC_EVENT_ENTRY(qd0_bnks,		L2C_TAD_EVENT_QD0_BNKS),
+	UC_EVENT_ENTRY(qd0_wdat,		L2C_TAD_EVENT_QD0_WDAT),
+	UC_EVENT_ENTRY(qd1_idx,			L2C_TAD_EVENT_QD1_IDX),
+	UC_EVENT_ENTRY(qd1_rdat,		L2C_TAD_EVENT_QD1_RDAT),
+	UC_EVENT_ENTRY(qd1_bnks,		L2C_TAD_EVENT_QD1_BNKS),
+	UC_EVENT_ENTRY(qd1_wdat,		L2C_TAD_EVENT_QD1_WDAT),
+	UC_EVENT_ENTRY(qd2_idx,			L2C_TAD_EVENT_QD2_IDX),
+	UC_EVENT_ENTRY(qd2_rdat,		L2C_TAD_EVENT_QD2_RDAT),
+	UC_EVENT_ENTRY(qd2_bnks,		L2C_TAD_EVENT_QD2_BNKS),
+	UC_EVENT_ENTRY(qd2_wdat,		L2C_TAD_EVENT_QD2_WDAT),
+	UC_EVENT_ENTRY(qd3_idx,			L2C_TAD_EVENT_QD3_IDX),
+	UC_EVENT_ENTRY(qd3_rdat,		L2C_TAD_EVENT_QD3_RDAT),
+	UC_EVENT_ENTRY(qd3_bnks,		L2C_TAD_EVENT_QD3_BNKS),
+	UC_EVENT_ENTRY(qd3_wdat,		L2C_TAD_EVENT_QD3_WDAT),
+	UC_EVENT_ENTRY(qd4_idx,			L2C_TAD_EVENT_QD4_IDX),
+	UC_EVENT_ENTRY(qd4_rdat,		L2C_TAD_EVENT_QD4_RDAT),
+	UC_EVENT_ENTRY(qd4_bnks,		L2C_TAD_EVENT_QD4_BNKS),
+	UC_EVENT_ENTRY(qd4_wdat,		L2C_TAD_EVENT_QD4_WDAT),
+	UC_EVENT_ENTRY(qd5_idx,			L2C_TAD_EVENT_QD5_IDX),
+	UC_EVENT_ENTRY(qd5_rdat,		L2C_TAD_EVENT_QD5_RDAT),
+	UC_EVENT_ENTRY(qd5_bnks,		L2C_TAD_EVENT_QD5_BNKS),
+	UC_EVENT_ENTRY(qd5_wdat,		L2C_TAD_EVENT_QD5_WDAT),
+	UC_EVENT_ENTRY(qd6_idx,			L2C_TAD_EVENT_QD6_IDX),
+	UC_EVENT_ENTRY(qd6_rdat,		L2C_TAD_EVENT_QD6_RDAT),
+	UC_EVENT_ENTRY(qd6_bnks,		L2C_TAD_EVENT_QD6_BNKS),
+	UC_EVENT_ENTRY(qd6_wdat,		L2C_TAD_EVENT_QD6_WDAT),
+	UC_EVENT_ENTRY(qd7_idx,			L2C_TAD_EVENT_QD7_IDX),
+	UC_EVENT_ENTRY(qd7_rdat,		L2C_TAD_EVENT_QD7_RDAT),
+	UC_EVENT_ENTRY(qd7_bnks,		L2C_TAD_EVENT_QD7_BNKS),
+	UC_EVENT_ENTRY(qd7_wdat,		L2C_TAD_EVENT_QD7_WDAT),
+	NULL,
+};
+
+static struct attribute_group thunder_l2c_tad_events_group = {
+	.name = "events",
+	.attrs = thunder_l2c_tad_events_attr,
+};
+
+static const struct attribute_group *thunder_l2c_tad_attr_groups[] = {
+	&thunder_uncore_attr_group,
+	&thunder_l2c_tad_format_group,
+	&thunder_l2c_tad_events_group,
+	NULL,
+};
+
+struct pmu thunder_l2c_tad_pmu = {
+	.name		= "thunder_l2c_tad",
+	.task_ctx_nr    = perf_invalid_context,
+	.event_init	= thunder_uncore_event_init,
+	.add		= thunder_uncore_add_l2c_tad,
+	.del		= thunder_uncore_del,
+	.start		= thunder_uncore_start_l2c_tad,
+	.stop		= thunder_uncore_stop_l2c_tad,
+	.read		= thunder_uncore_read,
+	.attr_groups	= thunder_l2c_tad_attr_groups,
+};
+
+static bool event_valid(u64 c)
+{
+	if ((c > 0 &&
+	     c <= L2C_TAD_EVENT_OPEN_CCPI) ||
+	    (c >= L2C_TAD_EVENT_LOOKUP &&
+	     c <= L2C_TAD_EVENT_LOOKUP_ALL) ||
+	    (c >= L2C_TAD_EVENT_TAG_ALC_HIT &&
+	     c <= L2C_TAD_EVENT_TAG_NALC_MISS) ||
+	    (c >= L2C_TAD_EVENT_LMC_WR &&
+	     c <= L2C_TAD_EVENT_STC_LCL_FAIL) ||
+	    (c >= L2C_TAD_EVENT_OCI_RTG_WAIT &&
+	     c <= L2C_TAD_EVENT_OCI_RTG_ALC_VIC) ||
+	    /* L2C_TAD_EVENT_QD[0..7] IDX,RDAT,BNKS,WDAT => 0x80 .. 0xf3 */
+	    ((c & 0x80) && ((c & 0xf) <= 3)))
+		return true;
+
+	return false;
+}
+
+int __init thunder_uncore_l2c_tad_setup(void)
+{
+	int ret = -ENOMEM;
+
+	thunder_uncore_l2c_tad = kzalloc(sizeof(*thunder_uncore_l2c_tad),
+					 GFP_KERNEL);
+	if (!thunder_uncore_l2c_tad)
+		goto fail_nomem;
+
+	ret = thunder_uncore_setup(thunder_uncore_l2c_tad, 0xa02e,
+				   &thunder_l2c_tad_pmu, L2C_TAD_NR_COUNTERS);
+	if (ret)
+		goto fail;
+
+	thunder_uncore_l2c_tad->event_valid = event_valid;
+	return 0;
+
+fail:
+	kfree(thunder_uncore_l2c_tad);
+fail_nomem:
+	return ret;
+}
-- 
2.9.0.rc0.21.g7777322

^ permalink raw reply related

* [PATCH v4 3/5] arm64: perf: Cavium ThunderX L2C CBC uncore support
From: Jan Glauber @ 2016-10-29 11:55 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <cover.1477741719.git.jglauber@cavium.com>

Support counters of the L2 cache crossbar connect.

Signed-off-by: Jan Glauber <jglauber@cavium.com>
---
 drivers/perf/uncore/Makefile                |   3 +-
 drivers/perf/uncore/uncore_cavium.c         |   1 +
 drivers/perf/uncore/uncore_cavium.h         |   1 +
 drivers/perf/uncore/uncore_cavium_l2c_cbc.c | 148 ++++++++++++++++++++++++++++
 4 files changed, 152 insertions(+), 1 deletion(-)
 create mode 100644 drivers/perf/uncore/uncore_cavium_l2c_cbc.c

diff --git a/drivers/perf/uncore/Makefile b/drivers/perf/uncore/Makefile
index 90850a2..d5ef3db 100644
--- a/drivers/perf/uncore/Makefile
+++ b/drivers/perf/uncore/Makefile
@@ -1,2 +1,3 @@
 obj-$(CONFIG_UNCORE_PMU_CAVIUM) += uncore_cavium.o		\
-				   uncore_cavium_l2c_tad.o
+				   uncore_cavium_l2c_tad.o	\
+				   uncore_cavium_l2c_cbc.o
diff --git a/drivers/perf/uncore/uncore_cavium.c b/drivers/perf/uncore/uncore_cavium.c
index 15e1aec..051f0fa 100644
--- a/drivers/perf/uncore/uncore_cavium.c
+++ b/drivers/perf/uncore/uncore_cavium.c
@@ -347,6 +347,7 @@ static int __init thunder_uncore_init(void)
 		return ret;
 
 	thunder_uncore_l2c_tad_setup();
+	thunder_uncore_l2c_cbc_setup();
 	return 0;
 }
 late_initcall(thunder_uncore_init);
diff --git a/drivers/perf/uncore/uncore_cavium.h b/drivers/perf/uncore/uncore_cavium.h
index 70a8214..91d674a 100644
--- a/drivers/perf/uncore/uncore_cavium.h
+++ b/drivers/perf/uncore/uncore_cavium.h
@@ -70,3 +70,4 @@ ssize_t thunder_events_sysfs_show(struct device *dev,
 				  struct device_attribute *attr,
 				  char *page);
 int thunder_uncore_l2c_tad_setup(void);
+int thunder_uncore_l2c_cbc_setup(void);
diff --git a/drivers/perf/uncore/uncore_cavium_l2c_cbc.c b/drivers/perf/uncore/uncore_cavium_l2c_cbc.c
new file mode 100644
index 0000000..95b6147
--- /dev/null
+++ b/drivers/perf/uncore/uncore_cavium_l2c_cbc.c
@@ -0,0 +1,148 @@
+/*
+ * Cavium Thunder uncore PMU support, L2 Cache,
+ * Crossbar connect (CBC) counters.
+ *
+ * Copyright 2016 Cavium Inc.
+ * Author: Jan Glauber <jan.glauber@cavium.com>
+ */
+
+#include <linux/perf_event.h>
+#include <linux/slab.h>
+
+#include "uncore_cavium.h"
+
+struct thunder_uncore *thunder_uncore_l2c_cbc;
+
+/* L2C CBC event list */
+#define L2C_CBC_EVENT_XMC0		0x00
+#define L2C_CBC_EVENT_XMD0		0x08
+#define L2C_CBC_EVENT_RSC0		0x10
+#define L2C_CBC_EVENT_RSD0		0x18
+#define L2C_CBC_EVENT_INV0		0x20
+#define L2C_CBC_EVENT_IOC0		0x28
+#define L2C_CBC_EVENT_IOR0		0x30
+#define L2C_CBC_EVENT_XMC1		0x40
+#define L2C_CBC_EVENT_XMD1		0x48
+#define L2C_CBC_EVENT_RSC1		0x50
+#define L2C_CBC_EVENT_RSD1		0x58
+#define L2C_CBC_EVENT_INV1		0x60
+#define L2C_CBC_EVENT_XMC2		0x80
+#define L2C_CBC_EVENT_XMD2		0x88
+#define L2C_CBC_EVENT_RSC2		0x90
+#define L2C_CBC_EVENT_RSD2		0x98
+
+static int l2c_cbc_events[] = {
+	L2C_CBC_EVENT_XMC0,
+	L2C_CBC_EVENT_XMD0,
+	L2C_CBC_EVENT_RSC0,
+	L2C_CBC_EVENT_RSD0,
+	L2C_CBC_EVENT_INV0,
+	L2C_CBC_EVENT_IOC0,
+	L2C_CBC_EVENT_IOR0,
+	L2C_CBC_EVENT_XMC1,
+	L2C_CBC_EVENT_XMD1,
+	L2C_CBC_EVENT_RSC1,
+	L2C_CBC_EVENT_RSD1,
+	L2C_CBC_EVENT_INV1,
+	L2C_CBC_EVENT_XMC2,
+	L2C_CBC_EVENT_XMD2,
+	L2C_CBC_EVENT_RSC2,
+	L2C_CBC_EVENT_RSD2,
+};
+
+static int thunder_uncore_add_l2c_cbc(struct perf_event *event, int flags)
+{
+	struct hw_perf_event *hwc = &event->hw;
+
+	return thunder_uncore_add(event, flags, 0,
+				  l2c_cbc_events[get_id(hwc->config)]);
+}
+
+PMU_FORMAT_ATTR(event, "config:0-4");
+
+static struct attribute *thunder_l2c_cbc_format_attr[] = {
+	&format_attr_event.attr,
+	&format_attr_node.attr,
+	NULL,
+};
+
+static struct attribute_group thunder_l2c_cbc_format_group = {
+	.name = "format",
+	.attrs = thunder_l2c_cbc_format_attr,
+};
+
+static struct attribute *thunder_l2c_cbc_events_attr[] = {
+	UC_EVENT_ENTRY(xmc0, 0),
+	UC_EVENT_ENTRY(xmd0, 1),
+	UC_EVENT_ENTRY(rsc0, 2),
+	UC_EVENT_ENTRY(rsd0, 3),
+	UC_EVENT_ENTRY(inv0, 4),
+	UC_EVENT_ENTRY(ioc0, 5),
+	UC_EVENT_ENTRY(ior0, 6),
+	UC_EVENT_ENTRY(xmc1, 7),
+	UC_EVENT_ENTRY(xmd1, 8),
+	UC_EVENT_ENTRY(rsc1, 9),
+	UC_EVENT_ENTRY(rsd1, 10),
+	UC_EVENT_ENTRY(inv1, 11),
+	UC_EVENT_ENTRY(xmc2, 12),
+	UC_EVENT_ENTRY(xmd2, 13),
+	UC_EVENT_ENTRY(rsc2, 14),
+	UC_EVENT_ENTRY(rsd2, 15),
+	NULL,
+};
+
+static struct attribute_group thunder_l2c_cbc_events_group = {
+	.name = "events",
+	.attrs = thunder_l2c_cbc_events_attr,
+};
+
+static const struct attribute_group *thunder_l2c_cbc_attr_groups[] = {
+	&thunder_uncore_attr_group,
+	&thunder_l2c_cbc_format_group,
+	&thunder_l2c_cbc_events_group,
+	NULL,
+};
+
+struct pmu thunder_l2c_cbc_pmu = {
+	.name		= "thunder_l2c_cbc",
+	.task_ctx_nr    = perf_invalid_context,
+	.event_init	= thunder_uncore_event_init,
+	.add		= thunder_uncore_add_l2c_cbc,
+	.del		= thunder_uncore_del,
+	.start		= thunder_uncore_start,
+	.stop		= thunder_uncore_stop,
+	.read		= thunder_uncore_read,
+	.attr_groups	= thunder_l2c_cbc_attr_groups,
+};
+
+static bool event_valid(u64 config)
+{
+	if (config < ARRAY_SIZE(l2c_cbc_events))
+		return true;
+
+	return false;
+}
+
+int __init thunder_uncore_l2c_cbc_setup(void)
+{
+	int ret = -ENOMEM;
+
+	thunder_uncore_l2c_cbc = kzalloc(sizeof(*thunder_uncore_l2c_cbc),
+					 GFP_KERNEL);
+	if (!thunder_uncore_l2c_cbc)
+		goto fail_nomem;
+
+	ret = thunder_uncore_setup(thunder_uncore_l2c_cbc, 0xa02f,
+				   &thunder_l2c_cbc_pmu,
+				   ARRAY_SIZE(l2c_cbc_events));
+	if (ret)
+		goto fail;
+
+	thunder_uncore_l2c_cbc->event_valid = event_valid;
+	return 0;
+
+fail:
+	kfree(thunder_uncore_l2c_cbc);
+fail_nomem:
+	return ret;
+}
-- 
2.9.0.rc0.21.g7777322

^ permalink raw reply related

* [PATCH v4 4/5] arm64: perf: Cavium ThunderX LMC uncore support
From: Jan Glauber @ 2016-10-29 11:55 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <cover.1477741719.git.jglauber@cavium.com>

Support counters on the DRAM controllers.

Signed-off-by: Jan Glauber <jglauber@cavium.com>
---
 drivers/perf/uncore/Makefile            |   3 +-
 drivers/perf/uncore/uncore_cavium.c     |   1 +
 drivers/perf/uncore/uncore_cavium.h     |   1 +
 drivers/perf/uncore/uncore_cavium_lmc.c | 118 ++++++++++++++++++++++++++++++++
 4 files changed, 122 insertions(+), 1 deletion(-)
 create mode 100644 drivers/perf/uncore/uncore_cavium_lmc.c

diff --git a/drivers/perf/uncore/Makefile b/drivers/perf/uncore/Makefile
index d5ef3db..ef04a2b9 100644
--- a/drivers/perf/uncore/Makefile
+++ b/drivers/perf/uncore/Makefile
@@ -1,3 +1,4 @@
 obj-$(CONFIG_UNCORE_PMU_CAVIUM) += uncore_cavium.o		\
 				   uncore_cavium_l2c_tad.o	\
-				   uncore_cavium_l2c_cbc.o
+				   uncore_cavium_l2c_cbc.o	\
+				   uncore_cavium_lmc.o
diff --git a/drivers/perf/uncore/uncore_cavium.c b/drivers/perf/uncore/uncore_cavium.c
index 051f0fa..fd9e49e 100644
--- a/drivers/perf/uncore/uncore_cavium.c
+++ b/drivers/perf/uncore/uncore_cavium.c
@@ -348,6 +348,7 @@ static int __init thunder_uncore_init(void)
 
 	thunder_uncore_l2c_tad_setup();
 	thunder_uncore_l2c_cbc_setup();
+	thunder_uncore_lmc_setup();
 	return 0;
 }
 late_initcall(thunder_uncore_init);
diff --git a/drivers/perf/uncore/uncore_cavium.h b/drivers/perf/uncore/uncore_cavium.h
index 91d674a..3897586 100644
--- a/drivers/perf/uncore/uncore_cavium.h
+++ b/drivers/perf/uncore/uncore_cavium.h
@@ -71,3 +71,4 @@ ssize_t thunder_events_sysfs_show(struct device *dev,
 				  char *page);
 int thunder_uncore_l2c_tad_setup(void);
 int thunder_uncore_l2c_cbc_setup(void);
+int thunder_uncore_lmc_setup(void);
diff --git a/drivers/perf/uncore/uncore_cavium_lmc.c b/drivers/perf/uncore/uncore_cavium_lmc.c
new file mode 100644
index 0000000..9668197
--- /dev/null
+++ b/drivers/perf/uncore/uncore_cavium_lmc.c
@@ -0,0 +1,118 @@
+/*
+ * Cavium Thunder uncore PMU support, Local memory controller (LMC) counters.
+ *
+ * Copyright 2016 Cavium Inc.
+ * Author: Jan Glauber <jan.glauber@cavium.com>
+ */
+
+#include <linux/perf_event.h>
+#include <linux/slab.h>
+
+#include "uncore_cavium.h"
+
+struct thunder_uncore *thunder_uncore_lmc;
+
+#define LMC_CONFIG_OFFSET		0x188
+#define LMC_CONFIG_RESET_BIT		BIT_ULL(17)
+
+/* LMC event list */
+#define LMC_EVENT_IFB_CNT		0x1d0
+#define LMC_EVENT_OPS_CNT		0x1d8
+#define LMC_EVENT_DCLK_CNT		0x1e0
+#define LMC_EVENT_BANK_CONFLICT1	0x360
+#define LMC_EVENT_BANK_CONFLICT2	0x368
+
+/* map counter numbers to register offsets */
+static int lmc_events[] = {
+	LMC_EVENT_IFB_CNT,
+	LMC_EVENT_OPS_CNT,
+	LMC_EVENT_DCLK_CNT,
+	LMC_EVENT_BANK_CONFLICT1,
+	LMC_EVENT_BANK_CONFLICT2,
+};
+
+static int thunder_uncore_add_lmc(struct perf_event *event, int flags)
+{
+	struct hw_perf_event *hwc = &event->hw;
+
+	return thunder_uncore_add(event, flags,
+				  LMC_CONFIG_OFFSET,
+				  lmc_events[get_id(hwc->config)]);
+}
+
+PMU_FORMAT_ATTR(event, "config:0-2");
+
+static struct attribute *thunder_lmc_format_attr[] = {
+	&format_attr_event.attr,
+	&format_attr_node.attr,
+	NULL,
+};
+
+static struct attribute_group thunder_lmc_format_group = {
+	.name = "format",
+	.attrs = thunder_lmc_format_attr,
+};
+
+static struct attribute *thunder_lmc_events_attr[] = {
+	UC_EVENT_ENTRY(ifb_cnt, 0),
+	UC_EVENT_ENTRY(ops_cnt, 1),
+	UC_EVENT_ENTRY(dclk_cnt, 2),
+	UC_EVENT_ENTRY(bank_conflict1, 3),
+	UC_EVENT_ENTRY(bank_conflict2, 4),
+	NULL,
+};
+
+static struct attribute_group thunder_lmc_events_group = {
+	.name = "events",
+	.attrs = thunder_lmc_events_attr,
+};
+
+static const struct attribute_group *thunder_lmc_attr_groups[] = {
+	&thunder_uncore_attr_group,
+	&thunder_lmc_format_group,
+	&thunder_lmc_events_group,
+	NULL,
+};
+
+struct pmu thunder_lmc_pmu = {
+	.name		= "thunder_lmc",
+	.task_ctx_nr    = perf_invalid_context,
+	.event_init	= thunder_uncore_event_init,
+	.add		= thunder_uncore_add_lmc,
+	.del		= thunder_uncore_del,
+	.start		= thunder_uncore_start,
+	.stop		= thunder_uncore_stop,
+	.read		= thunder_uncore_read,
+	.attr_groups	= thunder_lmc_attr_groups,
+};
+
+static bool event_valid(u64 config)
+{
+	if (config < ARRAY_SIZE(lmc_events))
+		return true;
+
+	return false;
+}
+
+int __init thunder_uncore_lmc_setup(void)
+{
+	int ret = -ENOMEM;
+
+	thunder_uncore_lmc = kzalloc(sizeof(*thunder_uncore_lmc), GFP_KERNEL);
+	if (!thunder_uncore_lmc)
+		goto fail_nomem;
+
+	ret = thunder_uncore_setup(thunder_uncore_lmc, 0xa022,
+				   &thunder_lmc_pmu,
+				   ARRAY_SIZE(lmc_events));
+	if (ret)
+		goto fail;
+
+	thunder_uncore_lmc->event_valid = event_valid;
+	return 0;
+
+fail:
+	kfree(thunder_uncore_lmc);
+fail_nomem:
+	return ret;
+}
-- 
2.9.0.rc0.21.g7777322

^ permalink raw reply related

* [PATCH v4 5/5] arm64: perf: Cavium ThunderX OCX TLK uncore support
From: Jan Glauber @ 2016-10-29 11:55 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <cover.1477741719.git.jglauber@cavium.com>

Support for the OCX transmit link counters.

Signed-off-by: Jan Glauber <jglauber@cavium.com>
---
 drivers/perf/uncore/Makefile                |   3 +-
 drivers/perf/uncore/uncore_cavium.c         |   1 +
 drivers/perf/uncore/uncore_cavium.h         |   1 +
 drivers/perf/uncore/uncore_cavium_ocx_tlk.c | 344 ++++++++++++++++++++++++++++
 4 files changed, 348 insertions(+), 1 deletion(-)
 create mode 100644 drivers/perf/uncore/uncore_cavium_ocx_tlk.c

diff --git a/drivers/perf/uncore/Makefile b/drivers/perf/uncore/Makefile
index ef04a2b9..7e2e8e5 100644
--- a/drivers/perf/uncore/Makefile
+++ b/drivers/perf/uncore/Makefile
@@ -1,4 +1,5 @@
 obj-$(CONFIG_UNCORE_PMU_CAVIUM) += uncore_cavium.o		\
 				   uncore_cavium_l2c_tad.o	\
 				   uncore_cavium_l2c_cbc.o	\
-				   uncore_cavium_lmc.o
+				   uncore_cavium_lmc.o		\
+				   uncore_cavium_ocx_tlk.o
diff --git a/drivers/perf/uncore/uncore_cavium.c b/drivers/perf/uncore/uncore_cavium.c
index fd9e49e..46ced45 100644
--- a/drivers/perf/uncore/uncore_cavium.c
+++ b/drivers/perf/uncore/uncore_cavium.c
@@ -349,6 +349,7 @@ static int __init thunder_uncore_init(void)
 	thunder_uncore_l2c_tad_setup();
 	thunder_uncore_l2c_cbc_setup();
 	thunder_uncore_lmc_setup();
+	thunder_uncore_ocx_tlk_setup();
 	return 0;
 }
 late_initcall(thunder_uncore_init);
diff --git a/drivers/perf/uncore/uncore_cavium.h b/drivers/perf/uncore/uncore_cavium.h
index 3897586..43ab426 100644
--- a/drivers/perf/uncore/uncore_cavium.h
+++ b/drivers/perf/uncore/uncore_cavium.h
@@ -72,3 +72,4 @@ ssize_t thunder_events_sysfs_show(struct device *dev,
 int thunder_uncore_l2c_tad_setup(void);
 int thunder_uncore_l2c_cbc_setup(void);
 int thunder_uncore_lmc_setup(void);
+int thunder_uncore_ocx_tlk_setup(void);
diff --git a/drivers/perf/uncore/uncore_cavium_ocx_tlk.c b/drivers/perf/uncore/uncore_cavium_ocx_tlk.c
new file mode 100644
index 0000000..b4fc32b
--- /dev/null
+++ b/drivers/perf/uncore/uncore_cavium_ocx_tlk.c
@@ -0,0 +1,344 @@
+/*
+ * Cavium Thunder uncore PMU support,
+ * CCPI interface controller (OCX) Transmit link (TLK) counters.
+ *
+ * Copyright 2016 Cavium Inc.
+ * Author: Jan Glauber <jan.glauber@cavium.com>
+ */
+
+#include <linux/perf_event.h>
+#include <linux/slab.h>
+
+#include "uncore_cavium.h"
+
+struct thunder_uncore *thunder_uncore_ocx_tlk;
+
+#define OCX_TLK_NR_UNITS			3
+#define OCX_TLK_UNIT_OFFSET			0x2000
+#define OCX_TLK_STAT_CTL			0x10040
+#define OCX_TLK_STAT_OFFSET			0x10400
+
+#define OCX_TLK_STAT_ENABLE_BIT			BIT_ULL(0)
+#define OCX_TLK_STAT_RESET_BIT			BIT_ULL(1)
+
+/* OCX TLK event list */
+#define OCX_TLK_EVENT_STAT_IDLE_CNT		0x00
+#define OCX_TLK_EVENT_STAT_DATA_CNT		0x08
+#define OCX_TLK_EVENT_STAT_SYNC_CNT		0x10
+#define OCX_TLK_EVENT_STAT_RETRY_CNT		0x18
+#define OCX_TLK_EVENT_STAT_ERR_CNT		0x20
+#define OCX_TLK_EVENT_STAT_MAT0_CNT		0x40
+#define OCX_TLK_EVENT_STAT_MAT1_CNT		0x48
+#define OCX_TLK_EVENT_STAT_MAT2_CNT		0x50
+#define OCX_TLK_EVENT_STAT_MAT3_CNT		0x58
+#define OCX_TLK_EVENT_STAT_VC0_CMD		0x80
+#define OCX_TLK_EVENT_STAT_VC1_CMD		0x88
+#define OCX_TLK_EVENT_STAT_VC2_CMD		0x90
+#define OCX_TLK_EVENT_STAT_VC3_CMD		0x98
+#define OCX_TLK_EVENT_STAT_VC4_CMD		0xa0
+#define OCX_TLK_EVENT_STAT_VC5_CMD		0xa8
+#define OCX_TLK_EVENT_STAT_VC0_PKT		0x100
+#define OCX_TLK_EVENT_STAT_VC1_PKT		0x108
+#define OCX_TLK_EVENT_STAT_VC2_PKT		0x110
+#define OCX_TLK_EVENT_STAT_VC3_PKT		0x118
+#define OCX_TLK_EVENT_STAT_VC4_PKT		0x120
+#define OCX_TLK_EVENT_STAT_VC5_PKT		0x128
+#define OCX_TLK_EVENT_STAT_VC6_PKT		0x130
+#define OCX_TLK_EVENT_STAT_VC7_PKT		0x138
+#define OCX_TLK_EVENT_STAT_VC8_PKT		0x140
+#define OCX_TLK_EVENT_STAT_VC9_PKT		0x148
+#define OCX_TLK_EVENT_STAT_VC10_PKT		0x150
+#define OCX_TLK_EVENT_STAT_VC11_PKT		0x158
+#define OCX_TLK_EVENT_STAT_VC12_PKT		0x160
+#define OCX_TLK_EVENT_STAT_VC13_PKT		0x168
+#define OCX_TLK_EVENT_STAT_VC0_CON		0x180
+#define OCX_TLK_EVENT_STAT_VC1_CON		0x188
+#define OCX_TLK_EVENT_STAT_VC2_CON		0x190
+#define OCX_TLK_EVENT_STAT_VC3_CON		0x198
+#define OCX_TLK_EVENT_STAT_VC4_CON		0x1a0
+#define OCX_TLK_EVENT_STAT_VC5_CON		0x1a8
+#define OCX_TLK_EVENT_STAT_VC6_CON		0x1b0
+#define OCX_TLK_EVENT_STAT_VC7_CON		0x1b8
+#define OCX_TLK_EVENT_STAT_VC8_CON		0x1c0
+#define OCX_TLK_EVENT_STAT_VC9_CON		0x1c8
+#define OCX_TLK_EVENT_STAT_VC10_CON		0x1d0
+#define OCX_TLK_EVENT_STAT_VC11_CON		0x1d8
+#define OCX_TLK_EVENT_STAT_VC12_CON		0x1e0
+#define OCX_TLK_EVENT_STAT_VC13_CON		0x1e8
+
+static int ocx_tlk_events[] = {
+	OCX_TLK_EVENT_STAT_IDLE_CNT,
+	OCX_TLK_EVENT_STAT_DATA_CNT,
+	OCX_TLK_EVENT_STAT_SYNC_CNT,
+	OCX_TLK_EVENT_STAT_RETRY_CNT,
+	OCX_TLK_EVENT_STAT_ERR_CNT,
+	OCX_TLK_EVENT_STAT_MAT0_CNT,
+	OCX_TLK_EVENT_STAT_MAT1_CNT,
+	OCX_TLK_EVENT_STAT_MAT2_CNT,
+	OCX_TLK_EVENT_STAT_MAT3_CNT,
+	OCX_TLK_EVENT_STAT_VC0_CMD,
+	OCX_TLK_EVENT_STAT_VC1_CMD,
+	OCX_TLK_EVENT_STAT_VC2_CMD,
+	OCX_TLK_EVENT_STAT_VC3_CMD,
+	OCX_TLK_EVENT_STAT_VC4_CMD,
+	OCX_TLK_EVENT_STAT_VC5_CMD,
+	OCX_TLK_EVENT_STAT_VC0_PKT,
+	OCX_TLK_EVENT_STAT_VC1_PKT,
+	OCX_TLK_EVENT_STAT_VC2_PKT,
+	OCX_TLK_EVENT_STAT_VC3_PKT,
+	OCX_TLK_EVENT_STAT_VC4_PKT,
+	OCX_TLK_EVENT_STAT_VC5_PKT,
+	OCX_TLK_EVENT_STAT_VC6_PKT,
+	OCX_TLK_EVENT_STAT_VC7_PKT,
+	OCX_TLK_EVENT_STAT_VC8_PKT,
+	OCX_TLK_EVENT_STAT_VC9_PKT,
+	OCX_TLK_EVENT_STAT_VC10_PKT,
+	OCX_TLK_EVENT_STAT_VC11_PKT,
+	OCX_TLK_EVENT_STAT_VC12_PKT,
+	OCX_TLK_EVENT_STAT_VC13_PKT,
+	OCX_TLK_EVENT_STAT_VC0_CON,
+	OCX_TLK_EVENT_STAT_VC1_CON,
+	OCX_TLK_EVENT_STAT_VC2_CON,
+	OCX_TLK_EVENT_STAT_VC3_CON,
+	OCX_TLK_EVENT_STAT_VC4_CON,
+	OCX_TLK_EVENT_STAT_VC5_CON,
+	OCX_TLK_EVENT_STAT_VC6_CON,
+	OCX_TLK_EVENT_STAT_VC7_CON,
+	OCX_TLK_EVENT_STAT_VC8_CON,
+	OCX_TLK_EVENT_STAT_VC9_CON,
+	OCX_TLK_EVENT_STAT_VC10_CON,
+	OCX_TLK_EVENT_STAT_VC11_CON,
+	OCX_TLK_EVENT_STAT_VC12_CON,
+	OCX_TLK_EVENT_STAT_VC13_CON,
+};
+
+/*
+ * The OCX devices have a single device per node, therefore picking the
+ * first device from the list is correct.
+ */
+static inline void __iomem *map_offset(struct thunder_uncore_node *node,
+				       unsigned long addr, int offset, int nr)
+{
+	struct thunder_uncore_unit *unit;
+
+	unit = list_first_entry(&node->unit_list, struct thunder_uncore_unit,
+				entry);
+	return (void __iomem *)(addr + unit->map + nr * offset);
+}
+
+static void __iomem *map_offset_ocx_tlk(struct thunder_uncore_node *node,
+					unsigned long addr, int nr)
+{
+	return (void __iomem *)map_offset(node, addr, nr, OCX_TLK_UNIT_OFFSET);
+}
+
+/*
+ * The OCX TLK counters can only be enabled/disabled as a set so we do
+ * this in pmu_enable/disable instead of start/stop.
+ */
+static void thunder_uncore_pmu_enable_ocx_tlk(struct pmu *pmu)
+{
+	struct thunder_uncore *uncore =
+		container_of(pmu, struct thunder_uncore, pmu);
+	int node = 0, i;
+
+	while (uncore->nodes[node++]) {
+		for (i = 0; i < OCX_TLK_NR_UNITS; i++) {
+			/* reset all TLK counters to zero */
+			writeb(OCX_TLK_STAT_RESET_BIT,
+			       map_offset_ocx_tlk(uncore->nodes[node],
+						  OCX_TLK_STAT_CTL, i));
+			/* enable all TLK counters */
+			writeb(OCX_TLK_STAT_ENABLE_BIT,
+			       map_offset_ocx_tlk(uncore->nodes[node],
+						  OCX_TLK_STAT_CTL, i));
+		}
+	}
+}
+
+/*
+ * The OCX TLK counters can only be enabled/disabled as a set so we do
+ * this in pmu_enable/disable instead of start/stop.
+ */
+static void thunder_uncore_pmu_disable_ocx_tlk(struct pmu *pmu)
+{
+	struct thunder_uncore *uncore =
+		container_of(pmu, struct thunder_uncore, pmu);
+	int node = 0, i;
+
+	while (uncore->nodes[node++]) {
+		for (i = 0; i < OCX_TLK_NR_UNITS; i++) {
+			/* disable all TLK counters */
+			writeb(0, map_offset_ocx_tlk(uncore->nodes[node],
+						     OCX_TLK_STAT_CTL, i));
+		}
+	}
+}
+
+/*
+ * Summarize counters across all TLK's. Different from the other uncore
+ * PMUs because all TLK's are on one PCI device.
+ */
+static void thunder_uncore_read_ocx_tlk(struct perf_event *event)
+{
+	struct thunder_uncore *uncore = to_uncore(event->pmu);
+	struct hw_perf_event *hwc = &event->hw;
+	struct thunder_uncore_node *node;
+	u64 new = 0;
+	int i;
+
+	/* read counter values from all units */
+	node = get_node(hwc->config, uncore);
+	for (i = 0; i < OCX_TLK_NR_UNITS; i++)
+		new += readq(map_offset_ocx_tlk(node, hwc->event_base, i));
+
+	local64_add(new, &hwc->prev_count);
+	local64_add(new, &event->count);
+}
+
+static void thunder_uncore_start_ocx_tlk(struct perf_event *event, int flags)
+{
+	struct thunder_uncore *uncore = to_uncore(event->pmu);
+	struct hw_perf_event *hwc = &event->hw;
+	struct thunder_uncore_node *node;
+	u64 new = 0;
+	int i;
+
+	/* read counter values from all units on the node */
+	node = get_node(hwc->config, uncore);
+	for (i = 0; i < OCX_TLK_NR_UNITS; i++)
+		new += readq(map_offset_ocx_tlk(node, hwc->event_base, i));
+	local64_set(&hwc->prev_count, new);
+
+	hwc->state = 0;
+	perf_event_update_userpage(event);
+}
+
+static int thunder_uncore_add_ocx_tlk(struct perf_event *event, int flags)
+{
+	struct hw_perf_event *hwc = &event->hw;
+
+	return thunder_uncore_add(event, flags,
+				  OCX_TLK_STAT_CTL,
+				  OCX_TLK_STAT_OFFSET + ocx_tlk_events[get_id(hwc->config)]);
+}
+
+PMU_FORMAT_ATTR(event, "config:0-5");
+
+static struct attribute *thunder_ocx_tlk_format_attr[] = {
+	&format_attr_event.attr,
+	&format_attr_node.attr,
+	NULL,
+};
+
+static struct attribute_group thunder_ocx_tlk_format_group = {
+	.name = "format",
+	.attrs = thunder_ocx_tlk_format_attr,
+};
+
+static struct attribute *thunder_ocx_tlk_events_attr[] = {
+	UC_EVENT_ENTRY(idle_cnt,	0),
+	UC_EVENT_ENTRY(data_cnt,	1),
+	UC_EVENT_ENTRY(sync_cnt,	2),
+	UC_EVENT_ENTRY(retry_cnt,	3),
+	UC_EVENT_ENTRY(err_cnt,		4),
+	UC_EVENT_ENTRY(mat0_cnt,	5),
+	UC_EVENT_ENTRY(mat1_cnt,	6),
+	UC_EVENT_ENTRY(mat2_cnt,	7),
+	UC_EVENT_ENTRY(mat3_cnt,	8),
+	UC_EVENT_ENTRY(vc0_cmd,		9),
+	UC_EVENT_ENTRY(vc1_cmd,		10),
+	UC_EVENT_ENTRY(vc2_cmd,		11),
+	UC_EVENT_ENTRY(vc3_cmd,		12),
+	UC_EVENT_ENTRY(vc4_cmd,		13),
+	UC_EVENT_ENTRY(vc5_cmd,		14),
+	UC_EVENT_ENTRY(vc0_pkt,		15),
+	UC_EVENT_ENTRY(vc1_pkt,		16),
+	UC_EVENT_ENTRY(vc2_pkt,		17),
+	UC_EVENT_ENTRY(vc3_pkt,		18),
+	UC_EVENT_ENTRY(vc4_pkt,		19),
+	UC_EVENT_ENTRY(vc5_pkt,		20),
+	UC_EVENT_ENTRY(vc6_pkt,		21),
+	UC_EVENT_ENTRY(vc7_pkt,		22),
+	UC_EVENT_ENTRY(vc8_pkt,		23),
+	UC_EVENT_ENTRY(vc9_pkt,		24),
+	UC_EVENT_ENTRY(vc10_pkt,	25),
+	UC_EVENT_ENTRY(vc11_pkt,	26),
+	UC_EVENT_ENTRY(vc12_pkt,	27),
+	UC_EVENT_ENTRY(vc13_pkt,	28),
+	UC_EVENT_ENTRY(vc0_con,		29),
+	UC_EVENT_ENTRY(vc1_con,		30),
+	UC_EVENT_ENTRY(vc2_con,		31),
+	UC_EVENT_ENTRY(vc3_con,		32),
+	UC_EVENT_ENTRY(vc4_con,		33),
+	UC_EVENT_ENTRY(vc5_con,		34),
+	UC_EVENT_ENTRY(vc6_con,		35),
+	UC_EVENT_ENTRY(vc7_con,		36),
+	UC_EVENT_ENTRY(vc8_con,		37),
+	UC_EVENT_ENTRY(vc9_con,		38),
+	UC_EVENT_ENTRY(vc10_con,	39),
+	UC_EVENT_ENTRY(vc11_con,	40),
+	UC_EVENT_ENTRY(vc12_con,	41),
+	UC_EVENT_ENTRY(vc13_con,	42),
+	NULL,
+};
+
+static struct attribute_group thunder_ocx_tlk_events_group = {
+	.name = "events",
+	.attrs = thunder_ocx_tlk_events_attr,
+};
+
+static const struct attribute_group *thunder_ocx_tlk_attr_groups[] = {
+	&thunder_uncore_attr_group,
+	&thunder_ocx_tlk_format_group,
+	&thunder_ocx_tlk_events_group,
+	NULL,
+};
+
+struct pmu thunder_ocx_tlk_pmu = {
+	.name		= "thunder_ocx_tlk",
+	.task_ctx_nr    = perf_invalid_context,
+	.pmu_enable	= thunder_uncore_pmu_enable_ocx_tlk,
+	.pmu_disable	= thunder_uncore_pmu_disable_ocx_tlk,
+	.event_init	= thunder_uncore_event_init,
+	.add		= thunder_uncore_add_ocx_tlk,
+	.del		= thunder_uncore_del,
+	.start		= thunder_uncore_start_ocx_tlk,
+	.stop		= thunder_uncore_stop,
+	.read		= thunder_uncore_read_ocx_tlk,
+	.attr_groups	= thunder_ocx_tlk_attr_groups,
+};
+
+static bool event_valid(u64 config)
+{
+	if (config < ARRAY_SIZE(ocx_tlk_events))
+		return true;
+
+	return false;
+}
+
+int __init thunder_uncore_ocx_tlk_setup(void)
+{
+	int ret;
+
+	thunder_uncore_ocx_tlk = kzalloc(sizeof(*thunder_uncore_ocx_tlk),
+					 GFP_KERNEL);
+	if (!thunder_uncore_ocx_tlk) {
+		ret = -ENOMEM;
+		goto fail_nomem;
+	}
+
+	ret = thunder_uncore_setup(thunder_uncore_ocx_tlk, 0xa013,
+				   &thunder_ocx_tlk_pmu,
+				   ARRAY_SIZE(ocx_tlk_events));
+	if (ret)
+		goto fail;
+
+	thunder_uncore_ocx_tlk->event_valid = event_valid;
+	return 0;
+
+fail:
+	kfree(thunder_uncore_ocx_tlk);
+fail_nomem:
+	return ret;
+}
-- 
2.9.0.rc0.21.g7777322

^ permalink raw reply related

* [PATCH v2] ARM: pxa: remove duplicated include from spitz.c
From: Robert Jarzmik @ 2016-10-29 11:56 UTC (permalink / raw)
  To: linux-arm-kernel

From: Wei Yongjun <weiyj.lk@gmail.com>

This partially reverts commit 12beb346710b ("Merge tag 'pxa-fixes-v4.8'
of https://github.com/rjarzmik/linux into randconfig-4.8").

This former patch introduced accidentally a double include of module.h.

Signed-off-by: Wei Yongjun <weiyj.lk@gmail.com>
Acked-by: Paul Gortmaker <paul.gortmaker@windriver.com>
[amended commit message and 2 comments]
Signed-off-by: Robert Jarzmik <robert.jarzmik@free.fr>
---
 arch/arm/mach-pxa/corgi.c | 1 -
 arch/arm/mach-pxa/spitz.c | 1 -
 2 files changed, 2 deletions(-)

diff --git a/arch/arm/mach-pxa/corgi.c b/arch/arm/mach-pxa/corgi.c
index 10bfdb169366..183cd3446f25 100644
--- a/arch/arm/mach-pxa/corgi.c
+++ b/arch/arm/mach-pxa/corgi.c
@@ -35,7 +35,6 @@
 #include <linux/mtd/sharpsl.h>
 #include <linux/input/matrix_keypad.h>
 #include <linux/gpio_keys.h>
-#include <linux/module.h>
 #include <linux/memblock.h>
 #include <video/w100fb.h>
 
diff --git a/arch/arm/mach-pxa/spitz.c b/arch/arm/mach-pxa/spitz.c
index 2c150bfc0cd5..67d66c702574 100644
--- a/arch/arm/mach-pxa/spitz.c
+++ b/arch/arm/mach-pxa/spitz.c
@@ -31,7 +31,6 @@
 #include <linux/input/matrix_keypad.h>
 #include <linux/regulator/machine.h>
 #include <linux/io.h>
-#include <linux/module.h>
 #include <linux/reboot.h>
 #include <linux/memblock.h>
 
-- 
2.1.4

^ permalink raw reply related

* [PATCH v3] ARM: bcm2835: Add names for the Raspberry Pi GPIO lines
From: Stefan Wahren @ 2016-10-29 12:15 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20161027165246.23936-1-eric@anholt.net>

Hi Eric,

> Eric Anholt <eric@anholt.net> hat am 27. Oktober 2016 um 18:52 geschrieben:
> 
> 
> From: Linus Walleij <linus.walleij@linaro.org>
> 
> The idea is to give useful names to GPIO lines that an implementer
> will be using from userspace, e.g. for maker type projects.  These are
> user-visible using tools/gpio/lsgpio.c

sorry for the late feedback, but did you check your patch against the Firmware
DTS [1]?

As an example the GPIO38 is connected and named as USB_LIMIT_1A2 since Raspberry
Pi 1 B Plus.

[1] -
https://github.com/raspberrypi/documentation/blob/master/configuration/images/dt-blob.dts

^ permalink raw reply

* Low network throughput on i.MX28
From: Jörg Krause @ 2016-10-29 13:08 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1143135945.89173.6f7a3a9a-5120-4cc2-a76b-92a516ab6500.open-xchange@email.1und1.de>

On Sat, 2016-10-29 at 11:08 +0200, Stefan Wahren wrote:
> > J?rg Krause <joerg.krause@embedded.rocks> hat am 29. Oktober 2016
> > um 01:07
> > geschrieben:
> > 
> > 
> > You mentioned [1] an optimization in the Freescale vendor Linux
> > kernel
> > [2]. I would really like to see this optimization in the mainline
> > kernel.
> > 
> > Did you ever tried to port this code from Freescale to mainline?
> 
> Yes, i tried once but i was frustrated soon because of the lot of
> required
> changes and resulting issues.

I can imagine.

> > 
> > Is it even possible, as the mainline driver uses the DMA engine?
> 
> I think the more important part would be analyse why the Mainline
> driver is
> slowlier. I mean to exactly identify the bottleneck.

I'll try to understand the driver implementation. However, I am not a
Linux kernel developer, so this will need some time for sure. Any help
will be appreciated!

> I don't have enough time and equipment for this. I better concentrate
> on standby
> support.

Many thanks for your work!

J?rg

^ permalink raw reply

* [PATCH 0/3] Support userspace irqchip with arch timers
From: Paolo Bonzini @ 2016-10-29 13:19 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <554F7514-1900-41B4-8DDC-36C00B903164@suse.de>

> > > > What the status of userspace for this thing? Are QEMU patches being
> > > > posted and reviewed?
> > > 
> > > I didn't see a notification that the patches were merged. Are they in
> > > Linus' tree yet? Then I can post enablement to qemu-devel.
> > 
> > I think you got it backward. I have no intention of merging them until I
> > see a vague consensus on the userspace API, and a set of patches ready
> > to be merged in QEMU.
> 
> That's not how kvm apis are made.

Actually I think it's always been like this, depending on what Marc meant for
"ready to be merged in QEMU".  It doesn't make sense to merge KVM APIs without
having userspace patches at least posted as RFC to qemu-devel, and without
having at least a positive response from the QEMU architecture maintainer.
ARM does require a bit more care because there's no overlap between kernel
and userspace maintainers, so perhaps that's the source of the confusion?

Now, of course merging the patches in QEMU may take a month or two depending
on the timing (because you have to wait for the patches to be merged into
Linus's tree and for the KVM headers to be updated in QEMU---which is not
going to happen during freeze of course).  So of course the KVM patch thus
can be committed even if QEMU is in freeze, as long as the QEMU architecture
maintainer gives an overall green light.

In fact a couple weeks from now would be the perfect time to post the patches
to QEMU.  Then you can get a review from Peter once he's back from vacation
(beginning of December), the KVM patches can easily make it for the 4.10 merge
window (end of December), and the userspace patches will hopefully be merged in
QEMU 2.9 in January 2017.

Thanks,

Paolo

^ permalink raw reply

* [PATCH] ARM: spear: Fix error handling
From: Christophe JAILLET @ 2016-10-29 13:58 UTC (permalink / raw)
  To: linux-arm-kernel

'clk_get_sys()' returns an error pointer in case of error, not NULL. So
test it with IS_ERR.

Signed-off-by: Christophe JAILLET <christophe.jaillet@wanadoo.fr>
---
 arch/arm/mach-spear/time.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm/mach-spear/time.c b/arch/arm/mach-spear/time.c
index 9ccffc1d0f28..4878ba90026d 100644
--- a/arch/arm/mach-spear/time.c
+++ b/arch/arm/mach-spear/time.c
@@ -233,7 +233,7 @@ void __init spear_setup_of_timer(void)
 	}
 
 	gpt_clk = clk_get_sys("gpt0", NULL);
-	if (!gpt_clk) {
+	if (IS_ERR(gpt_clk)) {
 		pr_err("%s:couldn't get clk for gpt\n", __func__);
 		goto err_iomap;
 	}
-- 
2.9.3

^ permalink raw reply related

* [PATCH] ARM: mm: add ARM_L1_CACHE_SHIFT_7 for UniPhier outer cache
From: Masahiro Yamada @ 2016-10-29 15:31 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1476880777-5068-1-git-send-email-yamada.masahiro@socionext.com>

Hi.

If there is no objection to this patch,
I will put it into Russell's patch tracker.


2016-10-19 21:39 GMT+09:00 Masahiro Yamada <yamada.masahiro@socionext.com>:
> The UniPhier outer cache (arch/arm/mm/cache-uniphier.c) has 128 byte
> line length and its tags are also managed per 128 byte line.  This
> is very unfortunate, but the current 64 byte alignment for kmalloc()
> causes sharing problems on DMA if used with this outer cache.
>
> This commit adds ARM_L1_CACHE_SHIFT_7 to increase the DMA minimum
> alignment to 128 byte if CACHE_UNIPHIER is enabled.  There are
> several drivers that assume aligning to L1_CACHE_BYTES will be DMA
> safe, so this commit also changes the L1_CACHE_BYTES for safety.
>
> Having said that, I hesitate to align all the other SoCs in Multi
> platform to the UniPhier's requirement.  So, I am disabling the
> CONFIG_CACHE_UNIPHIER by default, so that multi_v7_defconfig will
> still with CONFIG_ARM_L1_CACHE_SHIFT=6.  With this, UniPhier SoCs
> become a bit slower, but it is much better than system crash.
> If desired, the outer-cache can be enabled by the merge_config or
> something.
>
> Note:
> The UniPhier PH1-Pro5 SoC is equipped also with L3 cache with 256 byte
> line size but its tags are managed per 128 byte sub-line.
> So, ARM_L1_CACHE_SHIFT_7 should be fine for all the UniPhier SoCs.
>
> Signed-off-by: Masahiro Yamada <yamada.masahiro@socionext.com>
> ---
>
> I threw a question in January this year:
> http://lists.infradead.org/pipermail/linux-arm-kernel/2016-January/400289.html
>
> After a long interval, I came back to this topic.
>
>
>  arch/arm/mm/Kconfig | 8 +++++++-
>  1 file changed, 7 insertions(+), 1 deletion(-)
>
> diff --git a/arch/arm/mm/Kconfig b/arch/arm/mm/Kconfig
> index c1799dd..f68e8ec 100644
> --- a/arch/arm/mm/Kconfig
> +++ b/arch/arm/mm/Kconfig
> @@ -991,7 +991,7 @@ config CACHE_TAUROS2
>  config CACHE_UNIPHIER
>         bool "Enable the UniPhier outer cache controller"
>         depends on ARCH_UNIPHIER
> -       default y
> +       select ARM_L1_CACHE_SHIFT_7
>         select OUTER_CACHE
>         select OUTER_CACHE_SYNC
>         help
> @@ -1012,8 +1012,14 @@ config ARM_L1_CACHE_SHIFT_6
>         help
>           Setting ARM L1 cache line size to 64 Bytes.
>
> +config ARM_L1_CACHE_SHIFT_7
> +       bool
> +       help
> +         Setting ARM L1 cache line size to 128 Bytes.
> +
>  config ARM_L1_CACHE_SHIFT
>         int
> +       default 7 if ARM_L1_CACHE_SHIFT_7
>         default 6 if ARM_L1_CACHE_SHIFT_6
>         default 5
>
> --
> 1.9.1
>
>
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel



-- 
Best Regards
Masahiro Yamada

^ permalink raw reply

* [rjarzmik:pxa/for-next 8/8] arch/arm/mach-pxa/em-x270.c:987:15: error: variable 'camera_dummy_config' has initializer but incomplete type
From: kbuild test robot @ 2016-10-29 16:27 UTC (permalink / raw)
  To: linux-arm-kernel

tree:   https://github.com/rjarzmik/linux pxa/for-next
head:   f27d52aafe46f2cdce6a075970861dab30ff715d
commit: f27d52aafe46f2cdce6a075970861dab30ff715d [8/8] ARM: pxa: em-x270: use the new pxa_camera platform_data
config: arm-pxa_defconfig (attached as .config)
compiler: arm-linux-gnueabi-gcc (Debian 6.1.1-9) 6.1.1 20160705
reproduce:
        wget https://git.kernel.org/cgit/linux/kernel/git/wfg/lkp-tests.git/plain/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        git checkout f27d52aafe46f2cdce6a075970861dab30ff715d
        # save the attached .config to linux build tree
        make.cross ARCH=arm 

All error/warnings (new ones prefixed by >>):

>> arch/arm/mach-pxa/em-x270.c:987:15: error: variable 'camera_dummy_config' has initializer but incomplete type
    static struct fixed_voltage_config camera_dummy_config = {
                  ^~~~~~~~~~~~~~~~~~~~
>> arch/arm/mach-pxa/em-x270.c:988:2: error: unknown field 'supply_name' specified in initializer
     .supply_name  = "camera_vdd",
     ^
>> arch/arm/mach-pxa/em-x270.c:988:18: warning: excess elements in struct initializer
     .supply_name  = "camera_vdd",
                     ^~~~~~~~~~~~
   arch/arm/mach-pxa/em-x270.c:988:18: note: (near initialization for 'camera_dummy_config')
>> arch/arm/mach-pxa/em-x270.c:989:2: error: unknown field 'input_supply' specified in initializer
     .input_supply  = "vcc cam",
     ^
   arch/arm/mach-pxa/em-x270.c:989:19: warning: excess elements in struct initializer
     .input_supply  = "vcc cam",
                      ^~~~~~~~~
   arch/arm/mach-pxa/em-x270.c:989:19: note: (near initialization for 'camera_dummy_config')
>> arch/arm/mach-pxa/em-x270.c:990:2: error: unknown field 'microvolts' specified in initializer
     .microvolts  = 2800000,
     ^
   arch/arm/mach-pxa/em-x270.c:990:17: warning: excess elements in struct initializer
     .microvolts  = 2800000,
                    ^~~~~~~
   arch/arm/mach-pxa/em-x270.c:990:17: note: (near initialization for 'camera_dummy_config')
>> arch/arm/mach-pxa/em-x270.c:991:2: error: unknown field 'gpio' specified in initializer
     .gpio   = GPIO56_MT9M111_nOE,
     ^
>> arch/arm/mach-pxa/em-x270.c:991:12: error: 'GPIO56_MT9M111_nOE' undeclared here (not in a function)
     .gpio   = GPIO56_MT9M111_nOE,
               ^~~~~~~~~~~~~~~~~~
   arch/arm/mach-pxa/em-x270.c:991:12: warning: excess elements in struct initializer
   arch/arm/mach-pxa/em-x270.c:991:12: note: (near initialization for 'camera_dummy_config')
>> arch/arm/mach-pxa/em-x270.c:992:2: error: unknown field 'enable_high' specified in initializer
     .enable_high  = 0,
     ^
   arch/arm/mach-pxa/em-x270.c:992:18: warning: excess elements in struct initializer
     .enable_high  = 0,
                     ^
   arch/arm/mach-pxa/em-x270.c:992:18: note: (near initialization for 'camera_dummy_config')
>> arch/arm/mach-pxa/em-x270.c:993:2: error: unknown field 'init_data' specified in initializer
     .init_data  = &camera_dummy_initdata,
     ^
   arch/arm/mach-pxa/em-x270.c:993:16: warning: excess elements in struct initializer
     .init_data  = &camera_dummy_initdata,
                   ^
   arch/arm/mach-pxa/em-x270.c:993:16: note: (near initialization for 'camera_dummy_config')
>> arch/arm/mach-pxa/em-x270.c:987:36: error: storage size of 'camera_dummy_config' isn't known
    static struct fixed_voltage_config camera_dummy_config = {
                                       ^~~~~~~~~~~~~~~~~~~
>> arch/arm/mach-pxa/em-x270.c:996:31: warning: 'camera_supply_dummy_device' defined but not used [-Wunused-variable]
    static struct platform_device camera_supply_dummy_device = {
                                  ^~~~~~~~~~~~~~~~~~~~~~~~~~
>> arch/arm/mach-pxa/em-x270.c:959:26: warning: 'em_x270_camera_ldo' defined but not used [-Wunused-variable]
    static struct regulator *em_x270_camera_ldo;
                             ^~~~~~~~~~~~~~~~~~

vim +/camera_dummy_config +987 arch/arm/mach-pxa/em-x270.c

   953	#else
   954	static inline void em_x270_init_gpio_keys(void) {}
   955	#endif
   956	
   957	/* Quick Capture Interface and sensor setup */
   958	#if defined(CONFIG_VIDEO_PXA27x) || defined(CONFIG_VIDEO_PXA27x_MODULE)
 > 959	static struct regulator *em_x270_camera_ldo;
   960	
   961	static int em_x270_sensor_init(void)
   962	{
   963		int ret;
   964	
   965		ret = gpio_request(cam_reset, "camera reset");
   966		if (ret)
   967			return ret;
   968	
   969		gpio_direction_output(cam_reset, 0);
   970		gpio_set_value(cam_reset, 1);
   971	
   972		return 0;
   973	}
   974	
   975	static struct regulator_consumer_supply camera_dummy_supplies[] = {
   976		REGULATOR_SUPPLY("vdd", "0-005d"),
   977	};
   978	
   979	static struct regulator_init_data camera_dummy_initdata = {
   980		.consumer_supplies = camera_dummy_supplies,
   981		.num_consumer_supplies = ARRAY_SIZE(camera_dummy_supplies),
   982		.constraints = {
   983			.valid_ops_mask = REGULATOR_CHANGE_STATUS,
   984		},
   985	};
   986	
 > 987	static struct fixed_voltage_config camera_dummy_config = {
 > 988		.supply_name		= "camera_vdd",
 > 989		.input_supply		= "vcc cam",
 > 990		.microvolts		= 2800000,
 > 991		.gpio			= GPIO56_MT9M111_nOE,
 > 992		.enable_high		= 0,
 > 993		.init_data		= &camera_dummy_initdata,
   994	};
   995	
 > 996	static struct platform_device camera_supply_dummy_device = {
   997		.name	= "reg-fixed-voltage",
   998		.id	= 1,
   999		.dev	= {

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation
-------------- next part --------------
A non-text attachment was scrubbed...
Name: .config.gz
Type: application/gzip
Size: 30095 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20161030/40070bab/attachment-0001.gz>

^ permalink raw reply

* [PATCH -next] i2c: digicolor: use clk_disable_unprepare instead of clk_unprepare
From: Wei Yongjun @ 2016-10-29 16:31 UTC (permalink / raw)
  To: linux-arm-kernel

From: Wei Yongjun <weiyongjun1@huawei.com>

since clk_prepare_enable() is used to get i2c->clk, we should
use clk_disable_unprepare() to release it for the error path.

Signed-off-by: Wei Yongjun <weiyongjun1@huawei.com>
---
 drivers/i2c/busses/i2c-digicolor.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/i2c/busses/i2c-digicolor.c b/drivers/i2c/busses/i2c-digicolor.c
index 49f2084..50813a2 100644
--- a/drivers/i2c/busses/i2c-digicolor.c
+++ b/drivers/i2c/busses/i2c-digicolor.c
@@ -347,7 +347,7 @@ static int dc_i2c_probe(struct platform_device *pdev)
 
 	ret = i2c_add_adapter(&i2c->adap);
 	if (ret < 0) {
-		clk_unprepare(i2c->clk);
+		clk_disable_unprepare(i2c->clk);
 		return ret;
 	}

^ permalink raw reply related

* [GIT PULL] ARM: uniphier: fixes for v4.9
From: Olof Johansson @ 2016-10-29 18:08 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <CAK7LNATGyfiYYsxDeyhjerG16MMro--sxCC1nwpCu-9fN9+dBQ@mail.gmail.com>

On Sat, Oct 22, 2016 at 11:28:51PM +0900, Masahiro Yamada wrote:
> Hi Arnd, Olof,
> 
> Here are some fixes for v4.9.
> It is touching a reset controller driver, but Philipp gave me Acked-by
> for including it in my pull-request.
> 
> 
> Here is a question; do you have a chance to send a pull-request for fixes
> to Linus before -rc4?  In my understanding, pull requests for the next merge
> window are generally required to be based on a tag prior to -rc4.
> In the previous development cycle, I remember the fixes pull-request was
> sent around v4.8-rc7.  In this case, it would be a problem if a fixup commit
> and a new-development commit have a conflict with each other.
> If the first round of fixes pull-request is sent before -rc4, commits for
> the next merge window can be queued up based on -rc4 without any conflicts.

We send periodic pull requests, usually once per -rc (but sometimes we skip
one). These should make it into -rc3.

The base for next merge window should be based on as old a release as
practical, but what you can do is that you can use the fixes branch as the base
if you need to (just don't rebase it).


> The following changes since commit 1001354ca34179f3db924eb66672442a173147dc:
> 
>   Linux 4.9-rc1 (2016-10-15 12:17:50 -0700)
> 
> are available in the git repository at:
> 
>   git://git.kernel.org/pub/scm/linux/kernel/git/masahiroy/linux-uniphier.git
> tags/uniphier-fixes-v4.9
> 
> for you to fetch changes up to 8e68c65d111a57a4cbe41dc886bb2a1e671e0b6e:
> 
>   arm64: dts: uniphier: change MIO node to SD control node (2016-10-22
> 21:59:21 +0900)
> 
> ----------------------------------------------------------------
> UniPhier ARM SoC fixes for v4.9
> 
> - Add "select ARCH_HAS_RESET_CONTROLLER" in Kconfig
> - Rename wrongly-named mioctrl to sdctrl

Merged, thanks.


-Olof

^ permalink raw reply

* [GIT PULL] i.MX fixes for 4.9
From: Olof Johansson @ 2016-10-29 18:08 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20161024140622.GM30578@tiger>

On Mon, Oct 24, 2016 at 10:06:22PM +0800, Shawn Guo wrote:
> The following changes since commit 1001354ca34179f3db924eb66672442a173147dc:
> 
>   Linux 4.9-rc1 (2016-10-15 12:17:50 -0700)
> 
> are available in the git repository at:
> 
>   git://git.kernel.org/pub/scm/linux/kernel/git/shawnguo/linux.git tags/imx-fixes-4.9
> 
> for you to fetch changes up to 4edd601c5a9c5094daa714e65063e623826f3bcc:
> 
>   ARM: imx: mach-imx6q: Fix the PHY ID mask for AR8031 (2016-10-24 21:26:01 +0800)
> 
> ----------------------------------------------------------------
> The i.MX fixes for 4.9:
>  - A couple of patches from Fabio to fix the GPC power domain regression
>    which is caused by PM Domain core change 0159ec670763dd
>    ("PM / Domains: Verify the PM domain is present when adding a
>    provider"), and a related kernel crash seen with multi_v7_defconfig
>    build.
>  - Correct the PHY ID mask for AR8031 to match phy driver code.
>  - Apply new added timer erratum A008585 for LS1043A and LS2080A SoC.
>  - Correct vf610 global timer IRQ flag to avoid warning from gic driver
>    after commit 992345a58e0c ("irqchip/gic: WARN if setting the
>    interrupt type for a PPI fails").

Merged, thanks.


-Olof

^ 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