Driver core update for 3.10-rc1
Here's the merge request for the driver core tree for 3.10-rc1 It's pretty small, just a number of driver core and sysfs updates and fixes, all of which have been in linux-next for a while now. Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> -----BEGIN PGP SIGNATURE----- Version: GnuPG v2.0.19 (GNU/Linux) iEYEABECAAYFAlF+m4cACgkQMUfUDdst+ymp+wCgv/F7zAhZsKW5YT9A/FsTNl3m Ge8AnRlfYPwxM1Zt4kIuDAwfKuLTYV/B =swS7 -----END PGP SIGNATURE----- Merge tag 'driver-core-3.10-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core Pull driver core update from Greg Kroah-Hartman: "Here's the merge request for the driver core tree for 3.10-rc1 It's pretty small, just a number of driver core and sysfs updates and fixes, all of which have been in linux-next for a while now. Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>" Fixed conflict in kernel/rtmutex-tester.c, the locking tree had a better fix for the same sysfs file mode problem. * tag 'driver-core-3.10-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core: PM / Runtime: Idle devices asynchronously after probe|release driver core: handle user namespaces properly with the uid/gid devtmpfs change driver core: devtmpfs: fix compile failure with CONFIG_UIDGID_STRICT_TYPE_CHECKS devtmpfs: add base.h include driver core: add uid and gid to devtmpfs sysfs: check if one entry has been removed before freeing sysfs: fix crash_notes_size build warning sysfs: fix use after free in case of concurrent read/write and readdir rtmutex-tester: fix mode of sysfs files Documentation: Add ABI entry for crash_notes and crash_notes_size sysfs: Add crash_notes_size to export percpu note size driver core: platform_device.h: fix checkpatch errors and warnings driver core: platform.c: fix checkpatch errors and warnings driver core: warn that platform_driver_probe can not use deferred probing sysfs: use atomic_inc_unless_negative in sysfs_get_active base: core: WARN() about bogus permissions on device attributes device: separate all subsys mutexes
This commit is contained in:
commit
2794b5d408
@ -173,3 +173,15 @@ Description: Processor frequency boosting control
|
|||||||
Boosting allows the CPU and the firmware to run at a frequency
|
Boosting allows the CPU and the firmware to run at a frequency
|
||||||
beyound it's nominal limit.
|
beyound it's nominal limit.
|
||||||
More details can be found in Documentation/cpu-freq/boost.txt
|
More details can be found in Documentation/cpu-freq/boost.txt
|
||||||
|
|
||||||
|
|
||||||
|
What: /sys/devices/system/cpu/cpu#/crash_notes
|
||||||
|
/sys/devices/system/cpu/cpu#/crash_notes_size
|
||||||
|
Date: April 2013
|
||||||
|
Contact: kexec@lists.infradead.org
|
||||||
|
Description: address and size of the percpu note.
|
||||||
|
|
||||||
|
crash_notes: the physical address of the memory that holds the
|
||||||
|
note of cpu#.
|
||||||
|
|
||||||
|
crash_notes_size: size of the note of cpu#.
|
||||||
|
@ -1111,7 +1111,8 @@ struct class block_class = {
|
|||||||
.name = "block",
|
.name = "block",
|
||||||
};
|
};
|
||||||
|
|
||||||
static char *block_devnode(struct device *dev, umode_t *mode)
|
static char *block_devnode(struct device *dev, umode_t *mode,
|
||||||
|
kuid_t *uid, kgid_t *gid)
|
||||||
{
|
{
|
||||||
struct gendisk *disk = dev_to_disk(dev);
|
struct gendisk *disk = dev_to_disk(dev);
|
||||||
|
|
||||||
|
@ -898,18 +898,18 @@ static ssize_t bus_uevent_store(struct bus_type *bus,
|
|||||||
static BUS_ATTR(uevent, S_IWUSR, NULL, bus_uevent_store);
|
static BUS_ATTR(uevent, S_IWUSR, NULL, bus_uevent_store);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* __bus_register - register a driver-core subsystem
|
* bus_register - register a driver-core subsystem
|
||||||
* @bus: bus to register
|
* @bus: bus to register
|
||||||
* @key: lockdep class key
|
|
||||||
*
|
*
|
||||||
* Once we have that, we register the bus with the kobject
|
* Once we have that, we register the bus with the kobject
|
||||||
* infrastructure, then register the children subsystems it has:
|
* infrastructure, then register the children subsystems it has:
|
||||||
* the devices and drivers that belong to the subsystem.
|
* the devices and drivers that belong to the subsystem.
|
||||||
*/
|
*/
|
||||||
int __bus_register(struct bus_type *bus, struct lock_class_key *key)
|
int bus_register(struct bus_type *bus)
|
||||||
{
|
{
|
||||||
int retval;
|
int retval;
|
||||||
struct subsys_private *priv;
|
struct subsys_private *priv;
|
||||||
|
struct lock_class_key *key = &bus->lock_key;
|
||||||
|
|
||||||
priv = kzalloc(sizeof(struct subsys_private), GFP_KERNEL);
|
priv = kzalloc(sizeof(struct subsys_private), GFP_KERNEL);
|
||||||
if (!priv)
|
if (!priv)
|
||||||
@ -981,7 +981,7 @@ out:
|
|||||||
bus->p = NULL;
|
bus->p = NULL;
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(__bus_register);
|
EXPORT_SYMBOL_GPL(bus_register);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* bus_unregister - remove a bus from the system
|
* bus_unregister - remove a bus from the system
|
||||||
|
@ -283,15 +283,21 @@ static int dev_uevent(struct kset *kset, struct kobject *kobj,
|
|||||||
const char *tmp;
|
const char *tmp;
|
||||||
const char *name;
|
const char *name;
|
||||||
umode_t mode = 0;
|
umode_t mode = 0;
|
||||||
|
kuid_t uid = GLOBAL_ROOT_UID;
|
||||||
|
kgid_t gid = GLOBAL_ROOT_GID;
|
||||||
|
|
||||||
add_uevent_var(env, "MAJOR=%u", MAJOR(dev->devt));
|
add_uevent_var(env, "MAJOR=%u", MAJOR(dev->devt));
|
||||||
add_uevent_var(env, "MINOR=%u", MINOR(dev->devt));
|
add_uevent_var(env, "MINOR=%u", MINOR(dev->devt));
|
||||||
name = device_get_devnode(dev, &mode, &tmp);
|
name = device_get_devnode(dev, &mode, &uid, &gid, &tmp);
|
||||||
if (name) {
|
if (name) {
|
||||||
add_uevent_var(env, "DEVNAME=%s", name);
|
add_uevent_var(env, "DEVNAME=%s", name);
|
||||||
kfree(tmp);
|
|
||||||
if (mode)
|
if (mode)
|
||||||
add_uevent_var(env, "DEVMODE=%#o", mode & 0777);
|
add_uevent_var(env, "DEVMODE=%#o", mode & 0777);
|
||||||
|
if (!uid_eq(uid, GLOBAL_ROOT_UID))
|
||||||
|
add_uevent_var(env, "DEVUID=%u", from_kuid(&init_user_ns, uid));
|
||||||
|
if (!gid_eq(gid, GLOBAL_ROOT_GID))
|
||||||
|
add_uevent_var(env, "DEVGID=%u", from_kgid(&init_user_ns, gid));
|
||||||
|
kfree(tmp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -563,8 +569,15 @@ int device_create_file(struct device *dev,
|
|||||||
const struct device_attribute *attr)
|
const struct device_attribute *attr)
|
||||||
{
|
{
|
||||||
int error = 0;
|
int error = 0;
|
||||||
if (dev)
|
|
||||||
|
if (dev) {
|
||||||
|
WARN(((attr->attr.mode & S_IWUGO) && !attr->store),
|
||||||
|
"Write permission without 'store'\n");
|
||||||
|
WARN(((attr->attr.mode & S_IRUGO) && !attr->show),
|
||||||
|
"Read permission without 'show'\n");
|
||||||
error = sysfs_create_file(&dev->kobj, &attr->attr);
|
error = sysfs_create_file(&dev->kobj, &attr->attr);
|
||||||
|
}
|
||||||
|
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1274,6 +1287,8 @@ static struct device *next_device(struct klist_iter *i)
|
|||||||
* device_get_devnode - path of device node file
|
* device_get_devnode - path of device node file
|
||||||
* @dev: device
|
* @dev: device
|
||||||
* @mode: returned file access mode
|
* @mode: returned file access mode
|
||||||
|
* @uid: returned file owner
|
||||||
|
* @gid: returned file group
|
||||||
* @tmp: possibly allocated string
|
* @tmp: possibly allocated string
|
||||||
*
|
*
|
||||||
* Return the relative path of a possible device node.
|
* Return the relative path of a possible device node.
|
||||||
@ -1282,7 +1297,8 @@ static struct device *next_device(struct klist_iter *i)
|
|||||||
* freed by the caller.
|
* freed by the caller.
|
||||||
*/
|
*/
|
||||||
const char *device_get_devnode(struct device *dev,
|
const char *device_get_devnode(struct device *dev,
|
||||||
umode_t *mode, const char **tmp)
|
umode_t *mode, kuid_t *uid, kgid_t *gid,
|
||||||
|
const char **tmp)
|
||||||
{
|
{
|
||||||
char *s;
|
char *s;
|
||||||
|
|
||||||
@ -1290,7 +1306,7 @@ const char *device_get_devnode(struct device *dev,
|
|||||||
|
|
||||||
/* the device type may provide a specific name */
|
/* the device type may provide a specific name */
|
||||||
if (dev->type && dev->type->devnode)
|
if (dev->type && dev->type->devnode)
|
||||||
*tmp = dev->type->devnode(dev, mode);
|
*tmp = dev->type->devnode(dev, mode, uid, gid);
|
||||||
if (*tmp)
|
if (*tmp)
|
||||||
return *tmp;
|
return *tmp;
|
||||||
|
|
||||||
|
@ -132,6 +132,17 @@ static ssize_t show_crash_notes(struct device *dev, struct device_attribute *att
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
static DEVICE_ATTR(crash_notes, 0400, show_crash_notes, NULL);
|
static DEVICE_ATTR(crash_notes, 0400, show_crash_notes, NULL);
|
||||||
|
|
||||||
|
static ssize_t show_crash_notes_size(struct device *dev,
|
||||||
|
struct device_attribute *attr,
|
||||||
|
char *buf)
|
||||||
|
{
|
||||||
|
ssize_t rc;
|
||||||
|
|
||||||
|
rc = sprintf(buf, "%zu\n", sizeof(note_buf_t));
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
static DEVICE_ATTR(crash_notes_size, 0400, show_crash_notes_size, NULL);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -259,6 +270,9 @@ int __cpuinit register_cpu(struct cpu *cpu, int num)
|
|||||||
#ifdef CONFIG_KEXEC
|
#ifdef CONFIG_KEXEC
|
||||||
if (!error)
|
if (!error)
|
||||||
error = device_create_file(&cpu->dev, &dev_attr_crash_notes);
|
error = device_create_file(&cpu->dev, &dev_attr_crash_notes);
|
||||||
|
if (!error)
|
||||||
|
error = device_create_file(&cpu->dev,
|
||||||
|
&dev_attr_crash_notes_size);
|
||||||
#endif
|
#endif
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
@ -380,7 +380,7 @@ int driver_probe_device(struct device_driver *drv, struct device *dev)
|
|||||||
|
|
||||||
pm_runtime_barrier(dev);
|
pm_runtime_barrier(dev);
|
||||||
ret = really_probe(dev, drv);
|
ret = really_probe(dev, drv);
|
||||||
pm_runtime_idle(dev);
|
pm_request_idle(dev);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -428,7 +428,7 @@ int device_attach(struct device *dev)
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
ret = bus_for_each_drv(dev->bus, NULL, dev, __device_attach);
|
ret = bus_for_each_drv(dev->bus, NULL, dev, __device_attach);
|
||||||
pm_runtime_idle(dev);
|
pm_request_idle(dev);
|
||||||
}
|
}
|
||||||
out_unlock:
|
out_unlock:
|
||||||
device_unlock(dev);
|
device_unlock(dev);
|
||||||
@ -499,7 +499,7 @@ static void __device_release_driver(struct device *dev)
|
|||||||
BUS_NOTIFY_UNBIND_DRIVER,
|
BUS_NOTIFY_UNBIND_DRIVER,
|
||||||
dev);
|
dev);
|
||||||
|
|
||||||
pm_runtime_put_sync(dev);
|
pm_runtime_put(dev);
|
||||||
|
|
||||||
if (dev->bus && dev->bus->remove)
|
if (dev->bus && dev->bus->remove)
|
||||||
dev->bus->remove(dev);
|
dev->bus->remove(dev);
|
||||||
|
@ -24,6 +24,7 @@
|
|||||||
#include <linux/sched.h>
|
#include <linux/sched.h>
|
||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
#include <linux/kthread.h>
|
#include <linux/kthread.h>
|
||||||
|
#include "base.h"
|
||||||
|
|
||||||
static struct task_struct *thread;
|
static struct task_struct *thread;
|
||||||
|
|
||||||
@ -41,6 +42,8 @@ static struct req {
|
|||||||
int err;
|
int err;
|
||||||
const char *name;
|
const char *name;
|
||||||
umode_t mode; /* 0 => delete */
|
umode_t mode; /* 0 => delete */
|
||||||
|
kuid_t uid;
|
||||||
|
kgid_t gid;
|
||||||
struct device *dev;
|
struct device *dev;
|
||||||
} *requests;
|
} *requests;
|
||||||
|
|
||||||
@ -85,7 +88,9 @@ int devtmpfs_create_node(struct device *dev)
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
req.mode = 0;
|
req.mode = 0;
|
||||||
req.name = device_get_devnode(dev, &req.mode, &tmp);
|
req.uid = GLOBAL_ROOT_UID;
|
||||||
|
req.gid = GLOBAL_ROOT_GID;
|
||||||
|
req.name = device_get_devnode(dev, &req.mode, &req.uid, &req.gid, &tmp);
|
||||||
if (!req.name)
|
if (!req.name)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
@ -121,7 +126,7 @@ int devtmpfs_delete_node(struct device *dev)
|
|||||||
if (!thread)
|
if (!thread)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
req.name = device_get_devnode(dev, NULL, &tmp);
|
req.name = device_get_devnode(dev, NULL, NULL, NULL, &tmp);
|
||||||
if (!req.name)
|
if (!req.name)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
@ -187,7 +192,8 @@ static int create_path(const char *nodepath)
|
|||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int handle_create(const char *nodename, umode_t mode, struct device *dev)
|
static int handle_create(const char *nodename, umode_t mode, kuid_t uid,
|
||||||
|
kgid_t gid, struct device *dev)
|
||||||
{
|
{
|
||||||
struct dentry *dentry;
|
struct dentry *dentry;
|
||||||
struct path path;
|
struct path path;
|
||||||
@ -201,14 +207,14 @@ static int handle_create(const char *nodename, umode_t mode, struct device *dev)
|
|||||||
if (IS_ERR(dentry))
|
if (IS_ERR(dentry))
|
||||||
return PTR_ERR(dentry);
|
return PTR_ERR(dentry);
|
||||||
|
|
||||||
err = vfs_mknod(path.dentry->d_inode,
|
err = vfs_mknod(path.dentry->d_inode, dentry, mode, dev->devt);
|
||||||
dentry, mode, dev->devt);
|
|
||||||
if (!err) {
|
if (!err) {
|
||||||
struct iattr newattrs;
|
struct iattr newattrs;
|
||||||
|
|
||||||
/* fixup possibly umasked mode */
|
|
||||||
newattrs.ia_mode = mode;
|
newattrs.ia_mode = mode;
|
||||||
newattrs.ia_valid = ATTR_MODE;
|
newattrs.ia_uid = uid;
|
||||||
|
newattrs.ia_gid = gid;
|
||||||
|
newattrs.ia_valid = ATTR_MODE|ATTR_UID|ATTR_GID;
|
||||||
mutex_lock(&dentry->d_inode->i_mutex);
|
mutex_lock(&dentry->d_inode->i_mutex);
|
||||||
notify_change(dentry, &newattrs);
|
notify_change(dentry, &newattrs);
|
||||||
mutex_unlock(&dentry->d_inode->i_mutex);
|
mutex_unlock(&dentry->d_inode->i_mutex);
|
||||||
@ -358,10 +364,11 @@ int devtmpfs_mount(const char *mntdir)
|
|||||||
|
|
||||||
static DECLARE_COMPLETION(setup_done);
|
static DECLARE_COMPLETION(setup_done);
|
||||||
|
|
||||||
static int handle(const char *name, umode_t mode, struct device *dev)
|
static int handle(const char *name, umode_t mode, kuid_t uid, kgid_t gid,
|
||||||
|
struct device *dev)
|
||||||
{
|
{
|
||||||
if (mode)
|
if (mode)
|
||||||
return handle_create(name, mode, dev);
|
return handle_create(name, mode, uid, gid, dev);
|
||||||
else
|
else
|
||||||
return handle_remove(name, dev);
|
return handle_remove(name, dev);
|
||||||
}
|
}
|
||||||
@ -387,7 +394,8 @@ static int devtmpfsd(void *p)
|
|||||||
spin_unlock(&req_lock);
|
spin_unlock(&req_lock);
|
||||||
while (req) {
|
while (req) {
|
||||||
struct req *next = req->next;
|
struct req *next = req->next;
|
||||||
req->err = handle(req->name, req->mode, req->dev);
|
req->err = handle(req->name, req->mode,
|
||||||
|
req->uid, req->gid, req->dev);
|
||||||
complete(&req->done);
|
complete(&req->done);
|
||||||
req = next;
|
req = next;
|
||||||
}
|
}
|
||||||
|
@ -46,8 +46,8 @@ EXPORT_SYMBOL_GPL(platform_bus);
|
|||||||
* manipulate any relevant information in the pdev_archdata they can do:
|
* manipulate any relevant information in the pdev_archdata they can do:
|
||||||
*
|
*
|
||||||
* platform_device_alloc()
|
* platform_device_alloc()
|
||||||
* ... manipulate ...
|
* ... manipulate ...
|
||||||
* platform_device_add()
|
* platform_device_add()
|
||||||
*
|
*
|
||||||
* And if they don't care they can just call platform_device_register() and
|
* And if they don't care they can just call platform_device_register() and
|
||||||
* everything will just work out.
|
* everything will just work out.
|
||||||
@ -326,9 +326,7 @@ int platform_device_add(struct platform_device *pdev)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (p && insert_resource(p, r)) {
|
if (p && insert_resource(p, r)) {
|
||||||
printk(KERN_ERR
|
dev_err(&pdev->dev, "failed to claim resource %d\n", i);
|
||||||
"%s: failed to claim resource %d\n",
|
|
||||||
dev_name(&pdev->dev), i);
|
|
||||||
ret = -EBUSY;
|
ret = -EBUSY;
|
||||||
goto failed;
|
goto failed;
|
||||||
}
|
}
|
||||||
@ -555,7 +553,8 @@ EXPORT_SYMBOL_GPL(platform_driver_unregister);
|
|||||||
/**
|
/**
|
||||||
* platform_driver_probe - register driver for non-hotpluggable device
|
* platform_driver_probe - register driver for non-hotpluggable device
|
||||||
* @drv: platform driver structure
|
* @drv: platform driver structure
|
||||||
* @probe: the driver probe routine, probably from an __init section
|
* @probe: the driver probe routine, probably from an __init section,
|
||||||
|
* must not return -EPROBE_DEFER.
|
||||||
*
|
*
|
||||||
* Use this instead of platform_driver_register() when you know the device
|
* Use this instead of platform_driver_register() when you know the device
|
||||||
* is not hotpluggable and has already been registered, and you want to
|
* is not hotpluggable and has already been registered, and you want to
|
||||||
@ -566,6 +565,9 @@ EXPORT_SYMBOL_GPL(platform_driver_unregister);
|
|||||||
* into system-on-chip processors, where the controller devices have been
|
* into system-on-chip processors, where the controller devices have been
|
||||||
* configured as part of board setup.
|
* configured as part of board setup.
|
||||||
*
|
*
|
||||||
|
* This is incompatible with deferred probing so probe() must not
|
||||||
|
* return -EPROBE_DEFER.
|
||||||
|
*
|
||||||
* Returns zero if the driver registered and bound to a device, else returns
|
* Returns zero if the driver registered and bound to a device, else returns
|
||||||
* a negative error code and with the driver not registered.
|
* a negative error code and with the driver not registered.
|
||||||
*/
|
*/
|
||||||
@ -682,7 +684,7 @@ static int platform_uevent(struct device *dev, struct kobj_uevent_env *env)
|
|||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
/* Some devices have extra OF data and an OF-style MODALIAS */
|
/* Some devices have extra OF data and an OF-style MODALIAS */
|
||||||
rc = of_device_uevent_modalias(dev,env);
|
rc = of_device_uevent_modalias(dev, env);
|
||||||
if (rc != -ENODEV)
|
if (rc != -ENODEV)
|
||||||
return rc;
|
return rc;
|
||||||
|
|
||||||
@ -1126,8 +1128,8 @@ static int __init early_platform_driver_probe_id(char *class_str,
|
|||||||
|
|
||||||
switch (match_id) {
|
switch (match_id) {
|
||||||
case EARLY_PLATFORM_ID_ERROR:
|
case EARLY_PLATFORM_ID_ERROR:
|
||||||
pr_warning("%s: unable to parse %s parameter\n",
|
pr_warn("%s: unable to parse %s parameter\n",
|
||||||
class_str, epdrv->pdrv->driver.name);
|
class_str, epdrv->pdrv->driver.name);
|
||||||
/* fall-through */
|
/* fall-through */
|
||||||
case EARLY_PLATFORM_ID_UNSET:
|
case EARLY_PLATFORM_ID_UNSET:
|
||||||
match = NULL;
|
match = NULL;
|
||||||
@ -1158,8 +1160,8 @@ static int __init early_platform_driver_probe_id(char *class_str,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (epdrv->pdrv->probe(match))
|
if (epdrv->pdrv->probe(match))
|
||||||
pr_warning("%s: unable to probe %s early.\n",
|
pr_warn("%s: unable to probe %s early.\n",
|
||||||
class_str, match->name);
|
class_str, match->name);
|
||||||
else
|
else
|
||||||
n++;
|
n++;
|
||||||
}
|
}
|
||||||
|
@ -317,7 +317,8 @@ static const struct dev_pm_ops usb_device_pm_ops = {
|
|||||||
#endif /* CONFIG_PM */
|
#endif /* CONFIG_PM */
|
||||||
|
|
||||||
|
|
||||||
static char *usb_devnode(struct device *dev, umode_t *mode)
|
static char *usb_devnode(struct device *dev,
|
||||||
|
umode_t *mode, kuid_t *uid, kgid_t *gid)
|
||||||
{
|
{
|
||||||
struct usb_device *usb_dev;
|
struct usb_device *usb_dev;
|
||||||
|
|
||||||
|
@ -165,21 +165,8 @@ struct sysfs_dirent *sysfs_get_active(struct sysfs_dirent *sd)
|
|||||||
if (unlikely(!sd))
|
if (unlikely(!sd))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
while (1) {
|
if (!atomic_inc_unless_negative(&sd->s_active))
|
||||||
int v, t;
|
return NULL;
|
||||||
|
|
||||||
v = atomic_read(&sd->s_active);
|
|
||||||
if (unlikely(v < 0))
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
t = atomic_cmpxchg(&sd->s_active, v, v + 1);
|
|
||||||
if (likely(t == v))
|
|
||||||
break;
|
|
||||||
if (t < 0)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
cpu_relax();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (likely(!ignore_lockdep(sd)))
|
if (likely(!ignore_lockdep(sd)))
|
||||||
rwsem_acquire_read(&sd->dep_map, 0, 1, _RET_IP_);
|
rwsem_acquire_read(&sd->dep_map, 0, 1, _RET_IP_);
|
||||||
@ -281,6 +268,10 @@ void release_sysfs_dirent(struct sysfs_dirent * sd)
|
|||||||
*/
|
*/
|
||||||
parent_sd = sd->s_parent;
|
parent_sd = sd->s_parent;
|
||||||
|
|
||||||
|
WARN(!(sd->s_flags & SYSFS_FLAG_REMOVED),
|
||||||
|
"sysfs: free using entry: %s/%s\n",
|
||||||
|
parent_sd ? parent_sd->s_name : "", sd->s_name);
|
||||||
|
|
||||||
if (sysfs_type(sd) == SYSFS_KOBJ_LINK)
|
if (sysfs_type(sd) == SYSFS_KOBJ_LINK)
|
||||||
sysfs_put(sd->s_symlink.target_sd);
|
sysfs_put(sd->s_symlink.target_sd);
|
||||||
if (sysfs_type(sd) & SYSFS_COPY_NAME)
|
if (sysfs_type(sd) & SYSFS_COPY_NAME)
|
||||||
@ -399,7 +390,7 @@ struct sysfs_dirent *sysfs_new_dirent(const char *name, umode_t mode, int type)
|
|||||||
|
|
||||||
sd->s_name = name;
|
sd->s_name = name;
|
||||||
sd->s_mode = mode;
|
sd->s_mode = mode;
|
||||||
sd->s_flags = type;
|
sd->s_flags = type | SYSFS_FLAG_REMOVED;
|
||||||
|
|
||||||
return sd;
|
return sd;
|
||||||
|
|
||||||
@ -479,6 +470,9 @@ int __sysfs_add_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd)
|
|||||||
ps_iattrs->ia_ctime = ps_iattrs->ia_mtime = CURRENT_TIME;
|
ps_iattrs->ia_ctime = ps_iattrs->ia_mtime = CURRENT_TIME;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Mark the entry added into directory tree */
|
||||||
|
sd->s_flags &= ~SYSFS_FLAG_REMOVED;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1012,6 +1006,7 @@ static int sysfs_readdir(struct file * filp, void * dirent, filldir_t filldir)
|
|||||||
enum kobj_ns_type type;
|
enum kobj_ns_type type;
|
||||||
const void *ns;
|
const void *ns;
|
||||||
ino_t ino;
|
ino_t ino;
|
||||||
|
loff_t off;
|
||||||
|
|
||||||
type = sysfs_ns_type(parent_sd);
|
type = sysfs_ns_type(parent_sd);
|
||||||
ns = sysfs_info(dentry->d_sb)->ns[type];
|
ns = sysfs_info(dentry->d_sb)->ns[type];
|
||||||
@ -1034,6 +1029,7 @@ static int sysfs_readdir(struct file * filp, void * dirent, filldir_t filldir)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
mutex_lock(&sysfs_mutex);
|
mutex_lock(&sysfs_mutex);
|
||||||
|
off = filp->f_pos;
|
||||||
for (pos = sysfs_dir_pos(ns, parent_sd, filp->f_pos, pos);
|
for (pos = sysfs_dir_pos(ns, parent_sd, filp->f_pos, pos);
|
||||||
pos;
|
pos;
|
||||||
pos = sysfs_dir_next_pos(ns, parent_sd, filp->f_pos, pos)) {
|
pos = sysfs_dir_next_pos(ns, parent_sd, filp->f_pos, pos)) {
|
||||||
@ -1045,19 +1041,24 @@ static int sysfs_readdir(struct file * filp, void * dirent, filldir_t filldir)
|
|||||||
len = strlen(name);
|
len = strlen(name);
|
||||||
ino = pos->s_ino;
|
ino = pos->s_ino;
|
||||||
type = dt_type(pos);
|
type = dt_type(pos);
|
||||||
filp->f_pos = pos->s_hash;
|
off = filp->f_pos = pos->s_hash;
|
||||||
filp->private_data = sysfs_get(pos);
|
filp->private_data = sysfs_get(pos);
|
||||||
|
|
||||||
mutex_unlock(&sysfs_mutex);
|
mutex_unlock(&sysfs_mutex);
|
||||||
ret = filldir(dirent, name, len, filp->f_pos, ino, type);
|
ret = filldir(dirent, name, len, off, ino, type);
|
||||||
mutex_lock(&sysfs_mutex);
|
mutex_lock(&sysfs_mutex);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
mutex_unlock(&sysfs_mutex);
|
mutex_unlock(&sysfs_mutex);
|
||||||
if ((filp->f_pos > 1) && !pos) { /* EOF */
|
|
||||||
filp->f_pos = INT_MAX;
|
/* don't reference last entry if its refcount is dropped */
|
||||||
|
if (!pos) {
|
||||||
filp->private_data = NULL;
|
filp->private_data = NULL;
|
||||||
|
|
||||||
|
/* EOF and not changed as 0 or 1 in read/write path */
|
||||||
|
if (off == filp->f_pos && off > 1)
|
||||||
|
filp->f_pos = INT_MAX;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -25,6 +25,7 @@
|
|||||||
#include <linux/pm.h>
|
#include <linux/pm.h>
|
||||||
#include <linux/atomic.h>
|
#include <linux/atomic.h>
|
||||||
#include <linux/ratelimit.h>
|
#include <linux/ratelimit.h>
|
||||||
|
#include <linux/uidgid.h>
|
||||||
#include <asm/device.h>
|
#include <asm/device.h>
|
||||||
|
|
||||||
struct device;
|
struct device;
|
||||||
@ -111,17 +112,11 @@ struct bus_type {
|
|||||||
struct iommu_ops *iommu_ops;
|
struct iommu_ops *iommu_ops;
|
||||||
|
|
||||||
struct subsys_private *p;
|
struct subsys_private *p;
|
||||||
|
struct lock_class_key lock_key;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* This is a #define to keep the compiler from merging different
|
extern int __must_check bus_register(struct bus_type *bus);
|
||||||
* instances of the __key variable */
|
|
||||||
#define bus_register(subsys) \
|
|
||||||
({ \
|
|
||||||
static struct lock_class_key __key; \
|
|
||||||
__bus_register(subsys, &__key); \
|
|
||||||
})
|
|
||||||
extern int __must_check __bus_register(struct bus_type *bus,
|
|
||||||
struct lock_class_key *key);
|
|
||||||
extern void bus_unregister(struct bus_type *bus);
|
extern void bus_unregister(struct bus_type *bus);
|
||||||
|
|
||||||
extern int __must_check bus_rescan_devices(struct bus_type *bus);
|
extern int __must_check bus_rescan_devices(struct bus_type *bus);
|
||||||
@ -471,7 +466,8 @@ struct device_type {
|
|||||||
const char *name;
|
const char *name;
|
||||||
const struct attribute_group **groups;
|
const struct attribute_group **groups;
|
||||||
int (*uevent)(struct device *dev, struct kobj_uevent_env *env);
|
int (*uevent)(struct device *dev, struct kobj_uevent_env *env);
|
||||||
char *(*devnode)(struct device *dev, umode_t *mode);
|
char *(*devnode)(struct device *dev, umode_t *mode,
|
||||||
|
kuid_t *uid, kgid_t *gid);
|
||||||
void (*release)(struct device *dev);
|
void (*release)(struct device *dev);
|
||||||
|
|
||||||
const struct dev_pm_ops *pm;
|
const struct dev_pm_ops *pm;
|
||||||
@ -849,7 +845,8 @@ extern int device_rename(struct device *dev, const char *new_name);
|
|||||||
extern int device_move(struct device *dev, struct device *new_parent,
|
extern int device_move(struct device *dev, struct device *new_parent,
|
||||||
enum dpm_order dpm_order);
|
enum dpm_order dpm_order);
|
||||||
extern const char *device_get_devnode(struct device *dev,
|
extern const char *device_get_devnode(struct device *dev,
|
||||||
umode_t *mode, const char **tmp);
|
umode_t *mode, kuid_t *uid, kgid_t *gid,
|
||||||
|
const char **tmp);
|
||||||
extern void *dev_get_drvdata(const struct device *dev);
|
extern void *dev_get_drvdata(const struct device *dev);
|
||||||
extern int dev_set_drvdata(struct device *dev, void *data);
|
extern int dev_set_drvdata(struct device *dev, void *data);
|
||||||
|
|
||||||
|
@ -20,12 +20,12 @@
|
|||||||
struct mfd_cell;
|
struct mfd_cell;
|
||||||
|
|
||||||
struct platform_device {
|
struct platform_device {
|
||||||
const char * name;
|
const char *name;
|
||||||
int id;
|
int id;
|
||||||
bool id_auto;
|
bool id_auto;
|
||||||
struct device dev;
|
struct device dev;
|
||||||
u32 num_resources;
|
u32 num_resources;
|
||||||
struct resource * resource;
|
struct resource *resource;
|
||||||
|
|
||||||
const struct platform_device_id *id_entry;
|
const struct platform_device_id *id_entry;
|
||||||
|
|
||||||
@ -47,9 +47,12 @@ extern struct bus_type platform_bus_type;
|
|||||||
extern struct device platform_bus;
|
extern struct device platform_bus;
|
||||||
|
|
||||||
extern void arch_setup_pdev_archdata(struct platform_device *);
|
extern void arch_setup_pdev_archdata(struct platform_device *);
|
||||||
extern struct resource *platform_get_resource(struct platform_device *, unsigned int, unsigned int);
|
extern struct resource *platform_get_resource(struct platform_device *,
|
||||||
|
unsigned int, unsigned int);
|
||||||
extern int platform_get_irq(struct platform_device *, unsigned int);
|
extern int platform_get_irq(struct platform_device *, unsigned int);
|
||||||
extern struct resource *platform_get_resource_byname(struct platform_device *, unsigned int, const char *);
|
extern struct resource *platform_get_resource_byname(struct platform_device *,
|
||||||
|
unsigned int,
|
||||||
|
const char *);
|
||||||
extern int platform_get_irq_byname(struct platform_device *, const char *);
|
extern int platform_get_irq_byname(struct platform_device *, const char *);
|
||||||
extern int platform_add_devices(struct platform_device **, int);
|
extern int platform_add_devices(struct platform_device **, int);
|
||||||
|
|
||||||
@ -161,7 +164,8 @@ extern struct platform_device *platform_device_alloc(const char *name, int id);
|
|||||||
extern int platform_device_add_resources(struct platform_device *pdev,
|
extern int platform_device_add_resources(struct platform_device *pdev,
|
||||||
const struct resource *res,
|
const struct resource *res,
|
||||||
unsigned int num);
|
unsigned int num);
|
||||||
extern int platform_device_add_data(struct platform_device *pdev, const void *data, size_t size);
|
extern int platform_device_add_data(struct platform_device *pdev,
|
||||||
|
const void *data, size_t size);
|
||||||
extern int platform_device_add(struct platform_device *pdev);
|
extern int platform_device_add(struct platform_device *pdev);
|
||||||
extern void platform_device_del(struct platform_device *pdev);
|
extern void platform_device_del(struct platform_device *pdev);
|
||||||
extern void platform_device_put(struct platform_device *pdev);
|
extern void platform_device_put(struct platform_device *pdev);
|
||||||
@ -190,7 +194,8 @@ static inline void *platform_get_drvdata(const struct platform_device *pdev)
|
|||||||
return dev_get_drvdata(&pdev->dev);
|
return dev_get_drvdata(&pdev->dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void platform_set_drvdata(struct platform_device *pdev, void *data)
|
static inline void platform_set_drvdata(struct platform_device *pdev,
|
||||||
|
void *data)
|
||||||
{
|
{
|
||||||
dev_set_drvdata(&pdev->dev, data);
|
dev_set_drvdata(&pdev->dev, data);
|
||||||
}
|
}
|
||||||
@ -222,10 +227,10 @@ static void __exit __platform_driver##_exit(void) \
|
|||||||
} \
|
} \
|
||||||
module_exit(__platform_driver##_exit);
|
module_exit(__platform_driver##_exit);
|
||||||
|
|
||||||
extern struct platform_device *platform_create_bundle(struct platform_driver *driver,
|
extern struct platform_device *platform_create_bundle(
|
||||||
int (*probe)(struct platform_device *),
|
struct platform_driver *driver, int (*probe)(struct platform_device *),
|
||||||
struct resource *res, unsigned int n_res,
|
struct resource *res, unsigned int n_res,
|
||||||
const void *data, size_t size);
|
const void *data, size_t size);
|
||||||
|
|
||||||
/* early platform driver interface */
|
/* early platform driver interface */
|
||||||
struct early_platform_driver {
|
struct early_platform_driver {
|
||||||
|
Loading…
Reference in New Issue
Block a user