forked from Minki/linux
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:
commit
4549df891a
@ -1,99 +1,131 @@
|
||||
Platform Devices and Drivers
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
See <linux/platform_device.h> for the driver model interface to the
|
||||
platform bus: platform_device, and platform_driver. This pseudo-bus
|
||||
is used to connect devices on busses with minimal infrastructure,
|
||||
like those used to integrate peripherals on many system-on-chip
|
||||
processors, or some "legacy" PC interconnects; as opposed to large
|
||||
formally specified ones like PCI or USB.
|
||||
|
||||
|
||||
Platform devices
|
||||
~~~~~~~~~~~~~~~~
|
||||
Platform devices are devices that typically appear as autonomous
|
||||
entities in the system. This includes legacy port-based devices and
|
||||
host bridges to peripheral buses.
|
||||
host bridges to peripheral buses, and most controllers integrated
|
||||
into system-on-chip platforms. What they usually have in common
|
||||
is direct addressing from a CPU bus. Rarely, a platform_device will
|
||||
be connected through a segment of some other kind of bus; but its
|
||||
registers will still be directly addressible.
|
||||
|
||||
Platform devices are given a name, used in driver binding, and a
|
||||
list of resources such as addresses and IRQs.
|
||||
|
||||
struct platform_device {
|
||||
const char *name;
|
||||
u32 id;
|
||||
struct device dev;
|
||||
u32 num_resources;
|
||||
struct resource *resource;
|
||||
};
|
||||
|
||||
|
||||
Platform drivers
|
||||
~~~~~~~~~~~~~~~~
|
||||
Drivers for platform devices are typically very simple and
|
||||
unstructured. Either the device was present at a particular I/O port
|
||||
and the driver was loaded, or it was not. There was no possibility
|
||||
of hotplugging or alternative discovery besides probing at a specific
|
||||
I/O address and expecting a specific response.
|
||||
Platform drivers follow the standard driver model convention, where
|
||||
discovery/enumeration is handled outside the drivers, and drivers
|
||||
provide probe() and remove() methods. They support power management
|
||||
and shutdown notifications using the standard conventions.
|
||||
|
||||
struct platform_driver {
|
||||
int (*probe)(struct platform_device *);
|
||||
int (*remove)(struct platform_device *);
|
||||
void (*shutdown)(struct platform_device *);
|
||||
int (*suspend)(struct platform_device *, pm_message_t state);
|
||||
int (*suspend_late)(struct platform_device *, pm_message_t state);
|
||||
int (*resume_early)(struct platform_device *);
|
||||
int (*resume)(struct platform_device *);
|
||||
struct device_driver driver;
|
||||
};
|
||||
|
||||
Note that probe() should general verify that the specified device hardware
|
||||
actually exists; sometimes platform setup code can't be sure. The probing
|
||||
can use device resources, including clocks, and device platform_data.
|
||||
|
||||
Platform drivers register themselves the normal way:
|
||||
|
||||
int platform_driver_register(struct platform_driver *drv);
|
||||
|
||||
Or, in common situations where the device is known not to be hot-pluggable,
|
||||
the probe() routine can live in an init section to reduce the driver's
|
||||
runtime memory footprint:
|
||||
|
||||
int platform_driver_probe(struct platform_driver *drv,
|
||||
int (*probe)(struct platform_device *))
|
||||
|
||||
|
||||
Other Architectures, Modern Firmware, and new Platforms
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
These devices are not always at the legacy I/O ports. This is true on
|
||||
other architectures and on some modern architectures. In most cases,
|
||||
the drivers are modified to discover the devices at other well-known
|
||||
ports for the given platform. However, the firmware in these systems
|
||||
does usually know where exactly these devices reside, and in some
|
||||
cases, it's the only way of discovering them.
|
||||
Device Enumeration
|
||||
~~~~~~~~~~~~~~~~~~
|
||||
As a rule, platform specific (and often board-specific) setup code wil
|
||||
register platform devices:
|
||||
|
||||
int platform_device_register(struct platform_device *pdev);
|
||||
|
||||
int platform_add_devices(struct platform_device **pdevs, int ndev);
|
||||
|
||||
The general rule is to register only those devices that actually exist,
|
||||
but in some cases extra devices might be registered. For example, a kernel
|
||||
might be configured to work with an external network adapter that might not
|
||||
be populated on all boards, or likewise to work with an integrated controller
|
||||
that some boards might not hook up to any peripherals.
|
||||
|
||||
In some cases, boot firmware will export tables describing the devices
|
||||
that are populated on a given board. Without such tables, often the
|
||||
only way for system setup code to set up the correct devices is to build
|
||||
a kernel for a specific target board. Such board-specific kernels are
|
||||
common with embedded and custom systems development.
|
||||
|
||||
In many cases, the memory and IRQ resources associated with the platform
|
||||
device are not enough to let the device's driver work. Board setup code
|
||||
will often provide additional information using the device's platform_data
|
||||
field to hold additional information.
|
||||
|
||||
Embedded systems frequently need one or more clocks for platform devices,
|
||||
which are normally kept off until they're actively needed (to save power).
|
||||
System setup also associates those clocks with the device, so that that
|
||||
calls to clk_get(&pdev->dev, clock_name) return them as needed.
|
||||
|
||||
|
||||
The Platform Bus
|
||||
~~~~~~~~~~~~~~~~
|
||||
A platform bus has been created to deal with these issues. First and
|
||||
foremost, it groups all the legacy devices under a common bus, and
|
||||
gives them a common parent if they don't already have one.
|
||||
Device Naming and Driver Binding
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
The platform_device.dev.bus_id is the canonical name for the devices.
|
||||
It's built from two components:
|
||||
|
||||
But, besides the organizational benefits, the platform bus can also
|
||||
accommodate firmware-based enumeration.
|
||||
* platform_device.name ... which is also used to for driver matching.
|
||||
|
||||
* platform_device.id ... the device instance number, or else "-1"
|
||||
to indicate there's only one.
|
||||
|
||||
Device Discovery
|
||||
~~~~~~~~~~~~~~~~
|
||||
The platform bus has no concept of probing for devices. Devices
|
||||
discovery is left up to either the legacy drivers or the
|
||||
firmware. These entities are expected to notify the platform of
|
||||
devices that it discovers via the bus's add() callback:
|
||||
These are catenated, so name/id "serial"/0 indicates bus_id "serial.0", and
|
||||
"serial/3" indicates bus_id "serial.3"; both would use the platform_driver
|
||||
named "serial". While "my_rtc"/-1 would be bus_id "my_rtc" (no instance id)
|
||||
and use the platform_driver called "my_rtc".
|
||||
|
||||
platform_bus.add(parent,bus_id).
|
||||
Driver binding is performed automatically by the driver core, invoking
|
||||
driver probe() after finding a match between device and driver. If the
|
||||
probe() succeeds, the driver and device are bound as usual. There are
|
||||
three different ways to find such a match:
|
||||
|
||||
- Whenever a device is registered, the drivers for that bus are
|
||||
checked for matches. Platform devices should be registered very
|
||||
early during system boot.
|
||||
|
||||
Bus IDs
|
||||
~~~~~~~
|
||||
Bus IDs are the canonical names for the devices. There is no globally
|
||||
standard addressing mechanism for legacy devices. In the IA-32 world,
|
||||
we have Pnp IDs to use, as well as the legacy I/O ports. However,
|
||||
neither tell what the device really is or have any meaning on other
|
||||
platforms.
|
||||
- When a driver is registered using platform_driver_register(), all
|
||||
unbound devices on that bus are checked for matches. Drivers
|
||||
usually register later during booting, or by module loading.
|
||||
|
||||
Since both PnP IDs and the legacy I/O ports (and other standard I/O
|
||||
ports for specific devices) have a 1:1 mapping, we map the
|
||||
platform-specific name or identifier to a generic name (at least
|
||||
within the scope of the kernel).
|
||||
|
||||
For example, a serial driver might find a device at I/O 0x3f8. The
|
||||
ACPI firmware might also discover a device with PnP ID (_HID)
|
||||
PNP0501. Both correspond to the same device and should be mapped to the
|
||||
canonical name 'serial'.
|
||||
|
||||
The bus_id field should be a concatenation of the canonical name and
|
||||
the instance of that type of device. For example, the device at I/O
|
||||
port 0x3f8 should have a bus_id of "serial0". This places the
|
||||
responsibility of enumerating devices of a particular type up to the
|
||||
discovery mechanism. But, they are the entity that should know best
|
||||
(as opposed to the platform bus driver).
|
||||
|
||||
|
||||
Drivers
|
||||
~~~~~~~
|
||||
Drivers for platform devices should have a name that is the same as
|
||||
the canonical name of the devices they support. This allows the
|
||||
platform bus driver to do simple matching with the basic data
|
||||
structures to determine if a driver supports a certain device.
|
||||
|
||||
For example, a legacy serial driver should have a name of 'serial' and
|
||||
register itself with the platform bus.
|
||||
|
||||
|
||||
Driver Binding
|
||||
~~~~~~~~~~~~~~
|
||||
Legacy drivers assume they are bound to the device once they start up
|
||||
and probe an I/O port. Divorcing them from this will be a difficult
|
||||
process. However, that shouldn't prevent us from implementing
|
||||
firmware-based enumeration.
|
||||
|
||||
The firmware should notify the platform bus about devices before the
|
||||
legacy drivers have had a chance to load. Once the drivers are loaded,
|
||||
they driver model core will attempt to bind the driver to any
|
||||
previously-discovered devices. Once that has happened, it will be free
|
||||
to discover any other devices it pleases.
|
||||
- Registering a driver using platform_driver_probe() works just like
|
||||
using platform_driver_register(), except that the the driver won't
|
||||
be probed later if another device registers. (Which is OK, since
|
||||
this interface is only for use with non-hotpluggable devices.)
|
||||
|
||||
|
@ -156,14 +156,14 @@ static struct file_operations cpuid_fops = {
|
||||
.open = cpuid_open,
|
||||
};
|
||||
|
||||
static int cpuid_class_device_create(int i)
|
||||
static int cpuid_device_create(int i)
|
||||
{
|
||||
int err = 0;
|
||||
struct class_device *class_err;
|
||||
struct device *dev;
|
||||
|
||||
class_err = class_device_create(cpuid_class, NULL, MKDEV(CPUID_MAJOR, i), NULL, "cpu%d",i);
|
||||
if (IS_ERR(class_err))
|
||||
err = PTR_ERR(class_err);
|
||||
dev = device_create(cpuid_class, NULL, MKDEV(CPUID_MAJOR, i), "cpu%d",i);
|
||||
if (IS_ERR(dev))
|
||||
err = PTR_ERR(dev);
|
||||
return err;
|
||||
}
|
||||
|
||||
@ -174,10 +174,10 @@ static int cpuid_class_cpu_callback(struct notifier_block *nfb, unsigned long ac
|
||||
|
||||
switch (action) {
|
||||
case CPU_ONLINE:
|
||||
cpuid_class_device_create(cpu);
|
||||
cpuid_device_create(cpu);
|
||||
break;
|
||||
case CPU_DEAD:
|
||||
class_device_destroy(cpuid_class, MKDEV(CPUID_MAJOR, cpu));
|
||||
device_destroy(cpuid_class, MKDEV(CPUID_MAJOR, cpu));
|
||||
break;
|
||||
}
|
||||
return NOTIFY_OK;
|
||||
@ -206,7 +206,7 @@ static int __init cpuid_init(void)
|
||||
goto out_chrdev;
|
||||
}
|
||||
for_each_online_cpu(i) {
|
||||
err = cpuid_class_device_create(i);
|
||||
err = cpuid_device_create(i);
|
||||
if (err != 0)
|
||||
goto out_class;
|
||||
}
|
||||
@ -218,7 +218,7 @@ static int __init cpuid_init(void)
|
||||
out_class:
|
||||
i = 0;
|
||||
for_each_online_cpu(i) {
|
||||
class_device_destroy(cpuid_class, MKDEV(CPUID_MAJOR, i));
|
||||
device_destroy(cpuid_class, MKDEV(CPUID_MAJOR, i));
|
||||
}
|
||||
class_destroy(cpuid_class);
|
||||
out_chrdev:
|
||||
@ -232,7 +232,7 @@ static void __exit cpuid_exit(void)
|
||||
int cpu = 0;
|
||||
|
||||
for_each_online_cpu(cpu)
|
||||
class_device_destroy(cpuid_class, MKDEV(CPUID_MAJOR, cpu));
|
||||
device_destroy(cpuid_class, MKDEV(CPUID_MAJOR, cpu));
|
||||
class_destroy(cpuid_class);
|
||||
unregister_chrdev(CPUID_MAJOR, "cpu/cpuid");
|
||||
unregister_hotcpu_notifier(&cpuid_class_cpu_notifier);
|
||||
|
@ -239,14 +239,14 @@ static struct file_operations msr_fops = {
|
||||
.open = msr_open,
|
||||
};
|
||||
|
||||
static int msr_class_device_create(int i)
|
||||
static int msr_device_create(int i)
|
||||
{
|
||||
int err = 0;
|
||||
struct class_device *class_err;
|
||||
struct device *dev;
|
||||
|
||||
class_err = class_device_create(msr_class, NULL, MKDEV(MSR_MAJOR, i), NULL, "msr%d",i);
|
||||
if (IS_ERR(class_err))
|
||||
err = PTR_ERR(class_err);
|
||||
dev = device_create(msr_class, NULL, MKDEV(MSR_MAJOR, i), "msr%d",i);
|
||||
if (IS_ERR(dev))
|
||||
err = PTR_ERR(dev);
|
||||
return err;
|
||||
}
|
||||
|
||||
@ -258,10 +258,10 @@ static int msr_class_cpu_callback(struct notifier_block *nfb,
|
||||
|
||||
switch (action) {
|
||||
case CPU_ONLINE:
|
||||
msr_class_device_create(cpu);
|
||||
msr_device_create(cpu);
|
||||
break;
|
||||
case CPU_DEAD:
|
||||
class_device_destroy(msr_class, MKDEV(MSR_MAJOR, cpu));
|
||||
device_destroy(msr_class, MKDEV(MSR_MAJOR, cpu));
|
||||
break;
|
||||
}
|
||||
return NOTIFY_OK;
|
||||
@ -290,7 +290,7 @@ static int __init msr_init(void)
|
||||
goto out_chrdev;
|
||||
}
|
||||
for_each_online_cpu(i) {
|
||||
err = msr_class_device_create(i);
|
||||
err = msr_device_create(i);
|
||||
if (err != 0)
|
||||
goto out_class;
|
||||
}
|
||||
@ -302,7 +302,7 @@ static int __init msr_init(void)
|
||||
out_class:
|
||||
i = 0;
|
||||
for_each_online_cpu(i)
|
||||
class_device_destroy(msr_class, MKDEV(MSR_MAJOR, i));
|
||||
device_destroy(msr_class, MKDEV(MSR_MAJOR, i));
|
||||
class_destroy(msr_class);
|
||||
out_chrdev:
|
||||
unregister_chrdev(MSR_MAJOR, "cpu/msr");
|
||||
@ -314,7 +314,7 @@ static void __exit msr_exit(void)
|
||||
{
|
||||
int cpu = 0;
|
||||
for_each_online_cpu(cpu)
|
||||
class_device_destroy(msr_class, MKDEV(MSR_MAJOR, cpu));
|
||||
device_destroy(msr_class, MKDEV(MSR_MAJOR, cpu));
|
||||
class_destroy(msr_class);
|
||||
unregister_chrdev(MSR_MAJOR, "cpu/msr");
|
||||
unregister_hotcpu_notifier(&msr_class_cpu_notifier);
|
||||
|
@ -267,9 +267,9 @@ static int acpi_bind_one(struct device *dev, acpi_handle handle)
|
||||
{
|
||||
acpi_status status;
|
||||
|
||||
if (dev->firmware_data) {
|
||||
if (dev->archdata.acpi_handle) {
|
||||
printk(KERN_WARNING PREFIX
|
||||
"Drivers changed 'firmware_data' for %s\n", dev->bus_id);
|
||||
"Drivers changed 'acpi_handle' for %s\n", dev->bus_id);
|
||||
return -EINVAL;
|
||||
}
|
||||
get_device(dev);
|
||||
@ -278,25 +278,26 @@ static int acpi_bind_one(struct device *dev, acpi_handle handle)
|
||||
put_device(dev);
|
||||
return -EINVAL;
|
||||
}
|
||||
dev->firmware_data = handle;
|
||||
dev->archdata.acpi_handle = handle;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int acpi_unbind_one(struct device *dev)
|
||||
{
|
||||
if (!dev->firmware_data)
|
||||
if (!dev->archdata.acpi_handle)
|
||||
return 0;
|
||||
if (dev == acpi_get_physical_device(dev->firmware_data)) {
|
||||
if (dev == acpi_get_physical_device(dev->archdata.acpi_handle)) {
|
||||
/* acpi_get_physical_device increase refcnt by one */
|
||||
put_device(dev);
|
||||
acpi_detach_data(dev->firmware_data, acpi_glue_data_handler);
|
||||
dev->firmware_data = NULL;
|
||||
acpi_detach_data(dev->archdata.acpi_handle,
|
||||
acpi_glue_data_handler);
|
||||
dev->archdata.acpi_handle = NULL;
|
||||
/* acpi_bind_one increase refcnt by one */
|
||||
put_device(dev);
|
||||
} else {
|
||||
printk(KERN_ERR PREFIX
|
||||
"Oops, 'firmware_data' corrupt for %s\n", dev->bus_id);
|
||||
"Oops, 'acpi_handle' corrupt for %s\n", dev->bus_id);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@ -328,7 +329,8 @@ static int acpi_platform_notify(struct device *dev)
|
||||
if (!ret) {
|
||||
struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
|
||||
|
||||
acpi_get_name(dev->firmware_data, ACPI_FULL_PATHNAME, &buffer);
|
||||
acpi_get_name(dev->archdata.acpi_handle,
|
||||
ACPI_FULL_PATHNAME, &buffer);
|
||||
DBG("Device %s -> %s\n", dev->bus_id, (char *)buffer.pointer);
|
||||
kfree(buffer.pointer);
|
||||
} else
|
||||
|
@ -355,6 +355,21 @@ static void device_remove_attrs(struct bus_type * bus, struct device * dev)
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SYSFS_DEPRECATED
|
||||
static int make_deprecated_bus_links(struct device *dev)
|
||||
{
|
||||
return sysfs_create_link(&dev->kobj,
|
||||
&dev->bus->subsys.kset.kobj, "bus");
|
||||
}
|
||||
|
||||
static void remove_deprecated_bus_links(struct device *dev)
|
||||
{
|
||||
sysfs_remove_link(&dev->kobj, "bus");
|
||||
}
|
||||
#else
|
||||
static inline int make_deprecated_bus_links(struct device *dev) { return 0; }
|
||||
static inline void remove_deprecated_bus_links(struct device *dev) { }
|
||||
#endif
|
||||
|
||||
/**
|
||||
* bus_add_device - add device to bus
|
||||
@ -381,8 +396,7 @@ int bus_add_device(struct device * dev)
|
||||
&dev->bus->subsys.kset.kobj, "subsystem");
|
||||
if (error)
|
||||
goto out_subsys;
|
||||
error = sysfs_create_link(&dev->kobj,
|
||||
&dev->bus->subsys.kset.kobj, "bus");
|
||||
error = make_deprecated_bus_links(dev);
|
||||
if (error)
|
||||
goto out_deprecated;
|
||||
}
|
||||
@ -436,7 +450,7 @@ void bus_remove_device(struct device * dev)
|
||||
{
|
||||
if (dev->bus) {
|
||||
sysfs_remove_link(&dev->kobj, "subsystem");
|
||||
sysfs_remove_link(&dev->kobj, "bus");
|
||||
remove_deprecated_bus_links(dev);
|
||||
sysfs_remove_link(&dev->bus->devices.kobj, dev->bus_id);
|
||||
device_remove_attrs(dev->bus, dev);
|
||||
if (dev->is_registered) {
|
||||
@ -724,6 +738,8 @@ int bus_register(struct bus_type * bus)
|
||||
{
|
||||
int retval;
|
||||
|
||||
BLOCKING_INIT_NOTIFIER_HEAD(&bus->bus_notifier);
|
||||
|
||||
retval = kobject_set_name(&bus->subsys.kset.kobj, "%s", bus->name);
|
||||
if (retval)
|
||||
goto out;
|
||||
@ -782,6 +798,18 @@ void bus_unregister(struct bus_type * bus)
|
||||
subsystem_unregister(&bus->subsys);
|
||||
}
|
||||
|
||||
int bus_register_notifier(struct bus_type *bus, struct notifier_block *nb)
|
||||
{
|
||||
return blocking_notifier_chain_register(&bus->bus_notifier, nb);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(bus_register_notifier);
|
||||
|
||||
int bus_unregister_notifier(struct bus_type *bus, struct notifier_block *nb)
|
||||
{
|
||||
return blocking_notifier_chain_unregister(&bus->bus_notifier, nb);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(bus_unregister_notifier);
|
||||
|
||||
int __init buses_init(void)
|
||||
{
|
||||
return subsystem_register(&bus_subsys);
|
||||
|
@ -352,6 +352,92 @@ static const char *class_uevent_name(struct kset *kset, struct kobject *kobj)
|
||||
return class_dev->class->name;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SYSFS_DEPRECATED
|
||||
char *make_class_name(const char *name, struct kobject *kobj)
|
||||
{
|
||||
char *class_name;
|
||||
int size;
|
||||
|
||||
size = strlen(name) + strlen(kobject_name(kobj)) + 2;
|
||||
|
||||
class_name = kmalloc(size, GFP_KERNEL);
|
||||
if (!class_name)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
strcpy(class_name, name);
|
||||
strcat(class_name, ":");
|
||||
strcat(class_name, kobject_name(kobj));
|
||||
return class_name;
|
||||
}
|
||||
|
||||
static int deprecated_class_uevent(char **envp, int num_envp, int *cur_index,
|
||||
char *buffer, int buffer_size,
|
||||
int *cur_len,
|
||||
struct class_device *class_dev)
|
||||
{
|
||||
struct device *dev = class_dev->dev;
|
||||
char *path;
|
||||
|
||||
if (!dev)
|
||||
return 0;
|
||||
|
||||
/* add device, backing this class device (deprecated) */
|
||||
path = kobject_get_path(&dev->kobj, GFP_KERNEL);
|
||||
|
||||
add_uevent_var(envp, num_envp, cur_index, buffer, buffer_size,
|
||||
cur_len, "PHYSDEVPATH=%s", path);
|
||||
kfree(path);
|
||||
|
||||
if (dev->bus)
|
||||
add_uevent_var(envp, num_envp, cur_index,
|
||||
buffer, buffer_size, cur_len,
|
||||
"PHYSDEVBUS=%s", dev->bus->name);
|
||||
|
||||
if (dev->driver)
|
||||
add_uevent_var(envp, num_envp, cur_index,
|
||||
buffer, buffer_size, cur_len,
|
||||
"PHYSDEVDRIVER=%s", dev->driver->name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int make_deprecated_class_device_links(struct class_device *class_dev)
|
||||
{
|
||||
char *class_name;
|
||||
int error;
|
||||
|
||||
if (!class_dev->dev)
|
||||
return 0;
|
||||
|
||||
class_name = make_class_name(class_dev->class->name, &class_dev->kobj);
|
||||
error = sysfs_create_link(&class_dev->dev->kobj, &class_dev->kobj,
|
||||
class_name);
|
||||
kfree(class_name);
|
||||
return error;
|
||||
}
|
||||
|
||||
static void remove_deprecated_class_device_links(struct class_device *class_dev)
|
||||
{
|
||||
char *class_name;
|
||||
|
||||
if (!class_dev->dev)
|
||||
return;
|
||||
|
||||
class_name = make_class_name(class_dev->class->name, &class_dev->kobj);
|
||||
sysfs_remove_link(&class_dev->dev->kobj, class_name);
|
||||
kfree(class_name);
|
||||
}
|
||||
#else
|
||||
static inline int deprecated_class_uevent(char **envp, int num_envp,
|
||||
int *cur_index, char *buffer,
|
||||
int buffer_size, int *cur_len,
|
||||
struct class_device *class_dev)
|
||||
{ return 0; }
|
||||
static inline int make_deprecated_class_device_links(struct class_device *cd)
|
||||
{ return 0; }
|
||||
static void remove_deprecated_class_device_links(struct class_device *cd)
|
||||
{ }
|
||||
#endif
|
||||
|
||||
static int class_uevent(struct kset *kset, struct kobject *kobj, char **envp,
|
||||
int num_envp, char *buffer, int buffer_size)
|
||||
{
|
||||
@ -362,25 +448,8 @@ static int class_uevent(struct kset *kset, struct kobject *kobj, char **envp,
|
||||
|
||||
pr_debug("%s - name = %s\n", __FUNCTION__, class_dev->class_id);
|
||||
|
||||
if (class_dev->dev) {
|
||||
/* add device, backing this class device (deprecated) */
|
||||
struct device *dev = class_dev->dev;
|
||||
char *path = kobject_get_path(&dev->kobj, GFP_KERNEL);
|
||||
|
||||
add_uevent_var(envp, num_envp, &i, buffer, buffer_size,
|
||||
&length, "PHYSDEVPATH=%s", path);
|
||||
kfree(path);
|
||||
|
||||
if (dev->bus)
|
||||
add_uevent_var(envp, num_envp, &i,
|
||||
buffer, buffer_size, &length,
|
||||
"PHYSDEVBUS=%s", dev->bus->name);
|
||||
|
||||
if (dev->driver)
|
||||
add_uevent_var(envp, num_envp, &i,
|
||||
buffer, buffer_size, &length,
|
||||
"PHYSDEVDRIVER=%s", dev->driver->name);
|
||||
}
|
||||
deprecated_class_uevent(envp, num_envp, &i, buffer, buffer_size,
|
||||
&length, class_dev);
|
||||
|
||||
if (MAJOR(class_dev->devt)) {
|
||||
add_uevent_var(envp, num_envp, &i,
|
||||
@ -506,29 +575,11 @@ void class_device_initialize(struct class_device *class_dev)
|
||||
INIT_LIST_HEAD(&class_dev->node);
|
||||
}
|
||||
|
||||
char *make_class_name(const char *name, struct kobject *kobj)
|
||||
{
|
||||
char *class_name;
|
||||
int size;
|
||||
|
||||
size = strlen(name) + strlen(kobject_name(kobj)) + 2;
|
||||
|
||||
class_name = kmalloc(size, GFP_KERNEL);
|
||||
if (!class_name)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
strcpy(class_name, name);
|
||||
strcat(class_name, ":");
|
||||
strcat(class_name, kobject_name(kobj));
|
||||
return class_name;
|
||||
}
|
||||
|
||||
int class_device_add(struct class_device *class_dev)
|
||||
{
|
||||
struct class *parent_class = NULL;
|
||||
struct class_device *parent_class_dev = NULL;
|
||||
struct class_interface *class_intf;
|
||||
char *class_name = NULL;
|
||||
int error = -EINVAL;
|
||||
|
||||
class_dev = class_device_get(class_dev);
|
||||
@ -599,19 +650,17 @@ int class_device_add(struct class_device *class_dev)
|
||||
goto out5;
|
||||
|
||||
if (class_dev->dev) {
|
||||
class_name = make_class_name(class_dev->class->name,
|
||||
&class_dev->kobj);
|
||||
error = sysfs_create_link(&class_dev->kobj,
|
||||
&class_dev->dev->kobj, "device");
|
||||
if (error)
|
||||
goto out6;
|
||||
error = sysfs_create_link(&class_dev->dev->kobj, &class_dev->kobj,
|
||||
class_name);
|
||||
if (error)
|
||||
goto out7;
|
||||
}
|
||||
|
||||
error = class_device_add_groups(class_dev);
|
||||
if (error)
|
||||
goto out7;
|
||||
|
||||
error = make_deprecated_class_device_links(class_dev);
|
||||
if (error)
|
||||
goto out8;
|
||||
|
||||
@ -629,8 +678,7 @@ int class_device_add(struct class_device *class_dev)
|
||||
goto out1;
|
||||
|
||||
out8:
|
||||
if (class_dev->dev)
|
||||
sysfs_remove_link(&class_dev->kobj, class_name);
|
||||
class_device_remove_groups(class_dev);
|
||||
out7:
|
||||
if (class_dev->dev)
|
||||
sysfs_remove_link(&class_dev->kobj, "device");
|
||||
@ -649,7 +697,6 @@ int class_device_add(struct class_device *class_dev)
|
||||
class_put(parent_class);
|
||||
out1:
|
||||
class_device_put(class_dev);
|
||||
kfree(class_name);
|
||||
return error;
|
||||
}
|
||||
|
||||
@ -726,7 +773,6 @@ void class_device_del(struct class_device *class_dev)
|
||||
struct class *parent_class = class_dev->class;
|
||||
struct class_device *parent_device = class_dev->parent;
|
||||
struct class_interface *class_intf;
|
||||
char *class_name = NULL;
|
||||
|
||||
if (parent_class) {
|
||||
down(&parent_class->sem);
|
||||
@ -738,10 +784,8 @@ void class_device_del(struct class_device *class_dev)
|
||||
}
|
||||
|
||||
if (class_dev->dev) {
|
||||
class_name = make_class_name(class_dev->class->name,
|
||||
&class_dev->kobj);
|
||||
remove_deprecated_class_device_links(class_dev);
|
||||
sysfs_remove_link(&class_dev->kobj, "device");
|
||||
sysfs_remove_link(&class_dev->dev->kobj, class_name);
|
||||
}
|
||||
sysfs_remove_link(&class_dev->kobj, "subsystem");
|
||||
class_device_remove_file(class_dev, &class_dev->uevent_attr);
|
||||
@ -755,7 +799,6 @@ void class_device_del(struct class_device *class_dev)
|
||||
|
||||
class_device_put(parent_device);
|
||||
class_put(parent_class);
|
||||
kfree(class_name);
|
||||
}
|
||||
|
||||
void class_device_unregister(struct class_device *class_dev)
|
||||
@ -804,14 +847,17 @@ int class_device_rename(struct class_device *class_dev, char *new_name)
|
||||
pr_debug("CLASS: renaming '%s' to '%s'\n", class_dev->class_id,
|
||||
new_name);
|
||||
|
||||
#ifdef CONFIG_SYSFS_DEPRECATED
|
||||
if (class_dev->dev)
|
||||
old_class_name = make_class_name(class_dev->class->name,
|
||||
&class_dev->kobj);
|
||||
#endif
|
||||
|
||||
strlcpy(class_dev->class_id, new_name, KOBJ_NAME_LEN);
|
||||
|
||||
error = kobject_rename(&class_dev->kobj, new_name);
|
||||
|
||||
#ifdef CONFIG_SYSFS_DEPRECATED
|
||||
if (class_dev->dev) {
|
||||
new_class_name = make_class_name(class_dev->class->name,
|
||||
&class_dev->kobj);
|
||||
@ -819,6 +865,7 @@ int class_device_rename(struct class_device *class_dev, char *new_name)
|
||||
new_class_name);
|
||||
sysfs_remove_link(&class_dev->dev->kobj, old_class_name);
|
||||
}
|
||||
#endif
|
||||
class_device_put(class_dev);
|
||||
|
||||
kfree(old_class_name);
|
||||
@ -893,23 +940,6 @@ void class_interface_unregister(struct class_interface *class_intf)
|
||||
class_put(parent);
|
||||
}
|
||||
|
||||
int virtual_device_parent(struct device *dev)
|
||||
{
|
||||
if (!dev->class)
|
||||
return -ENODEV;
|
||||
|
||||
if (!dev->class->virtual_dir) {
|
||||
static struct kobject *virtual_dir = NULL;
|
||||
|
||||
if (!virtual_dir)
|
||||
virtual_dir = kobject_add_dir(&devices_subsys.kset.kobj, "virtual");
|
||||
dev->class->virtual_dir = kobject_add_dir(virtual_dir, dev->class->name);
|
||||
}
|
||||
|
||||
dev->kobj.parent = dev->class->virtual_dir;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int __init classes_init(void)
|
||||
{
|
||||
int retval;
|
||||
|
@ -17,6 +17,7 @@
|
||||
#include <linux/slab.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/kdev_t.h>
|
||||
#include <linux/notifier.h>
|
||||
|
||||
#include <asm/semaphore.h>
|
||||
|
||||
@ -153,20 +154,24 @@ static int dev_uevent(struct kset *kset, struct kobject *kobj, char **envp,
|
||||
"MINOR=%u", MINOR(dev->devt));
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SYSFS_DEPRECATED
|
||||
/* add bus name (same as SUBSYSTEM, deprecated) */
|
||||
if (dev->bus)
|
||||
add_uevent_var(envp, num_envp, &i,
|
||||
buffer, buffer_size, &length,
|
||||
"PHYSDEVBUS=%s", dev->bus->name);
|
||||
#endif
|
||||
|
||||
/* add driver name (PHYSDEV* values are deprecated)*/
|
||||
if (dev->driver) {
|
||||
add_uevent_var(envp, num_envp, &i,
|
||||
buffer, buffer_size, &length,
|
||||
"DRIVER=%s", dev->driver->name);
|
||||
#ifdef CONFIG_SYSFS_DEPRECATED
|
||||
add_uevent_var(envp, num_envp, &i,
|
||||
buffer, buffer_size, &length,
|
||||
"PHYSDEVDRIVER=%s", dev->driver->name);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* terminate, set to next free slot, shrink available space */
|
||||
@ -383,6 +388,52 @@ void device_initialize(struct device *dev)
|
||||
device_init_wakeup(dev, 0);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SYSFS_DEPRECATED
|
||||
static int setup_parent(struct device *dev, struct device *parent)
|
||||
{
|
||||
/* Set the parent to the class, not the parent device */
|
||||
/* this keeps sysfs from having a symlink to make old udevs happy */
|
||||
if (dev->class)
|
||||
dev->kobj.parent = &dev->class->subsys.kset.kobj;
|
||||
else if (parent)
|
||||
dev->kobj.parent = &parent->kobj;
|
||||
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
static int virtual_device_parent(struct device *dev)
|
||||
{
|
||||
if (!dev->class)
|
||||
return -ENODEV;
|
||||
|
||||
if (!dev->class->virtual_dir) {
|
||||
static struct kobject *virtual_dir = NULL;
|
||||
|
||||
if (!virtual_dir)
|
||||
virtual_dir = kobject_add_dir(&devices_subsys.kset.kobj, "virtual");
|
||||
dev->class->virtual_dir = kobject_add_dir(virtual_dir, dev->class->name);
|
||||
}
|
||||
|
||||
dev->kobj.parent = dev->class->virtual_dir;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int setup_parent(struct device *dev, struct device *parent)
|
||||
{
|
||||
int error;
|
||||
|
||||
/* if this is a class device, and has no parent, create one */
|
||||
if ((dev->class) && (parent == NULL)) {
|
||||
error = virtual_device_parent(dev);
|
||||
if (error)
|
||||
return error;
|
||||
} else if (parent)
|
||||
dev->kobj.parent = &parent->kobj;
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* device_add - add device to device hierarchy.
|
||||
* @dev: device.
|
||||
@ -405,29 +456,29 @@ int device_add(struct device *dev)
|
||||
if (!dev || !strlen(dev->bus_id))
|
||||
goto Error;
|
||||
|
||||
/* if this is a class device, and has no parent, create one */
|
||||
if ((dev->class) && (dev->parent == NULL)) {
|
||||
error = virtual_device_parent(dev);
|
||||
if (error)
|
||||
goto Error;
|
||||
}
|
||||
pr_debug("DEV: registering device: ID = '%s'\n", dev->bus_id);
|
||||
|
||||
parent = get_device(dev->parent);
|
||||
|
||||
pr_debug("DEV: registering device: ID = '%s'\n", dev->bus_id);
|
||||
error = setup_parent(dev, parent);
|
||||
if (error)
|
||||
goto Error;
|
||||
|
||||
/* first, register with generic layer. */
|
||||
kobject_set_name(&dev->kobj, "%s", dev->bus_id);
|
||||
if (parent)
|
||||
dev->kobj.parent = &parent->kobj;
|
||||
|
||||
if ((error = kobject_add(&dev->kobj)))
|
||||
error = kobject_add(&dev->kobj);
|
||||
if (error)
|
||||
goto Error;
|
||||
|
||||
/* notify platform of device entry */
|
||||
if (platform_notify)
|
||||
platform_notify(dev);
|
||||
|
||||
/* notify clients of device entry (new way) */
|
||||
if (dev->bus)
|
||||
blocking_notifier_call_chain(&dev->bus->bus_notifier,
|
||||
BUS_NOTIFY_ADD_DEVICE, dev);
|
||||
|
||||
dev->uevent_attr.attr.name = "uevent";
|
||||
dev->uevent_attr.attr.mode = S_IWUSR;
|
||||
if (dev->driver)
|
||||
@ -461,13 +512,18 @@ int device_add(struct device *dev)
|
||||
if (dev->class) {
|
||||
sysfs_create_link(&dev->kobj, &dev->class->subsys.kset.kobj,
|
||||
"subsystem");
|
||||
sysfs_create_link(&dev->class->subsys.kset.kobj, &dev->kobj,
|
||||
dev->bus_id);
|
||||
/* If this is not a "fake" compatible device, then create the
|
||||
* symlink from the class to the device. */
|
||||
if (dev->kobj.parent != &dev->class->subsys.kset.kobj)
|
||||
sysfs_create_link(&dev->class->subsys.kset.kobj,
|
||||
&dev->kobj, dev->bus_id);
|
||||
#ifdef CONFIG_SYSFS_DEPRECATED
|
||||
if (parent) {
|
||||
sysfs_create_link(&dev->kobj, &dev->parent->kobj, "device");
|
||||
class_name = make_class_name(dev->class->name, &dev->kobj);
|
||||
sysfs_create_link(&dev->parent->kobj, &dev->kobj, class_name);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
if ((error = device_add_attrs(dev)))
|
||||
@ -504,6 +560,9 @@ int device_add(struct device *dev)
|
||||
BusError:
|
||||
device_pm_remove(dev);
|
||||
PMError:
|
||||
if (dev->bus)
|
||||
blocking_notifier_call_chain(&dev->bus->bus_notifier,
|
||||
BUS_NOTIFY_DEL_DEVICE, dev);
|
||||
device_remove_groups(dev);
|
||||
GroupError:
|
||||
device_remove_attrs(dev);
|
||||
@ -586,7 +645,6 @@ void put_device(struct device * dev)
|
||||
void device_del(struct device * dev)
|
||||
{
|
||||
struct device * parent = dev->parent;
|
||||
char *class_name = NULL;
|
||||
struct class_interface *class_intf;
|
||||
|
||||
if (parent)
|
||||
@ -597,13 +655,21 @@ void device_del(struct device * dev)
|
||||
}
|
||||
if (dev->class) {
|
||||
sysfs_remove_link(&dev->kobj, "subsystem");
|
||||
sysfs_remove_link(&dev->class->subsys.kset.kobj, dev->bus_id);
|
||||
class_name = make_class_name(dev->class->name, &dev->kobj);
|
||||
/* If this is not a "fake" compatible device, remove the
|
||||
* symlink from the class to the device. */
|
||||
if (dev->kobj.parent != &dev->class->subsys.kset.kobj)
|
||||
sysfs_remove_link(&dev->class->subsys.kset.kobj,
|
||||
dev->bus_id);
|
||||
#ifdef CONFIG_SYSFS_DEPRECATED
|
||||
if (parent) {
|
||||
sysfs_remove_link(&dev->kobj, "device");
|
||||
char *class_name = make_class_name(dev->class->name,
|
||||
&dev->kobj);
|
||||
sysfs_remove_link(&dev->parent->kobj, class_name);
|
||||
kfree(class_name);
|
||||
sysfs_remove_link(&dev->kobj, "device");
|
||||
}
|
||||
kfree(class_name);
|
||||
#endif
|
||||
|
||||
down(&dev->class->sem);
|
||||
/* notify any interfaces that the device is now gone */
|
||||
list_for_each_entry(class_intf, &dev->class->interfaces, node)
|
||||
@ -616,13 +682,16 @@ void device_del(struct device * dev)
|
||||
device_remove_file(dev, &dev->uevent_attr);
|
||||
device_remove_groups(dev);
|
||||
device_remove_attrs(dev);
|
||||
bus_remove_device(dev);
|
||||
|
||||
/* Notify the platform of the removal, in case they
|
||||
* need to do anything...
|
||||
*/
|
||||
if (platform_notify_remove)
|
||||
platform_notify_remove(dev);
|
||||
bus_remove_device(dev);
|
||||
if (dev->bus)
|
||||
blocking_notifier_call_chain(&dev->bus->bus_notifier,
|
||||
BUS_NOTIFY_DEL_DEVICE, dev);
|
||||
device_pm_remove(dev);
|
||||
kobject_uevent(&dev->kobj, KOBJ_REMOVE);
|
||||
kobject_del(&dev->kobj);
|
||||
@ -681,12 +750,45 @@ int device_for_each_child(struct device * parent, void * data,
|
||||
return error;
|
||||
}
|
||||
|
||||
/**
|
||||
* device_find_child - device iterator for locating a particular device.
|
||||
* @parent: parent struct device
|
||||
* @data: Data to pass to match function
|
||||
* @match: Callback function to check device
|
||||
*
|
||||
* This is similar to the device_for_each_child() function above, but it
|
||||
* returns a reference to a device that is 'found' for later use, as
|
||||
* determined by the @match callback.
|
||||
*
|
||||
* The callback should return 0 if the device doesn't match and non-zero
|
||||
* if it does. If the callback returns non-zero and a reference to the
|
||||
* current device can be obtained, this function will return to the caller
|
||||
* and not iterate over any more devices.
|
||||
*/
|
||||
struct device * device_find_child(struct device *parent, void *data,
|
||||
int (*match)(struct device *, void *))
|
||||
{
|
||||
struct klist_iter i;
|
||||
struct device *child;
|
||||
|
||||
if (!parent)
|
||||
return NULL;
|
||||
|
||||
klist_iter_init(&parent->klist_children, &i);
|
||||
while ((child = next_device(&i)))
|
||||
if (match(child, data) && get_device(child))
|
||||
break;
|
||||
klist_iter_exit(&i);
|
||||
return child;
|
||||
}
|
||||
|
||||
int __init devices_init(void)
|
||||
{
|
||||
return subsystem_register(&devices_subsys);
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL_GPL(device_for_each_child);
|
||||
EXPORT_SYMBOL_GPL(device_find_child);
|
||||
|
||||
EXPORT_SYMBOL_GPL(device_initialize);
|
||||
EXPORT_SYMBOL_GPL(device_add);
|
||||
@ -809,8 +911,10 @@ int device_rename(struct device *dev, char *new_name)
|
||||
|
||||
pr_debug("DEVICE: renaming '%s' to '%s'\n", dev->bus_id, new_name);
|
||||
|
||||
#ifdef CONFIG_SYSFS_DEPRECATED
|
||||
if ((dev->class) && (dev->parent))
|
||||
old_class_name = make_class_name(dev->class->name, &dev->kobj);
|
||||
#endif
|
||||
|
||||
if (dev->class) {
|
||||
old_symlink_name = kmalloc(BUS_ID_SIZE, GFP_KERNEL);
|
||||
@ -825,6 +929,7 @@ int device_rename(struct device *dev, char *new_name)
|
||||
|
||||
error = kobject_rename(&dev->kobj, new_name);
|
||||
|
||||
#ifdef CONFIG_SYSFS_DEPRECATED
|
||||
if (old_class_name) {
|
||||
new_class_name = make_class_name(dev->class->name, &dev->kobj);
|
||||
if (new_class_name) {
|
||||
@ -833,6 +938,8 @@ int device_rename(struct device *dev, char *new_name)
|
||||
sysfs_remove_link(&dev->parent->kobj, old_class_name);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (dev->class) {
|
||||
sysfs_remove_link(&dev->class->subsys.kset.kobj,
|
||||
old_symlink_name);
|
||||
@ -848,3 +955,95 @@ int device_rename(struct device *dev, char *new_name)
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
|
||||
static int device_move_class_links(struct device *dev,
|
||||
struct device *old_parent,
|
||||
struct device *new_parent)
|
||||
{
|
||||
#ifdef CONFIG_SYSFS_DEPRECATED
|
||||
int error;
|
||||
char *class_name;
|
||||
|
||||
class_name = make_class_name(dev->class->name, &dev->kobj);
|
||||
if (!class_name) {
|
||||
error = PTR_ERR(class_name);
|
||||
class_name = NULL;
|
||||
goto out;
|
||||
}
|
||||
if (old_parent) {
|
||||
sysfs_remove_link(&dev->kobj, "device");
|
||||
sysfs_remove_link(&old_parent->kobj, class_name);
|
||||
}
|
||||
error = sysfs_create_link(&dev->kobj, &new_parent->kobj, "device");
|
||||
if (error)
|
||||
goto out;
|
||||
error = sysfs_create_link(&new_parent->kobj, &dev->kobj, class_name);
|
||||
if (error)
|
||||
sysfs_remove_link(&dev->kobj, "device");
|
||||
out:
|
||||
kfree(class_name);
|
||||
return error;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* device_move - moves a device to a new parent
|
||||
* @dev: the pointer to the struct device to be moved
|
||||
* @new_parent: the new parent of the device
|
||||
*/
|
||||
int device_move(struct device *dev, struct device *new_parent)
|
||||
{
|
||||
int error;
|
||||
struct device *old_parent;
|
||||
|
||||
dev = get_device(dev);
|
||||
if (!dev)
|
||||
return -EINVAL;
|
||||
|
||||
if (!device_is_registered(dev)) {
|
||||
error = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
new_parent = get_device(new_parent);
|
||||
if (!new_parent) {
|
||||
error = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
pr_debug("DEVICE: moving '%s' to '%s'\n", dev->bus_id,
|
||||
new_parent->bus_id);
|
||||
error = kobject_move(&dev->kobj, &new_parent->kobj);
|
||||
if (error) {
|
||||
put_device(new_parent);
|
||||
goto out;
|
||||
}
|
||||
old_parent = dev->parent;
|
||||
dev->parent = new_parent;
|
||||
if (old_parent)
|
||||
klist_remove(&dev->knode_parent);
|
||||
klist_add_tail(&dev->knode_parent, &new_parent->klist_children);
|
||||
if (!dev->class)
|
||||
goto out_put;
|
||||
error = device_move_class_links(dev, old_parent, new_parent);
|
||||
if (error) {
|
||||
/* We ignore errors on cleanup since we're hosed anyway... */
|
||||
device_move_class_links(dev, new_parent, old_parent);
|
||||
if (!kobject_move(&dev->kobj, &old_parent->kobj)) {
|
||||
klist_remove(&dev->knode_parent);
|
||||
if (old_parent)
|
||||
klist_add_tail(&dev->knode_parent,
|
||||
&old_parent->klist_children);
|
||||
}
|
||||
put_device(new_parent);
|
||||
goto out;
|
||||
}
|
||||
out_put:
|
||||
put_device(old_parent);
|
||||
out:
|
||||
put_device(dev);
|
||||
return error;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL_GPL(device_move);
|
||||
|
@ -26,6 +26,50 @@
|
||||
#define to_drv(node) container_of(node, struct device_driver, kobj.entry)
|
||||
|
||||
|
||||
static void driver_bound(struct device *dev)
|
||||
{
|
||||
if (klist_node_attached(&dev->knode_driver)) {
|
||||
printk(KERN_WARNING "%s: device %s already bound\n",
|
||||
__FUNCTION__, kobject_name(&dev->kobj));
|
||||
return;
|
||||
}
|
||||
|
||||
pr_debug("bound device '%s' to driver '%s'\n",
|
||||
dev->bus_id, dev->driver->name);
|
||||
|
||||
if (dev->bus)
|
||||
blocking_notifier_call_chain(&dev->bus->bus_notifier,
|
||||
BUS_NOTIFY_BOUND_DRIVER, dev);
|
||||
|
||||
klist_add_tail(&dev->knode_driver, &dev->driver->klist_devices);
|
||||
}
|
||||
|
||||
static int driver_sysfs_add(struct device *dev)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = sysfs_create_link(&dev->driver->kobj, &dev->kobj,
|
||||
kobject_name(&dev->kobj));
|
||||
if (ret == 0) {
|
||||
ret = sysfs_create_link(&dev->kobj, &dev->driver->kobj,
|
||||
"driver");
|
||||
if (ret)
|
||||
sysfs_remove_link(&dev->driver->kobj,
|
||||
kobject_name(&dev->kobj));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void driver_sysfs_remove(struct device *dev)
|
||||
{
|
||||
struct device_driver *drv = dev->driver;
|
||||
|
||||
if (drv) {
|
||||
sysfs_remove_link(&drv->kobj, kobject_name(&dev->kobj));
|
||||
sysfs_remove_link(&dev->kobj, "driver");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* device_bind_driver - bind a driver to one device.
|
||||
* @dev: device.
|
||||
@ -42,27 +86,8 @@
|
||||
*/
|
||||
int device_bind_driver(struct device *dev)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (klist_node_attached(&dev->knode_driver)) {
|
||||
printk(KERN_WARNING "%s: device %s already bound\n",
|
||||
__FUNCTION__, kobject_name(&dev->kobj));
|
||||
return 0;
|
||||
}
|
||||
|
||||
pr_debug("bound device '%s' to driver '%s'\n",
|
||||
dev->bus_id, dev->driver->name);
|
||||
klist_add_tail(&dev->knode_driver, &dev->driver->klist_devices);
|
||||
ret = sysfs_create_link(&dev->driver->kobj, &dev->kobj,
|
||||
kobject_name(&dev->kobj));
|
||||
if (ret == 0) {
|
||||
ret = sysfs_create_link(&dev->kobj, &dev->driver->kobj,
|
||||
"driver");
|
||||
if (ret)
|
||||
sysfs_remove_link(&dev->driver->kobj,
|
||||
kobject_name(&dev->kobj));
|
||||
}
|
||||
return ret;
|
||||
driver_bound(dev);
|
||||
return driver_sysfs_add(dev);
|
||||
}
|
||||
|
||||
struct stupid_thread_structure {
|
||||
@ -85,30 +110,32 @@ static int really_probe(void *void_data)
|
||||
drv->bus->name, drv->name, dev->bus_id);
|
||||
|
||||
dev->driver = drv;
|
||||
if (driver_sysfs_add(dev)) {
|
||||
printk(KERN_ERR "%s: driver_sysfs_add(%s) failed\n",
|
||||
__FUNCTION__, dev->bus_id);
|
||||
goto probe_failed;
|
||||
}
|
||||
|
||||
if (dev->bus->probe) {
|
||||
ret = dev->bus->probe(dev);
|
||||
if (ret) {
|
||||
dev->driver = NULL;
|
||||
if (ret)
|
||||
goto probe_failed;
|
||||
}
|
||||
} else if (drv->probe) {
|
||||
ret = drv->probe(dev);
|
||||
if (ret) {
|
||||
dev->driver = NULL;
|
||||
if (ret)
|
||||
goto probe_failed;
|
||||
}
|
||||
}
|
||||
if (device_bind_driver(dev)) {
|
||||
printk(KERN_ERR "%s: device_bind_driver(%s) failed\n",
|
||||
__FUNCTION__, dev->bus_id);
|
||||
/* How does undo a ->probe? We're screwed. */
|
||||
}
|
||||
|
||||
driver_bound(dev);
|
||||
ret = 1;
|
||||
pr_debug("%s: Bound Device %s to Driver %s\n",
|
||||
drv->bus->name, dev->bus_id, drv->name);
|
||||
goto done;
|
||||
|
||||
probe_failed:
|
||||
driver_sysfs_remove(dev);
|
||||
dev->driver = NULL;
|
||||
|
||||
if (ret == -ENODEV || ret == -ENXIO) {
|
||||
/* Driver matched, but didn't support device
|
||||
* or device not found.
|
||||
@ -284,10 +311,15 @@ static void __device_release_driver(struct device * dev)
|
||||
drv = dev->driver;
|
||||
if (drv) {
|
||||
get_driver(drv);
|
||||
sysfs_remove_link(&drv->kobj, kobject_name(&dev->kobj));
|
||||
driver_sysfs_remove(dev);
|
||||
sysfs_remove_link(&dev->kobj, "driver");
|
||||
klist_remove(&dev->knode_driver);
|
||||
|
||||
if (dev->bus)
|
||||
blocking_notifier_call_chain(&dev->bus->bus_notifier,
|
||||
BUS_NOTIFY_UNBIND_DRIVER,
|
||||
dev);
|
||||
|
||||
if (dev->bus && dev->bus->remove)
|
||||
dev->bus->remove(dev);
|
||||
else if (drv->remove)
|
||||
|
@ -21,6 +21,8 @@
|
||||
#include <linux/firmware.h>
|
||||
#include "base.h"
|
||||
|
||||
#define to_dev(obj) container_of(obj, struct device, kobj)
|
||||
|
||||
MODULE_AUTHOR("Manuel Estrada Sainz <ranty@debian.org>");
|
||||
MODULE_DESCRIPTION("Multi purpose firmware loading support");
|
||||
MODULE_LICENSE("GPL");
|
||||
@ -86,12 +88,12 @@ firmware_timeout_store(struct class *class, const char *buf, size_t count)
|
||||
|
||||
static CLASS_ATTR(timeout, 0644, firmware_timeout_show, firmware_timeout_store);
|
||||
|
||||
static void fw_class_dev_release(struct class_device *class_dev);
|
||||
static void fw_dev_release(struct device *dev);
|
||||
|
||||
static int firmware_class_uevent(struct class_device *class_dev, char **envp,
|
||||
int num_envp, char *buffer, int buffer_size)
|
||||
static int firmware_uevent(struct device *dev, char **envp, int num_envp,
|
||||
char *buffer, int buffer_size)
|
||||
{
|
||||
struct firmware_priv *fw_priv = class_get_devdata(class_dev);
|
||||
struct firmware_priv *fw_priv = dev_get_drvdata(dev);
|
||||
int i = 0, len = 0;
|
||||
|
||||
if (!test_bit(FW_STATUS_READY, &fw_priv->status))
|
||||
@ -110,21 +112,21 @@ static int firmware_class_uevent(struct class_device *class_dev, char **envp,
|
||||
|
||||
static struct class firmware_class = {
|
||||
.name = "firmware",
|
||||
.uevent = firmware_class_uevent,
|
||||
.release = fw_class_dev_release,
|
||||
.dev_uevent = firmware_uevent,
|
||||
.dev_release = fw_dev_release,
|
||||
};
|
||||
|
||||
static ssize_t
|
||||
firmware_loading_show(struct class_device *class_dev, char *buf)
|
||||
static ssize_t firmware_loading_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct firmware_priv *fw_priv = class_get_devdata(class_dev);
|
||||
struct firmware_priv *fw_priv = dev_get_drvdata(dev);
|
||||
int loading = test_bit(FW_STATUS_LOADING, &fw_priv->status);
|
||||
return sprintf(buf, "%d\n", loading);
|
||||
}
|
||||
|
||||
/**
|
||||
* firmware_loading_store - set value in the 'loading' control file
|
||||
* @class_dev: class_device pointer
|
||||
* @dev: device pointer
|
||||
* @buf: buffer to scan for loading control value
|
||||
* @count: number of bytes in @buf
|
||||
*
|
||||
@ -134,11 +136,11 @@ firmware_loading_show(struct class_device *class_dev, char *buf)
|
||||
* 0: Conclude the load and hand the data to the driver code.
|
||||
* -1: Conclude the load with an error and discard any written data.
|
||||
**/
|
||||
static ssize_t
|
||||
firmware_loading_store(struct class_device *class_dev,
|
||||
const char *buf, size_t count)
|
||||
static ssize_t firmware_loading_store(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
struct firmware_priv *fw_priv = class_get_devdata(class_dev);
|
||||
struct firmware_priv *fw_priv = dev_get_drvdata(dev);
|
||||
int loading = simple_strtol(buf, NULL, 10);
|
||||
|
||||
switch (loading) {
|
||||
@ -174,15 +176,14 @@ firmware_loading_store(struct class_device *class_dev,
|
||||
return count;
|
||||
}
|
||||
|
||||
static CLASS_DEVICE_ATTR(loading, 0644,
|
||||
firmware_loading_show, firmware_loading_store);
|
||||
static DEVICE_ATTR(loading, 0644, firmware_loading_show, firmware_loading_store);
|
||||
|
||||
static ssize_t
|
||||
firmware_data_read(struct kobject *kobj,
|
||||
char *buffer, loff_t offset, size_t count)
|
||||
{
|
||||
struct class_device *class_dev = to_class_dev(kobj);
|
||||
struct firmware_priv *fw_priv = class_get_devdata(class_dev);
|
||||
struct device *dev = to_dev(kobj);
|
||||
struct firmware_priv *fw_priv = dev_get_drvdata(dev);
|
||||
struct firmware *fw;
|
||||
ssize_t ret_count = count;
|
||||
|
||||
@ -234,7 +235,7 @@ fw_realloc_buffer(struct firmware_priv *fw_priv, int min_size)
|
||||
|
||||
/**
|
||||
* firmware_data_write - write method for firmware
|
||||
* @kobj: kobject for the class_device
|
||||
* @kobj: kobject for the device
|
||||
* @buffer: buffer being written
|
||||
* @offset: buffer offset for write in total data store area
|
||||
* @count: buffer size
|
||||
@ -246,8 +247,8 @@ static ssize_t
|
||||
firmware_data_write(struct kobject *kobj,
|
||||
char *buffer, loff_t offset, size_t count)
|
||||
{
|
||||
struct class_device *class_dev = to_class_dev(kobj);
|
||||
struct firmware_priv *fw_priv = class_get_devdata(class_dev);
|
||||
struct device *dev = to_dev(kobj);
|
||||
struct firmware_priv *fw_priv = dev_get_drvdata(dev);
|
||||
struct firmware *fw;
|
||||
ssize_t retval;
|
||||
|
||||
@ -280,13 +281,12 @@ static struct bin_attribute firmware_attr_data_tmpl = {
|
||||
.write = firmware_data_write,
|
||||
};
|
||||
|
||||
static void
|
||||
fw_class_dev_release(struct class_device *class_dev)
|
||||
static void fw_dev_release(struct device *dev)
|
||||
{
|
||||
struct firmware_priv *fw_priv = class_get_devdata(class_dev);
|
||||
struct firmware_priv *fw_priv = dev_get_drvdata(dev);
|
||||
|
||||
kfree(fw_priv);
|
||||
kfree(class_dev);
|
||||
kfree(dev);
|
||||
|
||||
module_put(THIS_MODULE);
|
||||
}
|
||||
@ -298,26 +298,23 @@ firmware_class_timeout(u_long data)
|
||||
fw_load_abort(fw_priv);
|
||||
}
|
||||
|
||||
static inline void
|
||||
fw_setup_class_device_id(struct class_device *class_dev, struct device *dev)
|
||||
static inline void fw_setup_device_id(struct device *f_dev, struct device *dev)
|
||||
{
|
||||
/* XXX warning we should watch out for name collisions */
|
||||
strlcpy(class_dev->class_id, dev->bus_id, BUS_ID_SIZE);
|
||||
strlcpy(f_dev->bus_id, dev->bus_id, BUS_ID_SIZE);
|
||||
}
|
||||
|
||||
static int
|
||||
fw_register_class_device(struct class_device **class_dev_p,
|
||||
const char *fw_name, struct device *device)
|
||||
static int fw_register_device(struct device **dev_p, const char *fw_name,
|
||||
struct device *device)
|
||||
{
|
||||
int retval;
|
||||
struct firmware_priv *fw_priv = kzalloc(sizeof(*fw_priv),
|
||||
GFP_KERNEL);
|
||||
struct class_device *class_dev = kzalloc(sizeof(*class_dev),
|
||||
GFP_KERNEL);
|
||||
struct device *f_dev = kzalloc(sizeof(*f_dev), GFP_KERNEL);
|
||||
|
||||
*class_dev_p = NULL;
|
||||
*dev_p = NULL;
|
||||
|
||||
if (!fw_priv || !class_dev) {
|
||||
if (!fw_priv || !f_dev) {
|
||||
printk(KERN_ERR "%s: kmalloc failed\n", __FUNCTION__);
|
||||
retval = -ENOMEM;
|
||||
goto error_kfree;
|
||||
@ -331,55 +328,54 @@ fw_register_class_device(struct class_device **class_dev_p,
|
||||
fw_priv->timeout.data = (u_long) fw_priv;
|
||||
init_timer(&fw_priv->timeout);
|
||||
|
||||
fw_setup_class_device_id(class_dev, device);
|
||||
class_dev->dev = device;
|
||||
class_dev->class = &firmware_class;
|
||||
class_set_devdata(class_dev, fw_priv);
|
||||
retval = class_device_register(class_dev);
|
||||
fw_setup_device_id(f_dev, device);
|
||||
f_dev->parent = device;
|
||||
f_dev->class = &firmware_class;
|
||||
dev_set_drvdata(f_dev, fw_priv);
|
||||
retval = device_register(f_dev);
|
||||
if (retval) {
|
||||
printk(KERN_ERR "%s: class_device_register failed\n",
|
||||
printk(KERN_ERR "%s: device_register failed\n",
|
||||
__FUNCTION__);
|
||||
goto error_kfree;
|
||||
}
|
||||
*class_dev_p = class_dev;
|
||||
*dev_p = f_dev;
|
||||
return 0;
|
||||
|
||||
error_kfree:
|
||||
kfree(fw_priv);
|
||||
kfree(class_dev);
|
||||
kfree(f_dev);
|
||||
return retval;
|
||||
}
|
||||
|
||||
static int
|
||||
fw_setup_class_device(struct firmware *fw, struct class_device **class_dev_p,
|
||||
const char *fw_name, struct device *device, int uevent)
|
||||
static int fw_setup_device(struct firmware *fw, struct device **dev_p,
|
||||
const char *fw_name, struct device *device,
|
||||
int uevent)
|
||||
{
|
||||
struct class_device *class_dev;
|
||||
struct device *f_dev;
|
||||
struct firmware_priv *fw_priv;
|
||||
int retval;
|
||||
|
||||
*class_dev_p = NULL;
|
||||
retval = fw_register_class_device(&class_dev, fw_name, device);
|
||||
*dev_p = NULL;
|
||||
retval = fw_register_device(&f_dev, fw_name, device);
|
||||
if (retval)
|
||||
goto out;
|
||||
|
||||
/* Need to pin this module until class device is destroyed */
|
||||
__module_get(THIS_MODULE);
|
||||
|
||||
fw_priv = class_get_devdata(class_dev);
|
||||
fw_priv = dev_get_drvdata(f_dev);
|
||||
|
||||
fw_priv->fw = fw;
|
||||
retval = sysfs_create_bin_file(&class_dev->kobj, &fw_priv->attr_data);
|
||||
retval = sysfs_create_bin_file(&f_dev->kobj, &fw_priv->attr_data);
|
||||
if (retval) {
|
||||
printk(KERN_ERR "%s: sysfs_create_bin_file failed\n",
|
||||
__FUNCTION__);
|
||||
goto error_unreg;
|
||||
}
|
||||
|
||||
retval = class_device_create_file(class_dev,
|
||||
&class_device_attr_loading);
|
||||
retval = device_create_file(f_dev, &dev_attr_loading);
|
||||
if (retval) {
|
||||
printk(KERN_ERR "%s: class_device_create_file failed\n",
|
||||
printk(KERN_ERR "%s: device_create_file failed\n",
|
||||
__FUNCTION__);
|
||||
goto error_unreg;
|
||||
}
|
||||
@ -388,11 +384,11 @@ fw_setup_class_device(struct firmware *fw, struct class_device **class_dev_p,
|
||||
set_bit(FW_STATUS_READY, &fw_priv->status);
|
||||
else
|
||||
set_bit(FW_STATUS_READY_NOHOTPLUG, &fw_priv->status);
|
||||
*class_dev_p = class_dev;
|
||||
*dev_p = f_dev;
|
||||
goto out;
|
||||
|
||||
error_unreg:
|
||||
class_device_unregister(class_dev);
|
||||
device_unregister(f_dev);
|
||||
out:
|
||||
return retval;
|
||||
}
|
||||
@ -401,7 +397,7 @@ static int
|
||||
_request_firmware(const struct firmware **firmware_p, const char *name,
|
||||
struct device *device, int uevent)
|
||||
{
|
||||
struct class_device *class_dev;
|
||||
struct device *f_dev;
|
||||
struct firmware_priv *fw_priv;
|
||||
struct firmware *firmware;
|
||||
int retval;
|
||||
@ -417,12 +413,11 @@ _request_firmware(const struct firmware **firmware_p, const char *name,
|
||||
goto out;
|
||||
}
|
||||
|
||||
retval = fw_setup_class_device(firmware, &class_dev, name, device,
|
||||
uevent);
|
||||
retval = fw_setup_device(firmware, &f_dev, name, device, uevent);
|
||||
if (retval)
|
||||
goto error_kfree_fw;
|
||||
|
||||
fw_priv = class_get_devdata(class_dev);
|
||||
fw_priv = dev_get_drvdata(f_dev);
|
||||
|
||||
if (uevent) {
|
||||
if (loading_timeout > 0) {
|
||||
@ -430,7 +425,7 @@ _request_firmware(const struct firmware **firmware_p, const char *name,
|
||||
add_timer(&fw_priv->timeout);
|
||||
}
|
||||
|
||||
kobject_uevent(&class_dev->kobj, KOBJ_ADD);
|
||||
kobject_uevent(&f_dev->kobj, KOBJ_ADD);
|
||||
wait_for_completion(&fw_priv->completion);
|
||||
set_bit(FW_STATUS_DONE, &fw_priv->status);
|
||||
del_timer_sync(&fw_priv->timeout);
|
||||
@ -445,7 +440,7 @@ _request_firmware(const struct firmware **firmware_p, const char *name,
|
||||
}
|
||||
fw_priv->fw = NULL;
|
||||
mutex_unlock(&fw_lock);
|
||||
class_device_unregister(class_dev);
|
||||
device_unregister(f_dev);
|
||||
goto out;
|
||||
|
||||
error_kfree_fw:
|
||||
|
@ -388,6 +388,11 @@ static int platform_drv_probe(struct device *_dev)
|
||||
return drv->probe(dev);
|
||||
}
|
||||
|
||||
static int platform_drv_probe_fail(struct device *_dev)
|
||||
{
|
||||
return -ENXIO;
|
||||
}
|
||||
|
||||
static int platform_drv_remove(struct device *_dev)
|
||||
{
|
||||
struct platform_driver *drv = to_platform_driver(_dev->driver);
|
||||
@ -451,6 +456,49 @@ void platform_driver_unregister(struct platform_driver *drv)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(platform_driver_unregister);
|
||||
|
||||
/**
|
||||
* platform_driver_probe - register driver for non-hotpluggable device
|
||||
* @drv: platform driver structure
|
||||
* @probe: the driver probe routine, probably from an __init section
|
||||
*
|
||||
* Use this instead of platform_driver_register() when you know the device
|
||||
* is not hotpluggable and has already been registered, and you want to
|
||||
* remove its run-once probe() infrastructure from memory after the driver
|
||||
* has bound to the device.
|
||||
*
|
||||
* One typical use for this would be with drivers for controllers integrated
|
||||
* into system-on-chip processors, where the controller devices have been
|
||||
* configured as part of board setup.
|
||||
*
|
||||
* Returns zero if the driver registered and bound to a device, else returns
|
||||
* a negative error code and with the driver not registered.
|
||||
*/
|
||||
int platform_driver_probe(struct platform_driver *drv,
|
||||
int (*probe)(struct platform_device *))
|
||||
{
|
||||
int retval, code;
|
||||
|
||||
/* temporary section violation during probe() */
|
||||
drv->probe = probe;
|
||||
retval = code = platform_driver_register(drv);
|
||||
|
||||
/* Fixup that section violation, being paranoid about code scanning
|
||||
* the list of drivers in order to probe new devices. Check to see
|
||||
* if the probe was successful, and make sure any forced probes of
|
||||
* new devices fail.
|
||||
*/
|
||||
spin_lock(&platform_bus_type.klist_drivers.k_lock);
|
||||
drv->probe = NULL;
|
||||
if (code == 0 && list_empty(&drv->driver.klist_devices.k_list))
|
||||
retval = -ENODEV;
|
||||
drv->driver.probe = platform_drv_probe_fail;
|
||||
spin_unlock(&platform_bus_type.klist_drivers.k_lock);
|
||||
|
||||
if (code != retval)
|
||||
platform_driver_unregister(drv);
|
||||
return retval;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(platform_driver_probe);
|
||||
|
||||
/* modalias support enables more hands-off userspace setup:
|
||||
* (a) environment variable lets new-style hotplug events work once system is
|
||||
|
@ -94,54 +94,63 @@ static struct attribute_group topology_attr_group = {
|
||||
.name = "topology"
|
||||
};
|
||||
|
||||
static cpumask_t topology_dev_map = CPU_MASK_NONE;
|
||||
|
||||
/* Add/Remove cpu_topology interface for CPU device */
|
||||
static int __cpuinit topology_add_dev(struct sys_device * sys_dev)
|
||||
static int __cpuinit topology_add_dev(unsigned int cpu)
|
||||
{
|
||||
return sysfs_create_group(&sys_dev->kobj, &topology_attr_group);
|
||||
int rc;
|
||||
struct sys_device *sys_dev = get_cpu_sysdev(cpu);
|
||||
|
||||
rc = sysfs_create_group(&sys_dev->kobj, &topology_attr_group);
|
||||
if (!rc)
|
||||
cpu_set(cpu, topology_dev_map);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int __cpuinit topology_remove_dev(struct sys_device * sys_dev)
|
||||
#ifdef CONFIG_HOTPLUG_CPU
|
||||
static void __cpuinit topology_remove_dev(unsigned int cpu)
|
||||
{
|
||||
struct sys_device *sys_dev = get_cpu_sysdev(cpu);
|
||||
|
||||
if (!cpu_isset(cpu, topology_dev_map))
|
||||
return;
|
||||
cpu_clear(cpu, topology_dev_map);
|
||||
sysfs_remove_group(&sys_dev->kobj, &topology_attr_group);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __cpuinit topology_cpu_callback(struct notifier_block *nfb,
|
||||
unsigned long action, void *hcpu)
|
||||
unsigned long action, void *hcpu)
|
||||
{
|
||||
unsigned int cpu = (unsigned long)hcpu;
|
||||
struct sys_device *sys_dev;
|
||||
int rc = 0;
|
||||
|
||||
sys_dev = get_cpu_sysdev(cpu);
|
||||
switch (action) {
|
||||
case CPU_ONLINE:
|
||||
topology_add_dev(sys_dev);
|
||||
case CPU_UP_PREPARE:
|
||||
rc = topology_add_dev(cpu);
|
||||
break;
|
||||
case CPU_UP_CANCELED:
|
||||
case CPU_DEAD:
|
||||
topology_remove_dev(sys_dev);
|
||||
topology_remove_dev(cpu);
|
||||
break;
|
||||
}
|
||||
return NOTIFY_OK;
|
||||
return rc ? NOTIFY_BAD : NOTIFY_OK;
|
||||
}
|
||||
|
||||
static struct notifier_block __cpuinitdata topology_cpu_notifier =
|
||||
{
|
||||
.notifier_call = topology_cpu_callback,
|
||||
};
|
||||
#endif
|
||||
|
||||
static int __cpuinit topology_sysfs_init(void)
|
||||
{
|
||||
int i;
|
||||
int cpu;
|
||||
int rc;
|
||||
|
||||
for_each_online_cpu(i) {
|
||||
topology_cpu_callback(&topology_cpu_notifier, CPU_ONLINE,
|
||||
(void *)(long)i);
|
||||
for_each_online_cpu(cpu) {
|
||||
rc = topology_add_dev(cpu);
|
||||
if (rc)
|
||||
return rc;
|
||||
}
|
||||
|
||||
register_hotcpu_notifier(&topology_cpu_notifier);
|
||||
hotcpu_notifier(topology_cpu_callback, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
device_initcall(topology_sysfs_init);
|
||||
|
||||
|
@ -162,7 +162,8 @@ static struct miscdevice rng_miscdev = {
|
||||
};
|
||||
|
||||
|
||||
static ssize_t hwrng_attr_current_store(struct class_device *class,
|
||||
static ssize_t hwrng_attr_current_store(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
const char *buf, size_t len)
|
||||
{
|
||||
int err;
|
||||
@ -192,7 +193,8 @@ static ssize_t hwrng_attr_current_store(struct class_device *class,
|
||||
return err ? : len;
|
||||
}
|
||||
|
||||
static ssize_t hwrng_attr_current_show(struct class_device *class,
|
||||
static ssize_t hwrng_attr_current_show(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
int err;
|
||||
@ -210,7 +212,8 @@ static ssize_t hwrng_attr_current_show(struct class_device *class,
|
||||
return ret;
|
||||
}
|
||||
|
||||
static ssize_t hwrng_attr_available_show(struct class_device *class,
|
||||
static ssize_t hwrng_attr_available_show(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
int err;
|
||||
@ -234,20 +237,18 @@ static ssize_t hwrng_attr_available_show(struct class_device *class,
|
||||
return ret;
|
||||
}
|
||||
|
||||
static CLASS_DEVICE_ATTR(rng_current, S_IRUGO | S_IWUSR,
|
||||
hwrng_attr_current_show,
|
||||
hwrng_attr_current_store);
|
||||
static CLASS_DEVICE_ATTR(rng_available, S_IRUGO,
|
||||
hwrng_attr_available_show,
|
||||
NULL);
|
||||
static DEVICE_ATTR(rng_current, S_IRUGO | S_IWUSR,
|
||||
hwrng_attr_current_show,
|
||||
hwrng_attr_current_store);
|
||||
static DEVICE_ATTR(rng_available, S_IRUGO,
|
||||
hwrng_attr_available_show,
|
||||
NULL);
|
||||
|
||||
|
||||
static void unregister_miscdev(void)
|
||||
{
|
||||
class_device_remove_file(rng_miscdev.class,
|
||||
&class_device_attr_rng_available);
|
||||
class_device_remove_file(rng_miscdev.class,
|
||||
&class_device_attr_rng_current);
|
||||
device_remove_file(rng_miscdev.this_device, &dev_attr_rng_available);
|
||||
device_remove_file(rng_miscdev.this_device, &dev_attr_rng_current);
|
||||
misc_deregister(&rng_miscdev);
|
||||
}
|
||||
|
||||
@ -258,20 +259,19 @@ static int register_miscdev(void)
|
||||
err = misc_register(&rng_miscdev);
|
||||
if (err)
|
||||
goto out;
|
||||
err = class_device_create_file(rng_miscdev.class,
|
||||
&class_device_attr_rng_current);
|
||||
err = device_create_file(rng_miscdev.this_device,
|
||||
&dev_attr_rng_current);
|
||||
if (err)
|
||||
goto err_misc_dereg;
|
||||
err = class_device_create_file(rng_miscdev.class,
|
||||
&class_device_attr_rng_available);
|
||||
err = device_create_file(rng_miscdev.this_device,
|
||||
&dev_attr_rng_available);
|
||||
if (err)
|
||||
goto err_remove_current;
|
||||
out:
|
||||
return err;
|
||||
|
||||
err_remove_current:
|
||||
class_device_remove_file(rng_miscdev.class,
|
||||
&class_device_attr_rng_current);
|
||||
device_remove_file(rng_miscdev.this_device, &dev_attr_rng_current);
|
||||
err_misc_dereg:
|
||||
misc_deregister(&rng_miscdev);
|
||||
goto out;
|
||||
|
@ -980,10 +980,10 @@ static int __init chr_dev_init(void)
|
||||
|
||||
mem_class = class_create(THIS_MODULE, "mem");
|
||||
for (i = 0; i < ARRAY_SIZE(devlist); i++)
|
||||
class_device_create(mem_class, NULL,
|
||||
MKDEV(MEM_MAJOR, devlist[i].minor),
|
||||
NULL, devlist[i].name);
|
||||
|
||||
device_create(mem_class, NULL,
|
||||
MKDEV(MEM_MAJOR, devlist[i].minor),
|
||||
devlist[i].name);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -169,11 +169,6 @@ fail:
|
||||
return err;
|
||||
}
|
||||
|
||||
/*
|
||||
* TODO for 2.7:
|
||||
* - add a struct kref to struct miscdevice and make all usages of
|
||||
* them dynamic.
|
||||
*/
|
||||
static struct class *misc_class;
|
||||
|
||||
static const struct file_operations misc_fops = {
|
||||
@ -228,10 +223,10 @@ int misc_register(struct miscdevice * misc)
|
||||
misc_minors[misc->minor >> 3] |= 1 << (misc->minor & 7);
|
||||
dev = MKDEV(MISC_MAJOR, misc->minor);
|
||||
|
||||
misc->class = class_device_create(misc_class, NULL, dev, misc->dev,
|
||||
misc->this_device = device_create(misc_class, misc->parent, dev,
|
||||
"%s", misc->name);
|
||||
if (IS_ERR(misc->class)) {
|
||||
err = PTR_ERR(misc->class);
|
||||
if (IS_ERR(misc->this_device)) {
|
||||
err = PTR_ERR(misc->this_device);
|
||||
goto out;
|
||||
}
|
||||
|
||||
@ -264,7 +259,7 @@ int misc_deregister(struct miscdevice * misc)
|
||||
|
||||
down(&misc_sem);
|
||||
list_del(&misc->list);
|
||||
class_device_destroy(misc_class, MKDEV(MISC_MAJOR, misc->minor));
|
||||
device_destroy(misc_class, MKDEV(MISC_MAJOR, misc->minor));
|
||||
if (i < DYNAMIC_MINORS && i>0) {
|
||||
misc_minors[i>>3] &= ~(1 << (misc->minor & 7));
|
||||
}
|
||||
|
@ -752,13 +752,13 @@ static const struct file_operations pp_fops = {
|
||||
|
||||
static void pp_attach(struct parport *port)
|
||||
{
|
||||
class_device_create(ppdev_class, NULL, MKDEV(PP_MAJOR, port->number),
|
||||
NULL, "parport%d", port->number);
|
||||
device_create(ppdev_class, NULL, MKDEV(PP_MAJOR, port->number),
|
||||
"parport%d", port->number);
|
||||
}
|
||||
|
||||
static void pp_detach(struct parport *port)
|
||||
{
|
||||
class_device_destroy(ppdev_class, MKDEV(PP_MAJOR, port->number));
|
||||
device_destroy(ppdev_class, MKDEV(PP_MAJOR, port->number));
|
||||
}
|
||||
|
||||
static struct parport_driver pp_driver = {
|
||||
|
@ -127,9 +127,9 @@ raw_ioctl(struct inode *inode, struct file *filp,
|
||||
|
||||
static void bind_device(struct raw_config_request *rq)
|
||||
{
|
||||
class_device_destroy(raw_class, MKDEV(RAW_MAJOR, rq->raw_minor));
|
||||
class_device_create(raw_class, NULL, MKDEV(RAW_MAJOR, rq->raw_minor),
|
||||
NULL, "raw%d", rq->raw_minor);
|
||||
device_destroy(raw_class, MKDEV(RAW_MAJOR, rq->raw_minor));
|
||||
device_create(raw_class, NULL, MKDEV(RAW_MAJOR, rq->raw_minor),
|
||||
"raw%d", rq->raw_minor);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -200,7 +200,7 @@ static int raw_ctl_ioctl(struct inode *inode, struct file *filp,
|
||||
if (rq.block_major == 0 && rq.block_minor == 0) {
|
||||
/* unbind */
|
||||
rawdev->binding = NULL;
|
||||
class_device_destroy(raw_class,
|
||||
device_destroy(raw_class,
|
||||
MKDEV(RAW_MAJOR, rq.raw_minor));
|
||||
} else {
|
||||
rawdev->binding = bdget(dev);
|
||||
@ -283,7 +283,7 @@ static int __init raw_init(void)
|
||||
ret = PTR_ERR(raw_class);
|
||||
goto error_region;
|
||||
}
|
||||
class_device_create(raw_class, NULL, MKDEV(RAW_MAJOR, 0), NULL, "rawctl");
|
||||
device_create(raw_class, NULL, MKDEV(RAW_MAJOR, 0), "rawctl");
|
||||
|
||||
return 0;
|
||||
|
||||
@ -295,7 +295,7 @@ error:
|
||||
|
||||
static void __exit raw_exit(void)
|
||||
{
|
||||
class_device_destroy(raw_class, MKDEV(RAW_MAJOR, 0));
|
||||
device_destroy(raw_class, MKDEV(RAW_MAJOR, 0));
|
||||
class_destroy(raw_class);
|
||||
cdev_del(&raw_cdev);
|
||||
unregister_chrdev_region(MKDEV(RAW_MAJOR, 0), MAX_RAW_MINORS);
|
||||
|
@ -1130,7 +1130,7 @@ struct tpm_chip *tpm_register_hardware(struct device *dev, const struct tpm_vend
|
||||
scnprintf(devname, DEVNAME_SIZE, "%s%d", "tpm", chip->dev_num);
|
||||
chip->vendor.miscdev.name = devname;
|
||||
|
||||
chip->vendor.miscdev.dev = dev;
|
||||
chip->vendor.miscdev.parent = dev;
|
||||
chip->dev = get_device(dev);
|
||||
|
||||
if (misc_register(&chip->vendor.miscdev)) {
|
||||
|
@ -3612,7 +3612,8 @@ static struct class *tty_class;
|
||||
* This field is optional, if there is no known struct device
|
||||
* for this tty device it can be set to NULL safely.
|
||||
*
|
||||
* Returns a pointer to the class device (or ERR_PTR(-EFOO) on error).
|
||||
* Returns a pointer to the struct device for this tty device
|
||||
* (or ERR_PTR(-EFOO) on error).
|
||||
*
|
||||
* This call is required to be made to register an individual tty device
|
||||
* if the tty driver's flags have the TTY_DRIVER_DYNAMIC_DEV bit set. If
|
||||
@ -3622,8 +3623,8 @@ static struct class *tty_class;
|
||||
* Locking: ??
|
||||
*/
|
||||
|
||||
struct class_device *tty_register_device(struct tty_driver *driver,
|
||||
unsigned index, struct device *device)
|
||||
struct device *tty_register_device(struct tty_driver *driver, unsigned index,
|
||||
struct device *device)
|
||||
{
|
||||
char name[64];
|
||||
dev_t dev = MKDEV(driver->major, driver->minor_start) + index;
|
||||
@ -3639,7 +3640,7 @@ struct class_device *tty_register_device(struct tty_driver *driver,
|
||||
else
|
||||
tty_line_name(driver, index, name);
|
||||
|
||||
return class_device_create(tty_class, NULL, dev, device, "%s", name);
|
||||
return device_create(tty_class, device, dev, name);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -3655,7 +3656,7 @@ struct class_device *tty_register_device(struct tty_driver *driver,
|
||||
|
||||
void tty_unregister_device(struct tty_driver *driver, unsigned index)
|
||||
{
|
||||
class_device_destroy(tty_class, MKDEV(driver->major, driver->minor_start) + index);
|
||||
device_destroy(tty_class, MKDEV(driver->major, driver->minor_start) + index);
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(tty_register_device);
|
||||
@ -3895,20 +3896,20 @@ static int __init tty_init(void)
|
||||
if (cdev_add(&tty_cdev, MKDEV(TTYAUX_MAJOR, 0), 1) ||
|
||||
register_chrdev_region(MKDEV(TTYAUX_MAJOR, 0), 1, "/dev/tty") < 0)
|
||||
panic("Couldn't register /dev/tty driver\n");
|
||||
class_device_create(tty_class, NULL, MKDEV(TTYAUX_MAJOR, 0), NULL, "tty");
|
||||
device_create(tty_class, NULL, MKDEV(TTYAUX_MAJOR, 0), "tty");
|
||||
|
||||
cdev_init(&console_cdev, &console_fops);
|
||||
if (cdev_add(&console_cdev, MKDEV(TTYAUX_MAJOR, 1), 1) ||
|
||||
register_chrdev_region(MKDEV(TTYAUX_MAJOR, 1), 1, "/dev/console") < 0)
|
||||
panic("Couldn't register /dev/console driver\n");
|
||||
class_device_create(tty_class, NULL, MKDEV(TTYAUX_MAJOR, 1), NULL, "console");
|
||||
device_create(tty_class, NULL, MKDEV(TTYAUX_MAJOR, 1), "console");
|
||||
|
||||
#ifdef CONFIG_UNIX98_PTYS
|
||||
cdev_init(&ptmx_cdev, &ptmx_fops);
|
||||
if (cdev_add(&ptmx_cdev, MKDEV(TTYAUX_MAJOR, 2), 1) ||
|
||||
register_chrdev_region(MKDEV(TTYAUX_MAJOR, 2), 1, "/dev/ptmx") < 0)
|
||||
panic("Couldn't register /dev/ptmx driver\n");
|
||||
class_device_create(tty_class, NULL, MKDEV(TTYAUX_MAJOR, 2), NULL, "ptmx");
|
||||
device_create(tty_class, NULL, MKDEV(TTYAUX_MAJOR, 2), "ptmx");
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_VT
|
||||
@ -3916,7 +3917,7 @@ static int __init tty_init(void)
|
||||
if (cdev_add(&vc0_cdev, MKDEV(TTY_MAJOR, 0), 1) ||
|
||||
register_chrdev_region(MKDEV(TTY_MAJOR, 0), 1, "/dev/vc/0") < 0)
|
||||
panic("Couldn't register /dev/tty0 driver\n");
|
||||
class_device_create(tty_class, NULL, MKDEV(TTY_MAJOR, 0), NULL, "tty0");
|
||||
device_create(tty_class, NULL, MKDEV(TTY_MAJOR, 0), "tty0");
|
||||
|
||||
vty_init();
|
||||
#endif
|
||||
|
@ -476,16 +476,16 @@ static struct class *vc_class;
|
||||
|
||||
void vcs_make_sysfs(struct tty_struct *tty)
|
||||
{
|
||||
class_device_create(vc_class, NULL, MKDEV(VCS_MAJOR, tty->index + 1),
|
||||
NULL, "vcs%u", tty->index + 1);
|
||||
class_device_create(vc_class, NULL, MKDEV(VCS_MAJOR, tty->index + 129),
|
||||
NULL, "vcsa%u", tty->index + 1);
|
||||
device_create(vc_class, NULL, MKDEV(VCS_MAJOR, tty->index + 1),
|
||||
"vcs%u", tty->index + 1);
|
||||
device_create(vc_class, NULL, MKDEV(VCS_MAJOR, tty->index + 129),
|
||||
"vcsa%u", tty->index + 1);
|
||||
}
|
||||
|
||||
void vcs_remove_sysfs(struct tty_struct *tty)
|
||||
{
|
||||
class_device_destroy(vc_class, MKDEV(VCS_MAJOR, tty->index + 1));
|
||||
class_device_destroy(vc_class, MKDEV(VCS_MAJOR, tty->index + 129));
|
||||
device_destroy(vc_class, MKDEV(VCS_MAJOR, tty->index + 1));
|
||||
device_destroy(vc_class, MKDEV(VCS_MAJOR, tty->index + 129));
|
||||
}
|
||||
|
||||
int __init vcs_init(void)
|
||||
@ -494,7 +494,7 @@ int __init vcs_init(void)
|
||||
panic("unable to get major %d for vcs device", VCS_MAJOR);
|
||||
vc_class = class_create(THIS_MODULE, "vc");
|
||||
|
||||
class_device_create(vc_class, NULL, MKDEV(VCS_MAJOR, 0), NULL, "vcs");
|
||||
class_device_create(vc_class, NULL, MKDEV(VCS_MAJOR, 128), NULL, "vcsa");
|
||||
device_create(vc_class, NULL, MKDEV(VCS_MAJOR, 0), "vcs");
|
||||
device_create(vc_class, NULL, MKDEV(VCS_MAJOR, 128), "vcsa");
|
||||
return 0;
|
||||
}
|
||||
|
@ -112,7 +112,7 @@
|
||||
struct con_driver {
|
||||
const struct consw *con;
|
||||
const char *desc;
|
||||
struct class_device *class_dev;
|
||||
struct device *dev;
|
||||
int node;
|
||||
int first;
|
||||
int last;
|
||||
@ -3023,10 +3023,10 @@ static inline int vt_unbind(struct con_driver *con)
|
||||
}
|
||||
#endif /* CONFIG_VT_HW_CONSOLE_BINDING */
|
||||
|
||||
static ssize_t store_bind(struct class_device *class_device,
|
||||
static ssize_t store_bind(struct device *dev, struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
struct con_driver *con = class_get_devdata(class_device);
|
||||
struct con_driver *con = dev_get_drvdata(dev);
|
||||
int bind = simple_strtoul(buf, NULL, 0);
|
||||
|
||||
if (bind)
|
||||
@ -3037,17 +3037,19 @@ static ssize_t store_bind(struct class_device *class_device,
|
||||
return count;
|
||||
}
|
||||
|
||||
static ssize_t show_bind(struct class_device *class_device, char *buf)
|
||||
static ssize_t show_bind(struct device *dev, struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct con_driver *con = class_get_devdata(class_device);
|
||||
struct con_driver *con = dev_get_drvdata(dev);
|
||||
int bind = con_is_bound(con->con);
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%i\n", bind);
|
||||
}
|
||||
|
||||
static ssize_t show_name(struct class_device *class_device, char *buf)
|
||||
static ssize_t show_name(struct device *dev, struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct con_driver *con = class_get_devdata(class_device);
|
||||
struct con_driver *con = dev_get_drvdata(dev);
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%s %s\n",
|
||||
(con->flag & CON_DRIVER_FLAG_MODULE) ? "(M)" : "(S)",
|
||||
@ -3055,43 +3057,40 @@ static ssize_t show_name(struct class_device *class_device, char *buf)
|
||||
|
||||
}
|
||||
|
||||
static struct class_device_attribute class_device_attrs[] = {
|
||||
static struct device_attribute device_attrs[] = {
|
||||
__ATTR(bind, S_IRUGO|S_IWUSR, show_bind, store_bind),
|
||||
__ATTR(name, S_IRUGO, show_name, NULL),
|
||||
};
|
||||
|
||||
static int vtconsole_init_class_device(struct con_driver *con)
|
||||
static int vtconsole_init_device(struct con_driver *con)
|
||||
{
|
||||
int i;
|
||||
int error = 0;
|
||||
|
||||
con->flag |= CON_DRIVER_FLAG_ATTR;
|
||||
class_set_devdata(con->class_dev, con);
|
||||
for (i = 0; i < ARRAY_SIZE(class_device_attrs); i++) {
|
||||
error = class_device_create_file(con->class_dev,
|
||||
&class_device_attrs[i]);
|
||||
dev_set_drvdata(con->dev, con);
|
||||
for (i = 0; i < ARRAY_SIZE(device_attrs); i++) {
|
||||
error = device_create_file(con->dev, &device_attrs[i]);
|
||||
if (error)
|
||||
break;
|
||||
}
|
||||
|
||||
if (error) {
|
||||
while (--i >= 0)
|
||||
class_device_remove_file(con->class_dev,
|
||||
&class_device_attrs[i]);
|
||||
device_remove_file(con->dev, &device_attrs[i]);
|
||||
con->flag &= ~CON_DRIVER_FLAG_ATTR;
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
static void vtconsole_deinit_class_device(struct con_driver *con)
|
||||
static void vtconsole_deinit_device(struct con_driver *con)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (con->flag & CON_DRIVER_FLAG_ATTR) {
|
||||
for (i = 0; i < ARRAY_SIZE(class_device_attrs); i++)
|
||||
class_device_remove_file(con->class_dev,
|
||||
&class_device_attrs[i]);
|
||||
for (i = 0; i < ARRAY_SIZE(device_attrs); i++)
|
||||
device_remove_file(con->dev, &device_attrs[i]);
|
||||
con->flag &= ~CON_DRIVER_FLAG_ATTR;
|
||||
}
|
||||
}
|
||||
@ -3179,18 +3178,17 @@ int register_con_driver(const struct consw *csw, int first, int last)
|
||||
if (retval)
|
||||
goto err;
|
||||
|
||||
con_driver->class_dev = class_device_create(vtconsole_class, NULL,
|
||||
MKDEV(0, con_driver->node),
|
||||
NULL, "vtcon%i",
|
||||
con_driver->node);
|
||||
con_driver->dev = device_create(vtconsole_class, NULL,
|
||||
MKDEV(0, con_driver->node),
|
||||
"vtcon%i", con_driver->node);
|
||||
|
||||
if (IS_ERR(con_driver->class_dev)) {
|
||||
printk(KERN_WARNING "Unable to create class_device for %s; "
|
||||
if (IS_ERR(con_driver->dev)) {
|
||||
printk(KERN_WARNING "Unable to create device for %s; "
|
||||
"errno = %ld\n", con_driver->desc,
|
||||
PTR_ERR(con_driver->class_dev));
|
||||
con_driver->class_dev = NULL;
|
||||
PTR_ERR(con_driver->dev));
|
||||
con_driver->dev = NULL;
|
||||
} else {
|
||||
vtconsole_init_class_device(con_driver);
|
||||
vtconsole_init_device(con_driver);
|
||||
}
|
||||
|
||||
err:
|
||||
@ -3226,12 +3224,12 @@ int unregister_con_driver(const struct consw *csw)
|
||||
|
||||
if (con_driver->con == csw &&
|
||||
con_driver->flag & CON_DRIVER_FLAG_MODULE) {
|
||||
vtconsole_deinit_class_device(con_driver);
|
||||
class_device_destroy(vtconsole_class,
|
||||
MKDEV(0, con_driver->node));
|
||||
vtconsole_deinit_device(con_driver);
|
||||
device_destroy(vtconsole_class,
|
||||
MKDEV(0, con_driver->node));
|
||||
con_driver->con = NULL;
|
||||
con_driver->desc = NULL;
|
||||
con_driver->class_dev = NULL;
|
||||
con_driver->dev = NULL;
|
||||
con_driver->node = 0;
|
||||
con_driver->flag = 0;
|
||||
con_driver->first = 0;
|
||||
@ -3289,19 +3287,18 @@ static int __init vtconsole_class_init(void)
|
||||
for (i = 0; i < MAX_NR_CON_DRIVER; i++) {
|
||||
struct con_driver *con = ®istered_con_driver[i];
|
||||
|
||||
if (con->con && !con->class_dev) {
|
||||
con->class_dev =
|
||||
class_device_create(vtconsole_class, NULL,
|
||||
MKDEV(0, con->node), NULL,
|
||||
"vtcon%i", con->node);
|
||||
if (con->con && !con->dev) {
|
||||
con->dev = device_create(vtconsole_class, NULL,
|
||||
MKDEV(0, con->node),
|
||||
"vtcon%i", con->node);
|
||||
|
||||
if (IS_ERR(con->class_dev)) {
|
||||
if (IS_ERR(con->dev)) {
|
||||
printk(KERN_WARNING "Unable to create "
|
||||
"class_device for %s; errno = %ld\n",
|
||||
con->desc, PTR_ERR(con->class_dev));
|
||||
con->class_dev = NULL;
|
||||
"device for %s; errno = %ld\n",
|
||||
con->desc, PTR_ERR(con->dev));
|
||||
con->dev = NULL;
|
||||
} else {
|
||||
vtconsole_init_class_device(con);
|
||||
vtconsole_init_device(con);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -42,7 +42,7 @@ static struct i2c_driver i2cdev_driver;
|
||||
struct i2c_dev {
|
||||
struct list_head list;
|
||||
struct i2c_adapter *adap;
|
||||
struct class_device *class_dev;
|
||||
struct device *dev;
|
||||
};
|
||||
|
||||
#define I2C_MINORS 256
|
||||
@ -92,15 +92,16 @@ static void return_i2c_dev(struct i2c_dev *i2c_dev)
|
||||
spin_unlock(&i2c_dev_list_lock);
|
||||
}
|
||||
|
||||
static ssize_t show_adapter_name(struct class_device *class_dev, char *buf)
|
||||
static ssize_t show_adapter_name(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct i2c_dev *i2c_dev = i2c_dev_get_by_minor(MINOR(class_dev->devt));
|
||||
struct i2c_dev *i2c_dev = i2c_dev_get_by_minor(MINOR(dev->devt));
|
||||
|
||||
if (!i2c_dev)
|
||||
return -ENODEV;
|
||||
return sprintf(buf, "%s\n", i2c_dev->adap->name);
|
||||
}
|
||||
static CLASS_DEVICE_ATTR(name, S_IRUGO, show_adapter_name, NULL);
|
||||
static DEVICE_ATTR(name, S_IRUGO, show_adapter_name, NULL);
|
||||
|
||||
static ssize_t i2cdev_read (struct file *file, char __user *buf, size_t count,
|
||||
loff_t *offset)
|
||||
@ -413,15 +414,14 @@ static int i2cdev_attach_adapter(struct i2c_adapter *adap)
|
||||
return PTR_ERR(i2c_dev);
|
||||
|
||||
/* register this i2c device with the driver core */
|
||||
i2c_dev->class_dev = class_device_create(i2c_dev_class, NULL,
|
||||
MKDEV(I2C_MAJOR, adap->nr),
|
||||
&adap->dev, "i2c-%d",
|
||||
adap->nr);
|
||||
if (!i2c_dev->class_dev) {
|
||||
i2c_dev->dev = device_create(i2c_dev_class, &adap->dev,
|
||||
MKDEV(I2C_MAJOR, adap->nr),
|
||||
"i2c-%d", adap->nr);
|
||||
if (!i2c_dev->dev) {
|
||||
res = -ENODEV;
|
||||
goto error;
|
||||
}
|
||||
res = class_device_create_file(i2c_dev->class_dev, &class_device_attr_name);
|
||||
res = device_create_file(i2c_dev->dev, &dev_attr_name);
|
||||
if (res)
|
||||
goto error_destroy;
|
||||
|
||||
@ -429,7 +429,7 @@ static int i2cdev_attach_adapter(struct i2c_adapter *adap)
|
||||
adap->name, adap->nr);
|
||||
return 0;
|
||||
error_destroy:
|
||||
class_device_destroy(i2c_dev_class, MKDEV(I2C_MAJOR, adap->nr));
|
||||
device_destroy(i2c_dev_class, MKDEV(I2C_MAJOR, adap->nr));
|
||||
error:
|
||||
return_i2c_dev(i2c_dev);
|
||||
kfree(i2c_dev);
|
||||
@ -444,9 +444,9 @@ static int i2cdev_detach_adapter(struct i2c_adapter *adap)
|
||||
if (!i2c_dev) /* attach_adapter must have failed */
|
||||
return 0;
|
||||
|
||||
class_device_remove_file(i2c_dev->class_dev, &class_device_attr_name);
|
||||
device_remove_file(i2c_dev->dev, &dev_attr_name);
|
||||
return_i2c_dev(i2c_dev);
|
||||
class_device_destroy(i2c_dev_class, MKDEV(I2C_MAJOR, adap->nr));
|
||||
device_destroy(i2c_dev_class, MKDEV(I2C_MAJOR, adap->nr));
|
||||
kfree(i2c_dev);
|
||||
|
||||
pr_debug("i2c-dev: adapter [%s] unregistered\n", adap->name);
|
||||
|
@ -297,7 +297,7 @@ static int serio_raw_connect(struct serio *serio, struct serio_driver *drv)
|
||||
|
||||
serio_raw->dev.minor = PSMOUSE_MINOR;
|
||||
serio_raw->dev.name = serio_raw->name;
|
||||
serio_raw->dev.dev = &serio->dev;
|
||||
serio_raw->dev.parent = &serio->dev;
|
||||
serio_raw->dev.fops = &serio_raw_fops;
|
||||
|
||||
err = misc_register(&serio_raw->dev);
|
||||
|
@ -702,7 +702,7 @@ struct cardstate *gigaset_initcs(struct gigaset_driver *drv, int channels,
|
||||
cs->open_count = 0;
|
||||
cs->dev = NULL;
|
||||
cs->tty = NULL;
|
||||
cs->class = NULL;
|
||||
cs->tty_dev = NULL;
|
||||
cs->cidmode = cidmode != 0;
|
||||
|
||||
//if(onechannel) { //FIXME
|
||||
|
@ -444,7 +444,7 @@ struct cardstate {
|
||||
struct gigaset_driver *driver;
|
||||
unsigned minor_index;
|
||||
struct device *dev;
|
||||
struct class_device *class;
|
||||
struct device *tty_dev;
|
||||
|
||||
const struct gigaset_ops *ops;
|
||||
|
||||
|
@ -625,13 +625,13 @@ void gigaset_if_init(struct cardstate *cs)
|
||||
return;
|
||||
|
||||
tasklet_init(&cs->if_wake_tasklet, &if_wake, (unsigned long) cs);
|
||||
cs->class = tty_register_device(drv->tty, cs->minor_index, NULL);
|
||||
cs->tty_dev = tty_register_device(drv->tty, cs->minor_index, NULL);
|
||||
|
||||
if (!IS_ERR(cs->class))
|
||||
class_set_devdata(cs->class, cs);
|
||||
if (!IS_ERR(cs->tty_dev))
|
||||
dev_set_drvdata(cs->tty_dev, cs);
|
||||
else {
|
||||
warn("could not register device to the tty subsystem");
|
||||
cs->class = NULL;
|
||||
cs->tty_dev = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
@ -645,7 +645,7 @@ void gigaset_if_free(struct cardstate *cs)
|
||||
|
||||
tasklet_disable(&cs->if_wake_tasklet);
|
||||
tasklet_kill(&cs->if_wake_tasklet);
|
||||
cs->class = NULL;
|
||||
cs->tty_dev = NULL;
|
||||
tty_unregister_device(drv->tty, cs->minor_index);
|
||||
}
|
||||
|
||||
|
@ -16,11 +16,12 @@
|
||||
#include "gigaset.h"
|
||||
#include <linux/ctype.h>
|
||||
|
||||
static ssize_t show_cidmode(struct class_device *class, char *buf)
|
||||
static ssize_t show_cidmode(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
int ret;
|
||||
unsigned long flags;
|
||||
struct cardstate *cs = class_get_devdata(class);
|
||||
struct cardstate *cs = dev_get_drvdata(dev);
|
||||
|
||||
spin_lock_irqsave(&cs->lock, flags);
|
||||
ret = sprintf(buf, "%u\n", cs->cidmode);
|
||||
@ -29,10 +30,10 @@ static ssize_t show_cidmode(struct class_device *class, char *buf)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static ssize_t set_cidmode(struct class_device *class,
|
||||
static ssize_t set_cidmode(struct device *dev, struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
struct cardstate *cs = class_get_devdata(class);
|
||||
struct cardstate *cs = dev_get_drvdata(dev);
|
||||
long int value;
|
||||
char *end;
|
||||
|
||||
@ -64,25 +65,25 @@ static ssize_t set_cidmode(struct class_device *class,
|
||||
return count;
|
||||
}
|
||||
|
||||
static CLASS_DEVICE_ATTR(cidmode, S_IRUGO|S_IWUSR, show_cidmode, set_cidmode);
|
||||
static DEVICE_ATTR(cidmode, S_IRUGO|S_IWUSR, show_cidmode, set_cidmode);
|
||||
|
||||
/* free sysfs for device */
|
||||
void gigaset_free_dev_sysfs(struct cardstate *cs)
|
||||
{
|
||||
if (!cs->class)
|
||||
if (!cs->tty_dev)
|
||||
return;
|
||||
|
||||
gig_dbg(DEBUG_INIT, "removing sysfs entries");
|
||||
class_device_remove_file(cs->class, &class_device_attr_cidmode);
|
||||
device_remove_file(cs->tty_dev, &dev_attr_cidmode);
|
||||
}
|
||||
|
||||
/* initialize sysfs for device */
|
||||
void gigaset_init_dev_sysfs(struct cardstate *cs)
|
||||
{
|
||||
if (!cs->class)
|
||||
if (!cs->tty_dev)
|
||||
return;
|
||||
|
||||
gig_dbg(DEBUG_INIT, "setting up sysfs");
|
||||
if (class_device_create_file(cs->class, &class_device_attr_cidmode))
|
||||
if (device_create_file(cs->tty_dev, &dev_attr_cidmode))
|
||||
dev_err(cs->dev, "could not create sysfs attribute\n");
|
||||
}
|
||||
|
@ -130,8 +130,8 @@ int mmc_init_queue(struct mmc_queue *mq, struct mmc_card *card, spinlock_t *lock
|
||||
u64 limit = BLK_BOUNCE_HIGH;
|
||||
int ret;
|
||||
|
||||
if (host->dev->dma_mask && *host->dev->dma_mask)
|
||||
limit = *host->dev->dma_mask;
|
||||
if (mmc_dev(host)->dma_mask && *mmc_dev(host)->dma_mask)
|
||||
limit = *mmc_dev(host)->dma_mask;
|
||||
|
||||
mq->card = card;
|
||||
mq->queue = blk_init_queue(mmc_request, lock);
|
||||
|
@ -199,7 +199,7 @@ void mmc_init_card(struct mmc_card *card, struct mmc_host *host)
|
||||
memset(card, 0, sizeof(struct mmc_card));
|
||||
card->host = host;
|
||||
device_initialize(&card->dev);
|
||||
card->dev.parent = card->host->dev;
|
||||
card->dev.parent = mmc_dev(host);
|
||||
card->dev.bus = &mmc_bus_type;
|
||||
card->dev.release = mmc_release_card;
|
||||
}
|
||||
@ -242,7 +242,7 @@ void mmc_remove_card(struct mmc_card *card)
|
||||
}
|
||||
|
||||
|
||||
static void mmc_host_classdev_release(struct class_device *dev)
|
||||
static void mmc_host_classdev_release(struct device *dev)
|
||||
{
|
||||
struct mmc_host *host = cls_dev_to_mmc_host(dev);
|
||||
kfree(host);
|
||||
@ -250,7 +250,7 @@ static void mmc_host_classdev_release(struct class_device *dev)
|
||||
|
||||
static struct class mmc_host_class = {
|
||||
.name = "mmc_host",
|
||||
.release = mmc_host_classdev_release,
|
||||
.dev_release = mmc_host_classdev_release,
|
||||
};
|
||||
|
||||
static DEFINE_IDR(mmc_host_idr);
|
||||
@ -267,10 +267,10 @@ struct mmc_host *mmc_alloc_host_sysfs(int extra, struct device *dev)
|
||||
if (host) {
|
||||
memset(host, 0, sizeof(struct mmc_host) + extra);
|
||||
|
||||
host->dev = dev;
|
||||
host->class_dev.dev = host->dev;
|
||||
host->parent = dev;
|
||||
host->class_dev.parent = dev;
|
||||
host->class_dev.class = &mmc_host_class;
|
||||
class_device_initialize(&host->class_dev);
|
||||
device_initialize(&host->class_dev);
|
||||
}
|
||||
|
||||
return host;
|
||||
@ -292,10 +292,10 @@ int mmc_add_host_sysfs(struct mmc_host *host)
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
snprintf(host->class_dev.class_id, BUS_ID_SIZE,
|
||||
snprintf(host->class_dev.bus_id, BUS_ID_SIZE,
|
||||
"mmc%d", host->index);
|
||||
|
||||
return class_device_add(&host->class_dev);
|
||||
return device_add(&host->class_dev);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -303,7 +303,7 @@ int mmc_add_host_sysfs(struct mmc_host *host)
|
||||
*/
|
||||
void mmc_remove_host_sysfs(struct mmc_host *host)
|
||||
{
|
||||
class_device_del(&host->class_dev);
|
||||
device_del(&host->class_dev);
|
||||
|
||||
spin_lock(&mmc_host_lock);
|
||||
idr_remove(&mmc_host_idr, host->index);
|
||||
@ -315,7 +315,7 @@ void mmc_remove_host_sysfs(struct mmc_host *host)
|
||||
*/
|
||||
void mmc_free_host_sysfs(struct mmc_host *host)
|
||||
{
|
||||
class_device_put(&host->class_dev);
|
||||
put_device(&host->class_dev);
|
||||
}
|
||||
|
||||
static struct workqueue_struct *workqueue;
|
||||
|
@ -1488,7 +1488,7 @@ static void __devinit wbsd_request_dma(struct wbsd_host *host, int dma)
|
||||
/*
|
||||
* Translate the address to a physical address.
|
||||
*/
|
||||
host->dma_addr = dma_map_single(host->mmc->dev, host->dma_buffer,
|
||||
host->dma_addr = dma_map_single(mmc_dev(host->mmc), host->dma_buffer,
|
||||
WBSD_DMA_SIZE, DMA_BIDIRECTIONAL);
|
||||
|
||||
/*
|
||||
@ -1512,7 +1512,7 @@ kfree:
|
||||
*/
|
||||
BUG_ON(1);
|
||||
|
||||
dma_unmap_single(host->mmc->dev, host->dma_addr,
|
||||
dma_unmap_single(mmc_dev(host->mmc), host->dma_addr,
|
||||
WBSD_DMA_SIZE, DMA_BIDIRECTIONAL);
|
||||
host->dma_addr = (dma_addr_t)NULL;
|
||||
|
||||
@ -1530,7 +1530,7 @@ err:
|
||||
static void __devexit wbsd_release_dma(struct wbsd_host *host)
|
||||
{
|
||||
if (host->dma_addr) {
|
||||
dma_unmap_single(host->mmc->dev, host->dma_addr,
|
||||
dma_unmap_single(mmc_dev(host->mmc), host->dma_addr,
|
||||
WBSD_DMA_SIZE, DMA_BIDIRECTIONAL);
|
||||
}
|
||||
kfree(host->dma_buffer);
|
||||
|
@ -860,7 +860,7 @@ static int __init ppp_init(void)
|
||||
err = PTR_ERR(ppp_class);
|
||||
goto out_chrdev;
|
||||
}
|
||||
class_device_create(ppp_class, NULL, MKDEV(PPP_MAJOR, 0), NULL, "ppp");
|
||||
device_create(ppp_class, NULL, MKDEV(PPP_MAJOR, 0), "ppp");
|
||||
}
|
||||
|
||||
out:
|
||||
@ -2675,7 +2675,7 @@ static void __exit ppp_cleanup(void)
|
||||
cardmap_destroy(&all_ppp_units);
|
||||
if (unregister_chrdev(PPP_MAJOR, "ppp") != 0)
|
||||
printk(KERN_ERR "PPP: failed to unregister PPP device\n");
|
||||
class_device_destroy(ppp_class, MKDEV(PPP_MAJOR, 0));
|
||||
device_destroy(ppp_class, MKDEV(PPP_MAJOR, 0));
|
||||
class_destroy(ppp_class);
|
||||
}
|
||||
|
||||
|
@ -1296,14 +1296,14 @@ register_framebuffer(struct fb_info *fb_info)
|
||||
break;
|
||||
fb_info->node = i;
|
||||
|
||||
fb_info->class_device = class_device_create(fb_class, NULL, MKDEV(FB_MAJOR, i),
|
||||
fb_info->device, "fb%d", i);
|
||||
if (IS_ERR(fb_info->class_device)) {
|
||||
fb_info->dev = device_create(fb_class, fb_info->device,
|
||||
MKDEV(FB_MAJOR, i), "fb%d", i);
|
||||
if (IS_ERR(fb_info->dev)) {
|
||||
/* Not fatal */
|
||||
printk(KERN_WARNING "Unable to create class_device for framebuffer %d; errno = %ld\n", i, PTR_ERR(fb_info->class_device));
|
||||
fb_info->class_device = NULL;
|
||||
printk(KERN_WARNING "Unable to create device for framebuffer %d; errno = %ld\n", i, PTR_ERR(fb_info->dev));
|
||||
fb_info->dev = NULL;
|
||||
} else
|
||||
fb_init_class_device(fb_info);
|
||||
fb_init_device(fb_info);
|
||||
|
||||
if (fb_info->pixmap.addr == NULL) {
|
||||
fb_info->pixmap.addr = kmalloc(FBPIXMAPSIZE, GFP_KERNEL);
|
||||
@ -1356,8 +1356,8 @@ unregister_framebuffer(struct fb_info *fb_info)
|
||||
fb_destroy_modelist(&fb_info->modelist);
|
||||
registered_fb[i]=NULL;
|
||||
num_registered_fb--;
|
||||
fb_cleanup_class_device(fb_info);
|
||||
class_device_destroy(fb_class, MKDEV(FB_MAJOR, i));
|
||||
fb_cleanup_device(fb_info);
|
||||
device_destroy(fb_class, MKDEV(FB_MAJOR, i));
|
||||
event.info = fb_info;
|
||||
fb_notifier_call_chain(FB_EVENT_FB_UNREGISTERED, &event);
|
||||
return 0;
|
||||
|
@ -73,7 +73,7 @@ EXPORT_SYMBOL(framebuffer_alloc);
|
||||
*
|
||||
* @info: frame buffer info structure
|
||||
*
|
||||
* Drop the reference count of the class_device embedded in the
|
||||
* Drop the reference count of the device embedded in the
|
||||
* framebuffer info structure.
|
||||
*
|
||||
*/
|
||||
@ -120,10 +120,10 @@ static int mode_string(char *buf, unsigned int offset,
|
||||
m, mode->xres, mode->yres, v, mode->refresh);
|
||||
}
|
||||
|
||||
static ssize_t store_mode(struct class_device *class_device, const char * buf,
|
||||
size_t count)
|
||||
static ssize_t store_mode(struct device *device, struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
struct fb_info *fb_info = class_get_devdata(class_device);
|
||||
struct fb_info *fb_info = dev_get_drvdata(device);
|
||||
char mstr[100];
|
||||
struct fb_var_screeninfo var;
|
||||
struct fb_modelist *modelist;
|
||||
@ -151,9 +151,10 @@ static ssize_t store_mode(struct class_device *class_device, const char * buf,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static ssize_t show_mode(struct class_device *class_device, char *buf)
|
||||
static ssize_t show_mode(struct device *device, struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct fb_info *fb_info = class_get_devdata(class_device);
|
||||
struct fb_info *fb_info = dev_get_drvdata(device);
|
||||
|
||||
if (!fb_info->mode)
|
||||
return 0;
|
||||
@ -161,10 +162,11 @@ static ssize_t show_mode(struct class_device *class_device, char *buf)
|
||||
return mode_string(buf, 0, fb_info->mode);
|
||||
}
|
||||
|
||||
static ssize_t store_modes(struct class_device *class_device, const char * buf,
|
||||
size_t count)
|
||||
static ssize_t store_modes(struct device *device,
|
||||
struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
struct fb_info *fb_info = class_get_devdata(class_device);
|
||||
struct fb_info *fb_info = dev_get_drvdata(device);
|
||||
LIST_HEAD(old_list);
|
||||
int i = count / sizeof(struct fb_videomode);
|
||||
|
||||
@ -186,9 +188,10 @@ static ssize_t store_modes(struct class_device *class_device, const char * buf,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static ssize_t show_modes(struct class_device *class_device, char *buf)
|
||||
static ssize_t show_modes(struct device *device, struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct fb_info *fb_info = class_get_devdata(class_device);
|
||||
struct fb_info *fb_info = dev_get_drvdata(device);
|
||||
unsigned int i;
|
||||
struct list_head *pos;
|
||||
struct fb_modelist *modelist;
|
||||
@ -203,10 +206,10 @@ static ssize_t show_modes(struct class_device *class_device, char *buf)
|
||||
return i;
|
||||
}
|
||||
|
||||
static ssize_t store_bpp(struct class_device *class_device, const char * buf,
|
||||
size_t count)
|
||||
static ssize_t store_bpp(struct device *device, struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
struct fb_info *fb_info = class_get_devdata(class_device);
|
||||
struct fb_info *fb_info = dev_get_drvdata(device);
|
||||
struct fb_var_screeninfo var;
|
||||
char ** last = NULL;
|
||||
int err;
|
||||
@ -218,16 +221,18 @@ static ssize_t store_bpp(struct class_device *class_device, const char * buf,
|
||||
return count;
|
||||
}
|
||||
|
||||
static ssize_t show_bpp(struct class_device *class_device, char *buf)
|
||||
static ssize_t show_bpp(struct device *device, struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct fb_info *fb_info = class_get_devdata(class_device);
|
||||
struct fb_info *fb_info = dev_get_drvdata(device);
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n", fb_info->var.bits_per_pixel);
|
||||
}
|
||||
|
||||
static ssize_t store_rotate(struct class_device *class_device, const char *buf,
|
||||
size_t count)
|
||||
static ssize_t store_rotate(struct device *device,
|
||||
struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
struct fb_info *fb_info = class_get_devdata(class_device);
|
||||
struct fb_info *fb_info = dev_get_drvdata(device);
|
||||
struct fb_var_screeninfo var;
|
||||
char **last = NULL;
|
||||
int err;
|
||||
@ -242,17 +247,19 @@ static ssize_t store_rotate(struct class_device *class_device, const char *buf,
|
||||
}
|
||||
|
||||
|
||||
static ssize_t show_rotate(struct class_device *class_device, char *buf)
|
||||
static ssize_t show_rotate(struct device *device,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct fb_info *fb_info = class_get_devdata(class_device);
|
||||
struct fb_info *fb_info = dev_get_drvdata(device);
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n", fb_info->var.rotate);
|
||||
}
|
||||
|
||||
static ssize_t store_virtual(struct class_device *class_device,
|
||||
const char * buf, size_t count)
|
||||
static ssize_t store_virtual(struct device *device,
|
||||
struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
struct fb_info *fb_info = class_get_devdata(class_device);
|
||||
struct fb_info *fb_info = dev_get_drvdata(device);
|
||||
struct fb_var_screeninfo var;
|
||||
char *last = NULL;
|
||||
int err;
|
||||
@ -269,23 +276,26 @@ static ssize_t store_virtual(struct class_device *class_device,
|
||||
return count;
|
||||
}
|
||||
|
||||
static ssize_t show_virtual(struct class_device *class_device, char *buf)
|
||||
static ssize_t show_virtual(struct device *device,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct fb_info *fb_info = class_get_devdata(class_device);
|
||||
struct fb_info *fb_info = dev_get_drvdata(device);
|
||||
return snprintf(buf, PAGE_SIZE, "%d,%d\n", fb_info->var.xres_virtual,
|
||||
fb_info->var.yres_virtual);
|
||||
}
|
||||
|
||||
static ssize_t show_stride(struct class_device *class_device, char *buf)
|
||||
static ssize_t show_stride(struct device *device,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct fb_info *fb_info = class_get_devdata(class_device);
|
||||
struct fb_info *fb_info = dev_get_drvdata(device);
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n", fb_info->fix.line_length);
|
||||
}
|
||||
|
||||
static ssize_t store_blank(struct class_device *class_device, const char * buf,
|
||||
size_t count)
|
||||
static ssize_t store_blank(struct device *device,
|
||||
struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
struct fb_info *fb_info = class_get_devdata(class_device);
|
||||
struct fb_info *fb_info = dev_get_drvdata(device);
|
||||
char *last = NULL;
|
||||
int err;
|
||||
|
||||
@ -299,42 +309,48 @@ static ssize_t store_blank(struct class_device *class_device, const char * buf,
|
||||
return count;
|
||||
}
|
||||
|
||||
static ssize_t show_blank(struct class_device *class_device, char *buf)
|
||||
static ssize_t show_blank(struct device *device,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
// struct fb_info *fb_info = class_get_devdata(class_device);
|
||||
// struct fb_info *fb_info = dev_get_drvdata(device);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static ssize_t store_console(struct class_device *class_device,
|
||||
const char * buf, size_t count)
|
||||
static ssize_t store_console(struct device *device,
|
||||
struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
// struct fb_info *fb_info = class_get_devdata(class_device);
|
||||
// struct fb_info *fb_info = dev_get_drvdata(device);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static ssize_t show_console(struct class_device *class_device, char *buf)
|
||||
static ssize_t show_console(struct device *device,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
// struct fb_info *fb_info = class_get_devdata(class_device);
|
||||
// struct fb_info *fb_info = dev_get_drvdata(device);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static ssize_t store_cursor(struct class_device *class_device,
|
||||
const char * buf, size_t count)
|
||||
static ssize_t store_cursor(struct device *device,
|
||||
struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
// struct fb_info *fb_info = class_get_devdata(class_device);
|
||||
// struct fb_info *fb_info = dev_get_drvdata(device);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static ssize_t show_cursor(struct class_device *class_device, char *buf)
|
||||
static ssize_t show_cursor(struct device *device,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
// struct fb_info *fb_info = class_get_devdata(class_device);
|
||||
// struct fb_info *fb_info = dev_get_drvdata(device);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static ssize_t store_pan(struct class_device *class_device, const char * buf,
|
||||
size_t count)
|
||||
static ssize_t store_pan(struct device *device,
|
||||
struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
struct fb_info *fb_info = class_get_devdata(class_device);
|
||||
struct fb_info *fb_info = dev_get_drvdata(device);
|
||||
struct fb_var_screeninfo var;
|
||||
char *last = NULL;
|
||||
int err;
|
||||
@ -355,24 +371,27 @@ static ssize_t store_pan(struct class_device *class_device, const char * buf,
|
||||
return count;
|
||||
}
|
||||
|
||||
static ssize_t show_pan(struct class_device *class_device, char *buf)
|
||||
static ssize_t show_pan(struct device *device,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct fb_info *fb_info = class_get_devdata(class_device);
|
||||
struct fb_info *fb_info = dev_get_drvdata(device);
|
||||
return snprintf(buf, PAGE_SIZE, "%d,%d\n", fb_info->var.xoffset,
|
||||
fb_info->var.xoffset);
|
||||
}
|
||||
|
||||
static ssize_t show_name(struct class_device *class_device, char *buf)
|
||||
static ssize_t show_name(struct device *device,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct fb_info *fb_info = class_get_devdata(class_device);
|
||||
struct fb_info *fb_info = dev_get_drvdata(device);
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%s\n", fb_info->fix.id);
|
||||
}
|
||||
|
||||
static ssize_t store_fbstate(struct class_device *class_device,
|
||||
const char *buf, size_t count)
|
||||
static ssize_t store_fbstate(struct device *device,
|
||||
struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
struct fb_info *fb_info = class_get_devdata(class_device);
|
||||
struct fb_info *fb_info = dev_get_drvdata(device);
|
||||
u32 state;
|
||||
char *last = NULL;
|
||||
|
||||
@ -385,17 +404,19 @@ static ssize_t store_fbstate(struct class_device *class_device,
|
||||
return count;
|
||||
}
|
||||
|
||||
static ssize_t show_fbstate(struct class_device *class_device, char *buf)
|
||||
static ssize_t show_fbstate(struct device *device,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct fb_info *fb_info = class_get_devdata(class_device);
|
||||
struct fb_info *fb_info = dev_get_drvdata(device);
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n", fb_info->state);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_FB_BACKLIGHT
|
||||
static ssize_t store_bl_curve(struct class_device *class_device,
|
||||
const char *buf, size_t count)
|
||||
static ssize_t store_bl_curve(struct device *device,
|
||||
struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
struct fb_info *fb_info = class_get_devdata(class_device);
|
||||
struct fb_info *fb_info = dev_get_drvdata(device);
|
||||
u8 tmp_curve[FB_BACKLIGHT_LEVELS];
|
||||
unsigned int i;
|
||||
|
||||
@ -432,9 +453,10 @@ static ssize_t store_bl_curve(struct class_device *class_device,
|
||||
return count;
|
||||
}
|
||||
|
||||
static ssize_t show_bl_curve(struct class_device *class_device, char *buf)
|
||||
static ssize_t show_bl_curve(struct device *device,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct fb_info *fb_info = class_get_devdata(class_device);
|
||||
struct fb_info *fb_info = dev_get_drvdata(device);
|
||||
ssize_t len = 0;
|
||||
unsigned int i;
|
||||
|
||||
@ -465,7 +487,7 @@ static ssize_t show_bl_curve(struct class_device *class_device, char *buf)
|
||||
/* When cmap is added back in it should be a binary attribute
|
||||
* not a text one. Consideration should also be given to converting
|
||||
* fbdev to use configfs instead of sysfs */
|
||||
static struct class_device_attribute class_device_attrs[] = {
|
||||
static struct device_attribute device_attrs[] = {
|
||||
__ATTR(bits_per_pixel, S_IRUGO|S_IWUSR, show_bpp, store_bpp),
|
||||
__ATTR(blank, S_IRUGO|S_IWUSR, show_blank, store_blank),
|
||||
__ATTR(console, S_IRUGO|S_IWUSR, show_console, store_console),
|
||||
@ -483,17 +505,16 @@ static struct class_device_attribute class_device_attrs[] = {
|
||||
#endif
|
||||
};
|
||||
|
||||
int fb_init_class_device(struct fb_info *fb_info)
|
||||
int fb_init_device(struct fb_info *fb_info)
|
||||
{
|
||||
int i, error = 0;
|
||||
|
||||
class_set_devdata(fb_info->class_device, fb_info);
|
||||
dev_set_drvdata(fb_info->dev, fb_info);
|
||||
|
||||
fb_info->class_flag |= FB_SYSFS_FLAG_ATTR;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(class_device_attrs); i++) {
|
||||
error = class_device_create_file(fb_info->class_device,
|
||||
&class_device_attrs[i]);
|
||||
for (i = 0; i < ARRAY_SIZE(device_attrs); i++) {
|
||||
error = device_create_file(fb_info->dev, &device_attrs[i]);
|
||||
|
||||
if (error)
|
||||
break;
|
||||
@ -501,22 +522,20 @@ int fb_init_class_device(struct fb_info *fb_info)
|
||||
|
||||
if (error) {
|
||||
while (--i >= 0)
|
||||
class_device_remove_file(fb_info->class_device,
|
||||
&class_device_attrs[i]);
|
||||
device_remove_file(fb_info->dev, &device_attrs[i]);
|
||||
fb_info->class_flag &= ~FB_SYSFS_FLAG_ATTR;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void fb_cleanup_class_device(struct fb_info *fb_info)
|
||||
void fb_cleanup_device(struct fb_info *fb_info)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
if (fb_info->class_flag & FB_SYSFS_FLAG_ATTR) {
|
||||
for (i = 0; i < ARRAY_SIZE(class_device_attrs); i++)
|
||||
class_device_remove_file(fb_info->class_device,
|
||||
&class_device_attrs[i]);
|
||||
for (i = 0; i < ARRAY_SIZE(device_attrs); i++)
|
||||
device_remove_file(fb_info->dev, &device_attrs[i]);
|
||||
|
||||
fb_info->class_flag &= ~FB_SYSFS_FLAG_ATTR;
|
||||
}
|
||||
|
@ -372,6 +372,51 @@ int sysfs_rename_dir(struct kobject * kobj, const char *new_name)
|
||||
return error;
|
||||
}
|
||||
|
||||
int sysfs_move_dir(struct kobject *kobj, struct kobject *new_parent)
|
||||
{
|
||||
struct dentry *old_parent_dentry, *new_parent_dentry, *new_dentry;
|
||||
struct sysfs_dirent *new_parent_sd, *sd;
|
||||
int error;
|
||||
|
||||
if (!new_parent)
|
||||
return -EINVAL;
|
||||
|
||||
old_parent_dentry = kobj->parent ?
|
||||
kobj->parent->dentry : sysfs_mount->mnt_sb->s_root;
|
||||
new_parent_dentry = new_parent->dentry;
|
||||
|
||||
again:
|
||||
mutex_lock(&old_parent_dentry->d_inode->i_mutex);
|
||||
if (!mutex_trylock(&new_parent_dentry->d_inode->i_mutex)) {
|
||||
mutex_unlock(&old_parent_dentry->d_inode->i_mutex);
|
||||
goto again;
|
||||
}
|
||||
|
||||
new_parent_sd = new_parent_dentry->d_fsdata;
|
||||
sd = kobj->dentry->d_fsdata;
|
||||
|
||||
new_dentry = lookup_one_len(kobj->name, new_parent_dentry,
|
||||
strlen(kobj->name));
|
||||
if (IS_ERR(new_dentry)) {
|
||||
error = PTR_ERR(new_dentry);
|
||||
goto out;
|
||||
} else
|
||||
error = 0;
|
||||
d_add(new_dentry, NULL);
|
||||
d_move(kobj->dentry, new_dentry);
|
||||
dput(new_dentry);
|
||||
|
||||
/* Remove from old parent's list and insert into new parent's list. */
|
||||
list_del_init(&sd->s_sibling);
|
||||
list_add(&sd->s_sibling, &new_parent_sd->s_children);
|
||||
|
||||
out:
|
||||
mutex_unlock(&new_parent_dentry->d_inode->i_mutex);
|
||||
mutex_unlock(&old_parent_dentry->d_inode->i_mutex);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
static int sysfs_dir_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
struct dentry * dentry = file->f_dentry;
|
||||
|
@ -190,6 +190,9 @@ fill_write_buffer(struct sysfs_buffer * buffer, const char __user * buf, size_t
|
||||
count = PAGE_SIZE - 1;
|
||||
error = copy_from_user(buffer->page,buf,count);
|
||||
buffer->needs_read_fill = 1;
|
||||
/* if buf is assumed to contain a string, terminate it by \0,
|
||||
so e.g. sscanf() can scan the string easily */
|
||||
buffer->page[count] = 0;
|
||||
return error ? -EFAULT : count;
|
||||
}
|
||||
|
||||
|
@ -357,7 +357,7 @@ struct device *acpi_get_physical_device(acpi_handle);
|
||||
/* helper */
|
||||
acpi_handle acpi_get_child(acpi_handle, acpi_integer);
|
||||
acpi_handle acpi_get_pci_rootbridge_handle(unsigned int, unsigned int);
|
||||
#define DEVICE_ACPI_HANDLE(dev) ((acpi_handle)((dev)->firmware_data))
|
||||
#define DEVICE_ACPI_HANDLE(dev) ((acpi_handle)((dev)->archdata.acpi_handle))
|
||||
|
||||
#endif /* CONFIG_ACPI */
|
||||
|
||||
|
7
include/asm-alpha/device.h
Normal file
7
include/asm-alpha/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>
|
||||
|
7
include/asm-arm/device.h
Normal file
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>
|
||||
|
7
include/asm-arm26/device.h
Normal file
7
include/asm-arm26/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>
|
||||
|
7
include/asm-avr32/device.h
Normal file
7
include/asm-avr32/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>
|
||||
|
7
include/asm-cris/device.h
Normal file
7
include/asm-cris/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>
|
||||
|
7
include/asm-frv/device.h
Normal file
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>
|
||||
|
12
include/asm-generic/device.h
Normal file
12
include/asm-generic/device.h
Normal file
@ -0,0 +1,12 @@
|
||||
/*
|
||||
* Arch specific extensions to struct device
|
||||
*
|
||||
* This file is released under the GPLv2
|
||||
*/
|
||||
#ifndef _ASM_GENERIC_DEVICE_H
|
||||
#define _ASM_GENERIC_DEVICE_H
|
||||
|
||||
struct dev_archdata {
|
||||
};
|
||||
|
||||
#endif /* _ASM_GENERIC_DEVICE_H */
|
7
include/asm-h8300/device.h
Normal file
7
include/asm-h8300/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>
|
||||
|
15
include/asm-i386/device.h
Normal file
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
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 */
|
7
include/asm-m32r/device.h
Normal file
7
include/asm-m32r/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>
|
||||
|
7
include/asm-m68k/device.h
Normal file
7
include/asm-m68k/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>
|
||||
|
7
include/asm-m68knommu/device.h
Normal file
7
include/asm-m68knommu/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>
|
||||
|
7
include/asm-mips/device.h
Normal file
7
include/asm-mips/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>
|
||||
|
7
include/asm-parisc/device.h
Normal file
7
include/asm-parisc/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>
|
||||
|
7
include/asm-powerpc/device.h
Normal file
7
include/asm-powerpc/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>
|
||||
|
7
include/asm-ppc/device.h
Normal file
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>
|
||||
|
7
include/asm-s390/device.h
Normal file
7
include/asm-s390/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>
|
||||
|
7
include/asm-sh/device.h
Normal file
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>
|
||||
|
7
include/asm-sh64/device.h
Normal file
7
include/asm-sh64/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>
|
||||
|
7
include/asm-sparc/device.h
Normal file
7
include/asm-sparc/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>
|
||||
|
7
include/asm-sparc64/device.h
Normal file
7
include/asm-sparc64/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>
|
||||
|
7
include/asm-um/device.h
Normal file
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>
|
||||
|
7
include/asm-v850/device.h
Normal file
7
include/asm-v850/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>
|
||||
|
15
include/asm-x86_64/device.h
Normal file
15
include/asm-x86_64/device.h
Normal file
@ -0,0 +1,15 @@
|
||||
/*
|
||||
* Arch specific extensions to struct device
|
||||
*
|
||||
* This file is released under the GPLv2
|
||||
*/
|
||||
#ifndef _ASM_X86_64_DEVICE_H
|
||||
#define _ASM_X86_64_DEVICE_H
|
||||
|
||||
struct dev_archdata {
|
||||
#ifdef CONFIG_ACPI
|
||||
void *acpi_handle;
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif /* _ASM_X86_64_DEVICE_H */
|
7
include/asm-xtensa/device.h
Normal file
7
include/asm-xtensa/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>
|
||||
|
@ -21,6 +21,7 @@
|
||||
#include <linux/pm.h>
|
||||
#include <asm/semaphore.h>
|
||||
#include <asm/atomic.h>
|
||||
#include <asm/device.h>
|
||||
|
||||
#define DEVICE_NAME_SIZE 50
|
||||
#define DEVICE_NAME_HALF __stringify(20) /* Less than half to accommodate slop */
|
||||
@ -42,6 +43,8 @@ struct bus_type {
|
||||
struct klist klist_devices;
|
||||
struct klist klist_drivers;
|
||||
|
||||
struct blocking_notifier_head bus_notifier;
|
||||
|
||||
struct bus_attribute * bus_attrs;
|
||||
struct device_attribute * dev_attrs;
|
||||
struct driver_attribute * drv_attrs;
|
||||
@ -75,6 +78,29 @@ int __must_check bus_for_each_drv(struct bus_type *bus,
|
||||
struct device_driver *start, void *data,
|
||||
int (*fn)(struct device_driver *, void *));
|
||||
|
||||
/*
|
||||
* Bus notifiers: Get notified of addition/removal of devices
|
||||
* and binding/unbinding of drivers to devices.
|
||||
* In the long run, it should be a replacement for the platform
|
||||
* notify hooks.
|
||||
*/
|
||||
struct notifier_block;
|
||||
|
||||
extern int bus_register_notifier(struct bus_type *bus,
|
||||
struct notifier_block *nb);
|
||||
extern int bus_unregister_notifier(struct bus_type *bus,
|
||||
struct notifier_block *nb);
|
||||
|
||||
/* All 4 notifers below get called with the target struct device *
|
||||
* as an argument. Note that those functions are likely to be called
|
||||
* with the device semaphore held in the core, so be careful.
|
||||
*/
|
||||
#define BUS_NOTIFY_ADD_DEVICE 0x00000001 /* device added */
|
||||
#define BUS_NOTIFY_DEL_DEVICE 0x00000002 /* device removed */
|
||||
#define BUS_NOTIFY_BOUND_DRIVER 0x00000003 /* driver bound to device */
|
||||
#define BUS_NOTIFY_UNBIND_DRIVER 0x00000004 /* driver about to be
|
||||
unbound */
|
||||
|
||||
/* driverfs interface for exporting bus attributes */
|
||||
|
||||
struct bus_attribute {
|
||||
@ -343,8 +369,6 @@ struct device {
|
||||
void *driver_data; /* data private to the driver */
|
||||
void *platform_data; /* Platform specific data, device
|
||||
core doesn't touch it */
|
||||
void *firmware_data; /* Firmware specific data (e.g. ACPI,
|
||||
BIOS data),reserved for device core*/
|
||||
struct dev_pm_info power;
|
||||
|
||||
u64 *dma_mask; /* dma mask (if dma'able device) */
|
||||
@ -358,6 +382,8 @@ struct device {
|
||||
|
||||
struct dma_coherent_mem *dma_mem; /* internal for coherent mem
|
||||
override */
|
||||
/* arch specific additions */
|
||||
struct dev_archdata archdata;
|
||||
|
||||
/* class_device migration path */
|
||||
struct list_head node;
|
||||
@ -395,7 +421,10 @@ extern int __must_check device_add(struct device * dev);
|
||||
extern void device_del(struct device * dev);
|
||||
extern int device_for_each_child(struct device *, void *,
|
||||
int (*fn)(struct device *, void *));
|
||||
extern struct device *device_find_child(struct device *, void *data,
|
||||
int (*match)(struct device *, void *));
|
||||
extern int device_rename(struct device *dev, char *new_name);
|
||||
extern int device_move(struct device *dev, struct device *new_parent);
|
||||
|
||||
/*
|
||||
* Manual binding of a device to driver. See drivers/base/bus.c
|
||||
@ -415,8 +444,6 @@ extern struct device *device_create(struct class *cls, struct device *parent,
|
||||
__attribute__((format(printf,4,5)));
|
||||
extern void device_destroy(struct class *cls, dev_t devt);
|
||||
|
||||
extern int virtual_device_parent(struct device *dev);
|
||||
|
||||
/*
|
||||
* Platform "fixup" functions - allow the platform to have their say
|
||||
* about devices and actions that the general device layer doesn't
|
||||
|
@ -774,8 +774,8 @@ struct fb_info {
|
||||
#endif
|
||||
|
||||
struct fb_ops *fbops;
|
||||
struct device *device;
|
||||
struct class_device *class_device; /* sysfs per device attrs */
|
||||
struct device *device; /* This is the parent */
|
||||
struct device *dev; /* This is this fb device */
|
||||
int class_flag; /* private sysfs flags */
|
||||
#ifdef CONFIG_FB_TILEBLITTING
|
||||
struct fb_tile_ops *tileops; /* Tile Blitting */
|
||||
@ -910,8 +910,8 @@ static inline void __fb_pad_aligned_buffer(u8 *dst, u32 d_pitch,
|
||||
/* drivers/video/fbsysfs.c */
|
||||
extern struct fb_info *framebuffer_alloc(size_t size, struct device *dev);
|
||||
extern void framebuffer_release(struct fb_info *info);
|
||||
extern int fb_init_class_device(struct fb_info *fb_info);
|
||||
extern void fb_cleanup_class_device(struct fb_info *head);
|
||||
extern int fb_init_device(struct fb_info *fb_info);
|
||||
extern void fb_cleanup_device(struct fb_info *head);
|
||||
extern void fb_bl_default_curve(struct fb_info *fb_info, u8 off, u8 min, u8 max);
|
||||
|
||||
/* drivers/video/fbmon.c */
|
||||
|
@ -47,6 +47,7 @@ enum kobject_action {
|
||||
KOBJ_UMOUNT = (__force kobject_action_t) 0x05, /* umount event for block devices (broken) */
|
||||
KOBJ_OFFLINE = (__force kobject_action_t) 0x06, /* device offline */
|
||||
KOBJ_ONLINE = (__force kobject_action_t) 0x07, /* device online */
|
||||
KOBJ_MOVE = (__force kobject_action_t) 0x08, /* device move */
|
||||
};
|
||||
|
||||
struct kobject {
|
||||
@ -76,6 +77,7 @@ extern int __must_check kobject_add(struct kobject *);
|
||||
extern void kobject_del(struct kobject *);
|
||||
|
||||
extern int __must_check kobject_rename(struct kobject *, const char *new_name);
|
||||
extern int __must_check kobject_move(struct kobject *, struct kobject *);
|
||||
|
||||
extern int __must_check kobject_register(struct kobject *);
|
||||
extern void kobject_unregister(struct kobject *);
|
||||
@ -264,6 +266,8 @@ extern int __must_check subsys_create_file(struct subsystem * ,
|
||||
|
||||
#if defined(CONFIG_HOTPLUG)
|
||||
void kobject_uevent(struct kobject *kobj, enum kobject_action action);
|
||||
void kobject_uevent_env(struct kobject *kobj, enum kobject_action action,
|
||||
char *envp[]);
|
||||
|
||||
int add_uevent_var(char **envp, int num_envp, int *cur_index,
|
||||
char *buffer, int buffer_size, int *cur_len,
|
||||
@ -271,6 +275,10 @@ int add_uevent_var(char **envp, int num_envp, int *cur_index,
|
||||
__attribute__((format (printf, 7, 8)));
|
||||
#else
|
||||
static inline void kobject_uevent(struct kobject *kobj, enum kobject_action action) { }
|
||||
static inline void kobject_uevent_env(struct kobject *kobj,
|
||||
enum kobject_action action,
|
||||
char *envp[])
|
||||
{ }
|
||||
|
||||
static inline int add_uevent_var(char **envp, int num_envp, int *cur_index,
|
||||
char *buffer, int buffer_size, int *cur_len,
|
||||
|
@ -31,15 +31,14 @@
|
||||
#define HPET_MINOR 228
|
||||
|
||||
struct device;
|
||||
struct class_device;
|
||||
|
||||
struct miscdevice {
|
||||
int minor;
|
||||
const char *name;
|
||||
const struct file_operations *fops;
|
||||
struct list_head list;
|
||||
struct device *dev;
|
||||
struct class_device *class;
|
||||
struct device *parent;
|
||||
struct device *this_device;
|
||||
};
|
||||
|
||||
extern int misc_register(struct miscdevice * misc);
|
||||
|
@ -74,8 +74,8 @@ struct mmc_card;
|
||||
struct device;
|
||||
|
||||
struct mmc_host {
|
||||
struct device *dev;
|
||||
struct class_device class_dev;
|
||||
struct device *parent;
|
||||
struct device class_dev;
|
||||
int index;
|
||||
const struct mmc_host_ops *ops;
|
||||
unsigned int f_min;
|
||||
@ -125,8 +125,8 @@ static inline void *mmc_priv(struct mmc_host *host)
|
||||
return (void *)host->private;
|
||||
}
|
||||
|
||||
#define mmc_dev(x) ((x)->dev)
|
||||
#define mmc_hostname(x) ((x)->class_dev.class_id)
|
||||
#define mmc_dev(x) ((x)->parent)
|
||||
#define mmc_hostname(x) ((x)->class_dev.bus_id)
|
||||
|
||||
extern int mmc_suspend_host(struct mmc_host *, pm_message_t);
|
||||
extern int mmc_resume_host(struct mmc_host *);
|
||||
|
@ -264,6 +264,7 @@ struct module
|
||||
struct module_attribute *modinfo_attrs;
|
||||
const char *version;
|
||||
const char *srcversion;
|
||||
struct kobject *drivers_dir;
|
||||
|
||||
/* Exported symbols */
|
||||
const struct kernel_symbol *syms;
|
||||
|
@ -58,6 +58,12 @@ struct platform_driver {
|
||||
extern int platform_driver_register(struct platform_driver *);
|
||||
extern void platform_driver_unregister(struct platform_driver *);
|
||||
|
||||
/* non-hotpluggable platform devices may use this so that probe() and
|
||||
* its support may live in __init sections, conserving runtime memory.
|
||||
*/
|
||||
extern int platform_driver_probe(struct platform_driver *driver,
|
||||
int (*probe)(struct platform_device *));
|
||||
|
||||
#define platform_get_drvdata(_dev) dev_get_drvdata(&(_dev)->dev)
|
||||
#define platform_set_drvdata(_dev,data) dev_set_drvdata(&(_dev)->dev, (data))
|
||||
|
||||
|
@ -96,6 +96,9 @@ sysfs_remove_dir(struct kobject *);
|
||||
extern int __must_check
|
||||
sysfs_rename_dir(struct kobject *, const char *new_name);
|
||||
|
||||
extern int __must_check
|
||||
sysfs_move_dir(struct kobject *, struct kobject *);
|
||||
|
||||
extern int __must_check
|
||||
sysfs_create_file(struct kobject *, const struct attribute *);
|
||||
|
||||
@ -142,6 +145,11 @@ static inline int sysfs_rename_dir(struct kobject * k, const char *new_name)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int sysfs_move_dir(struct kobject * k, struct kobject * new_parent)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int sysfs_create_file(struct kobject * k, const struct attribute * a)
|
||||
{
|
||||
return 0;
|
||||
|
@ -276,9 +276,8 @@ extern int tty_register_ldisc(int disc, struct tty_ldisc *new_ldisc);
|
||||
extern int tty_unregister_ldisc(int disc);
|
||||
extern int tty_register_driver(struct tty_driver *driver);
|
||||
extern int tty_unregister_driver(struct tty_driver *driver);
|
||||
extern struct class_device *tty_register_device(struct tty_driver *driver,
|
||||
unsigned index,
|
||||
struct device *dev);
|
||||
extern struct device *tty_register_device(struct tty_driver *driver,
|
||||
unsigned index, struct device *dev);
|
||||
extern void tty_unregister_device(struct tty_driver *driver, unsigned index);
|
||||
extern int tty_read_raw_data(struct tty_struct *tty, unsigned char *bufp,
|
||||
int buflen);
|
||||
|
@ -132,6 +132,7 @@ struct snd_card {
|
||||
int shutdown; /* this card is going down */
|
||||
int free_on_last_close; /* free in context of file_release */
|
||||
wait_queue_head_t shutdown_sleep;
|
||||
struct device *parent;
|
||||
struct device *dev;
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
@ -187,13 +188,14 @@ struct snd_minor {
|
||||
int device; /* device number */
|
||||
const struct file_operations *f_ops; /* file operations */
|
||||
void *private_data; /* private data for f_ops->open */
|
||||
struct class_device *class_dev; /* class device for sysfs */
|
||||
struct device *dev; /* device for sysfs */
|
||||
};
|
||||
|
||||
/* sound.c */
|
||||
|
||||
extern int snd_major;
|
||||
extern int snd_ecards_limit;
|
||||
extern struct class *sound_class;
|
||||
|
||||
void snd_request_card(int card);
|
||||
|
||||
@ -203,7 +205,7 @@ int snd_register_device(int type, struct snd_card *card, int dev,
|
||||
int snd_unregister_device(int type, struct snd_card *card, int dev);
|
||||
void *snd_lookup_minor_data(unsigned int minor, int type);
|
||||
int snd_add_device_sysfs_file(int type, struct snd_card *card, int dev,
|
||||
const struct class_device_attribute *attr);
|
||||
struct device_attribute *attr);
|
||||
|
||||
#ifdef CONFIG_SND_OSSEMUL
|
||||
int snd_register_oss_device(int type, struct snd_card *card, int dev,
|
||||
@ -255,7 +257,7 @@ int snd_card_file_add(struct snd_card *card, struct file *file);
|
||||
int snd_card_file_remove(struct snd_card *card, struct file *file);
|
||||
|
||||
#ifndef snd_card_set_dev
|
||||
#define snd_card_set_dev(card,devptr) ((card)->dev = (devptr))
|
||||
#define snd_card_set_dev(card,devptr) ((card)->parent = (devptr))
|
||||
#endif
|
||||
|
||||
/* device.c */
|
||||
|
20
init/Kconfig
20
init/Kconfig
@ -249,6 +249,26 @@ config CPUSETS
|
||||
|
||||
Say N if unsure.
|
||||
|
||||
config SYSFS_DEPRECATED
|
||||
bool "Create deprecated sysfs files"
|
||||
default y
|
||||
help
|
||||
This option creates deprecated symlinks such as the
|
||||
"device"-link, the <subsystem>:<name>-link, and the
|
||||
"bus"-link. It may also add deprecated key in the
|
||||
uevent environment.
|
||||
None of these features or values should be used today, as
|
||||
they export driver core implementation details to userspace
|
||||
or export properties which can't be kept stable across kernel
|
||||
releases.
|
||||
|
||||
If enabled, this option will also move any device structures
|
||||
that belong to a class, back into the /sys/class heirachy, in
|
||||
order to support older versions of udev.
|
||||
|
||||
If you are using a distro that was released in 2006 or later,
|
||||
it should be safe to say N here.
|
||||
|
||||
config RELAY
|
||||
bool "Kernel->user space relay support (formerly relayfs)"
|
||||
help
|
||||
|
@ -1086,22 +1086,35 @@ static int mod_sysfs_setup(struct module *mod,
|
||||
goto out;
|
||||
kobj_set_kset_s(&mod->mkobj, module_subsys);
|
||||
mod->mkobj.mod = mod;
|
||||
err = kobject_register(&mod->mkobj.kobj);
|
||||
|
||||
/* delay uevent until full sysfs population */
|
||||
kobject_init(&mod->mkobj.kobj);
|
||||
err = kobject_add(&mod->mkobj.kobj);
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
mod->drivers_dir = kobject_add_dir(&mod->mkobj.kobj, "drivers");
|
||||
if (!mod->drivers_dir)
|
||||
goto out_unreg;
|
||||
|
||||
err = module_param_sysfs_setup(mod, kparam, num_params);
|
||||
if (err)
|
||||
goto out_unreg;
|
||||
goto out_unreg_drivers;
|
||||
|
||||
err = module_add_modinfo_attrs(mod);
|
||||
if (err)
|
||||
goto out_unreg;
|
||||
goto out_unreg_param;
|
||||
|
||||
kobject_uevent(&mod->mkobj.kobj, KOBJ_ADD);
|
||||
return 0;
|
||||
|
||||
out_unreg_drivers:
|
||||
kobject_unregister(mod->drivers_dir);
|
||||
out_unreg_param:
|
||||
module_param_sysfs_remove(mod);
|
||||
out_unreg:
|
||||
kobject_unregister(&mod->mkobj.kobj);
|
||||
kobject_del(&mod->mkobj.kobj);
|
||||
kobject_put(&mod->mkobj.kobj);
|
||||
out:
|
||||
return err;
|
||||
}
|
||||
@ -1110,6 +1123,7 @@ static void mod_kobject_remove(struct module *mod)
|
||||
{
|
||||
module_remove_modinfo_attrs(mod);
|
||||
module_param_sysfs_remove(mod);
|
||||
kobject_unregister(mod->drivers_dir);
|
||||
|
||||
kobject_unregister(&mod->mkobj.kobj);
|
||||
}
|
||||
@ -2275,11 +2289,14 @@ void print_modules(void)
|
||||
|
||||
void module_add_driver(struct module *mod, struct device_driver *drv)
|
||||
{
|
||||
int no_warn;
|
||||
|
||||
if (!mod || !drv)
|
||||
return;
|
||||
|
||||
/* Don't check return code; this call is idempotent */
|
||||
sysfs_create_link(&drv->kobj, &mod->mkobj.kobj, "module");
|
||||
/* Don't check return codes; these calls are idempotent */
|
||||
no_warn = sysfs_create_link(&drv->kobj, &mod->mkobj.kobj, "module");
|
||||
no_warn = sysfs_create_link(mod->drivers_dir, &drv->kobj, drv->name);
|
||||
}
|
||||
EXPORT_SYMBOL(module_add_driver);
|
||||
|
||||
@ -2288,6 +2305,8 @@ void module_remove_driver(struct device_driver *drv)
|
||||
if (!drv)
|
||||
return;
|
||||
sysfs_remove_link(&drv->kobj, "module");
|
||||
if (drv->owner && drv->owner->drivers_dir)
|
||||
sysfs_remove_link(drv->owner->drivers_dir, drv->name);
|
||||
}
|
||||
EXPORT_SYMBOL(module_remove_driver);
|
||||
|
||||
|
@ -310,6 +310,56 @@ int kobject_rename(struct kobject * kobj, const char *new_name)
|
||||
return error;
|
||||
}
|
||||
|
||||
/**
|
||||
* kobject_move - move object to another parent
|
||||
* @kobj: object in question.
|
||||
* @new_parent: object's new parent
|
||||
*/
|
||||
|
||||
int kobject_move(struct kobject *kobj, struct kobject *new_parent)
|
||||
{
|
||||
int error;
|
||||
struct kobject *old_parent;
|
||||
const char *devpath = NULL;
|
||||
char *devpath_string = NULL;
|
||||
char *envp[2];
|
||||
|
||||
kobj = kobject_get(kobj);
|
||||
if (!kobj)
|
||||
return -EINVAL;
|
||||
new_parent = kobject_get(new_parent);
|
||||
if (!new_parent) {
|
||||
error = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
/* old object path */
|
||||
devpath = kobject_get_path(kobj, GFP_KERNEL);
|
||||
if (!devpath) {
|
||||
error = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
devpath_string = kmalloc(strlen(devpath) + 15, GFP_KERNEL);
|
||||
if (!devpath_string) {
|
||||
error = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
sprintf(devpath_string, "DEVPATH_OLD=%s", devpath);
|
||||
envp[0] = devpath_string;
|
||||
envp[1] = NULL;
|
||||
error = sysfs_move_dir(kobj, new_parent);
|
||||
if (error)
|
||||
goto out;
|
||||
old_parent = kobj->parent;
|
||||
kobj->parent = new_parent;
|
||||
kobject_put(old_parent);
|
||||
kobject_uevent_env(kobj, KOBJ_MOVE, envp);
|
||||
out:
|
||||
kobject_put(kobj);
|
||||
kfree(devpath_string);
|
||||
kfree(devpath);
|
||||
return error;
|
||||
}
|
||||
|
||||
/**
|
||||
* kobject_del - unlink kobject from hierarchy.
|
||||
* @kobj: object.
|
||||
|
@ -50,18 +50,22 @@ static char *action_to_string(enum kobject_action action)
|
||||
return "offline";
|
||||
case KOBJ_ONLINE:
|
||||
return "online";
|
||||
case KOBJ_MOVE:
|
||||
return "move";
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* kobject_uevent - notify userspace by ending an uevent
|
||||
* kobject_uevent_env - send an uevent with environmental data
|
||||
*
|
||||
* @action: action that is happening (usually KOBJ_ADD and KOBJ_REMOVE)
|
||||
* @action: action that is happening (usually KOBJ_MOVE)
|
||||
* @kobj: struct kobject that the action is happening to
|
||||
* @envp_ext: pointer to environmental data
|
||||
*/
|
||||
void kobject_uevent(struct kobject *kobj, enum kobject_action action)
|
||||
void kobject_uevent_env(struct kobject *kobj, enum kobject_action action,
|
||||
char *envp_ext[])
|
||||
{
|
||||
char **envp;
|
||||
char *buffer;
|
||||
@ -76,6 +80,7 @@ void kobject_uevent(struct kobject *kobj, enum kobject_action action)
|
||||
char *seq_buff;
|
||||
int i = 0;
|
||||
int retval;
|
||||
int j;
|
||||
|
||||
pr_debug("%s\n", __FUNCTION__);
|
||||
|
||||
@ -134,7 +139,8 @@ void kobject_uevent(struct kobject *kobj, enum kobject_action action)
|
||||
scratch += sprintf (scratch, "DEVPATH=%s", devpath) + 1;
|
||||
envp [i++] = scratch;
|
||||
scratch += sprintf(scratch, "SUBSYSTEM=%s", subsystem) + 1;
|
||||
|
||||
for (j = 0; envp_ext && envp_ext[j]; j++)
|
||||
envp[i++] = envp_ext[j];
|
||||
/* just reserve the space, overwrite it after kset call has returned */
|
||||
envp[i++] = seq_buff = scratch;
|
||||
scratch += strlen("SEQNUM=18446744073709551616") + 1;
|
||||
@ -200,6 +206,20 @@ exit:
|
||||
kfree(envp);
|
||||
return;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL_GPL(kobject_uevent_env);
|
||||
|
||||
/**
|
||||
* kobject_uevent - notify userspace by ending an uevent
|
||||
*
|
||||
* @action: action that is happening (usually KOBJ_ADD and KOBJ_REMOVE)
|
||||
* @kobj: struct kobject that the action is happening to
|
||||
*/
|
||||
void kobject_uevent(struct kobject *kobj, enum kobject_action action)
|
||||
{
|
||||
kobject_uevent_env(kobj, action, NULL);
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL_GPL(kobject_uevent);
|
||||
|
||||
/**
|
||||
|
@ -361,6 +361,8 @@ static int snd_card_do_free(struct snd_card *card)
|
||||
snd_printk(KERN_WARNING "unable to free card info\n");
|
||||
/* Not fatal error */
|
||||
}
|
||||
if (card->dev)
|
||||
device_unregister(card->dev);
|
||||
kfree(card);
|
||||
return 0;
|
||||
}
|
||||
@ -495,6 +497,12 @@ int snd_card_register(struct snd_card *card)
|
||||
int err;
|
||||
|
||||
snd_assert(card != NULL, return -EINVAL);
|
||||
if (!card->dev) {
|
||||
card->dev = device_create(sound_class, card->parent, 0,
|
||||
"card%i", card->number);
|
||||
if (IS_ERR(card->dev))
|
||||
card->dev = NULL;
|
||||
}
|
||||
if ((err = snd_device_register_all(card)) < 0)
|
||||
return err;
|
||||
mutex_lock(&snd_card_mutex);
|
||||
|
@ -910,7 +910,8 @@ void snd_pcm_detach_substream(struct snd_pcm_substream *substream)
|
||||
substream->pstr->substream_opened--;
|
||||
}
|
||||
|
||||
static ssize_t show_pcm_class(struct class_device *class_device, char *buf)
|
||||
static ssize_t show_pcm_class(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct snd_pcm *pcm;
|
||||
const char *str;
|
||||
@ -921,7 +922,7 @@ static ssize_t show_pcm_class(struct class_device *class_device, char *buf)
|
||||
[SNDRV_PCM_CLASS_DIGITIZER] = "digitizer",
|
||||
};
|
||||
|
||||
if (! (pcm = class_get_devdata(class_device)) ||
|
||||
if (! (pcm = dev_get_drvdata(dev)) ||
|
||||
pcm->dev_class > SNDRV_PCM_CLASS_LAST)
|
||||
str = "none";
|
||||
else
|
||||
@ -929,7 +930,7 @@ static ssize_t show_pcm_class(struct class_device *class_device, char *buf)
|
||||
return snprintf(buf, PAGE_SIZE, "%s\n", str);
|
||||
}
|
||||
|
||||
static struct class_device_attribute pcm_attrs =
|
||||
static struct device_attribute pcm_attrs =
|
||||
__ATTR(pcm_class, S_IRUGO, show_pcm_class, NULL);
|
||||
|
||||
static int snd_pcm_dev_register(struct snd_device *device)
|
||||
|
@ -61,9 +61,6 @@ EXPORT_SYMBOL(snd_ecards_limit);
|
||||
static struct snd_minor *snd_minors[SNDRV_OS_MINORS];
|
||||
static DEFINE_MUTEX(sound_mutex);
|
||||
|
||||
extern struct class *sound_class;
|
||||
|
||||
|
||||
#ifdef CONFIG_KMOD
|
||||
|
||||
/**
|
||||
@ -268,11 +265,10 @@ int snd_register_device(int type, struct snd_card *card, int dev,
|
||||
snd_minors[minor] = preg;
|
||||
if (card)
|
||||
device = card->dev;
|
||||
preg->class_dev = class_device_create(sound_class, NULL,
|
||||
MKDEV(major, minor),
|
||||
device, "%s", name);
|
||||
if (preg->class_dev)
|
||||
class_set_devdata(preg->class_dev, private_data);
|
||||
preg->dev = device_create(sound_class, device, MKDEV(major, minor),
|
||||
"%s", name);
|
||||
if (preg->dev)
|
||||
dev_set_drvdata(preg->dev, private_data);
|
||||
|
||||
mutex_unlock(&sound_mutex);
|
||||
return 0;
|
||||
@ -320,7 +316,7 @@ int snd_unregister_device(int type, struct snd_card *card, int dev)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
class_device_destroy(sound_class, MKDEV(major, minor));
|
||||
device_destroy(sound_class, MKDEV(major, minor));
|
||||
|
||||
kfree(snd_minors[minor]);
|
||||
snd_minors[minor] = NULL;
|
||||
@ -331,15 +327,15 @@ int snd_unregister_device(int type, struct snd_card *card, int dev)
|
||||
EXPORT_SYMBOL(snd_unregister_device);
|
||||
|
||||
int snd_add_device_sysfs_file(int type, struct snd_card *card, int dev,
|
||||
const struct class_device_attribute *attr)
|
||||
struct device_attribute *attr)
|
||||
{
|
||||
int minor, ret = -EINVAL;
|
||||
struct class_device *cdev;
|
||||
struct device *d;
|
||||
|
||||
mutex_lock(&sound_mutex);
|
||||
minor = find_snd_minor(type, card, dev);
|
||||
if (minor >= 0 && (cdev = snd_minors[minor]->class_dev) != NULL)
|
||||
ret = class_device_create_file(cdev, attr);
|
||||
if (minor >= 0 && (d = snd_minors[minor]->dev) != NULL)
|
||||
ret = device_create_file(d, attr);
|
||||
mutex_unlock(&sound_mutex);
|
||||
return ret;
|
||||
|
||||
|
@ -557,17 +557,17 @@ static int __init oss_init(void)
|
||||
sound_dmap_flag = (dmabuf > 0 ? 1 : 0);
|
||||
|
||||
for (i = 0; i < sizeof (dev_list) / sizeof *dev_list; i++) {
|
||||
class_device_create(sound_class, NULL,
|
||||
MKDEV(SOUND_MAJOR, dev_list[i].minor),
|
||||
NULL, "%s", dev_list[i].name);
|
||||
device_create(sound_class, NULL,
|
||||
MKDEV(SOUND_MAJOR, dev_list[i].minor),
|
||||
"%s", dev_list[i].name);
|
||||
|
||||
if (!dev_list[i].num)
|
||||
continue;
|
||||
|
||||
for (j = 1; j < *dev_list[i].num; j++)
|
||||
class_device_create(sound_class, NULL,
|
||||
MKDEV(SOUND_MAJOR, dev_list[i].minor + (j*0x10)),
|
||||
NULL, "%s%d", dev_list[i].name, j);
|
||||
device_create(sound_class, NULL,
|
||||
MKDEV(SOUND_MAJOR, dev_list[i].minor + (j*0x10)),
|
||||
"%s%d", dev_list[i].name, j);
|
||||
}
|
||||
|
||||
if (sound_nblocks >= 1024)
|
||||
@ -581,11 +581,11 @@ static void __exit oss_cleanup(void)
|
||||
int i, j;
|
||||
|
||||
for (i = 0; i < sizeof (dev_list) / sizeof *dev_list; i++) {
|
||||
class_device_destroy(sound_class, MKDEV(SOUND_MAJOR, dev_list[i].minor));
|
||||
device_destroy(sound_class, MKDEV(SOUND_MAJOR, dev_list[i].minor));
|
||||
if (!dev_list[i].num)
|
||||
continue;
|
||||
for (j = 1; j < *dev_list[i].num; j++)
|
||||
class_device_destroy(sound_class, MKDEV(SOUND_MAJOR, dev_list[i].minor + (j*0x10)));
|
||||
device_destroy(sound_class, MKDEV(SOUND_MAJOR, dev_list[i].minor + (j*0x10)));
|
||||
}
|
||||
|
||||
unregister_sound_special(1);
|
||||
|
@ -170,8 +170,8 @@ static int sound_insert_unit(struct sound_unit **list, const struct file_operati
|
||||
else
|
||||
sprintf(s->name, "sound/%s%d", name, r / SOUND_STEP);
|
||||
|
||||
class_device_create(sound_class, NULL, MKDEV(SOUND_MAJOR, s->unit_minor),
|
||||
dev, s->name+6);
|
||||
device_create(sound_class, dev, MKDEV(SOUND_MAJOR, s->unit_minor),
|
||||
s->name+6);
|
||||
return r;
|
||||
|
||||
fail:
|
||||
@ -193,7 +193,7 @@ static void sound_remove_unit(struct sound_unit **list, int unit)
|
||||
p = __sound_remove_unit(list, unit);
|
||||
spin_unlock(&sound_loader_lock);
|
||||
if (p) {
|
||||
class_device_destroy(sound_class, MKDEV(SOUND_MAJOR, p->unit_minor));
|
||||
device_destroy(sound_class, MKDEV(SOUND_MAJOR, p->unit_minor));
|
||||
kfree(p);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user