Skip to content

Commit

Permalink
Merge tag 'devicetree-fixes-for-5.12-2' of git://git.kernel.org/pub/s…
Browse files Browse the repository at this point in the history
…cm/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()
  • Loading branch information
Linus Torvalds committed Apr 9, 2021
2 parents a85f165 + d473d32 commit a252182
Show file tree
Hide file tree
Showing 11 changed files with 88 additions and 43 deletions.
2 changes: 1 addition & 1 deletion Documentation/devicetree/bindings/hwmon/ntc_thermistor.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
5 changes: 3 additions & 2 deletions Documentation/devicetree/bindings/iio/adc/ingenic,adc.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
4 changes: 3 additions & 1 deletion Documentation/devicetree/bindings/input/adc-joystick.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
4 changes: 3 additions & 1 deletion Documentation/devicetree/bindings/mfd/ab8500.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
16 changes: 8 additions & 8 deletions Documentation/devicetree/bindings/mfd/motorola-cpcap.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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".
Expand Down
36 changes: 23 additions & 13 deletions drivers/of/fdt.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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];
Expand Down Expand Up @@ -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");

Expand All @@ -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);
Expand All @@ -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");
}
Expand Down
2 changes: 2 additions & 0 deletions drivers/of/of_private.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
24 changes: 15 additions & 9 deletions drivers/of/overlay.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
*
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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 *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;
Expand All @@ -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;
Expand Down
11 changes: 10 additions & 1 deletion drivers/of/property.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
22 changes: 16 additions & 6 deletions drivers/of/unittest.c
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down Expand Up @@ -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
Expand All @@ -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;
}
Expand Down

0 comments on commit a252182

Please sign in to comment.