You've already forked linux-apfs
mirror of
https://github.com/linux-apfs/linux-apfs.git
synced 2026-05-01 15:00:59 -07:00
Merge master.kernel.org:/pub/scm/linux/kernel/git/gregkh/driver-2.6
This commit is contained in:
@@ -65,7 +65,7 @@ o isdn4k-utils 3.1pre1 # isdnctrl 2>&1|grep version
|
||||
o nfs-utils 1.0.5 # showmount --version
|
||||
o procps 3.2.0 # ps --version
|
||||
o oprofile 0.9 # oprofiled --version
|
||||
o udev 058 # udevinfo -V
|
||||
o udev 071 # udevinfo -V
|
||||
|
||||
Kernel compilation
|
||||
==================
|
||||
|
||||
@@ -345,8 +345,7 @@ if (!retval) {
|
||||
<programlisting>
|
||||
static inline void skel_delete (struct usb_skel *dev)
|
||||
{
|
||||
if (dev->bulk_in_buffer != NULL)
|
||||
kfree (dev->bulk_in_buffer);
|
||||
kfree (dev->bulk_in_buffer);
|
||||
if (dev->bulk_out_buffer != NULL)
|
||||
usb_buffer_free (dev->udev, dev->bulk_out_size,
|
||||
dev->bulk_out_buffer,
|
||||
|
||||
@@ -14,8 +14,8 @@ struct device_driver {
|
||||
int (*probe) (struct device * dev);
|
||||
int (*remove) (struct device * dev);
|
||||
|
||||
int (*suspend) (struct device * dev, pm_message_t state, u32 level);
|
||||
int (*resume) (struct device * dev, u32 level);
|
||||
int (*suspend) (struct device * dev, pm_message_t state);
|
||||
int (*resume) (struct device * dev);
|
||||
};
|
||||
|
||||
|
||||
@@ -194,69 +194,13 @@ device; i.e. anything in the device's driver_data field.
|
||||
If the device is still present, it should quiesce the device and place
|
||||
it into a supported low-power state.
|
||||
|
||||
int (*suspend) (struct device * dev, pm_message_t state, u32 level);
|
||||
int (*suspend) (struct device * dev, pm_message_t state);
|
||||
|
||||
suspend is called to put the device in a low power state. There are
|
||||
several stages to successfully suspending a device, which is denoted in
|
||||
the @level parameter. Breaking the suspend transition into several
|
||||
stages affords the platform flexibility in performing device power
|
||||
management based on the requirements of the system and the
|
||||
user-defined policy.
|
||||
suspend is called to put the device in a low power state.
|
||||
|
||||
SUSPEND_NOTIFY notifies the device that a suspend transition is about
|
||||
to happen. This happens on system power state transitions to verify
|
||||
that all devices can successfully suspend.
|
||||
int (*resume) (struct device * dev);
|
||||
|
||||
A driver may choose to fail on this call, which should cause the
|
||||
entire suspend transition to fail. A driver should fail only if it
|
||||
knows that the device will not be able to be resumed properly when the
|
||||
system wakes up again. It could also fail if it somehow determines it
|
||||
is in the middle of an operation too important to stop.
|
||||
|
||||
SUSPEND_DISABLE tells the device to stop I/O transactions. When it
|
||||
stops transactions, or what it should do with unfinished transactions
|
||||
is a policy of the driver. After this call, the driver should not
|
||||
accept any other I/O requests.
|
||||
|
||||
SUSPEND_SAVE_STATE tells the device to save the context of the
|
||||
hardware. This includes any bus-specific hardware state and
|
||||
device-specific hardware state. A pointer to this saved state can be
|
||||
stored in the device's saved_state field.
|
||||
|
||||
SUSPEND_POWER_DOWN tells the driver to place the device in the low
|
||||
power state requested.
|
||||
|
||||
Whether suspend is called with a given level is a policy of the
|
||||
platform. Some levels may be omitted; drivers must not assume the
|
||||
reception of any level. However, all levels must be called in the
|
||||
order above; i.e. notification will always come before disabling;
|
||||
disabling the device will come before suspending the device.
|
||||
|
||||
All calls are made with interrupts enabled, except for the
|
||||
SUSPEND_POWER_DOWN level.
|
||||
|
||||
int (*resume) (struct device * dev, u32 level);
|
||||
|
||||
Resume is used to bring a device back from a low power state. Like the
|
||||
suspend transition, it happens in several stages.
|
||||
|
||||
RESUME_POWER_ON tells the driver to set the power state to the state
|
||||
before the suspend call (The device could have already been in a low
|
||||
power state before the suspend call to put in a lower power state).
|
||||
|
||||
RESUME_RESTORE_STATE tells the driver to restore the state saved by
|
||||
the SUSPEND_SAVE_STATE suspend call.
|
||||
|
||||
RESUME_ENABLE tells the driver to start accepting I/O transactions
|
||||
again. Depending on driver policy, the device may already have pending
|
||||
I/O requests.
|
||||
|
||||
RESUME_POWER_ON is called with interrupts disabled. The other resume
|
||||
levels are called with interrupts enabled.
|
||||
|
||||
As with the various suspend stages, the driver must not assume that
|
||||
any other resume calls have been or will be made. Each call should be
|
||||
self-contained and not dependent on any external state.
|
||||
Resume is used to bring a device back from a low power state.
|
||||
|
||||
|
||||
Attributes
|
||||
|
||||
@@ -350,7 +350,7 @@ When a driver is registered, the bus's list of devices is iterated
|
||||
over. bus->match() is called for each device that is not already
|
||||
claimed by a driver.
|
||||
|
||||
When a device is successfully bound to a device, device->driver is
|
||||
When a device is successfully bound to a driver, device->driver is
|
||||
set, the device is added to a per-driver list of devices, and a
|
||||
symlink is created in the driver's sysfs directory that points to the
|
||||
device's physical directory:
|
||||
|
||||
@@ -550,15 +550,12 @@ struct locomo_save_data {
|
||||
u16 LCM_SPIMD;
|
||||
};
|
||||
|
||||
static int locomo_suspend(struct device *dev, pm_message_t state, u32 level)
|
||||
static int locomo_suspend(struct device *dev, pm_message_t state)
|
||||
{
|
||||
struct locomo *lchip = dev_get_drvdata(dev);
|
||||
struct locomo_save_data *save;
|
||||
unsigned long flags;
|
||||
|
||||
if (level != SUSPEND_DISABLE)
|
||||
return 0;
|
||||
|
||||
save = kmalloc(sizeof(struct locomo_save_data), GFP_KERNEL);
|
||||
if (!save)
|
||||
return -ENOMEM;
|
||||
@@ -597,16 +594,13 @@ static int locomo_suspend(struct device *dev, pm_message_t state, u32 level)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int locomo_resume(struct device *dev, u32 level)
|
||||
static int locomo_resume(struct device *dev)
|
||||
{
|
||||
struct locomo *lchip = dev_get_drvdata(dev);
|
||||
struct locomo_save_data *save;
|
||||
unsigned long r;
|
||||
unsigned long flags;
|
||||
|
||||
if (level != RESUME_ENABLE)
|
||||
return 0;
|
||||
|
||||
save = (struct locomo_save_data *) dev->power.saved_state;
|
||||
if (!save)
|
||||
return 0;
|
||||
|
||||
@@ -801,7 +801,7 @@ struct sa1111_save_data {
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
|
||||
static int sa1111_suspend(struct device *dev, pm_message_t state, u32 level)
|
||||
static int sa1111_suspend(struct device *dev, pm_message_t state)
|
||||
{
|
||||
struct sa1111 *sachip = dev_get_drvdata(dev);
|
||||
struct sa1111_save_data *save;
|
||||
@@ -809,9 +809,6 @@ static int sa1111_suspend(struct device *dev, pm_message_t state, u32 level)
|
||||
unsigned int val;
|
||||
void __iomem *base;
|
||||
|
||||
if (level != SUSPEND_DISABLE)
|
||||
return 0;
|
||||
|
||||
save = kmalloc(sizeof(struct sa1111_save_data), GFP_KERNEL);
|
||||
if (!save)
|
||||
return -ENOMEM;
|
||||
@@ -856,23 +853,19 @@ static int sa1111_suspend(struct device *dev, pm_message_t state, u32 level)
|
||||
/*
|
||||
* sa1111_resume - Restore the SA1111 device state.
|
||||
* @dev: device to restore
|
||||
* @level: resume level
|
||||
*
|
||||
* Restore the general state of the SA1111; clock control and
|
||||
* interrupt controller. Other parts of the SA1111 must be
|
||||
* restored by their respective drivers, and must be called
|
||||
* via LDM after this function.
|
||||
*/
|
||||
static int sa1111_resume(struct device *dev, u32 level)
|
||||
static int sa1111_resume(struct device *dev)
|
||||
{
|
||||
struct sa1111 *sachip = dev_get_drvdata(dev);
|
||||
struct sa1111_save_data *save;
|
||||
unsigned long flags, id;
|
||||
void __iomem *base;
|
||||
|
||||
if (level != RESUME_ENABLE)
|
||||
return 0;
|
||||
|
||||
save = (struct sa1111_save_data *)dev->power.saved_state;
|
||||
if (!save)
|
||||
return 0;
|
||||
|
||||
+11
-13
@@ -102,26 +102,24 @@ static void check_scoop_reg(struct scoop_dev *sdev)
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
static int scoop_suspend(struct device *dev, pm_message_t state, uint32_t level)
|
||||
static int scoop_suspend(struct device *dev, pm_message_t state)
|
||||
{
|
||||
if (level == SUSPEND_POWER_DOWN) {
|
||||
struct scoop_dev *sdev = dev_get_drvdata(dev);
|
||||
struct scoop_dev *sdev = dev_get_drvdata(dev);
|
||||
|
||||
check_scoop_reg(sdev);
|
||||
sdev->scoop_gpwr = SCOOP_REG(sdev->base, SCOOP_GPWR);
|
||||
SCOOP_REG(sdev->base, SCOOP_GPWR) = (sdev->scoop_gpwr & ~sdev->suspend_clr) | sdev->suspend_set;
|
||||
|
||||
check_scoop_reg(sdev);
|
||||
sdev->scoop_gpwr = SCOOP_REG(sdev->base, SCOOP_GPWR);
|
||||
SCOOP_REG(sdev->base, SCOOP_GPWR) = (sdev->scoop_gpwr & ~sdev->suspend_clr) | sdev->suspend_set;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int scoop_resume(struct device *dev, uint32_t level)
|
||||
static int scoop_resume(struct device *dev)
|
||||
{
|
||||
if (level == RESUME_POWER_ON) {
|
||||
struct scoop_dev *sdev = dev_get_drvdata(dev);
|
||||
struct scoop_dev *sdev = dev_get_drvdata(dev);
|
||||
|
||||
check_scoop_reg(sdev);
|
||||
SCOOP_REG(sdev->base,SCOOP_GPWR) = sdev->scoop_gpwr;
|
||||
|
||||
check_scoop_reg(sdev);
|
||||
SCOOP_REG(sdev->base,SCOOP_GPWR) = sdev->scoop_gpwr;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
|
||||
@@ -222,24 +222,22 @@ static int corgi_ssp_remove(struct device *dev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int corgi_ssp_suspend(struct device *dev, pm_message_t state, u32 level)
|
||||
static int corgi_ssp_suspend(struct device *dev, pm_message_t state)
|
||||
{
|
||||
if (level == SUSPEND_POWER_DOWN) {
|
||||
ssp_flush(&corgi_ssp_dev);
|
||||
ssp_save_state(&corgi_ssp_dev,&corgi_ssp_state);
|
||||
}
|
||||
ssp_flush(&corgi_ssp_dev);
|
||||
ssp_save_state(&corgi_ssp_dev,&corgi_ssp_state);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int corgi_ssp_resume(struct device *dev, u32 level)
|
||||
static int corgi_ssp_resume(struct device *dev)
|
||||
{
|
||||
if (level == RESUME_POWER_ON) {
|
||||
GPSR(ssp_machinfo->cs_lcdcon) = GPIO_bit(ssp_machinfo->cs_lcdcon); /* High - Disable LCD Control/Timing Gen */
|
||||
GPSR(ssp_machinfo->cs_max1111) = GPIO_bit(ssp_machinfo->cs_max1111); /* High - Disable MAX1111*/
|
||||
GPSR(ssp_machinfo->cs_ads7846) = GPIO_bit(ssp_machinfo->cs_ads7846); /* High - Disable ADS7846*/
|
||||
ssp_restore_state(&corgi_ssp_dev,&corgi_ssp_state);
|
||||
ssp_enable(&corgi_ssp_dev);
|
||||
}
|
||||
GPSR(ssp_machinfo->cs_lcdcon) = GPIO_bit(ssp_machinfo->cs_lcdcon); /* High - Disable LCD Control/Timing Gen */
|
||||
GPSR(ssp_machinfo->cs_max1111) = GPIO_bit(ssp_machinfo->cs_max1111); /* High - Disable MAX1111*/
|
||||
GPSR(ssp_machinfo->cs_ads7846) = GPIO_bit(ssp_machinfo->cs_ads7846); /* High - Disable ADS7846*/
|
||||
ssp_restore_state(&corgi_ssp_dev,&corgi_ssp_state);
|
||||
ssp_enable(&corgi_ssp_dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -178,33 +178,27 @@ static int neponset_probe(struct device *dev)
|
||||
/*
|
||||
* LDM power management.
|
||||
*/
|
||||
static int neponset_suspend(struct device *dev, pm_message_t state, u32 level)
|
||||
static int neponset_suspend(struct device *dev, pm_message_t state)
|
||||
{
|
||||
/*
|
||||
* Save state.
|
||||
*/
|
||||
if (level == SUSPEND_SAVE_STATE ||
|
||||
level == SUSPEND_DISABLE ||
|
||||
level == SUSPEND_POWER_DOWN) {
|
||||
if (!dev->power.saved_state)
|
||||
dev->power.saved_state = kmalloc(sizeof(unsigned int), GFP_KERNEL);
|
||||
if (!dev->power.saved_state)
|
||||
return -ENOMEM;
|
||||
if (!dev->power.saved_state)
|
||||
dev->power.saved_state = kmalloc(sizeof(unsigned int), GFP_KERNEL);
|
||||
if (!dev->power.saved_state)
|
||||
return -ENOMEM;
|
||||
|
||||
*(unsigned int *)dev->power.saved_state = NCR_0;
|
||||
}
|
||||
*(unsigned int *)dev->power.saved_state = NCR_0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int neponset_resume(struct device *dev, u32 level)
|
||||
static int neponset_resume(struct device *dev)
|
||||
{
|
||||
if (level == RESUME_RESTORE_STATE || level == RESUME_ENABLE) {
|
||||
if (dev->power.saved_state) {
|
||||
NCR_0 = *(unsigned int *)dev->power.saved_state;
|
||||
kfree(dev->power.saved_state);
|
||||
dev->power.saved_state = NULL;
|
||||
}
|
||||
if (dev->power.saved_state) {
|
||||
NCR_0 = *(unsigned int *)dev->power.saved_state;
|
||||
kfree(dev->power.saved_state);
|
||||
dev->power.saved_state = NULL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -163,7 +163,7 @@ static int cpuid_class_device_create(int i)
|
||||
int err = 0;
|
||||
struct class_device *class_err;
|
||||
|
||||
class_err = class_device_create(cpuid_class, MKDEV(CPUID_MAJOR, i), NULL, "cpu%d",i);
|
||||
class_err = class_device_create(cpuid_class, NULL, MKDEV(CPUID_MAJOR, i), NULL, "cpu%d",i);
|
||||
if (IS_ERR(class_err))
|
||||
err = PTR_ERR(class_err);
|
||||
return err;
|
||||
|
||||
@@ -246,7 +246,7 @@ static int msr_class_device_create(int i)
|
||||
int err = 0;
|
||||
struct class_device *class_err;
|
||||
|
||||
class_err = class_device_create(msr_class, MKDEV(MSR_MAJOR, i), NULL, "msr%d",i);
|
||||
class_err = class_device_create(msr_class, NULL, MKDEV(MSR_MAJOR, i), NULL, "msr%d",i);
|
||||
if (IS_ERR(class_err))
|
||||
err = PTR_ERR(class_err);
|
||||
return err;
|
||||
|
||||
@@ -19,6 +19,8 @@
|
||||
#include <linux/list.h>
|
||||
#include <linux/module.h>
|
||||
|
||||
#include "base.h"
|
||||
|
||||
/* This is a private structure used to tie the classdev and the
|
||||
* container .. it should never be visible outside this file */
|
||||
struct internal_container {
|
||||
|
||||
@@ -1,3 +1,15 @@
|
||||
|
||||
/* initialisation functions */
|
||||
|
||||
extern int devices_init(void);
|
||||
extern int buses_init(void);
|
||||
extern int classes_init(void);
|
||||
extern int firmware_init(void);
|
||||
extern int platform_bus_init(void);
|
||||
extern int system_bus_init(void);
|
||||
extern int cpu_dev_init(void);
|
||||
extern int attribute_container_init(void);
|
||||
|
||||
extern int bus_add_device(struct device * dev);
|
||||
extern void bus_remove_device(struct device * dev);
|
||||
|
||||
|
||||
+102
-52
@@ -99,7 +99,8 @@ struct class * class_get(struct class * cls)
|
||||
|
||||
void class_put(struct class * cls)
|
||||
{
|
||||
subsys_put(&cls->subsys);
|
||||
if (cls)
|
||||
subsys_put(&cls->subsys);
|
||||
}
|
||||
|
||||
|
||||
@@ -165,14 +166,25 @@ void class_unregister(struct class * cls)
|
||||
|
||||
static void class_create_release(struct class *cls)
|
||||
{
|
||||
pr_debug("%s called for %s\n", __FUNCTION__, cls->name);
|
||||
kfree(cls);
|
||||
}
|
||||
|
||||
static void class_device_create_release(struct class_device *class_dev)
|
||||
{
|
||||
pr_debug("%s called for %s\n", __FUNCTION__, class_dev->class_id);
|
||||
kfree(class_dev);
|
||||
}
|
||||
|
||||
/* needed to allow these devices to have parent class devices */
|
||||
static int class_device_create_hotplug(struct class_device *class_dev,
|
||||
char **envp, int num_envp,
|
||||
char *buffer, int buffer_size)
|
||||
{
|
||||
pr_debug("%s called for %s\n", __FUNCTION__, class_dev->class_id);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* class_create - create a struct class structure
|
||||
* @owner: pointer to the module that is to "own" this struct class
|
||||
@@ -301,10 +313,12 @@ static void class_dev_release(struct kobject * kobj)
|
||||
kfree(cd->devt_attr);
|
||||
cd->devt_attr = NULL;
|
||||
|
||||
if (cls->release)
|
||||
if (cd->release)
|
||||
cd->release(cd);
|
||||
else if (cls->release)
|
||||
cls->release(cd);
|
||||
else {
|
||||
printk(KERN_ERR "Device class '%s' does not have a release() function, "
|
||||
printk(KERN_ERR "Class Device '%s' does not have a release() function, "
|
||||
"it is broken and must be fixed.\n",
|
||||
cd->class_id);
|
||||
WARN_ON(1);
|
||||
@@ -382,14 +396,18 @@ static int class_hotplug(struct kset *kset, struct kobject *kobj, char **envp,
|
||||
buffer = &buffer[length];
|
||||
buffer_size -= length;
|
||||
|
||||
if (class_dev->class->hotplug) {
|
||||
/* have the bus specific function add its stuff */
|
||||
retval = class_dev->class->hotplug (class_dev, envp, num_envp,
|
||||
buffer, buffer_size);
|
||||
if (retval) {
|
||||
pr_debug ("%s - hotplug() returned %d\n",
|
||||
__FUNCTION__, retval);
|
||||
}
|
||||
if (class_dev->hotplug) {
|
||||
/* have the class device specific function add its stuff */
|
||||
retval = class_dev->hotplug(class_dev, envp, num_envp,
|
||||
buffer, buffer_size);
|
||||
if (retval)
|
||||
pr_debug("class_dev->hotplug() returned %d\n", retval);
|
||||
} else if (class_dev->class->hotplug) {
|
||||
/* have the class specific function add its stuff */
|
||||
retval = class_dev->class->hotplug(class_dev, envp, num_envp,
|
||||
buffer, buffer_size);
|
||||
if (retval)
|
||||
pr_debug("class->hotplug() returned %d\n", retval);
|
||||
}
|
||||
|
||||
return retval;
|
||||
@@ -442,6 +460,13 @@ static ssize_t show_dev(struct class_device *class_dev, char *buf)
|
||||
return print_dev_t(buf, class_dev->devt);
|
||||
}
|
||||
|
||||
static ssize_t store_uevent(struct class_device *class_dev,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
kobject_hotplug(&class_dev->kobj, KOBJ_ADD);
|
||||
return count;
|
||||
}
|
||||
|
||||
void class_device_initialize(struct class_device *class_dev)
|
||||
{
|
||||
kobj_set_kset_s(class_dev, class_obj_subsys);
|
||||
@@ -469,34 +494,45 @@ static char *make_class_name(struct class_device *class_dev)
|
||||
|
||||
int class_device_add(struct class_device *class_dev)
|
||||
{
|
||||
struct class * parent = NULL;
|
||||
struct class_interface * class_intf;
|
||||
struct class *parent_class = NULL;
|
||||
struct class_device *parent_class_dev = NULL;
|
||||
struct class_interface *class_intf;
|
||||
char *class_name = NULL;
|
||||
int error;
|
||||
int error = -EINVAL;
|
||||
|
||||
class_dev = class_device_get(class_dev);
|
||||
if (!class_dev)
|
||||
return -EINVAL;
|
||||
|
||||
if (!strlen(class_dev->class_id)) {
|
||||
error = -EINVAL;
|
||||
if (!strlen(class_dev->class_id))
|
||||
goto register_done;
|
||||
}
|
||||
|
||||
parent = class_get(class_dev->class);
|
||||
parent_class = class_get(class_dev->class);
|
||||
if (!parent_class)
|
||||
goto register_done;
|
||||
parent_class_dev = class_device_get(class_dev->parent);
|
||||
|
||||
pr_debug("CLASS: registering class device: ID = '%s'\n",
|
||||
class_dev->class_id);
|
||||
|
||||
/* first, register with generic layer. */
|
||||
kobject_set_name(&class_dev->kobj, "%s", class_dev->class_id);
|
||||
if (parent)
|
||||
class_dev->kobj.parent = &parent->subsys.kset.kobj;
|
||||
if (parent_class_dev)
|
||||
class_dev->kobj.parent = &parent_class_dev->kobj;
|
||||
else
|
||||
class_dev->kobj.parent = &parent_class->subsys.kset.kobj;
|
||||
|
||||
if ((error = kobject_add(&class_dev->kobj)))
|
||||
error = kobject_add(&class_dev->kobj);
|
||||
if (error)
|
||||
goto register_done;
|
||||
|
||||
/* add the needed attributes to this device */
|
||||
class_dev->uevent_attr.attr.name = "uevent";
|
||||
class_dev->uevent_attr.attr.mode = S_IWUSR;
|
||||
class_dev->uevent_attr.attr.owner = parent_class->owner;
|
||||
class_dev->uevent_attr.store = store_uevent;
|
||||
class_device_create_file(class_dev, &class_dev->uevent_attr);
|
||||
|
||||
if (MAJOR(class_dev->devt)) {
|
||||
struct class_device_attribute *attr;
|
||||
attr = kzalloc(sizeof(*attr), GFP_KERNEL);
|
||||
@@ -505,12 +541,10 @@ int class_device_add(struct class_device *class_dev)
|
||||
kobject_del(&class_dev->kobj);
|
||||
goto register_done;
|
||||
}
|
||||
|
||||
attr->attr.name = "dev";
|
||||
attr->attr.mode = S_IRUGO;
|
||||
attr->attr.owner = parent->owner;
|
||||
attr->attr.owner = parent_class->owner;
|
||||
attr->show = show_dev;
|
||||
attr->store = NULL;
|
||||
class_device_create_file(class_dev, attr);
|
||||
class_dev->devt_attr = attr;
|
||||
}
|
||||
@@ -524,20 +558,23 @@ int class_device_add(struct class_device *class_dev)
|
||||
class_name);
|
||||
}
|
||||
|
||||
/* notify any interfaces this device is now here */
|
||||
if (parent) {
|
||||
down(&parent->sem);
|
||||
list_add_tail(&class_dev->node, &parent->children);
|
||||
list_for_each_entry(class_intf, &parent->interfaces, node)
|
||||
if (class_intf->add)
|
||||
class_intf->add(class_dev);
|
||||
up(&parent->sem);
|
||||
}
|
||||
kobject_hotplug(&class_dev->kobj, KOBJ_ADD);
|
||||
|
||||
/* notify any interfaces this device is now here */
|
||||
if (parent_class) {
|
||||
down(&parent_class->sem);
|
||||
list_add_tail(&class_dev->node, &parent_class->children);
|
||||
list_for_each_entry(class_intf, &parent_class->interfaces, node)
|
||||
if (class_intf->add)
|
||||
class_intf->add(class_dev, class_intf);
|
||||
up(&parent_class->sem);
|
||||
}
|
||||
|
||||
register_done:
|
||||
if (error && parent)
|
||||
class_put(parent);
|
||||
if (error) {
|
||||
class_put(parent_class);
|
||||
class_device_put(parent_class_dev);
|
||||
}
|
||||
class_device_put(class_dev);
|
||||
kfree(class_name);
|
||||
return error;
|
||||
@@ -552,21 +589,28 @@ int class_device_register(struct class_device *class_dev)
|
||||
/**
|
||||
* class_device_create - creates a class device and registers it with sysfs
|
||||
* @cs: pointer to the struct class that this device should be registered to.
|
||||
* @parent: pointer to the parent struct class_device of this new device, if any.
|
||||
* @dev: the dev_t for the char device to be added.
|
||||
* @device: a pointer to a struct device that is assiociated with this class device.
|
||||
* @fmt: string for the class device's name
|
||||
*
|
||||
* This function can be used by char device classes. A struct
|
||||
* class_device will be created in sysfs, registered to the specified
|
||||
* class. A "dev" file will be created, showing the dev_t for the
|
||||
* device. The pointer to the struct class_device will be returned from
|
||||
* the call. Any further sysfs files that might be required can be
|
||||
* created using this pointer.
|
||||
* class.
|
||||
* A "dev" file will be created, showing the dev_t for the device, if
|
||||
* the dev_t is not 0,0.
|
||||
* If a pointer to a parent struct class_device is passed in, the newly
|
||||
* created struct class_device will be a child of that device in sysfs.
|
||||
* The pointer to the struct class_device will be returned from the
|
||||
* call. Any further sysfs files that might be required can be created
|
||||
* using this pointer.
|
||||
*
|
||||
* Note: the struct class passed to this function must have previously
|
||||
* been created with a call to class_create().
|
||||
*/
|
||||
struct class_device *class_device_create(struct class *cls, dev_t devt,
|
||||
struct class_device *class_device_create(struct class *cls,
|
||||
struct class_device *parent,
|
||||
dev_t devt,
|
||||
struct device *device, char *fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
@@ -585,6 +629,9 @@ struct class_device *class_device_create(struct class *cls, dev_t devt,
|
||||
class_dev->devt = devt;
|
||||
class_dev->dev = device;
|
||||
class_dev->class = cls;
|
||||
class_dev->parent = parent;
|
||||
class_dev->release = class_device_create_release;
|
||||
class_dev->hotplug = class_device_create_hotplug;
|
||||
|
||||
va_start(args, fmt);
|
||||
vsnprintf(class_dev->class_id, BUS_ID_SIZE, fmt, args);
|
||||
@@ -602,17 +649,18 @@ error:
|
||||
|
||||
void class_device_del(struct class_device *class_dev)
|
||||
{
|
||||
struct class * parent = class_dev->class;
|
||||
struct class_interface * class_intf;
|
||||
struct class *parent_class = class_dev->class;
|
||||
struct class_device *parent_device = class_dev->parent;
|
||||
struct class_interface *class_intf;
|
||||
char *class_name = NULL;
|
||||
|
||||
if (parent) {
|
||||
down(&parent->sem);
|
||||
if (parent_class) {
|
||||
down(&parent_class->sem);
|
||||
list_del_init(&class_dev->node);
|
||||
list_for_each_entry(class_intf, &parent->interfaces, node)
|
||||
list_for_each_entry(class_intf, &parent_class->interfaces, node)
|
||||
if (class_intf->remove)
|
||||
class_intf->remove(class_dev);
|
||||
up(&parent->sem);
|
||||
class_intf->remove(class_dev, class_intf);
|
||||
up(&parent_class->sem);
|
||||
}
|
||||
|
||||
if (class_dev->dev) {
|
||||
@@ -620,6 +668,7 @@ void class_device_del(struct class_device *class_dev)
|
||||
sysfs_remove_link(&class_dev->kobj, "device");
|
||||
sysfs_remove_link(&class_dev->dev->kobj, class_name);
|
||||
}
|
||||
class_device_remove_file(class_dev, &class_dev->uevent_attr);
|
||||
if (class_dev->devt_attr)
|
||||
class_device_remove_file(class_dev, class_dev->devt_attr);
|
||||
class_device_remove_attrs(class_dev);
|
||||
@@ -627,8 +676,8 @@ void class_device_del(struct class_device *class_dev)
|
||||
kobject_hotplug(&class_dev->kobj, KOBJ_REMOVE);
|
||||
kobject_del(&class_dev->kobj);
|
||||
|
||||
if (parent)
|
||||
class_put(parent);
|
||||
class_device_put(parent_device);
|
||||
class_put(parent_class);
|
||||
kfree(class_name);
|
||||
}
|
||||
|
||||
@@ -708,7 +757,8 @@ struct class_device * class_device_get(struct class_device *class_dev)
|
||||
|
||||
void class_device_put(struct class_device *class_dev)
|
||||
{
|
||||
kobject_put(&class_dev->kobj);
|
||||
if (class_dev)
|
||||
kobject_put(&class_dev->kobj);
|
||||
}
|
||||
|
||||
|
||||
@@ -728,7 +778,7 @@ int class_interface_register(struct class_interface *class_intf)
|
||||
list_add_tail(&class_intf->node, &parent->interfaces);
|
||||
if (class_intf->add) {
|
||||
list_for_each_entry(class_dev, &parent->children, node)
|
||||
class_intf->add(class_dev);
|
||||
class_intf->add(class_dev, class_intf);
|
||||
}
|
||||
up(&parent->sem);
|
||||
|
||||
@@ -747,7 +797,7 @@ void class_interface_unregister(struct class_interface *class_intf)
|
||||
list_del_init(&class_intf->node);
|
||||
if (class_intf->remove) {
|
||||
list_for_each_entry(class_dev, &parent->children, node)
|
||||
class_intf->remove(class_dev);
|
||||
class_intf->remove(class_dev, class_intf);
|
||||
}
|
||||
up(&parent->sem);
|
||||
|
||||
|
||||
+19
-2
@@ -154,6 +154,13 @@ static struct kset_hotplug_ops device_hotplug_ops = {
|
||||
.hotplug = dev_hotplug,
|
||||
};
|
||||
|
||||
static ssize_t store_uevent(struct device *dev, struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
kobject_hotplug(&dev->kobj, KOBJ_ADD);
|
||||
return count;
|
||||
}
|
||||
|
||||
/**
|
||||
* device_subsys - structure to be registered with kobject core.
|
||||
*/
|
||||
@@ -225,6 +232,7 @@ void device_initialize(struct device *dev)
|
||||
klist_children_put);
|
||||
INIT_LIST_HEAD(&dev->dma_pools);
|
||||
init_MUTEX(&dev->sem);
|
||||
device_init_wakeup(dev, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -258,6 +266,14 @@ int device_add(struct device *dev)
|
||||
|
||||
if ((error = kobject_add(&dev->kobj)))
|
||||
goto Error;
|
||||
|
||||
dev->uevent_attr.attr.name = "uevent";
|
||||
dev->uevent_attr.attr.mode = S_IWUSR;
|
||||
if (dev->driver)
|
||||
dev->uevent_attr.attr.owner = dev->driver->owner;
|
||||
dev->uevent_attr.store = store_uevent;
|
||||
device_create_file(dev, &dev->uevent_attr);
|
||||
|
||||
kobject_hotplug(&dev->kobj, KOBJ_ADD);
|
||||
if ((error = device_pm_add(dev)))
|
||||
goto PMError;
|
||||
@@ -349,6 +365,7 @@ void device_del(struct device * dev)
|
||||
|
||||
if (parent)
|
||||
klist_del(&dev->knode_parent);
|
||||
device_remove_file(dev, &dev->uevent_attr);
|
||||
|
||||
/* Notify the platform of the removal, in case they
|
||||
* need to do anything...
|
||||
@@ -390,11 +407,11 @@ static struct device * next_device(struct klist_iter * i)
|
||||
|
||||
/**
|
||||
* device_for_each_child - device child iterator.
|
||||
* @dev: parent struct device.
|
||||
* @parent: parent struct device.
|
||||
* @data: data for the callback.
|
||||
* @fn: function to be called for each device.
|
||||
*
|
||||
* Iterate over @dev's child devices, and call @fn for each,
|
||||
* Iterate over @parent's child devices, and call @fn for each,
|
||||
* passing it @data.
|
||||
*
|
||||
* We check the return of @fn each time. If it returns anything
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include <linux/topology.h>
|
||||
#include <linux/device.h>
|
||||
|
||||
#include "base.h"
|
||||
|
||||
struct sysdev_class cpu_sysdev_class = {
|
||||
set_kset_name("cpu"),
|
||||
|
||||
@@ -28,6 +28,7 @@ static struct device * next_device(struct klist_iter * i)
|
||||
/**
|
||||
* driver_for_each_device - Iterator for devices bound to a driver.
|
||||
* @drv: Driver we're iterating.
|
||||
* @start: Device to begin with
|
||||
* @data: Data to pass to the callback.
|
||||
* @fn: Function to call for each device.
|
||||
*
|
||||
@@ -57,7 +58,7 @@ EXPORT_SYMBOL_GPL(driver_for_each_device);
|
||||
|
||||
/**
|
||||
* driver_find_device - device iterator for locating a particular device.
|
||||
* @driver: The device's driver
|
||||
* @drv: The device's driver
|
||||
* @start: Device to begin with
|
||||
* @data: Data to pass to match function
|
||||
* @match: Callback function to check device
|
||||
|
||||
@@ -11,6 +11,9 @@
|
||||
#include <linux/kobject.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/device.h>
|
||||
|
||||
#include "base.h"
|
||||
|
||||
static decl_subsys(firmware, NULL, NULL);
|
||||
|
||||
|
||||
+2
-8
@@ -10,14 +10,8 @@
|
||||
#include <linux/device.h>
|
||||
#include <linux/init.h>
|
||||
|
||||
extern int devices_init(void);
|
||||
extern int buses_init(void);
|
||||
extern int classes_init(void);
|
||||
extern int firmware_init(void);
|
||||
extern int platform_bus_init(void);
|
||||
extern int system_bus_init(void);
|
||||
extern int cpu_dev_init(void);
|
||||
extern int attribute_container_init(void);
|
||||
#include "base.h"
|
||||
|
||||
/**
|
||||
* driver_init - initialize driver model.
|
||||
*
|
||||
|
||||
+8
-14
@@ -17,6 +17,8 @@
|
||||
#include <linux/bootmem.h>
|
||||
#include <linux/err.h>
|
||||
|
||||
#include "base.h"
|
||||
|
||||
struct device platform_bus = {
|
||||
.bus_id = "platform",
|
||||
};
|
||||
@@ -279,13 +281,9 @@ static int platform_suspend(struct device * dev, pm_message_t state)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
if (dev->driver && dev->driver->suspend) {
|
||||
ret = dev->driver->suspend(dev, state, SUSPEND_DISABLE);
|
||||
if (ret == 0)
|
||||
ret = dev->driver->suspend(dev, state, SUSPEND_SAVE_STATE);
|
||||
if (ret == 0)
|
||||
ret = dev->driver->suspend(dev, state, SUSPEND_POWER_DOWN);
|
||||
}
|
||||
if (dev->driver && dev->driver->suspend)
|
||||
ret = dev->driver->suspend(dev, state);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -293,13 +291,9 @@ static int platform_resume(struct device * dev)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
if (dev->driver && dev->driver->resume) {
|
||||
ret = dev->driver->resume(dev, RESUME_POWER_ON);
|
||||
if (ret == 0)
|
||||
ret = dev->driver->resume(dev, RESUME_RESTORE_STATE);
|
||||
if (ret == 0)
|
||||
ret = dev->driver->resume(dev, RESUME_ENABLE);
|
||||
}
|
||||
if (dev->driver && dev->driver->resume)
|
||||
ret = dev->driver->resume(dev);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user