* [PATCH/RFT 2/2] arm64: dts: renesas: r8a77965: Add PCIe device nodes
From: Simon Horman @ 2018-06-11 8:28 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1528373494-18503-3-git-send-email-ykaneko0929@gmail.com>
On Thu, Jun 07, 2018 at 09:11:34PM +0900, Yoshihiro Kaneko wrote:
> From: Takeshi Kihara <takeshi.kihara.df@renesas.com>
>
> This patch adds PCIe{0,1} device nodes to R8A77965 SoC.
>
> Based on a similar patches of the R8A7796 device tree
> by Harunobu Kurokawa <harunobu.kurokawa.dn@renesas.com>.
>
> Signed-off-by: Takeshi Kihara <takeshi.kihara.df@renesas.com>
> Signed-off-by: Yoshihiro Kaneko <ykaneko0929@gmail.com>
Hi,
This looks fine to me but I will wait to see if there are other reviews
before applying.
Reviewed-by: Simon Horman <horms+renesas@verge.net.au>
^ permalink raw reply
* [PATCH v3 1/3] ASoC: simple-card-utils: move hp and mic detect gpios from simple-card
From: Katsuhiro Suzuki @ 2018-06-11 8:32 UTC (permalink / raw)
To: linux-arm-kernel
This patch moves headphone and microphone jack detection gpios from
simple-card driver. It is preparing for using this feature from other
drivers.
Signed-off-by: Katsuhiro Suzuki <suzuki.katsuhiro@socionext.com>
---
Changes from v2:
- Nothing
Changes from v1:
- Move changes of audio-graph-card to other patch
---
include/sound/simple_card_utils.h | 15 +++++++
sound/soc/generic/simple-card-utils.c | 59 ++++++++++++++++++++++++
sound/soc/generic/simple-card.c | 64 ---------------------------
3 files changed, 74 insertions(+), 64 deletions(-)
diff --git a/include/sound/simple_card_utils.h b/include/sound/simple_card_utils.h
index 7e25afce6566..f82acef3b992 100644
--- a/include/sound/simple_card_utils.h
+++ b/include/sound/simple_card_utils.h
@@ -12,6 +12,11 @@
#include <sound/soc.h>
+#define asoc_simple_card_init_hp(card, sjack, prefix) \
+ asoc_simple_card_init_jack(card, sjack, 1, prefix)
+#define asoc_simple_card_init_mic(card, sjack, prefix) \
+ asoc_simple_card_init_jack(card, sjack, 0, prefix)
+
struct asoc_simple_dai {
const char *name;
unsigned int sysclk;
@@ -28,6 +33,12 @@ struct asoc_simple_card_data {
u32 convert_channels;
};
+struct asoc_simple_jack {
+ struct snd_soc_jack jack;
+ struct snd_soc_jack_pin pin;
+ struct snd_soc_jack_gpio gpio;
+};
+
int asoc_simple_card_parse_daifmt(struct device *dev,
struct device_node *node,
struct device_node *codec,
@@ -107,4 +118,8 @@ int asoc_simple_card_of_parse_routing(struct snd_soc_card *card,
int asoc_simple_card_of_parse_widgets(struct snd_soc_card *card,
char *prefix);
+int asoc_simple_card_init_jack(struct snd_soc_card *card,
+ struct asoc_simple_jack *sjack,
+ int is_hp, char *prefix);
+
#endif /* __SIMPLE_CARD_UTILS_H */
diff --git a/sound/soc/generic/simple-card-utils.c b/sound/soc/generic/simple-card-utils.c
index 3751a07de6aa..4398c9580929 100644
--- a/sound/soc/generic/simple-card-utils.c
+++ b/sound/soc/generic/simple-card-utils.c
@@ -8,9 +8,13 @@
* published by the Free Software Foundation.
*/
#include <linux/clk.h>
+#include <linux/gpio.h>
+#include <linux/gpio/consumer.h>
#include <linux/module.h>
#include <linux/of.h>
+#include <linux/of_gpio.h>
#include <linux/of_graph.h>
+#include <sound/jack.h>
#include <sound/simple_card_utils.h>
void asoc_simple_card_convert_fixup(struct asoc_simple_card_data *data,
@@ -419,6 +423,61 @@ int asoc_simple_card_of_parse_widgets(struct snd_soc_card *card,
}
EXPORT_SYMBOL_GPL(asoc_simple_card_of_parse_widgets);
+int asoc_simple_card_init_jack(struct snd_soc_card *card,
+ struct asoc_simple_jack *sjack,
+ int is_hp, char *prefix)
+{
+ struct device *dev = card->dev;
+ enum of_gpio_flags flags;
+ char prop[128];
+ char *pin_name;
+ char *gpio_name;
+ int mask;
+ int det;
+
+ if (!prefix)
+ prefix = "";
+
+ sjack->gpio.gpio = -ENOENT;
+
+ if (is_hp) {
+ snprintf(prop, sizeof(prop), "%shp-det-gpio", prefix);
+ pin_name = "Headphones";
+ gpio_name = "Headphone detection";
+ mask = SND_JACK_HEADPHONE;
+ } else {
+ snprintf(prop, sizeof(prop), "%smic-det-gpio", prefix);
+ pin_name = "Mic Jack";
+ gpio_name = "Mic detection";
+ mask = SND_JACK_MICROPHONE;
+ }
+
+ det = of_get_named_gpio_flags(dev->of_node, prop, 0, &flags);
+ if (det == -EPROBE_DEFER)
+ return -EPROBE_DEFER;
+
+ if (gpio_is_valid(det)) {
+ sjack->pin.pin = pin_name;
+ sjack->pin.mask = mask;
+
+ sjack->gpio.name = gpio_name;
+ sjack->gpio.report = mask;
+ sjack->gpio.gpio = det;
+ sjack->gpio.invert = !!(flags & OF_GPIO_ACTIVE_LOW);
+ sjack->gpio.debounce_time = 150;
+
+ snd_soc_card_jack_new(card, pin_name, mask,
+ &sjack->jack,
+ &sjack->pin, 1);
+
+ snd_soc_jack_add_gpios(&sjack->jack, 1,
+ &sjack->gpio);
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(asoc_simple_card_init_jack);
+
/* Module information */
MODULE_AUTHOR("Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>");
MODULE_DESCRIPTION("ALSA SoC Simple Card Utils");
diff --git a/sound/soc/generic/simple-card.c b/sound/soc/generic/simple-card.c
index 4a516c428b3d..1bbd9e46bf2a 100644
--- a/sound/soc/generic/simple-card.c
+++ b/sound/soc/generic/simple-card.c
@@ -10,23 +10,14 @@
*/
#include <linux/clk.h>
#include <linux/device.h>
-#include <linux/gpio.h>
#include <linux/module.h>
#include <linux/of.h>
-#include <linux/of_gpio.h>
#include <linux/platform_device.h>
#include <linux/string.h>
-#include <sound/jack.h>
#include <sound/simple_card.h>
#include <sound/soc-dai.h>
#include <sound/soc.h>
-struct asoc_simple_jack {
- struct snd_soc_jack jack;
- struct snd_soc_jack_pin pin;
- struct snd_soc_jack_gpio gpio;
-};
-
struct simple_card_data {
struct snd_soc_card snd_card;
struct simple_dai_props {
@@ -49,61 +40,6 @@ struct simple_card_data {
#define CELL "#sound-dai-cells"
#define PREFIX "simple-audio-card,"
-#define asoc_simple_card_init_hp(card, sjack, prefix)\
- asoc_simple_card_init_jack(card, sjack, 1, prefix)
-#define asoc_simple_card_init_mic(card, sjack, prefix)\
- asoc_simple_card_init_jack(card, sjack, 0, prefix)
-static int asoc_simple_card_init_jack(struct snd_soc_card *card,
- struct asoc_simple_jack *sjack,
- int is_hp, char *prefix)
-{
- struct device *dev = card->dev;
- enum of_gpio_flags flags;
- char prop[128];
- char *pin_name;
- char *gpio_name;
- int mask;
- int det;
-
- sjack->gpio.gpio = -ENOENT;
-
- if (is_hp) {
- snprintf(prop, sizeof(prop), "%shp-det-gpio", prefix);
- pin_name = "Headphones";
- gpio_name = "Headphone detection";
- mask = SND_JACK_HEADPHONE;
- } else {
- snprintf(prop, sizeof(prop), "%smic-det-gpio", prefix);
- pin_name = "Mic Jack";
- gpio_name = "Mic detection";
- mask = SND_JACK_MICROPHONE;
- }
-
- det = of_get_named_gpio_flags(dev->of_node, prop, 0, &flags);
- if (det == -EPROBE_DEFER)
- return -EPROBE_DEFER;
-
- if (gpio_is_valid(det)) {
- sjack->pin.pin = pin_name;
- sjack->pin.mask = mask;
-
- sjack->gpio.name = gpio_name;
- sjack->gpio.report = mask;
- sjack->gpio.gpio = det;
- sjack->gpio.invert = !!(flags & OF_GPIO_ACTIVE_LOW);
- sjack->gpio.debounce_time = 150;
-
- snd_soc_card_jack_new(card, pin_name, mask,
- &sjack->jack,
- &sjack->pin, 1);
-
- snd_soc_jack_add_gpios(&sjack->jack, 1,
- &sjack->gpio);
- }
-
- return 0;
-}
-
static int asoc_simple_card_startup(struct snd_pcm_substream *substream)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
--
2.17.1
^ permalink raw reply related
* [PATCH v3 2/3] ASoC: simple-card: move hp and mic detection to soc_card probe
From: Katsuhiro Suzuki @ 2018-06-11 8:32 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180611083214.16858-1-suzuki.katsuhiro@socionext.com>
This patch moves headphone and microphone detection to probe() of
snd_soc_card from init() of snd_soc_dai_link. This is because init()
is called (and an input device /dev/input/eventX is created too)
twice or above if simple card has two or more DAI links.
Signed-off-by: Katsuhiro Suzuki <suzuki.katsuhiro@socionext.com>
---
Changes from v2:
- Keep PREFIX of hp/mic detection properties
Changes from v1:
- Newly added
---
sound/soc/generic/simple-card.c | 25 +++++++++++++++++--------
1 file changed, 17 insertions(+), 8 deletions(-)
diff --git a/sound/soc/generic/simple-card.c b/sound/soc/generic/simple-card.c
index 1bbd9e46bf2a..da34016652c9 100644
--- a/sound/soc/generic/simple-card.c
+++ b/sound/soc/generic/simple-card.c
@@ -149,14 +149,6 @@ static int asoc_simple_card_dai_init(struct snd_soc_pcm_runtime *rtd)
if (ret < 0)
return ret;
- ret = asoc_simple_card_init_hp(rtd->card, &priv->hp_jack, PREFIX);
- if (ret < 0)
- return ret;
-
- ret = asoc_simple_card_init_mic(rtd->card, &priv->mic_jack, PREFIX);
- if (ret < 0)
- return ret;
-
return 0;
}
@@ -350,6 +342,22 @@ static int asoc_simple_card_parse_of(struct simple_card_data *priv)
return ret;
}
+static int asoc_simple_soc_card_probe(struct snd_soc_card *card)
+{
+ struct simple_card_data *priv = snd_soc_card_get_drvdata(card);
+ int ret;
+
+ ret = asoc_simple_card_init_hp(card, &priv->hp_jack, PREFIX);
+ if (ret < 0)
+ return ret;
+
+ ret = asoc_simple_card_init_mic(card, &priv->mic_jack, PREFIX);
+ if (ret < 0)
+ return ret;
+
+ return 0;
+}
+
static int asoc_simple_card_probe(struct platform_device *pdev)
{
struct simple_card_data *priv;
@@ -385,6 +393,7 @@ static int asoc_simple_card_probe(struct platform_device *pdev)
card->dev = dev;
card->dai_link = priv->dai_link;
card->num_links = num;
+ card->probe = asoc_simple_soc_card_probe;
if (np && of_device_is_available(np)) {
--
2.17.1
^ permalink raw reply related
* [PATCH v3 3/3] ASoC: audio-graph-card: add hp and mic detect gpios same as simple-card
From: Katsuhiro Suzuki @ 2018-06-11 8:32 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180611083214.16858-1-suzuki.katsuhiro@socionext.com>
This patch adds headphone and microphone jack detection gpios as same
as simple-card driver.
Signed-off-by: Katsuhiro Suzuki <suzuki.katsuhiro@socionext.com>
---
Changes from v2:
- Nothing
Changes from v1:
- Move changes of audio-graph-card to other patch
---
sound/soc/generic/audio-graph-card.c | 20 +++++++++++++++++++-
1 file changed, 19 insertions(+), 1 deletion(-)
diff --git a/sound/soc/generic/audio-graph-card.c b/sound/soc/generic/audio-graph-card.c
index 1b6164249341..2baa60d3b3cc 100644
--- a/sound/soc/generic/audio-graph-card.c
+++ b/sound/soc/generic/audio-graph-card.c
@@ -21,7 +21,6 @@
#include <linux/of_graph.h>
#include <linux/platform_device.h>
#include <linux/string.h>
-#include <sound/jack.h>
#include <sound/simple_card_utils.h>
struct graph_card_data {
@@ -32,6 +31,8 @@ struct graph_card_data {
unsigned int mclk_fs;
} *dai_props;
unsigned int mclk_fs;
+ struct asoc_simple_jack hp_jack;
+ struct asoc_simple_jack mic_jack;
struct snd_soc_dai_link *dai_link;
struct gpio_desc *pa_gpio;
};
@@ -278,6 +279,22 @@ static int asoc_graph_get_dais_count(struct device *dev)
return count;
}
+static int asoc_graph_soc_card_probe(struct snd_soc_card *card)
+{
+ struct graph_card_data *priv = snd_soc_card_get_drvdata(card);
+ int ret;
+
+ ret = asoc_simple_card_init_hp(card, &priv->hp_jack, NULL);
+ if (ret < 0)
+ return ret;
+
+ ret = asoc_simple_card_init_mic(card, &priv->mic_jack, NULL);
+ if (ret < 0)
+ return ret;
+
+ return 0;
+}
+
static int asoc_graph_card_probe(struct platform_device *pdev)
{
struct graph_card_data *priv;
@@ -319,6 +336,7 @@ static int asoc_graph_card_probe(struct platform_device *pdev)
card->num_links = num;
card->dapm_widgets = asoc_graph_card_dapm_widgets;
card->num_dapm_widgets = ARRAY_SIZE(asoc_graph_card_dapm_widgets);
+ card->probe = asoc_graph_soc_card_probe;
ret = asoc_graph_card_parse_of(priv);
if (ret < 0) {
--
2.17.1
^ permalink raw reply related
* [PATCH v1] ARM: imx: add imx7d-m4
From: Lucas Stach @ 2018-06-11 8:35 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180611082022.GG16091@dragon>
Hi Shawn,
Am Montag, den 11.06.2018, 16:20 +0800 schrieb Shawn Guo:
> On Mon, Jun 11, 2018 at 10:02:53AM +0200, Oleksij Rempel wrote:
> > Hi all,
> >
> > this patch was send 05.04.2018. Any comments?
> >
> > @Shawn, can you please take it?
>
> Honestly I'm not sure how useful it will be.??If we can have some i.MX
> developers ACK on it, I will be more comfortable to take it.
This is all highly experimental and in PoC stage, but we see some value
in running a second Linux system on the M4 coprocessor. There are lots
of things that still need to be figured out, but we are working on this
from time to time when there are some hours to spare.
This patch seems like a good step in the right direction and IMHO the
amount of code and changes is small enough to carry it upstream without
impacting anything else. I would be happy if this could be pulled in.
Regards,
Lucas
> >
> > On 05.04.2018 13:51, Oleksij Rempel wrote:
> > > Provide basic support for Cortex-M4 located on NXP iMX7D.
> > > This code was tested in combination with imx-rproc driver
> > > which will upload with specially formatted ELF image containing
> > > kernel, device and CPIO rootfs.
> > >
> > > > > > Signed-off-by: Oleksij Rempel <o.rempel@pengutronix.de>
> > > ---
> > > ?arch/arm/boot/dts/Makefile?????????|??2 +-
> > > ?arch/arm/mach-imx/Kconfig??????????| 33 +++++++++++++++++++++------------
> > > ?arch/arm/mach-imx/Makefile?????????|??3 ++-
> > > ?arch/arm/mach-imx/mach-imx7d-cm4.c | 21 +++++++++++++++++++++
> > > ?4 files changed, 45 insertions(+), 14 deletions(-)
> > > ?create mode 100644 arch/arm/mach-imx/mach-imx7d-cm4.c
> > >
> > > diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
> > > index 852452515bea..d49bb9a58aee 100644
> > > --- a/arch/arm/boot/dts/Makefile
> > > +++ b/arch/arm/boot/dts/Makefile
> > > @@ -527,7 +527,7 @@ dtb-$(CONFIG_SOC_IMX6UL) += \
> > > > > > ? imx6ul-tx6ul-0011.dtb \
> > > > > > ? imx6ul-tx6ul-mainboard.dtb \
> > > > > > ? imx6ull-14x14-evk.dtb
> > > -dtb-$(CONFIG_SOC_IMX7D) += \
> > > +dtb-$(CONFIG_SOC_IMX7D_CA7) += \
> > > > > > ? imx7d-cl-som-imx7.dtb \
> > > > > > ? imx7d-colibri-emmc-eval-v3.dtb \
> > > > > > ? imx7d-colibri-eval-v3.dtb \
> > > diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig
> > > index 782699e67600..101c8599d952 100644
> > > --- a/arch/arm/mach-imx/Kconfig
> > > +++ b/arch/arm/mach-imx/Kconfig
> > > @@ -528,18 +528,6 @@ config SOC_IMX6UL
> > > > > > ? help
> > > > > > ? ??This enables support for Freescale i.MX6 UltraLite processor.
> > > ?
> > > -config SOC_IMX7D
> > > > > > - bool "i.MX7 Dual support"
> > > > > > - select PINCTRL_IMX7D
> > > > > > - select ARM_GIC
> > > > > > - select HAVE_ARM_ARCH_TIMER
> > > > > > - select HAVE_IMX_ANATOP
> > > > > > - select HAVE_IMX_MMDC
> > > > > > - select HAVE_IMX_SRC
> > > > > > - select IMX_GPCV2
> > > > > > - help
> > > > > > - This enables support for Freescale i.MX7 Dual processor.
> > > -
> > > ?config SOC_LS1021A
> > > > > > ? bool "Freescale LS1021A support"
> > > > > > ? select ARM_GIC
> > > @@ -554,6 +542,27 @@ comment "Cortex-A/Cortex-M asymmetric multiprocessing platforms"
> > > ?
> > > ?if ARCH_MULTI_V7 || ARM_SINGLE_ARMV7M
> > > ?
> > > +config SOC_IMX7D_CA7
> > > > > > + bool
> > > > > > + select ARM_GIC
> > > > > > + select HAVE_ARM_ARCH_TIMER
> > > > > > + select HAVE_IMX_ANATOP
> > > > > > + select HAVE_IMX_MMDC
> > > > > > + select HAVE_IMX_SRC
> > > > > > + select IMX_GPCV2
> > > +
> > > +config SOC_IMX7D_CM4
> > > > > > + bool
> > > > > > + select ARMV7M_SYSTICK
> > > +
> > > +config SOC_IMX7D
> > > > > > + bool "i.MX7 Dual support"
> > > > > > + select PINCTRL_IMX7D
> > > > > > + select SOC_IMX7D_CA7 if ARCH_MULTI_V7
> > > > > > + select SOC_IMX7D_CM4 if ARM_SINGLE_ARMV7M
> > > > > > + help
> > > > > > + This enables support for Freescale i.MX7 Dual processor.
> > > +
> > > ?config SOC_VF610
> > > > > > ? bool "Vybrid Family VF610 support"
> > > > > > ? select ARM_GIC if ARCH_MULTI_V7
> > > diff --git a/arch/arm/mach-imx/Makefile b/arch/arm/mach-imx/Makefile
> > > index 8ff71058207d..68640f100ef3 100644
> > > --- a/arch/arm/mach-imx/Makefile
> > > +++ b/arch/arm/mach-imx/Makefile
> > > @@ -80,7 +80,8 @@ obj-$(CONFIG_SOC_IMX6Q) += mach-imx6q.o
> > > ?obj-$(CONFIG_SOC_IMX6SL) += mach-imx6sl.o
> > > ?obj-$(CONFIG_SOC_IMX6SX) += mach-imx6sx.o
> > > ?obj-$(CONFIG_SOC_IMX6UL) += mach-imx6ul.o
> > > -obj-$(CONFIG_SOC_IMX7D) += mach-imx7d.o
> > > +obj-$(CONFIG_SOC_IMX7D_CA7) += mach-imx7d.o
> > > +obj-$(CONFIG_SOC_IMX7D_CM4) += mach-imx7d-cm4.o
> > > ?
> > > ?ifeq ($(CONFIG_SUSPEND),y)
> > > ?AFLAGS_suspend-imx6.o :=-Wa,-march=armv7-a
> > > diff --git a/arch/arm/mach-imx/mach-imx7d-cm4.c b/arch/arm/mach-imx/mach-imx7d-cm4.c
> > > new file mode 100644
> > > index 000000000000..c36dea79aeb8
> > > --- /dev/null
> > > +++ b/arch/arm/mach-imx/mach-imx7d-cm4.c
> > > @@ -0,0 +1,21 @@
> > > +/*
> > > + * Copyright 2017 Pengutronix
> > > + *
> > > + * This program is free software; you can redistribute it and/or modify
> > > + * it under the terms of the GNU General Public License version 2 as
> > > + * published by the Free Software Foundation.
> > > + */
> > > +
> > > +#include <linux/kernel.h>
> > > +#include <asm/v7m.h>
> > > +#include <asm/mach/arch.h>
> > > +
> > > +static const char * const imx7d_cm4_dt_compat[] __initconst = {
> > > > > > + "fsl,imx7d-cm4",
> > > > > > + NULL,
> > > +};
> > > +
> > > +DT_MACHINE_START(IMX7D, "Freescale i.MX7 Dual Cortex-M4 (Device Tree)")
> > > > > > + .dt_compat = imx7d_cm4_dt_compat,
> > > > > > + .restart = armv7m_restart,
> > > +MACHINE_END
> > >
>
>
>
>
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* [PATCH v3 1/3] ASoC: simple-card-utils: move hp and mic detect gpios from simple-card
From: Kuninori Morimoto @ 2018-06-11 8:37 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180611083214.16858-1-suzuki.katsuhiro@socionext.com>
Hi
> This patch moves headphone and microphone jack detection gpios from
> simple-card driver. It is preparing for using this feature from other
> drivers.
>
> Signed-off-by: Katsuhiro Suzuki <suzuki.katsuhiro@socionext.com>
> ---
For all patches
Acked-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
^ permalink raw reply
* [PATCH 1/2] arm64: avoid alloc memory on offline node
From: Michal Hocko @ 2018-06-11 8:52 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <a880df29-b656-d98d-3037-b04761c7ed78@huawei.com>
On Mon 11-06-18 11:23:18, Xie XiuQi wrote:
> Hi Michal,
>
> On 2018/6/7 20:21, Michal Hocko wrote:
> > On Thu 07-06-18 19:55:53, Hanjun Guo wrote:
> >> On 2018/6/7 18:55, Michal Hocko wrote:
> > [...]
> >>> I am not sure I have the full context but pci_acpi_scan_root calls
> >>> kzalloc_node(sizeof(*info), GFP_KERNEL, node)
> >>> and that should fall back to whatever node that is online. Offline node
> >>> shouldn't keep any pages behind. So there must be something else going
> >>> on here and the patch is not the right way to handle it. What does
> >>> faddr2line __alloc_pages_nodemask+0xf0 tells on this kernel?
> >>
> >> The whole context is:
> >>
> >> The system is booted with a NUMA node has no memory attaching to it
> >> (memory-less NUMA node), also with NR_CPUS less than CPUs presented
> >> in MADT, so CPUs on this memory-less node are not brought up, and
> >> this NUMA node will not be online (but SRAT presents this NUMA node);
> >>
> >> Devices attaching to this NUMA node such as PCI host bridge still
> >> return the valid NUMA node via _PXM, but actually that valid NUMA node
> >> is not online which lead to this issue.
> >
> > But we should have other numa nodes on the zonelists so the allocator
> > should fall back to other node. If the zonelist is not intiailized
> > properly, though, then this can indeed show up as a problem. Knowing
> > which exact place has blown up would help get a better picture...
> >
>
> I specific a non-exist node to allocate memory using kzalloc_node,
> and got this following error message.
>
> And I found out there is just a VM_WARN, but it does not prevent the memory
> allocation continue.
>
> This nid would be use to access NODE_DADA(nid), so if nid is invalid,
> it would cause oops here.
>
> 459 /*
> 460 * Allocate pages, preferring the node given as nid. The node must be valid and
> 461 * online. For more general interface, see alloc_pages_node().
> 462 */
> 463 static inline struct page *
> 464 __alloc_pages_node(int nid, gfp_t gfp_mask, unsigned int order)
> 465 {
> 466 VM_BUG_ON(nid < 0 || nid >= MAX_NUMNODES);
> 467 VM_WARN_ON(!node_online(nid));
> 468
> 469 return __alloc_pages(gfp_mask, order, nid);
> 470 }
> 471
>
> (I wrote a ko, to allocate memory on a non-exist node using kzalloc_node().)
OK, so this is an artificialy broken code, right. You shouldn't get a
non-existent node via standard APIs AFAICS. The original report was
about an existing node which is offline AFAIU. That would be a different
case. If I am missing something and there are legitimate users that try
to allocate from non-existing nodes then we should handle that in
node_zonelist.
[...]
--
Michal Hocko
SUSE Labs
^ permalink raw reply
* [PATCH 02/20] coresight: of: Fix refcounting for graph nodes
From: Suzuki K Poulose @ 2018-06-11 9:18 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180608195530.GB30587@xps15>
On 08/06/18 20:55, Mathieu Poirier wrote:
> On Tue, Jun 05, 2018 at 10:43:13PM +0100, Suzuki K Poulose wrote:
>> The coresight driver doesn't drop the references on the
>> remote endpoint/port nodes. Add the missing of_node_put()
>> calls. To make it easier to handle different corner cases
>> cleanly, move the parsing of an endpoint to separate
>> function.
>
> Please split this as those are two different things.
Mathieu,
I can do that, its only that if someone were to backport
the fix for an older kernel, they would need to pick up these
two patches, which is still fine.
>
>>
>> Reported-by: Mathieu Poirier <mathieu.poirier@linaro.org>
>> Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
>> ---
>> drivers/hwtracing/coresight/of_coresight.c | 139 +++++++++++++++++------------
>> 1 file changed, 84 insertions(+), 55 deletions(-)
>>
>> diff --git a/drivers/hwtracing/coresight/of_coresight.c b/drivers/hwtracing/coresight/of_coresight.c
>> index a33a92e..8a23c63 100644
>> --- a/drivers/hwtracing/coresight/of_coresight.c
>> +++ b/drivers/hwtracing/coresight/of_coresight.c
>> +static int of_coresight_parse_endpoint(struct device_node *ep,
>> + struct coresight_platform_data *pdata,
>> + int *i)
>> +{
>> + int ret = 0;
>> + struct of_endpoint endpoint, rendpoint;
>> + struct device_node *rparent = NULL;
>> + struct device_node *rport = NULL;
>> + struct device *rdev = NULL;
>> +
>> + do {
...
>> + } while (0);
>
> That's a clever way of coding a classic 'goto' block.
>
>> +
>> + if (rparent)
>> + of_node_put(rparent);
>> + if (rport)
>> + of_node_put(rport);
>
> Perfect - thank you for that.
>
>> pdata->name = dev_name(dev);
>> + pdata->cpu = of_coresight_get_cpu(node);
>>
>> /* Get the number of input and output port for this component */
>> of_coresight_get_ports(node, &pdata->nr_inport, &pdata->nr_outport);
>>
>> - if (pdata->nr_outport) {
>> - ret = of_coresight_alloc_memory(dev, pdata);
>> + /* If there are not output connections, we are done */
>
> /not/no
Thanks for spotting.
Suzuki
^ permalink raw reply
* [PATCH 08/20] coresight: dts: Cleanup device tree graph bindings
From: Suzuki K Poulose @ 2018-06-11 9:22 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180608212211.GG30587@xps15>
On 08/06/18 22:22, Mathieu Poirier wrote:
> On Tue, Jun 05, 2018 at 10:43:19PM +0100, Suzuki K Poulose wrote:
>> The coresight drivers relied on default bindings for graph
>> in DT, while reusing the "reg" field of the "ports" to indicate
>> the actual hardware port number for the connections. However,
>> with the rules getting stricter w.r.t to the address mismatch
>> with the label, it is no longer possible to use the port address
>> field for the hardware port number. Hence, we add an explicit
>> property to denote the hardware port number, "coresight,hwid"
>> which must be specified for each "endpoint".
>>
>> Cc: Mathieu Poirier <mathieu.poirier@linaro.org>
>> Cc: Sudeep Holla <sudeep.holla@arm.com>
>> Cc: Rob Herring <robh@kernel.org>
>> Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
>> ---
>> .../devicetree/bindings/arm/coresight.txt | 29 ++++++++++---
>> drivers/hwtracing/coresight/of_coresight.c | 49 +++++++++++++++++-----
>> 2 files changed, 62 insertions(+), 16 deletions(-)
>>
>> diff --git a/Documentation/devicetree/bindings/arm/coresight.txt b/Documentation/devicetree/bindings/arm/coresight.txt
>> index ed6b555..bf75ab3 100644
>> --- a/Documentation/devicetree/bindings/arm/coresight.txt
>> +++ b/Documentation/devicetree/bindings/arm/coresight.txt
>> @@ -108,8 +108,13 @@ following properties to uniquely identify the connection details.
>> "slave-mode"
>> };
>
> For the binding part:
> Reviewed-by: Mathieu Poirier <mathieu.poirier@linaro.org>
>
>> diff --git a/drivers/hwtracing/coresight/of_coresight.c b/drivers/hwtracing/coresight/of_coresight.c
>> index d01a9ce..d23d7dd 100644
>> --- a/drivers/hwtracing/coresight/of_coresight.c
>> +++ b/drivers/hwtracing/coresight/of_coresight.c
...
>> +/*
>> * of_coresight_parse_endpoint : Parse the given output endpoint @ep
>> * and fill the connection information in *@pconn.
>> *
>> @@ -109,11 +134,11 @@ EXPORT_SYMBOL_GPL(of_coresight_get_cpu);
>> * 0 - If the parsing completed without any fatal errors.
Please note the return value description here. Further comments below.
>> * -Errno - Fatal error, abort the scanning.
>> */
>> -static int of_coresight_parse_endpoint(struct device_node *ep,
>> +static int of_coresight_parse_endpoint(struct device *dev,
>> + struct device_node *ep,
>> struct coresight_connection **pconn)
>> {
>> - int ret = 0;
>> - struct of_endpoint endpoint, rendpoint;
>> + int ret = 0, local_port, child_port;
>> struct device_node *rparent = NULL;
>> struct device_node *rep = NULL;
>> struct device *rdev = NULL;
>> @@ -128,7 +153,8 @@ static int of_coresight_parse_endpoint(struct device_node *ep,
>> break;
>>
>> /* Parse the local port details */
>> - if (of_graph_parse_endpoint(ep, &endpoint))
>> + local_port = of_coresight_endpoint_get_port_id(dev, ep);
>> + if (local_port < 0)
>> break;
>> /*
>> * Get a handle on the remote endpoint and the device it is
>> @@ -140,9 +166,6 @@ static int of_coresight_parse_endpoint(struct device_node *ep,
>> rparent = of_graph_get_port_parent(rep);
>> if (!rparent)
>> break;
>> - if (of_graph_parse_endpoint(rep, &rendpoint))
>> - break;
>> -
>> /* If the remote device is not available, defer probing */
>> rdev = of_coresight_get_endpoint_device(rparent);
>> if (!rdev) {
>> @@ -150,9 +173,15 @@ static int of_coresight_parse_endpoint(struct device_node *ep,
>> break;
>> }
>>
>> - conn->outport = endpoint.port;
>> + child_port = of_coresight_endpoint_get_port_id(rdev, rep);
>> + if (child_port < 0) {
>> + ret = 0;
>
> Why returning '0' on an error condition? Same for 'local_port' above.
>
If we are unable to parse a port, we can simply ignore the port and continue, which
is what we have today with the existing code. I didn't change it and still think
it is the best effort thing. We could spit a warning for such cases, if really needed.
Also, the parsing code almost never fails at the moment. If it fails to find "reg" field,
it is assumed to be '0'. Either way ignoring it seems harmless. That said I am open
to suggestions.
Cheers
Suzuki
^ permalink raw reply
* [PATCH v2] irqchip/gic-v3-its: fix ITS queue timeout
From: Marc Zyngier @ 2018-06-11 9:31 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1528252824-15144-1-git-send-email-yangyingliang@huawei.com>
On 06/06/18 03:40, Yang Yingliang wrote:
> When the kernel booted with maxcpus=x, 'x' is smaller
> than actual cpu numbers, the TAs of offline cpus won't
> be set to its->collection.
>
> If LPI is bind to offline cpu, sync cmd will use zero TA,
> it leads to ITS queue timeout. Fix this by choosing a
> online cpu, if there is no online cpu in cpu_mask.
>
> Signed-off-by: Yang Yingliang <yangyingliang@huawei.com>
> ---
> drivers/irqchip/irq-gic-v3-its.c | 9 +++++++--
> 1 file changed, 7 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c
> index 5416f2b..d8b9539 100644
> --- a/drivers/irqchip/irq-gic-v3-its.c
> +++ b/drivers/irqchip/irq-gic-v3-its.c
> @@ -2309,7 +2309,9 @@ static int its_irq_domain_activate(struct irq_domain *domain,
> cpu_mask = cpumask_of_node(its_dev->its->numa_node);
>
> /* Bind the LPI to the first possible CPU */
> - cpu = cpumask_first(cpu_mask);
> + cpu = cpumask_first_and(cpu_mask, cpu_online_mask);
> + if (cpu >= nr_cpu_ids)
> + cpu = cpumask_first(cpu_online_mask);
I've thought about this one a bit more, and apart from breaking TX1
in a very bad way, I think it is actually correct. It is just that
the commit message doesn't make much sense.
The way I understand it is:
- this is a NUMA system, with at least one node not online
- the SRAT table indicates that this ITS is local to an offline node
In that case, we need to pick an online CPU, and any will do (again,
ignoring the silly Cavium erratum). Explained like this, the above
hunk is sensible, and just needs to handle the TX1 quirk. Something like:
diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c
index 5416f2b2ac21..21b7b5151177 100644
--- a/drivers/irqchip/irq-gic-v3-its.c
+++ b/drivers/irqchip/irq-gic-v3-its.c
@@ -2309,7 +2309,13 @@ static int its_irq_domain_activate(struct irq_domain *domain,
cpu_mask = cpumask_of_node(its_dev->its->numa_node);
/* Bind the LPI to the first possible CPU */
- cpu = cpumask_first(cpu_mask);
+ cpu = cpumask_first_and(cpu_mask, cpu_online_mask);
+ if (cpu >= nr_cpu_idx) {
+ if (its_dev->its->flags & ITS_FLAGS_WORKAROUND_CAVIUM_23144)
+ return -EINVAL;
+
+ cpu = cpumask_first(cpu_online_mask);
+ }
its_dev->event_map.col_map[event] = cpu;
irq_data_update_effective_affinity(d, cpumask_of(cpu));
> its_dev->event_map.col_map[event] = cpu;
> irq_data_update_effective_affinity(d, cpumask_of(cpu));
>
> @@ -2466,7 +2468,10 @@ static int its_vpe_set_affinity(struct irq_data *d,
> bool force)
> {
> struct its_vpe *vpe = irq_data_get_irq_chip_data(d);
> - int cpu = cpumask_first(mask_val);
> + int cpu = cpumask_first_and(mask_val, cpu_online_mask);
> +
> + if (cpu >= nr_cpu_ids)
> + cpu = cpumask_first(cpu_online_mask);
>
> /*
> * Changing affinity is mega expensive, so let's be as lazy as
>
This hunk, on the other hand, is completely useless. Look how this is
called from vgic_v4_flush_hwstate():
err = irq_set_affinity(irq, cpumask_of(smp_processor_id()));
The mask is always that of the CPU we run on, and we're in a non-premptible
section. So no way we can be targeting an offline CPU.
If you quickly respin this patch with a decent commit log, I'll take it.
Thanks,
M.
--
Jazz is not dead. It just smells funny...
^ permalink raw reply related
* [PATCH] media: stm32-dcmi: add power saving support
From: Hugues Fruchet @ 2018-06-11 9:33 UTC (permalink / raw)
To: linux-arm-kernel
Implements runtime & system sleep power management ops.
Signed-off-by: Hugues Fruchet <hugues.fruchet@st.com>
---
drivers/media/platform/stm32/stm32-dcmi.c | 80 ++++++++++++++++++++++++-------
1 file changed, 64 insertions(+), 16 deletions(-)
diff --git a/drivers/media/platform/stm32/stm32-dcmi.c b/drivers/media/platform/stm32/stm32-dcmi.c
index 2e1933d..68da9ec 100644
--- a/drivers/media/platform/stm32/stm32-dcmi.c
+++ b/drivers/media/platform/stm32/stm32-dcmi.c
@@ -22,6 +22,7 @@
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/of_graph.h>
#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
#include <linux/reset.h>
#include <linux/videodev2.h>
@@ -578,9 +579,9 @@ static int dcmi_start_streaming(struct vb2_queue *vq, unsigned int count)
u32 val = 0;
int ret;
- ret = clk_enable(dcmi->mclk);
+ ret = pm_runtime_get_sync(dcmi->dev);
if (ret) {
- dev_err(dcmi->dev, "%s: Failed to start streaming, cannot enable clock\n",
+ dev_err(dcmi->dev, "%s: Failed to start streaming, cannot get sync\n",
__func__);
goto err_release_buffers;
}
@@ -590,7 +591,7 @@ static int dcmi_start_streaming(struct vb2_queue *vq, unsigned int count)
if (ret && ret != -ENOIOCTLCMD) {
dev_err(dcmi->dev, "%s: Failed to start streaming, subdev streamon error",
__func__);
- goto err_disable_clock;
+ goto err_pm_put;
}
spin_lock_irq(&dcmi->irqlock);
@@ -675,8 +676,8 @@ static int dcmi_start_streaming(struct vb2_queue *vq, unsigned int count)
err_subdev_streamoff:
v4l2_subdev_call(dcmi->entity.subdev, video, s_stream, 0);
-err_disable_clock:
- clk_disable(dcmi->mclk);
+err_pm_put:
+ pm_runtime_put(dcmi->dev);
err_release_buffers:
spin_lock_irq(&dcmi->irqlock);
@@ -749,7 +750,7 @@ static void dcmi_stop_streaming(struct vb2_queue *vq)
/* Stop all pending DMA operations */
dmaengine_terminate_all(dcmi->dma_chan);
- clk_disable(dcmi->mclk);
+ pm_runtime_put(dcmi->dev);
if (dcmi->errors_count)
dev_warn(dcmi->dev, "Some errors found while streaming: errors=%d (overrun=%d), buffers=%d\n",
@@ -1751,12 +1752,6 @@ static int dcmi_probe(struct platform_device *pdev)
return -EPROBE_DEFER;
}
- ret = clk_prepare(mclk);
- if (ret) {
- dev_err(&pdev->dev, "Unable to prepare mclk %p\n", mclk);
- goto err_dma_release;
- }
-
spin_lock_init(&dcmi->irqlock);
mutex_init(&dcmi->lock);
init_completion(&dcmi->complete);
@@ -1772,7 +1767,7 @@ static int dcmi_probe(struct platform_device *pdev)
/* Initialize the top-level structure */
ret = v4l2_device_register(&pdev->dev, &dcmi->v4l2_dev);
if (ret)
- goto err_clk_unprepare;
+ goto err_dma_release;
dcmi->vdev = video_device_alloc();
if (!dcmi->vdev) {
@@ -1832,14 +1827,15 @@ static int dcmi_probe(struct platform_device *pdev)
dev_info(&pdev->dev, "Probe done\n");
platform_set_drvdata(pdev, dcmi);
+
+ pm_runtime_enable(&pdev->dev);
+
return 0;
err_device_release:
video_device_release(dcmi->vdev);
err_device_unregister:
v4l2_device_unregister(&dcmi->v4l2_dev);
-err_clk_unprepare:
- clk_unprepare(dcmi->mclk);
err_dma_release:
dma_release_channel(dcmi->dma_chan);
@@ -1850,20 +1846,72 @@ static int dcmi_remove(struct platform_device *pdev)
{
struct stm32_dcmi *dcmi = platform_get_drvdata(pdev);
+ pm_runtime_disable(&pdev->dev);
+
v4l2_async_notifier_unregister(&dcmi->notifier);
v4l2_device_unregister(&dcmi->v4l2_dev);
- clk_unprepare(dcmi->mclk);
+
dma_release_channel(dcmi->dma_chan);
return 0;
}
+static __maybe_unused int dcmi_runtime_suspend(struct device *dev)
+{
+ struct stm32_dcmi *dcmi = dev_get_drvdata(dev);
+
+ clk_disable_unprepare(dcmi->mclk);
+
+ return 0;
+}
+
+static __maybe_unused int dcmi_runtime_resume(struct device *dev)
+{
+ struct stm32_dcmi *dcmi = dev_get_drvdata(dev);
+ int ret;
+
+ ret = clk_prepare_enable(dcmi->mclk);
+ if (ret)
+ dev_err(dev, "%s: Failed to prepare_enable clock\n", __func__);
+
+ return ret;
+}
+
+static __maybe_unused int dcmi_suspend(struct device *dev)
+{
+ /* disable clock */
+ pm_runtime_force_suspend(dev);
+
+ /* change pinctrl state */
+ pinctrl_pm_select_sleep_state(dev);
+
+ return 0;
+}
+
+static __maybe_unused int dcmi_resume(struct device *dev)
+{
+ /* restore pinctl default state */
+ pinctrl_pm_select_default_state(dev);
+
+ /* clock enable */
+ pm_runtime_force_resume(dev);
+
+ return 0;
+}
+
+static const struct dev_pm_ops dcmi_pm_ops = {
+ SET_SYSTEM_SLEEP_PM_OPS(dcmi_suspend, dcmi_resume)
+ SET_RUNTIME_PM_OPS(dcmi_runtime_suspend,
+ dcmi_runtime_resume, NULL)
+};
+
static struct platform_driver stm32_dcmi_driver = {
.probe = dcmi_probe,
.remove = dcmi_remove,
.driver = {
.name = DRV_NAME,
.of_match_table = of_match_ptr(stm32_dcmi_of_match),
+ .pm = &dcmi_pm_ops,
},
};
--
1.9.1
^ permalink raw reply related
* [PATCH] media: stm32-dcmi: increase max width/height to 2592
From: Hugues Fruchet @ 2018-06-11 9:41 UTC (permalink / raw)
To: linux-arm-kernel
DCMI can capture 5Mp raw frames, increase limit accordingly.
Signed-off-by: Hugues Fruchet <hugues.fruchet@st.com>
---
drivers/media/platform/stm32/stm32-dcmi.c | 19 ++++---------------
1 file changed, 4 insertions(+), 15 deletions(-)
diff --git a/drivers/media/platform/stm32/stm32-dcmi.c b/drivers/media/platform/stm32/stm32-dcmi.c
index 68da9ec..c55e6b5 100644
--- a/drivers/media/platform/stm32/stm32-dcmi.c
+++ b/drivers/media/platform/stm32/stm32-dcmi.c
@@ -90,14 +90,9 @@ enum state {
};
#define MIN_WIDTH 16U
-#define MAX_WIDTH 2048U
+#define MAX_WIDTH 2592U
#define MIN_HEIGHT 16U
-#define MAX_HEIGHT 2048U
-
-#define MIN_JPEG_WIDTH 16U
-#define MAX_JPEG_WIDTH 2592U
-#define MIN_JPEG_HEIGHT 16U
-#define MAX_JPEG_HEIGHT 2592U
+#define MAX_HEIGHT 2592U
#define TIMEOUT_MS 1000
@@ -844,14 +839,8 @@ static int dcmi_try_fmt(struct stm32_dcmi *dcmi, struct v4l2_format *f,
}
/* Limit to hardware capabilities */
- if (pix->pixelformat == V4L2_PIX_FMT_JPEG) {
- pix->width = clamp(pix->width, MIN_JPEG_WIDTH, MAX_JPEG_WIDTH);
- pix->height =
- clamp(pix->height, MIN_JPEG_HEIGHT, MAX_JPEG_HEIGHT);
- } else {
- pix->width = clamp(pix->width, MIN_WIDTH, MAX_WIDTH);
- pix->height = clamp(pix->height, MIN_HEIGHT, MAX_HEIGHT);
- }
+ pix->width = clamp(pix->width, MIN_WIDTH, MAX_WIDTH);
+ pix->height = clamp(pix->height, MIN_HEIGHT, MAX_HEIGHT);
/* No crop if JPEG is requested */
do_crop = dcmi->do_crop && (pix->pixelformat != V4L2_PIX_FMT_JPEG);
--
1.9.1
^ permalink raw reply related
* [PATCH 2/9] crypto: atmel-ecc: Silently ignore missing clock frequency
From: Tudor Ambarus @ 2018-06-11 9:46 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180605134950.6605-2-linus.walleij@linaro.org>
Hi, Linus, Wolfram,
On 06/05/2018 04:49 PM, Linus Walleij wrote:
> The Atmel ECC driver contains a check for the I2C bus clock
> frequency, so as to check that the I2C adapter in use
> satisfies the device specs.
>
> If the device is connected to a device tree node that does not
> contain a clock frequency setting, such as an I2C mux or gate,
> this blocks the probe. Make the probe continue silently if
> no clock frequency can be found, assuming all is safe.
I don't think it's safe. We use bus_clk_rate to compute the ecc508's
wake token. If you can't wake the device, it will ignore all your
commands.
My proposal was to introduce a bus_freq_hz member in the i2c_adapter
structure (https://patchwork.kernel.org/patch/10307637/), but I haven't
received feedback yet, Wolfram?
I would say first to check the bus_freq_hz from adapter (if it will be
accepted) else to look into dt and, in the last case, if nowhere
provided, to block the probe.
Thanks,
ta
>
> Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
> ---
> drivers/crypto/atmel-ecc.c | 11 +++++------
> 1 file changed, 5 insertions(+), 6 deletions(-)
>
> diff --git a/drivers/crypto/atmel-ecc.c b/drivers/crypto/atmel-ecc.c
> index e66f18a0ddd0..145ab3a39a56 100644
> --- a/drivers/crypto/atmel-ecc.c
> +++ b/drivers/crypto/atmel-ecc.c
> @@ -657,14 +657,13 @@ static int atmel_ecc_probe(struct i2c_client *client,
> return -ENODEV;
> }
>
> + /*
> + * Silently assume all is fine if there is no
> + * "clock-frequency" property.
> + */
> ret = of_property_read_u32(client->adapter->dev.of_node,
> "clock-frequency", &bus_clk_rate);
> - if (ret) {
> - dev_err(dev, "of: failed to read clock-frequency property\n");
> - return ret;
> - }
> -
> - if (bus_clk_rate > 1000000L) {
> + if (!ret && (bus_clk_rate > 1000000L)) {
> dev_err(dev, "%d exceeds maximum supported clock frequency (1MHz)\n",
> bus_clk_rate);
> return -EINVAL;
>
^ permalink raw reply
* [PATCH] media: stm32-dcmi: code cleanup
From: Hugues Fruchet @ 2018-06-11 9:50 UTC (permalink / raw)
To: linux-arm-kernel
Minor non-functional fixes around comments, variable namings
and trace point enhancement.
Signed-off-by: Hugues Fruchet <hugues.fruchet@st.com>
---
drivers/media/platform/stm32/stm32-dcmi.c | 18 ++++++++----------
1 file changed, 8 insertions(+), 10 deletions(-)
diff --git a/drivers/media/platform/stm32/stm32-dcmi.c b/drivers/media/platform/stm32/stm32-dcmi.c
index c55e6b5..b796334 100644
--- a/drivers/media/platform/stm32/stm32-dcmi.c
+++ b/drivers/media/platform/stm32/stm32-dcmi.c
@@ -249,13 +249,12 @@ static int dcmi_restart_capture(struct stm32_dcmi *dcmi)
static void dcmi_dma_callback(void *param)
{
struct stm32_dcmi *dcmi = (struct stm32_dcmi *)param;
- struct dma_chan *chan = dcmi->dma_chan;
struct dma_tx_state state;
enum dma_status status;
struct dcmi_buf *buf = dcmi->active;
/* Check DMA status */
- status = dmaengine_tx_status(chan, dcmi->dma_cookie, &state);
+ status = dmaengine_tx_status(dcmi->dma_chan, dcmi->dma_cookie, &state);
switch (status) {
case DMA_IN_PROGRESS:
@@ -309,10 +308,11 @@ static int dcmi_start_dma(struct stm32_dcmi *dcmi,
/* Prepare a DMA transaction */
desc = dmaengine_prep_slave_single(dcmi->dma_chan, buf->paddr,
buf->size,
- DMA_DEV_TO_MEM, DMA_PREP_INTERRUPT);
+ DMA_DEV_TO_MEM,
+ DMA_PREP_INTERRUPT);
if (!desc) {
- dev_err(dcmi->dev, "%s: DMA dmaengine_prep_slave_single failed for buffer size %zu\n",
- __func__, buf->size);
+ dev_err(dcmi->dev, "%s: DMA dmaengine_prep_slave_single failed for buffer phy=%pad size=%zu\n",
+ __func__, &buf->paddr, buf->size);
return -EINVAL;
}
@@ -378,7 +378,6 @@ static void dcmi_process_jpeg(struct stm32_dcmi *dcmi)
{
struct dma_tx_state state;
enum dma_status status;
- struct dma_chan *chan = dcmi->dma_chan;
struct dcmi_buf *buf = dcmi->active;
if (!buf)
@@ -386,8 +385,7 @@ static void dcmi_process_jpeg(struct stm32_dcmi *dcmi)
/*
* Because of variable JPEG buffer size sent by sensor,
- * DMA transfer never completes due to transfer size
- * never reached.
+ * DMA transfer never completes due to transfer size never reached.
* In order to ensure that all the JPEG data are transferred
* in active buffer memory, DMA is drained.
* Then DMA tx status gives the amount of data transferred
@@ -396,10 +394,10 @@ static void dcmi_process_jpeg(struct stm32_dcmi *dcmi)
*/
/* Drain DMA */
- dmaengine_synchronize(chan);
+ dmaengine_synchronize(dcmi->dma_chan);
/* Get DMA residue to get JPEG size */
- status = dmaengine_tx_status(chan, dcmi->dma_cookie, &state);
+ status = dmaengine_tx_status(dcmi->dma_chan, dcmi->dma_cookie, &state);
if (status != DMA_ERROR && state.residue < buf->size) {
/* Return JPEG buffer to V4L2 with received JPEG buffer size */
dcmi_buffer_done(dcmi, buf, buf->size - state.residue, 0);
--
1.9.1
^ permalink raw reply related
* [PATCH 0/4] Revisit and fix DCMI buffers handling
From: Hugues Fruchet @ 2018-06-11 9:50 UTC (permalink / raw)
To: linux-arm-kernel
Revisit and fix DCMI buffers handling.
Hugues Fruchet (4):
media: stm32-dcmi: do not fall into error on buffer starvation
media: stm32-dcmi: return buffer in error state on dma error
media: stm32-dcmi: clarify state logic on buffer starvation
media: stm32-dcmi: revisit buffer list management
drivers/media/platform/stm32/stm32-dcmi.c | 80 ++++++++++++++++---------------
1 file changed, 41 insertions(+), 39 deletions(-)
--
1.9.1
^ permalink raw reply
* [PATCH 1/4] media: stm32-dcmi: do not fall into error on buffer starvation
From: Hugues Fruchet @ 2018-06-11 9:50 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1528710627-8566-1-git-send-email-hugues.fruchet@st.com>
Return silently instead of falling into error when running
out of available buffers when restarting capture.
Capture will be restarted when new buffers will be
provided by V4L2 client.
Signed-off-by: Hugues Fruchet <hugues.fruchet@st.com>
---
drivers/media/platform/stm32/stm32-dcmi.c | 7 ++-----
1 file changed, 2 insertions(+), 5 deletions(-)
diff --git a/drivers/media/platform/stm32/stm32-dcmi.c b/drivers/media/platform/stm32/stm32-dcmi.c
index b796334..a3fbfac 100644
--- a/drivers/media/platform/stm32/stm32-dcmi.c
+++ b/drivers/media/platform/stm32/stm32-dcmi.c
@@ -228,13 +228,10 @@ static int dcmi_restart_capture(struct stm32_dcmi *dcmi)
/* Restart a new DMA transfer with next buffer */
if (list_empty(&dcmi->buffers)) {
- dev_err(dcmi->dev, "%s: No more buffer queued, cannot capture buffer\n",
- __func__);
- dcmi->errors_count++;
+ dev_dbg(dcmi->dev, "Capture restart is deferred to next buffer queueing\n");
dcmi->active = NULL;
-
spin_unlock_irq(&dcmi->irqlock);
- return -EINVAL;
+ return 0;
}
dcmi->active = list_entry(dcmi->buffers.next,
--
1.9.1
^ permalink raw reply related
* [PATCH 2/4] media: stm32-dcmi: return buffer in error state on dma error
From: Hugues Fruchet @ 2018-06-11 9:50 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1528710627-8566-1-git-send-email-hugues.fruchet@st.com>
Return buffer to V4L2 in error state if DMA error occurs.
Signed-off-by: Hugues Fruchet <hugues.fruchet@st.com>
---
drivers/media/platform/stm32/stm32-dcmi.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/drivers/media/platform/stm32/stm32-dcmi.c b/drivers/media/platform/stm32/stm32-dcmi.c
index a3fbfac..6ccf195 100644
--- a/drivers/media/platform/stm32/stm32-dcmi.c
+++ b/drivers/media/platform/stm32/stm32-dcmi.c
@@ -262,6 +262,9 @@ static void dcmi_dma_callback(void *param)
break;
case DMA_ERROR:
dev_err(dcmi->dev, "%s: Received DMA_ERROR\n", __func__);
+
+ /* Return buffer to V4L2 in error state */
+ dcmi_buffer_done(dcmi, buf, 0, -EIO);
break;
case DMA_COMPLETE:
dev_dbg(dcmi->dev, "%s: Received DMA_COMPLETE\n", __func__);
--
1.9.1
^ permalink raw reply related
* [PATCH 3/4] media: stm32-dcmi: clarify state logic on buffer starvation
From: Hugues Fruchet @ 2018-06-11 9:50 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1528710627-8566-1-git-send-email-hugues.fruchet@st.com>
Introduce WAIT_FOR_BUFFER state instead of "active" field checking
to manage buffer starvation case.
Signed-off-by: Hugues Fruchet <hugues.fruchet@st.com>
---
drivers/media/platform/stm32/stm32-dcmi.c | 11 ++++++++---
1 file changed, 8 insertions(+), 3 deletions(-)
diff --git a/drivers/media/platform/stm32/stm32-dcmi.c b/drivers/media/platform/stm32/stm32-dcmi.c
index 6ccf195..93bb03a 100644
--- a/drivers/media/platform/stm32/stm32-dcmi.c
+++ b/drivers/media/platform/stm32/stm32-dcmi.c
@@ -85,6 +85,7 @@
enum state {
STOPPED = 0,
+ WAIT_FOR_BUFFER,
RUNNING,
STOPPING,
};
@@ -230,6 +231,7 @@ static int dcmi_restart_capture(struct stm32_dcmi *dcmi)
if (list_empty(&dcmi->buffers)) {
dev_dbg(dcmi->dev, "Capture restart is deferred to next buffer queueing\n");
dcmi->active = NULL;
+ dcmi->state = WAIT_FOR_BUFFER;
spin_unlock_irq(&dcmi->irqlock);
return 0;
}
@@ -548,9 +550,11 @@ static void dcmi_buf_queue(struct vb2_buffer *vb)
spin_lock_irq(&dcmi->irqlock);
- if (dcmi->state == RUNNING && !dcmi->active) {
dcmi->active = buf;
+ if (dcmi->state == WAIT_FOR_BUFFER) {
+ dcmi->state = RUNNING;
+
dev_dbg(dcmi->dev, "Starting capture on buffer[%d] queued\n",
buf->vb.vb2_buf.index);
@@ -630,8 +634,6 @@ static int dcmi_start_streaming(struct vb2_queue *vq, unsigned int count)
/* Enable dcmi */
reg_set(dcmi->regs, DCMI_CR, CR_ENABLE);
- dcmi->state = RUNNING;
-
dcmi->sequence = 0;
dcmi->errors_count = 0;
dcmi->overrun_count = 0;
@@ -644,6 +646,7 @@ static int dcmi_start_streaming(struct vb2_queue *vq, unsigned int count)
*/
if (list_empty(&dcmi->buffers)) {
dev_dbg(dcmi->dev, "Start streaming is deferred to next buffer queueing\n");
+ dcmi->state = WAIT_FOR_BUFFER;
spin_unlock_irq(&dcmi->irqlock);
return 0;
}
@@ -653,6 +656,8 @@ static int dcmi_start_streaming(struct vb2_queue *vq, unsigned int count)
dev_dbg(dcmi->dev, "Start streaming, starting capture\n");
+ dcmi->state = RUNNING;
+
spin_unlock_irq(&dcmi->irqlock);
ret = dcmi_start_capture(dcmi);
if (ret) {
--
1.9.1
^ permalink raw reply related
* [PATCH 4/4] media: stm32-dcmi: revisit buffer list management
From: Hugues Fruchet @ 2018-06-11 9:50 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1528710627-8566-1-git-send-email-hugues.fruchet@st.com>
Cleanup "active" field usage and enhance list management
to avoid exceptions when releasing buffers on error or
stopping streaming.
Signed-off-by: Hugues Fruchet <hugues.fruchet@st.com>
---
drivers/media/platform/stm32/stm32-dcmi.c | 65 +++++++++++++++----------------
1 file changed, 31 insertions(+), 34 deletions(-)
diff --git a/drivers/media/platform/stm32/stm32-dcmi.c b/drivers/media/platform/stm32/stm32-dcmi.c
index 93bb03a..581ded0 100644
--- a/drivers/media/platform/stm32/stm32-dcmi.c
+++ b/drivers/media/platform/stm32/stm32-dcmi.c
@@ -191,7 +191,7 @@ static inline void reg_clear(void __iomem *base, u32 reg, u32 mask)
reg_write(base, reg, reg_read(base, reg) & ~mask);
}
-static int dcmi_start_capture(struct stm32_dcmi *dcmi);
+static int dcmi_start_capture(struct stm32_dcmi *dcmi, struct dcmi_buf *buf);
static void dcmi_buffer_done(struct stm32_dcmi *dcmi,
struct dcmi_buf *buf,
@@ -203,6 +203,8 @@ static void dcmi_buffer_done(struct stm32_dcmi *dcmi,
if (!buf)
return;
+ list_del_init(&buf->list);
+
vbuf = &buf->vb;
vbuf->sequence = dcmi->sequence++;
@@ -220,6 +222,8 @@ static void dcmi_buffer_done(struct stm32_dcmi *dcmi,
static int dcmi_restart_capture(struct stm32_dcmi *dcmi)
{
+ struct dcmi_buf *buf;
+
spin_lock_irq(&dcmi->irqlock);
if (dcmi->state != RUNNING) {
@@ -230,19 +234,16 @@ static int dcmi_restart_capture(struct stm32_dcmi *dcmi)
/* Restart a new DMA transfer with next buffer */
if (list_empty(&dcmi->buffers)) {
dev_dbg(dcmi->dev, "Capture restart is deferred to next buffer queueing\n");
- dcmi->active = NULL;
dcmi->state = WAIT_FOR_BUFFER;
spin_unlock_irq(&dcmi->irqlock);
return 0;
}
-
- dcmi->active = list_entry(dcmi->buffers.next,
- struct dcmi_buf, list);
- list_del_init(&dcmi->active->list);
+ buf = list_entry(dcmi->buffers.next, struct dcmi_buf, list);
+ dcmi->active = buf;
spin_unlock_irq(&dcmi->irqlock);
- return dcmi_start_capture(dcmi);
+ return dcmi_start_capture(dcmi, buf);
}
static void dcmi_dma_callback(void *param)
@@ -252,6 +253,8 @@ static void dcmi_dma_callback(void *param)
enum dma_status status;
struct dcmi_buf *buf = dcmi->active;
+ spin_lock_irq(&dcmi->irqlock);
+
/* Check DMA status */
status = dmaengine_tx_status(dcmi->dma_chan, dcmi->dma_cookie, &state);
@@ -274,15 +277,19 @@ static void dcmi_dma_callback(void *param)
/* Return buffer to V4L2 */
dcmi_buffer_done(dcmi, buf, buf->size, 0);
+ spin_unlock_irq(&dcmi->irqlock);
+
/* Restart capture */
if (dcmi_restart_capture(dcmi))
dev_err(dcmi->dev, "%s: Cannot restart capture on DMA complete\n",
__func__);
- break;
+ return;
default:
dev_err(dcmi->dev, "%s: Received unknown status\n", __func__);
break;
}
+
+ spin_unlock_irq(&dcmi->irqlock);
}
static int dcmi_start_dma(struct stm32_dcmi *dcmi,
@@ -334,10 +341,9 @@ static int dcmi_start_dma(struct stm32_dcmi *dcmi,
return 0;
}
-static int dcmi_start_capture(struct stm32_dcmi *dcmi)
+static int dcmi_start_capture(struct stm32_dcmi *dcmi, struct dcmi_buf *buf)
{
int ret;
- struct dcmi_buf *buf = dcmi->active;
if (!buf)
return -EINVAL;
@@ -491,8 +497,6 @@ static int dcmi_queue_setup(struct vb2_queue *vq,
*nplanes = 1;
sizes[0] = size;
- dcmi->active = NULL;
-
dev_dbg(dcmi->dev, "Setup queue, count=%d, size=%d\n",
*nbuffers, size);
@@ -550,23 +554,24 @@ static void dcmi_buf_queue(struct vb2_buffer *vb)
spin_lock_irq(&dcmi->irqlock);
- dcmi->active = buf;
+ /* Enqueue to video buffers list */
+ list_add_tail(&buf->list, &dcmi->buffers);
if (dcmi->state == WAIT_FOR_BUFFER) {
dcmi->state = RUNNING;
+ dcmi->active = buf;
dev_dbg(dcmi->dev, "Starting capture on buffer[%d] queued\n",
buf->vb.vb2_buf.index);
spin_unlock_irq(&dcmi->irqlock);
- if (dcmi_start_capture(dcmi))
+ if (dcmi_start_capture(dcmi, buf))
dev_err(dcmi->dev, "%s: Cannot restart capture on overflow or error\n",
__func__);
- } else {
- /* Enqueue to video buffers list */
- list_add_tail(&buf->list, &dcmi->buffers);
- spin_unlock_irq(&dcmi->irqlock);
+ return;
}
+
+ spin_unlock_irq(&dcmi->irqlock);
}
static int dcmi_start_streaming(struct vb2_queue *vq, unsigned int count)
@@ -638,7 +643,6 @@ static int dcmi_start_streaming(struct vb2_queue *vq, unsigned int count)
dcmi->errors_count = 0;
dcmi->overrun_count = 0;
dcmi->buffers_count = 0;
- dcmi->active = NULL;
/*
* Start transfer if at least one buffer has been queued,
@@ -651,15 +655,15 @@ static int dcmi_start_streaming(struct vb2_queue *vq, unsigned int count)
return 0;
}
- dcmi->active = list_entry(dcmi->buffers.next, struct dcmi_buf, list);
- list_del_init(&dcmi->active->list);
-
- dev_dbg(dcmi->dev, "Start streaming, starting capture\n");
+ buf = list_entry(dcmi->buffers.next, struct dcmi_buf, list);
+ dcmi->active = buf;
dcmi->state = RUNNING;
+ dev_dbg(dcmi->dev, "Start streaming, starting capture\n");
+
spin_unlock_irq(&dcmi->irqlock);
- ret = dcmi_start_capture(dcmi);
+ ret = dcmi_start_capture(dcmi, buf);
if (ret) {
dev_err(dcmi->dev, "%s: Start streaming failed, cannot start capture\n",
__func__);
@@ -683,15 +687,11 @@ static int dcmi_start_streaming(struct vb2_queue *vq, unsigned int count)
* Return all buffers to vb2 in QUEUED state.
* This will give ownership back to userspace
*/
- if (dcmi->active) {
- buf = dcmi->active;
- vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_QUEUED);
- dcmi->active = NULL;
- }
list_for_each_entry_safe(buf, node, &dcmi->buffers, list) {
list_del_init(&buf->list);
vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_QUEUED);
}
+ dcmi->active = NULL;
spin_unlock_irq(&dcmi->irqlock);
return ret;
@@ -733,16 +733,13 @@ static void dcmi_stop_streaming(struct vb2_queue *vq)
}
/* Return all queued buffers to vb2 in ERROR state */
- if (dcmi->active) {
- buf = dcmi->active;
- vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
- dcmi->active = NULL;
- }
list_for_each_entry_safe(buf, node, &dcmi->buffers, list) {
list_del_init(&buf->list);
vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
}
+ dcmi->active = NULL;
+
spin_unlock_irq(&dcmi->irqlock);
/* Stop all pending DMA operations */
--
1.9.1
^ permalink raw reply related
* [PATCH] media: stm32-dcmi: revisit stop streaming ops
From: Hugues Fruchet @ 2018-06-11 9:52 UTC (permalink / raw)
To: linux-arm-kernel
Do not wait for interrupt completion when stopping streaming,
stopping sensor and disabling interruptions are enough.
Signed-off-by: Hugues Fruchet <hugues.fruchet@st.com>
---
drivers/media/platform/stm32/stm32-dcmi.c | 29 +----------------------------
1 file changed, 1 insertion(+), 28 deletions(-)
diff --git a/drivers/media/platform/stm32/stm32-dcmi.c b/drivers/media/platform/stm32/stm32-dcmi.c
index 581ded0..f0134a6 100644
--- a/drivers/media/platform/stm32/stm32-dcmi.c
+++ b/drivers/media/platform/stm32/stm32-dcmi.c
@@ -87,7 +87,6 @@ enum state {
STOPPED = 0,
WAIT_FOR_BUFFER,
RUNNING,
- STOPPING,
};
#define MIN_WIDTH 16U
@@ -432,18 +431,6 @@ static irqreturn_t dcmi_irq_thread(int irq, void *arg)
spin_lock_irq(&dcmi->irqlock);
- /* Stop capture is required */
- if (dcmi->state == STOPPING) {
- reg_clear(dcmi->regs, DCMI_IER, IT_FRAME | IT_OVR | IT_ERR);
-
- dcmi->state = STOPPED;
-
- complete(&dcmi->complete);
-
- spin_unlock_irq(&dcmi->irqlock);
- return IRQ_HANDLED;
- }
-
if ((dcmi->misr & IT_OVR) || (dcmi->misr & IT_ERR)) {
dcmi->errors_count++;
if (dcmi->misr & IT_OVR)
@@ -701,8 +688,6 @@ static void dcmi_stop_streaming(struct vb2_queue *vq)
{
struct stm32_dcmi *dcmi = vb2_get_drv_priv(vq);
struct dcmi_buf *buf, *node;
- unsigned long time_ms = msecs_to_jiffies(TIMEOUT_MS);
- long timeout;
int ret;
/* Disable stream on the sub device */
@@ -712,13 +697,6 @@ static void dcmi_stop_streaming(struct vb2_queue *vq)
__func__, ret);
spin_lock_irq(&dcmi->irqlock);
- dcmi->state = STOPPING;
- spin_unlock_irq(&dcmi->irqlock);
-
- timeout = wait_for_completion_interruptible_timeout(&dcmi->complete,
- time_ms);
-
- spin_lock_irq(&dcmi->irqlock);
/* Disable interruptions */
reg_clear(dcmi->regs, DCMI_IER, IT_FRAME | IT_OVR | IT_ERR);
@@ -726,12 +704,6 @@ static void dcmi_stop_streaming(struct vb2_queue *vq)
/* Disable DCMI */
reg_clear(dcmi->regs, DCMI_CR, CR_ENABLE);
- if (!timeout) {
- dev_err(dcmi->dev, "%s: Timeout during stop streaming\n",
- __func__);
- dcmi->state = STOPPED;
- }
-
/* Return all queued buffers to vb2 in ERROR state */
list_for_each_entry_safe(buf, node, &dcmi->buffers, list) {
list_del_init(&buf->list);
@@ -739,6 +711,7 @@ static void dcmi_stop_streaming(struct vb2_queue *vq)
}
dcmi->active = NULL;
+ dcmi->state = STOPPED;
spin_unlock_irq(&dcmi->irqlock);
--
1.9.1
^ permalink raw reply related
* [PATCH V3] ARM: shmobile: Rework the PMIC IRQ line quirk
From: Geert Uytterhoeven @ 2018-06-11 9:56 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180604175911.799-1-marek.vasut+renesas@gmail.com>
Hi Marek,
On Mon, Jun 4, 2018 at 7:59 PM Marek Vasut <marek.vasut@gmail.com> wrote:
> Rather than hard-coding the quirk topology, which stopped scaling,
> parse the information from DT. The code looks for all compatible
> PMICs -- da9036 and da9210 -- and checks if their IRQ line is tied
da9063
> to the same pin. If so, the code sends a matching sequence to the
> PMIC to deassert the IRQ.
Note that not all R-Car Gen2 boards have all regulators described in DT yet.
E.g. gose lacks da9210. So that has to be fixed first.
>
> Signed-off-by: Marek Vasut <marek.vasut+renesas@gmail.com>
> Cc: Geert Uytterhoeven <geert+renesas@glider.be>
> Cc: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
> Cc: Simon Horman <horms+renesas@verge.net.au>
> Cc: Wolfram Sang <wsa+renesas@sang-engineering.com>
> Cc: linux-renesas-soc at vger.kernel.org
> ---
> V2: - Replace the DT shared IRQ check loop with memcmp()
> - Send the I2C message to deassert the IRQ line to all PMICs
> in the list with shared IRQ line instead of just one
> - Add comment that this works only in case all the PMICs are
> on the same I2C bus
> V3: - Drop the addr = 0x00 init
> - Drop reinit of argsa in rcar_gen2_regulator_quirk
Thanks for the update!
> --- a/arch/arm/mach-shmobile/regulator-quirk-rcar-gen2.c
> +++ b/arch/arm/mach-shmobile/regulator-quirk-rcar-gen2.c
> @@ -44,34 +46,45 @@
> /* start of DA9210 System Control and Event Registers */
> #define DA9210_REG_MASK_A 0x54
>
> +struct regulator_quirk {
> + struct list_head list;
> + const struct of_device_id *id;
> + struct of_phandle_args irq_args;
> + struct i2c_msg i2c_msg;
> + bool shared; /* IRQ line is shared */
> +};
> +
> +static LIST_HEAD(quirk_list);
> static void __iomem *irqc;
>
> /* first byte sets the memory pointer, following are consecutive reg values */
> static u8 da9063_irq_clr[] = { DA9063_REG_IRQ_MASK_A, 0xff, 0xff, 0xff, 0xff };
> static u8 da9210_irq_clr[] = { DA9210_REG_MASK_A, 0xff, 0xff };
>
> -static struct i2c_msg da9xxx_msgs[3] = {
> - {
> - .addr = 0x58,
> - .len = ARRAY_SIZE(da9063_irq_clr),
> - .buf = da9063_irq_clr,
> - }, {
> - .addr = 0x68,
> - .len = ARRAY_SIZE(da9210_irq_clr),
> - .buf = da9210_irq_clr,
> - }, {
> - .addr = 0x70,
> - .len = ARRAY_SIZE(da9210_irq_clr),
> - .buf = da9210_irq_clr,
> - },
> +static struct i2c_msg da9063_msgs = {
da9063_msg? (it's a single message)
> + .len = ARRAY_SIZE(da9063_irq_clr),
> + .buf = da9063_irq_clr,
> +};
> +
> +static struct i2c_msg da9210_msgs = {
da9210_msg?
> + .len = ARRAY_SIZE(da9210_irq_clr),
> + .buf = da9210_irq_clr,
> +};
> @@ -122,7 +143,13 @@ static struct notifier_block regulator_quirk_nb = {
>
> static int __init rcar_gen2_regulator_quirk(void)
> {
> - u32 mon;
> + struct device_node *np;
> + const struct of_device_id *id;
> + struct regulator_quirk *quirk;
> + struct regulator_quirk *pos;
> + struct of_phandle_args *argsa, *argsb;
> + u32 mon, addr;
> + int ret;
Some people prefer "Reverse Christmas Tree Ordering", i.e. longest line first.
>
> if (!of_machine_is_compatible("renesas,koelsch") &&
> !of_machine_is_compatible("renesas,lager") &&
> @@ -130,6 +157,45 @@ static int __init rcar_gen2_regulator_quirk(void)
> !of_machine_is_compatible("renesas,gose"))
> return -ENODEV;
I think the board checks above can be removed. That will auto-enable the
fix on e.g. Porter (once its regulators have ended up in DTS, of course).
>
> + for_each_matching_node_and_match(np, rcar_gen2_quirk_match, &id) {
> + if (!np || !of_device_is_available(np))
!np cannot happen
> + break;
> +
> + quirk = kzalloc(sizeof(*quirk), GFP_KERNEL);
Missing NULL check
> +
> + argsa = &quirk->irq_args;
> + memcpy(&quirk->i2c_msg, id->data, sizeof(quirk->i2c_msg));
> +
> + ret = of_property_read_u32(np, "reg", &addr);
> + if (ret)
> + return ret;
I think it's safer to skip this entry and continue, after calling
kfree(quirk), of course.
> +
> + quirk->id = id;
> + quirk->i2c_msg.addr = addr;
> + quirk->shared = false;
No need to clear shared, it was cleared by kzalloc().
> +
> + ret = of_irq_parse_one(np, 0, &quirk->irq_args);
> + if (ret)
> + return ret;
kfree(quirk) and continue...
Works fine on Koelsch, so
Tested-by: Geert Uytterhoeven <geert+renesas@glider.be>
Gr{oetje,eeting}s,
Geert
--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert at linux-m68k.org
In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
-- Linus Torvalds
^ permalink raw reply
* [PATCH/RFT 1/2] PCI: rcar: Add compatible string for r8a77965
From: Geert Uytterhoeven @ 2018-06-11 10:16 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1528373494-18503-2-git-send-email-ykaneko0929@gmail.com>
On Thu, Jun 7, 2018 at 2:14 PM Yoshihiro Kaneko <ykaneko0929@gmail.com> wrote:
> This patch adds support for r8a77965 (R-Car M3-N)
>
> Signed-off-by: Yoshihiro Kaneko <ykaneko0929@gmail.com>
Reviewed-by: Geert Uytterhoeven <geert+renesas@glider.be>
Gr{oetje,eeting}s,
Geert
--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert at linux-m68k.org
In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
-- Linus Torvalds
^ permalink raw reply
* handling voice calls in ALSA soc (on Droid 4)
From: Pavel Machek @ 2018-06-11 10:25 UTC (permalink / raw)
To: linux-arm-kernel
Hi!
During voice call, I need audio components to be active "as if" aplay
or arecord was running, because modem needs to comunicate with speaker
and microphone.
I hacked something up, but... I believe I'll need help here. Look at
"enable_call" for "interesting" stuff I had to do.
...and also. What is right interface for this? Mixer component that
says if voice call is active or not?
Any ideas?
Thanks,
Pavel
(edited).
+++ b/sound/soc/codecs/cpcap.c
@@ -330,6 +330,10 @@ static const char * const cpcap_in_left_mux_texts[] = {
"Off", "Mic 2", "Ext Left"
};
+static const char * const cpcap_mode_texts[] = {
+ "Normal", "Handsfree", "Call",
+};
+
/*
* input muxes use unusual register layout, so that we need to use custom
* getter/setter methods
@@ -354,6 +358,8 @@ static SOC_ENUM_SINGLE_DECL(cpcap_hs_l_mux_enum, 0, 6, cpcap_out_mux_texts);
static SOC_ENUM_SINGLE_DECL(cpcap_emu_l_mux_enum, 0, 7, cpcap_out_mux_texts);
static SOC_ENUM_SINGLE_DECL(cpcap_emu_r_mux_enum, 0, 8, cpcap_out_mux_texts);
+static SOC_ENUM_SINGLE_DECL(cpcap_mode_enum, 0, 9, cpcap_mode_texts);
+
static int cpcap_output_mux_get_enum(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
@@ -442,6 +448,211 @@ static int cpcap_output_mux_put_enum(struct snd_kcontrol *kcontrol,
return 0;
}
+static int mode;
+
+static int cpcap_mode_get_enum(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ ucontrol->value.enumerated.item[0] = mode;
+
+ return 0;
+}
+
+static struct snd_soc_dai *voice_codec_dai_hack;
+
+static int enable_call(struct snd_soc_component *component, int on)
+{
+ struct cpcap_audio *cpcap = snd_soc_component_get_drvdata(component);
+ struct snd_soc_pcm_runtime *rt;
+
+ rt = snd_soc_get_pcm_runtime(component->card, "40126000.mcbsp-cpcap-voice");
+ printk("num_dai: %d, got runtime %lx\n", component->num_dai, rt);
+
+ if (rt) {
+ snd_soc_dapm_stream_event(rt, SNDRV_PCM_STREAM_PLAYBACK, SND_SOC_DAPM_STREAM_START);
+ snd_soc_dapm_stream_event(rt, SNDRV_PCM_STREAM_CAPTURE, SND_SOC_DAPM_STREAM_START);
+ }
+
+ cpcap_set_sysclk(cpcap, CPCAP_DAI_VOICE, 1, 19200000);
+ cpcap_set_samprate(cpcap, CPCAP_DAI_VOICE, 8000);
+
+ cpcap_voice_set_dai_fmt(voice_codec_dai_hack,
+ SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM );
+
+ return 0;
+}
+
+static int cpcap_mode_put_enum(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_component *component = snd_soc_dapm_kcontrol_component(kcontrol);
+ struct cpcap_audio *cpcap = snd_soc_component_get_drvdata(component);
+ unsigned int muxval = ucontrol->value.enumerated.item[0];
+
+ printk("Requested mode %d\n", muxval);
+
+ mode = muxval;
+
+ switch (muxval) {
+ case 1:
+ enable_call(component, 1);
+ break;
+ case 2:
+ enable_call(component, 1);
+
+ regmap_assert(cpcap, CPCAP_REG_TXI, 0xffff, 0x0cc6);
...
+ break;
+
+ default:
+ break;
+ }
+
+ return 0;
+}
+
static int cpcap_input_right_mux_get_enum(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
@@ -630,6 +841,10 @@ static const struct snd_kcontrol_new cpcap_earpiece_mux =
SOC_DAPM_ENUM_EXT("Earpiece", cpcap_earpiece_mux_enum,
cpcap_output_mux_get_enum, cpcap_output_mux_put_enum);
+static const struct snd_kcontrol_new cpcap_mode =
+ SOC_DAPM_ENUM_EXT("Mode", cpcap_mode_enum,
+ cpcap_mode_get_enum, cpcap_mode_put_enum);
+
static const struct snd_kcontrol_new cpcap_hifi_mono_mixer_controls[] = {
SOC_DAPM_SINGLE("HiFi Mono Playback Switch",
CPCAP_REG_RXSDOA, CPCAP_BIT_MONO_DAC1, 1, 0),
@@ -771,6 +986,9 @@ static const struct snd_soc_dapm_widget cpcap_dapm_widgets[] = {
SND_SOC_DAPM_MUX("EMU Left Playback Route", SND_SOC_NOPM, 0, 0,
&cpcap_emu_left_mux),
+ SND_SOC_DAPM_MUX("Mode", SND_SOC_NOPM, 0, 0,
+ &cpcap_mode),
+
/* Output Amplifier */
SND_SOC_DAPM_PGA("Earpiece PGA",
CPCAP_REG_RXOA, CPCAP_BIT_A1_EAR_EN, 0, NULL, 0),
@@ -791,7 +1009,7 @@ static const struct snd_soc_dapm_widget cpcap_dapm_widgets[] = {
SND_SOC_DAPM_PGA("EMU Left PGA",
CPCAP_REG_RXOA, CPCAP_BIT_EMU_SPKR_L_EN, 0, NULL, 0),
- /* Headet Charge Pump */
+ /* Headset Charge Pump */
SND_SOC_DAPM_SUPPLY("Headset Charge Pump",
CPCAP_REG_RXOA, CPCAP_BIT_ST_HS_CP_EN, 0, NULL, 0),
@@ -1304,6 +1525,7 @@ static int cpcap_voice_set_dai_fmt(struct snd_soc_dai *codec_dai,
u16 val = 0x0000;
int err;
+ voice_codec_dai_hack = codec_dai;
dev_dbg(component->dev, "Voice setup dai format (%08x)", fmt);
/*
@@ -1343,10 +1565,7 @@ static int cpcap_voice_set_dai_fmt(struct snd_soc_dai *codec_dai,
break;
}
- if (val & BIT(CPCAP_BIT_CLK_INV))
- val &= ~BIT(CPCAP_BIT_CLK_INV);
- else
- val |= BIT(CPCAP_BIT_CLK_INV);
+ val ^= BIT(CPCAP_BIT_CLK_INV);
switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
case SND_SOC_DAIFMT_I2S:
--
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 181 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20180611/55bdfbe3/attachment.sig>
^ permalink raw reply
* [PATCH v3 0/6] add virt-dma support for imx-sdma
From: Lucas Stach @ 2018-06-11 11:01 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1528729173-28684-1-git-send-email-yibin.gong@nxp.com>
Hi Robin,
this series breaks serial DMA for me. I wasn't able to dig in deeper
yet. Please let me know if you can test/reproduce at your side, if not
I'll try to find some time to collect some more debug info.
Regards,
Lucas
Am Montag, den 11.06.2018, 22:59 +0800 schrieb Robin Gong:
> The legacy sdma driver has below limitations or drawbacks:
> ? 1. Hardcode the max BDs number as "PAGE_SIZE / sizeof(*)", and alloc
> ?????one page size for one channel regardless of only few BDs needed
> ?????most time. But in few cases, the max PAGE_SIZE maybe not enough.
> ? 2. One SDMA channel can't stop immediatley once channel disabled which
> ?????means SDMA interrupt may come in after this channel terminated.There
> ?????are some patches for this corner case such as commit "2746e2c389f9",
> ?????but not cover non-cyclic.
>
> The common virt-dma overcomes the above limitations. It can alloc bd
> dynamically and free bd once this tx transfer done. No memory wasted or
> maximum limititation here, only depends on how many memory can be requested
> from kernel. For No.2, such issue can be workaround by checking if there
> is available descript("sdmac->desc") now once the unwanted interrupt
> coming. At last the common virt-dma is easier for sdma driver maintain.
>
> Change from v2:
> ? 1. include Sascha's patch to make the main patch easier to review.
> ?????Thanks Sacha.
> ? 2. remove useless 'desc'/'chan' in struct sdma_channe.
>
> Change from v1:
> ? 1. split v1 patch into 5 patches.
> ? 2. remove some unnecessary condition check.
> ? 3. remove unnecessary 'pending' list.
>
> Robin Gong (5):
> ? dmaengine: imx-sdma: add virt-dma support
> ? Revert "dmaengine: imx-sdma: fix pagefault when channel is disabled
> ????during interrupt"
> ? dmaengine: imx-sdma: remove usless lock
> ? dmaengine: imx-sdma: remove the maximum limation for bd numbers
> ? dmaengine: imx-sdma: add sdma_transfer_init to decrease code overlap
>
> ?drivers/dma/Kconfig????|???1 +
> ?drivers/dma/imx-sdma.c | 392 ++++++++++++++++++++++++++++---------------------
> ?2 files changed, 227 insertions(+), 166 deletions(-)
>
> --?
> 2.7.4
>
> Robin Gong (5):
> ? dmaengine: imx-sdma: add virt-dma support
> ? Revert "dmaengine: imx-sdma: fix pagefault when channel is disabled
> ????during interrupt"
> ? dmaengine: imx-sdma: remove usless lock
> ? dmaengine: imx-sdma: remove the maximum limation for bd numbers
> ? dmaengine: imx-sdma: add sdma_transfer_init to decrease code overlap
>
> Sascha Hauer (1):
> ? dmaengine: imx-sdma: factor out a struct sdma_desc from struct
> ????sdma_channel
>
> ?drivers/dma/Kconfig????|???1 +
> ?drivers/dma/imx-sdma.c | 391 ++++++++++++++++++++++++++++---------------------
> ?2 files changed, 226 insertions(+), 166 deletions(-)
>
^ permalink raw reply
* [PATCH] net: thunderx: prevent concurrent data re-writing by nicvf_set_rx_mode
From: Dean Nelson @ 2018-06-11 11:22 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180610.123551.885190586229525170.davem@davemloft.net>
On 06/10/2018 02:35 PM, David Miller wrote:
> From: Vadim Lomovtsev <Vadim.Lomovtsev@caviumnetworks.com>
> Date: Fri, 8 Jun 2018 02:27:59 -0700
>
>> + /* Save message data locally to prevent them from
>> + * being overwritten by next ndo_set_rx_mode call().
>> + */
>> + spin_lock(&nic->rx_mode_wq_lock);
>> + mode = vf_work->mode;
>> + mc = vf_work->mc;
>> + vf_work->mc = NULL;
If I'm reading this code correctly, I believe nic->rx_mode_work.mc will
have been set to NULL before the lock is dropped by
nicvf_set_rx_mode_task() and acquired by nicvf_set_rx_mode().
>> + spin_unlock(&nic->rx_mode_wq_lock);
>
> At the moment you drop this lock, the memory behind 'mc' can be
> freed up by:
>
>> + spin_lock(&nic->rx_mode_wq_lock);
>> + kfree(nic->rx_mode_work.mc);
So the kfree() will be called with a NULL pointer and quickly return.
>
> And you'll crash when you dereference it above via
> __nicvf_set_rx_mode_task().
>
I believe the call to kfree() in nicvf_set_rx_mode() is there to free
up a mc_list that has been allocated by nicvf_set_rx_mode() during a
previous callback to the function, one that has not yet been processed
by nicvf_set_rx_mode_task().
In this way only the last 'unprocessed' callback to nicvf_set_rx_mode()
gets processed should there be multiple callbacks occurring between the
times the nicvf_set_rx_mode_task() runs.
In my testing with this patch, this is what I see happening.
^ permalink raw reply
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