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

* master.kernel.org:/pub/scm/linux/kernel/git/gregkh/driver-2.6: (36 commits)
  Driver core: show drivers in /sys/module/
  Documentation/driver-model/platform.txt update/rewrite
  Driver core: platform_driver_probe(), can save codespace
  driver core: Use klist_remove() in device_move()
  driver core: Introduce device_move(): move a device to a new parent.
  Driver core: make drivers/base/core.c:setup_parent() static
  driver core: Introduce device_find_child().
  sysfs: sysfs_write_file() writes zero terminated data
  cpu topology: consider sysfs_create_group return value
  Driver core: Call platform_notify_remove later
  ACPI: Change ACPI to use dev_archdata instead of firmware_data
  Driver core: add dev_archdata to struct device
  Driver core: convert sound core to use struct device
  Driver core: change mem class_devices to be real devices
  Driver core: convert fb code to use struct device
  Driver core: convert firmware code to use struct device
  Driver core: convert mmc code to use struct device
  Driver core: convert ppdev code to use struct device
  Driver core: convert PPP code to use struct device
  Driver core: convert cpuid code to use struct device
  ...
This commit is contained in:
Linus Torvalds 2006-12-01 16:41:07 -08:00
Родитель 6b8cc71ab2 e17e0f51ae
Коммит 4549df891a
80 изменённых файлов: 1411 добавлений и 600 удалений

Просмотреть файл

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

Просмотреть файл

@ -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
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)
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)
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)
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 = {
.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,
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)
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)
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)
{ {
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)
{ {
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)
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)
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)
} }
} }
#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)
&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)
{ {
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)
{ {
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)
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)
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,
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)
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)
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)
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)
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)
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)
} }
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)
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)
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)
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)
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;

Просмотреть файл

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

Просмотреть файл

@ -26,6 +26,50 @@
#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)
{
if (klist_node_attached(&dev->knode_driver)) {
printk(KERN_WARNING "%s: device %s already bound\n",
__FUNCTION__, kobject_name(&dev->kobj));
return;
}
pr_debug("bound device '%s' to driver '%s'\n",
dev->bus_id, dev->driver->name);
if (dev->bus)
blocking_notifier_call_chain(&dev->bus->bus_notifier,
BUS_NOTIFY_BOUND_DRIVER, dev);
klist_add_tail(&dev->knode_driver, &dev->driver->klist_devices);
}
static int driver_sysfs_add(struct device *dev)
{
int ret;
ret = sysfs_create_link(&dev->driver->kobj, &dev->kobj,
kobject_name(&dev->kobj));
if (ret == 0) {
ret = sysfs_create_link(&dev->kobj, &dev->driver->kobj,
"driver");
if (ret)
sysfs_remove_link(&dev->driver->kobj,
kobject_name(&dev->kobj));
}
return ret;
}
static void driver_sysfs_remove(struct device *dev)
{
struct device_driver *drv = dev->driver;
if (drv) {
sysfs_remove_link(&drv->kobj, kobject_name(&dev->kobj));
sysfs_remove_link(&dev->kobj, "driver");
}
}
/** /**
* device_bind_driver - bind a driver to one device. * device_bind_driver - bind a driver to one device.
* @dev: device. * @dev: device.
@ -42,27 +86,8 @@
*/ */
int device_bind_driver(struct device *dev) int device_bind_driver(struct device *dev)
{ {
int ret; driver_bound(dev);
return driver_sysfs_add(dev);
if (klist_node_attached(&dev->knode_driver)) {
printk(KERN_WARNING "%s: device %s already bound\n",
__FUNCTION__, kobject_name(&dev->kobj));
return 0;
}
pr_debug("bound device '%s' to driver '%s'\n",
dev->bus_id, dev->driver->name);
klist_add_tail(&dev->knode_driver, &dev->driver->klist_devices);
ret = sysfs_create_link(&dev->driver->kobj, &dev->kobj,
kobject_name(&dev->kobj));
if (ret == 0) {
ret = sysfs_create_link(&dev->kobj, &dev->driver->kobj,
"driver");
if (ret)
sysfs_remove_link(&dev->driver->kobj,
kobject_name(&dev->kobj));
}
return ret;
} }
struct stupid_thread_structure { struct stupid_thread_structure {
@ -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)
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 @@
#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)
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,
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)
* 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,
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)
/** /**
* 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
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 = {
.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)
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,
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,
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
_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,
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,
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,
} }
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)
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)
} }
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 = {
.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 = {
}; };
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,
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,
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,
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)
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,9 +980,9 @@ 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 @@ fail:
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)
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)
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 = {
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,
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,
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)
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 @@ error:
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
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;
* 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;
* 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,
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,
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)
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)
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;
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)
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 @@
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)
} }
#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,
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)
} }
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)
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)
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)
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;
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)
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)
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)
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)
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)
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,
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 {
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)
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)
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 @@
#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)
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,
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
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)
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)
} }
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)
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)
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)
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)
*/ */
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)
*/ */
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)
/* /*
* 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 @@ kfree:
*/ */
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 @@ err:
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)
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)
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)
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)
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;

Просмотреть файл

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

Просмотреть файл

@ -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
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);
/* 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 */

Просмотреть файл

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

7
include/asm-arm/device.h Normal file
Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

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

7
include/asm-frv/device.h Normal file
Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

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

15
include/asm-i386/device.h Normal file
Просмотреть файл

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

15
include/asm-ia64/device.h Normal file
Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

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

7
include/asm-ppc/device.h Normal file
Просмотреть файл

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

Просмотреть файл

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

7
include/asm-sh/device.h Normal file
Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

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

7
include/asm-um/device.h Normal file
Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

@ -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 {
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,
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 {
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 {
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);
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,
__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 {
#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,
/* 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 {
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 *);
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 * ,
#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,
__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 @@
#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;
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)
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
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 {
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 *);
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)
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);
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 {
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 {
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,
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);
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
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,
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)
{ {
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)
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)
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)
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)
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)
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)
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 @@ exit:
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)
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)
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)
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)
[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)
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);
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,
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)
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)
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)
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)
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
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)
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);
} }
} }