Commit 975f9ce9 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'driver-core-5.6-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core

Pull driver core updates from Greg KH:
 "Here is a small set of changes for 5.6-rc1 for the driver core and
  some firmware subsystem changes.

  Included in here are:
   - device.h splitup like you asked for months ago
   - devtmpfs minor cleanups
   - firmware core minor changes
   - debugfs fix for lockdown mode
   - kernfs cleanup fix
   - cpu topology minor fix

  All of these have been in linux-next for a while with no reported
  issues"

* tag 'driver-core-5.6-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core: (22 commits)
  firmware: Rename FW_OPT_NOFALLBACK to FW_OPT_NOFALLBACK_SYSFS
  devtmpfs: factor out common tail of devtmpfs_{create,delete}_node
  devtmpfs: initify a bit
  devtmpfs: simplify initialization of mount_dev
  devtmpfs: factor out setup part of devtmpfsd()
  devtmpfs: fix theoretical stale pointer deref in devtmpfsd()
  driver core: platform: fix u32 greater or equal to zero comparison
  cpu-topology: Don't error on more than CONFIG_NR_CPUS CPUs in device tree
  debugfs: Return -EPERM when locked down
  driver core: Print device when resources present in really_probe()
  driver core: Fix test_async_driver_probe if NUMA is disabled
  driver core: platform: Prevent resouce overflow from causing infinite loops
  fs/kernfs/dir.c: Clean code by removing always true condition
  component: do not dereference opaque pointer in debugfs
  drivers/component: remove modular code
  debugfs: Fix warnings when building documentation
  device.h: move 'struct driver' stuff out to device/driver.h
  device.h: move 'struct class' stuff out to device/class.h
  device.h: move 'struct bus' stuff out to device/bus.h
  device.h: move dev_printk()-like functions to dev_printk.h
  ...
