Commit e68d0119 authored by Heikki Krogerus's avatar Heikki Krogerus Committed by Greg Kroah-Hartman
Browse files

software node: Introduce device_add_software_node()



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: default avatarFelipe Balbi <balbi@kernel.org>
Signed-off-by: default avatarHeikki Krogerus <heikki.krogerus@linux.intel.com>
Link: https://lore.kernel.org/r/20210115094914.88401-2-heikki.krogerus@linux.intel.com


Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent c86cad04
Loading
Loading
Loading
Loading
+62 −9
Original line number Diff line number Diff line
@@ -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)
{
@@ -843,21 +856,61 @@ void fwnode_remove_software_node(struct fwnode_handle *fwnode)
}
EXPORT_SYMBOL_GPL(fwnode_remove_software_node);

int software_node_notify(struct device *dev, unsigned long action)
/**
 * 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)
{
	struct fwnode_handle *fwnode = dev_fwnode(dev);
	struct swnode *swnode;
	int ret;

	if (!fwnode)
		return 0;
	/* 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));

	if (!is_software_node(fwnode))
		fwnode = fwnode->secondary;
	if (!is_software_node(fwnode))
	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 = to_swnode(fwnode);
	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 swnode *swnode;
	int ret;

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

	switch (action) {
	case KOBJ_ADD:
+3 −0
Original line number Diff line number Diff line
@@ -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_ */