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: (36 commits)
  Driver core: show drivers in /sys/module/
  Documentation/driver-model/platform.txt update/rewrite
  Driver core: platform_driver_probe(), can save codespace
  driver core: Use klist_remove() in device_move()
  driver core: Introduce device_move(): move a device to a new parent.
  Driver core: make drivers/base/core.c:setup_parent() static
  driver core: Introduce device_find_child().
  sysfs: sysfs_write_file() writes zero terminated data
  cpu topology: consider sysfs_create_group return value
  Driver core: Call platform_notify_remove later
  ACPI: Change ACPI to use dev_archdata instead of firmware_data
  Driver core: add dev_archdata to struct device
  Driver core: convert sound core to use struct device
  Driver core: change mem class_devices to be real devices
  Driver core: convert fb code to use struct device
  Driver core: convert firmware code to use struct device
  Driver core: convert mmc code to use struct device
  Driver core: convert ppdev code to use struct device
  Driver core: convert PPP code to use struct device
  Driver core: convert cpuid code to use struct device
  ...
This commit is contained in:
Linus Torvalds 2006-12-01 16:41:07 -08:00
commit 4549df891a
80 changed files with 1411 additions and 600 deletions

View File

@ -1,99 +1,131 @@
Platform Devices and Drivers
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
See <linux/platform_device.h> for the driver model interface to the
platform bus: platform_device, and platform_driver. This pseudo-bus
is used to connect devices on busses with minimal infrastructure,
like those used to integrate peripherals on many system-on-chip
processors, or some "legacy" PC interconnects; as opposed to large
formally specified ones like PCI or USB.
Platform devices
~~~~~~~~~~~~~~~~
Platform devices are devices that typically appear as autonomous
entities in the system. This includes legacy port-based devices and
host bridges to peripheral buses.
host bridges to peripheral buses, and most controllers integrated
into system-on-chip platforms. What they usually have in common
is direct addressing from a CPU bus. Rarely, a platform_device will
be connected through a segment of some other kind of bus; but its
registers will still be directly addressible.
Platform devices are given a name, used in driver binding, and a
list of resources such as addresses and IRQs.
struct platform_device {
const char *name;
u32 id;
struct device dev;
u32 num_resources;
struct resource *resource;
};
Platform drivers
~~~~~~~~~~~~~~~~
Drivers for platform devices are typically very simple and
unstructured. Either the device was present at a particular I/O port
and the driver was loaded, or it was not. There was no possibility
of hotplugging or alternative discovery besides probing at a specific
I/O address and expecting a specific response.
Platform drivers follow the standard driver model convention, where
discovery/enumeration is handled outside the drivers, and drivers
provide probe() and remove() methods. They support power management
and shutdown notifications using the standard conventions.
struct platform_driver {
int (*probe)(struct platform_device *);
int (*remove)(struct platform_device *);
void (*shutdown)(struct platform_device *);
int (*suspend)(struct platform_device *, pm_message_t state);
int (*suspend_late)(struct platform_device *, pm_message_t state);
int (*resume_early)(struct platform_device *);
int (*resume)(struct platform_device *);
struct device_driver driver;
};
Note that probe() should general verify that the specified device hardware
actually exists; sometimes platform setup code can't be sure. The probing
can use device resources, including clocks, and device platform_data.
Platform drivers register themselves the normal way:
int platform_driver_register(struct platform_driver *drv);
Or, in common situations where the device is known not to be hot-pluggable,
the probe() routine can live in an init section to reduce the driver's
runtime memory footprint:
int platform_driver_probe(struct platform_driver *drv,
int (*probe)(struct platform_device *))
Other Architectures, Modern Firmware, and new Platforms
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
These devices are not always at the legacy I/O ports. This is true on
other architectures and on some modern architectures. In most cases,
the drivers are modified to discover the devices at other well-known
ports for the given platform. However, the firmware in these systems
does usually know where exactly these devices reside, and in some
cases, it's the only way of discovering them.
Device Enumeration
~~~~~~~~~~~~~~~~~~
As a rule, platform specific (and often board-specific) setup code wil
register platform devices:
int platform_device_register(struct platform_device *pdev);
int platform_add_devices(struct platform_device **pdevs, int ndev);
The general rule is to register only those devices that actually exist,
but in some cases extra devices might be registered. For example, a kernel
might be configured to work with an external network adapter that might not
be populated on all boards, or likewise to work with an integrated controller
that some boards might not hook up to any peripherals.
In some cases, boot firmware will export tables describing the devices
that are populated on a given board. Without such tables, often the
only way for system setup code to set up the correct devices is to build
a kernel for a specific target board. Such board-specific kernels are
common with embedded and custom systems development.
In many cases, the memory and IRQ resources associated with the platform
device are not enough to let the device's driver work. Board setup code
will often provide additional information using the device's platform_data
field to hold additional information.
Embedded systems frequently need one or more clocks for platform devices,
which are normally kept off until they're actively needed (to save power).
System setup also associates those clocks with the device, so that that
calls to clk_get(&pdev->dev, clock_name) return them as needed.
The Platform Bus
~~~~~~~~~~~~~~~~
A platform bus has been created to deal with these issues. First and
foremost, it groups all the legacy devices under a common bus, and
gives them a common parent if they don't already have one.
Device Naming and Driver Binding
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The platform_device.dev.bus_id is the canonical name for the devices.
It's built from two components:
But, besides the organizational benefits, the platform bus can also
accommodate firmware-based enumeration.
* platform_device.name ... which is also used to for driver matching.
* platform_device.id ... the device instance number, or else "-1"
to indicate there's only one.
Device Discovery
~~~~~~~~~~~~~~~~
The platform bus has no concept of probing for devices. Devices
discovery is left up to either the legacy drivers or the
firmware. These entities are expected to notify the platform of
devices that it discovers via the bus's add() callback:
These are catenated, so name/id "serial"/0 indicates bus_id "serial.0", and
"serial/3" indicates bus_id "serial.3"; both would use the platform_driver
named "serial". While "my_rtc"/-1 would be bus_id "my_rtc" (no instance id)
and use the platform_driver called "my_rtc".
platform_bus.add(parent,bus_id).
Driver binding is performed automatically by the driver core, invoking
driver probe() after finding a match between device and driver. If the
probe() succeeds, the driver and device are bound as usual. There are
three different ways to find such a match:
- Whenever a device is registered, the drivers for that bus are
checked for matches. Platform devices should be registered very
early during system boot.
Bus IDs
~~~~~~~
Bus IDs are the canonical names for the devices. There is no globally
standard addressing mechanism for legacy devices. In the IA-32 world,
we have Pnp IDs to use, as well as the legacy I/O ports. However,
neither tell what the device really is or have any meaning on other
platforms.
- When a driver is registered using platform_driver_register(), all
unbound devices on that bus are checked for matches. Drivers
usually register later during booting, or by module loading.
Since both PnP IDs and the legacy I/O ports (and other standard I/O
ports for specific devices) have a 1:1 mapping, we map the
platform-specific name or identifier to a generic name (at least
within the scope of the kernel).
For example, a serial driver might find a device at I/O 0x3f8. The
ACPI firmware might also discover a device with PnP ID (_HID)
PNP0501. Both correspond to the same device and should be mapped to the
canonical name 'serial'.
The bus_id field should be a concatenation of the canonical name and
the instance of that type of device. For example, the device at I/O
port 0x3f8 should have a bus_id of "serial0". This places the
responsibility of enumerating devices of a particular type up to the
discovery mechanism. But, they are the entity that should know best
(as opposed to the platform bus driver).
Drivers
~~~~~~~
Drivers for platform devices should have a name that is the same as
the canonical name of the devices they support. This allows the
platform bus driver to do simple matching with the basic data
structures to determine if a driver supports a certain device.
For example, a legacy serial driver should have a name of 'serial' and
register itself with the platform bus.
Driver Binding
~~~~~~~~~~~~~~
Legacy drivers assume they are bound to the device once they start up
and probe an I/O port. Divorcing them from this will be a difficult
process. However, that shouldn't prevent us from implementing
firmware-based enumeration.
The firmware should notify the platform bus about devices before the
legacy drivers have had a chance to load. Once the drivers are loaded,
they driver model core will attempt to bind the driver to any
previously-discovered devices. Once that has happened, it will be free
to discover any other devices it pleases.
- Registering a driver using platform_driver_probe() works just like
using platform_driver_register(), except that the the driver won't
be probed later if another device registers. (Which is OK, since
this interface is only for use with non-hotpluggable devices.)

View File

@ -156,14 +156,14 @@ static struct file_operations cpuid_fops = {
.open = cpuid_open,
};
static int cpuid_class_device_create(int i)
static int cpuid_device_create(int i)
{
int err = 0;
struct class_device *class_err;
struct device *dev;
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);
dev = device_create(cpuid_class, NULL, MKDEV(CPUID_MAJOR, i), "cpu%d",i);
if (IS_ERR(dev))
err = PTR_ERR(dev);
return err;
}
@ -174,10 +174,10 @@ static int cpuid_class_cpu_callback(struct notifier_block *nfb, unsigned long ac
switch (action) {
case CPU_ONLINE:
cpuid_class_device_create(cpu);
cpuid_device_create(cpu);
break;
case CPU_DEAD:
class_device_destroy(cpuid_class, MKDEV(CPUID_MAJOR, cpu));
device_destroy(cpuid_class, MKDEV(CPUID_MAJOR, cpu));
break;
}
return NOTIFY_OK;
@ -206,7 +206,7 @@ static int __init cpuid_init(void)
goto out_chrdev;
}
for_each_online_cpu(i) {
err = cpuid_class_device_create(i);
err = cpuid_device_create(i);
if (err != 0)
goto out_class;
}
@ -218,7 +218,7 @@ static int __init cpuid_init(void)
out_class:
i = 0;
for_each_online_cpu(i) {
class_device_destroy(cpuid_class, MKDEV(CPUID_MAJOR, i));
device_destroy(cpuid_class, MKDEV(CPUID_MAJOR, i));
}
class_destroy(cpuid_class);
out_chrdev:
@ -232,7 +232,7 @@ static void __exit cpuid_exit(void)
int cpu = 0;
for_each_online_cpu(cpu)
class_device_destroy(cpuid_class, MKDEV(CPUID_MAJOR, cpu));
device_destroy(cpuid_class, MKDEV(CPUID_MAJOR, cpu));
class_destroy(cpuid_class);
unregister_chrdev(CPUID_MAJOR, "cpu/cpuid");
unregister_hotcpu_notifier(&cpuid_class_cpu_notifier);

View File

@ -239,14 +239,14 @@ static struct file_operations msr_fops = {
.open = msr_open,
};
static int msr_class_device_create(int i)
static int msr_device_create(int i)
{
int err = 0;
struct class_device *class_err;
struct device *dev;
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);
dev = device_create(msr_class, NULL, MKDEV(MSR_MAJOR, i), "msr%d",i);
if (IS_ERR(dev))
err = PTR_ERR(dev);
return err;
}
@ -258,10 +258,10 @@ static int msr_class_cpu_callback(struct notifier_block *nfb,
switch (action) {
case CPU_ONLINE:
msr_class_device_create(cpu);
msr_device_create(cpu);
break;
case CPU_DEAD:
class_device_destroy(msr_class, MKDEV(MSR_MAJOR, cpu));
device_destroy(msr_class, MKDEV(MSR_MAJOR, cpu));
break;
}
return NOTIFY_OK;
@ -290,7 +290,7 @@ static int __init msr_init(void)
goto out_chrdev;
}
for_each_online_cpu(i) {
err = msr_class_device_create(i);
err = msr_device_create(i);
if (err != 0)
goto out_class;
}
@ -302,7 +302,7 @@ static int __init msr_init(void)
out_class:
i = 0;
for_each_online_cpu(i)
class_device_destroy(msr_class, MKDEV(MSR_MAJOR, i));
device_destroy(msr_class, MKDEV(MSR_MAJOR, i));
class_destroy(msr_class);
out_chrdev:
unregister_chrdev(MSR_MAJOR, "cpu/msr");
@ -314,7 +314,7 @@ static void __exit msr_exit(void)
{
int cpu = 0;
for_each_online_cpu(cpu)
class_device_destroy(msr_class, MKDEV(MSR_MAJOR, cpu));
device_destroy(msr_class, MKDEV(MSR_MAJOR, cpu));
class_destroy(msr_class);
unregister_chrdev(MSR_MAJOR, "cpu/msr");
unregister_hotcpu_notifier(&msr_class_cpu_notifier);

View File

@ -267,9 +267,9 @@ static int acpi_bind_one(struct device *dev, acpi_handle handle)
{
acpi_status status;
if (dev->firmware_data) {
if (dev->archdata.acpi_handle) {
printk(KERN_WARNING PREFIX
"Drivers changed 'firmware_data' for %s\n", dev->bus_id);
"Drivers changed 'acpi_handle' for %s\n", dev->bus_id);
return -EINVAL;
}
get_device(dev);
@ -278,25 +278,26 @@ static int acpi_bind_one(struct device *dev, acpi_handle handle)
put_device(dev);
return -EINVAL;
}
dev->firmware_data = handle;
dev->archdata.acpi_handle = handle;
return 0;
}
static int acpi_unbind_one(struct device *dev)
{
if (!dev->firmware_data)
if (!dev->archdata.acpi_handle)
return 0;
if (dev == acpi_get_physical_device(dev->firmware_data)) {
if (dev == acpi_get_physical_device(dev->archdata.acpi_handle)) {
/* acpi_get_physical_device increase refcnt by one */
put_device(dev);
acpi_detach_data(dev->firmware_data, acpi_glue_data_handler);
dev->firmware_data = NULL;
acpi_detach_data(dev->archdata.acpi_handle,
acpi_glue_data_handler);
dev->archdata.acpi_handle = NULL;
/* acpi_bind_one increase refcnt by one */
put_device(dev);
} else {
printk(KERN_ERR PREFIX
"Oops, 'firmware_data' corrupt for %s\n", dev->bus_id);
"Oops, 'acpi_handle' corrupt for %s\n", dev->bus_id);
}
return 0;
}
@ -328,7 +329,8 @@ static int acpi_platform_notify(struct device *dev)
if (!ret) {
struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
acpi_get_name(dev->firmware_data, ACPI_FULL_PATHNAME, &buffer);
acpi_get_name(dev->archdata.acpi_handle,
ACPI_FULL_PATHNAME, &buffer);
DBG("Device %s -> %s\n", dev->bus_id, (char *)buffer.pointer);
kfree(buffer.pointer);
} else

View File

