Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

software node: allow referencing firmware nodes

At the moment software nodes can only reference other software nodes.
This is a limitation for devices created, for instance, on the auxiliary
bus with a dynamic software node attached which cannot reference devices
the firmware node of which is "real" (as an OF node or otherwise).

Make it possible for a software node to reference all firmware nodes in
addition to static software nodes. To that end: add a second pointer to
struct software_node_ref_args of type struct fwnode_handle. The core
swnode code will first check the swnode pointer and if it's NULL, it
will assume the fwnode pointer should be set.

Software node graphs remain the same, as in: the remote endpoints still
have to be software nodes.

Acked-by: Linus Walleij <linus.walleij@linaro.org>
Reviewed-by: Sakari Ailus <sakari.ailus@linux.intel.com>
Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Acked-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
Reviewed-by: Charles Keepax <ckeepax@opensource.cirrus.com>
Tested-by: Charles Keepax <ckeepax@opensource.cirrus.com>
Signed-off-by: Philipp Zabel <p.zabel@pengutronix.de>

authored by

Bartosz Golaszewski and committed by
Philipp Zabel
d7cdbbc9 0651933c

+32 -5
+22 -2
drivers/base/swnode.c
··· 535 535 ref_array = prop->pointer; 536 536 ref = &ref_array[index]; 537 537 538 - refnode = software_node_fwnode(ref->node); 538 + /* 539 + * A software node can reference other software nodes or firmware 540 + * nodes (which are the abstraction layer sitting on top of them). 541 + * This is done to ensure we can create references to static software 542 + * nodes before they're registered with the firmware node framework. 543 + * At the time the reference is being resolved, we expect the swnodes 544 + * in question to already have been registered and to be backed by 545 + * a firmware node. This is why we use the fwnode API below to read the 546 + * relevant properties and bump the reference count. 547 + */ 548 + 549 + if (ref->swnode) 550 + refnode = software_node_fwnode(ref->swnode); 551 + else if (ref->fwnode) 552 + refnode = ref->fwnode; 553 + else 554 + return -EINVAL; 555 + 539 556 if (!refnode) 540 557 return -ENOENT; 541 558 ··· 650 633 651 634 ref = prop->pointer; 652 635 653 - return software_node_get(software_node_fwnode(ref[0].node)); 636 + if (!ref->swnode) 637 + return NULL; 638 + 639 + return software_node_get(software_node_fwnode(ref->swnode)); 654 640 } 655 641 656 642 static struct fwnode_handle *
+10 -3
include/linux/property.h
··· 355 355 356 356 /** 357 357 * struct software_node_ref_args - Reference property with additional arguments 358 - * @node: Reference to a software node 358 + * @swnode: Reference to a software node 359 + * @fwnode: Alternative reference to a firmware node handle 359 360 * @nargs: Number of elements in @args array 360 361 * @args: Integer arguments 361 362 */ 362 363 struct software_node_ref_args { 363 - const struct software_node *node; 364 + const struct software_node *swnode; 365 + struct fwnode_handle *fwnode; 364 366 unsigned int nargs; 365 367 u64 args[NR_FWNODE_REFERENCE_ARGS]; 366 368 }; 367 369 368 370 #define SOFTWARE_NODE_REFERENCE(_ref_, ...) \ 369 371 (const struct software_node_ref_args) { \ 370 - .node = _ref_, \ 372 + .swnode = _Generic(_ref_, \ 373 + const struct software_node *: _ref_, \ 374 + default: NULL), \ 375 + .fwnode = _Generic(_ref_, \ 376 + struct fwnode_handle *: _ref_, \ 377 + default: NULL), \ 371 378 .nargs = COUNT_ARGS(__VA_ARGS__), \ 372 379 .args = { __VA_ARGS__ }, \ 373 380 }