Skip to content

Commit

Permalink
software node: Introduce device_add_software_node()
Browse files Browse the repository at this point in the history
This helper will register a software node and then assign
it to device at the same time. The function will also make
sure that the device can't have more than one software node.

Acked-by: Felipe Balbi <[email protected]>
Signed-off-by: Heikki Krogerus <[email protected]>
Link: https://lore.kernel.org/r/[email protected]
Signed-off-by: Greg Kroah-Hartman <[email protected]>
  • Loading branch information
Heikki Krogerus authored and gregkh committed Jan 15, 2021
1 parent c86cad0 commit e68d011
Show file tree
Hide file tree
Showing 2 changed files with 65 additions and 9 deletions.
71 changes: 62 additions & 9 deletions drivers/base/swnode.c
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,19 @@ EXPORT_SYMBOL_GPL(is_software_node);
struct swnode, fwnode) : NULL; \
})

static inline struct swnode *dev_to_swnode(struct device *dev)
{
struct fwnode_handle *fwnode = dev_fwnode(dev);

if (!fwnode)
return NULL;

if (!is_software_node(fwnode))
fwnode = fwnode->secondary;

return to_swnode(fwnode);
}

static struct swnode *
software_node_to_swnode(const struct software_node *node)
{
Expand Down Expand Up @@ -843,22 +856,62 @@ void fwnode_remove_software_node(struct fwnode_handle *fwnode)
}
EXPORT_SYMBOL_GPL(fwnode_remove_software_node);

/**
* device_add_software_node - Assign software node to a device
* @dev: The device the software node is meant for.
* @swnode: The software node.
*
* This function will register @swnode and make it the secondary firmware node
* pointer of @dev. If @dev has no primary node, then @swnode will become the primary
* node.
*/
int device_add_software_node(struct device *dev, const struct software_node *swnode)
{
int ret;

/* Only one software node per device. */
if (dev_to_swnode(dev))
return -EBUSY;

ret = software_node_register(swnode);
if (ret)
return ret;

set_secondary_fwnode(dev, software_node_fwnode(swnode));

return 0;
}
EXPORT_SYMBOL_GPL(device_add_software_node);

/**
* device_remove_software_node - Remove device's software node
* @dev: The device with the software node.
*
* This function will unregister the software node of @dev.
*/
void device_remove_software_node(struct device *dev)
{
struct swnode *swnode;

swnode = dev_to_swnode(dev);
if (!swnode)
return;

software_node_notify(dev, KOBJ_REMOVE);
set_secondary_fwnode(dev, NULL);
kobject_put(&swnode->kobj);
}
EXPORT_SYMBOL_GPL(device_remove_software_node);

int software_node_notify(struct device *dev, unsigned long action)
{
struct fwnode_handle *fwnode = dev_fwnode(dev);
struct swnode *swnode;
int ret;

if (!fwnode)
return 0;

if (!is_software_node(fwnode))
fwnode = fwnode->secondary;
if (!is_software_node(fwnode))
swnode = dev_to_swnode(dev);
if (!swnode)
return 0;

swnode = to_swnode(fwnode);

switch (action) {
case KOBJ_ADD:
ret = sysfs_create_link(&dev->kobj, &swnode->kobj,
Expand Down
3 changes: 3 additions & 0 deletions include/linux/property.h
Original file line number Diff line number Diff line change
Expand Up @@ -488,4 +488,7 @@ fwnode_create_software_node(const struct property_entry *properties,
const struct fwnode_handle *parent);
void fwnode_remove_software_node(struct fwnode_handle *fwnode);

int device_add_software_node(struct device *dev, const struct software_node *swnode);
void device_remove_software_node(struct device *dev);

#endif /* _LINUX_PROPERTY_H_ */

0 comments on commit e68d011

Please sign in to comment.