Devicetree fixes for v5.12, take 2:

- 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.
 -----BEGIN PGP SIGNATURE-----
 
 iQJEBAABCgAuFiEEktVUI4SxYhzZyEuo+vtdtY28YcMFAmBwq7UQHHJvYmhAa2Vy
 bmVsLm9yZwAKCRD6+121jbxhw1IMD/4mnveo0vrzSBnB8Gj9MQ1NIPumUIpc/VN6
 NtfwZgemupEQM66TMQiHzeHSmQ7tY6SPRJnIlqZvWTvmeHYDOtrTtByR4BQHQb+E
 Foz6a+4aFQjo2Wc4LJG7Y+25sg+/outLuC8dBARpbi7uCEKlCOaVCpyMhR+61uvS
 JIqpNCbwKgos9aSTsNDpiturKlw9qMRq3jIITF/YS8R1QXuVgrDj6X7HDpm0iVxM
 IUZZz6Qe6lSsJodVNV+8sMIIF4I2pCfNlUo46W5q80VzerHTlp7aArFQdSpvCyHF
 StVS1a3ksYqycIsW90zgo+v3DrnKI6OSe9LqLsYOHwHCuu1G5t02RqoZ2/oYRZJX
 Ho1t+12AZpkcQ1DSm+nrawLGr7VJ9eFToGFhMeSIRiQebdKDWYbIJe21NSaEBYtO
 FTj5cigBopJOE7WrfIPuCZwfHokYqZeti/vaCYc5VkgVB25gVRsOowosE+Z7S2Rm
 xJvMDnKSCQprUbX6Q1w+9CZ79Ru/t/K/Xq0wakbhnFI+jiGhBbjfEyBfzCVUZcQq
 Jhl42KQPLCYeLpkuwFZBcRLZzOQU6xZHxWU8FfRulpMefIvDHFOvyNntElXrHSgg
 niMwCUY042eHXj/Ptg2cUYsYugiAik6+eEMtqX0tb61a1+n7UVztDGfjeWlbaIzP
 ol+Ba+6wCg==
 =7rNZ
 -----END PGP SIGNATURE-----

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()
This commit is contained in:
Linus Torvalds 2021-04-09 13:01:48 -07:00
commit a2521822bd
11 changed files with 88 additions and 43 deletions

View File

@ -32,7 +32,7 @@ Optional node properties:
- "#thermal-sensor-cells" Used to expose itself to thermal fw.
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:
ncp15wb473@0 {

View File

@ -14,8 +14,9 @@ description: >
Industrial I/O subsystem bindings for ADC controller found in
Ingenic JZ47xx SoCs.
ADC clients must use the format described in iio-bindings.txt, giving
a phandle and IIO specifier pair ("io-channels") to the ADC controller.
ADC clients must use the format described in
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:
compatible:

View File

@ -24,7 +24,9 @@ properties:
description: >
List of phandle and IIO specifier pairs.
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':
const: 1

View File

@ -5,7 +5,10 @@ Required properties:
- compatible: must be "resistive-adc-touch"
The device must be connected to an ADC device that provides channels for
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.
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

View File

@ -72,7 +72,9 @@ Required child device properties:
pwm|regulator|rtc|sysctrl|usb]";
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
temperatures.

View File

@ -16,14 +16,14 @@ Optional subnodes:
The sub-functions of CPCAP get their own node with their own compatible values,
which are described in the following files:
- ../power/supply/cpcap-battery.txt
- ../power/supply/cpcap-charger.txt
- ../regulator/cpcap-regulator.txt
- ../phy/phy-cpcap-usb.txt
- ../input/cpcap-pwrbutton.txt
- ../rtc/cpcap-rtc.txt
- ../leds/leds-cpcap.txt
- ../iio/adc/cpcap-adc.txt
- Documentation/devicetree/bindings/power/supply/cpcap-battery.txt
- Documentation/devicetree/bindings/power/supply/cpcap-charger.txt
- Documentation/devicetree/bindings/regulator/cpcap-regulator.txt
- Documentation/devicetree/bindings/phy/phy-cpcap-usb.txt
- Documentation/devicetree/bindings/input/cpcap-pwrbutton.txt
- Documentation/devicetree/bindings/rtc/cpcap-rtc.txt
- Documentation/devicetree/bindings/leds/leds-cpcap.txt
- Documentation/devicetree/bindings/iio/adc/motorola,cpcap-adc.yaml
The only exception is the audio codec. Instead of a compatible value its
node must be named "audio-codec".

View File

