mirror of
git://git.yoctoproject.org/linux-yocto.git
synced 2025-10-22 15:03:53 +02:00
Driver core changes for 6.16-rc1
Here are the driver core / kernfs changes for 6.16-rc1. Not a huge number of changes this development cycle, here's the summary of what is included in here: - kernfs locking tweaks, pushing some global locks down into a per-fs image lock - rust driver core and pci device bindings added for new features. - sysfs const work for bin_attributes. This churn should now be completed for those types of attributes - auxbus device creation helpers added - fauxbus fix for creating sysfs files after the probe completed properly - other tiny updates for driver core things. All of these have been in linux-next for over a week with no reported issues. Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> -----BEGIN PGP SIGNATURE----- iG0EABECAC0WIQT0tgzFv3jCIUoxPcsxR9QN2y37KQUCaDbe+g8cZ3JlZ0Brcm9h aC5jb20ACgkQMUfUDdst+ylYbACgl/MngU9pRnx5jZIQh6bWveFSeo8AnRE4U5x0 X+lgTPjGKL1RrV3C5HJp =+0BA -----END PGP SIGNATURE----- Merge tag 'driver-core-6.16-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/driver-core/driver-core Pull driver core updates from Greg KH: "Here are the driver core / kernfs changes for 6.16-rc1. Not a huge number of changes this development cycle, here's the summary of what is included in here: - kernfs locking tweaks, pushing some global locks down into a per-fs image lock - rust driver core and pci device bindings added for new features. - sysfs const work for bin_attributes. The final churn of switching away from and removing the transitional struct members, "read_new", "write_new" and "bin_attrs_new" will come after the merge window to avoid unnecesary merge conflicts. - auxbus device creation helpers added - fauxbus fix for creating sysfs files after the probe completed properly - other tiny updates for driver core things. All of these have been in linux-next for over a week with no reported issues" * tag 'driver-core-6.16-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/driver-core/driver-core: kernfs: Relax constraint in draining guard Documentation: embargoed-hardware-issues.rst: Remove myself drivers: hv: fix up const issue with vmbus_chan_bin_attrs firmware_loader: use SHA-256 library API instead of crypto_shash API docs: debugfs: do not recommend debugfs_remove_recursive PM: wakeup: Do not expose 4 device wakeup source APIs kernfs: switch global kernfs_rename_lock to per-fs lock kernfs: switch global kernfs_idr_lock to per-fs lock driver core: auxiliary bus: Fix IS_ERR() vs NULL mixup in __devm_auxiliary_device_create() sysfs: constify attribute_group::bin_attrs sysfs: constify bin_attribute argument of bin_attribute::read/write() software node: Correct a OOB check in software_node_get_reference_args() devres: simplify devm_kstrdup() using devm_kmemdup() platform: replace magic number with macro PLATFORM_DEVID_NONE component: do not try to unbind unbound components driver core: auxiliary bus: add device creation helpers driver core: faux: Add sysfs groups after probing
This commit is contained in:
commit
9d230d500b
|
@ -229,22 +229,15 @@ module is unloaded without explicitly removing debugfs entries, the result
|
|||
will be a lot of stale pointers and no end of highly antisocial behavior.
|
||||
So all debugfs users - at least those which can be built as modules - must
|
||||
be prepared to remove all files and directories they create there. A file
|
||||
can be removed with::
|
||||
or directory can be removed with::
|
||||
|
||||
void debugfs_remove(struct dentry *dentry);
|
||||
|
||||
The dentry value can be NULL or an error value, in which case nothing will
|
||||
be removed.
|
||||
|
||||
Once upon a time, debugfs users were required to remember the dentry
|
||||
pointer for every debugfs file they created so that all files could be
|
||||
cleaned up. We live in more civilized times now, though, and debugfs users
|
||||
can call::
|
||||
|
||||
void debugfs_remove_recursive(struct dentry *dentry);
|
||||
|
||||
If this function is passed a pointer for the dentry corresponding to the
|
||||
top-level directory, the entire hierarchy below that directory will be
|
||||
removed.
|
||||
be removed. Note that this function will recursively remove all files and
|
||||
directories underneath it. Previously, debugfs_remove_recursive() was used
|
||||
to perform that task, but this function is now just an alias to
|
||||
debugfs_remove(). debugfs_remove_recursive() should be considered
|
||||
deprecated.
|
||||
|
||||
.. [1] http://lwn.net/Articles/309298/
|
||||
|
|
|
@ -155,7 +155,7 @@ The general idea is:
|
|||
``my_variable``
|
||||
|
||||
- Clean up the directory when removing the device
|
||||
(``debugfs_remove_recursive(parent);``)
|
||||
(``debugfs_remove(parent);``)
|
||||
|
||||
For the full documentation see :doc:`/filesystems/debugfs`.
|
||||
|
||||
|
|
|
@ -290,7 +290,6 @@ an involved disclosed party. The current ambassadors list:
|
|||
AMD Tom Lendacky <thomas.lendacky@amd.com>
|
||||
Ampere Darren Hart <darren@os.amperecomputing.com>
|
||||
ARM Catalin Marinas <catalin.marinas@arm.com>
|
||||
IBM Power Michael Ellerman <ellerman@au.ibm.com>
|
||||
IBM Z Christian Borntraeger <borntraeger@de.ibm.com>
|
||||
Intel Tony Luck <tony.luck@intel.com>
|
||||
Qualcomm Trilok Soni <quic_tsoni@quicinc.com>
|
||||
|
|
|
@ -395,6 +395,114 @@ void auxiliary_driver_unregister(struct auxiliary_driver *auxdrv)
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(auxiliary_driver_unregister);
|
||||
|
||||
static void auxiliary_device_release(struct device *dev)
|
||||
{
|
||||
struct auxiliary_device *auxdev = to_auxiliary_dev(dev);
|
||||
|
||||
kfree(auxdev);
|
||||
}
|
||||
|
||||
/**
|
||||
* auxiliary_device_create - create a device on the auxiliary bus
|
||||
* @dev: parent device
|
||||
* @modname: module name used to create the auxiliary driver name.
|
||||
* @devname: auxiliary bus device name
|
||||
* @platform_data: auxiliary bus device platform data
|
||||
* @id: auxiliary bus device id
|
||||
*
|
||||
* Helper to create an auxiliary bus device.
|
||||
* The device created matches driver 'modname.devname' on the auxiliary bus.
|
||||
*/
|
||||
struct auxiliary_device *auxiliary_device_create(struct device *dev,
|
||||
const char *modname,
|
||||
const char *devname,
|
||||
void *platform_data,
|
||||
int id)
|
||||
{
|
||||
struct auxiliary_device *auxdev;
|
||||
int ret;
|
||||
|
||||
auxdev = kzalloc(sizeof(*auxdev), GFP_KERNEL);
|
||||
if (!auxdev)
|
||||
return NULL;
|
||||
|
||||
auxdev->id = id;
|
||||
auxdev->name = devname;
|
||||
auxdev->dev.parent = dev;
|
||||
auxdev->dev.platform_data = platform_data;
|
||||
auxdev->dev.release = auxiliary_device_release;
|
||||
device_set_of_node_from_dev(&auxdev->dev, dev);
|
||||
|
||||
ret = auxiliary_device_init(auxdev);
|
||||
if (ret) {
|
||||
kfree(auxdev);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ret = __auxiliary_device_add(auxdev, modname);
|
||||
if (ret) {
|
||||
/*
|
||||
* It may look odd but auxdev should not be freed here.
|
||||
* auxiliary_device_uninit() calls device_put() which call
|
||||
* the device release function, freeing auxdev.
|
||||
*/
|
||||
auxiliary_device_uninit(auxdev);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return auxdev;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(auxiliary_device_create);
|
||||
|
||||
/**
|
||||
* auxiliary_device_destroy - remove an auxiliary device
|
||||
* @auxdev: pointer to the auxdev to be removed
|
||||
*
|
||||
* Helper to remove an auxiliary device created with
|
||||
* auxiliary_device_create()
|
||||
*/
|
||||
void auxiliary_device_destroy(void *auxdev)
|
||||
{
|
||||
struct auxiliary_device *_auxdev = auxdev;
|
||||
|
||||
auxiliary_device_delete(_auxdev);
|
||||
auxiliary_device_uninit(_auxdev);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(auxiliary_device_destroy);
|
||||
|
||||
/**
|
||||
* __devm_auxiliary_device_create - create a managed device on the auxiliary bus
|
||||
* @dev: parent device
|
||||
* @modname: module name used to create the auxiliary driver name.
|
||||
* @devname: auxiliary bus device name
|
||||
* @platform_data: auxiliary bus device platform data
|
||||
* @id: auxiliary bus device id
|
||||
*
|
||||
* Device managed helper to create an auxiliary bus device.
|
||||
* The device created matches driver 'modname.devname' on the auxiliary bus.
|
||||
*/
|
||||
struct auxiliary_device *__devm_auxiliary_device_create(struct device *dev,
|
||||
const char *modname,
|
||||
const char *devname,
|
||||
void *platform_data,
|
||||
int id)
|
||||
{
|
||||
struct auxiliary_device *auxdev;
|
||||
int ret;
|
||||
|
||||
auxdev = auxiliary_device_create(dev, modname, devname, platform_data, id);
|
||||
if (!auxdev)
|
||||
return NULL;
|
||||
|
||||
ret = devm_add_action_or_reset(dev, auxiliary_device_destroy,
|
||||
auxdev);
|
||||
if (ret)
|
||||
return NULL;
|
||||
|
||||
return auxdev;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(__devm_auxiliary_device_create);
|
||||
|
||||
void __init auxiliary_bus_init(void)
|
||||
{
|
||||
WARN_ON(bus_register(&auxiliary_bus_type));
|
||||
|
|
|
@ -586,7 +586,8 @@ EXPORT_SYMBOL_GPL(component_master_is_bound);
|
|||
static void component_unbind(struct component *component,
|
||||
struct aggregate_device *adev, void *data)
|
||||
{
|
||||
WARN_ON(!component->bound);
|
||||
if (WARN_ON(!component->bound))
|
||||
return;
|
||||
|
||||
dev_dbg(adev->parent, "unbinding %s component %p (ops %ps)\n",
|
||||
dev_name(component->dev), component, component->ops);
|
||||
|
|
|
@ -987,17 +987,10 @@ EXPORT_SYMBOL_GPL(devm_krealloc);
|
|||
*/
|
||||
char *devm_kstrdup(struct device *dev, const char *s, gfp_t gfp)
|
||||
{
|
||||
size_t size;
|
||||
char *buf;
|
||||
|
||||
if (!s)
|
||||
return NULL;
|
||||
|
||||
size = strlen(s) + 1;
|
||||
buf = devm_kmalloc(dev, size, gfp);
|
||||
if (buf)
|
||||
memcpy(buf, s, size);
|
||||
return buf;
|
||||
return devm_kmemdup(dev, s, strlen(s) + 1, gfp);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(devm_kstrdup);
|
||||
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
struct faux_object {
|
||||
struct faux_device faux_dev;
|
||||
const struct faux_device_ops *faux_ops;
|
||||
const struct attribute_group **groups;
|
||||
};
|
||||
#define to_faux_object(dev) container_of_const(dev, struct faux_object, faux_dev.dev)
|
||||
|
||||
|
@ -43,10 +44,21 @@ static int faux_probe(struct device *dev)
|
|||
struct faux_object *faux_obj = to_faux_object(dev);
|
||||
struct faux_device *faux_dev = &faux_obj->faux_dev;
|
||||
const struct faux_device_ops *faux_ops = faux_obj->faux_ops;
|
||||
int ret = 0;
|
||||
int ret;
|
||||
|
||||
if (faux_ops && faux_ops->probe)
|
||||
if (faux_ops && faux_ops->probe) {
|
||||
ret = faux_ops->probe(faux_dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Add groups after the probe succeeds to ensure resources are
|
||||
* initialized correctly
|
||||
*/
|
||||
ret = device_add_groups(dev, faux_obj->groups);
|
||||
if (ret && faux_ops && faux_ops->remove)
|
||||
faux_ops->remove(faux_dev);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -57,6 +69,8 @@ static void faux_remove(struct device *dev)
|
|||
struct faux_device *faux_dev = &faux_obj->faux_dev;
|
||||
const struct faux_device_ops *faux_ops = faux_obj->faux_ops;
|
||||
|
||||
device_remove_groups(dev, faux_obj->groups);
|
||||
|
||||
if (faux_ops && faux_ops->remove)
|
||||
faux_ops->remove(faux_dev);
|
||||
}
|
||||
|
@ -124,8 +138,9 @@ struct faux_device *faux_device_create_with_groups(const char *name,
|
|||
if (!faux_obj)
|
||||
return NULL;
|
||||
|
||||
/* Save off the callbacks so we can use them in the future */
|
||||
/* Save off the callbacks and groups so we can use them in the future */
|
||||
faux_obj->faux_ops = faux_ops;
|
||||
faux_obj->groups = groups;
|
||||
|
||||
/* Initialize the device portion and register it with the driver core */
|
||||
faux_dev = &faux_obj->faux_dev;
|
||||
|
@ -138,7 +153,6 @@ struct faux_device *faux_device_create_with_groups(const char *name,
|
|||
else
|
||||
dev->parent = &faux_bus_root;
|
||||
dev->bus = &faux_bus_type;
|
||||
dev->groups = groups;
|
||||
dev_set_name(dev, "%s", name);
|
||||
|
||||
ret = device_add(dev);
|
||||
|
|
|
@ -3,8 +3,7 @@ menu "Firmware loader"
|
|||
|
||||
config FW_LOADER
|
||||
tristate "Firmware loading facility" if EXPERT
|
||||
select CRYPTO_HASH if FW_LOADER_DEBUG
|
||||
select CRYPTO_SHA256 if FW_LOADER_DEBUG
|
||||
select CRYPTO_LIB_SHA256 if FW_LOADER_DEBUG
|
||||
default y
|
||||
help
|
||||
This enables the firmware loading facility in the kernel. The kernel
|
||||
|
@ -28,7 +27,6 @@ config FW_LOADER
|
|||
|
||||
config FW_LOADER_DEBUG
|
||||
bool "Log filenames and checksums for loaded firmware"
|
||||
depends on CRYPTO = FW_LOADER || CRYPTO=y
|
||||
depends on DYNAMIC_DEBUG
|
||||
depends on FW_LOADER
|
||||
default FW_LOADER
|
||||
|
|
|
@ -806,41 +806,15 @@ static void fw_abort_batch_reqs(struct firmware *fw)
|
|||
}
|
||||
|
||||
#if defined(CONFIG_FW_LOADER_DEBUG)
|
||||
#include <crypto/hash.h>
|
||||
#include <crypto/sha2.h>
|
||||
|
||||
static void fw_log_firmware_info(const struct firmware *fw, const char *name, struct device *device)
|
||||
{
|
||||
struct shash_desc *shash;
|
||||
struct crypto_shash *alg;
|
||||
u8 *sha256buf;
|
||||
char *outbuf;
|
||||
u8 digest[SHA256_DIGEST_SIZE];
|
||||
|
||||
alg = crypto_alloc_shash("sha256", 0, 0);
|
||||
if (IS_ERR(alg))
|
||||
return;
|
||||
|
||||
sha256buf = kmalloc(SHA256_DIGEST_SIZE, GFP_KERNEL);
|
||||
outbuf = kmalloc(SHA256_BLOCK_SIZE + 1, GFP_KERNEL);
|
||||
shash = kmalloc(sizeof(*shash) + crypto_shash_descsize(alg), GFP_KERNEL);
|
||||
if (!sha256buf || !outbuf || !shash)
|
||||
goto out_free;
|
||||
|
||||
shash->tfm = alg;
|
||||
|
||||
if (crypto_shash_digest(shash, fw->data, fw->size, sha256buf) < 0)
|
||||
goto out_free;
|
||||
|
||||
for (int i = 0; i < SHA256_DIGEST_SIZE; i++)
|
||||
sprintf(&outbuf[i * 2], "%02x", sha256buf[i]);
|
||||
outbuf[SHA256_BLOCK_SIZE] = 0;
|
||||
dev_dbg(device, "Loaded FW: %s, sha256: %s\n", name, outbuf);
|
||||
|
||||
out_free:
|
||||
kfree(shash);
|
||||
kfree(outbuf);
|
||||
kfree(sha256buf);
|
||||
crypto_free_shash(alg);
|
||||
sha256(fw->data, fw->size, digest);
|
||||
dev_dbg(device, "Loaded FW: %s, sha256: %*phN\n",
|
||||
name, SHA256_DIGEST_SIZE, digest);
|
||||
}
|
||||
#else
|
||||
static void fw_log_firmware_info(const struct firmware *fw, const char *name,
|
||||
|
|
|
@ -982,7 +982,7 @@ struct platform_device * __init_or_module __platform_create_bundle(
|
|||
struct platform_device *pdev;
|
||||
int error;
|
||||
|
||||
pdev = platform_device_alloc(driver->driver.name, -1);
|
||||
pdev = platform_device_alloc(driver->driver.name, PLATFORM_DEVID_NONE);
|
||||
if (!pdev) {
|
||||
error = -ENOMEM;
|
||||
goto err_out;
|
||||
|
|
|
@ -77,7 +77,7 @@ static DEFINE_IDA(wakeup_ida);
|
|||
* wakeup_source_create - Create a struct wakeup_source object.
|
||||
* @name: Name of the new wakeup source.
|
||||
*/
|
||||
struct wakeup_source *wakeup_source_create(const char *name)
|
||||
static struct wakeup_source *wakeup_source_create(const char *name)
|
||||
{
|
||||
struct wakeup_source *ws;
|
||||
const char *ws_name;
|
||||
|
@ -106,7 +106,6 @@ err_name:
|
|||
err_ws:
|
||||
return NULL;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(wakeup_source_create);
|
||||
|
||||
/*
|
||||
* Record wakeup_source statistics being deleted into a dummy wakeup_source.
|
||||
|
@ -149,7 +148,7 @@ static void wakeup_source_free(struct wakeup_source *ws)
|
|||
*
|
||||
* Use only for wakeup source objects created with wakeup_source_create().
|
||||
*/
|
||||
void wakeup_source_destroy(struct wakeup_source *ws)
|
||||
static void wakeup_source_destroy(struct wakeup_source *ws)
|
||||
{
|
||||
if (!ws)
|
||||
return;
|
||||
|
@ -158,13 +157,12 @@ void wakeup_source_destroy(struct wakeup_source *ws)
|
|||
wakeup_source_record(ws);
|
||||
wakeup_source_free(ws);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(wakeup_source_destroy);
|
||||
|
||||
/**
|
||||
* wakeup_source_add - Add given object to the list of wakeup sources.
|
||||
* @ws: Wakeup source object to add to the list.
|
||||
*/
|
||||
void wakeup_source_add(struct wakeup_source *ws)
|
||||
static void wakeup_source_add(struct wakeup_source *ws)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
|
@ -179,13 +177,12 @@ void wakeup_source_add(struct wakeup_source *ws)
|
|||
list_add_rcu(&ws->entry, &wakeup_sources);
|
||||
raw_spin_unlock_irqrestore(&events_lock, flags);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(wakeup_source_add);
|
||||
|
||||
/**
|
||||
* wakeup_source_remove - Remove given object from the wakeup sources list.
|
||||
* @ws: Wakeup source object to remove from the list.
|
||||
*/
|
||||
void wakeup_source_remove(struct wakeup_source *ws)
|
||||
static void wakeup_source_remove(struct wakeup_source *ws)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
|
@ -204,7 +201,6 @@ void wakeup_source_remove(struct wakeup_source *ws)
|
|||
*/
|
||||
ws->timer.function = NULL;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(wakeup_source_remove);
|
||||
|
||||
/**
|
||||
* wakeup_source_register - Create wakeup source and add it to the list.
|
||||
|
|
|
@ -529,7 +529,7 @@ software_node_get_reference_args(const struct fwnode_handle *fwnode,
|
|||
if (prop->is_inline)
|
||||
return -EINVAL;
|
||||
|
||||
if (index * sizeof(*ref) >= prop->length)
|
||||
if ((index + 1) * sizeof(*ref) > prop->length)
|
||||
return -ENOENT;
|
||||
|
||||
ref_array = prop->pointer;
|
||||
|
|
|
@ -1841,7 +1841,7 @@ static struct attribute *vmbus_chan_attrs[] = {
|
|||
NULL
|
||||
};
|
||||
|
||||
static struct bin_attribute *vmbus_chan_bin_attrs[] = {
|
||||
static const struct bin_attribute *vmbus_chan_bin_attrs[] = {
|
||||
&chan_attr_ring_buffer,
|
||||
NULL
|
||||
};
|
||||
|
|
|
@ -17,7 +17,6 @@
|
|||
|
||||
#include "kernfs-internal.h"
|
||||
|
||||
DEFINE_RWLOCK(kernfs_rename_lock); /* kn->parent and ->name */
|
||||
/*
|
||||
* Don't use rename_lock to piggy back on pr_cont_buf. We don't want to
|
||||
* call pr_cont() while holding rename_lock. Because sometimes pr_cont()
|
||||
|
@ -27,7 +26,6 @@ DEFINE_RWLOCK(kernfs_rename_lock); /* kn->parent and ->name */
|
|||
*/
|
||||
static DEFINE_SPINLOCK(kernfs_pr_cont_lock);
|
||||
static char kernfs_pr_cont_buf[PATH_MAX]; /* protected by pr_cont_lock */
|
||||
static DEFINE_SPINLOCK(kernfs_idr_lock); /* root->ino_idr */
|
||||
|
||||
#define rb_to_kn(X) rb_entry((X), struct kernfs_node, rb)
|
||||
|
||||
|
@ -229,7 +227,7 @@ int kernfs_path_from_node(struct kernfs_node *to, struct kernfs_node *from,
|
|||
if (to) {
|
||||
root = kernfs_root(to);
|
||||
if (!(root->flags & KERNFS_ROOT_INVARIANT_PARENT)) {
|
||||
guard(read_lock_irqsave)(&kernfs_rename_lock);
|
||||
guard(read_lock_irqsave)(&root->kernfs_rename_lock);
|
||||
return kernfs_path_from_node_locked(to, from, buf, buflen);
|
||||
}
|
||||
}
|
||||
|
@ -296,12 +294,14 @@ out:
|
|||
struct kernfs_node *kernfs_get_parent(struct kernfs_node *kn)
|
||||
{
|
||||
struct kernfs_node *parent;
|
||||
struct kernfs_root *root;
|
||||
unsigned long flags;
|
||||
|
||||
read_lock_irqsave(&kernfs_rename_lock, flags);
|
||||
root = kernfs_root(kn);
|
||||
read_lock_irqsave(&root->kernfs_rename_lock, flags);
|
||||
parent = kernfs_parent(kn);
|
||||
kernfs_get(parent);
|
||||
read_unlock_irqrestore(&kernfs_rename_lock, flags);
|
||||
read_unlock_irqrestore(&root->kernfs_rename_lock, flags);
|
||||
|
||||
return parent;
|
||||
}
|
||||
|
@ -584,9 +584,9 @@ void kernfs_put(struct kernfs_node *kn)
|
|||
if (kernfs_type(kn) == KERNFS_LINK)
|
||||
kernfs_put(kn->symlink.target_kn);
|
||||
|
||||
spin_lock(&kernfs_idr_lock);
|
||||
spin_lock(&root->kernfs_idr_lock);
|
||||
idr_remove(&root->ino_idr, (u32)kernfs_ino(kn));
|
||||
spin_unlock(&kernfs_idr_lock);
|
||||
spin_unlock(&root->kernfs_idr_lock);
|
||||
|
||||
call_rcu(&kn->rcu, kernfs_free_rcu);
|
||||
|
||||
|
@ -639,13 +639,13 @@ static struct kernfs_node *__kernfs_new_node(struct kernfs_root *root,
|
|||
goto err_out1;
|
||||
|
||||
idr_preload(GFP_KERNEL);
|
||||
spin_lock(&kernfs_idr_lock);
|
||||
spin_lock(&root->kernfs_idr_lock);
|
||||
ret = idr_alloc_cyclic(&root->ino_idr, kn, 1, 0, GFP_ATOMIC);
|
||||
if (ret >= 0 && ret < root->last_id_lowbits)
|
||||
root->id_highbits++;
|
||||
id_highbits = root->id_highbits;
|
||||
root->last_id_lowbits = ret;
|
||||
spin_unlock(&kernfs_idr_lock);
|
||||
spin_unlock(&root->kernfs_idr_lock);
|
||||
idr_preload_end();
|
||||
if (ret < 0)
|
||||
goto err_out2;
|
||||
|
@ -681,9 +681,9 @@ static struct kernfs_node *__kernfs_new_node(struct kernfs_root *root,
|
|||
return kn;
|
||||
|
||||
err_out3:
|
||||
spin_lock(&kernfs_idr_lock);
|
||||
spin_lock(&root->kernfs_idr_lock);
|
||||
idr_remove(&root->ino_idr, (u32)kernfs_ino(kn));
|
||||
spin_unlock(&kernfs_idr_lock);
|
||||
spin_unlock(&root->kernfs_idr_lock);
|
||||
err_out2:
|
||||
kmem_cache_free(kernfs_node_cache, kn);
|
||||
err_out1:
|
||||
|
@ -989,10 +989,12 @@ struct kernfs_root *kernfs_create_root(struct kernfs_syscall_ops *scops,
|
|||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
idr_init(&root->ino_idr);
|
||||
spin_lock_init(&root->kernfs_idr_lock);
|
||||
init_rwsem(&root->kernfs_rwsem);
|
||||
init_rwsem(&root->kernfs_iattr_rwsem);
|
||||
init_rwsem(&root->kernfs_supers_rwsem);
|
||||
INIT_LIST_HEAD(&root->supers);
|
||||
rwlock_init(&root->kernfs_rename_lock);
|
||||
|
||||
/*
|
||||
* On 64bit ino setups, id is ino. On 32bit, low 32bits are ino.
|
||||
|
@ -1580,8 +1582,9 @@ void kernfs_break_active_protection(struct kernfs_node *kn)
|
|||
* invoked before finishing the kernfs operation. Note that while this
|
||||
* function restores the active reference, it doesn't and can't actually
|
||||
* restore the active protection - @kn may already or be in the process of
|
||||
* being removed. Once kernfs_break_active_protection() is invoked, that
|
||||
* protection is irreversibly gone for the kernfs operation instance.
|
||||
* being drained and removed. Once kernfs_break_active_protection() is
|
||||
* invoked, that protection is irreversibly gone for the kernfs operation
|
||||
* instance.
|
||||
*
|
||||
* While this function may be called at any point after
|
||||
* kernfs_break_active_protection() is invoked, its most useful location
|
||||
|
@ -1789,7 +1792,7 @@ int kernfs_rename_ns(struct kernfs_node *kn, struct kernfs_node *new_parent,
|
|||
/* rename_lock protects ->parent accessors */
|
||||
if (old_parent != new_parent) {
|
||||
kernfs_get(new_parent);
|
||||
write_lock_irq(&kernfs_rename_lock);
|
||||
write_lock_irq(&root->kernfs_rename_lock);
|
||||
|
||||
rcu_assign_pointer(kn->__parent, new_parent);
|
||||
|
||||
|
@ -1797,7 +1800,7 @@ int kernfs_rename_ns(struct kernfs_node *kn, struct kernfs_node *new_parent,
|
|||
if (new_name)
|
||||
rcu_assign_pointer(kn->name, new_name);
|
||||
|
||||
write_unlock_irq(&kernfs_rename_lock);
|
||||
write_unlock_irq(&root->kernfs_rename_lock);
|
||||
kernfs_put(old_parent);
|
||||
} else {
|
||||
/* name assignment is RCU protected, parent is the same */
|
||||
|
|
|
@ -778,8 +778,9 @@ bool kernfs_should_drain_open_files(struct kernfs_node *kn)
|
|||
/*
|
||||
* @kn being deactivated guarantees that @kn->attr.open can't change
|
||||
* beneath us making the lockless test below safe.
|
||||
* Callers post kernfs_unbreak_active_protection may be counted in
|
||||
* kn->active by now, do not WARN_ON because of them.
|
||||
*/
|
||||
WARN_ON_ONCE(atomic_read(&kn->active) != KN_DEACTIVATED_BIAS);
|
||||
|
||||
rcu_read_lock();
|
||||
on = rcu_dereference(kn->attr.open);
|
||||
|
|
|
@ -19,8 +19,6 @@
|
|||
#include <linux/kernfs.h>
|
||||
#include <linux/fs_context.h>
|
||||
|
||||
extern rwlock_t kernfs_rename_lock;
|
||||
|
||||
struct kernfs_iattrs {
|
||||
kuid_t ia_uid;
|
||||
kgid_t ia_gid;
|
||||
|
@ -40,6 +38,7 @@ struct kernfs_root {
|
|||
|
||||
/* private fields, do not use outside kernfs proper */
|
||||
struct idr ino_idr;
|
||||
spinlock_t kernfs_idr_lock; /* root->ino_idr */
|
||||
u32 last_id_lowbits;
|
||||
u32 id_highbits;
|
||||
struct kernfs_syscall_ops *syscall_ops;
|
||||
|
@ -52,6 +51,9 @@ struct kernfs_root {
|
|||
struct rw_semaphore kernfs_iattr_rwsem;
|
||||
struct rw_semaphore kernfs_supers_rwsem;
|
||||
|
||||
/* kn->parent and kn->name */
|
||||
rwlock_t kernfs_rename_lock;
|
||||
|
||||
struct rcu_head rcu;
|
||||
};
|
||||
|
||||
|
@ -107,6 +109,11 @@ static inline bool kernfs_root_is_locked(const struct kernfs_node *kn)
|
|||
return lockdep_is_held(&kernfs_root(kn)->kernfs_rwsem);
|
||||
}
|
||||
|
||||
static inline bool kernfs_rename_is_locked(const struct kernfs_node *kn)
|
||||
{
|
||||
return lockdep_is_held(&kernfs_root(kn)->kernfs_rename_lock);
|
||||
}
|
||||
|
||||
static inline const char *kernfs_rcu_name(const struct kernfs_node *kn)
|
||||
{
|
||||
return rcu_dereference_check(kn->name, kernfs_root_is_locked(kn));
|
||||
|
@ -117,14 +124,15 @@ static inline struct kernfs_node *kernfs_parent(const struct kernfs_node *kn)
|
|||
/*
|
||||
* The kernfs_node::__parent remains valid within a RCU section. The kn
|
||||
* can be reparented (and renamed) which changes the entry. This can be
|
||||
* avoided by locking kernfs_root::kernfs_rwsem or kernfs_rename_lock.
|
||||
* avoided by locking kernfs_root::kernfs_rwsem or
|
||||
* kernfs_root::kernfs_rename_lock.
|
||||
* Both locks can be used to obtain a reference on __parent. Once the
|
||||
* reference count reaches 0 then the node is about to be freed
|
||||
* and can not be renamed (or become a different parent) anymore.
|
||||
*/
|
||||
return rcu_dereference_check(kn->__parent,
|
||||
kernfs_root_is_locked(kn) ||
|
||||
lockdep_is_held(&kernfs_rename_lock) ||
|
||||
kernfs_rename_is_locked(kn) ||
|
||||
!atomic_read(&kn->count));
|
||||
}
|
||||
|
||||
|
|
|
@ -21,7 +21,7 @@ static void remove_files(struct kernfs_node *parent,
|
|||
const struct attribute_group *grp)
|
||||
{
|
||||
struct attribute *const *attr;
|
||||
struct bin_attribute *const *bin_attr;
|
||||
const struct bin_attribute *const *bin_attr;
|
||||
|
||||
if (grp->attrs)
|
||||
for (attr = grp->attrs; *attr; attr++)
|
||||
|
@ -47,7 +47,7 @@ static int create_files(struct kernfs_node *parent, struct kobject *kobj,
|
|||
const struct attribute_group *grp, int update)
|
||||
{
|
||||
struct attribute *const *attr;
|
||||
struct bin_attribute *const *bin_attr;
|
||||
const struct bin_attribute *const *bin_attr;
|
||||
int error = 0, i;
|
||||
|
||||
if (grp->attrs) {
|
||||
|
@ -521,7 +521,7 @@ static int sysfs_group_attrs_change_owner(struct kernfs_node *grp_kn,
|
|||
}
|
||||
|
||||
if (grp->bin_attrs) {
|
||||
struct bin_attribute *const *bin_attr;
|
||||
const struct bin_attribute *const *bin_attr;
|
||||
|
||||
for (bin_attr = grp->bin_attrs; *bin_attr; bin_attr++) {
|
||||
kn = kernfs_find_and_get(grp_kn, (*bin_attr)->attr.name);
|
||||
|
|
|
@ -254,6 +254,23 @@ int __auxiliary_driver_register(struct auxiliary_driver *auxdrv, struct module *
|
|||
|
||||
void auxiliary_driver_unregister(struct auxiliary_driver *auxdrv);
|
||||
|
||||
struct auxiliary_device *auxiliary_device_create(struct device *dev,
|
||||
const char *modname,
|
||||
const char *devname,
|
||||
void *platform_data,
|
||||
int id);
|
||||
void auxiliary_device_destroy(void *auxdev);
|
||||
|
||||
struct auxiliary_device *__devm_auxiliary_device_create(struct device *dev,
|
||||
const char *modname,
|
||||
const char *devname,
|
||||
void *platform_data,
|
||||
int id);
|
||||
|
||||
#define devm_auxiliary_device_create(dev, devname, platform_data) \
|
||||
__devm_auxiliary_device_create(dev, KBUILD_MODNAME, devname, \
|
||||
platform_data, 0)
|
||||
|
||||
/**
|
||||
* module_auxiliary_driver() - Helper macro for registering an auxiliary driver
|
||||
* @__auxiliary_driver: auxiliary driver struct
|
||||
|
|
|
@ -95,10 +95,6 @@ static inline void device_set_wakeup_path(struct device *dev)
|
|||
}
|
||||
|
||||
/* drivers/base/power/wakeup.c */
|
||||
extern struct wakeup_source *wakeup_source_create(const char *name);
|
||||
extern void wakeup_source_destroy(struct wakeup_source *ws);
|
||||
extern void wakeup_source_add(struct wakeup_source *ws);
|
||||
extern void wakeup_source_remove(struct wakeup_source *ws);
|
||||
extern struct wakeup_source *wakeup_source_register(struct device *dev,
|
||||
const char *name);
|
||||
extern void wakeup_source_unregister(struct wakeup_source *ws);
|
||||
|
@ -129,17 +125,6 @@ static inline bool device_can_wakeup(struct device *dev)
|
|||
return dev->power.can_wakeup;
|
||||
}
|
||||
|
||||
static inline struct wakeup_source *wakeup_source_create(const char *name)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline void wakeup_source_destroy(struct wakeup_source *ws) {}
|
||||
|
||||
static inline void wakeup_source_add(struct wakeup_source *ws) {}
|
||||
|
||||
static inline void wakeup_source_remove(struct wakeup_source *ws) {}
|
||||
|
||||
static inline struct wakeup_source *wakeup_source_register(struct device *dev,
|
||||
const char *name)
|
||||
{
|
||||
|
|
|
@ -107,7 +107,7 @@ struct attribute_group {
|
|||
int);
|
||||
struct attribute **attrs;
|
||||
union {
|
||||
struct bin_attribute **bin_attrs;
|
||||
const struct bin_attribute *const *bin_attrs;
|
||||
const struct bin_attribute *const *bin_attrs_new;
|
||||
};
|
||||
};
|
||||
|
@ -306,11 +306,11 @@ struct bin_attribute {
|
|||
size_t size;
|
||||
void *private;
|
||||
struct address_space *(*f_mapping)(void);
|
||||
ssize_t (*read)(struct file *, struct kobject *, struct bin_attribute *,
|
||||
ssize_t (*read)(struct file *, struct kobject *, const struct bin_attribute *,
|
||||
char *, loff_t, size_t);
|
||||
ssize_t (*read_new)(struct file *, struct kobject *, const struct bin_attribute *,
|
||||
char *, loff_t, size_t);
|
||||
ssize_t (*write)(struct file *, struct kobject *, struct bin_attribute *,
|
||||
ssize_t (*write)(struct file *, struct kobject *, const struct bin_attribute *,
|
||||
char *, loff_t, size_t);
|
||||
ssize_t (*write_new)(struct file *, struct kobject *,
|
||||
const struct bin_attribute *, char *, loff_t, size_t);
|
||||
|
@ -332,28 +332,11 @@ struct bin_attribute {
|
|||
*/
|
||||
#define sysfs_bin_attr_init(bin_attr) sysfs_attr_init(&(bin_attr)->attr)
|
||||
|
||||
typedef ssize_t __sysfs_bin_rw_handler_new(struct file *, struct kobject *,
|
||||
const struct bin_attribute *, char *, loff_t, size_t);
|
||||
|
||||
/* macros to create static binary attributes easier */
|
||||
#define __BIN_ATTR(_name, _mode, _read, _write, _size) { \
|
||||
.attr = { .name = __stringify(_name), .mode = _mode }, \
|
||||
.read = _Generic(_read, \
|
||||
__sysfs_bin_rw_handler_new * : NULL, \
|
||||
default : _read \
|
||||
), \
|
||||
.read_new = _Generic(_read, \
|
||||
__sysfs_bin_rw_handler_new * : _read, \
|
||||
default : NULL \
|
||||
), \
|
||||
.write = _Generic(_write, \
|
||||
__sysfs_bin_rw_handler_new * : NULL, \
|
||||
default : _write \
|
||||
), \
|
||||
.write_new = _Generic(_write, \
|
||||
__sysfs_bin_rw_handler_new * : _write, \
|
||||
default : NULL \
|
||||
), \
|
||||
.read = _read, \
|
||||
.write = _write, \
|
||||
.size = _size, \
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user