Merge branch 'driver-core-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core.git

This commit is contained in:
Stephen Rothwell 2025-01-13 09:12:08 +11:00
commit 51f36d61e6
4 changed files with 77 additions and 40 deletions

View File

@ -27,9 +27,17 @@ static ssize_t name##_read(struct file *file, struct kobject *kobj, \
loff_t off, size_t count) \
{ \
struct device *dev = kobj_to_dev(kobj); \
cpumask_var_t mask; \
ssize_t n; \
\
return cpumap_print_bitmask_to_buf(buf, topology_##mask(dev->id), \
off, count); \
if (!alloc_cpumask_var(&mask, GFP_KERNEL)) \
return -ENOMEM; \
\
cpumask_copy(mask, topology_##mask(dev->id)); \
n = cpumap_print_bitmask_to_buf(buf, mask, off, count); \
free_cpumask_var(mask); \
\
return n; \
} \
\
static ssize_t name##_list_read(struct file *file, struct kobject *kobj, \
@ -37,9 +45,17 @@ static ssize_t name##_list_read(struct file *file, struct kobject *kobj, \
loff_t off, size_t count) \
{ \
struct device *dev = kobj_to_dev(kobj); \
cpumask_var_t mask; \
ssize_t n; \
\
return cpumap_print_list_to_buf(buf, topology_##mask(dev->id), \
off, count); \
if (!alloc_cpumask_var(&mask, GFP_KERNEL)) \
return -ENOMEM; \
\
cpumask_copy(mask, topology_##mask(dev->id)); \
n = cpumap_print_list_to_buf(buf, mask, off, count); \
free_cpumask_var(mask); \
\
return n; \
}
define_id_show_func(physical_package_id, "%d");

View File

@ -64,22 +64,13 @@ const struct file_operations *debugfs_real_fops(const struct file *filp)
}
EXPORT_SYMBOL_GPL(debugfs_real_fops);
/**
* debugfs_file_get - mark the beginning of file data access
* @dentry: the dentry object whose data is being accessed.
*
* Up to a matching call to debugfs_file_put(), any successive call
* into the file removing functions debugfs_remove() and
* debugfs_remove_recursive() will block. Since associated private
* file data may only get freed after a successful return of any of
* the removal functions, you may safely access it after a successful
* call to debugfs_file_get() without worrying about lifetime issues.
*
* If -%EIO is returned, the file has already been removed and thus,
* it is not safe to access any of its data. If, on the other hand,
* it is allowed to access the file data, zero is returned.
*/
int debugfs_file_get(struct dentry *dentry)
enum dbgfs_get_mode {
DBGFS_GET_ALREADY,
DBGFS_GET_REGULAR,
DBGFS_GET_SHORT,
};
static int __debugfs_file_get(struct dentry *dentry, enum dbgfs_get_mode mode)
{
struct debugfs_fsdata *fsd;
void *d_fsd;
@ -96,15 +87,17 @@ int debugfs_file_get(struct dentry *dentry)
if (!((unsigned long)d_fsd & DEBUGFS_FSDATA_IS_REAL_FOPS_BIT)) {
fsd = d_fsd;
} else {
if (WARN_ON(mode == DBGFS_GET_ALREADY))
return -EINVAL;
fsd = kmalloc(sizeof(*fsd), GFP_KERNEL);
if (!fsd)
return -ENOMEM;
if ((unsigned long)d_fsd & DEBUGFS_FSDATA_IS_SHORT_FOPS_BIT) {
if (mode == DBGFS_GET_SHORT) {
fsd->real_fops = NULL;
fsd->short_fops = (void *)((unsigned long)d_fsd &
~(DEBUGFS_FSDATA_IS_REAL_FOPS_BIT |
DEBUGFS_FSDATA_IS_SHORT_FOPS_BIT));
~DEBUGFS_FSDATA_IS_REAL_FOPS_BIT);
} else {
fsd->real_fops = (void *)((unsigned long)d_fsd &
~DEBUGFS_FSDATA_IS_REAL_FOPS_BIT);
@ -138,6 +131,26 @@ int debugfs_file_get(struct dentry *dentry)
return 0;
}
/**
* debugfs_file_get - mark the beginning of file data access
* @dentry: the dentry object whose data is being accessed.
*
* Up to a matching call to debugfs_file_put(), any successive call
* into the file removing functions debugfs_remove() and
* debugfs_remove_recursive() will block. Since associated private
* file data may only get freed after a successful return of any of
* the removal functions, you may safely access it after a successful
* call to debugfs_file_get() without worrying about lifetime issues.
*
* If -%EIO is returned, the file has already been removed and thus,
* it is not safe to access any of its data. If, on the other hand,
* it is allowed to access the file data, zero is returned.
*/
int debugfs_file_get(struct dentry *dentry)
{
return __debugfs_file_get(dentry, DBGFS_GET_ALREADY);
}
EXPORT_SYMBOL_GPL(debugfs_file_get);
/**
@ -267,7 +280,7 @@ static int open_proxy_open(struct inode *inode, struct file *filp)
const struct file_operations *real_fops = NULL;
int r;
r = debugfs_file_get(dentry);
r = __debugfs_file_get(dentry, DBGFS_GET_REGULAR);
if (r)
return r == -EIO ? -ENOENT : r;
@ -424,7 +437,8 @@ static void __full_proxy_fops_init(struct file_operations *proxy_fops,
proxy_fops->unlocked_ioctl = full_proxy_unlocked_ioctl;
}
static int full_proxy_open(struct inode *inode, struct file *filp)
static int full_proxy_open(struct inode *inode, struct file *filp,
enum dbgfs_get_mode mode)
{
struct dentry *dentry = F_DENTRY(filp);
const struct file_operations *real_fops;
@ -432,7 +446,7 @@ static int full_proxy_open(struct inode *inode, struct file *filp)
struct debugfs_fsdata *fsd;
int r;
r = debugfs_file_get(dentry);
r = __debugfs_file_get(dentry, mode);
if (r)
return r == -EIO ? -ENOENT : r;
@ -491,8 +505,22 @@ out:
return r;
}
static int full_proxy_open_regular(struct inode *inode, struct file *filp)
{
return full_proxy_open(inode, filp, DBGFS_GET_REGULAR);
}
const struct file_operations debugfs_full_proxy_file_operations = {
.open = full_proxy_open,
.open = full_proxy_open_regular,
};
static int full_proxy_open_short(struct inode *inode, struct file *filp)
{
return full_proxy_open(inode, filp, DBGFS_GET_SHORT);
}
const struct file_operations debugfs_full_short_proxy_file_operations = {
.open = full_proxy_open_short,
};
ssize_t debugfs_attr_read(struct file *file, char __user *buf,

View File

@ -229,7 +229,7 @@ static void debugfs_release_dentry(struct dentry *dentry)
return;
/* check it wasn't a dir (no fsdata) or automount (no real_fops) */
if (fsd && fsd->real_fops) {
if (fsd && (fsd->real_fops || fsd->short_fops)) {
WARN_ON(!list_empty(&fsd->cancellations));
mutex_destroy(&fsd->cancellations_mtx);
}
@ -455,8 +455,7 @@ struct dentry *debugfs_create_file_full(const char *name, umode_t mode,
const struct file_operations *fops)
{
if (WARN_ON((unsigned long)fops &
(DEBUGFS_FSDATA_IS_SHORT_FOPS_BIT |
DEBUGFS_FSDATA_IS_REAL_FOPS_BIT)))
DEBUGFS_FSDATA_IS_REAL_FOPS_BIT))
return ERR_PTR(-EINVAL);
return __debugfs_create_file(name, mode, parent, data,
@ -471,15 +470,13 @@ struct dentry *debugfs_create_file_short(const char *name, umode_t mode,
const struct debugfs_short_fops *fops)
{
if (WARN_ON((unsigned long)fops &
(DEBUGFS_FSDATA_IS_SHORT_FOPS_BIT |
DEBUGFS_FSDATA_IS_REAL_FOPS_BIT)))
DEBUGFS_FSDATA_IS_REAL_FOPS_BIT))
return ERR_PTR(-EINVAL);
return __debugfs_create_file(name, mode, parent, data,
fops ? &debugfs_full_proxy_file_operations :
fops ? &debugfs_full_short_proxy_file_operations :
&debugfs_noop_file_operations,
(const void *)((unsigned long)fops |
DEBUGFS_FSDATA_IS_SHORT_FOPS_BIT));
fops);
}
EXPORT_SYMBOL_GPL(debugfs_create_file_short);

View File

@ -15,6 +15,7 @@ struct file_operations;
extern const struct file_operations debugfs_noop_file_operations;
extern const struct file_operations debugfs_open_proxy_file_operations;
extern const struct file_operations debugfs_full_proxy_file_operations;
extern const struct file_operations debugfs_full_short_proxy_file_operations;
struct debugfs_fsdata {
const struct file_operations *real_fops;
@ -40,11 +41,6 @@ struct debugfs_fsdata {
* pointer gets its lowest bit set.
*/
#define DEBUGFS_FSDATA_IS_REAL_FOPS_BIT BIT(0)
/*
* A dentry's ->d_fsdata, when pointing to real fops, is with
* short fops instead of full fops.
*/
#define DEBUGFS_FSDATA_IS_SHORT_FOPS_BIT BIT(1)
/* Access BITS */
#define DEBUGFS_ALLOW_API BIT(0)