summaryrefslogtreecommitdiff
path: root/drivers/base
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/base')
-rw-r--r--drivers/base/base.h36
-rw-r--r--drivers/base/bus.c11
-rw-r--r--drivers/base/core.c184
-rw-r--r--drivers/base/cpu.c4
-rw-r--r--drivers/base/dd.c27
-rw-r--r--drivers/base/devcoredump.c7
-rw-r--r--drivers/base/driver.c79
-rw-r--r--drivers/base/faux.c32
-rw-r--r--drivers/base/firmware_loader/main.c3
-rw-r--r--drivers/base/firmware_loader/sysfs_upload.c8
-rw-r--r--drivers/base/isa.c12
-rw-r--r--drivers/base/memory.c2
-rw-r--r--drivers/base/pinctrl.c2
-rw-r--r--drivers/base/platform.c23
-rw-r--r--drivers/base/property.c4
-rw-r--r--drivers/base/swnode.c40
16 files changed, 238 insertions, 236 deletions
diff --git a/drivers/base/base.h b/drivers/base/base.h
index 30b416588617..a5b7abc10ff0 100644
--- a/drivers/base/base.h
+++ b/drivers/base/base.h
@@ -86,18 +86,6 @@ struct driver_private {
};
#define to_driver(obj) container_of(obj, struct driver_private, kobj)
-#ifdef CONFIG_RUST
-/**
- * struct driver_type - Representation of a Rust driver type.
- */
-struct driver_type {
- /**
- * @id: Representation of core::any::TypeId.
- */
- u8 id[16];
-} __packed;
-#endif
-
/**
* struct device_private - structure to hold the private to the driver core
* portions of the device structure.
@@ -115,7 +103,6 @@ struct driver_type {
* 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.
@@ -132,9 +119,6 @@ struct device_private {
const struct device_driver *async_driver;
char *deferred_probe_reason;
struct device *device;
-#ifdef CONFIG_RUST
- struct driver_type driver_type;
-#endif
u8 dead:1;
};
#define to_device_private_parent(obj) \
@@ -188,6 +172,20 @@ static inline int driver_match_device(const struct device_driver *drv,
return drv->bus->match ? drv->bus->match(dev, drv) : 1;
}
+static inline bool dev_has_sync_state(struct device *dev)
+{
+ struct device_driver *drv;
+
+ if (!dev)
+ return false;
+ drv = READ_ONCE(dev->driver);
+ if (drv && drv->sync_state)
+ return true;
+ if (dev->bus && dev->bus->sync_state)
+ return true;
+ return false;
+}
+
static inline void dev_sync_state(struct device *dev)
{
if (dev->bus->sync_state)
@@ -196,8 +194,10 @@ static inline void dev_sync_state(struct device *dev)
dev->driver->sync_state(dev);
}
-int driver_add_groups(const struct device_driver *drv, const struct attribute_group **groups);
-void driver_remove_groups(const struct device_driver *drv, const struct attribute_group **groups);
+int driver_add_groups(const struct device_driver *drv,
+ const struct attribute_group *const *groups);
+void driver_remove_groups(const struct device_driver *drv,
+ const struct attribute_group *const *groups);
void device_driver_detach(struct device *dev);
static inline void device_set_driver(struct device *dev, const struct device_driver *drv)
diff --git a/drivers/base/bus.c b/drivers/base/bus.c
index 8b6722ff8590..d17bd91490ee 100644
--- a/drivers/base/bus.c
+++ b/drivers/base/bus.c
@@ -544,10 +544,10 @@ static const struct attribute_group driver_override_dev_group = {
*/
int bus_add_device(struct device *dev)
{
- struct subsys_private *sp = bus_to_subsys(dev->bus);
+ struct subsys_private *sp;
int error;
- if (!sp) {
+ if (!dev->bus) {
/*
* This is a normal operation for many devices that do not
* have a bus assigned to them, just say that all went
@@ -556,6 +556,13 @@ int bus_add_device(struct device *dev)
return 0;
}
+ sp = bus_to_subsys(dev->bus);
+ if (!sp) {
+ pr_err("%s: cannot add device '%s' to unregistered bus '%s'\n",
+ __func__, dev_name(dev), dev->bus->name);
+ return -EINVAL;
+ }
+
/*
* Reference in sp is now incremented and will be dropped when
* the device is removed from the bus
diff --git a/drivers/base/core.c b/drivers/base/core.c
index bd2ddf2aab50..4d026682944f 100644
--- a/drivers/base/core.c
+++ b/drivers/base/core.c
@@ -235,6 +235,79 @@ static void __fw_devlink_pickup_dangling_consumers(struct fwnode_handle *fwnode,
__fw_devlink_pickup_dangling_consumers(child, new_sup);
}
+static void fw_devlink_pickup_dangling_consumers(struct device *dev)
+{
+ struct fwnode_handle *child;
+
+ guard(mutex)(&fwnode_link_lock);
+
+ fwnode_for_each_available_child_node(dev->fwnode, child)
+ __fw_devlink_pickup_dangling_consumers(child, dev->fwnode);
+ __fw_devlink_link_to_consumers(dev);
+}
+
+/**
+ * fw_devlink_refresh_fwnode - Recheck the tree under this firmware node
+ * @fwnode: The fwnode under which the fwnode tree has changed
+ *
+ * This function is mainly meant to adjust the supplier/consumer dependencies
+ * after a fwnode tree overlay has occurred.
+ */
+void fw_devlink_refresh_fwnode(struct fwnode_handle *fwnode)
+{
+ struct device *dev;
+
+ /*
+ * Find the closest ancestor fwnode that has been converted to a device
+ * that can bind to a driver (bus device).
+ */
+ fwnode_handle_get(fwnode);
+ do {
+ if (fwnode_test_flag(fwnode, FWNODE_FLAG_NOT_DEVICE))
+ continue;
+
+ dev = get_dev_from_fwnode(fwnode);
+ if (!dev)
+ continue;
+
+ if (dev->bus)
+ break;
+
+ put_device(dev);
+ } while ((fwnode = fwnode_get_next_parent(fwnode)));
+
+ /*
+ * If none of the ancestor fwnodes have (yet) been converted to a device
+ * that can bind to a driver, there's nothing to fix up.
+ */
+ if (!fwnode)
+ return;
+
+ WARN(device_is_bound(dev) && dev->links.status != DL_DEV_DRIVER_BOUND,
+ "Don't multithread overlaying and probing the same device!\n");
+
+ /*
+ * If the device has already bound to a driver, then we need to redo
+ * some of the work that was done after the device was bound to a
+ * driver. If the device hasn't bound to a driver, running things too
+ * soon would incorrectly pick up consumers that it shouldn't.
+ */
+ if (dev->links.status == DL_DEV_DRIVER_BOUND) {
+ fw_devlink_pickup_dangling_consumers(dev);
+ /*
+ * Some of dangling consumers could have been put previously in
+ * the deferred probe list due to the unavailability of their
+ * suppliers. Those consumers have been picked up and some of
+ * their suppliers links have been updated. Time to re-try their
+ * probe sequence.
+ */
+ driver_deferred_probe_trigger();
+ }
+
+ put_device(dev);
+ fwnode_handle_put(fwnode);
+}
+
static DEFINE_MUTEX(device_links_lock);
DEFINE_STATIC_SRCU(device_links_srcu);
@@ -422,7 +495,7 @@ void device_pm_move_to_tail(struct device *dev)
#define to_devlink(dev) container_of((dev), struct device_link, link_dev)
static ssize_t status_show(struct device *dev,
- struct device_attribute *attr, char *buf)
+ const struct device_attribute *attr, char *buf)
{
const char *output;
@@ -452,10 +525,10 @@ static ssize_t status_show(struct device *dev,
return sysfs_emit(buf, "%s\n", output);
}
-static DEVICE_ATTR_RO(status);
+static const DEVICE_ATTR_RO(status);
static ssize_t auto_remove_on_show(struct device *dev,
- struct device_attribute *attr, char *buf)
+ const struct device_attribute *attr, char *buf)
{
struct device_link *link = to_devlink(dev);
const char *output;
@@ -469,27 +542,27 @@ static ssize_t auto_remove_on_show(struct device *dev,
return sysfs_emit(buf, "%s\n", output);
}
-static DEVICE_ATTR_RO(auto_remove_on);
+static const DEVICE_ATTR_RO(auto_remove_on);
static ssize_t runtime_pm_show(struct device *dev,
- struct device_attribute *attr, char *buf)
+ const struct device_attribute *attr, char *buf)
{
struct device_link *link = to_devlink(dev);
return sysfs_emit(buf, "%d\n", device_link_test(link, DL_FLAG_PM_RUNTIME));
}
-static DEVICE_ATTR_RO(runtime_pm);
+static const DEVICE_ATTR_RO(runtime_pm);
static ssize_t sync_state_only_show(struct device *dev,
- struct device_attribute *attr, char *buf)
+ const struct device_attribute *attr, char *buf)
{
struct device_link *link = to_devlink(dev);
return sysfs_emit(buf, "%d\n", device_link_test(link, DL_FLAG_SYNC_STATE_ONLY));
}
-static DEVICE_ATTR_RO(sync_state_only);
+static const DEVICE_ATTR_RO(sync_state_only);
-static struct attribute *devlink_attrs[] = {
+static const struct attribute *const devlink_attrs[] = {
&dev_attr_status.attr,
&dev_attr_auto_remove_on.attr,
&dev_attr_runtime_pm.attr,
@@ -1011,7 +1084,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) ||
+ return (fw_devlink_best_effort && dev_can_match(dev)) ||
(dev->fwnode && fwnode_test_flag(dev->fwnode, FWNODE_FLAG_BEST_EFFORT));
}
@@ -1079,7 +1152,7 @@ int device_links_check_suppliers(struct device *dev)
if (dev_is_best_effort(dev) &&
device_link_test(link, DL_FLAG_INFERRED) &&
- !link->supplier->can_match) {
+ !dev_can_match(link->supplier)) {
ret = -EAGAIN;
continue;
}
@@ -1123,7 +1196,7 @@ static void __device_links_queue_sync_state(struct device *dev,
if (!dev_has_sync_state(dev))
return;
- if (dev->state_synced)
+ if (dev_state_synced(dev))
return;
list_for_each_entry(link, &dev->links.consumers, s_node) {
@@ -1138,7 +1211,7 @@ static void __device_links_queue_sync_state(struct device *dev,
* than once. This can happen if new consumers get added to the device
* and probed before the list is flushed.
*/
- dev->state_synced = true;
+ dev_set_state_synced(dev);
if (WARN_ON(!list_empty(&dev->links.defer_sync)))
return;
@@ -1233,7 +1306,7 @@ static void device_link_drop_managed(struct device_link *link)
}
static ssize_t waiting_for_supplier_show(struct device *dev,
- struct device_attribute *attr,
+ const struct device_attribute *attr,
char *buf)
{
bool val;
@@ -1244,7 +1317,7 @@ static ssize_t waiting_for_supplier_show(struct device *dev,
device_unlock(dev);
return sysfs_emit(buf, "%u\n", val);
}
-static DEVICE_ATTR_RO(waiting_for_supplier);
+static const DEVICE_ATTR_RO(waiting_for_supplier);
/**
* device_links_force_bind - Prepares device to be force bound
@@ -1312,16 +1385,8 @@ void device_links_driver_bound(struct device *dev)
* child firmware node.
*/
if (dev->fwnode && dev->fwnode->dev == dev) {
- struct fwnode_handle *child;
-
fwnode_links_purge_suppliers(dev->fwnode);
-
- guard(mutex)(&fwnode_link_lock);
-
- fwnode_for_each_available_child_node(dev->fwnode, child)
- __fw_devlink_pickup_dangling_consumers(child,
- dev->fwnode);
- __fw_devlink_link_to_consumers(dev);
+ fw_devlink_pickup_dangling_consumers(dev);
}
device_remove_file(dev, &dev_attr_waiting_for_supplier);
@@ -1370,7 +1435,7 @@ void device_links_driver_bound(struct device *dev)
} else if (dev_is_best_effort(dev) &&
device_link_test(link, DL_FLAG_INFERRED) &&
link->status != DL_STATE_CONSUMER_PROBE &&
- !link->supplier->can_match) {
+ !dev_can_match(link->supplier)) {
/*
* When dev_is_best_effort() is true, we ignore device
* links to suppliers that don't have a driver. If the
@@ -1435,7 +1500,8 @@ static void __device_links_no_driver(struct device *dev)
if (link->supplier->links.status == DL_DEV_DRIVER_BOUND) {
WRITE_ONCE(link->status, DL_STATE_AVAILABLE);
} else {
- WARN_ON(!device_link_test(link, DL_FLAG_SYNC_STATE_ONLY));
+ WARN_ON(link->supplier->links.status != DL_DEV_UNBINDING &&
+ !device_link_test(link, DL_FLAG_SYNC_STATE_ONLY));
WRITE_ONCE(link->status, DL_STATE_DORMANT);
}
}
@@ -1758,7 +1824,7 @@ static int fw_devlink_no_driver(struct device *dev, void *data)
{
struct device_link *link = to_devlink(dev);
- if (!link->supplier->can_match)
+ if (!dev_can_match(link->supplier))
fw_devlink_relax_link(link);
return 0;
@@ -1779,7 +1845,7 @@ static int fw_devlink_dev_sync_state(struct device *dev, void *data)
struct device *sup = link->supplier;
if (!device_link_test(link, DL_FLAG_MANAGED) ||
- link->status == DL_STATE_ACTIVE || sup->state_synced ||
+ link->status == DL_STATE_ACTIVE || dev_state_synced(sup) ||
!dev_has_sync_state(sup))
return 0;
@@ -1793,7 +1859,7 @@ static int fw_devlink_dev_sync_state(struct device *dev, void *data)
return 0;
dev_warn(sup, "Timed out. Forcing sync_state()\n");
- sup->state_synced = true;
+ dev_set_state_synced(sup);
get_device(sup);
list_add_tail(&sup->links.defer_sync, data);
@@ -2419,9 +2485,11 @@ static ssize_t dev_attr_show(struct kobject *kobj, struct attribute *attr,
if (dev_attr->show)
ret = dev_attr->show(dev, dev_attr, buf);
+ else if (dev_attr->show_const)
+ ret = dev_attr->show_const(dev, dev_attr, buf);
if (ret >= (ssize_t)PAGE_SIZE) {
- printk("dev_attr_show: %pS returned bad count\n",
- dev_attr->show);
+ printk("dev_attr_show: %pS/%pS returned bad count\n",
+ dev_attr->show, dev_attr->show_const);
}
return ret;
}
@@ -2435,6 +2503,8 @@ static ssize_t dev_attr_store(struct kobject *kobj, struct attribute *attr,
if (dev_attr->store)
ret = dev_attr->store(dev, dev_attr, buf, count);
+ else if (dev_attr->store_const)
+ ret = dev_attr->store_const(dev, dev_attr, buf, count);
return ret;
}
@@ -2722,7 +2792,7 @@ static const struct kset_uevent_ops device_uevent_ops = {
.uevent = dev_uevent,
};
-static ssize_t uevent_show(struct device *dev, struct device_attribute *attr,
+static ssize_t uevent_show(struct device *dev, const struct device_attribute *attr,
char *buf)
{
struct kobject *top_kobj;
@@ -2765,7 +2835,7 @@ out:
return len;
}
-static ssize_t uevent_store(struct device *dev, struct device_attribute *attr,
+static ssize_t uevent_store(struct device *dev, const struct device_attribute *attr,
const char *buf, size_t count)
{
int rc;
@@ -2779,20 +2849,20 @@ static ssize_t uevent_store(struct device *dev, struct device_attribute *attr,
return count;
}
-static DEVICE_ATTR_RW(uevent);
+static const DEVICE_ATTR_RW(uevent);
-static ssize_t online_show(struct device *dev, struct device_attribute *attr,
+static ssize_t online_show(struct device *dev, const struct device_attribute *attr,
char *buf)
{
bool val;
device_lock(dev);
- val = !dev->offline;
+ val = !dev_offline(dev);
device_unlock(dev);
return sysfs_emit(buf, "%u\n", val);
}
-static ssize_t online_store(struct device *dev, struct device_attribute *attr,
+static ssize_t online_store(struct device *dev, const struct device_attribute *attr,
const char *buf, size_t count)
{
bool val;
@@ -2810,9 +2880,9 @@ static ssize_t online_store(struct device *dev, struct device_attribute *attr,
unlock_device_hotplug();
return ret < 0 ? ret : count;
}
-static DEVICE_ATTR_RW(online);
+static const DEVICE_ATTR_RW(online);
-static ssize_t removable_show(struct device *dev, struct device_attribute *attr,
+static ssize_t removable_show(struct device *dev, const struct device_attribute *attr,
char *buf)
{
const char *loc;
@@ -2829,7 +2899,7 @@ static ssize_t removable_show(struct device *dev, struct device_attribute *attr,
}
return sysfs_emit(buf, "%s\n", loc);
}
-static DEVICE_ATTR_RO(removable);
+static const DEVICE_ATTR_RO(removable);
int device_add_groups(struct device *dev,
const struct attribute_group *const *groups)
@@ -2913,7 +2983,7 @@ static int device_add_attrs(struct device *dev)
if (error)
goto err_remove_type_groups;
- if (device_supports_offline(dev) && !dev->offline_disabled) {
+ if (device_supports_offline(dev) && !dev_offline_disabled(dev)) {
error = device_create_file(dev, &dev_attr_online);
if (error)
goto err_remove_dev_groups;
@@ -2980,12 +3050,12 @@ static void device_remove_attrs(struct device *dev)
device_remove_groups(dev, class->dev_groups);
}
-static ssize_t dev_show(struct device *dev, struct device_attribute *attr,
+static ssize_t dev_show(struct device *dev, const struct device_attribute *attr,
char *buf)
{
return print_dev_t(buf, dev->devt);
}
-static DEVICE_ATTR_RO(dev);
+static const DEVICE_ATTR_RO(dev);
/* /sys/devices/ */
struct kset *devices_kset;
@@ -3047,10 +3117,10 @@ int device_create_file(struct device *dev,
int error = 0;
if (dev) {
- WARN(((attr->attr.mode & S_IWUGO) && !attr->store),
+ WARN(((attr->attr.mode & S_IWUGO) && !(attr->store || attr->store_const)),
"Attribute %s: write permission without 'store'\n",
attr->attr.name);
- WARN(((attr->attr.mode & S_IRUGO) && !attr->show),
+ WARN(((attr->attr.mode & S_IRUGO) && !(attr->show || attr->show_const)),
"Attribute %s: read permission without 'show'\n",
attr->attr.name);
error = sysfs_create_file(&dev->kobj, &attr->attr);
@@ -3170,11 +3240,7 @@ void device_initialize(struct device *dev)
INIT_LIST_HEAD(&dev->links.suppliers);
INIT_LIST_HEAD(&dev->links.defer_sync);
dev->links.status = DL_DEV_NO_DRIVER;
-#if defined(CONFIG_ARCH_HAS_SYNC_DMA_FOR_DEVICE) || \
- defined(CONFIG_ARCH_HAS_SYNC_DMA_FOR_CPU) || \
- defined(CONFIG_ARCH_HAS_SYNC_DMA_FOR_CPU_ALL)
- dev->dma_coherent = dma_default_coherent;
-#endif
+ dev_assign_dma_coherent(dev, dma_default_coherent);
swiotlb_dev_init(dev);
}
EXPORT_SYMBOL_GPL(device_initialize);
@@ -3710,7 +3776,7 @@ int device_add(struct device *dev)
* match with any driver, don't block its consumers from probing in
* case the consumer device is able to operate without this supplier.
*/
- if (dev->fwnode && fw_devlink_drv_reg_done && !dev->can_match)
+ if (dev->fwnode && fw_devlink_drv_reg_done && !dev_can_match(dev))
fw_devlink_unblock_consumers(dev);
if (parent)
@@ -4180,7 +4246,7 @@ static int device_check_offline(struct device *dev, void *not_used)
if (ret)
return ret;
- return device_supports_offline(dev) && !dev->offline ? -EBUSY : 0;
+ return device_supports_offline(dev) && !dev_offline(dev) ? -EBUSY : 0;
}
/**
@@ -4198,7 +4264,7 @@ int device_offline(struct device *dev)
{
int ret;
- if (dev->offline_disabled)
+ if (dev_offline_disabled(dev))
return -EPERM;
ret = device_for_each_child(dev, NULL, device_check_offline);
@@ -4207,13 +4273,13 @@ int device_offline(struct device *dev)
device_lock(dev);
if (device_supports_offline(dev)) {
- if (dev->offline) {
+ if (dev_offline(dev)) {
ret = 1;
} else {
ret = dev->bus->offline(dev);
if (!ret) {
kobject_uevent(&dev->kobj, KOBJ_OFFLINE);
- dev->offline = true;
+ dev_set_offline(dev);
}
}
}
@@ -4238,11 +4304,11 @@ int device_online(struct device *dev)
device_lock(dev);
if (device_supports_offline(dev)) {
- if (dev->offline) {
+ if (dev_offline(dev)) {
ret = dev->bus->online(dev);
if (!ret) {
kobject_uevent(&dev->kobj, KOBJ_ONLINE);
- dev->offline = false;
+ dev_clear_offline(dev);
}
} else {
ret = 1;
@@ -4716,7 +4782,7 @@ static int device_attrs_change_owner(struct device *dev, kuid_t kuid,
if (error)
return error;
- if (device_supports_offline(dev) && !dev->offline_disabled) {
+ if (device_supports_offline(dev) && !dev_offline_disabled(dev)) {
/* Change online device attributes of @dev to @kuid/@kgid. */
error = sysfs_file_change_owner(kobj, dev_attr_online.attr.name,
kuid, kgid);
@@ -5283,7 +5349,7 @@ void device_set_of_node_from_dev(struct device *dev, const struct device *dev2)
{
of_node_put(dev->of_node);
dev->of_node = of_node_get(dev2->of_node);
- dev->of_node_reused = true;
+ dev_set_of_node_reused(dev);
}
EXPORT_SYMBOL_GPL(device_set_of_node_from_dev);
diff --git a/drivers/base/cpu.c b/drivers/base/cpu.c
index 875abdc9942e..19d288a3c80c 100644
--- a/drivers/base/cpu.c
+++ b/drivers/base/cpu.c
@@ -422,8 +422,8 @@ int register_cpu(struct cpu *cpu, int num)
cpu->dev.id = num;
cpu->dev.bus = &cpu_subsys;
cpu->dev.release = cpu_device_release;
- cpu->dev.offline_disabled = !cpu->hotpluggable;
- cpu->dev.offline = !cpu_online(num);
+ dev_assign_offline_disabled(&cpu->dev, !cpu->hotpluggable);
+ dev_assign_offline(&cpu->dev, !cpu_online(num));
cpu->dev.of_node = of_get_cpu_node(num, NULL);
cpu->dev.groups = common_cpu_attr_groups;
if (cpu->hotpluggable)
diff --git a/drivers/base/dd.c b/drivers/base/dd.c
index 1dc1e3528043..60c005223844 100644
--- a/drivers/base/dd.c
+++ b/drivers/base/dd.c
@@ -132,7 +132,7 @@ static DECLARE_WORK(deferred_probe_work, deferred_probe_work_func);
void driver_deferred_probe_add(struct device *dev)
{
- if (!dev->can_match)
+ if (!dev_can_match(dev))
return;
mutex_lock(&deferred_probe_mutex);
@@ -323,12 +323,11 @@ void deferred_probe_extend_timeout(void)
* If the work hasn't been queued yet or if the work expired, don't
* start a new one.
*/
- if (cancel_delayed_work(&deferred_probe_timeout_work)) {
- schedule_delayed_work(&deferred_probe_timeout_work,
- driver_deferred_probe_timeout * HZ);
+ if (delayed_work_pending(&deferred_probe_timeout_work) &&
+ mod_delayed_work(system_percpu_wq, &deferred_probe_timeout_work,
+ secs_to_jiffies(driver_deferred_probe_timeout)))
pr_debug("Extended deferred probe timeout by %d secs\n",
driver_deferred_probe_timeout);
- }
}
/**
@@ -569,12 +568,10 @@ static ssize_t state_synced_store(struct device *dev,
return -EINVAL;
device_lock(dev);
- if (!dev->state_synced) {
- dev->state_synced = true;
+ if (!dev_test_and_set_state_synced(dev))
dev_sync_state(dev);
- } else {
+ else
ret = -EINVAL;
- }
device_unlock(dev);
return ret ? ret : count;
@@ -586,7 +583,7 @@ static ssize_t state_synced_show(struct device *dev,
bool val;
device_lock(dev);
- val = dev->state_synced;
+ val = dev_state_synced(dev);
device_unlock(dev);
return sysfs_emit(buf, "%u\n", val);
@@ -595,9 +592,9 @@ static DEVICE_ATTR_RW(state_synced);
static void device_unbind_cleanup(struct device *dev)
{
- devres_release_all(dev);
if (dev->driver->p_cb.post_unbind_rust)
dev->driver->p_cb.post_unbind_rust(dev);
+ devres_release_all(dev);
arch_teardown_dma_ops(dev);
kfree(dev->dma_range_map);
dev->dma_range_map = NULL;
@@ -849,14 +846,14 @@ static int __driver_probe_device(const struct device_driver *drv, struct device
return dev_err_probe(dev, -EPROBE_DEFER, "Device not ready to probe\n");
/*
- * Set can_match = true after calling dev_ready_to_probe(), so
+ * Call dev_set_can_match() after calling dev_ready_to_probe(), so
* driver_deferred_probe_add() won't actually add the device to the
* deferred probe list when dev_ready_to_probe() returns false.
*
* When dev_ready_to_probe() returns false, it means that device_add()
* will do another probe() attempt for us.
*/
- dev->can_match = true;
+ dev_set_can_match(dev);
dev_dbg(dev, "bus: '%s': %s: matched device with driver %s\n",
drv->bus->name, __func__, drv->name);
@@ -1002,7 +999,7 @@ static int __device_attach_driver(struct device_driver *drv, void *_data)
return 0;
} else if (ret == -EPROBE_DEFER) {
dev_dbg(dev, "Device match requests probe deferral\n");
- dev->can_match = true;
+ dev_set_can_match(dev);
driver_deferred_probe_add(dev);
/*
* Device can't match with a driver right now, so don't attempt
@@ -1254,7 +1251,7 @@ static int __driver_attach(struct device *dev, void *data)
return 0;
} else if (ret == -EPROBE_DEFER) {
dev_dbg(dev, "Device match requests probe deferral\n");
- dev->can_match = true;
+ dev_set_can_match(dev);
driver_deferred_probe_add(dev);
/*
* Driver could not match with device, but may match with
diff --git a/drivers/base/devcoredump.c b/drivers/base/devcoredump.c
index 7e4a491bf15e..8bb1763083dd 100644
--- a/drivers/base/devcoredump.c
+++ b/drivers/base/devcoredump.c
@@ -471,10 +471,3 @@ static int __init devcoredump_init(void)
return class_register(&devcd_class);
}
__initcall(devcoredump_init);
-
-static void __exit devcoredump_exit(void)
-{
- class_for_each_device(&devcd_class, NULL, NULL, devcd_free);
- class_unregister(&devcd_class);
-}
-__exitcall(devcoredump_exit);
diff --git a/drivers/base/driver.c b/drivers/base/driver.c
index 8ab010ddf709..5d9c39081339 100644
--- a/drivers/base/driver.c
+++ b/drivers/base/driver.c
@@ -31,81 +31,6 @@ static struct device *next_device(struct klist_iter *i)
}
/**
- * driver_set_override() - Helper to set or clear driver override.
- * @dev: Device to change
- * @override: Address of string to change (e.g. &device->driver_override);
- * The contents will be freed and hold newly allocated override.
- * @s: NUL-terminated string, new driver name to force a match, pass empty
- * string to clear it ("" or "\n", where the latter is only for sysfs
- * interface).
- * @len: length of @s
- *
- * Helper to set or clear driver override in a device, intended for the cases
- * when the driver_override field is allocated by driver/bus code.
- *
- * Returns: 0 on success or a negative error code on failure.
- */
-int driver_set_override(struct device *dev, const char **override,
- const char *s, size_t len)
-{
- const char *new, *old;
- char *cp;
-
- if (!override || !s)
- return -EINVAL;
-
- /*
- * The stored value will be used in sysfs show callback (sysfs_emit()),
- * which has a length limit of PAGE_SIZE and adds a trailing newline.
- * Thus we can store one character less to avoid truncation during sysfs
- * show.
- */
- if (len >= (PAGE_SIZE - 1))
- return -EINVAL;
-
- /*
- * Compute the real length of the string in case userspace sends us a
- * bunch of \0 characters like python likes to do.
- */
- len = strlen(s);
-
- if (!len) {
- /* Empty string passed - clear override */
- device_lock(dev);
- old = *override;
- *override = NULL;
- device_unlock(dev);
- kfree(old);
-
- return 0;
- }
-
- cp = strnchr(s, len, '\n');
- if (cp)
- len = cp - s;
-
- new = kstrndup(s, len, GFP_KERNEL);
- if (!new)
- return -ENOMEM;
-
- device_lock(dev);
- old = *override;
- if (cp != s) {
- *override = new;
- } else {
- /* "\n" passed - clear override */
- kfree(new);
- *override = NULL;
- }
- device_unlock(dev);
-
- kfree(old);
-
- return 0;
-}
-EXPORT_SYMBOL_GPL(driver_set_override);
-
-/**
* driver_for_each_device - Iterator for devices bound to a driver.
* @drv: Driver we're iterating.
* @start: Device to begin with
@@ -203,13 +128,13 @@ void driver_remove_file(const struct device_driver *drv,
EXPORT_SYMBOL_GPL(driver_remove_file);
int driver_add_groups(const struct device_driver *drv,
- const struct attribute_group **groups)
+ const struct attribute_group *const *groups)
{
return sysfs_create_groups(&drv->p->kobj, groups);
}
void driver_remove_groups(const struct device_driver *drv,
- const struct attribute_group **groups)
+ const struct attribute_group *const *groups)
{
sysfs_remove_groups(&drv->p->kobj, groups);
}
diff --git a/drivers/base/faux.c b/drivers/base/faux.c
index fb3e42f21362..a8329f88222e 100644
--- a/drivers/base/faux.c
+++ b/drivers/base/faux.c
@@ -133,6 +133,9 @@ struct faux_device *faux_device_create_with_groups(const char *name,
struct device *dev;
int ret;
+ if (!faux_bus_root)
+ return NULL;
+
faux_obj = kzalloc_obj(*faux_obj);
if (!faux_obj)
return NULL;
@@ -232,34 +235,29 @@ EXPORT_SYMBOL_GPL(faux_device_destroy);
int __init faux_bus_init(void)
{
+ struct device *root;
int ret;
- faux_bus_root = kzalloc_obj(*faux_bus_root);
- if (!faux_bus_root)
- return -ENOMEM;
-
- dev_set_name(faux_bus_root, "faux");
-
- ret = device_register(faux_bus_root);
- if (ret) {
- put_device(faux_bus_root);
- return ret;
- }
+ root = root_device_register("faux");
+ if (IS_ERR(root))
+ return PTR_ERR(root);
ret = bus_register(&faux_bus_type);
if (ret)
- goto error_bus;
+ goto err_deregister_root;
ret = driver_register(&faux_driver);
if (ret)
- goto error_driver;
+ goto err_deregister_bus;
- return ret;
+ faux_bus_root = root;
+
+ return 0;
-error_driver:
+err_deregister_bus:
bus_unregister(&faux_bus_type);
+err_deregister_root:
+ root_device_unregister(root);
-error_bus:
- device_unregister(faux_bus_root);
return ret;
}
diff --git a/drivers/base/firmware_loader/main.c b/drivers/base/firmware_loader/main.c
index a11b30dda23b..c96312ac2be7 100644
--- a/drivers/base/firmware_loader/main.c
+++ b/drivers/base/firmware_loader/main.c
@@ -1503,9 +1503,10 @@ static void device_cache_fw_images(void)
mutex_lock(&fw_lock);
fwc->state = FW_LOADER_START_CACHE;
- dpm_for_each_dev(NULL, dev_cache_fw_image);
mutex_unlock(&fw_lock);
+ dpm_for_each_dev(NULL, dev_cache_fw_image);
+
/* wait for completion of caching firmware for all devices */
async_synchronize_full_domain(&fw_cache_domain);
diff --git a/drivers/base/firmware_loader/sysfs_upload.c b/drivers/base/firmware_loader/sysfs_upload.c
index f59a7856934c..efc33294212f 100644
--- a/drivers/base/firmware_loader/sysfs_upload.c
+++ b/drivers/base/firmware_loader/sysfs_upload.c
@@ -343,7 +343,6 @@ firmware_upload_register(struct module *module, struct device *parent,
goto free_fw_upload_priv;
}
fw_upload->priv = fw_sysfs;
- fw_sysfs->fw_upload_priv = fw_upload_priv;
fw_dev = &fw_sysfs->dev;
ret = alloc_lookup_fw_priv(name, &fw_cache, &fw_priv, NULL, 0, 0,
@@ -351,10 +350,12 @@ firmware_upload_register(struct module *module, struct device *parent,
if (ret != 0) {
if (ret > 0)
ret = -EINVAL;
- goto free_fw_sysfs;
+ put_device(fw_dev);
+ goto free_fw_upload_priv;
}
fw_priv->is_paged_buf = true;
fw_sysfs->fw_priv = fw_priv;
+ fw_sysfs->fw_upload_priv = fw_upload_priv;
ret = device_add(fw_dev);
if (ret) {
@@ -365,9 +366,6 @@ firmware_upload_register(struct module *module, struct device *parent,
return fw_upload;
-free_fw_sysfs:
- kfree(fw_sysfs);
-
free_fw_upload_priv:
kfree(fw_upload_priv);
diff --git a/drivers/base/isa.c b/drivers/base/isa.c
index fd076cc63cb6..5887e4211f80 100644
--- a/drivers/base/isa.c
+++ b/drivers/base/isa.c
@@ -11,9 +11,7 @@
#include <linux/dma-mapping.h>
#include <linux/isa.h>
-static struct device isa_bus = {
- .init_name = "isa"
-};
+static struct device *isa_bus;
struct isa_dev {
struct device dev;
@@ -131,7 +129,7 @@ int isa_register_driver(struct isa_driver *isa_driver, unsigned int ndev)
break;
}
- isa_dev->dev.parent = &isa_bus;
+ isa_dev->dev.parent = isa_bus;
isa_dev->dev.bus = &isa_bus_type;
dev_set_name(&isa_dev->dev, "%s.%u",
@@ -169,9 +167,11 @@ static int __init isa_bus_init(void)
error = bus_register(&isa_bus_type);
if (!error) {
- error = device_register(&isa_bus);
- if (error)
+ isa_bus = root_device_register("isa");
+ if (IS_ERR(isa_bus)) {
+ error = PTR_ERR(isa_bus);
bus_unregister(&isa_bus_type);
+ }
}
return error;
}
diff --git a/drivers/base/memory.c b/drivers/base/memory.c
index 6981b55d582a..11d57cfa8d72 100644
--- a/drivers/base/memory.c
+++ b/drivers/base/memory.c
@@ -697,7 +697,7 @@ static int __add_memory_block(struct memory_block *memory)
memory->dev.id = memory->start_section_nr / sections_per_block;
memory->dev.release = memory_block_release;
memory->dev.groups = memory_memblk_attr_groups;
- memory->dev.offline = memory->state == MEM_OFFLINE;
+ dev_assign_offline(&memory->dev, memory->state == MEM_OFFLINE);
ret = device_register(&memory->dev);
if (ret) {
diff --git a/drivers/base/pinctrl.c b/drivers/base/pinctrl.c
index 6e250272c843..0bbc83231234 100644
--- a/drivers/base/pinctrl.c
+++ b/drivers/base/pinctrl.c
@@ -24,7 +24,7 @@ int pinctrl_bind_pins(struct device *dev)
{
int ret;
- if (dev->of_node_reused)
+ if (dev_of_node_reused(dev))
return 0;
dev->pins = devm_kzalloc(dev, sizeof(*(dev->pins)), GFP_KERNEL);
diff --git a/drivers/base/platform.c b/drivers/base/platform.c
index a19dd22deef2..fb9120b0bcfe 100644
--- a/drivers/base/platform.c
+++ b/drivers/base/platform.c
@@ -870,7 +870,7 @@ struct platform_device *platform_device_register_full(const struct platform_devi
pdev->dev.parent = pdevinfo->parent;
pdev->dev.fwnode = pdevinfo->fwnode;
pdev->dev.of_node = of_node_get(to_of_node(pdev->dev.fwnode));
- pdev->dev.of_node_reused = pdevinfo->of_node_reused;
+ dev_assign_of_node_reused(&pdev->dev, pdevinfo->of_node_reused);
if (pdevinfo->dma_mask) {
pdev->platform_dma_mask = pdevinfo->dma_mask;
@@ -915,11 +915,14 @@ EXPORT_SYMBOL_GPL(platform_device_register_full);
* __platform_driver_register - register a driver for platform-level devices
* @drv: platform driver structure
* @owner: owning module/driver
+ * @mod_name: module name string
*/
-int __platform_driver_register(struct platform_driver *drv, struct module *owner)
+int __platform_driver_register(struct platform_driver *drv, struct module *owner,
+ const char *mod_name)
{
drv->driver.owner = owner;
drv->driver.bus = &platform_bus_type;
+ drv->driver.mod_name = mod_name;
return driver_register(&drv->driver);
}
@@ -952,6 +955,7 @@ static int is_bound_to_driver(struct device *dev, void *driver)
* @drv: platform driver structure
* @probe: the driver probe routine, probably from an __init section
* @module: module which will be the owner of the driver
+ * @mod_name: module name string
*
* Use this instead of platform_driver_register() when you know the device
* is not hotpluggable and has already been registered, and you want to
@@ -969,7 +973,8 @@ static int is_bound_to_driver(struct device *dev, void *driver)
*/
int __init_or_module __platform_driver_probe(struct platform_driver *drv,
int (*probe)(struct platform_device *),
- struct module *module)
+ struct module *module,
+ const char *mod_name)
{
int retval;
@@ -997,7 +1002,7 @@ int __init_or_module __platform_driver_probe(struct platform_driver *drv,
/* temporary section violation during probe() */
drv->probe = probe;
- retval = __platform_driver_register(drv, module);
+ retval = __platform_driver_register(drv, module, mod_name);
if (retval)
return retval;
@@ -1025,6 +1030,7 @@ EXPORT_SYMBOL_GPL(__platform_driver_probe);
* @data: platform specific data for this platform device
* @size: size of platform specific data
* @module: module which will be the owner of the driver
+ * @mod_name: module name string
*
* Use this in legacy-style modules that probe hardware directly and
* register a single platform device and corresponding platform driver.
@@ -1035,7 +1041,7 @@ 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)
+ const void *data, size_t size, struct module *module, const char *mod_name)
{
struct platform_device *pdev;
int error;
@@ -1058,7 +1064,7 @@ __platform_create_bundle(struct platform_driver *driver,
if (error)
goto err_pdev_put;
- error = __platform_driver_probe(driver, probe, module);
+ error = __platform_driver_probe(driver, probe, module, mod_name);
if (error)
goto err_pdev_del;
@@ -1078,6 +1084,7 @@ EXPORT_SYMBOL_GPL(__platform_create_bundle);
* @drivers: an array of drivers to register
* @count: the number of drivers to register
* @owner: module owning the drivers
+ * @mod_name: module name string
*
* Registers platform drivers specified by an array. On failure to register a
* driver, all previously registered drivers will be unregistered. Callers of
@@ -1087,7 +1094,7 @@ EXPORT_SYMBOL_GPL(__platform_create_bundle);
* Returns: 0 on success or a negative error code on failure.
*/
int __platform_register_drivers(struct platform_driver * const *drivers,
- unsigned int count, struct module *owner)
+ unsigned int count, struct module *owner, const char *mod_name)
{
unsigned int i;
int err;
@@ -1095,7 +1102,7 @@ int __platform_register_drivers(struct platform_driver * const *drivers,
for (i = 0; i < count; i++) {
pr_debug("registering platform driver %ps\n", drivers[i]);
- err = __platform_driver_register(drivers[i], owner);
+ err = __platform_driver_register(drivers[i], owner, mod_name);
if (err < 0) {
pr_err("failed to register platform driver %ps: %d\n",
drivers[i], err);
diff --git a/drivers/base/property.c b/drivers/base/property.c
index 8e0148a37fff..e08eadd66f4f 100644
--- a/drivers/base/property.c
+++ b/drivers/base/property.c
@@ -1277,8 +1277,10 @@ fwnode_graph_get_endpoint_by_id(const struct fwnode_handle *fwnode,
if (fwnode_ep.port != port)
continue;
- if (fwnode_ep.id == endpoint)
+ if (fwnode_ep.id == endpoint) {
+ fwnode_handle_put(best_ep);
return ep;
+ }
if (!endpoint_next)
continue;
diff --git a/drivers/base/swnode.c b/drivers/base/swnode.c
index a19f8f722bc8..869228a65cb3 100644
--- a/drivers/base/swnode.c
+++ b/drivers/base/swnode.c
@@ -374,20 +374,28 @@ EXPORT_SYMBOL_GPL(property_entries_free);
/* -------------------------------------------------------------------------- */
/* fwnode operations */
-static struct fwnode_handle *software_node_get(struct fwnode_handle *fwnode)
+static struct swnode *swnode_get(struct swnode *swnode)
{
- struct swnode *swnode = to_swnode(fwnode);
-
kobject_get(&swnode->kobj);
+ return swnode;
+}
+
+static void swnode_put(struct swnode *swnode)
+{
+ kobject_put(&swnode->kobj);
+}
+
+static struct fwnode_handle *software_node_get(struct fwnode_handle *fwnode)
+{
+ struct swnode *swnode = swnode_get(to_swnode(fwnode));
+
return &swnode->fwnode;
}
static void software_node_put(struct fwnode_handle *fwnode)
{
- struct swnode *swnode = to_swnode(fwnode);
-
- kobject_put(&swnode->kobj);
+ swnode_put(to_swnode(fwnode));
}
static bool software_node_property_present(const struct fwnode_handle *fwnode,
@@ -493,7 +501,7 @@ software_node_get_named_child_node(const struct fwnode_handle *fwnode,
list_for_each_entry(child, &swnode->children, entry) {
if (!strcmp(childname, kobject_name(&child->kobj))) {
- kobject_get(&child->kobj);
+ swnode_get(child);
return &child->fwnode;
}
}
@@ -737,7 +745,7 @@ software_node_find_by_name(const struct software_node *parent, const char *name)
swnode = kobj_to_swnode(k);
if (parent == swnode->node->parent && swnode->node->name &&
!strcmp(name, swnode->node->name)) {
- kobject_get(&swnode->kobj);
+ swnode_get(swnode);
break;
}
swnode = NULL;
@@ -835,13 +843,13 @@ swnode_register(const struct software_node *node, struct swnode *parent,
parent ? &parent->kobj : NULL,
"node%d", swnode->id);
if (ret) {
- kobject_put(&swnode->kobj);
+ swnode_put(swnode);
return ERR_PTR(ret);
}
/*
* Assign the flag only in the successful case, so
- * the above kobject_put() won't mess up with properties.
+ * the above swnode_put() won't mess up with properties.
*/
swnode->allocated = allocated;
@@ -978,7 +986,7 @@ void fwnode_remove_software_node(struct fwnode_handle *fwnode)
if (!swnode)
return;
- kobject_put(&swnode->kobj);
+ swnode_put(swnode);
}
EXPORT_SYMBOL_GPL(fwnode_remove_software_node);
@@ -1002,7 +1010,7 @@ int device_add_software_node(struct device *dev, const struct software_node *nod
swnode = software_node_to_swnode(node);
if (swnode) {
- kobject_get(&swnode->kobj);
+ swnode_get(swnode);
} else {
ret = software_node_register(node);
if (ret)
@@ -1044,7 +1052,7 @@ void device_remove_software_node(struct device *dev)
software_node_notify_remove(dev);
set_secondary_fwnode(dev, NULL);
- kobject_put(&swnode->kobj);
+ swnode_put(swnode);
}
EXPORT_SYMBOL_GPL(device_remove_software_node);
@@ -1097,7 +1105,7 @@ void software_node_notify(struct device *dev)
if (!swnode)
return;
- kobject_get(&swnode->kobj);
+ swnode_get(swnode);
ret = sysfs_create_link(&dev->kobj, &swnode->kobj, "software_node");
if (ret)
return;
@@ -1119,11 +1127,11 @@ void software_node_notify_remove(struct device *dev)
sysfs_remove_link(&swnode->kobj, dev_name(dev));
sysfs_remove_link(&dev->kobj, "software_node");
- kobject_put(&swnode->kobj);
+ swnode_put(swnode);
if (swnode->managed) {
set_secondary_fwnode(dev, NULL);
- kobject_put(&swnode->kobj);
+ swnode_put(swnode);
}
}