parents 7ba31c3f 85db1cde
...@@ -248,6 +248,16 @@ core_initcall(free_raw_capacity); ...@@ -248,6 +248,16 @@ core_initcall(free_raw_capacity);
#endif #endif
#if defined(CONFIG_ARM64) || defined(CONFIG_RISCV) #if defined(CONFIG_ARM64) || defined(CONFIG_RISCV)
/*
* This function returns the logic cpu number of the node.
* There are basically three kinds of return values:
* (1) logic cpu number which is > 0.
* (2) -ENODEV when the device tree(DT) node is valid and found in the DT but
* there is no possible logical CPU in the kernel to match. This happens
* when CONFIG_NR_CPUS is configure to be smaller than the number of
* CPU nodes in DT. We need to just ignore this case.
* (3) -1 if the node does not exist in the device tree
*/
static int __init get_cpu_for_node(struct device_node *node) static int __init get_cpu_for_node(struct device_node *node)
{ {
struct device_node *cpu_node; struct device_node *cpu_node;
...@@ -261,7 +271,8 @@ static int __init get_cpu_for_node(struct device_node *node) ...@@ -261,7 +271,8 @@ static int __init get_cpu_for_node(struct device_node *node)
if (cpu >= 0) if (cpu >= 0)
topology_parse_cpu_capacity(cpu_node, cpu); topology_parse_cpu_capacity(cpu_node, cpu);
else else
pr_crit("Unable to find CPU node for %pOF\n", cpu_node); pr_info("CPU node for %pOF exist but the possible cpu range is :%*pbl\n",
cpu_node, cpumask_pr_args(cpu_possible_mask));
of_node_put(cpu_node); of_node_put(cpu_node);
return cpu; return cpu;
...@@ -286,9 +297,8 @@ static int __init parse_core(struct device_node *core, int package_id, ...@@ -286,9 +297,8 @@ static int __init parse_core(struct device_node *core, int package_id,
cpu_topology[cpu].package_id = package_id; cpu_topology[cpu].package_id = package_id;
cpu_topology[cpu].core_id = core_id; cpu_topology[cpu].core_id = core_id;
cpu_topology[cpu].thread_id = i; cpu_topology[cpu].thread_id = i;
} else { } else if (cpu != -ENODEV) {
pr_err("%pOF: Can't get CPU for thread\n", pr_err("%pOF: Can't get CPU for thread\n", t);
t);
of_node_put(t); of_node_put(t);
return -EINVAL; return -EINVAL;
} }
...@@ -307,7 +317,7 @@ static int __init parse_core(struct device_node *core, int package_id, ...@@ -307,7 +317,7 @@ static int __init parse_core(struct device_node *core, int package_id,
cpu_topology[cpu].package_id = package_id; cpu_topology[cpu].package_id = package_id;
cpu_topology[cpu].core_id = core_id; cpu_topology[cpu].core_id = core_id;
} else if (leaf) { } else if (leaf && cpu != -ENODEV) {
pr_err("%pOF: Can't get CPU for leaf core\n", core); pr_err("%pOF: Can't get CPU for leaf core\n", core);
return -EINVAL; return -EINVAL;
} }
......
/* SPDX-License-Identifier: GPL-2.0 */ /* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright (c) 2001-2003 Patrick Mochel <mochel@osdl.org>
* Copyright (c) 2004-2009 Greg Kroah-Hartman <gregkh@suse.de>
* Copyright (c) 2008-2012 Novell Inc.
* Copyright (c) 2012-2019 Greg Kroah-Hartman <gregkh@linuxfoundation.org>
* Copyright (c) 2012-2019 Linux Foundation
*
* Core driver model functions and structures that should not be
* shared outside of the drivers/base/ directory.
*
*/
#include <linux/notifier.h> #include <linux/notifier.h>
/** /**
...@@ -175,3 +186,11 @@ extern void device_links_unbind_consumers(struct device *dev); ...@@ -175,3 +186,11 @@ extern void device_links_unbind_consumers(struct device *dev);
/* device pm support */ /* device pm support */
void device_pm_move_to_tail(struct device *dev); void device_pm_move_to_tail(struct device *dev);
#ifdef CONFIG_DEVTMPFS
int devtmpfs_create_node(struct device *dev);
int devtmpfs_delete_node(struct device *dev);
#else
static inline int devtmpfs_create_node(struct device *dev) { return 0; }
static inline int devtmpfs_delete_node(struct device *dev) { return 0; }
#endif
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
*/ */
#include <linux/async.h> #include <linux/async.h>
#include <linux/device/bus.h>
#include <linux/device.h> #include <linux/device.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/errno.h> #include <linux/errno.h>
......
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
* Copyright (c) 2003-2004 IBM Corp. * Copyright (c) 2003-2004 IBM Corp.
*/ */
#include <linux/device/class.h>
#include <linux/device.h> #include <linux/device.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/init.h> #include <linux/init.h>
......
...@@ -11,7 +11,6 @@ ...@@ -11,7 +11,6 @@
#include <linux/device.h> #include <linux/device.h>
#include <linux/kref.h> #include <linux/kref.h>
#include <linux/list.h> #include <linux/list.h>
#include <linux/module.h>
#include <linux/mutex.h> #include <linux/mutex.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/debugfs.h> #include <linux/debugfs.h>
...@@ -102,11 +101,11 @@ static int component_devices_show(struct seq_file *s, void *data) ...@@ -102,11 +101,11 @@ static int component_devices_show(struct seq_file *s, void *data)
seq_printf(s, "%-40s %20s\n", "device name", "status"); seq_printf(s, "%-40s %20s\n", "device name", "status");
seq_puts(s, "-------------------------------------------------------------\n"); seq_puts(s, "-------------------------------------------------------------\n");
for (i = 0; i < match->num; i++) { for (i = 0; i < match->num; i++) {
struct device *d = (struct device *)match->compare[i].data; struct component *component = match->compare[i].component;
seq_printf(s, "%-40s %20s\n", dev_name(d), seq_printf(s, "%-40s %20s\n",
match->compare[i].component ? component ? dev_name(component->dev) : "(unknown)",
"registered" : "not registered"); component ? (component->bound ? "bound" : "not bound") : "not registered");
} }
mutex_unlock(&component_mutex); mutex_unlock(&component_mutex);
...@@ -775,5 +774,3 @@ void component_del(struct device *dev, const struct component_ops *ops) ...@@ -775,5 +774,3 @@ void component_del(struct device *dev, const struct component_ops *ops)
kfree(component); kfree(component);
} }
EXPORT_SYMBOL_GPL(component_del); EXPORT_SYMBOL_GPL(component_del);
MODULE_LICENSE("GPL v2");
...@@ -516,7 +516,10 @@ static int really_probe(struct device *dev, struct device_driver *drv) ...@@ -516,7 +516,10 @@ static int really_probe(struct device *dev, struct device_driver *drv)
atomic_inc(&probe_count); atomic_inc(&probe_count);
pr_debug("bus: '%s': %s: probing driver %s with device %s\n", pr_debug("bus: '%s': %s: probing driver %s with device %s\n",
drv->bus->name, __func__, drv->name, dev_name(dev)); drv->bus->name, __func__, drv->name, dev_name(dev));
WARN_ON(!list_empty(&dev->devres_head)); if (!list_empty(&dev->devres_head)) {
dev_crit(dev, "Resources present before probing\n");
return -EBUSY;
}
re_probe: re_probe:
dev->driver = drv; dev->driver = drv;
......
...@@ -30,11 +30,7 @@ ...@@ -30,11 +30,7 @@
static struct task_struct *thread; static struct task_struct *thread;
#if defined CONFIG_DEVTMPFS_MOUNT static int __initdata mount_dev = IS_ENABLED(CONFIG_DEVTMPFS_MOUNT);
static int mount_dev = 1;
#else
static int mount_dev;
#endif
static DEFINE_SPINLOCK(req_lock); static DEFINE_SPINLOCK(req_lock);
...@@ -93,6 +89,23 @@ static inline int is_blockdev(struct device *dev) ...@@ -93,6 +89,23 @@ static inline int is_blockdev(struct device *dev)
static inline int is_blockdev(struct device *dev) { return 0; } static inline int is_blockdev(struct device *dev) { return 0; }
#endif #endif
static int devtmpfs_submit_req(struct req *req, const char *tmp)
{
init_completion(&req->done);
spin_lock(&req_lock);
req->next = requests;
requests = req;
spin_unlock(&req_lock);
wake_up_process(thread);
wait_for_completion(&req->done);
kfree(tmp);
return req->err;
}
int devtmpfs_create_node(struct device *dev) int devtmpfs_create_node(struct device *dev)
{ {
const char *tmp = NULL; const char *tmp = NULL;
...@@ -117,19 +130,7 @@ int devtmpfs_create_node(struct device *dev) ...@@ -117,19 +130,7 @@ int devtmpfs_create_node(struct device *dev)
req.dev = dev; req.dev = dev;
init_completion(&req.done); return devtmpfs_submit_req(&req, tmp);
spin_lock(&req_lock);
req.next = requests;
requests = &req;
spin_unlock(&req_lock);
wake_up_process(thread);
wait_for_completion(&req.done);
kfree(tmp);
return req.err;
} }
int devtmpfs_delete_node(struct device *dev) int devtmpfs_delete_node(struct device *dev)
...@@ -147,18 +148,7 @@ int devtmpfs_delete_node(struct device *dev) ...@@ -147,18 +148,7 @@ int devtmpfs_delete_node(struct device *dev)
req.mode = 0; req.mode = 0;
req.dev = dev; req.dev = dev;
init_completion(&req.done); return devtmpfs_submit_req(&req, tmp);
spin_lock(&req_lock);
req.next = requests;
requests = &req;
spin_unlock(&req_lock);
wake_up_process(thread);
wait_for_completion(&req.done);
kfree(tmp);
return req.err;
} }
static int dev_mkdir(const char *name, umode_t mode) static int dev_mkdir(const char *name, umode_t mode)
...@@ -359,7 +349,7 @@ static int handle_remove(const char *nodename, struct device *dev) ...@@ -359,7 +349,7 @@ static int handle_remove(const char *nodename, struct device *dev)
* If configured, or requested by the commandline, devtmpfs will be * If configured, or requested by the commandline, devtmpfs will be
* auto-mounted after the kernel mounted the root filesystem. * auto-mounted after the kernel mounted the root filesystem.
*/ */
int devtmpfs_mount(void) int __init devtmpfs_mount(void)
{ {
int err; int err;
...@@ -388,18 +378,30 @@ static int handle(const char *name, umode_t mode, kuid_t uid, kgid_t gid, ...@@ -388,18 +378,30 @@ static int handle(const char *name, umode_t mode, kuid_t uid, kgid_t gid,
return handle_remove(name, dev); return handle_remove(name, dev);
} }
static int devtmpfsd(void *p) static int devtmpfs_setup(void *p)
{ {
int *err = p; int err;
*err = ksys_unshare(CLONE_NEWNS);
if (*err) err = ksys_unshare(CLONE_NEWNS);
if (err)
goto out; goto out;
*err = do_mount("devtmpfs", "/", "devtmpfs", MS_SILENT, NULL); err = do_mount("devtmpfs", "/", "devtmpfs", MS_SILENT, NULL);
if (*err) if (err)
goto out; goto out;
ksys_chdir("/.."); /* will traverse into overmounted root */ ksys_chdir("/.."); /* will traverse into overmounted root */
ksys_chroot("."); ksys_chroot(".");
out:
*(int *)p = err;
complete(&setup_done); complete(&setup_done);
return err;
}
static int devtmpfsd(void *p)
{
int err = devtmpfs_setup(p);
if (err)
return err;
while (1) { while (1) {
spin_lock(&req_lock); spin_lock(&req_lock);
while (requests) { while (requests) {
...@@ -420,9 +422,6 @@ static int devtmpfsd(void *p) ...@@ -420,9 +422,6 @@ static int devtmpfsd(void *p)
schedule(); schedule();
} }
return 0; return 0;
out:
complete(&setup_done);
return *err;
} }
/* /*
......
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
* Copyright (c) 2007 Novell Inc. * Copyright (c) 2007 Novell Inc.
*/ */
#include <linux/device/driver.h>
#include <linux/device.h> #include <linux/device.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/errno.h> #include <linux/errno.h>
......
...@@ -606,7 +606,7 @@ static bool fw_run_sysfs_fallback(enum fw_opt opt_flags) ...@@ -606,7 +606,7 @@ static bool fw_run_sysfs_fallback(enum fw_opt opt_flags)
return false; return false;
} }
if ((opt_flags & FW_OPT_NOFALLBACK)) if ((opt_flags & FW_OPT_NOFALLBACK_SYSFS))
return false; return false;
/* Also permit LSMs and IMA to fail firmware sysfs fallback */ /* Also permit LSMs and IMA to fail firmware sysfs fallback */
...@@ -630,10 +630,11 @@ static bool fw_run_sysfs_fallback(enum fw_opt opt_flags) ...@@ -630,10 +630,11 @@ static bool fw_run_sysfs_fallback(enum fw_opt opt_flags)
* interface. Userspace is in charge of loading the firmware through the sysfs * interface. Userspace is in charge of loading the firmware through the sysfs
* loading interface. This sysfs fallback mechanism may be disabled completely * loading interface. This sysfs fallback mechanism may be disabled completely
* on a system by setting the proc sysctl value ignore_sysfs_fallback to true. * on a system by setting the proc sysctl value ignore_sysfs_fallback to true.
* If this false we check if the internal API caller set the @FW_OPT_NOFALLBACK * If this is false we check if the internal API caller set the
* flag, if so it would also disable the fallback mechanism. A system may want * @FW_OPT_NOFALLBACK_SYSFS flag, if so it would also disable the fallback
* to enfoce the sysfs fallback mechanism at all times, it can do this by * mechanism. A system may want to enforce the sysfs fallback mechanism at all
* setting ignore_sysfs_fallback to false and force_sysfs_fallback to true. * times, it can do this by setting ignore_sysfs_fallback to false and
* force_sysfs_fallback to true.
* Enabling force_sysfs_fallback is functionally equivalent to build a kernel * Enabling force_sysfs_fallback is functionally equivalent to build a kernel
* with CONFIG_FW_LOADER_USER_HELPER_FALLBACK. * with CONFIG_FW_LOADER_USER_HELPER_FALLBACK.
**/ **/
......
...@@ -27,8 +27,8 @@ ...@@ -27,8 +27,8 @@
* firmware file lookup on storage is avoided. Used for calls where the * firmware file lookup on storage is avoided. Used for calls where the
* file may be too big, or where the driver takes charge of its own * file may be too big, or where the driver takes charge of its own
* firmware caching mechanism. * firmware caching mechanism.
* @FW_OPT_NOFALLBACK: Disable the fallback mechanism. Takes precedence over * @FW_OPT_NOFALLBACK_SYSFS: Disable the sysfs fallback mechanism. Takes
* &FW_OPT_UEVENT and &FW_OPT_USERHELPER. * precedence over &FW_OPT_UEVENT and &FW_OPT_USERHELPER.
*/ */
enum fw_opt { enum fw_opt {
FW_OPT_UEVENT = BIT(0), FW_OPT_UEVENT = BIT(0),
...@@ -36,7 +36,7 @@ enum fw_opt { ...@@ -36,7 +36,7 @@ enum fw_opt {
FW_OPT_USERHELPER = BIT(2), FW_OPT_USERHELPER = BIT(2),
FW_OPT_NO_WARN = BIT(3), FW_OPT_NO_WARN = BIT(3),
FW_OPT_NOCACHE = BIT(4), FW_OPT_NOCACHE = BIT(4),
FW_OPT_NOFALLBACK = BIT(5), FW_OPT_NOFALLBACK_SYSFS = BIT(5),
}; };
enum fw_status { enum fw_status {
......
...@@ -877,7 +877,7 @@ int request_firmware_direct(const struct firmware **firmware_p, ...@@ -877,7 +877,7 @@ int request_firmware_direct(const struct firmware **firmware_p,
__module_get(THIS_MODULE); __module_get(THIS_MODULE);
ret = _request_firmware(firmware_p, name, device, NULL, 0, ret = _request_firmware(firmware_p, name, device, NULL, 0,
FW_OPT_UEVENT | FW_OPT_NO_WARN | FW_OPT_UEVENT | FW_OPT_NO_WARN |
FW_OPT_NOFALLBACK); FW_OPT_NOFALLBACK_SYSFS);
module_put(THIS_MODULE); module_put(THIS_MODULE);
return ret; return ret;
} }
......
...@@ -27,6 +27,7 @@ ...@@ -27,6 +27,7 @@
#include <linux/limits.h> #include <linux/limits.h>
#include <linux/property.h> #include <linux/property.h>
#include <linux/kmemleak.h> #include <linux/kmemleak.h>
#include <linux/types.h>
#include "base.h" #include "base.h"
#include "power/power.h" #include "power/power.h"
...@@ -48,7 +49,7 @@ EXPORT_SYMBOL_GPL(platform_bus); ...@@ -48,7 +49,7 @@ EXPORT_SYMBOL_GPL(platform_bus);
struct resource *platform_get_resource(struct platform_device *dev, struct resource *platform_get_resource(struct platform_device *dev,
unsigned int type, unsigned int num) unsigned int type, unsigned int num)
{ {
int i; u32 i;
for (i = 0; i < dev->num_resources; i++) { for (i = 0; i < dev->num_resources; i++) {
struct resource *r = &dev->resource[i]; struct resource *r = &dev->resource[i];
...@@ -255,7 +256,7 @@ struct resource *platform_get_resource_byname(struct platform_device *dev, ...@@ -255,7 +256,7 @@ struct resource *platform_get_resource_byname(struct platform_device *dev,
unsigned int type, unsigned int type,
const char *name) const char *name)
{ {
int i; u32 i;
for (i = 0; i < dev->num_resources; i++) { for (i = 0; i < dev->num_resources; i++) {
struct resource *r = &dev->resource[i]; struct resource *r = &dev->resource[i];
...@@ -501,7 +502,8 @@ EXPORT_SYMBOL_GPL(platform_device_add_properties); ...@@ -501,7 +502,8 @@ EXPORT_SYMBOL_GPL(platform_device_add_properties);
*/ */
int platform_device_add(struct platform_device *pdev) int platform_device_add(struct platform_device *pdev)
{ {
int i, ret; u32 i;
int ret;
if (!pdev) if (!pdev)
return -EINVAL; return -EINVAL;
...@@ -569,7 +571,7 @@ int platform_device_add(struct platform_device *pdev) ...@@ -569,7 +571,7 @@ int platform_device_add(struct platform_device *pdev)
pdev->id = PLATFORM_DEVID_AUTO; pdev->id = PLATFORM_DEVID_AUTO;
} }
while (--i >= 0) { while (i--) {
struct resource *r = &pdev->resource[i]; struct resource *r = &pdev->resource[i];
if (r->parent) if (r->parent)
release_resource(r); release_resource(r);
...@@ -590,7 +592,7 @@ EXPORT_SYMBOL_GPL(platform_device_add); ...@@ -590,7 +592,7 @@ EXPORT_SYMBOL_GPL(platform_device_add);
*/ */
void platform_device_del(struct platform_device *pdev) void platform_device_del(struct platform_device *pdev)
{ {
int i; u32 i;
if (!IS_ERR_OR_NULL(pdev)) { if (!IS_ERR_OR_NULL(pdev)) {
device_del(&pdev->dev); device_del(&pdev->dev);
......
...@@ -44,7 +44,8 @@ static int test_probe(struct platform_device *pdev) ...@@ -44,7 +44,8 @@ static int test_probe(struct platform_device *pdev)
* performing an async init on that node. * performing an async init on that node.
*/ */
if (dev->driver->probe_type == PROBE_PREFER_ASYNCHRONOUS) { if (dev->driver->probe_type == PROBE_PREFER_ASYNCHRONOUS) {
if (dev_to_node(dev) != numa_node_id()) { if (IS_ENABLED(CONFIG_NUMA) &&
dev_to_node(dev) != numa_node_id()) {
dev_warn(dev, "NUMA node mismatch %d != %d\n", dev_warn(dev, "NUMA node mismatch %d != %d\n",
dev_to_node(dev), numa_node_id()); dev_to_node(dev), numa_node_id());
atomic_inc(&warnings); atomic_inc(&warnings);
......
...@@ -142,7 +142,7 @@ EXPORT_SYMBOL_GPL(debugfs_file_put); ...@@ -142,7 +142,7 @@ EXPORT_SYMBOL_GPL(debugfs_file_put);
* We also need to exclude any file that has ways to write or alter it as root * We also need to exclude any file that has ways to write or alter it as root
* can bypass the permissions check. * can bypass the permissions check.
*/ */
static bool debugfs_is_locked_down(struct inode *inode, static int debugfs_locked_down(struct inode *inode,
struct file *filp, struct file *filp,
const struct file_operations *real_fops) const struct file_operations *real_fops)
{ {
...@@ -151,9 +151,12 @@ static bool debugfs_is_locked_down(struct inode *inode, ...@@ -151,9 +151,12 @@ static bool debugfs_is_locked_down(struct inode *inode,
!real_fops->unlocked_ioctl && !real_fops->unlocked_ioctl &&
!real_fops->compat_ioctl && !real_fops->compat_ioctl &&
!real_fops->mmap) !real_fops->mmap)
return false; return 0;
if (security_locked_down(LOCKDOWN_DEBUGFS))
return -EPERM;
return security_locked_down(LOCKDOWN_DEBUGFS); return 0;
} }
static int open_proxy_open(struct inode *inode, struct file *filp) static int open_proxy_open(struct inode *inode, struct file *filp)
...@@ -168,7 +171,7 @@ static int open_proxy_open(struct inode *inode, struct file *filp) ...@@ -168,7 +171,7 @@ static int open_proxy_open(struct inode *inode, struct file *filp)
real_fops = debugfs_real_fops(filp); real_fops = debugfs_real_fops(filp);
r = debugfs_is_locked_down(inode, filp, real_fops); r = debugfs_locked_down(inode, filp, real_fops);
if (r) if (r)
goto out; goto out;
...@@ -298,7 +301,7 @@ static int full_proxy_open(struct inode *inode, struct file *filp) ...@@ -298,7 +301,7 @@ static int full_proxy_open(struct inode *inode, struct file *filp)
real_fops = debugfs_real_fops(filp); real_fops = debugfs_real_fops(filp);
r = debugfs_is_locked_down(inode, filp, real_fops); r = debugfs_locked_down(inode, filp, real_fops);
if (r) if (r)
goto out; goto out;
...@@ -496,10 +499,10 @@ DEFINE_DEBUGFS_ATTRIBUTE(fops_u32_wo, NULL, debugfs_u32_set, "%llu\n"); ...@@ -496,10 +499,10 @@ DEFINE_DEBUGFS_ATTRIBUTE(fops_u32_wo, NULL, debugfs_u32_set, "%llu\n");
* This function will return a pointer to a dentry if it succeeds. This * This function will return a pointer to a dentry if it succeeds. This
* pointer must be passed to the debugfs_remove() function when the file is * pointer must be passed to the debugfs_remove() function when the file is
* to be removed (no automatic cleanup happens if your module is unloaded, * to be removed (no automatic cleanup happens if your module is unloaded,
* you are responsible here.) If an error occurs, %ERR_PTR(-ERROR) will be * you are responsible here.) If an error occurs, ERR_PTR(-ERROR) will be
* returned. * returned.
* *
* If debugfs is not enabled in the kernel, the value %ERR_PTR(-ENODEV) will * If debugfs is not enabled in the kernel, the value ERR_PTR(-ENODEV) will
* be returned. * be returned.
*/ */
struct dentry *debugfs_create_u32(const char *name, umode_t mode, struct dentry *debugfs_create_u32(const char *name, umode_t mode,
...@@ -581,10 +584,10 @@ DEFINE_DEBUGFS_ATTRIBUTE(fops_ulong_wo, NULL, debugfs_ulong_set, "%llu\n"); ...@@ -581,10 +584,10 @@ DEFINE_DEBUGFS_ATTRIBUTE(fops_ulong_wo, NULL, debugfs_ulong_set, "%llu\n");
* This function will return a pointer to a dentry if it succeeds. This * This function will return a pointer to a dentry if it succeeds. This
* pointer must be passed to the debugfs_remove() function when the file is * pointer must be passed to the debugfs_remove() function when the file is
* to be removed (no automatic cleanup happens if your module is unloaded, * to be removed (no automatic cleanup happens if your module is unloaded,
* you are responsible here.) If an error occurs, %ERR_PTR(-ERROR) will be * you are responsible here.) If an error occurs, ERR_PTR(-ERROR) will be
* returned. * returned.
* *
* If debugfs is not enabled in the kernel, the value %ERR_PTR(-ENODEV) will * If debugfs is not enabled in the kernel, the value ERR_PTR(-ENODEV) will
* be returned. * be returned.
*/ */
struct dentry *debugfs_create_ulong(const char *name, umode_t mode, struct dentry *debugfs_create_ulong(const char *name, umode_t mode,
...@@ -846,10 +849,10 @@ static const struct file_operations fops_bool_wo = { ...@@ -846,10 +849,10 @@ static const struct file_operations fops_bool_wo = {
* This function will return a pointer to a dentry if it succeeds. This * This function will return a pointer to a dentry if it succeeds. This
* pointer must be passed to the debugfs_remove() function when the file is * pointer must be passed to the debugfs_remove() function when the file is
* to be removed (no automatic cleanup happens if your module is unloaded, * to be removed (no automatic cleanup happens if your module is unloaded,
* you are responsible here.) If an error occurs, %ERR_PTR(-ERROR) will be * you are responsible here.) If an error occurs, ERR_PTR(-ERROR) will be
* returned. * returned.
* *
* If debugfs is not enabled in the kernel, the value %ERR_PTR(-ENODEV) will * If debugfs is not enabled in the kernel, the value ERR_PTR(-ENODEV) will
* be returned. * be returned.
*/ */
struct dentry *debugfs_create_bool(const char *name, umode_t mode, struct dentry *debugfs_create_bool(const char *name, umode_t mode,
...@@ -899,10 +902,10 @@ static const struct file_operations fops_blob = { ...@@ -899,10 +902,10 @@ static const struct file_operations fops_blob = {
* This function will return a pointer to a dentry if it succeeds. This * This function will return a pointer to a dentry if it succeeds. This
* pointer must be passed to the debugfs_remove() function when the file is * pointer must be passed to the debugfs_remove() function when the file is
* to be removed (no automatic cleanup happens if your module is unloaded, * to be removed (no automatic cleanup happens if your module is unloaded,
* you are responsible here.) If an error occurs, %ERR_PTR(-ERROR) will be * you are responsible here.) If an error occurs, ERR_PTR(-ERROR) will be
* returned. * returned.
* *
* If debugfs is not enabled in the kernel, the value %ERR_PTR(-ENODEV) will * If debugfs is not enabled in the kernel, the value ERR_PTR(-ENODEV) will
* be returned. * be returned.
*/ */
struct dentry *debugfs_create_blob(const char *name, umode_t mode, struct dentry *debugfs_create_blob(const char *name, umode_t mode,
...@@ -1091,10 +1094,10 @@ static const struct file_operations fops_regset32 = { ...@@ -1091,10 +1094,10 @@ static const struct file_operations fops_regset32 = {
* This function will return a pointer to a dentry if it succeeds. This * This function will return a pointer to a dentry if it succeeds. This
* pointer must be passed to the debugfs_remove() function when the file is * pointer must be passed to the debugfs_remove() function when the file is
* to be removed (no automatic cleanup happens if your module is unloaded, * to be removed (no automatic cleanup happens if your module is unloaded,
* you are responsible here.) If an error occurs, %ERR_PTR(-ERROR) will be * you are responsible here.) If an error occurs, ERR_PTR(-ERROR) will be
* returned. * returned.
* *
* If debugfs is not enabled in the kernel, the value %ERR_PTR(-ENODEV) will * If debugfs is not enabled in the kernel, the value ERR_PTR(-ENODEV) will
* be returned. * be returned.
*/ */
struct dentry *debugfs_create_regset32(const char *name, umode_t mode, struct dentry *debugfs_create_regset32(const char *name, umode_t mode,
...@@ -1158,4 +1161,3 @@ struct dentry *debugfs_create_devm_seqfile(struct device *dev, const char *name, ...@@ -1158,4 +1161,3 @@ struct dentry *debugfs_create_devm_seqfile(struct device *dev, const char *name,
&debugfs_devm_entry_ops); &debugfs_devm_entry_ops);
} }
EXPORT_SYMBOL_GPL(debugfs_create_devm_seqfile); EXPORT_SYMBOL_GPL(debugfs_create_devm_seqfile);
...@@ -423,7 +423,7 @@ static struct dentry *__debugfs_create_file(const char *name, umode_t mode, ...@@ -423,7 +423,7 @@ static struct dentry *__debugfs_create_file(const char *name, umode_t mode,
* This function will return a pointer to a dentry if it succeeds. This * This function will return a pointer to a dentry if it succeeds. This
* pointer must be passed to the debugfs_remove() function when the file is * pointer must be passed to the debugfs_remove() function when the file is
* to be removed (no automatic cleanup happens if your module is unloaded, * to be removed (no automatic cleanup happens if your module is unloaded,
* you are responsible here.) If an error occurs, %ERR_PTR(-ERROR) will be * you are responsible here.) If an error occurs, ERR_PTR(-ERROR) will be
* returned. * returned.
* *
* If debugfs is not enabled in the kernel, the value -%ENODEV will be * If debugfs is not enabled in the kernel, the value -%ENODEV will be
...@@ -502,7 +502,7 @@ EXPORT_SYMBOL_GPL(debugfs_create_file_unsafe); ...@@ -502,7 +502,7 @@ EXPORT_SYMBOL_GPL(debugfs_create_file_unsafe);
* This function will return a pointer to a dentry if it succeeds. This * This function will return a pointer to a dentry if it succeeds. This
* pointer must be passed to the debugfs_remove() function when the file is * pointer must be passed to the debugfs_remove() function when the file is
* to be removed (no automatic cleanup happens if your module is unloaded, * to be removed (no automatic cleanup happens if your module is unloaded,
* you are responsible here.) If an error occurs, %ERR_PTR(-ERROR) will be * you are responsible here.) If an error occurs, ERR_PTR(-ERROR) will be
* returned. * returned.
* *
* If debugfs is not enabled in the kernel, the value -%ENODEV will be * If debugfs is not enabled in the kernel, the value -%ENODEV will be
...@@ -534,7 +534,7 @@ EXPORT_SYMBOL_GPL(debugfs_create_file_size); ...@@ -534,7 +534,7 @@ EXPORT_SYMBOL_GPL(debugfs_create_file_size);
* This function will return a pointer to a dentry if it succeeds. This * This function will return a pointer to a dentry if it succeeds. This
* pointer must be passed to the debugfs_remove() function when the file is * pointer must be passed to the debugfs_remove() function when the file is
* to be removed (no automatic cleanup happens if your module is unloaded, * to be removed (no automatic cleanup happens if your module is unloaded,
* you are responsible here.) If an error occurs, %ERR_PTR(-ERROR) will be * you are responsible here.) If an error occurs, ERR_PTR(-ERROR) will be
* returned. * returned.
* *
* If debugfs is not enabled in the kernel, the value -%ENODEV will be * If debugfs is not enabled in the kernel, the value -%ENODEV will be
...@@ -627,7 +627,7 @@ EXPORT_SYMBOL(debugfs_create_automount); ...@@ -627,7 +627,7 @@ EXPORT_SYMBOL(debugfs_create_automount);
* This function will return a pointer to a dentry if it succeeds. This * This function will return a pointer to a dentry if it succeeds. This
* pointer must be passed to the debugfs_remove() function when the symbolic * pointer must be passed to the debugfs_remove() function when the symbolic
* link is to be removed (no automatic cleanup happens if your module is * link is to be removed (no automatic cleanup happens if your module is
* unloaded, you are responsible here.) If an error occurs, %ERR_PTR(-ERROR) * unloaded, you are responsible here.) If an error occurs, ERR_PTR(-ERROR)
* will be returned. * will be returned.
* *
* If debugfs is not enabled in the kernel, the value -%ENODEV will be * If debugfs is not enabled in the kernel, the value -%ENODEV will be
...@@ -906,4 +906,3 @@ static int __init debugfs_init(void) ...@@ -906,4 +906,3 @@ static int __init debugfs_init(void)
return retval; return retval;
} }
core_initcall(debugfs_init); core_initcall(debugfs_init);
...@@ -1266,7 +1266,7 @@ void kernfs_activate(struct kernfs_node *kn) ...@@ -1266,7 +1266,7 @@ void kernfs_activate(struct kernfs_node *kn)
pos = NULL; pos = NULL;
while ((pos = kernfs_next_descendant_post(pos, kn))) { while ((pos = kernfs_next_descendant_post(pos, kn))) {
if (!pos || (pos->flags & KERNFS_ACTIVATED)) if (pos->flags & KERNFS_ACTIVATED)
continue; continue;
WARN_ON_ONCE(pos->parent && RB_EMPTY_NODE(&pos->rb)); WARN_ON_ONCE(pos->parent && RB_EMPTY_NODE(&pos->rb));
......
// SPDX-License-Identifier: GPL-2.0
/*
* dev_printk.h - printk messages helpers for devices
*
* Copyright (c) 2001-2003 Patrick Mochel <mochel@osdl.org>
* Copyright (c) 2004-2009 Greg Kroah-Hartman <gregkh@suse.de>
* Copyright (c) 2008-2009 Novell Inc.
*
*/
#ifndef _DEVICE_PRINTK_H_
#define _DEVICE_PRINTK_H_
#include <linux/compiler.h>
#include <linux/types.h>
#include <linux/ratelimit.h>
#ifndef dev_fmt
#define dev_fmt(fmt) fmt
#endif
struct device;
#ifdef CONFIG_PRINTK
__printf(3, 0) __cold
int dev_vprintk_emit(int level, const struct device *dev,
const char *fmt, va_list args);
__printf(3, 4) __cold
int dev_printk_emit(int level, const struct device *dev, const char *fmt, ...);
__printf(3, 4) __cold
void dev_printk(const char *level, const struct device *dev,
const char *fmt, ...);
__printf(2, 3) __cold
void _dev_emerg(const struct device *dev, const char *fmt, ...);
__printf(2, 3) __cold
void _dev_alert(const struct device *dev, const char *fmt, ...);
__printf(2, 3) __cold
void _dev_crit(const struct device *dev, const char *fmt, ...);
__printf(2, 3) __cold
void _dev_err(const struct device *dev, const char *fmt, ...);
__printf(2, 3) __cold
void _dev_warn(const struct device *dev, const char *fmt, ...);
__printf(2, 3) __cold
void _dev_notice(const struct device *dev, const char *fmt, ...);
__printf(2, 3) __cold
void _dev_info(const struct device *dev, const char *fmt, ...);
#else
static inline __printf(3, 0)
int dev_vprintk_emit(int level, const struct device *dev,
const char *fmt, va_list args)
{ return 0; }
static inline __printf(3, 4)
int dev_printk_emit(int level, const struct device *dev, const char *fmt, ...)
{ return 0; }
static inline void __dev_printk(const char *level, const struct device *dev,
struct va_format *vaf)
{}
static inline __printf(3, 4)
void dev_printk(const char *level, const struct device *dev,
const char *fmt, ...)
{}
static inline __printf(2, 3)
void _dev_emerg(const struct device *dev, const char *fmt, ...)
{}
static inline __printf(2, 3)
void _dev_crit(const struct device *dev, const char *fmt, ...)
{}
static inline __printf(2, 3)
void _dev_alert(const struct device *dev, const char *fmt, ...)
{}
static inline __printf(2, 3)
void _dev_err(const struct device *dev, const char *fmt, ...)
{}
static inline __printf(2, 3)
void _dev_warn(const struct device *dev, const char *fmt, ...)
{}
static inline __printf(2, 3)
void _dev_notice(const struct device *dev, const char *fmt, ...)
{}
static inline __printf(2, 3)
void _dev_info(const struct device *dev, const char *fmt, ...)
{}
#endif
/*
* #defines for all the dev_<level> macros to prefix with whatever
* possible use of #define dev_fmt(fmt) ...
*/
#define dev_emerg(dev, fmt, ...) \
_dev_emerg(dev, dev_fmt(fmt), ##__VA_ARGS__)
#define dev_crit(dev, fmt, ...) \
_dev_crit(dev, dev_fmt(fmt), ##__VA_ARGS__)
#define dev_alert(dev, fmt, ...) \
_dev_alert(dev, dev_fmt(fmt), ##__VA_ARGS__)
#define dev_err(dev, fmt, ...) \
_dev_err(dev, dev_fmt(fmt), ##__VA_ARGS__)
#define dev_warn(dev, fmt, ...) \
_dev_warn(dev, dev_fmt(fmt), ##__VA_ARGS__)
#define dev_notice(dev, fmt, ...) \
_dev_notice(dev, dev_fmt(fmt), ##__VA_ARGS__)
#define dev_info(dev, fmt, ...) \
_dev_info(dev, dev_fmt(fmt), ##__VA_ARGS__)
#if defined(CONFIG_DYNAMIC_DEBUG)
#define dev_dbg(dev, fmt, ...) \
dynamic_dev_dbg(dev, dev_fmt(fmt), ##__VA_ARGS__)
#elif defined(DEBUG)
#define dev_dbg(dev, fmt, ...) \
dev_printk(KERN_DEBUG, dev, dev_fmt(fmt), ##__VA_ARGS__)
#else
#define dev_dbg(dev, fmt, ...) \
({ \
if (0) \
dev_printk(KERN_DEBUG, dev, dev_fmt(fmt), ##__VA_ARGS__); \
})
#endif
#ifdef CONFIG_PRINTK
#define dev_level_once(dev_level, dev, fmt, ...) \
do { \
static bool __print_once __read_mostly; \
\
if (!__print_once) { \
__print_once = true; \
dev_level(dev, fmt, ##__VA_ARGS__); \
} \
} while (0)
#else
#define dev_level_once(dev_level, dev, fmt, ...) \
do { \
if (0) \
dev_level(dev, fmt, ##__VA_ARGS__); \
} while (0)
#endif
#define dev_emerg_once(dev, fmt, ...) \
dev_level_once(dev_emerg, dev, fmt, ##__VA_ARGS__)
#define dev_alert_once(dev, fmt, ...) \
dev_level_once(dev_alert, dev, fmt, ##__VA_ARGS__)
#define dev_crit_once(dev, fmt, ...) \
dev_level_once(dev_crit, dev, fmt, ##__VA_ARGS__)
#define dev_err_once(dev, fmt, ...) \
dev_level_once(dev_err, dev, fmt, ##__VA_ARGS__)
#define dev_warn_once(dev, fmt, ...) \
dev_level_once(dev_warn, dev, fmt, ##__VA_ARGS__)
#define dev_notice_once(dev, fmt, ...) \
dev_level_once(dev_notice, dev, fmt, ##__VA_ARGS__)
#define dev_info_once(dev, fmt, ...) \
dev_level_once(dev_info, dev, fmt, ##__VA_ARGS__)
#define dev_dbg_once(dev, fmt, ...) \
dev_level_once(dev_dbg, dev, fmt, ##__VA_ARGS__)
#define dev_level_ratelimited(dev_level, dev, fmt, ...) \
do { \
static DEFINE_RATELIMIT_STATE(_rs, \
DEFAULT_RATELIMIT_INTERVAL, \
DEFAULT_RATELIMIT_BURST); \
if (__ratelimit(&_rs)) \
dev_level(dev, fmt, ##__VA_ARGS__); \
} while (0)
#define dev_emerg_ratelimited(dev, fmt, ...) \
dev_level_ratelimited(dev_emerg, dev, fmt, ##__VA_ARGS__)
#define dev_alert_ratelimited(dev, fmt, ...) \
dev_level_ratelimited(dev_alert, dev, fmt, ##__VA_ARGS__)
#define dev_crit_ratelimited(dev, fmt, ...) \
dev_level_ratelimited(dev_crit, dev, fmt, ##__VA_ARGS__)
#define dev_err_ratelimited(dev, fmt, ...) \
dev_level_ratelimited(dev_err, dev, fmt, ##__VA_ARGS__)
#define dev_warn_ratelimited(dev, fmt, ...) \
dev_level_ratelimited(dev_warn, dev, fmt, ##__VA_ARGS__)
#define dev_notice_ratelimited(dev, fmt, ...) \
dev_level_ratelimited(dev_notice, dev, fmt, ##__VA_ARGS__)
#define dev_info_ratelimited(dev, fmt, ...) \
dev_level_ratelimited(dev_info, dev, fmt, ##__VA_ARGS__)
#if defined(CONFIG_DYNAMIC_DEBUG)
/* descriptor check is first to prevent flooding with "callbacks suppressed" */
#define dev_dbg_ratelimited(dev, fmt, ...) \
do { \
static DEFINE_RATELIMIT_STATE(_rs, \
DEFAULT_RATELIMIT_INTERVAL, \
DEFAULT_RATELIMIT_BURST); \
DEFINE_DYNAMIC_DEBUG_METADATA(descriptor, fmt); \
if (DYNAMIC_DEBUG_BRANCH(descriptor) && \
__ratelimit(&_rs)) \
__dynamic_dev_dbg(&descriptor, dev, dev_fmt(fmt), \
##__VA_ARGS__); \
} while (0)
#elif defined(DEBUG)
#define dev_dbg_ratelimited(dev, fmt, ...) \
do { \
static DEFINE_RATELIMIT_STATE(_rs, \
DEFAULT_RATELIMIT_INTERVAL, \
DEFAULT_RATELIMIT_BURST); \
if (__ratelimit(&_rs)) \
dev_printk(KERN_DEBUG, dev, dev_fmt(fmt), ##__VA_ARGS__); \
} while (0)
#else
#define dev_dbg_ratelimited(dev, fmt, ...) \
do { \
if (0) \
dev_printk(KERN_DEBUG, dev, dev_fmt(fmt), ##__VA_ARGS__); \
} while (0)
#endif
#ifdef VERBOSE_DEBUG
#define dev_vdbg dev_dbg
#else
#define dev_vdbg(dev, fmt, ...) \
({ \
if (0) \
dev_printk(KERN_DEBUG, dev, dev_fmt(fmt), ##__VA_ARGS__); \
})
#endif
/*
* dev_WARN*() acts like dev_printk(), but with the key difference of
* using WARN/WARN_ONCE to include file/line information and a backtrace.
*/
#define dev_WARN(dev, format, arg...) \
WARN(1, "%s %s: " format, dev_driver_string(dev), dev_name(dev), ## arg);
#define dev_WARN_ONCE(dev, condition, format, arg...) \
WARN_ONCE(condition, "%s %s: " format, \
dev_driver_string(dev), dev_name(dev), ## arg)
#endif /* _DEVICE_PRINTK_H_ */
This diff is collapsed.
This diff is collapsed.
// SPDX-License-Identifier: GPL-2.0
/*
* The class-specific portions of the driver model
*
* Copyright (c) 2001-2003 Patrick Mochel <mochel@osdl.org>
* Copyright (c) 2004-2009 Greg Kroah-Hartman <gregkh@suse.de>
* Copyright (c) 2008-2009 Novell Inc.
* Copyright (c) 2012-2019 Greg Kroah-Hartman <gregkh@linuxfoundation.org>
* Copyright (c) 2012-2019 Linux Foundation
*
* See Documentation/driver-api/driver-model/ for more information.
*/
#ifndef _DEVICE_CLASS_H_
#define _DEVICE_CLASS_H_
#include <linux/kobject.h>
#include <linux/klist.h>
#include <linux/pm.h>
#include <linux/device/bus.h>
struct device;
struct fwnode_handle;
/**
* struct class - device classes
* @name: Name of the class.
* @owner: The module owner.
* @class_groups: Default attributes of this class.
* @dev_groups: Default attributes of the devices that belong to the class.
* @dev_kobj: The kobject that represents this class and links it into the hierarchy.
* @dev_uevent: Called when a device is added, removed from this class, or a
* few other things that generate uevents to add the environment
* variables.
* @devnode: Callback to provide the devtmpfs.
* @class_release: Called to release this class.
* @dev_release: Called to release the device.
* @shutdown_pre: Called at shut-down time before driver shutdown.
* @ns_type: Callbacks so sysfs can detemine namespaces.
* @namespace: Namespace of the device belongs to this class.
* @get_ownership: Allows class to specify uid/gid of the sysfs directories
* for the devices belonging to the class. Usually tied to
* device's namespace.
* @pm: The default device power management operations of this class.
* @p: The private data of the driver core, no one other than the
* driver core can touch this.
*
* A class is a higher-level view of a device that abstracts out low-level
* implementation details. Drivers may see a SCSI disk or an ATA disk, but,
* at the class level, they are all simply disks. Classes allow user space
* to work with devices based on what they do, rather than how they are
* connected or how they work.
*/
struct class {
const char *name;
struct module *owner;
const struct attribute_group **class_groups;
const struct attribute_group **dev_groups;
struct kobject *dev_kobj;
int (*dev_uevent)(struct device *dev, struct kobj_uevent_env *env);
char *(*devnode)(struct device *dev, umode_t *mode);
void (*class_release)(struct class *class);
void (*dev_release)(struct device *dev);
int (*shutdown_pre)(struct device *dev);
const struct kobj_ns_type_operations *ns_type;
const void *(*namespace)(struct device *dev);
void (*get_ownership)(struct device *dev, kuid_t *uid, kgid_t *gid);
const struct dev_pm_ops *pm;
struct subsys_private *p;
};
struct class_dev_iter {
struct klist_iter ki;
const struct device_type *type;
};
extern struct kobject *sysfs_dev_block_kobj;
extern struct kobject *sysfs_dev_char_kobj;
extern int __must_check __class_register(struct class *class,
struct lock_class_key *key);
extern void class_unregister(struct class *class);
/* This is a #define to keep the compiler from merging different
* instances of the __key variable */
#define class_register(class) \
({ \
static struct lock_class_key __key; \
__class_register(class, &__key); \
})
struct class_compat;
struct class_compat *class_compat_register(const char *name);
void class_compat_unregister(struct class_compat *cls);
int class_compat_create_link(struct class_compat *cls, struct device *dev,
struct device *device_link);
void class_compat_remove_link(struct class_compat *cls, struct device *dev,
struct device *device_link);
extern void class_dev_iter_init(struct class_dev_iter *iter,
struct class *class,
struct device *start,
const struct device_type *type);
extern struct device *class_dev_iter_next(struct class_dev_iter *iter);
extern void class_dev_iter_exit(struct class_dev_iter *iter);
extern int class_for_each_device(struct class *class, struct device *start,
void *data,
int (*fn)(struct device *dev, void *data));
extern struct device *class_find_device(struct class *class,
struct device *start, const void *data,
int (*match)(struct device *, const void *));
/**
* class_find_device_by_name - device iterator for locating a particular device
* of a specific name.
* @class: class type
* @name: name of the device to match
*/
static inline struct device *class_find_device_by_name(struct class *class,
const char *name)
{
return class_find_device(class, NULL, name, device_match_name);
}
/**
* class_find_device_by_of_node : device iterator for locating a particular device
* matching the of_node.
* @class: class type
* @np: of_node of the device to match.
*/
static inline struct device *
class_find_device_by_of_node(struct class *class, const struct device_node *np)
{
return class_find_device(class, NULL, np, device_match_of_node);
}
/**
* class_find_device_by_fwnode : device iterator for locating a particular device
* matching the fwnode.
* @class: class type
* @fwnode: fwnode of the device to match.
*/
static inline struct device *
class_find_device_by_fwnode(struct class *class,
const struct fwnode_handle *fwnode)
{
return class_find_device(class, NULL, fwnode, device_match_fwnode);
}
/**
* class_find_device_by_devt : device iterator for locating a particular device
* matching the device type.
* @class: class type
* @devt: device type of the device to match.
*/
static inline struct device *class_find_device_by_devt(struct class *class,
dev_t devt)
{
return class_find_device(class, NULL, &devt, device_match_devt);
}
#ifdef CONFIG_ACPI
struct acpi_device;
/**
* class_find_device_by_acpi_dev : device iterator for locating a particular
* device matching the ACPI_COMPANION device.
* @class: class type
* @adev: ACPI_COMPANION device to match.
*/
static inline struct device *
class_find_device_by_acpi_dev(struct class *class, const struct acpi_device *adev)
{
return class_find_device(class, NULL, adev, device_match_acpi_dev);
}
#else
static inline struct device *
class_find_device_by_acpi_dev(struct class *class, const void *adev)
{
return NULL;
}
#endif
struct class_attribute {
struct attribute attr;
ssize_t (*show)(struct class *class, struct class_attribute *attr,
char *buf);
ssize_t (*store)(struct class *class, struct class_attribute *attr,
const char *buf, size_t count);
};
#define CLASS_ATTR_RW(_name) \
struct class_attribute class_attr_##_name = __ATTR_RW(_name)
#define CLASS_ATTR_RO(_name) \
struct class_attribute class_attr_##_name = __ATTR_RO(_name)
#define CLASS_ATTR_WO(_name) \
struct class_attribute class_attr_##_name = __ATTR_WO(_name)
extern int __must_check class_create_file_ns(struct class *class,
const struct class_attribute *attr,
const void *ns);
extern void class_remove_file_ns(struct class *class,
const struct class_attribute *attr,
const void *ns);
static inline int __must_check class_create_file(struct class *class,
const struct class_attribute *attr)
{
return class_create_file_ns(class, attr, NULL);
}
static inline void class_remove_file(struct class *class,
const struct class_attribute *attr)
{
return class_remove_file_ns(class, attr, NULL);
}
/* Simple class attribute that is just a static string */
struct class_attribute_string {
struct class_attribute attr;
char *str;
};
/* Currently read-only only */
#define _CLASS_ATTR_STRING(_name, _mode, _str) \
{ __ATTR(_name, _mode, show_class_attr_string, NULL), _str }
#define CLASS_ATTR_STRING(_name, _mode, _str) \
struct class_attribute_string class_attr_##_name = \
_CLASS_ATTR_STRING(_name, _mode, _str)
extern ssize_t show_class_attr_string(struct class *class, struct class_attribute *attr,
char *buf);
struct class_interface {
struct list_head node;
struct class *class;
int (*add_dev) (struct device *, struct class_interface *);
void (*remove_dev) (struct device *, struct class_interface *);
};
extern int __must_check class_interface_register(struct class_interface *);
extern void class_interface_unregister(struct class_interface *);
extern struct class * __must_check __class_create(struct module *owner,
const char *name,
struct lock_class_key *key);
extern void class_destroy(struct class *cls);
/* This is a #define to keep the compiler from merging different
* instances of the __key variable */
#define class_create(owner, name) \
({ \
static struct lock_class_key __key; \
__class_create(owner, name, &__key); \
})
#endif /* _DEVICE_CLASS_H_ */
This diff is collapsed.
...@@ -63,7 +63,7 @@ ...@@ -63,7 +63,7 @@
#include <linux/lockdep.h> #include <linux/lockdep.h>
#include <linux/kmemleak.h> #include <linux/kmemleak.h>
#include <linux/pid_namespace.h> #include <linux/pid_namespace.h>
#include <linux/device.h> #include <linux/device/driver.h>
#include <linux/kthread.h> #include <linux/kthread.h>
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/sched/init.h> #include <linux/sched/init.h>
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment