Commit 4549df89 authored by Linus Torvalds's avatar Linus Torvalds

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

* master.kernel.org:/pub/scm/linux/kernel/git/gregkh/driver-2.6: (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
  ...
parents 6b8cc71a e17e0f51
Platform Devices and Drivers 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
~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~
Platform devices are devices that typically appear as autonomous Platform devices are devices that typically appear as autonomous
entities in the system. This includes legacy port-based devices and 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
Platform drivers be connected through a segment of some other kind of bus; but its
~~~~~~~~~~~~~~~~ registers will still be directly addressible.
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 devices are given a name, used in driver binding, and a
list of resources such as addresses and IRQs.
Other Architectures, Modern Firmware, and new Platforms struct platform_device {
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ const char *name;
These devices are not always at the legacy I/O ports. This is true on u32 id;
other architectures and on some modern architectures. In most cases, struct device dev;
the drivers are modified to discover the devices at other well-known u32 num_resources;
ports for the given platform. However, the firmware in these systems struct resource *resource;
does usually know where exactly these devices reside, and in some };
cases, it's the only way of discovering them.
The Platform Bus Platform drivers
~~~~~~~~~~~~~~~~
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.
But, besides the organizational benefits, the platform bus can also
accommodate firmware-based enumeration.
Device Discovery
~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~
The platform bus has no concept of probing for devices. Devices Platform drivers follow the standard driver model convention, where
discovery is left up to either the legacy drivers or the discovery/enumeration is handled outside the drivers, and drivers
firmware. These entities are expected to notify the platform of provide probe() and remove() methods. They support power management
devices that it discovers via the bus's add() callback: and shutdown notifications using the standard conventions.
platform_bus.add(parent,bus_id). struct platform_driver {
int (*probe)(struct platform_device *);
int (*remove)(struct platform_device *);
Bus IDs void (*shutdown)(struct platform_device *);
~~~~~~~ int (*suspend)(struct platform_device *, pm_message_t state);
Bus IDs are the canonical names for the devices. There is no globally int (*suspend_late)(struct platform_device *, pm_message_t state);
standard addressing mechanism for legacy devices. In the IA-32 world, int (*resume_early)(struct platform_device *);
we have Pnp IDs to use, as well as the legacy I/O ports. However, int (*resume)(struct platform_device *);
neither tell what the device really is or have any meaning on other struct device_driver driver;
platforms. };
Since both PnP IDs and the legacy I/O ports (and other standard I/O Note that probe() should general verify that the specified device hardware
ports for specific devices) have a 1:1 mapping, we map the actually exists; sometimes platform setup code can't be sure. The probing
platform-specific name or identifier to a generic name (at least can use device resources, including clocks, and device platform_data.
within the scope of the kernel).
Platform drivers register themselves the normal way:
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) int platform_driver_register(struct platform_driver *drv);
PNP0501. Both correspond to the same device and should be mapped to the
canonical name 'serial'. 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
The bus_id field should be a concatenation of the canonical name and runtime memory footprint:
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 int platform_driver_probe(struct platform_driver *drv,
responsibility of enumerating devices of a particular type up to the int (*probe)(struct platform_device *))
discovery mechanism. But, they are the entity that should know best
(as opposed to the platform bus driver).
Device Enumeration
~~~~~~~~~~~~~~~~~~
Drivers As a rule, platform specific (and often board-specific) setup code wil
~~~~~~~ register platform devices:
Drivers for platform devices should have a name that is the same as
the canonical name of the devices they support. This allows the int platform_device_register(struct platform_device *pdev);
platform bus driver to do simple matching with the basic data
structures to determine if a driver supports a certain device. int platform_add_devices(struct platform_device **pdevs, int ndev);
For example, a legacy serial driver should have a name of 'serial' and The general rule is to register only those devices that actually exist,
register itself with the platform bus. 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
Driver Binding that some boards might not hook up to any peripherals.
~~~~~~~~~~~~~~
Legacy drivers assume they are bound to the device once they start up In some cases, boot firmware will export tables describing the devices
and probe an I/O port. Divorcing them from this will be a difficult that are populated on a given board. Without such tables, often the
process. However, that shouldn't prevent us from implementing only way for system setup code to set up the correct devices is to build
firmware-based enumeration. a kernel for a specific target board. Such board-specific kernels are
common with embedded and custom systems development.
The firmware should notify the platform bus about devices before the
legacy drivers have had a chance to load. Once the drivers are loaded, In many cases, the memory and IRQ resources associated with the platform
they driver model core will attempt to bind the driver to any device are not enough to let the device's driver work. Board setup code
previously-discovered devices. Once that has happened, it will be free will often provide additional information using the device's platform_data
to discover any other devices it pleases. 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.
Device Naming and Driver Binding
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The platform_device.dev.bus_id is the canonical name for the devices.
It's built from two components:
* 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.
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".
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.
- 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.
- 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.)
...@@ -156,14 +156,14 @@ static struct file_operations cpuid_fops = { ...@@ -156,14 +156,14 @@ static struct file_operations cpuid_fops = {
.open = cpuid_open, .open = cpuid_open,
}; };
static int cpuid_class_device_create(int i) static int cpuid_device_create(int i)
{ {
int err = 0; 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); dev = device_create(cpuid_class, NULL, MKDEV(CPUID_MAJOR, i), "cpu%d",i);
if (IS_ERR(class_err)) if (IS_ERR(dev))
err = PTR_ERR(class_err); err = PTR_ERR(dev);
return err; return err;
} }
...@@ -174,10 +174,10 @@ static int cpuid_class_cpu_callback(struct notifier_block *nfb, unsigned long ac ...@@ -174,10 +174,10 @@ static int cpuid_class_cpu_callback(struct notifier_block *nfb, unsigned long ac
switch (action) { switch (action) {
case CPU_ONLINE: case CPU_ONLINE:
cpuid_class_device_create(cpu); cpuid_device_create(cpu);
break; break;
case CPU_DEAD: case CPU_DEAD:
class_device_destroy(cpuid_class, MKDEV(CPUID_MAJOR, cpu)); device_destroy(cpuid_class, MKDEV(CPUID_MAJOR, cpu));
break; break;
} }
return NOTIFY_OK; return NOTIFY_OK;
...@@ -206,7 +206,7 @@ static int __init cpuid_init(void) ...@@ -206,7 +206,7 @@ static int __init cpuid_init(void)
goto out_chrdev; goto out_chrdev;
} }
for_each_online_cpu(i) { for_each_online_cpu(i) {
err = cpuid_class_device_create(i); err = cpuid_device_create(i);
if (err != 0) if (err != 0)
goto out_class; goto out_class;
} }
...@@ -218,7 +218,7 @@ static int __init cpuid_init(void) ...@@ -218,7 +218,7 @@ static int __init cpuid_init(void)
out_class: out_class:
i = 0; i = 0;
for_each_online_cpu(i) { 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); class_destroy(cpuid_class);
out_chrdev: out_chrdev:
...@@ -232,7 +232,7 @@ static void __exit cpuid_exit(void) ...@@ -232,7 +232,7 @@ static void __exit cpuid_exit(void)
int cpu = 0; int cpu = 0;
for_each_online_cpu(cpu) 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); class_destroy(cpuid_class);
unregister_chrdev(CPUID_MAJOR, "cpu/cpuid"); unregister_chrdev(CPUID_MAJOR, "cpu/cpuid");
unregister_hotcpu_notifier(&cpuid_class_cpu_notifier); unregister_hotcpu_notifier(&cpuid_class_cpu_notifier);
......
...@@ -239,14 +239,14 @@ static struct file_operations msr_fops = { ...@@ -239,14 +239,14 @@ static struct file_operations msr_fops = {
.open = msr_open, .open = msr_open,
}; };
static int msr_class_device_create(int i) static int msr_device_create(int i)
{ {
int err = 0; 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); dev = device_create(msr_class, NULL, MKDEV(MSR_MAJOR, i), "msr%d",i);
if (IS_ERR(class_err)) if (IS_ERR(dev))
err = PTR_ERR(class_err); err = PTR_ERR(dev);
return err; return err;
} }
...@@ -258,10 +258,10 @@ static int msr_class_cpu_callback(struct notifier_block *nfb, ...@@ -258,10 +258,10 @@ static int msr_class_cpu_callback(struct notifier_block *nfb,
switch (action) { switch (action) {
case CPU_ONLINE: case CPU_ONLINE:
msr_class_device_create(cpu); msr_device_create(cpu);
break; break;
case CPU_DEAD: case CPU_DEAD:
class_device_destroy(msr_class, MKDEV(MSR_MAJOR, cpu)); device_destroy(msr_class, MKDEV(MSR_MAJOR, cpu));
break; break;
} }
return NOTIFY_OK; return NOTIFY_OK;
...@@ -290,7 +290,7 @@ static int __init msr_init(void) ...@@ -290,7 +290,7 @@ static int __init msr_init(void)
goto out_chrdev; goto out_chrdev;
} }
for_each_online_cpu(i) { for_each_online_cpu(i) {
err = msr_class_device_create(i); err = msr_device_create(i);
if (err != 0) if (err != 0)
goto out_class; goto out_class;
} }
...@@ -302,7 +302,7 @@ static int __init msr_init(void) ...@@ -302,7 +302,7 @@ static int __init msr_init(void)
out_class: out_class:
i = 0; i = 0;
for_each_online_cpu(i) 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); class_destroy(msr_class);
out_chrdev: out_chrdev:
unregister_chrdev(MSR_MAJOR, "cpu/msr"); unregister_chrdev(MSR_MAJOR, "cpu/msr");
...@@ -314,7 +314,7 @@ static void __exit msr_exit(void) ...@@ -314,7 +314,7 @@ static void __exit msr_exit(void)
{ {
int cpu = 0; int cpu = 0;
for_each_online_cpu(cpu) 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); class_destroy(msr_class);
unregister_chrdev(MSR_MAJOR, "cpu/msr"); unregister_chrdev(MSR_MAJOR, "cpu/msr");
unregister_hotcpu_notifier(&msr_class_cpu_notifier); unregister_hotcpu_notifier(&msr_class_cpu_notifier);
......
...@@ -267,9 +267,9 @@ static int acpi_bind_one(struct device *dev, acpi_handle handle) ...@@ -267,9 +267,9 @@ static int acpi_bind_one(struct device *dev, acpi_handle handle)
{ {
acpi_status status; acpi_status status;
if (dev->firmware_data) { if (dev->archdata.acpi_handle) {
printk(KERN_WARNING PREFIX 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; return -EINVAL;
} }
get_device(dev); get_device(dev);
...@@ -278,25 +278,26 @@ static int acpi_bind_one(struct device *dev, acpi_handle handle) ...@@ -278,25 +278,26 @@ static int acpi_bind_one(struct device *dev, acpi_handle handle)
put_device(dev); put_device(dev);
return -EINVAL; return -EINVAL;
} }
dev->firmware_data = handle; dev->archdata.acpi_handle = handle;
return 0; return 0;
} }
static int acpi_unbind_one(struct device *dev) static int acpi_unbind_one(struct device *dev)
{ {
if (!dev->firmware_data) if (!dev->archdata.acpi_handle)
return 0; 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 */ /* acpi_get_physical_device increase refcnt by one */
put_device(dev); put_device(dev);
acpi_detach_data(dev->firmware_data, acpi_glue_data_handler); acpi_detach_data(dev->archdata.acpi_handle,
dev->firmware_data = NULL; acpi_glue_data_handler);
dev->archdata.acpi_handle = NULL;
/* acpi_bind_one increase refcnt by one */ /* acpi_bind_one increase refcnt by one */
put_device(dev); put_device(dev);
} else { } else {
printk(KERN_ERR PREFIX 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; return 0;
} }
...@@ -328,7 +329,8 @@ static int acpi_platform_notify(struct device *dev) ...@@ -328,7 +329,8 @@ static int acpi_platform_notify(struct device *dev)
if (!ret) { if (!ret) {
struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; 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); DBG("Device %s -> %s\n", dev->bus_id, (char *)buffer.pointer);
kfree(buffer.pointer); kfree(buffer.pointer);
} else } else
......
...@@ -355,6 +355,21 @@ static void device_remove_attrs(struct bus_type * bus, struct device * dev) ...@@ -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 * bus_add_device - add device to bus
...@@ -381,8 +396,7 @@ int bus_add_device(struct device * dev) ...@@ -381,8 +396,7 @@ int bus_add_device(struct device * dev)
&dev->bus->subsys.kset.kobj, "subsystem"); &dev->bus->subsys.kset.kobj, "subsystem");
if (error) if (error)
goto out_subsys; goto out_subsys;
error = sysfs_create_link(&dev->kobj, error = make_deprecated_bus_links(dev);
&dev->bus->subsys.kset.kobj, "bus");
if (error) if (error)
goto out_deprecated; goto out_deprecated;
} }
...@@ -436,7 +450,7 @@ void bus_remove_device(struct device * dev) ...@@ -436,7 +450,7 @@ void bus_remove_device(struct device * dev)
{ {
if (dev->bus) { if (dev->bus) {
sysfs_remove_link(&dev->kobj, "subsystem"); 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); sysfs_remove_link(&dev->bus->devices.kobj, dev->bus_id);
device_remove_attrs(dev->bus, dev); device_remove_attrs(dev->bus, dev);
if (dev->is_registered) { if (dev->is_registered) {
...@@ -724,6 +738,8 @@ int bus_register(struct bus_type * bus) ...@@ -724,6 +738,8 @@ int bus_register(struct bus_type * bus)
{ {
int retval; int retval;
BLOCKING_INIT_NOTIFIER_HEAD(&bus->bus_notifier);
retval = kobject_set_name(&bus->subsys.kset.kobj, "%s", bus->name); retval = kobject_set_name(&bus->subsys.kset.kobj, "%s", bus->name);
if (retval) if (retval)
goto out; goto out;
...@@ -782,6 +798,18 @@ void bus_unregister(struct bus_type * bus) ...@@ -782,6 +798,18 @@ void bus_unregister(struct bus_type * bus)
subsystem_unregister(&bus->subsys); 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) int __init buses_init(void)
{ {
return subsystem_register(&bus_subsys); return subsystem_register(&bus_subsys);
......
...@@ -352,6 +352,92 @@ static const char *class_uevent_name(struct kset *kset, struct kobject *kobj) ...@@ -352,6 +352,92 @@ static const char *class_uevent_name(struct kset *kset, struct kobject *kobj)
return class_dev->class->name; 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, static int class_uevent(struct kset *kset, struct kobject *kobj, char **envp,
int num_envp, char *buffer, int buffer_size) int num_envp, char *buffer, int buffer_size)
{ {
...@@ -362,25 +448,8 @@ static int class_uevent(struct kset *kset, struct kobject *kobj, char **envp, ...@@ -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); pr_debug("%s - name = %s\n", __FUNCTION__, class_dev->class_id);
if (class_dev->dev) { deprecated_class_uevent(envp, num_envp, &i, buffer, buffer_size,
/* add device, backing this class device (deprecated) */ &length, class_dev);
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);
}
if (MAJOR(class_dev->devt)) { if (MAJOR(class_dev->devt)) {
add_uevent_var(envp, num_envp, &i, add_uevent_var(envp, num_envp, &i,
...@@ -506,29 +575,11 @@ void class_device_initialize(struct class_device *class_dev) ...@@ -506,29 +575,11 @@ void class_device_initialize(struct class_device *class_dev)
INIT_LIST_HEAD(&class_dev->node); 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) int class_device_add(struct class_device *class_dev)
{ {
struct class *parent_class = NULL; struct class *parent_class = NULL;
struct class_device *parent_class_dev = NULL; struct class_device *parent_class_dev = NULL;
struct class_interface *class_intf; struct class_interface *class_intf;
char *class_name = NULL;
int error = -EINVAL; int error = -EINVAL;
class_dev = class_device_get(class_dev); class_dev = class_device_get(class_dev);
...@@ -599,19 +650,17 @@ int class_device_add(struct class_device *class_dev) ...@@ -599,19 +650,17 @@ int class_device_add(struct class_device *class_dev)
goto out5; goto out5;
if (class_dev->dev) { if (class_dev->dev) {
class_name = make_class_name(class_dev->class->name,
&class_dev->kobj);
error = sysfs_create_link(&class_dev->kobj, error = sysfs_create_link(&class_dev->kobj,
&class_dev->dev->kobj, "device"); &class_dev->dev->kobj, "device");
if (error) if (error)
goto out6; 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); error = class_device_add_groups(class_dev);
if (error)
goto out7;
error = make_deprecated_class_device_links(class_dev);
if (error) if (error)
goto out8; goto out8;
...@@ -629,8 +678,7 @@ int class_device_add(struct class_device *class_dev) ...@@ -629,8 +678,7 @@ int class_device_add(struct class_device *class_dev)
goto out1; goto out1;
out8: out8:
if (class_dev->dev) class_device_remove_groups(class_dev);
sysfs_remove_link(&class_dev->kobj, class_name);
out7: out7:
if (class_dev->dev) if (class_dev->dev)
sysfs_remove_link(&class_dev->kobj, "device"); sysfs_remove_link(&class_dev->kobj, "device");
...@@ -649,7 +697,6 @@ int class_device_add(struct class_device *class_dev) ...@@ -649,7 +697,6 @@ int class_device_add(struct class_device *class_dev)
class_put(parent_class); class_put(parent_class);
out1: out1:
class_device_put(class_dev); class_device_put(class_dev);
kfree(class_name);
return error; return error;
} }
...@@ -726,7 +773,6 @@ void class_device_del(struct class_device *class_dev) ...@@ -726,7 +773,6 @@ void class_device_del(struct class_device *class_dev)
struct class *parent_class = class_dev->class; struct class *parent_class = class_dev->class;
struct class_device *parent_device = class_dev->parent; struct class_device *parent_device = class_dev->parent;
struct class_interface *class_intf; struct class_interface *class_intf;
char *class_name = NULL;
if (parent_class) { if (parent_class) {
down(&parent_class->sem); down(&parent_class->sem);
...@@ -738,10 +784,8 @@ void class_device_del(struct class_device *class_dev) ...@@ -738,10 +784,8 @@ void class_device_del(struct class_device *class_dev)
} }
if (class_dev->dev) { if (class_dev->dev) {
class_name = make_class_name(class_dev->class->name, remove_deprecated_class_device_links(class_dev);
&class_dev->kobj);
sysfs_remove_link(&class_dev->kobj, "device"); sysfs_remove_link(&class_dev->kobj, "device");
sysfs_remove_link(&class_dev->dev->kobj, class_name);
} }
sysfs_remove_link(&class_dev->kobj, "subsystem"); sysfs_remove_link(&class_dev->kobj, "subsystem");
class_device_remove_file(class_dev, &class_dev->uevent_attr); class_device_remove_file(class_dev, &class_dev->uevent_attr);
...@@ -755,7 +799,6 @@ void class_device_del(struct class_device *class_dev) ...@@ -755,7 +799,6 @@ void class_device_del(struct class_device *class_dev)
class_device_put(parent_device); class_device_put(parent_device);
class_put(parent_class); class_put(parent_class);
kfree(class_name);
} }
void class_device_unregister(struct class_device *class_dev) 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) ...@@ -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, pr_debug("CLASS: renaming '%s' to '%s'\n", class_dev->class_id,
new_name); new_name);
#ifdef CONFIG_SYSFS_DEPRECATED
if (class_dev->dev) if (class_dev->dev)
old_class_name = make_class_name(class_dev->class->name, old_class_name = make_class_name(class_dev->class->name,
&class_dev->kobj); &class_dev->kobj);
#endif
strlcpy(class_dev->class_id, new_name, KOBJ_NAME_LEN); strlcpy(class_dev->class_id, new_name, KOBJ_NAME_LEN);
error = kobject_rename(&class_dev->kobj, new_name); error = kobject_rename(&class_dev->kobj, new_name);
#ifdef CONFIG_SYSFS_DEPRECATED
if (class_dev->dev) { if (class_dev->dev) {
new_class_name = make_class_name(class_dev->class->name, new_class_name = make_class_name(class_dev->class->name,
&class_dev->kobj); &class_dev->kobj);
...@@ -819,6 +865,7 @@ int class_device_rename(struct class_device *class_dev, char *new_name) ...@@ -819,6 +865,7 @@ int class_device_rename(struct class_device *class_dev, char *new_name)
new_class_name); new_class_name);
sysfs_remove_link(&class_dev->dev->kobj, old_class_name); sysfs_remove_link(&class_dev->dev->kobj, old_class_name);
} }
#endif
class_device_put(class_dev); class_device_put(class_dev);
kfree(old_class_name); kfree(old_class_name);
...@@ -893,23 +940,6 @@ void class_interface_unregister(struct class_interface *class_intf) ...@@ -893,23 +940,6 @@ void class_interface_unregister(struct class_interface *class_intf)
class_put(parent); 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 __init classes_init(void)
{ {
int retval; int retval;
......
This diff is collapsed.
...@@ -26,33 +26,28 @@ ...@@ -26,33 +26,28 @@
#define to_drv(node) container_of(node, struct device_driver, kobj.entry) #define to_drv(node) container_of(node, struct device_driver, kobj.entry)
/** static void driver_bound(struct device *dev)
* device_bind_driver - bind a driver to one device.
* @dev: device.
*
* Allow manual attachment of a driver to a device.
* Caller must have already set @dev->driver.
*
* Note that this does not modify the bus reference count
* nor take the bus's rwsem. Please verify those are accounted
* for before calling this. (It is ok to call with no other effort
* from a driver's probe() method.)
*
* This function must be called with @dev->sem held.
*/
int device_bind_driver(struct device *dev)
{ {
int ret;
if (klist_node_attached(&dev->knode_driver)) { if (klist_node_attached(&dev->knode_driver)) {
printk(KERN_WARNING "%s: device %s already bound\n", printk(KERN_WARNING "%s: device %s already bound\n",
__FUNCTION__, kobject_name(&dev->kobj)); __FUNCTION__, kobject_name(&dev->kobj));
return 0; return;
} }
pr_debug("bound device '%s' to driver '%s'\n", pr_debug("bound device '%s' to driver '%s'\n",
dev->bus_id, dev->driver->name); 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); 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, ret = sysfs_create_link(&dev->driver->kobj, &dev->kobj,
kobject_name(&dev->kobj)); kobject_name(&dev->kobj));
if (ret == 0) { if (ret == 0) {
...@@ -65,6 +60,36 @@ int device_bind_driver(struct device *dev) ...@@ -65,6 +60,36 @@ int device_bind_driver(struct device *dev)
return ret; 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.
*
* Allow manual attachment of a driver to a device.
* Caller must have already set @dev->driver.
*
* Note that this does not modify the bus reference count
* nor take the bus's rwsem. Please verify those are accounted
* for before calling this. (It is ok to call with no other effort
* from a driver's probe() method.)
*
* This function must be called with @dev->sem held.
*/
int device_bind_driver(struct device *dev)
{
driver_bound(dev);
return driver_sysfs_add(dev);
}
struct stupid_thread_structure { struct stupid_thread_structure {
struct device_driver *drv; struct device_driver *drv;
struct device *dev; struct device *dev;
...@@ -85,30 +110,32 @@ static int really_probe(void *void_data) ...@@ -85,30 +110,32 @@ static int really_probe(void *void_data)
drv->bus->name, drv->name, dev->bus_id); drv->bus->name, drv->name, dev->bus_id);
dev->driver = drv; 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) { if (dev->bus->probe) {
ret = dev->bus->probe(dev); ret = dev->bus->probe(dev);
if (ret) { if (ret)
dev->driver = NULL;
goto probe_failed; goto probe_failed;
}
} else if (drv->probe) { } else if (drv->probe) {
ret = drv->probe(dev); ret = drv->probe(dev);
if (ret) { if (ret)
dev->driver = NULL;
goto probe_failed; 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; ret = 1;
pr_debug("%s: Bound Device %s to Driver %s\n", pr_debug("%s: Bound Device %s to Driver %s\n",
drv->bus->name, dev->bus_id, drv->name); drv->bus->name, dev->bus_id, drv->name);
goto done; goto done;
probe_failed: probe_failed:
driver_sysfs_remove(dev);
dev->driver = NULL;
if (ret == -ENODEV || ret == -ENXIO) { if (ret == -ENODEV || ret == -ENXIO) {
/* Driver matched, but didn't support device /* Driver matched, but didn't support device
* or device not found. * or device not found.
...@@ -284,10 +311,15 @@ static void __device_release_driver(struct device * dev) ...@@ -284,10 +311,15 @@ static void __device_release_driver(struct device * dev)
drv = dev->driver; drv = dev->driver;
if (drv) { if (drv) {
get_driver(drv); get_driver(drv);
sysfs_remove_link(&drv->kobj, kobject_name(&dev->kobj)); driver_sysfs_remove(dev);
sysfs_remove_link(&dev->kobj, "driver"); sysfs_remove_link(&dev->kobj, "driver");
klist_remove(&dev->knode_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) if (dev->bus && dev->bus->remove)
dev->bus->remove(dev); dev->bus->remove(dev);
else if (drv->remove) else if (drv->remove)
......
...@@ -21,6 +21,8 @@ ...@@ -21,6 +21,8 @@
#include <linux/firmware.h> #include <linux/firmware.h>
#include "base.h" #include "base.h"
#define to_dev(obj) container_of(obj, struct device, kobj)
MODULE_AUTHOR("Manuel Estrada Sainz <ranty@debian.org>"); MODULE_AUTHOR("Manuel Estrada Sainz <ranty@debian.org>");
MODULE_DESCRIPTION("Multi purpose firmware loading support"); MODULE_DESCRIPTION("Multi purpose firmware loading support");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
...@@ -86,12 +88,12 @@ firmware_timeout_store(struct class *class, const char *buf, size_t count) ...@@ -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 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, static int firmware_uevent(struct device *dev, char **envp, int num_envp,
int num_envp, char *buffer, int buffer_size) 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; int i = 0, len = 0;
if (!test_bit(FW_STATUS_READY, &fw_priv->status)) 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, ...@@ -110,21 +112,21 @@ static int firmware_class_uevent(struct class_device *class_dev, char **envp,
static struct class firmware_class = { static struct class firmware_class = {
.name = "firmware", .name = "firmware",
.uevent = firmware_class_uevent, .dev_uevent = firmware_uevent,
.release = fw_class_dev_release, .dev_release = fw_dev_release,
}; };
static ssize_t static ssize_t firmware_loading_show(struct device *dev,
firmware_loading_show(struct class_device *class_dev, char *buf) 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); int loading = test_bit(FW_STATUS_LOADING, &fw_priv->status);
return sprintf(buf, "%d\n", loading); return sprintf(buf, "%d\n", loading);
} }
/** /**
* firmware_loading_store - set value in the 'loading' control file * 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 * @buf: buffer to scan for loading control value
* @count: number of bytes in @buf * @count: number of bytes in @buf
* *
...@@ -134,11 +136,11 @@ firmware_loading_show(struct class_device *class_dev, char *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. * 0: Conclude the load and hand the data to the driver code.
* -1: Conclude the load with an error and discard any written data. * -1: Conclude the load with an error and discard any written data.
**/ **/
static ssize_t static ssize_t firmware_loading_store(struct device *dev,
firmware_loading_store(struct class_device *class_dev, struct device_attribute *attr,
const char *buf, size_t count) 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); int loading = simple_strtol(buf, NULL, 10);
switch (loading) { switch (loading) {
...@@ -174,15 +176,14 @@ firmware_loading_store(struct class_device *class_dev, ...@@ -174,15 +176,14 @@ firmware_loading_store(struct class_device *class_dev,
return count; return count;
} }
static CLASS_DEVICE_ATTR(loading, 0644, static DEVICE_ATTR(loading, 0644, firmware_loading_show, firmware_loading_store);
firmware_loading_show, firmware_loading_store);
static ssize_t static ssize_t
firmware_data_read(struct kobject *kobj, firmware_data_read(struct kobject *kobj,
char *buffer, loff_t offset, size_t count) char *buffer, loff_t offset, size_t count)
{ {
struct class_device *class_dev = to_class_dev(kobj); struct device *dev = to_dev(kobj);
struct firmware_priv *fw_priv = class_get_devdata(class_dev); struct firmware_priv *fw_priv = dev_get_drvdata(dev);
struct firmware *fw; struct firmware *fw;
ssize_t ret_count = count; ssize_t ret_count = count;
...@@ -234,7 +235,7 @@ fw_realloc_buffer(struct firmware_priv *fw_priv, int min_size) ...@@ -234,7 +235,7 @@ fw_realloc_buffer(struct firmware_priv *fw_priv, int min_size)
/** /**
* firmware_data_write - write method for firmware * firmware_data_write - write method for firmware
* @kobj: kobject for the class_device * @kobj: kobject for the device
* @buffer: buffer being written * @buffer: buffer being written
* @offset: buffer offset for write in total data store area * @offset: buffer offset for write in total data store area
* @count: buffer size * @count: buffer size
...@@ -246,8 +247,8 @@ static ssize_t ...@@ -246,8 +247,8 @@ static ssize_t
firmware_data_write(struct kobject *kobj, firmware_data_write(struct kobject *kobj,
char *buffer, loff_t offset, size_t count) char *buffer, loff_t offset, size_t count)
{ {
struct class_device *class_dev = to_class_dev(kobj); struct device *dev = to_dev(kobj);
struct firmware_priv *fw_priv = class_get_devdata(class_dev); struct firmware_priv *fw_priv = dev_get_drvdata(dev);
struct firmware *fw; struct firmware *fw;
ssize_t retval; ssize_t retval;
...@@ -280,13 +281,12 @@ static struct bin_attribute firmware_attr_data_tmpl = { ...@@ -280,13 +281,12 @@ static struct bin_attribute firmware_attr_data_tmpl = {
.write = firmware_data_write, .write = firmware_data_write,
}; };
static void static void fw_dev_release(struct device *dev)
fw_class_dev_release(struct class_device *class_dev)
{ {
struct firmware_priv *fw_priv = class_get_devdata(class_dev); struct firmware_priv *fw_priv = dev_get_drvdata(dev);
kfree(fw_priv); kfree(fw_priv);
kfree(class_dev); kfree(dev);
module_put(THIS_MODULE); module_put(THIS_MODULE);
} }
...@@ -298,26 +298,23 @@ firmware_class_timeout(u_long data) ...@@ -298,26 +298,23 @@ firmware_class_timeout(u_long data)
fw_load_abort(fw_priv); fw_load_abort(fw_priv);
} }
static inline void static inline void fw_setup_device_id(struct device *f_dev, struct device *dev)
fw_setup_class_device_id(struct class_device *class_dev, struct device *dev)
{ {
/* XXX warning we should watch out for name collisions */ /* 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 static int fw_register_device(struct device **dev_p, const char *fw_name,
fw_register_class_device(struct class_device **class_dev_p, struct device *device)
const char *fw_name, struct device *device)
{ {
int retval; int retval;
struct firmware_priv *fw_priv = kzalloc(sizeof(*fw_priv), struct firmware_priv *fw_priv = kzalloc(sizeof(*fw_priv),
GFP_KERNEL); GFP_KERNEL);
struct class_device *class_dev = kzalloc(sizeof(*class_dev), struct device *f_dev = kzalloc(sizeof(*f_dev), GFP_KERNEL);
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__); printk(KERN_ERR "%s: kmalloc failed\n", __FUNCTION__);
retval = -ENOMEM; retval = -ENOMEM;
goto error_kfree; goto error_kfree;
...@@ -331,55 +328,54 @@ fw_register_class_device(struct class_device **class_dev_p, ...@@ -331,55 +328,54 @@ fw_register_class_device(struct class_device **class_dev_p,
fw_priv->timeout.data = (u_long) fw_priv; fw_priv->timeout.data = (u_long) fw_priv;
init_timer(&fw_priv->timeout); init_timer(&fw_priv->timeout);
fw_setup_class_device_id(class_dev, device); fw_setup_device_id(f_dev, device);
class_dev->dev = device; f_dev->parent = device;
class_dev->class = &firmware_class; f_dev->class = &firmware_class;
class_set_devdata(class_dev, fw_priv); dev_set_drvdata(f_dev, fw_priv);
retval = class_device_register(class_dev); retval = device_register(f_dev);
if (retval) { if (retval) {
printk(KERN_ERR "%s: class_device_register failed\n", printk(KERN_ERR "%s: device_register failed\n",
__FUNCTION__); __FUNCTION__);
goto error_kfree; goto error_kfree;
} }
*class_dev_p = class_dev; *dev_p = f_dev;
return 0; return 0;
error_kfree: error_kfree:
kfree(fw_priv); kfree(fw_priv);
kfree(class_dev); kfree(f_dev);
return retval; return retval;
} }
static int static int fw_setup_device(struct firmware *fw, struct device **dev_p,
fw_setup_class_device(struct firmware *fw, struct class_device **class_dev_p, const char *fw_name, struct device *device,
const char *fw_name, struct device *device, int uevent) int uevent)
{ {
struct class_device *class_dev; struct device *f_dev;
struct firmware_priv *fw_priv; struct firmware_priv *fw_priv;
int retval; int retval;
*class_dev_p = NULL; *dev_p = NULL;
retval = fw_register_class_device(&class_dev, fw_name, device); retval = fw_register_device(&f_dev, fw_name, device);
if (retval) if (retval)
goto out; goto out;
/* Need to pin this module until class device is destroyed */ /* Need to pin this module until class device is destroyed */
__module_get(THIS_MODULE); __module_get(THIS_MODULE);
fw_priv = class_get_devdata(class_dev); fw_priv = dev_get_drvdata(f_dev);
fw_priv->fw = fw; 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) { if (retval) {
printk(KERN_ERR "%s: sysfs_create_bin_file failed\n", printk(KERN_ERR "%s: sysfs_create_bin_file failed\n",
__FUNCTION__); __FUNCTION__);
goto error_unreg; goto error_unreg;
} }
retval = class_device_create_file(class_dev, retval = device_create_file(f_dev, &dev_attr_loading);
&class_device_attr_loading);
if (retval) { if (retval) {
printk(KERN_ERR "%s: class_device_create_file failed\n", printk(KERN_ERR "%s: device_create_file failed\n",
__FUNCTION__); __FUNCTION__);
goto error_unreg; goto error_unreg;
} }
...@@ -388,11 +384,11 @@ fw_setup_class_device(struct firmware *fw, struct class_device **class_dev_p, ...@@ -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); set_bit(FW_STATUS_READY, &fw_priv->status);
else else
set_bit(FW_STATUS_READY_NOHOTPLUG, &fw_priv->status); set_bit(FW_STATUS_READY_NOHOTPLUG, &fw_priv->status);
*class_dev_p = class_dev; *dev_p = f_dev;
goto out; goto out;
error_unreg: error_unreg:
class_device_unregister(class_dev); device_unregister(f_dev);
out: out:
return retval; return retval;
} }
...@@ -401,7 +397,7 @@ static int ...@@ -401,7 +397,7 @@ static int
_request_firmware(const struct firmware **firmware_p, const char *name, _request_firmware(const struct firmware **firmware_p, const char *name,
struct device *device, int uevent) struct device *device, int uevent)
{ {
struct class_device *class_dev; struct device *f_dev;
struct firmware_priv *fw_priv; struct firmware_priv *fw_priv;
struct firmware *firmware; struct firmware *firmware;
int retval; int retval;
...@@ -417,12 +413,11 @@ _request_firmware(const struct firmware **firmware_p, const char *name, ...@@ -417,12 +413,11 @@ _request_firmware(const struct firmware **firmware_p, const char *name,
goto out; goto out;
} }
retval = fw_setup_class_device(firmware, &class_dev, name, device, retval = fw_setup_device(firmware, &f_dev, name, device, uevent);
uevent);
if (retval) if (retval)
goto error_kfree_fw; goto error_kfree_fw;
fw_priv = class_get_devdata(class_dev); fw_priv = dev_get_drvdata(f_dev);
if (uevent) { if (uevent) {
if (loading_timeout > 0) { if (loading_timeout > 0) {
...@@ -430,7 +425,7 @@ _request_firmware(const struct firmware **firmware_p, const char *name, ...@@ -430,7 +425,7 @@ _request_firmware(const struct firmware **firmware_p, const char *name,
add_timer(&fw_priv->timeout); 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); wait_for_completion(&fw_priv->completion);
set_bit(FW_STATUS_DONE, &fw_priv->status); set_bit(FW_STATUS_DONE, &fw_priv->status);
del_timer_sync(&fw_priv->timeout); del_timer_sync(&fw_priv->timeout);
...@@ -445,7 +440,7 @@ _request_firmware(const struct firmware **firmware_p, const char *name, ...@@ -445,7 +440,7 @@ _request_firmware(const struct firmware **firmware_p, const char *name,
} }
fw_priv->fw = NULL; fw_priv->fw = NULL;
mutex_unlock(&fw_lock); mutex_unlock(&fw_lock);
class_device_unregister(class_dev); device_unregister(f_dev);
goto out; goto out;
error_kfree_fw: error_kfree_fw:
......
...@@ -388,6 +388,11 @@ static int platform_drv_probe(struct device *_dev) ...@@ -388,6 +388,11 @@ static int platform_drv_probe(struct device *_dev)
return drv->probe(dev); return drv->probe(dev);
} }
static int platform_drv_probe_fail(struct device *_dev)
{
return -ENXIO;
}
static int platform_drv_remove(struct device *_dev) static int platform_drv_remove(struct device *_dev)
{ {
struct platform_driver *drv = to_platform_driver(_dev->driver); struct platform_driver *drv = to_platform_driver(_dev->driver);
...@@ -451,6 +456,49 @@ void platform_driver_unregister(struct platform_driver *drv) ...@@ -451,6 +456,49 @@ void platform_driver_unregister(struct platform_driver *drv)
} }
EXPORT_SYMBOL_GPL(platform_driver_unregister); 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: /* modalias support enables more hands-off userspace setup:
* (a) environment variable lets new-style hotplug events work once system is * (a) environment variable lets new-style hotplug events work once system is
......
...@@ -94,54 +94,63 @@ static struct attribute_group topology_attr_group = { ...@@ -94,54 +94,63 @@ static struct attribute_group topology_attr_group = {
.name = "topology" .name = "topology"
}; };
static cpumask_t topology_dev_map = CPU_MASK_NONE;
/* Add/Remove cpu_topology interface for CPU device */ /* 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); sysfs_remove_group(&sys_dev->kobj, &topology_attr_group);
return 0;
} }
static int __cpuinit topology_cpu_callback(struct notifier_block *nfb, 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; unsigned int cpu = (unsigned long)hcpu;
struct sys_device *sys_dev; int rc = 0;
sys_dev = get_cpu_sysdev(cpu);
switch (action) { switch (action) {
case CPU_ONLINE: case CPU_UP_PREPARE:
topology_add_dev(sys_dev); rc = topology_add_dev(cpu);
break; break;
case CPU_UP_CANCELED:
case CPU_DEAD: case CPU_DEAD:
topology_remove_dev(sys_dev); topology_remove_dev(cpu);
break; break;
} }
return NOTIFY_OK; return rc ? NOTIFY_BAD : NOTIFY_OK;
} }
#endif
static struct notifier_block __cpuinitdata topology_cpu_notifier =
{
.notifier_call = topology_cpu_callback,
};
static int __cpuinit topology_sysfs_init(void) static int __cpuinit topology_sysfs_init(void)
{ {
int i; int cpu;
int rc;
for_each_online_cpu(i) { for_each_online_cpu(cpu) {
topology_cpu_callback(&topology_cpu_notifier, CPU_ONLINE, rc = topology_add_dev(cpu);
(void *)(long)i); if (rc)
return rc;
} }
hotcpu_notifier(topology_cpu_callback, 0);
register_hotcpu_notifier(&topology_cpu_notifier);
return 0; return 0;
} }
device_initcall(topology_sysfs_init); device_initcall(topology_sysfs_init);
...@@ -162,7 +162,8 @@ static struct miscdevice rng_miscdev = { ...@@ -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) const char *buf, size_t len)
{ {
int err; int err;
...@@ -192,7 +193,8 @@ static ssize_t hwrng_attr_current_store(struct class_device *class, ...@@ -192,7 +193,8 @@ static ssize_t hwrng_attr_current_store(struct class_device *class,
return err ? : len; 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) char *buf)
{ {
int err; int err;
...@@ -210,7 +212,8 @@ static ssize_t hwrng_attr_current_show(struct class_device *class, ...@@ -210,7 +212,8 @@ static ssize_t hwrng_attr_current_show(struct class_device *class,
return ret; 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) char *buf)
{ {
int err; int err;
...@@ -234,20 +237,18 @@ static ssize_t hwrng_attr_available_show(struct class_device *class, ...@@ -234,20 +237,18 @@ static ssize_t hwrng_attr_available_show(struct class_device *class,
return ret; return ret;
} }
static CLASS_DEVICE_ATTR(rng_current, S_IRUGO | S_IWUSR, static DEVICE_ATTR(rng_current, S_IRUGO | S_IWUSR,
hwrng_attr_current_show, hwrng_attr_current_show,
hwrng_attr_current_store); hwrng_attr_current_store);
static CLASS_DEVICE_ATTR(rng_available, S_IRUGO, static DEVICE_ATTR(rng_available, S_IRUGO,
hwrng_attr_available_show, hwrng_attr_available_show,
NULL); NULL);
static void unregister_miscdev(void) static void unregister_miscdev(void)
{ {
class_device_remove_file(rng_miscdev.class, device_remove_file(rng_miscdev.this_device, &dev_attr_rng_available);
&class_device_attr_rng_available); device_remove_file(rng_miscdev.this_device, &dev_attr_rng_current);
class_device_remove_file(rng_miscdev.class,
&class_device_attr_rng_current);
misc_deregister(&rng_miscdev); misc_deregister(&rng_miscdev);
} }
...@@ -258,20 +259,19 @@ static int register_miscdev(void) ...@@ -258,20 +259,19 @@ static int register_miscdev(void)
err = misc_register(&rng_miscdev); err = misc_register(&rng_miscdev);
if (err) if (err)
goto out; goto out;
err = class_device_create_file(rng_miscdev.class, err = device_create_file(rng_miscdev.this_device,
&class_device_attr_rng_current); &dev_attr_rng_current);
if (err) if (err)
goto err_misc_dereg; goto err_misc_dereg;
err = class_device_create_file(rng_miscdev.class, err = device_create_file(rng_miscdev.this_device,
&class_device_attr_rng_available); &dev_attr_rng_available);
if (err) if (err)
goto err_remove_current; goto err_remove_current;
out: out:
return err; return err;
err_remove_current: err_remove_current:
class_device_remove_file(rng_miscdev.class, device_remove_file(rng_miscdev.this_device, &dev_attr_rng_current);
&class_device_attr_rng_current);
err_misc_dereg: err_misc_dereg:
misc_deregister(&rng_miscdev); misc_deregister(&rng_miscdev);
goto out; goto out;
......
...@@ -980,10 +980,10 @@ static int __init chr_dev_init(void) ...@@ -980,10 +980,10 @@ static int __init chr_dev_init(void)
mem_class = class_create(THIS_MODULE, "mem"); mem_class = class_create(THIS_MODULE, "mem");
for (i = 0; i < ARRAY_SIZE(devlist); i++) for (i = 0; i < ARRAY_SIZE(devlist); i++)
class_device_create(mem_class, NULL, device_create(mem_class, NULL,
MKDEV(MEM_MAJOR, devlist[i].minor), MKDEV(MEM_MAJOR, devlist[i].minor),
NULL, devlist[i].name); devlist[i].name);
return 0; return 0;
} }
......
...@@ -169,11 +169,6 @@ static int misc_open(struct inode * inode, struct file * file) ...@@ -169,11 +169,6 @@ static int misc_open(struct inode * inode, struct file * file)
return err; 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 struct class *misc_class;
static const struct file_operations misc_fops = { static const struct file_operations misc_fops = {
...@@ -228,10 +223,10 @@ int misc_register(struct miscdevice * misc) ...@@ -228,10 +223,10 @@ int misc_register(struct miscdevice * misc)
misc_minors[misc->minor >> 3] |= 1 << (misc->minor & 7); misc_minors[misc->minor >> 3] |= 1 << (misc->minor & 7);
dev = MKDEV(MISC_MAJOR, misc->minor); 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); "%s", misc->name);
if (IS_ERR(misc->class)) { if (IS_ERR(misc->this_device)) {
err = PTR_ERR(misc->class); err = PTR_ERR(misc->this_device);
goto out; goto out;
} }
...@@ -264,7 +259,7 @@ int misc_deregister(struct miscdevice * misc) ...@@ -264,7 +259,7 @@ int misc_deregister(struct miscdevice * misc)
down(&misc_sem); down(&misc_sem);
list_del(&misc->list); 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) { if (i < DYNAMIC_MINORS && i>0) {
misc_minors[i>>3] &= ~(1 << (misc->minor & 7)); misc_minors[i>>3] &= ~(1 << (misc->minor & 7));
} }
......
...@@ -752,13 +752,13 @@ static const struct file_operations pp_fops = { ...@@ -752,13 +752,13 @@ static const struct file_operations pp_fops = {
static void pp_attach(struct parport *port) static void pp_attach(struct parport *port)
{ {
class_device_create(ppdev_class, NULL, MKDEV(PP_MAJOR, port->number), device_create(ppdev_class, NULL, MKDEV(PP_MAJOR, port->number),
NULL, "parport%d", port->number); "parport%d", port->number);
} }
static void pp_detach(struct parport *port) 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 = { static struct parport_driver pp_driver = {
......
...@@ -127,9 +127,9 @@ raw_ioctl(struct inode *inode, struct file *filp, ...@@ -127,9 +127,9 @@ raw_ioctl(struct inode *inode, struct file *filp,
static void bind_device(struct raw_config_request *rq) static void bind_device(struct raw_config_request *rq)
{ {
class_device_destroy(raw_class, MKDEV(RAW_MAJOR, rq->raw_minor)); device_destroy(raw_class, MKDEV(RAW_MAJOR, rq->raw_minor));
class_device_create(raw_class, NULL, MKDEV(RAW_MAJOR, rq->raw_minor), device_create(raw_class, NULL, MKDEV(RAW_MAJOR, rq->raw_minor),
NULL, "raw%d", rq->raw_minor); "raw%d", rq->raw_minor);
} }
/* /*
...@@ -200,7 +200,7 @@ static int raw_ctl_ioctl(struct inode *inode, struct file *filp, ...@@ -200,7 +200,7 @@ static int raw_ctl_ioctl(struct inode *inode, struct file *filp,
if (rq.block_major == 0 && rq.block_minor == 0) { if (rq.block_major == 0 && rq.block_minor == 0) {
/* unbind */ /* unbind */
rawdev->binding = NULL; rawdev->binding = NULL;
class_device_destroy(raw_class, device_destroy(raw_class,
MKDEV(RAW_MAJOR, rq.raw_minor)); MKDEV(RAW_MAJOR, rq.raw_minor));
} else { } else {
rawdev->binding = bdget(dev); rawdev->binding = bdget(dev);
...@@ -283,7 +283,7 @@ static int __init raw_init(void) ...@@ -283,7 +283,7 @@ static int __init raw_init(void)
ret = PTR_ERR(raw_class); ret = PTR_ERR(raw_class);
goto error_region; 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; return 0;
...@@ -295,7 +295,7 @@ static int __init raw_init(void) ...@@ -295,7 +295,7 @@ static int __init raw_init(void)
static void __exit raw_exit(void) 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); class_destroy(raw_class);
cdev_del(&raw_cdev); cdev_del(&raw_cdev);
unregister_chrdev_region(MKDEV(RAW_MAJOR, 0), MAX_RAW_MINORS); unregister_chrdev_region(MKDEV(RAW_MAJOR, 0), MAX_RAW_MINORS);
......
...@@ -1130,7 +1130,7 @@ struct tpm_chip *tpm_register_hardware(struct device *dev, const struct tpm_vend ...@@ -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); scnprintf(devname, DEVNAME_SIZE, "%s%d", "tpm", chip->dev_num);
chip->vendor.miscdev.name = devname; chip->vendor.miscdev.name = devname;
chip->vendor.miscdev.dev = dev; chip->vendor.miscdev.parent = dev;
chip->dev = get_device(dev); chip->dev = get_device(dev);
if (misc_register(&chip->vendor.miscdev)) { if (misc_register(&chip->vendor.miscdev)) {
......
...@@ -3612,7 +3612,8 @@ static struct class *tty_class; ...@@ -3612,7 +3612,8 @@ static struct class *tty_class;
* This field is optional, if there is no known struct device * This field is optional, if there is no known struct device
* for this tty device it can be set to NULL safely. * 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 * 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 * if the tty driver's flags have the TTY_DRIVER_DYNAMIC_DEV bit set. If
...@@ -3622,8 +3623,8 @@ static struct class *tty_class; ...@@ -3622,8 +3623,8 @@ static struct class *tty_class;
* Locking: ?? * Locking: ??
*/ */
struct class_device *tty_register_device(struct tty_driver *driver, struct device *tty_register_device(struct tty_driver *driver, unsigned index,
unsigned index, struct device *device) struct device *device)
{ {
char name[64]; char name[64];
dev_t dev = MKDEV(driver->major, driver->minor_start) + index; dev_t dev = MKDEV(driver->major, driver->minor_start) + index;
...@@ -3639,7 +3640,7 @@ struct class_device *tty_register_device(struct tty_driver *driver, ...@@ -3639,7 +3640,7 @@ struct class_device *tty_register_device(struct tty_driver *driver,
else else
tty_line_name(driver, index, name); 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, ...@@ -3655,7 +3656,7 @@ struct class_device *tty_register_device(struct tty_driver *driver,
void tty_unregister_device(struct tty_driver *driver, unsigned index) 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); EXPORT_SYMBOL(tty_register_device);
...@@ -3895,20 +3896,20 @@ static int __init tty_init(void) ...@@ -3895,20 +3896,20 @@ static int __init tty_init(void)
if (cdev_add(&tty_cdev, MKDEV(TTYAUX_MAJOR, 0), 1) || if (cdev_add(&tty_cdev, MKDEV(TTYAUX_MAJOR, 0), 1) ||
register_chrdev_region(MKDEV(TTYAUX_MAJOR, 0), 1, "/dev/tty") < 0) register_chrdev_region(MKDEV(TTYAUX_MAJOR, 0), 1, "/dev/tty") < 0)
panic("Couldn't register /dev/tty driver\n"); 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); cdev_init(&console_cdev, &console_fops);
if (cdev_add(&console_cdev, MKDEV(TTYAUX_MAJOR, 1), 1) || if (cdev_add(&console_cdev, MKDEV(TTYAUX_MAJOR, 1), 1) ||
register_chrdev_region(MKDEV(TTYAUX_MAJOR, 1), 1, "/dev/console") < 0) register_chrdev_region(MKDEV(TTYAUX_MAJOR, 1), 1, "/dev/console") < 0)
panic("Couldn't register /dev/console driver\n"); 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 #ifdef CONFIG_UNIX98_PTYS
cdev_init(&ptmx_cdev, &ptmx_fops); cdev_init(&ptmx_cdev, &ptmx_fops);
if (cdev_add(&ptmx_cdev, MKDEV(TTYAUX_MAJOR, 2), 1) || if (cdev_add(&ptmx_cdev, MKDEV(TTYAUX_MAJOR, 2), 1) ||
register_chrdev_region(MKDEV(TTYAUX_MAJOR, 2), 1, "/dev/ptmx") < 0) register_chrdev_region(MKDEV(TTYAUX_MAJOR, 2), 1, "/dev/ptmx") < 0)
panic("Couldn't register /dev/ptmx driver\n"); 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 #endif
#ifdef CONFIG_VT #ifdef CONFIG_VT
...@@ -3916,7 +3917,7 @@ static int __init tty_init(void) ...@@ -3916,7 +3917,7 @@ static int __init tty_init(void)
if (cdev_add(&vc0_cdev, MKDEV(TTY_MAJOR, 0), 1) || if (cdev_add(&vc0_cdev, MKDEV(TTY_MAJOR, 0), 1) ||
register_chrdev_region(MKDEV(TTY_MAJOR, 0), 1, "/dev/vc/0") < 0) register_chrdev_region(MKDEV(TTY_MAJOR, 0), 1, "/dev/vc/0") < 0)
panic("Couldn't register /dev/tty0 driver\n"); 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(); vty_init();
#endif #endif
......
...@@ -476,16 +476,16 @@ static struct class *vc_class; ...@@ -476,16 +476,16 @@ static struct class *vc_class;
void vcs_make_sysfs(struct tty_struct *tty) void vcs_make_sysfs(struct tty_struct *tty)
{ {
class_device_create(vc_class, NULL, MKDEV(VCS_MAJOR, tty->index + 1), device_create(vc_class, NULL, MKDEV(VCS_MAJOR, tty->index + 1),
NULL, "vcs%u", tty->index + 1); "vcs%u", tty->index + 1);
class_device_create(vc_class, NULL, MKDEV(VCS_MAJOR, tty->index + 129), device_create(vc_class, NULL, MKDEV(VCS_MAJOR, tty->index + 129),
NULL, "vcsa%u", tty->index + 1); "vcsa%u", tty->index + 1);
} }
void vcs_remove_sysfs(struct tty_struct *tty) void vcs_remove_sysfs(struct tty_struct *tty)
{ {
class_device_destroy(vc_class, MKDEV(VCS_MAJOR, tty->index + 1)); 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 + 129));
} }
int __init vcs_init(void) int __init vcs_init(void)
...@@ -494,7 +494,7 @@ 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); panic("unable to get major %d for vcs device", VCS_MAJOR);
vc_class = class_create(THIS_MODULE, "vc"); vc_class = class_create(THIS_MODULE, "vc");
class_device_create(vc_class, NULL, MKDEV(VCS_MAJOR, 0), NULL, "vcs"); device_create(vc_class, NULL, MKDEV(VCS_MAJOR, 0), "vcs");
class_device_create(vc_class, NULL, MKDEV(VCS_MAJOR, 128), NULL, "vcsa"); device_create(vc_class, NULL, MKDEV(VCS_MAJOR, 128), "vcsa");
return 0; return 0;
} }
...@@ -112,7 +112,7 @@ ...@@ -112,7 +112,7 @@
struct con_driver { struct con_driver {
const struct consw *con; const struct consw *con;
const char *desc; const char *desc;
struct class_device *class_dev; struct device *dev;
int node; int node;
int first; int first;
int last; int last;
...@@ -3023,10 +3023,10 @@ static inline int vt_unbind(struct con_driver *con) ...@@ -3023,10 +3023,10 @@ static inline int vt_unbind(struct con_driver *con)
} }
#endif /* CONFIG_VT_HW_CONSOLE_BINDING */ #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) 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); int bind = simple_strtoul(buf, NULL, 0);
if (bind) if (bind)
...@@ -3037,17 +3037,19 @@ static ssize_t store_bind(struct class_device *class_device, ...@@ -3037,17 +3037,19 @@ static ssize_t store_bind(struct class_device *class_device,
return count; 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); int bind = con_is_bound(con->con);
return snprintf(buf, PAGE_SIZE, "%i\n", bind); 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", return snprintf(buf, PAGE_SIZE, "%s %s\n",
(con->flag & CON_DRIVER_FLAG_MODULE) ? "(M)" : "(S)", (con->flag & CON_DRIVER_FLAG_MODULE) ? "(M)" : "(S)",
...@@ -3055,43 +3057,40 @@ static ssize_t show_name(struct class_device *class_device, char *buf) ...@@ -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(bind, S_IRUGO|S_IWUSR, show_bind, store_bind),
__ATTR(name, S_IRUGO, show_name, NULL), __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 i;
int error = 0; int error = 0;
con->flag |= CON_DRIVER_FLAG_ATTR; con->flag |= CON_DRIVER_FLAG_ATTR;
class_set_devdata(con->class_dev, con); dev_set_drvdata(con->dev, con);
for (i = 0; i < ARRAY_SIZE(class_device_attrs); i++) { for (i = 0; i < ARRAY_SIZE(device_attrs); i++) {
error = class_device_create_file(con->class_dev, error = device_create_file(con->dev, &device_attrs[i]);
&class_device_attrs[i]);
if (error) if (error)
break; break;
} }
if (error) { if (error) {
while (--i >= 0) while (--i >= 0)
class_device_remove_file(con->class_dev, device_remove_file(con->dev, &device_attrs[i]);
&class_device_attrs[i]);
con->flag &= ~CON_DRIVER_FLAG_ATTR; con->flag &= ~CON_DRIVER_FLAG_ATTR;
} }
return error; return error;
} }
static void vtconsole_deinit_class_device(struct con_driver *con) static void vtconsole_deinit_device(struct con_driver *con)
{ {
int i; int i;
if (con->flag & CON_DRIVER_FLAG_ATTR) { if (con->flag & CON_DRIVER_FLAG_ATTR) {
for (i = 0; i < ARRAY_SIZE(class_device_attrs); i++) for (i = 0; i < ARRAY_SIZE(device_attrs); i++)
class_device_remove_file(con->class_dev, device_remove_file(con->dev, &device_attrs[i]);
&class_device_attrs[i]);
con->flag &= ~CON_DRIVER_FLAG_ATTR; con->flag &= ~CON_DRIVER_FLAG_ATTR;
} }
} }
...@@ -3179,18 +3178,17 @@ int register_con_driver(const struct consw *csw, int first, int last) ...@@ -3179,18 +3178,17 @@ int register_con_driver(const struct consw *csw, int first, int last)
if (retval) if (retval)
goto err; goto err;
con_driver->class_dev = class_device_create(vtconsole_class, NULL, con_driver->dev = device_create(vtconsole_class, NULL,
MKDEV(0, con_driver->node), MKDEV(0, con_driver->node),
NULL, "vtcon%i", "vtcon%i", con_driver->node);
con_driver->node);
if (IS_ERR(con_driver->class_dev)) { if (IS_ERR(con_driver->dev)) {
printk(KERN_WARNING "Unable to create class_device for %s; " printk(KERN_WARNING "Unable to create device for %s; "
"errno = %ld\n", con_driver->desc, "errno = %ld\n", con_driver->desc,
PTR_ERR(con_driver->class_dev)); PTR_ERR(con_driver->dev));
con_driver->class_dev = NULL; con_driver->dev = NULL;
} else { } else {
vtconsole_init_class_device(con_driver); vtconsole_init_device(con_driver);
} }
err: err:
...@@ -3226,12 +3224,12 @@ int unregister_con_driver(const struct consw *csw) ...@@ -3226,12 +3224,12 @@ int unregister_con_driver(const struct consw *csw)
if (con_driver->con == csw && if (con_driver->con == csw &&
con_driver->flag & CON_DRIVER_FLAG_MODULE) { con_driver->flag & CON_DRIVER_FLAG_MODULE) {
vtconsole_deinit_class_device(con_driver); vtconsole_deinit_device(con_driver);
class_device_destroy(vtconsole_class, device_destroy(vtconsole_class,
MKDEV(0, con_driver->node)); MKDEV(0, con_driver->node));
con_driver->con = NULL; con_driver->con = NULL;
con_driver->desc = NULL; con_driver->desc = NULL;
con_driver->class_dev = NULL; con_driver->dev = NULL;
con_driver->node = 0; con_driver->node = 0;
con_driver->flag = 0; con_driver->flag = 0;
con_driver->first = 0; con_driver->first = 0;
...@@ -3289,19 +3287,18 @@ static int __init vtconsole_class_init(void) ...@@ -3289,19 +3287,18 @@ static int __init vtconsole_class_init(void)
for (i = 0; i < MAX_NR_CON_DRIVER; i++) { for (i = 0; i < MAX_NR_CON_DRIVER; i++) {
struct con_driver *con = &registered_con_driver[i]; struct con_driver *con = &registered_con_driver[i];
if (con->con && !con->class_dev) { if (con->con && !con->dev) {
con->class_dev = con->dev = device_create(vtconsole_class, NULL,
class_device_create(vtconsole_class, NULL, MKDEV(0, con->node),
MKDEV(0, con->node), NULL, "vtcon%i", con->node);
"vtcon%i", con->node);
if (IS_ERR(con->class_dev)) { if (IS_ERR(con->dev)) {
printk(KERN_WARNING "Unable to create " printk(KERN_WARNING "Unable to create "
"class_device for %s; errno = %ld\n", "device for %s; errno = %ld\n",
con->desc, PTR_ERR(con->class_dev)); con->desc, PTR_ERR(con->dev));
con->class_dev = NULL; con->dev = NULL;
} else { } else {
vtconsole_init_class_device(con); vtconsole_init_device(con);
} }
} }
} }
......
...@@ -42,7 +42,7 @@ static struct i2c_driver i2cdev_driver; ...@@ -42,7 +42,7 @@ static struct i2c_driver i2cdev_driver;
struct i2c_dev { struct i2c_dev {
struct list_head list; struct list_head list;
struct i2c_adapter *adap; struct i2c_adapter *adap;
struct class_device *class_dev; struct device *dev;
}; };
#define I2C_MINORS 256 #define I2C_MINORS 256
...@@ -92,15 +92,16 @@ static void return_i2c_dev(struct i2c_dev *i2c_dev) ...@@ -92,15 +92,16 @@ static void return_i2c_dev(struct i2c_dev *i2c_dev)
spin_unlock(&i2c_dev_list_lock); 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) if (!i2c_dev)
return -ENODEV; return -ENODEV;
return sprintf(buf, "%s\n", i2c_dev->adap->name); 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, static ssize_t i2cdev_read (struct file *file, char __user *buf, size_t count,
loff_t *offset) loff_t *offset)
...@@ -413,15 +414,14 @@ static int i2cdev_attach_adapter(struct i2c_adapter *adap) ...@@ -413,15 +414,14 @@ static int i2cdev_attach_adapter(struct i2c_adapter *adap)
return PTR_ERR(i2c_dev); return PTR_ERR(i2c_dev);
/* register this i2c device with the driver core */ /* register this i2c device with the driver core */
i2c_dev->class_dev = class_device_create(i2c_dev_class, NULL, i2c_dev->dev = device_create(i2c_dev_class, &adap->dev,
MKDEV(I2C_MAJOR, adap->nr), MKDEV(I2C_MAJOR, adap->nr),
&adap->dev, "i2c-%d", "i2c-%d", adap->nr);
adap->nr); if (!i2c_dev->dev) {
if (!i2c_dev->class_dev) {
res = -ENODEV; res = -ENODEV;
goto error; 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) if (res)
goto error_destroy; goto error_destroy;
...@@ -429,7 +429,7 @@ static int i2cdev_attach_adapter(struct i2c_adapter *adap) ...@@ -429,7 +429,7 @@ static int i2cdev_attach_adapter(struct i2c_adapter *adap)
adap->name, adap->nr); adap->name, adap->nr);
return 0; return 0;
error_destroy: error_destroy:
class_device_destroy(i2c_dev_class, MKDEV(I2C_MAJOR, adap->nr)); device_destroy(i2c_dev_class, MKDEV(I2C_MAJOR, adap->nr));
error: error:
return_i2c_dev(i2c_dev); return_i2c_dev(i2c_dev);
kfree(i2c_dev); kfree(i2c_dev);
...@@ -444,9 +444,9 @@ static int i2cdev_detach_adapter(struct i2c_adapter *adap) ...@@ -444,9 +444,9 @@ static int i2cdev_detach_adapter(struct i2c_adapter *adap)
if (!i2c_dev) /* attach_adapter must have failed */ if (!i2c_dev) /* attach_adapter must have failed */
return 0; 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); 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); kfree(i2c_dev);
pr_debug("i2c-dev: adapter [%s] unregistered\n", adap->name); pr_debug("i2c-dev: adapter [%s] unregistered\n", adap->name);
......
...@@ -297,7 +297,7 @@ static int serio_raw_connect(struct serio *serio, struct serio_driver *drv) ...@@ -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.minor = PSMOUSE_MINOR;
serio_raw->dev.name = serio_raw->name; 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; serio_raw->dev.fops = &serio_raw_fops;
err = misc_register(&serio_raw->dev); err = misc_register(&serio_raw->dev);
......
...@@ -702,7 +702,7 @@ struct cardstate *gigaset_initcs(struct gigaset_driver *drv, int channels, ...@@ -702,7 +702,7 @@ struct cardstate *gigaset_initcs(struct gigaset_driver *drv, int channels,
cs->open_count = 0; cs->open_count = 0;
cs->dev = NULL; cs->dev = NULL;
cs->tty = NULL; cs->tty = NULL;
cs->class = NULL; cs->tty_dev = NULL;
cs->cidmode = cidmode != 0; cs->cidmode = cidmode != 0;
//if(onechannel) { //FIXME //if(onechannel) { //FIXME
......
...@@ -444,7 +444,7 @@ struct cardstate { ...@@ -444,7 +444,7 @@ struct cardstate {
struct gigaset_driver *driver; struct gigaset_driver *driver;
unsigned minor_index; unsigned minor_index;
struct device *dev; struct device *dev;
struct class_device *class; struct device *tty_dev;
const struct gigaset_ops *ops; const struct gigaset_ops *ops;
......
...@@ -625,13 +625,13 @@ void gigaset_if_init(struct cardstate *cs) ...@@ -625,13 +625,13 @@ void gigaset_if_init(struct cardstate *cs)
return; return;
tasklet_init(&cs->if_wake_tasklet, &if_wake, (unsigned long) cs); 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)) if (!IS_ERR(cs->tty_dev))
class_set_devdata(cs->class, cs); dev_set_drvdata(cs->tty_dev, cs);
else { else {
warn("could not register device to the tty subsystem"); 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) ...@@ -645,7 +645,7 @@ void gigaset_if_free(struct cardstate *cs)
tasklet_disable(&cs->if_wake_tasklet); tasklet_disable(&cs->if_wake_tasklet);
tasklet_kill(&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); tty_unregister_device(drv->tty, cs->minor_index);
} }
......
...@@ -16,11 +16,12 @@ ...@@ -16,11 +16,12 @@
#include "gigaset.h" #include "gigaset.h"
#include <linux/ctype.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; int ret;
unsigned long flags; unsigned long flags;
struct cardstate *cs = class_get_devdata(class); struct cardstate *cs = dev_get_drvdata(dev);
spin_lock_irqsave(&cs->lock, flags); spin_lock_irqsave(&cs->lock, flags);
ret = sprintf(buf, "%u\n", cs->cidmode); ret = sprintf(buf, "%u\n", cs->cidmode);
...@@ -29,10 +30,10 @@ static ssize_t show_cidmode(struct class_device *class, char *buf) ...@@ -29,10 +30,10 @@ static ssize_t show_cidmode(struct class_device *class, char *buf)
return ret; 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) const char *buf, size_t count)
{ {
struct cardstate *cs = class_get_devdata(class); struct cardstate *cs = dev_get_drvdata(dev);
long int value; long int value;
char *end; char *end;
...@@ -64,25 +65,25 @@ static ssize_t set_cidmode(struct class_device *class, ...@@ -64,25 +65,25 @@ static ssize_t set_cidmode(struct class_device *class,
return count; 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 */ /* free sysfs for device */
void gigaset_free_dev_sysfs(struct cardstate *cs) void gigaset_free_dev_sysfs(struct cardstate *cs)
{ {
if (!cs->class) if (!cs->tty_dev)
return; return;
gig_dbg(DEBUG_INIT, "removing sysfs entries"); 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 */ /* initialize sysfs for device */
void gigaset_init_dev_sysfs(struct cardstate *cs) void gigaset_init_dev_sysfs(struct cardstate *cs)
{ {
if (!cs->class) if (!cs->tty_dev)
return; return;
gig_dbg(DEBUG_INIT, "setting up sysfs"); 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"); dev_err(cs->dev, "could not create sysfs attribute\n");
} }
...@@ -130,8 +130,8 @@ int mmc_init_queue(struct mmc_queue *mq, struct mmc_card *card, spinlock_t *lock ...@@ -130,8 +130,8 @@ int mmc_init_queue(struct mmc_queue *mq, struct mmc_card *card, spinlock_t *lock
u64 limit = BLK_BOUNCE_HIGH; u64 limit = BLK_BOUNCE_HIGH;
int ret; int ret;
if (host->dev->dma_mask && *host->dev->dma_mask) if (mmc_dev(host)->dma_mask && *mmc_dev(host)->dma_mask)
limit = *host->dev->dma_mask; limit = *mmc_dev(host)->dma_mask;
mq->card = card; mq->card = card;
mq->queue = blk_init_queue(mmc_request, lock); mq->queue = blk_init_queue(mmc_request, lock);
......
...@@ -199,7 +199,7 @@ void mmc_init_card(struct mmc_card *card, struct mmc_host *host) ...@@ -199,7 +199,7 @@ void mmc_init_card(struct mmc_card *card, struct mmc_host *host)
memset(card, 0, sizeof(struct mmc_card)); memset(card, 0, sizeof(struct mmc_card));
card->host = host; card->host = host;
device_initialize(&card->dev); device_initialize(&card->dev);
card->dev.parent = card->host->dev; card->dev.parent = mmc_dev(host);
card->dev.bus = &mmc_bus_type; card->dev.bus = &mmc_bus_type;
card->dev.release = mmc_release_card; card->dev.release = mmc_release_card;
} }
...@@ -242,7 +242,7 @@ void mmc_remove_card(struct mmc_card *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); struct mmc_host *host = cls_dev_to_mmc_host(dev);
kfree(host); kfree(host);
...@@ -250,7 +250,7 @@ static void mmc_host_classdev_release(struct class_device *dev) ...@@ -250,7 +250,7 @@ static void mmc_host_classdev_release(struct class_device *dev)
static struct class mmc_host_class = { static struct class mmc_host_class = {
.name = "mmc_host", .name = "mmc_host",
.release = mmc_host_classdev_release, .dev_release = mmc_host_classdev_release,
}; };
static DEFINE_IDR(mmc_host_idr); static DEFINE_IDR(mmc_host_idr);
...@@ -267,10 +267,10 @@ struct mmc_host *mmc_alloc_host_sysfs(int extra, struct device *dev) ...@@ -267,10 +267,10 @@ struct mmc_host *mmc_alloc_host_sysfs(int extra, struct device *dev)
if (host) { if (host) {
memset(host, 0, sizeof(struct mmc_host) + extra); memset(host, 0, sizeof(struct mmc_host) + extra);
host->dev = dev; host->parent = dev;
host->class_dev.dev = host->dev; host->class_dev.parent = dev;
host->class_dev.class = &mmc_host_class; host->class_dev.class = &mmc_host_class;
class_device_initialize(&host->class_dev); device_initialize(&host->class_dev);
} }
return host; return host;
...@@ -292,10 +292,10 @@ int mmc_add_host_sysfs(struct mmc_host *host) ...@@ -292,10 +292,10 @@ int mmc_add_host_sysfs(struct mmc_host *host)
if (err) if (err)
return 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); "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) ...@@ -303,7 +303,7 @@ int mmc_add_host_sysfs(struct mmc_host *host)
*/ */
void mmc_remove_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); spin_lock(&mmc_host_lock);
idr_remove(&mmc_host_idr, host->index); idr_remove(&mmc_host_idr, host->index);
...@@ -315,7 +315,7 @@ void mmc_remove_host_sysfs(struct mmc_host *host) ...@@ -315,7 +315,7 @@ void mmc_remove_host_sysfs(struct mmc_host *host)
*/ */
void mmc_free_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; static struct workqueue_struct *workqueue;
......
...@@ -1488,7 +1488,7 @@ static void __devinit wbsd_request_dma(struct wbsd_host *host, int dma) ...@@ -1488,7 +1488,7 @@ static void __devinit wbsd_request_dma(struct wbsd_host *host, int dma)
/* /*
* Translate the address to a physical address. * 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); WBSD_DMA_SIZE, DMA_BIDIRECTIONAL);
/* /*
...@@ -1512,7 +1512,7 @@ static void __devinit wbsd_request_dma(struct wbsd_host *host, int dma) ...@@ -1512,7 +1512,7 @@ static void __devinit wbsd_request_dma(struct wbsd_host *host, int dma)
*/ */
BUG_ON(1); 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); WBSD_DMA_SIZE, DMA_BIDIRECTIONAL);
host->dma_addr = (dma_addr_t)NULL; host->dma_addr = (dma_addr_t)NULL;
...@@ -1530,7 +1530,7 @@ static void __devinit wbsd_request_dma(struct wbsd_host *host, int dma) ...@@ -1530,7 +1530,7 @@ static void __devinit wbsd_request_dma(struct wbsd_host *host, int dma)
static void __devexit wbsd_release_dma(struct wbsd_host *host) static void __devexit wbsd_release_dma(struct wbsd_host *host)
{ {
if (host->dma_addr) { 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); WBSD_DMA_SIZE, DMA_BIDIRECTIONAL);
} }
kfree(host->dma_buffer); kfree(host->dma_buffer);
......
...@@ -860,7 +860,7 @@ static int __init ppp_init(void) ...@@ -860,7 +860,7 @@ static int __init ppp_init(void)
err = PTR_ERR(ppp_class); err = PTR_ERR(ppp_class);
goto out_chrdev; 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: out:
...@@ -2675,7 +2675,7 @@ static void __exit ppp_cleanup(void) ...@@ -2675,7 +2675,7 @@ static void __exit ppp_cleanup(void)
cardmap_destroy(&all_ppp_units); cardmap_destroy(&all_ppp_units);
if (unregister_chrdev(PPP_MAJOR, "ppp") != 0) if (unregister_chrdev(PPP_MAJOR, "ppp") != 0)
printk(KERN_ERR "PPP: failed to unregister PPP device\n"); 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); class_destroy(ppp_class);
} }
......
...@@ -1296,14 +1296,14 @@ register_framebuffer(struct fb_info *fb_info) ...@@ -1296,14 +1296,14 @@ register_framebuffer(struct fb_info *fb_info)
break; break;
fb_info->node = i; fb_info->node = i;
fb_info->class_device = class_device_create(fb_class, NULL, MKDEV(FB_MAJOR, i), fb_info->dev = device_create(fb_class, fb_info->device,
fb_info->device, "fb%d", i); MKDEV(FB_MAJOR, i), "fb%d", i);
if (IS_ERR(fb_info->class_device)) { if (IS_ERR(fb_info->dev)) {
/* Not fatal */ /* Not fatal */
printk(KERN_WARNING "Unable to create class_device for framebuffer %d; errno = %ld\n", i, PTR_ERR(fb_info->class_device)); printk(KERN_WARNING "Unable to create device for framebuffer %d; errno = %ld\n", i, PTR_ERR(fb_info->dev));
fb_info->class_device = NULL; fb_info->dev = NULL;
} else } else
fb_init_class_device(fb_info); fb_init_device(fb_info);
if (fb_info->pixmap.addr == NULL) { if (fb_info->pixmap.addr == NULL) {
fb_info->pixmap.addr = kmalloc(FBPIXMAPSIZE, GFP_KERNEL); fb_info->pixmap.addr = kmalloc(FBPIXMAPSIZE, GFP_KERNEL);
...@@ -1356,8 +1356,8 @@ unregister_framebuffer(struct fb_info *fb_info) ...@@ -1356,8 +1356,8 @@ unregister_framebuffer(struct fb_info *fb_info)
fb_destroy_modelist(&fb_info->modelist); fb_destroy_modelist(&fb_info->modelist);
registered_fb[i]=NULL; registered_fb[i]=NULL;
num_registered_fb--; num_registered_fb--;
fb_cleanup_class_device(fb_info); fb_cleanup_device(fb_info);
class_device_destroy(fb_class, MKDEV(FB_MAJOR, i)); device_destroy(fb_class, MKDEV(FB_MAJOR, i));
event.info = fb_info; event.info = fb_info;
fb_notifier_call_chain(FB_EVENT_FB_UNREGISTERED, &event); fb_notifier_call_chain(FB_EVENT_FB_UNREGISTERED, &event);
return 0; return 0;
......
This diff is collapsed.
...@@ -372,6 +372,51 @@ int sysfs_rename_dir(struct kobject * kobj, const char *new_name) ...@@ -372,6 +372,51 @@ int sysfs_rename_dir(struct kobject * kobj, const char *new_name)
return error; 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) static int sysfs_dir_open(struct inode *inode, struct file *file)
{ {
struct dentry * dentry = file->f_dentry; struct dentry * dentry = file->f_dentry;
......
...@@ -190,6 +190,9 @@ fill_write_buffer(struct sysfs_buffer * buffer, const char __user * buf, size_t ...@@ -190,6 +190,9 @@ fill_write_buffer(struct sysfs_buffer * buffer, const char __user * buf, size_t
count = PAGE_SIZE - 1; count = PAGE_SIZE - 1;
error = copy_from_user(buffer->page,buf,count); error = copy_from_user(buffer->page,buf,count);
buffer->needs_read_fill = 1; 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; return error ? -EFAULT : count;
} }
......
...@@ -357,7 +357,7 @@ struct device *acpi_get_physical_device(acpi_handle); ...@@ -357,7 +357,7 @@ struct device *acpi_get_physical_device(acpi_handle);
/* helper */ /* helper */
acpi_handle acpi_get_child(acpi_handle, acpi_integer); acpi_handle acpi_get_child(acpi_handle, acpi_integer);
acpi_handle acpi_get_pci_rootbridge_handle(unsigned int, unsigned int); 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 */ #endif /* CONFIG_ACPI */
......
/*
* Arch specific extensions to struct device
*
* This file is released under the GPLv2
*/
#include <asm-generic/device.h>
/*
* Arch specific extensions to struct device
*
* This file is released under the GPLv2
*/
#include <asm-generic/device.h>
/*
* Arch specific extensions to struct device
*
* This file is released under the GPLv2
*/
#include <asm-generic/device.h>
/*
* Arch specific extensions to struct device
*
* This file is released under the GPLv2
*/
#include <asm-generic/device.h>
/*
* Arch specific extensions to struct device
*
* This file is released under the GPLv2
*/
#include <asm-generic/device.h>
/*
* Arch specific extensions to struct device
*
* This file is released under the GPLv2
*/
#include <asm-generic/device.h>
/*
* 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 */
/*
* Arch specific extensions to struct device
*
* This file is released under the GPLv2
*/
#include <asm-generic/device.h>
/*
* 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 */
/*
* 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 */
/*
* Arch specific extensions to struct device
*
* This file is released under the GPLv2
*/
#include <asm-generic/device.h>
/*
* Arch specific extensions to struct device
*
* This file is released under the GPLv2
*/
#include <asm-generic/device.h>
/*
* Arch specific extensions to struct device
*
* This file is released under the GPLv2
*/
#include <asm-generic/device.h>
/*
* Arch specific extensions to struct device
*
* This file is released under the GPLv2
*/
#include <asm-generic/device.h>
/*
* Arch specific extensions to struct device
*
* This file is released under the GPLv2
*/
#include <asm-generic/device.h>
/*
* Arch specific extensions to struct device
*
* This file is released under the GPLv2
*/
#include <asm-generic/device.h>
/*
* Arch specific extensions to struct device
*
* This file is released under the GPLv2
*/
#include <asm-generic/device.h>
/*
* Arch specific extensions to struct device
*
* This file is released under the GPLv2
*/
#include <asm-generic/device.h>
/*
* Arch specific extensions to struct device
*
* This file is released under the GPLv2
*/
#include <asm-generic/device.h>
/*
* Arch specific extensions to struct device
*
* This file is released under the GPLv2
*/
#include <asm-generic/device.h>
/*
* Arch specific extensions to struct device
*
* This file is released under the GPLv2
*/
#include <asm-generic/device.h>
/*
* Arch specific extensions to struct device
*
* This file is released under the GPLv2
*/
#include <asm-generic/device.h>
/*
* Arch specific extensions to struct device
*
* This file is released under the GPLv2
*/
#include <asm-generic/device.h>
/*
* Arch specific extensions to struct device
*
* This file is released under the GPLv2
*/
#include <asm-generic/device.h>
/*
* 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 */
/*
* Arch specific extensions to struct device
*
* This file is released under the GPLv2
*/
#include <asm-generic/device.h>
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
#include <linux/pm.h> #include <linux/pm.h>
#include <asm/semaphore.h> #include <asm/semaphore.h>
#include <asm/atomic.h> #include <asm/atomic.h>
#include <asm/device.h>
#define DEVICE_NAME_SIZE 50 #define DEVICE_NAME_SIZE 50
#define DEVICE_NAME_HALF __stringify(20) /* Less than half to accommodate slop */ #define DEVICE_NAME_HALF __stringify(20) /* Less than half to accommodate slop */
...@@ -42,6 +43,8 @@ struct bus_type { ...@@ -42,6 +43,8 @@ struct bus_type {
struct klist klist_devices; struct klist klist_devices;
struct klist klist_drivers; struct klist klist_drivers;
struct blocking_notifier_head bus_notifier;
struct bus_attribute * bus_attrs; struct bus_attribute * bus_attrs;
struct device_attribute * dev_attrs; struct device_attribute * dev_attrs;
struct driver_attribute * drv_attrs; struct driver_attribute * drv_attrs;
...@@ -75,6 +78,29 @@ int __must_check bus_for_each_drv(struct bus_type *bus, ...@@ -75,6 +78,29 @@ int __must_check bus_for_each_drv(struct bus_type *bus,
struct device_driver *start, void *data, struct device_driver *start, void *data,
int (*fn)(struct device_driver *, void *)); 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 */ /* driverfs interface for exporting bus attributes */
struct bus_attribute { struct bus_attribute {
...@@ -343,8 +369,6 @@ struct device { ...@@ -343,8 +369,6 @@ struct device {
void *driver_data; /* data private to the driver */ void *driver_data; /* data private to the driver */
void *platform_data; /* Platform specific data, device void *platform_data; /* Platform specific data, device
core doesn't touch it */ 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; struct dev_pm_info power;
u64 *dma_mask; /* dma mask (if dma'able device) */ u64 *dma_mask; /* dma mask (if dma'able device) */
...@@ -358,6 +382,8 @@ struct device { ...@@ -358,6 +382,8 @@ struct device {
struct dma_coherent_mem *dma_mem; /* internal for coherent mem struct dma_coherent_mem *dma_mem; /* internal for coherent mem
override */ override */
/* arch specific additions */
struct dev_archdata archdata;
/* class_device migration path */ /* class_device migration path */
struct list_head node; struct list_head node;
...@@ -395,7 +421,10 @@ extern int __must_check device_add(struct device * dev); ...@@ -395,7 +421,10 @@ extern int __must_check device_add(struct device * dev);
extern void device_del(struct device * dev); extern void device_del(struct device * dev);
extern int device_for_each_child(struct device *, void *, extern int device_for_each_child(struct device *, void *,
int (*fn)(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_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 * 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, ...@@ -415,8 +444,6 @@ extern struct device *device_create(struct class *cls, struct device *parent,
__attribute__((format(printf,4,5))); __attribute__((format(printf,4,5)));
extern void device_destroy(struct class *cls, dev_t devt); 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 * Platform "fixup" functions - allow the platform to have their say
* about devices and actions that the general device layer doesn't * about devices and actions that the general device layer doesn't
......
...@@ -774,8 +774,8 @@ struct fb_info { ...@@ -774,8 +774,8 @@ struct fb_info {
#endif #endif
struct fb_ops *fbops; struct fb_ops *fbops;
struct device *device; struct device *device; /* This is the parent */
struct class_device *class_device; /* sysfs per device attrs */ struct device *dev; /* This is this fb device */
int class_flag; /* private sysfs flags */ int class_flag; /* private sysfs flags */
#ifdef CONFIG_FB_TILEBLITTING #ifdef CONFIG_FB_TILEBLITTING
struct fb_tile_ops *tileops; /* Tile Blitting */ struct fb_tile_ops *tileops; /* Tile Blitting */
...@@ -910,8 +910,8 @@ static inline void __fb_pad_aligned_buffer(u8 *dst, u32 d_pitch, ...@@ -910,8 +910,8 @@ static inline void __fb_pad_aligned_buffer(u8 *dst, u32 d_pitch,
/* drivers/video/fbsysfs.c */ /* drivers/video/fbsysfs.c */
extern struct fb_info *framebuffer_alloc(size_t size, struct device *dev); extern struct fb_info *framebuffer_alloc(size_t size, struct device *dev);
extern void framebuffer_release(struct fb_info *info); extern void framebuffer_release(struct fb_info *info);
extern int fb_init_class_device(struct fb_info *fb_info); extern int fb_init_device(struct fb_info *fb_info);
extern void fb_cleanup_class_device(struct fb_info *head); 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); extern void fb_bl_default_curve(struct fb_info *fb_info, u8 off, u8 min, u8 max);
/* drivers/video/fbmon.c */ /* drivers/video/fbmon.c */
......
...@@ -47,6 +47,7 @@ enum kobject_action { ...@@ -47,6 +47,7 @@ enum kobject_action {
KOBJ_UMOUNT = (__force kobject_action_t) 0x05, /* umount event for block devices (broken) */ KOBJ_UMOUNT = (__force kobject_action_t) 0x05, /* umount event for block devices (broken) */
KOBJ_OFFLINE = (__force kobject_action_t) 0x06, /* device offline */ KOBJ_OFFLINE = (__force kobject_action_t) 0x06, /* device offline */
KOBJ_ONLINE = (__force kobject_action_t) 0x07, /* device online */ KOBJ_ONLINE = (__force kobject_action_t) 0x07, /* device online */
KOBJ_MOVE = (__force kobject_action_t) 0x08, /* device move */
}; };
struct kobject { struct kobject {
...@@ -76,6 +77,7 @@ extern int __must_check kobject_add(struct kobject *); ...@@ -76,6 +77,7 @@ extern int __must_check kobject_add(struct kobject *);
extern void kobject_del(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_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 int __must_check kobject_register(struct kobject *);
extern void kobject_unregister(struct kobject *); extern void kobject_unregister(struct kobject *);
...@@ -264,6 +266,8 @@ extern int __must_check subsys_create_file(struct subsystem * , ...@@ -264,6 +266,8 @@ extern int __must_check subsys_create_file(struct subsystem * ,
#if defined(CONFIG_HOTPLUG) #if defined(CONFIG_HOTPLUG)
void kobject_uevent(struct kobject *kobj, enum kobject_action action); 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, int add_uevent_var(char **envp, int num_envp, int *cur_index,
char *buffer, int buffer_size, int *cur_len, char *buffer, int buffer_size, int *cur_len,
...@@ -271,6 +275,10 @@ int add_uevent_var(char **envp, int num_envp, int *cur_index, ...@@ -271,6 +275,10 @@ int add_uevent_var(char **envp, int num_envp, int *cur_index,
__attribute__((format (printf, 7, 8))); __attribute__((format (printf, 7, 8)));
#else #else
static inline void kobject_uevent(struct kobject *kobj, enum kobject_action action) { } 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, static inline int add_uevent_var(char **envp, int num_envp, int *cur_index,
char *buffer, int buffer_size, int *cur_len, char *buffer, int buffer_size, int *cur_len,
......
...@@ -31,15 +31,14 @@ ...@@ -31,15 +31,14 @@
#define HPET_MINOR 228 #define HPET_MINOR 228
struct device; struct device;
struct class_device;
struct miscdevice { struct miscdevice {
int minor; int minor;
const char *name; const char *name;
const struct file_operations *fops; const struct file_operations *fops;
struct list_head list; struct list_head list;
struct device *dev; struct device *parent;
struct class_device *class; struct device *this_device;
}; };
extern int misc_register(struct miscdevice * misc); extern int misc_register(struct miscdevice * misc);
......
...@@ -74,8 +74,8 @@ struct mmc_card; ...@@ -74,8 +74,8 @@ struct mmc_card;
struct device; struct device;
struct mmc_host { struct mmc_host {
struct device *dev; struct device *parent;
struct class_device class_dev; struct device class_dev;
int index; int index;
const struct mmc_host_ops *ops; const struct mmc_host_ops *ops;
unsigned int f_min; unsigned int f_min;
...@@ -125,8 +125,8 @@ static inline void *mmc_priv(struct mmc_host *host) ...@@ -125,8 +125,8 @@ static inline void *mmc_priv(struct mmc_host *host)
return (void *)host->private; return (void *)host->private;
} }
#define mmc_dev(x) ((x)->dev) #define mmc_dev(x) ((x)->parent)
#define mmc_hostname(x) ((x)->class_dev.class_id) #define mmc_hostname(x) ((x)->class_dev.bus_id)
extern int mmc_suspend_host(struct mmc_host *, pm_message_t); extern int mmc_suspend_host(struct mmc_host *, pm_message_t);
extern int mmc_resume_host(struct mmc_host *); extern int mmc_resume_host(struct mmc_host *);
......
...@@ -264,6 +264,7 @@ struct module ...@@ -264,6 +264,7 @@ struct module
struct module_attribute *modinfo_attrs; struct module_attribute *modinfo_attrs;
const char *version; const char *version;
const char *srcversion; const char *srcversion;
struct kobject *drivers_dir;
/* Exported symbols */ /* Exported symbols */
const struct kernel_symbol *syms; const struct kernel_symbol *syms;
......
...@@ -58,6 +58,12 @@ struct platform_driver { ...@@ -58,6 +58,12 @@ struct platform_driver {
extern int platform_driver_register(struct platform_driver *); extern int platform_driver_register(struct platform_driver *);
extern void platform_driver_unregister(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_get_drvdata(_dev) dev_get_drvdata(&(_dev)->dev)
#define platform_set_drvdata(_dev,data) dev_set_drvdata(&(_dev)->dev, (data)) #define platform_set_drvdata(_dev,data) dev_set_drvdata(&(_dev)->dev, (data))
......
...@@ -96,6 +96,9 @@ sysfs_remove_dir(struct kobject *); ...@@ -96,6 +96,9 @@ sysfs_remove_dir(struct kobject *);
extern int __must_check extern int __must_check
sysfs_rename_dir(struct kobject *, const char *new_name); sysfs_rename_dir(struct kobject *, const char *new_name);
extern int __must_check
sysfs_move_dir(struct kobject *, struct kobject *);
extern int __must_check extern int __must_check
sysfs_create_file(struct kobject *, const struct attribute *); 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) ...@@ -142,6 +145,11 @@ static inline int sysfs_rename_dir(struct kobject * k, const char *new_name)
return 0; 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) static inline int sysfs_create_file(struct kobject * k, const struct attribute * a)
{ {
return 0; return 0;
......
...@@ -276,9 +276,8 @@ extern int tty_register_ldisc(int disc, struct tty_ldisc *new_ldisc); ...@@ -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_unregister_ldisc(int disc);
extern int tty_register_driver(struct tty_driver *driver); extern int tty_register_driver(struct tty_driver *driver);
extern int tty_unregister_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, extern struct device *tty_register_device(struct tty_driver *driver,
unsigned index, unsigned index, struct device *dev);
struct device *dev);
extern void tty_unregister_device(struct tty_driver *driver, unsigned index); extern void tty_unregister_device(struct tty_driver *driver, unsigned index);
extern int tty_read_raw_data(struct tty_struct *tty, unsigned char *bufp, extern int tty_read_raw_data(struct tty_struct *tty, unsigned char *bufp,
int buflen); int buflen);
......
...@@ -132,6 +132,7 @@ struct snd_card { ...@@ -132,6 +132,7 @@ struct snd_card {
int shutdown; /* this card is going down */ int shutdown; /* this card is going down */
int free_on_last_close; /* free in context of file_release */ int free_on_last_close; /* free in context of file_release */
wait_queue_head_t shutdown_sleep; wait_queue_head_t shutdown_sleep;
struct device *parent;
struct device *dev; struct device *dev;
#ifdef CONFIG_PM #ifdef CONFIG_PM
...@@ -187,13 +188,14 @@ struct snd_minor { ...@@ -187,13 +188,14 @@ struct snd_minor {
int device; /* device number */ int device; /* device number */
const struct file_operations *f_ops; /* file operations */ const struct file_operations *f_ops; /* file operations */
void *private_data; /* private data for f_ops->open */ 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 */ /* sound.c */
extern int snd_major; extern int snd_major;
extern int snd_ecards_limit; extern int snd_ecards_limit;
extern struct class *sound_class;
void snd_request_card(int card); void snd_request_card(int card);
...@@ -203,7 +205,7 @@ int snd_register_device(int type, struct snd_card *card, int dev, ...@@ -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); int snd_unregister_device(int type, struct snd_card *card, int dev);
void *snd_lookup_minor_data(unsigned int minor, int type); void *snd_lookup_minor_data(unsigned int minor, int type);
int snd_add_device_sysfs_file(int type, struct snd_card *card, int dev, 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 #ifdef CONFIG_SND_OSSEMUL
int snd_register_oss_device(int type, struct snd_card *card, int dev, 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); ...@@ -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); int snd_card_file_remove(struct snd_card *card, struct file *file);
#ifndef snd_card_set_dev #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 #endif
/* device.c */ /* device.c */
......
...@@ -249,6 +249,26 @@ config CPUSETS ...@@ -249,6 +249,26 @@ config CPUSETS
Say N if unsure. 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 config RELAY
bool "Kernel->user space relay support (formerly relayfs)" bool "Kernel->user space relay support (formerly relayfs)"
help help
......
...@@ -1086,22 +1086,35 @@ static int mod_sysfs_setup(struct module *mod, ...@@ -1086,22 +1086,35 @@ static int mod_sysfs_setup(struct module *mod,
goto out; goto out;
kobj_set_kset_s(&mod->mkobj, module_subsys); kobj_set_kset_s(&mod->mkobj, module_subsys);
mod->mkobj.mod = mod; 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) if (err)
goto out; 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); err = module_param_sysfs_setup(mod, kparam, num_params);
if (err) if (err)
goto out_unreg; goto out_unreg_drivers;
err = module_add_modinfo_attrs(mod); err = module_add_modinfo_attrs(mod);
if (err) if (err)
goto out_unreg; goto out_unreg_param;
kobject_uevent(&mod->mkobj.kobj, KOBJ_ADD);
return 0; return 0;
out_unreg_drivers:
kobject_unregister(mod->drivers_dir);
out_unreg_param:
module_param_sysfs_remove(mod);
out_unreg: out_unreg:
kobject_unregister(&mod->mkobj.kobj); kobject_del(&mod->mkobj.kobj);
kobject_put(&mod->mkobj.kobj);
out: out:
return err; return err;
} }
...@@ -1110,6 +1123,7 @@ static void mod_kobject_remove(struct module *mod) ...@@ -1110,6 +1123,7 @@ static void mod_kobject_remove(struct module *mod)
{ {
module_remove_modinfo_attrs(mod); module_remove_modinfo_attrs(mod);
module_param_sysfs_remove(mod); module_param_sysfs_remove(mod);
kobject_unregister(mod->drivers_dir);
kobject_unregister(&mod->mkobj.kobj); kobject_unregister(&mod->mkobj.kobj);
} }
...@@ -2275,11 +2289,14 @@ void print_modules(void) ...@@ -2275,11 +2289,14 @@ void print_modules(void)
void module_add_driver(struct module *mod, struct device_driver *drv) void module_add_driver(struct module *mod, struct device_driver *drv)
{ {
int no_warn;
if (!mod || !drv) if (!mod || !drv)
return; return;
/* Don't check return code; this call is idempotent */ /* Don't check return codes; these calls are idempotent */
sysfs_create_link(&drv->kobj, &mod->mkobj.kobj, "module"); 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); EXPORT_SYMBOL(module_add_driver);
...@@ -2288,6 +2305,8 @@ void module_remove_driver(struct device_driver *drv) ...@@ -2288,6 +2305,8 @@ void module_remove_driver(struct device_driver *drv)
if (!drv) if (!drv)
return; return;
sysfs_remove_link(&drv->kobj, "module"); 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); EXPORT_SYMBOL(module_remove_driver);
......
...@@ -310,6 +310,56 @@ int kobject_rename(struct kobject * kobj, const char *new_name) ...@@ -310,6 +310,56 @@ int kobject_rename(struct kobject * kobj, const char *new_name)
return error; 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. * kobject_del - unlink kobject from hierarchy.
* @kobj: object. * @kobj: object.
......
...@@ -50,18 +50,22 @@ static char *action_to_string(enum kobject_action action) ...@@ -50,18 +50,22 @@ static char *action_to_string(enum kobject_action action)
return "offline"; return "offline";
case KOBJ_ONLINE: case KOBJ_ONLINE:
return "online"; return "online";
case KOBJ_MOVE:
return "move";
default: default:
return NULL; 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 * @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 **envp;
char *buffer; char *buffer;
...@@ -76,6 +80,7 @@ void kobject_uevent(struct kobject *kobj, enum kobject_action action) ...@@ -76,6 +80,7 @@ void kobject_uevent(struct kobject *kobj, enum kobject_action action)
char *seq_buff; char *seq_buff;
int i = 0; int i = 0;
int retval; int retval;
int j;
pr_debug("%s\n", __FUNCTION__); pr_debug("%s\n", __FUNCTION__);
...@@ -134,7 +139,8 @@ void kobject_uevent(struct kobject *kobj, enum kobject_action action) ...@@ -134,7 +139,8 @@ void kobject_uevent(struct kobject *kobj, enum kobject_action action)
scratch += sprintf (scratch, "DEVPATH=%s", devpath) + 1; scratch += sprintf (scratch, "DEVPATH=%s", devpath) + 1;
envp [i++] = scratch; envp [i++] = scratch;
scratch += sprintf(scratch, "SUBSYSTEM=%s", subsystem) + 1; 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 */ /* just reserve the space, overwrite it after kset call has returned */
envp[i++] = seq_buff = scratch; envp[i++] = seq_buff = scratch;
scratch += strlen("SEQNUM=18446744073709551616") + 1; scratch += strlen("SEQNUM=18446744073709551616") + 1;
...@@ -200,6 +206,20 @@ void kobject_uevent(struct kobject *kobj, enum kobject_action action) ...@@ -200,6 +206,20 @@ void kobject_uevent(struct kobject *kobj, enum kobject_action action)
kfree(envp); kfree(envp);
return; 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); EXPORT_SYMBOL_GPL(kobject_uevent);
/** /**
......
...@@ -361,6 +361,8 @@ static int snd_card_do_free(struct snd_card *card) ...@@ -361,6 +361,8 @@ static int snd_card_do_free(struct snd_card *card)
snd_printk(KERN_WARNING "unable to free card info\n"); snd_printk(KERN_WARNING "unable to free card info\n");
/* Not fatal error */ /* Not fatal error */
} }
if (card->dev)
device_unregister(card->dev);
kfree(card); kfree(card);
return 0; return 0;
} }
...@@ -495,6 +497,12 @@ int snd_card_register(struct snd_card *card) ...@@ -495,6 +497,12 @@ int snd_card_register(struct snd_card *card)
int err; int err;
snd_assert(card != NULL, return -EINVAL); 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) if ((err = snd_device_register_all(card)) < 0)
return err; return err;
mutex_lock(&snd_card_mutex); mutex_lock(&snd_card_mutex);
......
...@@ -910,7 +910,8 @@ void snd_pcm_detach_substream(struct snd_pcm_substream *substream) ...@@ -910,7 +910,8 @@ void snd_pcm_detach_substream(struct snd_pcm_substream *substream)
substream->pstr->substream_opened--; 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; struct snd_pcm *pcm;
const char *str; const char *str;
...@@ -921,7 +922,7 @@ static ssize_t show_pcm_class(struct class_device *class_device, char *buf) ...@@ -921,7 +922,7 @@ static ssize_t show_pcm_class(struct class_device *class_device, char *buf)
[SNDRV_PCM_CLASS_DIGITIZER] = "digitizer", [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) pcm->dev_class > SNDRV_PCM_CLASS_LAST)
str = "none"; str = "none";
else else
...@@ -929,7 +930,7 @@ static ssize_t show_pcm_class(struct class_device *class_device, char *buf) ...@@ -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); 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); __ATTR(pcm_class, S_IRUGO, show_pcm_class, NULL);
static int snd_pcm_dev_register(struct snd_device *device) static int snd_pcm_dev_register(struct snd_device *device)
......
...@@ -61,9 +61,6 @@ EXPORT_SYMBOL(snd_ecards_limit); ...@@ -61,9 +61,6 @@ EXPORT_SYMBOL(snd_ecards_limit);
static struct snd_minor *snd_minors[SNDRV_OS_MINORS]; static struct snd_minor *snd_minors[SNDRV_OS_MINORS];
static DEFINE_MUTEX(sound_mutex); static DEFINE_MUTEX(sound_mutex);
extern struct class *sound_class;
#ifdef CONFIG_KMOD #ifdef CONFIG_KMOD
/** /**
...@@ -268,11 +265,10 @@ int snd_register_device(int type, struct snd_card *card, int dev, ...@@ -268,11 +265,10 @@ int snd_register_device(int type, struct snd_card *card, int dev,
snd_minors[minor] = preg; snd_minors[minor] = preg;
if (card) if (card)
device = card->dev; device = card->dev;
preg->class_dev = class_device_create(sound_class, NULL, preg->dev = device_create(sound_class, device, MKDEV(major, minor),
MKDEV(major, minor), "%s", name);
device, "%s", name); if (preg->dev)
if (preg->class_dev) dev_set_drvdata(preg->dev, private_data);
class_set_devdata(preg->class_dev, private_data);
mutex_unlock(&sound_mutex); mutex_unlock(&sound_mutex);
return 0; return 0;
...@@ -320,7 +316,7 @@ int snd_unregister_device(int type, struct snd_card *card, int dev) ...@@ -320,7 +316,7 @@ int snd_unregister_device(int type, struct snd_card *card, int dev)
return -EINVAL; return -EINVAL;
} }
class_device_destroy(sound_class, MKDEV(major, minor)); device_destroy(sound_class, MKDEV(major, minor));
kfree(snd_minors[minor]); kfree(snd_minors[minor]);
snd_minors[minor] = NULL; snd_minors[minor] = NULL;
...@@ -331,15 +327,15 @@ int snd_unregister_device(int type, struct snd_card *card, int dev) ...@@ -331,15 +327,15 @@ int snd_unregister_device(int type, struct snd_card *card, int dev)
EXPORT_SYMBOL(snd_unregister_device); EXPORT_SYMBOL(snd_unregister_device);
int snd_add_device_sysfs_file(int type, struct snd_card *card, int dev, 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; int minor, ret = -EINVAL;
struct class_device *cdev; struct device *d;
mutex_lock(&sound_mutex); mutex_lock(&sound_mutex);
minor = find_snd_minor(type, card, dev); minor = find_snd_minor(type, card, dev);
if (minor >= 0 && (cdev = snd_minors[minor]->class_dev) != NULL) if (minor >= 0 && (d = snd_minors[minor]->dev) != NULL)
ret = class_device_create_file(cdev, attr); ret = device_create_file(d, attr);
mutex_unlock(&sound_mutex); mutex_unlock(&sound_mutex);
return ret; return ret;
......
...@@ -557,17 +557,17 @@ static int __init oss_init(void) ...@@ -557,17 +557,17 @@ static int __init oss_init(void)
sound_dmap_flag = (dmabuf > 0 ? 1 : 0); sound_dmap_flag = (dmabuf > 0 ? 1 : 0);
for (i = 0; i < sizeof (dev_list) / sizeof *dev_list; i++) { for (i = 0; i < sizeof (dev_list) / sizeof *dev_list; i++) {
class_device_create(sound_class, NULL, device_create(sound_class, NULL,
MKDEV(SOUND_MAJOR, dev_list[i].minor), MKDEV(SOUND_MAJOR, dev_list[i].minor),
NULL, "%s", dev_list[i].name); "%s", dev_list[i].name);
if (!dev_list[i].num) if (!dev_list[i].num)
continue; continue;
for (j = 1; j < *dev_list[i].num; j++) for (j = 1; j < *dev_list[i].num; j++)
class_device_create(sound_class, NULL, device_create(sound_class, NULL,
MKDEV(SOUND_MAJOR, dev_list[i].minor + (j*0x10)), MKDEV(SOUND_MAJOR, dev_list[i].minor + (j*0x10)),
NULL, "%s%d", dev_list[i].name, j); "%s%d", dev_list[i].name, j);
} }
if (sound_nblocks >= 1024) if (sound_nblocks >= 1024)
...@@ -581,11 +581,11 @@ static void __exit oss_cleanup(void) ...@@ -581,11 +581,11 @@ static void __exit oss_cleanup(void)
int i, j; int i, j;
for (i = 0; i < sizeof (dev_list) / sizeof *dev_list; i++) { 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) if (!dev_list[i].num)
continue; continue;
for (j = 1; j < *dev_list[i].num; j++) 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); unregister_sound_special(1);
......
...@@ -170,8 +170,8 @@ static int sound_insert_unit(struct sound_unit **list, const struct file_operati ...@@ -170,8 +170,8 @@ static int sound_insert_unit(struct sound_unit **list, const struct file_operati
else else
sprintf(s->name, "sound/%s%d", name, r / SOUND_STEP); sprintf(s->name, "sound/%s%d", name, r / SOUND_STEP);
class_device_create(sound_class, NULL, MKDEV(SOUND_MAJOR, s->unit_minor), device_create(sound_class, dev, MKDEV(SOUND_MAJOR, s->unit_minor),
dev, s->name+6); s->name+6);
return r; return r;
fail: fail:
...@@ -193,7 +193,7 @@ static void sound_remove_unit(struct sound_unit **list, int unit) ...@@ -193,7 +193,7 @@ static void sound_remove_unit(struct sound_unit **list, int unit)
p = __sound_remove_unit(list, unit); p = __sound_remove_unit(list, unit);
spin_unlock(&sound_loader_lock); spin_unlock(&sound_loader_lock);
if (p) { 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); kfree(p);
} }
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment