Merge git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-2.6
Trivial manual merge fixup for usb_find_interface clashes.
This commit is contained in:
commit
db9edfd7e3
64 changed files with 878 additions and 823 deletions
|
@ -115,7 +115,7 @@ Current PPC64 Linux EEH Implementation
|
||||||
At this time, a generic EEH recovery mechanism has been implemented,
|
At this time, a generic EEH recovery mechanism has been implemented,
|
||||||
so that individual device drivers do not need to be modified to support
|
so that individual device drivers do not need to be modified to support
|
||||||
EEH recovery. This generic mechanism piggy-backs on the PCI hotplug
|
EEH recovery. This generic mechanism piggy-backs on the PCI hotplug
|
||||||
infrastructure, and percolates events up through the hotplug/udev
|
infrastructure, and percolates events up through the userspace/udev
|
||||||
infrastructure. Followiing is a detailed description of how this is
|
infrastructure. Followiing is a detailed description of how this is
|
||||||
accomplished.
|
accomplished.
|
||||||
|
|
||||||
|
@ -172,7 +172,7 @@ A handler for the EEH notifier_block events is implemented in
|
||||||
drivers/pci/hotplug/pSeries_pci.c, called handle_eeh_events().
|
drivers/pci/hotplug/pSeries_pci.c, called handle_eeh_events().
|
||||||
It saves the device BAR's and then calls rpaphp_unconfig_pci_adapter().
|
It saves the device BAR's and then calls rpaphp_unconfig_pci_adapter().
|
||||||
This last call causes the device driver for the card to be stopped,
|
This last call causes the device driver for the card to be stopped,
|
||||||
which causes hotplug events to go out to user space. This triggers
|
which causes uevents to go out to user space. This triggers
|
||||||
user-space scripts that might issue commands such as "ifdown eth0"
|
user-space scripts that might issue commands such as "ifdown eth0"
|
||||||
for ethernet cards, and so on. This handler then sleeps for 5 seconds,
|
for ethernet cards, and so on. This handler then sleeps for 5 seconds,
|
||||||
hoping to give the user-space scripts enough time to complete.
|
hoping to give the user-space scripts enough time to complete.
|
||||||
|
@ -258,29 +258,30 @@ rpa_php_unconfig_pci_adapter() { // in rpaphp_pci.c
|
||||||
calls
|
calls
|
||||||
pci_destroy_dev (struct pci_dev *) {
|
pci_destroy_dev (struct pci_dev *) {
|
||||||
calls
|
calls
|
||||||
device_unregister (&dev->dev) { // in /drivers/base/core.c
|
device_unregister (&dev->dev) { // in /drivers/base/core.c
|
||||||
calls
|
calls
|
||||||
device_del(struct device * dev) { // in /drivers/base/core.c
|
device_del(struct device * dev) { // in /drivers/base/core.c
|
||||||
calls
|
calls
|
||||||
kobject_del() { //in /libs/kobject.c
|
kobject_del() { //in /libs/kobject.c
|
||||||
calls
|
calls
|
||||||
kobject_hotplug() { // in /libs/kobject.c
|
kobject_uevent() { // in /libs/kobject.c
|
||||||
calls
|
calls
|
||||||
kset_hotplug() { // in /lib/kobject.c
|
kset_uevent() { // in /lib/kobject.c
|
||||||
calls
|
calls
|
||||||
kset->hotplug_ops->hotplug() which is really just
|
kset->uevent_ops->uevent() // which is really just
|
||||||
a call to
|
a call to
|
||||||
dev_hotplug() { // in /drivers/base/core.c
|
dev_uevent() { // in /drivers/base/core.c
|
||||||
calls
|
calls
|
||||||
dev->bus->hotplug() which is really just a call to
|
dev->bus->uevent() which is really just a call to
|
||||||
pci_hotplug () { // in drivers/pci/hotplug.c
|
pci_uevent () { // in drivers/pci/hotplug.c
|
||||||
which prints device name, etc....
|
which prints device name, etc....
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
then kset_hotplug() calls
|
then kobject_uevent() sends a netlink uevent to userspace
|
||||||
call_usermodehelper () with
|
--> userspace uevent
|
||||||
argv[0]=hotplug_path[] which is "/sbin/hotplug"
|
(during early boot, nobody listens to netlink events and
|
||||||
--> event to userspace,
|
kobject_uevent() executes uevent_helper[], which runs the
|
||||||
|
event process /sbin/hotplug)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
kobject_del() then calls sysfs_remove_dir(), which would
|
kobject_del() then calls sysfs_remove_dir(), which would
|
||||||
|
|
|
@ -1480,12 +1480,6 @@ W: http://nfs.sourceforge.net/
|
||||||
W: http://www.cse.unsw.edu.au/~neilb/patches/linux-devel/
|
W: http://www.cse.unsw.edu.au/~neilb/patches/linux-devel/
|
||||||
S: Maintained
|
S: Maintained
|
||||||
|
|
||||||
KERNEL EVENT LAYER (KOBJECT_UEVENT)
|
|
||||||
P: Robert Love
|
|
||||||
M: rml@novell.com
|
|
||||||
L: linux-kernel@vger.kernel.org
|
|
||||||
S: Maintained
|
|
||||||
|
|
||||||
KEXEC
|
KEXEC
|
||||||
P: Eric Biederman
|
P: Eric Biederman
|
||||||
P: Randy Dunlap
|
P: Randy Dunlap
|
||||||
|
|
|
@ -45,7 +45,7 @@ static int amba_match(struct device *dev, struct device_driver *drv)
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_HOTPLUG
|
#ifdef CONFIG_HOTPLUG
|
||||||
static int amba_hotplug(struct device *dev, char **envp, int nr_env, char *buf, int bufsz)
|
static int amba_uevent(struct device *dev, char **envp, int nr_env, char *buf, int bufsz)
|
||||||
{
|
{
|
||||||
struct amba_device *pcdev = to_amba_device(dev);
|
struct amba_device *pcdev = to_amba_device(dev);
|
||||||
|
|
||||||
|
@ -58,7 +58,7 @@ static int amba_hotplug(struct device *dev, char **envp, int nr_env, char *buf,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
#define amba_hotplug NULL
|
#define amba_uevent NULL
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static int amba_suspend(struct device *dev, pm_message_t state)
|
static int amba_suspend(struct device *dev, pm_message_t state)
|
||||||
|
@ -88,7 +88,7 @@ static int amba_resume(struct device *dev)
|
||||||
static struct bus_type amba_bustype = {
|
static struct bus_type amba_bustype = {
|
||||||
.name = "amba",
|
.name = "amba",
|
||||||
.match = amba_match,
|
.match = amba_match,
|
||||||
.hotplug = amba_hotplug,
|
.uevent = amba_uevent,
|
||||||
.suspend = amba_suspend,
|
.suspend = amba_suspend,
|
||||||
.resume = amba_resume,
|
.resume = amba_resume,
|
||||||
};
|
};
|
||||||
|
|
|
@ -65,7 +65,7 @@ static int tiocx_match(struct device *dev, struct device_driver *drv)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int tiocx_hotplug(struct device *dev, char **envp, int num_envp,
|
static int tiocx_uevent(struct device *dev, char **envp, int num_envp,
|
||||||
char *buffer, int buffer_size)
|
char *buffer, int buffer_size)
|
||||||
{
|
{
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
@ -79,7 +79,7 @@ static void tiocx_bus_release(struct device *dev)
|
||||||
struct bus_type tiocx_bus_type = {
|
struct bus_type tiocx_bus_type = {
|
||||||
.name = "tiocx",
|
.name = "tiocx",
|
||||||
.match = tiocx_match,
|
.match = tiocx_match,
|
||||||
.hotplug = tiocx_hotplug,
|
.uevent = tiocx_uevent,
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -293,6 +293,6 @@ static int vio_hotplug(struct device *dev, char **envp, int num_envp,
|
||||||
|
|
||||||
struct bus_type vio_bus_type = {
|
struct bus_type vio_bus_type = {
|
||||||
.name = "vio",
|
.name = "vio",
|
||||||
.hotplug = vio_hotplug,
|
.uevent = vio_hotplug,
|
||||||
.match = vio_bus_match,
|
.match = vio_bus_match,
|
||||||
};
|
};
|
||||||
|
|
|
@ -358,7 +358,7 @@ static struct sysfs_ops disk_sysfs_ops = {
|
||||||
static ssize_t disk_uevent_store(struct gendisk * disk,
|
static ssize_t disk_uevent_store(struct gendisk * disk,
|
||||||
const char *buf, size_t count)
|
const char *buf, size_t count)
|
||||||
{
|
{
|
||||||
kobject_hotplug(&disk->kobj, KOBJ_ADD);
|
kobject_uevent(&disk->kobj, KOBJ_ADD);
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
static ssize_t disk_dev_read(struct gendisk * disk, char *page)
|
static ssize_t disk_dev_read(struct gendisk * disk, char *page)
|
||||||
|
@ -455,14 +455,14 @@ static struct kobj_type ktype_block = {
|
||||||
|
|
||||||
extern struct kobj_type ktype_part;
|
extern struct kobj_type ktype_part;
|
||||||
|
|
||||||
static int block_hotplug_filter(struct kset *kset, struct kobject *kobj)
|
static int block_uevent_filter(struct kset *kset, struct kobject *kobj)
|
||||||
{
|
{
|
||||||
struct kobj_type *ktype = get_ktype(kobj);
|
struct kobj_type *ktype = get_ktype(kobj);
|
||||||
|
|
||||||
return ((ktype == &ktype_block) || (ktype == &ktype_part));
|
return ((ktype == &ktype_block) || (ktype == &ktype_part));
|
||||||
}
|
}
|
||||||
|
|
||||||
static int block_hotplug(struct kset *kset, struct kobject *kobj, char **envp,
|
static int block_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)
|
||||||
{
|
{
|
||||||
struct kobj_type *ktype = get_ktype(kobj);
|
struct kobj_type *ktype = get_ktype(kobj);
|
||||||
|
@ -474,40 +474,40 @@ static int block_hotplug(struct kset *kset, struct kobject *kobj, char **envp,
|
||||||
|
|
||||||
if (ktype == &ktype_block) {
|
if (ktype == &ktype_block) {
|
||||||
disk = container_of(kobj, struct gendisk, kobj);
|
disk = container_of(kobj, struct gendisk, kobj);
|
||||||
add_hotplug_env_var(envp, num_envp, &i, buffer, buffer_size,
|
add_uevent_var(envp, num_envp, &i, buffer, buffer_size,
|
||||||
&length, "MINOR=%u", disk->first_minor);
|
&length, "MINOR=%u", disk->first_minor);
|
||||||
} else if (ktype == &ktype_part) {
|
} else if (ktype == &ktype_part) {
|
||||||
disk = container_of(kobj->parent, struct gendisk, kobj);
|
disk = container_of(kobj->parent, struct gendisk, kobj);
|
||||||
part = container_of(kobj, struct hd_struct, kobj);
|
part = container_of(kobj, struct hd_struct, kobj);
|
||||||
add_hotplug_env_var(envp, num_envp, &i, buffer, buffer_size,
|
add_uevent_var(envp, num_envp, &i, buffer, buffer_size,
|
||||||
&length, "MINOR=%u",
|
&length, "MINOR=%u",
|
||||||
disk->first_minor + part->partno);
|
disk->first_minor + part->partno);
|
||||||
} else
|
} else
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
add_hotplug_env_var(envp, num_envp, &i, buffer, buffer_size, &length,
|
add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &length,
|
||||||
"MAJOR=%u", disk->major);
|
"MAJOR=%u", disk->major);
|
||||||
|
|
||||||
/* add physical device, backing this device */
|
/* add physical device, backing this device */
|
||||||
physdev = disk->driverfs_dev;
|
physdev = disk->driverfs_dev;
|
||||||
if (physdev) {
|
if (physdev) {
|
||||||
char *path = kobject_get_path(&physdev->kobj, GFP_KERNEL);
|
char *path = kobject_get_path(&physdev->kobj, GFP_KERNEL);
|
||||||
|
|
||||||
add_hotplug_env_var(envp, num_envp, &i, buffer, buffer_size,
|
add_uevent_var(envp, num_envp, &i, buffer, buffer_size,
|
||||||
&length, "PHYSDEVPATH=%s", path);
|
&length, "PHYSDEVPATH=%s", path);
|
||||||
kfree(path);
|
kfree(path);
|
||||||
|
|
||||||
if (physdev->bus)
|
if (physdev->bus)
|
||||||
add_hotplug_env_var(envp, num_envp, &i,
|
add_uevent_var(envp, num_envp, &i,
|
||||||
buffer, buffer_size, &length,
|
buffer, buffer_size, &length,
|
||||||
"PHYSDEVBUS=%s",
|
"PHYSDEVBUS=%s",
|
||||||
physdev->bus->name);
|
physdev->bus->name);
|
||||||
|
|
||||||
if (physdev->driver)
|
if (physdev->driver)
|
||||||
add_hotplug_env_var(envp, num_envp, &i,
|
add_uevent_var(envp, num_envp, &i,
|
||||||
buffer, buffer_size, &length,
|
buffer, buffer_size, &length,
|
||||||
"PHYSDEVDRIVER=%s",
|
"PHYSDEVDRIVER=%s",
|
||||||
physdev->driver->name);
|
physdev->driver->name);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* terminate, set to next free slot, shrink available space */
|
/* terminate, set to next free slot, shrink available space */
|
||||||
|
@ -520,13 +520,13 @@ static int block_hotplug(struct kset *kset, struct kobject *kobj, char **envp,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct kset_hotplug_ops block_hotplug_ops = {
|
static struct kset_uevent_ops block_uevent_ops = {
|
||||||
.filter = block_hotplug_filter,
|
.filter = block_uevent_filter,
|
||||||
.hotplug = block_hotplug,
|
.uevent = block_uevent,
|
||||||
};
|
};
|
||||||
|
|
||||||
/* declare block_subsys. */
|
/* declare block_subsys. */
|
||||||
static decl_subsys(block, &ktype_block, &block_hotplug_ops);
|
static decl_subsys(block, &ktype_block, &block_uevent_ops);
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -172,21 +172,21 @@ static void container_notify_cb(acpi_handle handle, u32 type, void *context)
|
||||||
if (ACPI_FAILURE(status) || !device) {
|
if (ACPI_FAILURE(status) || !device) {
|
||||||
result = container_device_add(&device, handle);
|
result = container_device_add(&device, handle);
|
||||||
if (!result)
|
if (!result)
|
||||||
kobject_hotplug(&device->kobj,
|
kobject_uevent(&device->kobj,
|
||||||
KOBJ_ONLINE);
|
KOBJ_ONLINE);
|
||||||
else
|
else
|
||||||
printk("Failed to add container\n");
|
printk("Failed to add container\n");
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (ACPI_SUCCESS(status)) {
|
if (ACPI_SUCCESS(status)) {
|
||||||
/* device exist and this is a remove request */
|
/* device exist and this is a remove request */
|
||||||
kobject_hotplug(&device->kobj, KOBJ_OFFLINE);
|
kobject_uevent(&device->kobj, KOBJ_OFFLINE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case ACPI_NOTIFY_EJECT_REQUEST:
|
case ACPI_NOTIFY_EJECT_REQUEST:
|
||||||
if (!acpi_bus_get_device(handle, &device) && device) {
|
if (!acpi_bus_get_device(handle, &device) && device) {
|
||||||
kobject_hotplug(&device->kobj, KOBJ_OFFLINE);
|
kobject_uevent(&device->kobj, KOBJ_OFFLINE);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -748,7 +748,7 @@ int acpi_processor_device_add(acpi_handle handle, struct acpi_device **device)
|
||||||
return_VALUE(-ENODEV);
|
return_VALUE(-ENODEV);
|
||||||
|
|
||||||
if ((pr->id >= 0) && (pr->id < NR_CPUS)) {
|
if ((pr->id >= 0) && (pr->id < NR_CPUS)) {
|
||||||
kobject_hotplug(&(*device)->kobj, KOBJ_ONLINE);
|
kobject_uevent(&(*device)->kobj, KOBJ_ONLINE);
|
||||||
}
|
}
|
||||||
return_VALUE(0);
|
return_VALUE(0);
|
||||||
}
|
}
|
||||||
|
@ -788,13 +788,13 @@ acpi_processor_hotplug_notify(acpi_handle handle, u32 event, void *data)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pr->id >= 0 && (pr->id < NR_CPUS)) {
|
if (pr->id >= 0 && (pr->id < NR_CPUS)) {
|
||||||
kobject_hotplug(&device->kobj, KOBJ_OFFLINE);
|
kobject_uevent(&device->kobj, KOBJ_OFFLINE);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
result = acpi_processor_start(device);
|
result = acpi_processor_start(device);
|
||||||
if ((!result) && ((pr->id >= 0) && (pr->id < NR_CPUS))) {
|
if ((!result) && ((pr->id >= 0) && (pr->id < NR_CPUS))) {
|
||||||
kobject_hotplug(&device->kobj, KOBJ_ONLINE);
|
kobject_uevent(&device->kobj, KOBJ_ONLINE);
|
||||||
} else {
|
} else {
|
||||||
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
|
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
|
||||||
"Device [%s] failed to start\n",
|
"Device [%s] failed to start\n",
|
||||||
|
@ -818,7 +818,7 @@ acpi_processor_hotplug_notify(acpi_handle handle, u32 event, void *data)
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((pr->id < NR_CPUS) && (cpu_present(pr->id)))
|
if ((pr->id < NR_CPUS) && (cpu_present(pr->id)))
|
||||||
kobject_hotplug(&device->kobj, KOBJ_OFFLINE);
|
kobject_uevent(&device->kobj, KOBJ_OFFLINE);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
|
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
|
||||||
|
|
|
@ -78,7 +78,7 @@ static struct kobj_type ktype_acpi_ns = {
|
||||||
.release = acpi_device_release,
|
.release = acpi_device_release,
|
||||||
};
|
};
|
||||||
|
|
||||||
static int namespace_hotplug(struct kset *kset, struct kobject *kobj,
|
static int namespace_uevent(struct kset *kset, struct kobject *kobj,
|
||||||
char **envp, int num_envp, char *buffer,
|
char **envp, int num_envp, char *buffer,
|
||||||
int buffer_size)
|
int buffer_size)
|
||||||
{
|
{
|
||||||
|
@ -89,8 +89,8 @@ static int namespace_hotplug(struct kset *kset, struct kobject *kobj,
|
||||||
if (!dev->driver)
|
if (!dev->driver)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (add_hotplug_env_var(envp, num_envp, &i, buffer, buffer_size, &len,
|
if (add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &len,
|
||||||
"PHYSDEVDRIVER=%s", dev->driver->name))
|
"PHYSDEVDRIVER=%s", dev->driver->name))
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
envp[i] = NULL;
|
envp[i] = NULL;
|
||||||
|
@ -98,8 +98,8 @@ static int namespace_hotplug(struct kset *kset, struct kobject *kobj,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct kset_hotplug_ops namespace_hotplug_ops = {
|
static struct kset_uevent_ops namespace_uevent_ops = {
|
||||||
.hotplug = &namespace_hotplug,
|
.uevent = &namespace_uevent,
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct kset acpi_namespace_kset = {
|
static struct kset acpi_namespace_kset = {
|
||||||
|
@ -108,7 +108,7 @@ static struct kset acpi_namespace_kset = {
|
||||||
},
|
},
|
||||||
.subsys = &acpi_subsys,
|
.subsys = &acpi_subsys,
|
||||||
.ktype = &ktype_acpi_ns,
|
.ktype = &ktype_acpi_ns,
|
||||||
.hotplug_ops = &namespace_hotplug_ops,
|
.uevent_ops = &namespace_uevent_ops,
|
||||||
};
|
};
|
||||||
|
|
||||||
static void acpi_device_register(struct acpi_device *device,
|
static void acpi_device_register(struct acpi_device *device,
|
||||||
|
@ -347,7 +347,7 @@ static int acpi_bus_get_wakeup_device_flags(struct acpi_device *device)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* --------------------------------------------------------------------------
|
/* --------------------------------------------------------------------------
|
||||||
ACPI hotplug sysfs device file support
|
ACPI sysfs device file support
|
||||||
-------------------------------------------------------------------------- */
|
-------------------------------------------------------------------------- */
|
||||||
static ssize_t acpi_eject_store(struct acpi_device *device,
|
static ssize_t acpi_eject_store(struct acpi_device *device,
|
||||||
const char *buf, size_t count);
|
const char *buf, size_t count);
|
||||||
|
|
|
@ -19,11 +19,11 @@ config PREVENT_FIRMWARE_BUILD
|
||||||
If unsure say Y here.
|
If unsure say Y here.
|
||||||
|
|
||||||
config FW_LOADER
|
config FW_LOADER
|
||||||
tristate "Hotplug firmware loading support"
|
tristate "Userspace firmware loading support"
|
||||||
select HOTPLUG
|
select HOTPLUG
|
||||||
---help---
|
---help---
|
||||||
This option is provided for the case where no in-kernel-tree modules
|
This option is provided for the case where no in-kernel-tree modules
|
||||||
require hotplug firmware loading support, but a module built outside
|
require userspace firmware loading support, but a module built outside
|
||||||
the kernel tree does.
|
the kernel tree does.
|
||||||
|
|
||||||
config DEBUG_DRIVER
|
config DEBUG_DRIVER
|
||||||
|
|
|
@ -152,7 +152,11 @@ static ssize_t driver_unbind(struct device_driver *drv,
|
||||||
|
|
||||||
dev = bus_find_device(bus, NULL, (void *)buf, driver_helper);
|
dev = bus_find_device(bus, NULL, (void *)buf, driver_helper);
|
||||||
if (dev && dev->driver == drv) {
|
if (dev && dev->driver == drv) {
|
||||||
|
if (dev->parent) /* Needed for USB */
|
||||||
|
down(&dev->parent->sem);
|
||||||
device_release_driver(dev);
|
device_release_driver(dev);
|
||||||
|
if (dev->parent)
|
||||||
|
up(&dev->parent->sem);
|
||||||
err = count;
|
err = count;
|
||||||
}
|
}
|
||||||
put_device(dev);
|
put_device(dev);
|
||||||
|
@ -175,9 +179,13 @@ static ssize_t driver_bind(struct device_driver *drv,
|
||||||
|
|
||||||
dev = bus_find_device(bus, NULL, (void *)buf, driver_helper);
|
dev = bus_find_device(bus, NULL, (void *)buf, driver_helper);
|
||||||
if (dev && dev->driver == NULL) {
|
if (dev && dev->driver == NULL) {
|
||||||
|
if (dev->parent) /* Needed for USB */
|
||||||
|
down(&dev->parent->sem);
|
||||||
down(&dev->sem);
|
down(&dev->sem);
|
||||||
err = driver_probe_device(drv, dev);
|
err = driver_probe_device(drv, dev);
|
||||||
up(&dev->sem);
|
up(&dev->sem);
|
||||||
|
if (dev->parent)
|
||||||
|
up(&dev->parent->sem);
|
||||||
}
|
}
|
||||||
put_device(dev);
|
put_device(dev);
|
||||||
put_bus(bus);
|
put_bus(bus);
|
||||||
|
@ -420,6 +428,26 @@ static void driver_remove_attrs(struct bus_type * bus, struct device_driver * dr
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_HOTPLUG
|
||||||
|
/*
|
||||||
|
* Thanks to drivers making their tables __devinit, we can't allow manual
|
||||||
|
* bind and unbind from userspace unless CONFIG_HOTPLUG is enabled.
|
||||||
|
*/
|
||||||
|
static void add_bind_files(struct device_driver *drv)
|
||||||
|
{
|
||||||
|
driver_create_file(drv, &driver_attr_unbind);
|
||||||
|
driver_create_file(drv, &driver_attr_bind);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void remove_bind_files(struct device_driver *drv)
|
||||||
|
{
|
||||||
|
driver_remove_file(drv, &driver_attr_bind);
|
||||||
|
driver_remove_file(drv, &driver_attr_unbind);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
static inline void add_bind_files(struct device_driver *drv) {}
|
||||||
|
static inline void remove_bind_files(struct device_driver *drv) {}
|
||||||
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* bus_add_driver - Add a driver to the bus.
|
* bus_add_driver - Add a driver to the bus.
|
||||||
|
@ -449,8 +477,7 @@ int bus_add_driver(struct device_driver * drv)
|
||||||
module_add_driver(drv->owner, drv);
|
module_add_driver(drv->owner, drv);
|
||||||
|
|
||||||
driver_add_attrs(bus, drv);
|
driver_add_attrs(bus, drv);
|
||||||
driver_create_file(drv, &driver_attr_unbind);
|
add_bind_files(drv);
|
||||||
driver_create_file(drv, &driver_attr_bind);
|
|
||||||
}
|
}
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
@ -468,8 +495,7 @@ int bus_add_driver(struct device_driver * drv)
|
||||||
void bus_remove_driver(struct device_driver * drv)
|
void bus_remove_driver(struct device_driver * drv)
|
||||||
{
|
{
|
||||||
if (drv->bus) {
|
if (drv->bus) {
|
||||||
driver_remove_file(drv, &driver_attr_bind);
|
remove_bind_files(drv);
|
||||||
driver_remove_file(drv, &driver_attr_unbind);
|
|
||||||
driver_remove_attrs(drv->bus, drv);
|
driver_remove_attrs(drv->bus, drv);
|
||||||
klist_remove(&drv->knode_bus);
|
klist_remove(&drv->knode_bus);
|
||||||
pr_debug("bus %s: remove driver %s\n", drv->bus->name, drv->name);
|
pr_debug("bus %s: remove driver %s\n", drv->bus->name, drv->name);
|
||||||
|
@ -484,8 +510,13 @@ void bus_remove_driver(struct device_driver * drv)
|
||||||
/* Helper for bus_rescan_devices's iter */
|
/* Helper for bus_rescan_devices's iter */
|
||||||
static int bus_rescan_devices_helper(struct device *dev, void *data)
|
static int bus_rescan_devices_helper(struct device *dev, void *data)
|
||||||
{
|
{
|
||||||
if (!dev->driver)
|
if (!dev->driver) {
|
||||||
|
if (dev->parent) /* Needed for USB */
|
||||||
|
down(&dev->parent->sem);
|
||||||
device_attach(dev);
|
device_attach(dev);
|
||||||
|
if (dev->parent)
|
||||||
|
up(&dev->parent->sem);
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -178,7 +178,7 @@ static void class_device_create_release(struct class_device *class_dev)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* needed to allow these devices to have parent class devices */
|
/* needed to allow these devices to have parent class devices */
|
||||||
static int class_device_create_hotplug(struct class_device *class_dev,
|
static int class_device_create_uevent(struct class_device *class_dev,
|
||||||
char **envp, int num_envp,
|
char **envp, int num_envp,
|
||||||
char *buffer, int buffer_size)
|
char *buffer, int buffer_size)
|
||||||
{
|
{
|
||||||
|
@ -331,7 +331,7 @@ static struct kobj_type ktype_class_device = {
|
||||||
.release = class_dev_release,
|
.release = class_dev_release,
|
||||||
};
|
};
|
||||||
|
|
||||||
static int class_hotplug_filter(struct kset *kset, struct kobject *kobj)
|
static int class_uevent_filter(struct kset *kset, struct kobject *kobj)
|
||||||
{
|
{
|
||||||
struct kobj_type *ktype = get_ktype(kobj);
|
struct kobj_type *ktype = get_ktype(kobj);
|
||||||
|
|
||||||
|
@ -343,14 +343,14 @@ static int class_hotplug_filter(struct kset *kset, struct kobject *kobj)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char *class_hotplug_name(struct kset *kset, struct kobject *kobj)
|
static const char *class_uevent_name(struct kset *kset, struct kobject *kobj)
|
||||||
{
|
{
|
||||||
struct class_device *class_dev = to_class_dev(kobj);
|
struct class_device *class_dev = to_class_dev(kobj);
|
||||||
|
|
||||||
return class_dev->class->name;
|
return class_dev->class->name;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int class_hotplug(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)
|
||||||
{
|
{
|
||||||
struct class_device *class_dev = to_class_dev(kobj);
|
struct class_device *class_dev = to_class_dev(kobj);
|
||||||
|
@ -365,29 +365,29 @@ static int class_hotplug(struct kset *kset, struct kobject *kobj, char **envp,
|
||||||
struct device *dev = class_dev->dev;
|
struct device *dev = class_dev->dev;
|
||||||
char *path = kobject_get_path(&dev->kobj, GFP_KERNEL);
|
char *path = kobject_get_path(&dev->kobj, GFP_KERNEL);
|
||||||
|
|
||||||
add_hotplug_env_var(envp, num_envp, &i, buffer, buffer_size,
|
add_uevent_var(envp, num_envp, &i, buffer, buffer_size,
|
||||||
&length, "PHYSDEVPATH=%s", path);
|
&length, "PHYSDEVPATH=%s", path);
|
||||||
kfree(path);
|
kfree(path);
|
||||||
|
|
||||||
if (dev->bus)
|
if (dev->bus)
|
||||||
add_hotplug_env_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);
|
||||||
|
|
||||||
if (dev->driver)
|
if (dev->driver)
|
||||||
add_hotplug_env_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);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (MAJOR(class_dev->devt)) {
|
if (MAJOR(class_dev->devt)) {
|
||||||
add_hotplug_env_var(envp, num_envp, &i,
|
add_uevent_var(envp, num_envp, &i,
|
||||||
buffer, buffer_size, &length,
|
buffer, buffer_size, &length,
|
||||||
"MAJOR=%u", MAJOR(class_dev->devt));
|
"MAJOR=%u", MAJOR(class_dev->devt));
|
||||||
|
|
||||||
add_hotplug_env_var(envp, num_envp, &i,
|
add_uevent_var(envp, num_envp, &i,
|
||||||
buffer, buffer_size, &length,
|
buffer, buffer_size, &length,
|
||||||
"MINOR=%u", MINOR(class_dev->devt));
|
"MINOR=%u", MINOR(class_dev->devt));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* terminate, set to next free slot, shrink available space */
|
/* terminate, set to next free slot, shrink available space */
|
||||||
|
@ -397,30 +397,30 @@ static int class_hotplug(struct kset *kset, struct kobject *kobj, char **envp,
|
||||||
buffer = &buffer[length];
|
buffer = &buffer[length];
|
||||||
buffer_size -= length;
|
buffer_size -= length;
|
||||||
|
|
||||||
if (class_dev->hotplug) {
|
if (class_dev->uevent) {
|
||||||
/* have the class device specific function add its stuff */
|
/* have the class device specific function add its stuff */
|
||||||
retval = class_dev->hotplug(class_dev, envp, num_envp,
|
retval = class_dev->uevent(class_dev, envp, num_envp,
|
||||||
buffer, buffer_size);
|
buffer, buffer_size);
|
||||||
if (retval)
|
if (retval)
|
||||||
pr_debug("class_dev->hotplug() returned %d\n", retval);
|
pr_debug("class_dev->uevent() returned %d\n", retval);
|
||||||
} else if (class_dev->class->hotplug) {
|
} else if (class_dev->class->uevent) {
|
||||||
/* have the class specific function add its stuff */
|
/* have the class specific function add its stuff */
|
||||||
retval = class_dev->class->hotplug(class_dev, envp, num_envp,
|
retval = class_dev->class->uevent(class_dev, envp, num_envp,
|
||||||
buffer, buffer_size);
|
buffer, buffer_size);
|
||||||
if (retval)
|
if (retval)
|
||||||
pr_debug("class->hotplug() returned %d\n", retval);
|
pr_debug("class->uevent() returned %d\n", retval);
|
||||||
}
|
}
|
||||||
|
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct kset_hotplug_ops class_hotplug_ops = {
|
static struct kset_uevent_ops class_uevent_ops = {
|
||||||
.filter = class_hotplug_filter,
|
.filter = class_uevent_filter,
|
||||||
.name = class_hotplug_name,
|
.name = class_uevent_name,
|
||||||
.hotplug = class_hotplug,
|
.uevent = class_uevent,
|
||||||
};
|
};
|
||||||
|
|
||||||
static decl_subsys(class_obj, &ktype_class_device, &class_hotplug_ops);
|
static decl_subsys(class_obj, &ktype_class_device, &class_uevent_ops);
|
||||||
|
|
||||||
|
|
||||||
static int class_device_add_attrs(struct class_device * cd)
|
static int class_device_add_attrs(struct class_device * cd)
|
||||||
|
@ -464,7 +464,7 @@ static ssize_t show_dev(struct class_device *class_dev, char *buf)
|
||||||
static ssize_t store_uevent(struct class_device *class_dev,
|
static ssize_t store_uevent(struct class_device *class_dev,
|
||||||
const char *buf, size_t count)
|
const char *buf, size_t count)
|
||||||
{
|
{
|
||||||
kobject_hotplug(&class_dev->kobj, KOBJ_ADD);
|
kobject_uevent(&class_dev->kobj, KOBJ_ADD);
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -559,7 +559,7 @@ int class_device_add(struct class_device *class_dev)
|
||||||
class_name);
|
class_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
kobject_hotplug(&class_dev->kobj, KOBJ_ADD);
|
kobject_uevent(&class_dev->kobj, KOBJ_ADD);
|
||||||
|
|
||||||
/* notify any interfaces this device is now here */
|
/* notify any interfaces this device is now here */
|
||||||
if (parent_class) {
|
if (parent_class) {
|
||||||
|
@ -632,7 +632,7 @@ struct class_device *class_device_create(struct class *cls,
|
||||||
class_dev->class = cls;
|
class_dev->class = cls;
|
||||||
class_dev->parent = parent;
|
class_dev->parent = parent;
|
||||||
class_dev->release = class_device_create_release;
|
class_dev->release = class_device_create_release;
|
||||||
class_dev->hotplug = class_device_create_hotplug;
|
class_dev->uevent = class_device_create_uevent;
|
||||||
|
|
||||||
va_start(args, fmt);
|
va_start(args, fmt);
|
||||||
vsnprintf(class_dev->class_id, BUS_ID_SIZE, fmt, args);
|
vsnprintf(class_dev->class_id, BUS_ID_SIZE, fmt, args);
|
||||||
|
@ -674,7 +674,7 @@ void class_device_del(struct class_device *class_dev)
|
||||||
class_device_remove_file(class_dev, class_dev->devt_attr);
|
class_device_remove_file(class_dev, class_dev->devt_attr);
|
||||||
class_device_remove_attrs(class_dev);
|
class_device_remove_attrs(class_dev);
|
||||||
|
|
||||||
kobject_hotplug(&class_dev->kobj, KOBJ_REMOVE);
|
kobject_uevent(&class_dev->kobj, KOBJ_REMOVE);
|
||||||
kobject_del(&class_dev->kobj);
|
kobject_del(&class_dev->kobj);
|
||||||
|
|
||||||
class_device_put(parent_device);
|
class_device_put(parent_device);
|
||||||
|
|
|
@ -90,7 +90,7 @@ static struct kobj_type ktype_device = {
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
static int dev_hotplug_filter(struct kset *kset, struct kobject *kobj)
|
static int dev_uevent_filter(struct kset *kset, struct kobject *kobj)
|
||||||
{
|
{
|
||||||
struct kobj_type *ktype = get_ktype(kobj);
|
struct kobj_type *ktype = get_ktype(kobj);
|
||||||
|
|
||||||
|
@ -102,14 +102,14 @@ static int dev_hotplug_filter(struct kset *kset, struct kobject *kobj)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char *dev_hotplug_name(struct kset *kset, struct kobject *kobj)
|
static const char *dev_uevent_name(struct kset *kset, struct kobject *kobj)
|
||||||
{
|
{
|
||||||
struct device *dev = to_dev(kobj);
|
struct device *dev = to_dev(kobj);
|
||||||
|
|
||||||
return dev->bus->name;
|
return dev->bus->name;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int dev_hotplug(struct kset *kset, struct kobject *kobj, char **envp,
|
static int dev_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)
|
||||||
{
|
{
|
||||||
struct device *dev = to_dev(kobj);
|
struct device *dev = to_dev(kobj);
|
||||||
|
@ -119,15 +119,15 @@ static int dev_hotplug(struct kset *kset, struct kobject *kobj, char **envp,
|
||||||
|
|
||||||
/* add bus name of physical device */
|
/* add bus name of physical device */
|
||||||
if (dev->bus)
|
if (dev->bus)
|
||||||
add_hotplug_env_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);
|
||||||
|
|
||||||
/* add driver name of physical device */
|
/* add driver name of physical device */
|
||||||
if (dev->driver)
|
if (dev->driver)
|
||||||
add_hotplug_env_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);
|
||||||
|
|
||||||
/* terminate, set to next free slot, shrink available space */
|
/* terminate, set to next free slot, shrink available space */
|
||||||
envp[i] = NULL;
|
envp[i] = NULL;
|
||||||
|
@ -136,11 +136,11 @@ static int dev_hotplug(struct kset *kset, struct kobject *kobj, char **envp,
|
||||||
buffer = &buffer[length];
|
buffer = &buffer[length];
|
||||||
buffer_size -= length;
|
buffer_size -= length;
|
||||||
|
|
||||||
if (dev->bus && dev->bus->hotplug) {
|
if (dev->bus && dev->bus->uevent) {
|
||||||
/* have the bus specific function add its stuff */
|
/* have the bus specific function add its stuff */
|
||||||
retval = dev->bus->hotplug (dev, envp, num_envp, buffer, buffer_size);
|
retval = dev->bus->uevent(dev, envp, num_envp, buffer, buffer_size);
|
||||||
if (retval) {
|
if (retval) {
|
||||||
pr_debug ("%s - hotplug() returned %d\n",
|
pr_debug ("%s - uevent() returned %d\n",
|
||||||
__FUNCTION__, retval);
|
__FUNCTION__, retval);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -148,16 +148,16 @@ static int dev_hotplug(struct kset *kset, struct kobject *kobj, char **envp,
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct kset_hotplug_ops device_hotplug_ops = {
|
static struct kset_uevent_ops device_uevent_ops = {
|
||||||
.filter = dev_hotplug_filter,
|
.filter = dev_uevent_filter,
|
||||||
.name = dev_hotplug_name,
|
.name = dev_uevent_name,
|
||||||
.hotplug = dev_hotplug,
|
.uevent = dev_uevent,
|
||||||
};
|
};
|
||||||
|
|
||||||
static ssize_t store_uevent(struct device *dev, struct device_attribute *attr,
|
static ssize_t store_uevent(struct device *dev, struct device_attribute *attr,
|
||||||
const char *buf, size_t count)
|
const char *buf, size_t count)
|
||||||
{
|
{
|
||||||
kobject_hotplug(&dev->kobj, KOBJ_ADD);
|
kobject_uevent(&dev->kobj, KOBJ_ADD);
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -165,7 +165,7 @@ static ssize_t store_uevent(struct device *dev, struct device_attribute *attr,
|
||||||
* device_subsys - structure to be registered with kobject core.
|
* device_subsys - structure to be registered with kobject core.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
decl_subsys(devices, &ktype_device, &device_hotplug_ops);
|
decl_subsys(devices, &ktype_device, &device_uevent_ops);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -274,7 +274,7 @@ int device_add(struct device *dev)
|
||||||
dev->uevent_attr.store = store_uevent;
|
dev->uevent_attr.store = store_uevent;
|
||||||
device_create_file(dev, &dev->uevent_attr);
|
device_create_file(dev, &dev->uevent_attr);
|
||||||
|
|
||||||
kobject_hotplug(&dev->kobj, KOBJ_ADD);
|
kobject_uevent(&dev->kobj, KOBJ_ADD);
|
||||||
if ((error = device_pm_add(dev)))
|
if ((error = device_pm_add(dev)))
|
||||||
goto PMError;
|
goto PMError;
|
||||||
if ((error = bus_add_device(dev)))
|
if ((error = bus_add_device(dev)))
|
||||||
|
@ -291,7 +291,7 @@ int device_add(struct device *dev)
|
||||||
BusError:
|
BusError:
|
||||||
device_pm_remove(dev);
|
device_pm_remove(dev);
|
||||||
PMError:
|
PMError:
|
||||||
kobject_hotplug(&dev->kobj, KOBJ_REMOVE);
|
kobject_uevent(&dev->kobj, KOBJ_REMOVE);
|
||||||
kobject_del(&dev->kobj);
|
kobject_del(&dev->kobj);
|
||||||
Error:
|
Error:
|
||||||
if (parent)
|
if (parent)
|
||||||
|
@ -374,7 +374,7 @@ void device_del(struct device * dev)
|
||||||
platform_notify_remove(dev);
|
platform_notify_remove(dev);
|
||||||
bus_remove_device(dev);
|
bus_remove_device(dev);
|
||||||
device_pm_remove(dev);
|
device_pm_remove(dev);
|
||||||
kobject_hotplug(&dev->kobj, KOBJ_REMOVE);
|
kobject_uevent(&dev->kobj, KOBJ_REMOVE);
|
||||||
kobject_del(&dev->kobj);
|
kobject_del(&dev->kobj);
|
||||||
if (parent)
|
if (parent)
|
||||||
put_device(parent);
|
put_device(parent);
|
||||||
|
|
|
@ -41,14 +41,14 @@ static ssize_t store_online(struct sys_device *dev, const char *buf,
|
||||||
case '0':
|
case '0':
|
||||||
ret = cpu_down(cpu->sysdev.id);
|
ret = cpu_down(cpu->sysdev.id);
|
||||||
if (!ret)
|
if (!ret)
|
||||||
kobject_hotplug(&dev->kobj, KOBJ_OFFLINE);
|
kobject_uevent(&dev->kobj, KOBJ_OFFLINE);
|
||||||
break;
|
break;
|
||||||
case '1':
|
case '1':
|
||||||
ret = smp_prepare_cpu(cpu->sysdev.id);
|
ret = smp_prepare_cpu(cpu->sysdev.id);
|
||||||
if (!ret)
|
if (!ret)
|
||||||
ret = cpu_up(cpu->sysdev.id);
|
ret = cpu_up(cpu->sysdev.id);
|
||||||
if (!ret)
|
if (!ret)
|
||||||
kobject_hotplug(&dev->kobj, KOBJ_ONLINE);
|
kobject_uevent(&dev->kobj, KOBJ_ONLINE);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
|
|
|
@ -65,7 +65,8 @@ void device_bind_driver(struct device * dev)
|
||||||
* This function returns 1 if a match is found, an error if one
|
* This function returns 1 if a match is found, an error if one
|
||||||
* occurs (that is not -ENODEV or -ENXIO), and 0 otherwise.
|
* occurs (that is not -ENODEV or -ENXIO), and 0 otherwise.
|
||||||
*
|
*
|
||||||
* This function must be called with @dev->sem held.
|
* This function must be called with @dev->sem held. When called
|
||||||
|
* for a USB interface, @dev->parent->sem must be held as well.
|
||||||
*/
|
*/
|
||||||
int driver_probe_device(struct device_driver * drv, struct device * dev)
|
int driver_probe_device(struct device_driver * drv, struct device * dev)
|
||||||
{
|
{
|
||||||
|
@ -123,6 +124,8 @@ static int __device_attach(struct device_driver * drv, void * data)
|
||||||
*
|
*
|
||||||
* Returns 1 if the device was bound to a driver;
|
* Returns 1 if the device was bound to a driver;
|
||||||
* 0 if no matching device was found; error code otherwise.
|
* 0 if no matching device was found; error code otherwise.
|
||||||
|
*
|
||||||
|
* When called for a USB interface, @dev->parent->sem must be held.
|
||||||
*/
|
*/
|
||||||
int device_attach(struct device * dev)
|
int device_attach(struct device * dev)
|
||||||
{
|
{
|
||||||
|
@ -152,10 +155,14 @@ static int __driver_attach(struct device * dev, void * data)
|
||||||
* is an error.
|
* is an error.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
if (dev->parent) /* Needed for USB */
|
||||||
|
down(&dev->parent->sem);
|
||||||
down(&dev->sem);
|
down(&dev->sem);
|
||||||
if (!dev->driver)
|
if (!dev->driver)
|
||||||
driver_probe_device(drv, dev);
|
driver_probe_device(drv, dev);
|
||||||
up(&dev->sem);
|
up(&dev->sem);
|
||||||
|
if (dev->parent)
|
||||||
|
up(&dev->parent->sem);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -181,6 +188,8 @@ void driver_attach(struct device_driver * drv)
|
||||||
* Manually detach device from driver.
|
* Manually detach device from driver.
|
||||||
*
|
*
|
||||||
* __device_release_driver() must be called with @dev->sem held.
|
* __device_release_driver() must be called with @dev->sem held.
|
||||||
|
* When called for a USB interface, @dev->parent->sem must be held
|
||||||
|
* as well.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static void __device_release_driver(struct device * dev)
|
static void __device_release_driver(struct device * dev)
|
||||||
|
@ -233,10 +242,14 @@ void driver_detach(struct device_driver * drv)
|
||||||
get_device(dev);
|
get_device(dev);
|
||||||
spin_unlock(&drv->klist_devices.k_lock);
|
spin_unlock(&drv->klist_devices.k_lock);
|
||||||
|
|
||||||
|
if (dev->parent) /* Needed for USB */
|
||||||
|
down(&dev->parent->sem);
|
||||||
down(&dev->sem);
|
down(&dev->sem);
|
||||||
if (dev->driver == drv)
|
if (dev->driver == drv)
|
||||||
__device_release_driver(dev);
|
__device_release_driver(dev);
|
||||||
up(&dev->sem);
|
up(&dev->sem);
|
||||||
|
if (dev->parent)
|
||||||
|
up(&dev->parent->sem);
|
||||||
put_device(dev);
|
put_device(dev);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -85,17 +85,17 @@ 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_class_dev_release(struct class_device *class_dev);
|
||||||
int firmware_class_hotplug(struct class_device *dev, char **envp,
|
int firmware_class_uevent(struct class_device *dev, char **envp,
|
||||||
int num_envp, char *buffer, int buffer_size);
|
int num_envp, char *buffer, int buffer_size);
|
||||||
|
|
||||||
static struct class firmware_class = {
|
static struct class firmware_class = {
|
||||||
.name = "firmware",
|
.name = "firmware",
|
||||||
.hotplug = firmware_class_hotplug,
|
.uevent = firmware_class_uevent,
|
||||||
.release = fw_class_dev_release,
|
.release = fw_class_dev_release,
|
||||||
};
|
};
|
||||||
|
|
||||||
int
|
int
|
||||||
firmware_class_hotplug(struct class_device *class_dev, char **envp,
|
firmware_class_uevent(struct class_device *class_dev, char **envp,
|
||||||
int num_envp, char *buffer, int buffer_size)
|
int num_envp, char *buffer, int buffer_size)
|
||||||
{
|
{
|
||||||
struct firmware_priv *fw_priv = class_get_devdata(class_dev);
|
struct firmware_priv *fw_priv = class_get_devdata(class_dev);
|
||||||
|
@ -104,13 +104,12 @@ firmware_class_hotplug(struct class_device *class_dev, char **envp,
|
||||||
if (!test_bit(FW_STATUS_READY, &fw_priv->status))
|
if (!test_bit(FW_STATUS_READY, &fw_priv->status))
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
|
||||||
if (add_hotplug_env_var(envp, num_envp, &i, buffer, buffer_size, &len,
|
if (add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &len,
|
||||||
"FIRMWARE=%s", fw_priv->fw_id))
|
"FIRMWARE=%s", fw_priv->fw_id))
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
if (add_hotplug_env_var(envp, num_envp, &i, buffer, buffer_size, &len,
|
if (add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &len,
|
||||||
"TIMEOUT=%i", loading_timeout))
|
"TIMEOUT=%i", loading_timeout))
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
envp[i] = NULL;
|
envp[i] = NULL;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -352,7 +351,7 @@ error_kfree:
|
||||||
|
|
||||||
static int
|
static int
|
||||||
fw_setup_class_device(struct firmware *fw, struct class_device **class_dev_p,
|
fw_setup_class_device(struct firmware *fw, struct class_device **class_dev_p,
|
||||||
const char *fw_name, struct device *device, int hotplug)
|
const char *fw_name, struct device *device, int uevent)
|
||||||
{
|
{
|
||||||
struct class_device *class_dev;
|
struct class_device *class_dev;
|
||||||
struct firmware_priv *fw_priv;
|
struct firmware_priv *fw_priv;
|
||||||
|
@ -384,7 +383,7 @@ fw_setup_class_device(struct firmware *fw, struct class_device **class_dev_p,
|
||||||
goto error_unreg;
|
goto error_unreg;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hotplug)
|
if (uevent)
|
||||||
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);
|
||||||
|
@ -399,7 +398,7 @@ out:
|
||||||
|
|
||||||
static int
|
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 hotplug)
|
struct device *device, int uevent)
|
||||||
{
|
{
|
||||||
struct class_device *class_dev;
|
struct class_device *class_dev;
|
||||||
struct firmware_priv *fw_priv;
|
struct firmware_priv *fw_priv;
|
||||||
|
@ -418,19 +417,19 @@ _request_firmware(const struct firmware **firmware_p, const char *name,
|
||||||
}
|
}
|
||||||
|
|
||||||
retval = fw_setup_class_device(firmware, &class_dev, name, device,
|
retval = fw_setup_class_device(firmware, &class_dev, name, device,
|
||||||
hotplug);
|
uevent);
|
||||||
if (retval)
|
if (retval)
|
||||||
goto error_kfree_fw;
|
goto error_kfree_fw;
|
||||||
|
|
||||||
fw_priv = class_get_devdata(class_dev);
|
fw_priv = class_get_devdata(class_dev);
|
||||||
|
|
||||||
if (hotplug) {
|
if (uevent) {
|
||||||
if (loading_timeout > 0) {
|
if (loading_timeout > 0) {
|
||||||
fw_priv->timeout.expires = jiffies + loading_timeout * HZ;
|
fw_priv->timeout.expires = jiffies + loading_timeout * HZ;
|
||||||
add_timer(&fw_priv->timeout);
|
add_timer(&fw_priv->timeout);
|
||||||
}
|
}
|
||||||
|
|
||||||
kobject_hotplug(&class_dev->kobj, KOBJ_ADD);
|
kobject_uevent(&class_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);
|
||||||
|
@ -456,7 +455,7 @@ out:
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* request_firmware: - request firmware to hotplug and wait for it
|
* request_firmware: - send firmware request and wait for it
|
||||||
* @firmware_p: pointer to firmware image
|
* @firmware_p: pointer to firmware image
|
||||||
* @name: name of firmware file
|
* @name: name of firmware file
|
||||||
* @device: device for which firmware is being loaded
|
* @device: device for which firmware is being loaded
|
||||||
|
@ -466,7 +465,7 @@ out:
|
||||||
*
|
*
|
||||||
* Should be called from user context where sleeping is allowed.
|
* Should be called from user context where sleeping is allowed.
|
||||||
*
|
*
|
||||||
* @name will be used as $FIRMWARE in the hotplug environment and
|
* @name will be used as $FIRMWARE in the uevent environment and
|
||||||
* should be distinctive enough not to be confused with any other
|
* should be distinctive enough not to be confused with any other
|
||||||
* firmware image for this or any other device.
|
* firmware image for this or any other device.
|
||||||
**/
|
**/
|
||||||
|
@ -474,8 +473,8 @@ int
|
||||||
request_firmware(const struct firmware **firmware_p, const char *name,
|
request_firmware(const struct firmware **firmware_p, const char *name,
|
||||||
struct device *device)
|
struct device *device)
|
||||||
{
|
{
|
||||||
int hotplug = 1;
|
int uevent = 1;
|
||||||
return _request_firmware(firmware_p, name, device, hotplug);
|
return _request_firmware(firmware_p, name, device, uevent);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -518,7 +517,7 @@ struct firmware_work {
|
||||||
struct device *device;
|
struct device *device;
|
||||||
void *context;
|
void *context;
|
||||||
void (*cont)(const struct firmware *fw, void *context);
|
void (*cont)(const struct firmware *fw, void *context);
|
||||||
int hotplug;
|
int uevent;
|
||||||
};
|
};
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
@ -533,7 +532,7 @@ request_firmware_work_func(void *arg)
|
||||||
}
|
}
|
||||||
daemonize("%s/%s", "firmware", fw_work->name);
|
daemonize("%s/%s", "firmware", fw_work->name);
|
||||||
ret = _request_firmware(&fw, fw_work->name, fw_work->device,
|
ret = _request_firmware(&fw, fw_work->name, fw_work->device,
|
||||||
fw_work->hotplug);
|
fw_work->uevent);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
fw_work->cont(NULL, fw_work->context);
|
fw_work->cont(NULL, fw_work->context);
|
||||||
else {
|
else {
|
||||||
|
@ -548,7 +547,7 @@ request_firmware_work_func(void *arg)
|
||||||
/**
|
/**
|
||||||
* request_firmware_nowait: asynchronous version of request_firmware
|
* request_firmware_nowait: asynchronous version of request_firmware
|
||||||
* @module: module requesting the firmware
|
* @module: module requesting the firmware
|
||||||
* @hotplug: invokes hotplug event to copy the firmware image if this flag
|
* @uevent: sends uevent to copy the firmware image if this flag
|
||||||
* is non-zero else the firmware copy must be done manually.
|
* is non-zero else the firmware copy must be done manually.
|
||||||
* @name: name of firmware file
|
* @name: name of firmware file
|
||||||
* @device: device for which firmware is being loaded
|
* @device: device for which firmware is being loaded
|
||||||
|
@ -562,7 +561,7 @@ request_firmware_work_func(void *arg)
|
||||||
**/
|
**/
|
||||||
int
|
int
|
||||||
request_firmware_nowait(
|
request_firmware_nowait(
|
||||||
struct module *module, int hotplug,
|
struct module *module, int uevent,
|
||||||
const char *name, struct device *device, void *context,
|
const char *name, struct device *device, void *context,
|
||||||
void (*cont)(const struct firmware *fw, void *context))
|
void (*cont)(const struct firmware *fw, void *context))
|
||||||
{
|
{
|
||||||
|
@ -583,7 +582,7 @@ request_firmware_nowait(
|
||||||
.device = device,
|
.device = device,
|
||||||
.context = context,
|
.context = context,
|
||||||
.cont = cont,
|
.cont = cont,
|
||||||
.hotplug = hotplug,
|
.uevent = uevent,
|
||||||
};
|
};
|
||||||
|
|
||||||
ret = kernel_thread(request_firmware_work_func, fw_work,
|
ret = kernel_thread(request_firmware_work_func, fw_work,
|
||||||
|
|
|
@ -29,12 +29,12 @@ static struct sysdev_class memory_sysdev_class = {
|
||||||
set_kset_name(MEMORY_CLASS_NAME),
|
set_kset_name(MEMORY_CLASS_NAME),
|
||||||
};
|
};
|
||||||
|
|
||||||
static char *memory_hotplug_name(struct kset *kset, struct kobject *kobj)
|
static const char *memory_uevent_name(struct kset *kset, struct kobject *kobj)
|
||||||
{
|
{
|
||||||
return MEMORY_CLASS_NAME;
|
return MEMORY_CLASS_NAME;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int memory_hotplug(struct kset *kset, struct kobject *kobj, char **envp,
|
static int memory_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)
|
||||||
{
|
{
|
||||||
int retval = 0;
|
int retval = 0;
|
||||||
|
@ -42,9 +42,9 @@ static int memory_hotplug(struct kset *kset, struct kobject *kobj, char **envp,
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct kset_hotplug_ops memory_hotplug_ops = {
|
static struct kset_uevent_ops memory_uevent_ops = {
|
||||||
.name = memory_hotplug_name,
|
.name = memory_uevent_name,
|
||||||
.hotplug = memory_hotplug,
|
.uevent = memory_uevent,
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct notifier_block *memory_chain;
|
static struct notifier_block *memory_chain;
|
||||||
|
@ -431,7 +431,7 @@ int __init memory_dev_init(void)
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
memory_sysdev_class.kset.hotplug_ops = &memory_hotplug_ops;
|
memory_sysdev_class.kset.uevent_ops = &memory_uevent_ops;
|
||||||
ret = sysdev_class_register(&memory_sysdev_class);
|
ret = sysdev_class_register(&memory_sysdev_class);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
struct device platform_bus = {
|
struct device platform_bus = {
|
||||||
.bus_id = "platform",
|
.bus_id = "platform",
|
||||||
};
|
};
|
||||||
|
EXPORT_SYMBOL_GPL(platform_bus);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* platform_get_resource - get a resource for a device
|
* platform_get_resource - get a resource for a device
|
||||||
|
@ -49,6 +50,7 @@ platform_get_resource(struct platform_device *dev, unsigned int type,
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(platform_get_resource);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* platform_get_irq - get an IRQ for a device
|
* platform_get_irq - get an IRQ for a device
|
||||||
|
@ -61,6 +63,7 @@ int platform_get_irq(struct platform_device *dev, unsigned int num)
|
||||||
|
|
||||||
return r ? r->start : 0;
|
return r ? r->start : 0;
|
||||||
}
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(platform_get_irq);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* platform_get_resource_byname - get a resource for a device by name
|
* platform_get_resource_byname - get a resource for a device by name
|
||||||
|
@ -84,6 +87,7 @@ platform_get_resource_byname(struct platform_device *dev, unsigned int type,
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(platform_get_resource_byname);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* platform_get_irq - get an IRQ for a device
|
* platform_get_irq - get an IRQ for a device
|
||||||
|
@ -96,6 +100,7 @@ int platform_get_irq_byname(struct platform_device *dev, char *name)
|
||||||
|
|
||||||
return r ? r->start : 0;
|
return r ? r->start : 0;
|
||||||
}
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(platform_get_irq_byname);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* platform_add_devices - add a numbers of platform devices
|
* platform_add_devices - add a numbers of platform devices
|
||||||
|
@ -117,6 +122,7 @@ int platform_add_devices(struct platform_device **devs, int num)
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(platform_add_devices);
|
||||||
|
|
||||||
struct platform_object {
|
struct platform_object {
|
||||||
struct platform_device pdev;
|
struct platform_device pdev;
|
||||||
|
@ -168,7 +174,7 @@ struct platform_device *platform_device_alloc(const char *name, unsigned int id)
|
||||||
pa->pdev.dev.release = platform_device_release;
|
pa->pdev.dev.release = platform_device_release;
|
||||||
}
|
}
|
||||||
|
|
||||||
return pa ? &pa->pdev : NULL;
|
return pa ? &pa->pdev : NULL;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(platform_device_alloc);
|
EXPORT_SYMBOL_GPL(platform_device_alloc);
|
||||||
|
|
||||||
|
@ -257,7 +263,7 @@ int platform_device_add(struct platform_device *pdev)
|
||||||
p = &ioport_resource;
|
p = &ioport_resource;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (p && request_resource(p, r)) {
|
if (p && insert_resource(p, r)) {
|
||||||
printk(KERN_ERR
|
printk(KERN_ERR
|
||||||
"%s: failed to claim resource %d\n",
|
"%s: failed to claim resource %d\n",
|
||||||
pdev->dev.bus_id, i);
|
pdev->dev.bus_id, i);
|
||||||
|
@ -282,24 +288,13 @@ int platform_device_add(struct platform_device *pdev)
|
||||||
EXPORT_SYMBOL_GPL(platform_device_add);
|
EXPORT_SYMBOL_GPL(platform_device_add);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* platform_device_register - add a platform-level device
|
* platform_device_del - remove a platform-level device
|
||||||
* @pdev: platform device we're adding
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
int platform_device_register(struct platform_device * pdev)
|
|
||||||
{
|
|
||||||
device_initialize(&pdev->dev);
|
|
||||||
return platform_device_add(pdev);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* platform_device_unregister - remove a platform-level device
|
|
||||||
* @pdev: platform device we're removing
|
* @pdev: platform device we're removing
|
||||||
*
|
*
|
||||||
* Note that this function will also release all memory- and port-based
|
* Note that this function will also release all memory- and port-based
|
||||||
* resources owned by the device (@dev->resource).
|
* resources owned by the device (@dev->resource).
|
||||||
*/
|
*/
|
||||||
void platform_device_unregister(struct platform_device * pdev)
|
void platform_device_del(struct platform_device *pdev)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
@ -310,9 +305,37 @@ void platform_device_unregister(struct platform_device * pdev)
|
||||||
release_resource(r);
|
release_resource(r);
|
||||||
}
|
}
|
||||||
|
|
||||||
device_unregister(&pdev->dev);
|
device_del(&pdev->dev);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(platform_device_del);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* platform_device_register - add a platform-level device
|
||||||
|
* @pdev: platform device we're adding
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
int platform_device_register(struct platform_device * pdev)
|
||||||
|
{
|
||||||
|
device_initialize(&pdev->dev);
|
||||||
|
return platform_device_add(pdev);
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(platform_device_register);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* platform_device_unregister - unregister a platform-level device
|
||||||
|
* @pdev: platform device we're unregistering
|
||||||
|
*
|
||||||
|
* Unregistration is done in 2 steps. Fisrt we release all resources
|
||||||
|
* and remove it from the sybsystem, then we drop reference count by
|
||||||
|
* calling platform_device_put().
|
||||||
|
*/
|
||||||
|
void platform_device_unregister(struct platform_device * pdev)
|
||||||
|
{
|
||||||
|
platform_device_del(pdev);
|
||||||
|
platform_device_put(pdev);
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(platform_device_unregister);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* platform_device_register_simple
|
* platform_device_register_simple
|
||||||
|
@ -355,6 +378,7 @@ error:
|
||||||
platform_device_put(pdev);
|
platform_device_put(pdev);
|
||||||
return ERR_PTR(retval);
|
return ERR_PTR(retval);
|
||||||
}
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(platform_device_register_simple);
|
||||||
|
|
||||||
static int platform_drv_probe(struct device *_dev)
|
static int platform_drv_probe(struct device *_dev)
|
||||||
{
|
{
|
||||||
|
@ -476,6 +500,7 @@ struct bus_type platform_bus_type = {
|
||||||
.suspend = platform_suspend,
|
.suspend = platform_suspend,
|
||||||
.resume = platform_resume,
|
.resume = platform_resume,
|
||||||
};
|
};
|
||||||
|
EXPORT_SYMBOL_GPL(platform_bus_type);
|
||||||
|
|
||||||
int __init platform_bus_init(void)
|
int __init platform_bus_init(void)
|
||||||
{
|
{
|
||||||
|
@ -504,14 +529,3 @@ u64 dma_get_required_mask(struct device *dev)
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(dma_get_required_mask);
|
EXPORT_SYMBOL_GPL(dma_get_required_mask);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
EXPORT_SYMBOL_GPL(platform_bus);
|
|
||||||
EXPORT_SYMBOL_GPL(platform_bus_type);
|
|
||||||
EXPORT_SYMBOL_GPL(platform_add_devices);
|
|
||||||
EXPORT_SYMBOL_GPL(platform_device_register);
|
|
||||||
EXPORT_SYMBOL_GPL(platform_device_register_simple);
|
|
||||||
EXPORT_SYMBOL_GPL(platform_device_unregister);
|
|
||||||
EXPORT_SYMBOL_GPL(platform_get_irq);
|
|
||||||
EXPORT_SYMBOL_GPL(platform_get_resource);
|
|
||||||
EXPORT_SYMBOL_GPL(platform_get_irq_byname);
|
|
||||||
EXPORT_SYMBOL_GPL(platform_get_resource_byname);
|
|
||||||
|
|
|
@ -64,6 +64,7 @@ int dpm_runtime_suspend(struct device * dev, pm_message_t state)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#if 0
|
||||||
/**
|
/**
|
||||||
* dpm_set_power_state - Update power_state field.
|
* dpm_set_power_state - Update power_state field.
|
||||||
* @dev: Device.
|
* @dev: Device.
|
||||||
|
@ -80,3 +81,4 @@ void dpm_set_power_state(struct device * dev, pm_message_t state)
|
||||||
dev->power.power_state = state;
|
dev->power.power_state = state;
|
||||||
up(&dpm_sem);
|
up(&dpm_sem);
|
||||||
}
|
}
|
||||||
|
#endif /* 0 */
|
||||||
|
|
|
@ -3509,6 +3509,7 @@ static int __init ide_cdrom_init(void)
|
||||||
return driver_register(&ide_cdrom_driver.gen_driver);
|
return driver_register(&ide_cdrom_driver.gen_driver);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MODULE_ALIAS("ide:*m-cdrom*");
|
||||||
module_init(ide_cdrom_init);
|
module_init(ide_cdrom_init);
|
||||||
module_exit(ide_cdrom_exit);
|
module_exit(ide_cdrom_exit);
|
||||||
MODULE_LICENSE("GPL");
|
MODULE_LICENSE("GPL");
|
||||||
|
|
|
@ -1271,6 +1271,7 @@ static int __init idedisk_init(void)
|
||||||
return driver_register(&idedisk_driver.gen_driver);
|
return driver_register(&idedisk_driver.gen_driver);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MODULE_ALIAS("ide:*m-disk*");
|
||||||
module_init(idedisk_init);
|
module_init(idedisk_init);
|
||||||
module_exit(idedisk_exit);
|
module_exit(idedisk_exit);
|
||||||
MODULE_LICENSE("GPL");
|
MODULE_LICENSE("GPL");
|
||||||
|
|
|
@ -2197,6 +2197,7 @@ static int __init idefloppy_init(void)
|
||||||
return driver_register(&idefloppy_driver.gen_driver);
|
return driver_register(&idefloppy_driver.gen_driver);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MODULE_ALIAS("ide:*m-floppy*");
|
||||||
module_init(idefloppy_init);
|
module_init(idefloppy_init);
|
||||||
module_exit(idefloppy_exit);
|
module_exit(idefloppy_exit);
|
||||||
MODULE_LICENSE("GPL");
|
MODULE_LICENSE("GPL");
|
||||||
|
|
|
@ -4947,6 +4947,7 @@ out:
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MODULE_ALIAS("ide:*m-tape*");
|
||||||
module_init(idetape_init);
|
module_init(idetape_init);
|
||||||
module_exit(idetape_exit);
|
module_exit(idetape_exit);
|
||||||
MODULE_ALIAS_CHARDEV_MAJOR(IDETAPE_MAJOR);
|
MODULE_ALIAS_CHARDEV_MAJOR(IDETAPE_MAJOR);
|
||||||
|
|
|
@ -1904,9 +1904,69 @@ static int ide_bus_match(struct device *dev, struct device_driver *drv)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static char *media_string(ide_drive_t *drive)
|
||||||
|
{
|
||||||
|
switch (drive->media) {
|
||||||
|
case ide_disk:
|
||||||
|
return "disk";
|
||||||
|
case ide_cdrom:
|
||||||
|
return "cdrom";
|
||||||
|
case ide_tape:
|
||||||
|
return "tape";
|
||||||
|
case ide_floppy:
|
||||||
|
return "floppy";
|
||||||
|
default:
|
||||||
|
return "UNKNOWN";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static ssize_t media_show(struct device *dev, struct device_attribute *attr, char *buf)
|
||||||
|
{
|
||||||
|
ide_drive_t *drive = to_ide_device(dev);
|
||||||
|
return sprintf(buf, "%s\n", media_string(drive));
|
||||||
|
}
|
||||||
|
|
||||||
|
static ssize_t drivename_show(struct device *dev, struct device_attribute *attr, char *buf)
|
||||||
|
{
|
||||||
|
ide_drive_t *drive = to_ide_device(dev);
|
||||||
|
return sprintf(buf, "%s\n", drive->name);
|
||||||
|
}
|
||||||
|
|
||||||
|
static ssize_t modalias_show(struct device *dev, struct device_attribute *attr, char *buf)
|
||||||
|
{
|
||||||
|
ide_drive_t *drive = to_ide_device(dev);
|
||||||
|
return sprintf(buf, "ide:m-%s\n", media_string(drive));
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct device_attribute ide_dev_attrs[] = {
|
||||||
|
__ATTR_RO(media),
|
||||||
|
__ATTR_RO(drivename),
|
||||||
|
__ATTR_RO(modalias),
|
||||||
|
__ATTR_NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
static int ide_uevent(struct device *dev, char **envp, int num_envp,
|
||||||
|
char *buffer, int buffer_size)
|
||||||
|
{
|
||||||
|
ide_drive_t *drive = to_ide_device(dev);
|
||||||
|
int i = 0;
|
||||||
|
int length = 0;
|
||||||
|
|
||||||
|
add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &length,
|
||||||
|
"MEDIA=%s", media_string(drive));
|
||||||
|
add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &length,
|
||||||
|
"DRIVENAME=%s", drive->name);
|
||||||
|
add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &length,
|
||||||
|
"MODALIAS=ide:m-%s", media_string(drive));
|
||||||
|
envp[i] = NULL;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
struct bus_type ide_bus_type = {
|
struct bus_type ide_bus_type = {
|
||||||
.name = "ide",
|
.name = "ide",
|
||||||
.match = ide_bus_match,
|
.match = ide_bus_match,
|
||||||
|
.uevent = ide_uevent,
|
||||||
|
.dev_attrs = ide_dev_attrs,
|
||||||
.suspend = generic_ide_suspend,
|
.suspend = generic_ide_suspend,
|
||||||
.resume = generic_ide_resume,
|
.resume = generic_ide_resume,
|
||||||
};
|
};
|
||||||
|
|
|
@ -121,8 +121,8 @@ struct host_info {
|
||||||
};
|
};
|
||||||
|
|
||||||
static int nodemgr_bus_match(struct device * dev, struct device_driver * drv);
|
static int nodemgr_bus_match(struct device * dev, struct device_driver * drv);
|
||||||
static int nodemgr_hotplug(struct class_device *cdev, char **envp, int num_envp,
|
static int nodemgr_uevent(struct class_device *cdev, char **envp, int num_envp,
|
||||||
char *buffer, int buffer_size);
|
char *buffer, int buffer_size);
|
||||||
static void nodemgr_resume_ne(struct node_entry *ne);
|
static void nodemgr_resume_ne(struct node_entry *ne);
|
||||||
static void nodemgr_remove_ne(struct node_entry *ne);
|
static void nodemgr_remove_ne(struct node_entry *ne);
|
||||||
static struct node_entry *find_entry_by_guid(u64 guid);
|
static struct node_entry *find_entry_by_guid(u64 guid);
|
||||||
|
@ -162,7 +162,7 @@ static void ud_cls_release(struct class_device *class_dev)
|
||||||
static struct class nodemgr_ud_class = {
|
static struct class nodemgr_ud_class = {
|
||||||
.name = "ieee1394",
|
.name = "ieee1394",
|
||||||
.release = ud_cls_release,
|
.release = ud_cls_release,
|
||||||
.hotplug = nodemgr_hotplug,
|
.uevent = nodemgr_uevent,
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct hpsb_highlevel nodemgr_highlevel;
|
static struct hpsb_highlevel nodemgr_highlevel;
|
||||||
|
@ -966,7 +966,7 @@ static struct unit_directory *nodemgr_process_unit_directory
|
||||||
if (ud_child == NULL)
|
if (ud_child == NULL)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* inherit unspecified values so hotplug picks it up */
|
/* inherit unspecified values, the driver core picks it up */
|
||||||
if ((ud->flags & UNIT_DIRECTORY_MODEL_ID) &&
|
if ((ud->flags & UNIT_DIRECTORY_MODEL_ID) &&
|
||||||
!(ud_child->flags & UNIT_DIRECTORY_MODEL_ID))
|
!(ud_child->flags & UNIT_DIRECTORY_MODEL_ID))
|
||||||
{
|
{
|
||||||
|
@ -1062,8 +1062,8 @@ static void nodemgr_process_root_directory(struct host_info *hi, struct node_ent
|
||||||
|
|
||||||
#ifdef CONFIG_HOTPLUG
|
#ifdef CONFIG_HOTPLUG
|
||||||
|
|
||||||
static int nodemgr_hotplug(struct class_device *cdev, char **envp, int num_envp,
|
static int nodemgr_uevent(struct class_device *cdev, char **envp, int num_envp,
|
||||||
char *buffer, int buffer_size)
|
char *buffer, int buffer_size)
|
||||||
{
|
{
|
||||||
struct unit_directory *ud;
|
struct unit_directory *ud;
|
||||||
int i = 0;
|
int i = 0;
|
||||||
|
@ -1112,8 +1112,8 @@ do { \
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
static int nodemgr_hotplug(struct class_device *cdev, char **envp, int num_envp,
|
static int nodemgr_uevent(struct class_device *cdev, char **envp, int num_envp,
|
||||||
char *buffer, int buffer_size)
|
char *buffer, int buffer_size)
|
||||||
{
|
{
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
}
|
}
|
||||||
|
@ -1618,8 +1618,8 @@ static int nodemgr_host_thread(void *__hi)
|
||||||
|
|
||||||
/* Scan our nodes to get the bus options and create node
|
/* Scan our nodes to get the bus options and create node
|
||||||
* entries. This does not do the sysfs stuff, since that
|
* entries. This does not do the sysfs stuff, since that
|
||||||
* would trigger hotplug callbacks and such, which is a
|
* would trigger uevents and such, which is a bad idea at
|
||||||
* bad idea at this point. */
|
* this point. */
|
||||||
nodemgr_node_scan(hi, generation);
|
nodemgr_node_scan(hi, generation);
|
||||||
|
|
||||||
/* This actually does the full probe, with sysfs
|
/* This actually does the full probe, with sysfs
|
||||||
|
|
|
@ -434,24 +434,24 @@ static void ib_device_release(struct class_device *cdev)
|
||||||
kfree(dev);
|
kfree(dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ib_device_hotplug(struct class_device *cdev, char **envp,
|
static int ib_device_uevent(struct class_device *cdev, char **envp,
|
||||||
int num_envp, char *buf, int size)
|
int num_envp, char *buf, int size)
|
||||||
{
|
{
|
||||||
struct ib_device *dev = container_of(cdev, struct ib_device, class_dev);
|
struct ib_device *dev = container_of(cdev, struct ib_device, class_dev);
|
||||||
int i = 0, len = 0;
|
int i = 0, len = 0;
|
||||||
|
|
||||||
if (add_hotplug_env_var(envp, num_envp, &i, buf, size, &len,
|
if (add_uevent_var(envp, num_envp, &i, buf, size, &len,
|
||||||
"NAME=%s", dev->name))
|
"NAME=%s", dev->name))
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* It might be nice to pass the node GUID to hotplug, but
|
* It might be nice to pass the node GUID with the event, but
|
||||||
* right now the only way to get it is to query the device
|
* right now the only way to get it is to query the device
|
||||||
* provider, and this can crash during device removal because
|
* provider, and this can crash during device removal because
|
||||||
* we are will be running after driver removal has started.
|
* we are will be running after driver removal has started.
|
||||||
* We could add a node_guid field to struct ib_device, or we
|
* We could add a node_guid field to struct ib_device, or we
|
||||||
* could just let the hotplug script read the node GUID from
|
* could just let userspace read the node GUID from sysfs when
|
||||||
* sysfs when devices are added.
|
* devices are added.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
envp[i] = NULL;
|
envp[i] = NULL;
|
||||||
|
@ -653,7 +653,7 @@ static struct class_device_attribute *ib_class_attributes[] = {
|
||||||
static struct class ib_class = {
|
static struct class ib_class = {
|
||||||
.name = "infiniband",
|
.name = "infiniband",
|
||||||
.release = ib_device_release,
|
.release = ib_device_release,
|
||||||
.hotplug = ib_device_hotplug,
|
.uevent = ib_device_uevent,
|
||||||
};
|
};
|
||||||
|
|
||||||
int ib_device_register_sysfs(struct ib_device *device)
|
int ib_device_register_sysfs(struct ib_device *device)
|
||||||
|
|
|
@ -18,7 +18,6 @@
|
||||||
#include <linux/random.h>
|
#include <linux/random.h>
|
||||||
#include <linux/major.h>
|
#include <linux/major.h>
|
||||||
#include <linux/proc_fs.h>
|
#include <linux/proc_fs.h>
|
||||||
#include <linux/kobject_uevent.h>
|
|
||||||
#include <linux/interrupt.h>
|
#include <linux/interrupt.h>
|
||||||
#include <linux/poll.h>
|
#include <linux/poll.h>
|
||||||
#include <linux/device.h>
|
#include <linux/device.h>
|
||||||
|
@ -529,10 +528,49 @@ INPUT_DEV_STRING_ATTR_SHOW(name);
|
||||||
INPUT_DEV_STRING_ATTR_SHOW(phys);
|
INPUT_DEV_STRING_ATTR_SHOW(phys);
|
||||||
INPUT_DEV_STRING_ATTR_SHOW(uniq);
|
INPUT_DEV_STRING_ATTR_SHOW(uniq);
|
||||||
|
|
||||||
|
static int print_modalias_bits(char *buf, char prefix, unsigned long *arr,
|
||||||
|
unsigned int min, unsigned int max)
|
||||||
|
{
|
||||||
|
int len, i;
|
||||||
|
|
||||||
|
len = sprintf(buf, "%c", prefix);
|
||||||
|
for (i = min; i < max; i++)
|
||||||
|
if (arr[LONG(i)] & BIT(i))
|
||||||
|
len += sprintf(buf+len, "%X,", i);
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ssize_t input_dev_show_modalias(struct class_device *dev, char *buf)
|
||||||
|
{
|
||||||
|
struct input_dev *id = to_input_dev(dev);
|
||||||
|
ssize_t len = 0;
|
||||||
|
|
||||||
|
len += sprintf(buf+len, "input:b%04Xv%04Xp%04Xe%04X-",
|
||||||
|
id->id.bustype,
|
||||||
|
id->id.vendor,
|
||||||
|
id->id.product,
|
||||||
|
id->id.version);
|
||||||
|
|
||||||
|
len += print_modalias_bits(buf+len, 'e', id->evbit, 0, EV_MAX);
|
||||||
|
len += print_modalias_bits(buf+len, 'k', id->keybit,
|
||||||
|
KEY_MIN_INTERESTING, KEY_MAX);
|
||||||
|
len += print_modalias_bits(buf+len, 'r', id->relbit, 0, REL_MAX);
|
||||||
|
len += print_modalias_bits(buf+len, 'a', id->absbit, 0, ABS_MAX);
|
||||||
|
len += print_modalias_bits(buf+len, 'm', id->mscbit, 0, MSC_MAX);
|
||||||
|
len += print_modalias_bits(buf+len, 'l', id->ledbit, 0, LED_MAX);
|
||||||
|
len += print_modalias_bits(buf+len, 's', id->sndbit, 0, SND_MAX);
|
||||||
|
len += print_modalias_bits(buf+len, 'f', id->ffbit, 0, FF_MAX);
|
||||||
|
len += print_modalias_bits(buf+len, 'w', id->swbit, 0, SW_MAX);
|
||||||
|
len += sprintf(buf+len, "\n");
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
static CLASS_DEVICE_ATTR(modalias, S_IRUGO, input_dev_show_modalias, NULL);
|
||||||
|
|
||||||
static struct attribute *input_dev_attrs[] = {
|
static struct attribute *input_dev_attrs[] = {
|
||||||
&class_device_attr_name.attr,
|
&class_device_attr_name.attr,
|
||||||
&class_device_attr_phys.attr,
|
&class_device_attr_phys.attr,
|
||||||
&class_device_attr_uniq.attr,
|
&class_device_attr_uniq.attr,
|
||||||
|
&class_device_attr_modalias.attr,
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -611,10 +649,10 @@ static void input_dev_release(struct class_device *class_dev)
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Input hotplugging interface - loading event handlers based on
|
* Input uevent interface - loading event handlers based on
|
||||||
* device bitfields.
|
* device bitfields.
|
||||||
*/
|
*/
|
||||||
static int input_add_hotplug_bm_var(char **envp, int num_envp, int *cur_index,
|
static int input_add_uevent_bm_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,
|
||||||
const char *name, unsigned long *bitmap, int max)
|
const char *name, unsigned long *bitmap, int max)
|
||||||
{
|
{
|
||||||
|
@ -639,7 +677,7 @@ static int input_add_hotplug_bm_var(char **envp, int num_envp, int *cur_index,
|
||||||
|
|
||||||
#define INPUT_ADD_HOTPLUG_VAR(fmt, val...) \
|
#define INPUT_ADD_HOTPLUG_VAR(fmt, val...) \
|
||||||
do { \
|
do { \
|
||||||
int err = add_hotplug_env_var(envp, num_envp, &i, \
|
int err = add_uevent_var(envp, num_envp, &i, \
|
||||||
buffer, buffer_size, &len, \
|
buffer, buffer_size, &len, \
|
||||||
fmt, val); \
|
fmt, val); \
|
||||||
if (err) \
|
if (err) \
|
||||||
|
@ -648,15 +686,15 @@ static int input_add_hotplug_bm_var(char **envp, int num_envp, int *cur_index,
|
||||||
|
|
||||||
#define INPUT_ADD_HOTPLUG_BM_VAR(name, bm, max) \
|
#define INPUT_ADD_HOTPLUG_BM_VAR(name, bm, max) \
|
||||||
do { \
|
do { \
|
||||||
int err = input_add_hotplug_bm_var(envp, num_envp, &i, \
|
int err = input_add_uevent_bm_var(envp, num_envp, &i, \
|
||||||
buffer, buffer_size, &len, \
|
buffer, buffer_size, &len, \
|
||||||
name, bm, max); \
|
name, bm, max); \
|
||||||
if (err) \
|
if (err) \
|
||||||
return err; \
|
return err; \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
static int input_dev_hotplug(struct class_device *cdev, char **envp,
|
static int input_dev_uevent(struct class_device *cdev, char **envp,
|
||||||
int num_envp, char *buffer, int buffer_size)
|
int num_envp, char *buffer, int buffer_size)
|
||||||
{
|
{
|
||||||
struct input_dev *dev = to_input_dev(cdev);
|
struct input_dev *dev = to_input_dev(cdev);
|
||||||
int i = 0;
|
int i = 0;
|
||||||
|
@ -698,7 +736,7 @@ static int input_dev_hotplug(struct class_device *cdev, char **envp,
|
||||||
struct class input_class = {
|
struct class input_class = {
|
||||||
.name = "input",
|
.name = "input",
|
||||||
.release = input_dev_release,
|
.release = input_dev_release,
|
||||||
.hotplug = input_dev_hotplug,
|
.uevent = input_dev_uevent,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct input_dev *input_allocate_device(void)
|
struct input_dev *input_allocate_device(void)
|
||||||
|
|
|
@ -800,16 +800,16 @@ static int serio_bus_match(struct device *dev, struct device_driver *drv)
|
||||||
|
|
||||||
#ifdef CONFIG_HOTPLUG
|
#ifdef CONFIG_HOTPLUG
|
||||||
|
|
||||||
#define SERIO_ADD_HOTPLUG_VAR(fmt, val...) \
|
#define SERIO_ADD_UEVENT_VAR(fmt, val...) \
|
||||||
do { \
|
do { \
|
||||||
int err = add_hotplug_env_var(envp, num_envp, &i, \
|
int err = add_uevent_var(envp, num_envp, &i, \
|
||||||
buffer, buffer_size, &len, \
|
buffer, buffer_size, &len, \
|
||||||
fmt, val); \
|
fmt, val); \
|
||||||
if (err) \
|
if (err) \
|
||||||
return err; \
|
return err; \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
static int serio_hotplug(struct device *dev, char **envp, int num_envp, char *buffer, int buffer_size)
|
static int serio_uevent(struct device *dev, char **envp, int num_envp, char *buffer, int buffer_size)
|
||||||
{
|
{
|
||||||
struct serio *serio;
|
struct serio *serio;
|
||||||
int i = 0;
|
int i = 0;
|
||||||
|
@ -820,21 +820,21 @@ static int serio_hotplug(struct device *dev, char **envp, int num_envp, char *bu
|
||||||
|
|
||||||
serio = to_serio_port(dev);
|
serio = to_serio_port(dev);
|
||||||
|
|
||||||
SERIO_ADD_HOTPLUG_VAR("SERIO_TYPE=%02x", serio->id.type);
|
SERIO_ADD_UEVENT_VAR("SERIO_TYPE=%02x", serio->id.type);
|
||||||
SERIO_ADD_HOTPLUG_VAR("SERIO_PROTO=%02x", serio->id.proto);
|
SERIO_ADD_UEVENT_VAR("SERIO_PROTO=%02x", serio->id.proto);
|
||||||
SERIO_ADD_HOTPLUG_VAR("SERIO_ID=%02x", serio->id.id);
|
SERIO_ADD_UEVENT_VAR("SERIO_ID=%02x", serio->id.id);
|
||||||
SERIO_ADD_HOTPLUG_VAR("SERIO_EXTRA=%02x", serio->id.extra);
|
SERIO_ADD_UEVENT_VAR("SERIO_EXTRA=%02x", serio->id.extra);
|
||||||
SERIO_ADD_HOTPLUG_VAR("MODALIAS=serio:ty%02Xpr%02Xid%02Xex%02X",
|
SERIO_ADD_UEVENT_VAR("MODALIAS=serio:ty%02Xpr%02Xid%02Xex%02X",
|
||||||
serio->id.type, serio->id.proto, serio->id.id, serio->id.extra);
|
serio->id.type, serio->id.proto, serio->id.id, serio->id.extra);
|
||||||
envp[i] = NULL;
|
envp[i] = NULL;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
#undef SERIO_ADD_HOTPLUG_VAR
|
#undef SERIO_ADD_UEVENT_VAR
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
static int serio_hotplug(struct device *dev, char **envp, int num_envp, char *buffer, int buffer_size)
|
static int serio_uevent(struct device *dev, char **envp, int num_envp, char *buffer, int buffer_size)
|
||||||
{
|
{
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
}
|
}
|
||||||
|
@ -908,7 +908,7 @@ static int __init serio_init(void)
|
||||||
serio_bus.dev_attrs = serio_device_attrs;
|
serio_bus.dev_attrs = serio_device_attrs;
|
||||||
serio_bus.drv_attrs = serio_driver_attrs;
|
serio_bus.drv_attrs = serio_driver_attrs;
|
||||||
serio_bus.match = serio_bus_match;
|
serio_bus.match = serio_bus_match;
|
||||||
serio_bus.hotplug = serio_hotplug;
|
serio_bus.uevent = serio_uevent;
|
||||||
serio_bus.resume = serio_resume;
|
serio_bus.resume = serio_resume;
|
||||||
bus_register(&serio_bus);
|
bus_register(&serio_bus);
|
||||||
|
|
||||||
|
|
|
@ -128,7 +128,7 @@ static int macio_device_resume(struct device * dev)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int macio_hotplug (struct device *dev, char **envp, int num_envp,
|
static int macio_uevent(struct device *dev, char **envp, int num_envp,
|
||||||
char *buffer, int buffer_size)
|
char *buffer, int buffer_size)
|
||||||
{
|
{
|
||||||
struct macio_dev * macio_dev;
|
struct macio_dev * macio_dev;
|
||||||
|
@ -203,7 +203,7 @@ extern struct device_attribute macio_dev_attrs[];
|
||||||
struct bus_type macio_bus_type = {
|
struct bus_type macio_bus_type = {
|
||||||
.name = "macio",
|
.name = "macio",
|
||||||
.match = macio_bus_match,
|
.match = macio_bus_match,
|
||||||
.hotplug = macio_hotplug,
|
.uevent = macio_uevent,
|
||||||
.suspend = macio_device_suspend,
|
.suspend = macio_device_suspend,
|
||||||
.resume = macio_device_resume,
|
.resume = macio_device_resume,
|
||||||
.dev_attrs = macio_dev_attrs,
|
.dev_attrs = macio_dev_attrs,
|
||||||
|
|
|
@ -80,7 +80,7 @@ static int mmc_bus_match(struct device *dev, struct device_driver *drv)
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
mmc_bus_hotplug(struct device *dev, char **envp, int num_envp, char *buf,
|
mmc_bus_uevent(struct device *dev, char **envp, int num_envp, char *buf,
|
||||||
int buf_size)
|
int buf_size)
|
||||||
{
|
{
|
||||||
struct mmc_card *card = dev_to_mmc_card(dev);
|
struct mmc_card *card = dev_to_mmc_card(dev);
|
||||||
|
@ -140,7 +140,7 @@ static struct bus_type mmc_bus_type = {
|
||||||
.name = "mmc",
|
.name = "mmc",
|
||||||
.dev_attrs = mmc_dev_attrs,
|
.dev_attrs = mmc_dev_attrs,
|
||||||
.match = mmc_bus_match,
|
.match = mmc_bus_match,
|
||||||
.hotplug = mmc_bus_hotplug,
|
.uevent = mmc_bus_uevent,
|
||||||
.suspend = mmc_bus_suspend,
|
.suspend = mmc_bus_suspend,
|
||||||
.resume = mmc_bus_resume,
|
.resume = mmc_bus_resume,
|
||||||
};
|
};
|
||||||
|
|
|
@ -3,8 +3,8 @@
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include "pci.h"
|
#include "pci.h"
|
||||||
|
|
||||||
int pci_hotplug (struct device *dev, char **envp, int num_envp,
|
int pci_uevent(struct device *dev, char **envp, int num_envp,
|
||||||
char *buffer, int buffer_size)
|
char *buffer, int buffer_size)
|
||||||
{
|
{
|
||||||
struct pci_dev *pdev;
|
struct pci_dev *pdev;
|
||||||
int i = 0;
|
int i = 0;
|
||||||
|
@ -17,34 +17,34 @@ int pci_hotplug (struct device *dev, char **envp, int num_envp,
|
||||||
if (!pdev)
|
if (!pdev)
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
|
||||||
if (add_hotplug_env_var(envp, num_envp, &i,
|
if (add_uevent_var(envp, num_envp, &i,
|
||||||
buffer, buffer_size, &length,
|
buffer, buffer_size, &length,
|
||||||
"PCI_CLASS=%04X", pdev->class))
|
"PCI_CLASS=%04X", pdev->class))
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
if (add_hotplug_env_var(envp, num_envp, &i,
|
if (add_uevent_var(envp, num_envp, &i,
|
||||||
buffer, buffer_size, &length,
|
buffer, buffer_size, &length,
|
||||||
"PCI_ID=%04X:%04X", pdev->vendor, pdev->device))
|
"PCI_ID=%04X:%04X", pdev->vendor, pdev->device))
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
if (add_hotplug_env_var(envp, num_envp, &i,
|
if (add_uevent_var(envp, num_envp, &i,
|
||||||
buffer, buffer_size, &length,
|
buffer, buffer_size, &length,
|
||||||
"PCI_SUBSYS_ID=%04X:%04X", pdev->subsystem_vendor,
|
"PCI_SUBSYS_ID=%04X:%04X", pdev->subsystem_vendor,
|
||||||
pdev->subsystem_device))
|
pdev->subsystem_device))
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
if (add_hotplug_env_var(envp, num_envp, &i,
|
if (add_uevent_var(envp, num_envp, &i,
|
||||||
buffer, buffer_size, &length,
|
buffer, buffer_size, &length,
|
||||||
"PCI_SLOT_NAME=%s", pci_name(pdev)))
|
"PCI_SLOT_NAME=%s", pci_name(pdev)))
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
if (add_hotplug_env_var(envp, num_envp, &i,
|
if (add_uevent_var(envp, num_envp, &i,
|
||||||
buffer, buffer_size, &length,
|
buffer, buffer_size, &length,
|
||||||
"MODALIAS=pci:v%08Xd%08Xsv%08Xsd%08Xbc%02Xsc%02Xi%02x",
|
"MODALIAS=pci:v%08Xd%08Xsv%08Xsd%08Xbc%02Xsc%02Xi%02x",
|
||||||
pdev->vendor, pdev->device,
|
pdev->vendor, pdev->device,
|
||||||
pdev->subsystem_vendor, pdev->subsystem_device,
|
pdev->subsystem_vendor, pdev->subsystem_device,
|
||||||
(u8)(pdev->class >> 16), (u8)(pdev->class >> 8),
|
(u8)(pdev->class >> 16), (u8)(pdev->class >> 8),
|
||||||
(u8)(pdev->class)))
|
(u8)(pdev->class)))
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
envp[i] = NULL;
|
envp[i] = NULL;
|
||||||
|
|
|
@ -502,8 +502,8 @@ void pci_dev_put(struct pci_dev *dev)
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef CONFIG_HOTPLUG
|
#ifndef CONFIG_HOTPLUG
|
||||||
int pci_hotplug (struct device *dev, char **envp, int num_envp,
|
int pci_uevent(struct device *dev, char **envp, int num_envp,
|
||||||
char *buffer, int buffer_size)
|
char *buffer, int buffer_size)
|
||||||
{
|
{
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
}
|
}
|
||||||
|
@ -512,7 +512,7 @@ int pci_hotplug (struct device *dev, char **envp, int num_envp,
|
||||||
struct bus_type pci_bus_type = {
|
struct bus_type pci_bus_type = {
|
||||||
.name = "pci",
|
.name = "pci",
|
||||||
.match = pci_bus_match,
|
.match = pci_bus_match,
|
||||||
.hotplug = pci_hotplug,
|
.uevent = pci_uevent,
|
||||||
.suspend = pci_device_suspend,
|
.suspend = pci_device_suspend,
|
||||||
.resume = pci_device_resume,
|
.resume = pci_device_resume,
|
||||||
.dev_attrs = pci_dev_attrs,
|
.dev_attrs = pci_dev_attrs,
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/* Functions internal to the PCI core code */
|
/* Functions internal to the PCI core code */
|
||||||
|
|
||||||
extern int pci_hotplug (struct device *dev, char **envp, int num_envp,
|
extern int pci_uevent(struct device *dev, char **envp, int num_envp,
|
||||||
char *buffer, int buffer_size);
|
char *buffer, int buffer_size);
|
||||||
extern int pci_create_sysfs_dev_files(struct pci_dev *pdev);
|
extern int pci_create_sysfs_dev_files(struct pci_dev *pdev);
|
||||||
extern void pci_remove_sysfs_dev_files(struct pci_dev *pdev);
|
extern void pci_remove_sysfs_dev_files(struct pci_dev *pdev);
|
||||||
extern void pci_cleanup_rom(struct pci_dev *dev);
|
extern void pci_cleanup_rom(struct pci_dev *dev);
|
||||||
|
|
|
@ -901,14 +901,14 @@ int pcmcia_insert_card(struct pcmcia_socket *skt)
|
||||||
EXPORT_SYMBOL(pcmcia_insert_card);
|
EXPORT_SYMBOL(pcmcia_insert_card);
|
||||||
|
|
||||||
|
|
||||||
static int pcmcia_socket_hotplug(struct class_device *dev, char **envp,
|
static int pcmcia_socket_uevent(struct class_device *dev, char **envp,
|
||||||
int num_envp, char *buffer, int buffer_size)
|
int num_envp, char *buffer, int buffer_size)
|
||||||
{
|
{
|
||||||
struct pcmcia_socket *s = container_of(dev, struct pcmcia_socket, dev);
|
struct pcmcia_socket *s = container_of(dev, struct pcmcia_socket, dev);
|
||||||
int i = 0, length = 0;
|
int i = 0, length = 0;
|
||||||
|
|
||||||
if (add_hotplug_env_var(envp, num_envp, &i, buffer, buffer_size,
|
if (add_uevent_var(envp, num_envp, &i, buffer, buffer_size,
|
||||||
&length, "SOCKET_NO=%u", s->sock))
|
&length, "SOCKET_NO=%u", s->sock))
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
envp[i] = NULL;
|
envp[i] = NULL;
|
||||||
|
@ -927,7 +927,7 @@ static void pcmcia_release_socket_class(struct class *data)
|
||||||
|
|
||||||
struct class pcmcia_socket_class = {
|
struct class pcmcia_socket_class = {
|
||||||
.name = "pcmcia_socket",
|
.name = "pcmcia_socket",
|
||||||
.hotplug = pcmcia_socket_hotplug,
|
.uevent = pcmcia_socket_uevent,
|
||||||
.release = pcmcia_release_socket,
|
.release = pcmcia_release_socket,
|
||||||
.class_release = pcmcia_release_socket_class,
|
.class_release = pcmcia_release_socket_class,
|
||||||
};
|
};
|
||||||
|
|
|
@ -779,8 +779,8 @@ static int pcmcia_bus_match(struct device * dev, struct device_driver * drv) {
|
||||||
|
|
||||||
#ifdef CONFIG_HOTPLUG
|
#ifdef CONFIG_HOTPLUG
|
||||||
|
|
||||||
static int pcmcia_bus_hotplug(struct device *dev, char **envp, int num_envp,
|
static int pcmcia_bus_uevent(struct device *dev, char **envp, int num_envp,
|
||||||
char *buffer, int buffer_size)
|
char *buffer, int buffer_size)
|
||||||
{
|
{
|
||||||
struct pcmcia_device *p_dev;
|
struct pcmcia_device *p_dev;
|
||||||
int i, length = 0;
|
int i, length = 0;
|
||||||
|
@ -800,31 +800,31 @@ static int pcmcia_bus_hotplug(struct device *dev, char **envp, int num_envp,
|
||||||
|
|
||||||
i = 0;
|
i = 0;
|
||||||
|
|
||||||
if (add_hotplug_env_var(envp, num_envp, &i,
|
if (add_uevent_var(envp, num_envp, &i,
|
||||||
buffer, buffer_size, &length,
|
buffer, buffer_size, &length,
|
||||||
"SOCKET_NO=%u",
|
"SOCKET_NO=%u",
|
||||||
p_dev->socket->sock))
|
p_dev->socket->sock))
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
if (add_hotplug_env_var(envp, num_envp, &i,
|
if (add_uevent_var(envp, num_envp, &i,
|
||||||
buffer, buffer_size, &length,
|
buffer, buffer_size, &length,
|
||||||
"DEVICE_NO=%02X",
|
"DEVICE_NO=%02X",
|
||||||
p_dev->device_no))
|
p_dev->device_no))
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
if (add_hotplug_env_var(envp, num_envp, &i,
|
if (add_uevent_var(envp, num_envp, &i,
|
||||||
buffer, buffer_size, &length,
|
buffer, buffer_size, &length,
|
||||||
"MODALIAS=pcmcia:m%04Xc%04Xf%02Xfn%02Xpfn%02X"
|
"MODALIAS=pcmcia:m%04Xc%04Xf%02Xfn%02Xpfn%02X"
|
||||||
"pa%08Xpb%08Xpc%08Xpd%08X",
|
"pa%08Xpb%08Xpc%08Xpd%08X",
|
||||||
p_dev->has_manf_id ? p_dev->manf_id : 0,
|
p_dev->has_manf_id ? p_dev->manf_id : 0,
|
||||||
p_dev->has_card_id ? p_dev->card_id : 0,
|
p_dev->has_card_id ? p_dev->card_id : 0,
|
||||||
p_dev->has_func_id ? p_dev->func_id : 0,
|
p_dev->has_func_id ? p_dev->func_id : 0,
|
||||||
p_dev->func,
|
p_dev->func,
|
||||||
p_dev->device_no,
|
p_dev->device_no,
|
||||||
hash[0],
|
hash[0],
|
||||||
hash[1],
|
hash[1],
|
||||||
hash[2],
|
hash[2],
|
||||||
hash[3]))
|
hash[3]))
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
envp[i] = NULL;
|
envp[i] = NULL;
|
||||||
|
@ -834,7 +834,7 @@ static int pcmcia_bus_hotplug(struct device *dev, char **envp, int num_envp,
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
static int pcmcia_bus_hotplug(struct device *dev, char **envp, int num_envp,
|
static int pcmcia_bus_uevent(struct device *dev, char **envp, int num_envp,
|
||||||
char *buffer, int buffer_size)
|
char *buffer, int buffer_size)
|
||||||
{
|
{
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
@ -1223,7 +1223,7 @@ static struct class_interface pcmcia_bus_interface = {
|
||||||
|
|
||||||
struct bus_type pcmcia_bus_type = {
|
struct bus_type pcmcia_bus_type = {
|
||||||
.name = "pcmcia",
|
.name = "pcmcia",
|
||||||
.hotplug = pcmcia_bus_hotplug,
|
.uevent = pcmcia_bus_uevent,
|
||||||
.match = pcmcia_bus_match,
|
.match = pcmcia_bus_match,
|
||||||
.dev_attrs = pcmcia_dev_attrs,
|
.dev_attrs = pcmcia_dev_attrs,
|
||||||
};
|
};
|
||||||
|
|
|
@ -56,7 +56,6 @@
|
||||||
#include <linux/mm.h>
|
#include <linux/mm.h>
|
||||||
#include <linux/smp.h>
|
#include <linux/smp.h>
|
||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
#include <linux/kobject_uevent.h>
|
|
||||||
#include <linux/completion.h>
|
#include <linux/completion.h>
|
||||||
#include <linux/spinlock.h>
|
#include <linux/spinlock.h>
|
||||||
#include <linux/dmi.h>
|
#include <linux/dmi.h>
|
||||||
|
@ -106,8 +105,6 @@ static int pnp_dock_event(int dock, struct pnp_docking_station_info *info)
|
||||||
char *argv [3], **envp, *buf, *scratch;
|
char *argv [3], **envp, *buf, *scratch;
|
||||||
int i = 0, value;
|
int i = 0, value;
|
||||||
|
|
||||||
if (!hotplug_path [0])
|
|
||||||
return -ENOENT;
|
|
||||||
if (!current->fs->root) {
|
if (!current->fs->root) {
|
||||||
return -EAGAIN;
|
return -EAGAIN;
|
||||||
}
|
}
|
||||||
|
@ -119,8 +116,9 @@ static int pnp_dock_event(int dock, struct pnp_docking_station_info *info)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* only one standardized param to hotplug command: type */
|
/* FIXME: if there are actual users of this, it should be integrated into
|
||||||
argv [0] = hotplug_path;
|
* the driver core and use the usual infrastructure like sysfs and uevents */
|
||||||
|
argv [0] = "/sbin/pnpbios";
|
||||||
argv [1] = "dock";
|
argv [1] = "dock";
|
||||||
argv [2] = NULL;
|
argv [2] = NULL;
|
||||||
|
|
||||||
|
|
|
@ -45,7 +45,7 @@ ccwgroup_bus_match (struct device * dev, struct device_driver * drv)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
static int
|
static int
|
||||||
ccwgroup_hotplug (struct device *dev, char **envp, int num_envp, char *buffer,
|
ccwgroup_uevent (struct device *dev, char **envp, int num_envp, char *buffer,
|
||||||
int buffer_size)
|
int buffer_size)
|
||||||
{
|
{
|
||||||
/* TODO */
|
/* TODO */
|
||||||
|
@ -55,7 +55,7 @@ ccwgroup_hotplug (struct device *dev, char **envp, int num_envp, char *buffer,
|
||||||
static struct bus_type ccwgroup_bus_type = {
|
static struct bus_type ccwgroup_bus_type = {
|
||||||
.name = "ccwgroup",
|
.name = "ccwgroup",
|
||||||
.match = ccwgroup_bus_match,
|
.match = ccwgroup_bus_match,
|
||||||
.hotplug = ccwgroup_hotplug,
|
.uevent = ccwgroup_uevent,
|
||||||
};
|
};
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
|
|
|
@ -59,7 +59,7 @@ ccw_bus_match (struct device * dev, struct device_driver * drv)
|
||||||
* Heavily modeled on pci and usb hotplug.
|
* Heavily modeled on pci and usb hotplug.
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
ccw_hotplug (struct device *dev, char **envp, int num_envp,
|
ccw_uevent (struct device *dev, char **envp, int num_envp,
|
||||||
char *buffer, int buffer_size)
|
char *buffer, int buffer_size)
|
||||||
{
|
{
|
||||||
struct ccw_device *cdev = to_ccwdev(dev);
|
struct ccw_device *cdev = to_ccwdev(dev);
|
||||||
|
@ -110,7 +110,7 @@ ccw_hotplug (struct device *dev, char **envp, int num_envp,
|
||||||
struct bus_type ccw_bus_type = {
|
struct bus_type ccw_bus_type = {
|
||||||
.name = "ccw",
|
.name = "ccw",
|
||||||
.match = &ccw_bus_match,
|
.match = &ccw_bus_match,
|
||||||
.hotplug = &ccw_hotplug,
|
.uevent = &ccw_uevent,
|
||||||
};
|
};
|
||||||
|
|
||||||
static int io_subchannel_probe (struct device *);
|
static int io_subchannel_probe (struct device *);
|
||||||
|
|
|
@ -34,7 +34,6 @@
|
||||||
#include <linux/miscdevice.h>
|
#include <linux/miscdevice.h>
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/moduleparam.h>
|
#include <linux/moduleparam.h>
|
||||||
#include <linux/kobject_uevent.h>
|
|
||||||
#include <linux/proc_fs.h>
|
#include <linux/proc_fs.h>
|
||||||
#include <linux/syscalls.h>
|
#include <linux/syscalls.h>
|
||||||
#include "z90crypt.h"
|
#include "z90crypt.h"
|
||||||
|
|
|
@ -2132,7 +2132,7 @@ restart:
|
||||||
}
|
}
|
||||||
|
|
||||||
spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
|
spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
|
||||||
kobject_uevent(&ioa_cfg->host->shost_classdev.kobj, KOBJ_CHANGE, NULL);
|
kobject_uevent(&ioa_cfg->host->shost_classdev.kobj, KOBJ_CHANGE);
|
||||||
LEAVE;
|
LEAVE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -192,6 +192,7 @@ void usb_driver_release_interface(struct usb_driver *driver,
|
||||||
iface->condition = USB_INTERFACE_UNBOUND;
|
iface->condition = USB_INTERFACE_UNBOUND;
|
||||||
mark_quiesced(iface);
|
mark_quiesced(iface);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct find_interface_arg {
|
struct find_interface_arg {
|
||||||
int minor;
|
int minor;
|
||||||
struct usb_interface *interface;
|
struct usb_interface *interface;
|
||||||
|
@ -236,10 +237,7 @@ struct usb_interface *usb_find_interface(struct usb_driver *drv, int minor)
|
||||||
#ifdef CONFIG_HOTPLUG
|
#ifdef CONFIG_HOTPLUG
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* USB hotplugging invokes what /proc/sys/kernel/hotplug says
|
* This sends an uevent to userspace, typically helping to load driver
|
||||||
* (normally /sbin/hotplug) when USB devices get added or removed.
|
|
||||||
*
|
|
||||||
* This invokes a user mode policy agent, typically helping to load driver
|
|
||||||
* or other modules, configure the device, and more. Drivers can provide
|
* or other modules, configure the device, and more. Drivers can provide
|
||||||
* a MODULE_DEVICE_TABLE to help with module loading subtasks.
|
* a MODULE_DEVICE_TABLE to help with module loading subtasks.
|
||||||
*
|
*
|
||||||
|
@ -248,8 +246,8 @@ struct usb_interface *usb_find_interface(struct usb_driver *drv, int minor)
|
||||||
* delays in event delivery. Use sysfs (and DEVPATH) to make sure the
|
* delays in event delivery. Use sysfs (and DEVPATH) to make sure the
|
||||||
* device (and this configuration!) are still present.
|
* device (and this configuration!) are still present.
|
||||||
*/
|
*/
|
||||||
static int usb_hotplug (struct device *dev, char **envp, int num_envp,
|
static int usb_uevent(struct device *dev, char **envp, int num_envp,
|
||||||
char *buffer, int buffer_size)
|
char *buffer, int buffer_size)
|
||||||
{
|
{
|
||||||
struct usb_interface *intf;
|
struct usb_interface *intf;
|
||||||
struct usb_device *usb_dev;
|
struct usb_device *usb_dev;
|
||||||
|
@ -261,7 +259,7 @@ static int usb_hotplug (struct device *dev, char **envp, int num_envp,
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
|
||||||
/* driver is often null here; dev_dbg() would oops */
|
/* driver is often null here; dev_dbg() would oops */
|
||||||
pr_debug ("usb %s: hotplug\n", dev->bus_id);
|
pr_debug ("usb %s: uevent\n", dev->bus_id);
|
||||||
|
|
||||||
/* Must check driver_data here, as on remove driver is always NULL */
|
/* Must check driver_data here, as on remove driver is always NULL */
|
||||||
if ((dev->driver == &usb_generic_driver) ||
|
if ((dev->driver == &usb_generic_driver) ||
|
||||||
|
@ -288,51 +286,51 @@ static int usb_hotplug (struct device *dev, char **envp, int num_envp,
|
||||||
*
|
*
|
||||||
* FIXME reduce hardwired intelligence here
|
* FIXME reduce hardwired intelligence here
|
||||||
*/
|
*/
|
||||||
if (add_hotplug_env_var(envp, num_envp, &i,
|
if (add_uevent_var(envp, num_envp, &i,
|
||||||
buffer, buffer_size, &length,
|
buffer, buffer_size, &length,
|
||||||
"DEVICE=/proc/bus/usb/%03d/%03d",
|
"DEVICE=/proc/bus/usb/%03d/%03d",
|
||||||
usb_dev->bus->busnum, usb_dev->devnum))
|
usb_dev->bus->busnum, usb_dev->devnum))
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* per-device configurations are common */
|
/* per-device configurations are common */
|
||||||
if (add_hotplug_env_var(envp, num_envp, &i,
|
if (add_uevent_var(envp, num_envp, &i,
|
||||||
buffer, buffer_size, &length,
|
buffer, buffer_size, &length,
|
||||||
"PRODUCT=%x/%x/%x",
|
"PRODUCT=%x/%x/%x",
|
||||||
le16_to_cpu(usb_dev->descriptor.idVendor),
|
le16_to_cpu(usb_dev->descriptor.idVendor),
|
||||||
le16_to_cpu(usb_dev->descriptor.idProduct),
|
le16_to_cpu(usb_dev->descriptor.idProduct),
|
||||||
le16_to_cpu(usb_dev->descriptor.bcdDevice)))
|
le16_to_cpu(usb_dev->descriptor.bcdDevice)))
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
/* class-based driver binding models */
|
/* class-based driver binding models */
|
||||||
if (add_hotplug_env_var(envp, num_envp, &i,
|
if (add_uevent_var(envp, num_envp, &i,
|
||||||
buffer, buffer_size, &length,
|
buffer, buffer_size, &length,
|
||||||
"TYPE=%d/%d/%d",
|
"TYPE=%d/%d/%d",
|
||||||
usb_dev->descriptor.bDeviceClass,
|
usb_dev->descriptor.bDeviceClass,
|
||||||
usb_dev->descriptor.bDeviceSubClass,
|
usb_dev->descriptor.bDeviceSubClass,
|
||||||
usb_dev->descriptor.bDeviceProtocol))
|
usb_dev->descriptor.bDeviceProtocol))
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
if (add_hotplug_env_var(envp, num_envp, &i,
|
if (add_uevent_var(envp, num_envp, &i,
|
||||||
buffer, buffer_size, &length,
|
buffer, buffer_size, &length,
|
||||||
"INTERFACE=%d/%d/%d",
|
"INTERFACE=%d/%d/%d",
|
||||||
alt->desc.bInterfaceClass,
|
alt->desc.bInterfaceClass,
|
||||||
alt->desc.bInterfaceSubClass,
|
alt->desc.bInterfaceSubClass,
|
||||||
alt->desc.bInterfaceProtocol))
|
alt->desc.bInterfaceProtocol))
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
if (add_hotplug_env_var(envp, num_envp, &i,
|
if (add_uevent_var(envp, num_envp, &i,
|
||||||
buffer, buffer_size, &length,
|
buffer, buffer_size, &length,
|
||||||
"MODALIAS=usb:v%04Xp%04Xd%04Xdc%02Xdsc%02Xdp%02Xic%02Xisc%02Xip%02X",
|
"MODALIAS=usb:v%04Xp%04Xd%04Xdc%02Xdsc%02Xdp%02Xic%02Xisc%02Xip%02X",
|
||||||
le16_to_cpu(usb_dev->descriptor.idVendor),
|
le16_to_cpu(usb_dev->descriptor.idVendor),
|
||||||
le16_to_cpu(usb_dev->descriptor.idProduct),
|
le16_to_cpu(usb_dev->descriptor.idProduct),
|
||||||
le16_to_cpu(usb_dev->descriptor.bcdDevice),
|
le16_to_cpu(usb_dev->descriptor.bcdDevice),
|
||||||
usb_dev->descriptor.bDeviceClass,
|
usb_dev->descriptor.bDeviceClass,
|
||||||
usb_dev->descriptor.bDeviceSubClass,
|
usb_dev->descriptor.bDeviceSubClass,
|
||||||
usb_dev->descriptor.bDeviceProtocol,
|
usb_dev->descriptor.bDeviceProtocol,
|
||||||
alt->desc.bInterfaceClass,
|
alt->desc.bInterfaceClass,
|
||||||
alt->desc.bInterfaceSubClass,
|
alt->desc.bInterfaceSubClass,
|
||||||
alt->desc.bInterfaceProtocol))
|
alt->desc.bInterfaceProtocol))
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
envp[i] = NULL;
|
envp[i] = NULL;
|
||||||
|
@ -342,7 +340,7 @@ static int usb_hotplug (struct device *dev, char **envp, int num_envp,
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
static int usb_hotplug (struct device *dev, char **envp,
|
static int usb_uevent(struct device *dev, char **envp,
|
||||||
int num_envp, char *buffer, int buffer_size)
|
int num_envp, char *buffer, int buffer_size)
|
||||||
{
|
{
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
@ -1093,7 +1091,7 @@ static int usb_generic_resume(struct device *dev)
|
||||||
struct bus_type usb_bus_type = {
|
struct bus_type usb_bus_type = {
|
||||||
.name = "usb",
|
.name = "usb",
|
||||||
.match = usb_device_match,
|
.match = usb_device_match,
|
||||||
.hotplug = usb_hotplug,
|
.uevent = usb_uevent,
|
||||||
.suspend = usb_generic_suspend,
|
.suspend = usb_generic_suspend,
|
||||||
.resume = usb_generic_resume,
|
.resume = usb_generic_resume,
|
||||||
};
|
};
|
||||||
|
|
|
@ -4397,7 +4397,7 @@ static int __init etrax_usb_hc_init(void)
|
||||||
device_initialize(&fake_device);
|
device_initialize(&fake_device);
|
||||||
kobject_set_name(&fake_device.kobj, "etrax_usb");
|
kobject_set_name(&fake_device.kobj, "etrax_usb");
|
||||||
kobject_add(&fake_device.kobj);
|
kobject_add(&fake_device.kobj);
|
||||||
kobject_hotplug(&fake_device.kobj, KOBJ_ADD);
|
kobject_uevent(&fake_device.kobj, KOBJ_ADD);
|
||||||
hc->bus->controller = &fake_device;
|
hc->bus->controller = &fake_device;
|
||||||
usb_register_bus(hc->bus);
|
usb_register_bus(hc->bus);
|
||||||
|
|
||||||
|
|
|
@ -142,12 +142,12 @@ static struct bin_attribute w1_slave_attr_bin_id = {
|
||||||
/* Default family */
|
/* Default family */
|
||||||
static struct w1_family w1_default_family;
|
static struct w1_family w1_default_family;
|
||||||
|
|
||||||
static int w1_hotplug(struct device *dev, char **envp, int num_envp, char *buffer, int buffer_size);
|
static int w1_uevent(struct device *dev, char **envp, int num_envp, char *buffer, int buffer_size);
|
||||||
|
|
||||||
static struct bus_type w1_bus_type = {
|
static struct bus_type w1_bus_type = {
|
||||||
.name = "w1",
|
.name = "w1",
|
||||||
.match = w1_master_match,
|
.match = w1_master_match,
|
||||||
.hotplug = w1_hotplug,
|
.uevent = w1_uevent,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct device_driver w1_master_driver = {
|
struct device_driver w1_master_driver = {
|
||||||
|
@ -361,7 +361,7 @@ void w1_destroy_master_attributes(struct w1_master *master)
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_HOTPLUG
|
#ifdef CONFIG_HOTPLUG
|
||||||
static int w1_hotplug(struct device *dev, char **envp, int num_envp, char *buffer, int buffer_size)
|
static int w1_uevent(struct device *dev, char **envp, int num_envp, char *buffer, int buffer_size)
|
||||||
{
|
{
|
||||||
struct w1_master *md = NULL;
|
struct w1_master *md = NULL;
|
||||||
struct w1_slave *sl = NULL;
|
struct w1_slave *sl = NULL;
|
||||||
|
@ -377,7 +377,7 @@ static int w1_hotplug(struct device *dev, char **envp, int num_envp, char *buffe
|
||||||
event_owner = "slave";
|
event_owner = "slave";
|
||||||
name = sl->name;
|
name = sl->name;
|
||||||
} else {
|
} else {
|
||||||
dev_dbg(dev, "Unknown hotplug event.\n");
|
dev_dbg(dev, "Unknown event.\n");
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -386,18 +386,18 @@ static int w1_hotplug(struct device *dev, char **envp, int num_envp, char *buffe
|
||||||
if (dev->driver != &w1_slave_driver || !sl)
|
if (dev->driver != &w1_slave_driver || !sl)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
err = add_hotplug_env_var(envp, num_envp, &cur_index, buffer, buffer_size, &cur_len, "W1_FID=%02X", sl->reg_num.family);
|
err = add_uevent_var(envp, num_envp, &cur_index, buffer, buffer_size, &cur_len, "W1_FID=%02X", sl->reg_num.family);
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
err = add_hotplug_env_var(envp, num_envp, &cur_index, buffer, buffer_size, &cur_len, "W1_SLAVE_ID=%024LX", (u64)sl->reg_num.id);
|
err = add_uevent_var(envp, num_envp, &cur_index, buffer, buffer_size, &cur_len, "W1_SLAVE_ID=%024LX", (u64)sl->reg_num.id);
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
};
|
};
|
||||||
#else
|
#else
|
||||||
static int w1_hotplug(struct device *dev, char **envp, int num_envp, char *buffer, int buffer_size)
|
static int w1_uevent(struct device *dev, char **envp, int num_envp, char *buffer, int buffer_size)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -226,7 +226,7 @@ static struct sysfs_ops part_sysfs_ops = {
|
||||||
static ssize_t part_uevent_store(struct hd_struct * p,
|
static ssize_t part_uevent_store(struct hd_struct * p,
|
||||||
const char *page, size_t count)
|
const char *page, size_t count)
|
||||||
{
|
{
|
||||||
kobject_hotplug(&p->kobj, KOBJ_ADD);
|
kobject_uevent(&p->kobj, KOBJ_ADD);
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
static ssize_t part_dev_read(struct hd_struct * p, char *page)
|
static ssize_t part_dev_read(struct hd_struct * p, char *page)
|
||||||
|
@ -336,12 +336,31 @@ void add_partition(struct gendisk *disk, int part, sector_t start, sector_t len)
|
||||||
disk->part[part-1] = p;
|
disk->part[part-1] = p;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static char *make_block_name(struct gendisk *disk)
|
||||||
|
{
|
||||||
|
char *name;
|
||||||
|
static char *block_str = "block:";
|
||||||
|
int size;
|
||||||
|
|
||||||
|
size = strlen(block_str) + strlen(disk->disk_name) + 1;
|
||||||
|
name = kmalloc(size, GFP_KERNEL);
|
||||||
|
if (!name)
|
||||||
|
return NULL;
|
||||||
|
strcpy(name, block_str);
|
||||||
|
strcat(name, disk->disk_name);
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
static void disk_sysfs_symlinks(struct gendisk *disk)
|
static void disk_sysfs_symlinks(struct gendisk *disk)
|
||||||
{
|
{
|
||||||
struct device *target = get_device(disk->driverfs_dev);
|
struct device *target = get_device(disk->driverfs_dev);
|
||||||
if (target) {
|
if (target) {
|
||||||
|
char *disk_name = make_block_name(disk);
|
||||||
sysfs_create_link(&disk->kobj,&target->kobj,"device");
|
sysfs_create_link(&disk->kobj,&target->kobj,"device");
|
||||||
sysfs_create_link(&target->kobj,&disk->kobj,"block");
|
if (disk_name) {
|
||||||
|
sysfs_create_link(&target->kobj,&disk->kobj,disk_name);
|
||||||
|
kfree(disk_name);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -360,7 +379,7 @@ void register_disk(struct gendisk *disk)
|
||||||
if ((err = kobject_add(&disk->kobj)))
|
if ((err = kobject_add(&disk->kobj)))
|
||||||
return;
|
return;
|
||||||
disk_sysfs_symlinks(disk);
|
disk_sysfs_symlinks(disk);
|
||||||
kobject_hotplug(&disk->kobj, KOBJ_ADD);
|
kobject_uevent(&disk->kobj, KOBJ_ADD);
|
||||||
|
|
||||||
/* No minors to use for partitions */
|
/* No minors to use for partitions */
|
||||||
if (disk->minors == 1) {
|
if (disk->minors == 1) {
|
||||||
|
@ -461,10 +480,14 @@ void del_gendisk(struct gendisk *disk)
|
||||||
devfs_remove_disk(disk);
|
devfs_remove_disk(disk);
|
||||||
|
|
||||||
if (disk->driverfs_dev) {
|
if (disk->driverfs_dev) {
|
||||||
|
char *disk_name = make_block_name(disk);
|
||||||
sysfs_remove_link(&disk->kobj, "device");
|
sysfs_remove_link(&disk->kobj, "device");
|
||||||
sysfs_remove_link(&disk->driverfs_dev->kobj, "block");
|
if (disk_name) {
|
||||||
|
sysfs_remove_link(&disk->driverfs_dev->kobj, disk_name);
|
||||||
|
kfree(disk_name);
|
||||||
|
}
|
||||||
put_device(disk->driverfs_dev);
|
put_device(disk->driverfs_dev);
|
||||||
}
|
}
|
||||||
kobject_hotplug(&disk->kobj, KOBJ_REMOVE);
|
kobject_uevent(&disk->kobj, KOBJ_REMOVE);
|
||||||
kobject_del(&disk->kobj);
|
kobject_del(&disk->kobj);
|
||||||
}
|
}
|
||||||
|
|
15
fs/super.c
15
fs/super.c
|
@ -665,16 +665,6 @@ static int test_bdev_super(struct super_block *s, void *data)
|
||||||
return (void *)s->s_bdev == data;
|
return (void *)s->s_bdev == data;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void bdev_uevent(struct block_device *bdev, enum kobject_action action)
|
|
||||||
{
|
|
||||||
if (bdev->bd_disk) {
|
|
||||||
if (bdev->bd_part)
|
|
||||||
kobject_uevent(&bdev->bd_part->kobj, action, NULL);
|
|
||||||
else
|
|
||||||
kobject_uevent(&bdev->bd_disk->kobj, action, NULL);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct super_block *get_sb_bdev(struct file_system_type *fs_type,
|
struct super_block *get_sb_bdev(struct file_system_type *fs_type,
|
||||||
int flags, const char *dev_name, void *data,
|
int flags, const char *dev_name, void *data,
|
||||||
int (*fill_super)(struct super_block *, void *, int))
|
int (*fill_super)(struct super_block *, void *, int))
|
||||||
|
@ -717,10 +707,8 @@ struct super_block *get_sb_bdev(struct file_system_type *fs_type,
|
||||||
up_write(&s->s_umount);
|
up_write(&s->s_umount);
|
||||||
deactivate_super(s);
|
deactivate_super(s);
|
||||||
s = ERR_PTR(error);
|
s = ERR_PTR(error);
|
||||||
} else {
|
} else
|
||||||
s->s_flags |= MS_ACTIVE;
|
s->s_flags |= MS_ACTIVE;
|
||||||
bdev_uevent(bdev, KOBJ_MOUNT);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return s;
|
return s;
|
||||||
|
@ -736,7 +724,6 @@ void kill_block_super(struct super_block *sb)
|
||||||
{
|
{
|
||||||
struct block_device *bdev = sb->s_bdev;
|
struct block_device *bdev = sb->s_bdev;
|
||||||
|
|
||||||
bdev_uevent(bdev, KOBJ_UMOUNT);
|
|
||||||
generic_shutdown_super(sb);
|
generic_shutdown_super(sb);
|
||||||
sync_blockdev(bdev);
|
sync_blockdev(bdev);
|
||||||
close_bdev_excl(bdev);
|
close_bdev_excl(bdev);
|
||||||
|
|
|
@ -112,7 +112,11 @@ static int create_dir(struct kobject * k, struct dentry * p,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (error && (error != -EEXIST)) {
|
if (error && (error != -EEXIST)) {
|
||||||
sysfs_put((*d)->d_fsdata);
|
struct sysfs_dirent *sd = (*d)->d_fsdata;
|
||||||
|
if (sd) {
|
||||||
|
list_del_init(&sd->s_sibling);
|
||||||
|
sysfs_put(sd);
|
||||||
|
}
|
||||||
d_drop(*d);
|
d_drop(*d);
|
||||||
}
|
}
|
||||||
dput(*d);
|
dput(*d);
|
||||||
|
|
|
@ -47,8 +47,8 @@ struct bus_type {
|
||||||
struct driver_attribute * drv_attrs;
|
struct driver_attribute * drv_attrs;
|
||||||
|
|
||||||
int (*match)(struct device * dev, struct device_driver * drv);
|
int (*match)(struct device * dev, struct device_driver * drv);
|
||||||
int (*hotplug) (struct device *dev, char **envp,
|
int (*uevent)(struct device *dev, char **envp,
|
||||||
int num_envp, char *buffer, int buffer_size);
|
int num_envp, char *buffer, int buffer_size);
|
||||||
int (*suspend)(struct device * dev, pm_message_t state);
|
int (*suspend)(struct device * dev, pm_message_t state);
|
||||||
int (*resume)(struct device * dev);
|
int (*resume)(struct device * dev);
|
||||||
};
|
};
|
||||||
|
@ -151,7 +151,7 @@ struct class {
|
||||||
struct class_attribute * class_attrs;
|
struct class_attribute * class_attrs;
|
||||||
struct class_device_attribute * class_dev_attrs;
|
struct class_device_attribute * class_dev_attrs;
|
||||||
|
|
||||||
int (*hotplug)(struct class_device *dev, char **envp,
|
int (*uevent)(struct class_device *dev, char **envp,
|
||||||
int num_envp, char *buffer, int buffer_size);
|
int num_envp, char *buffer, int buffer_size);
|
||||||
|
|
||||||
void (*release)(struct class_device *dev);
|
void (*release)(struct class_device *dev);
|
||||||
|
@ -209,9 +209,9 @@ extern int class_device_create_file(struct class_device *,
|
||||||
* set, this will be called instead of the class specific release function.
|
* set, this will be called instead of the class specific release function.
|
||||||
* Only use this if you want to override the default release function, like
|
* Only use this if you want to override the default release function, like
|
||||||
* when you are nesting class_device structures.
|
* when you are nesting class_device structures.
|
||||||
* @hotplug: pointer to a hotplug function for this struct class_device. If
|
* @uevent: pointer to a uevent function for this struct class_device. If
|
||||||
* set, this will be called instead of the class specific hotplug function.
|
* set, this will be called instead of the class specific uevent function.
|
||||||
* Only use this if you want to override the default hotplug function, like
|
* Only use this if you want to override the default uevent function, like
|
||||||
* when you are nesting class_device structures.
|
* when you are nesting class_device structures.
|
||||||
*/
|
*/
|
||||||
struct class_device {
|
struct class_device {
|
||||||
|
@ -227,7 +227,7 @@ struct class_device {
|
||||||
struct class_device *parent; /* parent of this child device, if there is one */
|
struct class_device *parent; /* parent of this child device, if there is one */
|
||||||
|
|
||||||
void (*release)(struct class_device *dev);
|
void (*release)(struct class_device *dev);
|
||||||
int (*hotplug)(struct class_device *dev, char **envp,
|
int (*uevent)(struct class_device *dev, char **envp,
|
||||||
int num_envp, char *buffer, int buffer_size);
|
int num_envp, char *buffer, int buffer_size);
|
||||||
char class_id[BUS_ID_SIZE]; /* unique to this class */
|
char class_id[BUS_ID_SIZE]; /* unique to this class */
|
||||||
};
|
};
|
||||||
|
|
|
@ -14,7 +14,7 @@ struct device;
|
||||||
int request_firmware(const struct firmware **fw, const char *name,
|
int request_firmware(const struct firmware **fw, const char *name,
|
||||||
struct device *device);
|
struct device *device);
|
||||||
int request_firmware_nowait(
|
int request_firmware_nowait(
|
||||||
struct module *module, int hotplug,
|
struct module *module, int uevent,
|
||||||
const char *name, struct device *device, void *context,
|
const char *name, struct device *device, void *context,
|
||||||
void (*cont)(const struct firmware *fw, void *context));
|
void (*cont)(const struct firmware *fw, void *context));
|
||||||
|
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
#include <linux/time.h>
|
#include <linux/time.h>
|
||||||
#include <linux/list.h>
|
#include <linux/list.h>
|
||||||
#include <linux/device.h>
|
#include <linux/device.h>
|
||||||
|
#include <linux/mod_devicetable.h>
|
||||||
#else
|
#else
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
#include <sys/ioctl.h>
|
#include <sys/ioctl.h>
|
||||||
|
@ -511,6 +512,8 @@ struct input_absinfo {
|
||||||
#define KEY_FN_S 0x1e3
|
#define KEY_FN_S 0x1e3
|
||||||
#define KEY_FN_B 0x1e4
|
#define KEY_FN_B 0x1e4
|
||||||
|
|
||||||
|
/* We avoid low common keys in module aliases so they don't get huge. */
|
||||||
|
#define KEY_MIN_INTERESTING KEY_MUTE
|
||||||
#define KEY_MAX 0x1ff
|
#define KEY_MAX 0x1ff
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -793,6 +796,44 @@ struct ff_effect {
|
||||||
|
|
||||||
#define FF_MAX 0x7f
|
#define FF_MAX 0x7f
|
||||||
|
|
||||||
|
struct input_device_id {
|
||||||
|
|
||||||
|
kernel_ulong_t flags;
|
||||||
|
|
||||||
|
struct input_id id;
|
||||||
|
|
||||||
|
kernel_ulong_t evbit[EV_MAX/BITS_PER_LONG+1];
|
||||||
|
kernel_ulong_t keybit[KEY_MAX/BITS_PER_LONG+1];
|
||||||
|
kernel_ulong_t relbit[REL_MAX/BITS_PER_LONG+1];
|
||||||
|
kernel_ulong_t absbit[ABS_MAX/BITS_PER_LONG+1];
|
||||||
|
kernel_ulong_t mscbit[MSC_MAX/BITS_PER_LONG+1];
|
||||||
|
kernel_ulong_t ledbit[LED_MAX/BITS_PER_LONG+1];
|
||||||
|
kernel_ulong_t sndbit[SND_MAX/BITS_PER_LONG+1];
|
||||||
|
kernel_ulong_t ffbit[FF_MAX/BITS_PER_LONG+1];
|
||||||
|
kernel_ulong_t swbit[SW_MAX/BITS_PER_LONG+1];
|
||||||
|
|
||||||
|
kernel_ulong_t driver_info;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Structure for hotplug & device<->driver matching.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define INPUT_DEVICE_ID_MATCH_BUS 1
|
||||||
|
#define INPUT_DEVICE_ID_MATCH_VENDOR 2
|
||||||
|
#define INPUT_DEVICE_ID_MATCH_PRODUCT 4
|
||||||
|
#define INPUT_DEVICE_ID_MATCH_VERSION 8
|
||||||
|
|
||||||
|
#define INPUT_DEVICE_ID_MATCH_EVBIT 0x010
|
||||||
|
#define INPUT_DEVICE_ID_MATCH_KEYBIT 0x020
|
||||||
|
#define INPUT_DEVICE_ID_MATCH_RELBIT 0x040
|
||||||
|
#define INPUT_DEVICE_ID_MATCH_ABSBIT 0x080
|
||||||
|
#define INPUT_DEVICE_ID_MATCH_MSCIT 0x100
|
||||||
|
#define INPUT_DEVICE_ID_MATCH_LEDBIT 0x200
|
||||||
|
#define INPUT_DEVICE_ID_MATCH_SNDBIT 0x400
|
||||||
|
#define INPUT_DEVICE_ID_MATCH_FFBIT 0x800
|
||||||
|
#define INPUT_DEVICE_ID_MATCH_SWBIT 0x1000
|
||||||
|
|
||||||
#ifdef __KERNEL__
|
#ifdef __KERNEL__
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -901,49 +942,11 @@ struct input_dev {
|
||||||
};
|
};
|
||||||
#define to_input_dev(d) container_of(d, struct input_dev, cdev)
|
#define to_input_dev(d) container_of(d, struct input_dev, cdev)
|
||||||
|
|
||||||
/*
|
|
||||||
* Structure for hotplug & device<->driver matching.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define INPUT_DEVICE_ID_MATCH_BUS 1
|
|
||||||
#define INPUT_DEVICE_ID_MATCH_VENDOR 2
|
|
||||||
#define INPUT_DEVICE_ID_MATCH_PRODUCT 4
|
|
||||||
#define INPUT_DEVICE_ID_MATCH_VERSION 8
|
|
||||||
|
|
||||||
#define INPUT_DEVICE_ID_MATCH_EVBIT 0x010
|
|
||||||
#define INPUT_DEVICE_ID_MATCH_KEYBIT 0x020
|
|
||||||
#define INPUT_DEVICE_ID_MATCH_RELBIT 0x040
|
|
||||||
#define INPUT_DEVICE_ID_MATCH_ABSBIT 0x080
|
|
||||||
#define INPUT_DEVICE_ID_MATCH_MSCIT 0x100
|
|
||||||
#define INPUT_DEVICE_ID_MATCH_LEDBIT 0x200
|
|
||||||
#define INPUT_DEVICE_ID_MATCH_SNDBIT 0x400
|
|
||||||
#define INPUT_DEVICE_ID_MATCH_FFBIT 0x800
|
|
||||||
#define INPUT_DEVICE_ID_MATCH_SWBIT 0x1000
|
|
||||||
|
|
||||||
#define INPUT_DEVICE_ID_MATCH_DEVICE\
|
#define INPUT_DEVICE_ID_MATCH_DEVICE\
|
||||||
(INPUT_DEVICE_ID_MATCH_BUS | INPUT_DEVICE_ID_MATCH_VENDOR | INPUT_DEVICE_ID_MATCH_PRODUCT)
|
(INPUT_DEVICE_ID_MATCH_BUS | INPUT_DEVICE_ID_MATCH_VENDOR | INPUT_DEVICE_ID_MATCH_PRODUCT)
|
||||||
#define INPUT_DEVICE_ID_MATCH_DEVICE_AND_VERSION\
|
#define INPUT_DEVICE_ID_MATCH_DEVICE_AND_VERSION\
|
||||||
(INPUT_DEVICE_ID_MATCH_DEVICE | INPUT_DEVICE_ID_MATCH_VERSION)
|
(INPUT_DEVICE_ID_MATCH_DEVICE | INPUT_DEVICE_ID_MATCH_VERSION)
|
||||||
|
|
||||||
struct input_device_id {
|
|
||||||
|
|
||||||
unsigned long flags;
|
|
||||||
|
|
||||||
struct input_id id;
|
|
||||||
|
|
||||||
unsigned long evbit[NBITS(EV_MAX)];
|
|
||||||
unsigned long keybit[NBITS(KEY_MAX)];
|
|
||||||
unsigned long relbit[NBITS(REL_MAX)];
|
|
||||||
unsigned long absbit[NBITS(ABS_MAX)];
|
|
||||||
unsigned long mscbit[NBITS(MSC_MAX)];
|
|
||||||
unsigned long ledbit[NBITS(LED_MAX)];
|
|
||||||
unsigned long sndbit[NBITS(SND_MAX)];
|
|
||||||
unsigned long ffbit[NBITS(FF_MAX)];
|
|
||||||
unsigned long swbit[NBITS(SW_MAX)];
|
|
||||||
|
|
||||||
unsigned long driver_info;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct input_handle;
|
struct input_handle;
|
||||||
|
|
||||||
struct input_handler {
|
struct input_handler {
|
||||||
|
|
|
@ -23,14 +23,27 @@
|
||||||
#include <linux/spinlock.h>
|
#include <linux/spinlock.h>
|
||||||
#include <linux/rwsem.h>
|
#include <linux/rwsem.h>
|
||||||
#include <linux/kref.h>
|
#include <linux/kref.h>
|
||||||
#include <linux/kobject_uevent.h>
|
|
||||||
#include <linux/kernel.h>
|
#include <linux/kernel.h>
|
||||||
#include <asm/atomic.h>
|
#include <asm/atomic.h>
|
||||||
|
|
||||||
#define KOBJ_NAME_LEN 20
|
#define KOBJ_NAME_LEN 20
|
||||||
|
#define UEVENT_HELPER_PATH_LEN 256
|
||||||
|
|
||||||
/* counter to tag the hotplug event, read only except for the kobject core */
|
/* path to the userspace helper executed on an event */
|
||||||
extern u64 hotplug_seqnum;
|
extern char uevent_helper[];
|
||||||
|
|
||||||
|
/* counter to tag the uevent, read only except for the kobject core */
|
||||||
|
extern u64 uevent_seqnum;
|
||||||
|
|
||||||
|
/* the actions here must match the proper string in lib/kobject_uevent.c */
|
||||||
|
typedef int __bitwise kobject_action_t;
|
||||||
|
enum kobject_action {
|
||||||
|
KOBJ_ADD = (__force kobject_action_t) 0x01, /* exclusive to core */
|
||||||
|
KOBJ_REMOVE = (__force kobject_action_t) 0x02, /* exclusive to core */
|
||||||
|
KOBJ_CHANGE = (__force kobject_action_t) 0x03, /* device state change */
|
||||||
|
KOBJ_OFFLINE = (__force kobject_action_t) 0x04, /* device offline */
|
||||||
|
KOBJ_ONLINE = (__force kobject_action_t) 0x05, /* device online */
|
||||||
|
};
|
||||||
|
|
||||||
struct kobject {
|
struct kobject {
|
||||||
const char * k_name;
|
const char * k_name;
|
||||||
|
@ -87,15 +100,14 @@ struct kobj_type {
|
||||||
* of object; multiple ksets can belong to one subsystem. All
|
* of object; multiple ksets can belong to one subsystem. All
|
||||||
* ksets of a subsystem share the subsystem's lock.
|
* ksets of a subsystem share the subsystem's lock.
|
||||||
*
|
*
|
||||||
* Each kset can support hotplugging; if it does, it will be given
|
* Each kset can support specific event variables; it can
|
||||||
* the opportunity to filter out specific kobjects from being
|
* supress the event generation or add subsystem specific
|
||||||
* reported, as well as to add its own "data" elements to the
|
* variables carried with the event.
|
||||||
* environment being passed to the hotplug helper.
|
|
||||||
*/
|
*/
|
||||||
struct kset_hotplug_ops {
|
struct kset_uevent_ops {
|
||||||
int (*filter)(struct kset *kset, struct kobject *kobj);
|
int (*filter)(struct kset *kset, struct kobject *kobj);
|
||||||
const char *(*name)(struct kset *kset, struct kobject *kobj);
|
const char *(*name)(struct kset *kset, struct kobject *kobj);
|
||||||
int (*hotplug)(struct kset *kset, struct kobject *kobj, char **envp,
|
int (*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);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -105,7 +117,7 @@ struct kset {
|
||||||
struct list_head list;
|
struct list_head list;
|
||||||
spinlock_t list_lock;
|
spinlock_t list_lock;
|
||||||
struct kobject kobj;
|
struct kobject kobj;
|
||||||
struct kset_hotplug_ops * hotplug_ops;
|
struct kset_uevent_ops * uevent_ops;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -153,20 +165,20 @@ struct subsystem {
|
||||||
struct rw_semaphore rwsem;
|
struct rw_semaphore rwsem;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define decl_subsys(_name,_type,_hotplug_ops) \
|
#define decl_subsys(_name,_type,_uevent_ops) \
|
||||||
struct subsystem _name##_subsys = { \
|
struct subsystem _name##_subsys = { \
|
||||||
.kset = { \
|
.kset = { \
|
||||||
.kobj = { .name = __stringify(_name) }, \
|
.kobj = { .name = __stringify(_name) }, \
|
||||||
.ktype = _type, \
|
.ktype = _type, \
|
||||||
.hotplug_ops =_hotplug_ops, \
|
.uevent_ops =_uevent_ops, \
|
||||||
} \
|
} \
|
||||||
}
|
}
|
||||||
#define decl_subsys_name(_varname,_name,_type,_hotplug_ops) \
|
#define decl_subsys_name(_varname,_name,_type,_uevent_ops) \
|
||||||
struct subsystem _varname##_subsys = { \
|
struct subsystem _varname##_subsys = { \
|
||||||
.kset = { \
|
.kset = { \
|
||||||
.kobj = { .name = __stringify(_name) }, \
|
.kobj = { .name = __stringify(_name) }, \
|
||||||
.ktype = _type, \
|
.ktype = _type, \
|
||||||
.hotplug_ops =_hotplug_ops, \
|
.uevent_ops =_uevent_ops, \
|
||||||
} \
|
} \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -241,15 +253,17 @@ struct subsys_attribute {
|
||||||
extern int subsys_create_file(struct subsystem * , struct subsys_attribute *);
|
extern int subsys_create_file(struct subsystem * , struct subsys_attribute *);
|
||||||
extern void subsys_remove_file(struct subsystem * , struct subsys_attribute *);
|
extern void subsys_remove_file(struct subsystem * , struct subsys_attribute *);
|
||||||
|
|
||||||
#ifdef CONFIG_HOTPLUG
|
#if defined(CONFIG_HOTPLUG) & defined(CONFIG_NET)
|
||||||
void kobject_hotplug(struct kobject *kobj, enum kobject_action action);
|
void kobject_uevent(struct kobject *kobj, enum kobject_action action);
|
||||||
int add_hotplug_env_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,
|
||||||
const char *format, ...)
|
const char *format, ...)
|
||||||
__attribute__((format (printf, 7, 8)));
|
__attribute__((format (printf, 7, 8)));
|
||||||
#else
|
#else
|
||||||
static inline void kobject_hotplug(struct kobject *kobj, enum kobject_action action) { }
|
static inline void kobject_uevent(struct kobject *kobj, enum kobject_action action) { }
|
||||||
static inline int add_hotplug_env_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,
|
||||||
const char *format, ...)
|
const char *format, ...)
|
||||||
{ return 0; }
|
{ return 0; }
|
||||||
|
|
|
@ -1,57 +0,0 @@
|
||||||
/*
|
|
||||||
* kobject_uevent.h - list of kobject user events that can be generated
|
|
||||||
*
|
|
||||||
* Copyright (C) 2004 IBM Corp.
|
|
||||||
* Copyright (C) 2004 Greg Kroah-Hartman <greg@kroah.com>
|
|
||||||
*
|
|
||||||
* This file is released under the GPLv2.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _KOBJECT_EVENT_H_
|
|
||||||
#define _KOBJECT_EVENT_H_
|
|
||||||
|
|
||||||
#define HOTPLUG_PATH_LEN 256
|
|
||||||
|
|
||||||
/* path to the hotplug userspace helper executed on an event */
|
|
||||||
extern char hotplug_path[];
|
|
||||||
|
|
||||||
/*
|
|
||||||
* If you add an action here, you must also add the proper string to the
|
|
||||||
* lib/kobject_uevent.c file.
|
|
||||||
*/
|
|
||||||
typedef int __bitwise kobject_action_t;
|
|
||||||
enum kobject_action {
|
|
||||||
KOBJ_ADD = (__force kobject_action_t) 0x01, /* add event, for hotplug */
|
|
||||||
KOBJ_REMOVE = (__force kobject_action_t) 0x02, /* remove event, for hotplug */
|
|
||||||
KOBJ_CHANGE = (__force kobject_action_t) 0x03, /* a sysfs attribute file has changed */
|
|
||||||
KOBJ_MOUNT = (__force kobject_action_t) 0x04, /* mount event for block devices */
|
|
||||||
KOBJ_UMOUNT = (__force kobject_action_t) 0x05, /* umount event for block devices */
|
|
||||||
KOBJ_OFFLINE = (__force kobject_action_t) 0x06, /* offline event for hotplug devices */
|
|
||||||
KOBJ_ONLINE = (__force kobject_action_t) 0x07, /* online event for hotplug devices */
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef CONFIG_KOBJECT_UEVENT
|
|
||||||
int kobject_uevent(struct kobject *kobj,
|
|
||||||
enum kobject_action action,
|
|
||||||
struct attribute *attr);
|
|
||||||
int kobject_uevent_atomic(struct kobject *kobj,
|
|
||||||
enum kobject_action action,
|
|
||||||
struct attribute *attr);
|
|
||||||
#else
|
|
||||||
static inline int kobject_uevent(struct kobject *kobj,
|
|
||||||
enum kobject_action action,
|
|
||||||
struct attribute *attr)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
static inline int kobject_uevent_atomic(struct kobject *kobj,
|
|
||||||
enum kobject_action action,
|
|
||||||
struct attribute *attr)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -41,6 +41,7 @@ extern struct platform_device *platform_device_alloc(const char *name, unsigned
|
||||||
extern int platform_device_add_resources(struct platform_device *pdev, struct resource *res, unsigned int num);
|
extern int platform_device_add_resources(struct platform_device *pdev, struct resource *res, unsigned int num);
|
||||||
extern int platform_device_add_data(struct platform_device *pdev, void *data, size_t size);
|
extern int platform_device_add_data(struct platform_device *pdev, void *data, size_t size);
|
||||||
extern int platform_device_add(struct platform_device *pdev);
|
extern int platform_device_add(struct platform_device *pdev);
|
||||||
|
extern void platform_device_del(struct platform_device *pdev);
|
||||||
extern void platform_device_put(struct platform_device *pdev);
|
extern void platform_device_put(struct platform_device *pdev);
|
||||||
|
|
||||||
struct platform_driver {
|
struct platform_driver {
|
||||||
|
|
|
@ -124,7 +124,7 @@ enum
|
||||||
KERN_OVERFLOWUID=46, /* int: overflow UID */
|
KERN_OVERFLOWUID=46, /* int: overflow UID */
|
||||||
KERN_OVERFLOWGID=47, /* int: overflow GID */
|
KERN_OVERFLOWGID=47, /* int: overflow GID */
|
||||||
KERN_SHMPATH=48, /* string: path to shm fs */
|
KERN_SHMPATH=48, /* string: path to shm fs */
|
||||||
KERN_HOTPLUG=49, /* string: path to hotplug policy agent */
|
KERN_HOTPLUG=49, /* string: path to uevent helper (deprecated) */
|
||||||
KERN_IEEE_EMULATION_WARNINGS=50, /* int: unimplemented ieee instructions */
|
KERN_IEEE_EMULATION_WARNINGS=50, /* int: unimplemented ieee instructions */
|
||||||
KERN_S390_USER_DEBUG_LOGGING=51, /* int: dumps of user faults */
|
KERN_S390_USER_DEBUG_LOGGING=51, /* int: dumps of user faults */
|
||||||
KERN_CORE_USES_PID=52, /* int: use core or core.%pid */
|
KERN_CORE_USES_PID=52, /* int: use core or core.%pid */
|
||||||
|
|
|
@ -225,7 +225,7 @@ struct usb_interface_cache {
|
||||||
* Device drivers should not attempt to activate configurations. The choice
|
* Device drivers should not attempt to activate configurations. The choice
|
||||||
* of which configuration to install is a policy decision based on such
|
* of which configuration to install is a policy decision based on such
|
||||||
* considerations as available power, functionality provided, and the user's
|
* considerations as available power, functionality provided, and the user's
|
||||||
* desires (expressed through hotplug scripts). However, drivers can call
|
* desires (expressed through userspace tools). However, drivers can call
|
||||||
* usb_reset_configuration() to reinitialize the current configuration and
|
* usb_reset_configuration() to reinitialize the current configuration and
|
||||||
* all its interfaces.
|
* all its interfaces.
|
||||||
*/
|
*/
|
||||||
|
|
36
init/Kconfig
36
init/Kconfig
|
@ -197,33 +197,6 @@ config AUDITSYSCALL
|
||||||
can be used independently or with another kernel subsystem,
|
can be used independently or with another kernel subsystem,
|
||||||
such as SELinux.
|
such as SELinux.
|
||||||
|
|
||||||
config HOTPLUG
|
|
||||||
bool "Support for hot-pluggable devices" if !ARCH_S390
|
|
||||||
default ARCH_S390
|
|
||||||
help
|
|
||||||
This option is provided for the case where no in-kernel-tree
|
|
||||||
modules require HOTPLUG functionality, but a module built
|
|
||||||
outside the kernel tree does. Such modules require Y here.
|
|
||||||
|
|
||||||
config KOBJECT_UEVENT
|
|
||||||
bool "Kernel Userspace Events" if EMBEDDED
|
|
||||||
depends on NET
|
|
||||||
default y
|
|
||||||
help
|
|
||||||
This option enables the kernel userspace event layer, which is a
|
|
||||||
simple mechanism for kernel-to-user communication over a netlink
|
|
||||||
socket.
|
|
||||||
The goal of the kernel userspace events layer is to provide a simple
|
|
||||||
and efficient events system, that notifies userspace about kobject
|
|
||||||
state changes. This will enable applications to just listen for
|
|
||||||
events instead of polling system devices and files.
|
|
||||||
Hotplug events (kobject addition and removal) are also available on
|
|
||||||
the netlink socket in addition to the execution of /sbin/hotplug if
|
|
||||||
CONFIG_HOTPLUG is enabled.
|
|
||||||
|
|
||||||
Say Y, unless you are building a system requiring minimal memory
|
|
||||||
consumption.
|
|
||||||
|
|
||||||
config IKCONFIG
|
config IKCONFIG
|
||||||
bool "Kernel .config support"
|
bool "Kernel .config support"
|
||||||
---help---
|
---help---
|
||||||
|
@ -308,6 +281,15 @@ config KALLSYMS_EXTRA_PASS
|
||||||
you wait for kallsyms to be fixed.
|
you wait for kallsyms to be fixed.
|
||||||
|
|
||||||
|
|
||||||
|
config HOTPLUG
|
||||||
|
bool "Support for hot-pluggable devices" if EMBEDDED
|
||||||
|
default y
|
||||||
|
help
|
||||||
|
This option is provided for the case where no hotplug or uevent
|
||||||
|
capabilities is wanted by the kernel. You should only consider
|
||||||
|
disabling this option for embedded systems that do not use modules, a
|
||||||
|
dynamic /dev tree, or dynamic device discovery. Just say Y.
|
||||||
|
|
||||||
config PRINTK
|
config PRINTK
|
||||||
default y
|
default y
|
||||||
bool "Enable support for printk" if EMBEDDED
|
bool "Enable support for printk" if EMBEDDED
|
||||||
|
|
|
@ -15,6 +15,9 @@
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/init.h>
|
#include <linux/init.h>
|
||||||
|
|
||||||
|
u64 uevent_seqnum;
|
||||||
|
char uevent_helper[UEVENT_HELPER_PATH_LEN] = "/sbin/hotplug";
|
||||||
|
|
||||||
#define KERNEL_ATTR_RO(_name) \
|
#define KERNEL_ATTR_RO(_name) \
|
||||||
static struct subsys_attribute _name##_attr = __ATTR_RO(_name)
|
static struct subsys_attribute _name##_attr = __ATTR_RO(_name)
|
||||||
|
|
||||||
|
@ -23,11 +26,29 @@ static struct subsys_attribute _name##_attr = \
|
||||||
__ATTR(_name, 0644, _name##_show, _name##_store)
|
__ATTR(_name, 0644, _name##_show, _name##_store)
|
||||||
|
|
||||||
#ifdef CONFIG_HOTPLUG
|
#ifdef CONFIG_HOTPLUG
|
||||||
static ssize_t hotplug_seqnum_show(struct subsystem *subsys, char *page)
|
/* current uevent sequence number */
|
||||||
|
static ssize_t uevent_seqnum_show(struct subsystem *subsys, char *page)
|
||||||
{
|
{
|
||||||
return sprintf(page, "%llu\n", (unsigned long long)hotplug_seqnum);
|
return sprintf(page, "%llu\n", (unsigned long long)uevent_seqnum);
|
||||||
}
|
}
|
||||||
KERNEL_ATTR_RO(hotplug_seqnum);
|
KERNEL_ATTR_RO(uevent_seqnum);
|
||||||
|
|
||||||
|
/* uevent helper program, used during early boo */
|
||||||
|
static ssize_t uevent_helper_show(struct subsystem *subsys, char *page)
|
||||||
|
{
|
||||||
|
return sprintf(page, "%s\n", uevent_helper);
|
||||||
|
}
|
||||||
|
static ssize_t uevent_helper_store(struct subsystem *subsys, const char *page, size_t count)
|
||||||
|
{
|
||||||
|
if (count+1 > UEVENT_HELPER_PATH_LEN)
|
||||||
|
return -ENOENT;
|
||||||
|
memcpy(uevent_helper, page, count);
|
||||||
|
uevent_helper[count] = '\0';
|
||||||
|
if (count && uevent_helper[count-1] == '\n')
|
||||||
|
uevent_helper[count-1] = '\0';
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
KERNEL_ATTR_RW(uevent_helper);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef CONFIG_KEXEC
|
#ifdef CONFIG_KEXEC
|
||||||
|
@ -45,7 +66,8 @@ EXPORT_SYMBOL_GPL(kernel_subsys);
|
||||||
|
|
||||||
static struct attribute * kernel_attrs[] = {
|
static struct attribute * kernel_attrs[] = {
|
||||||
#ifdef CONFIG_HOTPLUG
|
#ifdef CONFIG_HOTPLUG
|
||||||
&hotplug_seqnum_attr.attr,
|
&uevent_seqnum_attr.attr,
|
||||||
|
&uevent_helper_attr.attr,
|
||||||
#endif
|
#endif
|
||||||
#ifdef CONFIG_KEXEC
|
#ifdef CONFIG_KEXEC
|
||||||
&crash_notes_attr.attr,
|
&crash_notes_attr.attr,
|
||||||
|
|
|
@ -31,6 +31,7 @@
|
||||||
#include <linux/smp_lock.h>
|
#include <linux/smp_lock.h>
|
||||||
#include <linux/init.h>
|
#include <linux/init.h>
|
||||||
#include <linux/kernel.h>
|
#include <linux/kernel.h>
|
||||||
|
#include <linux/kobject.h>
|
||||||
#include <linux/net.h>
|
#include <linux/net.h>
|
||||||
#include <linux/sysrq.h>
|
#include <linux/sysrq.h>
|
||||||
#include <linux/highuid.h>
|
#include <linux/highuid.h>
|
||||||
|
@ -83,9 +84,6 @@ static int ngroups_max = NGROUPS_MAX;
|
||||||
#ifdef CONFIG_KMOD
|
#ifdef CONFIG_KMOD
|
||||||
extern char modprobe_path[];
|
extern char modprobe_path[];
|
||||||
#endif
|
#endif
|
||||||
#ifdef CONFIG_HOTPLUG
|
|
||||||
extern char hotplug_path[];
|
|
||||||
#endif
|
|
||||||
#ifdef CONFIG_CHR_DEV_SG
|
#ifdef CONFIG_CHR_DEV_SG
|
||||||
extern int sg_big_buff;
|
extern int sg_big_buff;
|
||||||
#endif
|
#endif
|
||||||
|
@ -397,8 +395,8 @@ static ctl_table kern_table[] = {
|
||||||
{
|
{
|
||||||
.ctl_name = KERN_HOTPLUG,
|
.ctl_name = KERN_HOTPLUG,
|
||||||
.procname = "hotplug",
|
.procname = "hotplug",
|
||||||
.data = &hotplug_path,
|
.data = &uevent_helper,
|
||||||
.maxlen = HOTPLUG_PATH_LEN,
|
.maxlen = UEVENT_HELPER_PATH_LEN,
|
||||||
.mode = 0644,
|
.mode = 0644,
|
||||||
.proc_handler = &proc_dostring,
|
.proc_handler = &proc_dostring,
|
||||||
.strategy = &sysctl_string,
|
.strategy = &sysctl_string,
|
||||||
|
|
|
@ -199,6 +199,8 @@ void klist_iter_init_node(struct klist * k, struct klist_iter * i, struct klist_
|
||||||
i->i_klist = k;
|
i->i_klist = k;
|
||||||
i->i_head = &k->k_list;
|
i->i_head = &k->k_list;
|
||||||
i->i_cur = n;
|
i->i_cur = n;
|
||||||
|
if (n)
|
||||||
|
kref_get(&n->n_ref);
|
||||||
}
|
}
|
||||||
|
|
||||||
EXPORT_SYMBOL_GPL(klist_iter_init_node);
|
EXPORT_SYMBOL_GPL(klist_iter_init_node);
|
||||||
|
|
|
@ -207,7 +207,7 @@ int kobject_register(struct kobject * kobj)
|
||||||
kobject_name(kobj),error);
|
kobject_name(kobj),error);
|
||||||
dump_stack();
|
dump_stack();
|
||||||
} else
|
} else
|
||||||
kobject_hotplug(kobj, KOBJ_ADD);
|
kobject_uevent(kobj, KOBJ_ADD);
|
||||||
} else
|
} else
|
||||||
error = -EINVAL;
|
error = -EINVAL;
|
||||||
return error;
|
return error;
|
||||||
|
@ -312,7 +312,7 @@ void kobject_del(struct kobject * kobj)
|
||||||
void kobject_unregister(struct kobject * kobj)
|
void kobject_unregister(struct kobject * kobj)
|
||||||
{
|
{
|
||||||
pr_debug("kobject %s: unregistering\n",kobject_name(kobj));
|
pr_debug("kobject %s: unregistering\n",kobject_name(kobj));
|
||||||
kobject_hotplug(kobj, KOBJ_REMOVE);
|
kobject_uevent(kobj, KOBJ_REMOVE);
|
||||||
kobject_del(kobj);
|
kobject_del(kobj);
|
||||||
kobject_put(kobj);
|
kobject_put(kobj);
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,14 +19,16 @@
|
||||||
#include <linux/skbuff.h>
|
#include <linux/skbuff.h>
|
||||||
#include <linux/netlink.h>
|
#include <linux/netlink.h>
|
||||||
#include <linux/string.h>
|
#include <linux/string.h>
|
||||||
#include <linux/kobject_uevent.h>
|
|
||||||
#include <linux/kobject.h>
|
#include <linux/kobject.h>
|
||||||
#include <net/sock.h>
|
#include <net/sock.h>
|
||||||
|
|
||||||
#define BUFFER_SIZE 1024 /* buffer for the hotplug env */
|
#define BUFFER_SIZE 1024 /* buffer for the variables */
|
||||||
#define NUM_ENVP 32 /* number of env pointers */
|
#define NUM_ENVP 32 /* number of env pointers */
|
||||||
|
|
||||||
#if defined(CONFIG_KOBJECT_UEVENT) || defined(CONFIG_HOTPLUG)
|
#if defined(CONFIG_HOTPLUG) && defined(CONFIG_NET)
|
||||||
|
static DEFINE_SPINLOCK(sequence_lock);
|
||||||
|
static struct sock *uevent_sock;
|
||||||
|
|
||||||
static char *action_to_string(enum kobject_action action)
|
static char *action_to_string(enum kobject_action action)
|
||||||
{
|
{
|
||||||
switch (action) {
|
switch (action) {
|
||||||
|
@ -36,10 +38,6 @@ static char *action_to_string(enum kobject_action action)
|
||||||
return "remove";
|
return "remove";
|
||||||
case KOBJ_CHANGE:
|
case KOBJ_CHANGE:
|
||||||
return "change";
|
return "change";
|
||||||
case KOBJ_MOUNT:
|
|
||||||
return "mount";
|
|
||||||
case KOBJ_UMOUNT:
|
|
||||||
return "umount";
|
|
||||||
case KOBJ_OFFLINE:
|
case KOBJ_OFFLINE:
|
||||||
return "offline";
|
return "offline";
|
||||||
case KOBJ_ONLINE:
|
case KOBJ_ONLINE:
|
||||||
|
@ -48,306 +46,183 @@ static char *action_to_string(enum kobject_action action)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef CONFIG_KOBJECT_UEVENT
|
|
||||||
static struct sock *uevent_sock;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* send_uevent - notify userspace by sending event through netlink socket
|
* kobject_uevent - notify userspace by ending an uevent
|
||||||
*
|
*
|
||||||
* @signal: signal name
|
* @action: action that is happening (usually KOBJ_ADD and KOBJ_REMOVE)
|
||||||
* @obj: object path (kobject)
|
|
||||||
* @envp: possible hotplug environment to pass with the message
|
|
||||||
* @gfp_mask:
|
|
||||||
*/
|
|
||||||
static int send_uevent(const char *signal, const char *obj,
|
|
||||||
char **envp, gfp_t gfp_mask)
|
|
||||||
{
|
|
||||||
struct sk_buff *skb;
|
|
||||||
char *pos;
|
|
||||||
int len;
|
|
||||||
|
|
||||||
if (!uevent_sock)
|
|
||||||
return -EIO;
|
|
||||||
|
|
||||||
len = strlen(signal) + 1;
|
|
||||||
len += strlen(obj) + 1;
|
|
||||||
|
|
||||||
/* allocate buffer with the maximum possible message size */
|
|
||||||
skb = alloc_skb(len + BUFFER_SIZE, gfp_mask);
|
|
||||||
if (!skb)
|
|
||||||
return -ENOMEM;
|
|
||||||
|
|
||||||
pos = skb_put(skb, len);
|
|
||||||
sprintf(pos, "%s@%s", signal, obj);
|
|
||||||
|
|
||||||
/* copy the environment key by key to our continuous buffer */
|
|
||||||
if (envp) {
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for (i = 2; envp[i]; i++) {
|
|
||||||
len = strlen(envp[i]) + 1;
|
|
||||||
pos = skb_put(skb, len);
|
|
||||||
strcpy(pos, envp[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
NETLINK_CB(skb).dst_group = 1;
|
|
||||||
return netlink_broadcast(uevent_sock, skb, 0, 1, gfp_mask);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int do_kobject_uevent(struct kobject *kobj, enum kobject_action action,
|
|
||||||
struct attribute *attr, gfp_t gfp_mask)
|
|
||||||
{
|
|
||||||
char *path;
|
|
||||||
char *attrpath;
|
|
||||||
char *signal;
|
|
||||||
int len;
|
|
||||||
int rc = -ENOMEM;
|
|
||||||
|
|
||||||
path = kobject_get_path(kobj, gfp_mask);
|
|
||||||
if (!path)
|
|
||||||
return -ENOMEM;
|
|
||||||
|
|
||||||
signal = action_to_string(action);
|
|
||||||
if (!signal)
|
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
if (attr) {
|
|
||||||
len = strlen(path);
|
|
||||||
len += strlen(attr->name) + 2;
|
|
||||||
attrpath = kmalloc(len, gfp_mask);
|
|
||||||
if (!attrpath)
|
|
||||||
goto exit;
|
|
||||||
sprintf(attrpath, "%s/%s", path, attr->name);
|
|
||||||
rc = send_uevent(signal, attrpath, NULL, gfp_mask);
|
|
||||||
kfree(attrpath);
|
|
||||||
} else
|
|
||||||
rc = send_uevent(signal, path, NULL, gfp_mask);
|
|
||||||
|
|
||||||
exit:
|
|
||||||
kfree(path);
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* kobject_uevent - notify userspace by sending event through netlink socket
|
|
||||||
*
|
|
||||||
* @signal: signal name
|
|
||||||
* @kobj: struct kobject that the event is happening to
|
|
||||||
* @attr: optional struct attribute the event belongs to
|
|
||||||
*/
|
|
||||||
int kobject_uevent(struct kobject *kobj, enum kobject_action action,
|
|
||||||
struct attribute *attr)
|
|
||||||
{
|
|
||||||
return do_kobject_uevent(kobj, action, attr, GFP_KERNEL);
|
|
||||||
}
|
|
||||||
EXPORT_SYMBOL_GPL(kobject_uevent);
|
|
||||||
|
|
||||||
int kobject_uevent_atomic(struct kobject *kobj, enum kobject_action action,
|
|
||||||
struct attribute *attr)
|
|
||||||
{
|
|
||||||
return do_kobject_uevent(kobj, action, attr, GFP_ATOMIC);
|
|
||||||
}
|
|
||||||
EXPORT_SYMBOL_GPL(kobject_uevent_atomic);
|
|
||||||
|
|
||||||
static int __init kobject_uevent_init(void)
|
|
||||||
{
|
|
||||||
uevent_sock = netlink_kernel_create(NETLINK_KOBJECT_UEVENT, 1, NULL,
|
|
||||||
THIS_MODULE);
|
|
||||||
|
|
||||||
if (!uevent_sock) {
|
|
||||||
printk(KERN_ERR
|
|
||||||
"kobject_uevent: unable to create netlink socket!\n");
|
|
||||||
return -ENODEV;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
postcore_initcall(kobject_uevent_init);
|
|
||||||
|
|
||||||
#else
|
|
||||||
static inline int send_uevent(const char *signal, const char *obj,
|
|
||||||
char **envp, int gfp_mask)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* CONFIG_KOBJECT_UEVENT */
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef CONFIG_HOTPLUG
|
|
||||||
char hotplug_path[HOTPLUG_PATH_LEN] = "/sbin/hotplug";
|
|
||||||
u64 hotplug_seqnum;
|
|
||||||
static DEFINE_SPINLOCK(sequence_lock);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* kobject_hotplug - notify userspace by executing /sbin/hotplug
|
|
||||||
*
|
|
||||||
* @action: action that is happening (usually "ADD" or "REMOVE")
|
|
||||||
* @kobj: struct kobject that the action is happening to
|
* @kobj: struct kobject that the action is happening to
|
||||||
*/
|
*/
|
||||||
void kobject_hotplug(struct kobject *kobj, enum kobject_action action)
|
void kobject_uevent(struct kobject *kobj, enum kobject_action action)
|
||||||
{
|
{
|
||||||
char *argv [3];
|
char **envp;
|
||||||
char **envp = NULL;
|
char *buffer;
|
||||||
char *buffer = NULL;
|
|
||||||
char *seq_buff;
|
|
||||||
char *scratch;
|
char *scratch;
|
||||||
|
const char *action_string;
|
||||||
|
const char *devpath = NULL;
|
||||||
|
const char *subsystem;
|
||||||
|
struct kobject *top_kobj;
|
||||||
|
struct kset *kset;
|
||||||
|
struct kset_uevent_ops *uevent_ops;
|
||||||
|
u64 seq;
|
||||||
|
char *seq_buff;
|
||||||
int i = 0;
|
int i = 0;
|
||||||
int retval;
|
int retval;
|
||||||
char *kobj_path = NULL;
|
|
||||||
const char *name = NULL;
|
|
||||||
char *action_string;
|
|
||||||
u64 seq;
|
|
||||||
struct kobject *top_kobj = kobj;
|
|
||||||
struct kset *kset;
|
|
||||||
static struct kset_hotplug_ops null_hotplug_ops;
|
|
||||||
struct kset_hotplug_ops *hotplug_ops = &null_hotplug_ops;
|
|
||||||
|
|
||||||
/* If this kobj does not belong to a kset,
|
pr_debug("%s\n", __FUNCTION__);
|
||||||
try to find a parent that does. */
|
|
||||||
if (!top_kobj->kset && top_kobj->parent) {
|
|
||||||
do {
|
|
||||||
top_kobj = top_kobj->parent;
|
|
||||||
} while (!top_kobj->kset && top_kobj->parent);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (top_kobj->kset)
|
|
||||||
kset = top_kobj->kset;
|
|
||||||
else
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (kset->hotplug_ops)
|
|
||||||
hotplug_ops = kset->hotplug_ops;
|
|
||||||
|
|
||||||
/* If the kset has a filter operation, call it.
|
|
||||||
Skip the event, if the filter returns zero. */
|
|
||||||
if (hotplug_ops->filter) {
|
|
||||||
if (!hotplug_ops->filter(kset, kobj))
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
pr_debug ("%s\n", __FUNCTION__);
|
|
||||||
|
|
||||||
action_string = action_to_string(action);
|
action_string = action_to_string(action);
|
||||||
if (!action_string)
|
if (!action_string)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
envp = kmalloc(NUM_ENVP * sizeof (char *), GFP_KERNEL);
|
/* search the kset we belong to */
|
||||||
|
top_kobj = kobj;
|
||||||
|
if (!top_kobj->kset && top_kobj->parent) {
|
||||||
|
do {
|
||||||
|
top_kobj = top_kobj->parent;
|
||||||
|
} while (!top_kobj->kset && top_kobj->parent);
|
||||||
|
}
|
||||||
|
if (!top_kobj->kset)
|
||||||
|
return;
|
||||||
|
|
||||||
|
kset = top_kobj->kset;
|
||||||
|
uevent_ops = kset->uevent_ops;
|
||||||
|
|
||||||
|
/* skip the event, if the filter returns zero. */
|
||||||
|
if (uevent_ops && uevent_ops->filter)
|
||||||
|
if (!uevent_ops->filter(kset, kobj))
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* environment index */
|
||||||
|
envp = kzalloc(NUM_ENVP * sizeof (char *), GFP_KERNEL);
|
||||||
if (!envp)
|
if (!envp)
|
||||||
return;
|
return;
|
||||||
memset (envp, 0x00, NUM_ENVP * sizeof (char *));
|
|
||||||
|
|
||||||
|
/* environment values */
|
||||||
buffer = kmalloc(BUFFER_SIZE, GFP_KERNEL);
|
buffer = kmalloc(BUFFER_SIZE, GFP_KERNEL);
|
||||||
if (!buffer)
|
if (!buffer)
|
||||||
goto exit;
|
goto exit;
|
||||||
|
|
||||||
if (hotplug_ops->name)
|
/* complete object path */
|
||||||
name = hotplug_ops->name(kset, kobj);
|
devpath = kobject_get_path(kobj, GFP_KERNEL);
|
||||||
if (name == NULL)
|
if (!devpath)
|
||||||
name = kobject_name(&kset->kobj);
|
|
||||||
|
|
||||||
argv [0] = hotplug_path;
|
|
||||||
argv [1] = (char *)name; /* won't be changed but 'const' has to go */
|
|
||||||
argv [2] = NULL;
|
|
||||||
|
|
||||||
/* minimal command environment */
|
|
||||||
envp [i++] = "HOME=/";
|
|
||||||
envp [i++] = "PATH=/sbin:/bin:/usr/sbin:/usr/bin";
|
|
||||||
|
|
||||||
scratch = buffer;
|
|
||||||
|
|
||||||
envp [i++] = scratch;
|
|
||||||
scratch += sprintf(scratch, "ACTION=%s", action_string) + 1;
|
|
||||||
|
|
||||||
kobj_path = kobject_get_path(kobj, GFP_KERNEL);
|
|
||||||
if (!kobj_path)
|
|
||||||
goto exit;
|
goto exit;
|
||||||
|
|
||||||
envp [i++] = scratch;
|
/* originating subsystem */
|
||||||
scratch += sprintf (scratch, "DEVPATH=%s", kobj_path) + 1;
|
if (uevent_ops && uevent_ops->name)
|
||||||
|
subsystem = uevent_ops->name(kset, kobj);
|
||||||
|
else
|
||||||
|
subsystem = kobject_name(&kset->kobj);
|
||||||
|
|
||||||
envp [i++] = scratch;
|
/* event environemnt for helper process only */
|
||||||
scratch += sprintf(scratch, "SUBSYSTEM=%s", name) + 1;
|
envp[i++] = "HOME=/";
|
||||||
|
envp[i++] = "PATH=/sbin:/bin:/usr/sbin:/usr/bin";
|
||||||
|
|
||||||
/* reserve space for the sequence,
|
/* default keys */
|
||||||
* put the real one in after the hotplug call */
|
scratch = buffer;
|
||||||
|
envp [i++] = scratch;
|
||||||
|
scratch += sprintf(scratch, "ACTION=%s", action_string) + 1;
|
||||||
|
envp [i++] = scratch;
|
||||||
|
scratch += sprintf (scratch, "DEVPATH=%s", devpath) + 1;
|
||||||
|
envp [i++] = scratch;
|
||||||
|
scratch += sprintf(scratch, "SUBSYSTEM=%s", subsystem) + 1;
|
||||||
|
|
||||||
|
/* 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;
|
||||||
|
|
||||||
if (hotplug_ops->hotplug) {
|
/* let the kset specific function add its stuff */
|
||||||
/* have the kset specific function add its stuff */
|
if (uevent_ops && uevent_ops->uevent) {
|
||||||
retval = hotplug_ops->hotplug (kset, kobj,
|
retval = uevent_ops->uevent(kset, kobj,
|
||||||
&envp[i], NUM_ENVP - i, scratch,
|
&envp[i], NUM_ENVP - i, scratch,
|
||||||
BUFFER_SIZE - (scratch - buffer));
|
BUFFER_SIZE - (scratch - buffer));
|
||||||
if (retval) {
|
if (retval) {
|
||||||
pr_debug ("%s - hotplug() returned %d\n",
|
pr_debug ("%s - uevent() returned %d\n",
|
||||||
__FUNCTION__, retval);
|
__FUNCTION__, retval);
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* we will send an event, request a new sequence number */
|
||||||
spin_lock(&sequence_lock);
|
spin_lock(&sequence_lock);
|
||||||
seq = ++hotplug_seqnum;
|
seq = ++uevent_seqnum;
|
||||||
spin_unlock(&sequence_lock);
|
spin_unlock(&sequence_lock);
|
||||||
sprintf(seq_buff, "SEQNUM=%llu", (unsigned long long)seq);
|
sprintf(seq_buff, "SEQNUM=%llu", (unsigned long long)seq);
|
||||||
|
|
||||||
pr_debug ("%s: %s %s seq=%llu %s %s %s %s %s\n",
|
/* send netlink message */
|
||||||
__FUNCTION__, argv[0], argv[1], (unsigned long long)seq,
|
if (uevent_sock) {
|
||||||
envp[0], envp[1], envp[2], envp[3], envp[4]);
|
struct sk_buff *skb;
|
||||||
|
size_t len;
|
||||||
|
|
||||||
send_uevent(action_string, kobj_path, envp, GFP_KERNEL);
|
/* allocate message with the maximum possible size */
|
||||||
|
len = strlen(action_string) + strlen(devpath) + 2;
|
||||||
|
skb = alloc_skb(len + BUFFER_SIZE, GFP_KERNEL);
|
||||||
|
if (skb) {
|
||||||
|
/* add header */
|
||||||
|
scratch = skb_put(skb, len);
|
||||||
|
sprintf(scratch, "%s@%s", action_string, devpath);
|
||||||
|
|
||||||
if (!hotplug_path[0])
|
/* copy keys to our continuous event payload buffer */
|
||||||
goto exit;
|
for (i = 2; envp[i]; i++) {
|
||||||
|
len = strlen(envp[i]) + 1;
|
||||||
|
scratch = skb_put(skb, len);
|
||||||
|
strcpy(scratch, envp[i]);
|
||||||
|
}
|
||||||
|
|
||||||
retval = call_usermodehelper (argv[0], argv, envp, 0);
|
NETLINK_CB(skb).dst_group = 1;
|
||||||
if (retval)
|
netlink_broadcast(uevent_sock, skb, 0, 1, GFP_KERNEL);
|
||||||
pr_debug ("%s - call_usermodehelper returned %d\n",
|
}
|
||||||
__FUNCTION__, retval);
|
}
|
||||||
|
|
||||||
|
/* call uevent_helper, usually only enabled during early boot */
|
||||||
|
if (uevent_helper[0]) {
|
||||||
|
char *argv [3];
|
||||||
|
|
||||||
|
argv [0] = uevent_helper;
|
||||||
|
argv [1] = (char *)subsystem;
|
||||||
|
argv [2] = NULL;
|
||||||
|
call_usermodehelper (argv[0], argv, envp, 0);
|
||||||
|
}
|
||||||
|
|
||||||
exit:
|
exit:
|
||||||
kfree(kobj_path);
|
kfree(devpath);
|
||||||
kfree(buffer);
|
kfree(buffer);
|
||||||
kfree(envp);
|
kfree(envp);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(kobject_hotplug);
|
EXPORT_SYMBOL_GPL(kobject_uevent);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* add_hotplug_env_var - helper for creating hotplug environment variables
|
* add_uevent_var - helper for creating event variables
|
||||||
* @envp: Pointer to table of environment variables, as passed into
|
* @envp: Pointer to table of environment variables, as passed into
|
||||||
* hotplug() method.
|
* uevent() method.
|
||||||
* @num_envp: Number of environment variable slots available, as
|
* @num_envp: Number of environment variable slots available, as
|
||||||
* passed into hotplug() method.
|
* passed into uevent() method.
|
||||||
* @cur_index: Pointer to current index into @envp. It should be
|
* @cur_index: Pointer to current index into @envp. It should be
|
||||||
* initialized to 0 before the first call to add_hotplug_env_var(),
|
* initialized to 0 before the first call to add_uevent_var(),
|
||||||
* and will be incremented on success.
|
* and will be incremented on success.
|
||||||
* @buffer: Pointer to buffer for environment variables, as passed
|
* @buffer: Pointer to buffer for environment variables, as passed
|
||||||
* into hotplug() method.
|
* into uevent() method.
|
||||||
* @buffer_size: Length of @buffer, as passed into hotplug() method.
|
* @buffer_size: Length of @buffer, as passed into uevent() method.
|
||||||
* @cur_len: Pointer to current length of space used in @buffer.
|
* @cur_len: Pointer to current length of space used in @buffer.
|
||||||
* Should be initialized to 0 before the first call to
|
* Should be initialized to 0 before the first call to
|
||||||
* add_hotplug_env_var(), and will be incremented on success.
|
* add_uevent_var(), and will be incremented on success.
|
||||||
* @format: Format for creating environment variable (of the form
|
* @format: Format for creating environment variable (of the form
|
||||||
* "XXX=%x") for snprintf().
|
* "XXX=%x") for snprintf().
|
||||||
*
|
*
|
||||||
* Returns 0 if environment variable was added successfully or -ENOMEM
|
* Returns 0 if environment variable was added successfully or -ENOMEM
|
||||||
* if no space was available.
|
* if no space was available.
|
||||||
*/
|
*/
|
||||||
int add_hotplug_env_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,
|
||||||
const char *format, ...)
|
const char *format, ...)
|
||||||
{
|
{
|
||||||
va_list args;
|
va_list args;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We check against num_envp - 1 to make sure there is at
|
* We check against num_envp - 1 to make sure there is at
|
||||||
* least one slot left after we return, since the hotplug
|
* least one slot left after we return, since kobject_uevent()
|
||||||
* method needs to set the last slot to NULL.
|
* needs to set the last slot to NULL.
|
||||||
*/
|
*/
|
||||||
if (*cur_index >= num_envp - 1)
|
if (*cur_index >= num_envp - 1)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
@ -366,6 +241,22 @@ int add_hotplug_env_var(char **envp, int num_envp, int *cur_index,
|
||||||
(*cur_index)++;
|
(*cur_index)++;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(add_hotplug_env_var);
|
EXPORT_SYMBOL_GPL(add_uevent_var);
|
||||||
|
|
||||||
|
static int __init kobject_uevent_init(void)
|
||||||
|
{
|
||||||
|
uevent_sock = netlink_kernel_create(NETLINK_KOBJECT_UEVENT, 1, NULL,
|
||||||
|
THIS_MODULE);
|
||||||
|
|
||||||
|
if (!uevent_sock) {
|
||||||
|
printk(KERN_ERR
|
||||||
|
"kobject_uevent: unable to create netlink socket!\n");
|
||||||
|
return -ENODEV;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
postcore_initcall(kobject_uevent_init);
|
||||||
|
|
||||||
#endif /* CONFIG_HOTPLUG */
|
#endif /* CONFIG_HOTPLUG */
|
||||||
|
|
|
@ -78,7 +78,7 @@ static struct class_device_attribute *bt_attrs[] = {
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef CONFIG_HOTPLUG
|
#ifdef CONFIG_HOTPLUG
|
||||||
static int bt_hotplug(struct class_device *cdev, char **envp, int num_envp, char *buf, int size)
|
static int bt_uevent(struct class_device *cdev, char **envp, int num_envp, char *buf, int size)
|
||||||
{
|
{
|
||||||
struct hci_dev *hdev = class_get_devdata(cdev);
|
struct hci_dev *hdev = class_get_devdata(cdev);
|
||||||
int n, i = 0;
|
int n, i = 0;
|
||||||
|
@ -107,7 +107,7 @@ struct class bt_class = {
|
||||||
.name = "bluetooth",
|
.name = "bluetooth",
|
||||||
.release = bt_release,
|
.release = bt_release,
|
||||||
#ifdef CONFIG_HOTPLUG
|
#ifdef CONFIG_HOTPLUG
|
||||||
.hotplug = bt_hotplug,
|
.uevent = bt_uevent,
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -248,7 +248,7 @@ int br_sysfs_addif(struct net_bridge_port *p)
|
||||||
if (err)
|
if (err)
|
||||||
goto out2;
|
goto out2;
|
||||||
|
|
||||||
kobject_hotplug(&p->kobj, KOBJ_ADD);
|
kobject_uevent(&p->kobj, KOBJ_ADD);
|
||||||
return 0;
|
return 0;
|
||||||
out2:
|
out2:
|
||||||
kobject_del(&p->kobj);
|
kobject_del(&p->kobj);
|
||||||
|
@ -260,7 +260,7 @@ void br_sysfs_removeif(struct net_bridge_port *p)
|
||||||
{
|
{
|
||||||
pr_debug("br_sysfs_removeif\n");
|
pr_debug("br_sysfs_removeif\n");
|
||||||
sysfs_remove_link(&p->br->ifobj, p->dev->name);
|
sysfs_remove_link(&p->br->ifobj, p->dev->name);
|
||||||
kobject_hotplug(&p->kobj, KOBJ_REMOVE);
|
kobject_uevent(&p->kobj, KOBJ_REMOVE);
|
||||||
kobject_del(&p->kobj);
|
kobject_del(&p->kobj);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -84,16 +84,11 @@ static ssize_t netdev_store(struct class_device *dev,
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* generate a read-only network device class attribute */
|
NETDEVICE_SHOW(addr_len, fmt_dec);
|
||||||
#define NETDEVICE_ATTR(field, format_string) \
|
NETDEVICE_SHOW(iflink, fmt_dec);
|
||||||
NETDEVICE_SHOW(field, format_string) \
|
NETDEVICE_SHOW(ifindex, fmt_dec);
|
||||||
static CLASS_DEVICE_ATTR(field, S_IRUGO, show_##field, NULL) \
|
NETDEVICE_SHOW(features, fmt_long_hex);
|
||||||
|
NETDEVICE_SHOW(type, fmt_dec);
|
||||||
NETDEVICE_ATTR(addr_len, fmt_dec);
|
|
||||||
NETDEVICE_ATTR(iflink, fmt_dec);
|
|
||||||
NETDEVICE_ATTR(ifindex, fmt_dec);
|
|
||||||
NETDEVICE_ATTR(features, fmt_long_hex);
|
|
||||||
NETDEVICE_ATTR(type, fmt_dec);
|
|
||||||
|
|
||||||
/* use same locking rules as GIFHWADDR ioctl's */
|
/* use same locking rules as GIFHWADDR ioctl's */
|
||||||
static ssize_t format_addr(char *buf, const unsigned char *addr, int len)
|
static ssize_t format_addr(char *buf, const unsigned char *addr, int len)
|
||||||
|
@ -136,10 +131,6 @@ static ssize_t show_carrier(struct class_device *dev, char *buf)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static CLASS_DEVICE_ATTR(address, S_IRUGO, show_address, NULL);
|
|
||||||
static CLASS_DEVICE_ATTR(broadcast, S_IRUGO, show_broadcast, NULL);
|
|
||||||
static CLASS_DEVICE_ATTR(carrier, S_IRUGO, show_carrier, NULL);
|
|
||||||
|
|
||||||
/* read-write attributes */
|
/* read-write attributes */
|
||||||
NETDEVICE_SHOW(mtu, fmt_dec);
|
NETDEVICE_SHOW(mtu, fmt_dec);
|
||||||
|
|
||||||
|
@ -153,8 +144,6 @@ static ssize_t store_mtu(struct class_device *dev, const char *buf, size_t len)
|
||||||
return netdev_store(dev, buf, len, change_mtu);
|
return netdev_store(dev, buf, len, change_mtu);
|
||||||
}
|
}
|
||||||
|
|
||||||
static CLASS_DEVICE_ATTR(mtu, S_IRUGO | S_IWUSR, show_mtu, store_mtu);
|
|
||||||
|
|
||||||
NETDEVICE_SHOW(flags, fmt_hex);
|
NETDEVICE_SHOW(flags, fmt_hex);
|
||||||
|
|
||||||
static int change_flags(struct net_device *net, unsigned long new_flags)
|
static int change_flags(struct net_device *net, unsigned long new_flags)
|
||||||
|
@ -167,8 +156,6 @@ static ssize_t store_flags(struct class_device *dev, const char *buf, size_t len
|
||||||
return netdev_store(dev, buf, len, change_flags);
|
return netdev_store(dev, buf, len, change_flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
static CLASS_DEVICE_ATTR(flags, S_IRUGO | S_IWUSR, show_flags, store_flags);
|
|
||||||
|
|
||||||
NETDEVICE_SHOW(tx_queue_len, fmt_ulong);
|
NETDEVICE_SHOW(tx_queue_len, fmt_ulong);
|
||||||
|
|
||||||
static int change_tx_queue_len(struct net_device *net, unsigned long new_len)
|
static int change_tx_queue_len(struct net_device *net, unsigned long new_len)
|
||||||
|
@ -182,9 +169,6 @@ static ssize_t store_tx_queue_len(struct class_device *dev, const char *buf, siz
|
||||||
return netdev_store(dev, buf, len, change_tx_queue_len);
|
return netdev_store(dev, buf, len, change_tx_queue_len);
|
||||||
}
|
}
|
||||||
|
|
||||||
static CLASS_DEVICE_ATTR(tx_queue_len, S_IRUGO | S_IWUSR, show_tx_queue_len,
|
|
||||||
store_tx_queue_len);
|
|
||||||
|
|
||||||
NETDEVICE_SHOW(weight, fmt_dec);
|
NETDEVICE_SHOW(weight, fmt_dec);
|
||||||
|
|
||||||
static int change_weight(struct net_device *net, unsigned long new_weight)
|
static int change_weight(struct net_device *net, unsigned long new_weight)
|
||||||
|
@ -198,24 +182,21 @@ static ssize_t store_weight(struct class_device *dev, const char *buf, size_t le
|
||||||
return netdev_store(dev, buf, len, change_weight);
|
return netdev_store(dev, buf, len, change_weight);
|
||||||
}
|
}
|
||||||
|
|
||||||
static CLASS_DEVICE_ATTR(weight, S_IRUGO | S_IWUSR, show_weight,
|
static struct class_device_attribute net_class_attributes[] = {
|
||||||
store_weight);
|
__ATTR(addr_len, S_IRUGO, show_addr_len, NULL),
|
||||||
|
__ATTR(iflink, S_IRUGO, show_iflink, NULL),
|
||||||
|
__ATTR(ifindex, S_IRUGO, show_ifindex, NULL),
|
||||||
static struct class_device_attribute *net_class_attributes[] = {
|
__ATTR(features, S_IRUGO, show_features, NULL),
|
||||||
&class_device_attr_ifindex,
|
__ATTR(type, S_IRUGO, show_type, NULL),
|
||||||
&class_device_attr_iflink,
|
__ATTR(address, S_IRUGO, show_address, NULL),
|
||||||
&class_device_attr_addr_len,
|
__ATTR(broadcast, S_IRUGO, show_broadcast, NULL),
|
||||||
&class_device_attr_tx_queue_len,
|
__ATTR(carrier, S_IRUGO, show_carrier, NULL),
|
||||||
&class_device_attr_features,
|
__ATTR(mtu, S_IRUGO | S_IWUSR, show_mtu, store_mtu),
|
||||||
&class_device_attr_mtu,
|
__ATTR(flags, S_IRUGO | S_IWUSR, show_flags, store_flags),
|
||||||
&class_device_attr_flags,
|
__ATTR(tx_queue_len, S_IRUGO | S_IWUSR, show_tx_queue_len,
|
||||||
&class_device_attr_weight,
|
store_tx_queue_len),
|
||||||
&class_device_attr_type,
|
__ATTR(weight, S_IRUGO | S_IWUSR, show_weight, store_weight),
|
||||||
&class_device_attr_address,
|
{}
|
||||||
&class_device_attr_broadcast,
|
|
||||||
&class_device_attr_carrier,
|
|
||||||
NULL
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Show a given an attribute in the statistics group */
|
/* Show a given an attribute in the statistics group */
|
||||||
|
@ -369,14 +350,14 @@ static struct attribute_group wireless_group = {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef CONFIG_HOTPLUG
|
#ifdef CONFIG_HOTPLUG
|
||||||
static int netdev_hotplug(struct class_device *cd, char **envp,
|
static int netdev_uevent(struct class_device *cd, char **envp,
|
||||||
int num_envp, char *buf, int size)
|
int num_envp, char *buf, int size)
|
||||||
{
|
{
|
||||||
struct net_device *dev = to_net_dev(cd);
|
struct net_device *dev = to_net_dev(cd);
|
||||||
int i = 0;
|
int i = 0;
|
||||||
int n;
|
int n;
|
||||||
|
|
||||||
/* pass interface in env to hotplug. */
|
/* pass interface to uevent. */
|
||||||
envp[i++] = buf;
|
envp[i++] = buf;
|
||||||
n = snprintf(buf, size, "INTERFACE=%s", dev->name) + 1;
|
n = snprintf(buf, size, "INTERFACE=%s", dev->name) + 1;
|
||||||
buf += n;
|
buf += n;
|
||||||
|
@ -407,8 +388,9 @@ static void netdev_release(struct class_device *cd)
|
||||||
static struct class net_class = {
|
static struct class net_class = {
|
||||||
.name = "net",
|
.name = "net",
|
||||||
.release = netdev_release,
|
.release = netdev_release,
|
||||||
|
.class_dev_attrs = net_class_attributes,
|
||||||
#ifdef CONFIG_HOTPLUG
|
#ifdef CONFIG_HOTPLUG
|
||||||
.hotplug = netdev_hotplug,
|
.uevent = netdev_uevent,
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -431,8 +413,6 @@ void netdev_unregister_sysfs(struct net_device * net)
|
||||||
int netdev_register_sysfs(struct net_device *net)
|
int netdev_register_sysfs(struct net_device *net)
|
||||||
{
|
{
|
||||||
struct class_device *class_dev = &(net->class_dev);
|
struct class_device *class_dev = &(net->class_dev);
|
||||||
int i;
|
|
||||||
struct class_device_attribute *attr;
|
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
class_dev->class = &net_class;
|
class_dev->class = &net_class;
|
||||||
|
@ -442,12 +422,6 @@ int netdev_register_sysfs(struct net_device *net)
|
||||||
if ((ret = class_device_register(class_dev)))
|
if ((ret = class_device_register(class_dev)))
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
for (i = 0; (attr = net_class_attributes[i]) != NULL; i++) {
|
|
||||||
if ((ret = class_device_create_file(class_dev, attr)))
|
|
||||||
goto out_unreg;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (net->get_stats &&
|
if (net->get_stats &&
|
||||||
(ret = sysfs_create_group(&class_dev->kobj, &netstat_group)))
|
(ret = sysfs_create_group(&class_dev->kobj, &netstat_group)))
|
||||||
goto out_unreg;
|
goto out_unreg;
|
||||||
|
|
|
@ -16,8 +16,10 @@
|
||||||
* use either stdint.h or inttypes.h for the rest. */
|
* use either stdint.h or inttypes.h for the rest. */
|
||||||
#if KERNEL_ELFCLASS == ELFCLASS32
|
#if KERNEL_ELFCLASS == ELFCLASS32
|
||||||
typedef Elf32_Addr kernel_ulong_t;
|
typedef Elf32_Addr kernel_ulong_t;
|
||||||
|
#define BITS_PER_LONG 32
|
||||||
#else
|
#else
|
||||||
typedef Elf64_Addr kernel_ulong_t;
|
typedef Elf64_Addr kernel_ulong_t;
|
||||||
|
#define BITS_PER_LONG 64
|
||||||
#endif
|
#endif
|
||||||
#ifdef __sun__
|
#ifdef __sun__
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
|
@ -35,6 +37,7 @@ typedef unsigned char __u8;
|
||||||
* even potentially has different endianness and word sizes, since
|
* even potentially has different endianness and word sizes, since
|
||||||
* we handle those differences explicitly below */
|
* we handle those differences explicitly below */
|
||||||
#include "../../include/linux/mod_devicetable.h"
|
#include "../../include/linux/mod_devicetable.h"
|
||||||
|
#include "../../include/linux/input.h"
|
||||||
|
|
||||||
#define ADD(str, sep, cond, field) \
|
#define ADD(str, sep, cond, field) \
|
||||||
do { \
|
do { \
|
||||||
|
@ -366,6 +369,61 @@ static int do_i2c_entry(const char *filename, struct i2c_device_id *i2c, char *a
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
|
||||||
|
|
||||||
|
static void do_input(char *alias,
|
||||||
|
kernel_ulong_t *arr, unsigned int min, unsigned int max)
|
||||||
|
{
|
||||||
|
unsigned int i;
|
||||||
|
for (i = min; i < max; i++) {
|
||||||
|
if (arr[i/BITS_PER_LONG] & (1 << (i%BITS_PER_LONG)))
|
||||||
|
sprintf(alias+strlen(alias), "%X,*", i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* input:b0v0p0e0-eXkXrXaXmXlXsXfXwX where X is comma-separated %02X. */
|
||||||
|
static int do_input_entry(const char *filename, struct input_device_id *id,
|
||||||
|
char *alias)
|
||||||
|
{
|
||||||
|
sprintf(alias, "input:");
|
||||||
|
|
||||||
|
ADD(alias, "b", id->flags&INPUT_DEVICE_ID_MATCH_BUS, id->id.bustype);
|
||||||
|
ADD(alias, "v", id->flags&INPUT_DEVICE_ID_MATCH_VENDOR, id->id.vendor);
|
||||||
|
ADD(alias, "p", id->flags&INPUT_DEVICE_ID_MATCH_PRODUCT,
|
||||||
|
id->id.product);
|
||||||
|
ADD(alias, "e", id->flags&INPUT_DEVICE_ID_MATCH_VERSION,
|
||||||
|
id->id.version);
|
||||||
|
|
||||||
|
sprintf(alias + strlen(alias), "-e*");
|
||||||
|
if (id->flags&INPUT_DEVICE_ID_MATCH_EVBIT)
|
||||||
|
do_input(alias, id->evbit, 0, EV_MAX);
|
||||||
|
sprintf(alias + strlen(alias), "k*");
|
||||||
|
if (id->flags&INPUT_DEVICE_ID_MATCH_KEYBIT)
|
||||||
|
do_input(alias, id->keybit, KEY_MIN_INTERESTING, KEY_MAX);
|
||||||
|
sprintf(alias + strlen(alias), "r*");
|
||||||
|
if (id->flags&INPUT_DEVICE_ID_MATCH_RELBIT)
|
||||||
|
do_input(alias, id->relbit, 0, REL_MAX);
|
||||||
|
sprintf(alias + strlen(alias), "a*");
|
||||||
|
if (id->flags&INPUT_DEVICE_ID_MATCH_ABSBIT)
|
||||||
|
do_input(alias, id->absbit, 0, ABS_MAX);
|
||||||
|
sprintf(alias + strlen(alias), "m*");
|
||||||
|
if (id->flags&INPUT_DEVICE_ID_MATCH_MSCIT)
|
||||||
|
do_input(alias, id->mscbit, 0, MSC_MAX);
|
||||||
|
sprintf(alias + strlen(alias), "l*");
|
||||||
|
if (id->flags&INPUT_DEVICE_ID_MATCH_LEDBIT)
|
||||||
|
do_input(alias, id->ledbit, 0, LED_MAX);
|
||||||
|
sprintf(alias + strlen(alias), "s*");
|
||||||
|
if (id->flags&INPUT_DEVICE_ID_MATCH_SNDBIT)
|
||||||
|
do_input(alias, id->sndbit, 0, SND_MAX);
|
||||||
|
sprintf(alias + strlen(alias), "f*");
|
||||||
|
if (id->flags&INPUT_DEVICE_ID_MATCH_FFBIT)
|
||||||
|
do_input(alias, id->ffbit, 0, SND_MAX);
|
||||||
|
sprintf(alias + strlen(alias), "w*");
|
||||||
|
if (id->flags&INPUT_DEVICE_ID_MATCH_SWBIT)
|
||||||
|
do_input(alias, id->swbit, 0, SW_MAX);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
/* Ignore any prefix, eg. v850 prepends _ */
|
/* Ignore any prefix, eg. v850 prepends _ */
|
||||||
static inline int sym_is(const char *symbol, const char *name)
|
static inline int sym_is(const char *symbol, const char *name)
|
||||||
{
|
{
|
||||||
|
@ -453,7 +511,9 @@ void handle_moddevtable(struct module *mod, struct elf_info *info,
|
||||||
else if (sym_is(symname, "__mod_i2c_device_table"))
|
else if (sym_is(symname, "__mod_i2c_device_table"))
|
||||||
do_table(symval, sym->st_size, sizeof(struct i2c_device_id),
|
do_table(symval, sym->st_size, sizeof(struct i2c_device_id),
|
||||||
do_i2c_entry, mod);
|
do_i2c_entry, mod);
|
||||||
|
else if (sym_is(symname, "__mod_input_device_table"))
|
||||||
|
do_table(symval, sym->st_size, sizeof(struct input_device_id),
|
||||||
|
do_input_entry, mod);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Now add out buffered information to the generated C source */
|
/* Now add out buffered information to the generated C source */
|
||||||
|
|
Loading…
Reference in a new issue