@ -205,7 +205,7 @@ static void populate_properties(const void *blob,
*pprev = NULL;
}
static bool populate_node(const void *blob,
static int populate_node(const void *blob,
int offset,
void **mem,
struct device_node *dad,
@ -214,24 +214,24 @@ static bool populate_node(const void *blob,
{
struct device_node *np;
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) {
*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));
if (!dryrun) {
char *fn;
of_node_init(np);
np->full_name = fn = ((char *)np) + sizeof(*np);
memcpy(fn, pathp, l);
memcpy(fn, pathp, len);
if (dad != NULL) {
np->parent = dad;
@ -295,6 +295,7 @@ static int unflatten_dt_nodes(const void *blob,
struct device_node *nps[FDT_MAX_DEPTH];
void *base = mem;
bool dryrun = !base;
int ret;
if (nodepp)
*nodepp = NULL;
@ -322,9 +323,10 @@ static int unflatten_dt_nodes(const void *blob,
!of_fdt_device_is_available(blob, offset))
continue;
if (!populate_node(blob, offset, &mem, nps[depth],
&nps[depth+1], dryrun))
return mem - base;
ret = populate_node(blob, offset, &mem, nps[depth],
&nps[depth+1], dryrun);
if (ret < 0)
return ret;
if (!dryrun && nodepp && !*nodepp)
*nodepp = nps[depth+1];
@ -372,6 +374,10 @@ void *__unflatten_device_tree(const void *blob,
{
int size;
void *mem;
int ret;
if (mynodes)
*mynodes = NULL;
pr_debug(" -> unflatten_device_tree()\n");
@ -392,7 +398,7 @@ void *__unflatten_device_tree(const void *blob,
/* First pass, scan for size */
size = unflatten_dt_nodes(blob, NULL, dad, NULL);
if (size < 0)
if (size <= 0)
return NULL;
size = ALIGN(size, 4);
@ -410,12 +416,16 @@ void *__unflatten_device_tree(const void *blob,
pr_debug(" unflattening %p...\n", mem);
/* 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)
pr_warn("End of tree marker overwritten: %08x\n",
be32_to_cpup(mem + size));
if (detached && mynodes) {
if (ret <= 0)
return NULL;
if (detached && mynodes && *mynodes) {
of_node_set_flag(*mynodes, OF_DETACHED);
pr_debug("unflattened tree is detached\n");
}

View File

@ -8,6 +8,8 @@
* Copyright (C) 1996-2005 Paul Mackerras.
*/
#define FDT_ALIGN_SIZE 8
/**
* struct alias_prop - Alias property in 'aliases' node
* @link: List node to link the structure in aliases_lookup list

View File

@ -57,7 +57,7 @@ struct fragment {
* struct overlay_changeset
* @id: changeset identifier
* @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
* @count: count of fragment structures
* @fragments: fragment nodes in the overlay expanded device tree
@ -719,8 +719,8 @@ static struct device_node *find_target(struct device_node *info_node)
/**
* init_overlay_changeset() - initialize overlay changeset from overlay tree
* @ovcs: Overlay changeset to build
* @fdt: the FDT that was unflattened to create @tree
* @tree: Contains all the overlay fragments and overlay fixup nodes
* @fdt: base of memory allocated to hold aligned FDT that was unflattened to create @tree
* @tree: Contains the overlay fragments and overlay fixup nodes
*
* Initialize @ovcs. Populate @ovcs->fragments with node information from
* 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)
* internal documentation
*
* 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
* @ovcs_id: Pointer to overlay changeset id
*
@ -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
* 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);
if (ret) {
@ -1014,10 +1016,11 @@ out:
int of_overlay_fdt_apply(const void *overlay_fdt, u32 overlay_fdt_size,
int *ovcs_id)
{
const void *new_fdt;
void *new_fdt;
void *new_fdt_align;
int ret;
u32 size;
struct device_node *overlay_root;
struct device_node *overlay_root = NULL;
*ovcs_id = 0;
ret = 0;
@ -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()
* 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)
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) {
pr_err("unable to unflatten overlay_fdt\n");
ret = -EINVAL;

View File

@ -1262,7 +1262,16 @@ DEFINE_SIMPLE_PROP(pinctrl7, "pinctrl-7", NULL)
DEFINE_SIMPLE_PROP(pinctrl8, "pinctrl-8", NULL)
DEFINE_SUFFIX_PROP(regulators, "-supply", NULL)
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,
const char *prop_name, int index)

View File

@ -22,6 +22,7 @@
#include <linux/slab.h>
#include <linux/device.h>
#include <linux/platform_device.h>
#include <linux/kernel.h>
#include <linux/i2c.h>
#include <linux/i2c-mux.h>
@ -1408,7 +1409,8 @@ static void attach_node_and_children(struct device_node *np)
static int __init unittest_data_add(void)
{
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
* created by cmd_dt_S_dtb in scripts/Makefile.lib
@ -1417,21 +1419,29 @@ static int __init unittest_data_add(void)
extern uint8_t __dtb_testcases_end[];
const int size = __dtb_testcases_end - __dtb_testcases_begin;
int rc;
void *ret;
if (!size) {
pr_warn("%s: No testcase data to attach; not running tests\n",
__func__);
pr_warn("%s: testcases is empty\n", __func__);
return -ENODATA;
}
/* creating copy */
unittest_data = kmemdup(__dtb_testcases_begin, size, GFP_KERNEL);
unittest_data = kmalloc(size + FDT_ALIGN_SIZE, GFP_KERNEL);
if (!unittest_data)
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) {
pr_warn("%s: No tree to attach; not running tests\n", __func__);
pr_warn("%s: testcases tree is empty\n", __func__);
kfree(unittest_data);
return -ENODATA;
}