Commit a2521822 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'devicetree-fixes-for-5.12-2' of git://git.kernel.org/pub/scm/linux/kernel/git/robh/linux

Pull devicetree fixes from Rob Herring:

 - Fix fw_devlink failure with ".*,nr-gpios" properties

 - Doc link reference fixes from Mauro

 - Fixes for unaligned FDT handling found on OpenRisc. First, avoid
   crash with better error handling when unflattening an unaligned FDT.
   Second, fix memory allocations for FDTs to ensure alignment.

* tag 'devicetree-fixes-for-5.12-2' of git://git.kernel.org/pub/scm/linux/kernel/git/robh/linux:
  of: property: fw_devlink: do not link ".*,nr-gpios"
  dt-bindings:iio:adc: update motorola,cpcap-adc.yaml reference
  dt-bindings: fix references for iio-bindings.txt
  dt-bindings: don't use ../dir for doc references
  of: unittest: overlay: ensure proper alignment of copied FDT
  of: properly check for error returned by fdt_get_name()
parents a85f165e d473d32c
...@@ -32,7 +32,7 @@ Optional node properties: ...@@ -32,7 +32,7 @@ Optional node properties:
- "#thermal-sensor-cells" Used to expose itself to thermal fw. - "#thermal-sensor-cells" Used to expose itself to thermal fw.
Read more about iio bindings at Read more about iio bindings at
Documentation/devicetree/bindings/iio/iio-bindings.txt https://github.com/devicetree-org/dt-schema/blob/master/schemas/iio/
Example: Example:
ncp15wb473@0 { ncp15wb473@0 {
......
...@@ -14,8 +14,9 @@ description: > ...@@ -14,8 +14,9 @@ description: >
Industrial I/O subsystem bindings for ADC controller found in Industrial I/O subsystem bindings for ADC controller found in
Ingenic JZ47xx SoCs. Ingenic JZ47xx SoCs.
ADC clients must use the format described in iio-bindings.txt, giving ADC clients must use the format described in
a phandle and IIO specifier pair ("io-channels") to the ADC controller. https://github.com/devicetree-org/dt-schema/blob/master/schemas/iio/iio-consumer.yaml,
giving a phandle and IIO specifier pair ("io-channels") to the ADC controller.
properties: properties:
compatible: compatible:
......
...@@ -24,7 +24,9 @@ properties: ...@@ -24,7 +24,9 @@ properties:
description: > description: >
List of phandle and IIO specifier pairs. List of phandle and IIO specifier pairs.
Each pair defines one ADC channel to which a joystick axis is connected. Each pair defines one ADC channel to which a joystick axis is connected.
See Documentation/devicetree/bindings/iio/iio-bindings.txt for details. See
https://github.com/devicetree-org/dt-schema/blob/master/schemas/iio/iio-consumer.yaml
for details.
'#address-cells': '#address-cells':
const: 1 const: 1
......
...@@ -5,7 +5,10 @@ Required properties: ...@@ -5,7 +5,10 @@ Required properties:
- compatible: must be "resistive-adc-touch" - compatible: must be "resistive-adc-touch"
The device must be connected to an ADC device that provides channels for The device must be connected to an ADC device that provides channels for
position measurement and optional pressure. position measurement and optional pressure.
Refer to ../iio/iio-bindings.txt for details Refer to
https://github.com/devicetree-org/dt-schema/blob/master/schemas/iio/iio-consumer.yaml
for details
- iio-channels: must have at least two channels connected to an ADC device. - iio-channels: must have at least two channels connected to an ADC device.
These should correspond to the channels exposed by the ADC device and should These should correspond to the channels exposed by the ADC device and should
have the right index as the ADC device registers them. These channels have the right index as the ADC device registers them. These channels
......
...@@ -72,7 +72,9 @@ Required child device properties: ...@@ -72,7 +72,9 @@ Required child device properties:
pwm|regulator|rtc|sysctrl|usb]"; pwm|regulator|rtc|sysctrl|usb]";
A few child devices require ADC channels from the GPADC node. Those follow the A few child devices require ADC channels from the GPADC node. Those follow the
standard bindings from iio/iio-bindings.txt and iio/adc/adc.txt standard bindings from
https://github.com/devicetree-org/dt-schema/blob/master/schemas/iio/iio-consumer.yaml
and Documentation/devicetree/bindings/iio/adc/adc.yaml
abx500-temp : io-channels "aux1" and "aux2" for measuring external abx500-temp : io-channels "aux1" and "aux2" for measuring external
temperatures. temperatures.
......
...@@ -16,14 +16,14 @@ Optional subnodes: ...@@ -16,14 +16,14 @@ Optional subnodes:
The sub-functions of CPCAP get their own node with their own compatible values, The sub-functions of CPCAP get their own node with their own compatible values,
which are described in the following files: which are described in the following files:
- ../power/supply/cpcap-battery.txt - Documentation/devicetree/bindings/power/supply/cpcap-battery.txt
- ../power/supply/cpcap-charger.txt - Documentation/devicetree/bindings/power/supply/cpcap-charger.txt
- ../regulator/cpcap-regulator.txt - Documentation/devicetree/bindings/regulator/cpcap-regulator.txt
- ../phy/phy-cpcap-usb.txt - Documentation/devicetree/bindings/phy/phy-cpcap-usb.txt
- ../input/cpcap-pwrbutton.txt - Documentation/devicetree/bindings/input/cpcap-pwrbutton.txt
- ../rtc/cpcap-rtc.txt - Documentation/devicetree/bindings/rtc/cpcap-rtc.txt
- ../leds/leds-cpcap.txt - Documentation/devicetree/bindings/leds/leds-cpcap.txt
- ../iio/adc/cpcap-adc.txt - Documentation/devicetree/bindings/iio/adc/motorola,cpcap-adc.yaml
The only exception is the audio codec. Instead of a compatible value its The only exception is the audio codec. Instead of a compatible value its
node must be named "audio-codec". node must be named "audio-codec".
......
...@@ -205,7 +205,7 @@ static void populate_properties(const void *blob, ...@@ -205,7 +205,7 @@ static void populate_properties(const void *blob,
*pprev = NULL; *pprev = NULL;
} }
static bool populate_node(const void *blob, static int populate_node(const void *blob,
int offset, int offset,
void **mem, void **mem,
struct device_node *dad, struct device_node *dad,
...@@ -214,24 +214,24 @@ static bool populate_node(const void *blob, ...@@ -214,24 +214,24 @@ static bool populate_node(const void *blob,
{ {
struct device_node *np; struct device_node *np;
const char *pathp; const char *pathp;
unsigned int l, allocl; int len;
pathp = fdt_get_name(blob, offset, &l); pathp = fdt_get_name(blob, offset, &len);
if (!pathp) { if (!pathp) {
*pnp = NULL; *pnp = NULL;
return false; return len;
} }
allocl = ++l; len++;
np = unflatten_dt_alloc(mem, sizeof(struct device_node) + allocl, np = unflatten_dt_alloc(mem, sizeof(struct device_node) + len,
__alignof__(struct device_node)); __alignof__(struct device_node));
if (!dryrun) { if (!dryrun) {
char *fn; char *fn;
of_node_init(np); of_node_init(np);
np->full_name = fn = ((char *)np) + sizeof(*np); np->full_name = fn = ((char *)np) + sizeof(*np);
memcpy(fn, pathp, l); memcpy(fn, pathp, len);
if (dad != NULL) { if (dad != NULL) {
np->parent = dad; np->parent = dad;
...@@ -295,6 +295,7 @@ static int unflatten_dt_nodes(const void *blob, ...@@ -295,6 +295,7 @@ static int unflatten_dt_nodes(const void *blob,
struct device_node *nps[FDT_MAX_DEPTH]; struct device_node *nps[FDT_MAX_DEPTH];
void *base = mem; void *base = mem;
bool dryrun = !base; bool dryrun = !base;
int ret;
if (nodepp) if (nodepp)
*nodepp = NULL; *nodepp = NULL;
...@@ -322,9 +323,10 @@ static int unflatten_dt_nodes(const void *blob, ...@@ -322,9 +323,10 @@ static int unflatten_dt_nodes(const void *blob,
!of_fdt_device_is_available(blob, offset)) !of_fdt_device_is_available(blob, offset))
continue; continue;
if (!populate_node(blob, offset, &mem, nps[depth], ret = populate_node(blob, offset, &mem, nps[depth],
&nps[depth+1], dryrun)) &nps[depth+1], dryrun);
return mem - base; if (ret < 0)
return ret;
if (!dryrun && nodepp && !*nodepp) if (!dryrun && nodepp && !*nodepp)
*nodepp = nps[depth+1]; *nodepp = nps[depth+1];
...@@ -372,6 +374,10 @@ void *__unflatten_device_tree(const void *blob, ...@@ -372,6 +374,10 @@ void *__unflatten_device_tree(const void *blob,
{ {
int size; int size;
void *mem; void *mem;
int ret;
if (mynodes)
*mynodes = NULL;
pr_debug(" -> unflatten_device_tree()\n"); pr_debug(" -> unflatten_device_tree()\n");
...@@ -392,7 +398,7 @@ void *__unflatten_device_tree(const void *blob, ...@@ -392,7 +398,7 @@ void *__unflatten_device_tree(const void *blob,
/* First pass, scan for size */ /* First pass, scan for size */
size = unflatten_dt_nodes(blob, NULL, dad, NULL); size = unflatten_dt_nodes(blob, NULL, dad, NULL);
if (size < 0) if (size <= 0)
return NULL; return NULL;
size = ALIGN(size, 4); size = ALIGN(size, 4);
...@@ -410,12 +416,16 @@ void *__unflatten_device_tree(const void *blob, ...@@ -410,12 +416,16 @@ void *__unflatten_device_tree(const void *blob,
pr_debug(" unflattening %p...\n", mem); pr_debug(" unflattening %p...\n", mem);
/* Second pass, do actual unflattening */ /* Second pass, do actual unflattening */
unflatten_dt_nodes(blob, mem, dad, mynodes); ret = unflatten_dt_nodes(blob, mem, dad, mynodes);
if (be32_to_cpup(mem + size) != 0xdeadbeef) if (be32_to_cpup(mem + size) != 0xdeadbeef)
pr_warn("End of tree marker overwritten: %08x\n", pr_warn("End of tree marker overwritten: %08x\n",
be32_to_cpup(mem + size)); be32_to_cpup(mem + size));
if (detached && mynodes) { if (ret <= 0)
return NULL;
if (detached && mynodes && *mynodes) {
of_node_set_flag(*mynodes, OF_DETACHED); of_node_set_flag(*mynodes, OF_DETACHED);
pr_debug("unflattened tree is detached\n"); pr_debug("unflattened tree is detached\n");
} }
......
...@@ -8,6 +8,8 @@ ...@@ -8,6 +8,8 @@
* Copyright (C) 1996-2005 Paul Mackerras. * Copyright (C) 1996-2005 Paul Mackerras.
*/ */
#define FDT_ALIGN_SIZE 8
/** /**
* struct alias_prop - Alias property in 'aliases' node * struct alias_prop - Alias property in 'aliases' node
* @link: List node to link the structure in aliases_lookup list * @link: List node to link the structure in aliases_lookup list
......
...@@ -57,7 +57,7 @@ struct fragment { ...@@ -57,7 +57,7 @@ struct fragment {
* struct overlay_changeset * struct overlay_changeset
* @id: changeset identifier * @id: changeset identifier
* @ovcs_list: list on which we are located * @ovcs_list: list on which we are located
* @fdt: FDT that was unflattened to create @overlay_tree * @fdt: base of memory allocated to hold aligned FDT that was unflattened to create @overlay_tree
* @overlay_tree: expanded device tree that contains the fragment nodes * @overlay_tree: expanded device tree that contains the fragment nodes
* @count: count of fragment structures * @count: count of fragment structures
* @fragments: fragment nodes in the overlay expanded device tree * @fragments: fragment nodes in the overlay expanded device tree
...@@ -719,8 +719,8 @@ static struct device_node *find_target(struct device_node *info_node) ...@@ -719,8 +719,8 @@ static struct device_node *find_target(struct device_node *info_node)
/** /**
* init_overlay_changeset() - initialize overlay changeset from overlay tree * init_overlay_changeset() - initialize overlay changeset from overlay tree
* @ovcs: Overlay changeset to build * @ovcs: Overlay changeset to build
* @fdt: the FDT that was unflattened to create @tree * @fdt: base of memory allocated to hold aligned FDT that was unflattened to create @tree
* @tree: Contains all the overlay fragments and overlay fixup nodes * @tree: Contains the overlay fragments and overlay fixup nodes
* *
* Initialize @ovcs. Populate @ovcs->fragments with node information from * Initialize @ovcs. Populate @ovcs->fragments with node information from
* the top level of @tree. The relevant top level nodes are the fragment * the top level of @tree. The relevant top level nodes are the fragment
...@@ -873,7 +873,7 @@ static void free_overlay_changeset(struct overlay_changeset *ovcs) ...@@ -873,7 +873,7 @@ static void free_overlay_changeset(struct overlay_changeset *ovcs)
* internal documentation * internal documentation
* *
* of_overlay_apply() - Create and apply an overlay changeset * of_overlay_apply() - Create and apply an overlay changeset
* @fdt: the FDT that was unflattened to create @tree * @fdt: base of memory allocated to hold the aligned FDT
* @tree: Expanded overlay device tree * @tree: Expanded overlay device tree
* @ovcs_id: Pointer to overlay changeset id * @ovcs_id: Pointer to overlay changeset id
* *
...@@ -953,7 +953,9 @@ static int of_overlay_apply(const void *fdt, struct device_node *tree, ...@@ -953,7 +953,9 @@ static int of_overlay_apply(const void *fdt, struct device_node *tree,
/* /*
* after overlay_notify(), ovcs->overlay_tree related pointers may have * after overlay_notify(), ovcs->overlay_tree related pointers may have
* leaked to drivers, so can not kfree() tree, aka ovcs->overlay_tree; * leaked to drivers, so can not kfree() tree, aka ovcs->overlay_tree;
* and can not free fdt, aka ovcs->fdt * and can not free memory containing aligned fdt. The aligned fdt
* is contained within the memory at ovcs->fdt, possibly at an offset
* from ovcs->fdt.
*/ */
ret = overlay_notify(ovcs, OF_OVERLAY_PRE_APPLY); ret = overlay_notify(ovcs, OF_OVERLAY_PRE_APPLY);
if (ret) { if (ret) {
...@@ -1014,10 +1016,11 @@ static int of_overlay_apply(const void *fdt, struct device_node *tree, ...@@ -1014,10 +1016,11 @@ static int of_overlay_apply(const void *fdt, struct device_node *tree,
int of_overlay_fdt_apply(const void *overlay_fdt, u32 overlay_fdt_size, int of_overlay_fdt_apply(const void *overlay_fdt, u32 overlay_fdt_size,
int *ovcs_id) int *ovcs_id)
{ {
const void *new_fdt; void *new_fdt;
void *new_fdt_align;
int ret; int ret;
u32 size; u32 size;
struct device_node *overlay_root; struct device_node *overlay_root = NULL;
*ovcs_id = 0; *ovcs_id = 0;
ret = 0; ret = 0;
...@@ -1036,11 +1039,14 @@ int of_overlay_fdt_apply(const void *overlay_fdt, u32 overlay_fdt_size, ...@@ -1036,11 +1039,14 @@ int of_overlay_fdt_apply(const void *overlay_fdt, u32 overlay_fdt_size,
* Must create permanent copy of FDT because of_fdt_unflatten_tree() * Must create permanent copy of FDT because of_fdt_unflatten_tree()
* will create pointers to the passed in FDT in the unflattened tree. * will create pointers to the passed in FDT in the unflattened tree.
*/ */
new_fdt = kmemdup(overlay_fdt, size, GFP_KERNEL); new_fdt = kmalloc(size + FDT_ALIGN_SIZE, GFP_KERNEL);
if (!new_fdt) if (!new_fdt)
return -ENOMEM; return -ENOMEM;
of_fdt_unflatten_tree(new_fdt, NULL, &overlay_root); new_fdt_align = PTR_ALIGN(new_fdt, FDT_ALIGN_SIZE);
memcpy(new_fdt_align, overlay_fdt, size);
of_fdt_unflatten_tree(new_fdt_align, NULL, &overlay_root);
if (!overlay_root) { if (!overlay_root) {
pr_err("unable to unflatten overlay_fdt\n"); pr_err("unable to unflatten overlay_fdt\n");
ret = -EINVAL; ret = -EINVAL;
......
...@@ -1262,7 +1262,16 @@ DEFINE_SIMPLE_PROP(pinctrl7, "pinctrl-7", NULL) ...@@ -1262,7 +1262,16 @@ DEFINE_SIMPLE_PROP(pinctrl7, "pinctrl-7", NULL)
DEFINE_SIMPLE_PROP(pinctrl8, "pinctrl-8", NULL) DEFINE_SIMPLE_PROP(pinctrl8, "pinctrl-8", NULL)
DEFINE_SUFFIX_PROP(regulators, "-supply", NULL) DEFINE_SUFFIX_PROP(regulators, "-supply", NULL)
DEFINE_SUFFIX_PROP(gpio, "-gpio", "#gpio-cells") DEFINE_SUFFIX_PROP(gpio, "-gpio", "#gpio-cells")
DEFINE_SUFFIX_PROP(gpios, "-gpios", "#gpio-cells")
static struct device_node *parse_gpios(struct device_node *np,
const char *prop_name, int index)
{
if (!strcmp_suffix(prop_name, ",nr-gpios"))
return NULL;
return parse_suffix_prop_cells(np, prop_name, index, "-gpios",
"#gpio-cells");
}
static struct device_node *parse_iommu_maps(struct device_node *np, static struct device_node *parse_iommu_maps(struct device_node *np,
const char *prop_name, int index) const char *prop_name, int index)
......
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/device.h> #include <linux/device.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/kernel.h>
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/i2c-mux.h> #include <linux/i2c-mux.h>
...@@ -1408,7 +1409,8 @@ static void attach_node_and_children(struct device_node *np) ...@@ -1408,7 +1409,8 @@ static void attach_node_and_children(struct device_node *np)
static int __init unittest_data_add(void) static int __init unittest_data_add(void)
{ {
void *unittest_data; void *unittest_data;
struct device_node *unittest_data_node, *np; void *unittest_data_align;
struct device_node *unittest_data_node = NULL, *np;
/* /*
* __dtb_testcases_begin[] and __dtb_testcases_end[] are magically * __dtb_testcases_begin[] and __dtb_testcases_end[] are magically
* created by cmd_dt_S_dtb in scripts/Makefile.lib * created by cmd_dt_S_dtb in scripts/Makefile.lib
...@@ -1417,21 +1419,29 @@ static int __init unittest_data_add(void) ...@@ -1417,21 +1419,29 @@ static int __init unittest_data_add(void)
extern uint8_t __dtb_testcases_end[]; extern uint8_t __dtb_testcases_end[];
const int size = __dtb_testcases_end - __dtb_testcases_begin; const int size = __dtb_testcases_end - __dtb_testcases_begin;
int rc; int rc;
void *ret;
if (!size) { if (!size) {
pr_warn("%s: No testcase data to attach; not running tests\n", pr_warn("%s: testcases is empty\n", __func__);
__func__);
return -ENODATA; return -ENODATA;
} }
/* creating copy */ /* creating copy */
unittest_data = kmemdup(__dtb_testcases_begin, size, GFP_KERNEL); unittest_data = kmalloc(size + FDT_ALIGN_SIZE, GFP_KERNEL);
if (!unittest_data) if (!unittest_data)
return -ENOMEM; return -ENOMEM;
of_fdt_unflatten_tree(unittest_data, NULL, &unittest_data_node); unittest_data_align = PTR_ALIGN(unittest_data, FDT_ALIGN_SIZE);
memcpy(unittest_data_align, __dtb_testcases_begin, size);
ret = of_fdt_unflatten_tree(unittest_data_align, NULL, &unittest_data_node);
if (!ret) {
pr_warn("%s: unflatten testcases tree failed\n", __func__);
kfree(unittest_data);
return -ENODATA;
}
if (!unittest_data_node) { if (!unittest_data_node) {
pr_warn("%s: No tree to attach; not running tests\n", __func__); pr_warn("%s: testcases tree is empty\n", __func__);
kfree(unittest_data); kfree(unittest_data);
return -ENODATA; return -ENODATA;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment