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