* [v1, 0/1] gpio: dts: aspeed: Add SGPIO driver
From: Hongwei Zhang @ 2019-09-25 19:20 UTC (permalink / raw)
To: Linus Walleij, Andrew Jeffery, linux-gpio, Joel Stanley
Cc: Mark Rutland, devicetree, Arnd Bergmann, linux-aspeed,
Ard Biesheuvel, Masahiro Yamada, linux-kernel, Russell King,
Mike Rapoport, Bartosz Golaszewski, Rob Herring,
Benjamin Gaignard, Mauro Carvalho Chehab, Doug Anderson,
Andrew Morton, Hongwei Zhang, linux-arm-kernel
In-Reply-To: <1569351740-6285-1-git-send-email-hongweiz@ami.com>
>
> > The related SGPIO driver has been accepted and merged into v5.4:
> > _http://patchwork.ozlabs.org/patch/1150357/
>
> Oh what a mess, it didn't add the necessary code into Kconfig and Makefile, also names it sgpio-gpio.c
> when everything else is named gpio-sgpio.c.
>
> I guess I have to fix it up. My fault for missing.
>
> Linus Walleij
Thanks Linus,
It's not your fault, I misunderstood a earlier comment from another
reviewer and thought I should wait until the driver is accecpted,
and then submit the patch to include / enable it.
As Bart suggested, I splitte the patches.
Regarding the driver name, following the gpio-SoC_name.o convention
in the Makefile, we choose sgpio-aspeed.o .
--Hongwei
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* [v1, 1/1] gpio: dts: aspeed: Add SGPIO driver
From: Hongwei Zhang @ 2019-09-25 19:19 UTC (permalink / raw)
To: Bartosz Golaszewski, Linus Walleij, Andrew Jeffery, linux-gpio,
Joel Stanley
Cc: Mark Rutland, devicetree, Arnd Bergmann, linux-aspeed,
Ard Biesheuvel, linux-kernel, Russell King, Mike Rapoport,
Masahiro Yamada, Rob Herring, Benjamin Gaignard,
Mauro Carvalho Chehab, Doug Anderson, Andrew Morton,
Hongwei Zhang, linux-arm-kernel
In-Reply-To: <1569352021-6383-1-git-send-email-hongweiz@ami.com>
> > obj-$(CONFIG_GPIO_BD70528) += gpio-bd70528.o
> > --
> > 2.7.4
> >
>
> This should be split into separate patches with one extending the binding document and one adding
> actual support.
>
> Bart
Thanks Bart,
I just submitted splitted patches.
--Hongwei
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* [PATCH 2/2] soc: amlogic: ee-pwrc: ensure driver state maches HW state
From: Kevin Hilman @ 2019-09-25 19:12 UTC (permalink / raw)
To: linux-amlogic, Neil Armstrong; +Cc: linux-arm-kernel, linux-pm
In-Reply-To: <20190925191233.22253-1-khilman@baylibre.com>
During init, ensure that the driver on/off state as well as clock
state matches the hardware state by calling drivers on/off functions
based on whether the HW state is on/off.
Signed-off-by: Kevin Hilman <khilman@baylibre.com>
---
drivers/soc/amlogic/meson-ee-pwrc.c | 30 +++++++++--------------------
1 file changed, 9 insertions(+), 21 deletions(-)
diff --git a/drivers/soc/amlogic/meson-ee-pwrc.c b/drivers/soc/amlogic/meson-ee-pwrc.c
index dcce8e694a07..2cb5341aedfa 100644
--- a/drivers/soc/amlogic/meson-ee-pwrc.c
+++ b/drivers/soc/amlogic/meson-ee-pwrc.c
@@ -323,6 +323,8 @@ static int meson_ee_pwrc_init_domain(struct platform_device *pdev,
struct meson_ee_pwrc *pwrc,
struct meson_ee_pwrc_domain *dom)
{
+ bool is_off;
+
dom->pwrc = pwrc;
dom->num_rstc = dom->desc.reset_names_count;
dom->num_clks = dom->desc.clk_names_count;
@@ -356,27 +358,13 @@ static int meson_ee_pwrc_init_domain(struct platform_device *pdev,
dom->base.power_on = meson_ee_pwrc_on;
dom->base.power_off = meson_ee_pwrc_off;
- /*
- * TOFIX: This is a special case for the VPU power domain, which can
- * be enabled previously by the bootloader. In this case the VPU
- * pipeline may be functional but no driver maybe never attach
- * to this power domain, and if the domain is disabled it could
- * cause system errors. This is why the pm_domain_always_on_gov
- * is used here.
- * For the same reason, the clocks should be enabled in case
- * we need to power the domain off, otherwise the internal clocks
- * prepare/enable counters won't be in sync.
- */
- if (dom->num_clks && dom->desc.is_off && !dom->desc.is_off(dom)) {
- int ret = clk_bulk_prepare_enable(dom->num_clks, dom->clks);
- if (ret)
- return ret;
-
- pm_genpd_init(&dom->base, &pm_domain_always_on_gov, false);
- } else
- pm_genpd_init(&dom->base, NULL,
- (dom->desc.is_off ?
- dom->desc.is_off(dom) : true));
+ /* Ensure that driver state matches HW state */
+ is_off = dom->desc.is_off ? dom->desc.is_off(dom) : true;
+ if (is_off)
+ meson_ee_pwrc_off(&dom->base);
+ else
+ meson_ee_pwrc_on(&dom->base);
+ pm_genpd_init(&dom->base, NULL, is_off);
return 0;
}
--
2.22.0
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* [PATCH 1/2] soc: amlogic: ee-pwrc: rename get_power
From: Kevin Hilman @ 2019-09-25 19:12 UTC (permalink / raw)
To: linux-amlogic, Neil Armstrong; +Cc: linux-arm-kernel, linux-pm
In-Reply-To: <20190925191233.22253-1-khilman@baylibre.com>
The function named _get_power() is misleading since it returns true
if the power is off. Rename to _is_off() for better readability.
Signed-off-by: Kevin Hilman <khilman@baylibre.com>
---
drivers/soc/amlogic/meson-ee-pwrc.c | 34 ++++++++++++++---------------
1 file changed, 17 insertions(+), 17 deletions(-)
diff --git a/drivers/soc/amlogic/meson-ee-pwrc.c b/drivers/soc/amlogic/meson-ee-pwrc.c
index 5823f5b67d16..dcce8e694a07 100644
--- a/drivers/soc/amlogic/meson-ee-pwrc.c
+++ b/drivers/soc/amlogic/meson-ee-pwrc.c
@@ -56,7 +56,7 @@ struct meson_ee_pwrc_domain_desc {
struct meson_ee_pwrc_top_domain *top_pd;
unsigned int mem_pd_count;
struct meson_ee_pwrc_mem_domain *mem_pd;
- bool (*get_power)(struct meson_ee_pwrc_domain *pwrc_domain);
+ bool (*is_off)(struct meson_ee_pwrc_domain *pwrc_domain);
};
struct meson_ee_pwrc_domain_data {
@@ -173,7 +173,7 @@ static struct meson_ee_pwrc_mem_domain sm1_pwrc_mem_audio[] = {
{ HHI_AUDIO_MEM_PD_REG0, GENMASK(27, 26) },
};
-#define VPU_PD(__name, __top_pd, __mem, __get_power, __resets, __clks) \
+#define VPU_PD(__name, __top_pd, __mem, __is_off, __resets, __clks) \
{ \
.name = __name, \
.reset_names_count = __resets, \
@@ -181,40 +181,40 @@ static struct meson_ee_pwrc_mem_domain sm1_pwrc_mem_audio[] = {
.top_pd = __top_pd, \
.mem_pd_count = ARRAY_SIZE(__mem), \
.mem_pd = __mem, \
- .get_power = __get_power, \
+ .is_off = __is_off, \
}
-#define TOP_PD(__name, __top_pd, __mem, __get_power) \
+#define TOP_PD(__name, __top_pd, __mem, __is_off) \
{ \
.name = __name, \
.top_pd = __top_pd, \
.mem_pd_count = ARRAY_SIZE(__mem), \
.mem_pd = __mem, \
- .get_power = __get_power, \
+ .is_off = __is_off, \
}
#define MEM_PD(__name, __mem) \
TOP_PD(__name, NULL, __mem, NULL)
-static bool pwrc_ee_get_power(struct meson_ee_pwrc_domain *pwrc_domain);
+static bool pwrc_ee_is_off(struct meson_ee_pwrc_domain *pwrc_domain);
static struct meson_ee_pwrc_domain_desc g12a_pwrc_domains[] = {
[PWRC_G12A_VPU_ID] = VPU_PD("VPU", &g12a_pwrc_vpu, g12a_pwrc_mem_vpu,
- pwrc_ee_get_power, 11, 2),
+ pwrc_ee_is_off, 11, 2),
[PWRC_G12A_ETH_ID] = MEM_PD("ETH", g12a_pwrc_mem_eth),
};
static struct meson_ee_pwrc_domain_desc sm1_pwrc_domains[] = {
[PWRC_SM1_VPU_ID] = VPU_PD("VPU", &sm1_pwrc_vpu, sm1_pwrc_mem_vpu,
- pwrc_ee_get_power, 11, 2),
+ pwrc_ee_is_off, 11, 2),
[PWRC_SM1_NNA_ID] = TOP_PD("NNA", &sm1_pwrc_nna, sm1_pwrc_mem_nna,
- pwrc_ee_get_power),
+ pwrc_ee_is_off),
[PWRC_SM1_USB_ID] = TOP_PD("USB", &sm1_pwrc_usb, sm1_pwrc_mem_usb,
- pwrc_ee_get_power),
+ pwrc_ee_is_off),
[PWRC_SM1_PCIE_ID] = TOP_PD("PCI", &sm1_pwrc_pci, sm1_pwrc_mem_pcie,
- pwrc_ee_get_power),
+ pwrc_ee_is_off),
[PWRC_SM1_GE2D_ID] = TOP_PD("GE2D", &sm1_pwrc_ge2d, sm1_pwrc_mem_ge2d,
- pwrc_ee_get_power),
+ pwrc_ee_is_off),
[PWRC_SM1_AUDIO_ID] = MEM_PD("AUDIO", sm1_pwrc_mem_audio),
[PWRC_SM1_ETH_ID] = MEM_PD("ETH", g12a_pwrc_mem_eth),
};
@@ -237,7 +237,7 @@ struct meson_ee_pwrc {
struct genpd_onecell_data xlate;
};
-static bool pwrc_ee_get_power(struct meson_ee_pwrc_domain *pwrc_domain)
+static bool pwrc_ee_is_off(struct meson_ee_pwrc_domain *pwrc_domain)
{
u32 reg;
@@ -367,7 +367,7 @@ static int meson_ee_pwrc_init_domain(struct platform_device *pdev,
* we need to power the domain off, otherwise the internal clocks
* prepare/enable counters won't be in sync.
*/
- if (dom->num_clks && dom->desc.get_power && !dom->desc.get_power(dom)) {
+ if (dom->num_clks && dom->desc.is_off && !dom->desc.is_off(dom)) {
int ret = clk_bulk_prepare_enable(dom->num_clks, dom->clks);
if (ret)
return ret;
@@ -375,8 +375,8 @@ static int meson_ee_pwrc_init_domain(struct platform_device *pdev,
pm_genpd_init(&dom->base, &pm_domain_always_on_gov, false);
} else
pm_genpd_init(&dom->base, NULL,
- (dom->desc.get_power ?
- dom->desc.get_power(dom) : true));
+ (dom->desc.is_off ?
+ dom->desc.is_off(dom) : true));
return 0;
}
@@ -454,7 +454,7 @@ static void meson_ee_pwrc_shutdown(struct platform_device *pdev)
for (i = 0 ; i < pwrc->xlate.num_domains ; ++i) {
struct meson_ee_pwrc_domain *dom = &pwrc->domains[i];
- if (dom->desc.get_power && !dom->desc.get_power(dom))
+ if (dom->desc.is_off && !dom->desc.is_off(dom))
meson_ee_pwrc_off(&dom->base);
}
}
--
2.22.0
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* [PATCH 0/2] soc: amlogic: ee-pwrc: cleanup init state
From: Kevin Hilman @ 2019-09-25 19:12 UTC (permalink / raw)
To: linux-amlogic, Neil Armstrong; +Cc: linux-arm-kernel, linux-pm
Cleanup the PM domain init state and ensure that the driver state
matches the HW state for all domains.
Tested on meson-sm1-sei610.
Kevin Hilman (2):
soc: amlogic: ee-pwrc: rename get_power
soc: amlogic: ee-pwrc: ensure driver state maches HW state
drivers/soc/amlogic/meson-ee-pwrc.c | 58 ++++++++++++-----------------
1 file changed, 23 insertions(+), 35 deletions(-)
--
2.22.0
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* [PATCH 2/2] nvmem: add Rockchip OTP driver
From: Heiko Stuebner @ 2019-09-25 18:49 UTC (permalink / raw)
To: srinivas.kandagatla
Cc: mark.rutland, devicetree, Heiko Stuebner, linux-kernel,
linux-rockchip, robh+dt, Finley Xiao, linux-arm-kernel,
christoph.muellner
In-Reply-To: <20190925184957.14338-1-heiko@sntech.de>
From: Finley Xiao <finley.xiao@rock-chips.com>
Newer Rockchip socs like the px30 use a different one-time-programmable
memory controller for things like cpu-id and leakage information,
so add the necessary driver for it.
Signed-off-by: Finley Xiao <finley.xiao@rock-chips.com>
[ported from vendor 4.4, converted to clock-bulk API and cleanups]
Signed-off-by: Heiko Stuebner <heiko@sntech.de>
---
drivers/nvmem/Kconfig | 11 ++
drivers/nvmem/Makefile | 2 +
drivers/nvmem/rockchip-otp.c | 268 +++++++++++++++++++++++++++++++++++
3 files changed, 281 insertions(+)
create mode 100644 drivers/nvmem/rockchip-otp.c
diff --git a/drivers/nvmem/Kconfig b/drivers/nvmem/Kconfig
index c2ec750cae6e..80b7e5d9c448 100644
--- a/drivers/nvmem/Kconfig
+++ b/drivers/nvmem/Kconfig
@@ -119,6 +119,17 @@ config ROCKCHIP_EFUSE
This driver can also be built as a module. If so, the module
will be called nvmem_rockchip_efuse.
+config ROCKCHIP_OTP
+ tristate "Rockchip OTP controller support"
+ depends on ARCH_ROCKCHIP || COMPILE_TEST
+ depends on HAS_IOMEM
+ help
+ This is a simple drive to dump specified values of Rockchip SoC
+ from otp, such as cpu-leakage.
+
+ This driver can also be built as a module. If so, the module
+ will be called nvmem_rockchip_otp.
+
config NVMEM_BCM_OCOTP
tristate "Broadcom On-Chip OTP Controller support"
depends on ARCH_BCM_IPROC || COMPILE_TEST
diff --git a/drivers/nvmem/Makefile b/drivers/nvmem/Makefile
index e5c153d99a67..bbdbb929470f 100644
--- a/drivers/nvmem/Makefile
+++ b/drivers/nvmem/Makefile
@@ -30,6 +30,8 @@ obj-$(CONFIG_QCOM_QFPROM) += nvmem_qfprom.o
nvmem_qfprom-y := qfprom.o
obj-$(CONFIG_ROCKCHIP_EFUSE) += nvmem_rockchip_efuse.o
nvmem_rockchip_efuse-y := rockchip-efuse.o
+obj-$(CONFIG_ROCKCHIP_OTP) += nvmem-rockchip-otp.o
+nvmem-rockchip-otp-y := rockchip-otp.o
obj-$(CONFIG_NVMEM_SUNXI_SID) += nvmem_sunxi_sid.o
nvmem_stm32_romem-y := stm32-romem.o
obj-$(CONFIG_NVMEM_STM32_ROMEM) += nvmem_stm32_romem.o
diff --git a/drivers/nvmem/rockchip-otp.c b/drivers/nvmem/rockchip-otp.c
new file mode 100644
index 000000000000..9f53bcce2f87
--- /dev/null
+++ b/drivers/nvmem/rockchip-otp.c
@@ -0,0 +1,268 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Rockchip OTP Driver
+ *
+ * Copyright (c) 2018 Rockchip Electronics Co. Ltd.
+ * Author: Finley Xiao <finley.xiao@rock-chips.com>
+ */
+
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/io.h>
+#include <linux/iopoll.h>
+#include <linux/module.h>
+#include <linux/nvmem-provider.h>
+#include <linux/reset.h>
+#include <linux/slab.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+
+/* OTP Register Offsets */
+#define OTPC_SBPI_CTRL 0x0020
+#define OTPC_SBPI_CMD_VALID_PRE 0x0024
+#define OTPC_SBPI_CS_VALID_PRE 0x0028
+#define OTPC_SBPI_STATUS 0x002C
+#define OTPC_USER_CTRL 0x0100
+#define OTPC_USER_ADDR 0x0104
+#define OTPC_USER_ENABLE 0x0108
+#define OTPC_USER_Q 0x0124
+#define OTPC_INT_STATUS 0x0304
+#define OTPC_SBPI_CMD0_OFFSET 0x1000
+#define OTPC_SBPI_CMD1_OFFSET 0x1004
+
+/* OTP Register bits and masks */
+#define OTPC_USER_ADDR_MASK GENMASK(31, 16)
+#define OTPC_USE_USER BIT(0)
+#define OTPC_USE_USER_MASK GENMASK(16, 16)
+#define OTPC_USER_FSM_ENABLE BIT(0)
+#define OTPC_USER_FSM_ENABLE_MASK GENMASK(16, 16)
+#define OTPC_SBPI_DONE BIT(1)
+#define OTPC_USER_DONE BIT(2)
+
+#define SBPI_DAP_ADDR 0x02
+#define SBPI_DAP_ADDR_SHIFT 8
+#define SBPI_DAP_ADDR_MASK GENMASK(31, 24)
+#define SBPI_CMD_VALID_MASK GENMASK(31, 16)
+#define SBPI_DAP_CMD_WRF 0xC0
+#define SBPI_DAP_REG_ECC 0x3A
+#define SBPI_ECC_ENABLE 0x00
+#define SBPI_ECC_DISABLE 0x09
+#define SBPI_ENABLE BIT(0)
+#define SBPI_ENABLE_MASK GENMASK(16, 16)
+
+#define OTPC_TIMEOUT 10000
+
+struct rockchip_otp {
+ struct device *dev;
+ void __iomem *base;
+ struct clk_bulk_data *clks;
+ int num_clks;
+ struct reset_control *rst;
+};
+
+/* list of required clocks */
+static const char * const rockchip_otp_clocks[] = {
+ "otp", "apb_pclk", "phy",
+};
+
+struct rockchip_data {
+ int size;
+};
+
+static int rockchip_otp_reset(struct rockchip_otp *otp)
+{
+ int ret;
+
+ ret = reset_control_assert(otp->rst);
+ if (ret) {
+ dev_err(otp->dev, "failed to assert otp phy %d\n", ret);
+ return ret;
+ }
+
+ udelay(2);
+
+ ret = reset_control_deassert(otp->rst);
+ if (ret) {
+ dev_err(otp->dev, "failed to deassert otp phy %d\n", ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+static int rockchip_otp_wait_status(struct rockchip_otp *otp, u32 flag)
+{
+ u32 status = 0;
+ int ret;
+
+ ret = readl_poll_timeout_atomic(otp->base + OTPC_INT_STATUS, status,
+ (status & flag), 1, OTPC_TIMEOUT);
+ if (ret)
+ return ret;
+
+ /* clean int status */
+ writel(flag, otp->base + OTPC_INT_STATUS);
+
+ return 0;
+}
+
+static int rockchip_otp_ecc_enable(struct rockchip_otp *otp, bool enable)
+{
+ int ret = 0;
+
+ writel(SBPI_DAP_ADDR_MASK | (SBPI_DAP_ADDR << SBPI_DAP_ADDR_SHIFT),
+ otp->base + OTPC_SBPI_CTRL);
+
+ writel(SBPI_CMD_VALID_MASK | 0x1, otp->base + OTPC_SBPI_CMD_VALID_PRE);
+ writel(SBPI_DAP_CMD_WRF | SBPI_DAP_REG_ECC,
+ otp->base + OTPC_SBPI_CMD0_OFFSET);
+ if (enable)
+ writel(SBPI_ECC_ENABLE, otp->base + OTPC_SBPI_CMD1_OFFSET);
+ else
+ writel(SBPI_ECC_DISABLE, otp->base + OTPC_SBPI_CMD1_OFFSET);
+
+ writel(SBPI_ENABLE_MASK | SBPI_ENABLE, otp->base + OTPC_SBPI_CTRL);
+
+ ret = rockchip_otp_wait_status(otp, OTPC_SBPI_DONE);
+ if (ret < 0)
+ dev_err(otp->dev, "timeout during ecc_enable\n");
+
+ return ret;
+}
+
+static int rockchip_otp_read(void *context, unsigned int offset,
+ void *val, size_t bytes)
+{
+ struct rockchip_otp *otp = context;
+ u8 *buf = val;
+ int ret = 0;
+
+ ret = clk_bulk_prepare_enable(otp->num_clks, otp->clks);
+ if (ret < 0) {
+ dev_err(otp->dev, "failed to prepare/enable clks\n");
+ return ret;
+ }
+
+ ret = rockchip_otp_reset(otp);
+ if (ret) {
+ dev_err(otp->dev, "failed to reset otp phy\n");
+ goto disable_clks;
+ }
+
+ ret = rockchip_otp_ecc_enable(otp, false);
+ if (ret < 0) {
+ dev_err(otp->dev, "rockchip_otp_ecc_enable err\n");
+ goto disable_clks;
+ }
+
+ writel(OTPC_USE_USER | OTPC_USE_USER_MASK, otp->base + OTPC_USER_CTRL);
+ udelay(5);
+ while (bytes--) {
+ writel(offset++ | OTPC_USER_ADDR_MASK,
+ otp->base + OTPC_USER_ADDR);
+ writel(OTPC_USER_FSM_ENABLE | OTPC_USER_FSM_ENABLE_MASK,
+ otp->base + OTPC_USER_ENABLE);
+ ret = rockchip_otp_wait_status(otp, OTPC_USER_DONE);
+ if (ret < 0) {
+ dev_err(otp->dev, "timeout during read setup\n");
+ goto read_end;
+ }
+ *buf++ = readb(otp->base + OTPC_USER_Q);
+ }
+
+read_end:
+ writel(0x0 | OTPC_USE_USER_MASK, otp->base + OTPC_USER_CTRL);
+disable_clks:
+ clk_bulk_disable_unprepare(otp->num_clks, otp->clks);
+
+ return ret;
+}
+
+static struct nvmem_config otp_config = {
+ .name = "rockchip-otp",
+ .owner = THIS_MODULE,
+ .read_only = true,
+ .stride = 1,
+ .word_size = 1,
+ .reg_read = rockchip_otp_read,
+};
+
+static const struct rockchip_data px30_data = {
+ .size = 0x40,
+};
+
+static const struct of_device_id rockchip_otp_match[] = {
+ {
+ .compatible = "rockchip,px30-otp",
+ .data = (void *)&px30_data,
+ },
+ {
+ .compatible = "rockchip,rk3308-otp",
+ .data = (void *)&px30_data,
+ },
+ { /* sentinel */ },
+};
+MODULE_DEVICE_TABLE(of, rockchip_otp_match);
+
+static int rockchip_otp_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct rockchip_otp *otp;
+ const struct rockchip_data *data;
+ struct nvmem_device *nvmem;
+ int ret, i;
+
+ data = of_device_get_match_data(dev);
+ if (!data) {
+ dev_err(dev, "failed to get match data\n");
+ return -EINVAL;
+ }
+
+ otp = devm_kzalloc(&pdev->dev, sizeof(struct rockchip_otp),
+ GFP_KERNEL);
+ if (!otp)
+ return -ENOMEM;
+
+ otp->dev = dev;
+ otp->base = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(otp->base))
+ return PTR_ERR(otp->base);
+
+ otp->num_clks = ARRAY_SIZE(rockchip_otp_clocks);
+ otp->clks = devm_kcalloc(dev, otp->num_clks,
+ sizeof(*otp->clks), GFP_KERNEL);
+ if (!otp->clks)
+ return -ENOMEM;
+
+ for (i = 0; i < otp->num_clks; ++i)
+ otp->clks[i].id = rockchip_otp_clocks[i];
+
+ ret = devm_clk_bulk_get(dev, otp->num_clks, otp->clks);
+ if (ret)
+ return ret;
+
+ otp->rst = devm_reset_control_get(dev, "phy");
+ if (IS_ERR(otp->rst))
+ return PTR_ERR(otp->rst);
+
+ otp_config.size = data->size;
+ otp_config.priv = otp;
+ otp_config.dev = dev;
+ nvmem = devm_nvmem_register(dev, &otp_config);
+
+ return PTR_ERR_OR_ZERO(nvmem);
+}
+
+static struct platform_driver rockchip_otp_driver = {
+ .probe = rockchip_otp_probe,
+ .driver = {
+ .name = "rockchip-otp",
+ .of_match_table = rockchip_otp_match,
+ },
+};
+
+module_platform_driver(rockchip_otp_driver);
+MODULE_DESCRIPTION("Rockchip OTP driver");
+MODULE_LICENSE("GPL v2");
--
2.23.0
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* [PATCH 1/2] dt-bindings: nvmem: add binding for Rockchip OTP controller
From: Heiko Stuebner @ 2019-09-25 18:49 UTC (permalink / raw)
To: srinivas.kandagatla
Cc: mark.rutland, devicetree, Heiko Stuebner, linux-kernel,
linux-rockchip, robh+dt, linux-arm-kernel, christoph.muellner
Newer Rockchip SoCs use a different IP for accessing special one-
time-programmable memory, so add a binding for these controllers.
Signed-off-by: Heiko Stuebner <heiko@sntech.de>
---
.../bindings/nvmem/rockchip-otp.txt | 25 +++++++++++++++++++
1 file changed, 25 insertions(+)
create mode 100644 Documentation/devicetree/bindings/nvmem/rockchip-otp.txt
diff --git a/Documentation/devicetree/bindings/nvmem/rockchip-otp.txt b/Documentation/devicetree/bindings/nvmem/rockchip-otp.txt
new file mode 100644
index 000000000000..40f649f7c2e5
--- /dev/null
+++ b/Documentation/devicetree/bindings/nvmem/rockchip-otp.txt
@@ -0,0 +1,25 @@
+Rockchip internal OTP (One Time Programmable) memory device tree bindings
+
+Required properties:
+- compatible: Should be one of the following.
+ - "rockchip,px30-otp" - for PX30 SoCs.
+ - "rockchip,rk3308-otp" - for RK3308 SoCs.
+- reg: Should contain the registers location and size
+- clocks: Must contain an entry for each entry in clock-names.
+- clock-names: Should be "otp", "apb_pclk" and "phy".
+- resets: Must contain an entry for each entry in reset-names.
+ See ../../reset/reset.txt for details.
+- reset-names: Should be "phy".
+
+See nvmem.txt for more information.
+
+Example:
+ otp: otp@ff290000 {
+ compatible = "rockchip,px30-otp";
+ reg = <0x0 0xff290000 0x0 0x4000>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ clocks = <&cru SCLK_OTP_USR>, <&cru PCLK_OTP_NS>,
+ <&cru PCLK_OTP_PHY>;
+ clock-names = "otp", "apb_pclk", "phy";
+ };
--
2.23.0
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* [PATCH] iommu/rockchip: don't use platform_get_irq to implicitly count irqs
From: Heiko Stuebner @ 2019-09-25 18:43 UTC (permalink / raw)
To: joro; +Cc: linux-rockchip, iommu, linux-kernel, linux-arm-kernel,
Heiko Stuebner
Till now the Rockchip iommu driver walked through the irq list via
platform_get_irq() until it encountered an ENXIO error. With the
recent change to add a central error message, this always results
in such an error for each iommu on probe and shutdown.
To not confuse people, switch to platform_count_irqs() to get the
actual number of interrupts before walking through them.
Fixes: 7723f4c5ecdb ("driver core: platform: Add an error message to platform_get_irq*()")
Signed-off-by: Heiko Stuebner <heiko@sntech.de>
---
drivers/iommu/rockchip-iommu.c | 19 ++++++++++++++-----
1 file changed, 14 insertions(+), 5 deletions(-)
diff --git a/drivers/iommu/rockchip-iommu.c b/drivers/iommu/rockchip-iommu.c
index 26290f310f90..4dcbf68dfda4 100644
--- a/drivers/iommu/rockchip-iommu.c
+++ b/drivers/iommu/rockchip-iommu.c
@@ -100,6 +100,7 @@ struct rk_iommu {
struct device *dev;
void __iomem **bases;
int num_mmu;
+ int num_irq;
struct clk_bulk_data *clocks;
int num_clocks;
bool reset_disabled;
@@ -1136,7 +1137,7 @@ static int rk_iommu_probe(struct platform_device *pdev)
struct rk_iommu *iommu;
struct resource *res;
int num_res = pdev->num_resources;
- int err, i, irq;
+ int err, i;
iommu = devm_kzalloc(dev, sizeof(*iommu), GFP_KERNEL);
if (!iommu)
@@ -1163,6 +1164,10 @@ static int rk_iommu_probe(struct platform_device *pdev)
if (iommu->num_mmu == 0)
return PTR_ERR(iommu->bases[0]);
+ iommu->num_irq = platform_irq_count(pdev);
+ if (iommu->num_irq < 0)
+ return iommu->num_irq;
+
iommu->reset_disabled = device_property_read_bool(dev,
"rockchip,disable-mmu-reset");
@@ -1219,8 +1224,9 @@ static int rk_iommu_probe(struct platform_device *pdev)
pm_runtime_enable(dev);
- i = 0;
- while ((irq = platform_get_irq(pdev, i++)) != -ENXIO) {
+ for (i = 0; i < iommu->num_irq; i++) {
+ int irq = platform_get_irq(pdev, i);
+
if (irq < 0)
return irq;
@@ -1245,10 +1251,13 @@ static int rk_iommu_probe(struct platform_device *pdev)
static void rk_iommu_shutdown(struct platform_device *pdev)
{
struct rk_iommu *iommu = platform_get_drvdata(pdev);
- int i = 0, irq;
+ int i;
+
+ for (i = 0; i < iommu->num_irq; i++) {
+ int irq = platform_get_irq(pdev, i);
- while ((irq = platform_get_irq(pdev, i++)) != -ENXIO)
devm_free_irq(iommu->dev, irq, iommu);
+ }
pm_runtime_force_suspend(&pdev->dev);
}
--
2.23.0
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* Re: [PATCH] arm64: Allow disabling of the compat vDSO
From: Nick Desaulniers @ 2019-09-25 17:31 UTC (permalink / raw)
To: Catalin Marinas
Cc: Ard Biesheuvel, LKML, Thomas Gleixner, Vincenzo Frascino,
Will Deacon, Linux ARM
In-Reply-To: <20190925170838.GK7042@arrakis.emea.arm.com>
On Wed, Sep 25, 2019 at 10:08 AM Catalin Marinas
<catalin.marinas@arm.com> wrote:
>
> This is just a temporary hiding of the issue, not a complete fix.
Yep.
> Vincenzo will do the fix later on.
Appreciated, I'm happy to help discuss, review, and test.
> > > - check whether COMPATCC is clang or not rather than CC_IS_CLANG, which
> > > only checks the native compiler
> >
> > When cross compiling, IIUC CC_IS_CLANG is referring to CC which is the
> > cross compiler, which is different than HOSTCC which is the host
> > compiler. HOSTCC is used mostly for things in scripts/ while CC is
> > used to compile a majority of the kernel in a cross compile.
>
> We need the third compiler here for the compat vDSO (at least with gcc),
> COMPATCC. I'm tempted to just drop the CONFIG_CROSS_COMPILE_COMPAT_VDSO
> altogether and only rely on a COMPATCC. This way we can add
> COMPATCC_IS_CLANG etc. in the Kconfig checks directly.
Oh, man, yeah 3 compilers in that case:
1. HOSTCC
2. CC
3. COMPATCC
>
> If clang can build both 32 and 64-bit with the same binary (just
> different options), we could maybe have COMPATCC default to CC and add a
> check on whether COMPATCC generates 32-bit binaries.
Cross compilation work differently between GCC and Clang from a
developers perspective. In GCC, at ./configure time you select which
architecture you'd like to cross compile for, and you get one binary
that targets one architecture. You get a nice compiler that can do
mostly static dispatch at the cost of needing multiple binaries in
admittedly rare scenarios like the one we have here. Clang defaults
to all backends enabled when invoking cmake (though there are options
to enable certain backends; Sony for instance enables only x86_64 for
their PS4 SDK (and thus I break their build frequently with my arm64
unit tests)).
Clang can do all of the above with one binary. The codebase makes
heavy use of OOP+virtual dispatch to run ISA specific and general code
transformations (virtual dispatch is slower than static dispatch, but
relative to what the compiler is actually doing, I suspect the effects
are minimal. Folks are also heavily invested in researching
"devirtualization"). With one clang binary, I can do:
# implicitly uses the host's ISA, for me that's x86_64-linux-gnu
$ clang foo.c
$ clang -target aarch64-linux-gnu foo.c
$ clang -target arm-linux-gnueabi foo.c
Admittedly, it's not as simple for the kernel's case; the top level
Makefile sets some flags to support invoking Clang from a non-standard
location, and telling it where to find binutils because we can't
assemble the kernel with LLVM's substitute for GAS).
--
Thanks,
~Nick Desaulniers
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* Re: [PATCH V9 2/2] mailbox: introduce ARM SMC based mailbox
From: Andre Przywara @ 2019-09-25 17:09 UTC (permalink / raw)
To: Peng Fan
Cc: mark.rutland@arm.com, devicetree@vger.kernel.org,
f.fainelli@gmail.com, jassisinghbrar@gmail.com,
linux-kernel@vger.kernel.org, robh+dt@kernel.org, dl-linux-imx,
sudeep.holla@arm.com, linux-arm-kernel@lists.infradead.org
In-Reply-To: <1569377224-5755-3-git-send-email-peng.fan@nxp.com>
On Wed, 25 Sep 2019 02:09:11 +0000
Peng Fan <peng.fan@nxp.com> wrote:
Hi,
> From: Peng Fan <peng.fan@nxp.com>
>
> This mailbox driver implements a mailbox which signals transmitted data
> via an ARM smc (secure monitor call) instruction. The mailbox receiver
> is implemented in firmware and can synchronously return data when it
> returns execution to the non-secure world again.
> An asynchronous receive path is not implemented.
> This allows the usage of a mailbox to trigger firmware actions on SoCs
> which either don't have a separate management processor or on which such
> a core is not available. A user of this mailbox could be the SCP
> interface.
>
> Modified from Andre Przywara's v2 patch
> https://lore.kernel.org/patchwork/patch/812999/
>
> Cc: Andre Przywara <andre.przywara@arm.com>
> Signed-off-by: Peng Fan <peng.fan@nxp.com>
Many thanks for the changes, that looks good to me now!
One tiny thing below, but anyway:
Reviewed-by: Andre Przywara <andre.przywara@arm.com>
> ---
> drivers/mailbox/Kconfig | 7 ++
> drivers/mailbox/Makefile | 2 +
> drivers/mailbox/arm-smc-mailbox.c | 167 +++++++++++++++++++++++++++++++++
> include/linux/mailbox/arm-smccc-mbox.h | 20 ++++
> 4 files changed, 196 insertions(+)
> create mode 100644 drivers/mailbox/arm-smc-mailbox.c
> create mode 100644 include/linux/mailbox/arm-smccc-mbox.h
>
> diff --git a/drivers/mailbox/Kconfig b/drivers/mailbox/Kconfig
> index ab4eb750bbdd..7707ee26251a 100644
> --- a/drivers/mailbox/Kconfig
> +++ b/drivers/mailbox/Kconfig
> @@ -16,6 +16,13 @@ config ARM_MHU
> The controller has 3 mailbox channels, the last of which can be
> used in Secure mode only.
>
> +config ARM_SMC_MBOX
> + tristate "Generic ARM smc mailbox"
> + depends on OF && HAVE_ARM_SMCCC
> + help
> + Generic mailbox driver which uses ARM smc calls to call into
> + firmware for triggering mailboxes.
> +
> config IMX_MBOX
> tristate "i.MX Mailbox"
> depends on ARCH_MXC || COMPILE_TEST
> diff --git a/drivers/mailbox/Makefile b/drivers/mailbox/Makefile
> index c22fad6f696b..93918a84c91b 100644
> --- a/drivers/mailbox/Makefile
> +++ b/drivers/mailbox/Makefile
> @@ -7,6 +7,8 @@ obj-$(CONFIG_MAILBOX_TEST) += mailbox-test.o
>
> obj-$(CONFIG_ARM_MHU) += arm_mhu.o
>
> +obj-$(CONFIG_ARM_SMC_MBOX) += arm-smc-mailbox.o
> +
> obj-$(CONFIG_IMX_MBOX) += imx-mailbox.o
>
> obj-$(CONFIG_ARMADA_37XX_RWTM_MBOX) += armada-37xx-rwtm-mailbox.o
> diff --git a/drivers/mailbox/arm-smc-mailbox.c b/drivers/mailbox/arm-smc-mailbox.c
> new file mode 100644
> index 000000000000..6f0b5fd6ad1b
> --- /dev/null
> +++ b/drivers/mailbox/arm-smc-mailbox.c
> @@ -0,0 +1,167 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright (C) 2016,2017 ARM Ltd.
> + * Copyright 2019 NXP
> + */
> +
> +#include <linux/arm-smccc.h>
> +#include <linux/device.h>
> +#include <linux/kernel.h>
> +#include <linux/interrupt.h>
We don't need this include anymore.
Cheers,
Andre.
> +#include <linux/mailbox_controller.h>
> +#include <linux/mailbox/arm-smccc-mbox.h>
> +#include <linux/module.h>
> +#include <linux/platform_device.h>
> +
> +typedef unsigned long (smc_mbox_fn)(unsigned int, unsigned long,
> + unsigned long, unsigned long,
> + unsigned long, unsigned long,
> + unsigned long);
> +
> +struct arm_smc_chan_data {
> + unsigned int function_id;
> + smc_mbox_fn *invoke_smc_mbox_fn;
> +};
> +
> +static int arm_smc_send_data(struct mbox_chan *link, void *data)
> +{
> + struct arm_smc_chan_data *chan_data = link->con_priv;
> + struct arm_smccc_mbox_cmd *cmd = data;
> + unsigned long ret;
> +
> + if (ARM_SMCCC_IS_64(chan_data->function_id)) {
> + ret = chan_data->invoke_smc_mbox_fn(chan_data->function_id,
> + cmd->args_smccc64[0],
> + cmd->args_smccc64[1],
> + cmd->args_smccc64[2],
> + cmd->args_smccc64[3],
> + cmd->args_smccc64[4],
> + cmd->args_smccc64[5]);
> + } else {
> + ret = chan_data->invoke_smc_mbox_fn(chan_data->function_id,
> + cmd->args_smccc32[0],
> + cmd->args_smccc32[1],
> + cmd->args_smccc32[2],
> + cmd->args_smccc32[3],
> + cmd->args_smccc32[4],
> + cmd->args_smccc32[5]);
> + }
> +
> + mbox_chan_received_data(link, (void *)ret);
> +
> + return 0;
> +}
> +
> +static unsigned long __invoke_fn_hvc(unsigned int function_id,
> + unsigned long arg0, unsigned long arg1,
> + unsigned long arg2, unsigned long arg3,
> + unsigned long arg4, unsigned long arg5)
> +{
> + struct arm_smccc_res res;
> +
> + arm_smccc_hvc(function_id, arg0, arg1, arg2, arg3, arg4,
> + arg5, 0, &res);
> + return res.a0;
> +}
> +
> +static unsigned long __invoke_fn_smc(unsigned int function_id,
> + unsigned long arg0, unsigned long arg1,
> + unsigned long arg2, unsigned long arg3,
> + unsigned long arg4, unsigned long arg5)
> +{
> + struct arm_smccc_res res;
> +
> + arm_smccc_smc(function_id, arg0, arg1, arg2, arg3, arg4,
> + arg5, 0, &res);
> + return res.a0;
> +}
> +
> +static const struct mbox_chan_ops arm_smc_mbox_chan_ops = {
> + .send_data = arm_smc_send_data,
> +};
> +
> +static struct mbox_chan *
> +arm_smc_mbox_of_xlate(struct mbox_controller *mbox,
> + const struct of_phandle_args *sp)
> +{
> + return mbox->chans;
> +}
> +
> +static int arm_smc_mbox_probe(struct platform_device *pdev)
> +{
> + struct device *dev = &pdev->dev;
> + struct mbox_controller *mbox;
> + struct arm_smc_chan_data *chan_data;
> + int ret;
> +
> + mbox = devm_kzalloc(dev, sizeof(*mbox), GFP_KERNEL);
> + if (!mbox)
> + return -ENOMEM;
> +
> + mbox->of_xlate = arm_smc_mbox_of_xlate;
> + mbox->num_chans = 1;
> + mbox->chans = devm_kzalloc(dev, sizeof(*mbox->chans), GFP_KERNEL);
> + if (!mbox->chans)
> + return -ENOMEM;
> +
> + chan_data = devm_kzalloc(dev, sizeof(*chan_data), GFP_KERNEL);
> + if (!chan_data)
> + return -ENOMEM;
> +
> + ret = of_property_read_u32(dev->of_node, "arm,func-id",
> + &chan_data->function_id);
> + if (ret)
> + return ret;
> +
> + if (of_device_is_compatible(dev->of_node, "arm,smc-mbox"))
> + chan_data->invoke_smc_mbox_fn = __invoke_fn_smc;
> + else
> + chan_data->invoke_smc_mbox_fn = __invoke_fn_hvc;
> +
> +
> + mbox->chans->con_priv = chan_data;
> +
> + mbox->txdone_poll = false;
> + mbox->txdone_irq = false;
> + mbox->ops = &arm_smc_mbox_chan_ops;
> + mbox->dev = dev;
> +
> + platform_set_drvdata(pdev, mbox);
> +
> + ret = devm_mbox_controller_register(dev, mbox);
> + if (ret)
> + return ret;
> +
> + dev_info(dev, "ARM SMC mailbox enabled.\n");
> +
> + return ret;
> +}
> +
> +static int arm_smc_mbox_remove(struct platform_device *pdev)
> +{
> + struct mbox_controller *mbox = platform_get_drvdata(pdev);
> +
> + mbox_controller_unregister(mbox);
> + return 0;
> +}
> +
> +static const struct of_device_id arm_smc_mbox_of_match[] = {
> + { .compatible = "arm,smc-mbox", },
> + { .compatible = "arm,hvc-mbox", },
> + {},
> +};
> +MODULE_DEVICE_TABLE(of, arm_smc_mbox_of_match);
> +
> +static struct platform_driver arm_smc_mbox_driver = {
> + .driver = {
> + .name = "arm-smc-mbox",
> + .of_match_table = arm_smc_mbox_of_match,
> + },
> + .probe = arm_smc_mbox_probe,
> + .remove = arm_smc_mbox_remove,
> +};
> +module_platform_driver(arm_smc_mbox_driver);
> +
> +MODULE_AUTHOR("Peng Fan <peng.fan@nxp.com>");
> +MODULE_DESCRIPTION("Generic ARM smc mailbox driver");
> +MODULE_LICENSE("GPL v2");
> diff --git a/include/linux/mailbox/arm-smccc-mbox.h b/include/linux/mailbox/arm-smccc-mbox.h
> new file mode 100644
> index 000000000000..d35fb89a77f5
> --- /dev/null
> +++ b/include/linux/mailbox/arm-smccc-mbox.h
> @@ -0,0 +1,20 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +
> +#ifndef _LINUX_ARM_SMCCC_MBOX_H_
> +#define _LINUX_ARM_SMCCC_MBOX_H_
> +
> +#include <linux/types.h>
> +
> +/**
> + * struct arm_smccc_mbox_cmd - ARM SMCCC message structure
> + * @args_smccc32/64: actual usage of registers is up to the protocol
> + * (within the SMCCC limits)
> + */
> +struct arm_smccc_mbox_cmd {
> + union {
> + u32 args_smccc32[6];
> + u64 args_smccc64[6];
> + };
> +};
> +
> +#endif /* _LINUX_ARM_SMCCC_MBOX_H_ */
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* Re: [PATCH V9 1/2] dt-bindings: mailbox: add binding doc for the ARM SMC/HVC mailbox
From: Andre Przywara @ 2019-09-25 17:09 UTC (permalink / raw)
To: Peng Fan
Cc: mark.rutland@arm.com, devicetree@vger.kernel.org,
f.fainelli@gmail.com, jassisinghbrar@gmail.com,
linux-kernel@vger.kernel.org, robh+dt@kernel.org, dl-linux-imx,
sudeep.holla@arm.com, linux-arm-kernel@lists.infradead.org
In-Reply-To: <1569377224-5755-2-git-send-email-peng.fan@nxp.com>
On Wed, 25 Sep 2019 02:09:08 +0000
Peng Fan <peng.fan@nxp.com> wrote:
Hi,
> From: Peng Fan <peng.fan@nxp.com>
>
> The ARM SMC/HVC mailbox binding describes a firmware interface to trigger
> actions in software layers running in the EL2 or EL3 exception levels.
> The term "ARM" here relates to the SMC instruction as part of the ARM
> instruction set, not as a standard endorsed by ARM Ltd.
>
> Signed-off-by: Peng Fan <peng.fan@nxp.com>
> Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
> ---
> .../devicetree/bindings/mailbox/arm-smc.yaml | 96 ++++++++++++++++++++++
> 1 file changed, 96 insertions(+)
> create mode 100644 Documentation/devicetree/bindings/mailbox/arm-smc.yaml
>
> diff --git a/Documentation/devicetree/bindings/mailbox/arm-smc.yaml b/Documentation/devicetree/bindings/mailbox/arm-smc.yaml
> new file mode 100644
> index 000000000000..b061954d1678
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/mailbox/arm-smc.yaml
> @@ -0,0 +1,96 @@
> +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/mailbox/arm-smc.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: ARM SMC Mailbox Interface
> +
> +maintainers:
> + - Peng Fan <peng.fan@nxp.com>
> +
> +description: |
> + This mailbox uses the ARM smc (secure monitor call) or hvc (hypervisor
> + call) instruction to trigger a mailbox-connected activity in firmware,
> + executing on the very same core as the caller. The value of r0/w0/x0
> + the firmware returns after the smc call is delivered as a received
> + message to the mailbox framework, so synchronous communication can be
> + established. The exact meaning of the action the mailbox triggers as
> + well as the return value is defined by their users and is not subject
> + to this binding.
> +
> + One example use case of this mailbox is the SCMI interface, which uses
> + shared memory to transfer commands and parameters, and a mailbox to
> + trigger a function call. This allows SoCs without a separate management
> + processor (or when such a processor is not available or used) to use
> + this standardized interface anyway.
> +
> + This binding describes no hardware, but establishes a firmware interface.
> + Upon receiving an SMC using the described SMC function identifier, the
> + firmware is expected to trigger some mailbox connected functionality.
> + The communication follows the ARM SMC calling convention.
> + Firmware expects an SMC function identifier in r0 or w0. The supported
> + identifier are passed from consumers, or listed in the the arm,func-id
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
This is now obsolete.
The rest looks good to me, thanks for the changes!
Reviewed-by: Andre Przywara <andre.przywara@arm.com>
Cheers,
Andre.
> + property as described below. The firmware can return one value in
> + the first SMC result register, it is expected to be an error value,
> + which shall be propagated to the mailbox client.
> +
> + Any core which supports the SMC or HVC instruction can be used, as long
> + as a firmware component running in EL3 or EL2 is handling these calls.
> +
> +properties:
> + compatible:
> + oneOf:
> + - description:
> + For implementations using ARM SMC instruction.
> + const: arm,smc-mbox
> +
> + - description:
> + For implementations using ARM HVC instruction.
> + const: arm,hvc-mbox
> +
> + "#mbox-cells":
> + const: 0
> +
> + arm,func-id:
> + description: |
> + An single 32-bit value specifying the function ID used by the mailbox.
> + The function ID follows the ARM SMC calling convention standard.
> + $ref: /schemas/types.yaml#/definitions/uint32
> +
> +required:
> + - compatible
> + - "#mbox-cells"
> + - arm,func-id
> +
> +examples:
> + - |
> + sram@93f000 {
> + compatible = "mmio-sram";
> + reg = <0x0 0x93f000 0x0 0x1000>;
> + #address-cells = <1>;
> + #size-cells = <1>;
> + ranges = <0x0 0x93f000 0x1000>;
> +
> + cpu_scp_lpri: scp-shmem@0 {
> + compatible = "arm,scmi-shmem";
> + reg = <0x0 0x200>;
> + };
> + };
> +
> + smc_tx_mbox: tx_mbox {
> + #mbox-cells = <0>;
> + compatible = "arm,smc-mbox";
> + arm,func-id = <0xc20000fe>;
> + };
> +
> + firmware {
> + scmi {
> + compatible = "arm,scmi";
> + mboxes = <&smc_tx_mbox>;
> + mbox-names = "tx";
> + shmem = <&cpu_scp_lpri>;
> + };
> + };
> +
> +...
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* Re: [PATCH] arm64: Allow disabling of the compat vDSO
From: Catalin Marinas @ 2019-09-25 17:08 UTC (permalink / raw)
To: Nick Desaulniers
Cc: Ard Biesheuvel, LKML, Thomas Gleixner, Vincenzo Frascino,
Will Deacon, Linux ARM
In-Reply-To: <CAKwvOdn2Sf7aAt0zqUUqGY6nXg-C3be7An9amy4tfiNr_8ERJw@mail.gmail.com>
On Wed, Sep 25, 2019 at 09:53:16AM -0700, Nick Desaulniers wrote:
> On Wed, Sep 25, 2019 at 6:09 AM Catalin Marinas <catalin.marinas@arm.com> wrote:
> >
> > The compat vDSO building requires a cross-compiler than produces AArch32
> > binaries, defined via CONFIG_CROSS_COMPILE_COMPAT_VDSO or the
> > CROSS_COMPILE_COMPAT environment variable. If none of these is defined,
> > building the kernel always prints a warning as there is no way to
> > deselect the compat vDSO.
> >
> > Add an arm64 Kconfig entry to allow the deselection of the compat vDSO.
> > In addition, make it an EXPERT option, default n, until other issues
> > with the compat vDSO are solved (64-bit only kernel headers included in
> > user-space vDSO code, CC_IS_CLANG irrelevant to CROSS_COMPILE_COMPAT).
>
> CC_IS_CLANG might be because then CC can be reused with different
> flags, rather than providing a different cross compiler binary via
> config option.
>
> >
> > Fixes: bfe801ebe84f ("arm64: vdso: Enable vDSO compat support")
> > Cc: Will Deacon <will@kernel.org>
> > Cc: Vincenzo Frascino <vincenzo.frascino@arm.com>
> > Cc: Thomas Gleixner <tglx@linutronix.de>
> > Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
>
> Thanks for the patch.
> Reviewed-by: Nick Desaulniers <ndesaulniers@google.com>
> Link: https://github.com/ClangBuiltLinux/linux/issues/595
This is just a temporary hiding of the issue, not a complete fix.
Vincenzo will do the fix later on.
> Overall, this work is important to Android; the ARMv8-A series of
> mobile SoCs we see today have to support 32b and 64b (A32+A64?) for at
> least a few more years; we would like gettimeofday() and friends to be
> fast for 32b and 64b applications.
I agree, it just needs some tweaking and hopefully we get most of it
fixed in 5.4.
> > Suggestions for future improvements of the compat vDSO handling:
> >
> > - replace the CROSS_COMPILE_COMPAT prefix with a full COMPATCC; maybe
> > check that it indeed produces 32-bit code
> >
> > - check whether COMPATCC is clang or not rather than CC_IS_CLANG, which
> > only checks the native compiler
>
> When cross compiling, IIUC CC_IS_CLANG is referring to CC which is the
> cross compiler, which is different than HOSTCC which is the host
> compiler. HOSTCC is used mostly for things in scripts/ while CC is
> used to compile a majority of the kernel in a cross compile.
We need the third compiler here for the compat vDSO (at least with gcc),
COMPATCC. I'm tempted to just drop the CONFIG_CROSS_COMPILE_COMPAT_VDSO
altogether and only rely on a COMPATCC. This way we can add
COMPATCC_IS_CLANG etc. in the Kconfig checks directly.
If clang can build both 32 and 64-bit with the same binary (just
different options), we could maybe have COMPATCC default to CC and add a
check on whether COMPATCC generates 32-bit binaries.
> > - clean up the headers includes; vDSO should not include kernel-only
> > headers that may even contain code patched at run-time
>
> This is a big one; Clang validates the inline asm constraints for
> extended inline assembly, GCC does not for dead code. So Clang chokes
> on the inclusion of arm64 headers using extended inline assembly when
> being compiled for arm-linux-gnueabi.
Whether clang or gcc, I'd like this fixed anyway. At some point we may
inadvertently rely on some code which is patched at boot time for the
kernel code but not for the vDSO.
Thanks.
--
Catalin
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* Re: [PATCH v2 linux-next 0/4] arm/arm64: configs: Convert all CONFIG_REMOTEPROC instances to y
From: Christoph Hellwig @ 2019-09-25 17:05 UTC (permalink / raw)
To: Keerthy
Cc: linux-omap, arnd, tony, catalin.marinas, nsekhar, linux-kernel,
bjorn.andersson, t-kristo, olof, will, hch, linux-arm-kernel
In-Reply-To: <20190920075946.13282-1-j-keerthy@ti.com>
Thanks Keerthy,
the patches look good to me:
Acked-by: Christoph Hellwig <hch@lst.de>
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* Re: [PATCH] arm64: Allow disabling of the compat vDSO
From: Nick Desaulniers @ 2019-09-25 16:53 UTC (permalink / raw)
To: Catalin Marinas
Cc: Ard Biesheuvel, LKML, Thomas Gleixner, Vincenzo Frascino,
Will Deacon, Linux ARM
In-Reply-To: <20190925130926.50674-1-catalin.marinas@arm.com>
On Wed, Sep 25, 2019 at 6:09 AM Catalin Marinas <catalin.marinas@arm.com> wrote:
>
> The compat vDSO building requires a cross-compiler than produces AArch32
> binaries, defined via CONFIG_CROSS_COMPILE_COMPAT_VDSO or the
> CROSS_COMPILE_COMPAT environment variable. If none of these is defined,
> building the kernel always prints a warning as there is no way to
> deselect the compat vDSO.
>
> Add an arm64 Kconfig entry to allow the deselection of the compat vDSO.
> In addition, make it an EXPERT option, default n, until other issues
> with the compat vDSO are solved (64-bit only kernel headers included in
> user-space vDSO code, CC_IS_CLANG irrelevant to CROSS_COMPILE_COMPAT).
CC_IS_CLANG might be because then CC can be reused with different
flags, rather than providing a different cross compiler binary via
config option.
>
> Fixes: bfe801ebe84f ("arm64: vdso: Enable vDSO compat support")
> Cc: Will Deacon <will@kernel.org>
> Cc: Vincenzo Frascino <vincenzo.frascino@arm.com>
> Cc: Thomas Gleixner <tglx@linutronix.de>
> Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
Thanks for the patch.
Reviewed-by: Nick Desaulniers <ndesaulniers@google.com>
Link: https://github.com/ClangBuiltLinux/linux/issues/595
Overall, this work is important to Android; the ARMv8-A series of
mobile SoCs we see today have to support 32b and 64b (A32+A64?) for at
least a few more years; we would like gettimeofday() and friends to be
fast for 32b and 64b applications.
> ---
>
> It looks like you can't really win with the current compat vDSO logic.
> You either don't have a compat cross-compiler and you get a Makefile
> warning or you have one and a get a compiler warning (or failure)
> because of the 64-bit kernel headers included in 32-bit user-space code.
>
> "depends on BROKEN" for ARM64_COMPAT_VDSO also work for me instead of
> EXPERT. I'll leave it up to Will to decide but I'd like at least this
> patch in -rc2 (even better if everything else is fixed before the final
> 5.4).
>
> Suggestions for future improvements of the compat vDSO handling:
>
> - replace the CROSS_COMPILE_COMPAT prefix with a full COMPATCC; maybe
> check that it indeed produces 32-bit code
>
> - check whether COMPATCC is clang or not rather than CC_IS_CLANG, which
> only checks the native compiler
When cross compiling, IIUC CC_IS_CLANG is referring to CC which is the
cross compiler, which is different than HOSTCC which is the host
compiler. HOSTCC is used mostly for things in scripts/ while CC is
used to compile a majority of the kernel in a cross compile.
>
> - clean up the headers includes; vDSO should not include kernel-only
> headers that may even contain code patched at run-time
This is a big one; Clang validates the inline asm constraints for
extended inline assembly, GCC does not for dead code. So Clang chokes
on the inclusion of arm64 headers using extended inline assembly when
being compiled for arm-linux-gnueabi.
>
> arch/arm64/Kconfig | 10 +++++++++-
> 1 file changed, 9 insertions(+), 1 deletion(-)
>
> diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
> index 866e05882799..83a9a78085c6 100644
> --- a/arch/arm64/Kconfig
> +++ b/arch/arm64/Kconfig
> @@ -110,7 +110,6 @@ config ARM64
> select GENERIC_STRNLEN_USER
> select GENERIC_TIME_VSYSCALL
> select GENERIC_GETTIMEOFDAY
> - select GENERIC_COMPAT_VDSO if (!CPU_BIG_ENDIAN && COMPAT)
> select HANDLE_DOMAIN_IRQ
> select HARDIRQS_SW_RESEND
> select HAVE_PCI
> @@ -1185,6 +1184,15 @@ config KUSER_HELPERS
> Say N here only if you are absolutely certain that you do not
> need these helpers; otherwise, the safe option is to say Y.
>
> +config ARM64_COMPAT_VDSO
> + bool "Enable the 32-bit vDSO" if EXPERT
> + depends on !CPU_BIG_ENDIAN
> + select GENERIC_COMPAT_VDSO
> + help
> + Enable the vDSO support for 32-bit applications. You would
> + need to set the 32-bit cross-compiler prefix in
> + CONFIG_CROSS_COMPILE_COMPAT_VDSO or the CROSS_COMPILE_COMPAT
> + environment variable.
>
> menuconfig ARMV8_DEPRECATED
> bool "Emulate deprecated/obsolete ARMv8 instructions"
--
Thanks,
~Nick Desaulniers
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* Re: [PATCH 00/11] of: Fix DMA configuration for non-DT masters
From: Robin Murphy @ 2019-09-25 16:52 UTC (permalink / raw)
To: Rob Herring, Nicolas Saenz Julienne
Cc: devicetree, Matthias Brugger, Frank Rowand, linux-arm-msm,
linux-wireless, linux-kernel@vger.kernel.org, dri-devel, etnaviv,
open list:DMA GENERIC OFFLOAD ENGINE SUBSYSTEM, Florian Fainelli,
Stefan Wahren, james.quinlan, linux-pci, linux-tegra, xen-devel,
Dan Williams, freedreno,
moderated list:ARM/FREESCALE IMX / MXC ARM ARCHITECTURE,
Linux Media Mailing List
In-Reply-To: <CAL_JsqLhx500cx3YLoC7HL1ux3bBpV+fEA2Qnk7D5RFGgiGzSw@mail.gmail.com>
On 25/09/2019 17:16, Rob Herring wrote:
> On Wed, Sep 25, 2019 at 10:30 AM Nicolas Saenz Julienne
> <nsaenzjulienne@suse.de> wrote:
>>
>> On Wed, 2019-09-25 at 16:09 +0100, Robin Murphy wrote:
>>> On 25/09/2019 15:52, Nicolas Saenz Julienne wrote:
>>>> On Tue, 2019-09-24 at 16:59 -0500, Rob Herring wrote:
>>>>> On Tue, Sep 24, 2019 at 1:12 PM Nicolas Saenz Julienne
>>>>> <nsaenzjulienne@suse.de> wrote:
>>>>>> Hi All,
>>>>>> this series tries to address one of the issues blocking us from
>>>>>> upstreaming Broadcom's STB PCIe controller[1]. Namely, the fact that
>>>>>> devices not represented in DT which sit behind a PCI bus fail to get the
>>>>>> bus' DMA addressing constraints.
>>>>>>
>>>>>> This is due to the fact that of_dma_configure() assumes it's receiving a
>>>>>> DT node representing the device being configured, as opposed to the PCIe
>>>>>> bridge node we currently pass. This causes the code to directly jump
>>>>>> into PCI's parent node when checking for 'dma-ranges' and misses
>>>>>> whatever was set there.
>>>>>>
>>>>>> To address this I create a new API in OF - inspired from Robin Murphys
>>>>>> original proposal[2] - which accepts a bus DT node as it's input in
>>>>>> order to configure a device's DMA constraints. The changes go deep into
>>>>>> of/address.c's implementation, as a device being having a DT node
>>>>>> assumption was pretty strong.
>>>>>>
>>>>>> On top of this work, I also cleaned up of_dma_configure() removing its
>>>>>> redundant arguments and creating an alternative function for the special
>>>>>> cases
>>>>>> not applicable to either the above case or the default usage.
>>>>>>
>>>>>> IMO the resulting functions are more explicit. They will probably
>>>>>> surface some hacky usages that can be properly fixed as I show with the
>>>>>> DT fixes on the Layerscape platform.
>>>>>>
>>>>>> This was also tested on a Raspberry Pi 4 with a custom PCIe driver and
>>>>>> on a Seattle AMD board.
>>>>>
>>>>> Humm, I've been working on this issue too. Looks similar though yours
>>>>> has a lot more churn and there's some other bugs I've found.
>>>>
>>>> That's good news, and yes now that I see it, some stuff on my series is
>>>> overly
>>>> complicated. Specially around of_translate_*().
>>>>
>>>> On top of that, you removed in of_dma_get_range():
>>>>
>>>> - /*
>>>> - * At least empty ranges has to be defined for parent node if
>>>> - * DMA is supported
>>>> - */
>>>> - if (!ranges)
>>>> - break;
>>>>
>>>> Which I assumed was bound to the standard and makes things easier.
>>>>
>>>>> Can you test out this branch[1]. I don't have any h/w needing this,
>>>>> but wrote a unittest and tested with modified QEMU.
>>>>
>>>> I reviewed everything, I did find a minor issue, see the patch attached.
>>>
>>> WRT that patch, the original intent of "force_dma" was purely to
>>> consider a device DMA-capable regardless of the presence of
>>> "dma-ranges". Expecting of_dma_configure() to do anything for a non-OF
>>> device has always been bogus - magic paravirt devices which appear out
>>> of nowhere and expect to be treated as genuine DMA masters are a
>>> separate problem that we haven't really approached yet.
>>
>> I agree it's clearly abusing the function. I have no problem with the behaviour
>> change if it's OK with you.
Thinking about it, you could probably just remove that call from the Xen
DRM driver now anyway - since the dma-direct rework, we lost the ability
to set dma_dummy_ops by default, and NULL ops now represent what it
(presumably) wants.
>> Robin, have you looked into supporting multiple dma-ranges? It's the next thing
>> we need for BCM STB's PCIe. I'll have a go at it myself if nothing is in the
>> works already.
>
> Multiple dma-ranges as far as configuring inbound windows should work
> already other than the bug when there's any parent translation. But if
> you mean supporting multiple DMA offsets and masks per device in the
> DMA API, there's nothing in the works yet.
There's also the in-between step of making of_dma_get_range() return a
size based on all the dma-ranges entries rather than only the first one
- otherwise, something like [1] can lead to pretty unworkable default
masks. We implemented that when doing acpi_dma_get_range(), it's just
that the OF counterpart never caught up.
Robin.
[1]
http://linux-arm.org/git?p=linux-rm.git;a=commitdiff;h=a2814af56b3486c2985a95540a88d8f9fa3a699f
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* Re: [PATCH] [MT6660] Mediatek Smart Amplifier Driver
From: Mark Brown @ 2019-09-25 16:50 UTC (permalink / raw)
To: Richtek Jeff Chang
Cc: alsa-devel, linux-kernel, tiwai, lgirdwood, linux-mediatek,
matthias.bgg, perex, linux-arm-kernel
In-Reply-To: <3a9f66b3-bdb7-9bec-a9c4-ac58d3efa543@gmail.com>
[-- Attachment #1.1: Type: text/plain, Size: 2008 bytes --]
On Wed, Sep 25, 2019 at 06:04:23PM +0800, Richtek Jeff Chang wrote:
> Mark Brown 於 2019/9/4 下午7:56 寫道:
> > On Wed, Sep 04, 2019 at 03:07:06PM +0800, Richtek Jeff Chang wrote:
> > > > It would be good to implement a regmap rather than open coding
> > > > *everything* - it'd give you things like this without needing to open
> > > > code them. Providing you don't use the cache code it should cope fine
> > > > with variable register sizes.
> > > Due to our hardware design, it is hard to implement regmap for MT6660.
> > You definitely can't use all the functionality due to the variable
> > register sizes but using reg_write() and reg_read() should get you most
> > of it.
> How can I fill the val_bits for variable register size?
> I try to use all 32 bits val_bits, but our chip some registers are
> overlap...
> Do you have any suggestion for this issue? Thank you very much!
If you use reg_read() and reg_write() operations you can hide the
register size within them - the rest of the code thinks the
registers are all the 32 bits but when doing I/O it can use the
appropriate size for a given register.
> > > > > + for (i = 0; i < len; i++) {
> > > > > + ret = mt6660_i2c_update_bits(chip, init_table[i].addr,
> > > > > + init_table[i].mask, init_table[i].data);
> > > > > + if (ret < 0)
> > > > > + return ret;
> > > > Why are we not using the chip defaults here?
> > > Because MT6660 needs this initial setting for working well.
> > What are these settings? Are you sure they are generic settings and
> > not board specific?
> Yes, they are generic setting. It comes from our hardware designers.
You should probably be using the regmap register patch feature,
it's for things like this where the chip should always be used
with a different set of defaults to the silicon.
> Should I send new patch file to you in this mail loop, or I should send new
> patch via new Email Loop?
A new one please.
[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]
[-- Attachment #2: Type: text/plain, Size: 176 bytes --]
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* Re: [PATCH v8 6/6] PM / devfreq: Use PM QoS for sysfs min/max_freq
From: Matthias Kaehlcke @ 2019-09-25 16:45 UTC (permalink / raw)
To: Chanwoo Choi
Cc: Artur Świgoń, Abel Vesa, Saravana Kannan, linux-pm,
Viresh Kumar, NXP Linux Team, Krzysztof Kozlowski, Lukasz Luba,
Kyungmin Park, MyungJoo Ham, Alexandre Bailon, Leonard Crestez,
Georgi Djakov, linux-arm-kernel, Jacky Bai
In-Reply-To: <c521989f-51b6-84eb-b4f1-c4469494345e@samsung.com>
On Wed, Sep 25, 2019 at 11:41:07AM +0900, Chanwoo Choi wrote:
> On 19. 9. 24. 오후 7:11, Leonard Crestez wrote:
> > Switch the handling of min_freq and max_freq from sysfs to use the
> > dev_pm_qos_request interface.
> >
> > Since PM QoS handles frequencies as kHz this change reduces the
> > precision of min_freq and max_freq. This shouldn't introduce problems
> > because frequencies which are not an integer number of kHz are likely
> > not an integer number of Hz either.
> >
> > Try to ensure compatibility by rounding min values down and rounding
> > max values up.
> >
> > Signed-off-by: Leonard Crestez <leonard.crestez@nxp.com>
> > Reviewed-by: Matthias Kaehlcke <mka@chromium.org>
> > ---
> > drivers/devfreq/devfreq.c | 46 ++++++++++++++++++++++++---------------
> > include/linux/devfreq.h | 9 ++++----
> > 2 files changed, 33 insertions(+), 22 deletions(-)
> >
> > diff --git a/drivers/devfreq/devfreq.c b/drivers/devfreq/devfreq.c
> > index 784f3e40536a..8bb7efd821ab 100644
> > --- a/drivers/devfreq/devfreq.c
> > +++ b/drivers/devfreq/devfreq.c
> > @@ -137,14 +137,10 @@ static void get_freq_range(struct devfreq *devfreq,
> > qos_max_freq = dev_pm_qos_read_value(devfreq->dev.parent,
> > DEV_PM_QOS_MIN_FREQUENCY);
> > *min_freq = max(*min_freq, HZ_PER_KHZ * qos_min_freq);
> > *max_freq = min(*max_freq, HZ_PER_KHZ * qos_max_freq);
> >
> > - /* constraints from sysfs */
> > - *min_freq = max(*min_freq, devfreq->min_freq);
> > - *max_freq = min(*max_freq, devfreq->max_freq);
> > -
> > /* constraints from OPP interface */
> > *min_freq = max(*min_freq, devfreq->scaling_min_freq);
> > /* scaling_max_freq can be zero on error */
> > if (devfreq->scaling_max_freq)
> > *max_freq = min(*max_freq, devfreq->scaling_max_freq);
> > @@ -679,10 +675,12 @@ static void devfreq_dev_release(struct device *dev)
> > DEV_PM_QOS_MIN_FREQUENCY);
> >
> > if (devfreq->profile->exit)
> > devfreq->profile->exit(devfreq->dev.parent);
> >
> > + dev_pm_qos_remove_request(&devfreq->user_max_freq_req);
> > + dev_pm_qos_remove_request(&devfreq->user_min_freq_req);
>
> Please check the return value if error happen, just print the err with dev_err()
> without stopping the release steps.
I wonder if dev_warn() would be more appropriate, since the current operation
is not aborted.
> > kfree(devfreq->time_in_state);
> > kfree(devfreq->trans_table);
> > mutex_destroy(&devfreq->lock);
> > kfree(devfreq);
> > }
> > @@ -747,18 +745,25 @@ struct devfreq *devfreq_add_device(struct device *dev,
> > devfreq->scaling_min_freq = find_available_min_freq(devfreq);
> > if (!devfreq->scaling_min_freq) {
> > err = -EINVAL;
> > goto err_dev;
> > }
> > - devfreq->min_freq = devfreq->scaling_min_freq;
> >
> > devfreq->scaling_max_freq = find_available_max_freq(devfreq);
> > if (!devfreq->scaling_max_freq) {
> > err = -EINVAL;
> > goto err_dev;
> > }
> > - devfreq->max_freq = devfreq->scaling_max_freq;
> > +
> > + err = dev_pm_qos_add_request(dev, &devfreq->user_min_freq_req,
> > + DEV_PM_QOS_MIN_FREQUENCY, 0);
> > + if (err < 0)
> > + goto err_dev;
> > + err = dev_pm_qos_add_request(dev, &devfreq->user_max_freq_req,
> > + DEV_PM_QOS_MAX_FREQUENCY, S32_MAX);
> > + if (err < 0)
> > + goto err_dev;
> >
> > devfreq->suspend_freq = dev_pm_opp_get_suspend_opp_freq(dev);
> > atomic_set(&devfreq->suspend_count, 0);
> >
> > devfreq->trans_table = kzalloc(
> > @@ -843,10 +848,14 @@ struct devfreq *devfreq_add_device(struct device *dev,
> > err_dev:
> > /*
> > * Cleanup path for errors that happen before registration.
> > * Otherwise we rely on devfreq_dev_release.
> > */
> > + if (dev_pm_qos_request_active(&devfreq->user_max_freq_req))
> > + dev_pm_qos_remove_request(&devfreq->user_max_freq_req);
>
> Please check the return value if error happen, just print the err with dev_err()
> without stopping the release steps.
>
> dev_err(... "failed to remove request of DEV_PM_QOS_MAX_FREQUENCY\n");
dev_warn() for the same reason as above?
I think the message would be better with a slight change:
"failed to remove DEV_PM_QOS_MAX_FREQUENCY request\n"
>
> > + if (dev_pm_qos_request_active(&devfreq->user_min_freq_req))
> > + dev_pm_qos_remove_request(&devfreq->user_min_freq_req);
>
> dev_err(... "failed to remove request of DEV_PM_QOS_MIN_FREQUENCY\n");
ditto
> > kfree(devfreq->time_in_state);
> > kfree(devfreq->trans_table);
> > kfree(devfreq);
> > err_out:
> > return ERR_PTR(err);
> > @@ -1407,14 +1416,15 @@ static ssize_t min_freq_store(struct device *dev, struct device_attribute *attr,
> >
> > ret = sscanf(buf, "%lu", &value);
> > if (ret != 1)
> > return -EINVAL;
> >
> > - mutex_lock(&df->lock);
> > - df->min_freq = value;
> > - update_devfreq(df);
> > - mutex_unlock(&df->lock);
> > + /* round down to kHz for PM QoS */
>
> I prefer more detailed description as following:
>
> /*
> * Round down to KHz to decide the proper minimum frequency
it should be kHz, with a lower-case 'k', as in the original comment.
> * which is closed to user request.
> */
The comment you suggest doesn't provide any information about why the
conversion to kHz is done, in this sense the original comment that
mentions PM QoS provides more value.
With whatever we end up, I suggest to use 'convert' instead of
'round down'.
> > + ret = dev_pm_qos_update_request(&df->user_min_freq_req,
> > + value / HZ_PER_KHZ);
> > + if (ret < 0)
> > + return ret;
> >
> > return count;
> > }
> >
> > static ssize_t min_freq_show(struct device *dev, struct device_attribute *attr,
> > @@ -1439,19 +1449,19 @@ static ssize_t max_freq_store(struct device *dev, struct device_attribute *attr,
> >
> > ret = sscanf(buf, "%lu", &value);
> > if (ret != 1)
> > return -EINVAL;
> >
> > - mutex_lock(&df->lock);
> > -
> > - /* Interpret zero as "don't care" */
> > - if (!value)
> > - value = ULONG_MAX;
> > + /* round up to kHz for PM QoS and interpret zero as "don't care" */
>
> I think that "don't care" comment style is not good.
>
> I referred to the Documentation/ABI/testing/sysfs-class-devfreq file.
> I prefer more detailed description as following:
> /*
> * Round up to KHz to decide the proper maximum frequency
kHz
> * which is closed to user request. If value is zero,
> * the user does not care.
"the user does not care" is still very casual you didn't like initially.
How about "A value of zero is interpreted as 'no limit'."?
As for the min freq, I think PM QoS should be mentioned to make clear why
the conversion to kHz is needed.
> */
>
>
> > + if (value)
> > + value = DIV_ROUND_UP(value, HZ_PER_KHZ);
> > + else
> > + value = S32_MAX;
> >
> > - df->max_freq = value;
> > - update_devfreq(df);
> > - mutex_unlock(&df->lock);
> > + ret = dev_pm_qos_update_request(&df->user_max_freq_req, value);
> > + if (ret < 0)
> > + return ret;
> >
> > return count;
> > }
> > static DEVICE_ATTR_RW(min_freq);
> >
> > diff --git a/include/linux/devfreq.h b/include/linux/devfreq.h
> > index dac0dffeabb4..7849fe4c666d 100644
> > --- a/include/linux/devfreq.h
> > +++ b/include/linux/devfreq.h
> > @@ -11,10 +11,11 @@
> > #define __LINUX_DEVFREQ_H__
> >
> > #include <linux/device.h>
> > #include <linux/notifier.h>
> > #include <linux/pm_opp.h>
> > +#include <linux/pm_qos.h>
> >
> > #define DEVFREQ_NAME_LEN 16
> >
> > /* DEVFREQ governor name */
> > #define DEVFREQ_GOV_SIMPLE_ONDEMAND "simple_ondemand"
> > @@ -121,12 +122,12 @@ struct devfreq_dev_profile {
> > * devfreq.nb to the corresponding register notifier call chain.
> > * @work: delayed work for load monitoring.
> > * @previous_freq: previously configured frequency value.
> > * @data: Private data of the governor. The devfreq framework does not
> > * touch this.
> > - * @min_freq: Limit minimum frequency requested by user (0: none)
> > - * @max_freq: Limit maximum frequency requested by user (0: none)
> > + * @user_min_freq_req: PM QoS min frequency request from user (via sysfs)
>
> min -> minimum and then remove parenthesis as following:
> PM QoS minimum frequency request by user via sysfs
>
> > + * @user_max_freq_req: PM QoS max frequency request from user (via sysfs)
>
> ditto. max -> maximum
> PM QoS maximum frequency request by user via sysfs
>
> > * @scaling_min_freq: Limit minimum frequency requested by OPP interface
> > * @scaling_max_freq: Limit maximum frequency requested by OPP interface
> > * @stop_polling: devfreq polling status of a device.
> > * @suspend_freq: frequency of a device set during suspend phase.
> > * @resume_freq: frequency of a device set in resume phase.
> > @@ -161,12 +162,12 @@ struct devfreq {
> > unsigned long previous_freq;
> > struct devfreq_dev_status last_status;
> >
> > void *data; /* private data for governors */
> >
> > - unsigned long min_freq;
> > - unsigned long max_freq;
> > + struct dev_pm_qos_request user_min_freq_req;
> > + struct dev_pm_qos_request user_max_freq_req;
> > unsigned long scaling_min_freq;
> > unsigned long scaling_max_freq;
> > bool stop_polling;
> >
> > unsigned long suspend_freq;
> >
>
>
> --
> Best Regards,
> Chanwoo Choi
> Samsung Electronics
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* Re: [PATCH] clocksource: mediatek: fix error handling
From: Daniel Lezcano @ 2019-09-25 16:42 UTC (permalink / raw)
To: Fabien Parent, linux-kernel, linux-arm-kernel, linux-mediatek
Cc: matthias.bgg, tglx
In-Reply-To: <20190919191315.25190-1-fparent@baylibre.com>
On 19/09/2019 21:13, Fabien Parent wrote:
> When timer_of_init fails, it cleans up after itself by undoing
> everything it did during the initialization function.
>
> mtk_syst_init and mtk_gpt_init both call timer_of_cleanup if
> timer_of_init fails. timer_of_cleanup try to release the resource taken.
> Since these resources have already been cleaned up by timer_of_init,
> we end up getting a few warnings printed:
[ ... ]
> This commit remove the calls to timer_of_cleanup when timer_of_init
> fails since it is unnecessary and actually cause warnings to be printed.
>
> Signed-off-by: Fabien Parent <fparent@baylibre.com>
Applied, thanks for the fix!
In the future add the 'Fixes' tag please.
-- Daniel
--
<http://www.linaro.org/> Linaro.org │ Open source software for ARM SoCs
Follow Linaro: <http://www.facebook.com/pages/Linaro> Facebook |
<http://twitter.com/#!/linaroorg> Twitter |
<http://www.linaro.org/linaro-blog/> Blog
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* [PATCH 3/3] memory: samsung: exynos5422-dmc: Add support for interrupt from performance counters
From: Lukasz Luba @ 2019-09-25 16:18 UTC (permalink / raw)
To: devicetree, linux-kernel, linux-pm, linux-samsung-soc,
linux-arm-kernel
Cc: mark.rutland, willy.mh.wolff.ml, robh+dt, b.zolnierkie, krzk,
Lukasz Luba, cw00.choi, kyungmin.park, kgene, myungjoo.ham,
s.nawrocki, m.szyprowski
In-Reply-To: <20190925161813.21117-1-l.luba@partner.samsung.com>
Introduce a new interrupt driven mechanism for managing speed of the
memory controller. The interrupts are generated due to performance
counters overflow. The performance counters might track memory reads,
writes, transfers, page misses, etc. In the basic algorithm tracking
read transfers and calculating memory pressure should be enough to
skip polling mode in devfreq.
Signed-off-by: Lukasz Luba <l.luba@partner.samsung.com>
---
drivers/memory/samsung/exynos5422-dmc.c | 297 ++++++++++++++++++++++--
1 file changed, 272 insertions(+), 25 deletions(-)
diff --git a/drivers/memory/samsung/exynos5422-dmc.c b/drivers/memory/samsung/exynos5422-dmc.c
index 0fe5f2186139..86e1844b97ef 100644
--- a/drivers/memory/samsung/exynos5422-dmc.c
+++ b/drivers/memory/samsung/exynos5422-dmc.c
@@ -8,6 +8,7 @@
#include <linux/devfreq.h>
#include <linux/devfreq-event.h>
#include <linux/device.h>
+#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/mfd/syscon.h>
#include <linux/module.h>
@@ -35,6 +36,29 @@
#define USE_BPLL_TIMINGS (0)
#define EXYNOS5_AREF_NORMAL (0x2e)
+#define DREX_PPCCLKCON (0x0130)
+#define DREX_PEREV2CONFIG (0x013c)
+#define DREX_PMNC_PPC (0xE000)
+#define DREX_CNTENS_PPC (0xE010)
+#define DREX_CNTENC_PPC (0xE020)
+#define DREX_INTENS_PPC (0xE030)
+#define DREX_INTENC_PPC (0xE040)
+#define DREX_FLAG_PPC (0xE050)
+#define DREX_PMCNT2_PPC (0xE130)
+
+#define CC_RESET BIT(2)
+#define PPC_COUNTER_RESET BIT(1)
+#define PPC_ENABLE BIT(0)
+#define PEREV_CLK_EN BIT(0)
+#define PERF_CNT2 BIT(2)
+#define PERF_CCNT BIT(31)
+
+#define READ_TRANSFER_CH0 (0x6d)
+#define READ_TRANSFER_CH1 (0x6f)
+
+#define PERF_COUNTER_START_VALUE 0xff000000
+#define PERF_EVENT_UP_DOWN_THRESHOLD 900000000ULL
+
/**
* struct dmc_opp_table - Operating level desciption
*
@@ -85,6 +109,9 @@ struct exynos5_dmc {
struct clk *mout_mx_mspll_ccore_phy;
struct devfreq_event_dev **counter;
int num_counters;
+ u64 last_overflow_ts[2];
+ unsigned long load, total;
+ bool in_irq_mode;
};
#define TIMING_FIELD(t_name, t_bit_beg, t_bit_end) \
@@ -653,6 +680,167 @@ static int exynos5_counters_get(struct exynos5_dmc *dmc,
return 0;
}
+/**
+ * exynos5_dmc_start_perf_events() - Setup and start performance event counters
+ * @dmc: device for which the counters are going to be checked
+ * @beg_value: initial value for the counter
+ *
+ * Function which enables needed counters, interrupts and sets initial values
+ * then starts the counters.
+ */
+static void exynos5_dmc_start_perf_events(struct exynos5_dmc *dmc,
+ u32 beg_value)
+{
+ /* Enable interrupts for counter 2 */
+ writel(PERF_CNT2, dmc->base_drexi0 + DREX_INTENS_PPC);
+ writel(PERF_CNT2, dmc->base_drexi1 + DREX_INTENS_PPC);
+ /* Enable counter 2 and CCNT */
+ writel(PERF_CNT2 | PERF_CCNT, dmc->base_drexi0 + DREX_CNTENS_PPC);
+ writel(PERF_CNT2 | PERF_CCNT, dmc->base_drexi1 + DREX_CNTENS_PPC);
+ /* Clear overflow flag for all counters */
+ writel(PERF_CNT2 | PERF_CCNT, dmc->base_drexi0 + DREX_FLAG_PPC);
+ writel(PERF_CNT2 | PERF_CCNT, dmc->base_drexi1 + DREX_FLAG_PPC);
+ /* Reset all counters */
+ writel(CC_RESET | PPC_COUNTER_RESET, dmc->base_drexi0 + DREX_PMNC_PPC);
+ writel(CC_RESET | PPC_COUNTER_RESET, dmc->base_drexi1 + DREX_PMNC_PPC);
+ /*
+ * Set start value for the counters, the number of samples that
+ * will be gathered is calculated as: 0xffffffff - beg_value
+ */
+ writel(beg_value, dmc->base_drexi0 + DREX_PMCNT2_PPC);
+ writel(beg_value, dmc->base_drexi1 + DREX_PMCNT2_PPC);
+ /* Start all counters */
+ writel(PPC_ENABLE, dmc->base_drexi0 + DREX_PMNC_PPC);
+ writel(PPC_ENABLE, dmc->base_drexi1 + DREX_PMNC_PPC);
+}
+
+/**
+ * exynos5_dmc_perf_events_calc() - Calculate utilization
+ * @dmc: device for which the counters are going to be checked
+ * @diff_ts: time between last interrupt and current one
+ *
+ * Function which calculates needed utilization for the devfreq governor.
+ * It prepares values for 'busy_time' and 'total_time' based on elapsed time
+ * between interrupts, which approximates utilization.
+ */
+static void exynos5_dmc_perf_events_calc(struct exynos5_dmc *dmc, u64 diff_ts)
+{
+ /*
+ * This is a simple algorithm for managing traffic on DMC.
+ * When there is almost no load the counters overflow every 4s,
+ * no mater the DMC frequency.
+ * The high load might be approximated using linear function.
+ * Knowing that, simple calculation can provide 'busy_time' and
+ * 'total_time' to the devfreq governor which picks up target
+ * frequency.
+ * We want a fast ramp up and slow decay in frequency change function.
+ */
+ if (diff_ts < PERF_EVENT_UP_DOWN_THRESHOLD) {
+ /*
+ * Set higher utilization for the simple_ondemand governor.
+ * The governor should increase the frequency of the DMC.
+ */
+ dmc->load = 70;
+ dmc->total = 100;
+ } else {
+ /*
+ * Set low utilization for the simple_ondemand governor.
+ * The governor should decrease the frequency of the DMC.
+ */
+ dmc->load = 35;
+ dmc->total = 100;
+ }
+
+ dev_dbg(dmc->dev, "diff_ts=%llu\n", diff_ts);
+}
+
+/**
+ * exynos5_dmc_perf_events_check() - Checks the status of the counters
+ * @dmc: device for which the counters are going to be checked
+ *
+ * Function which is called from threaded IRQ to check the counters state
+ * and to call approximation for the needed utilization.
+ */
+static void exynos5_dmc_perf_events_check(struct exynos5_dmc *dmc)
+{
+ u32 val;
+ u64 diff_ts, ts;
+
+ ts = ktime_get_ns();
+
+ /* Stop all counters */
+ writel(0, dmc->base_drexi0 + DREX_PMNC_PPC);
+ writel(0, dmc->base_drexi1 + DREX_PMNC_PPC);
+
+ /* Check the source in interrupt flag registers (which channel) */
+ val = readl(dmc->base_drexi0 + DREX_FLAG_PPC);
+ if (val) {
+ diff_ts = ts - dmc->last_overflow_ts[0];
+ dmc->last_overflow_ts[0] = ts;
+ dev_dbg(dmc->dev, "drex0 0xE050 val= 0x%08x\n", val);
+ } else {
+ val = readl(dmc->base_drexi1 + DREX_FLAG_PPC);
+ diff_ts = ts - dmc->last_overflow_ts[1];
+ dmc->last_overflow_ts[1] = ts;
+ dev_dbg(dmc->dev, "drex1 0xE050 val= 0x%08x\n", val);
+ }
+
+ exynos5_dmc_perf_events_calc(dmc, diff_ts);
+
+ exynos5_dmc_start_perf_events(dmc, PERF_COUNTER_START_VALUE);
+}
+
+/**
+ * exynos5_dmc_enable_perf_events() - Enable performance events
+ * @dmc: device for which the counters are going to be checked
+ *
+ * Function which is setup needed environment and enables counters.
+ */
+static void exynos5_dmc_enable_perf_events(struct exynos5_dmc *dmc)
+{
+ u64 ts;
+
+ /* Enable Performance Event Clock */
+ writel(PEREV_CLK_EN, dmc->base_drexi0 + DREX_PPCCLKCON);
+ writel(PEREV_CLK_EN, dmc->base_drexi1 + DREX_PPCCLKCON);
+
+ /* Select read transfers as performance event2 */
+ writel(READ_TRANSFER_CH0, dmc->base_drexi0 + DREX_PEREV2CONFIG);
+ writel(READ_TRANSFER_CH1, dmc->base_drexi1 + DREX_PEREV2CONFIG);
+
+ dmc->in_irq_mode = 1;
+
+ ts = ktime_get_ns();
+ dmc->last_overflow_ts[0] = ts;
+ dmc->last_overflow_ts[1] = ts;
+
+ /* Devfreq shouldn't be faster than initialization, play safe though. */
+ dmc->load = 99;
+ dmc->total = 100;
+}
+
+/**
+ * exynos5_dmc_disable_perf_events() - Disable performance events
+ * @dmc: device for which the counters are going to be checked
+ *
+ * Function which stops, disables performance event counters and interrupts.
+ */
+static void exynos5_dmc_disable_perf_events(struct exynos5_dmc *dmc)
+{
+ /* Stop all counters */
+ writel(0, dmc->base_drexi0 + DREX_PMNC_PPC);
+ writel(0, dmc->base_drexi1 + DREX_PMNC_PPC);
+ /* Disable interrupts for counter 2 */
+ writel(PERF_CNT2, dmc->base_drexi0 + DREX_INTENC_PPC);
+ writel(PERF_CNT2, dmc->base_drexi1 + DREX_INTENC_PPC);
+ /* Disable counter 2 and CCNT */
+ writel(PERF_CNT2 | PERF_CCNT, dmc->base_drexi0 + DREX_CNTENC_PPC);
+ writel(PERF_CNT2 | PERF_CCNT, dmc->base_drexi1 + DREX_CNTENC_PPC);
+ /* Clear overflow flag for all counters */
+ writel(PERF_CNT2 | PERF_CCNT, dmc->base_drexi0 + DREX_FLAG_PPC);
+ writel(PERF_CNT2 | PERF_CCNT, dmc->base_drexi1 + DREX_FLAG_PPC);
+}
+
/**
* exynos5_dmc_get_status() - Read current DMC performance statistics.
* @dev: device for which the statistics are requested
@@ -669,18 +857,24 @@ static int exynos5_dmc_get_status(struct device *dev,
unsigned long load, total;
int ret;
- ret = exynos5_counters_get(dmc, &load, &total);
- if (ret < 0)
- return -EINVAL;
+ if (dmc->in_irq_mode) {
+ stat->current_frequency = dmc->curr_rate;
+ stat->busy_time = dmc->load;
+ stat->total_time = dmc->total;
+ } else {
+ ret = exynos5_counters_get(dmc, &load, &total);
+ if (ret < 0)
+ return -EINVAL;
- /* To protect from overflow in calculation ratios, divide by 1024 */
- stat->busy_time = load >> 10;
- stat->total_time = total >> 10;
+ /* To protect from overflow, divide by 1024 */
+ stat->busy_time = load >> 10;
+ stat->total_time = total >> 10;
- ret = exynos5_counters_set_event(dmc);
- if (ret < 0) {
- dev_err(dev, "could not set event counter\n");
- return ret;
+ ret = exynos5_counters_set_event(dmc);
+ if (ret < 0) {
+ dev_err(dev, "could not set event counter\n");
+ return ret;
+ }
}
return 0;
@@ -712,7 +906,6 @@ static int exynos5_dmc_get_cur_freq(struct device *dev, unsigned long *freq)
* It provides to the devfreq framework needed functions and polling period.
*/
static struct devfreq_dev_profile exynos5_dmc_df_profile = {
- .polling_ms = 500,
.target = exynos5_dmc_target,
.get_dev_status = exynos5_dmc_get_status,
.get_cur_freq = exynos5_dmc_get_cur_freq,
@@ -1108,6 +1301,26 @@ static inline int exynos5_dmc_set_pause_on_switching(struct exynos5_dmc *dmc)
return 0;
}
+static irqreturn_t dmc_irq_thread(int irq, void *priv)
+{
+ int res;
+ struct exynos5_dmc *dmc = priv;
+
+ dev_dbg(dmc->dev, "irq thread handler\n");
+
+ mutex_lock(&dmc->df->lock);
+
+ exynos5_dmc_perf_events_check(dmc);
+
+ res = update_devfreq(dmc->df);
+ if (res)
+ dev_err(dmc->dev, "devfreq failed with %d\n", res);
+
+ mutex_unlock(&dmc->df->lock);
+
+ return IRQ_HANDLED;
+}
+
/**
* exynos5_dmc_probe() - Probe function for the DMC driver
* @pdev: platform device for which the driver is going to be initialized
@@ -1125,6 +1338,7 @@ static int exynos5_dmc_probe(struct platform_device *pdev)
struct device_node *np = dev->of_node;
struct exynos5_dmc *dmc;
struct resource *res;
+ int irq;
dmc = devm_kzalloc(dev, sizeof(*dmc), GFP_KERNEL);
if (!dmc)
@@ -1172,24 +1386,48 @@ static int exynos5_dmc_probe(struct platform_device *pdev)
goto remove_clocks;
}
- ret = exynos5_performance_counters_init(dmc);
- if (ret) {
- dev_warn(dev, "couldn't probe performance counters\n");
- goto remove_clocks;
- }
-
ret = exynos5_dmc_set_pause_on_switching(dmc);
if (ret) {
dev_warn(dev, "couldn't get access to PAUSE register\n");
goto err_devfreq_add;
}
- /*
- * Setup default thresholds for the devfreq governor.
- * The values are chosen based on experiments.
- */
- dmc->gov_data.upthreshold = 30;
- dmc->gov_data.downdifferential = 5;
+ /* There is two modes in which the driver works: polling or IRQ */
+ irq = platform_get_irq(pdev, 0);
+ if (irq < 0) {
+ ret = exynos5_performance_counters_init(dmc);
+ if (ret) {
+ dev_warn(dev, "couldn't probe performance counters\n");
+ goto remove_clocks;
+ }
+
+ /*
+ * Setup default thresholds for the devfreq governor.
+ * The values are chosen based on experiments.
+ */
+ dmc->gov_data.upthreshold = 30;
+ dmc->gov_data.downdifferential = 5;
+
+ exynos5_dmc_df_profile.polling_ms = 500;
+ } else {
+ ret = devm_request_threaded_irq(dev, irq, NULL,
+ dmc_irq_thread, IRQF_ONESHOT,
+ dev_name(dev), dmc);
+ if (ret) {
+ dev_err(dev, "couldn't grab IRQ\n");
+ goto remove_clocks;
+ }
+
+ /*
+ * Setup default thresholds for the devfreq governor.
+ * The values are chosen based on experiments.
+ */
+ dmc->gov_data.upthreshold = 55;
+ dmc->gov_data.downdifferential = 5;
+
+ exynos5_dmc_enable_perf_events(dmc);
+ }
+
dmc->df = devm_devfreq_add_device(dev, &exynos5_dmc_df_profile,
DEVFREQ_GOV_SIMPLE_ONDEMAND,
@@ -1200,12 +1438,18 @@ static int exynos5_dmc_probe(struct platform_device *pdev)
goto err_devfreq_add;
}
+ if (dmc->in_irq_mode)
+ exynos5_dmc_start_perf_events(dmc, PERF_COUNTER_START_VALUE);
+
dev_info(dev, "DMC initialized\n");
return 0;
err_devfreq_add:
- exynos5_counters_disable_edev(dmc);
+ if (dmc->in_irq_mode)
+ exynos5_dmc_disable_perf_events(dmc);
+ else
+ exynos5_counters_disable_edev(dmc);
remove_clocks:
clk_disable_unprepare(dmc->mout_bpll);
clk_disable_unprepare(dmc->fout_bpll);
@@ -1225,7 +1469,10 @@ static int exynos5_dmc_remove(struct platform_device *pdev)
{
struct exynos5_dmc *dmc = dev_get_drvdata(&pdev->dev);
- exynos5_counters_disable_edev(dmc);
+ if (dmc->in_irq_mode)
+ exynos5_dmc_disable_perf_events(dmc);
+ else
+ exynos5_counters_disable_edev(dmc);
clk_disable_unprepare(dmc->mout_bpll);
clk_disable_unprepare(dmc->fout_bpll);
--
2.17.1
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* [PATCH 2/3] ARM: dts: exynos: map 0x10000 SFR instead of 0x100 in DMC Exynos5422
From: Lukasz Luba @ 2019-09-25 16:18 UTC (permalink / raw)
To: devicetree, linux-kernel, linux-pm, linux-samsung-soc,
linux-arm-kernel
Cc: mark.rutland, willy.mh.wolff.ml, robh+dt, b.zolnierkie, krzk,
Lukasz Luba, cw00.choi, kyungmin.park, kgene, myungjoo.ham,
s.nawrocki, m.szyprowski
In-Reply-To: <20190925161813.21117-1-l.luba@partner.samsung.com>
There is a need to access registers at address offset near 0x10000.
These registers are private DMC performance counters, which might be used
as interrupt trigger when overflow. Potential usage is to skip polling
in devfreq framework and switch to interrupt managed bandwidth control.
Signed-off-by: Lukasz Luba <l.luba@partner.samsung.com>
---
arch/arm/boot/dts/exynos5420.dtsi | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/arm/boot/dts/exynos5420.dtsi b/arch/arm/boot/dts/exynos5420.dtsi
index 72738e620d11..b695f07f7eed 100644
--- a/arch/arm/boot/dts/exynos5420.dtsi
+++ b/arch/arm/boot/dts/exynos5420.dtsi
@@ -239,7 +239,7 @@
dmc: memory-controller@10c20000 {
compatible = "samsung,exynos5422-dmc";
- reg = <0x10c20000 0x100>, <0x10c30000 0x100>;
+ reg = <0x10c20000 0x10000>, <0x10c30000 0x10000>;
interrupt-parent = <&combiner>;
interrupts = <16 0>;
clocks = <&clock CLK_FOUT_SPLL>,
--
2.17.1
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* [PATCH 1/3] ARM: dts: exynos: Add interrupt to DMC controller in Exynos5422
From: Lukasz Luba @ 2019-09-25 16:18 UTC (permalink / raw)
To: devicetree, linux-kernel, linux-pm, linux-samsung-soc,
linux-arm-kernel
Cc: mark.rutland, willy.mh.wolff.ml, robh+dt, b.zolnierkie, krzk,
Lukasz Luba, cw00.choi, kyungmin.park, kgene, myungjoo.ham,
s.nawrocki, m.szyprowski
In-Reply-To: <20190925161813.21117-1-l.luba@partner.samsung.com>
Add interrupt to Dynamic Memory Controller in Exynos5422 and Odroid
XU3-family boards. It will be used instead of devfreq polling mode
governor. The interrupt is connected to performance counters private
for DMC, which might track utilisation of the memory channels.
Signed-off-by: Lukasz Luba <l.luba@partner.samsung.com>
---
arch/arm/boot/dts/exynos5420.dtsi | 2 ++
1 file changed, 2 insertions(+)
diff --git a/arch/arm/boot/dts/exynos5420.dtsi b/arch/arm/boot/dts/exynos5420.dtsi
index ac49373baae7..72738e620d11 100644
--- a/arch/arm/boot/dts/exynos5420.dtsi
+++ b/arch/arm/boot/dts/exynos5420.dtsi
@@ -240,6 +240,8 @@
dmc: memory-controller@10c20000 {
compatible = "samsung,exynos5422-dmc";
reg = <0x10c20000 0x100>, <0x10c30000 0x100>;
+ interrupt-parent = <&combiner>;
+ interrupts = <16 0>;
clocks = <&clock CLK_FOUT_SPLL>,
<&clock CLK_MOUT_SCLK_SPLL>,
<&clock CLK_FF_DOUT_SPLL2>,
--
2.17.1
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* [PATCH 0/3] Exynos5 DMC interrupt mode
From: Lukasz Luba @ 2019-09-25 16:18 UTC (permalink / raw)
To: devicetree, linux-kernel, linux-pm, linux-samsung-soc,
linux-arm-kernel
Cc: mark.rutland, willy.mh.wolff.ml, robh+dt, b.zolnierkie, krzk,
Lukasz Luba, cw00.choi, kyungmin.park, kgene, myungjoo.ham,
s.nawrocki, m.szyprowski
In-Reply-To: <CGME20190925161841eucas1p12b3b798020b3493e9a4804d98b422f17@eucas1p1.samsung.com>
Hi all,
This is a patch set for the Exynos5 Dynamic Memory Controller
driver which could be found in Krzysztof's tree [1]. It is on top of a
merge of the two branches [1][2].
It adds interrupt mode which does not relay on devfreq polling.
Instead of checking the device state by the framework, driver uses local
performance events counters which could trigger interrupt when overflow.
Thanks to this approach the driver avoids issues present in devfreq framework,
when default polling check does not occur.
The algorithm calculates 'busy_time' and 'total_time' needed for devfreq
governors (simple_ondemand) based on requests transactions traffic.
Regards,
Lukasz Luba
[1] https://git.kernel.org/pub/scm/linux/kernel/git/krzk/linux.git/log/?h=for-v5.4-5.5/memory-samsung-dmc
[2] https://git.kernel.org/pub/scm/linux/kernel/git/krzk/linux.git/log/?h=for-v5.4-5.5/memory-samsung-dmc-dt
Lukasz Luba (3):
ARM: dts: exynos: Add interrupt to DMC controller in Exynos5422
ARM: dts: exynos: map 0x10000 SFR instead of 0x100 in DMC Exynos5422
memory: samsung: exynos5422-dmc: Add support for interrupt from
performance counters
arch/arm/boot/dts/exynos5420.dtsi | 4 +-
drivers/memory/samsung/exynos5422-dmc.c | 297 ++++++++++++++++++++++--
2 files changed, 275 insertions(+), 26 deletions(-)
--
2.17.1
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* Re: [PATCH 00/11] of: Fix DMA configuration for non-DT masters
From: Rob Herring @ 2019-09-25 16:16 UTC (permalink / raw)
To: Nicolas Saenz Julienne
Cc: devicetree, Matthias Brugger, Frank Rowand, linux-arm-msm,
linux-wireless, linux-kernel@vger.kernel.org, dri-devel, etnaviv,
open list:DMA GENERIC OFFLOAD ENGINE SUBSYSTEM, Florian Fainelli,
Stefan Wahren, james.quinlan, linux-pci, linux-tegra, xen-devel,
Dan Williams, freedreno, Robin Murphy,
moderated list:ARM/FREESCALE IMX / MXC ARM ARCHITECTURE,
Linux Media Mailing List
In-Reply-To: <43fb5fe1de317d65a4edf592f88ea150c6e3b8cc.camel@suse.de>
On Wed, Sep 25, 2019 at 10:30 AM Nicolas Saenz Julienne
<nsaenzjulienne@suse.de> wrote:
>
> On Wed, 2019-09-25 at 16:09 +0100, Robin Murphy wrote:
> > On 25/09/2019 15:52, Nicolas Saenz Julienne wrote:
> > > On Tue, 2019-09-24 at 16:59 -0500, Rob Herring wrote:
> > > > On Tue, Sep 24, 2019 at 1:12 PM Nicolas Saenz Julienne
> > > > <nsaenzjulienne@suse.de> wrote:
> > > > > Hi All,
> > > > > this series tries to address one of the issues blocking us from
> > > > > upstreaming Broadcom's STB PCIe controller[1]. Namely, the fact that
> > > > > devices not represented in DT which sit behind a PCI bus fail to get the
> > > > > bus' DMA addressing constraints.
> > > > >
> > > > > This is due to the fact that of_dma_configure() assumes it's receiving a
> > > > > DT node representing the device being configured, as opposed to the PCIe
> > > > > bridge node we currently pass. This causes the code to directly jump
> > > > > into PCI's parent node when checking for 'dma-ranges' and misses
> > > > > whatever was set there.
> > > > >
> > > > > To address this I create a new API in OF - inspired from Robin Murphys
> > > > > original proposal[2] - which accepts a bus DT node as it's input in
> > > > > order to configure a device's DMA constraints. The changes go deep into
> > > > > of/address.c's implementation, as a device being having a DT node
> > > > > assumption was pretty strong.
> > > > >
> > > > > On top of this work, I also cleaned up of_dma_configure() removing its
> > > > > redundant arguments and creating an alternative function for the special
> > > > > cases
> > > > > not applicable to either the above case or the default usage.
> > > > >
> > > > > IMO the resulting functions are more explicit. They will probably
> > > > > surface some hacky usages that can be properly fixed as I show with the
> > > > > DT fixes on the Layerscape platform.
> > > > >
> > > > > This was also tested on a Raspberry Pi 4 with a custom PCIe driver and
> > > > > on a Seattle AMD board.
> > > >
> > > > Humm, I've been working on this issue too. Looks similar though yours
> > > > has a lot more churn and there's some other bugs I've found.
> > >
> > > That's good news, and yes now that I see it, some stuff on my series is
> > > overly
> > > complicated. Specially around of_translate_*().
> > >
> > > On top of that, you removed in of_dma_get_range():
> > >
> > > - /*
> > > - * At least empty ranges has to be defined for parent node if
> > > - * DMA is supported
> > > - */
> > > - if (!ranges)
> > > - break;
> > >
> > > Which I assumed was bound to the standard and makes things easier.
> > >
> > > > Can you test out this branch[1]. I don't have any h/w needing this,
> > > > but wrote a unittest and tested with modified QEMU.
> > >
> > > I reviewed everything, I did find a minor issue, see the patch attached.
> >
> > WRT that patch, the original intent of "force_dma" was purely to
> > consider a device DMA-capable regardless of the presence of
> > "dma-ranges". Expecting of_dma_configure() to do anything for a non-OF
> > device has always been bogus - magic paravirt devices which appear out
> > of nowhere and expect to be treated as genuine DMA masters are a
> > separate problem that we haven't really approached yet.
>
> I agree it's clearly abusing the function. I have no problem with the behaviour
> change if it's OK with you.
>
> Robin, have you looked into supporting multiple dma-ranges? It's the next thing
> we need for BCM STB's PCIe. I'll have a go at it myself if nothing is in the
> works already.
Multiple dma-ranges as far as configuring inbound windows should work
already other than the bug when there's any parent translation. But if
you mean supporting multiple DMA offsets and masks per device in the
DMA API, there's nothing in the works yet.
Rob
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* [RFC PATCH 18/18] net: wireguard - switch to crypto API for packet encryption
From: Ard Biesheuvel @ 2019-09-25 16:12 UTC (permalink / raw)
To: linux-crypto
Cc: Jason A . Donenfeld, Catalin Marinas, Herbert Xu, Arnd Bergmann,
Ard Biesheuvel, Greg KH, Eric Biggers, Samuel Neves, Will Deacon,
Dan Carpenter, Andy Lutomirski, Marc Zyngier, Linus Torvalds,
David Miller, linux-arm-kernel
In-Reply-To: <20190925161255.1871-1-ard.biesheuvel@linaro.org>
Replace the chacha20poly1305() library calls with invocations of the
RFC7539 AEAD, as implemented by the generic chacha20poly1305 template.
For now, only synchronous AEADs are supported, but looking at the code,
it does not look terribly complicated to add support for async versions
of rfc7539(chacha20,poly1305) as well, some of which already exist in
the drivers/crypto tree.
The nonce related changes are there to address the mismatch between the
96-bit nonce (aka IV) that the rfc7539() template expects, and the 64-bit
nonce that WireGuard uses.
Note that these changes take advantage of the fact that synchronous
instantiations of the generic rfc7539() template will use a zero reqsize
if possible, removing the need for heap allocations for the request
structures.
This code was tested using the included netns.sh script, and by connecting
to the WireGuard demo server
(https://www.wireguard.com/quickstart/#demo-server)
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
---
drivers/net/wireguard/noise.c | 34 ++++++++++++-
drivers/net/wireguard/noise.h | 3 +-
drivers/net/wireguard/queueing.h | 5 +-
drivers/net/wireguard/receive.c | 51 ++++++++++++--------
drivers/net/wireguard/send.c | 45 ++++++++++-------
5 files changed, 97 insertions(+), 41 deletions(-)
diff --git a/drivers/net/wireguard/noise.c b/drivers/net/wireguard/noise.c
index bf0b8c5ab298..0e7aab9f645d 100644
--- a/drivers/net/wireguard/noise.c
+++ b/drivers/net/wireguard/noise.c
@@ -109,16 +109,37 @@ static struct noise_keypair *keypair_create(struct wg_peer *peer)
if (unlikely(!keypair))
return NULL;
+
+ keypair->sending.tfm = crypto_alloc_aead("rfc7539(chacha20,poly1305)",
+ 0, CRYPTO_ALG_ASYNC);
+ if (unlikely(IS_ERR(keypair->sending.tfm)))
+ goto free_keypair;
+ keypair->receiving.tfm = crypto_alloc_aead("rfc7539(chacha20,poly1305)",
+ 0, CRYPTO_ALG_ASYNC);
+ if (unlikely(IS_ERR(keypair->receiving.tfm)))
+ goto free_sending_tfm;
+
keypair->internal_id = atomic64_inc_return(&keypair_counter);
keypair->entry.type = INDEX_HASHTABLE_KEYPAIR;
keypair->entry.peer = peer;
kref_init(&keypair->refcount);
return keypair;
+
+free_sending_tfm:
+ crypto_free_aead(keypair->sending.tfm);
+free_keypair:
+ kzfree(keypair);
+ return NULL;
}
static void keypair_free_rcu(struct rcu_head *rcu)
{
- kzfree(container_of(rcu, struct noise_keypair, rcu));
+ struct noise_keypair *keypair =
+ container_of(rcu, struct noise_keypair, rcu);
+
+ crypto_free_aead(keypair->sending.tfm);
+ crypto_free_aead(keypair->receiving.tfm);
+ kzfree(keypair);
}
static void keypair_free_kref(struct kref *kref)
@@ -360,11 +381,20 @@ static void derive_keys(struct noise_symmetric_key *first_dst,
struct noise_symmetric_key *second_dst,
const u8 chaining_key[NOISE_HASH_LEN])
{
- kdf(first_dst->key, second_dst->key, NULL, NULL,
+ u8 key[2][NOISE_SYMMETRIC_KEY_LEN];
+ int err;
+
+ kdf(key[0], key[1], NULL, NULL,
NOISE_SYMMETRIC_KEY_LEN, NOISE_SYMMETRIC_KEY_LEN, 0, 0,
chaining_key);
symmetric_key_init(first_dst);
symmetric_key_init(second_dst);
+
+ err = crypto_aead_setkey(first_dst->tfm, key[0], sizeof(key[0])) ?:
+ crypto_aead_setkey(second_dst->tfm, key[1], sizeof(key[1]));
+ memzero_explicit(key, sizeof(key));
+ if (unlikely(err))
+ pr_warn_once("crypto_aead_setkey() failed (%d)\n", err);
}
static bool __must_check mix_dh(u8 chaining_key[NOISE_HASH_LEN],
diff --git a/drivers/net/wireguard/noise.h b/drivers/net/wireguard/noise.h
index 9c2cc62dc11e..6f033d2ea52c 100644
--- a/drivers/net/wireguard/noise.h
+++ b/drivers/net/wireguard/noise.h
@@ -8,6 +8,7 @@
#include "messages.h"
#include "peerlookup.h"
+#include <crypto/aead.h>
#include <linux/types.h>
#include <linux/spinlock.h>
#include <linux/atomic.h>
@@ -26,7 +27,7 @@ union noise_counter {
};
struct noise_symmetric_key {
- u8 key[NOISE_SYMMETRIC_KEY_LEN];
+ struct crypto_aead *tfm;
union noise_counter counter;
u64 birthdate;
bool is_valid;
diff --git a/drivers/net/wireguard/queueing.h b/drivers/net/wireguard/queueing.h
index f8de703dff97..593971edf8a3 100644
--- a/drivers/net/wireguard/queueing.h
+++ b/drivers/net/wireguard/queueing.h
@@ -55,9 +55,10 @@ enum packet_state {
};
struct packet_cb {
- u64 nonce;
- struct noise_keypair *keypair;
atomic_t state;
+ __le32 ivpad; /* pad 64-bit nonce to 96 bits */
+ __le64 nonce;
+ struct noise_keypair *keypair;
u32 mtu;
u8 ds;
};
diff --git a/drivers/net/wireguard/receive.c b/drivers/net/wireguard/receive.c
index 900c76edb9d6..395089e7e3a6 100644
--- a/drivers/net/wireguard/receive.c
+++ b/drivers/net/wireguard/receive.c
@@ -11,7 +11,7 @@
#include "cookie.h"
#include "socket.h"
-#include <linux/simd.h>
+#include <crypto/aead.h>
#include <linux/ip.h>
#include <linux/ipv6.h>
#include <linux/udp.h>
@@ -244,13 +244,14 @@ static void keep_key_fresh(struct wg_peer *peer)
}
}
-static bool decrypt_packet(struct sk_buff *skb, struct noise_symmetric_key *key,
- simd_context_t *simd_context)
+static bool decrypt_packet(struct sk_buff *skb, struct noise_symmetric_key *key)
{
struct scatterlist sg[MAX_SKB_FRAGS + 8];
+ struct aead_request *req, stackreq;
struct sk_buff *trailer;
unsigned int offset;
int num_frags;
+ int err;
if (unlikely(!key))
return false;
@@ -262,8 +263,8 @@ static bool decrypt_packet(struct sk_buff *skb, struct noise_symmetric_key *key,
return false;
}
- PACKET_CB(skb)->nonce =
- le64_to_cpu(((struct message_data *)skb->data)->counter);
+ PACKET_CB(skb)->ivpad = 0;
+ PACKET_CB(skb)->nonce = ((struct message_data *)skb->data)->counter;
/* We ensure that the network header is part of the packet before we
* call skb_cow_data, so that there's no chance that data is removed
@@ -281,9 +282,23 @@ static bool decrypt_packet(struct sk_buff *skb, struct noise_symmetric_key *key,
if (skb_to_sgvec(skb, sg, 0, skb->len) <= 0)
return false;
- if (!chacha20poly1305_decrypt_sg(sg, sg, skb->len, NULL, 0,
- PACKET_CB(skb)->nonce, key->key,
- simd_context))
+ if (unlikely(crypto_aead_reqsize(key->tfm) > 0)) {
+ req = aead_request_alloc(key->tfm, GFP_ATOMIC);
+ if (!req)
+ return false;
+ } else {
+ req = &stackreq;
+ aead_request_set_tfm(req, key->tfm);
+ }
+
+ aead_request_set_ad(req, 0);
+ aead_request_set_callback(req, 0, NULL, NULL);
+ aead_request_set_crypt(req, sg, sg, skb->len,
+ (u8 *)&PACKET_CB(skb)->ivpad);
+ err = crypto_aead_decrypt(req);
+ if (unlikely(req != &stackreq))
+ aead_request_free(req);
+ if (err)
return false;
/* Another ugly situation of pushing and pulling the header so as to
@@ -475,10 +490,10 @@ int wg_packet_rx_poll(struct napi_struct *napi, int budget)
goto next;
if (unlikely(!counter_validate(&keypair->receiving.counter,
- PACKET_CB(skb)->nonce))) {
+ le64_to_cpu(PACKET_CB(skb)->nonce)))) {
net_dbg_ratelimited("%s: Packet has invalid nonce %llu (max %llu)\n",
peer->device->dev->name,
- PACKET_CB(skb)->nonce,
+ le64_to_cpu(PACKET_CB(skb)->nonce),
keypair->receiving.counter.receive.counter);
goto next;
}
@@ -510,21 +525,19 @@ void wg_packet_decrypt_worker(struct work_struct *work)
{
struct crypt_queue *queue = container_of(work, struct multicore_worker,
work)->ptr;
- simd_context_t simd_context;
struct sk_buff *skb;
- simd_get(&simd_context);
while ((skb = ptr_ring_consume_bh(&queue->ring)) != NULL) {
- enum packet_state state = likely(decrypt_packet(skb,
- &PACKET_CB(skb)->keypair->receiving,
- &simd_context)) ?
- PACKET_STATE_CRYPTED : PACKET_STATE_DEAD;
+ enum packet_state state;
+
+ if (likely(decrypt_packet(skb,
+ &PACKET_CB(skb)->keypair->receiving)))
+ state = PACKET_STATE_CRYPTED;
+ else
+ state = PACKET_STATE_DEAD;
wg_queue_enqueue_per_peer_napi(&PACKET_PEER(skb)->rx_queue, skb,
state);
- simd_relax(&simd_context);
}
-
- simd_put(&simd_context);
}
static void wg_packet_consume_data(struct wg_device *wg, struct sk_buff *skb)
diff --git a/drivers/net/wireguard/send.c b/drivers/net/wireguard/send.c
index b0df5c717502..48d1fb02f575 100644
--- a/drivers/net/wireguard/send.c
+++ b/drivers/net/wireguard/send.c
@@ -11,7 +11,7 @@
#include "messages.h"
#include "cookie.h"
-#include <linux/simd.h>
+#include <crypto/aead.h>
#include <linux/uio.h>
#include <linux/inetdevice.h>
#include <linux/socket.h>
@@ -157,11 +157,11 @@ static unsigned int calculate_skb_padding(struct sk_buff *skb)
return padded_size - last_unit;
}
-static bool encrypt_packet(struct sk_buff *skb, struct noise_keypair *keypair,
- simd_context_t *simd_context)
+static bool encrypt_packet(struct sk_buff *skb, struct noise_keypair *keypair)
{
unsigned int padding_len, plaintext_len, trailer_len;
struct scatterlist sg[MAX_SKB_FRAGS + 8];
+ struct aead_request *req, stackreq;
struct message_data *header;
struct sk_buff *trailer;
int num_frags;
@@ -199,7 +199,7 @@ static bool encrypt_packet(struct sk_buff *skb, struct noise_keypair *keypair,
header = (struct message_data *)skb_push(skb, sizeof(*header));
header->header.type = cpu_to_le32(MESSAGE_DATA);
header->key_idx = keypair->remote_index;
- header->counter = cpu_to_le64(PACKET_CB(skb)->nonce);
+ header->counter = PACKET_CB(skb)->nonce;
pskb_put(skb, trailer, trailer_len);
/* Now we can encrypt the scattergather segments */
@@ -207,9 +207,24 @@ static bool encrypt_packet(struct sk_buff *skb, struct noise_keypair *keypair,
if (skb_to_sgvec(skb, sg, sizeof(struct message_data),
noise_encrypted_len(plaintext_len)) <= 0)
return false;
- return chacha20poly1305_encrypt_sg(sg, sg, plaintext_len, NULL, 0,
- PACKET_CB(skb)->nonce,
- keypair->sending.key, simd_context);
+
+ if (unlikely(crypto_aead_reqsize(keypair->sending.tfm) > 0)) {
+ req = aead_request_alloc(keypair->sending.tfm, GFP_ATOMIC);
+ if (!req)
+ return false;
+ } else {
+ req = &stackreq;
+ aead_request_set_tfm(req, keypair->sending.tfm);
+ }
+
+ aead_request_set_ad(req, 0);
+ aead_request_set_callback(req, 0, NULL, NULL);
+ aead_request_set_crypt(req, sg, sg, plaintext_len,
+ (u8 *)&PACKET_CB(skb)->ivpad);
+ crypto_aead_encrypt(req);
+ if (unlikely(req != &stackreq))
+ aead_request_free(req);
+ return true;
}
void wg_packet_send_keepalive(struct wg_peer *peer)
@@ -296,16 +311,13 @@ void wg_packet_encrypt_worker(struct work_struct *work)
struct crypt_queue *queue = container_of(work, struct multicore_worker,
work)->ptr;
struct sk_buff *first, *skb, *next;
- simd_context_t simd_context;
- simd_get(&simd_context);
while ((first = ptr_ring_consume_bh(&queue->ring)) != NULL) {
enum packet_state state = PACKET_STATE_CRYPTED;
skb_walk_null_queue_safe(first, skb, next) {
if (likely(encrypt_packet(skb,
- PACKET_CB(first)->keypair,
- &simd_context))) {
+ PACKET_CB(first)->keypair))) {
wg_reset_packet(skb);
} else {
state = PACKET_STATE_DEAD;
@@ -314,10 +326,7 @@ void wg_packet_encrypt_worker(struct work_struct *work)
}
wg_queue_enqueue_per_peer(&PACKET_PEER(first)->tx_queue, first,
state);
-
- simd_relax(&simd_context);
}
- simd_put(&simd_context);
}
static void wg_packet_create_data(struct sk_buff *first)
@@ -389,13 +398,15 @@ void wg_packet_send_staged_packets(struct wg_peer *peer)
* handshake.
*/
skb_queue_walk(&packets, skb) {
+ u64 counter = atomic64_inc_return(&key->counter.counter) - 1;
+
/* 0 for no outer TOS: no leak. TODO: at some later point, we
* might consider using flowi->tos as outer instead.
*/
PACKET_CB(skb)->ds = ip_tunnel_ecn_encap(0, ip_hdr(skb), skb);
- PACKET_CB(skb)->nonce =
- atomic64_inc_return(&key->counter.counter) - 1;
- if (unlikely(PACKET_CB(skb)->nonce >= REJECT_AFTER_MESSAGES))
+ PACKET_CB(skb)->ivpad = 0;
+ PACKET_CB(skb)->nonce = cpu_to_le64(counter);
+ if (unlikely(counter >= REJECT_AFTER_MESSAGES))
goto out_invalid;
}
--
2.20.1
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* [RFC PATCH 17/18] wg switch to lib/crypto algos
From: Ard Biesheuvel @ 2019-09-25 16:12 UTC (permalink / raw)
To: linux-crypto
Cc: Jason A . Donenfeld, Catalin Marinas, Herbert Xu, Arnd Bergmann,
Ard Biesheuvel, Greg KH, Eric Biggers, Samuel Neves, Will Deacon,
Dan Carpenter, Andy Lutomirski, Marc Zyngier, Linus Torvalds,
David Miller, linux-arm-kernel
In-Reply-To: <20190925161255.1871-1-ard.biesheuvel@linaro.org>
---
drivers/net/Kconfig | 6 +++---
drivers/net/wireguard/cookie.c | 4 ++--
drivers/net/wireguard/messages.h | 6 +++---
3 files changed, 8 insertions(+), 8 deletions(-)
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index c26aef673538..3bd4dc662392 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -77,9 +77,9 @@ config WIREGUARD
depends on IPV6 || !IPV6
select NET_UDP_TUNNEL
select DST_CACHE
- select ZINC_CHACHA20POLY1305
- select ZINC_BLAKE2S
- select ZINC_CURVE25519
+ select CRYPTO_LIB_CHACHA20POLY1305
+ select CRYPTO_LIB_BLAKE2S
+ select CRYPTO_LIB_CURVE25519
help
WireGuard is a secure, fast, and easy to use replacement for IPSec
that uses modern cryptography and clever networking tricks. It's
diff --git a/drivers/net/wireguard/cookie.c b/drivers/net/wireguard/cookie.c
index bd23a14ff87f..104b739c327f 100644
--- a/drivers/net/wireguard/cookie.c
+++ b/drivers/net/wireguard/cookie.c
@@ -10,8 +10,8 @@
#include "ratelimiter.h"
#include "timers.h"
-#include <zinc/blake2s.h>
-#include <zinc/chacha20poly1305.h>
+#include <crypto/blake2s.h>
+#include <crypto/chacha20poly1305.h>
#include <net/ipv6.h>
#include <crypto/algapi.h>
diff --git a/drivers/net/wireguard/messages.h b/drivers/net/wireguard/messages.h
index 3cfd1c5e9b02..4bbb1f97af04 100644
--- a/drivers/net/wireguard/messages.h
+++ b/drivers/net/wireguard/messages.h
@@ -6,9 +6,9 @@
#ifndef _WG_MESSAGES_H
#define _WG_MESSAGES_H
-#include <zinc/curve25519.h>
-#include <zinc/chacha20poly1305.h>
-#include <zinc/blake2s.h>
+#include <crypto/blake2s.h>
+#include <crypto/chacha20poly1305.h>
+#include <crypto/curve25519.h>
#include <linux/kernel.h>
#include <linux/param.h>
--
2.20.1
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox