aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/base/core.c51
-rw-r--r--include/linux/acpi.h4
-rw-r--r--include/linux/device.h3
-rw-r--r--include/linux/fwnode.h1
4 files changed, 57 insertions, 2 deletions
diff --git a/drivers/base/core.c b/drivers/base/core.c
index 07304a3b9ee2..c7e2a9a70865 100644
--- a/drivers/base/core.c
+++ b/drivers/base/core.c
@@ -12,6 +12,7 @@
12 12
13#include <linux/device.h> 13#include <linux/device.h>
14#include <linux/err.h> 14#include <linux/err.h>
15#include <linux/fwnode.h>
15#include <linux/init.h> 16#include <linux/init.h>
16#include <linux/module.h> 17#include <linux/module.h>
17#include <linux/slab.h> 18#include <linux/slab.h>
@@ -2133,3 +2134,53 @@ define_dev_printk_level(dev_notice, KERN_NOTICE);
2133define_dev_printk_level(_dev_info, KERN_INFO); 2134define_dev_printk_level(_dev_info, KERN_INFO);
2134 2135
2135#endif 2136#endif
2137
2138static inline bool fwnode_is_primary(struct fwnode_handle *fwnode)
2139{
2140 return fwnode && !IS_ERR(fwnode->secondary);
2141}
2142
2143/**
2144 * set_primary_fwnode - Change the primary firmware node of a given device.
2145 * @dev: Device to handle.
2146 * @fwnode: New primary firmware node of the device.
2147 *
2148 * Set the device's firmware node pointer to @fwnode, but if a secondary
2149 * firmware node of the device is present, preserve it.
2150 */
2151void set_primary_fwnode(struct device *dev, struct fwnode_handle *fwnode)
2152{
2153 if (fwnode) {
2154 struct fwnode_handle *fn = dev->fwnode;
2155
2156 if (fwnode_is_primary(fn))
2157 fn = fn->secondary;
2158
2159 fwnode->secondary = fn;
2160 dev->fwnode = fwnode;
2161 } else {
2162 dev->fwnode = fwnode_is_primary(dev->fwnode) ?
2163 dev->fwnode->secondary : NULL;
2164 }
2165}
2166EXPORT_SYMBOL_GPL(set_primary_fwnode);
2167
2168/**
2169 * set_secondary_fwnode - Change the secondary firmware node of a given device.
2170 * @dev: Device to handle.
2171 * @fwnode: New secondary firmware node of the device.
2172 *
2173 * If a primary firmware node of the device is present, set its secondary
2174 * pointer to @fwnode. Otherwise, set the device's firmware node pointer to
2175 * @fwnode.
2176 */
2177void set_secondary_fwnode(struct device *dev, struct fwnode_handle *fwnode)
2178{
2179 if (fwnode)
2180 fwnode->secondary = ERR_PTR(-ENODEV);
2181
2182 if (fwnode_is_primary(dev->fwnode))
2183 dev->fwnode->secondary = fwnode;
2184 else
2185 dev->fwnode = fwnode;
2186}
diff --git a/include/linux/acpi.h b/include/linux/acpi.h
index ec488d03b518..dd12127f171c 100644
--- a/include/linux/acpi.h
+++ b/include/linux/acpi.h
@@ -54,8 +54,8 @@ static inline acpi_handle acpi_device_handle(struct acpi_device *adev)
54} 54}
55 55
56#define ACPI_COMPANION(dev) acpi_node((dev)->fwnode) 56#define ACPI_COMPANION(dev) acpi_node((dev)->fwnode)
57#define ACPI_COMPANION_SET(dev, adev) (dev)->fwnode = (adev) ? \ 57#define ACPI_COMPANION_SET(dev, adev) set_primary_fwnode(dev, (adev) ? \
58 acpi_fwnode_handle(adev) : NULL 58 acpi_fwnode_handle(adev) : NULL)
59#define ACPI_HANDLE(dev) acpi_device_handle(ACPI_COMPANION(dev)) 59#define ACPI_HANDLE(dev) acpi_device_handle(ACPI_COMPANION(dev))
60 60
61static inline bool has_acpi_companion(struct device *dev) 61static inline bool has_acpi_companion(struct device *dev)
diff --git a/include/linux/device.h b/include/linux/device.h
index badef20b876a..324d02add7b4 100644
--- a/include/linux/device.h
+++ b/include/linux/device.h
@@ -940,6 +940,9 @@ extern void unlock_device_hotplug(void);
940extern int lock_device_hotplug_sysfs(void); 940extern int lock_device_hotplug_sysfs(void);
941extern int device_offline(struct device *dev); 941extern int device_offline(struct device *dev);
942extern int device_online(struct device *dev); 942extern int device_online(struct device *dev);
943extern void set_primary_fwnode(struct device *dev, struct fwnode_handle *fwnode);
944extern void set_secondary_fwnode(struct device *dev, struct fwnode_handle *fwnode);
945
943/* 946/*
944 * Root device objects for grouping under /sys/devices 947 * Root device objects for grouping under /sys/devices
945 */ 948 */
diff --git a/include/linux/fwnode.h b/include/linux/fwnode.h
index 17bb5f039509..fc30b84b532a 100644
--- a/include/linux/fwnode.h
+++ b/include/linux/fwnode.h
@@ -20,6 +20,7 @@ enum fwnode_type {
20 20
21struct fwnode_handle { 21struct fwnode_handle {
22 enum fwnode_type type; 22 enum fwnode_type type;
23 struct fwnode_handle *secondary;
23}; 24};
24 25
25#endif 26#endif