* FW: RE: [PATCH 0/4] PM / devfreq: Fix module autoload for platform drivers
From: MyungJoo Ham @ 2016-10-20 2:31 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <CGME20161019210645epcas1p449463edf9c3cb3681b0a4e8116ccf7f2@epcas1p4.samsung.com>
> > Hello,
> >
> > I noticed that module autoload won't be working in some of the defreq
> > platform drivers. This patch series contains the fixes for these.
> >
> > Best regards,
> > Javier
> >
> >
> > Javier Martinez Canillas (4):
> > PM / devfreq: rk3399_dmc: Fix module autoload
> > PM / devfreq: exynos-nocp: Fix module autoload
> > PM / devfreq: rockchip-dfi: Fix module autoload
> > PM / devfreq: exynos-ppmu: Fix module autoload
>
> Acked-by: MyungJoo Ham <myungjoo.ham@samsung.com>
>
> All the four are not at for-4.9-rc branch.
not --> now
> https://git.kernel.org/cgit/linux/kernel/git/mzx/devfreq.git/log/?h=for-4.9-rc
>
>
> Cheers,
> MyungJoo
>
> >
> > drivers/devfreq/event/exynos-nocp.c | 1 +
> > drivers/devfreq/event/exynos-ppmu.c | 1 +
> > drivers/devfreq/event/rockchip-dfi.c | 1 +
> > drivers/devfreq/rk3399_dmc.c | 1 +
> > 4 files changed, 4 insertions(+)
> >
> > --
> > 2.7.4
^ permalink raw reply
* [PATCH v2 1/4] cpufreq: pxa: use generic platdev driver for device-tree
From: Viresh Kumar @ 2016-10-20 3:34 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <87bmyg3xzh.fsf@belgarion.home>
On 19-10-16, 22:06, Robert Jarzmik wrote:
> Viresh Kumar <viresh.kumar@linaro.org> writes:
>
> >> >> + { .compatible = "marvell,pxa250", },
> >> >> + { .compatible = "marvell,pxa270", },
> >> >>
> >> >> { .compatible = "samsung,exynos3250", },
> >> >> { .compatible = "samsung,exynos4210", },
> >> >
> >> > Isn't there a race between cpufreq-dt and the platform driver to
> >> > register first ?
> >> Ah, could you be more specific about the race you're talking of ?
> >>
> >> My understanding was that cpufreq-dt-platdev does create the device, and
> >> cpufreq-dt is a driver for it, so there is no race but a direct relationship
> >> AFAIU.
> >
> > I mean that both the driver may try to register to the cpufreq core if
> > they are both compiled in a single image.
> Euh I still don't follow you. The only driver that can register to the cpufreq
> core is cpufreq-dt.
I was wondering on what will happen if both cpufreq-dt and your pxa2xx-cpufreq
driver are present in the same kernel image. In that case the init routines of
both of them will try to call cpufreq_register_driver().
--
viresh
^ permalink raw reply
* [PATCH v2 0/8] drm/sun4i: Support first display pipeline on sun6i
From: Chen-Yu Tsai @ 2016-10-20 3:43 UTC (permalink / raw)
To: linux-arm-kernel
Hi everyone,
This series adds support for the first display pipeline found on the
A31 and A31s SoCs, with output through the RGB LCD interface.
This has been tested on the Sinlinx SinA31s development board, with
its included 7" LCD panel, and the Merrii Hummingbird A31 development
board, with its dumb VGA DAC bridge.
Changes since v1:
- Made quirk structures static
- Dropped unused/unsupported quirks
- Dropped dotclock max frequency quirk patch.
The check for maximum PLL clock will be moved to the clk driver.
- Changed is_sun5i quirk to has_unknown_mux
- Dropped SinA31s LCD patch
- Added patch to support enable pin GPIO for dumb VGA DACs
- Added patch to enable VGA output via dumb VGA DAC on Hummingbird
A31 board
Regards
ChenYu
Chen-Yu Tsai (8):
drm/bridge: rgb-to-vga: Support an enable GPIO
drm/sun4i: sun6i-drc: Support DRC on A31 and A31s
drm/sun4i: tcon: Move SoC specific quirks to a DT matched data
structure
drm/sun4i: Add compatible string for A31/A31s TCON (timing controller)
drm/sun4i: Add compatible strings for A31/A31s display pipelines
ARM: dts: sun6i: Add device nodes for first display pipeline
ARM: dts: sun6i: Add A31 LCD0 RGB888 pins
ARM: dts: sun6i: hummingbird-a31: Enable display output through VGA
bridge
.../bindings/display/bridge/dumb-vga-dac.txt | 2 +
.../bindings/display/sunxi/sun4i-drm.txt | 10 +-
arch/arm/boot/dts/sun6i-a31-hummingbird.dts | 56 +++++++
arch/arm/boot/dts/sun6i-a31.dtsi | 165 +++++++++++++++++++++
arch/arm/boot/dts/sun6i-a31s.dtsi | 8 +
drivers/gpu/drm/bridge/dumb-vga-dac.c | 28 ++++
drivers/gpu/drm/sun4i/sun4i_backend.c | 1 +
drivers/gpu/drm/sun4i/sun4i_drv.c | 5 +
drivers/gpu/drm/sun4i/sun4i_tcon.c | 43 ++++--
drivers/gpu/drm/sun4i/sun4i_tcon.h | 11 +-
drivers/gpu/drm/sun4i/sun6i_drc.c | 2 +
11 files changed, 311 insertions(+), 20 deletions(-)
--
2.9.3
^ permalink raw reply
* [PATCH v2 1/8] drm/bridge: rgb-to-vga: Support an enable GPIO
From: Chen-Yu Tsai @ 2016-10-20 3:43 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161020034344.14154-1-wens@csie.org>
Some rgb-to-vga bridges have an enable GPIO, either directly tied to
an enable pin on the bridge IC, or indirectly controlling a power
switch.
Add support for it.
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 | 28 ++++++++++++++++++++++
2 files changed, 30 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..d3484822bf77 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:
+- enable-gpios: GPIO pin to enable or disable the bridge
Example
-------
diff --git a/drivers/gpu/drm/bridge/dumb-vga-dac.c b/drivers/gpu/drm/bridge/dumb-vga-dac.c
index afec232185a7..b487e5e9b56d 100644
--- a/drivers/gpu/drm/bridge/dumb-vga-dac.c
+++ b/drivers/gpu/drm/bridge/dumb-vga-dac.c
@@ -10,6 +10,7 @@
* the License, or (at your option) any later version.
*/
+#include <linux/gpio/consumer.h>
#include <linux/module.h>
#include <linux/of_graph.h>
@@ -23,6 +24,7 @@ struct dumb_vga {
struct drm_connector connector;
struct i2c_adapter *ddc;
+ struct gpio_desc *enable_gpio;
};
static inline struct dumb_vga *
@@ -124,8 +126,26 @@ 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);
+
+ if (vga->enable_gpio)
+ gpiod_set_value_cansleep(vga->enable_gpio, 1);
+}
+
+static void dumb_vga_disable(struct drm_bridge *bridge)
+{
+ struct dumb_vga *vga = drm_bridge_to_dumb_vga(bridge);
+
+ if (vga->enable_gpio)
+ gpiod_set_value_cansleep(vga->enable_gpio, 0);
+}
+
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 +189,14 @@ static int dumb_vga_probe(struct platform_device *pdev)
return -ENOMEM;
platform_set_drvdata(pdev, vga);
+ vga->enable_gpio = devm_gpiod_get_optional(&pdev->dev, "enable",
+ GPIOD_OUT_LOW);
+ if (IS_ERR(vga->enable_gpio)) {
+ ret = PTR_ERR(vga->enable_gpio);
+ dev_err(&pdev->dev, "failed to request GPIO: %d\n", ret);
+ return 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 v2 2/8] drm/sun4i: sun6i-drc: Support DRC on A31 and A31s
From: Chen-Yu Tsai @ 2016-10-20 3:43 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161020034344.14154-1-wens@csie.org>
The A31 and A31s also have the DRC as part of the display pipeline.
As we know virtually nothing about them, just add compatible strings
for both SoCs to the stub driver.
Signed-off-by: Chen-Yu Tsai <wens@csie.org>
Acked-by: Rob Herring <robh@kernel.org>
---
Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt | 2 ++
drivers/gpu/drm/sun4i/sun6i_drc.c | 2 ++
2 files changed, 4 insertions(+)
diff --git a/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt b/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt
index b95696d748c7..5368961cd727 100644
--- a/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt
+++ b/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt
@@ -64,6 +64,8 @@ adaptive backlight control.
Required properties:
- compatible: value must be one of:
+ * allwinner,sun6i-a31-drc
+ * allwinner,sun6i-a31s-drc
* allwinner,sun8i-a33-drc
- reg: base address and size of the memory-mapped region.
- interrupts: interrupt associated to this IP
diff --git a/drivers/gpu/drm/sun4i/sun6i_drc.c b/drivers/gpu/drm/sun4i/sun6i_drc.c
index bf6d846d8132..6ef707c5a719 100644
--- a/drivers/gpu/drm/sun4i/sun6i_drc.c
+++ b/drivers/gpu/drm/sun4i/sun6i_drc.c
@@ -98,6 +98,8 @@ static int sun6i_drc_remove(struct platform_device *pdev)
}
static const struct of_device_id sun6i_drc_of_table[] = {
+ { .compatible = "allwinner,sun6i-a31-drc" },
+ { .compatible = "allwinner,sun6i-a31s-drc" },
{ .compatible = "allwinner,sun8i-a33-drc" },
{ }
};
--
2.9.3
^ permalink raw reply related
* [PATCH v2 3/8] drm/sun4i: tcon: Move SoC specific quirks to a DT matched data structure
From: Chen-Yu Tsai @ 2016-10-20 3:43 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161020034344.14154-1-wens@csie.org>
We already have some differences between the 2 supported SoCs.
More will be added as we support other SoCs. To avoid bloating
the probe function with even more conditionals, move the quirks
to a separate data structure that's tied to the compatible string.
Signed-off-by: Chen-Yu Tsai <wens@csie.org>
---
drivers/gpu/drm/sun4i/sun4i_tcon.c | 33 ++++++++++++++++++---------------
drivers/gpu/drm/sun4i/sun4i_tcon.h | 11 +++++++----
2 files changed, 25 insertions(+), 19 deletions(-)
diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.c b/drivers/gpu/drm/sun4i/sun4i_tcon.c
index cadacb517f95..7658f0337e0b 100644
--- a/drivers/gpu/drm/sun4i/sun4i_tcon.c
+++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c
@@ -20,6 +20,7 @@
#include <linux/component.h>
#include <linux/ioport.h>
#include <linux/of_address.h>
+#include <linux/of_device.h>
#include <linux/of_graph.h>
#include <linux/of_irq.h>
#include <linux/regmap.h>
@@ -62,7 +63,7 @@ void sun4i_tcon_channel_disable(struct sun4i_tcon *tcon, int channel)
return;
}
- WARN_ON(!tcon->has_channel_1);
+ WARN_ON(!tcon->quirks->has_channel_1);
regmap_update_bits(tcon->regs, SUN4I_TCON1_CTL_REG,
SUN4I_TCON1_CTL_TCON_ENABLE, 0);
clk_disable_unprepare(tcon->sclk1);
@@ -80,7 +81,7 @@ void sun4i_tcon_channel_enable(struct sun4i_tcon *tcon, int channel)
return;
}
- WARN_ON(!tcon->has_channel_1);
+ WARN_ON(!tcon->quirks->has_channel_1);
regmap_update_bits(tcon->regs, SUN4I_TCON1_CTL_REG,
SUN4I_TCON1_CTL_TCON_ENABLE,
SUN4I_TCON1_CTL_TCON_ENABLE);
@@ -202,7 +203,7 @@ void sun4i_tcon1_mode_set(struct sun4i_tcon *tcon,
u8 clk_delay;
u32 val;
- WARN_ON(!tcon->has_channel_1);
+ WARN_ON(!tcon->quirks->has_channel_1);
/* Adjust clock delay */
clk_delay = sun4i_tcon_get_clk_delay(mode, 1);
@@ -266,7 +267,7 @@ void sun4i_tcon1_mode_set(struct sun4i_tcon *tcon,
/*
* FIXME: Undocumented bits
*/
- if (tcon->has_mux)
+ if (tcon->quirks->has_unknown_mux)
regmap_write(tcon->regs, SUN4I_TCON_MUX_CTRL_REG, 1);
}
EXPORT_SYMBOL(sun4i_tcon1_mode_set);
@@ -327,7 +328,7 @@ static int sun4i_tcon_init_clocks(struct device *dev,
return PTR_ERR(tcon->sclk0);
}
- if (tcon->has_channel_1) {
+ if (tcon->quirks->has_channel_1) {
tcon->sclk1 = devm_clk_get(dev, "tcon-ch1");
if (IS_ERR(tcon->sclk1)) {
dev_err(dev, "Couldn't get the TCON channel 1 clock\n");
@@ -487,14 +488,7 @@ static int sun4i_tcon_bind(struct device *dev, struct device *master,
drv->tcon = tcon;
tcon->drm = drm;
tcon->dev = dev;
-
- if (of_device_is_compatible(dev->of_node, "allwinner,sun5i-a13-tcon")) {
- tcon->has_mux = true;
- tcon->has_channel_1 = true;
- } else {
- tcon->has_mux = false;
- tcon->has_channel_1 = false;
- }
+ tcon->quirks = of_device_get_match_data(dev);
tcon->lcd_rst = devm_reset_control_get(dev, "lcd");
if (IS_ERR(tcon->lcd_rst)) {
@@ -588,9 +582,18 @@ static int sun4i_tcon_remove(struct platform_device *pdev)
return 0;
}
+static const struct sun4i_tcon_quirks sun5i_a13_quirks = {
+ .has_unknown_mux = true,
+ .has_channel_1 = true,
+};
+
+static const struct sun4i_tcon_quirks sun8i_a33_quirks = {
+ /* nothing is supported */
+};
+
static const struct of_device_id sun4i_tcon_of_table[] = {
- { .compatible = "allwinner,sun5i-a13-tcon" },
- { .compatible = "allwinner,sun8i-a33-tcon" },
+ { .compatible = "allwinner,sun5i-a13-tcon", .data = &sun5i_a13_quirks },
+ { .compatible = "allwinner,sun8i-a33-tcon", .data = &sun8i_a33_quirks },
{ }
};
MODULE_DEVICE_TABLE(of, sun4i_tcon_of_table);
diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.h b/drivers/gpu/drm/sun4i/sun4i_tcon.h
index 12bd48925f4d..166064bafe2e 100644
--- a/drivers/gpu/drm/sun4i/sun4i_tcon.h
+++ b/drivers/gpu/drm/sun4i/sun4i_tcon.h
@@ -142,6 +142,11 @@
#define SUN4I_TCON_MAX_CHANNELS 2
+struct sun4i_tcon_quirks {
+ bool has_unknown_mux; /* sun5i has undocumented mux */
+ bool has_channel_1; /* a33 does not have channel 1 */
+};
+
struct sun4i_tcon {
struct device *dev;
struct drm_device *drm;
@@ -160,12 +165,10 @@ struct sun4i_tcon {
/* Reset control */
struct reset_control *lcd_rst;
- /* Platform adjustments */
- bool has_mux;
-
struct drm_panel *panel;
- bool has_channel_1;
+ /* Platform adjustments */
+ const struct sun4i_tcon_quirks *quirks;
};
struct drm_bridge *sun4i_tcon_find_bridge(struct device_node *node);
--
2.9.3
^ permalink raw reply related
* [PATCH v2 4/8] drm/sun4i: Add compatible string for A31/A31s TCON (timing controller)
From: Chen-Yu Tsai @ 2016-10-20 3:43 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161020034344.14154-1-wens@csie.org>
The A31 TCON has mux controls for how TCON outputs are routed to the
HDMI and MIPI DSI blocks.
Since the A31s does not have MIPI DSI, it only has a mux for the HDMI
controller input.
This patch only adds support for the compatible strings. Actual support
for the mux controls should be added with HDMI and MIPI DSI support.
Signed-off-by: Chen-Yu Tsai <wens@csie.org>
---
Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt | 4 +++-
drivers/gpu/drm/sun4i/sun4i_drv.c | 2 ++
drivers/gpu/drm/sun4i/sun4i_tcon.c | 10 ++++++++++
3 files changed, 15 insertions(+), 1 deletion(-)
diff --git a/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt b/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt
index 5368961cd727..15fdca8909f2 100644
--- a/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt
+++ b/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt
@@ -28,6 +28,8 @@ The TCON acts as a timing controller for RGB, LVDS and TV interfaces.
Required properties:
- compatible: value must be either:
* allwinner,sun5i-a13-tcon
+ * allwinner,sun6i-a31-tcon
+ * allwinner,sun6i-a31s-tcon
* allwinner,sun8i-a33-tcon
- reg: base address and size of memory-mapped region
- interrupts: interrupt associated to this IP
@@ -50,7 +52,7 @@ Required properties:
second the block connected to the TCON channel 1 (usually the TV
encoder)
-On the A13, there is one more clock required:
+On SoCs other than the A33, there is one more clock required:
- 'tcon-ch1': The clock driving the TCON channel 1
DRC
diff --git a/drivers/gpu/drm/sun4i/sun4i_drv.c b/drivers/gpu/drm/sun4i/sun4i_drv.c
index 0da9862ad8ed..a15c231fbd59 100644
--- a/drivers/gpu/drm/sun4i/sun4i_drv.c
+++ b/drivers/gpu/drm/sun4i/sun4i_drv.c
@@ -207,6 +207,8 @@ static bool sun4i_drv_node_is_frontend(struct device_node *node)
static bool sun4i_drv_node_is_tcon(struct device_node *node)
{
return of_device_is_compatible(node, "allwinner,sun5i-a13-tcon") ||
+ of_device_is_compatible(node, "allwinner,sun6i-a31-tcon") ||
+ of_device_is_compatible(node, "allwinner,sun6i-a31s-tcon") ||
of_device_is_compatible(node, "allwinner,sun8i-a33-tcon");
}
diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.c b/drivers/gpu/drm/sun4i/sun4i_tcon.c
index 7658f0337e0b..c6afb2448655 100644
--- a/drivers/gpu/drm/sun4i/sun4i_tcon.c
+++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c
@@ -587,12 +587,22 @@ static const struct sun4i_tcon_quirks sun5i_a13_quirks = {
.has_channel_1 = true,
};
+static const struct sun4i_tcon_quirks sun6i_a31_quirks = {
+ .has_channel_1 = true,
+};
+
+static const struct sun4i_tcon_quirks sun6i_a31s_quirks = {
+ .has_channel_1 = true,
+};
+
static const struct sun4i_tcon_quirks sun8i_a33_quirks = {
/* nothing is supported */
};
static const struct of_device_id sun4i_tcon_of_table[] = {
{ .compatible = "allwinner,sun5i-a13-tcon", .data = &sun5i_a13_quirks },
+ { .compatible = "allwinner,sun6i-a31-tcon", .data = &sun6i_a31_quirks },
+ { .compatible = "allwinner,sun6i-a31s-tcon", .data = &sun6i_a31s_quirks },
{ .compatible = "allwinner,sun8i-a33-tcon", .data = &sun8i_a33_quirks },
{ }
};
--
2.9.3
^ permalink raw reply related
* [PATCH v2 5/8] drm/sun4i: Add compatible strings for A31/A31s display pipelines
From: Chen-Yu Tsai @ 2016-10-20 3:43 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161020034344.14154-1-wens@csie.org>
The A31's display pipeline has 2 frontends, 2 backends, and 2 TCONs. It
also has new display enhancement blocks, such as the DRC (Dynamic Range
Controller), the DEU (Display Enhancement Unit), and the CMU (Color
Management Unit). It supports HDMI, MIPI DSI, and 2 LCD/LVDS channels.
The A31s display pipeline is almost the same, just without MIPI DSI.
Only the TCON seems to be different, due to the missing mux for MIPI
DSI.
Add compatible strings for both of them.
Signed-off-by: Chen-Yu Tsai <wens@csie.org>
Acked-by: Rob Herring <robh@kernel.org>
---
Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt | 4 ++++
drivers/gpu/drm/sun4i/sun4i_backend.c | 1 +
drivers/gpu/drm/sun4i/sun4i_drv.c | 3 +++
3 files changed, 8 insertions(+)
diff --git a/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt b/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt
index 15fdca8909f2..b82c00449468 100644
--- a/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt
+++ b/Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt
@@ -91,6 +91,7 @@ system.
Required properties:
- compatible: value must be one of:
* allwinner,sun5i-a13-display-backend
+ * allwinner,sun6i-a31-display-backend
* allwinner,sun8i-a33-display-backend
- reg: base address and size of the memory-mapped region.
- clocks: phandles to the clocks feeding the frontend and backend
@@ -121,6 +122,7 @@ deinterlacing and color space conversion.
Required properties:
- compatible: value must be one of:
* allwinner,sun5i-a13-display-frontend
+ * allwinner,sun6i-a31-display-frontend
* allwinner,sun8i-a33-display-frontend
- reg: base address and size of the memory-mapped region.
- interrupts: interrupt associated to this IP
@@ -146,6 +148,8 @@ extra node.
Required properties:
- compatible: value must be one of:
* allwinner,sun5i-a13-display-engine
+ * allwinner,sun6i-a31-display-engine
+ * allwinner,sun6i-a31s-display-engine
* allwinner,sun8i-a33-display-engine
- allwinner,pipelines: list of phandle to the display engine
diff --git a/drivers/gpu/drm/sun4i/sun4i_backend.c b/drivers/gpu/drm/sun4i/sun4i_backend.c
index 32c0584e3c35..6e6c59a661b6 100644
--- a/drivers/gpu/drm/sun4i/sun4i_backend.c
+++ b/drivers/gpu/drm/sun4i/sun4i_backend.c
@@ -408,6 +408,7 @@ static int sun4i_backend_remove(struct platform_device *pdev)
static const struct of_device_id sun4i_backend_of_table[] = {
{ .compatible = "allwinner,sun5i-a13-display-backend" },
+ { .compatible = "allwinner,sun6i-a31-display-backend" },
{ .compatible = "allwinner,sun8i-a33-display-backend" },
{ }
};
diff --git a/drivers/gpu/drm/sun4i/sun4i_drv.c b/drivers/gpu/drm/sun4i/sun4i_drv.c
index a15c231fbd59..fa6568e1822a 100644
--- a/drivers/gpu/drm/sun4i/sun4i_drv.c
+++ b/drivers/gpu/drm/sun4i/sun4i_drv.c
@@ -201,6 +201,7 @@ static const struct component_master_ops sun4i_drv_master_ops = {
static bool sun4i_drv_node_is_frontend(struct device_node *node)
{
return of_device_is_compatible(node, "allwinner,sun5i-a13-display-frontend") ||
+ of_device_is_compatible(node, "allwinner,sun6i-a31-display-frontend") ||
of_device_is_compatible(node, "allwinner,sun8i-a33-display-frontend");
}
@@ -324,6 +325,8 @@ static int sun4i_drv_remove(struct platform_device *pdev)
static const struct of_device_id sun4i_drv_of_table[] = {
{ .compatible = "allwinner,sun5i-a13-display-engine" },
+ { .compatible = "allwinner,sun6i-a31-display-engine" },
+ { .compatible = "allwinner,sun6i-a31s-display-engine" },
{ .compatible = "allwinner,sun8i-a33-display-engine" },
{ }
};
--
2.9.3
^ permalink raw reply related
* [PATCH v2 6/8] ARM: dts: sun6i: Add device nodes for first display pipeline
From: Chen-Yu Tsai @ 2016-10-20 3:43 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161020034344.14154-1-wens@csie.org>
The A31 has 2 parallel display pipelines, which can be intermixed.
However the driver currently only supports one of them.
Signed-off-by: Chen-Yu Tsai <wens@csie.org>
---
arch/arm/boot/dts/sun6i-a31.dtsi | 152 ++++++++++++++++++++++++++++++++++++++
arch/arm/boot/dts/sun6i-a31s.dtsi | 8 ++
2 files changed, 160 insertions(+)
diff --git a/arch/arm/boot/dts/sun6i-a31.dtsi b/arch/arm/boot/dts/sun6i-a31.dtsi
index c1b891e75f18..4d2c7786b92a 100644
--- a/arch/arm/boot/dts/sun6i-a31.dtsi
+++ b/arch/arm/boot/dts/sun6i-a31.dtsi
@@ -231,6 +231,11 @@
};
};
+ de: display-engine {
+ compatible = "allwinner,sun6i-a31-display-engine";
+ allwinner,pipelines = <&fe0>;
+ };
+
soc at 01c00000 {
compatible = "simple-bus";
#address-cells = <1>;
@@ -246,6 +251,44 @@
#dma-cells = <1>;
};
+ tcon0: lcd-controller at 01c0c000 {
+ compatible = "allwinner,sun6i-a31-tcon";
+ reg = <0x01c0c000 0x1000>;
+ interrupts = <GIC_SPI 86 IRQ_TYPE_LEVEL_HIGH>;
+ resets = <&ccu RST_AHB1_LCD0>;
+ reset-names = "lcd";
+ clocks = <&ccu CLK_AHB1_LCD0>,
+ <&ccu CLK_LCD0_CH0>,
+ <&ccu CLK_LCD0_CH1>;
+ clock-names = "ahb",
+ "tcon-ch0",
+ "tcon-ch1";
+ clock-output-names = "tcon0-pixel-clock";
+ status = "disabled";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ tcon0_in: port at 0 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0>;
+
+ tcon0_in_drc0: endpoint at 0 {
+ reg = <0>;
+ remote-endpoint = <&drc0_out_tcon0>;
+ };
+ };
+
+ tcon0_out: port at 1 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <1>;
+ };
+ };
+ };
+
mmc0: mmc at 01c0f000 {
compatible = "allwinner,sun7i-a20-mmc";
reg = <0x01c0f000 0x1000>;
@@ -799,6 +842,115 @@
interrupts = <GIC_PPI 9 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>;
};
+ fe0: display-frontend at 01e00000 {
+ compatible = "allwinner,sun6i-a31-display-frontend";
+ reg = <0x01e00000 0x20000>;
+ interrupts = <GIC_SPI 93 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_AHB1_FE0>, <&ccu CLK_FE0>,
+ <&ccu CLK_DRAM_FE0>;
+ clock-names = "ahb", "mod",
+ "ram";
+ resets = <&ccu RST_AHB1_FE0>;
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ fe0_out: port at 1 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <1>;
+
+ fe0_out_be0: endpoint at 0 {
+ reg = <0>;
+ remote-endpoint = <&be0_in_fe0>;
+ };
+ };
+ };
+ };
+
+ be0: display-backend at 01e60000 {
+ compatible = "allwinner,sun6i-a31-display-backend";
+ reg = <0x01e60000 0x10000>;
+ interrupts = <GIC_SPI 95 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_AHB1_BE0>, <&ccu CLK_BE0>,
+ <&ccu CLK_DRAM_BE0>;
+ clock-names = "ahb", "mod",
+ "ram";
+ resets = <&ccu RST_AHB1_BE0>;
+
+ assigned-clocks = <&ccu CLK_BE0>;
+ assigned-clock-rates = <300000000>;
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ be0_in: port at 0 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0>;
+
+ be0_in_fe0: endpoint at 0 {
+ reg = <0>;
+ remote-endpoint = <&fe0_out_be0>;
+ };
+ };
+
+ be0_out: port at 1 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <1>;
+
+ be0_out_drc0: endpoint at 0 {
+ reg = <0>;
+ remote-endpoint = <&drc0_in_be0>;
+ };
+ };
+ };
+ };
+
+ drc0: drc at 01e70000 {
+ compatible = "allwinner,sun6i-a31-drc";
+ reg = <0x01e70000 0x10000>;
+ interrupts = <GIC_SPI 91 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_AHB1_DRC0>, <&ccu CLK_IEP_DRC0>,
+ <&ccu CLK_DRAM_DRC0>;
+ clock-names = "ahb", "mod",
+ "ram";
+ resets = <&ccu RST_AHB1_DRC0>;
+
+ assigned-clocks = <&ccu CLK_IEP_DRC0>;
+ assigned-clock-rates = <300000000>;
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ drc0_in: port at 0 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0>;
+
+ drc0_in_be0: endpoint at 0 {
+ reg = <0>;
+ remote-endpoint = <&be0_out_drc0>;
+ };
+ };
+
+ drc0_out: port at 1 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <1>;
+
+ drc0_out_tcon0: endpoint at 0 {
+ reg = <0>;
+ remote-endpoint = <&tcon0_in_drc0>;
+ };
+ };
+ };
+ };
+
rtc: rtc at 01f00000 {
compatible = "allwinner,sun6i-a31-rtc";
reg = <0x01f00000 0x54>;
diff --git a/arch/arm/boot/dts/sun6i-a31s.dtsi b/arch/arm/boot/dts/sun6i-a31s.dtsi
index c17a32771b98..97e2c51d0aea 100644
--- a/arch/arm/boot/dts/sun6i-a31s.dtsi
+++ b/arch/arm/boot/dts/sun6i-a31s.dtsi
@@ -48,6 +48,14 @@
#include "sun6i-a31.dtsi"
+&de {
+ compatible = "allwinner,sun6i-a31s-display-engine";
+};
+
&pio {
compatible = "allwinner,sun6i-a31s-pinctrl";
};
+
+&tcon0 {
+ compatible = "allwinner,sun6i-a31s-tcon";
+};
--
2.9.3
^ permalink raw reply related
* [PATCH v2 7/8] ARM: dts: sun6i: Add A31 LCD0 RGB888 pins
From: Chen-Yu Tsai @ 2016-10-20 3:43 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161020034344.14154-1-wens@csie.org>
The LCD0 controller on the A31 can do RGB output up to 8 bits per
channel. Add the pins for RGB888 output.
Signed-off-by: Chen-Yu Tsai <wens@csie.org>
---
arch/arm/boot/dts/sun6i-a31.dtsi | 13 +++++++++++++
1 file changed, 13 insertions(+)
diff --git a/arch/arm/boot/dts/sun6i-a31.dtsi b/arch/arm/boot/dts/sun6i-a31.dtsi
index 4d2c7786b92a..2e8bf93dcfb2 100644
--- a/arch/arm/boot/dts/sun6i-a31.dtsi
+++ b/arch/arm/boot/dts/sun6i-a31.dtsi
@@ -540,6 +540,19 @@
allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
};
+ lcd0_rgb888_pins: lcd0_rgb888 {
+ allwinner,pins = "PD0", "PD1", "PD2", "PD3",
+ "PD4", "PD5", "PD6", "PD7",
+ "PD8", "PD9", "PD10", "PD11",
+ "PD12", "PD13", "PD14", "PD15",
+ "PD16", "PD17", "PD18", "PD19",
+ "PD20", "PD21", "PD22", "PD23",
+ "PD24", "PD25", "PD26", "PD27";
+ allwinner,function = "lcd0";
+ allwinner,drive = <SUN4I_PINCTRL_10_MA>;
+ allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
+ };
+
mmc0_pins_a: mmc0 at 0 {
allwinner,pins = "PF0", "PF1", "PF2",
"PF3", "PF4", "PF5";
--
2.9.3
^ permalink raw reply related
* [PATCH v2 8/8] ARM: dts: sun6i: hummingbird-a31: Enable display output through VGA bridge
From: Chen-Yu Tsai @ 2016-10-20 3:43 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161020034344.14154-1-wens@csie.org>
The Hummingbird A31 board has a RGB-to-VGA bridge which converts RGB
output from the LCD interface to VGA signals.
Enable this part of the display pipeline.
Signed-off-by: Chen-Yu Tsai <wens@csie.org>
---
arch/arm/boot/dts/sun6i-a31-hummingbird.dts | 56 +++++++++++++++++++++++++++++
1 file changed, 56 insertions(+)
diff --git a/arch/arm/boot/dts/sun6i-a31-hummingbird.dts b/arch/arm/boot/dts/sun6i-a31-hummingbird.dts
index 9a74637f677f..05a49b2147f1 100644
--- a/arch/arm/boot/dts/sun6i-a31-hummingbird.dts
+++ b/arch/arm/boot/dts/sun6i-a31-hummingbird.dts
@@ -63,6 +63,49 @@
stdout-path = "serial0:115200n8";
};
+ bridge {
+ compatible = "dumb-vga-dac";
+ #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_bridge_in: endpoint at 0 {
+ reg = <0>;
+ remote-endpoint = <&tcon0_out_vga>;
+ };
+ };
+
+ port at 1 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <1>;
+
+ vga_bridge_out: endpoint at 0 {
+ reg = <0>;
+ remote-endpoint = <&vga_con_in>;
+ };
+ };
+ };
+ };
+
+ vga {
+ compatible = "vga-connector";
+
+ port {
+ vga_con_in: endpoint {
+ remote-endpoint = <&vga_bridge_out>;
+ };
+ };
+ };
+
wifi_pwrseq: wifi_pwrseq {
compatible = "mmc-pwrseq-simple";
reset-gpios = <&pio 6 10 GPIO_ACTIVE_LOW>; /* PG10 */
@@ -245,6 +288,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_bridge_in>;
+ };
+};
+
&uart0 {
pinctrl-names = "default";
pinctrl-0 = <&uart0_pins_a>;
--
2.9.3
^ permalink raw reply related
* [PATCH 1/2] arm64/numa: fix pcpu_cpu_distance() to get correct CPU proximity
From: Hanjun Guo @ 2016-10-20 3:52 UTC (permalink / raw)
To: linux-arm-kernel
From: Yisheng Xie <xieyisheng1@huawei.com>
The pcpu_build_alloc_info() function group CPUs according to their
proximity, by call callback function @cpu_distance_fn from different
ARCHs.
For arm64 the callback of @cpu_distance_fn is
pcpu_cpu_distance(from, to)
-> node_distance(from, to)
The @from and @to for function node_distance() should be nid.
However, pcpu_cpu_distance() in arch/arm64/mm/numa.c just past the
cpu id for @from and @to.
For this incorrect cpu proximity get from ARCH, it may cause each CPU
in one group and make group_cnt out of bound:
setup_per_cpu_areas()
pcpu_embed_first_chunk()
pcpu_build_alloc_info()
in pcpu_build_alloc_info, since cpu_distance_fn will return
REMOTE_DISTANCE if we pass cpu ids (0,1,2...), so
cpu_distance_fn(cpu, tcpu) > LOCAL_DISTANCE will wrongly be ture.
This may results in triggering the BUG_ON(unit != nr_units) later:
[ 0.000000] kernel BUG at mm/percpu.c:1916!
[ 0.000000] Internal error: Oops - BUG: 0 [#1] PREEMPT SMP
[ 0.000000] Modules linked in:
[ 0.000000] CPU: 0 PID: 0 Comm: swapper Not tainted 4.9.0-rc1-00003-g14155ca-dirty #26
[ 0.000000] Hardware name: Hisilicon Hi1616 Evaluation Board (DT)
[ 0.000000] task: ffff000008d6e900 task.stack: ffff000008d60000
[ 0.000000] PC is at pcpu_embed_first_chunk+0x420/0x704
[ 0.000000] LR is at pcpu_embed_first_chunk+0x3bc/0x704
[ 0.000000] pc : [<ffff000008c754f4>] lr : [<ffff000008c75490>] pstate: 800000c5
[ 0.000000] sp : ffff000008d63eb0
[ 0.000000] x29: ffff000008d63eb0 [ 0.000000] x28: 0000000000000000
[ 0.000000] x27: 0000000000000040 [ 0.000000] x26: ffff8413fbfcef00
[ 0.000000] x25: 0000000000000042 [ 0.000000] x24: 0000000000000042
[ 0.000000] x23: 0000000000001000 [ 0.000000] x22: 0000000000000046
[ 0.000000] x21: 0000000000000001 [ 0.000000] x20: ffff000008cb3bc8
[ 0.000000] x19: ffff8413fbfcf570 [ 0.000000] x18: 0000000000000000
[ 0.000000] x17: ffff000008e49ae0 [ 0.000000] x16: 0000000000000003
[ 0.000000] x15: 000000000000001e [ 0.000000] x14: 0000000000000004
[ 0.000000] x13: 0000000000000000 [ 0.000000] x12: 000000000000006f
[ 0.000000] x11: 00000413fbffff00 [ 0.000000] x10: 0000000000000004
[ 0.000000] x9 : 0000000000000000 [ 0.000000] x8 : 0000000000000001
[ 0.000000] x7 : ffff8413fbfcf63c [ 0.000000] x6 : ffff000008d65d28
[ 0.000000] x5 : ffff000008d65e50 [ 0.000000] x4 : 0000000000000000
[ 0.000000] x3 : ffff000008cb3cc8 [ 0.000000] x2 : 0000000000000040
[ 0.000000] x1 : 0000000000000040 [ 0.000000] x0 : 0000000000000000
[...]
[ 0.000000] Call trace:
[ 0.000000] Exception stack(0xffff000008d63ce0 to 0xffff000008d63e10)
[ 0.000000] 3ce0: ffff8413fbfcf570 0001000000000000 ffff000008d63eb0 ffff000008c754f4
[ 0.000000] 3d00: ffff000008d63d50 ffff0000081af210 00000413fbfff010 0000000000001000
[ 0.000000] 3d20: ffff000008d63d50 ffff0000081af220 00000413fbfff010 0000000000001000
[ 0.000000] 3d40: 00000413fbfcef00 0000000000000004 ffff000008d63db0 ffff0000081af390
[ 0.000000] 3d60: 00000413fbfcef00 0000000000001000 0000000000000000 0000000000001000
[ 0.000000] 3d80: 0000000000000000 0000000000000040 0000000000000040 ffff000008cb3cc8
[ 0.000000] 3da0: 0000000000000000 ffff000008d65e50 ffff000008d65d28 ffff8413fbfcf63c
[ 0.000000] 3dc0: 0000000000000001 0000000000000000 0000000000000004 00000413fbffff00
[ 0.000000] 3de0: 000000000000006f 0000000000000000 0000000000000004 000000000000001e
[ 0.000000] 3e00: 0000000000000003 ffff000008e49ae0
[ 0.000000] [<ffff000008c754f4>] pcpu_embed_first_chunk+0x420/0x704
[ 0.000000] [<ffff000008c6658c>] setup_per_cpu_areas+0x38/0xc8
[ 0.000000] [<ffff000008c608d8>] start_kernel+0x10c/0x390
[ 0.000000] [<ffff000008c601d8>] __primary_switched+0x5c/0x64
[ 0.000000] Code: b8018660 17ffffd7 6b16037f 54000080 (d4210000)
[ 0.000000] ---[ end trace 0000000000000000 ]---
[ 0.000000] Kernel panic - not syncing: Attempted to kill the idle task!
Fix by getting CPUs proximity through its node. We only care about
whether it is LOCAL_DISTANCE or not, for pcpu_build_alloc_info() only
use this to group CPUs.
Fixes: 7af3a0a99252 ("arm64/numa: support HAVE_SETUP_PER_CPU_AREA")
Signed-off-by: Yisheng Xie <xieyisheng1@huawei.com>
Signed-off-by: Hanjun Guo <hanjun.guo@linaro.org>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
Cc: Will Deacon <will.deacon@arm.com>
Cc: Zhen Lei <thunder.leizhen@huawei.com>
---
arch/arm64/mm/numa.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/arch/arm64/mm/numa.c b/arch/arm64/mm/numa.c
index 778a985..34415fc 100644
--- a/arch/arm64/mm/numa.c
+++ b/arch/arm64/mm/numa.c
@@ -147,7 +147,10 @@ static int __init early_cpu_to_node(int cpu)
static int __init pcpu_cpu_distance(unsigned int from, unsigned int to)
{
- return node_distance(from, to);
+ if (early_cpu_to_node(from) == early_cpu_to_node(to))
+ return LOCAL_DISTANCE;
+ else
+ return REMOTE_DISTANCE;
}
static void * __init pcpu_fc_alloc(unsigned int cpu, size_t size,
--
1.7.12.4
^ permalink raw reply related
* [PATCH 2/2] arm64/numa: fix incorrect print of end_pfn
From: Hanjun Guo @ 2016-10-20 3:52 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1476935576-59941-1-git-send-email-guohanjun@huawei.com>
From: Hanjun Guo <hanjun.guo@linaro.org>
When booting on NUMA system with memory-less node (no
memory dimm on this memory controller), the print
for setup_node_data() is incorrect:
NUMA: Initmem setup node 2 [mem 0x00000000-0xffffffffffffffff]
It should be 0, not 0xffffffffffffffff as there is
no memory on that node.
Fixes: 1a2db300348b ("arm64, numa: Add NUMA support for arm64 platforms.")
Signed-off-by: Hanjun Guo <hanjun.guo@linaro.org>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Ganapatrao Kulkarni <gkulkarni@caviumnetworks.com>
Cc: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
Cc: Will Deacon <will.deacon@arm.com>
---
arch/arm64/mm/numa.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/arch/arm64/mm/numa.c b/arch/arm64/mm/numa.c
index 34415fc..148e1fc 100644
--- a/arch/arm64/mm/numa.c
+++ b/arch/arm64/mm/numa.c
@@ -227,7 +227,8 @@ static void __init setup_node_data(int nid, u64 start_pfn, u64 end_pfn)
int tnid;
pr_info("Initmem setup node %d [mem %#010Lx-%#010Lx]\n",
- nid, start_pfn << PAGE_SHIFT, (end_pfn << PAGE_SHIFT) - 1);
+ nid, start_pfn << PAGE_SHIFT,
+ end_pfn ? (end_pfn << PAGE_SHIFT) - 1 : 0);
nd_pa = memblock_alloc_try_nid(nd_size, SMP_CACHE_BYTES, nid);
nd = __va(nd_pa);
--
1.7.12.4
^ permalink raw reply related
* [PATCH v2 2/2] arm64: dts: uniphier: add CPU clocks and OPP tables for LD20 SoC
From: Viresh Kumar @ 2016-10-20 3:55 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1476926126-6079-2-git-send-email-yamada.masahiro@socionext.com>
On 20-10-16, 10:15, Masahiro Yamada wrote:
> + opp at 666666666 {
> + opp-hz = /bits/ 64 <666667000>;
> + clock-latency-ns = <300>;
> + };
> + opp at 733333333 {
> + opp-hz = /bits/ 64 <733334000>;
> + clock-latency-ns = <300>;
> + };
Forgot changing these ? Please make sure to update all of them.
--
viresh
^ permalink raw reply
* [PATCH v2 2/2] arm64: dts: uniphier: add CPU clocks and OPP tables for LD20 SoC
From: Masahiro Yamada @ 2016-10-20 3:59 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161020035542.GG11766@vireshk-i7>
2016-10-20 12:55 GMT+09:00 Viresh Kumar <viresh.kumar@linaro.org>:
> On 20-10-16, 10:15, Masahiro Yamada wrote:
>> + opp at 666666666 {
>> + opp-hz = /bits/ 64 <666667000>;
>> + clock-latency-ns = <300>;
>> + };
>> + opp at 733333333 {
>> + opp-hz = /bits/ 64 <733334000>;
>> + clock-latency-ns = <300>;
>> + };
>
> Forgot changing these ? Please make sure to update all of them.
>
Oops, I missed that.
Will fix soon.
Thanks!
--
Best Regards
Masahiro Yamada
^ permalink raw reply
* [PATCH 1/2] arm64/numa: fix pcpu_cpu_distance() to get correct CPU proximity
From: Hanjun Guo @ 2016-10-20 4:03 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1476935576-59941-1-git-send-email-guohanjun@huawei.com>
On 2016/10/20 11:52, Hanjun Guo wrote:
> From: Yisheng Xie <xieyisheng1@huawei.com>
>
> The pcpu_build_alloc_info() function group CPUs according to their
> proximity, by call callback function @cpu_distance_fn from different
> ARCHs.
>
> For arm64 the callback of @cpu_distance_fn is
> pcpu_cpu_distance(from, to)
> -> node_distance(from, to)
> The @from and @to for function node_distance() should be nid.
>
> However, pcpu_cpu_distance() in arch/arm64/mm/numa.c just past the
> cpu id for @from and @to.
>
> For this incorrect cpu proximity get from ARCH, it may cause each CPU
> in one group and make group_cnt out of bound:
>
> setup_per_cpu_areas()
> pcpu_embed_first_chunk()
> pcpu_build_alloc_info()
> in pcpu_build_alloc_info, since cpu_distance_fn will return
> REMOTE_DISTANCE if we pass cpu ids (0,1,2...), so
> cpu_distance_fn(cpu, tcpu) > LOCAL_DISTANCE will wrongly be ture.
>
> This may results in triggering the BUG_ON(unit != nr_units) later:
>
> [ 0.000000] kernel BUG at mm/percpu.c:1916!
> [ 0.000000] Internal error: Oops - BUG: 0 [#1] PREEMPT SMP
> [ 0.000000] Modules linked in:
> [ 0.000000] CPU: 0 PID: 0 Comm: swapper Not tainted 4.9.0-rc1-00003-g14155ca-dirty #26
> [ 0.000000] Hardware name: Hisilicon Hi1616 Evaluation Board (DT)
> [ 0.000000] task: ffff000008d6e900 task.stack: ffff000008d60000
> [ 0.000000] PC is at pcpu_embed_first_chunk+0x420/0x704
> [ 0.000000] LR is at pcpu_embed_first_chunk+0x3bc/0x704
> [ 0.000000] pc : [<ffff000008c754f4>] lr : [<ffff000008c75490>] pstate: 800000c5
> [ 0.000000] sp : ffff000008d63eb0
> [ 0.000000] x29: ffff000008d63eb0 [ 0.000000] x28: 0000000000000000
> [ 0.000000] x27: 0000000000000040 [ 0.000000] x26: ffff8413fbfcef00
> [ 0.000000] x25: 0000000000000042 [ 0.000000] x24: 0000000000000042
> [ 0.000000] x23: 0000000000001000 [ 0.000000] x22: 0000000000000046
> [ 0.000000] x21: 0000000000000001 [ 0.000000] x20: ffff000008cb3bc8
> [ 0.000000] x19: ffff8413fbfcf570 [ 0.000000] x18: 0000000000000000
> [ 0.000000] x17: ffff000008e49ae0 [ 0.000000] x16: 0000000000000003
> [ 0.000000] x15: 000000000000001e [ 0.000000] x14: 0000000000000004
> [ 0.000000] x13: 0000000000000000 [ 0.000000] x12: 000000000000006f
> [ 0.000000] x11: 00000413fbffff00 [ 0.000000] x10: 0000000000000004
> [ 0.000000] x9 : 0000000000000000 [ 0.000000] x8 : 0000000000000001
> [ 0.000000] x7 : ffff8413fbfcf63c [ 0.000000] x6 : ffff000008d65d28
> [ 0.000000] x5 : ffff000008d65e50 [ 0.000000] x4 : 0000000000000000
> [ 0.000000] x3 : ffff000008cb3cc8 [ 0.000000] x2 : 0000000000000040
> [ 0.000000] x1 : 0000000000000040 [ 0.000000] x0 : 0000000000000000
> [...]
> [ 0.000000] Call trace:
> [ 0.000000] Exception stack(0xffff000008d63ce0 to 0xffff000008d63e10)
> [ 0.000000] 3ce0: ffff8413fbfcf570 0001000000000000 ffff000008d63eb0 ffff000008c754f4
> [ 0.000000] 3d00: ffff000008d63d50 ffff0000081af210 00000413fbfff010 0000000000001000
> [ 0.000000] 3d20: ffff000008d63d50 ffff0000081af220 00000413fbfff010 0000000000001000
> [ 0.000000] 3d40: 00000413fbfcef00 0000000000000004 ffff000008d63db0 ffff0000081af390
> [ 0.000000] 3d60: 00000413fbfcef00 0000000000001000 0000000000000000 0000000000001000
> [ 0.000000] 3d80: 0000000000000000 0000000000000040 0000000000000040 ffff000008cb3cc8
> [ 0.000000] 3da0: 0000000000000000 ffff000008d65e50 ffff000008d65d28 ffff8413fbfcf63c
> [ 0.000000] 3dc0: 0000000000000001 0000000000000000 0000000000000004 00000413fbffff00
> [ 0.000000] 3de0: 000000000000006f 0000000000000000 0000000000000004 000000000000001e
> [ 0.000000] 3e00: 0000000000000003 ffff000008e49ae0
> [ 0.000000] [<ffff000008c754f4>] pcpu_embed_first_chunk+0x420/0x704
> [ 0.000000] [<ffff000008c6658c>] setup_per_cpu_areas+0x38/0xc8
> [ 0.000000] [<ffff000008c608d8>] start_kernel+0x10c/0x390
> [ 0.000000] [<ffff000008c601d8>] __primary_switched+0x5c/0x64
> [ 0.000000] Code: b8018660 17ffffd7 6b16037f 54000080 (d4210000)
> [ 0.000000] ---[ end trace 0000000000000000 ]---
> [ 0.000000] Kernel panic - not syncing: Attempted to kill the idle task!
>
> Fix by getting CPUs proximity through its node. We only care about
> whether it is LOCAL_DISTANCE or not, for pcpu_build_alloc_info() only
> use this to group CPUs.
>
> Fixes: 7af3a0a99252 ("arm64/numa: support HAVE_SETUP_PER_CPU_AREA")
> Signed-off-by: Yisheng Xie <xieyisheng1@huawei.com>
> Signed-off-by: Hanjun Guo <hanjun.guo@linaro.org>
> Cc: Catalin Marinas <catalin.marinas@arm.com>
> Cc: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
> Cc: Will Deacon <will.deacon@arm.com>
> Cc: Zhen Lei <thunder.leizhen@huawei.com>
> ---
> arch/arm64/mm/numa.c | 5 ++++-
> 1 file changed, 4 insertions(+), 1 deletion(-)
>
> diff --git a/arch/arm64/mm/numa.c b/arch/arm64/mm/numa.c
> index 778a985..34415fc 100644
> --- a/arch/arm64/mm/numa.c
> +++ b/arch/arm64/mm/numa.c
> @@ -147,7 +147,10 @@ static int __init early_cpu_to_node(int cpu)
>
> static int __init pcpu_cpu_distance(unsigned int from, unsigned int to)
> {
> - return node_distance(from, to);
> + if (early_cpu_to_node(from) == early_cpu_to_node(to))
> + return LOCAL_DISTANCE;
> + else
> + return REMOTE_DISTANCE;
> }
>
> static void * __init pcpu_fc_alloc(unsigned int cpu, size_t size,
We trigger this bug with NR_CPUS=64 in the config instead of 4096 in defconfig
for arm64, and we have 64 cpus in the system. I think that's why this bug wasn't
triggered yet on other ARM64 NUMA platforms, this bug should generic for all ARM64
platforms.
Thanks
Hanjun
^ permalink raw reply
* [PATCH 0/5] Switch to the DT cpufreq policy on the Integrator
From: Viresh Kumar @ 2016-10-20 4:20 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1476871154-32243-1-git-send-email-linus.walleij@linaro.org>
On 19-10-16, 11:59, Linus Walleij wrote:
> This switches the ARM Integrator/AP and Integrator/CP to use the
> Device Tree cpufreq policy with its definition of operating points
> using the generic OPP library.
>
> The Integrators does not need to control a regulator to switch
> frequency, only a clock. This clock and its device tree bindings
> have been defined in the device tree and merged upstream for v4.9.
>
> This approach provides a little better granularity on the
> Integrator/AP where I defined a few operating points: before
> this change the Integrator would just switch between min speed
> (12 MHz) and max speed (71 MHz). Now it can switch between a
> few arbitrarily chosen OPPs as in the examples below:
>
> The following tests were made on the Integrator/AP:
>
> /sys/devices/system/cpu/cpufreq/policy0 echo ondemand > scaling_governor
> cpu cpu0: dev_pm_opp_set_rate: switching OPP: 71000000 Hz --> 24000000 Hz
> cpu cpu0: dev_pm_opp_set_rate: switching OPP: 24000000 Hz --> 12000000 Hz
> cpu cpu0: dev_pm_opp_set_rate: switching OPP: 12000000 Hz --> 24000000 Hz
> cpu cpu0: dev_pm_opp_set_rate: switching OPP: 24000000 Hz --> 12000000 Hz
>
> The switch from 12 to 24 MHz is triggered by as little as using the
> command line with the ondemand governor. If we do this:
>
> yes > /dev/null &
> cpu cpu0: dev_pm_opp_set_rate: switching OPP: 12000000 Hz --> 36000000 Hz
> cpu cpu0: dev_pm_opp_set_rate: switching OPP: 36000000 Hz --> 71000000 Hz
> pkill yes
> cpu cpu0: dev_pm_opp_set_rate: switching OPP: 71000000 Hz --> 12000000 Hz
>
> So the algorithm is indeed using all the OPPs.
>
> Also as a confirmation test to make sure performance is affected by the
> speed changes, we set the performance governor and:
>
> echo 12000 > scaling_max_freq
> cpu cpu0: dev_pm_opp_set_rate: switching OPP: 71000000 Hz --> 12000000 Hz
> time find /sys|sort|uniq > /dev/null
> real 0m 45.51s
> user 0m 11.15s
> sys 0m 26.74s
>
> echo 71000 > scaling_max_freq
> cpu cpu0: dev_pm_opp_set_rate: switching OPP: 12000000 Hz --> 71000000 Hz
> time find /sys|sort|uniq
> > /dev/null
> real 0m 9.13s
> user 0m 2.35s
> sys 0m 5.50s
>
> So it is working.
>
> If people are happy with this approach and approve of the patches
> I'd like an ACK from the cpufreq people and then merge the whole set
> through ARM SoC.
Acked-by: Viresh Kumar <viresh.kumar@linaro.org>
--
viresh
^ permalink raw reply
* [PATCH v3 1/2] arm64: dts: uniphier: add CPU clock and OPP table for LD11 SoC
From: Masahiro Yamada @ 2016-10-20 4:44 UTC (permalink / raw)
To: linux-arm-kernel
Add a CPU clock to every CPU node and a CPU OPP table to use the
generic cpufreq driver.
Note:
clock-latency-ns (300ns) was calculated based on the CPU-gear switch
sequencer spec; it takes 12 clock cycles on the sequencer running
at 50 MHz, plus a bit additional latency.
Signed-off-by: Masahiro Yamada <yamada.masahiro@socionext.com>
---
Changes in v2:
- Match the node name to the opp-hz property.
arch/arm64/boot/dts/socionext/uniphier-ld11.dtsi | 38 ++++++++++++++++++++++++
1 file changed, 38 insertions(+)
diff --git a/arch/arm64/boot/dts/socionext/uniphier-ld11.dtsi b/arch/arm64/boot/dts/socionext/uniphier-ld11.dtsi
index 73e0acf..bb05f0a 100644
--- a/arch/arm64/boot/dts/socionext/uniphier-ld11.dtsi
+++ b/arch/arm64/boot/dts/socionext/uniphier-ld11.dtsi
@@ -70,14 +70,18 @@
device_type = "cpu";
compatible = "arm,cortex-a53", "arm,armv8";
reg = <0 0x000>;
+ clocks = <&sys_clk 33>;
enable-method = "psci";
+ operating-points-v2 = <&cluster0_opp>;
};
cpu1: cpu at 1 {
device_type = "cpu";
compatible = "arm,cortex-a53", "arm,armv8";
reg = <0 0x001>;
+ clocks = <&sys_clk 33>;
enable-method = "psci";
+ operating-points-v2 = <&cluster0_opp>;
};
};
@@ -86,6 +90,40 @@
method = "smc";
};
+ cluster0_opp: opp_table {
+ compatible = "operating-points-v2";
+ opp-shared;
+
+ opp at 245000000 {
+ opp-hz = /bits/ 64 <245000000>;
+ clock-latency-ns = <300>;
+ };
+ opp at 250000000 {
+ opp-hz = /bits/ 64 <250000000>;
+ clock-latency-ns = <300>;
+ };
+ opp at 490000000 {
+ opp-hz = /bits/ 64 <490000000>;
+ clock-latency-ns = <300>;
+ };
+ opp at 500000000 {
+ opp-hz = /bits/ 64 <500000000>;
+ clock-latency-ns = <300>;
+ };
+ opp at 653334000 {
+ opp-hz = /bits/ 64 <653334000>;
+ clock-latency-ns = <300>;
+ };
+ opp at 666667000 {
+ opp-hz = /bits/ 64 <666667000>;
+ clock-latency-ns = <300>;
+ };
+ opp at 980000000 {
+ opp-hz = /bits/ 64 <980000000>;
+ clock-latency-ns = <300>;
+ };
+ };
+
clocks {
refclk: ref {
compatible = "fixed-clock";
--
1.9.1
^ permalink raw reply related
* [PATCH v3 2/2] arm64: dts: uniphier: add CPU clocks and OPP tables for LD20 SoC
From: Masahiro Yamada @ 2016-10-20 4:44 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1476938647-26376-1-git-send-email-yamada.masahiro@socionext.com>
Add a CPU clock to every CPU node and CPU OPP tables to use the
generic cpufreq driver. All the CPUs in each cluster share the
same OPP table.
Note:
clock-latency-ns (300ns) was calculated based on the CPU-gear switch
sequencer spec; it takes 12 clock cycles on the sequencer running
at 50 MHz, plus a bit additional latency.
Signed-off-by: Masahiro Yamada <yamada.masahiro@socionext.com>
- Fix cluster1 OPP as well.
---
Changes in v2:
- Match the node name to the opp-hz property.
arch/arm64/boot/dts/socionext/uniphier-ld20.dtsi | 84 ++++++++++++++++++++++++
1 file changed, 84 insertions(+)
diff --git a/arch/arm64/boot/dts/socionext/uniphier-ld20.dtsi b/arch/arm64/boot/dts/socionext/uniphier-ld20.dtsi
index 6f48e82..a9a08dd 100644
--- a/arch/arm64/boot/dts/socionext/uniphier-ld20.dtsi
+++ b/arch/arm64/boot/dts/socionext/uniphier-ld20.dtsi
@@ -79,28 +79,36 @@
device_type = "cpu";
compatible = "arm,cortex-a72", "arm,armv8";
reg = <0 0x000>;
+ clocks = <&sys_clk 32>;
enable-method = "psci";
+ operating-points-v2 = <&cluster0_opp>;
};
cpu1: cpu at 1 {
device_type = "cpu";
compatible = "arm,cortex-a72", "arm,armv8";
reg = <0 0x001>;
+ clocks = <&sys_clk 32>;
enable-method = "psci";
+ operating-points-v2 = <&cluster0_opp>;
};
cpu2: cpu at 100 {
device_type = "cpu";
compatible = "arm,cortex-a53", "arm,armv8";
reg = <0 0x100>;
+ clocks = <&sys_clk 33>;
enable-method = "psci";
+ operating-points-v2 = <&cluster1_opp>;
};
cpu3: cpu at 101 {
device_type = "cpu";
compatible = "arm,cortex-a53", "arm,armv8";
reg = <0 0x101>;
+ clocks = <&sys_clk 33>;
enable-method = "psci";
+ operating-points-v2 = <&cluster1_opp>;
};
};
@@ -109,6 +117,82 @@
method = "smc";
};
+ cluster0_opp: opp_table0 {
+ compatible = "operating-points-v2";
+ opp-shared;
+
+ opp at 250000000 {
+ opp-hz = /bits/ 64 <250000000>;
+ clock-latency-ns = <300>;
+ };
+ opp at 275000000 {
+ opp-hz = /bits/ 64 <275000000>;
+ clock-latency-ns = <300>;
+ };
+ opp at 500000000 {
+ opp-hz = /bits/ 64 <500000000>;
+ clock-latency-ns = <300>;
+ };
+ opp at 550000000 {
+ opp-hz = /bits/ 64 <550000000>;
+ clock-latency-ns = <300>;
+ };
+ opp at 666667000 {
+ opp-hz = /bits/ 64 <666667000>;
+ clock-latency-ns = <300>;
+ };
+ opp at 733334000 {
+ opp-hz = /bits/ 64 <733334000>;
+ clock-latency-ns = <300>;
+ };
+ opp at 1000000000 {
+ opp-hz = /bits/ 64 <1000000000>;
+ clock-latency-ns = <300>;
+ };
+ opp at 1100000000 {
+ opp-hz = /bits/ 64 <1100000000>;
+ clock-latency-ns = <300>;
+ };
+ };
+
+ cluster1_opp: opp_table1 {
+ compatible = "operating-points-v2";
+ opp-shared;
+
+ opp at 250000000 {
+ opp-hz = /bits/ 64 <250000000>;
+ clock-latency-ns = <300>;
+ };
+ opp at 275000000 {
+ opp-hz = /bits/ 64 <275000000>;
+ clock-latency-ns = <300>;
+ };
+ opp at 500000000 {
+ opp-hz = /bits/ 64 <500000000>;
+ clock-latency-ns = <300>;
+ };
+ opp at 550000000 {
+ opp-hz = /bits/ 64 <550000000>;
+ clock-latency-ns = <300>;
+ };
+ opp at 666667000 {
+ opp-hz = /bits/ 64 <666667000>;
+ clock-latency-ns = <300>;
+ };
+ opp at 733334000 {
+ opp-hz = /bits/ 64 <733334000>;
+ clock-latency-ns = <300>;
+ };
+ opp at 1000000000 {
+ opp-hz = /bits/ 64 <1000000000>;
+ clock-latency-ns = <300>;
+ };
+ opp at 1100000000 {
+ opp-hz = /bits/ 64 <1100000000>;
+ clock-latency-ns = <300>;
+ };
+ };
+
clocks {
refclk: ref {
compatible = "fixed-clock";
--
1.9.1
^ permalink raw reply related
* [PATCH v3 1/2] arm64: dts: uniphier: add CPU clock and OPP table for LD11 SoC
From: Viresh Kumar @ 2016-10-20 4:47 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1476938647-26376-1-git-send-email-yamada.masahiro@socionext.com>
On 20-10-16, 13:44, Masahiro Yamada wrote:
> Add a CPU clock to every CPU node and a CPU OPP table to use the
> generic cpufreq driver.
>
> Note:
> clock-latency-ns (300ns) was calculated based on the CPU-gear switch
> sequencer spec; it takes 12 clock cycles on the sequencer running
> at 50 MHz, plus a bit additional latency.
>
> Signed-off-by: Masahiro Yamada <yamada.masahiro@socionext.com>
> ---
>
> Changes in v2:
> - Match the node name to the opp-hz property.
For both the patches ..
Acked-by: Viresh Kumar <viresh.kumar@linaro.org>
--
viresh
^ permalink raw reply
* [PATCH 0/5] Switch to the DT cpufreq policy on the Integrator
From: Viresh Kumar @ 2016-10-20 4:47 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161020042012.GI11766@vireshk-i7>
On 20-10-16, 09:50, Viresh Kumar wrote:
> On 19-10-16, 11:59, Linus Walleij wrote:
> > This switches the ARM Integrator/AP and Integrator/CP to use the
> > Device Tree cpufreq policy with its definition of operating points
> > using the generic OPP library.
> >
> > The Integrators does not need to control a regulator to switch
> > frequency, only a clock. This clock and its device tree bindings
> > have been defined in the device tree and merged upstream for v4.9.
> >
> > This approach provides a little better granularity on the
> > Integrator/AP where I defined a few operating points: before
> > this change the Integrator would just switch between min speed
> > (12 MHz) and max speed (71 MHz). Now it can switch between a
> > few arbitrarily chosen OPPs as in the examples below:
> >
> > The following tests were made on the Integrator/AP:
> >
> > /sys/devices/system/cpu/cpufreq/policy0 echo ondemand > scaling_governor
> > cpu cpu0: dev_pm_opp_set_rate: switching OPP: 71000000 Hz --> 24000000 Hz
> > cpu cpu0: dev_pm_opp_set_rate: switching OPP: 24000000 Hz --> 12000000 Hz
> > cpu cpu0: dev_pm_opp_set_rate: switching OPP: 12000000 Hz --> 24000000 Hz
> > cpu cpu0: dev_pm_opp_set_rate: switching OPP: 24000000 Hz --> 12000000 Hz
> >
> > The switch from 12 to 24 MHz is triggered by as little as using the
> > command line with the ondemand governor. If we do this:
> >
> > yes > /dev/null &
> > cpu cpu0: dev_pm_opp_set_rate: switching OPP: 12000000 Hz --> 36000000 Hz
> > cpu cpu0: dev_pm_opp_set_rate: switching OPP: 36000000 Hz --> 71000000 Hz
> > pkill yes
> > cpu cpu0: dev_pm_opp_set_rate: switching OPP: 71000000 Hz --> 12000000 Hz
> >
> > So the algorithm is indeed using all the OPPs.
> >
> > Also as a confirmation test to make sure performance is affected by the
> > speed changes, we set the performance governor and:
> >
> > echo 12000 > scaling_max_freq
> > cpu cpu0: dev_pm_opp_set_rate: switching OPP: 71000000 Hz --> 12000000 Hz
> > time find /sys|sort|uniq > /dev/null
> > real 0m 45.51s
> > user 0m 11.15s
> > sys 0m 26.74s
> >
> > echo 71000 > scaling_max_freq
> > cpu cpu0: dev_pm_opp_set_rate: switching OPP: 12000000 Hz --> 71000000 Hz
> > time find /sys|sort|uniq
> > > /dev/null
> > real 0m 9.13s
> > user 0m 2.35s
> > sys 0m 5.50s
> >
> > So it is working.
> >
> > If people are happy with this approach and approve of the patches
> > I'd like an ACK from the cpufreq people and then merge the whole set
> > through ARM SoC.
>
> Acked-by: Viresh Kumar <viresh.kumar@linaro.org>
Integrator is an UP, right? Otherwise you may want to use operating-points-v2
bindings instead.
--
viresh
^ permalink raw reply
* [PATCH V2 0/5] ARM64: More flexible HW watchpoint
From: Pratyush Anand @ 2016-10-20 5:48 UTC (permalink / raw)
To: linux-arm-kernel
Currently, we do not support all the byte select option provided by ARM64
specs for a HW watchpoint.
This patch set will help user to instrument a watchpoint with all possible
byte select options.
Changes since v1:
Introduced a new patch 3/5 where it takes care of the situation when HW
does not report a watchpoint hit with the address that matches one of the
watchpoints set.
Added corresponding test case to test that functionality.
Pavel Labath (1):
arm64: hw_breakpoint: Handle inexact watchpoint addresses
Pratyush Anand (4):
hw_breakpoint: Allow watchpoint of length 3,5,6 and 7
arm64: Allow hw watchpoint at varied offset from base address
arm64: Allow hw watchpoint of length 3,5,6 and 7
selftests: arm64: add test for unaligned/inexact watchpoint handling
arch/arm64/include/asm/hw_breakpoint.h | 6 +-
arch/arm64/kernel/hw_breakpoint.c | 149 +++++++++----
arch/arm64/kernel/ptrace.c | 5 +-
include/uapi/linux/hw_breakpoint.h | 4 +
tools/include/uapi/linux/hw_breakpoint.h | 4 +
tools/testing/selftests/breakpoints/Makefile | 5 +-
.../selftests/breakpoints/breakpoint_test_arm64.c | 236 +++++++++++++++++++++
7 files changed, 366 insertions(+), 43 deletions(-)
create mode 100644 tools/testing/selftests/breakpoints/breakpoint_test_arm64.c
--
2.7.4
^ permalink raw reply
* [PATCH V2 1/5] hw_breakpoint: Allow watchpoint of length 3,5,6 and 7
From: Pratyush Anand @ 2016-10-20 5:48 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <cover.1476941895.git.panand@redhat.com>
We only support breakpoint/watchpoint of length 1, 2, 4 and 8. If we can
support other length as well, then user may watch more data with less
number of watchpoints (provided hardware supports it). For example: if we
have to watch only 4th, 5th and 6th byte from a 64 bit aligned address, we
will have to use two slots to implement it currently. One slot will watch a
half word at offset 4 and other a byte at offset 6. If we can have a
watchpoint of length 3 then we can watch it with single slot as well.
ARM64 hardware does support such functionality, therefore adding these new
definitions in generic layer.
Signed-off-by: Pratyush Anand <panand@redhat.com>
---
include/uapi/linux/hw_breakpoint.h | 4 ++++
tools/include/uapi/linux/hw_breakpoint.h | 4 ++++
2 files changed, 8 insertions(+)
diff --git a/include/uapi/linux/hw_breakpoint.h b/include/uapi/linux/hw_breakpoint.h
index b04000a2296a..2b65efd19a46 100644
--- a/include/uapi/linux/hw_breakpoint.h
+++ b/include/uapi/linux/hw_breakpoint.h
@@ -4,7 +4,11 @@
enum {
HW_BREAKPOINT_LEN_1 = 1,
HW_BREAKPOINT_LEN_2 = 2,
+ HW_BREAKPOINT_LEN_3 = 3,
HW_BREAKPOINT_LEN_4 = 4,
+ HW_BREAKPOINT_LEN_5 = 5,
+ HW_BREAKPOINT_LEN_6 = 6,
+ HW_BREAKPOINT_LEN_7 = 7,
HW_BREAKPOINT_LEN_8 = 8,
};
diff --git a/tools/include/uapi/linux/hw_breakpoint.h b/tools/include/uapi/linux/hw_breakpoint.h
index b04000a2296a..2b65efd19a46 100644
--- a/tools/include/uapi/linux/hw_breakpoint.h
+++ b/tools/include/uapi/linux/hw_breakpoint.h
@@ -4,7 +4,11 @@
enum {
HW_BREAKPOINT_LEN_1 = 1,
HW_BREAKPOINT_LEN_2 = 2,
+ HW_BREAKPOINT_LEN_3 = 3,
HW_BREAKPOINT_LEN_4 = 4,
+ HW_BREAKPOINT_LEN_5 = 5,
+ HW_BREAKPOINT_LEN_6 = 6,
+ HW_BREAKPOINT_LEN_7 = 7,
HW_BREAKPOINT_LEN_8 = 8,
};
--
2.7.4
^ permalink raw reply related
* [PATCH V2 2/5] arm64: Allow hw watchpoint at varied offset from base address
From: Pratyush Anand @ 2016-10-20 5:48 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <cover.1476941895.git.panand@redhat.com>
ARM64 hardware supports watchpoint at any double word aligned address.
However, it can select any consecutive bytes from offset 0 to 7 from that
base address. For example, if base address is programmed as 0x420030 and
byte select is 0x1C, then access of 0x420032,0x420033 and 0x420034 will
generate a watchpoint exception.
Currently, we do not have such modularity. We can only program byte,
halfword, word and double word access exception from any base address.
This patch adds support to overcome above limitations.
Signed-off-by: Pratyush Anand <panand@redhat.com>
---
arch/arm64/include/asm/hw_breakpoint.h | 2 +-
arch/arm64/kernel/hw_breakpoint.c | 45 ++++++++++++++++------------------
arch/arm64/kernel/ptrace.c | 5 ++--
3 files changed, 25 insertions(+), 27 deletions(-)
diff --git a/arch/arm64/include/asm/hw_breakpoint.h b/arch/arm64/include/asm/hw_breakpoint.h
index 115ea2a64520..4f4e58bee9bc 100644
--- a/arch/arm64/include/asm/hw_breakpoint.h
+++ b/arch/arm64/include/asm/hw_breakpoint.h
@@ -118,7 +118,7 @@ struct perf_event;
struct pmu;
extern int arch_bp_generic_fields(struct arch_hw_breakpoint_ctrl ctrl,
- int *gen_len, int *gen_type);
+ int *gen_len, int *gen_type, int *offset);
extern int arch_check_bp_in_kernelspace(struct perf_event *bp);
extern int arch_validate_hwbkpt_settings(struct perf_event *bp);
extern int hw_breakpoint_exceptions_notify(struct notifier_block *unused,
diff --git a/arch/arm64/kernel/hw_breakpoint.c b/arch/arm64/kernel/hw_breakpoint.c
index 26a6bf77d272..3c2b96803eba 100644
--- a/arch/arm64/kernel/hw_breakpoint.c
+++ b/arch/arm64/kernel/hw_breakpoint.c
@@ -349,7 +349,7 @@ int arch_check_bp_in_kernelspace(struct perf_event *bp)
* to generic breakpoint descriptions.
*/
int arch_bp_generic_fields(struct arch_hw_breakpoint_ctrl ctrl,
- int *gen_len, int *gen_type)
+ int *gen_len, int *gen_type, int *offset)
{
/* Type */
switch (ctrl.type) {
@@ -369,8 +369,10 @@ int arch_bp_generic_fields(struct arch_hw_breakpoint_ctrl ctrl,
return -EINVAL;
}
+ *offset = ffs(ctrl.len) - 1;
+
/* Len */
- switch (ctrl.len) {
+ switch (ctrl.len >> *offset) {
case ARM_BREAKPOINT_LEN_1:
*gen_len = HW_BREAKPOINT_LEN_1;
break;
@@ -517,18 +519,17 @@ int arch_validate_hwbkpt_settings(struct perf_event *bp)
default:
return -EINVAL;
}
-
- info->address &= ~alignment_mask;
- info->ctrl.len <<= offset;
} else {
if (info->ctrl.type == ARM_BREAKPOINT_EXECUTE)
alignment_mask = 0x3;
else
alignment_mask = 0x7;
- if (info->address & alignment_mask)
- return -EINVAL;
+ offset = info->address & alignment_mask;
}
+ info->address &= ~alignment_mask;
+ info->ctrl.len <<= offset;
+
/*
* Disallow per-task kernel breakpoints since these would
* complicate the stepping code.
@@ -665,8 +666,8 @@ static int watchpoint_handler(unsigned long addr, unsigned int esr,
struct pt_regs *regs)
{
int i, step = 0, *kernel_step, access;
- u32 ctrl_reg;
- u64 val, alignment_mask;
+ u32 ctrl_reg, lens, lene;
+ u64 val;
struct perf_event *wp, **slots;
struct debug_info *debug_info;
struct arch_hw_breakpoint *info;
@@ -684,25 +685,21 @@ static int watchpoint_handler(unsigned long addr, unsigned int esr,
goto unlock;
info = counter_arch_bp(wp);
- /* AArch32 watchpoints are either 4 or 8 bytes aligned. */
- if (is_compat_task()) {
- if (info->ctrl.len == ARM_BREAKPOINT_LEN_8)
- alignment_mask = 0x7;
- else
- alignment_mask = 0x3;
- } else {
- alignment_mask = 0x7;
- }
- /* Check if the watchpoint value matches. */
+ /* Check if the watchpoint value and byte select match. */
val = read_wb_reg(AARCH64_DBG_REG_WVR, i);
- if (val != (addr & ~alignment_mask))
- goto unlock;
-
- /* Possible match, check the byte address select to confirm. */
ctrl_reg = read_wb_reg(AARCH64_DBG_REG_WCR, i);
decode_ctrl_reg(ctrl_reg, &ctrl);
- if (!((1 << (addr & alignment_mask)) & ctrl.len))
+ lens = ffs(ctrl.len) - 1;
+ lene = fls(ctrl.len) - 1;
+ /*
+ * FIXME: reported address can be anywhere between "the
+ * lowest address accessed by the memory access that
+ * triggered the watchpoint" and "the highest watchpointed
+ * address accessed by the memory access". So, it may not
+ * lie in the interval of watchpoint address range.
+ */
+ if (addr < val + lens || addr > val + lene)
goto unlock;
/*
diff --git a/arch/arm64/kernel/ptrace.c b/arch/arm64/kernel/ptrace.c
index e0c81da60f76..0eb366a94382 100644
--- a/arch/arm64/kernel/ptrace.c
+++ b/arch/arm64/kernel/ptrace.c
@@ -327,13 +327,13 @@ static int ptrace_hbp_fill_attr_ctrl(unsigned int note_type,
struct arch_hw_breakpoint_ctrl ctrl,
struct perf_event_attr *attr)
{
- int err, len, type, disabled = !ctrl.enabled;
+ int err, len, type, offset, disabled = !ctrl.enabled;
attr->disabled = disabled;
if (disabled)
return 0;
- err = arch_bp_generic_fields(ctrl, &len, &type);
+ err = arch_bp_generic_fields(ctrl, &len, &type, &offset);
if (err)
return err;
@@ -352,6 +352,7 @@ static int ptrace_hbp_fill_attr_ctrl(unsigned int note_type,
attr->bp_len = len;
attr->bp_type = type;
+ attr->bp_addr += offset;
return 0;
}
--
2.7.4
^ permalink raw reply related
* [PATCH V2 3/5] arm64: hw_breakpoint: Handle inexact watchpoint addresses
From: Pratyush Anand @ 2016-10-20 5:48 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <cover.1476941895.git.panand@redhat.com>
From: Pavel Labath <test.tberghammer@gmail.com>
Arm64 hardware does not always report a watchpoint hit address that
matches one of the watchpoints set. It can also report an address
"near" the watchpoint if a single instruction access both watched and
unwatched addresses. There is no straight-forward way, short of
disassembling the offending instruction, to map that address back to
the watchpoint.
Previously, when the hardware reported a watchpoint hit on an address
that did not match our watchpoint (this happens in case of instructions
which access large chunks of memory such as "stp") the process would
enter a loop where we would be continually resuming it (because we did
not recognise that watchpoint hit) and it would keep hitting the
watchpoint again and again. The tracing process would never get
notified of the watchpoint hit.
This commit fixes the problem by looking at the watchpoints near the
address reported by the hardware. If the address does not exactly match
one of the watchpoints we have set, it attributes the hit to the
nearest watchpoint we have. This heuristic is a bit dodgy, but I don't
think we can do much more, given the hardware limitations.
[panand: reworked to rebase on his patches]
Signed-off-by: Pavel Labath <labath@google.com>
Signed-off-by: Pratyush Anand <panand@redhat.com>
---
arch/arm64/kernel/hw_breakpoint.c | 94 +++++++++++++++++++++++++++------------
1 file changed, 66 insertions(+), 28 deletions(-)
diff --git a/arch/arm64/kernel/hw_breakpoint.c b/arch/arm64/kernel/hw_breakpoint.c
index 3c2b96803eba..c57bc90b8286 100644
--- a/arch/arm64/kernel/hw_breakpoint.c
+++ b/arch/arm64/kernel/hw_breakpoint.c
@@ -662,11 +662,46 @@ unlock:
}
NOKPROBE_SYMBOL(breakpoint_handler);
+/*
+ * Arm64 hardware does not always report a watchpoint hit address that matches
+ * one of the watchpoints set. It can also report an address "near" the
+ * watchpoint if a single instruction access both watched and unwatched
+ * addresses. There is no straight-forward way, short of disassembling the
+ * offending instruction, to map that address back to the watchpoint. This
+ * function computes the distance of the memory access from the watchpoint as a
+ * heuristic for the likelyhood that a given access triggered the watchpoint.
+ *
+ * See Section D2.10.5 "Determining the memory location that caused a Watchpoint
+ * exception" of ARMv8 Architecture Reference Manual for details.
+ *
+ * The function returns the distance of the address from the bytes watched by
+ * the watchpoint. In case of an exact match, it returns 0.
+ */
+static u64 get_distance_from_watchpoint(unsigned long addr, u64 val,
+ struct arch_hw_breakpoint_ctrl *ctrl)
+{
+ u64 wp_low, wp_high;
+ u32 lens, lene;
+
+ lens = ffs(ctrl->len) - 1;
+ lene = fls(ctrl->len) - 1;
+
+ wp_low = val + lens;
+ wp_high = val + lene;
+ if (addr < wp_low)
+ return wp_low - addr;
+ else if (addr > wp_high)
+ return addr - wp_high;
+ else
+ return 0;
+}
+
static int watchpoint_handler(unsigned long addr, unsigned int esr,
struct pt_regs *regs)
{
- int i, step = 0, *kernel_step, access;
- u32 ctrl_reg, lens, lene;
+ int i, step = 0, *kernel_step, access, closest_match = 0;
+ u64 min_dist = -1, dist;
+ u32 ctrl_reg;
u64 val;
struct perf_event *wp, **slots;
struct debug_info *debug_info;
@@ -676,31 +711,15 @@ static int watchpoint_handler(unsigned long addr, unsigned int esr,
slots = this_cpu_ptr(wp_on_reg);
debug_info = ¤t->thread.debug;
+ /*
+ * Find all watchpoints that match the reported address. If no exact
+ * match is found. Attribute the hit to the closest watchpoint.
+ */
+ rcu_read_lock();
for (i = 0; i < core_num_wrps; ++i) {
- rcu_read_lock();
-
wp = slots[i];
-
if (wp == NULL)
- goto unlock;
-
- info = counter_arch_bp(wp);
-
- /* Check if the watchpoint value and byte select match. */
- val = read_wb_reg(AARCH64_DBG_REG_WVR, i);
- ctrl_reg = read_wb_reg(AARCH64_DBG_REG_WCR, i);
- decode_ctrl_reg(ctrl_reg, &ctrl);
- lens = ffs(ctrl.len) - 1;
- lene = fls(ctrl.len) - 1;
- /*
- * FIXME: reported address can be anywhere between "the
- * lowest address accessed by the memory access that
- * triggered the watchpoint" and "the highest watchpointed
- * address accessed by the memory access". So, it may not
- * lie in the interval of watchpoint address range.
- */
- if (addr < val + lens || addr > val + lene)
- goto unlock;
+ continue;
/*
* Check that the access type matches.
@@ -709,18 +728,37 @@ static int watchpoint_handler(unsigned long addr, unsigned int esr,
access = (esr & AARCH64_ESR_ACCESS_MASK) ? HW_BREAKPOINT_W :
HW_BREAKPOINT_R;
if (!(access & hw_breakpoint_type(wp)))
- goto unlock;
+ continue;
+
+ /* Check if the watchpoint value and byte select match. */
+ val = read_wb_reg(AARCH64_DBG_REG_WVR, i);
+ ctrl_reg = read_wb_reg(AARCH64_DBG_REG_WCR, i);
+ decode_ctrl_reg(ctrl_reg, &ctrl);
+ dist = get_distance_from_watchpoint(addr, val, &ctrl);
+ if (dist < min_dist) {
+ min_dist = dist;
+ closest_match = i;
+ }
+ /* Is this an exact match? */
+ if (dist != 0)
+ continue;
+ info = counter_arch_bp(wp);
info->trigger = addr;
perf_bp_event(wp, regs);
/* Do we need to handle the stepping? */
if (is_default_overflow_handler(wp))
step = 1;
-
-unlock:
- rcu_read_unlock();
}
+ if (min_dist > 0 && min_dist != -1) {
+ /* No exact match found. */
+ wp = slots[closest_match];
+ info = counter_arch_bp(wp);
+ info->trigger = addr;
+ perf_bp_event(wp, regs);
+ }
+ rcu_read_unlock();
if (!step)
return 0;
--
2.7.4
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox