Commit 29e7ee37 authored by Linus Torvalds's avatar Linus Torvalds

Merge master.kernel.org:/pub/scm/linux/kernel/git/gregkh/driver-2.6

* master.kernel.org:/pub/scm/linux/kernel/git/gregkh/driver-2.6:
  sysfs: cosmetic clean up on node creation failure paths
  sysfs: kill an extra put in sysfs_create_link() failure path
  Driver core: check return code of sysfs_create_link()
  HOWTO: Add the knwon_regression URI to the documentation
  dev_vdbg() documentation
  dev_vdbg(), available with -DVERBOSE_DEBUG
  sysfs: make sysfs_init_inode() static
  sysfs: fix sysfs root inode nlink accounting
  Documentation fix devres.txt: lib/iomap.c -> lib/devres.c
  sysfs: avoid kmem_cache_free(NULL)
  PM: remove deprecated dpm_runtime_* routines
  PM: Remove deprecated sysfs files
  Driver core: accept all valid action-strings in uevent-trigger
  debugfs: remove rmdir() non-empty complaint
parents fc15bc81 967e35dc
...@@ -633,12 +633,27 @@ covers RTL which is used frequently with assembly language in the kernel. ...@@ -633,12 +633,27 @@ covers RTL which is used frequently with assembly language in the kernel.
Kernel developers like to be seen as literate. Do mind the spelling Kernel developers like to be seen as literate. Do mind the spelling
of kernel messages to make a good impression. Do not use crippled of kernel messages to make a good impression. Do not use crippled
words like "dont" and use "do not" or "don't" instead. words like "dont"; use "do not" or "don't" instead. Make the messages
concise, clear, and unambiguous.
Kernel messages do not have to be terminated with a period. Kernel messages do not have to be terminated with a period.
Printing numbers in parentheses (%d) adds no value and should be avoided. Printing numbers in parentheses (%d) adds no value and should be avoided.
There are a number of driver model diagnostic macros in <linux/device.h>
which you should use to make sure messages are matched to the right device
and driver, and are tagged with the right level: dev_err(), dev_warn(),
dev_info(), and so forth. For messages that aren't associated with a
particular device, <linux/kernel.h> defines pr_debug() and pr_info().
Coming up with good debugging messages can be quite a challenge; and once
you have them, they can be a huge help for remote troubleshooting. Such
messages should be compiled out when the DEBUG symbol is not defined (that
is, by default they are not included). When you use dev_dbg() or pr_debug(),
that's automatic. Many subsystems have Kconfig options to turn on -DDEBUG.
A related convention uses VERBOSE_DEBUG to add dev_vdbg() messages to the
ones already enabled by DEBUG.
Chapter 14: Allocating memory Chapter 14: Allocating memory
...@@ -790,4 +805,5 @@ Kernel CodingStyle, by greg@kroah.com at OLS 2002: ...@@ -790,4 +805,5 @@ Kernel CodingStyle, by greg@kroah.com at OLS 2002:
http://www.kroah.com/linux/talks/ols_2002_kernel_codingstyle_talk/html/ http://www.kroah.com/linux/talks/ols_2002_kernel_codingstyle_talk/html/
-- --
Last updated on 2006-December-06. Last updated on 2007-July-13.
...@@ -249,6 +249,9 @@ process is as follows: ...@@ -249,6 +249,9 @@ process is as follows:
release a new -rc kernel every week. release a new -rc kernel every week.
- Process continues until the kernel is considered "ready", the - Process continues until the kernel is considered "ready", the
process should last around 6 weeks. process should last around 6 weeks.
- A list of known regressions present in each -rc release is
tracked at the following URI:
http://kernelnewbies.org/known_regressions
It is worth mentioning what Andrew Morton wrote on the linux-kernel It is worth mentioning what Andrew Morton wrote on the linux-kernel
mailing list about kernel releases: mailing list about kernel releases:
......
...@@ -207,7 +207,7 @@ responsibility. This is usually non-issue because bus ops and ...@@ -207,7 +207,7 @@ responsibility. This is usually non-issue because bus ops and
resource allocations already do the job. resource allocations already do the job.
For an example of single-instance devres type, read pcim_iomap_table() For an example of single-instance devres type, read pcim_iomap_table()
in lib/iomap.c. in lib/devres.c.
All devres interface functions can be called without context if the All devres interface functions can be called without context if the
right gfp mask is given. right gfp mask is given.
......
...@@ -26,9 +26,7 @@ Who: Hans Verkuil <hverkuil@xs4all.nl> and ...@@ -26,9 +26,7 @@ Who: Hans Verkuil <hverkuil@xs4all.nl> and
--------------------------- ---------------------------
What: /sys/devices/.../power/state What: dev->power.power_state
dev->power.power_state
dpm_runtime_{suspend,resume)()
When: July 2007 When: July 2007
Why: Broken design for runtime control over driver power states, confusing Why: Broken design for runtime control over driver power states, confusing
driver-internal runtime power management with: mechanisms to support driver-internal runtime power management with: mechanisms to support
......
...@@ -24,6 +24,8 @@ ...@@ -24,6 +24,8 @@
#include "base.h" #include "base.h"
#include "power/power.h" #include "power/power.h"
extern const char *kobject_actions[];
int (*platform_notify)(struct device * dev) = NULL; int (*platform_notify)(struct device * dev) = NULL;
int (*platform_notify_remove)(struct device * dev) = NULL; int (*platform_notify_remove)(struct device * dev) = NULL;
...@@ -303,10 +305,25 @@ out: ...@@ -303,10 +305,25 @@ out:
static ssize_t store_uevent(struct device *dev, struct device_attribute *attr, static ssize_t store_uevent(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count) const char *buf, size_t count)
{ {
if (memcmp(buf, "add", 3) != 0) size_t len = count;
enum kobject_action action;
if (len && buf[len-1] == '\n')
len--;
for (action = 0; action < KOBJ_MAX; action++) {
if (strncmp(kobject_actions[action], buf, len) != 0)
continue;
if (kobject_actions[action][len] != '\0')
continue;
kobject_uevent(&dev->kobj, action);
goto out;
}
dev_err(dev, "uevent: unsupported action-string; this will " dev_err(dev, "uevent: unsupported action-string; this will "
"be ignored in a future kernel version"); "be ignored in a future kernel version\n");
kobject_uevent(&dev->kobj, KOBJ_ADD); kobject_uevent(&dev->kobj, KOBJ_ADD);
out:
return count; return count;
} }
...@@ -643,6 +660,82 @@ static int setup_parent(struct device *dev, struct device *parent) ...@@ -643,6 +660,82 @@ static int setup_parent(struct device *dev, struct device *parent)
return 0; return 0;
} }
static int device_add_class_symlinks(struct device *dev)
{
int error;
if (!dev->class)
return 0;
error = sysfs_create_link(&dev->kobj, &dev->class->subsys.kobj,
"subsystem");
if (error)
goto out;
/*
* If this is not a "fake" compatible device, then create the
* symlink from the class to the device.
*/
if (dev->kobj.parent != &dev->class->subsys.kobj) {
error = sysfs_create_link(&dev->class->subsys.kobj, &dev->kobj,
dev->bus_id);
if (error)
goto out_subsys;
}
/* only bus-device parents get a "device"-link */
if (dev->parent && dev->parent->bus) {
error = sysfs_create_link(&dev->kobj, &dev->parent->kobj,
"device");
if (error)
goto out_busid;
#ifdef CONFIG_SYSFS_DEPRECATED
{
char * class_name = make_class_name(dev->class->name,
&dev->kobj);
if (class_name)
error = sysfs_create_link(&dev->parent->kobj,
&dev->kobj, class_name);
kfree(class_name);
if (error)
goto out_device;
}
#endif
}
return 0;
#ifdef CONFIG_SYSFS_DEPRECATED
out_device:
if (dev->parent)
sysfs_remove_link(&dev->kobj, "device");
#endif
out_busid:
if (dev->kobj.parent != &dev->class->subsys.kobj)
sysfs_remove_link(&dev->class->subsys.kobj, dev->bus_id);
out_subsys:
sysfs_remove_link(&dev->kobj, "subsystem");
out:
return error;
}
static void device_remove_class_symlinks(struct device *dev)
{
if (!dev->class)
return;
if (dev->parent) {
#ifdef CONFIG_SYSFS_DEPRECATED
char *class_name;
class_name = make_class_name(dev->class->name, &dev->kobj);
if (class_name) {
sysfs_remove_link(&dev->parent->kobj, class_name);
kfree(class_name);
}
#endif
sysfs_remove_link(&dev->kobj, "device");
}
if (dev->kobj.parent != &dev->class->subsys.kobj)
sysfs_remove_link(&dev->class->subsys.kobj, dev->bus_id);
sysfs_remove_link(&dev->kobj, "subsystem");
}
/** /**
* device_add - add device to device hierarchy. * device_add - add device to device hierarchy.
* @dev: device. * @dev: device.
...@@ -657,7 +750,6 @@ static int setup_parent(struct device *dev, struct device *parent) ...@@ -657,7 +750,6 @@ static int setup_parent(struct device *dev, struct device *parent)
int device_add(struct device *dev) int device_add(struct device *dev)
{ {
struct device *parent = NULL; struct device *parent = NULL;
char *class_name = NULL;
struct class_interface *class_intf; struct class_interface *class_intf;
int error = -EINVAL; int error = -EINVAL;
...@@ -697,27 +789,9 @@ int device_add(struct device *dev) ...@@ -697,27 +789,9 @@ int device_add(struct device *dev)
goto ueventattrError; goto ueventattrError;
} }
if (dev->class) { error = device_add_class_symlinks(dev);
sysfs_create_link(&dev->kobj, &dev->class->subsys.kobj, if (error)
"subsystem"); goto SymlinkError;
/* If this is not a "fake" compatible device, then create the
* symlink from the class to the device. */
if (dev->kobj.parent != &dev->class->subsys.kobj)
sysfs_create_link(&dev->class->subsys.kobj,
&dev->kobj, dev->bus_id);
if (parent) {
sysfs_create_link(&dev->kobj, &dev->parent->kobj,
"device");
#ifdef CONFIG_SYSFS_DEPRECATED
class_name = make_class_name(dev->class->name,
&dev->kobj);
if (class_name)
sysfs_create_link(&dev->parent->kobj,
&dev->kobj, class_name);
#endif
}
}
error = device_add_attrs(dev); error = device_add_attrs(dev);
if (error) if (error)
goto AttrsError; goto AttrsError;
...@@ -744,7 +818,6 @@ int device_add(struct device *dev) ...@@ -744,7 +818,6 @@ int device_add(struct device *dev)
up(&dev->class->sem); up(&dev->class->sem);
} }
Done: Done:
kfree(class_name);
put_device(dev); put_device(dev);
return error; return error;
BusError: BusError:
...@@ -755,6 +828,8 @@ int device_add(struct device *dev) ...@@ -755,6 +828,8 @@ int device_add(struct device *dev)
BUS_NOTIFY_DEL_DEVICE, dev); BUS_NOTIFY_DEL_DEVICE, dev);
device_remove_attrs(dev); device_remove_attrs(dev);
AttrsError: AttrsError:
device_remove_class_symlinks(dev);
SymlinkError:
if (MAJOR(dev->devt)) if (MAJOR(dev->devt))
device_remove_file(dev, &devt_attr); device_remove_file(dev, &devt_attr);
...@@ -1139,7 +1214,7 @@ int device_rename(struct device *dev, char *new_name) ...@@ -1139,7 +1214,7 @@ int device_rename(struct device *dev, char *new_name)
{ {
char *old_class_name = NULL; char *old_class_name = NULL;
char *new_class_name = NULL; char *new_class_name = NULL;
char *old_symlink_name = NULL; char *old_device_name = NULL;
int error; int error;
dev = get_device(dev); dev = get_device(dev);
...@@ -1153,42 +1228,49 @@ int device_rename(struct device *dev, char *new_name) ...@@ -1153,42 +1228,49 @@ int device_rename(struct device *dev, char *new_name)
old_class_name = make_class_name(dev->class->name, &dev->kobj); old_class_name = make_class_name(dev->class->name, &dev->kobj);
#endif #endif
if (dev->class) { old_device_name = kmalloc(BUS_ID_SIZE, GFP_KERNEL);
old_symlink_name = kmalloc(BUS_ID_SIZE, GFP_KERNEL); if (!old_device_name) {
if (!old_symlink_name) {
error = -ENOMEM; error = -ENOMEM;
goto out_free_old_class; goto out;
}
strlcpy(old_symlink_name, dev->bus_id, BUS_ID_SIZE);
} }
strlcpy(old_device_name, dev->bus_id, BUS_ID_SIZE);
strlcpy(dev->bus_id, new_name, BUS_ID_SIZE); strlcpy(dev->bus_id, new_name, BUS_ID_SIZE);
error = kobject_rename(&dev->kobj, new_name); error = kobject_rename(&dev->kobj, new_name);
if (error) {
strlcpy(dev->bus_id, old_device_name, BUS_ID_SIZE);
goto out;
}
#ifdef CONFIG_SYSFS_DEPRECATED #ifdef CONFIG_SYSFS_DEPRECATED
if (old_class_name) { if (old_class_name) {
new_class_name = make_class_name(dev->class->name, &dev->kobj); new_class_name = make_class_name(dev->class->name, &dev->kobj);
if (new_class_name) { if (new_class_name) {
sysfs_create_link(&dev->parent->kobj, &dev->kobj, error = sysfs_create_link(&dev->parent->kobj,
new_class_name); &dev->kobj, new_class_name);
if (error)
goto out;
sysfs_remove_link(&dev->parent->kobj, old_class_name); sysfs_remove_link(&dev->parent->kobj, old_class_name);
} }
} }
#endif #endif
if (dev->class) { if (dev->class) {
sysfs_remove_link(&dev->class->subsys.kobj, sysfs_remove_link(&dev->class->subsys.kobj, old_device_name);
old_symlink_name); error = sysfs_create_link(&dev->class->subsys.kobj, &dev->kobj,
sysfs_create_link(&dev->class->subsys.kobj, &dev->kobj,
dev->bus_id); dev->bus_id);
if (error) {
/* Uh... how to unravel this if restoring can fail? */
dev_err(dev, "%s: sysfs_create_symlink failed (%d)\n",
__FUNCTION__, error);
} }
}
out:
put_device(dev); put_device(dev);
kfree(new_class_name); kfree(new_class_name);
kfree(old_symlink_name);
out_free_old_class:
kfree(old_class_name); kfree(old_class_name);
kfree(old_device_name);
return error; return error;
} }
......
obj-y := shutdown.o obj-y := shutdown.o
obj-$(CONFIG_PM) += main.o suspend.o resume.o runtime.o sysfs.o obj-$(CONFIG_PM) += main.o suspend.o resume.o sysfs.o
obj-$(CONFIG_PM_TRACE) += trace.o obj-$(CONFIG_PM_TRACE) += trace.o
ifeq ($(CONFIG_DEBUG_DRIVER),y) ifeq ($(CONFIG_DEBUG_DRIVER),y)
......
...@@ -62,11 +62,6 @@ extern int resume_device(struct device *); ...@@ -62,11 +62,6 @@ extern int resume_device(struct device *);
*/ */
extern int suspend_device(struct device *, pm_message_t); extern int suspend_device(struct device *, pm_message_t);
/*
* runtime.c
*/
#else /* CONFIG_PM */ #else /* CONFIG_PM */
......
/*
* drivers/base/power/runtime.c - Handling dynamic device power management.
*
* Copyright (c) 2003 Patrick Mochel
* Copyright (c) 2003 Open Source Development Lab
*
*/
#include <linux/device.h>
#include "power.h"
static void runtime_resume(struct device * dev)
{
dev_dbg(dev, "resuming\n");
if (!dev->power.power_state.event)
return;
if (!resume_device(dev))
dev->power.power_state = PMSG_ON;
}
/**
* dpm_runtime_resume - Power one device back on.
* @dev: Device.
*
* Bring one device back to the on state by first powering it
* on, then restoring state. We only operate on devices that aren't
* already on.
* FIXME: We need to handle devices that are in an unknown state.
*/
void dpm_runtime_resume(struct device * dev)
{
mutex_lock(&dpm_mtx);
runtime_resume(dev);
mutex_unlock(&dpm_mtx);
}
EXPORT_SYMBOL(dpm_runtime_resume);
/**
* dpm_runtime_suspend - Put one device in low-power state.
* @dev: Device.
* @state: State to enter.
*/
int dpm_runtime_suspend(struct device * dev, pm_message_t state)
{
int error = 0;
mutex_lock(&dpm_mtx);
if (dev->power.power_state.event == state.event)
goto Done;
if (dev->power.power_state.event)
runtime_resume(dev);
if (!(error = suspend_device(dev, state)))
dev->power.power_state = state;
Done:
mutex_unlock(&dpm_mtx);
return error;
}
EXPORT_SYMBOL(dpm_runtime_suspend);
#if 0
/**
* dpm_set_power_state - Update power_state field.
* @dev: Device.
* @state: Power state device is in.
*
* This is an update mechanism for drivers to notify the core
* what power state a device is in. Device probing code may not
* always be able to tell, but we need accurate information to
* work reliably.
*/
void dpm_set_power_state(struct device * dev, pm_message_t state)
{
mutex_lock(&dpm_mtx);
dev->power.power_state = state;
mutex_unlock(&dpm_mtx);
}
#endif /* 0 */
...@@ -7,69 +7,6 @@ ...@@ -7,69 +7,6 @@
#include "power.h" #include "power.h"
#ifdef CONFIG_PM_SYSFS_DEPRECATED
/**
* state - Control current power state of device
*
* show() returns the current power state of the device. '0' indicates
* the device is on. Other values (2) indicate the device is in some low
* power state.
*
* store() sets the current power state, which is an integer valued
* 0, 2, or 3. Devices with bus.suspend_late(), or bus.resume_early()
* methods fail this operation; those methods couldn't be called.
* Otherwise,
*
* - If the recorded dev->power.power_state.event matches the
* target value, nothing is done.
* - If the recorded event code is nonzero, the device is reactivated
* by calling bus.resume() and/or class.resume().
* - If the target value is nonzero, the device is suspended by
* calling class.suspend() and/or bus.suspend() with event code
* PM_EVENT_SUSPEND.
*
* This mechanism is DEPRECATED and should only be used for testing.
*/
static ssize_t state_show(struct device * dev, struct device_attribute *attr, char * buf)
{
if (dev->power.power_state.event)
return sprintf(buf, "2\n");
else
return sprintf(buf, "0\n");
}
static ssize_t state_store(struct device * dev, struct device_attribute *attr, const char * buf, size_t n)
{
pm_message_t state;
int error = -EINVAL;
/* disallow incomplete suspend sequences */
if (dev->bus && (dev->bus->suspend_late || dev->bus->resume_early))
return error;
state.event = PM_EVENT_SUSPEND;
/* Older apps expected to write "3" here - confused with PCI D3 */
if ((n == 1) && !strcmp(buf, "3"))
error = dpm_runtime_suspend(dev, state);
if ((n == 1) && !strcmp(buf, "2"))
error = dpm_runtime_suspend(dev, state);
if ((n == 1) && !strcmp(buf, "0")) {
dpm_runtime_resume(dev);
error = 0;
}
return error ? error : n;
}
static DEVICE_ATTR(state, 0644, state_show, state_store);
#endif /* CONFIG_PM_SYSFS_DEPRECATED */
/* /*
* wakeup - Report/change current wakeup option for device * wakeup - Report/change current wakeup option for device
* *
...@@ -143,9 +80,6 @@ static DEVICE_ATTR(wakeup, 0644, wake_show, wake_store); ...@@ -143,9 +80,6 @@ static DEVICE_ATTR(wakeup, 0644, wake_show, wake_store);
static struct attribute * power_attrs[] = { static struct attribute * power_attrs[] = {
#ifdef CONFIG_PM_SYSFS_DEPRECATED
&dev_attr_state.attr,
#endif
&dev_attr_wakeup.attr, &dev_attr_wakeup.attr,
NULL, NULL,
}; };
......
...@@ -1127,6 +1127,34 @@ static int pcmcia_bus_uevent(struct device *dev, char **envp, int num_envp, ...@@ -1127,6 +1127,34 @@ static int pcmcia_bus_uevent(struct device *dev, char **envp, int num_envp,
#endif #endif
/************************ runtime PM support ***************************/
static int pcmcia_dev_suspend(struct device *dev, pm_message_t state);
static int pcmcia_dev_resume(struct device *dev);
static int runtime_suspend(struct device *dev)
{
int rc;
down(&dev->sem);
rc = pcmcia_dev_suspend(dev, PMSG_SUSPEND);
up(&dev->sem);
if (!rc)
dev->power.power_state.event = PM_EVENT_SUSPEND;
return rc;
}
static void runtime_resume(struct device *dev)
{
int rc;
down(&dev->sem);
rc = pcmcia_dev_resume(dev);
up(&dev->sem);
if (!rc)
dev->power.power_state.event = PM_EVENT_ON;
}
/************************ per-device sysfs output ***************************/ /************************ per-device sysfs output ***************************/
#define pcmcia_device_attr(field, test, format) \ #define pcmcia_device_attr(field, test, format) \
...@@ -1173,9 +1201,9 @@ static ssize_t pcmcia_store_pm_state(struct device *dev, struct device_attribute ...@@ -1173,9 +1201,9 @@ static ssize_t pcmcia_store_pm_state(struct device *dev, struct device_attribute
return -EINVAL; return -EINVAL;
if ((!p_dev->suspended) && !strncmp(buf, "off", 3)) if ((!p_dev->suspended) && !strncmp(buf, "off", 3))
ret = dpm_runtime_suspend(dev, PMSG_SUSPEND); ret = runtime_suspend(dev);
else if (p_dev->suspended && !strncmp(buf, "on", 2)) else if (p_dev->suspended && !strncmp(buf, "on", 2))
dpm_runtime_resume(dev); runtime_resume(dev);
return ret ? ret : count; return ret ? ret : count;
} }
...@@ -1312,10 +1340,10 @@ static int pcmcia_bus_suspend_callback(struct device *dev, void * _data) ...@@ -1312,10 +1340,10 @@ static int pcmcia_bus_suspend_callback(struct device *dev, void * _data)
struct pcmcia_socket *skt = _data; struct pcmcia_socket *skt = _data;
struct pcmcia_device *p_dev = to_pcmcia_dev(dev); struct pcmcia_device *p_dev = to_pcmcia_dev(dev);
if (p_dev->socket != skt) if (p_dev->socket != skt || p_dev->suspended)
return 0; return 0;
return dpm_runtime_suspend(dev, PMSG_SUSPEND); return runtime_suspend(dev);
} }
static int pcmcia_bus_resume_callback(struct device *dev, void * _data) static int pcmcia_bus_resume_callback(struct device *dev, void * _data)
...@@ -1323,10 +1351,10 @@ static int pcmcia_bus_resume_callback(struct device *dev, void * _data) ...@@ -1323,10 +1351,10 @@ static int pcmcia_bus_resume_callback(struct device *dev, void * _data)
struct pcmcia_socket *skt = _data; struct pcmcia_socket *skt = _data;
struct pcmcia_device *p_dev = to_pcmcia_dev(dev); struct pcmcia_device *p_dev = to_pcmcia_dev(dev);
if (p_dev->socket != skt) if (p_dev->socket != skt || !p_dev->suspended)
return 0; return 0;
dpm_runtime_resume(dev); runtime_resume(dev);
return 0; return 0;
} }
......
...@@ -29,13 +29,6 @@ ...@@ -29,13 +29,6 @@
#include "hcd.h" #include "hcd.h"
#include "usb.h" #include "usb.h"
#define VERBOSE_DEBUG 0
#if VERBOSE_DEBUG
#define dev_vdbg dev_dbg
#else
#define dev_vdbg(dev, fmt, args...) do { } while (0)
#endif
#ifdef CONFIG_HOTPLUG #ifdef CONFIG_HOTPLUG
......
...@@ -345,11 +345,6 @@ void debugfs_remove(struct dentry *dentry) ...@@ -345,11 +345,6 @@ void debugfs_remove(struct dentry *dentry)
switch (dentry->d_inode->i_mode & S_IFMT) { switch (dentry->d_inode->i_mode & S_IFMT) {
case S_IFDIR: case S_IFDIR:
ret = simple_rmdir(parent->d_inode, dentry); ret = simple_rmdir(parent->d_inode, dentry);
if (ret)
printk(KERN_ERR
"DebugFS rmdir on %s failed : "
"directory not empty.\n",
dentry->d_name.name);
break; break;
case S_IFLNK: case S_IFLNK:
kfree(dentry->d_inode->i_private); kfree(dentry->d_inode->i_private);
......
...@@ -361,20 +361,20 @@ static struct dentry_operations sysfs_dentry_ops = { ...@@ -361,20 +361,20 @@ static struct dentry_operations sysfs_dentry_ops = {
struct sysfs_dirent *sysfs_new_dirent(const char *name, umode_t mode, int type) struct sysfs_dirent *sysfs_new_dirent(const char *name, umode_t mode, int type)
{ {
char *dup_name = NULL; char *dup_name = NULL;
struct sysfs_dirent *sd = NULL; struct sysfs_dirent *sd;
if (type & SYSFS_COPY_NAME) { if (type & SYSFS_COPY_NAME) {
name = dup_name = kstrdup(name, GFP_KERNEL); name = dup_name = kstrdup(name, GFP_KERNEL);
if (!name) if (!name)
goto err_out; return NULL;
} }
sd = kmem_cache_zalloc(sysfs_dir_cachep, GFP_KERNEL); sd = kmem_cache_zalloc(sysfs_dir_cachep, GFP_KERNEL);
if (!sd) if (!sd)
goto err_out; goto err_out1;
if (sysfs_alloc_ino(&sd->s_ino)) if (sysfs_alloc_ino(&sd->s_ino))
goto err_out; goto err_out2;
atomic_set(&sd->s_count, 1); atomic_set(&sd->s_count, 1);
atomic_set(&sd->s_active, 0); atomic_set(&sd->s_active, 0);
...@@ -386,9 +386,10 @@ struct sysfs_dirent *sysfs_new_dirent(const char *name, umode_t mode, int type) ...@@ -386,9 +386,10 @@ struct sysfs_dirent *sysfs_new_dirent(const char *name, umode_t mode, int type)
return sd; return sd;
err_out: err_out2:
kfree(dup_name);
kmem_cache_free(sysfs_dir_cachep, sd); kmem_cache_free(sysfs_dir_cachep, sd);
err_out1:
kfree(dup_name);
return NULL; return NULL;
} }
...@@ -698,17 +699,19 @@ static int create_dir(struct kobject *kobj, struct sysfs_dirent *parent_sd, ...@@ -698,17 +699,19 @@ static int create_dir(struct kobject *kobj, struct sysfs_dirent *parent_sd,
/* link in */ /* link in */
sysfs_addrm_start(&acxt, parent_sd); sysfs_addrm_start(&acxt, parent_sd);
if (!sysfs_find_dirent(parent_sd, name)) { if (!sysfs_find_dirent(parent_sd, name)) {
sysfs_add_one(&acxt, sd); sysfs_add_one(&acxt, sd);
sysfs_link_sibling(sd); sysfs_link_sibling(sd);
} }
if (sysfs_addrm_finish(&acxt)) {
*p_sd = sd;
return 0;
}
if (!sysfs_addrm_finish(&acxt)) {
sysfs_put(sd); sysfs_put(sd);
return -EEXIST; return -EEXIST;
}
*p_sd = sd;
return 0;
} }
int sysfs_create_subdir(struct kobject *kobj, const char *name, int sysfs_create_subdir(struct kobject *kobj, const char *name,
......
...@@ -410,11 +410,12 @@ int sysfs_add_file(struct sysfs_dirent *dir_sd, const struct attribute *attr, ...@@ -410,11 +410,12 @@ int sysfs_add_file(struct sysfs_dirent *dir_sd, const struct attribute *attr,
sysfs_link_sibling(sd); sysfs_link_sibling(sd);
} }
if (sysfs_addrm_finish(&acxt)) if (!sysfs_addrm_finish(&acxt)) {
return 0;
sysfs_put(sd); sysfs_put(sd);
return -EEXIST; return -EEXIST;
}
return 0;
} }
......
...@@ -133,7 +133,7 @@ static inline void set_inode_attr(struct inode * inode, struct iattr * iattr) ...@@ -133,7 +133,7 @@ static inline void set_inode_attr(struct inode * inode, struct iattr * iattr)
*/ */
static struct lock_class_key sysfs_inode_imutex_key; static struct lock_class_key sysfs_inode_imutex_key;
void sysfs_init_inode(struct sysfs_dirent *sd, struct inode *inode) static void sysfs_init_inode(struct sysfs_dirent *sd, struct inode *inode)
{ {
inode->i_blocks = 0; inode->i_blocks = 0;
inode->i_mapping->a_ops = &sysfs_aops; inode->i_mapping->a_ops = &sysfs_aops;
......
...@@ -43,19 +43,19 @@ static int sysfs_fill_super(struct super_block *sb, void *data, int silent) ...@@ -43,19 +43,19 @@ static int sysfs_fill_super(struct super_block *sb, void *data, int silent)
sb->s_time_gran = 1; sb->s_time_gran = 1;
sysfs_sb = sb; sysfs_sb = sb;
inode = new_inode(sysfs_sb); /* get root inode, initialize and unlock it */
inode = sysfs_get_inode(&sysfs_root);
if (!inode) { if (!inode) {
pr_debug("sysfs: could not get root inode\n"); pr_debug("sysfs: could not get root inode\n");
return -ENOMEM; return -ENOMEM;
} }
sysfs_init_inode(&sysfs_root, inode);
inode->i_op = &sysfs_dir_inode_operations; inode->i_op = &sysfs_dir_inode_operations;
inode->i_fop = &sysfs_dir_operations; inode->i_fop = &sysfs_dir_operations;
/* directory inodes start off with i_nlink == 2 (for "." entry) */ inc_nlink(inode); /* directory, account for "." */
inc_nlink(inode); unlock_new_inode(inode);
/* instantiate and link root dentry */
root = d_alloc_root(inode); root = d_alloc_root(inode);
if (!root) { if (!root) {
pr_debug("%s: could not get root dentry!\n",__FUNCTION__); pr_debug("%s: could not get root dentry!\n",__FUNCTION__);
......
...@@ -86,7 +86,9 @@ int sysfs_create_link(struct kobject * kobj, struct kobject * target, const char ...@@ -86,7 +86,9 @@ int sysfs_create_link(struct kobject * kobj, struct kobject * target, const char
sd = sysfs_new_dirent(name, S_IFLNK|S_IRWXUGO, SYSFS_KOBJ_LINK); sd = sysfs_new_dirent(name, S_IFLNK|S_IRWXUGO, SYSFS_KOBJ_LINK);
if (!sd) if (!sd)
goto out_put; goto out_put;
sd->s_elem.symlink.target_sd = target_sd; sd->s_elem.symlink.target_sd = target_sd;
target_sd = NULL; /* reference is now owned by the symlink */
sysfs_addrm_start(&acxt, parent_sd); sysfs_addrm_start(&acxt, parent_sd);
...@@ -95,11 +97,13 @@ int sysfs_create_link(struct kobject * kobj, struct kobject * target, const char ...@@ -95,11 +97,13 @@ int sysfs_create_link(struct kobject * kobj, struct kobject * target, const char
sysfs_link_sibling(sd); sysfs_link_sibling(sd);
} }
if (sysfs_addrm_finish(&acxt)) if (!sysfs_addrm_finish(&acxt)) {
error = -EEXIST;
goto out_put;
}
return 0; return 0;
error = -EEXIST;
/* fall through */
out_put: out_put:
sysfs_put(target_sd); sysfs_put(target_sd);
sysfs_put(sd); sysfs_put(sd);
......
...@@ -71,7 +71,6 @@ extern void sysfs_remove_one(struct sysfs_addrm_cxt *acxt, ...@@ -71,7 +71,6 @@ extern void sysfs_remove_one(struct sysfs_addrm_cxt *acxt,
extern int sysfs_addrm_finish(struct sysfs_addrm_cxt *acxt); extern int sysfs_addrm_finish(struct sysfs_addrm_cxt *acxt);
extern void sysfs_delete_inode(struct inode *inode); extern void sysfs_delete_inode(struct inode *inode);
extern void sysfs_init_inode(struct sysfs_dirent *sd, struct inode *inode);
extern struct inode * sysfs_get_inode(struct sysfs_dirent *sd); extern struct inode * sysfs_get_inode(struct sysfs_dirent *sd);
extern void sysfs_instantiate(struct dentry *dentry, struct inode *inode); extern void sysfs_instantiate(struct dentry *dentry, struct inode *inode);
......
...@@ -572,6 +572,16 @@ dev_dbg(struct device * dev, const char * fmt, ...) ...@@ -572,6 +572,16 @@ dev_dbg(struct device * dev, const char * fmt, ...)
} }
#endif #endif
#ifdef VERBOSE_DEBUG
#define dev_vdbg dev_dbg
#else
static inline int __attribute__ ((format (printf, 2, 3)))
dev_vdbg(struct device * dev, const char * fmt, ...)
{
return 0;
}
#endif
#define dev_err(dev, format, arg...) \ #define dev_err(dev, format, arg...) \
dev_printk(KERN_ERR , dev , format , ## arg) dev_printk(KERN_ERR , dev , format , ## arg)
#define dev_info(dev, format, arg...) \ #define dev_info(dev, format, arg...) \
......
...@@ -36,15 +36,24 @@ extern char uevent_helper[]; ...@@ -36,15 +36,24 @@ extern char uevent_helper[];
/* 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;
/* the actions here must match the proper string in lib/kobject_uevent.c */ /*
typedef int __bitwise kobject_action_t; * The actions here must match the index to the string array
* in lib/kobject_uevent.c
*
* Do not add new actions here without checking with the driver-core
* maintainers. Action strings are not meant to express subsystem
* or device specific properties. In most cases you want to send a
* kobject_uevent_env(kobj, KOBJ_CHANGE, env) with additional event
* specific variables added to the event environment.
*/
enum kobject_action { enum kobject_action {
KOBJ_ADD = (__force kobject_action_t) 0x01, /* exclusive to core */ KOBJ_ADD,
KOBJ_REMOVE = (__force kobject_action_t) 0x02, /* exclusive to core */ KOBJ_REMOVE,
KOBJ_CHANGE = (__force kobject_action_t) 0x03, /* device state change */ KOBJ_CHANGE,
KOBJ_OFFLINE = (__force kobject_action_t) 0x04, /* device offline */ KOBJ_MOVE,
KOBJ_ONLINE = (__force kobject_action_t) 0x05, /* device online */ KOBJ_ONLINE,
KOBJ_MOVE = (__force kobject_action_t) 0x06, /* device move */ KOBJ_OFFLINE,
KOBJ_MAX
}; };
struct kobject { struct kobject {
......
...@@ -284,8 +284,6 @@ extern int device_prepare_suspend(pm_message_t state); ...@@ -284,8 +284,6 @@ extern int device_prepare_suspend(pm_message_t state);
#define device_may_wakeup(dev) \ #define device_may_wakeup(dev) \
(device_can_wakeup(dev) && (dev)->power.should_wakeup) (device_can_wakeup(dev) && (dev)->power.should_wakeup)
extern int dpm_runtime_suspend(struct device *, pm_message_t);
extern void dpm_runtime_resume(struct device *);
extern void __suspend_report_result(const char *function, void *fn, int ret); extern void __suspend_report_result(const char *function, void *fn, int ret);
#define suspend_report_result(fn, ret) \ #define suspend_report_result(fn, ret) \
...@@ -317,15 +315,6 @@ static inline int device_suspend(pm_message_t state) ...@@ -317,15 +315,6 @@ static inline int device_suspend(pm_message_t state)
#define device_set_wakeup_enable(dev,val) do{}while(0) #define device_set_wakeup_enable(dev,val) do{}while(0)
#define device_may_wakeup(dev) (0) #define device_may_wakeup(dev) (0)
static inline int dpm_runtime_suspend(struct device * dev, pm_message_t state)
{
return 0;
}
static inline void dpm_runtime_resume(struct device * dev)
{
}
#define suspend_report_result(fn, ret) do { } while (0) #define suspend_report_result(fn, ret) do { } while (0)
static inline int call_platform_enable_wakeup(struct device *dev, int is_on) static inline int call_platform_enable_wakeup(struct device *dev, int is_on)
......
...@@ -65,18 +65,6 @@ config PM_TRACE ...@@ -65,18 +65,6 @@ config PM_TRACE
CAUTION: this option will cause your machine's real-time clock to be CAUTION: this option will cause your machine's real-time clock to be
set to an invalid time after a resume. set to an invalid time after a resume.
config PM_SYSFS_DEPRECATED
bool "Driver model /sys/devices/.../power/state files (DEPRECATED)"
depends on PM && SYSFS
default n
help
The driver model started out with a sysfs file intended to provide
a userspace hook for device power management. This feature has never
worked very well, except for limited testing purposes, and so it will
be removed. It's not clear that a generic mechanism could really
handle the wide variability of device power states; any replacements
are likely to be bus or driver specific.
config SOFTWARE_SUSPEND config SOFTWARE_SUSPEND
bool "Software Suspend (Hibernation)" bool "Software Suspend (Hibernation)"
depends on PM && SWAP && (((X86 || PPC64_SWSUSP) && (!SMP || SUSPEND_SMP)) || ((FRV || PPC32) && !SMP)) depends on PM && SWAP && (((X86 || PPC64_SWSUSP) && (!SMP || SUSPEND_SMP)) || ((FRV || PPC32) && !SMP))
......
...@@ -33,25 +33,15 @@ static DEFINE_SPINLOCK(sequence_lock); ...@@ -33,25 +33,15 @@ static DEFINE_SPINLOCK(sequence_lock);
static struct sock *uevent_sock; static struct sock *uevent_sock;
#endif #endif
static char *action_to_string(enum kobject_action action) /* the strings here must match the enum in include/linux/kobject.h */
{ const char *kobject_actions[] = {
switch (action) { "add",
case KOBJ_ADD: "remove",
return "add"; "change",
case KOBJ_REMOVE: "move",
return "remove"; "online",
case KOBJ_CHANGE: "offline",
return "change"; };
case KOBJ_OFFLINE:
return "offline";
case KOBJ_ONLINE:
return "online";
case KOBJ_MOVE:
return "move";
default:
return NULL;
}
}
/** /**
* kobject_uevent_env - send an uevent with environmental data * kobject_uevent_env - send an uevent with environmental data
...@@ -83,7 +73,7 @@ int kobject_uevent_env(struct kobject *kobj, enum kobject_action action, ...@@ -83,7 +73,7 @@ int kobject_uevent_env(struct kobject *kobj, enum kobject_action action,
pr_debug("%s\n", __FUNCTION__); pr_debug("%s\n", __FUNCTION__);
action_string = action_to_string(action); action_string = kobject_actions[action];
if (!action_string) { if (!action_string) {
pr_debug("kobject attempted to send uevent without action_string!\n"); pr_debug("kobject attempted to send uevent without action_string!\n");
return -EINVAL; return -EINVAL;
......
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