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
This commit is contained in:
commit
29e7ee378e
|
@ -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
|
||||
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.
|
||||
|
||||
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
|
||||
|
||||
|
@ -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/
|
||||
|
||||
--
|
||||
Last updated on 2006-December-06.
|
||||
Last updated on 2007-July-13.
|
||||
|
||||
|
|
|
@ -249,6 +249,9 @@ process is as follows:
|
|||
release a new -rc kernel every week.
|
||||
- Process continues until the kernel is considered "ready", the
|
||||
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
|
||||
mailing list about kernel releases:
|
||||
|
|
|
@ -207,7 +207,7 @@ responsibility. This is usually non-issue because bus ops and
|
|||
resource allocations already do the job.
|
||||
|
||||
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
|
||||
right gfp mask is given.
|
||||
|
|
|
@ -26,9 +26,7 @@ Who: Hans Verkuil <hverkuil@xs4all.nl> and
|
|||
|
||||
---------------------------
|
||||
|
||||
What: /sys/devices/.../power/state
|
||||
dev->power.power_state
|
||||
dpm_runtime_{suspend,resume)()
|
||||
What: dev->power.power_state
|
||||
When: July 2007
|
||||
Why: Broken design for runtime control over driver power states, confusing
|
||||
driver-internal runtime power management with: mechanisms to support
|
||||
|
|
|
@ -24,6 +24,8 @@
|
|||
#include "base.h"
|
||||
#include "power/power.h"
|
||||
|
||||
extern const char *kobject_actions[];
|
||||
|
||||
int (*platform_notify)(struct device * dev) = NULL;
|
||||
int (*platform_notify_remove)(struct device * dev) = NULL;
|
||||
|
||||
|
@ -303,10 +305,25 @@ out:
|
|||
static ssize_t store_uevent(struct device *dev, struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
if (memcmp(buf, "add", 3) != 0)
|
||||
dev_err(dev, "uevent: unsupported action-string; this will "
|
||||
"be ignored in a future kernel version");
|
||||
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 "
|
||||
"be ignored in a future kernel version\n");
|
||||
kobject_uevent(&dev->kobj, KOBJ_ADD);
|
||||
out:
|
||||
return count;
|
||||
}
|
||||
|
||||
|
@ -643,6 +660,82 @@ static int setup_parent(struct device *dev, struct device *parent)
|
|||
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.
|
||||
* @dev: device.
|
||||
|
@ -657,7 +750,6 @@ static int setup_parent(struct device *dev, struct device *parent)
|
|||
int device_add(struct device *dev)
|
||||
{
|
||||
struct device *parent = NULL;
|
||||
char *class_name = NULL;
|
||||
struct class_interface *class_intf;
|
||||
int error = -EINVAL;
|
||||
|
||||
|
@ -697,27 +789,9 @@ int device_add(struct device *dev)
|
|||
goto ueventattrError;
|
||||
}
|
||||
|
||||
if (dev->class) {
|
||||
sysfs_create_link(&dev->kobj, &dev->class->subsys.kobj,
|
||||
"subsystem");
|
||||
/* 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_class_symlinks(dev);
|
||||
if (error)
|
||||
goto SymlinkError;
|
||||
error = device_add_attrs(dev);
|
||||
if (error)
|
||||
goto AttrsError;
|
||||
|
@ -744,7 +818,6 @@ int device_add(struct device *dev)
|
|||
up(&dev->class->sem);
|
||||
}
|
||||
Done:
|
||||
kfree(class_name);
|
||||
put_device(dev);
|
||||
return error;
|
||||
BusError:
|
||||
|
@ -755,6 +828,8 @@ int device_add(struct device *dev)
|
|||
BUS_NOTIFY_DEL_DEVICE, dev);
|
||||
device_remove_attrs(dev);
|
||||
AttrsError:
|
||||
device_remove_class_symlinks(dev);
|
||||
SymlinkError:
|
||||
if (MAJOR(dev->devt))
|
||||
device_remove_file(dev, &devt_attr);
|
||||
|
||||
|
@ -1139,7 +1214,7 @@ int device_rename(struct device *dev, char *new_name)
|
|||
{
|
||||
char *old_class_name = NULL;
|
||||
char *new_class_name = NULL;
|
||||
char *old_symlink_name = NULL;
|
||||
char *old_device_name = NULL;
|
||||
int error;
|
||||
|
||||
dev = get_device(dev);
|
||||
|
@ -1153,42 +1228,49 @@ int device_rename(struct device *dev, char *new_name)
|
|||
old_class_name = make_class_name(dev->class->name, &dev->kobj);
|
||||
#endif
|
||||
|
||||
if (dev->class) {
|
||||
old_symlink_name = kmalloc(BUS_ID_SIZE, GFP_KERNEL);
|
||||
if (!old_symlink_name) {
|
||||
error = -ENOMEM;
|
||||
goto out_free_old_class;
|
||||
}
|
||||
strlcpy(old_symlink_name, dev->bus_id, BUS_ID_SIZE);
|
||||
old_device_name = kmalloc(BUS_ID_SIZE, GFP_KERNEL);
|
||||
if (!old_device_name) {
|
||||
error = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
strlcpy(old_device_name, dev->bus_id, BUS_ID_SIZE);
|
||||
strlcpy(dev->bus_id, new_name, BUS_ID_SIZE);
|
||||
|
||||
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
|
||||
if (old_class_name) {
|
||||
new_class_name = make_class_name(dev->class->name, &dev->kobj);
|
||||
if (new_class_name) {
|
||||
sysfs_create_link(&dev->parent->kobj, &dev->kobj,
|
||||
new_class_name);
|
||||
error = sysfs_create_link(&dev->parent->kobj,
|
||||
&dev->kobj, new_class_name);
|
||||
if (error)
|
||||
goto out;
|
||||
sysfs_remove_link(&dev->parent->kobj, old_class_name);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (dev->class) {
|
||||
sysfs_remove_link(&dev->class->subsys.kobj,
|
||||
old_symlink_name);
|
||||
sysfs_create_link(&dev->class->subsys.kobj, &dev->kobj,
|
||||
dev->bus_id);
|
||||
sysfs_remove_link(&dev->class->subsys.kobj, old_device_name);
|
||||
error = sysfs_create_link(&dev->class->subsys.kobj, &dev->kobj,
|
||||
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);
|
||||
|
||||
kfree(new_class_name);
|
||||
kfree(old_symlink_name);
|
||||
out_free_old_class:
|
||||
kfree(old_class_name);
|
||||
kfree(old_device_name);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
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
|
||||
|
||||
ifeq ($(CONFIG_DEBUG_DRIVER),y)
|
||||
|
|
|
@ -62,11 +62,6 @@ extern int resume_device(struct device *);
|
|||
*/
|
||||
extern int suspend_device(struct device *, pm_message_t);
|
||||
|
||||
|
||||
/*
|
||||
* runtime.c
|
||||
*/
|
||||
|
||||
#else /* CONFIG_PM */
|
||||
|
||||
|
||||
|
|
|
@ -1,85 +0,0 @@
|
|||
/*
|
||||
* 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 @@
|
|||
#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
|
||||
*
|
||||
|
@ -143,9 +80,6 @@ static DEVICE_ATTR(wakeup, 0644, wake_show, wake_store);
|
|||
|
||||
|
||||
static struct attribute * power_attrs[] = {
|
||||
#ifdef CONFIG_PM_SYSFS_DEPRECATED
|
||||
&dev_attr_state.attr,
|
||||
#endif
|
||||
&dev_attr_wakeup.attr,
|
||||
NULL,
|
||||
};
|
||||
|
|
|
@ -1127,6 +1127,34 @@ static int pcmcia_bus_uevent(struct device *dev, char **envp, int num_envp,
|
|||
|
||||
#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 ***************************/
|
||||
|
||||
#define pcmcia_device_attr(field, test, format) \
|
||||
|
@ -1173,9 +1201,9 @@ static ssize_t pcmcia_store_pm_state(struct device *dev, struct device_attribute
|
|||
return -EINVAL;
|
||||
|
||||
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))
|
||||
dpm_runtime_resume(dev);
|
||||
runtime_resume(dev);
|
||||
|
||||
return ret ? ret : count;
|
||||
}
|
||||
|
@ -1312,10 +1340,10 @@ static int pcmcia_bus_suspend_callback(struct device *dev, void * _data)
|
|||
struct pcmcia_socket *skt = _data;
|
||||
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 dpm_runtime_suspend(dev, PMSG_SUSPEND);
|
||||
return runtime_suspend(dev);
|
||||
}
|
||||
|
||||
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_device *p_dev = to_pcmcia_dev(dev);
|
||||
|
||||
if (p_dev->socket != skt)
|
||||
if (p_dev->socket != skt || !p_dev->suspended)
|
||||
return 0;
|
||||
|
||||
dpm_runtime_resume(dev);
|
||||
runtime_resume(dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -29,13 +29,6 @@
|
|||
#include "hcd.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
|
||||
|
||||
|
|
|
@ -345,11 +345,6 @@ void debugfs_remove(struct dentry *dentry)
|
|||
switch (dentry->d_inode->i_mode & S_IFMT) {
|
||||
case S_IFDIR:
|
||||
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;
|
||||
case S_IFLNK:
|
||||
kfree(dentry->d_inode->i_private);
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
char *dup_name = NULL;
|
||||
struct sysfs_dirent *sd = NULL;
|
||||
struct sysfs_dirent *sd;
|
||||
|
||||
if (type & SYSFS_COPY_NAME) {
|
||||
name = dup_name = kstrdup(name, GFP_KERNEL);
|
||||
if (!name)
|
||||
goto err_out;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
sd = kmem_cache_zalloc(sysfs_dir_cachep, GFP_KERNEL);
|
||||
if (!sd)
|
||||
goto err_out;
|
||||
goto err_out1;
|
||||
|
||||
if (sysfs_alloc_ino(&sd->s_ino))
|
||||
goto err_out;
|
||||
goto err_out2;
|
||||
|
||||
atomic_set(&sd->s_count, 1);
|
||||
atomic_set(&sd->s_active, 0);
|
||||
|
@ -386,9 +386,10 @@ struct sysfs_dirent *sysfs_new_dirent(const char *name, umode_t mode, int type)
|
|||
|
||||
return sd;
|
||||
|
||||
err_out:
|
||||
kfree(dup_name);
|
||||
err_out2:
|
||||
kmem_cache_free(sysfs_dir_cachep, sd);
|
||||
err_out1:
|
||||
kfree(dup_name);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -698,17 +699,19 @@ static int create_dir(struct kobject *kobj, struct sysfs_dirent *parent_sd,
|
|||
|
||||
/* link in */
|
||||
sysfs_addrm_start(&acxt, parent_sd);
|
||||
|
||||
if (!sysfs_find_dirent(parent_sd, name)) {
|
||||
sysfs_add_one(&acxt, sd);
|
||||
sysfs_link_sibling(sd);
|
||||
}
|
||||
if (sysfs_addrm_finish(&acxt)) {
|
||||
*p_sd = sd;
|
||||
return 0;
|
||||
|
||||
if (!sysfs_addrm_finish(&acxt)) {
|
||||
sysfs_put(sd);
|
||||
return -EEXIST;
|
||||
}
|
||||
|
||||
sysfs_put(sd);
|
||||
return -EEXIST;
|
||||
*p_sd = sd;
|
||||
return 0;
|
||||
}
|
||||
|
||||
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,
|
|||
sysfs_link_sibling(sd);
|
||||
}
|
||||
|
||||
if (sysfs_addrm_finish(&acxt))
|
||||
return 0;
|
||||
if (!sysfs_addrm_finish(&acxt)) {
|
||||
sysfs_put(sd);
|
||||
return -EEXIST;
|
||||
}
|
||||
|
||||
sysfs_put(sd);
|
||||
return -EEXIST;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
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_mapping->a_ops = &sysfs_aops;
|
||||
|
|
|
@ -43,19 +43,19 @@ static int sysfs_fill_super(struct super_block *sb, void *data, int silent)
|
|||
sb->s_time_gran = 1;
|
||||
sysfs_sb = sb;
|
||||
|
||||
inode = new_inode(sysfs_sb);
|
||||
/* get root inode, initialize and unlock it */
|
||||
inode = sysfs_get_inode(&sysfs_root);
|
||||
if (!inode) {
|
||||
pr_debug("sysfs: could not get root inode\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
sysfs_init_inode(&sysfs_root, inode);
|
||||
|
||||
inode->i_op = &sysfs_dir_inode_operations;
|
||||
inode->i_fop = &sysfs_dir_operations;
|
||||
/* directory inodes start off with i_nlink == 2 (for "." entry) */
|
||||
inc_nlink(inode);
|
||||
inc_nlink(inode); /* directory, account for "." */
|
||||
unlock_new_inode(inode);
|
||||
|
||||
/* instantiate and link root dentry */
|
||||
root = d_alloc_root(inode);
|
||||
if (!root) {
|
||||
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
|
|||
sd = sysfs_new_dirent(name, S_IFLNK|S_IRWXUGO, SYSFS_KOBJ_LINK);
|
||||
if (!sd)
|
||||
goto out_put;
|
||||
|
||||
sd->s_elem.symlink.target_sd = target_sd;
|
||||
target_sd = NULL; /* reference is now owned by the symlink */
|
||||
|
||||
sysfs_addrm_start(&acxt, parent_sd);
|
||||
|
||||
|
@ -95,11 +97,13 @@ int sysfs_create_link(struct kobject * kobj, struct kobject * target, const char
|
|||
sysfs_link_sibling(sd);
|
||||
}
|
||||
|
||||
if (sysfs_addrm_finish(&acxt))
|
||||
return 0;
|
||||
if (!sysfs_addrm_finish(&acxt)) {
|
||||
error = -EEXIST;
|
||||
goto out_put;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
error = -EEXIST;
|
||||
/* fall through */
|
||||
out_put:
|
||||
sysfs_put(target_sd);
|
||||
sysfs_put(sd);
|
||||
|
|
|
@ -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 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 void sysfs_instantiate(struct dentry *dentry, struct inode *inode);
|
||||
|
||||
|
|
|
@ -572,6 +572,16 @@ dev_dbg(struct device * dev, const char * fmt, ...)
|
|||
}
|
||||
#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...) \
|
||||
dev_printk(KERN_ERR , dev , format , ## arg)
|
||||
#define dev_info(dev, format, arg...) \
|
||||
|
|
|
@ -36,15 +36,24 @@ extern char uevent_helper[];
|
|||
/* counter to tag the uevent, read only except for the kobject core */
|
||||
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 {
|
||||
KOBJ_ADD = (__force kobject_action_t) 0x01, /* exclusive to core */
|
||||
KOBJ_REMOVE = (__force kobject_action_t) 0x02, /* exclusive to core */
|
||||
KOBJ_CHANGE = (__force kobject_action_t) 0x03, /* device state change */
|
||||
KOBJ_OFFLINE = (__force kobject_action_t) 0x04, /* device offline */
|
||||
KOBJ_ONLINE = (__force kobject_action_t) 0x05, /* device online */
|
||||
KOBJ_MOVE = (__force kobject_action_t) 0x06, /* device move */
|
||||
KOBJ_ADD,
|
||||
KOBJ_REMOVE,
|
||||
KOBJ_CHANGE,
|
||||
KOBJ_MOVE,
|
||||
KOBJ_ONLINE,
|
||||
KOBJ_OFFLINE,
|
||||
KOBJ_MAX
|
||||
};
|
||||
|
||||
struct kobject {
|
||||
|
|
|
@ -284,8 +284,6 @@ extern int device_prepare_suspend(pm_message_t state);
|
|||
#define device_may_wakeup(dev) \
|
||||
(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);
|
||||
|
||||
#define suspend_report_result(fn, ret) \
|
||||
|
@ -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_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)
|
||||
|
||||
static inline int call_platform_enable_wakeup(struct device *dev, int is_on)
|
||||
|
|
|
@ -65,18 +65,6 @@ config PM_TRACE
|
|||
CAUTION: this option will cause your machine's real-time clock to be
|
||||
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
|
||||
bool "Software Suspend (Hibernation)"
|
||||
depends on PM && SWAP && (((X86 || PPC64_SWSUSP) && (!SMP || SUSPEND_SMP)) || ((FRV || PPC32) && !SMP))
|
||||
|
|
|
@ -33,25 +33,15 @@ static DEFINE_SPINLOCK(sequence_lock);
|
|||
static struct sock *uevent_sock;
|
||||
#endif
|
||||
|
||||
static char *action_to_string(enum kobject_action action)
|
||||
{
|
||||
switch (action) {
|
||||
case KOBJ_ADD:
|
||||
return "add";
|
||||
case KOBJ_REMOVE:
|
||||
return "remove";
|
||||
case KOBJ_CHANGE:
|
||||
return "change";
|
||||
case KOBJ_OFFLINE:
|
||||
return "offline";
|
||||
case KOBJ_ONLINE:
|
||||
return "online";
|
||||
case KOBJ_MOVE:
|
||||
return "move";
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
/* the strings here must match the enum in include/linux/kobject.h */
|
||||
const char *kobject_actions[] = {
|
||||
"add",
|
||||
"remove",
|
||||
"change",
|
||||
"move",
|
||||
"online",
|
||||
"offline",
|
||||
};
|
||||
|
||||
/**
|
||||
* kobject_uevent_env - send an uevent with environmental data
|
||||
|
@ -83,7 +73,7 @@ int kobject_uevent_env(struct kobject *kobj, enum kobject_action action,
|
|||
|
||||
pr_debug("%s\n", __FUNCTION__);
|
||||
|
||||
action_string = action_to_string(action);
|
||||
action_string = kobject_actions[action];
|
||||
if (!action_string) {
|
||||
pr_debug("kobject attempted to send uevent without action_string!\n");
|
||||
return -EINVAL;
|
||||
|
|
Loading…
Reference in a new issue