* [RFC PATCH 0/2] software node: API documentation @ 2019-10-02 12:33 Heikki Krogerus 2019-10-02 12:33 ` [RFC PATCH 1/2] software node: Add missing kernel-doc function descriptions Heikki Krogerus 2019-10-02 12:33 ` [RFC PATCH 2/2] software node: Add documentation Heikki Krogerus 0 siblings, 2 replies; 5+ messages in thread From: Heikki Krogerus @ 2019-10-02 12:33 UTC (permalink / raw) To: Laurent Pinchart Cc: Dmitry Torokhov, Andy Shevchenko, Rafael J. Wysocki, Mika Westerberg, linux-doc, linux-kernel Hi, I'm sending this as an RFC first. I would like to wait for the API change Dmitry proposed [1] before we add the final API documentation for the software nodes. At this point I would like to know if the generic use is explained clearly enough and if there is anything missing that should be added. [1] https://lkml.org/lkml/2019/9/11/8 thanks, Heikki Krogerus (2): software node: Add missing kernel-doc function descriptions software node: Add documentation Documentation/driver-api/software_node.rst | 197 +++++++++++++++++++++ drivers/base/swnode.c | 23 +++ 2 files changed, 220 insertions(+) create mode 100644 Documentation/driver-api/software_node.rst -- 2.23.0 ^ permalink raw reply [flat|nested] 5+ messages in thread
* [RFC PATCH 1/2] software node: Add missing kernel-doc function descriptions 2019-10-02 12:33 [RFC PATCH 0/2] software node: API documentation Heikki Krogerus @ 2019-10-02 12:33 ` Heikki Krogerus 2019-10-02 12:33 ` [RFC PATCH 2/2] software node: Add documentation Heikki Krogerus 1 sibling, 0 replies; 5+ messages in thread From: Heikki Krogerus @ 2019-10-02 12:33 UTC (permalink / raw) To: Laurent Pinchart Cc: Dmitry Torokhov, Andy Shevchenko, Rafael J. Wysocki, Mika Westerberg, linux-doc, linux-kernel Some of the functions were missing kernel-doc style descriptions. Signed-off-by: Heikki Krogerus <heikki.krogerus@linux.intel.com> --- drivers/base/swnode.c | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/drivers/base/swnode.c b/drivers/base/swnode.c index a1f3f0994f9f..51c9e6c56c26 100644 --- a/drivers/base/swnode.c +++ b/drivers/base/swnode.c @@ -33,6 +33,10 @@ static struct kset *swnode_kset; static const struct fwnode_operations software_node_ops; +/** + * is_software_node - Test if fwnode handle is software node + * @fwnode: The fwnode handle to test + */ bool is_software_node(const struct fwnode_handle *fwnode) { return !IS_ERR_OR_NULL(fwnode) && fwnode->ops == &software_node_ops; @@ -71,6 +75,10 @@ software_node_to_swnode(const struct software_node *node) return swnode; } +/** + * to_software_node - Convert fwnode handle to software node + * @fwnode: The fwnode handle of the software node + */ const struct software_node *to_software_node(struct fwnode_handle *fwnode) { struct swnode *swnode = to_swnode(fwnode); @@ -79,6 +87,10 @@ const struct software_node *to_software_node(struct fwnode_handle *fwnode) } EXPORT_SYMBOL_GPL(to_software_node); +/** + * software_node_fwnode - Convert software node to fwnode handle + * @swnode: The software node + */ struct fwnode_handle *software_node_fwnode(const struct software_node *node) { struct swnode *swnode = software_node_to_swnode(node); @@ -802,6 +814,13 @@ int software_node_register(const struct software_node *node) } EXPORT_SYMBOL_GPL(software_node_register); +/** + * fwnode_create_software_node - Create and register a software node + * @properties: Device properties for the software node + * @parent: The parent node + * + * Returnes the fwnode handle of the software node on success. + */ struct fwnode_handle * fwnode_create_software_node(const struct property_entry *properties, const struct fwnode_handle *parent) @@ -834,6 +853,10 @@ fwnode_create_software_node(const struct property_entry *properties, } EXPORT_SYMBOL_GPL(fwnode_create_software_node); +/** + * fwnode_remove_software_node - Remove a software node + * @fwnode: The fwnode handle of the software node + */ void fwnode_remove_software_node(struct fwnode_handle *fwnode) { struct swnode *swnode = to_swnode(fwnode); -- 2.23.0 ^ permalink raw reply related [flat|nested] 5+ messages in thread
* [RFC PATCH 2/2] software node: Add documentation 2019-10-02 12:33 [RFC PATCH 0/2] software node: API documentation Heikki Krogerus 2019-10-02 12:33 ` [RFC PATCH 1/2] software node: Add missing kernel-doc function descriptions Heikki Krogerus @ 2019-10-02 12:33 ` Heikki Krogerus 2019-10-04 2:56 ` Randy Dunlap 1 sibling, 1 reply; 5+ messages in thread From: Heikki Krogerus @ 2019-10-02 12:33 UTC (permalink / raw) To: Laurent Pinchart Cc: Dmitry Torokhov, Andy Shevchenko, Rafael J. Wysocki, Mika Westerberg, linux-doc, linux-kernel API documentation for the software nodes. Signed-off-by: Heikki Krogerus <heikki.krogerus@linux.intel.com> --- Documentation/driver-api/software_node.rst | 197 +++++++++++++++++++++ 1 file changed, 197 insertions(+) create mode 100644 Documentation/driver-api/software_node.rst diff --git a/Documentation/driver-api/software_node.rst b/Documentation/driver-api/software_node.rst new file mode 100644 index 000000000000..cf8a05c34e9e --- /dev/null +++ b/Documentation/driver-api/software_node.rst @@ -0,0 +1,197 @@ + +.. _software_node: + +============== +Software nodes +============== + +Introduction +============ + +Software node is a :c:type:`struct fwnode_handle <fwnode_handle>` type, +analogous to the ACPI and DT firmware nodes except that the software nodes are +created in kernel code (hence the name "software" node). The software nodes can +be used to complement fwnodes representing real firmware nodes when they are +incomplete, for example missing device properties, and to supply the primary +fwnode when the firmware lacks hardware description for a device completely. + +NOTE! The primary hardware description should always come from either ACPI +tables or DT. Describing an entire system with software nodes, though possible, +is not acceptable! The software nodes should only complement the primary +hardware description. + +Hierarchy +========= + +The software nodes support hierarchy (i.e. the software nodes can have child +software nodes and a parent software node) just like ACPI and DT firmware nodes, +but there is no dedicated root software node object. It means that a software +node at the root level does not have a parent. + +Note! Only other software nodes can be children and the parent for a software +node. + +Device properties +================= + +The software node device properties are described with :c:type:`struct +property_entry <property_entry>`. When a software node is created that has +device properties, it is supplied with a zero terminated array of property +entries. Normally the properties are described with helper macros:: + + static const u8 u8_array[] = { 0, 1, 2, 3 }; + static const u16 u16_array[] = { 0, 1, 2, 3 }; + static const u32 u32_array[] = { 0, 1, 2, 3 }; + static const u64 u64_array[] = { 0, 1, 2, 3 }; + + static const struct property_entry my_props[] = { + PROPERTY_ENTRY_U8_ARRAY("u8_array_example", u8_array), + PROPERTY_ENTRY_U16_ARRAY("u16_array_example", u16_array), + PROPERTY_ENTRY_U32_ARRAY("u32_array_example", u32_array), + PROPERTY_ENTRY_U64_ARRAY("u64_array_example", u64_array), + PROPERTY_ENTRY_U8("u8_example", 0xff), + PROPERTY_ENTRY_U16("u16_example", 0xffff), + PROPERTY_ENTRY_U32("u32_example", 0xffffffff), + PROPERTY_ENTRY_U64("u64_example", 0xffffffffffffffff), + PROPERTY_ENTRY_STRING("string_example", "string"), + { } + }; + +Note! If "build-in" device properties are supplied to already existing device +entries by using :c:func:`device_add_properties`, a software node is actually +created for that device. That software node is just assigned to the device +automatically in the function. + +Usage +===== + +Node creation +------------- + +Static nodes +~~~~~~~~~~~~ + +In a normal case the software nodes are described statically with +:c:type:`struct software_node <software_node>`, and then registered with +:c:func:`software_node_register`. Usually there is more then one software node +that needs to be registered. A helper :c:func:`software_node_register_nodes` +registers a zero terminated array of software nodes:: + + static const struct property_entry props[] = { + PROPERTY_ENTRY_STRING("foo", "bar"), + { } + }; + + static const struct software_node my_nodes[] = { + { "grandparent" }, /* no parent nor properties */ + { "parent", &my_nodes[0] }, /* parent, but no propreties */ + { "child", &my_nodes[1], props }, /* parent and properties */ + { } + }; + + static int my_init(void) + { + return software_node_register_nodes(my_nodes); + } + +Note! The above example names the nodes "grandparent", "parent" and "child", but +the software nodes don't actually have to be named. If no name is supplied for a +software node when it's being registered, the API names the node "node<n>" where +<n> is index number. + +Dynamic nodes +~~~~~~~~~~~~~ + +The Quick (and dirty) method. A software node can be created on the fly with +:c:func:`fwnode_create_software_node`. The nodes create "on-the-fly" don't +differ from statically described software nodes in any way, but for now the API +does not support naming of these nodes:: + + static const struct property_entry my_props[] = { + PROPERTY_ENTRY_STRING("foo", "bar"), + { } + }; + + static int my_init(void) + { + struct fwnode_handle *fwnode; + + /* Software node without a parent. */ + fwnode = fwnode_create_software_node(my_props, NULL); + if (IS_ERR(fwnode)) + return PTR_ERR(fwnode); + + return -1; + } + +Linking software nodes with the device (struct device) entries +-------------------------------------------------------------- + +Ideally the software node should be assigned to the device entry before the +device is registered (just like any other fwnode). + +When the software node is the primary fwnode for the device, the fwnode of the +device needs to simply point to the software node fwnode. Using a helper +:c:func:`software_node_fwnode` in the following example:: + + static const struct software_node my_node = { + .name = "thenode", + }; + + static int my_init(void) + { + struct device my_device = { }; + int ret; + + ret = software_node_register(my_node); + if (ret) + return ret; + + device_initialize(&my_device); + dev_set_name(&my_device, "thedevice") + + my_device.fwnode = software_node_fwnode(swnode); + + return device_add(&my_device); + } + +When the software node is the secondary fwnode for a device, i.e. the device has +either ACPI or DT (or something else) firmware node as the primary fwnode, the +node should be assigned with :c:func:`set_secondary_fwnode`. If the +``secondary`` member of the primary fwnode needs to be manually made to point +to the software node, the code needs to make sure that the ``secondary`` member +of the software node fwnode points to a specific value of ``ERR_PTR(-ENODEV)``:: + + struct fwnode_handle *fwnode = software_node_fwnode(swnode); + + fwnode->secondary = ERR_PTR(-ENODEV); + dev->fwnode->secondary = fwnode; + +Note! There is no requirement to bind a software node with a device entry, i.e. +having "sub-nodes" that represent for example certain resources the parent +software node has is not a problem. + +Node References +--------------- + +TODO + +Device graph +------------ + +TODO + +API +=== + +.. kernel-doc:: include/linux/property.h + :internal: software_node + +.. kernel-doc:: include/linux/fwnode.h + :internal: fwnode_handle + +.. kernel-doc:: drivers/base/core.c + :functions: set_secondary_fwnode + +.. kernel-doc:: drivers/base/swnode.c + :functions: is_software_node is_software_node software_node_fwnode software_node_find_by_name software_node_register_nodes software_node_unregister_nodes software_node_register software_node_register fwnode_create_software_node fwnode_remove_software_node -- 2.23.0 ^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [RFC PATCH 2/2] software node: Add documentation 2019-10-02 12:33 ` [RFC PATCH 2/2] software node: Add documentation Heikki Krogerus @ 2019-10-04 2:56 ` Randy Dunlap 2019-10-04 8:54 ` Heikki Krogerus 0 siblings, 1 reply; 5+ messages in thread From: Randy Dunlap @ 2019-10-04 2:56 UTC (permalink / raw) To: Heikki Krogerus, Laurent Pinchart Cc: Dmitry Torokhov, Andy Shevchenko, Rafael J. Wysocki, Mika Westerberg, linux-doc, linux-kernel Hi, Below are a few doc edits for you. On 10/2/19 5:33 AM, Heikki Krogerus wrote: > API documentation for the software nodes. > > Signed-off-by: Heikki Krogerus <heikki.krogerus@linux.intel.com> > --- > Documentation/driver-api/software_node.rst | 197 +++++++++++++++++++++ > 1 file changed, 197 insertions(+) > create mode 100644 Documentation/driver-api/software_node.rst > > diff --git a/Documentation/driver-api/software_node.rst b/Documentation/driver-api/software_node.rst > new file mode 100644 > index 000000000000..cf8a05c34e9e > --- /dev/null > +++ b/Documentation/driver-api/software_node.rst > @@ -0,0 +1,197 @@ > + > +.. _software_node: > + > +============== > +Software nodes > +============== > + > +Introduction > +============ > + > +Software node is a :c:type:`struct fwnode_handle <fwnode_handle>` type, > +analogous to the ACPI and DT firmware nodes except that the software nodes are > +created in kernel code (hence the name "software" node). The software nodes can > +be used to complement fwnodes representing real firmware nodes when they are > +incomplete, for example missing device properties, and to supply the primary > +fwnode when the firmware lacks hardware description for a device completely. > + > +NOTE! The primary hardware description should always come from either ACPI > +tables or DT. Describing an entire system with software nodes, though possible, > +is not acceptable! The software nodes should only complement the primary > +hardware description. > + > +Hierarchy > +========= > + > +The software nodes support hierarchy (i.e. the software nodes can have child I would s/child/children/ > +software nodes and a parent software node) just like ACPI and DT firmware nodes, > +but there is no dedicated root software node object. It means that a software > +node at the root level does not have a parent. > + > +Note! Only other software nodes can be children and the parent for a software > +node. > + > +Device properties > +================= > + > +The software node device properties are described with :c:type:`struct > +property_entry <property_entry>`. When a software node is created that has > +device properties, it is supplied with a zero terminated array of property > +entries. Normally the properties are described with helper macros:: > + > + static const u8 u8_array[] = { 0, 1, 2, 3 }; > + static const u16 u16_array[] = { 0, 1, 2, 3 }; > + static const u32 u32_array[] = { 0, 1, 2, 3 }; > + static const u64 u64_array[] = { 0, 1, 2, 3 }; > + > + static const struct property_entry my_props[] = { > + PROPERTY_ENTRY_U8_ARRAY("u8_array_example", u8_array), > + PROPERTY_ENTRY_U16_ARRAY("u16_array_example", u16_array), > + PROPERTY_ENTRY_U32_ARRAY("u32_array_example", u32_array), > + PROPERTY_ENTRY_U64_ARRAY("u64_array_example", u64_array), > + PROPERTY_ENTRY_U8("u8_example", 0xff), > + PROPERTY_ENTRY_U16("u16_example", 0xffff), > + PROPERTY_ENTRY_U32("u32_example", 0xffffffff), > + PROPERTY_ENTRY_U64("u64_example", 0xffffffffffffffff), > + PROPERTY_ENTRY_STRING("string_example", "string"), > + { } > + }; > + > +Note! If "build-in" device properties are supplied to already existing device "built-in" > +entries by using :c:func:`device_add_properties`, a software node is actually > +created for that device. That software node is just assigned to the device > +automatically in the function. > + > +Usage > +===== > + > +Node creation > +------------- > + > +Static nodes > +~~~~~~~~~~~~ > + > +In a normal case the software nodes are described statically with > +:c:type:`struct software_node <software_node>`, and then registered with > +:c:func:`software_node_register`. Usually there is more then one software node than > +that needs to be registered. A helper :c:func:`software_node_register_nodes` > +registers a zero terminated array of software nodes:: > + > + static const struct property_entry props[] = { > + PROPERTY_ENTRY_STRING("foo", "bar"), > + { } > + }; > + > + static const struct software_node my_nodes[] = { > + { "grandparent" }, /* no parent nor properties */ > + { "parent", &my_nodes[0] }, /* parent, but no propreties */ properties > + { "child", &my_nodes[1], props }, /* parent and properties */ > + { } > + }; > + > + static int my_init(void) > + { > + return software_node_register_nodes(my_nodes); > + } > + > +Note! The above example names the nodes "grandparent", "parent" and "child", but > +the software nodes don't actually have to be named. If no name is supplied for a > +software node when it's being registered, the API names the node "node<n>" where > +<n> is index number. > + > +Dynamic nodes > +~~~~~~~~~~~~~ > + > +The Quick (and dirty) method. A software node can be created on the fly with > +:c:func:`fwnode_create_software_node`. The nodes create "on-the-fly" don't created > +differ from statically described software nodes in any way, but for now the API > +does not support naming of these nodes:: > + > + static const struct property_entry my_props[] = { > + PROPERTY_ENTRY_STRING("foo", "bar"), > + { } > + }; > + > + static int my_init(void) > + { > + struct fwnode_handle *fwnode; > + > + /* Software node without a parent. */ > + fwnode = fwnode_create_software_node(my_props, NULL); > + if (IS_ERR(fwnode)) > + return PTR_ERR(fwnode); > + > + return -1; > + } > + > +Linking software nodes with the device (struct device) entries > +-------------------------------------------------------------- > + > +Ideally the software node should be assigned to the device entry before the > +device is registered (just like any other fwnode). > + > +When the software node is the primary fwnode for the device, the fwnode of the > +device needs to simply point to the software node fwnode. Using a helper > +:c:func:`software_node_fwnode` in the following example:: > + > + static const struct software_node my_node = { > + .name = "thenode", > + }; > + > + static int my_init(void) > + { > + struct device my_device = { }; > + int ret; > + > + ret = software_node_register(my_node); > + if (ret) > + return ret; > + > + device_initialize(&my_device); > + dev_set_name(&my_device, "thedevice") > + > + my_device.fwnode = software_node_fwnode(swnode); > + > + return device_add(&my_device); > + } > + > +When the software node is the secondary fwnode for a device, i.e. the device has > +either ACPI or DT (or something else) firmware node as the primary fwnode, the > +node should be assigned with :c:func:`set_secondary_fwnode`. If the > +``secondary`` member of the primary fwnode needs to be manually made to point > +to the software node, the code needs to make sure that the ``secondary`` member > +of the software node fwnode points to a specific value of ``ERR_PTR(-ENODEV)``:: > + > + struct fwnode_handle *fwnode = software_node_fwnode(swnode); > + > + fwnode->secondary = ERR_PTR(-ENODEV); > + dev->fwnode->secondary = fwnode; > + > +Note! There is no requirement to bind a software node with a device entry, i.e. > +having "sub-nodes" that represent for example certain resources the parent > +software node has is not a problem. > + > +Node References > +--------------- > + > +TODO > + > +Device graph > +------------ > + > +TODO > + > +API > +=== > + > +.. kernel-doc:: include/linux/property.h > + :internal: software_node > + > +.. kernel-doc:: include/linux/fwnode.h > + :internal: fwnode_handle > + > +.. kernel-doc:: drivers/base/core.c > + :functions: set_secondary_fwnode > + > +.. kernel-doc:: drivers/base/swnode.c > + :functions: is_software_node is_software_node software_node_fwnode software_node_find_by_name software_node_register_nodes software_node_unregister_nodes software_node_register software_node_register fwnode_create_software_node fwnode_remove_software_node > Thanks for the doc. -- ~Randy ^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [RFC PATCH 2/2] software node: Add documentation 2019-10-04 2:56 ` Randy Dunlap @ 2019-10-04 8:54 ` Heikki Krogerus 0 siblings, 0 replies; 5+ messages in thread From: Heikki Krogerus @ 2019-10-04 8:54 UTC (permalink / raw) To: Randy Dunlap Cc: Laurent Pinchart, Dmitry Torokhov, Andy Shevchenko, Rafael J. Wysocki, Mika Westerberg, linux-doc, linux-kernel On Thu, Oct 03, 2019 at 07:56:59PM -0700, Randy Dunlap wrote: > Hi, > Below are a few doc edits for you. Thank you for the review! I'll fix the v2 according to your comments. thanks, -- heikki ^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2019-10-04 8:54 UTC | newest] Thread overview: 5+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2019-10-02 12:33 [RFC PATCH 0/2] software node: API documentation Heikki Krogerus 2019-10-02 12:33 ` [RFC PATCH 1/2] software node: Add missing kernel-doc function descriptions Heikki Krogerus 2019-10-02 12:33 ` [RFC PATCH 2/2] software node: Add documentation Heikki Krogerus 2019-10-04 2:56 ` Randy Dunlap 2019-10-04 8:54 ` Heikki Krogerus
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox