Linux-ARM-Kernel Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH V6 08/13] boot_constraint: Manage deferrable constraints
From: Viresh Kumar @ 2018-01-10  3:47 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <cover.1515554879.git.viresh.kumar@linaro.org>

It is possible that some of the resources aren't available at the time
constraints are getting set and the boot constraints core will return
-EPROBE_DEFER for them. In order to retry adding the constraints at a
later point of time (after the resource is added and before any of its
users come up), this patch proposes two things:

- Each constraint is represented by a virtual platform device, so that
  it is re-probed again until the time all the dependencies aren't met.
  The platform device is removed along with the constraint, with help of
  the free_resources() callback.

- Enable early defer probing support by calling
  driver_enable_deferred_probe(), so that the core retries probing
  deferred devices every time any device is bound to a driver. This
  makes sure that the constraint is set before any of the users of the
  resources come up.

This is tested on ARM64 Hikey board where probe was deferred for a
device.

Tested-by: Rajendra Nayak <rnayak@codeaurora.org>
Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
---
 drivers/base/dd.c                        |  12 ++
 drivers/boot_constraint/Makefile         |   2 +-
 drivers/boot_constraint/deferrable_dev.c | 241 +++++++++++++++++++++++++++++++
 include/linux/boot_constraint.h          |  27 ++++
 4 files changed, 281 insertions(+), 1 deletion(-)
 create mode 100644 drivers/boot_constraint/deferrable_dev.c

diff --git a/drivers/base/dd.c b/drivers/base/dd.c
index dc89f98a2487..48a9945ff206 100644
--- a/drivers/base/dd.c
+++ b/drivers/base/dd.c
@@ -227,6 +227,18 @@ void device_unblock_probing(void)
 	driver_deferred_probe_trigger();
 }
 