@ -355,6 +355,21 @@ static void device_remove_attrs(struct bus_type * bus, struct device * dev)
}
}
#ifdef CONFIG_SYSFS_DEPRECATED
static int make_deprecated_bus_links(struct device *dev)
{
return sysfs_create_link(&dev->kobj,
&dev->bus->subsys.kset.kobj, "bus");
}
static void remove_deprecated_bus_links(struct device *dev)
{
sysfs_remove_link(&dev->kobj, "bus");
}
#else
static inline int make_deprecated_bus_links(struct device *dev) { return 0; }
static inline void remove_deprecated_bus_links(struct device *dev) { }
#endif
/**
* bus_add_device - add device to bus
@ -381,8 +396,7 @@ int bus_add_device(struct device * dev)
&dev->bus->subsys.kset.kobj, "subsystem");
if (error)
goto out_subsys;
error = sysfs_create_link(&dev->kobj,
&dev->bus->subsys.kset.kobj, "bus");
error = make_deprecated_bus_links(dev);
if (error)
goto out_deprecated;
}
@ -436,7 +450,7 @@ void bus_remove_device(struct device * dev)
{
if (dev->bus) {
sysfs_remove_link(&dev->kobj, "subsystem");
sysfs_remove_link(&dev->kobj, "bus");
remove_deprecated_bus_links(dev);
sysfs_remove_link(&dev->bus->devices.kobj, dev->bus_id);
device_remove_attrs(dev->bus, dev);
if (dev->is_registered) {
@ -724,6 +738,8 @@ int bus_register(struct bus_type * bus)
{
int retval;
BLOCKING_INIT_NOTIFIER_HEAD(&bus->bus_notifier);
retval = kobject_set_name(&bus->subsys.kset.kobj, "%s", bus->name);
if (retval)
goto out;
@ -782,6 +798,18 @@ void bus_unregister(struct bus_type * bus)
subsystem_unregister(&bus->subsys);
}
int bus_register_notifier(struct bus_type *bus, struct notifier_block *nb)
{
return blocking_notifier_chain_register(&bus->bus_notifier, nb);
}
EXPORT_SYMBOL_GPL(bus_register_notifier);
int bus_unregister_notifier(struct bus_type *bus, struct notifier_block *nb)
{
return blocking_notifier_chain_unregister(&bus->bus_notifier, nb);
}
EXPORT_SYMBOL_GPL(bus_unregister_notifier);
int __init buses_init(void)
{
return subsystem_register(&bus_subsys);

View File

@ -352,6 +352,92 @@ static const char *class_uevent_name(struct kset *kset, struct kobject *kobj)
return class_dev->class->name;
}
#ifdef CONFIG_SYSFS_DEPRECATED
char *make_class_name(const char *name, struct kobject *kobj)
{
char *class_name;
int size;
size = strlen(name) + strlen(kobject_name(kobj)) + 2;
class_name = kmalloc(size, GFP_KERNEL);
if (!class_name)
return ERR_PTR(-ENOMEM);
strcpy(class_name, name);
strcat(class_name, ":");
strcat(class_name, kobject_name(kobj));
return class_name;
}
static int deprecated_class_uevent(char **envp, int num_envp, int *cur_index,
char *buffer, int buffer_size,
int *cur_len,
struct class_device *class_dev)
{
struct device *dev = class_dev->dev;
char *path;
if (!dev)
return 0;
/* add device, backing this class device (deprecated) */
path = kobject_get_path(&dev->kobj, GFP_KERNEL);
add_uevent_var(envp, num_envp, cur_index, buffer, buffer_size,
cur_len, "PHYSDEVPATH=%s", path);
kfree(path);
if (dev->bus)
add_uevent_var(envp, num_envp, cur_index,
buffer, buffer_size, cur_len,
"PHYSDEVBUS=%s", dev->bus->name);
if (dev->driver)
add_uevent_var(envp, num_envp, cur_index,
buffer, buffer_size, cur_len,
"PHYSDEVDRIVER=%s", dev->driver->name);
return 0;
}
static int make_deprecated_class_device_links(struct class_device *class_dev)
{
char *class_name;
int error;
if (!class_dev->dev)
return 0;
class_name = make_class_name(class_dev->class->name, &class_dev->kobj);
error = sysfs_create_link(&class_dev->dev->kobj, &class_dev->kobj,
class_name);
kfree(class_name);
return error;
}
static void remove_deprecated_class_device_links(struct class_device *class_dev)
{
char *class_name;
if (!class_dev->dev)
return;
class_name = make_class_name(class_dev->class->name, &class_dev->kobj);
sysfs_remove_link(&class_dev->dev->kobj, class_name);
kfree(class_name);
}
#else
static inline int deprecated_class_uevent(char **envp, int num_envp,
int *cur_index, char *buffer,
int buffer_size, int *cur_len,
struct class_device *class_dev)
{ return 0; }
static inline int make_deprecated_class_device_links(struct class_device *cd)
{ return 0; }
static void remove_deprecated_class_device_links(struct class_device *cd)
{ }
#endif
static int class_uevent(struct kset *kset, struct kobject *kobj, char **envp,
int num_envp, char *buffer, int buffer_size)
{
@ -362,25 +448,8 @@ static int class_uevent(struct kset *kset, struct kobject *kobj, char **envp,
pr_debug("%s - name = %s\n", __FUNCTION__, class_dev->class_id);
if (class_dev->dev) {
/* add device, backing this class device (deprecated) */
struct device *dev = class_dev->dev;
char *path = kobject_get_path(&dev->kobj, GFP_KERNEL);
add_uevent_var(envp, num_envp, &i, buffer, buffer_size,
&length, "PHYSDEVPATH=%s", path);
kfree(path);
if (dev->bus)
add_uevent_var(envp, num_envp, &i,
buffer, buffer_size, &length,
"PHYSDEVBUS=%s", dev->bus->name);
if (dev->driver)
add_uevent_var(envp, num_envp, &i,
buffer, buffer_size, &length,
"PHYSDEVDRIVER=%s", dev->driver->name);
}
deprecated_class_uevent(envp, num_envp, &i, buffer, buffer_size,
&length, class_dev);
if (MAJOR(class_dev->devt)) {
add_uevent_var(envp, num_envp, &i,
@ -506,29 +575,11 @@ void class_device_initialize(struct class_device *class_dev)
INIT_LIST_HEAD(&class_dev->node);
}
char *make_class_name(const char *name, struct kobject *kobj)
{
char *class_name;
int size;
size = strlen(name) + strlen(kobject_name(kobj)) + 2;
class_name = kmalloc(size, GFP_KERNEL);
if (!class_name)
return ERR_PTR(-ENOMEM);
strcpy(class_name, name);
strcat(class_name, ":");
strcat(class_name, kobject_name(kobj));
return class_name;
}
int class_device_add(struct class_device *class_dev)
{
struct class *parent_class = NULL;
struct class_device *parent_class_dev = NULL;
struct class_interface *class_intf;
char *class_name = NULL;
int error = -EINVAL;
class_dev = class_device_get(class_dev);
@ -599,19 +650,17 @@ int class_device_add(struct class_device *class_dev)
goto out5;
if (class_dev->dev) {
class_name = make_class_name(class_dev->class->name,
&class_dev->kobj);
error = sysfs_create_link(&class_dev->kobj,
&class_dev->dev->kobj, "device");
if (error)
goto out6;
error = sysfs_create_link(&class_dev->dev->kobj, &class_dev->kobj,
class_name);
if (error)
goto out7;
}
error = class_device_add_groups(class_dev);
if (error)
goto out7;
error = make_deprecated_class_device_links(class_dev);
if (error)
goto out8;
@ -629,8 +678,7 @@ int class_device_add(struct class_device *class_dev)
goto out1;
out8:
if (class_dev->dev)
sysfs_remove_link(&class_dev->kobj, class_name);
class_device_remove_groups(class_dev);
out7:
if (class_dev->dev)
sysfs_remove_link(&class_dev->kobj, "device");
@ -649,7 +697,6 @@ int class_device_add(struct class_device *class_dev)
class_put(parent_class);
out1:
class_device_put(class_dev);
kfree(class_name);
return error;
}
@ -726,7 +773,6 @@ void class_device_del(struct class_device *class_dev)
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_class) {
down(&parent_class->sem);
@ -738,10 +784,8 @@ void class_device_del(struct class_device *class_dev)
}
if (class_dev->dev) {
class_name = make_class_name(class_dev->class->name,
&class_dev->kobj);
remove_deprecated_class_device_links(class_dev);
sysfs_remove_link(&class_dev->kobj, "device");
sysfs_remove_link(&class_dev->dev->kobj, class_name);
}
sysfs_remove_link(&class_dev->kobj, "subsystem");
class_device_remove_file(class_dev, &class_dev->uevent_attr);
@ -755,7 +799,6 @@ void class_device_del(struct class_device *class_dev)
class_device_put(parent_device);
class_put(parent_class);
kfree(class_name);
}
void class_device_unregister(struct class_device *class_dev)
@ -804,14 +847,17 @@ int class_device_rename(struct class_device *class_dev, char *new_name)
pr_debug("CLASS: renaming '%s' to '%s'\n", class_dev->class_id,
new_name);
#ifdef CONFIG_SYSFS_DEPRECATED
if (class_dev->dev)
old_class_name = make_class_name(class_dev->class->name,
&class_dev->kobj);
#endif
strlcpy(class_dev->class_id, new_name, KOBJ_NAME_LEN);
error = kobject_rename(&class_dev->kobj, new_name);
#ifdef CONFIG_SYSFS_DEPRECATED
if (class_dev->dev) {
new_class_name = make_class_name(class_dev->class->name,
&class_dev->kobj);
@ -819,6 +865,7 @@ int class_device_rename(struct class_device *class_dev, char *new_name)
new_class_name);
sysfs_remove_link(&class_dev->dev->kobj, old_class_name);
}
#endif
class_device_put(class_dev);
kfree(old_class_name);
@ -893,23 +940,6 @@ void class_interface_unregister(struct class_interface *class_intf)
class_put(parent);
}
int virtual_device_parent(struct device *dev)
{
if (!dev->class)
return -ENODEV;
if (!dev->class->virtual_dir) {
static struct kobject *virtual_dir = NULL;
if (!virtual_dir)
virtual_dir = kobject_add_dir(&devices_subsys.kset.kobj, "virtual");
dev->class->virtual_dir = kobject_add_dir(virtual_dir, dev->class->name);
}
dev->kobj.parent = dev->class->virtual_dir;
return 0;
}
int __init classes_init(void)
{
int retval;

View File

@ -17,6 +17,7 @@
#include <linux/slab.h>
#include <linux/string.h>
#include <linux/kdev_t.h>
#include <linux/notifier.h>
#include <asm/semaphore.h>
@ -153,20 +154,24 @@ static int dev_uevent(struct kset *kset, struct kobject *kobj, char **envp,
"MINOR=%u", MINOR(dev->devt));
}
#ifdef CONFIG_SYSFS_DEPRECATED
/* add bus name (same as SUBSYSTEM, deprecated) */
if (dev->bus)
add_uevent_var(envp, num_envp, &i,
buffer, buffer_size, &length,
"PHYSDEVBUS=%s", dev->bus->name);
#endif
/* add driver name (PHYSDEV* values are deprecated)*/
if (dev->driver) {
add_uevent_var(envp, num_envp, &i,
buffer, buffer_size, &length,
"DRIVER=%s", dev->driver->name);
#ifdef CONFIG_SYSFS_DEPRECATED
add_uevent_var(envp, num_envp, &i,
buffer, buffer_size, &length,
"PHYSDEVDRIVER=%s", dev->driver->name);
#endif
}
/* terminate, set to next free slot, shrink available space */
@ -383,6 +388,52 @@ void device_initialize(struct device *dev)
device_init_wakeup(dev, 0);
}
#ifdef CONFIG_SYSFS_DEPRECATED
static int setup_parent(struct device *dev, struct device *parent)
{
/* Set the parent to the class, not the parent device */
/* this keeps sysfs from having a symlink to make old udevs happy */
if (dev->class)
dev->kobj.parent = &dev->class->subsys.kset.kobj;
else if (parent)
dev->kobj.parent = &parent->kobj;
return 0;
}
#else
static int virtual_device_parent(struct device *dev)
{
if (!dev->class)
return -ENODEV;
if (!dev->class->virtual_dir) {
static struct kobject *virtual_dir = NULL;
if (!virtual_dir)
virtual_dir = kobject_add_dir(&devices_subsys.kset.kobj, "virtual");
dev->class->virtual_dir = kobject_add_dir(virtual_dir, dev->class->name);
}
dev->kobj.parent = dev->class->virtual_dir;
return 0;
}
static int setup_parent(struct device *dev, struct device *parent)
{
int error;
/* if this is a class device, and has no parent, create one */
if ((dev->class) && (parent == NULL)) {
error = virtual_device_parent(dev);
if (error)
return error;
} else if (parent)
dev->kobj.parent = &parent->kobj;
return 0;
}
#endif
/**
* device_add - add device to device hierarchy.
* @dev: device.
@ -405,29 +456,29 @@ int device_add(struct device *dev)
if (!dev || !strlen(dev->bus_id))
goto Error;
/* if this is a class device, and has no parent, create one */
if ((dev->class) && (dev->parent == NULL)) {
error = virtual_device_parent(dev);
if (error)
goto Error;
}
pr_debug("DEV: registering device: ID = '%s'\n", dev->bus_id);
parent = get_device(dev->parent);
pr_debug("DEV: registering device: ID = '%s'\n", dev->bus_id);
error = setup_parent(dev, parent);
if (error)
goto Error;
/* first, register with generic layer. */
kobject_set_name(&dev->kobj, "%s", dev->bus_id);
if (parent)
dev->kobj.parent = &parent->kobj;
if ((error = kobject_add(&dev->kobj)))
error = kobject_add(&dev->kobj);
if (error)
goto Error;
/* notify platform of device entry */
if (platform_notify)
platform_notify(dev);
/* notify clients of device entry (new way) */
if (dev->bus)
blocking_notifier_call_chain(&dev->bus->bus_notifier,
BUS_NOTIFY_ADD_DEVICE, dev);
dev->uevent_attr.attr.name = "uevent";
dev->uevent_attr.attr.mode = S_IWUSR;
if (dev->driver)
@ -461,13 +512,18 @@ int device_add(struct device *dev)
if (dev->class) {
sysfs_create_link(&dev->kobj, &dev->class->subsys.kset.kobj,
"subsystem");
sysfs_create_link(&dev->class->subsys.kset.kobj, &dev->kobj,
dev->bus_id);
/* 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.kset.kobj)
sysfs_create_link(&dev->class->subsys.kset.kobj,
&dev->kobj, dev->bus_id);
#ifdef CONFIG_SYSFS_DEPRECATED
if (parent) {
sysfs_create_link(&dev->kobj, &dev->parent->kobj, "device");
class_name = make_class_name(dev->class->name, &dev->kobj);
sysfs_create_link(&dev->parent->kobj, &dev->kobj, class_name);
}
#endif
}
if ((error = device_add_attrs(dev)))
@ -504,6 +560,9 @@ int device_add(struct device *dev)
BusError:
device_pm_remove(dev);
PMError:
if (dev->bus)
blocking_notifier_call_chain(&dev->bus->bus_notifier,
BUS_NOTIFY_DEL_DEVICE, dev);
device_remove_groups(dev);
GroupError:
device_remove_attrs(dev);
@ -586,7 +645,6 @@ void put_device(struct device * dev)
void device_del(struct device * dev)
{
struct device * parent = dev->parent;
char *class_name = NULL;
struct class_interface *class_intf;
if (parent)
@ -597,13 +655,21 @@ void device_del(struct device * dev)
}
if (dev->class) {
sysfs_remove_link(&dev->kobj, "subsystem");
sysfs_remove_link(&dev->class->subsys.kset.kobj, dev->bus_id);
class_name = make_class_name(dev->class->name, &dev->kobj);
/* If this is not a "fake" compatible device, remove the
* symlink from the class to the device. */
if (dev->kobj.parent != &dev->class->subsys.kset.kobj)
sysfs_remove_link(&dev->class->subsys.kset.kobj,
dev->bus_id);
#ifdef CONFIG_SYSFS_DEPRECATED
if (parent) {
sysfs_remove_link(&dev->kobj, "device");
char *class_name = make_class_name(dev->class->name,
&dev->kobj);
sysfs_remove_link(&dev->parent->kobj, class_name);
kfree(class_name);
sysfs_remove_link(&dev->kobj, "device");
}
kfree(class_name);
#endif
down(&dev->class->sem);
/* notify any interfaces that the device is now gone */
list_for_each_entry(class_intf, &dev->class->interfaces, node)
@ -616,13 +682,16 @@ void device_del(struct device * dev)
device_remove_file(dev, &dev->uevent_attr);
device_remove_groups(dev);
device_remove_attrs(dev);
bus_remove_device(dev);
/* Notify the platform of the removal, in case they
* need to do anything...
*/
if (platform_notify_remove)
platform_notify_remove(dev);
bus_remove_device(dev);
if (dev->bus)
blocking_notifier_call_chain(&dev->bus->bus_notifier,
BUS_NOTIFY_DEL_DEVICE, dev);
device_pm_remove(dev);
kobject_uevent(&dev->kobj, KOBJ_REMOVE);
kobject_del(&dev->kobj);
@ -681,12 +750,45 @@ int device_for_each_child(struct device * parent, void * data,
return error;
}
/**
* device_find_child - device iterator for locating a particular device.
* @parent: parent struct device
* @data: Data to pass to match function
* @match: Callback function to check device
*
* This is similar to the device_for_each_child() function above, but it
* returns a reference to a device that is 'found' for later use, as
* determined by the @match callback.
*
* The callback should return 0 if the device doesn't match and non-zero
* if it does. If the callback returns non-zero and a reference to the
* current device can be obtained, this function will return to the caller
* and not iterate over any more devices.
*/
struct device * device_find_child(struct device *parent, void *data,
int (*match)(struct device *, void *))
{
struct klist_iter i;
struct device *child;
if (!parent)
return NULL;
klist_iter_init(&parent->klist_children, &i);
while ((child = next_device(&i)))
if (match(child, data) && get_device(child))
break;
klist_iter_exit(&i);
return child;
}
int __init devices_init(void)
{
return subsystem_register(&devices_subsys);
}
EXPORT_SYMBOL_GPL(device_for_each_child);
EXPORT_SYMBOL_GPL(device_find_child);
EXPORT_SYMBOL_GPL(device_initialize);
EXPORT_SYMBOL_GPL(device_add);
@ -809,8 +911,10 @@ int device_rename(struct device *dev, char *new_name)
pr_debug("DEVICE: renaming '%s' to '%s'\n", dev->bus_id, new_name);
#ifdef CONFIG_SYSFS_DEPRECATED
if ((dev->class) && (dev->parent))
old_class_name = make_class_name(dev->class->name, &dev->kobj);
#endif
if (dev->class) {
old_symlink_name = kmalloc(BUS_ID_SIZE, GFP_KERNEL);
@ -825,6 +929,7 @@ int device_rename(struct device *dev, char *new_name)
error = kobject_rename(&dev->kobj, new_name);
#ifdef CONFIG_SYSFS_DEPRECATED
if (old_class_name) {
new_class_name = make_class_name(dev->class->name, &dev->kobj);
if (new_class_name) {
@ -833,6 +938,8 @@ int device_rename(struct device *dev, char *new_name)
sysfs_remove_link(&dev->parent->kobj, old_class_name);
}
}
#endif
if (dev->class) {
sysfs_remove_link(&dev->class->subsys.kset.kobj,
old_symlink_name);
@ -848,3 +955,95 @@ int device_rename(struct device *dev, char *new_name)
return error;
}
static int device_move_class_links(struct device *dev,
struct device *old_parent,
struct device *new_parent)
{
#ifdef CONFIG_SYSFS_DEPRECATED
int error;
char *class_name;
class_name = make_class_name(dev->class->name, &dev->kobj);
if (!class_name) {
error = PTR_ERR(class_name);
class_name = NULL;
goto out;
}
if (old_parent) {
sysfs_remove_link(&dev->kobj, "device");
sysfs_remove_link(&old_parent->kobj, class_name);
}
error = sysfs_create_link(&dev->kobj, &new_parent->kobj, "device");
if (error)
goto out;
error = sysfs_create_link(&new_parent->kobj, &dev->kobj, class_name);
if (error)
sysfs_remove_link(&dev->kobj, "device");
out:
kfree(class_name);
return error;
#else
return 0;
#endif
}
/**
* device_move - moves a device to a new parent
* @dev: the pointer to the struct device to be moved
* @new_parent: the new parent of the device
*/
int device_move(struct device *dev, struct device *new_parent)
{
int error;
struct device *old_parent;
dev = get_device(dev);
if (!dev)
return -EINVAL;
if (!device_is_registered(dev)) {
error = -EINVAL;
goto out;
}
new_parent = get_device(new_parent);
if (!new_parent) {
error = -EINVAL;
goto out;
}
pr_debug("DEVICE: moving '%s' to '%s'\n", dev->bus_id,
new_parent->bus_id);
error = kobject_move(&dev->kobj, &new_parent->kobj);
if (error) {
put_device(new_parent);
goto out;
}
old_parent = dev->parent;
dev->parent = new_parent;
if (old_parent)
klist_remove(&dev->knode_parent);
klist_add_tail(&dev->knode_parent, &new_parent->klist_children);
if (!dev->class)
goto out_put;
error = device_move_class_links(dev, old_parent, new_parent);
if (error) {
/* We ignore errors on cleanup since we're hosed anyway... */
device_move_class_links(dev, new_parent, old_parent);
if (!kobject_move(&dev->kobj, &old_parent->kobj)) {
klist_remove(&dev->knode_parent);
if (old_parent)
klist_add_tail(&dev->knode_parent,
&old_parent->klist_children);
}
put_device(new_parent);
goto out;
}
out_put:
put_device(old_parent);
out:
put_device(dev);
return error;
}
EXPORT_SYMBOL_GPL(device_move);

View File

@ -26,6 +26,50 @@
#define to_drv(node) container_of(node, struct device_driver, kobj.entry)
static void driver_bound(struct device *dev)
{
if (klist_node_attached(&dev->knode_driver)) {
printk(KERN_WARNING "%s: device %s already bound\n",
__FUNCTION__, kobject_name(&dev->kobj));
return;
}
pr_debug("bound device '%s' to driver '%s'\n",
dev->bus_id, dev->driver->name);
if (dev->bus)
blocking_notifier_call_chain(&dev->bus->bus_notifier,
BUS_NOTIFY_BOUND_DRIVER, dev);
klist_add_tail(&dev->knode_driver, &dev->driver->klist_devices);
}
static int driver_sysfs_add(struct device *dev)
{
int ret;
ret = sysfs_create_link(&dev->driver->kobj, &dev->kobj,
kobject_name(&dev->kobj));
if (ret == 0) {
ret = sysfs_create_link(&dev->kobj, &dev->driver->kobj,
"driver");
if (ret)
sysfs_remove_link(&dev->driver->kobj,
kobject_name(&dev->kobj));
}
return ret;
}
static void driver_sysfs_remove(struct device *dev)
{
struct device_driver *drv = dev->driver;
if (drv) {
sysfs_remove_link(&drv->kobj, kobject_name(&dev->kobj));
sysfs_remove_link(&dev->kobj, "driver");
}
}
/**
* device_bind_driver - bind a driver to one device.
* @dev: device.
@ -42,27 +86,8 @@
*/
int device_bind_driver(struct device *dev)
{
int ret;
if (klist_node_attached(&dev->knode_driver)) {
printk(KERN_WARNING "%s: device %s already bound\n",
__FUNCTION__, kobject_name(&dev->kobj));
return 0;
}
pr_debug("bound device '%s' to driver '%s'\n",
dev->bus_id, dev->driver->name);
klist_add_tail(&dev->knode_driver, &dev->driver->klist_devices);
ret = sysfs_create_link(&dev->driver->kobj, &dev->kobj,
kobject_name(&dev->kobj));
if (ret == 0) {
ret = sysfs_create_link(&dev->kobj, &dev->driver->kobj,
"driver");
if (ret)
sysfs_remove_link(&dev->driver->kobj,
kobject_name(&dev->kobj));
}
return ret;
driver_bound(dev);
return driver_sysfs_add(dev);
}
struct stupid_thread_structure {
@ -85,30 +110,32 @@ static int really_probe(void *void_data)
drv->bus->name, drv->name, dev->bus_id);
dev->driver = drv;
if (driver_sysfs_add(dev)) {
printk(KERN_ERR "%s: driver_sysfs_add(%s) failed\n",
__FUNCTION__, dev->bus_id);
goto probe_failed;
}
if (dev->bus->probe) {
ret = dev->bus->probe(dev);
if (ret) {
dev->driver = NULL;
if (ret)
goto probe_failed;
}
} else if (drv->probe) {
ret = drv->probe(dev);
if (ret) {
dev->driver = NULL;
if (ret)
goto probe_failed;
}
}
if (device_bind_driver(dev)) {
printk(KERN_ERR "%s: device_bind_driver(%s) failed\n",
__FUNCTION__, dev->bus_id);
/* How does undo a ->probe? We're screwed. */
}
driver_bound(dev);
ret = 1;
pr_debug("%s: Bound Device %s to Driver %s\n",
drv->bus->name, dev->bus_id, drv->name);
goto done;
probe_failed:
driver_sysfs_remove(dev);
dev->driver = NULL;
if (ret == -ENODEV || ret == -ENXIO) {
/* Driver matched, but didn't support device
* or device not found.
@ -284,10 +311,15 @@ static void __device_release_driver(struct device * dev)
drv = dev->driver;
if (drv) {
get_driver(drv);
sysfs_remove_link(&drv->kobj, kobject_name(&dev->kobj));
driver_sysfs_remove(dev);
sysfs_remove_link(&dev->kobj, "driver");
klist_remove(&dev->knode_driver);
if (dev->bus)
blocking_notifier_call_chain(&dev->bus->bus_notifier,
BUS_NOTIFY_UNBIND_DRIVER,
dev);
if (dev->bus && dev->bus->remove)
dev->bus->remove(dev);
else if (drv->remove)

View File

@ -21,6 +21,8 @@
#include <linux/firmware.h>
#include "base.h"
#define to_dev(obj) container_of(obj, struct device, kobj)
MODULE_AUTHOR("Manuel Estrada Sainz <ranty@debian.org>");
MODULE_DESCRIPTION("Multi purpose firmware loading support");
MODULE_LICENSE("GPL");
@ -86,12 +88,12 @@ firmware_timeout_store(struct class *class, const char *buf, size_t count)
static CLASS_ATTR(timeout, 0644, firmware_timeout_show, firmware_timeout_store);
static void fw_class_dev_release(struct class_device *class_dev);
static void fw_dev_release(struct device *dev);
static int firmware_class_uevent(struct class_device *class_dev, char **envp,
int num_envp, char *buffer, int buffer_size)
static int firmware_uevent(struct device *dev, char **envp, int num_envp,
char *buffer, int buffer_size)
{
struct firmware_priv *fw_priv = class_get_devdata(class_dev);
struct firmware_priv *fw_priv = dev_get_drvdata(dev);
int i = 0, len = 0;
if (!test_bit(FW_STATUS_READY, &fw_priv->status))
@ -110,21 +112,21 @@ static int firmware_class_uevent(struct class_device *class_dev, char **envp,
static struct class firmware_class = {
.name = "firmware",
.uevent = firmware_class_uevent,
.release = fw_class_dev_release,
.dev_uevent = firmware_uevent,
.dev_release = fw_dev_release,
};
static ssize_t
firmware_loading_show(struct class_device *class_dev, char *buf)
static ssize_t firmware_loading_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct firmware_priv *fw_priv = class_get_devdata(class_dev);
struct firmware_priv *fw_priv = dev_get_drvdata(dev);
int loading = test_bit(FW_STATUS_LOADING, &fw_priv->status);
return sprintf(buf, "%d\n", loading);
}
/**
* firmware_loading_store - set value in the 'loading' control file
* @class_dev: class_device pointer
* @dev: device pointer
* @buf: buffer to scan for loading control value
* @count: number of bytes in @buf
*
@ -134,11 +136,11 @@ firmware_loading_show(struct class_device *class_dev, char *buf)
* 0: Conclude the load and hand the data to the driver code.
* -1: Conclude the load with an error and discard any written data.
**/
static ssize_t
firmware_loading_store(struct class_device *class_dev,
const char *buf, size_t count)
static ssize_t firmware_loading_store(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
struct firmware_priv *fw_priv = class_get_devdata(class_dev);
struct firmware_priv *fw_priv = dev_get_drvdata(dev);
int loading = simple_strtol(buf, NULL, 10);
switch (loading) {
@ -174,15 +176,14 @@ firmware_loading_store(struct class_device *class_dev,
return count;
}
static CLASS_DEVICE_ATTR(loading, 0644,
firmware_loading_show, firmware_loading_store);
static DEVICE_ATTR(loading, 0644, firmware_loading_show, firmware_loading_store);
static ssize_t
firmware_data_read(struct kobject *kobj,
char *buffer, loff_t offset, size_t count)
{
struct class_device *class_dev = to_class_dev(kobj);
struct firmware_priv *fw_priv = class_get_devdata(class_dev);
struct device *dev = to_dev(kobj);
struct firmware_priv *fw_priv = dev_get_drvdata(dev);
struct firmware *fw;
ssize_t ret_count = count;
@ -234,7 +235,7 @@ fw_realloc_buffer(struct firmware_priv *fw_priv, int min_size)
/**
* firmware_data_write - write method for firmware
* @kobj: kobject for the class_device
* @kobj: kobject for the device
* @buffer: buffer being written
* @offset: buffer offset for write in total data store area
* @count: buffer size
@ -246,8 +247,8 @@ static ssize_t
firmware_data_write(struct kobject *kobj,
char *buffer, loff_t offset, size_t count)
{
struct class_device *class_dev = to_class_dev(kobj);
struct firmware_priv *fw_priv = class_get_devdata(class_dev);
struct device *dev = to_dev(kobj);
struct firmware_priv *fw_priv = dev_get_drvdata(dev);
struct firmware *fw;
ssize_t retval;
@ -280,13 +281,12 @@ static struct bin_attribute firmware_attr_data_tmpl = {
.write = firmware_data_write,
};
static void
fw_class_dev_release(struct class_device *class_dev)
static void fw_dev_release(struct device *dev)
{
struct firmware_priv *fw_priv = class_get_devdata(class_dev);
struct firmware_priv *fw_priv = dev_get_drvdata(dev);
kfree(fw_priv);
kfree(class_dev);
kfree(dev);
module_put(THIS_MODULE);
}
@ -298,26 +298,23 @@ firmware_class_timeout(u_long data)
fw_load_abort(fw_priv);
}
static inline void
fw_setup_class_device_id(struct class_device *class_dev, struct device *dev)
static inline void fw_setup_device_id(struct device *f_dev, struct device *dev)
{
/* XXX warning we should watch out for name collisions */
strlcpy(class_dev->class_id, dev->bus_id, BUS_ID_SIZE);
strlcpy(f_dev->bus_id, dev->bus_id, BUS_ID_SIZE);
}
static int
fw_register_class_device(struct class_device **class_dev_p,
const char *fw_name, struct device *device)
static int fw_register_device(struct device **dev_p, const char *fw_name,
struct device *device)
{
int retval;
struct firmware_priv *fw_priv = kzalloc(sizeof(*fw_priv),
GFP_KERNEL);
struct class_device *class_dev = kzalloc(sizeof(*class_dev),
GFP_KERNEL);
struct device *f_dev = kzalloc(sizeof(*f_dev), GFP_KERNEL);
*class_dev_p = NULL;
*dev_p = NULL;
if (!fw_priv || !class_dev) {
if (!fw_priv || !f_dev) {
printk(KERN_ERR "%s: kmalloc failed\n", __FUNCTION__);
retval = -ENOMEM;
goto error_kfree;
@ -331,55 +328,54 @@ fw_register_class_device(struct class_device **class_dev_p,
fw_priv->timeout.data = (u_long) fw_priv;
init_timer(&fw_priv->timeout);
fw_setup_class_device_id(class_dev, device);
class_dev->dev = device;
class_dev->class = &firmware_class;
class_set_devdata(class_dev, fw_priv);
retval = class_device_register(class_dev);
fw_setup_device_id(f_dev, device);
f_dev->parent = device;
f_dev->class = &firmware_class;
dev_set_drvdata(f_dev, fw_priv);
retval = device_register(f_dev);
if (retval) {
printk(KERN_ERR "%s: class_device_register failed\n",
printk(KERN_ERR "%s: device_register failed\n",
__FUNCTION__);
goto error_kfree;
}
*class_dev_p = class_dev;
*dev_p = f_dev;
return 0;
error_kfree:
kfree(fw_priv);
kfree(class_dev);
kfree(f_dev);
return retval;
}
static int
fw_setup_class_device(struct firmware *fw, struct class_device **class_dev_p,
const char *fw_name, struct device *device, int uevent)
static int fw_setup_device(struct firmware *fw, struct device **dev_p,
const char *fw_name, struct device *device,
int uevent)
{
struct class_device *class_dev;
struct device *f_dev;
struct firmware_priv *fw_priv;
int retval;
*class_dev_p = NULL;
retval = fw_register_class_device(&class_dev, fw_name, device);
*dev_p = NULL;
retval = fw_register_device(&f_dev, fw_name, device);
if (retval)
goto out;
/* Need to pin this module until class device is destroyed */
__module_get(THIS_MODULE);
fw_priv = class_get_devdata(class_dev);
fw_priv = dev_get_drvdata(f_dev);
fw_priv->fw = fw;
retval = sysfs_create_bin_file(&class_dev->kobj, &fw_priv->attr_data);
retval = sysfs_create_bin_file(&f_dev->kobj, &fw_priv->attr_data);
if (retval) {
printk(KERN_ERR "%s: sysfs_create_bin_file failed\n",
__FUNCTION__);
goto error_unreg;
}
retval = class_device_create_file(class_dev,
&class_device_attr_loading);
retval = device_create_file(f_dev, &dev_attr_loading);
if (retval) {
printk(KERN_ERR "%s: class_device_create_file failed\n",
printk(KERN_ERR "%s: device_create_file failed\n",
__FUNCTION__);
goto error_unreg;
}
@ -388,11 +384,11 @@ fw_setup_class_device(struct firmware *fw, struct class_device **class_dev_p,
set_bit(FW_STATUS_READY, &fw_priv->status);
else
set_bit(FW_STATUS_READY_NOHOTPLUG, &fw_priv->status);
*class_dev_p = class_dev;
*dev_p = f_dev;
goto out;
error_unreg:
class_device_unregister(class_dev);
device_unregister(f_dev);
out:
return retval;
}
@ -401,7 +397,7 @@ static int
_request_firmware(const struct firmware **firmware_p, const char *name,
struct device *device, int uevent)
{
struct class_device *class_dev;
struct device *f_dev;
struct firmware_priv *fw_priv;
struct firmware *firmware;
int retval;
@ -417,12 +413,11 @@ _request_firmware(const struct firmware **firmware_p, const char *name,
goto out;
}
retval = fw_setup_class_device(firmware, &class_dev, name, device,
uevent);
retval = fw_setup_device(firmware, &f_dev, name, device, uevent);
if (retval)
goto error_kfree_fw;
fw_priv = class_get_devdata(class_dev);
fw_priv = dev_get_drvdata(f_dev);
if (uevent) {
if (loading_timeout > 0) {
@ -430,7 +425,7 @@ _request_firmware(const struct firmware **firmware_p, const char *name,
add_timer(&fw_priv->timeout);
}
kobject_uevent(&class_dev->kobj, KOBJ_ADD);
kobject_uevent(&f_dev->kobj, KOBJ_ADD);
wait_for_completion(&fw_priv->completion);
set_bit(FW_STATUS_DONE, &fw_priv->status);
del_timer_sync(&fw_priv->timeout);
@ -445,7 +440,7 @@ _request_firmware(const struct firmware **firmware_p, const char *name,
}
fw_priv->fw = NULL;
mutex_unlock(&fw_lock);
class_device_unregister(class_dev);
device_unregister(f_dev);
goto out;
error_kfree_fw:

View File

@ -388,6 +388,11 @@ static int platform_drv_probe(struct device *_dev)
return drv->probe(dev);
}
static int platform_drv_probe_fail(struct device *_dev)
{
return -ENXIO;
}
static int platform_drv_remove(struct device *_dev)
{
struct platform_driver *drv = to_platform_driver(_dev->driver);
@ -451,6 +456,49 @@ void platform_driver_unregister(struct platform_driver *drv)
}
EXPORT_SYMBOL_GPL(platform_driver_unregister);
/**
* platform_driver_probe - register driver for non-hotpluggable device
* @drv: platform driver structure
* @probe: the driver probe routine, probably from an __init section
*
* Use this instead of platform_driver_register() when you know the device
* is not hotpluggable and has already been registered, and you want to
* remove its run-once probe() infrastructure from memory after the driver
* has bound to the device.
*
* One typical use for this would be with drivers for controllers integrated
* into system-on-chip processors, where the controller devices have been
* configured as part of board setup.
*
* Returns zero if the driver registered and bound to a device, else returns
* a negative error code and with the driver not registered.
*/
int platform_driver_probe(struct platform_driver *drv,
int (*probe)(struct platform_device *))
{
int retval, code;
/* temporary section violation during probe() */
drv->probe = probe;
retval = code = platform_driver_register(drv);
/* Fixup that section violation, being paranoid about code scanning
* the list of drivers in order to probe new devices. Check to see
* if the probe was successful, and make sure any forced probes of
* new devices fail.
*/
spin_lock(&platform_bus_type.klist_drivers.k_lock);
drv->probe = NULL;
if (code == 0 && list_empty(&drv->driver.klist_devices.k_list))
retval = -ENODEV;
drv->driver.probe = platform_drv_probe_fail;
spin_unlock(&platform_bus_type.klist_drivers.k_lock);
if (code != retval)
platform_driver_unregister(drv);
return retval;
}
EXPORT_SYMBOL_GPL(platform_driver_probe);
/* modalias support enables more hands-off userspace setup:
* (a) environment variable lets new-style hotplug events work once system is

View File

@ -94,54 +94,63 @@ static struct attribute_group topology_attr_group = {
.name = "topology"
};
static cpumask_t topology_dev_map = CPU_MASK_NONE;
/* Add/Remove cpu_topology interface for CPU device */
static int __cpuinit topology_add_dev(struct sys_device * sys_dev)
static int __cpuinit topology_add_dev(unsigned int cpu)
{
return sysfs_create_group(&sys_dev->kobj, &topology_attr_group);
int rc;
struct sys_device *sys_dev = get_cpu_sysdev(cpu);
rc = sysfs_create_group(&sys_dev->kobj, &topology_attr_group);
if (!rc)
cpu_set(cpu, topology_dev_map);
return rc;
}
static int __cpuinit topology_remove_dev(struct sys_device * sys_dev)
#ifdef CONFIG_HOTPLUG_CPU
static void __cpuinit topology_remove_dev(unsigned int cpu)
{
struct sys_device *sys_dev = get_cpu_sysdev(cpu);
if (!cpu_isset(cpu, topology_dev_map))
return;
cpu_clear(cpu, topology_dev_map);
sysfs_remove_group(&sys_dev->kobj, &topology_attr_group);
return 0;
}
static int __cpuinit topology_cpu_callback(struct notifier_block *nfb,
unsigned long action, void *hcpu)
unsigned long action, void *hcpu)
{
unsigned int cpu = (unsigned long)hcpu;
struct sys_device *sys_dev;
int rc = 0;
sys_dev = get_cpu_sysdev(cpu);
switch (action) {
case CPU_ONLINE:
topology_add_dev(sys_dev);
case CPU_UP_PREPARE:
rc = topology_add_dev(cpu);
break;
case CPU_UP_CANCELED:
case CPU_DEAD:
topology_remove_dev(sys_dev);
topology_remove_dev(cpu);
break;
}
return NOTIFY_OK;
return rc ? NOTIFY_BAD : NOTIFY_OK;
}
static struct notifier_block __cpuinitdata topology_cpu_notifier =
{
.notifier_call = topology_cpu_callback,
};
#endif
static int __cpuinit topology_sysfs_init(void)
{
int i;
int cpu;
int rc;
for_each_online_cpu(i) {
topology_cpu_callback(&topology_cpu_notifier, CPU_ONLINE,
(void *)(long)i);
for_each_online_cpu(cpu) {
rc = topology_add_dev(cpu);
if (rc)
return rc;
}
register_hotcpu_notifier(&topology_cpu_notifier);
hotcpu_notifier(topology_cpu_callback, 0);
return 0;
}
device_initcall(topology_sysfs_init);

View File

@ -162,7 +162,8 @@ static struct miscdevice rng_miscdev = {
};
static ssize_t hwrng_attr_current_store(struct class_device *class,
static ssize_t hwrng_attr_current_store(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t len)
{
int err;
@ -192,7 +193,8 @@ static ssize_t hwrng_attr_current_store(struct class_device *class,
return err ? : len;
}
static ssize_t hwrng_attr_current_show(struct class_device *class,
static ssize_t hwrng_attr_current_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{
int err;
@ -210,7 +212,8 @@ static ssize_t hwrng_attr_current_show(struct class_device *class,
return ret;
}
static ssize_t hwrng_attr_available_show(struct class_device *class,
static ssize_t hwrng_attr_available_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{
int err;
@ -234,20 +237,18 @@ static ssize_t hwrng_attr_available_show(struct class_device *class,
return ret;
}
static CLASS_DEVICE_ATTR(rng_current, S_IRUGO | S_IWUSR,
hwrng_attr_current_show,
hwrng_attr_current_store);
static CLASS_DEVICE_ATTR(rng_available, S_IRUGO,
hwrng_attr_available_show,
NULL);
static DEVICE_ATTR(rng_current, S_IRUGO | S_IWUSR,
hwrng_attr_current_show,
hwrng_attr_current_store);
static DEVICE_ATTR(rng_available, S_IRUGO,
hwrng_attr_available_show,
NULL);
static void unregister_miscdev(void)
{
class_device_remove_file(rng_miscdev.class,
&class_device_attr_rng_available);
class_device_remove_file(rng_miscdev.class,
&class_device_attr_rng_current);
device_remove_file(rng_miscdev.this_device, &dev_attr_rng_available);
device_remove_file(rng_miscdev.this_device, &dev_attr_rng_current);
misc_deregister(&rng_miscdev);
}
@ -258,20 +259,19 @@ static int register_miscdev(void)
err = misc_register(&rng_miscdev);
if (err)
goto out;
err = class_device_create_file(rng_miscdev.class,
&class_device_attr_rng_current);
err = device_create_file(rng_miscdev.this_device,
&dev_attr_rng_current);
if (err)
goto err_misc_dereg;
err = class_device_create_file(rng_miscdev.class,
&class_device_attr_rng_available);
err = device_create_file(rng_miscdev.this_device,
&dev_attr_rng_available);
if (err)
goto err_remove_current;
out:
return err;
err_remove_current:
class_device_remove_file(rng_miscdev.class,
&class_device_attr_rng_current);
device_remove_file(rng_miscdev.this_device, &dev_attr_rng_current);
err_misc_dereg:
misc_deregister(&rng_miscdev);
goto out;

View File

@ -980,10 +980,10 @@ static int __init chr_dev_init(void)
mem_class = class_create(THIS_MODULE, "mem");
for (i = 0; i < ARRAY_SIZE(devlist); i++)
class_device_create(mem_class, NULL,
MKDEV(MEM_MAJOR, devlist[i].minor),
NULL, devlist[i].name);
device_create(mem_class, NULL,
MKDEV(MEM_MAJOR, devlist[i].minor),
devlist[i].name);
return 0;
}

View File

@ -169,11 +169,6 @@ fail:
return err;
}
/*
* TODO for 2.7:
* - add a struct kref to struct miscdevice and make all usages of
* them dynamic.
*/
static struct class *misc_class;
static const struct file_operations misc_fops = {
@ -228,10 +223,10 @@ int misc_register(struct miscdevice * misc)
misc_minors[misc->minor >> 3] |= 1 << (misc->minor & 7);
dev = MKDEV(MISC_MAJOR, misc->minor);
misc->class = class_device_create(misc_class, NULL, dev, misc->dev,
misc->this_device = device_create(misc_class, misc->parent, dev,
"%s", misc->name);
if (IS_ERR(misc->class)) {
err = PTR_ERR(misc->class);
if (IS_ERR(misc->this_device)) {
err = PTR_ERR(misc->this_device);
goto out;
}
@ -264,7 +259,7 @@ int misc_deregister(struct miscdevice * misc)
down(&misc_sem);
list_del(&misc->list);
class_device_destroy(misc_class, MKDEV(MISC_MAJOR, misc->minor));
device_destroy(misc_class, MKDEV(MISC_MAJOR, misc->minor));
if (i < DYNAMIC_MINORS && i>0) {
misc_minors[i>>3] &= ~(1 << (misc->minor & 7));
}

View File

@ -752,13 +752,13 @@ static const struct file_operations pp_fops = {
static void pp_attach(struct parport *port)
{
class_device_create(ppdev_class, NULL, MKDEV(PP_MAJOR, port->number),
NULL, "parport%d", port->number);
device_create(ppdev_class, NULL, MKDEV(PP_MAJOR, port->number),
"parport%d", port->number);
}
static void pp_detach(struct parport *port)
{
class_device_destroy(ppdev_class, MKDEV(PP_MAJOR, port->number));
device_destroy(ppdev_class, MKDEV(PP_MAJOR, port->number));
}
static struct parport_driver pp_driver = {

View File

@ -127,9 +127,9 @@ raw_ioctl(struct inode *inode, struct file *filp,
static void bind_device(struct raw_config_request *rq)
{
class_device_destroy(raw_class, MKDEV(RAW_MAJOR, rq->raw_minor));
class_device_create(raw_class, NULL, MKDEV(RAW_MAJOR, rq->raw_minor),
NULL, "raw%d", rq->raw_minor);
device_destroy(raw_class, MKDEV(RAW_MAJOR, rq->raw_minor));
device_create(raw_class, NULL, MKDEV(RAW_MAJOR, rq->raw_minor),
"raw%d", rq->raw_minor);
}
/*
@ -200,7 +200,7 @@ static int raw_ctl_ioctl(struct inode *inode, struct file *filp,
if (rq.block_major == 0 && rq.block_minor == 0) {
/* unbind */
rawdev->binding = NULL;
class_device_destroy(raw_class,
device_destroy(raw_class,
MKDEV(RAW_MAJOR, rq.raw_minor));
} else {
rawdev->binding = bdget(dev);
@ -283,7 +283,7 @@ static int __init raw_init(void)
ret = PTR_ERR(raw_class);
goto error_region;
}
class_device_create(raw_class, NULL, MKDEV(RAW_MAJOR, 0), NULL, "rawctl");
device_create(raw_class, NULL, MKDEV(RAW_MAJOR, 0), "rawctl");
return 0;
@ -295,7 +295,7 @@ error:
static void __exit raw_exit(void)
{
class_device_destroy(raw_class, MKDEV(RAW_MAJOR, 0));
device_destroy(raw_class, MKDEV(RAW_MAJOR, 0));
class_destroy(raw_class);
cdev_del(&raw_cdev);
unregister_chrdev_region(MKDEV(RAW_MAJOR, 0), MAX_RAW_MINORS);

View File

@ -1130,7 +1130,7 @@ struct tpm_chip *tpm_register_hardware(struct device *dev, const struct tpm_vend
scnprintf(devname, DEVNAME_SIZE, "%s%d", "tpm", chip->dev_num);
chip->vendor.miscdev.name = devname;
chip->vendor.miscdev.dev = dev;
chip->vendor.miscdev.parent = dev;
chip->dev = get_device(dev);
if (misc_register(&chip->vendor.miscdev)) {

View File

@ -3612,7 +3612,8 @@ static struct class *tty_class;
* This field is optional, if there is no known struct device
* for this tty device it can be set to NULL safely.
*
* Returns a pointer to the class device (or ERR_PTR(-EFOO) on error).
* Returns a pointer to the struct device for this tty device
* (or ERR_PTR(-EFOO) on error).
*
* This call is required to be made to register an individual tty device
* if the tty driver's flags have the TTY_DRIVER_DYNAMIC_DEV bit set. If
@ -3622,8 +3623,8 @@ static struct class *tty_class;
* Locking: ??
*/
struct class_device *tty_register_device(struct tty_driver *driver,
unsigned index, struct device *device)
struct device *tty_register_device(struct tty_driver *driver, unsigned index,
struct device *device)
{
char name[64];
dev_t dev = MKDEV(driver->major, driver->minor_start) + index;
@ -3639,7 +3640,7 @@ struct class_device *tty_register_device(struct tty_driver *driver,
else
tty_line_name(driver, index, name);
return class_device_create(tty_class, NULL, dev, device, "%s", name);
return device_create(tty_class, device, dev, name);
}
/**
@ -3655,7 +3656,7 @@ struct class_device *tty_register_device(struct tty_driver *driver,
void tty_unregister_device(struct tty_driver *driver, unsigned index)
{
class_device_destroy(tty_class, MKDEV(driver->major, driver->minor_start) + index);
device_destroy(tty_class, MKDEV(driver->major, driver->minor_start) + index);
}
EXPORT_SYMBOL(tty_register_device);
@ -3895,20 +3896,20 @@ static int __init tty_init(void)
if (cdev_add(&tty_cdev, MKDEV(TTYAUX_MAJOR, 0), 1) ||
register_chrdev_region(MKDEV(TTYAUX_MAJOR, 0), 1, "/dev/tty") < 0)
panic("Couldn't register /dev/tty driver\n");
class_device_create(tty_class, NULL, MKDEV(TTYAUX_MAJOR, 0), NULL, "tty");
device_create(tty_class, NULL, MKDEV(TTYAUX_MAJOR, 0), "tty");
cdev_init(&console_cdev, &console_fops);
if (cdev_add(&console_cdev, MKDEV(TTYAUX_MAJOR, 1), 1) ||
register_chrdev_region(MKDEV(TTYAUX_MAJOR, 1), 1, "/dev/console") < 0)
panic("Couldn't register /dev/console driver\n");
class_device_create(tty_class, NULL, MKDEV(TTYAUX_MAJOR, 1), NULL, "console");
device_create(tty_class, NULL, MKDEV(TTYAUX_MAJOR, 1), "console");
#ifdef CONFIG_UNIX98_PTYS
cdev_init(&ptmx_cdev, &ptmx_fops);
if (cdev_add(&ptmx_cdev, MKDEV(TTYAUX_MAJOR, 2), 1) ||
register_chrdev_region(MKDEV(TTYAUX_MAJOR, 2), 1, "/dev/ptmx") < 0)
panic("Couldn't register /dev/ptmx driver\n");
class_device_create(tty_class, NULL, MKDEV(TTYAUX_MAJOR, 2), NULL, "ptmx");
device_create(tty_class, NULL, MKDEV(TTYAUX_MAJOR, 2), "ptmx");
#endif
#ifdef CONFIG_VT
@ -3916,7 +3917,7 @@ static int __init tty_init(void)
if (cdev_add(&vc0_cdev, MKDEV(TTY_MAJOR, 0), 1) ||
register_chrdev_region(MKDEV(TTY_MAJOR, 0), 1, "/dev/vc/0") < 0)
panic("Couldn't register /dev/tty0 driver\n");
class_device_create(tty_class, NULL, MKDEV(TTY_MAJOR, 0), NULL, "tty0");
device_create(tty_class, NULL, MKDEV(TTY_MAJOR, 0), "tty0");
vty_init();
#endif

View File

@ -476,16 +476,16 @@ static struct class *vc_class;
void vcs_make_sysfs(struct tty_struct *tty)
{
class_device_create(vc_class, NULL, MKDEV(VCS_MAJOR, tty->index + 1),
NULL, "vcs%u", tty->index + 1);
class_device_create(vc_class, NULL, MKDEV(VCS_MAJOR, tty->index + 129),
NULL, "vcsa%u", tty->index + 1);
device_create(vc_class, NULL, MKDEV(VCS_MAJOR, tty->index + 1),
"vcs%u", tty->index + 1);
device_create(vc_class, NULL, MKDEV(VCS_MAJOR, tty->index + 129),
"vcsa%u", tty->index + 1);
}
void vcs_remove_sysfs(struct tty_struct *tty)
{
class_device_destroy(vc_class, MKDEV(VCS_MAJOR, tty->index + 1));
class_device_destroy(vc_class, MKDEV(VCS_MAJOR, tty->index + 129));
device_destroy(vc_class, MKDEV(VCS_MAJOR, tty->index + 1));
device_destroy(vc_class, MKDEV(VCS_MAJOR, tty->index + 129));
}
int __init vcs_init(void)
@ -494,7 +494,7 @@ int __init vcs_init(void)
panic("unable to get major %d for vcs device", VCS_MAJOR);
vc_class = class_create(THIS_MODULE, "vc");
class_device_create(vc_class, NULL, MKDEV(VCS_MAJOR, 0), NULL, "vcs");
class_device_create(vc_class, NULL, MKDEV(VCS_MAJOR, 128), NULL, "vcsa");
device_create(vc_class, NULL, MKDEV(VCS_MAJOR, 0), "vcs");
device_create(vc_class, NULL, MKDEV(VCS_MAJOR, 128), "vcsa");
return 0;
}

View File

@ -112,7 +112,7 @@
struct con_driver {
const struct consw *con;
const char *desc;
struct class_device *class_dev;
struct device *dev;
int node;
int first;
int last;
@ -3023,10 +3023,10 @@ static inline int vt_unbind(struct con_driver *con)
}
#endif /* CONFIG_VT_HW_CONSOLE_BINDING */
static ssize_t store_bind(struct class_device *class_device,
static ssize_t store_bind(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
struct con_driver *con = class_get_devdata(class_device);
struct con_driver *con = dev_get_drvdata(dev);
int bind = simple_strtoul(buf, NULL, 0);
if (bind)
@ -3037,17 +3037,19 @@ static ssize_t store_bind(struct class_device *class_device,
return count;
}
static ssize_t show_bind(struct class_device *class_device, char *buf)
static ssize_t show_bind(struct device *dev, struct device_attribute *attr,
char *buf)
{
struct con_driver *con = class_get_devdata(class_device);
struct con_driver *con = dev_get_drvdata(dev);
int bind = con_is_bound(con->con);
return snprintf(buf, PAGE_SIZE, "%i\n", bind);
}
static ssize_t show_name(struct class_device *class_device, char *buf)
static ssize_t show_name(struct device *dev, struct device_attribute *attr,
char *buf)
{
struct con_driver *con = class_get_devdata(class_device);
struct con_driver *con = dev_get_drvdata(dev);
return snprintf(buf, PAGE_SIZE, "%s %s\n",
(con->flag & CON_DRIVER_FLAG_MODULE) ? "(M)" : "(S)",
@ -3055,43 +3057,40 @@ static ssize_t show_name(struct class_device *class_device, char *buf)
}
static struct class_device_attribute class_device_attrs[] = {
static struct device_attribute device_attrs[] = {
__ATTR(bind, S_IRUGO|S_IWUSR, show_bind, store_bind),
__ATTR(name, S_IRUGO, show_name, NULL),
};
static int vtconsole_init_class_device(struct con_driver *con)
static int vtconsole_init_device(struct con_driver *con)
{
int i;
int error = 0;
con->flag |= CON_DRIVER_FLAG_ATTR;
class_set_devdata(con->class_dev, con);
for (i = 0; i < ARRAY_SIZE(class_device_attrs); i++) {
error = class_device_create_file(con->class_dev,
&class_device_attrs[i]);
dev_set_drvdata(con->dev, con);
for (i = 0; i < ARRAY_SIZE(device_attrs); i++) {
error = device_create_file(con->dev, &device_attrs[i]);
if (error)
break;
}
if (error) {
while (--i >= 0)
class_device_remove_file(con->class_dev,
&class_device_attrs[i]);
device_remove_file(con->dev, &device_attrs[i]);
con->flag &= ~CON_DRIVER_FLAG_ATTR;
}
return error;
}
static void vtconsole_deinit_class_device(struct con_driver *con)
static void vtconsole_deinit_device(struct con_driver *con)
{
int i;
if (con->flag & CON_DRIVER_FLAG_ATTR) {
for (i = 0; i < ARRAY_SIZE(class_device_attrs); i++)
class_device_remove_file(con->class_dev,
&class_device_attrs[i]);
for (i = 0; i < ARRAY_SIZE(device_attrs); i++)
device_remove_file(con->dev, &device_attrs[i]);
con->flag &= ~CON_DRIVER_FLAG_ATTR;
}
}
@ -3179,18 +3178,17 @@ int register_con_driver(const struct consw *csw, int first, int last)
if (retval)
goto err;
con_driver->class_dev = class_device_create(vtconsole_class, NULL,
MKDEV(0, con_driver->node),
NULL, "vtcon%i",
con_driver->node);
con_driver->dev = device_create(vtconsole_class, NULL,
MKDEV(0, con_driver->node),
"vtcon%i", con_driver->node);
if (IS_ERR(con_driver->class_dev)) {
printk(KERN_WARNING "Unable to create class_device for %s; "
if (IS_ERR(con_driver->dev)) {
printk(KERN_WARNING "Unable to create device for %s; "
"errno = %ld\n", con_driver->desc,
PTR_ERR(con_driver->class_dev));
con_driver->class_dev = NULL;
PTR_ERR(con_driver->dev));
con_driver->dev = NULL;
} else {
vtconsole_init_class_device(con_driver);
vtconsole_init_device(con_driver);
}
err:
@ -3226,12 +3224,12 @@ int unregister_con_driver(const struct consw *csw)
if (con_driver->con == csw &&
con_driver->flag & CON_DRIVER_FLAG_MODULE) {
vtconsole_deinit_class_device(con_driver);
class_device_destroy(vtconsole_class,
MKDEV(0, con_driver->node));
vtconsole_deinit_device(con_driver);
device_destroy(vtconsole_class,
MKDEV(0, con_driver->node));
con_driver->con = NULL;
con_driver->desc = NULL;
con_driver->class_dev = NULL;
con_driver->dev = NULL;
con_driver->node = 0;
con_driver->flag = 0;
con_driver->first = 0;
@ -3289,19 +3287,18 @@ static int __init vtconsole_class_init(void)
for (i = 0; i < MAX_NR_CON_DRIVER; i++) {
struct con_driver *con = &registered_con_driver[i];
if (con->con && !con->class_dev) {
con->class_dev =
class_device_create(vtconsole_class, NULL,
MKDEV(0, con->node), NULL,
"vtcon%i", con->node);
if (con->con && !con->dev) {
con->dev = device_create(vtconsole_class, NULL,
MKDEV(0, con->node),
"vtcon%i", con->node);
if (IS_ERR(con->class_dev)) {
if (IS_ERR(con->dev)) {
printk(KERN_WARNING "Unable to create "
"class_device for %s; errno = %ld\n",
con->desc, PTR_ERR(con->class_dev));
con->class_dev = NULL;
"device for %s; errno = %ld\n",
con->desc, PTR_ERR(con->dev));
con->dev = NULL;
} else {
vtconsole_init_class_device(con);
vtconsole_init_device(con);
}
}
}

View File

@ -42,7 +42,7 @@ static struct i2c_driver i2cdev_driver;
struct i2c_dev {
struct list_head list;
struct i2c_adapter *adap;
struct class_device *class_dev;
struct device *dev;
};
#define I2C_MINORS 256
@ -92,15 +92,16 @@ static void return_i2c_dev(struct i2c_dev *i2c_dev)
spin_unlock(&i2c_dev_list_lock);
}
static ssize_t show_adapter_name(struct class_device *class_dev, char *buf)
static ssize_t show_adapter_name(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct i2c_dev *i2c_dev = i2c_dev_get_by_minor(MINOR(class_dev->devt));
struct i2c_dev *i2c_dev = i2c_dev_get_by_minor(MINOR(dev->devt));
if (!i2c_dev)
return -ENODEV;
return sprintf(buf, "%s\n", i2c_dev->adap->name);
}
static CLASS_DEVICE_ATTR(name, S_IRUGO, show_adapter_name, NULL);
static DEVICE_ATTR(name, S_IRUGO, show_adapter_name, NULL);
static ssize_t i2cdev_read (struct file *file, char __user *buf, size_t count,
loff_t *offset)
@ -413,15 +414,14 @@ static int i2cdev_attach_adapter(struct i2c_adapter *adap)
return PTR_ERR(i2c_dev);
/* register this i2c device with the driver core */
i2c_dev->class_dev = class_device_create(i2c_dev_class, NULL,
MKDEV(I2C_MAJOR, adap->nr),
&adap->dev, "i2c-%d",
adap->nr);
if (!i2c_dev->class_dev) {
i2c_dev->dev = device_create(i2c_dev_class, &adap->dev,
MKDEV(I2C_MAJOR, adap->nr),
"i2c-%d", adap->nr);
if (!i2c_dev->dev) {
res = -ENODEV;
goto error;
}
res = class_device_create_file(i2c_dev->class_dev, &class_device_attr_name);
res = device_create_file(i2c_dev->dev, &dev_attr_name);
if (res)
goto error_destroy;
@ -429,7 +429,7 @@ static int i2cdev_attach_adapter(struct i2c_adapter *adap)
adap->name, adap->nr);
return 0;
error_destroy:
class_device_destroy(i2c_dev_class, MKDEV(I2C_MAJOR, adap->nr));
device_destroy(i2c_dev_class, MKDEV(I2C_MAJOR, adap->nr));
error:
return_i2c_dev(i2c_dev);
kfree(i2c_dev);
@ -444,9 +444,9 @@ static int i2cdev_detach_adapter(struct i2c_adapter *adap)
if (!i2c_dev) /* attach_adapter must have failed */
return 0;
class_device_remove_file(i2c_dev->class_dev, &class_device_attr_name);
device_remove_file(i2c_dev->dev, &dev_attr_name);
return_i2c_dev(i2c_dev);
class_device_destroy(i2c_dev_class, MKDEV(I2C_MAJOR, adap->nr));
device_destroy(i2c_dev_class, MKDEV(I2C_MAJOR, adap->nr));
kfree(i2c_dev);
pr_debug("i2c-dev: adapter [%s] unregistered\n", adap->name);

View File

@ -297,7 +297,7 @@ static int serio_raw_connect(struct serio *serio, struct serio_driver *drv)
serio_raw->dev.minor = PSMOUSE_MINOR;
serio_raw->dev.name = serio_raw->name;
serio_raw->dev.dev = &serio->dev;
serio_raw->dev.parent = &serio->dev;
serio_raw->dev.fops = &serio_raw_fops;
err = misc_register(&serio_raw->dev);

View File

@ -702,7 +702,7 @@ struct cardstate *gigaset_initcs(struct gigaset_driver *drv, int channels,
cs->open_count = 0;
cs->dev = NULL;
cs->tty = NULL;
cs->class = NULL;
cs->tty_dev = NULL;
cs->cidmode = cidmode != 0;
//if(onechannel) { //FIXME

View File

@ -444,7 +444,7 @@ struct cardstate {
struct gigaset_driver *driver;
unsigned minor_index;
struct device *dev;
struct class_device *class;
struct device *tty_dev;
const struct gigaset_ops *ops;

View File

@ -625,13 +625,13 @@ void gigaset_if_init(struct cardstate *cs)
return;
tasklet_init(&cs->if_wake_tasklet, &if_wake, (unsigned long) cs);
cs->class = tty_register_device(drv->tty, cs->minor_index, NULL);
cs->tty_dev = tty_register_device(drv->tty, cs->minor_index, NULL);
if (!IS_ERR(cs->class))
class_set_devdata(cs->class, cs);
if (!IS_ERR(cs->tty_dev))
dev_set_drvdata(cs->tty_dev, cs);
else {
warn("could not register device to the tty subsystem");
cs->class = NULL;
cs->tty_dev = NULL;
}
}
@ -645,7 +645,7 @@ void gigaset_if_free(struct cardstate *cs)
tasklet_disable(&cs->if_wake_tasklet);
tasklet_kill(&cs->if_wake_tasklet);
cs->class = NULL;
cs->tty_dev = NULL;
tty_unregister_device(drv->tty, cs->minor_index);
}

View File

@ -16,11 +16,12 @@
#include "gigaset.h"
#include <linux/ctype.h>
static ssize_t show_cidmode(struct class_device *class, char *buf)
static ssize_t show_cidmode(struct device *dev,
struct device_attribute *attr, char *buf)
{
int ret;
unsigned long flags;
struct cardstate *cs = class_get_devdata(class);
struct cardstate *cs = dev_get_drvdata(dev);
spin_lock_irqsave(&cs->lock, flags);
ret = sprintf(buf, "%u\n", cs->cidmode);
@ -29,10 +30,10 @@ static ssize_t show_cidmode(struct class_device *class, char *buf)
return ret;
}
static ssize_t set_cidmode(struct class_device *class,
static ssize_t set_cidmode(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
struct cardstate *cs = class_get_devdata(class);
struct cardstate *cs = dev_get_drvdata(dev);
long int value;
char *end;
@ -64,25 +65,25 @@ static ssize_t set_cidmode(struct class_device *class,
return count;
}
static CLASS_DEVICE_ATTR(cidmode, S_IRUGO|S_IWUSR, show_cidmode, set_cidmode);
static DEVICE_ATTR(cidmode, S_IRUGO|S_IWUSR, show_cidmode, set_cidmode);
/* free sysfs for device */
void gigaset_free_dev_sysfs(struct cardstate *cs)
{
if (!cs->class)
if (!cs->tty_dev)
return;
gig_dbg(DEBUG_INIT, "removing sysfs entries");
class_device_remove_file(cs->class, &class_device_attr_cidmode);
device_remove_file(cs->tty_dev, &dev_attr_cidmode);
}
/* initialize sysfs for device */
void gigaset_init_dev_sysfs(struct cardstate *cs)
{
if (!cs->class)
if (!cs->tty_dev)
return;
gig_dbg(DEBUG_INIT, "setting up sysfs");
if (class_device_create_file(cs->class, &class_device_attr_cidmode))
if (device_create_file(cs->tty_dev, &dev_attr_cidmode))
dev_err(cs->dev, "could not create sysfs attribute\n");
}

View File

@ -130,8 +130,8 @@ int mmc_init_queue(struct mmc_queue *mq, struct mmc_card *card, spinlock_t *lock
u64 limit = BLK_BOUNCE_HIGH;
int ret;
if (host->dev->dma_mask && *host->dev->dma_mask)
limit = *host->dev->dma_mask;
if (mmc_dev(host)->dma_mask && *mmc_dev(host)->dma_mask)
limit = *mmc_dev(host)->dma_mask;
mq->card = card;
mq->queue = blk_init_queue(mmc_request, lock);

View File

@ -199,7 +199,7 @@ void mmc_init_card(struct mmc_card *card, struct mmc_host *host)
memset(card, 0, sizeof(struct mmc_card));
card->host = host;
device_initialize(&card->dev);
card->dev.parent = card->host->dev;
card->dev.parent = mmc_dev(host);
card->dev.bus = &mmc_bus_type;
card->dev.release = mmc_release_card;
}
@ -242,7 +242,7 @@ void mmc_remove_card(struct mmc_card *card)
}
static void mmc_host_classdev_release(struct class_device *dev)
static void mmc_host_classdev_release(struct device *dev)
{
struct mmc_host *host = cls_dev_to_mmc_host(dev);
kfree(host);
@ -250,7 +250,7 @@ static void mmc_host_classdev_release(struct class_device *dev)
static struct class mmc_host_class = {
.name = "mmc_host",
.release = mmc_host_classdev_release,
.dev_release = mmc_host_classdev_release,
};
static DEFINE_IDR(mmc_host_idr);
@ -267,10 +267,10 @@ struct mmc_host *mmc_alloc_host_sysfs(int extra, struct device *dev)
if (host) {
memset(host, 0, sizeof(struct mmc_host) + extra);
host->dev = dev;
host->class_dev.dev = host->dev;
host->parent = dev;
host->class_dev.parent = dev;
host->class_dev.class = &mmc_host_class;
class_device_initialize(&host->class_dev);
device_initialize(&host->class_dev);
}
return host;
@ -292,10 +292,10 @@ int mmc_add_host_sysfs(struct mmc_host *host)
if (err)
return err;
snprintf(host->class_dev.class_id, BUS_ID_SIZE,
snprintf(host->class_dev.bus_id, BUS_ID_SIZE,
"mmc%d", host->index);
return class_device_add(&host->class_dev);
return device_add(&host->class_dev);
}
/*
@ -303,7 +303,7 @@ int mmc_add_host_sysfs(struct mmc_host *host)
*/
void mmc_remove_host_sysfs(struct mmc_host *host)
{
class_device_del(&host->class_dev);
device_del(&host->class_dev);
spin_lock(&mmc_host_lock);
idr_remove(&mmc_host_idr, host->index);
@ -315,7 +315,7 @@ void mmc_remove_host_sysfs(struct mmc_host *host)
*/
void mmc_free_host_sysfs(struct mmc_host *host)
{
class_device_put(&host->class_dev);
put_device(&host->class_dev);
}
static struct workqueue_struct *workqueue;

View File

@ -1488,7 +1488,7 @@ static void __devinit wbsd_request_dma(struct wbsd_host *host, int dma)
/*
* Translate the address to a physical address.
*/
host->dma_addr = dma_map_single(host->mmc->dev, host->dma_buffer,
host->dma_addr = dma_map_single(mmc_dev(host->mmc), host->dma_buffer,
WBSD_DMA_SIZE, DMA_BIDIRECTIONAL);
/*
@ -1512,7 +1512,7 @@ kfree:
*/
BUG_ON(1);
dma_unmap_single(host->mmc->dev, host->dma_addr,
dma_unmap_single(mmc_dev(host->mmc), host->dma_addr,
WBSD_DMA_SIZE, DMA_BIDIRECTIONAL);
host->dma_addr = (dma_addr_t)NULL;
@ -1530,7 +1530,7 @@ err:
static void __devexit wbsd_release_dma(struct wbsd_host *host)
{
if (host->dma_addr) {
dma_unmap_single(host->mmc->dev, host->dma_addr,
dma_unmap_single(mmc_dev(host->mmc), host->dma_addr,
WBSD_DMA_SIZE, DMA_BIDIRECTIONAL);
}
kfree(host->dma_buffer);

View File

@ -860,7 +860,7 @@ static int __init ppp_init(void)
err = PTR_ERR(ppp_class);
goto out_chrdev;
}
class_device_create(ppp_class, NULL, MKDEV(PPP_MAJOR, 0), NULL, "ppp");
device_create(ppp_class, NULL, MKDEV(PPP_MAJOR, 0), "ppp");
}
out:
@ -2675,7 +2675,7 @@ static void __exit ppp_cleanup(void)
cardmap_destroy(&all_ppp_units);
if (unregister_chrdev(PPP_MAJOR, "ppp") != 0)
printk(KERN_ERR "PPP: failed to unregister PPP device\n");
class_device_destroy(ppp_class, MKDEV(PPP_MAJOR, 0));
device_destroy(ppp_class, MKDEV(PPP_MAJOR, 0));
class_destroy(ppp_class);
}

View File

@ -1296,14 +1296,14 @@ register_framebuffer(struct fb_info *fb_info)
break;
fb_info->node = i;
fb_info->class_device = class_device_create(fb_class, NULL, MKDEV(FB_MAJOR, i),
fb_info->device, "fb%d", i);
if (IS_ERR(fb_info->class_device)) {
fb_info->dev = device_create(fb_class, fb_info->device,
MKDEV(FB_MAJOR, i), "fb%d", i);
if (IS_ERR(fb_info->dev)) {
/* Not fatal */
printk(KERN_WARNING "Unable to create class_device for framebuffer %d; errno = %ld\n", i, PTR_ERR(fb_info->class_device));
fb_info->class_device = NULL;
printk(KERN_WARNING "Unable to create device for framebuffer %d; errno = %ld\n", i, PTR_ERR(fb_info->dev));
fb_info->dev = NULL;
} else
fb_init_class_device(fb_info);
fb_init_device(fb_info);
if (fb_info->pixmap.addr == NULL) {
fb_info->pixmap.addr = kmalloc(FBPIXMAPSIZE, GFP_KERNEL);
@ -1356,8 +1356,8 @@ unregister_framebuffer(struct fb_info *fb_info)
fb_destroy_modelist(&fb_info->modelist);
registered_fb[i]=NULL;
num_registered_fb--;
fb_cleanup_class_device(fb_info);
class_device_destroy(fb_class, MKDEV(FB_MAJOR, i));
fb_cleanup_device(fb_info);
device_destroy(fb_class, MKDEV(FB_MAJOR, i));
event.info = fb_info;
fb_notifier_call_chain(FB_EVENT_FB_UNREGISTERED, &event);
return 0;

View File

@ -73,7 +73,7 @@ EXPORT_SYMBOL(framebuffer_alloc);
*
* @info: frame buffer info structure
*
* Drop the reference count of the class_device embedded in the
* Drop the reference count of the device embedded in the
* framebuffer info structure.
*
*/
@ -120,10 +120,10 @@ static int mode_string(char *buf, unsigned int offset,
m, mode->xres, mode->yres, v, mode->refresh);
}
static ssize_t store_mode(struct class_device *class_device, const char * buf,
size_t count)
static ssize_t store_mode(struct device *device, struct device_attribute *attr,
const char *buf, size_t count)
{
struct fb_info *fb_info = class_get_devdata(class_device);
struct fb_info *fb_info = dev_get_drvdata(device);
char mstr[100];
struct fb_var_screeninfo var;
struct fb_modelist *modelist;
@ -151,9 +151,10 @@ static ssize_t store_mode(struct class_device *class_device, const char * buf,
return -EINVAL;
}
static ssize_t show_mode(struct class_device *class_device, char *buf)
static ssize_t show_mode(struct device *device, struct device_attribute *attr,
char *buf)
{
struct fb_info *fb_info = class_get_devdata(class_device);
struct fb_info *fb_info = dev_get_drvdata(device);
if (!fb_info->mode)
return 0;
@ -161,10 +162,11 @@ static ssize_t show_mode(struct class_device *class_device, char *buf)
return mode_string(buf, 0, fb_info->mode);
}
static ssize_t store_modes(struct class_device *class_device, const char * buf,
size_t count)
static ssize_t store_modes(struct device *device,
struct device_attribute *attr,
const char *buf, size_t count)
{
struct fb_info *fb_info = class_get_devdata(class_device);
struct fb_info *fb_info = dev_get_drvdata(device);
LIST_HEAD(old_list);
int i = count / sizeof(struct fb_videomode);
@ -186,9 +188,10 @@ static ssize_t store_modes(struct class_device *class_device, const char * buf,
return 0;
}
static ssize_t show_modes(struct class_device *class_device, char *buf)
static ssize_t show_modes(struct device *device, struct device_attribute *attr,
char *buf)
{
struct fb_info *fb_info = class_get_devdata(class_device);
struct fb_info *fb_info = dev_get_drvdata(device);
unsigned int i;
struct list_head *pos;
struct fb_modelist *modelist;
@ -203,10 +206,10 @@ static ssize_t show_modes(struct class_device *class_device, char *buf)
return i;
}
static ssize_t store_bpp(struct class_device *class_device, const char * buf,
size_t count)
static ssize_t store_bpp(struct device *device, struct device_attribute *attr,
const char *buf, size_t count)
{
struct fb_info *fb_info = class_get_devdata(class_device);
struct fb_info *fb_info = dev_get_drvdata(device);
struct fb_var_screeninfo var;
char ** last = NULL;
int err;
@ -218,16 +221,18 @@ static ssize_t store_bpp(struct class_device *class_device, const char * buf,
return count;
}
static ssize_t show_bpp(struct class_device *class_device, char *buf)
static ssize_t show_bpp(struct device *device, struct device_attribute *attr,
char *buf)
{
struct fb_info *fb_info = class_get_devdata(class_device);
struct fb_info *fb_info = dev_get_drvdata(device);
return snprintf(buf, PAGE_SIZE, "%d\n", fb_info->var.bits_per_pixel);
}
static ssize_t store_rotate(struct class_device *class_device, const char *buf,
size_t count)
static ssize_t store_rotate(struct device *device,
struct device_attribute *attr,
const char *buf, size_t count)
{
struct fb_info *fb_info = class_get_devdata(class_device);
struct fb_info *fb_info = dev_get_drvdata(device);
struct fb_var_screeninfo var;
char **last = NULL;
int err;
@ -242,17 +247,19 @@ static ssize_t store_rotate(struct class_device *class_device, const char *buf,
}
static ssize_t show_rotate(struct class_device *class_device, char *buf)
static ssize_t show_rotate(struct device *device,
struct device_attribute *attr, char *buf)
{
struct fb_info *fb_info = class_get_devdata(class_device);
struct fb_info *fb_info = dev_get_drvdata(device);
return snprintf(buf, PAGE_SIZE, "%d\n", fb_info->var.rotate);
}
static ssize_t store_virtual(struct class_device *class_device,
const char * buf, size_t count)
static ssize_t store_virtual(struct device *device,
struct device_attribute *attr,
const char *buf, size_t count)
{
struct fb_info *fb_info = class_get_devdata(class_device);
struct fb_info *fb_info = dev_get_drvdata(device);
struct fb_var_screeninfo var;
char *last = NULL;
int err;
@ -269,23 +276,26 @@ static ssize_t store_virtual(struct class_device *class_device,
return count;
}
static ssize_t show_virtual(struct class_device *class_device, char *buf)
static ssize_t show_virtual(struct device *device,
struct device_attribute *attr, char *buf)
{
struct fb_info *fb_info = class_get_devdata(class_device);
struct fb_info *fb_info = dev_get_drvdata(device);
return snprintf(buf, PAGE_SIZE, "%d,%d\n", fb_info->var.xres_virtual,
fb_info->var.yres_virtual);
}
static ssize_t show_stride(struct class_device *class_device, char *buf)
static ssize_t show_stride(struct device *device,
struct device_attribute *attr, char *buf)
{
struct fb_info *fb_info = class_get_devdata(class_device);
struct fb_info *fb_info = dev_get_drvdata(device);
return snprintf(buf, PAGE_SIZE, "%d\n", fb_info->fix.line_length);
}
static ssize_t store_blank(struct class_device *class_device, const char * buf,
size_t count)
static ssize_t store_blank(struct device *device,
struct device_attribute *attr,
const char *buf, size_t count)
{
struct fb_info *fb_info = class_get_devdata(class_device);
struct fb_info *fb_info = dev_get_drvdata(device);
char *last = NULL;
int err;
@ -299,42 +309,48 @@ static ssize_t store_blank(struct class_device *class_device, const char * buf,
return count;
}
static ssize_t show_blank(struct class_device *class_device, char *buf)
static ssize_t show_blank(struct device *device,
struct device_attribute *attr, char *buf)
{
// struct fb_info *fb_info = class_get_devdata(class_device);
// struct fb_info *fb_info = dev_get_drvdata(device);
return 0;
}
static ssize_t store_console(struct class_device *class_device,
const char * buf, size_t count)
static ssize_t store_console(struct device *device,
struct device_attribute *attr,
const char *buf, size_t count)
{
// struct fb_info *fb_info = class_get_devdata(class_device);
// struct fb_info *fb_info = dev_get_drvdata(device);
return 0;
}
static ssize_t show_console(struct class_device *class_device, char *buf)
static ssize_t show_console(struct device *device,
struct device_attribute *attr, char *buf)
{
// struct fb_info *fb_info = class_get_devdata(class_device);
// struct fb_info *fb_info = dev_get_drvdata(device);
return 0;
}
static ssize_t store_cursor(struct class_device *class_device,
const char * buf, size_t count)
static ssize_t store_cursor(struct device *device,
struct device_attribute *attr,
const char *buf, size_t count)
{
// struct fb_info *fb_info = class_get_devdata(class_device);
// struct fb_info *fb_info = dev_get_drvdata(device);
return 0;
}
static ssize_t show_cursor(struct class_device *class_device, char *buf)
static ssize_t show_cursor(struct device *device,
struct device_attribute *attr, char *buf)
{
// struct fb_info *fb_info = class_get_devdata(class_device);
// struct fb_info *fb_info = dev_get_drvdata(device);
return 0;
}
static ssize_t store_pan(struct class_device *class_device, const char * buf,
size_t count)
static ssize_t store_pan(struct device *device,
struct device_attribute *attr,
const char *buf, size_t count)
{
struct fb_info *fb_info = class_get_devdata(class_device);
struct fb_info *fb_info = dev_get_drvdata(device);
struct fb_var_screeninfo var;
char *last = NULL;
int err;
@ -355,24 +371,27 @@ static ssize_t store_pan(struct class_device *class_device, const char * buf,
return count;
}
static ssize_t show_pan(struct class_device *class_device, char *buf)
static ssize_t show_pan(struct device *device,
struct device_attribute *attr, char *buf)
{
struct fb_info *fb_info = class_get_devdata(class_device);
struct fb_info *fb_info = dev_get_drvdata(device);
return snprintf(buf, PAGE_SIZE, "%d,%d\n", fb_info->var.xoffset,
fb_info->var.xoffset);
}
static ssize_t show_name(struct class_device *class_device, char *buf)
static ssize_t show_name(struct device *device,
struct device_attribute *attr, char *buf)
{
struct fb_info *fb_info = class_get_devdata(class_device);
struct fb_info *fb_info = dev_get_drvdata(device);
return snprintf(buf, PAGE_SIZE, "%s\n", fb_info->fix.id);
}
static ssize_t store_fbstate(struct class_device *class_device,
const char *buf, size_t count)
static ssize_t store_fbstate(struct device *device,
struct device_attribute *attr,
const char *buf, size_t count)
{
struct fb_info *fb_info = class_get_devdata(class_device);
struct fb_info *fb_info = dev_get_drvdata(device);
u32 state;
char *last = NULL;
@ -385,17 +404,19 @@ static ssize_t store_fbstate(struct class_device *class_device,
return count;
}
static ssize_t show_fbstate(struct class_device *class_device, char *buf)
static ssize_t show_fbstate(struct device *device,
struct device_attribute *attr, char *buf)
{
struct fb_info *fb_info = class_get_devdata(class_device);
struct fb_info *fb_info = dev_get_drvdata(device);
return snprintf(buf, PAGE_SIZE, "%d\n", fb_info->state);
}
#ifdef CONFIG_FB_BACKLIGHT
static ssize_t store_bl_curve(struct class_device *class_device,
const char *buf, size_t count)
static ssize_t store_bl_curve(struct device *device,
struct device_attribute *attr,
const char *buf, size_t count)
{
struct fb_info *fb_info = class_get_devdata(class_device);
struct fb_info *fb_info = dev_get_drvdata(device);
u8 tmp_curve[FB_BACKLIGHT_LEVELS];
unsigned int i;
@ -432,9 +453,10 @@ static ssize_t store_bl_curve(struct class_device *class_device,
return count;
}
static ssize_t show_bl_curve(struct class_device *class_device, char *buf)
static ssize_t show_bl_curve(struct device *device,
struct device_attribute *attr, char *buf)
{
struct fb_info *fb_info = class_get_devdata(class_device);
struct fb_info *fb_info = dev_get_drvdata(device);
ssize_t len = 0;
unsigned int i;
@ -465,7 +487,7 @@ static ssize_t show_bl_curve(struct class_device *class_device, char *buf)
/* When cmap is added back in it should be a binary attribute
* not a text one. Consideration should also be given to converting
* fbdev to use configfs instead of sysfs */
static struct class_device_attribute class_device_attrs[] = {
static struct device_attribute device_attrs[] = {
__ATTR(bits_per_pixel, S_IRUGO|S_IWUSR, show_bpp, store_bpp),
__ATTR(blank, S_IRUGO|S_IWUSR, show_blank, store_blank),
__ATTR(console, S_IRUGO|S_IWUSR, show_console, store_console),
@ -483,17 +505,16 @@ static struct class_device_attribute class_device_attrs[] = {
#endif
};
int fb_init_class_device(struct fb_info *fb_info)
int fb_init_device(struct fb_info *fb_info)
{
int i, error = 0;
class_set_devdata(fb_info->class_device, fb_info);
dev_set_drvdata(fb_info->dev, fb_info);
fb_info->class_flag |= FB_SYSFS_FLAG_ATTR;
for (i = 0; i < ARRAY_SIZE(class_device_attrs); i++) {
error = class_device_create_file(fb_info->class_device,
&class_device_attrs[i]);
for (i = 0; i < ARRAY_SIZE(device_attrs); i++) {
error = device_create_file(fb_info->dev, &device_attrs[i]);
if (error)
break;
@ -501,22 +522,20 @@ int fb_init_class_device(struct fb_info *fb_info)
if (error) {
while (--i >= 0)
class_device_remove_file(fb_info->class_device,
&class_device_attrs[i]);
device_remove_file(fb_info->dev, &device_attrs[i]);
fb_info->class_flag &= ~FB_SYSFS_FLAG_ATTR;
}
return 0;
}
void fb_cleanup_class_device(struct fb_info *fb_info)
void fb_cleanup_device(struct fb_info *fb_info)
{
unsigned int i;
if (fb_info->class_flag & FB_SYSFS_FLAG_ATTR) {
for (i = 0; i < ARRAY_SIZE(class_device_attrs); i++)
class_device_remove_file(fb_info->class_device,
&class_device_attrs[i]);
for (i = 0; i < ARRAY_SIZE(device_attrs); i++)
device_remove_file(fb_info->dev, &device_attrs[i]);
fb_info->class_flag &= ~FB_SYSFS_FLAG_ATTR;
}

View File

@ -372,6 +372,51 @@ int sysfs_rename_dir(struct kobject * kobj, const char *new_name)
return error;
}
int sysfs_move_dir(struct kobject *kobj, struct kobject *new_parent)
{
struct dentry *old_parent_dentry, *new_parent_dentry, *new_dentry;
struct sysfs_dirent *new_parent_sd, *sd;
int error;
if (!new_parent)
return -EINVAL;
old_parent_dentry = kobj->parent ?
kobj->parent->dentry : sysfs_mount->mnt_sb->s_root;
new_parent_dentry = new_parent->dentry;
again:
mutex_lock(&old_parent_dentry->d_inode->i_mutex);
if (!mutex_trylock(&new_parent_dentry->d_inode->i_mutex)) {
mutex_unlock(&old_parent_dentry->d_inode->i_mutex);
goto again;
}
new_parent_sd = new_parent_dentry->d_fsdata;
sd = kobj->dentry->d_fsdata;
new_dentry = lookup_one_len(kobj->name, new_parent_dentry,
strlen(kobj->name));
if (IS_ERR(new_dentry)) {
error = PTR_ERR(new_dentry);
goto out;
} else
error = 0;
d_add(new_dentry, NULL);
d_move(kobj->dentry, new_dentry);
dput(new_dentry);
/* Remove from old parent's list and insert into new parent's list. */
list_del_init(&sd->s_sibling);
list_add(&sd->s_sibling, &new_parent_sd->s_children);
out:
mutex_unlock(&new_parent_dentry->d_inode->i_mutex);
mutex_unlock(&old_parent_dentry->d_inode->i_mutex);
return error;
}
static int sysfs_dir_open(struct inode *inode, struct file *file)
{
struct dentry * dentry = file->f_dentry;

View File

@ -190,6 +190,9 @@ fill_write_buffer(struct sysfs_buffer * buffer, const char __user * buf, size_t
count = PAGE_SIZE - 1;
error = copy_from_user(buffer->page,buf,count);
buffer->needs_read_fill = 1;
/* if buf is assumed to contain a string, terminate it by \0,
so e.g. sscanf() can scan the string easily */
buffer->page[count] = 0;
return error ? -EFAULT : count;
}

View File

@ -357,7 +357,7 @@ struct device *acpi_get_physical_device(acpi_handle);
/* helper */
acpi_handle acpi_get_child(acpi_handle, acpi_integer);
acpi_handle acpi_get_pci_rootbridge_handle(unsigned int, unsigned int);
#define DEVICE_ACPI_HANDLE(dev) ((acpi_handle)((dev)->firmware_data))
#define DEVICE_ACPI_HANDLE(dev) ((acpi_handle)((dev)->archdata.acpi_handle))
#endif /* CONFIG_ACPI */

View File

@ -0,0 +1,7 @@
/*
* Arch specific extensions to struct device
*
* This file is released under the GPLv2
*/
#include <asm-generic/device.h>

7
include/asm-arm/device.h Normal file
View File

@ -0,0 +1,7 @@
/*
* Arch specific extensions to struct device
*
* This file is released under the GPLv2
*/
#include <asm-generic/device.h>

View File

@ -0,0 +1,7 @@
/*
* Arch specific extensions to struct device
*
* This file is released under the GPLv2
*/
#include <asm-generic/device.h>

View File

@ -0,0 +1,7 @@
/*
* Arch specific extensions to struct device
*
* This file is released under the GPLv2
*/
#include <asm-generic/device.h>

View File

@ -0,0 +1,7 @@
/*
* Arch specific extensions to struct device
*
* This file is released under the GPLv2
*/
#include <asm-generic/device.h>

7
include/asm-frv/device.h Normal file
View File

@ -0,0 +1,7 @@
/*
* Arch specific extensions to struct device
*
* This file is released under the GPLv2
*/
#include <asm-generic/device.h>

View File

@ -0,0 +1,12 @@
/*
* Arch specific extensions to struct device
*
* This file is released under the GPLv2
*/
#ifndef _ASM_GENERIC_DEVICE_H
#define _ASM_GENERIC_DEVICE_H
struct dev_archdata {
};
#endif /* _ASM_GENERIC_DEVICE_H */

View File

@ -0,0 +1,7 @@
/*
* Arch specific extensions to struct device
*
* This file is released under the GPLv2
*/
#include <asm-generic/device.h>

15
include/asm-i386/device.h Normal file
View File

@ -0,0 +1,15 @@
/*
* Arch specific extensions to struct device
*
* This file is released under the GPLv2
*/
#ifndef _ASM_I386_DEVICE_H
#define _ASM_I386_DEVICE_H
struct dev_archdata {
#ifdef CONFIG_ACPI
void *acpi_handle;
#endif
};
#endif /* _ASM_I386_DEVICE_H */

15
include/asm-ia64/device.h Normal file
View File

@ -0,0 +1,15 @@
/*
* Arch specific extensions to struct device
*
* This file is released under the GPLv2
*/
#ifndef _ASM_IA64_DEVICE_H
#define _ASM_IA64_DEVICE_H
struct dev_archdata {
#ifdef CONFIG_ACPI
void *acpi_handle;
#endif
};
#endif /* _ASM_IA64_DEVICE_H */

View File

@ -0,0 +1,7 @@
/*
* Arch specific extensions to struct device
*
* This file is released under the GPLv2
*/
#include <asm-generic/device.h>

View File

@ -0,0 +1,7 @@
/*
* Arch specific extensions to struct device
*
* This file is released under the GPLv2
*/
#include <asm-generic/device.h>

View File

@ -0,0 +1,7 @@
/*
* Arch specific extensions to struct device
*
* This file is released under the GPLv2
*/
#include <asm-generic/device.h>

View File

@ -0,0 +1,7 @@
/*
* Arch specific extensions to struct device
*
* This file is released under the GPLv2
*/
#include <asm-generic/device.h>

View File

@ -0,0 +1,7 @@
/*
* Arch specific extensions to struct device
*
* This file is released under the GPLv2
*/
#include <asm-generic/device.h>

View File

@ -0,0 +1,7 @@
/*
* Arch specific extensions to struct device
*
* This file is released under the GPLv2
*/
#include <asm-generic/device.h>

7
include/asm-ppc/device.h Normal file
View File

@ -0,0 +1,7 @@
/*
* Arch specific extensions to struct device
*
* This file is released under the GPLv2
*/
#include <asm-generic/device.h>

View File

@ -0,0 +1,7 @@
/*
* Arch specific extensions to struct device
*
* This file is released under the GPLv2
*/
#include <asm-generic/device.h>

7
include/asm-sh/device.h Normal file
View File

@ -0,0 +1,7 @@
/*
* Arch specific extensions to struct device
*
* This file is released under the GPLv2
*/
#include <asm-generic/device.h>

View File

@ -0,0 +1,7 @@
/*
* Arch specific extensions to struct device
*
* This file is released under the GPLv2
*/
#include <asm-generic/device.h>

View File

@ -0,0 +1,7 @@
/*
* Arch specific extensions to struct device
*
* This file is released under the GPLv2
*/
#include <asm-generic/device.h>

View File

@ -0,0 +1,7 @@
/*
* Arch specific extensions to struct device
*
* This file is released under the GPLv2
*/
#include <asm-generic/device.h>

7
include/asm-um/device.h Normal file
View File

@ -0,0 +1,7 @@
/*
* Arch specific extensions to struct device
*
* This file is released under the GPLv2
*/
#include <asm-generic/device.h>

View File

@ -0,0 +1,7 @@
/*
* Arch specific extensions to struct device
*
* This file is released under the GPLv2
*/
#include <asm-generic/device.h>

View File

@ -0,0 +1,15 @@
/*
* Arch specific extensions to struct device
*
* This file is released under the GPLv2
*/
#ifndef _ASM_X86_64_DEVICE_H
#define _ASM_X86_64_DEVICE_H
struct dev_archdata {
#ifdef CONFIG_ACPI
void *acpi_handle;
#endif
};
#endif /* _ASM_X86_64_DEVICE_H */

View File

@ -0,0 +1,7 @@
/*
* Arch specific extensions to struct device
*
* This file is released under the GPLv2
*/
#include <asm-generic/device.h>

View File

@ -21,6 +21,7 @@
#include <linux/pm.h>
#include <asm/semaphore.h>
#include <asm/atomic.h>
#include <asm/device.h>
#define DEVICE_NAME_SIZE 50
#define DEVICE_NAME_HALF __stringify(20) /* Less than half to accommodate slop */
@ -42,6 +43,8 @@ struct bus_type {
struct klist klist_devices;
struct klist klist_drivers;
struct blocking_notifier_head bus_notifier;
struct bus_attribute * bus_attrs;
struct device_attribute * dev_attrs;
struct driver_attribute * drv_attrs;
@ -75,6 +78,29 @@ int __must_check bus_for_each_drv(struct bus_type *bus,
struct device_driver *start, void *data,
int (*fn)(struct device_driver *, void *));
/*
* Bus notifiers: Get notified of addition/removal of devices
* and binding/unbinding of drivers to devices.
* In the long run, it should be a replacement for the platform
* notify hooks.
*/
struct notifier_block;
extern int bus_register_notifier(struct bus_type *bus,
struct notifier_block *nb);
extern int bus_unregister_notifier(struct bus_type *bus,
struct notifier_block *nb);
/* All 4 notifers below get called with the target struct device *
* as an argument. Note that those functions are likely to be called
* with the device semaphore held in the core, so be careful.
*/
#define BUS_NOTIFY_ADD_DEVICE 0x00000001 /* device added */
#define BUS_NOTIFY_DEL_DEVICE 0x00000002 /* device removed */
#define BUS_NOTIFY_BOUND_DRIVER 0x00000003 /* driver bound to device */
#define BUS_NOTIFY_UNBIND_DRIVER 0x00000004 /* driver about to be
unbound */
/* driverfs interface for exporting bus attributes */
struct bus_attribute {
@ -343,8 +369,6 @@ struct device {
void *driver_data; /* data private to the driver */
void *platform_data; /* Platform specific data, device
core doesn't touch it */
void *firmware_data; /* Firmware specific data (e.g. ACPI,
BIOS data),reserved for device core*/
struct dev_pm_info power;
u64 *dma_mask; /* dma mask (if dma'able device) */
@ -358,6 +382,8 @@ struct device {
struct dma_coherent_mem *dma_mem; /* internal for coherent mem
override */
/* arch specific additions */
struct dev_archdata archdata;
/* class_device migration path */
struct list_head node;
@ -395,7 +421,10 @@ extern int __must_check device_add(struct device * dev);
extern void device_del(struct device * dev);
extern int device_for_each_child(struct device *, void *,
int (*fn)(struct device *, void *));
extern struct device *device_find_child(struct device *, void *data,
int (*match)(struct device *, void *));
extern int device_rename(struct device *dev, char *new_name);
extern int device_move(struct device *dev, struct device *new_parent);
/*
* Manual binding of a device to driver. See drivers/base/bus.c
@ -415,8 +444,6 @@ extern struct device *device_create(struct class *cls, struct device *parent,
__attribute__((format(printf,4,5)));
extern void device_destroy(struct class *cls, dev_t devt);
extern int virtual_device_parent(struct device *dev);
/*
* Platform "fixup" functions - allow the platform to have their say
* about devices and actions that the general device layer doesn't

View File

@ -774,8 +774,8 @@ struct fb_info {
#endif
struct fb_ops *fbops;
struct device *device;
struct class_device *class_device; /* sysfs per device attrs */
struct device *device; /* This is the parent */
struct device *dev; /* This is this fb device */
int class_flag; /* private sysfs flags */
#ifdef CONFIG_FB_TILEBLITTING
struct fb_tile_ops *tileops; /* Tile Blitting */
@ -910,8 +910,8 @@ static inline void __fb_pad_aligned_buffer(u8 *dst, u32 d_pitch,
/* drivers/video/fbsysfs.c */
extern struct fb_info *framebuffer_alloc(size_t size, struct device *dev);
extern void framebuffer_release(struct fb_info *info);
extern int fb_init_class_device(struct fb_info *fb_info);
extern void fb_cleanup_class_device(struct fb_info *head);
extern int fb_init_device(struct fb_info *fb_info);
extern void fb_cleanup_device(struct fb_info *head);
extern void fb_bl_default_curve(struct fb_info *fb_info, u8 off, u8 min, u8 max);
/* drivers/video/fbmon.c */

View File

@ -47,6 +47,7 @@ enum kobject_action {
KOBJ_UMOUNT = (__force kobject_action_t) 0x05, /* umount event for block devices (broken) */
KOBJ_OFFLINE = (__force kobject_action_t) 0x06, /* device offline */
KOBJ_ONLINE = (__force kobject_action_t) 0x07, /* device online */
KOBJ_MOVE = (__force kobject_action_t) 0x08, /* device move */
};
struct kobject {
@ -76,6 +77,7 @@ extern int __must_check kobject_add(struct kobject *);
extern void kobject_del(struct kobject *);
extern int __must_check kobject_rename(struct kobject *, const char *new_name);
extern int __must_check kobject_move(struct kobject *, struct kobject *);
extern int __must_check kobject_register(struct kobject *);
extern void kobject_unregister(struct kobject *);
@ -264,6 +266,8 @@ extern int __must_check subsys_create_file(struct subsystem * ,
#if defined(CONFIG_HOTPLUG)
void kobject_uevent(struct kobject *kobj, enum kobject_action action);
void kobject_uevent_env(struct kobject *kobj, enum kobject_action action,
char *envp[]);
int add_uevent_var(char **envp, int num_envp, int *cur_index,
char *buffer, int buffer_size, int *cur_len,
@ -271,6 +275,10 @@ int add_uevent_var(char **envp, int num_envp, int *cur_index,
__attribute__((format (printf, 7, 8)));
#else
static inline void kobject_uevent(struct kobject *kobj, enum kobject_action action) { }
static inline void kobject_uevent_env(struct kobject *kobj,
enum kobject_action action,
char *envp[])
{ }
static inline int add_uevent_var(char **envp, int num_envp, int *cur_index,
char *buffer, int buffer_size, int *cur_len,

View File

@ -31,15 +31,14 @@
#define HPET_MINOR 228
struct device;
struct class_device;
struct miscdevice {
int minor;
const char *name;
const struct file_operations *fops;
struct list_head list;
struct device *dev;
struct class_device *class;
struct device *parent;
struct device *this_device;
};
extern int misc_register(struct miscdevice * misc);

View File

@ -74,8 +74,8 @@ struct mmc_card;
struct device;
struct mmc_host {
struct device *dev;
struct class_device class_dev;
struct device *parent;
struct device class_dev;
int index;
const struct mmc_host_ops *ops;
unsigned int f_min;
@ -125,8 +125,8 @@ static inline void *mmc_priv(struct mmc_host *host)
return (void *)host->private;
}
#define mmc_dev(x) ((x)->dev)
#define mmc_hostname(x) ((x)->class_dev.class_id)
#define mmc_dev(x) ((x)->parent)
#define mmc_hostname(x) ((x)->class_dev.bus_id)
extern int mmc_suspend_host(struct mmc_host *, pm_message_t);
extern int mmc_resume_host(struct mmc_host *);

View File

@ -264,6 +264,7 @@ struct module
struct module_attribute *modinfo_attrs;
const char *version;
const char *srcversion;
struct kobject *drivers_dir;
/* Exported symbols */
const struct kernel_symbol *syms;

View File

@ -58,6 +58,12 @@ struct platform_driver {
extern int platform_driver_register(struct platform_driver *);
extern void platform_driver_unregister(struct platform_driver *);
/* non-hotpluggable platform devices may use this so that probe() and
* its support may live in __init sections, conserving runtime memory.
*/
extern int platform_driver_probe(struct platform_driver *driver,
int (*probe)(struct platform_device *));
#define platform_get_drvdata(_dev) dev_get_drvdata(&(_dev)->dev)
#define platform_set_drvdata(_dev,data) dev_set_drvdata(&(_dev)->dev, (data))

View File

@ -96,6 +96,9 @@ sysfs_remove_dir(struct kobject *);
extern int __must_check
sysfs_rename_dir(struct kobject *, const char *new_name);
extern int __must_check
sysfs_move_dir(struct kobject *, struct kobject *);
extern int __must_check
sysfs_create_file(struct kobject *, const struct attribute *);
@ -142,6 +145,11 @@ static inline int sysfs_rename_dir(struct kobject * k, const char *new_name)
return 0;
}
static inline int sysfs_move_dir(struct kobject * k, struct kobject * new_parent)
{
return 0;
}
static inline int sysfs_create_file(struct kobject * k, const struct attribute * a)
{
return 0;

View File

@ -276,9 +276,8 @@ extern int tty_register_ldisc(int disc, struct tty_ldisc *new_ldisc);
extern int tty_unregister_ldisc(int disc);
extern int tty_register_driver(struct tty_driver *driver);
extern int tty_unregister_driver(struct tty_driver *driver);
extern struct class_device *tty_register_device(struct tty_driver *driver,
unsigned index,
struct device *dev);
extern struct device *tty_register_device(struct tty_driver *driver,
unsigned index, struct device *dev);
extern void tty_unregister_device(struct tty_driver *driver, unsigned index);
extern int tty_read_raw_data(struct tty_struct *tty, unsigned char *bufp,
int buflen);

View File

@ -132,6 +132,7 @@ struct snd_card {
int shutdown; /* this card is going down */
int free_on_last_close; /* free in context of file_release */
wait_queue_head_t shutdown_sleep;
struct device *parent;
struct device *dev;
#ifdef CONFIG_PM
@ -187,13 +188,14 @@ struct snd_minor {
int device; /* device number */
const struct file_operations *f_ops; /* file operations */
void *private_data; /* private data for f_ops->open */
struct class_device *class_dev; /* class device for sysfs */
struct device *dev; /* device for sysfs */
};
/* sound.c */
extern int snd_major;
extern int snd_ecards_limit;
extern struct class *sound_class;
void snd_request_card(int card);
@ -203,7 +205,7 @@ int snd_register_device(int type, struct snd_card *card, int dev,
int snd_unregister_device(int type, struct snd_card *card, int dev);
void *snd_lookup_minor_data(unsigned int minor, int type);
int snd_add_device_sysfs_file(int type, struct snd_card *card, int dev,
const struct class_device_attribute *attr);
struct device_attribute *attr);
#ifdef CONFIG_SND_OSSEMUL
int snd_register_oss_device(int type, struct snd_card *card, int dev,
@ -255,7 +257,7 @@ int snd_card_file_add(struct snd_card *card, struct file *file);
int snd_card_file_remove(struct snd_card *card, struct file *file);
#ifndef snd_card_set_dev
#define snd_card_set_dev(card,devptr) ((card)->dev = (devptr))
#define snd_card_set_dev(card,devptr) ((card)->parent = (devptr))
#endif
/* device.c */

View File

@ -249,6 +249,26 @@ config CPUSETS
Say N if unsure.
config SYSFS_DEPRECATED
bool "Create deprecated sysfs files"
default y
help
This option creates deprecated symlinks such as the
"device"-link, the <subsystem>:<name>-link, and the
"bus"-link. It may also add deprecated key in the
uevent environment.
None of these features or values should be used today, as
they export driver core implementation details to userspace
or export properties which can't be kept stable across kernel
releases.
If enabled, this option will also move any device structures
that belong to a class, back into the /sys/class heirachy, in
order to support older versions of udev.
If you are using a distro that was released in 2006 or later,
it should be safe to say N here.
config RELAY
bool "Kernel->user space relay support (formerly relayfs)"
help

View File

@ -1086,22 +1086,35 @@ static int mod_sysfs_setup(struct module *mod,
goto out;
kobj_set_kset_s(&mod->mkobj, module_subsys);
mod->mkobj.mod = mod;
err = kobject_register(&mod->mkobj.kobj);
/* delay uevent until full sysfs population */
kobject_init(&mod->mkobj.kobj);
err = kobject_add(&mod->mkobj.kobj);
if (err)
goto out;
mod->drivers_dir = kobject_add_dir(&mod->mkobj.kobj, "drivers");
if (!mod->drivers_dir)
goto out_unreg;
err = module_param_sysfs_setup(mod, kparam, num_params);
if (err)
goto out_unreg;
goto out_unreg_drivers;
err = module_add_modinfo_attrs(mod);
if (err)
goto out_unreg;
goto out_unreg_param;
kobject_uevent(&mod->mkobj.kobj, KOBJ_ADD);
return 0;
out_unreg_drivers:
kobject_unregister(mod->drivers_dir);
out_unreg_param:
module_param_sysfs_remove(mod);
out_unreg:
kobject_unregister(&mod->mkobj.kobj);
kobject_del(&mod->mkobj.kobj);
kobject_put(&mod->mkobj.kobj);
out:
return err;
}
@ -1110,6 +1123,7 @@ static void mod_kobject_remove(struct module *mod)
{
module_remove_modinfo_attrs(mod);
module_param_sysfs_remove(mod);
kobject_unregister(mod->drivers_dir);
kobject_unregister(&mod->mkobj.kobj);
}
@ -2275,11 +2289,14 @@ void print_modules(void)
void module_add_driver(struct module *mod, struct device_driver *drv)
{
int no_warn;
if (!mod || !drv)
return;
/* Don't check return code; this call is idempotent */
sysfs_create_link(&drv->kobj, &mod->mkobj.kobj, "module");
/* Don't check return codes; these calls are idempotent */
no_warn = sysfs_create_link(&drv->kobj, &mod->mkobj.kobj, "module");
no_warn = sysfs_create_link(mod->drivers_dir, &drv->kobj, drv->name);
}
EXPORT_SYMBOL(module_add_driver);
@ -2288,6 +2305,8 @@ void module_remove_driver(struct device_driver *drv)
if (!drv)
return;
sysfs_remove_link(&drv->kobj, "module");
if (drv->owner && drv->owner->drivers_dir)
sysfs_remove_link(drv->owner->drivers_dir, drv->name);
}
EXPORT_SYMBOL(module_remove_driver);

View File

@ -310,6 +310,56 @@ int kobject_rename(struct kobject * kobj, const char *new_name)
return error;
}
/**
* kobject_move - move object to another parent
* @kobj: object in question.
* @new_parent: object's new parent
*/
int kobject_move(struct kobject *kobj, struct kobject *new_parent)
{
int error;
struct kobject *old_parent;
const char *devpath = NULL;
char *devpath_string = NULL;
char *envp[2];
kobj = kobject_get(kobj);
if (!kobj)
return -EINVAL;
new_parent = kobject_get(new_parent);
if (!new_parent) {
error = -EINVAL;
goto out;
}
/* old object path */
devpath = kobject_get_path(kobj, GFP_KERNEL);
if (!devpath) {
error = -ENOMEM;
goto out;
}
devpath_string = kmalloc(strlen(devpath) + 15, GFP_KERNEL);
if (!devpath_string) {
error = -ENOMEM;
goto out;
}
sprintf(devpath_string, "DEVPATH_OLD=%s", devpath);
envp[0] = devpath_string;
envp[1] = NULL;
error = sysfs_move_dir(kobj, new_parent);
if (error)
goto out;
old_parent = kobj->parent;
kobj->parent = new_parent;
kobject_put(old_parent);
kobject_uevent_env(kobj, KOBJ_MOVE, envp);
out:
kobject_put(kobj);
kfree(devpath_string);
kfree(devpath);
return error;
}
/**
* kobject_del - unlink kobject from hierarchy.
* @kobj: object.

View File

@ -50,18 +50,22 @@ static char *action_to_string(enum kobject_action action)
return "offline";
case KOBJ_ONLINE:
return "online";
case KOBJ_MOVE:
return "move";
default:
return NULL;
}
}
/**
* kobject_uevent - notify userspace by ending an uevent
* kobject_uevent_env - send an uevent with environmental data
*
* @action: action that is happening (usually KOBJ_ADD and KOBJ_REMOVE)
* @action: action that is happening (usually KOBJ_MOVE)
* @kobj: struct kobject that the action is happening to
* @envp_ext: pointer to environmental data
*/
void kobject_uevent(struct kobject *kobj, enum kobject_action action)
void kobject_uevent_env(struct kobject *kobj, enum kobject_action action,
char *envp_ext[])
{
char **envp;
char *buffer;
@ -76,6 +80,7 @@ void kobject_uevent(struct kobject *kobj, enum kobject_action action)
char *seq_buff;
int i = 0;
int retval;
int j;
pr_debug("%s\n", __FUNCTION__);
@ -134,7 +139,8 @@ void kobject_uevent(struct kobject *kobj, enum kobject_action action)
scratch += sprintf (scratch, "DEVPATH=%s", devpath) + 1;
envp [i++] = scratch;
scratch += sprintf(scratch, "SUBSYSTEM=%s", subsystem) + 1;
for (j = 0; envp_ext && envp_ext[j]; j++)
envp[i++] = envp_ext[j];
/* just reserve the space, overwrite it after kset call has returned */
envp[i++] = seq_buff = scratch;
scratch += strlen("SEQNUM=18446744073709551616") + 1;
@ -200,6 +206,20 @@ exit:
kfree(envp);
return;
}
EXPORT_SYMBOL_GPL(kobject_uevent_env);
/**
* kobject_uevent - notify userspace by ending an uevent
*
* @action: action that is happening (usually KOBJ_ADD and KOBJ_REMOVE)
* @kobj: struct kobject that the action is happening to
*/
void kobject_uevent(struct kobject *kobj, enum kobject_action action)
{
kobject_uevent_env(kobj, action, NULL);
}
EXPORT_SYMBOL_GPL(kobject_uevent);
/**

View File

@ -361,6 +361,8 @@ static int snd_card_do_free(struct snd_card *card)
snd_printk(KERN_WARNING "unable to free card info\n");
/* Not fatal error */
}
if (card->dev)
device_unregister(card->dev);
kfree(card);
return 0;
}
@ -495,6 +497,12 @@ int snd_card_register(struct snd_card *card)
int err;
snd_assert(card != NULL, return -EINVAL);
if (!card->dev) {
card->dev = device_create(sound_class, card->parent, 0,
"card%i", card->number);
if (IS_ERR(card->dev))
card->dev = NULL;
}
if ((err = snd_device_register_all(card)) < 0)
return err;
mutex_lock(&snd_card_mutex);

View File

@ -910,7 +910,8 @@ void snd_pcm_detach_substream(struct snd_pcm_substream *substream)
substream->pstr->substream_opened--;
}
static ssize_t show_pcm_class(struct class_device *class_device, char *buf)
static ssize_t show_pcm_class(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct snd_pcm *pcm;
const char *str;
@ -921,7 +922,7 @@ static ssize_t show_pcm_class(struct class_device *class_device, char *buf)
[SNDRV_PCM_CLASS_DIGITIZER] = "digitizer",
};
if (! (pcm = class_get_devdata(class_device)) ||
if (! (pcm = dev_get_drvdata(dev)) ||
pcm->dev_class > SNDRV_PCM_CLASS_LAST)
str = "none";
else
@ -929,7 +930,7 @@ static ssize_t show_pcm_class(struct class_device *class_device, char *buf)
return snprintf(buf, PAGE_SIZE, "%s\n", str);
}
static struct class_device_attribute pcm_attrs =
static struct device_attribute pcm_attrs =
__ATTR(pcm_class, S_IRUGO, show_pcm_class, NULL);
static int snd_pcm_dev_register(struct snd_device *device)

View File

@ -61,9 +61,6 @@ EXPORT_SYMBOL(snd_ecards_limit);
static struct snd_minor *snd_minors[SNDRV_OS_MINORS];
static DEFINE_MUTEX(sound_mutex);
extern struct class *sound_class;
#ifdef CONFIG_KMOD
/**
@ -268,11 +265,10 @@ int snd_register_device(int type, struct snd_card *card, int dev,
snd_minors[minor] = preg;
if (card)
device = card->dev;
preg->class_dev = class_device_create(sound_class, NULL,
MKDEV(major, minor),
device, "%s", name);
if (preg->class_dev)
class_set_devdata(preg->class_dev, private_data);
preg->dev = device_create(sound_class, device, MKDEV(major, minor),
"%s", name);
if (preg->dev)
dev_set_drvdata(preg->dev, private_data);
mutex_unlock(&sound_mutex);
return 0;
@ -320,7 +316,7 @@ int snd_unregister_device(int type, struct snd_card *card, int dev)
return -EINVAL;
}
class_device_destroy(sound_class, MKDEV(major, minor));
device_destroy(sound_class, MKDEV(major, minor));
kfree(snd_minors[minor]);
snd_minors[minor] = NULL;
@ -331,15 +327,15 @@ int snd_unregister_device(int type, struct snd_card *card, int dev)
EXPORT_SYMBOL(snd_unregister_device);
int snd_add_device_sysfs_file(int type, struct snd_card *card, int dev,
const struct class_device_attribute *attr)
struct device_attribute *attr)
{
int minor, ret = -EINVAL;
struct class_device *cdev;
struct device *d;
mutex_lock(&sound_mutex);
minor = find_snd_minor(type, card, dev);
if (minor >= 0 && (cdev = snd_minors[minor]->class_dev) != NULL)
ret = class_device_create_file(cdev, attr);
if (minor >= 0 && (d = snd_minors[minor]->dev) != NULL)
ret = device_create_file(d, attr);
mutex_unlock(&sound_mutex);
return ret;

View File

@ -557,17 +557,17 @@ static int __init oss_init(void)
sound_dmap_flag = (dmabuf > 0 ? 1 : 0);
for (i = 0; i < sizeof (dev_list) / sizeof *dev_list; i++) {
class_device_create(sound_class, NULL,
MKDEV(SOUND_MAJOR, dev_list[i].minor),
NULL, "%s", dev_list[i].name);
device_create(sound_class, NULL,
MKDEV(SOUND_MAJOR, dev_list[i].minor),
"%s", dev_list[i].name);
if (!dev_list[i].num)
continue;
for (j = 1; j < *dev_list[i].num; j++)
class_device_create(sound_class, NULL,
MKDEV(SOUND_MAJOR, dev_list[i].minor + (j*0x10)),
NULL, "%s%d", dev_list[i].name, j);
device_create(sound_class, NULL,
MKDEV(SOUND_MAJOR, dev_list[i].minor + (j*0x10)),
"%s%d", dev_list[i].name, j);
}
if (sound_nblocks >= 1024)
@ -581,11 +581,11 @@ static void __exit oss_cleanup(void)
int i, j;
for (i = 0; i < sizeof (dev_list) / sizeof *dev_list; i++) {
class_device_destroy(sound_class, MKDEV(SOUND_MAJOR, dev_list[i].minor));
device_destroy(sound_class, MKDEV(SOUND_MAJOR, dev_list[i].minor));
if (!dev_list[i].num)
continue;
for (j = 1; j < *dev_list[i].num; j++)
class_device_destroy(sound_class, MKDEV(SOUND_MAJOR, dev_list[i].minor + (j*0x10)));
device_destroy(sound_class, MKDEV(SOUND_MAJOR, dev_list[i].minor + (j*0x10)));
}
unregister_sound_special(1);

View File

@ -170,8 +170,8 @@ static int sound_insert_unit(struct sound_unit **list, const struct file_operati
else
sprintf(s->name, "sound/%s%d", name, r / SOUND_STEP);
class_device_create(sound_class, NULL, MKDEV(SOUND_MAJOR, s->unit_minor),
dev, s->name+6);
device_create(sound_class, dev, MKDEV(SOUND_MAJOR, s->unit_minor),
s->name+6);
return r;
fail:
@ -193,7 +193,7 @@ static void sound_remove_unit(struct sound_unit **list, int unit)
p = __sound_remove_unit(list, unit);
spin_unlock(&sound_loader_lock);
if (p) {
class_device_destroy(sound_class, MKDEV(SOUND_MAJOR, p->unit_minor));
device_destroy(sound_class, MKDEV(SOUND_MAJOR, p->unit_minor));
kfree(p);
}
}