* Re: [PATCH 0/2] x86/entry: simplify RESTORE_CR3
From: Andy Lutomirski @ 2020-05-29 18:17 UTC (permalink / raw)
To: Lai Jiangshan
Cc: LKML, Andy Lutomirski, Peter Zijlstra, Thomas Gleixner, X86 ML
In-Reply-To: <20200526043507.51977-1-laijs@linux.alibaba.com>
On Mon, May 25, 2020 at 9:35 PM Lai Jiangshan <laijs@linux.alibaba.com> wrote:
>
> When I searched percpu data touched by entry code for #DB
> protection[1], it seems to me RESTORE_CR3() does too much work,
> this patchset simplifies it.
>
> Patch 1 enhances 21e944591102("x86/mm: Optimize RESTORE_CR3") for
> kernel CR3.
>
> Patch 2 *reverts* 21e944591102("x86/mm: Optimize RESTORE_CR3") for
> User CR3.
This series looks correct, but I don't think it's 5.8 material. I
also want to try moving all this code to C, so it's possible this
little series will become obsolete.
>
> Cc: Andy Lutomirski <luto@kernel.org>
> Cc: Peter Zijlstra (Intel) <peterz@infradead.org>
> Cc: Thomas Gleixner <tglx@linutronix.de>
> Cc: x86@kernel.org
> Link: https://lore.kernel.org/lkml/20200525145102.122557-1-laijs@linux.alibaba.com
> Lai Jiangshan (2):
> x86/entry: Don't write to CR3 when restoring to kernel CR3
> x86/entry: always flush user CR3 in RESTORE_CR3
>
> arch/x86/entry/calling.h | 36 ++++++++----------------------------
> arch/x86/entry/entry_64.S | 6 +++---
> 2 files changed, 11 insertions(+), 31 deletions(-)
>
> --
> 2.20.1
>
^ permalink raw reply
* Re: [PATCH] ASoC: mediatek: mt6358: support DMIC one-wire mode
From: Mark Brown @ 2020-05-29 18:16 UTC (permalink / raw)
To: Tzung-Bi Shih
Cc: Hariprasad Kelam, Linux Kernel Mailing List, howie.huang,
Takashi Iwai, ALSA development, Jiaxin Yu, Liam Girdwood,
linux-mediatek, Matthias Brugger, linux-arm-kernel
In-Reply-To: <CA+Px+wVhXoU=BdBmMW0sdPtUrnQH+Kn6dkFdW-n67qEDGceCEQ@mail.gmail.com>
[-- Attachment #1: Type: text/plain, Size: 657 bytes --]
On Sat, May 30, 2020 at 01:26:20AM +0800, Tzung-Bi Shih wrote:
> On Fri, May 29, 2020 at 9:05 PM Mark Brown <broonie@kernel.org> wrote:
> > I thought that was normal for DMICs - is this selecting between left and
> > right or something?
> Not sure what is the common name but use the same context here.
> MT6358 accepts up to 2 PDM wires for 2 DMICs.
> If one wire mode is on, MT6358 only accepts 1 PDM wire.
> If one wire mode is off, MT6358 merges L/R from 2 PDM wires into 1
> I2S-like to SoC.
Oh, interesting - so it's essentially a mixer? Not seen that before but
makes sense. In any case this definitely seems like a good fit for a DT
property.
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]
^ permalink raw reply
* Re: [PATCH] spi: bcm2835: Enable shared interrupt support
From: Lukas Wunner @ 2020-05-29 18:16 UTC (permalink / raw)
To: Florian Fainelli
Cc: Nicolas Saenz Julienne, Mark Brown, Ray Jui, Scott Branden,
bcm-kernel-feedback-list, Martin Sperl, linux-spi,
linux-rpi-kernel, linux-arm-kernel, linux-kernel
In-Reply-To: <b832eaed-b480-b3b6-4df0-75abcc11f08a@gmail.com>
On Fri, May 29, 2020 at 11:03:48AM -0700, Florian Fainelli wrote:
> On 5/29/20 10:53 AM, Lukas Wunner wrote:
> > On Fri, May 29, 2020 at 10:46:01AM -0700, Florian Fainelli wrote:
> >> On 5/29/20 10:43 AM, Lukas Wunner wrote:
> >>> Finally, it would be nice if the check would be optimized away when
> >>> compiling for pre-RasPi4 products, maybe something like:
> >>>
> >>> + if (IS_ENABLED(CONFIG_ARM_LPAE) && !(cs & BCM2835_SPI_CS_INTR))
> >>> + return IRQ_NONE;
> >>
> >> Rather than keying this off ARM_LPAE or any other option, this should be
> >> keyed off a compatible string, that way we can even conditionally pass
> >> IRQF_SHARED to the interrupt handler if we care so much about performance.
> >
> > But a compatible string can't be checked at compile time, can it?
>
> No, but you can have a different interrupt handler that it set at
> runtime if you want to completely eliminate this comparison.
Good idea. In fact the IRQ handler for platforms with shared interrupts
could just be a wrapper which performs the BCM2835_SPI_CS_INTR check
then tail-calls the existing IRQ handler. The compiler would just
inline it and everything would be fine.
> My point is that CONFIG_ARM_LPAE is just too brittle, there is nothing
> that prevents you from using a non-LPAE kernel on the Pi 4, even PCIe
> could be made to work if using super section mappings to map the PCIe
> outbound space. Even on models with over 4GB of DRAM, if you are willing
> to lose some of it, it can work.
Agreed.
Thanks,
Lukas
^ permalink raw reply
* Re: [PATCH] ASoC: mediatek: mt6358: support DMIC one-wire mode
From: Mark Brown @ 2020-05-29 18:16 UTC (permalink / raw)
To: Tzung-Bi Shih
Cc: Hariprasad Kelam, Linux Kernel Mailing List, howie.huang,
Takashi Iwai, ALSA development, Jiaxin Yu, Liam Girdwood,
linux-mediatek, Matthias Brugger, linux-arm-kernel
In-Reply-To: <CA+Px+wVhXoU=BdBmMW0sdPtUrnQH+Kn6dkFdW-n67qEDGceCEQ@mail.gmail.com>
[-- Attachment #1.1: Type: text/plain, Size: 657 bytes --]
On Sat, May 30, 2020 at 01:26:20AM +0800, Tzung-Bi Shih wrote:
> On Fri, May 29, 2020 at 9:05 PM Mark Brown <broonie@kernel.org> wrote:
> > I thought that was normal for DMICs - is this selecting between left and
> > right or something?
> Not sure what is the common name but use the same context here.
> MT6358 accepts up to 2 PDM wires for 2 DMICs.
> If one wire mode is on, MT6358 only accepts 1 PDM wire.
> If one wire mode is off, MT6358 merges L/R from 2 PDM wires into 1
> I2S-like to SoC.
Oh, interesting - so it's essentially a mixer? Not seen that before but
makes sense. In any case this definitely seems like a good fit for a DT
property.
[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]
[-- Attachment #2: Type: text/plain, Size: 170 bytes --]
_______________________________________________
Linux-mediatek mailing list
Linux-mediatek@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-mediatek
^ permalink raw reply
* Re: [PATCH] ASoC: mediatek: mt6358: support DMIC one-wire mode
From: Mark Brown @ 2020-05-29 18:16 UTC (permalink / raw)
To: Tzung-Bi Shih
Cc: Hariprasad Kelam, Linux Kernel Mailing List, howie.huang,
Takashi Iwai, ALSA development, Jiaxin Yu, Liam Girdwood,
linux-mediatek, Matthias Brugger, linux-arm-kernel
In-Reply-To: <CA+Px+wVhXoU=BdBmMW0sdPtUrnQH+Kn6dkFdW-n67qEDGceCEQ@mail.gmail.com>
[-- Attachment #1.1: Type: text/plain, Size: 657 bytes --]
On Sat, May 30, 2020 at 01:26:20AM +0800, Tzung-Bi Shih wrote:
> On Fri, May 29, 2020 at 9:05 PM Mark Brown <broonie@kernel.org> wrote:
> > I thought that was normal for DMICs - is this selecting between left and
> > right or something?
> Not sure what is the common name but use the same context here.
> MT6358 accepts up to 2 PDM wires for 2 DMICs.
> If one wire mode is on, MT6358 only accepts 1 PDM wire.
> If one wire mode is off, MT6358 merges L/R from 2 PDM wires into 1
> I2S-like to SoC.
Oh, interesting - so it's essentially a mixer? Not seen that before but
makes sense. In any case this definitely seems like a good fit for a DT
property.
[-- 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] ASoC: mediatek: mt6358: support DMIC one-wire mode
From: Mark Brown @ 2020-05-29 18:16 UTC (permalink / raw)
To: Tzung-Bi Shih
Cc: Jiaxin Yu, Liam Girdwood, Takashi Iwai, Matthias Brugger,
Hariprasad Kelam, ALSA development, linux-arm-kernel,
linux-mediatek, Linux Kernel Mailing List, howie.huang
In-Reply-To: <CA+Px+wVhXoU=BdBmMW0sdPtUrnQH+Kn6dkFdW-n67qEDGceCEQ@mail.gmail.com>
[-- Attachment #1: Type: text/plain, Size: 657 bytes --]
On Sat, May 30, 2020 at 01:26:20AM +0800, Tzung-Bi Shih wrote:
> On Fri, May 29, 2020 at 9:05 PM Mark Brown <broonie@kernel.org> wrote:
> > I thought that was normal for DMICs - is this selecting between left and
> > right or something?
> Not sure what is the common name but use the same context here.
> MT6358 accepts up to 2 PDM wires for 2 DMICs.
> If one wire mode is on, MT6358 only accepts 1 PDM wire.
> If one wire mode is off, MT6358 merges L/R from 2 PDM wires into 1
> I2S-like to SoC.
Oh, interesting - so it's essentially a mixer? Not seen that before but
makes sense. In any case this definitely seems like a good fit for a DT
property.
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]
^ permalink raw reply
* [PATCH 10/10] dtoc add test for cd-gpios
From: Walter Lozano @ 2020-05-29 18:15 UTC (permalink / raw)
To: u-boot
In-Reply-To: <20200529181521.22073-1-walter.lozano@collabora.com>
Add a test for dtoc taking into account the cd-gpios property.
Signed-off-by: Walter Lozano <walter.lozano@collabora.com>
---
tools/dtoc/dtoc_test_phandle_cd_gpios.dts | 42 ++++++++++++++
tools/dtoc/test_dtoc.py | 67 +++++++++++++++++++++++
2 files changed, 109 insertions(+)
create mode 100644 tools/dtoc/dtoc_test_phandle_cd_gpios.dts
diff --git a/tools/dtoc/dtoc_test_phandle_cd_gpios.dts b/tools/dtoc/dtoc_test_phandle_cd_gpios.dts
new file mode 100644
index 0000000000..241743e73e
--- /dev/null
+++ b/tools/dtoc/dtoc_test_phandle_cd_gpios.dts
@@ -0,0 +1,42 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Test device tree file for dtoc
+ *
+ * Copyright 2020 Collabora Ltd.
+ */
+
+/dts-v1/;
+
+/ {
+ phandle: phandle-target {
+ u-boot,dm-pre-reloc;
+ compatible = "target";
+ intval = <0>;
+ #gpio-cells = <0>;
+ };
+
+ phandle_1: phandle2-target {
+ u-boot,dm-pre-reloc;
+ compatible = "target";
+ intval = <1>;
+ #gpio-cells = <1>;
+ };
+ phandle_2: phandle3-target {
+ u-boot,dm-pre-reloc;
+ compatible = "target";
+ intval = <2>;
+ #gpio-cells = <2>;
+ };
+
+ phandle-source {
+ u-boot,dm-pre-reloc;
+ compatible = "source";
+ cd-gpios = <&phandle &phandle_1 11 &phandle_2 12 13 &phandle>;
+ };
+
+ phandle-source2 {
+ u-boot,dm-pre-reloc;
+ compatible = "source";
+ cd-gpios = <&phandle>;
+ };
+};
diff --git a/tools/dtoc/test_dtoc.py b/tools/dtoc/test_dtoc.py
index 4bfbab7d37..a59f8aa9a6 100755
--- a/tools/dtoc/test_dtoc.py
+++ b/tools/dtoc/test_dtoc.py
@@ -395,6 +395,73 @@ U_BOOT_DEVICE(phandle_source2) = {
void populate_phandle_data(void) {
\tdtv_phandle_source2.clocks[0].node = DM_GET_DEVICE(phandle_target);
}
+''', data)
+
+ def test_phandle_cd_gpio(self):
+ """Test that phandle targets are generated when unsing cd-gpios"""
+ dtb_file = get_dtb_file('dtoc_test_phandle_cd_gpios.dts')
+ output = tools.GetOutputFilename('output')
+ dtb_platdata.run_steps(['platdata'], dtb_file, False, output, True)
+ with open(output) as infile:
+ data = infile.read()
+ self._CheckStrings(C_HEADER + '''
+static struct dtd_target dtv_phandle_target = {
+\t.intval\t\t\t= 0x0,
+};
+U_BOOT_DEVICE(phandle_target) = {
+\t.name\t\t= "target",
+\t.platdata\t= &dtv_phandle_target,
+\t.platdata_size\t= sizeof(dtv_phandle_target),
+};
+
+static struct dtd_target dtv_phandle2_target = {
+\t.intval\t\t\t= 0x1,
+};
+U_BOOT_DEVICE(phandle2_target) = {
+\t.name\t\t= "target",
+\t.platdata\t= &dtv_phandle2_target,
+\t.platdata_size\t= sizeof(dtv_phandle2_target),
+};
+
+static struct dtd_target dtv_phandle3_target = {
+\t.intval\t\t\t= 0x2,
+};
+U_BOOT_DEVICE(phandle3_target) = {
+\t.name\t\t= "target",
+\t.platdata\t= &dtv_phandle3_target,
+\t.platdata_size\t= sizeof(dtv_phandle3_target),
+};
+
+static struct dtd_source dtv_phandle_source = {
+\t.cd_gpios\t\t= {
+\t\t\t{NULL, {}},
+\t\t\t{NULL, {11}},
+\t\t\t{NULL, {12, 13}},
+\t\t\t{NULL, {}},},
+};
+U_BOOT_DEVICE(phandle_source) = {
+\t.name\t\t= "source",
+\t.platdata\t= &dtv_phandle_source,
+\t.platdata_size\t= sizeof(dtv_phandle_source),
+};
+
+static struct dtd_source dtv_phandle_source2 = {
+\t.cd_gpios\t\t= {
+\t\t\t{NULL, {}},},
+};
+U_BOOT_DEVICE(phandle_source2) = {
+\t.name\t\t= "source",
+\t.platdata\t= &dtv_phandle_source2,
+\t.platdata_size\t= sizeof(dtv_phandle_source2),
+};
+
+void populate_phandle_data(void) {
+\tdtv_phandle_source.cd_gpios[0].node = DM_GET_DEVICE(phandle_target);
+\tdtv_phandle_source.cd_gpios[1].node = DM_GET_DEVICE(phandle2_target);
+\tdtv_phandle_source.cd_gpios[2].node = DM_GET_DEVICE(phandle3_target);
+\tdtv_phandle_source.cd_gpios[3].node = DM_GET_DEVICE(phandle_target);
+\tdtv_phandle_source2.cd_gpios[0].node = DM_GET_DEVICE(phandle_target);
+}
''', data)
def test_phandle_bad(self):
--
2.20.1
^ permalink raw reply related
* [PATCH 09/10] dtoc: update dtb_platdata to support cd-gpios
From: Walter Lozano @ 2020-05-29 18:15 UTC (permalink / raw)
To: u-boot
In-Reply-To: <20200529181521.22073-1-walter.lozano@collabora.com>
Currently dtoc does not support the property cd-gpios used to declare
the gpios for card detect in mmc.
This patch adds support to cd-gpios property.
Signed-off-by: Walter Lozano <walter.lozano@collabora.com>
---
tools/dtoc/dtb_platdata.py | 13 ++++++++-----
tools/dtoc/test_dtoc.py | 2 +-
2 files changed, 9 insertions(+), 6 deletions(-)
diff --git a/tools/dtoc/dtb_platdata.py b/tools/dtoc/dtb_platdata.py
index 59b720703c..3f7defb26e 100644
--- a/tools/dtoc/dtb_platdata.py
+++ b/tools/dtoc/dtb_platdata.py
@@ -250,7 +250,7 @@ class DtbPlatdata(object):
Return:
Number of argument cells is this is a phandle, else None
"""
- if prop.name in ['clocks']:
+ if prop.name in ['clocks', 'cd-gpios']:
if not isinstance(prop.value, list):
prop.value = [prop.value]
val = prop.value
@@ -270,11 +270,14 @@ class DtbPlatdata(object):
if not target:
raise ValueError("Cannot parse '%s' in node '%s'" %
(prop.name, node_name))
- prop_name = '#clock-cells'
- cells = target.props.get(prop_name)
+ cells = None
+ for prop_name in ['#clock-cells', '#gpio-cells']:
+ cells = target.props.get(prop_name)
+ if cells:
+ break
if not cells:
- raise ValueError("Node '%s' has no '%s' property" %
- (target.name, prop_name))
+ raise ValueError("Node '%s' has no cells property" %
+ (target.name))
num_args = fdt_util.fdt32_to_cpu(cells.value)
max_args = max(max_args, num_args)
args.append(num_args)
diff --git a/tools/dtoc/test_dtoc.py b/tools/dtoc/test_dtoc.py
index f2155528f8..4bfbab7d37 100755
--- a/tools/dtoc/test_dtoc.py
+++ b/tools/dtoc/test_dtoc.py
@@ -414,7 +414,7 @@ void populate_phandle_data(void) {
output = tools.GetOutputFilename('output')
with self.assertRaises(ValueError) as e:
dtb_platdata.run_steps(['struct'], dtb_file, False, output, True)
- self.assertIn("Node 'phandle-target' has no '#clock-cells' property",
+ self.assertIn("Node 'phandle-target' has no cells property",
str(e.exception))
def test_aliases(self):
--
2.20.1
^ permalink raw reply related
* [PATCH 08/10] dtoc: update tests to match new platdata
From: Walter Lozano @ 2020-05-29 18:15 UTC (permalink / raw)
To: u-boot
In-Reply-To: <20200529181521.22073-1-walter.lozano@collabora.com>
After using a new approach to link nodes when OF_PLATDATA is enabled
the test cases need to be update.
This patch updates the tests based on this new implementation.
Signed-off-by: Walter Lozano <walter.lozano@collabora.com>
---
tools/dtoc/test_dtoc.py | 95 +++++++++++++++++++++++------------------
1 file changed, 54 insertions(+), 41 deletions(-)
diff --git a/tools/dtoc/test_dtoc.py b/tools/dtoc/test_dtoc.py
index a9b605cac8..f2155528f8 100755
--- a/tools/dtoc/test_dtoc.py
+++ b/tools/dtoc/test_dtoc.py
@@ -47,6 +47,9 @@ C_HEADER = '''/*
#include <dt-structs.h>
'''
+C_EMPTY_POPULATE_PHANDLE_DATA = '''void populate_phandle_data(void) {
+}
+'''
def get_dtb_file(dts_fname, capture_stderr=False):
@@ -162,7 +165,7 @@ class TestDtoc(unittest.TestCase):
dtb_platdata.run_steps(['platdata'], dtb_file, False, output, True)
with open(output) as infile:
lines = infile.read().splitlines()
- self.assertEqual(C_HEADER.splitlines() + [''], lines)
+ self.assertEqual(C_HEADER.splitlines() + [''] + C_EMPTY_POPULATE_PHANDLE_DATA.splitlines(), lines)
def test_simple(self):
"""Test output from some simple nodes with various types of data"""
@@ -197,7 +200,7 @@ struct dtd_sandbox_spl_test_2 {
with open(output) as infile:
data = infile.read()
self._CheckStrings(C_HEADER + '''
-static const struct dtd_sandbox_spl_test dtv_spl_test = {
+static struct dtd_sandbox_spl_test dtv_spl_test = {
\t.boolval\t\t= true,
\t.bytearray\t\t= {0x6, 0x0, 0x0},
\t.byteval\t\t= 0x5,
@@ -215,7 +218,7 @@ U_BOOT_DEVICE(spl_test) = {
\t.platdata_size\t= sizeof(dtv_spl_test),
};
-static const struct dtd_sandbox_spl_test dtv_spl_test2 = {
+static struct dtd_sandbox_spl_test dtv_spl_test2 = {
\t.bytearray\t\t= {0x1, 0x23, 0x34},
\t.byteval\t\t= 0x8,
\t.intarray\t\t= {0x5, 0x0, 0x0, 0x0},
@@ -231,7 +234,7 @@ U_BOOT_DEVICE(spl_test2) = {
\t.platdata_size\t= sizeof(dtv_spl_test2),
};
-static const struct dtd_sandbox_spl_test dtv_spl_test3 = {
+static struct dtd_sandbox_spl_test dtv_spl_test3 = {
\t.stringarray\t\t= {"one", "", ""},
};
U_BOOT_DEVICE(spl_test3) = {
@@ -240,7 +243,7 @@ U_BOOT_DEVICE(spl_test3) = {
\t.platdata_size\t= sizeof(dtv_spl_test3),
};
-static const struct dtd_sandbox_spl_test_2 dtv_spl_test4 = {
+static struct dtd_sandbox_spl_test_2 dtv_spl_test4 = {
};
U_BOOT_DEVICE(spl_test4) = {
\t.name\t\t= "sandbox_spl_test_2",
@@ -248,7 +251,7 @@ U_BOOT_DEVICE(spl_test4) = {
\t.platdata_size\t= sizeof(dtv_spl_test4),
};
-static const struct dtd_sandbox_i2c_test dtv_i2c_at_0 = {
+static struct dtd_sandbox_i2c_test dtv_i2c_at_0 = {
};
U_BOOT_DEVICE(i2c_at_0) = {
\t.name\t\t= "sandbox_i2c_test",
@@ -256,7 +259,7 @@ U_BOOT_DEVICE(i2c_at_0) = {
\t.platdata_size\t= sizeof(dtv_i2c_at_0),
};
-static const struct dtd_sandbox_pmic_test dtv_pmic_at_9 = {
+static struct dtd_sandbox_pmic_test dtv_pmic_at_9 = {
\t.low_power\t\t= true,
\t.reg\t\t\t= {0x9, 0x0},
};
@@ -266,7 +269,7 @@ U_BOOT_DEVICE(pmic_at_9) = {
\t.platdata_size\t= sizeof(dtv_pmic_at_9),
};
-''', data)
+''' + C_EMPTY_POPULATE_PHANDLE_DATA, data)
def test_phandle(self):
"""Test output from a node containing a phandle reference"""
@@ -288,7 +291,7 @@ struct dtd_target {
with open(output) as infile:
data = infile.read()
self._CheckStrings(C_HEADER + '''
-static const struct dtd_target dtv_phandle_target = {
+static struct dtd_target dtv_phandle_target = {
\t.intval\t\t\t= 0x0,
};
U_BOOT_DEVICE(phandle_target) = {
@@ -297,7 +300,7 @@ U_BOOT_DEVICE(phandle_target) = {
\t.platdata_size\t= sizeof(dtv_phandle_target),
};
-static const struct dtd_target dtv_phandle2_target = {
+static struct dtd_target dtv_phandle2_target = {
\t.intval\t\t\t= 0x1,
};
U_BOOT_DEVICE(phandle2_target) = {
@@ -306,7 +309,7 @@ U_BOOT_DEVICE(phandle2_target) = {
\t.platdata_size\t= sizeof(dtv_phandle2_target),
};
-static const struct dtd_target dtv_phandle3_target = {
+static struct dtd_target dtv_phandle3_target = {
\t.intval\t\t\t= 0x2,
};
U_BOOT_DEVICE(phandle3_target) = {
@@ -315,12 +318,12 @@ U_BOOT_DEVICE(phandle3_target) = {
\t.platdata_size\t= sizeof(dtv_phandle3_target),
};
-static const struct dtd_source dtv_phandle_source = {
+static struct dtd_source dtv_phandle_source = {
\t.clocks\t\t\t= {
-\t\t\t{&dtv_phandle_target, {}},
-\t\t\t{&dtv_phandle2_target, {11}},
-\t\t\t{&dtv_phandle3_target, {12, 13}},
-\t\t\t{&dtv_phandle_target, {}},},
+\t\t\t{NULL, {}},
+\t\t\t{NULL, {11}},
+\t\t\t{NULL, {12, 13}},
+\t\t\t{NULL, {}},},
};
U_BOOT_DEVICE(phandle_source) = {
\t.name\t\t= "source",
@@ -328,9 +331,9 @@ U_BOOT_DEVICE(phandle_source) = {
\t.platdata_size\t= sizeof(dtv_phandle_source),
};
-static const struct dtd_source dtv_phandle_source2 = {
+static struct dtd_source dtv_phandle_source2 = {
\t.clocks\t\t\t= {
-\t\t\t{&dtv_phandle_target, {}},},
+\t\t\t{NULL, {}},},
};
U_BOOT_DEVICE(phandle_source2) = {
\t.name\t\t= "source",
@@ -338,6 +341,13 @@ U_BOOT_DEVICE(phandle_source2) = {
\t.platdata_size\t= sizeof(dtv_phandle_source2),
};
+void populate_phandle_data(void) {
+\tdtv_phandle_source.clocks[0].node = DM_GET_DEVICE(phandle_target);
+\tdtv_phandle_source.clocks[1].node = DM_GET_DEVICE(phandle2_target);
+\tdtv_phandle_source.clocks[2].node = DM_GET_DEVICE(phandle3_target);
+\tdtv_phandle_source.clocks[3].node = DM_GET_DEVICE(phandle_target);
+\tdtv_phandle_source2.clocks[0].node = DM_GET_DEVICE(phandle_target);
+}
''', data)
def test_phandle_single(self):
@@ -364,7 +374,7 @@ struct dtd_target {
with open(output) as infile:
data = infile.read()
self._CheckStrings(C_HEADER + '''
-static const struct dtd_target dtv_phandle_target = {
+static struct dtd_target dtv_phandle_target = {
};
U_BOOT_DEVICE(phandle_target) = {
\t.name\t\t= "target",
@@ -372,9 +382,9 @@ U_BOOT_DEVICE(phandle_target) = {
\t.platdata_size\t= sizeof(dtv_phandle_target),
};
-static const struct dtd_source dtv_phandle_source2 = {
+static struct dtd_source dtv_phandle_source2 = {
\t.clocks\t\t\t= {
-\t\t\t{&dtv_phandle_target, {}},},
+\t\t\t{NULL, {}},},
};
U_BOOT_DEVICE(phandle_source2) = {
\t.name\t\t= "source",
@@ -382,6 +392,9 @@ U_BOOT_DEVICE(phandle_source2) = {
\t.platdata_size\t= sizeof(dtv_phandle_source2),
};
+void populate_phandle_data(void) {
+\tdtv_phandle_source2.clocks[0].node = DM_GET_DEVICE(phandle_target);
+}
''', data)
def test_phandle_bad(self):
@@ -423,7 +436,7 @@ struct dtd_compat1 {
with open(output) as infile:
data = infile.read()
self._CheckStrings(C_HEADER + '''
-static const struct dtd_compat1 dtv_spl_test = {
+static struct dtd_compat1 dtv_spl_test = {
\t.intval\t\t\t= 0x1,
};
U_BOOT_DEVICE(spl_test) = {
@@ -432,7 +445,7 @@ U_BOOT_DEVICE(spl_test) = {
\t.platdata_size\t= sizeof(dtv_spl_test),
};
-''', data)
+''' + C_EMPTY_POPULATE_PHANDLE_DATA, data)
def test_addresses64(self):
"""Test output from a node with a 'reg' property with na=2, ns=2"""
@@ -457,7 +470,7 @@ struct dtd_test3 {
with open(output) as infile:
data = infile.read()
self._CheckStrings(C_HEADER + '''
-static const struct dtd_test1 dtv_test1 = {
+static struct dtd_test1 dtv_test1 = {
\t.reg\t\t\t= {0x1234, 0x5678},
};
U_BOOT_DEVICE(test1) = {
@@ -466,7 +479,7 @@ U_BOOT_DEVICE(test1) = {
\t.platdata_size\t= sizeof(dtv_test1),
};
-static const struct dtd_test2 dtv_test2 = {
+static struct dtd_test2 dtv_test2 = {
\t.reg\t\t\t= {0x1234567890123456, 0x9876543210987654},
};
U_BOOT_DEVICE(test2) = {
@@ -475,7 +488,7 @@ U_BOOT_DEVICE(test2) = {
\t.platdata_size\t= sizeof(dtv_test2),
};
-static const struct dtd_test3 dtv_test3 = {
+static struct dtd_test3 dtv_test3 = {
\t.reg\t\t\t= {0x1234567890123456, 0x9876543210987654, 0x2, 0x3},
};
U_BOOT_DEVICE(test3) = {
@@ -484,7 +497,7 @@ U_BOOT_DEVICE(test3) = {
\t.platdata_size\t= sizeof(dtv_test3),
};
-''', data)
+''' + C_EMPTY_POPULATE_PHANDLE_DATA, data)
def test_addresses32(self):
"""Test output from a node with a 'reg' property with na=1, ns=1"""
@@ -506,7 +519,7 @@ struct dtd_test2 {
with open(output) as infile:
data = infile.read()
self._CheckStrings(C_HEADER + '''
-static const struct dtd_test1 dtv_test1 = {
+static struct dtd_test1 dtv_test1 = {
\t.reg\t\t\t= {0x1234, 0x5678},
};
U_BOOT_DEVICE(test1) = {
@@ -515,7 +528,7 @@ U_BOOT_DEVICE(test1) = {
\t.platdata_size\t= sizeof(dtv_test1),
};
-static const struct dtd_test2 dtv_test2 = {
+static struct dtd_test2 dtv_test2 = {
\t.reg\t\t\t= {0x12345678, 0x98765432, 0x2, 0x3},
};
U_BOOT_DEVICE(test2) = {
@@ -524,7 +537,7 @@ U_BOOT_DEVICE(test2) = {
\t.platdata_size\t= sizeof(dtv_test2),
};
-''', data)
+''' + C_EMPTY_POPULATE_PHANDLE_DATA, data)
def test_addresses64_32(self):
"""Test output from a node with a 'reg' property with na=2, ns=1"""
@@ -549,7 +562,7 @@ struct dtd_test3 {
with open(output) as infile:
data = infile.read()
self._CheckStrings(C_HEADER + '''
-static const struct dtd_test1 dtv_test1 = {
+static struct dtd_test1 dtv_test1 = {
\t.reg\t\t\t= {0x123400000000, 0x5678},
};
U_BOOT_DEVICE(test1) = {
@@ -558,7 +571,7 @@ U_BOOT_DEVICE(test1) = {
\t.platdata_size\t= sizeof(dtv_test1),
};
-static const struct dtd_test2 dtv_test2 = {
+static struct dtd_test2 dtv_test2 = {
\t.reg\t\t\t= {0x1234567890123456, 0x98765432},
};
U_BOOT_DEVICE(test2) = {
@@ -567,7 +580,7 @@ U_BOOT_DEVICE(test2) = {
\t.platdata_size\t= sizeof(dtv_test2),
};
-static const struct dtd_test3 dtv_test3 = {
+static struct dtd_test3 dtv_test3 = {
\t.reg\t\t\t= {0x1234567890123456, 0x98765432, 0x2, 0x3},
};
U_BOOT_DEVICE(test3) = {
@@ -576,7 +589,7 @@ U_BOOT_DEVICE(test3) = {
\t.platdata_size\t= sizeof(dtv_test3),
};
-''', data)
+''' + C_EMPTY_POPULATE_PHANDLE_DATA, data)
def test_addresses32_64(self):
"""Test output from a node with a 'reg' property with na=1, ns=2"""
@@ -601,7 +614,7 @@ struct dtd_test3 {
with open(output) as infile:
data = infile.read()
self._CheckStrings(C_HEADER + '''
-static const struct dtd_test1 dtv_test1 = {
+static struct dtd_test1 dtv_test1 = {
\t.reg\t\t\t= {0x1234, 0x567800000000},
};
U_BOOT_DEVICE(test1) = {
@@ -610,7 +623,7 @@ U_BOOT_DEVICE(test1) = {
\t.platdata_size\t= sizeof(dtv_test1),
};
-static const struct dtd_test2 dtv_test2 = {
+static struct dtd_test2 dtv_test2 = {
\t.reg\t\t\t= {0x12345678, 0x9876543210987654},
};
U_BOOT_DEVICE(test2) = {
@@ -619,7 +632,7 @@ U_BOOT_DEVICE(test2) = {
\t.platdata_size\t= sizeof(dtv_test2),
};
-static const struct dtd_test3 dtv_test3 = {
+static struct dtd_test3 dtv_test3 = {
\t.reg\t\t\t= {0x12345678, 0x9876543210987654, 0x2, 0x3},
};
U_BOOT_DEVICE(test3) = {
@@ -628,7 +641,7 @@ U_BOOT_DEVICE(test3) = {
\t.platdata_size\t= sizeof(dtv_test3),
};
-''', data)
+''' + C_EMPTY_POPULATE_PHANDLE_DATA, data)
def test_bad_reg(self):
"""Test that a reg property with an invalid type generates an error"""
@@ -668,7 +681,7 @@ struct dtd_sandbox_spl_test {
with open(output) as infile:
data = infile.read()
self._CheckStrings(C_HEADER + '''
-static const struct dtd_sandbox_spl_test dtv_spl_test = {
+static struct dtd_sandbox_spl_test dtv_spl_test = {
\t.intval\t\t\t= 0x1,
};
U_BOOT_DEVICE(spl_test) = {
@@ -677,7 +690,7 @@ U_BOOT_DEVICE(spl_test) = {
\t.platdata_size\t= sizeof(dtv_spl_test),
};
-static const struct dtd_sandbox_spl_test dtv_spl_test2 = {
+static struct dtd_sandbox_spl_test dtv_spl_test2 = {
\t.intarray\t\t= 0x5,
};
U_BOOT_DEVICE(spl_test2) = {
@@ -686,7 +699,7 @@ U_BOOT_DEVICE(spl_test2) = {
\t.platdata_size\t= sizeof(dtv_spl_test2),
};
-''', data)
+''' + C_EMPTY_POPULATE_PHANDLE_DATA, data)
def testStdout(self):
"""Test output to stdout"""
--
2.20.1
^ permalink raw reply related
* [PATCH 07/10] dm: doc: update of-plat with new phandle support
From: Walter Lozano @ 2020-05-29 18:15 UTC (permalink / raw)
To: u-boot
In-Reply-To: <20200529181521.22073-1-walter.lozano@collabora.com>
Update documentation to reflect the new phandle support when OF_PLATDATA
is used. Now phandles are implemented as pointers to U_BOOT_DEVICE,
which makes it possible to get a pointer to the actual device.
Signed-off-by: Walter Lozano <walter.lozano@collabora.com>
---
doc/driver-model/of-plat.rst | 24 ++++++++++++++++--------
1 file changed, 16 insertions(+), 8 deletions(-)
diff --git a/doc/driver-model/of-plat.rst b/doc/driver-model/of-plat.rst
index aa0c8dde91..67477feec3 100644
--- a/doc/driver-model/of-plat.rst
+++ b/doc/driver-model/of-plat.rst
@@ -69,9 +69,8 @@ strictly necessary. Notable problems include:
- Correct relations between nodes are not implemented. This means that
parent/child relations (like bus device iteration) do not work yet.
Some phandles (those that are recognised as such) are converted into
- a pointer to platform data. This pointer can potentially be used to
- access the referenced device (by searching for the pointer value).
- This feature is not yet implemented, however.
+ a pointer to struct driver_info. This pointer can be used to access
+ the referenced device.
How it works
@@ -146,10 +145,10 @@ and the following device declaration:
.clock_freq_min_max = {0x61a80, 0x8f0d180},
.vmmc_supply = 0xb,
.num_slots = 0x1,
- .clocks = {{&dtv_clock_controller_at_ff760000, 456},
- {&dtv_clock_controller_at_ff760000, 68},
- {&dtv_clock_controller_at_ff760000, 114},
- {&dtv_clock_controller_at_ff760000, 118}},
+ .clocks = {{NULL, 456},
+ {NULL, 68},
+ {NULL, 114},
+ {NULL, 118}},
.cap_mmc_highspeed = true,
.disable_wp = true,
.bus_width = 0x4,
@@ -164,6 +163,13 @@ and the following device declaration:
.platdata_size = sizeof(dtv_dwmmc_at_ff0c0000),
};
+ void populate_phandle_data(void) {
+ dtv_dwmmc_at_ff0c0000.clocks[0].node = DM_GET_DEVICE(clock_controller_at_ff760000);
+ dtv_dwmmc_at_ff0c0000.clocks[1].node = DM_GET_DEVICE(clock_controller_at_ff760000);
+ dtv_dwmmc_at_ff0c0000.clocks[2].node = DM_GET_DEVICE(clock_controller_at_ff760000);
+ dtv_dwmmc_at_ff0c0000.clocks[3].node = DM_GET_DEVICE(clock_controller_at_ff760000);
+ }
+
The device is then instantiated at run-time and the platform data can be
accessed using:
@@ -329,7 +335,9 @@ prevents them being used inadvertently. All usage must be bracketed with
#if CONFIG_IS_ENABLED(OF_PLATDATA).
The dt-platdata.c file contains the device declarations and is is built in
-spl/dt-platdata.c.
+spl/dt-platdata.c. It additionally contains the definition of
+populate_phandle_data() which is responsible of filling the phandle
+information by adding references to U_BOOT_DEVICE by using DM_GET_DEVICE
The beginnings of a libfdt Python module are provided. So far this only
implements a subset of the features.
--
2.20.1
^ permalink raw reply related
* [PATCH 06/10] dtoc: extend dtoc to use struct driver_info when linking nodes
From: Walter Lozano @ 2020-05-29 18:15 UTC (permalink / raw)
To: u-boot
In-Reply-To: <20200529181521.22073-1-walter.lozano@collabora.com>
In the current implementation, when dtoc parses a dtb to generate a struct
platdata it converts the information related to linked nodes as pointers
to struct platdata of destination nodes. By doing this, it makes
difficult to get pointer to udevices created based on these
information.
This patch extends dtoc to use struct driver_info when populating
information about linked nodes, which makes it easier to later get
the devices created. In this context, reimplement functions like
clk_get_by_index_platdata() which made use of the previous approach.
Signed-off-by: Walter Lozano <walter.lozano@collabora.com>
---
drivers/clk/clk-uclass.c | 11 +++++------
drivers/misc/irq-uclass.c | 10 ++++------
drivers/mmc/ftsdc010_mci.c | 2 +-
drivers/mmc/rockchip_dw_mmc.c | 2 +-
drivers/mmc/rockchip_sdhci.c | 2 +-
drivers/ram/rockchip/sdram_rk3399.c | 2 +-
drivers/spi/rk_spi.c | 2 +-
include/clk.h | 4 ++--
tools/dtoc/dtb_platdata.py | 24 +++++++++++++++++++++---
9 files changed, 37 insertions(+), 22 deletions(-)
diff --git a/drivers/clk/clk-uclass.c b/drivers/clk/clk-uclass.c
index 71878474eb..412f26cd29 100644
--- a/drivers/clk/clk-uclass.c
+++ b/drivers/clk/clk-uclass.c
@@ -25,17 +25,16 @@ static inline const struct clk_ops *clk_dev_ops(struct udevice *dev)
#if CONFIG_IS_ENABLED(OF_CONTROL)
# if CONFIG_IS_ENABLED(OF_PLATDATA)
-int clk_get_by_index_platdata(struct udevice *dev, int index,
- struct phandle_1_arg *cells, struct clk *clk)
+int clk_get_by_driver_info(struct udevice *dev, struct phandle_1_arg *cells,
+ struct clk *clk)
{
int ret;
- if (index != 0)
- return -ENOSYS;
- ret = uclass_get_device(UCLASS_CLK, 0, &clk->dev);
+ ret = device_get_by_driver_info((struct driver_info *)cells->node,
+ &clk->dev);
if (ret)
return ret;
- clk->id = cells[0].arg[0];
+ clk->id = cells->arg[0];
return 0;
}
diff --git a/drivers/misc/irq-uclass.c b/drivers/misc/irq-uclass.c
index 61aa10e465..3c38681108 100644
--- a/drivers/misc/irq-uclass.c
+++ b/drivers/misc/irq-uclass.c
@@ -63,17 +63,15 @@ int irq_read_and_clear(struct irq *irq)
}
#if CONFIG_IS_ENABLED(OF_PLATDATA)
-int irq_get_by_index_platdata(struct udevice *dev, int index,
- struct phandle_1_arg *cells, struct irq *irq)
+int irq_get_by_driver_info(struct udevice *dev,
+ struct phandle_1_arg *cells, struct irq *irq)
{
int ret;
- if (index != 0)
- return -ENOSYS;
- ret = uclass_get_device(UCLASS_IRQ, 0, &irq->dev);
+ ret = device_get_by_driver_info(cells->node, &irq->dev);
if (ret)
return ret;
- irq->id = cells[0].arg[0];
+ irq->id = cells->arg[0];
return 0;
}
diff --git a/drivers/mmc/ftsdc010_mci.c b/drivers/mmc/ftsdc010_mci.c
index 9c15eb36d6..efa92d48be 100644
--- a/drivers/mmc/ftsdc010_mci.c
+++ b/drivers/mmc/ftsdc010_mci.c
@@ -437,7 +437,7 @@ static int ftsdc010_mmc_probe(struct udevice *dev)
chip->priv = dev;
chip->dev_index = 1;
memcpy(priv->minmax, dtplat->clock_freq_min_max, sizeof(priv->minmax));
- ret = clk_get_by_index_platdata(dev, 0, dtplat->clocks, &priv->clk);
+ ret = clk_get_by_driver_info(dev, dtplat->clocks, &priv->clk);
if (ret < 0)
return ret;
#endif
diff --git a/drivers/mmc/rockchip_dw_mmc.c b/drivers/mmc/rockchip_dw_mmc.c
index a0e1be8794..7b4479543c 100644
--- a/drivers/mmc/rockchip_dw_mmc.c
+++ b/drivers/mmc/rockchip_dw_mmc.c
@@ -120,7 +120,7 @@ static int rockchip_dwmmc_probe(struct udevice *dev)
priv->minmax[0] = 400000; /* 400 kHz */
priv->minmax[1] = dtplat->max_frequency;
- ret = clk_get_by_index_platdata(dev, 0, dtplat->clocks, &priv->clk);
+ ret = clk_get_by_driver_info(dev, dtplat->clocks, &priv->clk);
if (ret < 0)
return ret;
#else
diff --git a/drivers/mmc/rockchip_sdhci.c b/drivers/mmc/rockchip_sdhci.c
index b440996b26..b073f1a08d 100644
--- a/drivers/mmc/rockchip_sdhci.c
+++ b/drivers/mmc/rockchip_sdhci.c
@@ -46,7 +46,7 @@ static int arasan_sdhci_probe(struct udevice *dev)
host->name = dev->name;
host->ioaddr = map_sysmem(dtplat->reg[0], dtplat->reg[1]);
max_frequency = dtplat->max_frequency;
- ret = clk_get_by_index_platdata(dev, 0, dtplat->clocks, &clk);
+ ret = clk_get_by_driver_info(dev, dtplat->clocks, &clk);
#else
max_frequency = dev_read_u32_default(dev, "max-frequency", 0);
ret = clk_get_by_index(dev, 0, &clk);
diff --git a/drivers/ram/rockchip/sdram_rk3399.c b/drivers/ram/rockchip/sdram_rk3399.c
index d69ef01d08..87ec25f893 100644
--- a/drivers/ram/rockchip/sdram_rk3399.c
+++ b/drivers/ram/rockchip/sdram_rk3399.c
@@ -3125,7 +3125,7 @@ static int rk3399_dmc_init(struct udevice *dev)
priv->cic, priv->pmugrf, priv->pmusgrf, priv->pmucru, priv->pmu);
#if CONFIG_IS_ENABLED(OF_PLATDATA)
- ret = clk_get_by_index_platdata(dev, 0, dtplat->clocks, &priv->ddr_clk);
+ ret = clk_get_by_driver_info(dev, dtplat->clocks, &priv->ddr_clk);
#else
ret = clk_get_by_index(dev, 0, &priv->ddr_clk);
#endif
diff --git a/drivers/spi/rk_spi.c b/drivers/spi/rk_spi.c
index 95eeb8307a..bd0337272e 100644
--- a/drivers/spi/rk_spi.c
+++ b/drivers/spi/rk_spi.c
@@ -181,7 +181,7 @@ static int conv_of_platdata(struct udevice *dev)
plat->base = dtplat->reg[0];
plat->frequency = 20000000;
- ret = clk_get_by_index_platdata(dev, 0, dtplat->clocks, &priv->clk);
+ ret = clk_get_by_driver_info(dev, dtplat->clocks, &priv->clk);
if (ret < 0)
return ret;
dev->req_seq = 0;
diff --git a/include/clk.h b/include/clk.h
index c6a2713f62..a62e2efa2c 100644
--- a/include/clk.h
+++ b/include/clk.h
@@ -89,8 +89,8 @@ struct clk_bulk {
#if CONFIG_IS_ENABLED(OF_CONTROL) && CONFIG_IS_ENABLED(CLK)
struct phandle_1_arg;
-int clk_get_by_index_platdata(struct udevice *dev, int index,
- struct phandle_1_arg *cells, struct clk *clk);
+int clk_get_by_driver_info(struct udevice *dev,
+ struct phandle_1_arg *cells, struct clk *clk);
/**
* clk_get_by_index - Get/request a clock by integer index.
diff --git a/tools/dtoc/dtb_platdata.py b/tools/dtoc/dtb_platdata.py
index 0a54188348..59b720703c 100644
--- a/tools/dtoc/dtb_platdata.py
+++ b/tools/dtoc/dtb_platdata.py
@@ -146,6 +146,7 @@ class DtbPlatdata(object):
_aliases: Dict that hold aliases for compatible strings
_drivers: List of valid driver names found in drivers/
_driver_aliases: Dict that holds aliases for driver names
+ _links: List of links to be included in populate_phandle_data
"""
def __init__(self, dtb_fname, include_disabled, warning_disable):
self._fdt = None
@@ -158,6 +159,7 @@ class DtbPlatdata(object):
self._aliases = {}
self._drivers = []
self._driver_aliases = {}
+ self._links = []
def get_normalized_compat_name(self, node):
"""Get a node's normalized compat name
@@ -540,7 +542,7 @@ class DtbPlatdata(object):
"""
struct_name, _ = self.get_normalized_compat_name(node)
var_name = conv_name_to_c(node.name)
- self.buf('static const struct %s%s %s%s = {\n' %
+ self.buf('static struct %s%s %s%s = {\n' %
(STRUCT_PREFIX, struct_name, VAL_PREFIX, var_name))
for pname in sorted(node.props):
prop = node.props[pname]
@@ -559,6 +561,7 @@ class DtbPlatdata(object):
if info:
# Process the list as pairs of (phandle, id)
pos = 0
+ item = 0
for args in info.args:
phandle_cell = prop.value[pos]
phandle = fdt_util.fdt32_to_cpu(phandle_cell)
@@ -568,8 +571,14 @@ class DtbPlatdata(object):
for i in range(args):
arg_values.append(str(fdt_util.fdt32_to_cpu(prop.value[pos + 1 + i])))
pos += 1 + args
- vals.append('\t{&%s%s, {%s}}' % (VAL_PREFIX, name,
- ', '.join(arg_values)))
+ # node member is filled with NULL as the real value
+ # will be update at run-time by populate_phandle_data()
+ vals.append('\t{NULL, {%s}}' % (', '.join(arg_values)))
+ var_node = '%s%s.%s[%d].node' % (VAL_PREFIX, var_name, member_name, item)
+ # Save the the link information to be use to define
+ # populate_phandle_data
+ self._links.append({'var_node': var_node, 'dev_name': name})
+ item += 1
for val in vals:
self.buf('\n\t\t%s,' % val)
else:
@@ -625,6 +634,15 @@ class DtbPlatdata(object):
self.output_node(node)
nodes_to_output.remove(node)
+ # Define populate_phandle_data which will add the linking between
+ # nodes using DM_GET_DEVICE
+ # dtv_dmc_at_xxx.clocks[0].node = DM_GET_DEVICE(clock_controller_at_xxx)
+ self.buf('void populate_phandle_data(void) {\n')
+ for l in self._links:
+ self.buf('\t%s = DM_GET_DEVICE(%s);\n' % (l['var_node'], l['dev_name']))
+ self.buf('}\n')
+
+ self.out(''.join(self.get_buf()))
def run_steps(args, dtb_file, include_disabled, output, warning_disable = False):
"""Run all the steps of the dtoc tool
--
2.20.1
^ permalink raw reply related
* [PATCH 05/10] core: extend struct driver_info to point to device
From: Walter Lozano @ 2020-05-29 18:15 UTC (permalink / raw)
To: u-boot
In-Reply-To: <20200529181521.22073-1-walter.lozano@collabora.com>
Currently when creating an U_BOOT_DEVICE entry a struct driver_info
is declared, which contains the data needed to instantiate the device.
However, the actual device is created at runtime and there is no proper
way to get the device based on its struct driver_info.
This patch extends struct driver_info adding a pointer to udevice which
is populated during the bind process, allowing to generate a set of
functions to get the device based on its struct driver_info.
Signed-off-by: Walter Lozano <walter.lozano@collabora.com>
---
drivers/core/device.c | 26 +++++++++++++++++++++++---
drivers/core/root.c | 4 ++++
include/dm/device.h | 14 ++++++++++++++
include/dm/platdata.h | 14 ++++++++++++++
4 files changed, 55 insertions(+), 3 deletions(-)
diff --git a/drivers/core/device.c b/drivers/core/device.c
index a0ad080aaf..5adbc30849 100644
--- a/drivers/core/device.c
+++ b/drivers/core/device.c
@@ -250,6 +250,7 @@ int device_bind_by_name(struct udevice *parent, bool pre_reloc_only,
{
struct driver *drv;
uint platdata_size = 0;
+ int ret = 0;
drv = lists_driver_lookup_name(info->name);
if (!drv)
@@ -260,9 +261,16 @@ int device_bind_by_name(struct udevice *parent, bool pre_reloc_only,
#if CONFIG_IS_ENABLED(OF_PLATDATA)
platdata_size = info->platdata_size;
#endif
- return device_bind_common(parent, drv, info->name,
- (void *)info->platdata, 0, ofnode_null(), platdata_size,
- devp);
+ ret = device_bind_common(parent, drv, info->name,
+ (void *)info->platdata, 0, ofnode_null(),
+ platdata_size, devp);
+ if (ret)
+ return ret;
+#if CONFIG_IS_ENABLED(OF_PLATDATA)
+ info->dev = *devp;
+#endif
+
+ return ret;
}
static void *alloc_priv(int size, uint flags)
@@ -727,6 +735,18 @@ int device_get_global_by_ofnode(ofnode ofnode, struct udevice **devp)
return device_get_device_tail(dev, dev ? 0 : -ENOENT, devp);
}
+#if CONFIG_IS_ENABLED(OF_PLATDATA)
+int device_get_by_driver_info(const struct driver_info *info,
+ struct udevice **devp)
+{
+ struct udevice *dev;
+
+ dev = info->dev;
+
+ return device_get_device_tail(dev, dev ? 0 : -ENOENT, devp);
+}
+#endif
+
int device_find_first_child(const struct udevice *parent, struct udevice **devp)
{
if (list_empty(&parent->child_head)) {
diff --git a/drivers/core/root.c b/drivers/core/root.c
index c9ee56478a..8f47a6b356 100644
--- a/drivers/core/root.c
+++ b/drivers/core/root.c
@@ -346,6 +346,10 @@ int dm_init_and_scan(bool pre_reloc_only)
{
int ret;
+#if CONFIG_IS_ENABLED(OF_PLATDATA)
+ populate_phandle_data();
+#endif
+
ret = dm_init(IS_ENABLED(CONFIG_OF_LIVE));
if (ret) {
debug("dm_init() failed: %d\n", ret);
diff --git a/include/dm/device.h b/include/dm/device.h
index 2cfe10766f..a3b3e5bc46 100644
--- a/include/dm/device.h
+++ b/include/dm/device.h
@@ -538,6 +538,20 @@ int device_find_global_by_ofnode(ofnode node, struct udevice **devp);
*/
int device_get_global_by_ofnode(ofnode node, struct udevice **devp);
+/**
+ * device_get_by_driver_info() - Get a device based on driver_info
+ *
+ * Locates a device by its struct driver_info.
+ *
+ * The device is probed to activate it ready for use.
+ *
+ * @info: Struct driver_info
+ * @devp: Returns pointer to device if found, otherwise this is set to NULL
+ * @return 0 if OK, -ve on error
+ */
+int device_get_by_driver_info(const struct driver_info *info,
+ struct udevice **devp);
+
/**
* device_find_first_child() - Find the first child of a device
*
diff --git a/include/dm/platdata.h b/include/dm/platdata.h
index c972fa6936..238379b0e4 100644
--- a/include/dm/platdata.h
+++ b/include/dm/platdata.h
@@ -22,12 +22,14 @@
* @name: Driver name
* @platdata: Driver-specific platform data
* @platdata_size: Size of platform data structure
+ * @dev: Device created from this structure data
*/
struct driver_info {
const char *name;
const void *platdata;
#if CONFIG_IS_ENABLED(OF_PLATDATA)
uint platdata_size;
+ struct udevice *dev;
#endif
};
@@ -43,4 +45,16 @@ struct driver_info {
#define U_BOOT_DEVICES(__name) \
ll_entry_declare_list(struct driver_info, __name, driver_info)
+/* Get a pointer to a given driver */
+#define DM_GET_DEVICE(__name) \
+ ll_entry_get(struct driver_info, __name, driver_info)
+
+/**
+ * populate_phandle_data() - Populates phandle data in platda
+ *
+ * This populates phandle data with an U_BOOT_DEVICE entry get by
+ * DM_GET_DEVICE. The implementation of this function will be done
+ * by dtoc when parsing dtb.
+ */
+void populate_phandle_data(void);
#endif
--
2.20.1
^ permalink raw reply related
* [PATCH 04/10] core: drop const for struct driver_info
From: Walter Lozano @ 2020-05-29 18:15 UTC (permalink / raw)
To: u-boot
In-Reply-To: <20200529181521.22073-1-walter.lozano@collabora.com>
In order to prepare for a new support of phandle when OF_PLATDATA is used
drop the const for struct driver_info as this struct will need to be
updated on runtime.
Signed-off-by: Walter Lozano <walter.lozano@collabora.com>
---
drivers/core/device.c | 2 +-
drivers/core/root.c | 2 +-
include/dm/device-internal.h | 2 +-
3 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/drivers/core/device.c b/drivers/core/device.c
index 0157bb1fe0..a0ad080aaf 100644
--- a/drivers/core/device.c
+++ b/drivers/core/device.c
@@ -246,7 +246,7 @@ int device_bind_ofnode(struct udevice *parent, const struct driver *drv,
}
int device_bind_by_name(struct udevice *parent, bool pre_reloc_only,
- const struct driver_info *info, struct udevice **devp)
+ struct driver_info *info, struct udevice **devp)
{
struct driver *drv;
uint platdata_size = 0;
diff --git a/drivers/core/root.c b/drivers/core/root.c
index 14df16c280..c9ee56478a 100644
--- a/drivers/core/root.c
+++ b/drivers/core/root.c
@@ -25,7 +25,7 @@
DECLARE_GLOBAL_DATA_PTR;
-static const struct driver_info root_info = {
+static struct driver_info root_info = {
.name = "root_driver",
};
diff --git a/include/dm/device-internal.h b/include/dm/device-internal.h
index 294d6c1810..5145fb4e14 100644
--- a/include/dm/device-internal.h
+++ b/include/dm/device-internal.h
@@ -81,7 +81,7 @@ int device_bind_with_driver_data(struct udevice *parent,
* @return 0 if OK, -ve on error
*/
int device_bind_by_name(struct udevice *parent, bool pre_reloc_only,
- const struct driver_info *info, struct udevice **devp);
+ struct driver_info *info, struct udevice **devp);
/**
* device_ofdata_to_platdata() - Read platform data for a device
--
2.20.1
^ permalink raw reply related
* [PATCH 03/10] dm: doc: update of-plat with the suppor for driver aliases
From: Walter Lozano @ 2020-05-29 18:15 UTC (permalink / raw)
To: u-boot
In-Reply-To: <20200529181521.22073-1-walter.lozano@collabora.com>
Update the documentation with the support for driver aliases using
U_BOOT_DRIVER_ALIAS.
Signed-off-by: Walter Lozano <walter.lozano@collabora.com>
---
doc/driver-model/of-plat.rst | 14 +++++++++++++-
1 file changed, 13 insertions(+), 1 deletion(-)
diff --git a/doc/driver-model/of-plat.rst b/doc/driver-model/of-plat.rst
index 034a68bb4e..aa0c8dde91 100644
--- a/doc/driver-model/of-plat.rst
+++ b/doc/driver-model/of-plat.rst
@@ -183,6 +183,17 @@ via U_BOOT_DRIVER(). This effectively means that a U_BOOT_DRIVER() with a
it to a valid name for C) is needed, so a dedicated driver is required for
each 'compatible' string.
+In order to make this a bit more flexible U_BOOT_DRIVER_ALIAS macro can be
+used to declare an alias for a driver name, typically a 'compatible' string.
+This macro produces no code, but it is by dtoc tool.
+
+During the build process dtoc parses both U_BOOT_DRIVER and U_BOOT_DRIVER_ALIAS
+to build a list of valid driver names and driver aliases. If the 'compatible'
+string used for a device does not not match a valid driver name, it will be
+checked against the list of driver aliases in order to get the right driver
+name to use. If in this step there is no match found a warning is issued to
+avoid run-time failures.
+
Where a node has multiple compatible strings, a #define is used to make them
equivalent, e.g.:
@@ -269,7 +280,7 @@ For example:
};
U_BOOT_DRIVER(mmc_drv) = {
- .name = "vendor_mmc", /* matches compatible string */
+ .name = "mmc_drv",
.id = UCLASS_MMC,
.of_match = mmc_ids,
.ofdata_to_platdata = mmc_ofdata_to_platdata,
@@ -278,6 +289,7 @@ For example:
.platdata_auto_alloc_size = sizeof(struct mmc_platdata),
};
+ U_BOOT_DRIVER_ALIAS(vendor_mmc, mmc_drv) /* matches compatible string */
Note that struct mmc_platdata is defined in the C file, not in a header. This
is to avoid needing to include dt-structs.h in a header file. The idea is to
--
2.20.1
^ permalink raw reply related
* [PATCH 02/10] dtoc: add option to disable warnings
From: Walter Lozano @ 2020-05-29 18:15 UTC (permalink / raw)
To: u-boot
In-Reply-To: <20200529181521.22073-1-walter.lozano@collabora.com>
As dtoc now performs checks for valid driver names, when running dtoc
tests several warnings arise as these tests don't use valid driver
names.
This patch adds an option to disable those warning, which is only
intended for running tests.
Signed-off-by: Walter Lozano <walter.lozano@collabora.com>
---
tools/dtoc/dtb_platdata.py | 11 +++++---
tools/dtoc/test_dtoc.py | 54 +++++++++++++++++++-------------------
2 files changed, 34 insertions(+), 31 deletions(-)
diff --git a/tools/dtoc/dtb_platdata.py b/tools/dtoc/dtb_platdata.py
index 23cfda2f88..0a54188348 100644
--- a/tools/dtoc/dtb_platdata.py
+++ b/tools/dtoc/dtb_platdata.py
@@ -141,17 +141,19 @@ class DtbPlatdata(object):
_valid_nodes: A list of Node object with compatible strings
_include_disabled: true to include nodes marked status = "disabled"
_outfile: The current output file (sys.stdout or a real file)
+ _warning_disabled: true to disable warnings about driver names not found
_lines: Stashed list of output lines for outputting in the future
_aliases: Dict that hold aliases for compatible strings
_drivers: List of valid driver names found in drivers/
_driver_aliases: Dict that holds aliases for driver names
"""
- def __init__(self, dtb_fname, include_disabled):
+ def __init__(self, dtb_fname, include_disabled, warning_disable):
self._fdt = None
self._dtb_fname = dtb_fname
self._valid_nodes = None
self._include_disabled = include_disabled
self._outfile = None
+ self._warning_disable = warning_disable
self._lines = []
self._aliases = {}
self._drivers = []
@@ -177,7 +179,8 @@ class DtbPlatdata(object):
compat_c_old = compat_c
compat_c = self._driver_aliases.get(compat_c)
if not compat_c:
- print('WARNING: the driver %s was not found in the driver list' % (compat_c_old))
+ if not self._warning_disable: # pragma: no cover
+ print('WARNING: the driver %s was not found in the driver list' % (compat_c_old))
compat_c = compat_c_old
else: # pragma: no cover
aliases_c = [compat_c_old] + aliases_c
@@ -623,7 +626,7 @@ class DtbPlatdata(object):
nodes_to_output.remove(node)
-def run_steps(args, dtb_file, include_disabled, output):
+def run_steps(args, dtb_file, include_disabled, output, warning_disable = False):
"""Run all the steps of the dtoc tool
Args:
@@ -635,7 +638,7 @@ def run_steps(args, dtb_file, include_disabled, output):
if not args:
raise ValueError('Please specify a command: struct, platdata')
- plat = DtbPlatdata(dtb_file, include_disabled)
+ plat = DtbPlatdata(dtb_file, include_disabled, warning_disable)
plat.scan_drivers()
plat.scan_dtb()
plat.scan_tree()
diff --git a/tools/dtoc/test_dtoc.py b/tools/dtoc/test_dtoc.py
index 8498e8303c..a9b605cac8 100755
--- a/tools/dtoc/test_dtoc.py
+++ b/tools/dtoc/test_dtoc.py
@@ -154,12 +154,12 @@ class TestDtoc(unittest.TestCase):
"""Test output from a device tree file with no nodes"""
dtb_file = get_dtb_file('dtoc_test_empty.dts')
output = tools.GetOutputFilename('output')
- dtb_platdata.run_steps(['struct'], dtb_file, False, output)
+ dtb_platdata.run_steps(['struct'], dtb_file, False, output, True)
with open(output) as infile:
lines = infile.read().splitlines()
self.assertEqual(HEADER.splitlines(), lines)
- dtb_platdata.run_steps(['platdata'], dtb_file, False, output)
+ dtb_platdata.run_steps(['platdata'], dtb_file, False, output, True)
with open(output) as infile:
lines = infile.read().splitlines()
self.assertEqual(C_HEADER.splitlines() + [''], lines)
@@ -168,7 +168,7 @@ class TestDtoc(unittest.TestCase):
"""Test output from some simple nodes with various types of data"""
dtb_file = get_dtb_file('dtoc_test_simple.dts')
output = tools.GetOutputFilename('output')
- dtb_platdata.run_steps(['struct'], dtb_file, False, output)
+ dtb_platdata.run_steps(['struct'], dtb_file, False, output, True)
with open(output) as infile:
data = infile.read()
self._CheckStrings(HEADER + '''
@@ -193,7 +193,7 @@ struct dtd_sandbox_spl_test_2 {
};
''', data)
- dtb_platdata.run_steps(['platdata'], dtb_file, False, output)
+ dtb_platdata.run_steps(['platdata'], dtb_file, False, output, True)
with open(output) as infile:
data = infile.read()
self._CheckStrings(C_HEADER + '''
@@ -272,7 +272,7 @@ U_BOOT_DEVICE(pmic_at_9) = {
"""Test output from a node containing a phandle reference"""
dtb_file = get_dtb_file('dtoc_test_phandle.dts')
output = tools.GetOutputFilename('output')
- dtb_platdata.run_steps(['struct'], dtb_file, False, output)
+ dtb_platdata.run_steps(['struct'], dtb_file, False, output, True)
with open(output) as infile:
data = infile.read()
self._CheckStrings(HEADER + '''
@@ -284,7 +284,7 @@ struct dtd_target {
};
''', data)
- dtb_platdata.run_steps(['platdata'], dtb_file, False, output)
+ dtb_platdata.run_steps(['platdata'], dtb_file, False, output, True)
with open(output) as infile:
data = infile.read()
self._CheckStrings(C_HEADER + '''
@@ -344,7 +344,7 @@ U_BOOT_DEVICE(phandle_source2) = {
"""Test output from a node containing a phandle reference"""
dtb_file = get_dtb_file('dtoc_test_phandle_single.dts')
output = tools.GetOutputFilename('output')
- dtb_platdata.run_steps(['struct'], dtb_file, False, output)
+ dtb_platdata.run_steps(['struct'], dtb_file, False, output, True)
with open(output) as infile:
data = infile.read()
self._CheckStrings(HEADER + '''
@@ -360,7 +360,7 @@ struct dtd_target {
"""Test that phandle targets are generated before their references"""
dtb_file = get_dtb_file('dtoc_test_phandle_reorder.dts')
output = tools.GetOutputFilename('output')
- dtb_platdata.run_steps(['platdata'], dtb_file, False, output)
+ dtb_platdata.run_steps(['platdata'], dtb_file, False, output, True)
with open(output) as infile:
data = infile.read()
self._CheckStrings(C_HEADER + '''
@@ -390,7 +390,7 @@ U_BOOT_DEVICE(phandle_source2) = {
capture_stderr=True)
output = tools.GetOutputFilename('output')
with self.assertRaises(ValueError) as e:
- dtb_platdata.run_steps(['struct'], dtb_file, False, output)
+ dtb_platdata.run_steps(['struct'], dtb_file, False, output, True)
self.assertIn("Cannot parse 'clocks' in node 'phandle-source'",
str(e.exception))
@@ -400,7 +400,7 @@ U_BOOT_DEVICE(phandle_source2) = {
capture_stderr=True)
output = tools.GetOutputFilename('output')
with self.assertRaises(ValueError) as e:
- dtb_platdata.run_steps(['struct'], dtb_file, False, output)
+ dtb_platdata.run_steps(['struct'], dtb_file, False, output, True)
self.assertIn("Node 'phandle-target' has no '#clock-cells' property",
str(e.exception))
@@ -408,7 +408,7 @@ U_BOOT_DEVICE(phandle_source2) = {
"""Test output from a node with multiple compatible strings"""
dtb_file = get_dtb_file('dtoc_test_aliases.dts')
output = tools.GetOutputFilename('output')
- dtb_platdata.run_steps(['struct'], dtb_file, False, output)
+ dtb_platdata.run_steps(['struct'], dtb_file, False, output, True)
with open(output) as infile:
data = infile.read()
self._CheckStrings(HEADER + '''
@@ -419,7 +419,7 @@ struct dtd_compat1 {
#define dtd_compat3 dtd_compat1
''', data)
- dtb_platdata.run_steps(['platdata'], dtb_file, False, output)
+ dtb_platdata.run_steps(['platdata'], dtb_file, False, output, True)
with open(output) as infile:
data = infile.read()
self._CheckStrings(C_HEADER + '''
@@ -438,7 +438,7 @@ U_BOOT_DEVICE(spl_test) = {
"""Test output from a node with a 'reg' property with na=2, ns=2"""
dtb_file = get_dtb_file('dtoc_test_addr64.dts')
output = tools.GetOutputFilename('output')
- dtb_platdata.run_steps(['struct'], dtb_file, False, output)
+ dtb_platdata.run_steps(['struct'], dtb_file, False, output, True)
with open(output) as infile:
data = infile.read()
self._CheckStrings(HEADER + '''
@@ -453,7 +453,7 @@ struct dtd_test3 {
};
''', data)
- dtb_platdata.run_steps(['platdata'], dtb_file, False, output)
+ dtb_platdata.run_steps(['platdata'], dtb_file, False, output, True)
with open(output) as infile:
data = infile.read()
self._CheckStrings(C_HEADER + '''
@@ -490,7 +490,7 @@ U_BOOT_DEVICE(test3) = {
"""Test output from a node with a 'reg' property with na=1, ns=1"""
dtb_file = get_dtb_file('dtoc_test_addr32.dts')
output = tools.GetOutputFilename('output')
- dtb_platdata.run_steps(['struct'], dtb_file, False, output)
+ dtb_platdata.run_steps(['struct'], dtb_file, False, output, True)
with open(output) as infile:
data = infile.read()
self._CheckStrings(HEADER + '''
@@ -502,7 +502,7 @@ struct dtd_test2 {
};
''', data)
- dtb_platdata.run_steps(['platdata'], dtb_file, False, output)
+ dtb_platdata.run_steps(['platdata'], dtb_file, False, output, True)
with open(output) as infile:
data = infile.read()
self._CheckStrings(C_HEADER + '''
@@ -530,7 +530,7 @@ U_BOOT_DEVICE(test2) = {
"""Test output from a node with a 'reg' property with na=2, ns=1"""
dtb_file = get_dtb_file('dtoc_test_addr64_32.dts')
output = tools.GetOutputFilename('output')
- dtb_platdata.run_steps(['struct'], dtb_file, False, output)
+ dtb_platdata.run_steps(['struct'], dtb_file, False, output, True)
with open(output) as infile:
data = infile.read()
self._CheckStrings(HEADER + '''
@@ -545,7 +545,7 @@ struct dtd_test3 {
};
''', data)
- dtb_platdata.run_steps(['platdata'], dtb_file, False, output)
+ dtb_platdata.run_steps(['platdata'], dtb_file, False, output, True)
with open(output) as infile:
data = infile.read()
self._CheckStrings(C_HEADER + '''
@@ -582,7 +582,7 @@ U_BOOT_DEVICE(test3) = {
"""Test output from a node with a 'reg' property with na=1, ns=2"""
dtb_file = get_dtb_file('dtoc_test_addr32_64.dts')
output = tools.GetOutputFilename('output')
- dtb_platdata.run_steps(['struct'], dtb_file, False, output)
+ dtb_platdata.run_steps(['struct'], dtb_file, False, output, True)
with open(output) as infile:
data = infile.read()
self._CheckStrings(HEADER + '''
@@ -597,7 +597,7 @@ struct dtd_test3 {
};
''', data)
- dtb_platdata.run_steps(['platdata'], dtb_file, False, output)
+ dtb_platdata.run_steps(['platdata'], dtb_file, False, output, True)
with open(output) as infile:
data = infile.read()
self._CheckStrings(C_HEADER + '''
@@ -636,7 +636,7 @@ U_BOOT_DEVICE(test3) = {
dtb_file = get_dtb_file('dtoc_test_bad_reg.dts', capture_stderr=True)
output = tools.GetOutputFilename('output')
with self.assertRaises(ValueError) as e:
- dtb_platdata.run_steps(['struct'], dtb_file, False, output)
+ dtb_platdata.run_steps(['struct'], dtb_file, False, output, True)
self.assertIn("Node 'spl-test' reg property is not an int",
str(e.exception))
@@ -646,7 +646,7 @@ U_BOOT_DEVICE(test3) = {
dtb_file = get_dtb_file('dtoc_test_bad_reg2.dts', capture_stderr=True)
output = tools.GetOutputFilename('output')
with self.assertRaises(ValueError) as e:
- dtb_platdata.run_steps(['struct'], dtb_file, False, output)
+ dtb_platdata.run_steps(['struct'], dtb_file, False, output, True)
self.assertIn("Node 'spl-test' reg property has 3 cells which is not a multiple of na + ns = 1 + 1)",
str(e.exception))
@@ -654,7 +654,7 @@ U_BOOT_DEVICE(test3) = {
"""Test that a subequent node can add a new property to a struct"""
dtb_file = get_dtb_file('dtoc_test_add_prop.dts')
output = tools.GetOutputFilename('output')
- dtb_platdata.run_steps(['struct'], dtb_file, False, output)
+ dtb_platdata.run_steps(['struct'], dtb_file, False, output, True)
with open(output) as infile:
data = infile.read()
self._CheckStrings(HEADER + '''
@@ -664,7 +664,7 @@ struct dtd_sandbox_spl_test {
};
''', data)
- dtb_platdata.run_steps(['platdata'], dtb_file, False, output)
+ dtb_platdata.run_steps(['platdata'], dtb_file, False, output, True)
with open(output) as infile:
data = infile.read()
self._CheckStrings(C_HEADER + '''
@@ -692,12 +692,12 @@ U_BOOT_DEVICE(spl_test2) = {
"""Test output to stdout"""
dtb_file = get_dtb_file('dtoc_test_simple.dts')
with test_util.capture_sys_output() as (stdout, stderr):
- dtb_platdata.run_steps(['struct'], dtb_file, False, '-')
+ dtb_platdata.run_steps(['struct'], dtb_file, False, '-', True)
def testNoCommand(self):
"""Test running dtoc without a command"""
with self.assertRaises(ValueError) as e:
- dtb_platdata.run_steps([], '', False, '')
+ dtb_platdata.run_steps([], '', False, '', True)
self.assertIn("Please specify a command: struct, platdata",
str(e.exception))
@@ -706,6 +706,6 @@ U_BOOT_DEVICE(spl_test2) = {
dtb_file = get_dtb_file('dtoc_test_simple.dts')
output = tools.GetOutputFilename('output')
with self.assertRaises(ValueError) as e:
- dtb_platdata.run_steps(['invalid-cmd'], dtb_file, False, output)
+ dtb_platdata.run_steps(['invalid-cmd'], dtb_file, False, output, True)
self.assertIn("Unknown command 'invalid-cmd': (use: struct, platdata)",
str(e.exception))
--
2.20.1
^ permalink raw reply related
* [PATCH 01/10] dtoc: add support to scan drivers
From: Walter Lozano @ 2020-05-29 18:15 UTC (permalink / raw)
To: u-boot
In-Reply-To: <20200529181521.22073-1-walter.lozano@collabora.com>
Currently dtoc scans dtbs to convert them to struct platdata and
to generate U_BOOT_DEVICE entries. These entries need to be filled
with the driver name, but at this moment the information used is the
compatible name present in the dtb. This causes that only nodes with
a compatible name that matches a driver name generate a working
entry.
In order to improve this behaviour, this patch adds to dtoc the
capability of scan drivers source code to generate a list of valid driver
names. This allows to rise a warning in the case that an U_BOOT_DEVICE
entry will try to use a name not valid.
Additionally, in order to add more flexibility to the solution, adds the
U_BOOT_DRIVER_ALIAS macro, which generates no code at all, but allows an
easy way to declare driver name aliases. Thanks to this, dtoc can look
for the driver name based on its alias when it populates the U_BOOT_DEVICE
entry.
Signed-off-by: Walter Lozano <walter.lozano@collabora.com>
---
include/dm/device.h | 7 ++++
tools/dtoc/dtb_platdata.py | 83 ++++++++++++++++++++++++++++++++++++--
2 files changed, 86 insertions(+), 4 deletions(-)
diff --git a/include/dm/device.h b/include/dm/device.h
index 975eec5d0e..2cfe10766f 100644
--- a/include/dm/device.h
+++ b/include/dm/device.h
@@ -282,6 +282,13 @@ struct driver {
#define DM_GET_DRIVER(__name) \
ll_entry_get(struct driver, __name, driver)
+/**
+ * Declare a macro to state a alias for a driver name. This macro will
+ * produce no code but its information will be parsed by tools like
+ * dtoc
+ */
+#define U_BOOT_DRIVER_ALIAS(__name, __alias)
+
/**
* dev_get_platdata() - Get the platform data for a device
*
diff --git a/tools/dtoc/dtb_platdata.py b/tools/dtoc/dtb_platdata.py
index ecfe0624d1..23cfda2f88 100644
--- a/tools/dtoc/dtb_platdata.py
+++ b/tools/dtoc/dtb_platdata.py
@@ -13,6 +13,8 @@ static data.
import collections
import copy
+import os
+import re
import sys
from dtoc import fdt
@@ -140,6 +142,9 @@ class DtbPlatdata(object):
_include_disabled: true to include nodes marked status = "disabled"
_outfile: The current output file (sys.stdout or a real file)
_lines: Stashed list of output lines for outputting in the future
+ _aliases: Dict that hold aliases for compatible strings
+ _drivers: List of valid driver names found in drivers/
+ _driver_aliases: Dict that holds aliases for driver names
"""
def __init__(self, dtb_fname, include_disabled):
self._fdt = None
@@ -149,6 +154,35 @@ class DtbPlatdata(object):
self._outfile = None
self._lines = []
self._aliases = {}
+ self._drivers = []
+ self._driver_aliases = {}
+
+ def get_normalized_compat_name(self, node):
+ """Get a node's normalized compat name
+
+ Returns a valid driver name by retrieving node's first compatible
+ string as a C identifier and perfomrming a check against _drivers
+ and a lookup in driver_aliases rising a warning in case of failure.
+
+ Args:
+ node: Node object to check
+ Return:
+ Tuple:
+ Driver name associated with the first compatible string
+ List of C identifiers for all the other compatible strings
+ (possibly empty)
+ """
+ compat_c, aliases_c = get_compat_name(node)
+ if compat_c not in self._drivers:
+ compat_c_old = compat_c
+ compat_c = self._driver_aliases.get(compat_c)
+ if not compat_c:
+ print('WARNING: the driver %s was not found in the driver list' % (compat_c_old))
+ compat_c = compat_c_old
+ else: # pragma: no cover
+ aliases_c = [compat_c_old] + aliases_c
+
+ return compat_c, aliases_c
def setup_output(self, fname):
"""Set up the output destination
@@ -243,6 +277,46 @@ class DtbPlatdata(object):
return PhandleInfo(max_args, args)
return None
+ def scan_driver(self, fn):
+ """Scan a driver file to build a list of driver names and aliases
+
+ This procedure will populate self._drivers and self._driver_aliases
+
+ Args
+ fn: Driver filename to scan
+ """
+ with open(fn) as fd:
+
+ buff = fd.read()
+
+ # The following re will search for driver names declared as
+ # U_BOOT_DRIVER(driver_name)
+ drivers = re.findall('U_BOOT_DRIVER\((.*)\)', buff)
+
+ for driver in drivers:
+ self._drivers.append(driver)
+
+ # The following re will search for driver aliases declared as
+ # U_BOOT_DRIVER_ALIAS(alias, driver_name)
+ driver_aliases = re.findall('U_BOOT_DRIVER_ALIAS\(\s*(\w+)\s*,\s*(\w+)\s*\)', buff)
+
+ for alias in driver_aliases: # pragma: no cover
+ if len(alias) != 2:
+ continue
+ self._driver_aliases[alias[1]] = alias[0]
+
+ def scan_drivers(self):
+ """Scan the driver folders to build a list of driver names and aliases
+
+ This procedure will populate self._drivers and self._driver_aliases
+
+ """
+ for (dirpath, dirnames, filenames) in os.walk('./'):
+ for fn in filenames:
+ if not fn.endswith('.c'):
+ continue
+ self.scan_driver(dirpath + '/' + fn)
+
def scan_dtb(self):
"""Scan the device tree to obtain a tree of nodes and properties
@@ -353,7 +427,7 @@ class DtbPlatdata(object):
"""
structs = {}
for node in self._valid_nodes:
- node_name, _ = get_compat_name(node)
+ node_name, _ = self.get_normalized_compat_name(node)
fields = {}
# Get a list of all the valid properties in this node.
@@ -377,14 +451,14 @@ class DtbPlatdata(object):
upto = 0
for node in self._valid_nodes:
- node_name, _ = get_compat_name(node)
+ node_name, _ = self.get_normalized_compat_name(node)
struct = structs[node_name]
for name, prop in node.props.items():
if name not in PROP_IGNORE_LIST and name[0] != '#':
prop.Widen(struct[name])
upto += 1
- struct_name, aliases = get_compat_name(node)
+ struct_name, aliases = self.get_normalized_compat_name(node)
for alias in aliases:
self._aliases[alias] = struct_name
@@ -461,7 +535,7 @@ class DtbPlatdata(object):
Args:
node: node to output
"""
- struct_name, _ = get_compat_name(node)
+ struct_name, _ = self.get_normalized_compat_name(node)
var_name = conv_name_to_c(node.name)
self.buf('static const struct %s%s %s%s = {\n' %
(STRUCT_PREFIX, struct_name, VAL_PREFIX, var_name))
@@ -562,6 +636,7 @@ def run_steps(args, dtb_file, include_disabled, output):
raise ValueError('Please specify a command: struct, platdata')
plat = DtbPlatdata(dtb_file, include_disabled)
+ plat.scan_drivers()
plat.scan_dtb()
plat.scan_tree()
plat.scan_reg_sizes()
--
2.20.1
^ permalink raw reply related
* [PATCH 00/10] improve OF_PLATDATA support
From: Walter Lozano @ 2020-05-29 18:15 UTC (permalink / raw)
To: u-boot
When using OF_PLATDATA dtbs are converted to C structs in order to save
space as we can remove both dtbs and libraries from TPL/SPL binaries.
This patchset tries to improve its support by overcoming some limitations
in the current implementation
First, the support for scan and check for valid driver/aliases is added
in order to generate U_BOOT_DEVICE entries with valid driver names.
Secondly, the way information about linked noded (phandle) is generated
in C structs is improved in order to make it easier to get a device
associated to its data.
Lastly the the suport for the property cd-gpios is added, which is used to
configure the card detection gpio on MMC is added.
This implementation is based in discussion in [1], [2] and [3]
[1] https://patchwork.ozlabs.org/patch/1249198/
[2] https://patchwork.ozlabs.org/project/uboot/list/?series=167495&state=*
[3] https://patchwork.ozlabs.org/project/uboot/list/?series=176759&state=*
Walter Lozano (10):
dtoc: add support to scan drivers
dtoc: add option to disable warnings
dm: doc: update of-plat with the suppor for driver aliases
core: drop const for struct driver_info
core: extend struct driver_info to point to device
dtoc: extend dtoc to use struct driver_info when linking nodes
dm: doc: update of-plat with new phandle support
dtoc: update tests to match new platdata
dtoc: update dtb_platdata to support cd-gpios
dtoc add test for cd-gpios
doc/driver-model/of-plat.rst | 38 +++-
drivers/clk/clk-uclass.c | 11 +-
drivers/core/device.c | 28 ++-
drivers/core/root.c | 6 +-
drivers/misc/irq-uclass.c | 10 +-
drivers/mmc/ftsdc010_mci.c | 2 +-
drivers/mmc/rockchip_dw_mmc.c | 2 +-
drivers/mmc/rockchip_sdhci.c | 2 +-
drivers/ram/rockchip/sdram_rk3399.c | 2 +-
drivers/spi/rk_spi.c | 2 +-
include/clk.h | 4 +-
include/dm/device-internal.h | 2 +-
include/dm/device.h | 21 +++
include/dm/platdata.h | 14 ++
tools/dtoc/dtb_platdata.py | 129 +++++++++++--
tools/dtoc/dtoc_test_phandle_cd_gpios.dts | 42 +++++
tools/dtoc/test_dtoc.py | 218 +++++++++++++++-------
17 files changed, 415 insertions(+), 118 deletions(-)
create mode 100644 tools/dtoc/dtoc_test_phandle_cd_gpios.dts
--
2.20.1
^ permalink raw reply
* [PATCH v1] NFS: Fix direct WRITE throughput regression
From: Chuck Lever @ 2020-05-29 18:14 UTC (permalink / raw)
To: anna.schumaker, trondmy; +Cc: linux-nfs
I measured a 50% throughput regression for large direct writes.
The observed on-the-wire behavior is that the client sends every
NFS WRITE twice: once as an UNSTABLE WRITE plus a COMMIT, and once
as a FILE_SYNC WRITE.
This is because the nfs_write_match_verf() check in
nfs_direct_commit_complete() fails for every WRITE.
Buffered writes use nfs_write_completion(), which sets req->wb_verf
correctly. Direct writes use nfs_direct_write_completion(), which
does not set req->wb_verf at all. This leaves req->wb_verf set to
all zeroes for every direct WRITE, and thus
nfs_direct_commit_completion() always sets NFS_ODIRECT_RESCHED_WRITES.
This fix appears to restore nearly all of the lost performance.
Fixes: 1f28476dcb98 ("NFS: Fix O_DIRECT commit verifier handling")
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
fs/nfs/direct.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/fs/nfs/direct.c b/fs/nfs/direct.c
index a57e7c72c7f4..d49b1d197908 100644
--- a/fs/nfs/direct.c
+++ b/fs/nfs/direct.c
@@ -731,6 +731,8 @@ static void nfs_direct_write_completion(struct nfs_pgio_header *hdr)
nfs_list_remove_request(req);
if (request_commit) {
kref_get(&req->wb_kref);
+ memcpy(&req->wb_verf, &hdr->verf.verifier,
+ sizeof(req->wb_verf));
nfs_mark_request_commit(req, hdr->lseg, &cinfo,
hdr->ds_commit_idx);
}
^ permalink raw reply related
* Re: [PATCH v3 02/25] dt-bindings: clock: Add a binding for the RPi Firmware clocks
From: Rob Herring @ 2020-05-29 18:14 UTC (permalink / raw)
To: Maxime Ripard
Cc: devicetree, Tim Gover, Dave Stevenson, Stephen Boyd,
Michael Turquette, linux-kernel, Phil Elwell, Rob Herring,
bcm-kernel-feedback-list, Nicolas Saenz Julienne, linux-clk,
linux-arm-kernel, linux-rpi-kernel
In-Reply-To: <919e2f2f13583d4d53d0e95b81fc3fb8a7606107.1590594293.git-series.maxime@cerno.tech>
On Wed, 27 May 2020 17:44:58 +0200, Maxime Ripard wrote:
> The firmware running on the RPi VideoCore can be used to discover and
> change the various clocks running in the BCM2711. Since devices will
> need to use them through the DT, let's add a pretty simple binding.
>
> Cc: Michael Turquette <mturquette@baylibre.com>
> Cc: Stephen Boyd <sboyd@kernel.org>
> Cc: Rob Herring <robh+dt@kernel.org>
> Cc: linux-clk@vger.kernel.org
> Cc: devicetree@vger.kernel.org
> Signed-off-by: Maxime Ripard <maxime@cerno.tech>
> ---
> Documentation/devicetree/bindings/arm/bcm/raspberrypi,bcm2835-firmware.yaml | 24 ++++++++++++++++++++++++
> 1 file changed, 24 insertions(+)
>
Reviewed-by: Rob Herring <robh@kernel.org>
_______________________________________________
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 v3 02/25] dt-bindings: clock: Add a binding for the RPi Firmware clocks
From: Rob Herring @ 2020-05-29 18:14 UTC (permalink / raw)
To: Maxime Ripard
Cc: linux-kernel, Tim Gover, Rob Herring, Stephen Boyd,
Dave Stevenson, Michael Turquette, devicetree, linux-arm-kernel,
Nicolas Saenz Julienne, linux-clk, Phil Elwell,
bcm-kernel-feedback-list, linux-rpi-kernel
In-Reply-To: <919e2f2f13583d4d53d0e95b81fc3fb8a7606107.1590594293.git-series.maxime@cerno.tech>
On Wed, 27 May 2020 17:44:58 +0200, Maxime Ripard wrote:
> The firmware running on the RPi VideoCore can be used to discover and
> change the various clocks running in the BCM2711. Since devices will
> need to use them through the DT, let's add a pretty simple binding.
>
> Cc: Michael Turquette <mturquette@baylibre.com>
> Cc: Stephen Boyd <sboyd@kernel.org>
> Cc: Rob Herring <robh+dt@kernel.org>
> Cc: linux-clk@vger.kernel.org
> Cc: devicetree@vger.kernel.org
> Signed-off-by: Maxime Ripard <maxime@cerno.tech>
> ---
> Documentation/devicetree/bindings/arm/bcm/raspberrypi,bcm2835-firmware.yaml | 24 ++++++++++++++++++++++++
> 1 file changed, 24 insertions(+)
>
Reviewed-by: Rob Herring <robh@kernel.org>
^ permalink raw reply
* Re: [PATCH v2 0/4] Four SRP initiator and target patches
From: Jason Gunthorpe @ 2020-05-29 18:14 UTC (permalink / raw)
To: Bart Van Assche; +Cc: Leon Romanovsky, Doug Ledford, linux-rdma
In-Reply-To: <20200525172212.14413-1-bvanassche@acm.org>
On Mon, May 25, 2020 at 10:22:08AM -0700, Bart Van Assche wrote:
> Hi Jason,
>
> Please consider these four patches for kernel v5.8 or v5.9 (not sure if it is
> still possible to include these in v5.8).
>
> Thanks,
>
> Bart.
>
> Changes compared to v1:
> - Changed %d into %u in the SRP patch as requested by Leon.
> - Simplified patch "RDMA/srpt: Increase max_send_sge".
>
> Bart Van Assche (4):
> RDMA/srp: Make the channel count configurable per target
> RDMA/srpt: Make debug output more detailed
> RDMA/srpt: Reduce max_recv_sge to 1
> RDMA/srpt: Increase max_send_sge
Applied to for-next with the revise commit message
Thanks,
Jason
^ permalink raw reply
* Re: [PATCH 8/8] blk-mq: drain I/O when all CPUs in a hctx are offline
From: Paul E. McKenney @ 2020-05-29 18:13 UTC (permalink / raw)
To: Ming Lei
Cc: Bart Van Assche, Christoph Hellwig, linux-block, John Garry,
Hannes Reinecke, Thomas Gleixner, linux-kernel
In-Reply-To: <20200529035315.GD1075489@T590>
On Fri, May 29, 2020 at 11:53:15AM +0800, Ming Lei wrote:
> Hi Paul,
>
> On Thu, May 28, 2020 at 08:07:28PM -0700, Paul E. McKenney wrote:
> > On Fri, May 29, 2020 at 09:53:04AM +0800, Ming Lei wrote:
> > > Hi Paul,
> > >
> > > Thanks for your response!
> > >
> > > On Thu, May 28, 2020 at 10:21:21AM -0700, Paul E. McKenney wrote:
> > > > On Thu, May 28, 2020 at 06:37:47AM -0700, Bart Van Assche wrote:
> > > > > On 2020-05-27 22:19, Ming Lei wrote:
> > > > > > On Wed, May 27, 2020 at 08:33:48PM -0700, Bart Van Assche wrote:
> > > > > >> My understanding is that operations that have acquire semantics pair
> > > > > >> with operations that have release semantics. I haven't been able to find
> > > > > >> any documentation that shows that smp_mb__after_atomic() has release
> > > > > >> semantics. So I looked up its definition. This is what I found:
> > > > > >>
> > > > > >> $ git grep -nH 'define __smp_mb__after_atomic'
> > > > > >> arch/ia64/include/asm/barrier.h:49:#define __smp_mb__after_atomic()
> > > > > >> barrier()
> > > > > >> arch/mips/include/asm/barrier.h:133:#define __smp_mb__after_atomic()
> > > > > >> smp_llsc_mb()
> > > > > >> arch/s390/include/asm/barrier.h:50:#define __smp_mb__after_atomic()
> > > > > >> barrier()
> > > > > >> arch/sparc/include/asm/barrier_64.h:57:#define __smp_mb__after_atomic()
> > > > > >> barrier()
> > > > > >> arch/x86/include/asm/barrier.h:83:#define __smp_mb__after_atomic() do {
> > > > > >> } while (0)
> > > > > >> arch/xtensa/include/asm/barrier.h:20:#define __smp_mb__after_atomic()
> > > > > >> barrier()
> > > > > >> include/asm-generic/barrier.h:116:#define __smp_mb__after_atomic()
> > > > > >> __smp_mb()
> > > > > >>
> > > > > >> My interpretation of the above is that not all smp_mb__after_atomic()
> > > > > >> implementations have release semantics. Do you agree with this conclusion?
> > > > > >
> > > > > > I understand smp_mb__after_atomic() orders set_bit(BLK_MQ_S_INACTIVE)
> > > > > > and reading the tag bit which is done in blk_mq_all_tag_iter().
> > > > > >
> > > > > > So the two pair of OPs are ordered:
> > > > > >
> > > > > > 1) if one request(tag bit) is allocated before setting BLK_MQ_S_INACTIVE,
> > > > > > the tag bit will be observed in blk_mq_all_tag_iter() from blk_mq_hctx_has_requests(),
> > > > > > so the request will be drained.
> > > > > >
> > > > > > OR
> > > > > >
> > > > > > 2) if one request(tag bit) is allocated after setting BLK_MQ_S_INACTIVE,
> > > > > > the request(tag bit) will be released and retried on another CPU
> > > > > > finally, see __blk_mq_alloc_request().
> > > > > >
> > > > > > Cc Paul and linux-kernel list.
> > > > >
> > > > > I do not agree with the above conclusion. My understanding of
> > > > > acquire/release labels is that if the following holds:
> > > > > (1) A store operation that stores the value V into memory location M has
> > > > > a release label.
> > > > > (2) A load operation that reads memory location M has an acquire label.
> > > > > (3) The load operation (2) retrieves the value V that was stored by (1).
> > > > >
> > > > > that the following ordering property holds: all load and store
> > > > > instructions that happened before the store instruction (1) in program
> > > > > order are guaranteed to happen before the load and store instructions
> > > > > that follow (2) in program order.
> > > > >
> > > > > In the ARM manual these semantics have been described as follows: "A
> > > > > Store-Release instruction is multicopy atomic when observed with a
> > > > > Load-Acquire instruction".
> > > > >
> > > > > In this case the load-acquire operation is the
> > > > > "test_and_set_bit_lock(nr, word)" statement from the sbitmap code. That
> > > > > code is executed indirectly by blk_mq_get_tag(). Since there is no
> > > > > matching store-release instruction in __blk_mq_alloc_request() for
> > > > > 'word', ordering of the &data->hctx->state and 'tag' memory locations is
> > > > > not guaranteed by the acquire property of the "test_and_set_bit_lock(nr,
> > > > > word)" statement from the sbitmap code.
> > > >
> > > > I feel like I just parachuted into the middle of the conversation,
> > > > so let me start by giving a (silly) example illustrating the limits of
> > > > smp_mb__{before,after}_atomic() that might be tangling things up.
> > > >
> > > > But please please please avoid doing this in real code unless you have
> > > > an extremely good reason included in a comment.
> > > >
> > > > void t1(void)
> > > > {
> > > > WRITE_ONCE(a, 1);
> > > > smp_mb__before_atomic();
> > > > WRITE_ONCE(b, 1); // Just Say No to code here!!!
> > > > atomic_inc(&c);
> > > > WRITE_ONCE(d, 1); // Just Say No to code here!!!
> > > > smp_mb__after_atomic();
> > > > WRITE_ONCE(e, 1);
> > > > }
> > > >
> > > > void t2(void)
> > > > {
> > > > r1 = READ_ONCE(e);
> > > > smp_mb();
> > > > r2 = READ_ONCE(d);
> > > > smp_mb();
> > > > r3 = READ_ONCE(c);
> > > > smp_mb();
> > > > r4 = READ_ONCE(b);
> > > > smp_mb();
> > > > r5 = READ_ONCE(a);
> > > > }
> > > >
> > > > Each platform must provide strong ordering for either atomic_inc()
> > > > on the one hand (as ia64 does) or for smp_mb__{before,after}_atomic()
> > > > on the other (as powerpc does). Note that both ia64 and powerpc are
> > > > weakly ordered.
> > > >
> > > > So ia64 could see (r1 == 1 && r2 == 0) on the one hand as well as (r4 ==
> > > > 1 && r5 == 0). So clearly smp_mb_{before,after}_atomic() need not have
> > > > any ordering properties whatsoever.
> > > >
> > > > Similarly, powerpc could see (r3 == 1 && r4 == 0) on the one hand as well
> > > > as (r2 == 1 && r3 == 0) on the other. Or even both at the same time.
> > > > So clearly atomic_inc() need not have any ordering properties whatsoever.
> > > >
> > > > But the combination of smp_mb__before_atomic() and the later atomic_inc()
> > > > does provide full ordering, so that no architecture can see (r3 == 1 &&
> > > > r5 == 0), and either of r1 or r2 can be substituted for r3.
> > > >
> > > > Similarly, atomic_inc() and the late4r smp_mb__after_atomic() also
> > > > provide full ordering, so that no architecture can see (r1 == 1 && r3 ==
> > > > 0), and either r4 or r5 can be substituted for r3.
> > > >
> > > >
> > > > So a call to set_bit() followed by a call to smp_mb__after_atomic() will
> > > > provide a full memory barrier (implying release semantics) for any write
> > > > access after the smp_mb__after_atomic() with respect to the set_bit() or
> > > > any access preceding it. But the set_bit() by itself won't have release
> > > > semantics, nor will the smp_mb__after_atomic(), only their combination
> > > > further combined with some write following the smp_mb__after_atomic().
> > > >
> > > > More generally, there will be the equivalent of smp_mb() somewhere between
> > > > the set_bit() and every access following the smp_mb__after_atomic().
> > > >
> > > > Does that help, or am I missing the point?
> > >
> > > Yeah, it does help.
> > >
> > > BTW, can we replace the smp_mb__after_atomic() with smp_mb() for
> > > ordering set_bit() and the memory OP following the smp_mb()?
> >
> > Placing an smp_mb() between set_bit() and a later access will indeed
> > order set_bit() with that later access.
> >
> > That said, I don't know this code well enough to say whether or not
> > that ordering is sufficient.
>
> Another pair is in blk_mq_get_tag(), and we expect the following two
> memory OPs are ordered:
>
> 1) set bit in successful test_and_set_bit_lock(), which is called
> from sbitmap_get()
>
> 2) test_bit(BLK_MQ_S_INACTIVE, &data->hctx->state)
>
> Do you think that the above two OPs are ordered?
Given that he has been through the code, I would like to hear Bart's
thoughts, actually.
Thanx, Paul
^ permalink raw reply
* Re: [PATCH v5 02/11] dt-bindings: i2c: Discard i2c-slave flag from the DW I2C example
From: Rob Herring @ 2020-05-29 18:13 UTC (permalink / raw)
To: Serge Semin
Cc: Serge Semin, Jarkko Nikula, Wolfram Sang, Alexey Malahov,
Thomas Bogendoerfer, Andy Shevchenko, Mika Westerberg, linux-mips,
linux-i2c, devicetree, linux-kernel
In-Reply-To: <20200527153351.rmzguymz7lm6gvsx@mobilestation>
On Wed, May 27, 2020 at 06:33:51PM +0300, Serge Semin wrote:
> Rob,
> Could you pay attention to this patch? The patchset review procedure is
> nearly over, while the DT part is only partly reviewed by you.
Pretty sure I commented on this. Not sure what version, you're sending
new versions too fast. Give people time to review.
>
> Thanks
> -Sergey
>
> On Wed, May 27, 2020 at 06:30:37PM +0300, Serge Semin wrote:
> > dtc currently doesn't support I2C_OWN_SLAVE_ADDRESS flag set in the
> > i2c "reg" property. If it is the compiler will print a warning:
> >
> > Warning (i2c_bus_reg): /example-2/i2c@1120000/eeprom@64: I2C bus unit address format error, expected "40000064"
> > Warning (i2c_bus_reg): /example-2/i2c@1120000/eeprom@64:reg: I2C address must be less than 10-bits, got "0x40000064"
> >
> > In order to silence dtc up let's discard the flag from the DW I2C DT
> > binding example for now. Just revert this commit when dtc is fixed.
> >
> > Signed-off-by: Serge Semin <Sergey.Semin@baikalelectronics.ru>
> > Cc: Alexey Malahov <Alexey.Malahov@baikalelectronics.ru>
> > Cc: Thomas Bogendoerfer <tsbogend@alpha.franken.de>
> > Cc: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
> > Cc: Mika Westerberg <mika.westerberg@linux.intel.com>
> > Cc: linux-mips@vger.kernel.org
> >
> > ---
> >
> > Changelog v3:
> > - This is a new patch created as a result of the Rob request to remove
> > the EEPROM-slave bit setting in the DT binndings example until the dtc
> > is fixed.
> > ---
> > Documentation/devicetree/bindings/i2c/snps,designware-i2c.yaml | 2 +-
> > 1 file changed, 1 insertion(+), 1 deletion(-)
> >
> > diff --git a/Documentation/devicetree/bindings/i2c/snps,designware-i2c.yaml b/Documentation/devicetree/bindings/i2c/snps,designware-i2c.yaml
> > index 4bd430b2b41d..101d78e8f19d 100644
> > --- a/Documentation/devicetree/bindings/i2c/snps,designware-i2c.yaml
> > +++ b/Documentation/devicetree/bindings/i2c/snps,designware-i2c.yaml
> > @@ -137,7 +137,7 @@ examples:
> >
> > eeprom@64 {
> > compatible = "linux,slave-24c02";
> > - reg = <0x40000064>;
> > + reg = <0x64>;
This is wrong though because "linux,slave-24c02" should have bit 30 set.
(And either the unit-address was wrong or we can define the unit-address
does not include the high bits.)
Rob
^ permalink raw reply
* Re: [PATCH V5 0/9] Enable ext4 support for per-file/directory DAX operations
From: Ira Weiny @ 2020-05-29 18:12 UTC (permalink / raw)
To: Theodore Y. Ts'o
Cc: linux-ext4, Andreas Dilger, Jan Kara, Eric Biggers, Al Viro,
Dan Williams, Dave Chinner, Christoph Hellwig, Jeff Moyer,
Darrick J. Wong, linux-fsdevel, linux-kernel
In-Reply-To: <20200529041717.GN228632@mit.edu>
On Fri, May 29, 2020 at 12:17:17AM -0400, Theodore Y. Ts'o wrote:
> On Thu, May 28, 2020 at 10:54:41PM -0400, Theodore Y. Ts'o wrote:
> >
> > Thanks, applied to the ext4-dax branch.
> >
>
> I spoke too soon. While I tried merging with the ext4.git dev branch,
> a merge conflict made me look closer and I realize I needed to make
> the following changes (see diff between your patch set and what is
> currently in ext4-dax).
>
> Essentially, I needed to rework the branch to take into account commit
> e0198aff3ae3 ("ext4: reject mount options not supported when
> remounting in handle_mount_opt()").
>
> The problem is that if you allow handle_mount_opt() to apply the
> changes to the dax settings, and then later on, ext4_remount() realize
> that we're remounting, and we need to reject the change, there's a
> race if we restore the mount options to the original configuration.
> Specifically, as Syzkaller pointed out, between when we change the dax
> settings and then reset them, it's possible for some file to be opened
> with "wrong" dax setting, and then when they are reset, *boom*.
>
> The correct way to deal with this is to reject the mount option change
> much earlier, in handle_mount_opt(), *before* we mess with the dax
> settings.
>
> Please take a look at the ext4-dax for the actual changes which I
> made.
>
> Cheers,
>
> - Ted
>
>
> diff --git a/fs/ext4/super.c b/fs/ext4/super.c
> index 3658e3016999..9a37d70394b2 100644
> --- a/fs/ext4/super.c
> +++ b/fs/ext4/super.c
> @@ -1733,7 +1733,7 @@ static int clear_qf_name(struct super_block *sb, int qtype)
> #define MOPT_NO_EXT3 0x0200
> #define MOPT_EXT4_ONLY (MOPT_NO_EXT2 | MOPT_NO_EXT3)
> #define MOPT_STRING 0x0400
> -#define MOPT_SKIP 0x0800
I think we still need MOPT_SKIP...
This was put in to skip these options when printing to deal with printing only
dax=inode when it was specified by the user.
Ah but I see now. By taking MOPT_SET away you have created the same behavior?
This is orthogonal to the remount issue right?
> +#define MOPT_NO_REMOUNT 0x0800
>
> static const struct mount_opts {
> int token;
> @@ -1783,18 +1783,15 @@ static const struct mount_opts {
> {Opt_min_batch_time, 0, MOPT_GTE0},
> {Opt_inode_readahead_blks, 0, MOPT_GTE0},
> {Opt_init_itable, 0, MOPT_GTE0},
> - {Opt_dax, EXT4_MOUNT_DAX_ALWAYS, MOPT_SET | MOPT_SKIP},
> - {Opt_dax_always, EXT4_MOUNT_DAX_ALWAYS,
> - MOPT_EXT4_ONLY | MOPT_SET | MOPT_SKIP},
> - {Opt_dax_inode, EXT4_MOUNT2_DAX_INODE,
> - MOPT_EXT4_ONLY | MOPT_SET | MOPT_SKIP},
> - {Opt_dax_never, EXT4_MOUNT2_DAX_NEVER,
> - MOPT_EXT4_ONLY | MOPT_SET | MOPT_SKIP},
> + {Opt_dax, 0, MOPT_NO_REMOUNT},
> + {Opt_dax_always, 0, MOPT_NO_REMOUNT},
> + {Opt_dax_inode, 0, MOPT_NO_REMOUNT},
> + {Opt_dax_never, 0, MOPT_NO_REMOUNT},
Even if MOPT_SET is redundant. Why don't we need still need MOPT_EXT4_ONLY?
And why don't we need to associate the defines; EXT4_MOUNT_DAX_ALWAYS etc?
> {Opt_stripe, 0, MOPT_GTE0},
> {Opt_resuid, 0, MOPT_GTE0},
> {Opt_resgid, 0, MOPT_GTE0},
> - {Opt_journal_dev, 0, MOPT_NO_EXT2 | MOPT_GTE0},
> - {Opt_journal_path, 0, MOPT_NO_EXT2 | MOPT_STRING},
> + {Opt_journal_dev, 0, MOPT_NO_EXT2 | MOPT_GTE0 | MOPT_NO_REMOUNT},
> + {Opt_journal_path, 0, MOPT_NO_EXT2 | MOPT_STRING | MOPT_NO_REMOUNT},
> {Opt_journal_ioprio, 0, MOPT_NO_EXT2 | MOPT_GTE0},
> {Opt_data_journal, EXT4_MOUNT_JOURNAL_DATA, MOPT_NO_EXT2 | MOPT_DATAJ},
> {Opt_data_ordered, EXT4_MOUNT_ORDERED_DATA, MOPT_NO_EXT2 | MOPT_DATAJ},
> @@ -1831,7 +1828,7 @@ static const struct mount_opts {
> {Opt_jqfmt_vfsv1, QFMT_VFS_V1, MOPT_QFMT},
> {Opt_max_dir_size_kb, 0, MOPT_GTE0},
> {Opt_test_dummy_encryption, 0, MOPT_GTE0},
> - {Opt_nombcache, EXT4_MOUNT_NO_MBCACHE, MOPT_SET},
> + {Opt_nombcache, EXT4_MOUNT_NO_MBCACHE, MOPT_SET | MOPT_NO_REMOUNT},
> {Opt_err, 0, 0}
> };
>
> @@ -1929,6 +1926,12 @@ static int handle_mount_opt(struct super_block *sb, char *opt, int token,
> "Mount option \"%s\" incompatible with ext3", opt);
> return -1;
> }
> + if ((m->flags & MOPT_NO_REMOUNT) && is_remount) {
> + ext4_msg(sb, KERN_ERR,
> + "Mount option \"%s\" not supported when remounting",
> + opt);
> + return -1;
> + }
I think this is cleaner!
Thanks, I did test this but not while trying to manipulate files as the same time
as a remount. So a race would not have been caught.
Thanks!
Ira
>
> if (args->from && !(m->flags & MOPT_STRING) && match_int(args, &arg))
> return -1;
> @@ -2008,11 +2011,6 @@ static int handle_mount_opt(struct super_block *sb, char *opt, int token,
> }
> sbi->s_resgid = gid;
> } else if (token == Opt_journal_dev) {
> - if (is_remount) {
> - ext4_msg(sb, KERN_ERR,
> - "Cannot specify journal on remount");
> - return -1;
> - }
> *journal_devnum = arg;
> } else if (token == Opt_journal_path) {
> char *journal_path;
> @@ -2020,11 +2018,6 @@ static int handle_mount_opt(struct super_block *sb, char *opt, int token,
> struct path path;
> int error;
>
> - if (is_remount) {
> - ext4_msg(sb, KERN_ERR,
> - "Cannot specify journal on remount");
> - return -1;
> - }
> journal_path = match_strdup(&args[0]);
> if (!journal_path) {
> ext4_msg(sb, KERN_ERR, "error: could not dup "
> @@ -2287,7 +2280,7 @@ static int _ext4_show_options(struct seq_file *seq, struct super_block *sb,
> for (m = ext4_mount_opts; m->token != Opt_err; m++) {
> int want_set = m->flags & MOPT_SET;
> if (((m->flags & (MOPT_SET|MOPT_CLEAR)) == 0) ||
> - (m->flags & MOPT_CLEAR_ERR) || m->flags & MOPT_SKIP)
> + (m->flags & MOPT_CLEAR_ERR))
> continue;
> if (!nodefs && !(m->mount_opt & (sbi->s_mount_opt ^ def_mount_opt)))
> continue; /* skip if same as the default */
> @@ -5474,24 +5467,6 @@ static int ext4_remount(struct super_block *sb, int *flags, char *data)
> }
> }
>
> - if ((sbi->s_mount_opt ^ old_opts.s_mount_opt) & EXT4_MOUNT_NO_MBCACHE) {
> - ext4_msg(sb, KERN_ERR, "can't enable nombcache during remount");
> - err = -EINVAL;
> - goto restore_opts;
> - }
> -
> - if ((sbi->s_mount_opt ^ old_opts.s_mount_opt) & EXT4_MOUNT_DAX_ALWAYS ||
> - (sbi->s_mount_opt2 ^ old_opts.s_mount_opt2) & EXT4_MOUNT2_DAX_NEVER ||
> - (sbi->s_mount_opt2 ^ old_opts.s_mount_opt2) & EXT4_MOUNT2_DAX_INODE) {
> - ext4_msg(sb, KERN_WARNING, "warning: refusing change of "
> - "dax mount option with busy inodes while remounting");
> - sbi->s_mount_opt &= ~EXT4_MOUNT_DAX_ALWAYS;
> - sbi->s_mount_opt |= old_opts.s_mount_opt & EXT4_MOUNT_DAX_ALWAYS;
> - sbi->s_mount_opt2 &= ~(EXT4_MOUNT2_DAX_NEVER | EXT4_MOUNT2_DAX_INODE);
> - sbi->s_mount_opt2 |= old_opts.s_mount_opt2 &
> - (EXT4_MOUNT2_DAX_NEVER | EXT4_MOUNT2_DAX_INODE);
> - }
> -
> if (sbi->s_mount_flags & EXT4_MF_FS_ABORTED)
> ext4_abort(sb, EXT4_ERR_ESHUTDOWN, "Abort forced by user");
>
^ permalink raw reply
* Re: [PATCH net] l2tp: do not use inet_hash()/inet_unhash()
From: Eric Dumazet @ 2020-05-29 18:12 UTC (permalink / raw)
To: David S . Miller
Cc: netdev, Eric Dumazet, James Chapman, Andrii Nakryiko,
syzbot+3610d489778b57cc8031
In-Reply-To: <20200529180838.107255-1-edumazet@google.com>
On Fri, May 29, 2020 at 11:08 AM Eric Dumazet <edumazet@google.com> wrote:
>
> syzbot recently found a way to crash the kernel [1]
>
> Issue here is that inet_hash() & inet_unhash() are currently
> only meant to be used by TCP & DCCP, since only these protocols
> provide the needed hashinfo pointer.
>
> L2TP uses a single list (instead of a hash table)
>
> This old bug became an issue after commit 610236587600
> ("bpf: Add new cgroup attach type to enable sock modifications")
> since after this commit, sk_common_release() can be called
> while the L2TP socket is still considered 'hashed'.
>
> Fixes: 0d76751fad77 ("l2tp: Add L2TPv3 IP encapsulation (no UDP) support")
> Signed-off-by: Eric Dumazet <edumazet@google.com>
> Cc: James Chapman <jchapman@katalix.com>
> Cc: Andrii Nakryiko <andriin@fb.com>
> Reported-by: syzbot+3610d489778b57cc8031@syzkaller.appspotmail.com
> ---
>
Will send a V2, I missed that ip and ipv6 modules were using a different rwlock.
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.