summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/base/Kconfig9
-rw-r--r--drivers/base/auxiliary.c6
-rw-r--r--drivers/base/base.h98
-rw-r--r--drivers/base/core.c29
-rw-r--r--drivers/base/dd.c52
-rw-r--r--drivers/base/devres.c277
-rw-r--r--drivers/base/init.c1
-rw-r--r--drivers/base/memory.c2
-rw-r--r--drivers/base/platform.c58
-rw-r--r--drivers/base/property.c14
-rw-r--r--drivers/base/soc.c23
-rw-r--r--drivers/base/swnode.c13
-rw-r--r--drivers/bus/fsl-mc/fsl-mc-bus.c43
-rw-r--r--drivers/bus/imx-weim.c2
-rw-r--r--drivers/i2c/i2c-core-of.c2
-rw-r--r--drivers/net/phy/mdio_bus_provider.c4
-rw-r--r--drivers/of/base.c30
-rw-r--r--drivers/of/dynamic.c2
-rw-r--r--drivers/of/platform.c2
-rw-r--r--drivers/pci/pci-driver.c11
-rw-r--r--drivers/pci/pci-sysfs.c28
-rw-r--r--drivers/pci/probe.c1
-rw-r--r--drivers/platform/wmi/core.c36
-rw-r--r--drivers/s390/cio/cio.h5
-rw-r--r--drivers/s390/cio/css.c34
-rw-r--r--drivers/s390/crypto/ap_bus.c34
-rw-r--r--drivers/s390/crypto/ap_bus.h1
-rw-r--r--drivers/s390/crypto/ap_queue.c24
-rw-r--r--drivers/soc/fsl/guts.c12
-rw-r--r--drivers/soc/imx/soc-imx8m.c11
-rw-r--r--drivers/soc/imx/soc-imx9.c4
-rw-r--r--drivers/soc/sunxi/sunxi_mbus.c2
-rw-r--r--drivers/soundwire/debugfs.c9
-rw-r--r--drivers/spi/spi.c2
-rw-r--r--drivers/vdpa/vdpa.c48
-rw-r--r--drivers/vfio/fsl-mc/vfio_fsl_mc.c4
-rw-r--r--drivers/vfio/pci/vfio_pci_core.c5
-rw-r--r--drivers/xen/xen-pciback/pci_stub.c6
38 files changed, 451 insertions, 493 deletions
diff --git a/drivers/base/Kconfig b/drivers/base/Kconfig
index 1786d87b29e2..f7d385cbd3ba 100644
--- a/drivers/base/Kconfig
+++ b/drivers/base/Kconfig
@@ -73,6 +73,15 @@ config DEVTMPFS_SAFE
with the PROT_EXEC flag. This can break, for example, non-KMS
video drivers.
+config DRIVER_DEFERRED_PROBE_TIMEOUT
+ int "Default value for deferred_probe_timeout"
+ default 0 if !MODULES
+ default 10 if MODULES
+ help
+ Set the default value for the deferred_probe_timeout kernel parameter.
+ See Documentation/admin-guide/kernel-parameters.txt for a description
+ of the deferred_probe_timeout kernel parameter.
+
config STANDALONE
bool "Select only drivers that don't need compile-time external firmware"
default y
diff --git a/drivers/base/auxiliary.c b/drivers/base/auxiliary.c
index 9fd3820d1f8a..16b8bdab30c8 100644
--- a/drivers/base/auxiliary.c
+++ b/drivers/base/auxiliary.c
@@ -207,11 +207,6 @@ static int auxiliary_uevent(const struct device *dev, struct kobj_uevent_env *en
(int)(p - name), name);
}
-static const struct dev_pm_ops auxiliary_dev_pm_ops = {
- SET_RUNTIME_PM_OPS(pm_generic_runtime_suspend, pm_generic_runtime_resume, NULL)
- SET_SYSTEM_SLEEP_PM_OPS(pm_generic_suspend, pm_generic_resume)
-};
-
static int auxiliary_bus_probe(struct device *dev)
{
const struct auxiliary_driver *auxdrv = to_auxiliary_drv(dev->driver);
@@ -258,7 +253,6 @@ static const struct bus_type auxiliary_bus_type = {
.shutdown = auxiliary_bus_shutdown,
.match = auxiliary_match,
.uevent = auxiliary_uevent,
- .pm = &auxiliary_dev_pm_ops,
};
/**
diff --git a/drivers/base/base.h b/drivers/base/base.h
index 1af95ac68b77..30b416588617 100644
--- a/drivers/base/base.h
+++ b/drivers/base/base.h
@@ -13,27 +13,28 @@
#include <linux/notifier.h>
/**
- * struct subsys_private - structure to hold the private to the driver core portions of the bus_type/class structure.
- *
- * @subsys - the struct kset that defines this subsystem
- * @devices_kset - the subsystem's 'devices' directory
- * @interfaces - list of subsystem interfaces associated
- * @mutex - protect the devices, and interfaces lists.
- *
- * @drivers_kset - the list of drivers associated
- * @klist_devices - the klist to iterate over the @devices_kset
- * @klist_drivers - the klist to iterate over the @drivers_kset
- * @bus_notifier - the bus notifier list for anything that cares about things
- * on this bus.
- * @bus - pointer back to the struct bus_type that this structure is associated
- * with.
+ * struct subsys_private - structure to hold the private to the driver core
+ * portions of the bus_type/class structure.
+ * @subsys: the struct kset that defines this subsystem
+ * @devices_kset: the subsystem's 'devices' directory
+ * @interfaces: list of subsystem interfaces associated
+ * @mutex: protect the devices, and interfaces lists.
+ * @drivers_kset: the list of drivers associated
+ * @klist_devices: the klist to iterate over the @devices_kset
+ * @klist_drivers: the klist to iterate over the @drivers_kset
+ * @bus_notifier: the bus notifier list for anything that cares about things
+ * on this bus.
+ * @drivers_autoprobe: gate whether new devices are automatically attached to
+ * registered drivers, or new drivers automatically attach
+ * to existing devices.
+ * @bus: pointer back to the struct bus_type that this structure is associated
+ * with.
* @dev_root: Default device to use as the parent.
- *
- * @glue_dirs - "glue" directory to put in-between the parent device to
- * avoid namespace conflicts
- * @class - pointer back to the struct class that this structure is associated
- * with.
- * @lock_key: Lock class key for use by the lock validator
+ * @glue_dirs: "glue" directory to put in-between the parent device to
+ * avoid namespace conflicts
+ * @class: pointer back to the struct class that this structure is associated
+ * with.
+ * @lock_key: Lock class key for use by the lock validator
*
* This structure is the one that is the actual kobject allowing struct
* bus_type/class to be statically allocated safely. Nothing outside of the
@@ -98,24 +99,26 @@ struct driver_type {
#endif
/**
- * struct device_private - structure to hold the private to the driver core portions of the device structure.
- *
- * @klist_children - klist containing all children of this device
- * @knode_parent - node in sibling list
- * @knode_driver - node in driver list
- * @knode_bus - node in bus list
- * @knode_class - node in class list
- * @deferred_probe - entry in deferred_probe_list which is used to retry the
- * binding of drivers which were unable to get all the resources needed by
- * the device; typically because it depends on another driver getting
- * probed first.
- * @async_driver - pointer to device driver awaiting probe via async_probe
- * @device - pointer back to the struct device that this structure is
- * associated with.
- * @driver_type - The type of the bound Rust driver.
- * @dead - This device is currently either in the process of or has been
- * removed from the system. Any asynchronous events scheduled for this
- * device should exit without taking any action.
+ * struct device_private - structure to hold the private to the driver core
+ * portions of the device structure.
+ * @klist_children: klist containing all children of this device
+ * @knode_parent: node in sibling list
+ * @knode_driver: node in driver list
+ * @knode_bus: node in bus list
+ * @knode_class: node in class list
+ * @deferred_probe: entry in deferred_probe_list which is used to retry the
+ * binding of drivers which were unable to get all the
+ * resources needed by the device; typically because it depends
+ * on another driver getting probed first.
+ * @async_driver: pointer to device driver awaiting probe via async_probe
+ * @deferred_probe_reason: capture the -EPROBE_DEFER message emitted with
+ * dev_err_probe() for later retrieval via debugfs
+ * @device: pointer back to the struct device that this structure is
+ * associated with.
+ * @driver_type: The type of the bound Rust driver.
+ * @dead: This device is currently either in the process of or has been
+ * removed from the system. Any asynchronous events scheduled for this
+ * device should exit without taking any action.
*
* Nothing outside of the driver core should ever touch these fields.
*/
@@ -213,6 +216,24 @@ static inline void device_set_driver(struct device *dev, const struct device_dri
WRITE_ONCE(dev->driver, (struct device_driver *)drv);
}
+struct devres_node;
+typedef void (*dr_node_release_t)(struct device *dev, struct devres_node *node);
+typedef void (*dr_node_free_t)(struct devres_node *node);
+
+struct devres_node {
+ struct list_head entry;
+ dr_node_release_t release;
+ dr_node_free_t free_node;
+ const char *name;
+ size_t size;
+};
+
+void devres_node_init(struct devres_node *node, dr_node_release_t release,
+ dr_node_free_t free_node);
+void devres_node_add(struct device *dev, struct devres_node *node);
+bool devres_node_remove(struct device *dev, struct devres_node *node);
+void devres_set_node_dbginfo(struct devres_node *node, const char *name,
+ size_t size);
void devres_for_each_res(struct device *dev, dr_release_t release,
dr_match_t match, void *match_data,
void (*fn)(struct device *, void *, void *),
@@ -291,6 +312,7 @@ static inline int devtmpfs_create_node(struct device *dev) { return 0; }
static inline int devtmpfs_delete_node(struct device *dev) { return 0; }
#endif
+void software_node_init(void);
void software_node_notify(struct device *dev);
void software_node_notify_remove(struct device *dev);
diff --git a/drivers/base/core.c b/drivers/base/core.c
index 0613de0fbe44..673d709fa7e6 100644
--- a/drivers/base/core.c
+++ b/drivers/base/core.c
@@ -182,7 +182,7 @@ void fw_devlink_purge_absent_suppliers(struct fwnode_handle *fwnode)
if (fwnode->dev)
return;
- fwnode->flags |= FWNODE_FLAG_NOT_DEVICE;
+ fwnode_set_flag(fwnode, FWNODE_FLAG_NOT_DEVICE);
fwnode_links_purge_consumers(fwnode);
fwnode_for_each_available_child_node(fwnode, child)
@@ -228,7 +228,7 @@ static void __fw_devlink_pickup_dangling_consumers(struct fwnode_handle *fwnode,
if (fwnode->dev && fwnode->dev->bus)
return;
- fwnode->flags |= FWNODE_FLAG_NOT_DEVICE;
+ fwnode_set_flag(fwnode, FWNODE_FLAG_NOT_DEVICE);
__fwnode_links_move_consumers(fwnode, new_sup);
fwnode_for_each_available_child_node(fwnode, child)
@@ -1012,7 +1012,7 @@ static void device_links_missing_supplier(struct device *dev)
static bool dev_is_best_effort(struct device *dev)
{
return (fw_devlink_best_effort && dev->can_match) ||
- (dev->fwnode && (dev->fwnode->flags & FWNODE_FLAG_BEST_EFFORT));
+ (dev->fwnode && fwnode_test_flag(dev->fwnode, FWNODE_FLAG_BEST_EFFORT));
}
static struct fwnode_handle *fwnode_links_check_suppliers(
@@ -1723,11 +1723,11 @@ bool fw_devlink_is_strict(void)
static void fw_devlink_parse_fwnode(struct fwnode_handle *fwnode)
{
- if (fwnode->flags & FWNODE_FLAG_LINKS_ADDED)
+ if (fwnode_test_flag(fwnode, FWNODE_FLAG_LINKS_ADDED))
return;
fwnode_call_int_op(fwnode, add_links);
- fwnode->flags |= FWNODE_FLAG_LINKS_ADDED;
+ fwnode_set_flag(fwnode, FWNODE_FLAG_LINKS_ADDED);
}
static void fw_devlink_parse_fwtree(struct fwnode_handle *fwnode)
@@ -1885,7 +1885,7 @@ static bool fwnode_init_without_drv(struct fwnode_handle *fwnode)
struct device *dev;
bool ret;
- if (!(fwnode->flags & FWNODE_FLAG_INITIALIZED))
+ if (!fwnode_test_flag(fwnode, FWNODE_FLAG_INITIALIZED))
return false;
dev = get_dev_from_fwnode(fwnode);
@@ -2001,10 +2001,10 @@ static bool __fw_devlink_relax_cycles(struct fwnode_handle *con_handle,
* We aren't trying to find all cycles. Just a cycle between con and
* sup_handle.
*/
- if (sup_handle->flags & FWNODE_FLAG_VISITED)
+ if (fwnode_test_flag(sup_handle, FWNODE_FLAG_VISITED))
return false;
- sup_handle->flags |= FWNODE_FLAG_VISITED;
+ fwnode_set_flag(sup_handle, FWNODE_FLAG_VISITED);
/* Termination condition. */
if (sup_handle == con_handle) {
@@ -2074,7 +2074,7 @@ static bool __fw_devlink_relax_cycles(struct fwnode_handle *con_handle,
}
out:
- sup_handle->flags &= ~FWNODE_FLAG_VISITED;
+ fwnode_clear_flag(sup_handle, FWNODE_FLAG_VISITED);
put_device(sup_dev);
put_device(con_dev);
put_device(par_dev);
@@ -2127,7 +2127,7 @@ static int fw_devlink_create_devlink(struct device *con,
* When such a flag is set, we can't create device links where P is the
* supplier of C as that would delay the probe of C.
*/
- if (sup_handle->flags & FWNODE_FLAG_NEEDS_CHILD_BOUND_ON_ADD &&
+ if (fwnode_test_flag(sup_handle, FWNODE_FLAG_NEEDS_CHILD_BOUND_ON_ADD) &&
fwnode_is_ancestor_of(sup_handle, con->fwnode))
return -EINVAL;
@@ -2150,7 +2150,7 @@ static int fw_devlink_create_devlink(struct device *con,
else
flags = FW_DEVLINK_FLAGS_PERMISSIVE;
- if (sup_handle->flags & FWNODE_FLAG_NOT_DEVICE)
+ if (fwnode_test_flag(sup_handle, FWNODE_FLAG_NOT_DEVICE))
sup_dev = fwnode_get_next_parent_dev(sup_handle);
else
sup_dev = get_dev_from_fwnode(sup_handle);
@@ -2162,7 +2162,7 @@ static int fw_devlink_create_devlink(struct device *con,
* supplier device indefinitely.
*/
if (sup_dev->links.status == DL_DEV_NO_DRIVER &&
- sup_handle->flags & FWNODE_FLAG_INITIALIZED) {
+ fwnode_test_flag(sup_handle, FWNODE_FLAG_INITIALIZED)) {
dev_dbg(con,
"Not linking %pfwf - dev might never probe\n",
sup_handle);
@@ -2831,14 +2831,15 @@ static ssize_t removable_show(struct device *dev, struct device_attribute *attr,
}
static DEVICE_ATTR_RO(removable);
-int device_add_groups(struct device *dev, const struct attribute_group **groups)
+int device_add_groups(struct device *dev,
+ const struct attribute_group *const *groups)
{
return sysfs_create_groups(&dev->kobj, groups);
}
EXPORT_SYMBOL_GPL(device_add_groups);
void device_remove_groups(struct device *dev,
- const struct attribute_group **groups)
+ const struct attribute_group *const *groups)
{
sysfs_remove_groups(&dev->kobj, groups);
}
diff --git a/drivers/base/dd.c b/drivers/base/dd.c
index 37c7e54e0e4c..cb5046f0634d 100644
--- a/drivers/base/dd.c
+++ b/drivers/base/dd.c
@@ -257,11 +257,7 @@ static int deferred_devs_show(struct seq_file *s, void *data)
}
DEFINE_SHOW_ATTRIBUTE(deferred_devs);
-#ifdef CONFIG_MODULES
-static int driver_deferred_probe_timeout = 10;
-#else
-static int driver_deferred_probe_timeout;
-#endif
+static int driver_deferred_probe_timeout = CONFIG_DRIVER_DEFERRED_PROBE_TIMEOUT;
static int __init deferred_probe_timeout_setup(char *str)
{
@@ -383,8 +379,7 @@ __exitcall(deferred_probe_exit);
int __device_set_driver_override(struct device *dev, const char *s, size_t len)
{
- const char *new, *old;
- char *cp;
+ const char *new = NULL, *old;
if (!s)
return -EINVAL;
@@ -404,37 +399,30 @@ int __device_set_driver_override(struct device *dev, const char *s, size_t len)
*/
len = strlen(s);
- if (!len) {
- /* Empty string passed - clear override */
- spin_lock(&dev->driver_override.lock);
- old = dev->driver_override.name;
- dev->driver_override.name = NULL;
- spin_unlock(&dev->driver_override.lock);
- kfree(old);
+ /* Handle trailing newline */
+ if (len) {
+ char *cp;
- return 0;
+ cp = strnchr(s, len, '\n');
+ if (cp)
+ len = cp - s;
}
- cp = strnchr(s, len, '\n');
- if (cp)
- len = cp - s;
-
- new = kstrndup(s, len, GFP_KERNEL);
- if (!new)
- return -ENOMEM;
+ /*
+ * If empty string or "\n" passed, new remains NULL, clearing
+ * the driver_override.name.
+ */
+ if (len) {
+ new = kstrndup(s, len, GFP_KERNEL);
+ if (!new)
+ return -ENOMEM;
+ }
- spin_lock(&dev->driver_override.lock);
- old = dev->driver_override.name;
- if (cp != s) {
+ scoped_guard(spinlock, &dev->driver_override.lock) {
+ old = dev->driver_override.name;
dev->driver_override.name = new;
- spin_unlock(&dev->driver_override.lock);
- } else {
- /* "\n" passed - clear override */
- dev->driver_override.name = NULL;
- spin_unlock(&dev->driver_override.lock);
-
- kfree(new);
}
+
kfree(old);
return 0;
diff --git a/drivers/base/devres.c b/drivers/base/devres.c
index 171750c1f691..9d9842fc5a19 100644
--- a/drivers/base/devres.c
+++ b/drivers/base/devres.c
@@ -16,15 +16,9 @@
#include "base.h"
#include "trace.h"
-struct devres_node {
- struct list_head entry;
- dr_release_t release;
- const char *name;
- size_t size;
-};
-
struct devres {
struct devres_node node;
+ dr_release_t release;
/*
* Some archs want to perform DMA into kmalloc caches
* and need a guaranteed alignment larger than
@@ -42,7 +36,21 @@ struct devres_group {
/* -- 8 pointers */
};
-static void set_node_dbginfo(struct devres_node *node, const char *name,
+void devres_node_init(struct devres_node *node,
+ dr_node_release_t release,
+ dr_node_free_t free_node)
+{
+ INIT_LIST_HEAD(&node->entry);
+ node->release = release;
+ node->free_node = free_node;
+}
+
+static inline void free_node(struct devres_node *node)
+{
+ node->free_node(node);
+}
+
+void devres_set_node_dbginfo(struct devres_node *node, const char *name,
size_t size)
{
node->name = name;
@@ -75,12 +83,12 @@ static void devres_log(struct device *dev, struct devres_node *node,
* Release functions for devres group. These callbacks are used only
* for identification.
*/
-static void group_open_release(struct device *dev, void *res)
+static void group_open_release(struct device *dev, struct devres_node *node)
{
/* noop */
}
-static void group_close_release(struct device *dev, void *res)
+static void group_close_release(struct device *dev, struct devres_node *node)
{
/* noop */
}
@@ -107,6 +115,20 @@ static bool check_dr_size(size_t size, size_t *tot_size)
return true;
}
+static void dr_node_release(struct device *dev, struct devres_node *node)
+{
+ struct devres *dr = container_of(node, struct devres, node);
+
+ dr->release(dev, dr->data);
+}
+
+static void dr_node_free(struct devres_node *node)
+{
+ struct devres *dr = container_of(node, struct devres, node);
+
+ kfree(dr);
+}
+
static __always_inline struct devres *alloc_dr(dr_release_t release,
size_t size, gfp_t gfp, int nid)
{
@@ -124,8 +146,8 @@ static __always_inline struct devres *alloc_dr(dr_release_t release,
if (!(gfp & __GFP_ZERO))
memset(dr, 0, offsetof(struct devres, data));
- INIT_LIST_HEAD(&dr->node.entry);
- dr->node.release = release;
+ devres_node_init(&dr->node, dr_node_release, dr_node_free);
+ dr->release = release;
return dr;
}
@@ -167,7 +189,7 @@ void *__devres_alloc_node(dr_release_t release, size_t size, gfp_t gfp, int nid,
dr = alloc_dr(release, size, gfp | __GFP_ZERO, nid);
if (unlikely(!dr))
return NULL;
- set_node_dbginfo(&dr->node, name, size);
+ devres_set_node_dbginfo(&dr->node, name, size);
return dr->data;
}
EXPORT_SYMBOL_GPL(__devres_alloc_node);
@@ -194,26 +216,31 @@ void devres_for_each_res(struct device *dev, dr_release_t release,
{
struct devres_node *node;
struct devres_node *tmp;
- unsigned long flags;
if (!fn)
return;
- spin_lock_irqsave(&dev->devres_lock, flags);
+ guard(spinlock_irqsave)(&dev->devres_lock);
list_for_each_entry_safe_reverse(node, tmp,
&dev->devres_head, entry) {
struct devres *dr = container_of(node, struct devres, node);
- if (node->release != release)
+ if (node->release != dr_node_release)
+ continue;
+ if (dr->release != release)
continue;
if (match && !match(dev, dr->data, match_data))
continue;
fn(dev, dr->data, data);
}
- spin_unlock_irqrestore(&dev->devres_lock, flags);
}
EXPORT_SYMBOL_GPL(devres_for_each_res);
+static inline void free_dr(struct devres *dr)
+{
+ free_node(&dr->node);
+}
+
/**
* devres_free - Free device resource data
* @res: Pointer to devres data to free
@@ -226,11 +253,18 @@ void devres_free(void *res)
struct devres *dr = container_of(res, struct devres, data);
BUG_ON(!list_empty(&dr->node.entry));
- kfree(dr);
+ free_dr(dr);
}
}
EXPORT_SYMBOL_GPL(devres_free);
+void devres_node_add(struct device *dev, struct devres_node *node)
+{
+ guard(spinlock_irqsave)(&dev->devres_lock);
+
+ add_dr(dev, node);
+}
+
/**
* devres_add - Register device resource
* @dev: Device to add resource to
@@ -243,11 +277,8 @@ EXPORT_SYMBOL_GPL(devres_free);
void devres_add(struct device *dev, void *res)
{
struct devres *dr = container_of(res, struct devres, data);
- unsigned long flags;
- spin_lock_irqsave(&dev->devres_lock, flags);
- add_dr(dev, &dr->node);
- spin_unlock_irqrestore(&dev->devres_lock, flags);
+ devres_node_add(dev, &dr->node);
}
EXPORT_SYMBOL_GPL(devres_add);
@@ -259,7 +290,9 @@ static struct devres *find_dr(struct device *dev, dr_release_t release,
list_for_each_entry_reverse(node, &dev->devres_head, entry) {
struct devres *dr = container_of(node, struct devres, node);
- if (node->release != release)
+ if (node->release != dr_node_release)
+ continue;
+ if (dr->release != release)
continue;
if (match && !match(dev, dr->data, match_data))
continue;
@@ -287,14 +320,12 @@ void *devres_find(struct device *dev, dr_release_t release,
dr_match_t match, void *match_data)
{
struct devres *dr;
- unsigned long flags;
- spin_lock_irqsave(&dev->devres_lock, flags);
+ guard(spinlock_irqsave)(&dev->devres_lock);
dr = find_dr(dev, release, match, match_data);
- spin_unlock_irqrestore(&dev->devres_lock, flags);
-
if (dr)
return dr->data;
+
return NULL;
}
EXPORT_SYMBOL_GPL(devres_find);
@@ -321,7 +352,7 @@ void *devres_get(struct device *dev, void *new_res,
unsigned long flags;
spin_lock_irqsave(&dev->devres_lock, flags);
- dr = find_dr(dev, new_dr->node.release, match, match_data);
+ dr = find_dr(dev, new_dr->release, match, match_data);
if (!dr) {
add_dr(dev, &new_dr->node);
dr = new_dr;
@@ -334,6 +365,22 @@ void *devres_get(struct device *dev, void *new_res,
}
EXPORT_SYMBOL_GPL(devres_get);
+bool devres_node_remove(struct device *dev, struct devres_node *node)
+{
+ struct devres_node *__node;
+
+ guard(spinlock_irqsave)(&dev->devres_lock);
+ list_for_each_entry_reverse(__node, &dev->devres_head, entry) {
+ if (__node == node) {
+ list_del_init(&node->entry);
+ devres_log(dev, node, "REM");
+ return true;
+ }
+ }
+
+ return false;
+}
+
/**
* devres_remove - Find a device resource and remove it
* @dev: Device to find resource from
@@ -353,18 +400,15 @@ void *devres_remove(struct device *dev, dr_release_t release,
dr_match_t match, void *match_data)
{
struct devres *dr;
- unsigned long flags;
- spin_lock_irqsave(&dev->devres_lock, flags);
+ guard(spinlock_irqsave)(&dev->devres_lock);
dr = find_dr(dev, release, match, match_data);
if (dr) {
list_del_init(&dr->node.entry);
devres_log(dev, &dr->node, "REM");
+ return dr->data;
}
- spin_unlock_irqrestore(&dev->devres_lock, flags);
- if (dr)
- return dr->data;
return NULL;
}
EXPORT_SYMBOL_GPL(devres_remove);
@@ -495,15 +539,12 @@ static int remove_nodes(struct device *dev,
static void release_nodes(struct device *dev, struct list_head *todo)
{
- struct devres *dr, *tmp;
+ struct devres_node *node, *tmp;
- /* Release. Note that both devres and devres_group are
- * handled as devres in the following loop. This is safe.
- */
- list_for_each_entry_safe_reverse(dr, tmp, todo, node.entry) {
- devres_log(dev, &dr->node, "REL");
- dr->node.release(dev, dr->data);
- kfree(dr);
+ list_for_each_entry_safe_reverse(node, tmp, todo, entry) {
+ devres_log(dev, node, "REL");
+ node->release(dev, node);
+ free_node(node);
}
}
@@ -536,6 +577,13 @@ int devres_release_all(struct device *dev)
return cnt;
}
+static void devres_group_free(struct devres_node *node)
+{
+ struct devres_group *grp = container_of(node, struct devres_group, node[0]);
+
+ kfree(grp);
+}
+
/**
* devres_open_group - Open a new devres group
* @dev: Device to open devres group for
@@ -552,26 +600,21 @@ int devres_release_all(struct device *dev)
void *devres_open_group(struct device *dev, void *id, gfp_t gfp)
{
struct devres_group *grp;
- unsigned long flags;
grp = kmalloc_obj(*grp, gfp);
if (unlikely(!grp))
return NULL;
- grp->node[0].release = &group_open_release;
- grp->node[1].release = &group_close_release;
- INIT_LIST_HEAD(&grp->node[0].entry);
- INIT_LIST_HEAD(&grp->node[1].entry);
- set_node_dbginfo(&grp->node[0], "grp<", 0);
- set_node_dbginfo(&grp->node[1], "grp>", 0);
+ devres_node_init(&grp->node[0], &group_open_release, devres_group_free);
+ devres_node_init(&grp->node[1], &group_close_release, NULL);
+ devres_set_node_dbginfo(&grp->node[0], "grp<", 0);
+ devres_set_node_dbginfo(&grp->node[1], "grp>", 0);
grp->id = grp;
if (id)
grp->id = id;
grp->color = 0;
- spin_lock_irqsave(&dev->devres_lock, flags);
- add_dr(dev, &grp->node[0]);
- spin_unlock_irqrestore(&dev->devres_lock, flags);
+ devres_node_add(dev, &grp->node[0]);
return grp->id;
}
EXPORT_SYMBOL_GPL(devres_open_group);
@@ -613,17 +656,13 @@ static struct devres_group *find_group(struct device *dev, void *id)
void devres_close_group(struct device *dev, void *id)
{
struct devres_group *grp;
- unsigned long flags;
-
- spin_lock_irqsave(&dev->devres_lock, flags);
+ guard(spinlock_irqsave)(&dev->devres_lock);
grp = find_group(dev, id);
if (grp)
add_dr(dev, &grp->node[1]);
else
WARN_ON(1);
-
- spin_unlock_irqrestore(&dev->devres_lock, flags);
}
EXPORT_SYMBOL_GPL(devres_close_group);
@@ -677,7 +716,6 @@ int devres_release_group(struct device *dev, void *id)
int cnt = 0;
spin_lock_irqsave(&dev->devres_lock, flags);
-
grp = find_group(dev, id);
if (grp) {
struct list_head *first = &grp->node[0].entry;
@@ -687,20 +725,18 @@ int devres_release_group(struct device *dev, void *id)
end = grp->node[1].entry.next;
cnt = remove_nodes(dev, first, end, &todo);
- spin_unlock_irqrestore(&dev->devres_lock, flags);
-
- release_nodes(dev, &todo);
} else if (list_empty(&dev->devres_head)) {
/*
* dev is probably dying via devres_release_all(): groups
* have already been removed and are on the process of
* being released - don't touch and don't warn.
*/
- spin_unlock_irqrestore(&dev->devres_lock, flags);
} else {
WARN_ON(1);
- spin_unlock_irqrestore(&dev->devres_lock, flags);
}
+ spin_unlock_irqrestore(&dev->devres_lock, flags);
+
+ release_nodes(dev, &todo);
return cnt;
}
@@ -716,20 +752,29 @@ struct action_devres {
void (*action)(void *);
};
-static int devm_action_match(struct device *dev, void *res, void *p)
+struct devres_action {
+ struct devres_node node;
+ struct action_devres action;
+};
+
+static int devm_action_match(struct devres_action *devres, struct action_devres *target)
{
- struct action_devres *devres = res;
- struct action_devres *target = p;
+ return devres->action.action == target->action &&
+ devres->action.data == target->data;
+}
- return devres->action == target->action &&
- devres->data == target->data;
+static void devm_action_release(struct device *dev, struct devres_node *node)
+{
+ struct devres_action *devres = container_of(node, struct devres_action, node);
+
+ devres->action.action(devres->action.data);
}
-static void devm_action_release(struct device *dev, void *res)
+static void devm_action_free(struct devres_node *node)
{
- struct action_devres *devres = res;
+ struct devres_action *action = container_of(node, struct devres_action, node);
- devres->action(devres->data);
+ kfree(action);
}
/**
@@ -744,32 +789,71 @@ static void devm_action_release(struct device *dev, void *res)
*/
int __devm_add_action(struct device *dev, void (*action)(void *), void *data, const char *name)
{
- struct action_devres *devres;
+ struct devres_action *devres;
- devres = __devres_alloc_node(devm_action_release, sizeof(struct action_devres),
- GFP_KERNEL, NUMA_NO_NODE, name);
+ devres = kzalloc_obj(*devres);
if (!devres)
return -ENOMEM;
- devres->data = data;
- devres->action = action;
+ devres_node_init(&devres->node, devm_action_release, devm_action_free);
+ devres_set_node_dbginfo(&devres->node, name, sizeof(*devres));
- devres_add(dev, devres);
+ devres->action.data = data;
+ devres->action.action = action;
+
+ devres_node_add(dev, &devres->node);
return 0;
}
EXPORT_SYMBOL_GPL(__devm_add_action);
-bool devm_is_action_added(struct device *dev, void (*action)(void *), void *data)
+static struct devres_action *devres_action_find(struct device *dev,
+ void (*action)(void *),
+ void *data)
{
- struct action_devres devres = {
+ struct devres_node *node;
+ struct action_devres target = {
.data = data,
.action = action,
};
- return devres_find(dev, devm_action_release, devm_action_match, &devres);
+ list_for_each_entry_reverse(node, &dev->devres_head, entry) {
+ struct devres_action *dr = container_of(node, struct devres_action, node);
+
+ if (node->release != devm_action_release)
+ continue;
+ if (devm_action_match(dr, &target))
+ return dr;
+ }
+
+ return NULL;
+}
+
+bool devm_is_action_added(struct device *dev, void (*action)(void *), void *data)
+{
+ guard(spinlock_irqsave)(&dev->devres_lock);
+
+ return !!devres_action_find(dev, action, data);
}
EXPORT_SYMBOL_GPL(devm_is_action_added);
+static struct devres_action *remove_action(struct device *dev,
+ void (*action)(void *),
+ void *data)
+{
+ struct devres_action *dr;
+
+ guard(spinlock_irqsave)(&dev->devres_lock);
+
+ dr = devres_action_find(dev, action, data);
+ if (!dr)
+ return ERR_PTR(-ENOENT);
+
+ list_del_init(&dr->node.entry);
+ devres_log(dev, &dr->node, "REM");
+
+ return dr;
+}
+
/**
* devm_remove_action_nowarn() - removes previously added custom action
* @dev: Device that owns the action
@@ -794,13 +878,15 @@ int devm_remove_action_nowarn(struct device *dev,
void (*action)(void *),
void *data)
{
- struct action_devres devres = {
- .data = data,
- .action = action,
- };
+ struct devres_action *dr;
- return devres_destroy(dev, devm_action_release, devm_action_match,
- &devres);
+ dr = remove_action(dev, action, data);
+ if (IS_ERR(dr))
+ return PTR_ERR(dr);
+
+ kfree(dr);
+
+ return 0;
}
EXPORT_SYMBOL_GPL(devm_remove_action_nowarn);
@@ -816,14 +902,15 @@ EXPORT_SYMBOL_GPL(devm_remove_action_nowarn);
*/
void devm_release_action(struct device *dev, void (*action)(void *), void *data)
{
- struct action_devres devres = {
- .data = data,
- .action = action,
- };
+ struct devres_action *dr;
- WARN_ON(devres_release(dev, devm_action_release, devm_action_match,
- &devres));
+ dr = remove_action(dev, action, data);
+ if (WARN_ON(IS_ERR(dr)))
+ return;
+
+ dr->action.action(dr->action.data);
+ kfree(dr);
}
EXPORT_SYMBOL_GPL(devm_release_action);
@@ -869,7 +956,7 @@ void *devm_kmalloc(struct device *dev, size_t size, gfp_t gfp)
* This is named devm_kzalloc_release for historical reasons
* The initial implementation did not support kmalloc, only kzalloc
*/
- set_node_dbginfo(&dr->node, "devm_kzalloc_release", size);
+ devres_set_node_dbginfo(&dr->node, "devm_kzalloc_release", size);
devres_add(dev, dr->data);
return dr->data;
}
@@ -940,6 +1027,8 @@ void *devm_krealloc(struct device *dev, void *ptr, size_t new_size, gfp_t gfp)
if (!new_dr)
return NULL;
+ devres_set_node_dbginfo(&new_dr->node, "devm_krealloc_release", new_size);
+
/*
* The spinlock protects the linked list against concurrent
* modifications but not the resource itself.
@@ -949,7 +1038,7 @@ void *devm_krealloc(struct device *dev, void *ptr, size_t new_size, gfp_t gfp)
old_dr = find_dr(dev, devm_kmalloc_release, devm_kmalloc_match, ptr);
if (!old_dr) {
spin_unlock_irqrestore(&dev->devres_lock, flags);
- kfree(new_dr);
+ free_dr(new_dr);
WARN(1, "Memory chunk not managed or managed by a different device.");
return NULL;
}
@@ -969,7 +1058,7 @@ void *devm_krealloc(struct device *dev, void *ptr, size_t new_size, gfp_t gfp)
* list. This is also the reason why we must not use devm_kfree() - the
* links are no longer valid.
*/
- kfree(old_dr);
+ free_dr(old_dr);
return new_dr->data;
}
diff --git a/drivers/base/init.c b/drivers/base/init.c
index 9d2b06d65dfc..af8014416c24 100644
--- a/drivers/base/init.c
+++ b/drivers/base/init.c
@@ -34,6 +34,7 @@ void __init driver_init(void)
*/
faux_bus_init();
of_core_init();
+ software_node_init();
platform_bus_init();
auxiliary_bus_init();
memory_dev_init();
diff --git a/drivers/base/memory.c b/drivers/base/memory.c
index a3091924918b..0d6ccc7cdf05 100644
--- a/drivers/base/memory.c
+++ b/drivers/base/memory.c
@@ -815,7 +815,7 @@ static int add_memory_block(unsigned long block_id, int nid, unsigned long state
/*
* MEM_ONLINE at this point implies early memory. With NUMA,
* we'll determine the zone when setting the node id via
- * memory_block_add_nid(). Memory hotplug updated the zone
+ * memory_block_add_nid_early(). Memory hotplug updated the zone
* manually when memory onlining/offlining succeeds.
*/
mem->zone = early_node_zone_for_memory_block(mem, NUMA_NO_NODE);
diff --git a/drivers/base/platform.c b/drivers/base/platform.c
index d44591d52e36..75b4698d0e58 100644
--- a/drivers/base/platform.c
+++ b/drivers/base/platform.c
@@ -75,7 +75,7 @@ struct resource *platform_get_mem_or_io(struct platform_device *dev,
for (i = 0; i < dev->num_resources; i++) {
struct resource *r = &dev->resource[i];
- if ((resource_type(r) & (IORESOURCE_MEM|IORESOURCE_IO)) && num-- == 0)
+ if ((resource_type(r) & (IORESOURCE_MEM | IORESOURCE_IO)) && num-- == 0)
return r;
}
return NULL;
@@ -97,7 +97,7 @@ EXPORT_SYMBOL_GPL(platform_get_mem_or_io);
*/
void __iomem *
devm_platform_get_and_ioremap_resource(struct platform_device *pdev,
- unsigned int index, struct resource **res)
+ unsigned int index, struct resource **res)
{
struct resource *r;
@@ -172,7 +172,7 @@ static const struct cpumask *get_irq_affinity(struct platform_device *dev,
* @num: interrupt number index
* @affinity: optional cpumask pointer to get the affinity of a per-cpu interrupt
*
- * Gets an interupt for a platform device. Device drivers should check the
+ * Gets an interrupt for a platform device. Device drivers should check the
* return value for errors so as to not pass a negative integer value to
* the request_irq() APIs. Optional affinity information is provided in the
* affinity pointer if available, and NULL otherwise.
@@ -843,12 +843,14 @@ EXPORT_SYMBOL_GPL(platform_device_unregister);
*
* Returns &struct platform_device pointer on success, or ERR_PTR() on error.
*/
-struct platform_device *platform_device_register_full(
- const struct platform_device_info *pdevinfo)
+struct platform_device *platform_device_register_full(const struct platform_device_info *pdevinfo)
{
int ret;
struct platform_device *pdev;
+ if (pdevinfo->swnode && pdevinfo->properties)
+ return ERR_PTR(-EINVAL);
+
pdev = platform_device_alloc(pdevinfo->name, pdevinfo->id);
if (!pdev)
return ERR_PTR(-ENOMEM);
@@ -864,17 +866,19 @@ struct platform_device *platform_device_register_full(
pdev->dev.coherent_dma_mask = pdevinfo->dma_mask;
}
- ret = platform_device_add_resources(pdev,
- pdevinfo->res, pdevinfo->num_res);
+ ret = platform_device_add_resources(pdev, pdevinfo->res, pdevinfo->num_res);
if (ret)
goto err;
- ret = platform_device_add_data(pdev,
- pdevinfo->data, pdevinfo->size_data);
+ ret = platform_device_add_data(pdev, pdevinfo->data, pdevinfo->size_data);
if (ret)
goto err;
- if (pdevinfo->properties) {
+ if (pdevinfo->swnode) {
+ ret = device_add_software_node(&pdev->dev, pdevinfo->swnode);
+ if (ret)
+ goto err;
+ } else if (pdevinfo->properties) {
ret = device_create_managed_software_node(&pdev->dev,
pdevinfo->properties, NULL);
if (ret)
@@ -898,8 +902,7 @@ EXPORT_SYMBOL_GPL(platform_device_register_full);
* @drv: platform driver structure
* @owner: owning module/driver
*/
-int __platform_driver_register(struct platform_driver *drv,
- struct module *owner)
+int __platform_driver_register(struct platform_driver *drv, struct module *owner)
{
drv->driver.owner = owner;
drv->driver.bus = &platform_bus_type;
@@ -951,13 +954,14 @@ static int is_bound_to_driver(struct device *dev, void *driver)
* a negative error code and with the driver not registered.
*/
int __init_or_module __platform_driver_probe(struct platform_driver *drv,
- int (*probe)(struct platform_device *), struct module *module)
+ int (*probe)(struct platform_device *),
+ struct module *module)
{
int retval;
if (drv->driver.probe_type == PROBE_PREFER_ASYNCHRONOUS) {
pr_err("%s: drivers registered with %s can not be probed asynchronously\n",
- drv->driver.name, __func__);
+ drv->driver.name, __func__);
return -EINVAL;
}
@@ -1013,11 +1017,11 @@ EXPORT_SYMBOL_GPL(__platform_driver_probe);
*
* Returns &struct platform_device pointer on success, or ERR_PTR() on error.
*/
-struct platform_device * __init_or_module __platform_create_bundle(
- struct platform_driver *driver,
- int (*probe)(struct platform_device *),
- struct resource *res, unsigned int n_res,
- const void *data, size_t size, struct module *module)
+struct platform_device * __init_or_module
+__platform_create_bundle(struct platform_driver *driver,
+ int (*probe)(struct platform_device *),
+ struct resource *res, unsigned int n_res,
+ const void *data, size_t size, struct module *module)
{
struct platform_device *pdev;
int error;
@@ -1116,9 +1120,8 @@ void platform_unregister_drivers(struct platform_driver * const *drivers,
}
EXPORT_SYMBOL_GPL(platform_unregister_drivers);
-static const struct platform_device_id *platform_match_id(
- const struct platform_device_id *id,
- struct platform_device *pdev)
+static const struct platform_device_id *
+platform_match_id(const struct platform_device_id *id, struct platform_device *pdev)
{
while (id->name[0]) {
if (strcmp(pdev->name, id->name) == 0) {
@@ -1311,13 +1314,12 @@ static struct attribute *platform_dev_attrs[] = {
NULL,
};
-static umode_t platform_dev_attrs_visible(struct kobject *kobj, struct attribute *a,
- int n)
+static umode_t platform_dev_attrs_visible(struct kobject *kobj,
+ struct attribute *a, int n)
{
struct device *dev = container_of(kobj, typeof(*dev), kobj);
- if (a == &dev_attr_numa_node.attr &&
- dev_to_node(dev) == NUMA_NO_NODE)
+ if (a == &dev_attr_numa_node.attr && dev_to_node(dev) == NUMA_NO_NODE)
return 0;
return a->mode;
@@ -1329,7 +1331,6 @@ static const struct attribute_group platform_dev_group = {
};
__ATTRIBUTE_GROUPS(platform_dev);
-
/**
* platform_match - bind platform device to platform driver.
* @dev: device.
@@ -1384,8 +1385,7 @@ static int platform_uevent(const struct device *dev, struct kobj_uevent_env *env
if (rc != -ENODEV)
return rc;
- add_uevent_var(env, "MODALIAS=%s%s", PLATFORM_MODULE_PREFIX,
- pdev->name);
+ add_uevent_var(env, "MODALIAS=%s%s", PLATFORM_MODULE_PREFIX, pdev->name);
return 0;
}
diff --git a/drivers/base/property.c b/drivers/base/property.c
index 8d9a34be57fb..d16e9c5f1921 100644
--- a/drivers/base/property.c
+++ b/drivers/base/property.c
@@ -38,6 +38,8 @@ EXPORT_SYMBOL_GPL(__dev_fwnode_const);
* @propname: Name of the property
*
* Check if property @propname is present in the device firmware description.
+ * This function is the unambiguous way to check that given property is present
+ * in the device firmware description.
*
* Return: true if property @propname is present. Otherwise, returns false.
*/
@@ -52,6 +54,10 @@ EXPORT_SYMBOL_GPL(device_property_present);
* @fwnode: Firmware node whose property to check
* @propname: Name of the property
*
+ * Check if property @propname is present in the firmware node description.
+ * This function is the unambiguous way to check that given property is present
+ * in the firmware node description.
+ *
* Return: true if property @propname is present. Otherwise, returns false.
*/
bool fwnode_property_present(const struct fwnode_handle *fwnode,
@@ -75,9 +81,9 @@ EXPORT_SYMBOL_GPL(fwnode_property_present);
* @dev: Device whose property is being checked
* @propname: Name of the property
*
- * Return if property @propname is true or false in the device firmware description.
+ * Use device_property_present() to check for the property presence.
*
- * Return: true if property @propname is present. Otherwise, returns false.
+ * Return: if property @propname is true or false in the device firmware description.
*/
bool device_property_read_bool(const struct device *dev, const char *propname)
{
@@ -90,7 +96,9 @@ EXPORT_SYMBOL_GPL(device_property_read_bool);
* @fwnode: Firmware node whose property to check
* @propname: Name of the property
*
- * Return if property @propname is true or false in the firmware description.
+ * Use fwnode_property_present() to check for the property presence.
+ *
+ * Return: if property @propname is true or false in the firmware node description.
*/
bool fwnode_property_read_bool(const struct fwnode_handle *fwnode,
const char *propname)
diff --git a/drivers/base/soc.c b/drivers/base/soc.c
index c8d3db9daa2f..65ce72d49230 100644
--- a/drivers/base/soc.c
+++ b/drivers/base/soc.c
@@ -5,16 +5,16 @@
* Author: Lee Jones <lee.jones@linaro.org> for ST-Ericsson.
*/
-#include <linux/sysfs.h>
+#include <linux/err.h>
+#include <linux/glob.h>
+#include <linux/idr.h>
#include <linux/init.h>
#include <linux/of.h>
-#include <linux/stat.h>
#include <linux/slab.h>
-#include <linux/idr.h>
#include <linux/spinlock.h>
+#include <linux/stat.h>
+#include <linux/sysfs.h>
#include <linux/sys_soc.h>
-#include <linux/err.h>
-#include <linux/glob.h>
static DEFINE_IDA(soc_ida);
@@ -111,17 +111,14 @@ static void soc_release(struct device *dev)
kfree(soc_dev);
}
-static void soc_device_get_machine(struct soc_device_attribute *soc_dev_attr)
+int soc_attr_read_machine(struct soc_device_attribute *soc_dev_attr)
{
- struct device_node *np;
-
if (soc_dev_attr->machine)
- return;
+ return -EBUSY;
- np = of_find_node_by_path("/");
- of_property_read_string(np, "model", &soc_dev_attr->machine);
- of_node_put(np);
+ return of_machine_read_model(&soc_dev_attr->machine);
}
+EXPORT_SYMBOL_GPL(soc_attr_read_machine);
static struct soc_device_attribute *early_soc_dev_attr;
@@ -131,7 +128,7 @@ struct soc_device *soc_device_register(struct soc_device_attribute *soc_dev_attr
const struct attribute_group **soc_attr_groups;
int ret;
- soc_device_get_machine(soc_dev_attr);
+ soc_attr_read_machine(soc_dev_attr);
if (!soc_bus_registered) {
if (early_soc_dev_attr)
diff --git a/drivers/base/swnode.c b/drivers/base/swnode.c
index 51320837f3a9..a80575bf598b 100644
--- a/drivers/base/swnode.c
+++ b/drivers/base/swnode.c
@@ -1127,18 +1127,9 @@ void software_node_notify_remove(struct device *dev)
}
}
-static int __init software_node_init(void)
+void __init software_node_init(void)
{
swnode_kset = kset_create_and_add("software_nodes", NULL, kernel_kobj);
if (!swnode_kset)
- return -ENOMEM;
- return 0;
-}
-postcore_initcall(software_node_init);
-
-static void __exit software_node_exit(void)
-{
- ida_destroy(&swnode_root_ids);
- kset_unregister(swnode_kset);
+ pr_err("failed to register software nodes\n");
}
-__exitcall(software_node_exit);
diff --git a/drivers/bus/fsl-mc/fsl-mc-bus.c b/drivers/bus/fsl-mc/fsl-mc-bus.c
index c117745cf206..221146e4860b 100644
--- a/drivers/bus/fsl-mc/fsl-mc-bus.c
+++ b/drivers/bus/fsl-mc/fsl-mc-bus.c
@@ -86,12 +86,16 @@ static int fsl_mc_bus_match(struct device *dev, const struct device_driver *drv)
struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev);
const struct fsl_mc_driver *mc_drv = to_fsl_mc_driver(drv);
bool found = false;
+ int ret;
/* When driver_override is set, only bind to the matching driver */
- if (mc_dev->driver_override) {
- found = !strcmp(mc_dev->driver_override, mc_drv->driver.name);
+ ret = device_match_driver_override(dev, drv);
+ if (ret > 0) {
+ found = true;
goto out;
}
+ if (ret == 0)
+ goto out;
if (!mc_drv->match_id_table)
goto out;
@@ -210,39 +214,8 @@ static ssize_t modalias_show(struct device *dev, struct device_attribute *attr,
}
static DEVICE_ATTR_RO(modalias);
-static ssize_t driver_override_store(struct device *dev,
- struct device_attribute *attr,
- const char *buf, size_t count)
-{
- struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev);
- int ret;
-
- if (WARN_ON(dev->bus != &fsl_mc_bus_type))
- return -EINVAL;
-
- ret = driver_set_override(dev, &mc_dev->driver_override, buf, count);
- if (ret)
- return ret;
-
- return count;
-}
-
-static ssize_t driver_override_show(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev);
- ssize_t len;
-
- device_lock(dev);
- len = sysfs_emit(buf, "%s\n", mc_dev->driver_override);
- device_unlock(dev);
- return len;
-}
-static DEVICE_ATTR_RW(driver_override);
-
static struct attribute *fsl_mc_dev_attrs[] = {
&dev_attr_modalias.attr,
- &dev_attr_driver_override.attr,
NULL,
};
@@ -345,6 +318,7 @@ ATTRIBUTE_GROUPS(fsl_mc_bus);
const struct bus_type fsl_mc_bus_type = {
.name = "fsl-mc",
+ .driver_override = true,
.match = fsl_mc_bus_match,
.uevent = fsl_mc_bus_uevent,
.probe = fsl_mc_probe,
@@ -910,9 +884,6 @@ static struct notifier_block fsl_mc_nb;
*/
void fsl_mc_device_remove(struct fsl_mc_device *mc_dev)
{
- kfree(mc_dev->driver_override);
- mc_dev->driver_override = NULL;
-
/*
* The device-specific remove callback will get invoked by device_del()
*/
diff --git a/drivers/bus/imx-weim.c b/drivers/bus/imx-weim.c
index 83d623d97f5f..f735e0462c55 100644
--- a/drivers/bus/imx-weim.c
+++ b/drivers/bus/imx-weim.c
@@ -332,7 +332,7 @@ static int of_weim_notify(struct notifier_block *nb, unsigned long action,
* fw_devlink doesn't skip adding consumers to this
* device.
*/
- rd->dn->fwnode.flags &= ~FWNODE_FLAG_NOT_DEVICE;
+ fwnode_clear_flag(&rd->dn->fwnode, FWNODE_FLAG_NOT_DEVICE);
if (!of_platform_device_create(rd->dn, NULL, &pdev->dev)) {
dev_err(&pdev->dev,
"Failed to create child device '%pOF'\n",
diff --git a/drivers/i2c/i2c-core-of.c b/drivers/i2c/i2c-core-of.c
index eb7fb202355f..354a88d0599e 100644
--- a/drivers/i2c/i2c-core-of.c
+++ b/drivers/i2c/i2c-core-of.c
@@ -180,7 +180,7 @@ static int of_i2c_notify(struct notifier_block *nb, unsigned long action,
* Clear the flag before adding the device so that fw_devlink
* doesn't skip adding consumers to this device.
*/
- rd->dn->fwnode.flags &= ~FWNODE_FLAG_NOT_DEVICE;
+ fwnode_clear_flag(&rd->dn->fwnode, FWNODE_FLAG_NOT_DEVICE);
client = of_i2c_register_device(adap, rd->dn);
if (IS_ERR(client)) {
dev_err(&adap->dev, "failed to create client for '%pOF'\n",
diff --git a/drivers/net/phy/mdio_bus_provider.c b/drivers/net/phy/mdio_bus_provider.c
index 4b0637405740..fd691c5424ea 100644
--- a/drivers/net/phy/mdio_bus_provider.c
+++ b/drivers/net/phy/mdio_bus_provider.c
@@ -294,8 +294,8 @@ int __mdiobus_register(struct mii_bus *bus, struct module *owner)
return -EINVAL;
if (bus->parent && bus->parent->of_node)
- bus->parent->of_node->fwnode.flags |=
- FWNODE_FLAG_NEEDS_CHILD_BOUND_ON_ADD;
+ fwnode_set_flag(&bus->parent->of_node->fwnode,
+ FWNODE_FLAG_NEEDS_CHILD_BOUND_ON_ADD);
WARN(bus->state != MDIOBUS_ALLOCATED &&
bus->state != MDIOBUS_UNREGISTERED,
diff --git a/drivers/of/base.c b/drivers/of/base.c
index 57420806c1a2..180dbce65b98 100644
--- a/drivers/of/base.c
+++ b/drivers/of/base.c
@@ -435,6 +435,34 @@ bool of_machine_compatible_match(const char *const *compats)
EXPORT_SYMBOL(of_machine_compatible_match);
/**
+ * of_machine_read_compatible - Get the compatible string of this machine
+ * @compatible: address at which the address of the compatible string will be
+ * stored
+ * @index: index of the compatible entry in the list
+ *
+ * Returns:
+ * 0 on success, negative error number on failure.
+ */
+int of_machine_read_compatible(const char **compatible, unsigned int index)
+{
+ return of_property_read_string_index(of_root, "compatible", index, compatible);
+}
+EXPORT_SYMBOL_GPL(of_machine_read_compatible);
+
+/**
+ * of_machine_read_model - Get the model string of this machine
+ * @model: address at which the address of the model string will be stored
+ *
+ * Returns:
+ * 0 on success, negative error number on failure.
+ */
+int of_machine_read_model(const char **model)
+{
+ return of_property_read_string(of_root, "model", model);
+}
+EXPORT_SYMBOL_GPL(of_machine_read_model);
+
+/**
* of_machine_device_match - Test root of device tree against a of_device_id array
* @matches: NULL terminated array of of_device_id match structures to search in
*
@@ -1915,7 +1943,7 @@ void of_alias_scan(void * (*dt_alloc)(u64 size, u64 align))
if (name)
of_stdout = of_find_node_opts_by_path(name, &of_stdout_options);
if (of_stdout)
- of_stdout->fwnode.flags |= FWNODE_FLAG_BEST_EFFORT;
+ fwnode_set_flag(&of_stdout->fwnode, FWNODE_FLAG_BEST_EFFORT);
}
if (!of_aliases)
diff --git a/drivers/of/dynamic.c b/drivers/of/dynamic.c
index 1a06175def37..ade288372101 100644
--- a/drivers/of/dynamic.c
+++ b/drivers/of/dynamic.c
@@ -225,7 +225,7 @@ static void __of_attach_node(struct device_node *np)
np->sibling = np->parent->child;
np->parent->child = np;
of_node_clear_flag(np, OF_DETACHED);
- np->fwnode.flags |= FWNODE_FLAG_NOT_DEVICE;
+ fwnode_set_flag(&np->fwnode, FWNODE_FLAG_NOT_DEVICE);
raw_spin_unlock_irqrestore(&devtree_lock, flags);
diff --git a/drivers/of/platform.c b/drivers/of/platform.c
index ba591fbceb56..7eeaf8e27b5b 100644
--- a/drivers/of/platform.c
+++ b/drivers/of/platform.c
@@ -742,7 +742,7 @@ static int of_platform_notify(struct notifier_block *nb,
* Clear the flag before adding the device so that fw_devlink
* doesn't skip adding consumers to this device.
*/
- rd->dn->fwnode.flags &= ~FWNODE_FLAG_NOT_DEVICE;
+ fwnode_clear_flag(&rd->dn->fwnode, FWNODE_FLAG_NOT_DEVICE);
/* pdev_parent may be NULL when no bus platform device */
pdev_parent = of_find_device_by_node(parent);
pdev = of_platform_device_create(rd->dn, NULL,
diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c
index dd9075403987..d10ece0889f0 100644
--- a/drivers/pci/pci-driver.c
+++ b/drivers/pci/pci-driver.c
@@ -138,9 +138,11 @@ static const struct pci_device_id *pci_match_device(struct pci_driver *drv,
{
struct pci_dynid *dynid;
const struct pci_device_id *found_id = NULL, *ids;
+ int ret;
/* When driver_override is set, only bind to the matching driver */
- if (dev->driver_override && strcmp(dev->driver_override, drv->name))
+ ret = device_match_driver_override(&dev->dev, &drv->driver);
+ if (ret == 0)
return NULL;
/* Look at the dynamic ids first, before the static ones */
@@ -164,7 +166,7 @@ static const struct pci_device_id *pci_match_device(struct pci_driver *drv,
* matching.
*/
if (found_id->override_only) {
- if (dev->driver_override)
+ if (ret > 0)
return found_id;
} else {
return found_id;
@@ -172,7 +174,7 @@ static const struct pci_device_id *pci_match_device(struct pci_driver *drv,
}
/* driver_override will always match, send a dummy id */
- if (dev->driver_override)
+ if (ret > 0)
return &pci_device_id_any;
return NULL;
}
@@ -452,7 +454,7 @@ static int __pci_device_probe(struct pci_driver *drv, struct pci_dev *pci_dev)
static inline bool pci_device_can_probe(struct pci_dev *pdev)
{
return (!pdev->is_virtfn || pdev->physfn->sriov->drivers_autoprobe ||
- pdev->driver_override);
+ device_has_driver_override(&pdev->dev));
}
#else
static inline bool pci_device_can_probe(struct pci_dev *pdev)
@@ -1722,6 +1724,7 @@ static const struct cpumask *pci_device_irq_get_affinity(struct device *dev,
const struct bus_type pci_bus_type = {
.name = "pci",
+ .driver_override = true,
.match = pci_bus_match,
.uevent = pci_uevent,
.probe = pci_device_probe,
diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c
index 16eaaf749ba9..a9006cf4e9c8 100644
--- a/drivers/pci/pci-sysfs.c
+++ b/drivers/pci/pci-sysfs.c
@@ -615,33 +615,6 @@ static ssize_t devspec_show(struct device *dev,
static DEVICE_ATTR_RO(devspec);
#endif
-static ssize_t driver_override_store(struct device *dev,
- struct device_attribute *attr,
- const char *buf, size_t count)
-{
- struct pci_dev *pdev = to_pci_dev(dev);
- int ret;
-
- ret = driver_set_override(dev, &pdev->driver_override, buf, count);
- if (ret)
- return ret;
-
- return count;
-}
-
-static ssize_t driver_override_show(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct pci_dev *pdev = to_pci_dev(dev);
- ssize_t len;
-
- device_lock(dev);
- len = sysfs_emit(buf, "%s\n", pdev->driver_override);
- device_unlock(dev);
- return len;
-}
-static DEVICE_ATTR_RW(driver_override);
-
static struct attribute *pci_dev_attrs[] = {
&dev_attr_power_state.attr,
&dev_attr_resource.attr,
@@ -669,7 +642,6 @@ static struct attribute *pci_dev_attrs[] = {
#ifdef CONFIG_OF
&dev_attr_devspec.attr,
#endif
- &dev_attr_driver_override.attr,
&dev_attr_ari_enabled.attr,
NULL,
};
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index bccc7a4bdd79..b4707640e102 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -2488,7 +2488,6 @@ static void pci_release_dev(struct device *dev)
pci_release_of_node(pci_dev);
pcibios_release_device(pci_dev);
pci_bus_put(pci_dev->bus);
- kfree(pci_dev->driver_override);
bitmap_free(pci_dev->dma_alias_mask);
dev_dbg(dev, "device released\n");
kfree(pci_dev);
diff --git a/drivers/platform/wmi/core.c b/drivers/platform/wmi/core.c
index b8e6b9a421c6..750e3619724e 100644
--- a/drivers/platform/wmi/core.c
+++ b/drivers/platform/wmi/core.c
@@ -842,39 +842,11 @@ static ssize_t expensive_show(struct device *dev,
}
static DEVICE_ATTR_RO(expensive);
-static ssize_t driver_override_show(struct device *dev, struct device_attribute *attr,
- char *buf)
-{
- struct wmi_device *wdev = to_wmi_device(dev);
- ssize_t ret;
-
- device_lock(dev);
- ret = sysfs_emit(buf, "%s\n", wdev->driver_override);
- device_unlock(dev);
-
- return ret;
-}
-
-static ssize_t driver_override_store(struct device *dev, struct device_attribute *attr,
- const char *buf, size_t count)
-{
- struct wmi_device *wdev = to_wmi_device(dev);
- int ret;
-
- ret = driver_set_override(dev, &wdev->driver_override, buf, count);
- if (ret < 0)
- return ret;
-
- return count;
-}
-static DEVICE_ATTR_RW(driver_override);
-
static struct attribute *wmi_attrs[] = {
&dev_attr_modalias.attr,
&dev_attr_guid.attr,
&dev_attr_instance_count.attr,
&dev_attr_expensive.attr,
- &dev_attr_driver_override.attr,
NULL
};
ATTRIBUTE_GROUPS(wmi);
@@ -943,7 +915,6 @@ static void wmi_dev_release(struct device *dev)
{
struct wmi_block *wblock = dev_to_wblock(dev);
- kfree(wblock->dev.driver_override);
kfree(wblock);
}
@@ -952,10 +923,12 @@ static int wmi_dev_match(struct device *dev, const struct device_driver *driver)
const struct wmi_driver *wmi_driver = to_wmi_driver(driver);
struct wmi_block *wblock = dev_to_wblock(dev);
const struct wmi_device_id *id = wmi_driver->id_table;
+ int ret;
/* When driver_override is set, only bind to the matching driver */
- if (wblock->dev.driver_override)
- return !strcmp(wblock->dev.driver_override, driver->name);
+ ret = device_match_driver_override(dev, driver);
+ if (ret >= 0)
+ return ret;
if (id == NULL)
return 0;
@@ -1076,6 +1049,7 @@ static struct class wmi_bus_class = {
static const struct bus_type wmi_bus_type = {
.name = "wmi",
.dev_groups = wmi_groups,
+ .driver_override = true,
.match = wmi_dev_match,
.uevent = wmi_dev_uevent,
.probe = wmi_dev_probe,
diff --git a/drivers/s390/cio/cio.h b/drivers/s390/cio/cio.h
index 08a5e9380e75..bad142c536e1 100644
--- a/drivers/s390/cio/cio.h
+++ b/drivers/s390/cio/cio.h
@@ -103,11 +103,6 @@ struct subchannel {
struct work_struct todo_work;
struct schib_config config;
u64 dma_mask;
- /*
- * Driver name to force a match. Do not set directly, because core
- * frees it. Use driver_set_override() to set or clear it.
- */
- const char *driver_override;
} __attribute__ ((aligned(8)));
DECLARE_PER_CPU_ALIGNED(struct irb, cio_irb);
diff --git a/drivers/s390/cio/css.c b/drivers/s390/cio/css.c
index 5ab239f38588..e5a0ec6b4e3e 100644
--- a/drivers/s390/cio/css.c
+++ b/drivers/s390/cio/css.c
@@ -159,7 +159,6 @@ static void css_subchannel_release(struct device *dev)
sch->config.intparm = 0;
cio_commit_config(sch);
- kfree(sch->driver_override);
kfree(sch);
}
@@ -323,37 +322,9 @@ static ssize_t modalias_show(struct device *dev, struct device_attribute *attr,
static DEVICE_ATTR_RO(modalias);
-static ssize_t driver_override_store(struct device *dev,
- struct device_attribute *attr,
- const char *buf, size_t count)
-{
- struct subchannel *sch = to_subchannel(dev);
- int ret;
-
- ret = driver_set_override(dev, &sch->driver_override, buf, count);
- if (ret)
- return ret;
-
- return count;
-}
-
-static ssize_t driver_override_show(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct subchannel *sch = to_subchannel(dev);
- ssize_t len;
-
- device_lock(dev);
- len = sysfs_emit(buf, "%s\n", sch->driver_override);
- device_unlock(dev);
- return len;
-}
-static DEVICE_ATTR_RW(driver_override);
-
static struct attribute *subch_attrs[] = {
&dev_attr_type.attr,
&dev_attr_modalias.attr,
- &dev_attr_driver_override.attr,
NULL,
};
@@ -1356,9 +1327,11 @@ static int css_bus_match(struct device *dev, const struct device_driver *drv)
struct subchannel *sch = to_subchannel(dev);
const struct css_driver *driver = to_cssdriver(drv);
struct css_device_id *id;
+ int ret;
/* When driver_override is set, only bind to the matching driver */
- if (sch->driver_override && strcmp(sch->driver_override, drv->name))
+ ret = device_match_driver_override(dev, drv);
+ if (ret == 0)
return 0;
for (id = driver->subchannel_type; id->match_flags; id++) {
@@ -1415,6 +1388,7 @@ static int css_uevent(const struct device *dev, struct kobj_uevent_env *env)
static const struct bus_type css_bus_type = {
.name = "css",
+ .driver_override = true,
.match = css_bus_match,
.probe = css_probe,
.remove = css_remove,
diff --git a/drivers/s390/crypto/ap_bus.c b/drivers/s390/crypto/ap_bus.c
index d652df96a507..f24e27add721 100644
--- a/drivers/s390/crypto/ap_bus.c
+++ b/drivers/s390/crypto/ap_bus.c
@@ -859,25 +859,24 @@ static int __ap_queue_devices_with_id_unregister(struct device *dev, void *data)
static int __ap_revise_reserved(struct device *dev, void *dummy)
{
- int rc, card, queue, devres, drvres;
+ int rc, card, queue, devres, drvres, ovrd;
if (is_queue_dev(dev)) {
struct ap_driver *ap_drv = to_ap_drv(dev->driver);
struct ap_queue *aq = to_ap_queue(dev);
- struct ap_device *ap_dev = &aq->ap_dev;
card = AP_QID_CARD(aq->qid);
queue = AP_QID_QUEUE(aq->qid);
- if (ap_dev->driver_override) {
- if (strcmp(ap_dev->driver_override,
- ap_drv->driver.name)) {
- pr_debug("reprobing queue=%02x.%04x\n", card, queue);
- rc = device_reprobe(dev);
- if (rc) {
- AP_DBF_WARN("%s reprobing queue=%02x.%04x failed\n",
- __func__, card, queue);
- }
+ ovrd = device_match_driver_override(dev, &ap_drv->driver);
+ if (ovrd > 0) {
+ /* override set and matches, nothing to do */
+ } else if (ovrd == 0) {
+ pr_debug("reprobing queue=%02x.%04x\n", card, queue);
+ rc = device_reprobe(dev);
+ if (rc) {
+ AP_DBF_WARN("%s reprobing queue=%02x.%04x failed\n",
+ __func__, card, queue);
}
} else {
mutex_lock(&ap_attr_mutex);
@@ -928,7 +927,7 @@ int ap_owned_by_def_drv(int card, int queue)
if (aq) {
const struct device_driver *drv = aq->ap_dev.device.driver;
const struct ap_driver *ap_drv = to_ap_drv(drv);
- bool override = !!aq->ap_dev.driver_override;
+ bool override = device_has_driver_override(&aq->ap_dev.device);
if (override && drv && ap_drv->flags & AP_DRIVER_FLAG_DEFAULT)
rc = 1;
@@ -977,7 +976,7 @@ static int ap_device_probe(struct device *dev)
{
struct ap_device *ap_dev = to_ap_dev(dev);
struct ap_driver *ap_drv = to_ap_drv(dev->driver);
- int card, queue, devres, drvres, rc = -ENODEV;
+ int card, queue, devres, drvres, rc = -ENODEV, ovrd;
if (!get_device(dev))
return rc;
@@ -991,10 +990,11 @@ static int ap_device_probe(struct device *dev)
*/
card = AP_QID_CARD(to_ap_queue(dev)->qid);
queue = AP_QID_QUEUE(to_ap_queue(dev)->qid);
- if (ap_dev->driver_override) {
- if (strcmp(ap_dev->driver_override,
- ap_drv->driver.name))
- goto out;
+ ovrd = device_match_driver_override(dev, &ap_drv->driver);
+ if (ovrd > 0) {
+ /* override set and matches, nothing to do */
+ } else if (ovrd == 0) {
+ goto out;
} else {
mutex_lock(&ap_attr_mutex);
devres = test_bit_inv(card, ap_perms.apm) &&
diff --git a/drivers/s390/crypto/ap_bus.h b/drivers/s390/crypto/ap_bus.h
index 51e08f27bd75..04ea256ecf91 100644
--- a/drivers/s390/crypto/ap_bus.h
+++ b/drivers/s390/crypto/ap_bus.h
@@ -166,7 +166,6 @@ void ap_driver_unregister(struct ap_driver *);
struct ap_device {
struct device device;
int device_type; /* AP device type. */
- const char *driver_override;
};
#define to_ap_dev(x) container_of((x), struct ap_device, device)
diff --git a/drivers/s390/crypto/ap_queue.c b/drivers/s390/crypto/ap_queue.c
index 3fe2e41c5c6b..ca9819e6f7e7 100644
--- a/drivers/s390/crypto/ap_queue.c
+++ b/drivers/s390/crypto/ap_queue.c
@@ -734,26 +734,14 @@ static ssize_t driver_override_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{
- struct ap_queue *aq = to_ap_queue(dev);
- struct ap_device *ap_dev = &aq->ap_dev;
- int rc;
-
- device_lock(dev);
- if (ap_dev->driver_override)
- rc = sysfs_emit(buf, "%s\n", ap_dev->driver_override);
- else
- rc = sysfs_emit(buf, "\n");
- device_unlock(dev);
-
- return rc;
+ guard(spinlock)(&dev->driver_override.lock);
+ return sysfs_emit(buf, "%s\n", dev->driver_override.name ?: "");
}
static ssize_t driver_override_store(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
- struct ap_queue *aq = to_ap_queue(dev);
- struct ap_device *ap_dev = &aq->ap_dev;
int rc = -EINVAL;
bool old_value;
@@ -764,13 +752,13 @@ static ssize_t driver_override_store(struct device *dev,
if (ap_apmask_aqmask_in_use)
goto out;
- old_value = ap_dev->driver_override ? true : false;
- rc = driver_set_override(dev, &ap_dev->driver_override, buf, count);
+ old_value = device_has_driver_override(dev);
+ rc = __device_set_driver_override(dev, buf, count);
if (rc)
goto out;
- if (old_value && !ap_dev->driver_override)
+ if (old_value && !device_has_driver_override(dev))
--ap_driver_override_ctr;
- else if (!old_value && ap_dev->driver_override)
+ else if (!old_value && device_has_driver_override(dev))
++ap_driver_override_ctr;
rc = count;
diff --git a/drivers/soc/fsl/guts.c b/drivers/soc/fsl/guts.c
index 40afb27b582b..9bee7baec2b9 100644
--- a/drivers/soc/fsl/guts.c
+++ b/drivers/soc/fsl/guts.c
@@ -186,7 +186,6 @@ static int __init fsl_guts_init(void)
const struct fsl_soc_data *soc_data;
const struct of_device_id *match;
struct ccsr_guts __iomem *regs;
- const char *machine = NULL;
struct device_node *np;
bool little_endian;
u64 soc_uid = 0;
@@ -217,13 +216,9 @@ static int __init fsl_guts_init(void)
if (!soc_dev_attr)
return -ENOMEM;
- if (of_property_read_string(of_root, "model", &machine))
- of_property_read_string_index(of_root, "compatible", 0, &machine);
- if (machine) {
- soc_dev_attr->machine = kstrdup(machine, GFP_KERNEL);
- if (!soc_dev_attr->machine)
- goto err_nomem;
- }
+ ret = soc_attr_read_machine(soc_dev_attr);
+ if (ret)
+ of_machine_read_compatible(&soc_dev_attr->machine, 0);
soc_die = fsl_soc_die_match(svr, fsl_soc_die);
if (soc_die) {
@@ -267,7 +262,6 @@ static int __init fsl_guts_init(void)
err_nomem:
ret = -ENOMEM;
err:
- kfree(soc_dev_attr->machine);
kfree(soc_dev_attr->family);
kfree(soc_dev_attr->soc_id);
kfree(soc_dev_attr->revision);
diff --git a/drivers/soc/imx/soc-imx8m.c b/drivers/soc/imx/soc-imx8m.c
index 8e2322999f09..77763a107edb 100644
--- a/drivers/soc/imx/soc-imx8m.c
+++ b/drivers/soc/imx/soc-imx8m.c
@@ -226,7 +226,6 @@ static int imx8m_soc_probe(struct platform_device *pdev)
const struct imx8_soc_data *data;
struct imx8_soc_drvdata *drvdata;
struct device *dev = &pdev->dev;
- const struct of_device_id *id;
struct soc_device *soc_dev;
u32 soc_rev = 0;
u64 soc_uid[2] = {0, 0};
@@ -244,15 +243,11 @@ static int imx8m_soc_probe(struct platform_device *pdev)
soc_dev_attr->family = "Freescale i.MX";
- ret = of_property_read_string(of_root, "model", &soc_dev_attr->machine);
+ ret = soc_attr_read_machine(soc_dev_attr);
if (ret)
return ret;
- id = of_match_node(imx8_soc_match, of_root);
- if (!id)
- return -ENODEV;
-
- data = id->data;
+ data = device_get_match_data(dev);
if (data) {
soc_dev_attr->soc_id = data->name;
ret = imx8m_soc_prepare(pdev, data->ocotp_compatible);
@@ -326,7 +321,7 @@ static int __init imx8_soc_init(void)
int ret;
/* No match means this is non-i.MX8M hardware, do nothing. */
- if (!of_match_node(imx8_soc_match, of_root))
+ if (!of_machine_device_match(imx8_soc_match))
return 0;
ret = platform_driver_register(&imx8m_soc_driver);
diff --git a/drivers/soc/imx/soc-imx9.c b/drivers/soc/imx/soc-imx9.c
index d67bc7402b10..58eef7d4f908 100644
--- a/drivers/soc/imx/soc-imx9.c
+++ b/drivers/soc/imx/soc-imx9.c
@@ -30,7 +30,7 @@ static int imx9_soc_probe(struct platform_device *pdev)
if (!attr)
return -ENOMEM;
- err = of_property_read_string(of_root, "model", &attr->machine);
+ err = soc_attr_read_machine(attr);
if (err)
return dev_err_probe(dev, err, "%s: missing model property\n", __func__);
@@ -89,7 +89,7 @@ static int __init imx9_soc_init(void)
struct platform_device *pdev;
/* No match means it is not an i.MX 9 series SoC, do nothing. */
- if (!of_match_node(imx9_soc_match, of_root))
+ if (!of_machine_device_match(imx9_soc_match))
return 0;
ret = platform_driver_register(&imx9_soc_driver);
diff --git a/drivers/soc/sunxi/sunxi_mbus.c b/drivers/soc/sunxi/sunxi_mbus.c
index 1734da357ca2..8bc5f62ff258 100644
--- a/drivers/soc/sunxi/sunxi_mbus.c
+++ b/drivers/soc/sunxi/sunxi_mbus.c
@@ -118,7 +118,7 @@ static const char * const sunxi_mbus_platforms[] __initconst = {
static int __init sunxi_mbus_init(void)
{
- if (!of_device_compatible_match(of_root, sunxi_mbus_platforms))
+ if (!of_machine_compatible_match(sunxi_mbus_platforms))
return 0;
bus_register_notifier(&platform_bus_type, &sunxi_mbus_nb);
diff --git a/drivers/soundwire/debugfs.c b/drivers/soundwire/debugfs.c
index ccc9670ef77c..2905ec19b838 100644
--- a/drivers/soundwire/debugfs.c
+++ b/drivers/soundwire/debugfs.c
@@ -358,8 +358,8 @@ void sdw_slave_debugfs_init(struct sdw_slave *slave)
debugfs_create_file("go", 0200, d, slave, &cmd_go_fops);
debugfs_create_file("read_buffer", 0400, d, slave, &read_buffer_fops);
- firmware_file = NULL;
- debugfs_create_str("firmware_file", 0200, d, &firmware_file);
+ if (firmware_file)
+ debugfs_create_str("firmware_file", 0200, d, &firmware_file);
slave->debugfs = d;
}
@@ -371,10 +371,15 @@ void sdw_slave_debugfs_exit(struct sdw_slave *slave)
void sdw_debugfs_init(void)
{
+ if (!firmware_file)
+ firmware_file = kstrdup("", GFP_KERNEL);
+
sdw_debugfs_root = debugfs_create_dir("soundwire", NULL);
}
void sdw_debugfs_exit(void)
{
debugfs_remove_recursive(sdw_debugfs_root);
+ kfree(firmware_file);
+ firmware_file = NULL;
}
diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
index 9b1125556d29..91dd831d2d3b 100644
--- a/drivers/spi/spi.c
+++ b/drivers/spi/spi.c
@@ -4943,7 +4943,7 @@ static int of_spi_notify(struct notifier_block *nb, unsigned long action,
* Clear the flag before adding the device so that fw_devlink
* doesn't skip adding consumers to this device.
*/
- rd->dn->fwnode.flags &= ~FWNODE_FLAG_NOT_DEVICE;
+ fwnode_clear_flag(&rd->dn->fwnode, FWNODE_FLAG_NOT_DEVICE);
spi = of_register_spi_device(ctlr, rd->dn);
put_device(&ctlr->dev);
diff --git a/drivers/vdpa/vdpa.c b/drivers/vdpa/vdpa.c
index 34874beb0152..caf0ee5d6856 100644
--- a/drivers/vdpa/vdpa.c
+++ b/drivers/vdpa/vdpa.c
@@ -67,57 +67,20 @@ static void vdpa_dev_remove(struct device *d)
static int vdpa_dev_match(struct device *dev, const struct device_driver *drv)
{
- struct vdpa_device *vdev = dev_to_vdpa(dev);
+ int ret;
/* Check override first, and if set, only use the named driver */
- if (vdev->driver_override)
- return strcmp(vdev->driver_override, drv->name) == 0;
+ ret = device_match_driver_override(dev, drv);
+ if (ret >= 0)
+ return ret;
/* Currently devices must be supported by all vDPA bus drivers */
return 1;
}
-static ssize_t driver_override_store(struct device *dev,
- struct device_attribute *attr,
- const char *buf, size_t count)
-{
- struct vdpa_device *vdev = dev_to_vdpa(dev);
- int ret;
-
- ret = driver_set_override(dev, &vdev->driver_override, buf, count);
- if (ret)
- return ret;
-
- return count;
-}
-
-static ssize_t driver_override_show(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct vdpa_device *vdev = dev_to_vdpa(dev);
- ssize_t len;
-
- device_lock(dev);
- len = sysfs_emit(buf, "%s\n", vdev->driver_override);
- device_unlock(dev);
-
- return len;
-}
-static DEVICE_ATTR_RW(driver_override);
-
-static struct attribute *vdpa_dev_attrs[] = {
- &dev_attr_driver_override.attr,
- NULL,
-};
-
-static const struct attribute_group vdpa_dev_group = {
- .attrs = vdpa_dev_attrs,
-};
-__ATTRIBUTE_GROUPS(vdpa_dev);
-
static const struct bus_type vdpa_bus = {
.name = "vdpa",
- .dev_groups = vdpa_dev_groups,
+ .driver_override = true,
.match = vdpa_dev_match,
.probe = vdpa_dev_probe,
.remove = vdpa_dev_remove,
@@ -132,7 +95,6 @@ static void vdpa_release_dev(struct device *d)
ops->free(vdev);
ida_free(&vdpa_index_ida, vdev->index);
- kfree(vdev->driver_override);
kfree(vdev);
}
diff --git a/drivers/vfio/fsl-mc/vfio_fsl_mc.c b/drivers/vfio/fsl-mc/vfio_fsl_mc.c
index 462fae1aa538..b4c3958201b2 100644
--- a/drivers/vfio/fsl-mc/vfio_fsl_mc.c
+++ b/drivers/vfio/fsl-mc/vfio_fsl_mc.c
@@ -424,9 +424,7 @@ static int vfio_fsl_mc_bus_notifier(struct notifier_block *nb,
if (action == BUS_NOTIFY_ADD_DEVICE &&
vdev->mc_dev == mc_cont) {
- mc_dev->driver_override = kasprintf(GFP_KERNEL, "%s",
- vfio_fsl_mc_ops.name);
- if (!mc_dev->driver_override)
+ if (device_set_driver_override(dev, vfio_fsl_mc_ops.name))
dev_warn(dev, "VFIO_FSL_MC: Setting driver override for device in dprc %s failed\n",
dev_name(&mc_cont->dev));
else
diff --git a/drivers/vfio/pci/vfio_pci_core.c b/drivers/vfio/pci/vfio_pci_core.c
index d43745fe4c84..460852f79f29 100644
--- a/drivers/vfio/pci/vfio_pci_core.c
+++ b/drivers/vfio/pci/vfio_pci_core.c
@@ -1987,9 +1987,8 @@ static int vfio_pci_bus_notifier(struct notifier_block *nb,
pdev->is_virtfn && physfn == vdev->pdev) {
pci_info(vdev->pdev, "Captured SR-IOV VF %s driver_override\n",
pci_name(pdev));
- pdev->driver_override = kasprintf(GFP_KERNEL, "%s",
- vdev->vdev.ops->name);
- WARN_ON(!pdev->driver_override);
+ WARN_ON(device_set_driver_override(&pdev->dev,
+ vdev->vdev.ops->name));
} else if (action == BUS_NOTIFY_BOUND_DRIVER &&
pdev->is_virtfn && physfn == vdev->pdev) {
struct pci_driver *drv = pci_dev_driver(pdev);
diff --git a/drivers/xen/xen-pciback/pci_stub.c b/drivers/xen/xen-pciback/pci_stub.c
index e4b27aecbf05..79a2b5dfd694 100644
--- a/drivers/xen/xen-pciback/pci_stub.c
+++ b/drivers/xen/xen-pciback/pci_stub.c
@@ -598,6 +598,8 @@ static int pcistub_seize(struct pci_dev *dev,
return err;
}
+static struct pci_driver xen_pcibk_pci_driver;
+
/* Called when 'bind'. This means we must _NOT_ call pci_reset_function or
* other functions that take the sysfs lock. */
static int pcistub_probe(struct pci_dev *dev, const struct pci_device_id *id)
@@ -609,8 +611,8 @@ static int pcistub_probe(struct pci_dev *dev, const struct pci_device_id *id)
match = pcistub_match(dev);
- if ((dev->driver_override &&
- !strcmp(dev->driver_override, PCISTUB_DRIVER_NAME)) ||
+ if (device_match_driver_override(&dev->dev,
+ &xen_pcibk_pci_driver.driver) > 0 ||
match) {
if (dev->hdr_type != PCI_HEADER_TYPE_NORMAL