+/**
+ * driver_enable_deferred_probe() - Enable probing of deferred devices
+ *
+ * We don't want to get in the way when the bulk of drivers are getting probed
+ * and so deferred probe is disabled in the beginning. Enable it now because we
+ * need it.
+ */
+void driver_enable_deferred_probe(void)
+{
+	driver_deferred_probe_enable = true;
+}
+
 /**
  * deferred_probe_initcall() - Enable probing of deferred devices
  *
diff --git a/drivers/boot_constraint/Makefile b/drivers/boot_constraint/Makefile
index b7ade1a7afb5..a765094623a3 100644
--- a/drivers/boot_constraint/Makefile
+++ b/drivers/boot_constraint/Makefile
@@ -1,3 +1,3 @@
 # Makefile for device boot constraints
 
-obj-y := clk.o core.o pm.o supply.o
+obj-y := clk.o deferrable_dev.o core.o pm.o supply.o
diff --git a/drivers/boot_constraint/deferrable_dev.c b/drivers/boot_constraint/deferrable_dev.c
new file mode 100644
index 000000000000..158c04d41e09
--- /dev/null
+++ b/drivers/boot_constraint/deferrable_dev.c
@@ -0,0 +1,241 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2017 Linaro.
+ * Viresh Kumar <viresh.kumar@linaro.org>
+ */
+
+#include <linux/err.h>
+#include <linux/idr.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+
+#include "core.h"
+
+static DEFINE_IDA(pdev_index);
+
+void driver_enable_deferred_probe(void);
+
+struct boot_constraint_pdata {
+	struct device *dev;
+	struct dev_boot_constraint constraint;
+	int probe_failed;
+	int index;
+};
+
+static void boot_constraint_remove(void *data)
+{
+	struct platform_device *pdev = data;
+	struct boot_constraint_pdata *pdata = dev_get_platdata(&pdev->dev);
+
+	ida_simple_remove(&pdev_index, pdata->index);
+	kfree(pdata->constraint.data);
+	platform_device_unregister(pdev);
+}
+
+/*
+ * A platform device is added for each and every constraint, to handle
+ * -EPROBE_DEFER properly.
+ */
+static int boot_constraint_probe(struct platform_device *pdev)
+{
+	struct boot_constraint_pdata *pdata = dev_get_platdata(&pdev->dev);
+	struct dev_boot_constraint_info info;
+	int ret;
+
+	if (WARN_ON(!pdata))
+		return -EINVAL;
+
+	info.constraint = pdata->constraint;
+	info.free_resources = boot_constraint_remove;
+	info.free_resources_data = pdev;
+
+	ret = dev_boot_constraint_add(pdata->dev, &info);
+	if (ret) {
+		if (ret == -EPROBE_DEFER)
+			driver_enable_deferred_probe();
+		else
+			pdata->probe_failed = ret;
+	}
+
+	return ret;
+}
+
+static struct platform_driver boot_constraint_driver = {
+	.driver = {
+		.name = "boot-constraints-dev",
+	},
+	.probe = boot_constraint_probe,
+};
+
+static int __init boot_constraint_init(void)
+{
+	return platform_driver_register(&boot_constraint_driver);
+}
+core_initcall(boot_constraint_init);
+
+static int boot_constraint_add_dev(struct device *dev,
+				   struct dev_boot_constraint *constraint)
+{
+	struct boot_constraint_pdata pdata = {
+		.dev = dev,
+		.constraint.type = constraint->type,
+	};
+	struct platform_device *pdev;
+	struct boot_constraint_pdata *pdev_pdata;
+	int size, ret;
+
+	switch (constraint->type) {
+	case DEV_BOOT_CONSTRAINT_CLK:
+		size = sizeof(struct dev_boot_constraint_clk_info);
+		break;
+	case DEV_BOOT_CONSTRAINT_PM:
+		size = 0;
+		break;
+	case DEV_BOOT_CONSTRAINT_SUPPLY:
+		size = sizeof(struct dev_boot_constraint_supply_info);
+		break;
+	default:
+		dev_err(dev, "%s: Constraint type (%d) not supported\n",
+			__func__, constraint->type);
+		return -EINVAL;
+	}
+
+	/* Will be freed from boot_constraint_remove() */
+	pdata.constraint.data = kmemdup(constraint->data, size, GFP_KERNEL);
+	if (!pdata.constraint.data)
+		return -ENOMEM;
+
+	ret = ida_simple_get(&pdev_index, 0, 256, GFP_KERNEL);
+	if (ret < 0) {
+		dev_err(dev, "failed to allocate index (%d)\n", ret);
+		goto free;
+	}
+
+	pdata.index = ret;
+
+	pdev = platform_device_register_data(NULL, "boot-constraints-dev", ret,
+					     &pdata, sizeof(pdata));
+	if (IS_ERR(pdev)) {
+		dev_err(dev, "%s: Failed to create pdev (%ld)\n", __func__,
+			PTR_ERR(pdev));
+		ret = PTR_ERR(pdev);
+		goto ida_remove;
+	}
+
+	/* Release resources if probe has failed */
+	pdev_pdata = dev_get_platdata(&pdev->dev);
+	if (pdev_pdata->probe_failed) {
+		ret = pdev_pdata->probe_failed;
+		goto remove_pdev;
+	}
+
+	return 0;
+
+remove_pdev:
+	platform_device_unregister(pdev);
+ida_remove:
+	ida_simple_remove(&pdev_index, pdata.index);
+free:
+	kfree(pdata.constraint.data);
+
+	return ret;
+}
+
+static int dev_boot_constraint_add_deferrable(struct device *dev,
+			struct dev_boot_constraint *constraints, int count)
+{
+	int ret, i;
+
+	for (i = 0; i < count; i++) {
+		ret = boot_constraint_add_dev(dev, &constraints[i]);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
+/* This only creates platform devices for now */
+static void add_deferrable_of_single(struct device_node *np,
+				     struct dev_boot_constraint *constraints,
+				     int count)
+{
+	struct device *dev;
+	int ret;
+
+	if (!of_device_is_available(np))
+		return;
+
+	ret = of_platform_bus_create(np, NULL, NULL, NULL, false);
+	if (ret)
+		return;
+
+	dev = of_find_any_device_by_node(np);
+	if (!dev) {
+		pr_err("Boot Constraints: Failed to find dev: %pOF\n", np);
+		return;
+	}
+
+	ret = dev_boot_constraint_add_deferrable(dev, constraints, count);
+	if (ret)
+		dev_err(dev, "Failed to add boot constraint (%d)\n", ret);
+}
+
+/* Not all compatible device nodes may have boot constraints */
+static bool node_has_boot_constraints(struct device_node *np,
+				      struct dev_boot_constraint_of *oconst)
+{
+	int i;
+
+	if (!oconst->dev_names)
+		return true;
+
+	for (i = 0; i < oconst->dev_names_count; i++) {
+		if (!strcmp(oconst->dev_names[i], kbasename(np->full_name)))
+			return true;
+	}
+
+	return false;
+}
+
+/**
+ * dev_boot_constraint_add_deferrable_of: Adds all constraints for a platform.
+ *
+ * @oconst: This is an array of 'struct dev_boot_constraint_of', where each
+ * entry of the array is used to add one or more boot constraints across one or
+ * more devices having the same compatibility in the device tree.
+ * @count: Size of the 'oconst' array.
+ *
+ * This helper routine provides an easy way to add all boot constraints for a
+ * machine or platform. Just like dev_boot_constraint_add(), this must be called
+ * before the devices (to which we want to add constraints) are probed by their
+ * drivers, otherwise the boot constraint will never get removed for those
+ * devices and may result in unwanted behavior of the hardware. The boot
+ * constraints are removed by the driver core automatically after the devices
+ * are probed (successfully or unsuccessfully).
+ *
+ * This adds the boot constraints in a deferrable way and the caller need not
+ * worry about the availability of the resources required by the constraint.
+ * This routine will return successfully and the constraint will be added by the
+ * boot constraint core as soon as the resource is available at a later point in
+ * time.
+ */
+void dev_boot_constraint_add_deferrable_of(struct dev_boot_constraint_of *oconst,
+					   int count)
+{
+	struct device_node *np;
+	int i;
+
+	for (i = 0; i < count; i++) {
+		for_each_compatible_node(np, NULL, oconst[i].compat) {
+			if (!node_has_boot_constraints(np, &oconst[i]))
+				continue;
+
+			add_deferrable_of_single(np, oconst[i].constraints,
+						 oconst[i].count);
+		}
+	}
+}
+EXPORT_SYMBOL_GPL(dev_boot_constraint_add_deferrable_of);
diff --git a/include/linux/boot_constraint.h b/include/linux/boot_constraint.h
index 12fac0d565b0..ab752e19bfd0 100644
--- a/include/linux/boot_constraint.h
+++ b/include/linux/boot_constraint.h
@@ -79,16 +79,43 @@ struct dev_boot_constraint_info {
 	void *free_resources_data;
 };
 
+/**
+ * struct dev_boot_constraint_of - This is used to add one or more boot
+ * constraints across one or more devices having the same compatibility in the
+ * device tree.
+ *
+ * @compat: This must match the compatible string of the devices to which we
+ * want to apply constraints.
+ * @constraints: This points to one or more boot constraints.
+ * @count: This contains the number of boot constraints pointed by the
+ * 'constraints' field.
+ * @dev_names: This is used to limit the application of boot constraints to only
+ * a subset of devices with matching compatibility.
+ * @dev_names_count: This is the number of devices pointed by the 'dev_names'
+ * array.
+ */
+struct dev_boot_constraint_of {
+	const char *compat;
+	struct dev_boot_constraint *constraints;
+	unsigned int count;
+
+	const char * const *dev_names;
+	unsigned int dev_names_count;
+};
+
 #ifdef CONFIG_DEV_BOOT_CONSTRAINT
 int dev_boot_constraint_add(struct device *dev,
 			    struct dev_boot_constraint_info *info);
 void dev_boot_constraints_remove(struct device *dev);
+void dev_boot_constraint_add_deferrable_of(struct dev_boot_constraint_of *oconst,
+					   int count);
 #else
 static inline
 int dev_boot_constraint_add(struct device *dev,
 			    struct dev_boot_constraint_info *info)
 { return 0; }
 static inline void dev_boot_constraints_remove(struct device *dev) {}
+static inline void dev_boot_constraint_add_deferrable_of(struct dev_boot_constraint_of *oconst, int count) {}
 #endif /* CONFIG_DEV_BOOT_CONSTRAINT */
 
 #endif /* _LINUX_BOOT_CONSTRAINT_H */
-- 
2.15.0.194.g9af6a3dea062

^ permalink raw reply related

* [PATCH V6 09/13] boot_constraint: Add support for Hisilicon platforms
From: Viresh Kumar @ 2018-01-10  3:47 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <cover.1515554879.git.viresh.kumar@linaro.org>

This adds boot constraint support for Hisilicon platforms. Currently
only one use case is supported: earlycon. One of the UART is enabled by
the bootloader and is used for early console in the kernel. The boot
constraint core handles it properly and removes constraints once the
serial device is probed by its driver.

This is tested on hi6220-hikey 96board.

Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
---
 arch/arm64/Kconfig.platforms     |   1 +
 drivers/boot_constraint/Makefile |   2 +
 drivers/boot_constraint/hikey.c  | 158 +++++++++++++++++++++++++++++++++++++++
 3 files changed, 161 insertions(+)
 create mode 100644 drivers/boot_constraint/hikey.c

diff --git a/arch/arm64/Kconfig.platforms b/arch/arm64/Kconfig.platforms
index 2401373565ff..a586ed728393 100644
--- a/arch/arm64/Kconfig.platforms
+++ b/arch/arm64/Kconfig.platforms
@@ -87,6 +87,7 @@ config ARCH_HISI
 	select ARM_TIMER_SP804
 	select HISILICON_IRQ_MBIGEN if PCI
 	select PINCTRL
+	select DEV_BOOT_CONSTRAINT
 	help
 	  This enables support for Hisilicon ARMv8 SoC family
 
diff --git a/drivers/boot_constraint/Makefile b/drivers/boot_constraint/Makefile
index a765094623a3..5609280162c4 100644
--- a/drivers/boot_constraint/Makefile
+++ b/drivers/boot_constraint/Makefile
@@ -1,3 +1,5 @@
 # Makefile for device boot constraints
 
 obj-y := clk.o deferrable_dev.o core.o pm.o supply.o
+
+obj-$(CONFIG_ARCH_HISI)			+= hikey.o
diff --git a/drivers/boot_constraint/hikey.c b/drivers/boot_constraint/hikey.c
new file mode 100644
index 000000000000..25acb4070569
--- /dev/null
+++ b/drivers/boot_constraint/hikey.c
@@ -0,0 +1,158 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * This takes care of Hisilicon boot time device constraints, normally set by
+ * the Bootloader.
+ *
+ * Copyright (C) 2017 Linaro.
+ * Viresh Kumar <viresh.kumar@linaro.org>
+ */
+
+#include <linux/boot_constraint.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/of.h>
+
+static bool earlycon_boot_constraints_enabled __initdata;
+
+static int __init enable_earlycon_boot_constraints(char *str)
+{
+	earlycon_boot_constraints_enabled = true;
+
+	return 0;
+}
+
+__setup_param("earlycon", boot_constraint_earlycon,
+	      enable_earlycon_boot_constraints, 0);
+__setup_param("earlyprintk", boot_constraint_earlyprintk,
+	      enable_earlycon_boot_constraints, 0);
+
+
+struct hikey_machine_constraints {
+	struct dev_boot_constraint_of *dev_constraints;
+	unsigned int count;
+};
+
+static struct dev_boot_constraint_clk_info uart_iclk_info = {
+	.name = "uartclk",
+};
+
+static struct dev_boot_constraint_clk_info uart_pclk_info = {
+	.name = "apb_pclk",
+};
+
+static struct dev_boot_constraint hikey3660_uart_constraints[] = {
+	{
+		.type = DEV_BOOT_CONSTRAINT_CLK,
+		.data = &uart_iclk_info,
+	}, {
+		.type = DEV_BOOT_CONSTRAINT_CLK,
+		.data = &uart_pclk_info,
+	},
+};
+
+static const char * const uarts_hikey3660[] = {
+	"serial at fff32000",	/* UART 6 */
+};
+
+static struct dev_boot_constraint_of hikey3660_dev_constraints[] = {
+	{
+		.compat = "arm,pl011",
+		.constraints = hikey3660_uart_constraints,
+		.count = ARRAY_SIZE(hikey3660_uart_constraints),
+
+		.dev_names = uarts_hikey3660,
+		.dev_names_count = ARRAY_SIZE(uarts_hikey3660),
+	},
+};
+
+static struct hikey_machine_constraints hikey3660_constraints = {
+	.dev_constraints = hikey3660_dev_constraints,
+	.count = ARRAY_SIZE(hikey3660_dev_constraints),
+};
+
+static const char * const uarts_hikey6220[] = {
+	"uart at f7113000",	/* UART 3 */
+};
+
+static struct dev_boot_constraint_of hikey6220_dev_constraints[] = {
+	{
+		.compat = "arm,pl011",
+		.constraints = hikey3660_uart_constraints,
+		.count = ARRAY_SIZE(hikey3660_uart_constraints),
+
+		.dev_names = uarts_hikey6220,
+		.dev_names_count = ARRAY_SIZE(uarts_hikey6220),
+	},
+};
+
+static struct hikey_machine_constraints hikey6220_constraints = {
+	.dev_constraints = hikey6220_dev_constraints,
+	.count = ARRAY_SIZE(hikey6220_dev_constraints),
+};
+
+static struct dev_boot_constraint hikey3798cv200_uart_constraints[] = {
+	{
+		.type = DEV_BOOT_CONSTRAINT_CLK,
+		.data = &uart_pclk_info,
+	},
+};
+
+static const char * const uarts_hikey3798cv200[] = {
+	"serial at 8b00000",	/* UART 0 */
+};
+
+static struct dev_boot_constraint_of hikey3798cv200_dev_constraints[] = {
+	{
+		.compat = "arm,pl011",
+		.constraints = hikey3798cv200_uart_constraints,
+		.count = ARRAY_SIZE(hikey3798cv200_uart_constraints),
+
+		.dev_names = uarts_hikey3798cv200,
+		.dev_names_count = ARRAY_SIZE(uarts_hikey3798cv200),
+	},
+};
+
+static struct hikey_machine_constraints hikey3798cv200_constraints = {
+	.dev_constraints = hikey3798cv200_dev_constraints,
+	.count = ARRAY_SIZE(hikey3798cv200_dev_constraints),
+};
+
+static const struct of_device_id machines[] __initconst = {
+	{ .compatible = "hisilicon,hi3660", .data = &hikey3660_constraints },
+	{ .compatible = "hisilicon,hi3798cv200", .data = &hikey3798cv200_constraints },
+	{ .compatible = "hisilicon,hi6220", .data = &hikey6220_constraints },
+	{ }
+};
+
+static int __init hikey_constraints_init(void)
+{
+	const struct hikey_machine_constraints *constraints;
+	const struct of_device_id *match;
+	struct device_node *np;
+
+	if (!earlycon_boot_constraints_enabled)
+		return 0;
+
+	np = of_find_node_by_path("/");
+	if (!np)
+		return -ENODEV;
+
+	match = of_match_node(machines, np);
+	of_node_put(np);
+
+	if (!match)
+		return 0;
+
+	constraints = match->data;
+
+	dev_boot_constraint_add_deferrable_of(constraints->dev_constraints,
+					      constraints->count);
+
+	return 0;
+}
+
+/*
+ * The amba-pl011 driver registers itself from arch_initcall level. Setup the
+ * serial boot constraints before that in order not to miss any boot messages.
+ */
+postcore_initcall_sync(hikey_constraints_init);
-- 
2.15.0.194.g9af6a3dea062

^ permalink raw reply related

* [PATCH V6 10/13] boot_constraint: Add support for IMX platform
From: Viresh Kumar @ 2018-01-10  3:47 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <cover.1515554879.git.viresh.kumar@linaro.org>

This adds boot constraint support for IMX platforms. Currently only one
use case is supported: earlycon. Some of the UARTs are enabled by the
bootloader and are used for early console in the kernel. The boot
constraint core handles them properly and removes them once the serial
device is probed by its driver.

This gets rid of lots of hacky code in the clock drivers.

Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
---
 arch/arm/mach-imx/Kconfig         |   1 +
 drivers/boot_constraint/Makefile  |   1 +
 drivers/boot_constraint/imx.c     | 126 ++++++++++++++++++++++++++++++++++++++
 drivers/clk/imx/clk-imx25.c       |  12 ----
 drivers/clk/imx/clk-imx27.c       |  13 ----
 drivers/clk/imx/clk-imx31.c       |  12 ----
 drivers/clk/imx/clk-imx35.c       |  10 ---
 drivers/clk/imx/clk-imx51-imx53.c |  16 -----
 drivers/clk/imx/clk-imx6q.c       |   8 ---
 drivers/clk/imx/clk-imx6sl.c      |   8 ---
 drivers/clk/imx/clk-imx6sx.c      |   8 ---
 drivers/clk/imx/clk-imx7d.c       |  14 -----
 drivers/clk/imx/clk.c             |  38 ------------
 drivers/clk/imx/clk.h             |   1 -
 14 files changed, 128 insertions(+), 140 deletions(-)
 create mode 100644 drivers/boot_constraint/imx.c

diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig
index 782699e67600..f4d505fed092 100644
--- a/arch/arm/mach-imx/Kconfig
+++ b/arch/arm/mach-imx/Kconfig
@@ -4,6 +4,7 @@ menuconfig ARCH_MXC
 	select ARCH_SUPPORTS_BIG_ENDIAN
 	select CLKSRC_IMX_GPT
 	select GENERIC_IRQ_CHIP
+	select DEV_BOOT_CONSTRAINT
 	select GPIOLIB
 	select PINCTRL
 	select PM_OPP if PM
diff --git a/drivers/boot_constraint/Makefile b/drivers/boot_constraint/Makefile
index 5609280162c4..f3e123b5d854 100644
--- a/drivers/boot_constraint/Makefile
+++ b/drivers/boot_constraint/Makefile
@@ -3,3 +3,4 @@
 obj-y := clk.o deferrable_dev.o core.o pm.o supply.o
 
 obj-$(CONFIG_ARCH_HISI)			+= hikey.o
+obj-$(CONFIG_ARCH_MXC)			+= imx.o
diff --git a/drivers/boot_constraint/imx.c b/drivers/boot_constraint/imx.c
new file mode 100644
index 000000000000..a4f3af33ba86
--- /dev/null
+++ b/drivers/boot_constraint/imx.c
@@ -0,0 +1,126 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * This takes care of IMX boot time device constraints, normally set by the
+ * Bootloader.
+ *
+ * Copyright (C) 2017 Linaro.
+ * Viresh Kumar <viresh.kumar@linaro.org>
+ */
+
+#include <linux/boot_constraint.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/of.h>
+
+static bool earlycon_boot_constraints_enabled __initdata;
+
+static int __init enable_earlycon_boot_constraints(char *str)
+{
+	earlycon_boot_constraints_enabled = true;
+
+	return 0;
+}
+
+__setup_param("earlycon", boot_constraint_earlycon,
+	      enable_earlycon_boot_constraints, 0);
+__setup_param("earlyprintk", boot_constraint_earlyprintk,
+	      enable_earlycon_boot_constraints, 0);
+
+
+struct imx_machine_constraints {
+	struct dev_boot_constraint_of *dev_constraints;
+	unsigned int count;
+};
+
+static struct dev_boot_constraint_clk_info uart_ipg_clk_info = {
+	.name = "ipg",
+};
+
+static struct dev_boot_constraint_clk_info uart_per_clk_info = {
+	.name = "per",
+};
+
+static struct dev_boot_constraint imx_uart_constraints[] = {
+	{
+		.type = DEV_BOOT_CONSTRAINT_CLK,
+		.data = &uart_ipg_clk_info,
+	}, {
+		.type = DEV_BOOT_CONSTRAINT_CLK,
+		.data = &uart_per_clk_info,
+	},
+};
+
+static struct dev_boot_constraint_of imx_dev_constraints[] = {
+	{
+		.compat = "fsl,imx21-uart",
+		.constraints = imx_uart_constraints,
+		.count = ARRAY_SIZE(imx_uart_constraints),
+	},
+};
+
+static struct imx_machine_constraints imx_constraints = {
+	.dev_constraints = imx_dev_constraints,
+	.count = ARRAY_SIZE(imx_dev_constraints),
+};
+
+/* imx7 */
+static struct dev_boot_constraint_of imx7_dev_constraints[] = {
+	{
+		.compat = "fsl,imx6q-uart",
+		.constraints = imx_uart_constraints,
+		.count = ARRAY_SIZE(imx_uart_constraints),
+	},
+};
+
+static struct imx_machine_constraints imx7_constraints = {
+	.dev_constraints = imx7_dev_constraints,
+	.count = ARRAY_SIZE(imx7_dev_constraints),
+};
+
+static const struct of_device_id machines[] __initconst = {
+	{ .compatible = "fsl,imx25", .data = &imx_constraints },
+	{ .compatible = "fsl,imx27", .data = &imx_constraints },
+	{ .compatible = "fsl,imx31", .data = &imx_constraints },
+	{ .compatible = "fsl,imx35", .data = &imx_constraints },
+	{ .compatible = "fsl,imx50", .data = &imx_constraints },
+	{ .compatible = "fsl,imx51", .data = &imx_constraints },
+	{ .compatible = "fsl,imx53", .data = &imx_constraints },
+	{ .compatible = "fsl,imx6dl", .data = &imx_constraints },
+	{ .compatible = "fsl,imx6q", .data = &imx_constraints },
+	{ .compatible = "fsl,imx6qp", .data = &imx_constraints },
+	{ .compatible = "fsl,imx6sl", .data = &imx_constraints },
+	{ .compatible = "fsl,imx6sx", .data = &imx_constraints },
+	{ .compatible = "fsl,imx6ul", .data = &imx_constraints },
+	{ .compatible = "fsl,imx6ull", .data = &imx_constraints },
+	{ .compatible = "fsl,imx7d", .data = &imx7_constraints },
+	{ .compatible = "fsl,imx7s", .data = &imx7_constraints },
+	{ }
+};
+
+static int __init imx_constraints_init(void)
+{
+	const struct imx_machine_constraints *constraints;
+	const struct of_device_id *match;
+	struct device_node *np;
+
+	if (!earlycon_boot_constraints_enabled)
+		return 0;
+
+	np = of_find_node_by_path("/");
+	if (!np)
+		return -ENODEV;
+
+	match = of_match_node(machines, np);
+	of_node_put(np);
+
+	if (!match)
+		return 0;
+
+	constraints = match->data;
+
+	dev_boot_constraint_add_deferrable_of(constraints->dev_constraints,
+					      constraints->count);
+
+	return 0;
+}
+subsys_initcall(imx_constraints_init);
diff --git a/drivers/clk/imx/clk-imx25.c b/drivers/clk/imx/clk-imx25.c
index 23686f756b5e..4df652cd912c 100644
--- a/drivers/clk/imx/clk-imx25.c
+++ b/drivers/clk/imx/clk-imx25.c
@@ -86,16 +86,6 @@ enum mx25_clks {
 
 static struct clk *clk[clk_max];
 
-static struct clk ** const uart_clks[] __initconst = {
-	&clk[uart_ipg_per],
-	&clk[uart1_ipg],
-	&clk[uart2_ipg],
-	&clk[uart3_ipg],
-	&clk[uart4_ipg],
-	&clk[uart5_ipg],
-	NULL
-};
-
 static int __init __mx25_clocks_init(void __iomem *ccm_base)
 {
 	BUG_ON(!ccm_base);
@@ -241,8 +231,6 @@ static int __init __mx25_clocks_init(void __iomem *ccm_base)
 	 */
 	clk_set_parent(clk[cko_sel], clk[ipg]);
 
-	imx_register_uart_clocks(uart_clks);
-
 	return 0;
 }
 
diff --git a/drivers/clk/imx/clk-imx27.c b/drivers/clk/imx/clk-imx27.c
index 0a0ab95d16fe..379709d21b04 100644
--- a/drivers/clk/imx/clk-imx27.c
+++ b/drivers/clk/imx/clk-imx27.c
@@ -48,17 +48,6 @@ static const char *ssi_sel_clks[] = { "spll_gate", "mpll", };
 static struct clk *clk[IMX27_CLK_MAX];
 static struct clk_onecell_data clk_data;
 
-static struct clk ** const uart_clks[] __initconst = {
-	&clk[IMX27_CLK_PER1_GATE],
-	&clk[IMX27_CLK_UART1_IPG_GATE],
-	&clk[IMX27_CLK_UART2_IPG_GATE],
-	&clk[IMX27_CLK_UART3_IPG_GATE],
-	&clk[IMX27_CLK_UART4_IPG_GATE],
-	&clk[IMX27_CLK_UART5_IPG_GATE],
-	&clk[IMX27_CLK_UART6_IPG_GATE],
-	NULL
-};
-
 static void __init _mx27_clocks_init(unsigned long fref)
 {
 	BUG_ON(!ccm);
@@ -175,8 +164,6 @@ static void __init _mx27_clocks_init(unsigned long fref)
 
 	clk_prepare_enable(clk[IMX27_CLK_EMI_AHB_GATE]);
 
-	imx_register_uart_clocks(uart_clks);
-
 	imx_print_silicon_rev("i.MX27", mx27_revision());
 }
 
diff --git a/drivers/clk/imx/clk-imx31.c b/drivers/clk/imx/clk-imx31.c
index cbce308aad04..d0a720b61aca 100644
--- a/drivers/clk/imx/clk-imx31.c
+++ b/drivers/clk/imx/clk-imx31.c
@@ -63,16 +63,6 @@ enum mx31_clks {
 static struct clk *clk[clk_max];
 static struct clk_onecell_data clk_data;
 
-static struct clk ** const uart_clks[] __initconst = {
-	&clk[ipg],
-	&clk[uart1_gate],
-	&clk[uart2_gate],
-	&clk[uart3_gate],
-	&clk[uart4_gate],
-	&clk[uart5_gate],
-	NULL
-};
-
 static void __init _mx31_clocks_init(void __iomem *base, unsigned long fref)
 {
 	clk[dummy] = imx_clk_fixed("dummy", 0);
@@ -208,8 +198,6 @@ int __init mx31_clocks_init(unsigned long fref)
 	clk_register_clkdev(clk[sdma_gate], NULL, "imx31-sdma");
 	clk_register_clkdev(clk[iim_gate], "iim", NULL);
 
-
-	imx_register_uart_clocks(uart_clks);
 	mxc_timer_init(MX31_GPT1_BASE_ADDR, MX31_INT_GPT, GPT_TYPE_IMX31);
 
 	return 0;
diff --git a/drivers/clk/imx/clk-imx35.c b/drivers/clk/imx/clk-imx35.c
index 203cad6c9aab..081aacd2335b 100644
--- a/drivers/clk/imx/clk-imx35.c
+++ b/drivers/clk/imx/clk-imx35.c
@@ -86,14 +86,6 @@ enum mx35_clks {
 
 static struct clk *clk[clk_max];
 
-static struct clk ** const uart_clks[] __initconst = {
-	&clk[ipg],
-	&clk[uart1_gate],
-	&clk[uart2_gate],
-	&clk[uart3_gate],
-	NULL
-};
-
 static void __init _mx35_clocks_init(void)
 {
 	void __iomem *base;
@@ -247,8 +239,6 @@ static void __init _mx35_clocks_init(void)
 	 */
 	clk_prepare_enable(clk[scc_gate]);
 
-	imx_register_uart_clocks(uart_clks);
-
 	imx_print_silicon_rev("i.MX35", mx35_revision());
 }
 
diff --git a/drivers/clk/imx/clk-imx51-imx53.c b/drivers/clk/imx/clk-imx51-imx53.c
index 7bcaf270db11..2da06f8ffae1 100644
--- a/drivers/clk/imx/clk-imx51-imx53.c
+++ b/drivers/clk/imx/clk-imx51-imx53.c
@@ -131,20 +131,6 @@ static const char *ieee1588_sels[] = { "pll3_sw", "pll4_sw", "dummy" /* usbphy2_
 static struct clk *clk[IMX5_CLK_END];
 static struct clk_onecell_data clk_data;
 
-static struct clk ** const uart_clks[] __initconst = {
-	&clk[IMX5_CLK_UART1_IPG_GATE],
-	&clk[IMX5_CLK_UART1_PER_GATE],
-	&clk[IMX5_CLK_UART2_IPG_GATE],
-	&clk[IMX5_CLK_UART2_PER_GATE],
-	&clk[IMX5_CLK_UART3_IPG_GATE],
-	&clk[IMX5_CLK_UART3_PER_GATE],
-	&clk[IMX5_CLK_UART4_IPG_GATE],
-	&clk[IMX5_CLK_UART4_PER_GATE],
-	&clk[IMX5_CLK_UART5_IPG_GATE],
-	&clk[IMX5_CLK_UART5_PER_GATE],
-	NULL
-};
-
 static void __init mx5_clocks_common_init(void __iomem *ccm_base)
 {
 	clk[IMX5_CLK_DUMMY]		= imx_clk_fixed("dummy", 0);
@@ -325,8 +311,6 @@ static void __init mx5_clocks_common_init(void __iomem *ccm_base)
 	clk_prepare_enable(clk[IMX5_CLK_TMAX1]);
 	clk_prepare_enable(clk[IMX5_CLK_TMAX2]); /* esdhc2, fec */
 	clk_prepare_enable(clk[IMX5_CLK_TMAX3]); /* esdhc1, esdhc4 */
-
-	imx_register_uart_clocks(uart_clks);
 }
 
 static void __init mx50_clocks_init(struct device_node *np)
diff --git a/drivers/clk/imx/clk-imx6q.c b/drivers/clk/imx/clk-imx6q.c
index 8d518ad5dc13..255f571c0b0d 100644
--- a/drivers/clk/imx/clk-imx6q.c
+++ b/drivers/clk/imx/clk-imx6q.c
@@ -150,12 +150,6 @@ static inline int clk_on_imx6dl(void)
 	return of_machine_is_compatible("fsl,imx6dl");
 }
 
-static struct clk ** const uart_clks[] __initconst = {
-	&clk[IMX6QDL_CLK_UART_IPG],
-	&clk[IMX6QDL_CLK_UART_SERIAL],
-	NULL
-};
-
 static int ldb_di_sel_by_clock_id(int clock_id)
 {
 	switch (clock_id) {
@@ -918,7 +912,5 @@ static void __init imx6q_clocks_init(struct device_node *ccm_node)
 		clk_set_parent(clk[IMX6QDL_CLK_GPU2D_CORE_SEL],
 			       clk[IMX6QDL_CLK_PLL3_USB_OTG]);
 	}
-
-	imx_register_uart_clocks(uart_clks);
 }
 CLK_OF_DECLARE(imx6q, "fsl,imx6q-ccm", imx6q_clocks_init);
diff --git a/drivers/clk/imx/clk-imx6sl.c b/drivers/clk/imx/clk-imx6sl.c
index 9642cdf0fb88..97ab67783609 100644
--- a/drivers/clk/imx/clk-imx6sl.c
+++ b/drivers/clk/imx/clk-imx6sl.c
@@ -185,12 +185,6 @@ void imx6sl_set_wait_clk(bool enter)
 		imx6sl_enable_pll_arm(false);
 }
 
-static struct clk ** const uart_clks[] __initconst = {
-	&clks[IMX6SL_CLK_UART],
-	&clks[IMX6SL_CLK_UART_SERIAL],
-	NULL
-};
-
 static void __init imx6sl_clocks_init(struct device_node *ccm_node)
 {
 	struct device_node *np;
@@ -447,7 +441,5 @@ static void __init imx6sl_clocks_init(struct device_node *ccm_node)
 
 	clk_set_parent(clks[IMX6SL_CLK_LCDIF_AXI_SEL],
 		       clks[IMX6SL_CLK_PLL2_PFD2]);
-
-	imx_register_uart_clocks(uart_clks);
 }
 CLK_OF_DECLARE(imx6sl, "fsl,imx6sl-ccm", imx6sl_clocks_init);
diff --git a/drivers/clk/imx/clk-imx6sx.c b/drivers/clk/imx/clk-imx6sx.c
index e6d389e333d7..e38dfb855ae8 100644
--- a/drivers/clk/imx/clk-imx6sx.c
+++ b/drivers/clk/imx/clk-imx6sx.c
@@ -137,12 +137,6 @@ static u32 share_count_ssi3;
 static u32 share_count_sai1;
 static u32 share_count_sai2;
 
-static struct clk ** const uart_clks[] __initconst = {
-	&clks[IMX6SX_CLK_UART_IPG],
-	&clks[IMX6SX_CLK_UART_SERIAL],
-	NULL
-};
-
 static void __init imx6sx_clocks_init(struct device_node *ccm_node)
 {
 	struct device_node *np;
@@ -566,7 +560,5 @@ static void __init imx6sx_clocks_init(struct device_node *ccm_node)
 
 	clk_set_parent(clks[IMX6SX_CLK_QSPI1_SEL], clks[IMX6SX_CLK_PLL2_BUS]);
 	clk_set_parent(clks[IMX6SX_CLK_QSPI2_SEL], clks[IMX6SX_CLK_PLL2_BUS]);
-
-	imx_register_uart_clocks(uart_clks);
 }
 CLK_OF_DECLARE(imx6sx, "fsl,imx6sx-ccm", imx6sx_clocks_init);
diff --git a/drivers/clk/imx/clk-imx7d.c b/drivers/clk/imx/clk-imx7d.c
index 80dc211eb74b..91e5bda48df2 100644
--- a/drivers/clk/imx/clk-imx7d.c
+++ b/drivers/clk/imx/clk-imx7d.c
@@ -387,17 +387,6 @@ static int const clks_init_on[] __initconst = {
 
 static struct clk_onecell_data clk_data;
 
-static struct clk ** const uart_clks[] __initconst = {
-	&clks[IMX7D_UART1_ROOT_CLK],
-	&clks[IMX7D_UART2_ROOT_CLK],
-	&clks[IMX7D_UART3_ROOT_CLK],
-	&clks[IMX7D_UART4_ROOT_CLK],
-	&clks[IMX7D_UART5_ROOT_CLK],
-	&clks[IMX7D_UART6_ROOT_CLK],
-	&clks[IMX7D_UART7_ROOT_CLK],
-	NULL
-};
-
 static void __init imx7d_clocks_init(struct device_node *ccm_node)
 {
 	struct device_node *np;
@@ -884,8 +873,5 @@ static void __init imx7d_clocks_init(struct device_node *ccm_node)
 
 	/* set uart module clock's parent clock source that must be great then 80MHz */
 	clk_set_parent(clks[IMX7D_UART1_ROOT_SRC], clks[IMX7D_OSC_24M_CLK]);
-
-	imx_register_uart_clocks(uart_clks);
-
 }
 CLK_OF_DECLARE(imx7d, "fsl,imx7d-ccm", imx7d_clocks_init);
diff --git a/drivers/clk/imx/clk.c b/drivers/clk/imx/clk.c
index 9074e6974b6d..d8a64367a061 100644
--- a/drivers/clk/imx/clk.c
+++ b/drivers/clk/imx/clk.c
@@ -74,41 +74,3 @@ void imx_cscmr1_fixup(u32 *val)
 	*val ^= CSCMR1_FIXUP;
 	return;
 }
-
-static int imx_keep_uart_clocks __initdata;
-static struct clk ** const *imx_uart_clocks __initdata;
-
-static int __init imx_keep_uart_clocks_param(char *str)
-{
-	imx_keep_uart_clocks = 1;
-
-	return 0;
-}
-__setup_param("earlycon", imx_keep_uart_earlycon,
-	      imx_keep_uart_clocks_param, 0);
-__setup_param("earlyprintk", imx_keep_uart_earlyprintk,
-	      imx_keep_uart_clocks_param, 0);
-
-void __init imx_register_uart_clocks(struct clk ** const clks[])
-{
-	if (imx_keep_uart_clocks) {
-		int i;
-
-		imx_uart_clocks = clks;
-		for (i = 0; imx_uart_clocks[i]; i++)
-			clk_prepare_enable(*imx_uart_clocks[i]);
-	}
-}
-
-static int __init imx_clk_disable_uart(void)
-{
-	if (imx_keep_uart_clocks && imx_uart_clocks) {
-		int i;
-
-		for (i = 0; imx_uart_clocks[i]; i++)
-			clk_disable_unprepare(*imx_uart_clocks[i]);
-	}
-
-	return 0;
-}
-late_initcall_sync(imx_clk_disable_uart);
diff --git a/drivers/clk/imx/clk.h b/drivers/clk/imx/clk.h
index d69c4bbf3597..c5edde073cea 100644
--- a/drivers/clk/imx/clk.h
+++ b/drivers/clk/imx/clk.h
@@ -8,7 +8,6 @@
 extern spinlock_t imx_ccm_lock;
 
 void imx_check_clocks(struct clk *clks[], unsigned int count);
-void imx_register_uart_clocks(struct clk ** const clks[]);
 
 extern void imx_cscmr1_fixup(u32 *val);
 
-- 
2.15.0.194.g9af6a3dea062

^ permalink raw reply related

* [PATCH V6 11/13] boot_constraint: Add Qualcomm display controller constraints
From: Viresh Kumar @ 2018-01-10  3:47 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <cover.1515554879.git.viresh.kumar@linaro.org>

From: Rajendra Nayak <rnayak@codeaurora.org>

This sets boot constraints for the display controller used on Qualcomm
dragonboard 410c.

The display controlled is enabled by the bootloader to show a flash
screen during kernel boot. The handover to kernel should be without any
glitches on the screen.The resources of the display controller (like
regulators) are shared with other peripherals, which may reconfigure
those resources before the display driver comes up. The same problem can
happen if the display driver probes first, as the constraints of the
other devices (sharing same resources with display controller) may not
be honored anymore by the kernel.

Signed-off-by: Rajendra Nayak <rnayak@codeaurora.org>
Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
---
 arch/arm64/Kconfig.platforms     |   1 +
 drivers/boot_constraint/Makefile |   1 +
 drivers/boot_constraint/qcom.c   | 122 +++++++++++++++++++++++++++++++++++++++
 3 files changed, 124 insertions(+)
 create mode 100644 drivers/boot_constraint/qcom.c

diff --git a/arch/arm64/Kconfig.platforms b/arch/arm64/Kconfig.platforms
index a586ed728393..b514327290ca 100644
--- a/arch/arm64/Kconfig.platforms
+++ b/arch/arm64/Kconfig.platforms
@@ -136,6 +136,7 @@ config ARCH_QCOM
 	bool "Qualcomm Platforms"
 	select GPIOLIB
 	select PINCTRL
+	select DEV_BOOT_CONSTRAINT
 	help
 	  This enables support for the ARMv8 based Qualcomm chipsets.
 
diff --git a/drivers/boot_constraint/Makefile b/drivers/boot_constraint/Makefile
index f3e123b5d854..7b6b5966c908 100644
--- a/drivers/boot_constraint/Makefile
+++ b/drivers/boot_constraint/Makefile
@@ -4,3 +4,4 @@ obj-y := clk.o deferrable_dev.o core.o pm.o supply.o
 
 obj-$(CONFIG_ARCH_HISI)			+= hikey.o
 obj-$(CONFIG_ARCH_MXC)			+= imx.o
+obj-$(CONFIG_ARCH_QCOM)			+= qcom.o
diff --git a/drivers/boot_constraint/qcom.c b/drivers/boot_constraint/qcom.c
new file mode 100644
index 000000000000..0498f464da05
--- /dev/null
+++ b/drivers/boot_constraint/qcom.c
@@ -0,0 +1,122 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * This sets up Dragonboard 410c constraints on behalf of the bootloader, which
+ * uses display controller to display a flash screen during system boot.
+ *
+ * Copyright (C) 2017 Linaro.
+ * Viresh Kumar <viresh.kumar@linaro.org>
+ * Rajendra Nayak <rnayak@codeaurora.org>
+ */
+
+#include <linux/boot_constraint.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/of.h>
+
+static struct dev_boot_constraint_clk_info iface_clk_info = {
+	.name = "iface_clk",
+};
+
+static struct dev_boot_constraint_clk_info bus_clk_info = {
+	.name = "bus_clk",
+};
+
+static struct dev_boot_constraint_clk_info core_clk_info = {
+	.name = "core_clk",
+};
+
+static struct dev_boot_constraint_clk_info vsync_clk_info = {
+	.name = "vsync_clk",
+};
+
+static struct dev_boot_constraint_clk_info esc0_clk_info = {
+	.name = "core_clk",
+};
+
+static struct dev_boot_constraint_clk_info byte_clk_info = {
+	.name = "byte_clk",
+};
+
+static struct dev_boot_constraint_clk_info pixel_clk_info = {
+	.name = "pixel_clk",
+};
+
+static struct dev_boot_constraint_supply_info vdda_info = {
+	.name = "vdda"
+};
+
+static struct dev_boot_constraint_supply_info vddio_info = {
+	.name = "vddio"
+};
+
+static struct dev_boot_constraint constraints_mdss[] = {
+	{
+		.type = DEV_BOOT_CONSTRAINT_PM,
+		.data = NULL,
+	},
+};
+
+static struct dev_boot_constraint constraints_mdp[] = {
+	{
+		.type = DEV_BOOT_CONSTRAINT_CLK,
+		.data = &iface_clk_info,
+	}, {
+		.type = DEV_BOOT_CONSTRAINT_CLK,
+		.data = &bus_clk_info,
+	}, {
+		.type = DEV_BOOT_CONSTRAINT_CLK,
+		.data = &core_clk_info,
+	}, {
+		.type = DEV_BOOT_CONSTRAINT_CLK,
+		.data = &vsync_clk_info,
+	},
+};
+
+static struct dev_boot_constraint constraints_dsi[] = {
+	{
+		.type = DEV_BOOT_CONSTRAINT_CLK,
+		.data = &esc0_clk_info,
+	}, {
+		.type = DEV_BOOT_CONSTRAINT_CLK,
+		.data = &byte_clk_info,
+	}, {
+		.type = DEV_BOOT_CONSTRAINT_CLK,
+		.data = &pixel_clk_info,
+	}, {
+		.type = DEV_BOOT_CONSTRAINT_SUPPLY,
+		.data = &vdda_info,
+
+	}, {
+		.type = DEV_BOOT_CONSTRAINT_SUPPLY,
+		.data = &vddio_info,
+	},
+};
+
+static struct dev_boot_constraint_of constraints[] = {
+	{
+		.compat = "qcom,mdss",
+		.constraints = constraints_mdss,
+		.count = ARRAY_SIZE(constraints_mdss),
+	}, {
+		.compat = "qcom,mdp5",
+		.constraints = constraints_mdp,
+		.count = ARRAY_SIZE(constraints_mdp),
+	}, {
+		.compat = "qcom,mdss-dsi-ctrl",
+		.constraints = constraints_dsi,
+		.count = ARRAY_SIZE(constraints_dsi),
+	},
+};
+
+static int __init qcom_constraints_init(void)
+{
+	/* Only Dragonboard 410c is supported for now */
+	if (!of_machine_is_compatible("qcom,apq8016-sbc"))
+		return 0;
+
+	dev_boot_constraint_add_deferrable_of(constraints,
+					      ARRAY_SIZE(constraints));
+
+	return 0;
+}
+subsys_initcall(qcom_constraints_init);
-- 
2.15.0.194.g9af6a3dea062

^ permalink raw reply related

* [PATCH V6 12/13] boot_constraint: Update MAINTAINERS
From: Viresh Kumar @ 2018-01-10  3:47 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <cover.1515554879.git.viresh.kumar@linaro.org>

Add entry for boot constraint subsystem in MAINTAINERS.

Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
---
 MAINTAINERS | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index b46c9cea5ae5..0b9be1c5a982 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -2718,6 +2718,15 @@ S:	Supported
 F:	drivers/net/bonding/
 F:	include/uapi/linux/if_bonding.h
 
+BOOT CONSTRAINT SUBSYSTEM
+M:	Viresh Kumar <vireshk@kernel.org>
+L:	linux-kernel at vger.kernel.org
+S:	Maintained
+T:	git git://git.linaro.org/people/vireshk/linux.git
+F:	Documentation/driver-api/boot_constraint/
+F:	drivers/boot_constraint/
+F:	include/linux/boot_constraint.h
+
 BPF (Safe dynamic programs and tools)
 M:	Alexei Starovoitov <ast@kernel.org>
 M:	Daniel Borkmann <daniel@iogearbox.net>
-- 
2.15.0.194.g9af6a3dea062

^ permalink raw reply related

* [PATCH V6 13/13] boot_constraint: Add documentation
From: Viresh Kumar @ 2018-01-10  3:47 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <cover.1515554879.git.viresh.kumar@linaro.org>

This adds boot constraint documentation.

Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
---
 .../driver-api/boot-constraint/constraints.rst     | 98 ++++++++++++++++++++++
 Documentation/driver-api/boot-constraint/index.rst |  4 +
 Documentation/driver-api/index.rst                 |  1 +
 3 files changed, 103 insertions(+)
 create mode 100644 Documentation/driver-api/boot-constraint/constraints.rst
 create mode 100644 Documentation/driver-api/boot-constraint/index.rst

diff --git a/Documentation/driver-api/boot-constraint/constraints.rst b/Documentation/driver-api/boot-constraint/constraints.rst
new file mode 100644
index 000000000000..036bb77a26f9
--- /dev/null
+++ b/Documentation/driver-api/boot-constraint/constraints.rst
@@ -0,0 +1,98 @@
+.. include:: <isonum.txt>
+
+=========================
+Boot Constraint Subsystem
+=========================
+
+:Copyright: |copy| 2017 Viresh Kumar <vireshk@kernel.org>, Linaro Ltd.
+
+Introduction
+============
+
+A lot of devices are configured and powered ON by the bootloader before passing
+on control to the operating system, Linux in our case.  It is important for some
+of them to keep working until the time a Linux device driver probes the device
+and reconfigure it.
+
+A typical example of that can be the LCD controller, which is used by the
+bootloaders to show image(s) while the platform boots Linux.  The LCD controller
+can be using resources like clk, regulators, etc, that are shared with other
+devices. These shared resources should be configured in such a way that they
+satisfy need of all the user devices.  If another device's (X) driver gets
+probed before the LCD controller driver, then it may end up disabling or
+reconfiguring these resources to ranges satisfying only the current user (device
+X) and that may make the LCD screen unstable and present a bad user experience.
+
+Another case can be a debug serial port (earlycon) enabled from the bootloader,
+which may be used to debug early kernel oops.
+
+There are also cases where the resources may not be shared, but the kernel will
+disable them forcefully as no users may have appeared until a certain point in
+the kernel boot.
+
+Of course we can have more complex cases where the same resource is getting used
+by multiple devices while the kernel boots and the order in which the devices
+get probed wouldn't matter as the other devices may break because of the chosen
+configuration of the first probed device.
+
+Adding boot constraints
+=======================
+
+A boot constraint defines a configuration requirement set for the device by the
+boot loader. For example, if a clock is enabled for a device by the bootloader
+and we want the device to be working as is until the time the device is probed
+by its driver, then keeping this clock enabled is one of the boot constraint.
+
+Following are the different type of boot constraints supported currently by the
+core:
+
+.. kernel-doc:: include/linux/boot_constraint.h
+   :functions: dev_boot_constraint_type
+
+
+A single boot constraint can be added using the following helper:
+
+.. kernel-doc:: drivers/boot_constraint/core.c
+   :functions: dev_boot_constraint_add
+
+
+The second parameter to this routine describes the constraint to add and is
+represented by following structures:
+
+.. kernel-doc:: include/linux/boot_constraint.h
+   :functions: dev_boot_constraint dev_boot_constraint_info
+
+The power domain boot constraint doesn't need any data, while the clock and
+power supply boot constraint specific data is represented by following
+structures:
+
+.. kernel-doc:: include/linux/boot_constraint.h
+   :functions: dev_boot_constraint_supply_info dev_boot_constraint_clk_info
+
+
+In order to simplify adding multiple boot constraints for a platform, the boot
+constraints core supplies another helper which can be used to add all
+constraints for the platform.
+
+.. kernel-doc:: drivers/boot_constraint/deferrable_dev.c
+   :functions: dev_boot_constraint_add_deferrable_of
+
+
+The argument of this routine is described by following structure:
+
+.. kernel-doc:: include/linux/boot_constraint.h
+   :functions: dev_boot_constraint_of
+
+
+Removing boot constraints
+=========================
+
+Once the boot constraints are added, they will be honored by the boot constraint
+core until the time a driver tries to probe the device. The constraints are
+removed by the driver core if either the driver successfully probed the device
+or failed with an error value other than -EPROBE_DEFER. The constraints are kept
+as is for deferred probe. The driver core removes the constraints using the
+following helper, which must not be called directly by the platforms:
+
+.. kernel-doc:: drivers/boot_constraint/core.c
+   :functions: dev_boot_constraints_remove
diff --git a/Documentation/driver-api/boot-constraint/index.rst b/Documentation/driver-api/boot-constraint/index.rst
new file mode 100644
index 000000000000..d6fce17626a2
--- /dev/null
+++ b/Documentation/driver-api/boot-constraint/index.rst
@@ -0,0 +1,4 @@
+.. toctree::
+   :maxdepth: 1
+
+   constraints
diff --git a/Documentation/driver-api/index.rst b/Documentation/driver-api/index.rst
index d17a9876b473..e591c172b5b5 100644
--- a/Documentation/driver-api/index.rst
+++ b/Documentation/driver-api/index.rst
@@ -47,6 +47,7 @@ available subsections can be seen below.
    gpio
    misc_devices
    dmaengine/index
+   boot-constraint/index
 
 .. only::  subproject and html
 
-- 
2.15.0.194.g9af6a3dea062

^ permalink raw reply related

* [PATCH] hw_random: mediatek: Setup default RNG quality
From: sean.wang at mediatek.com @ 2018-01-10  4:02 UTC (permalink / raw)
  To: linux-arm-kernel

From: Sean Wang <sean.wang@mediatek.com>

When hw_random device's quality is non-zero, it will automatically fill
the kernel's entropy pool at boot.  For the purpose, one conservative
quality value is being picked up as the default value.

Signed-off-by: Sean Wang <sean.wang@mediatek.com>
---
 drivers/char/hw_random/mtk-rng.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/char/hw_random/mtk-rng.c b/drivers/char/hw_random/mtk-rng.c
index 8da7bcf..7f99cd5 100644
--- a/drivers/char/hw_random/mtk-rng.c
+++ b/drivers/char/hw_random/mtk-rng.c
@@ -135,6 +135,7 @@ static int mtk_rng_probe(struct platform_device *pdev)
 #endif
 	priv->rng.read = mtk_rng_read;
 	priv->rng.priv = (unsigned long)&pdev->dev;
+	priv->rng.quality = 900;
 
 	priv->clk = devm_clk_get(&pdev->dev, "rng");
 	if (IS_ERR(priv->clk)) {
-- 
2.7.4

^ permalink raw reply related

* [PATCH 2/2] cpufreq: scpi: remove arm_big_little dependency
From: Viresh Kumar @ 2018-01-10  4:19 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1515516568-31359-3-git-send-email-sudeep.holla@arm.com>

On 09-01-18, 16:49, Sudeep Holla wrote:
> +static int
> +scpi_get_sharing_cpus(struct device *cpu_dev, struct cpumask *cpumask)
>  {
> -	return scpi_ops->get_transition_latency(cpu_dev);
> +	int cpu, domain, tdomain;
> +	struct device *tcpu_dev;
> +
> +	domain = scpi_ops->device_domain_id(cpu_dev);
> +	if (domain < 0)
> +		return domain;
> +
> +	for_each_possible_cpu(cpu) {
> +		if (cpu == cpu_dev->id)
> +			continue;
> +
> +		tcpu_dev = get_cpu_device(cpu);
> +		if (!tcpu_dev)
> +			continue;
> +
> +		tdomain = scpi_ops->device_domain_id(tcpu_dev);
> +		if (tdomain == domain)
> +			cpumask_set_cpu(cpu, cpumask);
> +	}
> +
> +	return 0;
>  }

So this is the main thing you want to achieve ? i.e. get the
policy->cpus from scpi_ops, right ?

Why can't we update .init_opp_table() to include policy as a parameter
and let individual stub drivers update policy->cpus then ?

-- 
viresh

^ permalink raw reply

* [PATCH v3 2/2] dt-bindings: mailbox: Add Xilinx IPI Mailbox
From: Jassi Brar @ 2018-01-10  4:42 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <BY1PR0201MB0885F2BCD9FE353171B54888B0110@BY1PR0201MB0885.namprd02.prod.outlook.com>

On Wed, Jan 10, 2018 at 6:52 AM, Jiaying Liang <jliang@xilinx.com> wrote:
>> From: Jassi Brar [mailto:jassisinghbrar at gmail.com]

>> > +
>> > +Controller Device Node:
>> > +===========================
>> > +Required properties:
>> > +--------------------
>> > +- compatible:          Shall be: "xlnx,zynqmp-ipi-mailbox"
>> > +- reg:                 IPI buffers address ranges
>> > +- reg-names:           Names of the reg resources. It should have:
>> > +                       * local_request_region
>> > +                         - IPI request msg buffer written by local and read
>> > +                           by remote
>> > +                       * local_response_region
>> > +                         - IPI response msg buffer written by local and read
>> > +                           by remote
>> > +                       * remote_request_region
>> > +                         - IPI request msg buffer written by remote and read
>> > +                           by local
>> > +                       * remote_response_region
>> > +                         - IPI response msg buffer written by remote and read
>> > +                           by local
>> >
>> shmem is option and external to the controller. It should be passed via
>> client's binding.
>> Please have a look at Sudeep's proposed patch
>> https://www.spinics.net/lists/arm-kernel/msg626120.html
> [Wendy] thanks for the link, but those 'buffers" are registers in the hardware
> but not memory.
>
No, that is for memory, not registers.
Please have a more careful look at the patch.

>>
>> > +- #mbox-cells:         Shall be 1. It contains:
>> > +                       * tx(0) or rx(1) channel
>> > +- xlnx,ipi-ids:                Xilinx IPI agent IDs of the two peers of the
>> > +                       Xilinx IPI communication channel.
>> > +- interrupt-parent:    Phandle for the interrupt controller
>> > +- interrupts:          Interrupt information corresponding to the
>> > +                       interrupt-names property.
>> > +
>> > +Optional properties:
>> > +--------------------
>> > +- method:              The method of accessing the IPI agent registers.
>> > +                       Permitted values are: "smc" and "hvc". Default is
>> > +                       "smc".
>> > +
>> Andre almost implemented the generic driver. Can you please have a look at
>> https://www.spinics.net/lists/arm-kernel/msg595416.html
>> and see if you can just finish it off?
> [Wendy] This mailbox controller is about to use Xilinx IPI hardware as mailbox.
>
I couldn't find anything specific to Xilinx h/w
zynqmp_ipi_fw_call() is same as arm_smc_send_data() in Andre's driver
(though it needs to pass on [R2,R7] as I suggested in reply to him).

> We use it to send notification/short request to firmware (usually running on
> another core on SoC),
>
So does Andre's driver. Which is precise and generic, so I much prefer that.

> and also to receive notification/short request from firmware.
> Interrupt is used in the receiving direction. It looks different to the usage of
> mailbox driver from the link.
>
Yes, there is some difference. But nothing related to your h/w.
Andre's driver assume synchronous transmits where the response is
filled in the regs upon return.
What kind of calls do you make to your remote firmware? I would expect
them to be 'fast'.

> Is there a plan to extend the ARM SMC mailbox driver
> to both trigger firmware actions and receive request from firmware?
>
Sure if we have a genuine requirement we can support RX path as well.

Thanks.

^ permalink raw reply

* [PATCH v3 3/6] coresight: Support panic kdump functionality
From: Leo Yan @ 2018-01-10  5:19 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20180109184126.GA21932@xps15>

On Tue, Jan 09, 2018 at 11:41:26AM -0700, Mathieu Poirier wrote:
> On Thu, Dec 21, 2017 at 04:20:12PM +0800, Leo Yan wrote:
> > After kernel panic happens, coresight has many useful info can be used
> > for analysis.  For example, the trace info from ETB RAM can be used to
> > check the CPU execution flows before crash.  So we can save the tracing
> > data from sink devices, and rely on kdump to save DDR content and uses
> > "crash" tool to extract coresight dumping from vmcore file.
> > 
> > This patch is to add a simple framework to support panic dump
> > functionality; it registers panic notifier, and provide the general APIs
> > {coresight_kdump_add|coresight_kdump_del} as helper functions so any
> > coresight device can add itself into dump list or delete as needed.
> > 
> > This driver provides helper function coresight_kdump_update() to update
> > the dump buffer base address and buffer size.  This function can be used
> > by coresight driver, e.g. it can be used to save ETM meta data info at
> > runtime and these info can be prepared pre panic happening.
> > 
> > When kernel panic happens, the notifier iterates dump list and calls
> > callback function to dump device specific info.  The panic dump is
> > mainly used to dump trace data so we can get to know the execution flow
> > before the panic happens.
> > 
> > Signed-off-by: Leo Yan <leo.yan@linaro.org>
> > ---
> >  drivers/hwtracing/coresight/Kconfig                |   9 ++
> >  drivers/hwtracing/coresight/Makefile               |   1 +
> >  .../hwtracing/coresight/coresight-panic-kdump.c    | 154 +++++++++++++++++++++
> >  drivers/hwtracing/coresight/coresight-priv.h       |  13 ++
> >  include/linux/coresight.h                          |   7 +
> >  5 files changed, 184 insertions(+)
> >  create mode 100644 drivers/hwtracing/coresight/coresight-panic-kdump.c
> > 
> > diff --git a/drivers/hwtracing/coresight/Kconfig b/drivers/hwtracing/coresight/Kconfig
> > index ef9cb3c..4812529 100644
> > --- a/drivers/hwtracing/coresight/Kconfig
> > +++ b/drivers/hwtracing/coresight/Kconfig
> > @@ -103,4 +103,13 @@ config CORESIGHT_CPU_DEBUG
> >  	  properly, please refer Documentation/trace/coresight-cpu-debug.txt
> >  	  for detailed description and the example for usage.
> >  
> > +config CORESIGHT_PANIC_KDUMP
> > +	bool "CoreSight Panic Kdump driver"
> > +	depends on ARM || ARM64
> 
> At this time only ETMv4 supports the feature, so it is only ARM64.

Thanks for reviewing, Mathieu.

Will change to only for ARM64.

> > +	help
> > +	  This driver provides panic kdump functionality for CoreSight
> > +	  devices.  When a kernel panic happen a device supplied callback function
> > +	  is used to save trace data to memory. From there we rely on kdump to extract
> > +	  the trace data from kernel dump file.
> > +
> >  endif
> > diff --git a/drivers/hwtracing/coresight/Makefile b/drivers/hwtracing/coresight/Makefile
> > index 61db9dd..946fe19 100644
> > --- a/drivers/hwtracing/coresight/Makefile
> > +++ b/drivers/hwtracing/coresight/Makefile
> > @@ -18,3 +18,4 @@ obj-$(CONFIG_CORESIGHT_SOURCE_ETM4X) += coresight-etm4x.o \
> >  obj-$(CONFIG_CORESIGHT_DYNAMIC_REPLICATOR) += coresight-dynamic-replicator.o
> >  obj-$(CONFIG_CORESIGHT_STM) += coresight-stm.o
> >  obj-$(CONFIG_CORESIGHT_CPU_DEBUG) += coresight-cpu-debug.o
> > +obj-$(CONFIG_CORESIGHT_PANIC_KDUMP) += coresight-panic-kdump.o
> > diff --git a/drivers/hwtracing/coresight/coresight-panic-kdump.c b/drivers/hwtracing/coresight/coresight-panic-kdump.c
> > new file mode 100644
> > index 0000000..c21d20b
> > --- /dev/null
> > +++ b/drivers/hwtracing/coresight/coresight-panic-kdump.c
> > @@ -0,0 +1,154 @@
> > +// SPDX-License-Identifier: GPL-2.0
> > +// Copyright (c) 2017 Linaro Limited.
> > +#include <linux/coresight.h>
> > +#include <linux/coresight-pmu.h>
> > +#include <linux/cpumask.h>
> > +#include <linux/device.h>
> > +#include <linux/init.h>
> > +#include <linux/list.h>
> > +#include <linux/mm.h>
> > +#include <linux/perf_event.h>
> > +#include <linux/slab.h>
> > +#include <linux/types.h>
> > +
> > +#include "coresight-priv.h"
> > +
> > +typedef void (*coresight_cb_t)(void *data);
> > +
> > +/**
> > + * struct coresight_kdump_node - Node information for dump
> > + * @cpu:	The cpu this node is affined to.
> > + * @csdev:	Handler for coresight device.
> > + * @buf:	Pointer for dump buffer.
> > + * @buf_size:	Length of dump buffer.
> > + * @list:	Hook to the list.
> > + */
> > +struct coresight_kdump_node {
> > +	int cpu;
> > +	struct coresight_device *csdev;
> > +	char *buf;
> > +	unsigned int buf_size;
> > +	struct list_head list;
> > +};
> > +
> > +static DEFINE_SPINLOCK(coresight_kdump_lock);
> > +static LIST_HEAD(coresight_kdump_list);
> > +static struct notifier_block coresight_kdump_nb;
> > +
> > +int coresight_kdump_update(struct coresight_device *csdev, char *buf,
> > +			   unsigned int buf_size)
> > +{
> > +	struct coresight_kdump_node *node = csdev->dump_node;
> > +
> > +	if (!node) {
> > +		dev_err(&csdev->dev, "Failed to update dump node.\n");
> > +		return -EINVAL;
> > +	}
> > +
> > +	node->buf = buf;
> > +	node->buf_size = buf_size;
> > +	return 0;
> > +}
> > +
> > +int coresight_kdump_add(struct coresight_device *csdev, int cpu)
> > +{
> > +	struct coresight_kdump_node *node;
> > +	unsigned long flags;
> > +
> > +	node = kzalloc(sizeof(*node), GFP_KERNEL);
> > +	if (!node)
> > +		return -ENOMEM;
> > +
> > +	csdev->dump_node = (void *)node;
> > +	node->cpu = cpu;
> > +	node->csdev = csdev;
> > +
> > +	spin_lock_irqsave(&coresight_kdump_lock, flags);
> > +	list_add_tail(&node->list, &coresight_kdump_list);
> > +	spin_unlock_irqrestore(&coresight_kdump_lock, flags);
> > +	return 0;
> > +}
> > +
> > +void coresight_kdump_del(struct coresight_device *csdev)
> > +{
> > +	struct coresight_kdump_node *node, *next;
> > +	unsigned long flags;
> > +
> > +	spin_lock_irqsave(&coresight_kdump_lock, flags);
> > +	list_for_each_entry_safe(node, next, &coresight_kdump_list, list) {
> > +		if (node->csdev == csdev) {
> > +			list_del(&node->list);
> > +			kfree(node);
> > +			break;
> > +		}
> > +	}
> > +	spin_unlock_irqrestore(&coresight_kdump_lock, flags);
> > +}
> > +
> > +static coresight_cb_t
> > +coresight_kdump_get_cb(struct coresight_device *csdev)
> > +{
> > +	coresight_cb_t cb = NULL;
> > +
> > +	switch (csdev->type) {
> > +	case CORESIGHT_DEV_TYPE_SINK:
> > +	case CORESIGHT_DEV_TYPE_LINKSINK:
> > +		cb = sink_ops(csdev)->panic_cb;
> > +		break;
> > +	case CORESIGHT_DEV_TYPE_SOURCE:
> > +		cb = source_ops(csdev)->panic_cb;
> > +		break;
> > +	case CORESIGHT_DEV_TYPE_LINK:
> > +		cb = link_ops(csdev)->panic_cb;
> > +		break;
> 
> I don't see why we need a callback for link devices - didn't I raised
> that question before?

Yes, sorry I have not deleted for link devices completely. Will remove
it.

> And I've been thinking further about this.  The way we call the panic callbacks
> won't work.  When a panic is triggered there might be trace data in the CS network
> that hasn't made it to the sink yet and calling the panic callbacks for sinks
> will lead to a loss of data.
> 
> That is why, when accessing from both sysFS and perf, the current implementation
> takes great care to stop the tracers first and then deal with the sink.  To fix
> this I suggest to call the panic callbacks only for sources.  What happens there
> will depend on what interface is used (sysFS or perf) - look at what is
> currently done to get a better understanding.

Will look into this.

If I understand correctly, we need firstly stop tracers and save trace
data from sink, right? If so we need use single callback function to
disable path and dump data for sink, will study current case and check
what's the clean method for kdump.

> > +	default:
> > +		dev_info(&csdev->dev, "Unsupport panic dump\n");
> 
> I would not bother with the dev_info()...

Will remove it.

> > +		break;
> > +	}
> > +
> > +	return cb;
> > +}
> > +
> > +/**
> > + * coresight_kdump_notify - Invoke panic dump callbacks, this is
> > + * the main function to fulfill the panic dump.  It distinguishs
> > + * to two types: one is pre panic dump which the callback function
> > + * handler is NULL and coresight drivers can use function
> > + * coresight_kdump_update() to directly update dump buffer base
> > + * address and buffer size, for this case this function does nothing
> > + * and directly bail out; another case is for post panic dump so
> > + * invoke callback on alive CPU.
> 
> Now that pre and post processing are gone the description above doesn't match
> what the function is doing.

Yeah, will remove 'pre' and 'post' to avoid confusion.

> > + *
> > + * Returns: 0 on success.
> > + */
> > +static int coresight_kdump_notify(struct notifier_block *nb,
> > +				  unsigned long mode, void *_unused)
> > +{
> > +	struct coresight_kdump_node *node;
> > +	struct coresight_device *csdev;
> > +	coresight_cb_t cb;
> > +	unsigned long flags;
> > +
> > +	spin_lock_irqsave(&coresight_kdump_lock, flags);
> > +
> > +	list_for_each_entry(node, &coresight_kdump_list, list) {
> > +		csdev = node->csdev;
> > +		cb = coresight_kdump_get_cb(csdev);
> > +		if (cb)
> > +			cb(csdev);
> > +	}
> > +
> > +	spin_unlock_irqrestore(&coresight_kdump_lock, flags);
> > +	return 0;
> > +}
> > +
> > +static int __init coresight_kdump_init(void)
> > +{
> > +	int ret;
> > +
> > +	coresight_kdump_nb.notifier_call = coresight_kdump_notify;
> > +	ret = atomic_notifier_chain_register(&panic_notifier_list,
> > +					     &coresight_kdump_nb);
> > +	return ret;
> > +}
> > +late_initcall(coresight_kdump_init);
> > diff --git a/drivers/hwtracing/coresight/coresight-priv.h b/drivers/hwtracing/coresight/coresight-priv.h
> > index f1d0e21d..937750e 100644
> > --- a/drivers/hwtracing/coresight/coresight-priv.h
> > +++ b/drivers/hwtracing/coresight/coresight-priv.h
> > @@ -151,4 +151,17 @@ static inline int etm_readl_cp14(u32 off, unsigned int *val) { return 0; }
> >  static inline int etm_writel_cp14(u32 off, u32 val) { return 0; }
> >  #endif
> >  
> > +#ifdef CONFIG_CORESIGHT_PANIC_KDUMP
> > +extern int coresight_kdump_add(struct coresight_device *csdev, int cpu);
> > +extern void coresight_kdump_del(struct coresight_device *csdev);
> > +extern int coresight_kdump_update(struct coresight_device *csdev,
> > +				  char *buf, unsigned int buf_size);
> > +#else
> > +static inline int
> > +coresight_kdump_add(struct coresight_device *csdev, int cpu) { return 0; }
> > +static inline void coresight_kdump_del(struct coresight_device *csdev) {}
> > +static inline int coresight_kdump_update(struct coresight_device *csdev,
> > +	char *buf, unsigned int buf_size) { return 0; }
> 
> static inline int
> coresight_kdump_update(struct coresight_device *csdev, char *buf,
>                        unsigned int buf_size) { return 0; }

Will fix.

> > +#endif
> > +
> >  #endif
> > diff --git a/include/linux/coresight.h b/include/linux/coresight.h
> > index d950dad..43e40fa 100644
> > --- a/include/linux/coresight.h
> > +++ b/include/linux/coresight.h
> > @@ -171,6 +171,7 @@ struct coresight_device {
> >  	bool orphan;
> >  	bool enable;	/* true only if configured as part of a path */
> >  	bool activated;	/* true only if a sink is part of a path */
> > +	void *dump_node;
> 
> Please add a description for this entry.

Will do.

Thanks,
Leo Yan

> >  };
> >  
> >  #define to_coresight_device(d) container_of(d, struct coresight_device, dev)
> > @@ -189,6 +190,7 @@ struct coresight_device {
> >   * @set_buffer:		initialises buffer mechanic before a trace session.
> >   * @reset_buffer:	finalises buffer mechanic after a trace session.
> >   * @update_buffer:	update buffer pointers after a trace session.
> > + * @panic_cb:		hook function for panic notifier.
> >   */
> >  struct coresight_ops_sink {
> >  	int (*enable)(struct coresight_device *csdev, u32 mode);
> > @@ -205,6 +207,7 @@ struct coresight_ops_sink {
> >  	void (*update_buffer)(struct coresight_device *csdev,
> >  			      struct perf_output_handle *handle,
> >  			      void *sink_config);
> > +	void (*panic_cb)(void *data);
> >  };
> >  
> >  /**
> > @@ -212,10 +215,12 @@ struct coresight_ops_sink {
> >   * Operations available for links.
> >   * @enable:	enables flow between iport and oport.
> >   * @disable:	disables flow between iport and oport.
> > + * @panic_cb:	hook function for panic notifier.
> >   */
> >  struct coresight_ops_link {
> >  	int (*enable)(struct coresight_device *csdev, int iport, int oport);
> >  	void (*disable)(struct coresight_device *csdev, int iport, int oport);
> > +	void (*panic_cb)(void *data);
> >  };
> >  
> >  /**
> > @@ -227,6 +232,7 @@ struct coresight_ops_link {
> >   *		to the HW.
> >   * @enable:	enables tracing for a source.
> >   * @disable:	disables tracing for a source.
> > + * @panic_cb:	hook function for panic notifier.
> >   */
> >  struct coresight_ops_source {
> >  	int (*cpu_id)(struct coresight_device *csdev);
> > @@ -235,6 +241,7 @@ struct coresight_ops_source {
> >  		      struct perf_event *event,  u32 mode);
> >  	void (*disable)(struct coresight_device *csdev,
> >  			struct perf_event *event);
> > +	void (*panic_cb)(void *data);
> >  };
> >  
> >  struct coresight_ops {
> > -- 
> > 2.7.4
> > 

^ permalink raw reply

* [PATCH v3 6/6] coresight: etm4x: Support panic kdump
From: Leo Yan @ 2018-01-10  5:33 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20180109202128.GB21932@xps15>

On Tue, Jan 09, 2018 at 01:21:28PM -0700, Mathieu Poirier wrote:
> On Thu, Dec 21, 2017 at 04:20:15PM +0800, Leo Yan wrote:
> > ETMv4 hardware information and configuration needs to be saved as
> > metadata; these metadata should be compatible with tool 'perf' and
> > can be used for tracing data analysis.  ETMv4 usually works as tracer
> > per CPU, we cannot wait to gather ETM info after the CPU has been panic
> > and cannot execute dump operations for itself; so should gather
> > metadata when the corresponding CPU is alive.
> > 
> > Since values in TRCIDR{0, 1, 2, 8} and TRCAUTHSTATUS are read-only and
> > won't change at the runtime.  Those registers value are filled when
> > tracers are instantiated.
> > 
> > The configuration and control registers TRCCONFIGR and TRCTRACEIDR are
> > dynamically configured, we record their value when enabling coresight
> > path.  When operating from sysFS tracer these two registers are recorded
> > in etm4_enable_sysfs() and add kdump node into list, and remove the
> > kdump node in etm4_disable_sysfs().  When operating from perf,
> > etm_setup_aux() adds all tracers to the dump list and etm4_enable_perf()
> > is used to record configuration registers and update dump buffer info,
> > this can avoid unnecessary list addition and deletion operations.
> > Removal of the tracers from the dump list is done in function
> > free_event_data().
> > 
> > Suggested-by: Mathieu Poirier <mathieu.poirier@linaro.org>
> > Signed-off-by: Leo Yan <leo.yan@linaro.org>
> > ---
> >  drivers/hwtracing/coresight/coresight-etm-perf.c | 12 +++++++++++-
> >  drivers/hwtracing/coresight/coresight-etm4x.c    | 23 +++++++++++++++++++++++
> >  drivers/hwtracing/coresight/coresight-etm4x.h    | 15 +++++++++++++++
> >  3 files changed, 49 insertions(+), 1 deletion(-)
> > 
> > diff --git a/drivers/hwtracing/coresight/coresight-etm-perf.c b/drivers/hwtracing/coresight/coresight-etm-perf.c
> > index 8a0ad77..fec779b 100644
> > --- a/drivers/hwtracing/coresight/coresight-etm-perf.c
> > +++ b/drivers/hwtracing/coresight/coresight-etm-perf.c
> > @@ -137,6 +137,12 @@ static void free_event_data(struct work_struct *work)
> >  	}
> >  
> >  	for_each_cpu(cpu, mask) {
> > +		struct coresight_device *csdev;
> > +
> > +		csdev = per_cpu(csdev_src, cpu);
> > +		if (csdev)
> > +			coresight_kdump_del(csdev);
> > +
> >  		if (!(IS_ERR_OR_NULL(event_data->path[cpu])))
> >  			coresight_release_path(event_data->path[cpu]);
> >  	}
> > @@ -195,7 +201,7 @@ static void etm_free_aux(void *data)
> >  static void *etm_setup_aux(int event_cpu, void **pages,
> >  			   int nr_pages, bool overwrite)
> >  {
> > -	int cpu;
> > +	int cpu, ret;
> >  	cpumask_t *mask;
> >  	struct coresight_device *sink;
> >  	struct etm_event_data *event_data = NULL;
> > @@ -238,6 +244,10 @@ static void *etm_setup_aux(int event_cpu, void **pages,
> >  		event_data->path[cpu] = coresight_build_path(csdev, sink);
> >  		if (IS_ERR(event_data->path[cpu]))
> >  			goto err;
> > +
> > +		ret = coresight_kdump_add(csdev, cpu);
> 
> Aren't you missing the configuration for trcconfigr and trctraceidr?

Ah, should update these two configurations in function
etm4_enable_perf()?

> > +		if (ret)
> > +			goto err;
> >  	}
> >  
> >  	if (!sink_ops(sink)->alloc_buffer)
> > diff --git a/drivers/hwtracing/coresight/coresight-etm4x.c b/drivers/hwtracing/coresight/coresight-etm4x.c
> > index cf364a5..cbde398 100644
> > --- a/drivers/hwtracing/coresight/coresight-etm4x.c
> > +++ b/drivers/hwtracing/coresight/coresight-etm4x.c
> > @@ -258,10 +258,19 @@ static int etm4_enable_perf(struct coresight_device *csdev,
> >  static int etm4_enable_sysfs(struct coresight_device *csdev)
> >  {
> >  	struct etmv4_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
> > +	struct etmv4_config *config = &drvdata->config;
> > +	struct etmv4_metadata *metadata = &drvdata->metadata;
> >  	int ret;
> >  
> >  	spin_lock(&drvdata->spinlock);
> >  
> > +	/* Update meta data and add into kdump list */
> > +	metadata->trcconfigr = config->cfg;
> > +	metadata->trctraceidr = drvdata->trcid;
> > +
> > +	coresight_kdump_add(csdev, drvdata->cpu);
> > +	coresight_kdump_update(csdev, (char *)metadata, sizeof(*metadata));
> > +
> >  	/*
> >  	 * Executing etm4_enable_hw on the cpu whose ETM is being enabled
> >  	 * ensures that register writes occur when cpu is powered.
> > @@ -384,6 +393,9 @@ static void etm4_disable_sysfs(struct coresight_device *csdev)
> >  	 */
> >  	smp_call_function_single(drvdata->cpu, etm4_disable_hw, drvdata, 1);
> >  
> > +	/* Delete from kdump list */
> > +	coresight_kdump_del(csdev);
> > +
> >  	spin_unlock(&drvdata->spinlock);
> >  	cpus_read_unlock();
> >  
> > @@ -438,6 +450,7 @@ static void etm4_init_arch_data(void *info)
> >  	u32 etmidr4;
> >  	u32 etmidr5;
> >  	struct etmv4_drvdata *drvdata = info;
> > +	struct etmv4_metadata *metadata = &drvdata->metadata;
> >  
> >  	/* Make sure all registers are accessible */
> >  	etm4_os_unlock(drvdata);
> > @@ -590,6 +603,16 @@ static void etm4_init_arch_data(void *info)
> >  	drvdata->nrseqstate = BMVAL(etmidr5, 25, 27);
> >  	/* NUMCNTR, bits[30:28] number of counters available for tracing */
> >  	drvdata->nr_cntr = BMVAL(etmidr5, 28, 30);
> > +
> > +	/* Update metadata */
> > +	metadata->magic = ETM4_METADATA_MAGIC;
> > +	metadata->cpu = drvdata->cpu;
> > +	metadata->trcidr0 = readl_relaxed(drvdata->base + TRCIDR0);
> > +	metadata->trcidr1 = readl_relaxed(drvdata->base + TRCIDR1);
> > +	metadata->trcidr2 = readl_relaxed(drvdata->base + TRCIDR2);
> > +	metadata->trcidr8 = readl_relaxed(drvdata->base + TRCIDR8);
> > +	metadata->trcauthstatus = readl_relaxed(drvdata->base + TRCAUTHSTATUS);
> > +
> >  	CS_LOCK(drvdata->base);
> >  }
> >  
> > diff --git a/drivers/hwtracing/coresight/coresight-etm4x.h b/drivers/hwtracing/coresight/coresight-etm4x.h
> > index b3b5ea7..08dc8b7 100644
> > --- a/drivers/hwtracing/coresight/coresight-etm4x.h
> > +++ b/drivers/hwtracing/coresight/coresight-etm4x.h
> > @@ -198,6 +198,20 @@
> >  #define ETM_EXLEVEL_NS_HYP		BIT(14)
> >  #define ETM_EXLEVEL_NS_NA		BIT(15)
> >  
> > +#define ETM4_METADATA_MAGIC		0x4040404040404040ULL
> 
> This is a duplicate of the magic value found in cs-etm.h but I'm not sure of
> what we'll do about that. It is probably time to come up
> with a shared file between the kernel and the perf tools, just like
> coresight-pmu.h.  You can have a stab at it or concentrate on my previous
> comments for now - it's entirely up to you.

I will do some try for this for changing to use one shared single
header, if I have no confidence for this I will go back to keep this
code for new version patch.

> > +
> > +struct etmv4_metadata {
> > +	u64 magic;
> > +	u64 cpu;
> > +	u64 trcconfigr;
> > +	u64 trctraceidr;
> > +	u64 trcidr0;
> > +	u64 trcidr1;
> > +	u64 trcidr2;
> > +	u64 trcidr8;
> > +	u64 trcauthstatus;
> > +};
> 
> Same here...  This is a duplicate of struct etmv4_drvdata.  Again not sure about
> the best way to handle this.  I'll think about it.

Sure, I might check with you when I spin patches for this.

Thanks,
Leo Yan

> > +
> >  /**
> >   * struct etmv4_config - configuration information related to an ETMv4
> >   * @mode:	Controls various modes supported by this ETM.
> > @@ -393,6 +407,7 @@ struct etmv4_drvdata {
> >  	bool				atbtrig;
> >  	bool				lpoverride;
> >  	struct etmv4_config		config;
> > +	struct etmv4_metadata		metadata;
> >  };
> >  
> >  /* Address comparator access types */
> > -- 
> > 2.7.4
> > 

^ permalink raw reply

* [PATCH v2 5/5] pinctrl: imx6ul: add IOMUXC SNVS pinctrl driver for i.MX 6ULL
From: A.s. Dong @ 2018-01-10  5:35 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <CACRpkdYJcS3Ng=uR-iPgJ22ABfbiVENjWGsaWwShUfbg1hU4+g@mail.gmail.com>

Hi Linus,

> -----Original Message-----
> From: Linus Walleij [mailto:linus.walleij at linaro.org]
> Sent: Tuesday, January 09, 2018 10:08 PM
....
> 
> Stefan, would you consider making a patch adding you, Dong Aisheng and
> Shawn Guo as maintainers in MAINTAINERS for
> drivers/pinctrl/freescale/*
> Documentation/devicetree/bindings/pinctrl/fsl,*
> ?

I'm okay to take that MAINTAINER work.
Thanks for the nomination.

Regards
Dong Aisheng

^ permalink raw reply

* [PATCH 05/10] perf tools: Add support for decoding CoreSight trace data
From: Leo Yan @ 2018-01-10  5:59 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <CAJ9a7VjEdu9gsTw9eLhLJnfjxewZHAr4k-DELMPk3zoG=ZPj6g@mail.gmail.com>

Hi Mike,

On Tue, Jan 09, 2018 at 12:09:58PM +0000, Mike Leach wrote:
> Hi Leo,
> 
> The OCSD_GEN_TRC_ELEM_ADDR_NACC element indicates that the decoder
> does not have an code image mapping for the address contained in the
> trace, at the location described by this element. the payload for the
> NACC element is the memory location it could not address.
> This means that it cannot correctly follow the instruction execution
> sequence described by the individual trace packets.
> 
> The dump option works because we do not need to follow the execution
> sequence to dump raw trace packets.
> 
> It is not clear to me if the perf script option as you specified is
> mapping the vmlinux image into the decoder.

I only can say that the 'perf script' has loaded symbol list by the
option '--kallsyms ./System.map'.  Here have one corner case is for
option '-k vmlinux', at my side I build 'perf' tool without linking
libelf, so perf cannot directly parse kernel symbol.  If the perf
tool is built with linking libelf, then we can directly load kernel
symbol mapping from vmlinux and don't need specifiy option
'--kallsyms ./System.map' anymore.

Could you point which perf code will pass vmlinux mapping to the
decoder? I don't know this before.  After some debugging I only found
perf relies on OpenCSD to return back OCSD_GEN_TRC_ELEM_INSTR_RANGE
and then perf will do symbol/sym_off analysis, otherwise it will skip
symbol analysis.

BTW, I use the same 'perf script' command with OpenCSD v0.7.5, it
can return back OCSD_GEN_TRC_ELEM_INSTR_RANGE but not
OCSD_GEN_TRC_ELEM_ADDR_NACC so it can print out kernel symbol, this
is for using the same perf.data and vmlinux files.

Thanks,
Leo Yan

> On 30 December 2017 at 00:33, Leo Yan <leo.yan@linaro.org> wrote:
> > Hi Mathieu, Mike,
> >
> > On Fri, Dec 15, 2017 at 09:44:54AM -0700, Mathieu Poirier wrote:
> >> Adding functionality to create a CoreSight trace decoder capable
> >> of decoding trace data pushed by a client application.
> >>
> >> Co-authored-by: Tor Jeremiassen <tor@ti.com>
> >> Signed-off-by: Mathieu Poirier <mathieu.poirier@linaro.org>
> >> ---
> >>  tools/perf/util/cs-etm-decoder/cs-etm-decoder.c | 119 ++++++++++++++++++++++++
> >>  1 file changed, 119 insertions(+)
> >>
> >> diff --git a/tools/perf/util/cs-etm-decoder/cs-etm-decoder.c b/tools/perf/util/cs-etm-decoder/cs-etm-decoder.c
> >> index 6a4c86b1431f..57b020b0b36f 100644
> >> --- a/tools/perf/util/cs-etm-decoder/cs-etm-decoder.c
> >> +++ b/tools/perf/util/cs-etm-decoder/cs-etm-decoder.c
> >> @@ -200,6 +200,121 @@ static void cs_etm_decoder__clear_buffer(struct cs_etm_decoder *decoder)
> >>       }
> >>  }
> >>
> >> +static ocsd_datapath_resp_t
> >> +cs_etm_decoder__buffer_packet(struct cs_etm_decoder *decoder,
> >> +                           const ocsd_generic_trace_elem *elem,
> >> +                           const u8 trace_chan_id,
> >> +                           enum cs_etm_sample_type sample_type)
> >> +{
> >> +     u32 et = 0;
> >> +     struct int_node *inode = NULL;
> >> +
> >> +     if (decoder->packet_count >= MAX_BUFFER - 1)
> >> +             return OCSD_RESP_FATAL_SYS_ERR;
> >> +
> >> +     /* Search the RB tree for the cpu associated with this traceID */
> >> +     inode = intlist__find(traceid_list, trace_chan_id);
> >> +     if (!inode)
> >> +             return OCSD_RESP_FATAL_SYS_ERR;
> >> +
> >> +     et = decoder->tail;
> >> +     decoder->packet_buffer[et].sample_type = sample_type;
> >> +     decoder->packet_buffer[et].start_addr = elem->st_addr;
> >> +     decoder->packet_buffer[et].end_addr = elem->en_addr;
> >> +     decoder->packet_buffer[et].exc = false;
> >> +     decoder->packet_buffer[et].exc_ret = false;
> >> +     decoder->packet_buffer[et].cpu = *((int *)inode->priv);
> >> +
> >> +     /* Wrap around if need be */
> >> +     et = (et + 1) & (MAX_BUFFER - 1);
> >> +
> >> +     decoder->tail = et;
> >> +     decoder->packet_count++;
> >> +
> >> +     if (decoder->packet_count == MAX_BUFFER - 1)
> >> +             return OCSD_RESP_WAIT;
> >> +
> >> +     return OCSD_RESP_CONT;
> >> +}
> >> +
> >> +static ocsd_datapath_resp_t cs_etm_decoder__gen_trace_elem_printer(
> >> +                             const void *context,
> >> +                             const ocsd_trc_index_t indx __maybe_unused,
> >> +                             const u8 trace_chan_id __maybe_unused,
> >> +                             const ocsd_generic_trace_elem *elem)
> >> +{
> >> +     ocsd_datapath_resp_t resp = OCSD_RESP_CONT;
> >> +     struct cs_etm_decoder *decoder = (struct cs_etm_decoder *) context;
> >
> > After apply this patch set and build 'perf' tool with linking
> > OpenCSDv0.8.0 libs, I can everytime OpenCSD parses 'elem->elem_type'
> > is OCSD_GEN_TRC_ELEM_ADDR_NACC but not OCSD_GEN_TRC_ELEM_INSTR_RANGE.
> >
> > As result, the 'perf' tool can dump the raw data with '-D' option but
> > it cannot analyze the symbol and symbol offset with below command:
> >
> > ./perf script -v -a -F cpu,event,ip,sym,symoff -i ./perf.data -k vmlinux
> > --kallsyms ./System.map
> >
> > Have uploaded perf.data/vmlinux/System.map in the folder:
> > http://people.linaro.org/~leo.yan/binaries/perf_4.15_r4/
> >
> > Thanks,
> > Leo Yan
> >
> >> +     switch (elem->elem_type) {
> >> +     case OCSD_GEN_TRC_ELEM_UNKNOWN:
> >> +             break;
> >> +     case OCSD_GEN_TRC_ELEM_NO_SYNC:
> >> +             decoder->trace_on = false;
> >> +             break;
> >> +     case OCSD_GEN_TRC_ELEM_TRACE_ON:
> >> +             decoder->trace_on = true;
> >> +             break;
> >> +     case OCSD_GEN_TRC_ELEM_INSTR_RANGE:
> >> +             resp = cs_etm_decoder__buffer_packet(decoder, elem,
> >> +                                                  trace_chan_id,
> >> +                                                  CS_ETM_RANGE);
> >> +             break;
> >> +     case OCSD_GEN_TRC_ELEM_EXCEPTION:
> >> +             decoder->packet_buffer[decoder->tail].exc = true;
> >> +             break;
> >> +     case OCSD_GEN_TRC_ELEM_EXCEPTION_RET:
> >> +             decoder->packet_buffer[decoder->tail].exc_ret = true;
> >> +             break;
> >> +     case OCSD_GEN_TRC_ELEM_PE_CONTEXT:
> >> +     case OCSD_GEN_TRC_ELEM_EO_TRACE:
> >> +     case OCSD_GEN_TRC_ELEM_ADDR_NACC:
> >> +     case OCSD_GEN_TRC_ELEM_TIMESTAMP:
> >> +     case OCSD_GEN_TRC_ELEM_CYCLE_COUNT:
> >> +     case OCSD_GEN_TRC_ELEM_ADDR_UNKNOWN:
> >> +     case OCSD_GEN_TRC_ELEM_EVENT:
> >> +     case OCSD_GEN_TRC_ELEM_SWTRACE:
> >> +     case OCSD_GEN_TRC_ELEM_CUSTOM:
> >> +     default:
> >> +             break;
> >> +     }
> >> +
> >> +     return resp;
> >> +}
> >> +
> >> +static int cs_etm_decoder__create_etm_packet_decoder(
> >> +                                     struct cs_etm_trace_params *t_params,
> >> +                                     struct cs_etm_decoder *decoder)
> >> +{
> >> +     const char *decoder_name;
> >> +     ocsd_etmv4_cfg trace_config_etmv4;
> >> +     void *trace_config;
> >> +     u8 csid;
> >> +
> >> +     switch (t_params->protocol) {
> >> +     case CS_ETM_PROTO_ETMV4i:
> >> +             cs_etm_decoder__gen_etmv4_config(t_params, &trace_config_etmv4);
> >> +             decoder_name = OCSD_BUILTIN_DCD_ETMV4I;
> >> +             trace_config = &trace_config_etmv4;
> >> +             break;
> >> +     default:
> >> +             return -1;
> >> +     }
> >> +
> >> +     if (ocsd_dt_create_decoder(decoder->dcd_tree,
> >> +                                  decoder_name,
> >> +                                  OCSD_CREATE_FLG_FULL_DECODER,
> >> +                                  trace_config, &csid))
> >> +             return -1;
> >> +
> >> +     if (ocsd_dt_set_gen_elem_outfn(decoder->dcd_tree,
> >> +                                    cs_etm_decoder__gen_trace_elem_printer,
> >> +                                    decoder))
> >> +             return -1;
> >> +
> >> +     return 0;
> >> +}
> >> +
> >>  static int
> >>  cs_etm_decoder__create_etm_decoder(struct cs_etm_decoder_params *d_params,
> >>                                  struct cs_etm_trace_params *t_params,
> >> @@ -208,6 +323,10 @@ cs_etm_decoder__create_etm_decoder(struct cs_etm_decoder_params *d_params,
> >>       if (d_params->operation == CS_ETM_OPERATION_PRINT)
> >>               return cs_etm_decoder__create_etm_packet_printer(t_params,
> >>                                                                decoder);
> >> +     else if (d_params->operation == CS_ETM_OPERATION_DECODE)
> >> +             return cs_etm_decoder__create_etm_packet_decoder(t_params,
> >> +                                                              decoder);
> >> +
> >>       return -1;
> >>  }
> >>
> >> --
> >> 2.7.4
> >>
> >
> > _______________________________________________
> > linux-arm-kernel mailing list
> > linux-arm-kernel at lists.infradead.org
> > http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
> 
> 
> 
> -- 
> Mike Leach
> Principal Engineer, ARM Ltd.
> Blackburn Design Centre. UK

^ permalink raw reply

* [PATCH 3/3] pinctrl: qcom: Don't allow protected pins to be requested
From: Bjorn Andersson @ 2018-01-10  6:11 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20180110015848.11480-4-sboyd@codeaurora.org>

On Tue 09 Jan 17:58 PST 2018, Stephen Boyd wrote:

I like it, a few comment below though.

> +static int msm_gpio_init_irq_valid_mask(struct gpio_chip *chip,
> +					struct msm_pinctrl *pctrl)
> +{
> +	int ret;
> +	unsigned int len, i;
> +	unsigned int max_gpios = pctrl->soc->ngpios;
> +	struct device_node *np = pctrl->dev->of_node;
> +
> +	/* The number of GPIOs in the ACPI tables */
> +	ret = device_property_read_u16_array(pctrl->dev, "gpios", NULL, 0);
> +	if (ret > 0 && ret < max_gpios) {
> +		u16 *tmp;
> +
> +		len = ret;
> +		tmp = kmalloc_array(len, sizeof(tmp[0]), GFP_KERNEL);
> +		if (!tmp)
> +			return -ENOMEM;
> +
> +		ret = device_property_read_u16_array(pctrl->dev, "gpios", tmp,
> +						     len);
> +		if (ret < 0) {
> +			dev_err(pctrl->dev, "could not read list of GPIOs\n");
> +			kfree(tmp);
> +			return ret;
> +		}
> +
> +		bitmap_zero(chip->irq_valid_mask, max_gpios);

The valid_mask is moving into the gpio_irq_chip, so this should be
chip->irq.valid_mask.

See dc7b0387ee89 ("gpio: Move irq_valid_mask into struct gpio_irq_chip")

> +		for (i = 0; i < len; i++)
> +			set_bit(tmp[i], chip->irq_valid_mask);
> +

You're leaking tmp here.

> +		return 0;
> +	}
> +
> +	/* If there's a DT ngpios-ranges property then add those ranges */
> +	ret = of_property_count_u32_elems(np,  "ngpios-ranges");
> +	if (ret > 0 && ret % 2 == 0 && ret / 2 < max_gpios) {
> +		u32 start;
> +		u32 count;
> +
> +		len = ret / 2;
> +		bitmap_zero(chip->irq_valid_mask, max_gpios);
> +
> +		for (i = 0; i < len; i++) {

If you take steps of 2, when looping from 0 to ret, your loop index will
have the value that you're passing as index into the read - without
duplicating it.

> +			of_property_read_u32_index(np, "ngpios-ranges",
> +						   i * 2, &start);
> +			of_property_read_u32_index(np, "ngpios-ranges",
> +						   i * 2 + 1, &count);
> +			bitmap_set(chip->irq_valid_mask, start, count);
> +		}
> +	}
> +
> +	return 0;
> +}
[..]
> @@ -824,6 +907,7 @@ static int msm_gpio_init(struct msm_pinctrl *pctrl)
>  	chip->parent = pctrl->dev;
>  	chip->owner = THIS_MODULE;
>  	chip->of_node = pctrl->dev->of_node;
> +	chip->irq_need_valid_mask = msm_gpio_needs_irq_valid_mask(pctrl);

chip->irq.need_valid_mask

>  
>  	ret = gpiochip_add_data(&pctrl->chip, pctrl);
>  	if (ret) {
> @@ -831,6 +915,12 @@ static int msm_gpio_init(struct msm_pinctrl *pctrl)
>  		return ret;
>  	}
>  
> +	ret = msm_gpio_init_irq_valid_mask(chip, pctrl);
> +	if (ret) {
> +		dev_err(pctrl->dev, "Failed to setup irq valid bits\n");

gpiochip_remove() here, to release resources allocated by
gpiochip_add_data.

> +		return ret;
> +	}
> +
>  	ret = gpiochip_add_pin_range(&pctrl->chip, dev_name(pctrl->dev), 0, 0, chip->ngpio);
>  	if (ret) {
>  		dev_err(pctrl->dev, "Failed to add pin range\n");

Regards,
Bjorn

^ permalink raw reply

* [PATCH 1/3] gpiolib: Export gpiochip_irqchip_irq_valid() to drivers
From: Bjorn Andersson @ 2018-01-10  6:16 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20180110015848.11480-2-sboyd@codeaurora.org>

On Tue 09 Jan 17:58 PST 2018, Stephen Boyd wrote:

> Some pinctrl drivers can use the gpiochip irq valid information
> to figure out if certain gpios are exposed to the kernel for
> usage or not. Expose this API so we can use it in the
> pinmux_ops::request ops.
> 
> Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>

Acked-by: Bjorn Andersson <bjorn.andersson@linaro.org>

Regards,
Bjorn

> ---
>  drivers/gpio/gpiolib.c      | 5 +++--
>  include/linux/gpio/driver.h | 3 +++
>  2 files changed, 6 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c
> index b80936a25caa..c18b7b60ea1d 100644
> --- a/drivers/gpio/gpiolib.c
> +++ b/drivers/gpio/gpiolib.c
> @@ -1503,14 +1503,15 @@ static void gpiochip_irqchip_free_valid_mask(struct gpio_chip *gpiochip)
>  	gpiochip->irq.valid_mask = NULL;
>  }
>  
> -static bool gpiochip_irqchip_irq_valid(const struct gpio_chip *gpiochip,
> -				       unsigned int offset)
> +bool gpiochip_irqchip_irq_valid(const struct gpio_chip *gpiochip,
> +				unsigned int offset)
>  {
>  	/* No mask means all valid */
>  	if (likely(!gpiochip->irq.valid_mask))
>  		return true;
>  	return test_bit(offset, gpiochip->irq.valid_mask);
>  }
> +EXPORT_SYMBOL_GPL(gpiochip_irqchip_irq_valid);
>  
>  /**
>   * gpiochip_set_cascaded_irqchip() - connects a cascaded irqchip to a gpiochip
> diff --git a/include/linux/gpio/driver.h b/include/linux/gpio/driver.h
> index 7258cd676df4..1ba9a331ec51 100644
> --- a/include/linux/gpio/driver.h
> +++ b/include/linux/gpio/driver.h
> @@ -436,6 +436,9 @@ int gpiochip_irqchip_add_key(struct gpio_chip *gpiochip,
>  			     struct lock_class_key *lock_key,
>  			     struct lock_class_key *request_key);
>  
> +bool gpiochip_irqchip_irq_valid(const struct gpio_chip *gpiochip,
> +				unsigned int offset);
> +
>  #ifdef CONFIG_LOCKDEP
>  
>  /*
> -- 
> The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
> a Linux Foundation Collaborative Project
> 

^ permalink raw reply

* [PATCH v2] iommu/exynos: Don't unconditionally steal bus ops
From: Marek Szyprowski @ 2018-01-10  6:27 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <da24d31fc6f4be7b44ceef215f672c0ed3c37979.1515511941.git.robin.murphy@arm.com>

Hi Robin,

On 2018-01-09 16:34, Robin Murphy wrote:
> Removing the early device registration hook overlooked the fact that
> it only ran conditionally on a compatible device being present in the
> DT. With exynos_iommu_init() now running as an unconditional initcall,
> problems arise on non-Exynos systems when other IOMMU drivers find
> themselves unable to install their ops on the platform bus, or at worst
> the Exynos ops get called with someone else's domain and all hell breaks
> loose.
>
> The global ops/cache setup could probably all now be triggered from the
> first IOMMU probe, as with dma_dev assigment, but for the time being the
> simplest fix is to resurrect the logic from commit a7b67cd5d9af
> ("iommu/exynos: Play nice in multi-platform builds") to explicitly check
> the DT for the presence of an Exynos IOMMU before trying anything.
>
> Fixes: 928055a01b3f ("iommu/exynos: Remove custom platform device registration code")
> Signed-off-by: Robin Murphy <robin.murphy@arm.com>

Acked-by: Marek Szyprowski <m.szyprowski@samsung.com>

> ---
>
> v2: Use the simpler explicit DT check.
>
>   drivers/iommu/exynos-iommu.c | 7 +++++++
>   1 file changed, 7 insertions(+)
>
> diff --git a/drivers/iommu/exynos-iommu.c b/drivers/iommu/exynos-iommu.c
> index 79c45650f8de..736d4552d96f 100644
> --- a/drivers/iommu/exynos-iommu.c
> +++ b/drivers/iommu/exynos-iommu.c
> @@ -1353,8 +1353,15 @@ static const struct iommu_ops exynos_iommu_ops = {
>   
>   static int __init exynos_iommu_init(void)
>   {
> +	struct device_node *np;
>   	int ret;
>   
> +	np = of_find_matching_node(NULL, sysmmu_of_match);
> +	if (!np)
> +		return 0;
> +
> +	of_node_put(np);
> +
>   	lv2table_kmem_cache = kmem_cache_create("exynos-iommu-lv2table",
>   				LV2TABLE_SIZE, LV2TABLE_SIZE, 0, NULL);
>   	if (!lv2table_kmem_cache) {

Best regards
-- 
Marek Szyprowski, PhD
Samsung R&D Institute Poland

^ permalink raw reply

* [PATCH 0/2] pinctrl: meson: use one uniform 'function' name
From: Jerome Brunet @ 2018-01-10  7:28 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <a6a4ed23-696c-ae2d-9b6a-c2578372b1aa@amlogic.com>

On Wed, 2018-01-10 at 10:12 +0800, Yixun Lan wrote:
> 
> On 01/08/18 16:52, Jerome Brunet wrote:
> > On Mon, 2018-01-08 at 15:33 +0800, Yixun Lan wrote:
> > > These two patches are general improvement for meson pinctrl driver.
> > > It make the two pinctrl trees (ee/ao) to share one uniform 'function' name for
> > > one hardware block even its pin groups live inside two differet hardware domains,
> > > which for example EE vs AO domain here.
> > > 
> > > This idea is motivated by Martin's question at [1]
> > > 
> > > [1]
> > >  http://lkml.kernel.org/r/CAFBinCCuQ-NK747+GHDkhZty_UMMgzCYOYFcNTrRDJgU8OM=Gw at mail.gmail.com
> > > 
> > > 
> > > Yixun Lan (2):
> > >   pinctrl: meson: introduce a macro to have name/groups seperated
> > >   pinctrl: meson-axg: correct the pin expansion of UART_AO_B
> > > 
> > >  drivers/pinctrl/meson/pinctrl-meson-axg.c | 4 ++--
> > >  drivers/pinctrl/meson/pinctrl-meson.h     | 8 +++++---
> > >  2 files changed, 7 insertions(+), 5 deletions(-)
> > 
> > Hi Yixun,
> > 
> > Honestly, I don't like the idea. I think it adds an unnecessary complexity.
> > I don't see the point of FUNCTION_EX(uart_ao_b, _z) when you could simply write 
> > FUNCTION(uart_ao_b_z) ... especially when there is just a couple of function per
> > SoC available on different domains.
> > 
> > A pinctrl driver can already be challenging to understand at first, let's keep
> > it simple and avoid adding more macros.
> > 
> 
> Hi Jerome?
>   In my opinion, the idea of keeping one uniform 'function' in DT (thus
> introducing another macro) is worth considering. It would make the DT
> part much clean.

Ok this is your opinion. I don't share it. Keeping function names tidy is good,
I don't think we need another macro to do so.

>   And yes, it's a trade-off here, either we 1) do more in code to make
> DT clean or 2) do nothing in the code level to make DT live with it.

I don't see how adding a macro doing just string concatenation is going to make
anything more clean. It does not prevent one to write FUNCTION_EX(uart_ao_b,
_gpioz), resulting in uart_ao_b_gpioz, which is what is apparently considered
'not clean'

BTW, there no cleanness issue here, the name is just out of the 'usual scheme'
but there is no problem with. If you want to change this, and
s/uart_ao_b_gpioz/uart_ao_b_z/, now is the time to change it. 

> 
> Yixun
> --
> To unsubscribe from this list: send the line "unsubscribe linux-gpio" in
> the body of a message to majordomo at vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* [PATCH v2 0/2] phy: rockchip-emmc: fixes emmc-phy power on failed with rk3399 SoCs
From: Caesar Wang @ 2018-01-10  7:37 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Kishon,

Since the Shawn isn't available, I take over this series patches for now.

As the original bug had tracked on https://issuetracker.google.com/71561742.
In some cases, the mmc phy power on failed during booting up.
The log as below:
...
[   2.375333] rockchip_emmc_phy_power: caldone timeout.
[    2.377815] phy phy-ff770000.syscon:phy at f780.4: phy poweron failed --> -110
...
[    2.489295] mmc0: mmc_select_hs400es failed, error -110
[    2.489302] mmc0: error -110 whilst initialising MMC card
..

The actual emulate, the wait 5us for calpad busy trimming, that's no enough.
We need give the enough margin for it.

Verified on url =
        https://chromium.googlesource.com/chromiumos/third_party/kernel/+/chromeos-4.4
This series patches can apply and bring up with kernel-next on rk3399 chromebook.

-Caesar


Changes in v2:
- print the return valut with regmap_read_poll_timeout failing.
- As Brian commented on https://patchwork.kernel.org/patch/10139891/,
  changed the note and added to print error value with
  regmap_read_poll_timeout API.

Shawn Lin (2):
  phy: rockchip-emmc: retry calpad busy trimming
  phy: rockchip-emmc: use regmap_read_poll_timeout to poll dllrdy

 drivers/phy/rockchip/phy-rockchip-emmc.c | 60 +++++++++++++++-----------------
 1 file changed, 28 insertions(+), 32 deletions(-)

-- 
2.7.4

^ permalink raw reply

* [PATCH v2 1/2] phy: rockchip-emmc: retry calpad busy trimming
From: Caesar Wang @ 2018-01-10  7:37 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1515569879-31808-1-git-send-email-wxt@rock-chips.com>

From: Shawn Lin <shawn.lin@rock-chips.com>

It turns out that 5us isn't enough for all cases, so let's
retry some more times to wait for caldone.

Signed-off-by: Shawn Lin <shawn.lin@rock-chips.com>
Tested-by: Ziyuan Xu <xzy.xu@rock-chips.com>
Signed-off-by: Caesar Wang <wxt@rock-chips.com>
---

Changes in v2:
- print the return valut with regmap_read_poll_timeout failing.

 drivers/phy/rockchip/phy-rockchip-emmc.c | 27 +++++++++++++++++----------
 1 file changed, 17 insertions(+), 10 deletions(-)

diff --git a/drivers/phy/rockchip/phy-rockchip-emmc.c b/drivers/phy/rockchip/phy-rockchip-emmc.c
index f1b24f1..574838f 100644
--- a/drivers/phy/rockchip/phy-rockchip-emmc.c
+++ b/drivers/phy/rockchip/phy-rockchip-emmc.c
@@ -76,6 +76,10 @@
 #define PHYCTRL_OTAPDLYSEL_MASK		0xf
 #define PHYCTRL_OTAPDLYSEL_SHIFT	0x7
 
+#define PHYCTRL_IS_CALDONE(x) \
+	((((x) >> PHYCTRL_CALDONE_SHIFT) & \
+	  PHYCTRL_CALDONE_MASK) == PHYCTRL_CALDONE_DONE)
+
 struct rockchip_emmc_phy {
 	unsigned int	reg_offset;
 	struct regmap	*reg_base;
@@ -90,6 +94,7 @@ static int rockchip_emmc_phy_power(struct phy *phy, bool on_off)
 	unsigned int freqsel = PHYCTRL_FREQSEL_200M;
 	unsigned long rate;
 	unsigned long timeout;
+	int ret;
 
 	/*
 	 * Keep phyctrl_pdb and phyctrl_endll low to allow
@@ -160,17 +165,19 @@ static int rockchip_emmc_phy_power(struct phy *phy, bool on_off)
 				   PHYCTRL_PDB_SHIFT));
 
 	/*
-	 * According to the user manual, it asks driver to
-	 * wait 5us for calpad busy trimming
+	 * According to the user manual, it asks driver to wait 5us for
+	 * calpad busy trimming. However it is documented that this value is
+	 * PVT(A.K.A process,voltage and temperature) relevant, so some
+	 * failure cases are found which indicates we should be more tolerant
+	 * to calpad busy trimming.
 	 */
-	udelay(5);
-	regmap_read(rk_phy->reg_base,
-		    rk_phy->reg_offset + GRF_EMMCPHY_STATUS,
-		    &caldone);
-	caldone = (caldone >> PHYCTRL_CALDONE_SHIFT) & PHYCTRL_CALDONE_MASK;
-	if (caldone != PHYCTRL_CALDONE_DONE) {
-		pr_err("rockchip_emmc_phy_power: caldone timeout.\n");
-		return -ETIMEDOUT;
+	ret = regmap_read_poll_timeout(rk_phy->reg_base,
+				       rk_phy->reg_offset + GRF_EMMCPHY_STATUS,
+				       caldone, PHYCTRL_IS_CALDONE(caldone),
+				       5, 50);
+	if (ret) {
+		pr_err("%s: caldone timeout, ret=%d\n", __func__, ret);
+		return ret;
 	}
 
 	/* Set the frequency of the DLL operation */
-- 
2.7.4

^ permalink raw reply related

* [PATCH v2 2/2] phy: rockchip-emmc: use regmap_read_poll_timeout to poll dllrdy
From: Caesar Wang @ 2018-01-10  7:37 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1515569879-31808-1-git-send-email-wxt@rock-chips.com>

From: Shawn Lin <shawn.lin@rock-chips.com>

Just use the API instead of open-coding it, no functional change
intended.

Signed-off-by: Shawn Lin <shawn.lin@rock-chips.com>
Reviewed-by: Brian Norris <briannorris@chromium.org>
Signed-off-by: Caesar Wang <wxt@rock-chips.com>

---

Changes in v2:
- As Brian commented on https://patchwork.kernel.org/patch/10139891/,
  changed the note and added to print error value with
  regmap_read_poll_timeout API.

 drivers/phy/rockchip/phy-rockchip-emmc.c | 33 +++++++++++---------------------
 1 file changed, 11 insertions(+), 22 deletions(-)

diff --git a/drivers/phy/rockchip/phy-rockchip-emmc.c b/drivers/phy/rockchip/phy-rockchip-emmc.c
index 574838f..343c623 100644
--- a/drivers/phy/rockchip/phy-rockchip-emmc.c
+++ b/drivers/phy/rockchip/phy-rockchip-emmc.c
@@ -79,6 +79,9 @@
 #define PHYCTRL_IS_CALDONE(x) \
 	((((x) >> PHYCTRL_CALDONE_SHIFT) & \
 	  PHYCTRL_CALDONE_MASK) == PHYCTRL_CALDONE_DONE)
+#define PHYCTRL_IS_DLLRDY(x) \
+	((((x) >> PHYCTRL_DLLRDY_SHIFT) & \
+	  PHYCTRL_DLLRDY_MASK) == PHYCTRL_DLLRDY_DONE)
 
 struct rockchip_emmc_phy {
 	unsigned int	reg_offset;
@@ -93,7 +96,6 @@ static int rockchip_emmc_phy_power(struct phy *phy, bool on_off)
 	unsigned int dllrdy;
 	unsigned int freqsel = PHYCTRL_FREQSEL_200M;
 	unsigned long rate;
-	unsigned long timeout;
 	int ret;
 
 	/*
@@ -217,28 +219,15 @@ static int rockchip_emmc_phy_power(struct phy *phy, bool on_off)
 	 * NOTE: There appear to be corner cases where the DLL seems to take
 	 * extra long to lock for reasons that aren't understood.  In some
 	 * extreme cases we've seen it take up to over 10ms (!).  We'll be
-	 * generous and give it 50ms.  We still busy wait here because:
-	 * - In most cases it should be super fast.
-	 * - This is not called lots during normal operation so it shouldn't
-	 *   be a power or performance problem to busy wait.  We expect it
-	 *   only at boot / resume.  In both cases, eMMC is probably on the
-	 *   critical path so busy waiting a little extra time should be OK.
+	 * generous and give it 50ms.
 	 */
-	timeout = jiffies + msecs_to_jiffies(50);
-	do {
-		udelay(1);
-
-		regmap_read(rk_phy->reg_base,
-			rk_phy->reg_offset + GRF_EMMCPHY_STATUS,
-			&dllrdy);
-		dllrdy = (dllrdy >> PHYCTRL_DLLRDY_SHIFT) & PHYCTRL_DLLRDY_MASK;
-		if (dllrdy == PHYCTRL_DLLRDY_DONE)
-			break;
-	} while (!time_after(jiffies, timeout));
-
-	if (dllrdy != PHYCTRL_DLLRDY_DONE) {
-		pr_err("rockchip_emmc_phy_power: dllrdy timeout.\n");
-		return -ETIMEDOUT;
+	ret = regmap_read_poll_timeout(rk_phy->reg_base,
+				       rk_phy->reg_offset + GRF_EMMCPHY_STATUS,
+				       dllrdy, PHYCTRL_IS_DLLRDY(dllrdy),
+				       1, 50 * USEC_PER_MSEC);
+	if (ret) {
+		pr_err("%s: dllrdy timeout. ret=%d\n", __func__, ret);
+		return ret;
 	}
 
 	return 0;
-- 
2.7.4

^ permalink raw reply related

* consolidate direct dma mapping V3
From: Christoph Hellwig @ 2018-01-10  7:59 UTC (permalink / raw)
  To: linux-arm-kernel

Almost every architecture supports a direct dma mapping implementation,
where no iommu is used and the device dma address is a 1:1 mapping to
the physical address or has a simple linear offset.  Currently the
code for this implementation is most duplicated over the architectures,
and the duplicated again in the swiotlb code, and then duplicated again
for special cases like the x86 memory encryption DMA ops.

This series takes the existing very simple dma-noop dma mapping
implementation, enhances it with all the x86 features and quirks, and
creates a common set of architecture hooks for it and the swiotlb code.

It then switches a number of architectures to this generic
direct map implemention.

Note that for now this only handles architectures that do cache coherent
DMA, but a similar consolidation for non-coherent architectures is in the
work for later merge windows.

A git tree is also available:

   git://git.infradead.org/users/hch/misc.git dma-direct.3

Gitweb:

   http://git.infradead.org/users/hch/misc.git/shortlog/refs/heads/dma-direct.3

Changes since V1:
 - fixed a few patch description typos
 - fixed a few printk formats
 - fixed an off by one in dma_coherent_ok
 - add a few Reviewed-by/Acked-by tags.
 - moved the swiotlb consolidation to a new series
 - dropped a few patches for now to not overwhelem the x86
   maintainers.  They will be resubmitted in the next merge window

^ permalink raw reply

* [PATCH 01/33] alpha: mark jensen as broken
From: Christoph Hellwig @ 2018-01-10  7:59 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20180110080027.13879-1-hch@lst.de>

CONFIG_ALPHA_JENSEN has failed to compile since commit 6aca0503
("alpha/dma: use common noop dma ops"), so mark it as broken.

Signed-off-by: Christoph Hellwig <hch@lst.de>
---
 arch/alpha/Kconfig | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/alpha/Kconfig b/arch/alpha/Kconfig
index b31b974a03cb..e96adcbcab41 100644
--- a/arch/alpha/Kconfig
+++ b/arch/alpha/Kconfig
@@ -209,6 +209,7 @@ config ALPHA_EIGER
 
 config ALPHA_JENSEN
 	bool "Jensen"
+	depends on BROKEN
 	help
 	  DEC PC 150 AXP (aka Jensen): This is a very old Digital system - one
 	  of the first-generation Alpha systems. A number of these systems
-- 
2.14.2

^ permalink raw reply related

* [PATCH 02/33] hexagon: remove unused flush_write_buffers definition
From: Christoph Hellwig @ 2018-01-10  7:59 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20180110080027.13879-1-hch@lst.de>

Signed-off-by: Christoph Hellwig <hch@lst.de>
---
 arch/hexagon/include/asm/io.h | 2 --
 1 file changed, 2 deletions(-)

diff --git a/arch/hexagon/include/asm/io.h b/arch/hexagon/include/asm/io.h
index 66f5e9a61efc..9e8621d94ee9 100644
--- a/arch/hexagon/include/asm/io.h
+++ b/arch/hexagon/include/asm/io.h
@@ -330,8 +330,6 @@ static inline void outsl(unsigned long port, const void *buffer, int count)
 	}
 }
 
-#define flush_write_buffers() do { } while (0)
-
 #endif /* __KERNEL__ */
 
 #endif
-- 
2.14.2

^ permalink raw reply related

* [PATCH 03/33] m32r: remove unused flush_write_buffers definition
From: Christoph Hellwig @ 2018-01-10  7:59 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20180110080027.13879-1-hch@lst.de>

Signed-off-by: Christoph Hellwig <hch@lst.de>
---
 arch/m32r/include/asm/io.h | 2 --
 1 file changed, 2 deletions(-)

diff --git a/arch/m32r/include/asm/io.h b/arch/m32r/include/asm/io.h
index 1b653bb16f9a..a4272d8f0d9c 100644
--- a/arch/m32r/include/asm/io.h
+++ b/arch/m32r/include/asm/io.h
@@ -191,8 +191,6 @@ static inline void _writel(unsigned long l, unsigned long addr)
 
 #define mmiowb()
 
-#define flush_write_buffers() do { } while (0)  /* M32R_FIXME */
-
 static inline void
 memset_io(volatile void __iomem *addr, unsigned char val, int count)
 {
-- 
2.14.2

^ permalink raw reply related

* [PATCH 04/33] powerpc: remove unused flush_write_buffers definition
From: Christoph Hellwig @ 2018-01-10  7:59 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20180110080027.13879-1-hch@lst.de>

Signed-off-by: Christoph Hellwig <hch@lst.de>
---
 arch/powerpc/include/asm/dma-mapping.h | 3 ---
 1 file changed, 3 deletions(-)

diff --git a/arch/powerpc/include/asm/dma-mapping.h b/arch/powerpc/include/asm/dma-mapping.h
index 5a6cbe11db6f..592c7f418aa0 100644
--- a/arch/powerpc/include/asm/dma-mapping.h
+++ b/arch/powerpc/include/asm/dma-mapping.h
@@ -107,9 +107,6 @@ static inline void set_dma_offset(struct device *dev, dma_addr_t off)
 		dev->archdata.dma_offset = off;
 }
 
-/* this will be removed soon */
-#define flush_write_buffers()
-
 #define HAVE_ARCH_DMA_SET_MASK 1
 extern int dma_set_mask(struct device *dev, u64 dma_mask);
 
-- 
2.14.2

^ permalink raw reply related


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