mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2024-11-24 16:20:55 +07:00
Driver core / kernfs pull request for 3.16-rc1
Here is the "big" pull request for 3.16-rc1. Not a lot of changes here, some kernfs work, a revert of a very old driver core change that ended up cauing some memory leaks on driver probe error paths, and other minor things. As was pointed out earlier today, one commit here,26fc9cd200
(kernfs: move the last knowledge of sysfs out from kernfs) is also needed in your 3.15-final branch as well. If you could cherry-pick it there, it would be most appreciated by Andy Lutomirski to prevent a regression there. All of these have been in linux-next for a while. Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> -----BEGIN PGP SIGNATURE----- Version: GnuPG v2.0.22 (GNU/Linux) iEYEABECAAYFAlONV9YACgkQMUfUDdst+yn0sQCfWWYg1oVXyu6f0uJjYbVBFkpD UHgAoJxxfwTZJq/xYrnk6+RqUowIsUlh =ojAS -----END PGP SIGNATURE----- Merge tag 'driver-core-3.16-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core into next Pull driver core / kernfs changes from Greg KH: "Here is the "big" pull request for 3.16-rc1. Not a lot of changes here, some kernfs work, a revert of a very old driver core change that ended up cauing some memory leaks on driver probe error paths, and other minor things. As was pointed out earlier today, one commit here,26fc9cd200
("kernfs: move the last knowledge of sysfs out from kernfs") is also needed in your 3.15-final branch as well. If you could cherry-pick it there, it would be most appreciated by Andy Lutomirski to prevent a regression there. All of these have been in linux-next for a while" * tag 'driver-core-3.16-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core: crypto/nx/nx-842: dev_set_drvdata can no longer fail kernfs: move the last knowledge of sysfs out from kernfs sysfs: fix attribute_group bin file path on removal sysfs.h: don't return a void-valued expression in sysfs_remove_file init.h: Update initcall_sync variants to fix build errors driver core: Inline dev_set/get_drvdata driver core: dev_get_drvdata: Don't check for NULL dev driver core: dev_set_drvdata returns void driver core: dev_set_drvdata can no longer fail driver core: Move driver_data back to struct device lib/devres.c: fix checkpatch warnings lib/devres.c: use dev in devm_request_and_ioremap kobject: Make support for uevent_helper optional. kernfs: make kernfs_notify() trigger inotify events too kernfs: implement kernfs_root->supers list
This commit is contained in:
commit
5da77761e6
@ -1,10 +1,10 @@
|
|||||||
menu "Generic Driver Options"
|
menu "Generic Driver Options"
|
||||||
|
|
||||||
config UEVENT_HELPER_PATH
|
config UEVENT_HELPER
|
||||||
string "path to uevent helper"
|
bool "Support for uevent helper"
|
||||||
default ""
|
default y
|
||||||
help
|
help
|
||||||
Path to uevent helper program forked by the kernel for
|
The uevent helper program is forked by the kernel for
|
||||||
every uevent.
|
every uevent.
|
||||||
Before the switch to the netlink-based uevent source, this was
|
Before the switch to the netlink-based uevent source, this was
|
||||||
used to hook hotplug scripts into kernel device events. It
|
used to hook hotplug scripts into kernel device events. It
|
||||||
@ -15,8 +15,13 @@ config UEVENT_HELPER_PATH
|
|||||||
that it creates a high system load, or on smaller systems
|
that it creates a high system load, or on smaller systems
|
||||||
it is known to create out-of-memory situations during bootup.
|
it is known to create out-of-memory situations during bootup.
|
||||||
|
|
||||||
To disable user space helper program execution at early boot
|
config UEVENT_HELPER_PATH
|
||||||
time specify an empty string here. This setting can be altered
|
string "path to uevent helper"
|
||||||
|
depends on UEVENT_HELPER
|
||||||
|
default ""
|
||||||
|
help
|
||||||
|
To disable user space helper program execution at by default
|
||||||
|
specify an empty string here. This setting can still be altered
|
||||||
via /proc/sys/kernel/hotplug or via /sys/kernel/uevent_helper
|
via /proc/sys/kernel/hotplug or via /sys/kernel/uevent_helper
|
||||||
later at runtime.
|
later at runtime.
|
||||||
|
|
||||||
|
@ -63,8 +63,6 @@ struct driver_private {
|
|||||||
* binding of drivers which were unable to get all the resources needed by
|
* binding of drivers which were unable to get all the resources needed by
|
||||||
* the device; typically because it depends on another driver getting
|
* the device; typically because it depends on another driver getting
|
||||||
* probed first.
|
* probed first.
|
||||||
* @driver_data - private pointer for driver specific info. Will turn into a
|
|
||||||
* list soon.
|
|
||||||
* @device - pointer back to the struct class that this structure is
|
* @device - pointer back to the struct class that this structure is
|
||||||
* associated with.
|
* associated with.
|
||||||
*
|
*
|
||||||
@ -76,7 +74,6 @@ struct device_private {
|
|||||||
struct klist_node knode_driver;
|
struct klist_node knode_driver;
|
||||||
struct klist_node knode_bus;
|
struct klist_node knode_bus;
|
||||||
struct list_head deferred_probe;
|
struct list_head deferred_probe;
|
||||||
void *driver_data;
|
|
||||||
struct device *device;
|
struct device *device;
|
||||||
};
|
};
|
||||||
#define to_device_private_parent(obj) \
|
#define to_device_private_parent(obj) \
|
||||||
|
@ -587,29 +587,3 @@ void driver_detach(struct device_driver *drv)
|
|||||||
put_device(dev);
|
put_device(dev);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* These exports can't be _GPL due to .h files using this within them, and it
|
|
||||||
* might break something that was previously working...
|
|
||||||
*/
|
|
||||||
void *dev_get_drvdata(const struct device *dev)
|
|
||||||
{
|
|
||||||
if (dev && dev->p)
|
|
||||||
return dev->p->driver_data;
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
EXPORT_SYMBOL(dev_get_drvdata);
|
|
||||||
|
|
||||||
int dev_set_drvdata(struct device *dev, void *data)
|
|
||||||
{
|
|
||||||
int error;
|
|
||||||
|
|
||||||
if (!dev->p) {
|
|
||||||
error = device_private_init(dev);
|
|
||||||
if (error)
|
|
||||||
return error;
|
|
||||||
}
|
|
||||||
dev->p->driver_data = data;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
EXPORT_SYMBOL(dev_set_drvdata);
|
|
||||||
|
@ -1197,12 +1197,7 @@ static int __init nx842_probe(struct vio_dev *viodev,
|
|||||||
}
|
}
|
||||||
|
|
||||||
rcu_read_lock();
|
rcu_read_lock();
|
||||||
if (dev_set_drvdata(&viodev->dev, rcu_dereference(devdata))) {
|
dev_set_drvdata(&viodev->dev, rcu_dereference(devdata));
|
||||||
rcu_read_unlock();
|
|
||||||
dev_err(&viodev->dev, "failed to set driver data for device\n");
|
|
||||||
ret = -1;
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
rcu_read_unlock();
|
rcu_read_unlock();
|
||||||
|
|
||||||
if (sysfs_create_group(&viodev->dev.kobj, &nx842_attribute_group)) {
|
if (sysfs_create_group(&viodev->dev.kobj, &nx842_attribute_group)) {
|
||||||
|
@ -542,12 +542,7 @@ static int exynos_sysmmu_probe(struct platform_device *pdev)
|
|||||||
goto err_alloc;
|
goto err_alloc;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = dev_set_drvdata(dev, data);
|
dev_set_drvdata(dev, data);
|
||||||
if (ret) {
|
|
||||||
dev_dbg(dev, "Unabled to initialize driver data\n");
|
|
||||||
goto err_init;
|
|
||||||
}
|
|
||||||
|
|
||||||
data->nsfrs = pdev->num_resources / 2;
|
data->nsfrs = pdev->num_resources / 2;
|
||||||
data->sfrbases = kmalloc(sizeof(*data->sfrbases) * data->nsfrs,
|
data->sfrbases = kmalloc(sizeof(*data->sfrbases) * data->nsfrs,
|
||||||
GFP_KERNEL);
|
GFP_KERNEL);
|
||||||
|
@ -349,7 +349,6 @@ struct vfio_device *vfio_group_create_device(struct vfio_group *group,
|
|||||||
void *device_data)
|
void *device_data)
|
||||||
{
|
{
|
||||||
struct vfio_device *device;
|
struct vfio_device *device;
|
||||||
int ret;
|
|
||||||
|
|
||||||
device = kzalloc(sizeof(*device), GFP_KERNEL);
|
device = kzalloc(sizeof(*device), GFP_KERNEL);
|
||||||
if (!device)
|
if (!device)
|
||||||
@ -360,12 +359,7 @@ struct vfio_device *vfio_group_create_device(struct vfio_group *group,
|
|||||||
device->group = group;
|
device->group = group;
|
||||||
device->ops = ops;
|
device->ops = ops;
|
||||||
device->device_data = device_data;
|
device->device_data = device_data;
|
||||||
|
dev_set_drvdata(dev, device);
|
||||||
ret = dev_set_drvdata(dev, device);
|
|
||||||
if (ret) {
|
|
||||||
kfree(device);
|
|
||||||
return ERR_PTR(ret);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* No need to get group_lock, caller has group reference */
|
/* No need to get group_lock, caller has group reference */
|
||||||
vfio_group_get(group);
|
vfio_group_get(group);
|
||||||
|
@ -714,6 +714,7 @@ struct kernfs_root *kernfs_create_root(struct kernfs_syscall_ops *scops,
|
|||||||
return ERR_PTR(-ENOMEM);
|
return ERR_PTR(-ENOMEM);
|
||||||
|
|
||||||
ida_init(&root->ino_ida);
|
ida_init(&root->ino_ida);
|
||||||
|
INIT_LIST_HEAD(&root->supers);
|
||||||
|
|
||||||
kn = __kernfs_new_node(root, "", S_IFDIR | S_IRUGO | S_IXUGO,
|
kn = __kernfs_new_node(root, "", S_IFDIR | S_IRUGO | S_IXUGO,
|
||||||
KERNFS_DIR);
|
KERNFS_DIR);
|
||||||
|
@ -14,6 +14,7 @@
|
|||||||
#include <linux/poll.h>
|
#include <linux/poll.h>
|
||||||
#include <linux/pagemap.h>
|
#include <linux/pagemap.h>
|
||||||
#include <linux/sched.h>
|
#include <linux/sched.h>
|
||||||
|
#include <linux/fsnotify.h>
|
||||||
|
|
||||||
#include "kernfs-internal.h"
|
#include "kernfs-internal.h"
|
||||||
|
|
||||||
@ -790,20 +791,48 @@ static unsigned int kernfs_fop_poll(struct file *filp, poll_table *wait)
|
|||||||
*/
|
*/
|
||||||
void kernfs_notify(struct kernfs_node *kn)
|
void kernfs_notify(struct kernfs_node *kn)
|
||||||
{
|
{
|
||||||
|
struct kernfs_root *root = kernfs_root(kn);
|
||||||
struct kernfs_open_node *on;
|
struct kernfs_open_node *on;
|
||||||
|
struct kernfs_super_info *info;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
|
||||||
|
if (WARN_ON(kernfs_type(kn) != KERNFS_FILE))
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* kick poll */
|
||||||
spin_lock_irqsave(&kernfs_open_node_lock, flags);
|
spin_lock_irqsave(&kernfs_open_node_lock, flags);
|
||||||
|
|
||||||
if (!WARN_ON(kernfs_type(kn) != KERNFS_FILE)) {
|
on = kn->attr.open;
|
||||||
on = kn->attr.open;
|
if (on) {
|
||||||
if (on) {
|
atomic_inc(&on->event);
|
||||||
atomic_inc(&on->event);
|
wake_up_interruptible(&on->poll);
|
||||||
wake_up_interruptible(&on->poll);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
spin_unlock_irqrestore(&kernfs_open_node_lock, flags);
|
spin_unlock_irqrestore(&kernfs_open_node_lock, flags);
|
||||||
|
|
||||||
|
/* kick fsnotify */
|
||||||
|
mutex_lock(&kernfs_mutex);
|
||||||
|
|
||||||
|
list_for_each_entry(info, &root->supers, node) {
|
||||||
|
struct inode *inode;
|
||||||
|
struct dentry *dentry;
|
||||||
|
|
||||||
|
inode = ilookup(info->sb, kn->ino);
|
||||||
|
if (!inode)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
dentry = d_find_any_alias(inode);
|
||||||
|
if (dentry) {
|
||||||
|
fsnotify_parent(NULL, dentry, FS_MODIFY);
|
||||||
|
fsnotify(inode, FS_MODIFY, inode, FSNOTIFY_EVENT_INODE,
|
||||||
|
NULL, 0);
|
||||||
|
dput(dentry);
|
||||||
|
}
|
||||||
|
|
||||||
|
iput(inode);
|
||||||
|
}
|
||||||
|
|
||||||
|
mutex_unlock(&kernfs_mutex);
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(kernfs_notify);
|
EXPORT_SYMBOL_GPL(kernfs_notify);
|
||||||
|
|
||||||
|
@ -49,6 +49,8 @@ static inline struct kernfs_root *kernfs_root(struct kernfs_node *kn)
|
|||||||
* mount.c
|
* mount.c
|
||||||
*/
|
*/
|
||||||
struct kernfs_super_info {
|
struct kernfs_super_info {
|
||||||
|
struct super_block *sb;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The root associated with this super_block. Each super_block is
|
* The root associated with this super_block. Each super_block is
|
||||||
* identified by the root and ns it's associated with.
|
* identified by the root and ns it's associated with.
|
||||||
@ -62,6 +64,9 @@ struct kernfs_super_info {
|
|||||||
* an array and compare kernfs_node tag against every entry.
|
* an array and compare kernfs_node tag against every entry.
|
||||||
*/
|
*/
|
||||||
const void *ns;
|
const void *ns;
|
||||||
|
|
||||||
|
/* anchored at kernfs_root->supers, protected by kernfs_mutex */
|
||||||
|
struct list_head node;
|
||||||
};
|
};
|
||||||
#define kernfs_info(SB) ((struct kernfs_super_info *)(SB->s_fs_info))
|
#define kernfs_info(SB) ((struct kernfs_super_info *)(SB->s_fs_info))
|
||||||
|
|
||||||
|
@ -62,15 +62,16 @@ struct kernfs_root *kernfs_root_from_sb(struct super_block *sb)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int kernfs_fill_super(struct super_block *sb)
|
static int kernfs_fill_super(struct super_block *sb, unsigned long magic)
|
||||||
{
|
{
|
||||||
struct kernfs_super_info *info = kernfs_info(sb);
|
struct kernfs_super_info *info = kernfs_info(sb);
|
||||||
struct inode *inode;
|
struct inode *inode;
|
||||||
struct dentry *root;
|
struct dentry *root;
|
||||||
|
|
||||||
|
info->sb = sb;
|
||||||
sb->s_blocksize = PAGE_CACHE_SIZE;
|
sb->s_blocksize = PAGE_CACHE_SIZE;
|
||||||
sb->s_blocksize_bits = PAGE_CACHE_SHIFT;
|
sb->s_blocksize_bits = PAGE_CACHE_SHIFT;
|
||||||
sb->s_magic = SYSFS_MAGIC;
|
sb->s_magic = magic;
|
||||||
sb->s_op = &kernfs_sops;
|
sb->s_op = &kernfs_sops;
|
||||||
sb->s_time_gran = 1;
|
sb->s_time_gran = 1;
|
||||||
|
|
||||||
@ -131,6 +132,7 @@ const void *kernfs_super_ns(struct super_block *sb)
|
|||||||
* @fs_type: file_system_type of the fs being mounted
|
* @fs_type: file_system_type of the fs being mounted
|
||||||
* @flags: mount flags specified for the mount
|
* @flags: mount flags specified for the mount
|
||||||
* @root: kernfs_root of the hierarchy being mounted
|
* @root: kernfs_root of the hierarchy being mounted
|
||||||
|
* @magic: file system specific magic number
|
||||||
* @new_sb_created: tell the caller if we allocated a new superblock
|
* @new_sb_created: tell the caller if we allocated a new superblock
|
||||||
* @ns: optional namespace tag of the mount
|
* @ns: optional namespace tag of the mount
|
||||||
*
|
*
|
||||||
@ -142,8 +144,8 @@ const void *kernfs_super_ns(struct super_block *sb)
|
|||||||
* The return value can be passed to the vfs layer verbatim.
|
* The return value can be passed to the vfs layer verbatim.
|
||||||
*/
|
*/
|
||||||
struct dentry *kernfs_mount_ns(struct file_system_type *fs_type, int flags,
|
struct dentry *kernfs_mount_ns(struct file_system_type *fs_type, int flags,
|
||||||
struct kernfs_root *root, bool *new_sb_created,
|
struct kernfs_root *root, unsigned long magic,
|
||||||
const void *ns)
|
bool *new_sb_created, const void *ns)
|
||||||
{
|
{
|
||||||
struct super_block *sb;
|
struct super_block *sb;
|
||||||
struct kernfs_super_info *info;
|
struct kernfs_super_info *info;
|
||||||
@ -166,12 +168,18 @@ struct dentry *kernfs_mount_ns(struct file_system_type *fs_type, int flags,
|
|||||||
*new_sb_created = !sb->s_root;
|
*new_sb_created = !sb->s_root;
|
||||||
|
|
||||||
if (!sb->s_root) {
|
if (!sb->s_root) {
|
||||||
error = kernfs_fill_super(sb);
|
struct kernfs_super_info *info = kernfs_info(sb);
|
||||||
|
|
||||||
|
error = kernfs_fill_super(sb, magic);
|
||||||
if (error) {
|
if (error) {
|
||||||
deactivate_locked_super(sb);
|
deactivate_locked_super(sb);
|
||||||
return ERR_PTR(error);
|
return ERR_PTR(error);
|
||||||
}
|
}
|
||||||
sb->s_flags |= MS_ACTIVE;
|
sb->s_flags |= MS_ACTIVE;
|
||||||
|
|
||||||
|
mutex_lock(&kernfs_mutex);
|
||||||
|
list_add(&info->node, &root->supers);
|
||||||
|
mutex_unlock(&kernfs_mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
return dget(sb->s_root);
|
return dget(sb->s_root);
|
||||||
@ -190,6 +198,10 @@ void kernfs_kill_sb(struct super_block *sb)
|
|||||||
struct kernfs_super_info *info = kernfs_info(sb);
|
struct kernfs_super_info *info = kernfs_info(sb);
|
||||||
struct kernfs_node *root_kn = sb->s_root->d_fsdata;
|
struct kernfs_node *root_kn = sb->s_root->d_fsdata;
|
||||||
|
|
||||||
|
mutex_lock(&kernfs_mutex);
|
||||||
|
list_del(&info->node);
|
||||||
|
mutex_unlock(&kernfs_mutex);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Remove the superblock from fs_supers/s_instances
|
* Remove the superblock from fs_supers/s_instances
|
||||||
* so we can't find it, before freeing kernfs_super_info.
|
* so we can't find it, before freeing kernfs_super_info.
|
||||||
|
@ -18,7 +18,7 @@
|
|||||||
#include "sysfs.h"
|
#include "sysfs.h"
|
||||||
|
|
||||||
|
|
||||||
static void remove_files(struct kernfs_node *parent, struct kobject *kobj,
|
static void remove_files(struct kernfs_node *parent,
|
||||||
const struct attribute_group *grp)
|
const struct attribute_group *grp)
|
||||||
{
|
{
|
||||||
struct attribute *const *attr;
|
struct attribute *const *attr;
|
||||||
@ -29,7 +29,7 @@ static void remove_files(struct kernfs_node *parent, struct kobject *kobj,
|
|||||||
kernfs_remove_by_name(parent, (*attr)->name);
|
kernfs_remove_by_name(parent, (*attr)->name);
|
||||||
if (grp->bin_attrs)
|
if (grp->bin_attrs)
|
||||||
for (bin_attr = grp->bin_attrs; *bin_attr; bin_attr++)
|
for (bin_attr = grp->bin_attrs; *bin_attr; bin_attr++)
|
||||||
sysfs_remove_bin_file(kobj, *bin_attr);
|
kernfs_remove_by_name(parent, (*bin_attr)->attr.name);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int create_files(struct kernfs_node *parent, struct kobject *kobj,
|
static int create_files(struct kernfs_node *parent, struct kobject *kobj,
|
||||||
@ -62,7 +62,7 @@ static int create_files(struct kernfs_node *parent, struct kobject *kobj,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (error) {
|
if (error) {
|
||||||
remove_files(parent, kobj, grp);
|
remove_files(parent, grp);
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -79,7 +79,7 @@ static int create_files(struct kernfs_node *parent, struct kobject *kobj,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (error)
|
if (error)
|
||||||
remove_files(parent, kobj, grp);
|
remove_files(parent, grp);
|
||||||
}
|
}
|
||||||
exit:
|
exit:
|
||||||
return error;
|
return error;
|
||||||
@ -224,7 +224,7 @@ void sysfs_remove_group(struct kobject *kobj,
|
|||||||
kernfs_get(kn);
|
kernfs_get(kn);
|
||||||
}
|
}
|
||||||
|
|
||||||
remove_files(kn, kobj, grp);
|
remove_files(kn, grp);
|
||||||
if (grp->name)
|
if (grp->name)
|
||||||
kernfs_remove(kn);
|
kernfs_remove(kn);
|
||||||
|
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
#define DEBUG
|
#define DEBUG
|
||||||
|
|
||||||
#include <linux/fs.h>
|
#include <linux/fs.h>
|
||||||
|
#include <linux/magic.h>
|
||||||
#include <linux/mount.h>
|
#include <linux/mount.h>
|
||||||
#include <linux/init.h>
|
#include <linux/init.h>
|
||||||
#include <linux/user_namespace.h>
|
#include <linux/user_namespace.h>
|
||||||
@ -38,7 +39,8 @@ static struct dentry *sysfs_mount(struct file_system_type *fs_type,
|
|||||||
}
|
}
|
||||||
|
|
||||||
ns = kobj_ns_grab_current(KOBJ_NS_TYPE_NET);
|
ns = kobj_ns_grab_current(KOBJ_NS_TYPE_NET);
|
||||||
root = kernfs_mount_ns(fs_type, flags, sysfs_root, &new_sb, ns);
|
root = kernfs_mount_ns(fs_type, flags, sysfs_root,
|
||||||
|
SYSFS_MAGIC, &new_sb, ns);
|
||||||
if (IS_ERR(root) || !new_sb)
|
if (IS_ERR(root) || !new_sb)
|
||||||
kobj_ns_drop(KOBJ_NS_TYPE_NET, ns);
|
kobj_ns_drop(KOBJ_NS_TYPE_NET, ns);
|
||||||
return root;
|
return root;
|
||||||
|
@ -673,6 +673,7 @@ struct acpi_dev_node {
|
|||||||
* variants, which GPIO pins act in what additional roles, and so
|
* variants, which GPIO pins act in what additional roles, and so
|
||||||
* on. This shrinks the "Board Support Packages" (BSPs) and
|
* on. This shrinks the "Board Support Packages" (BSPs) and
|
||||||
* minimizes board-specific #ifdefs in drivers.
|
* minimizes board-specific #ifdefs in drivers.
|
||||||
|
* @driver_data: Private pointer for driver specific info.
|
||||||
* @power: For device power management.
|
* @power: For device power management.
|
||||||
* See Documentation/power/devices.txt for details.
|
* See Documentation/power/devices.txt for details.
|
||||||
* @pm_domain: Provide callbacks that are executed during system suspend,
|
* @pm_domain: Provide callbacks that are executed during system suspend,
|
||||||
@ -734,6 +735,8 @@ struct device {
|
|||||||
device */
|
device */
|
||||||
void *platform_data; /* Platform specific data, device
|
void *platform_data; /* Platform specific data, device
|
||||||
core doesn't touch it */
|
core doesn't touch it */
|
||||||
|
void *driver_data; /* Driver data, set and get with
|
||||||
|
dev_set/get_drvdata */
|
||||||
struct dev_pm_info power;
|
struct dev_pm_info power;
|
||||||
struct dev_pm_domain *pm_domain;
|
struct dev_pm_domain *pm_domain;
|
||||||
|
|
||||||
@ -823,6 +826,16 @@ static inline void set_dev_node(struct device *dev, int node)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
static inline void *dev_get_drvdata(const struct device *dev)
|
||||||
|
{
|
||||||
|
return dev->driver_data;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void dev_set_drvdata(struct device *dev, void *data)
|
||||||
|
{
|
||||||
|
dev->driver_data = data;
|
||||||
|
}
|
||||||
|
|
||||||
static inline struct pm_subsys_data *dev_to_psd(struct device *dev)
|
static inline struct pm_subsys_data *dev_to_psd(struct device *dev)
|
||||||
{
|
{
|
||||||
return dev ? dev->power.subsys_data : NULL;
|
return dev ? dev->power.subsys_data : NULL;
|
||||||
@ -907,8 +920,6 @@ extern int device_move(struct device *dev, struct device *new_parent,
|
|||||||
extern const char *device_get_devnode(struct device *dev,
|
extern const char *device_get_devnode(struct device *dev,
|
||||||
umode_t *mode, kuid_t *uid, kgid_t *gid,
|
umode_t *mode, kuid_t *uid, kgid_t *gid,
|
||||||
const char **tmp);
|
const char **tmp);
|
||||||
extern void *dev_get_drvdata(const struct device *dev);
|
|
||||||
extern int dev_set_drvdata(struct device *dev, void *data);
|
|
||||||
|
|
||||||
static inline bool device_supports_offline(struct device *dev)
|
static inline bool device_supports_offline(struct device *dev)
|
||||||
{
|
{
|
||||||
|
@ -297,16 +297,28 @@ void __init parse_early_options(char *cmdline);
|
|||||||
|
|
||||||
#else /* MODULE */
|
#else /* MODULE */
|
||||||
|
|
||||||
/* Don't use these in loadable modules, but some people do... */
|
/*
|
||||||
|
* In most cases loadable modules do not need custom
|
||||||
|
* initcall levels. There are still some valid cases where
|
||||||
|
* a driver may be needed early if built in, and does not
|
||||||
|
* matter when built as a loadable module. Like bus
|
||||||
|
* snooping debug drivers.
|
||||||
|
*/
|
||||||
#define early_initcall(fn) module_init(fn)
|
#define early_initcall(fn) module_init(fn)
|
||||||
#define core_initcall(fn) module_init(fn)
|
#define core_initcall(fn) module_init(fn)
|
||||||
|
#define core_initcall_sync(fn) module_init(fn)
|
||||||
#define postcore_initcall(fn) module_init(fn)
|
#define postcore_initcall(fn) module_init(fn)
|
||||||
|
#define postcore_initcall_sync(fn) module_init(fn)
|
||||||
#define arch_initcall(fn) module_init(fn)
|
#define arch_initcall(fn) module_init(fn)
|
||||||
#define subsys_initcall(fn) module_init(fn)
|
#define subsys_initcall(fn) module_init(fn)
|
||||||
|
#define subsys_initcall_sync(fn) module_init(fn)
|
||||||
#define fs_initcall(fn) module_init(fn)
|
#define fs_initcall(fn) module_init(fn)
|
||||||
|
#define fs_initcall_sync(fn) module_init(fn)
|
||||||
#define rootfs_initcall(fn) module_init(fn)
|
#define rootfs_initcall(fn) module_init(fn)
|
||||||
#define device_initcall(fn) module_init(fn)
|
#define device_initcall(fn) module_init(fn)
|
||||||
|
#define device_initcall_sync(fn) module_init(fn)
|
||||||
#define late_initcall(fn) module_init(fn)
|
#define late_initcall(fn) module_init(fn)
|
||||||
|
#define late_initcall_sync(fn) module_init(fn)
|
||||||
|
|
||||||
#define console_initcall(fn) module_init(fn)
|
#define console_initcall(fn) module_init(fn)
|
||||||
#define security_initcall(fn) module_init(fn)
|
#define security_initcall(fn) module_init(fn)
|
||||||
|
@ -161,6 +161,10 @@ struct kernfs_root {
|
|||||||
/* private fields, do not use outside kernfs proper */
|
/* private fields, do not use outside kernfs proper */
|
||||||
struct ida ino_ida;
|
struct ida ino_ida;
|
||||||
struct kernfs_syscall_ops *syscall_ops;
|
struct kernfs_syscall_ops *syscall_ops;
|
||||||
|
|
||||||
|
/* list of kernfs_super_info of this root, protected by kernfs_mutex */
|
||||||
|
struct list_head supers;
|
||||||
|
|
||||||
wait_queue_head_t deactivate_waitq;
|
wait_queue_head_t deactivate_waitq;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -297,8 +301,8 @@ void kernfs_notify(struct kernfs_node *kn);
|
|||||||
|
|
||||||
const void *kernfs_super_ns(struct super_block *sb);
|
const void *kernfs_super_ns(struct super_block *sb);
|
||||||
struct dentry *kernfs_mount_ns(struct file_system_type *fs_type, int flags,
|
struct dentry *kernfs_mount_ns(struct file_system_type *fs_type, int flags,
|
||||||
struct kernfs_root *root, bool *new_sb_created,
|
struct kernfs_root *root, unsigned long magic,
|
||||||
const void *ns);
|
bool *new_sb_created, const void *ns);
|
||||||
void kernfs_kill_sb(struct super_block *sb);
|
void kernfs_kill_sb(struct super_block *sb);
|
||||||
|
|
||||||
void kernfs_init(void);
|
void kernfs_init(void);
|
||||||
@ -391,7 +395,8 @@ static inline const void *kernfs_super_ns(struct super_block *sb)
|
|||||||
|
|
||||||
static inline struct dentry *
|
static inline struct dentry *
|
||||||
kernfs_mount_ns(struct file_system_type *fs_type, int flags,
|
kernfs_mount_ns(struct file_system_type *fs_type, int flags,
|
||||||
struct kernfs_root *root, bool *new_sb_created, const void *ns)
|
struct kernfs_root *root, unsigned long magic,
|
||||||
|
bool *new_sb_created, const void *ns)
|
||||||
{ return ERR_PTR(-ENOSYS); }
|
{ return ERR_PTR(-ENOSYS); }
|
||||||
|
|
||||||
static inline void kernfs_kill_sb(struct super_block *sb) { }
|
static inline void kernfs_kill_sb(struct super_block *sb) { }
|
||||||
@ -449,9 +454,11 @@ static inline int kernfs_rename(struct kernfs_node *kn,
|
|||||||
|
|
||||||
static inline struct dentry *
|
static inline struct dentry *
|
||||||
kernfs_mount(struct file_system_type *fs_type, int flags,
|
kernfs_mount(struct file_system_type *fs_type, int flags,
|
||||||
struct kernfs_root *root, bool *new_sb_created)
|
struct kernfs_root *root, unsigned long magic,
|
||||||
|
bool *new_sb_created)
|
||||||
{
|
{
|
||||||
return kernfs_mount_ns(fs_type, flags, root, new_sb_created, NULL);
|
return kernfs_mount_ns(fs_type, flags, root,
|
||||||
|
magic, new_sb_created, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* __LINUX_KERNFS_H */
|
#endif /* __LINUX_KERNFS_H */
|
||||||
|
@ -32,8 +32,10 @@
|
|||||||
#define UEVENT_NUM_ENVP 32 /* number of env pointers */
|
#define UEVENT_NUM_ENVP 32 /* number of env pointers */
|
||||||
#define UEVENT_BUFFER_SIZE 2048 /* buffer for the variables */
|
#define UEVENT_BUFFER_SIZE 2048 /* buffer for the variables */
|
||||||
|
|
||||||
|
#ifdef CONFIG_UEVENT_HELPER
|
||||||
/* path to the userspace helper executed on an event */
|
/* path to the userspace helper executed on an event */
|
||||||
extern char uevent_helper[];
|
extern char uevent_helper[];
|
||||||
|
#endif
|
||||||
|
|
||||||
/* counter to tag the uevent, read only except for the kobject core */
|
/* counter to tag the uevent, read only except for the kobject core */
|
||||||
extern u64 uevent_seqnum;
|
extern u64 uevent_seqnum;
|
||||||
|
@ -437,7 +437,7 @@ static inline int __must_check sysfs_create_file(struct kobject *kobj,
|
|||||||
static inline void sysfs_remove_file(struct kobject *kobj,
|
static inline void sysfs_remove_file(struct kobject *kobj,
|
||||||
const struct attribute *attr)
|
const struct attribute *attr)
|
||||||
{
|
{
|
||||||
return sysfs_remove_file_ns(kobj, attr, NULL);
|
sysfs_remove_file_ns(kobj, attr, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int sysfs_rename_link(struct kobject *kobj, struct kobject *target,
|
static inline int sysfs_rename_link(struct kobject *kobj, struct kobject *target,
|
||||||
|
@ -33,6 +33,7 @@
|
|||||||
#include <linux/init_task.h>
|
#include <linux/init_task.h>
|
||||||
#include <linux/kernel.h>
|
#include <linux/kernel.h>
|
||||||
#include <linux/list.h>
|
#include <linux/list.h>
|
||||||
|
#include <linux/magic.h>
|
||||||
#include <linux/mm.h>
|
#include <linux/mm.h>
|
||||||
#include <linux/mutex.h>
|
#include <linux/mutex.h>
|
||||||
#include <linux/mount.h>
|
#include <linux/mount.h>
|
||||||
@ -1604,7 +1605,8 @@ static struct dentry *cgroup_mount(struct file_system_type *fs_type,
|
|||||||
if (ret)
|
if (ret)
|
||||||
return ERR_PTR(ret);
|
return ERR_PTR(ret);
|
||||||
|
|
||||||
dentry = kernfs_mount(fs_type, flags, root->kf_root, &new_sb);
|
dentry = kernfs_mount(fs_type, flags, root->kf_root,
|
||||||
|
CGROUP_SUPER_MAGIC, &new_sb);
|
||||||
if (IS_ERR(dentry) || !new_sb)
|
if (IS_ERR(dentry) || !new_sb)
|
||||||
cgroup_put(&root->cgrp);
|
cgroup_put(&root->cgrp);
|
||||||
return dentry;
|
return dentry;
|
||||||
|
@ -37,6 +37,7 @@ static ssize_t uevent_seqnum_show(struct kobject *kobj,
|
|||||||
}
|
}
|
||||||
KERNEL_ATTR_RO(uevent_seqnum);
|
KERNEL_ATTR_RO(uevent_seqnum);
|
||||||
|
|
||||||
|
#ifdef CONFIG_UEVENT_HELPER
|
||||||
/* uevent helper program, used during early boot */
|
/* uevent helper program, used during early boot */
|
||||||
static ssize_t uevent_helper_show(struct kobject *kobj,
|
static ssize_t uevent_helper_show(struct kobject *kobj,
|
||||||
struct kobj_attribute *attr, char *buf)
|
struct kobj_attribute *attr, char *buf)
|
||||||
@ -56,7 +57,7 @@ static ssize_t uevent_helper_store(struct kobject *kobj,
|
|||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
KERNEL_ATTR_RW(uevent_helper);
|
KERNEL_ATTR_RW(uevent_helper);
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef CONFIG_PROFILING
|
#ifdef CONFIG_PROFILING
|
||||||
static ssize_t profiling_show(struct kobject *kobj,
|
static ssize_t profiling_show(struct kobject *kobj,
|
||||||
@ -189,7 +190,9 @@ EXPORT_SYMBOL_GPL(kernel_kobj);
|
|||||||
static struct attribute * kernel_attrs[] = {
|
static struct attribute * kernel_attrs[] = {
|
||||||
&fscaps_attr.attr,
|
&fscaps_attr.attr,
|
||||||
&uevent_seqnum_attr.attr,
|
&uevent_seqnum_attr.attr,
|
||||||
|
#ifdef CONFIG_UEVENT_HELPER
|
||||||
&uevent_helper_attr.attr,
|
&uevent_helper_attr.attr,
|
||||||
|
#endif
|
||||||
#ifdef CONFIG_PROFILING
|
#ifdef CONFIG_PROFILING
|
||||||
&profiling_attr.attr,
|
&profiling_attr.attr,
|
||||||
#endif
|
#endif
|
||||||
|
@ -643,7 +643,7 @@ static struct ctl_table kern_table[] = {
|
|||||||
.extra2 = &one,
|
.extra2 = &one,
|
||||||
},
|
},
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef CONFIG_UEVENT_HELPER
|
||||||
{
|
{
|
||||||
.procname = "hotplug",
|
.procname = "hotplug",
|
||||||
.data = &uevent_helper,
|
.data = &uevent_helper,
|
||||||
@ -651,7 +651,7 @@ static struct ctl_table kern_table[] = {
|
|||||||
.mode = 0644,
|
.mode = 0644,
|
||||||
.proc_handler = proc_dostring,
|
.proc_handler = proc_dostring,
|
||||||
},
|
},
|
||||||
|
#endif
|
||||||
#ifdef CONFIG_CHR_DEV_SG
|
#ifdef CONFIG_CHR_DEV_SG
|
||||||
{
|
{
|
||||||
.procname = "sg-big-buff",
|
.procname = "sg-big-buff",
|
||||||
|
10
lib/devres.c
10
lib/devres.c
@ -157,12 +157,12 @@ EXPORT_SYMBOL(devm_ioremap_resource);
|
|||||||
* if (!base)
|
* if (!base)
|
||||||
* return -EADDRNOTAVAIL;
|
* return -EADDRNOTAVAIL;
|
||||||
*/
|
*/
|
||||||
void __iomem *devm_request_and_ioremap(struct device *device,
|
void __iomem *devm_request_and_ioremap(struct device *dev,
|
||||||
struct resource *res)
|
struct resource *res)
|
||||||
{
|
{
|
||||||
void __iomem *dest_ptr;
|
void __iomem *dest_ptr;
|
||||||
|
|
||||||
dest_ptr = devm_ioremap_resource(device, res);
|
dest_ptr = devm_ioremap_resource(dev, res);
|
||||||
if (IS_ERR(dest_ptr))
|
if (IS_ERR(dest_ptr))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
@ -194,7 +194,7 @@ static int devm_ioport_map_match(struct device *dev, void *res,
|
|||||||
* Managed ioport_map(). Map is automatically unmapped on driver
|
* Managed ioport_map(). Map is automatically unmapped on driver
|
||||||
* detach.
|
* detach.
|
||||||
*/
|
*/
|
||||||
void __iomem * devm_ioport_map(struct device *dev, unsigned long port,
|
void __iomem *devm_ioport_map(struct device *dev, unsigned long port,
|
||||||
unsigned int nr)
|
unsigned int nr)
|
||||||
{
|
{
|
||||||
void __iomem **ptr, *addr;
|
void __iomem **ptr, *addr;
|
||||||
@ -265,7 +265,7 @@ static void pcim_iomap_release(struct device *gendev, void *res)
|
|||||||
* be safely called without context and guaranteed to succed once
|
* be safely called without context and guaranteed to succed once
|
||||||
* allocated.
|
* allocated.
|
||||||
*/
|
*/
|
||||||
void __iomem * const * pcim_iomap_table(struct pci_dev *pdev)
|
void __iomem * const *pcim_iomap_table(struct pci_dev *pdev)
|
||||||
{
|
{
|
||||||
struct pcim_iomap_devres *dr, *new_dr;
|
struct pcim_iomap_devres *dr, *new_dr;
|
||||||
|
|
||||||
@ -290,7 +290,7 @@ EXPORT_SYMBOL(pcim_iomap_table);
|
|||||||
* Managed pci_iomap(). Map is automatically unmapped on driver
|
* Managed pci_iomap(). Map is automatically unmapped on driver
|
||||||
* detach.
|
* detach.
|
||||||
*/
|
*/
|
||||||
void __iomem * pcim_iomap(struct pci_dev *pdev, int bar, unsigned long maxlen)
|
void __iomem *pcim_iomap(struct pci_dev *pdev, int bar, unsigned long maxlen)
|
||||||
{
|
{
|
||||||
void __iomem **tbl;
|
void __iomem **tbl;
|
||||||
|
|
||||||
|
@ -29,7 +29,9 @@
|
|||||||
|
|
||||||
|
|
||||||
u64 uevent_seqnum;
|
u64 uevent_seqnum;
|
||||||
|
#ifdef CONFIG_UEVENT_HELPER
|
||||||
char uevent_helper[UEVENT_HELPER_PATH_LEN] = CONFIG_UEVENT_HELPER_PATH;
|
char uevent_helper[UEVENT_HELPER_PATH_LEN] = CONFIG_UEVENT_HELPER_PATH;
|
||||||
|
#endif
|
||||||
#ifdef CONFIG_NET
|
#ifdef CONFIG_NET
|
||||||
struct uevent_sock {
|
struct uevent_sock {
|
||||||
struct list_head list;
|
struct list_head list;
|
||||||
@ -109,6 +111,7 @@ static int kobj_bcast_filter(struct sock *dsk, struct sk_buff *skb, void *data)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef CONFIG_UEVENT_HELPER
|
||||||
static int kobj_usermode_filter(struct kobject *kobj)
|
static int kobj_usermode_filter(struct kobject *kobj)
|
||||||
{
|
{
|
||||||
const struct kobj_ns_type_operations *ops;
|
const struct kobj_ns_type_operations *ops;
|
||||||
@ -147,6 +150,7 @@ static void cleanup_uevent_env(struct subprocess_info *info)
|
|||||||
{
|
{
|
||||||
kfree(info->data);
|
kfree(info->data);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* kobject_uevent_env - send an uevent with environmental data
|
* kobject_uevent_env - send an uevent with environmental data
|
||||||
@ -323,6 +327,7 @@ int kobject_uevent_env(struct kobject *kobj, enum kobject_action action,
|
|||||||
#endif
|
#endif
|
||||||
mutex_unlock(&uevent_sock_mutex);
|
mutex_unlock(&uevent_sock_mutex);
|
||||||
|
|
||||||
|
#ifdef CONFIG_UEVENT_HELPER
|
||||||
/* call uevent_helper, usually only enabled during early boot */
|
/* call uevent_helper, usually only enabled during early boot */
|
||||||
if (uevent_helper[0] && !kobj_usermode_filter(kobj)) {
|
if (uevent_helper[0] && !kobj_usermode_filter(kobj)) {
|
||||||
struct subprocess_info *info;
|
struct subprocess_info *info;
|
||||||
@ -347,6 +352,7 @@ int kobject_uevent_env(struct kobject *kobj, enum kobject_action action,
|
|||||||
env = NULL; /* freed by cleanup_uevent_env */
|
env = NULL; /* freed by cleanup_uevent_env */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
exit:
|
exit:
|
||||||
kfree(devpath);
|
kfree(devpath);
|
||||||
|
Loading…
Reference in New Issue
Block a user