Commit 2794b5d4 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'driver-core-3.10-rc1' of...

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
parents 4f567cbc 0d1d392f
...@@ -173,3 +173,15 @@ Description: Processor frequency boosting control ...@@ -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 = { ...@@ -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, ...@@ -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 @@ int __bus_register(struct bus_type *bus, struct lock_class_key *key) ...@@ -981,7 +981,7 @@ int __bus_register(struct bus_type *bus, struct lock_class_key *key)
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, ...@@ -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, ...@@ -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) ...@@ -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) ...@@ -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, ...@@ -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 ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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 @@ ...@@ -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 { ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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); ...@@ -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) ...@@ -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); ...@@ -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); ...@@ -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) ...@@ -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, ...@@ -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, ...@@ -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 = { ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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 @@ ...@@ -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 { ...@@ -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 { ...@@ -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); ...@@ -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 @@ ...@@ -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; ...@@ -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); ...@@ -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) ...@@ -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) \ ...@@ -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 {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment