Merge git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core-2.6: UIO: fix specific device driver missing statement for depmod Driver core: remove pr_fmt() from dynamic_dev_dbg() printk driver core: prevent device_for_each_child from oopsing dynamic debug: resurrect old pr_debug() semantics as pr_devel() Driver Core: early platform driver proc: mounts_poll() make consistent to mdstat_poll sysfs: sysfs poll keep the poll rule of regular file. driver core: allow non-root users to listen to uevents driver core: fix driver_match_device sysfs: don't use global workqueue in sysfs_schedule_callback()
This commit is contained in:
commit
74a205a3f1
|
@ -169,3 +169,62 @@ three different ways to find such a match:
|
||||||
be probed later if another device registers. (Which is OK, since
|
be probed later if another device registers. (Which is OK, since
|
||||||
this interface is only for use with non-hotpluggable devices.)
|
this interface is only for use with non-hotpluggable devices.)
|
||||||
|
|
||||||
|
|
||||||
|
Early Platform Devices and Drivers
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
The early platform interfaces provide platform data to platform device
|
||||||
|
drivers early on during the system boot. The code is built on top of the
|
||||||
|
early_param() command line parsing and can be executed very early on.
|
||||||
|
|
||||||
|
Example: "earlyprintk" class early serial console in 6 steps
|
||||||
|
|
||||||
|
1. Registering early platform device data
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
The architecture code registers platform device data using the function
|
||||||
|
early_platform_add_devices(). In the case of early serial console this
|
||||||
|
should be hardware configuration for the serial port. Devices registered
|
||||||
|
at this point will later on be matched against early platform drivers.
|
||||||
|
|
||||||
|
2. Parsing kernel command line
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
The architecture code calls parse_early_param() to parse the kernel
|
||||||
|
command line. This will execute all matching early_param() callbacks.
|
||||||
|
User specified early platform devices will be registered at this point.
|
||||||
|
For the early serial console case the user can specify port on the
|
||||||
|
kernel command line as "earlyprintk=serial.0" where "earlyprintk" is
|
||||||
|
the class string, "serial" is the name of the platfrom driver and
|
||||||
|
0 is the platform device id. If the id is -1 then the dot and the
|
||||||
|
id can be omitted.
|
||||||
|
|
||||||
|
3. Installing early platform drivers belonging to a certain class
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
The architecture code may optionally force registration of all early
|
||||||
|
platform drivers belonging to a certain class using the function
|
||||||
|
early_platform_driver_register_all(). User specified devices from
|
||||||
|
step 2 have priority over these. This step is omitted by the serial
|
||||||
|
driver example since the early serial driver code should be disabled
|
||||||
|
unless the user has specified port on the kernel command line.
|
||||||
|
|
||||||
|
4. Early platform driver registration
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
Compiled-in platform drivers making use of early_platform_init() are
|
||||||
|
automatically registered during step 2 or 3. The serial driver example
|
||||||
|
should use early_platform_init("earlyprintk", &platform_driver).
|
||||||
|
|
||||||
|
5. Probing of early platform drivers belonging to a certain class
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
The architecture code calls early_platform_driver_probe() to match
|
||||||
|
registered early platform devices associated with a certain class with
|
||||||
|
registered early platform drivers. Matched devices will get probed().
|
||||||
|
This step can be executed at any point during the early boot. As soon
|
||||||
|
as possible may be good for the serial port case.
|
||||||
|
|
||||||
|
6. Inside the early platform driver probe()
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
The driver code needs to take special care during early boot, especially
|
||||||
|
when it comes to memory allocation and interrupt registration. The code
|
||||||
|
in the probe() function can use is_early_platform_device() to check if
|
||||||
|
it is called at early platform device or at the regular platform device
|
||||||
|
time. The early serial driver performs register_console() at this point.
|
||||||
|
|
||||||
|
For further information, see <linux/platform_device.h>.
|
||||||
|
|
|
@ -115,7 +115,7 @@ extern int driver_probe_device(struct device_driver *drv, struct device *dev);
|
||||||
static inline int driver_match_device(struct device_driver *drv,
|
static inline int driver_match_device(struct device_driver *drv,
|
||||||
struct device *dev)
|
struct device *dev)
|
||||||
{
|
{
|
||||||
return drv->bus->match && drv->bus->match(dev, drv);
|
return drv->bus->match ? drv->bus->match(dev, drv) : 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
extern void sysdev_shutdown(void);
|
extern void sysdev_shutdown(void);
|
||||||
|
|
|
@ -1142,6 +1142,9 @@ int device_for_each_child(struct device *parent, void *data,
|
||||||
struct device *child;
|
struct device *child;
|
||||||
int error = 0;
|
int error = 0;
|
||||||
|
|
||||||
|
if (!parent->p)
|
||||||
|
return 0;
|
||||||
|
|
||||||
klist_iter_init(&parent->p->klist_children, &i);
|
klist_iter_init(&parent->p->klist_children, &i);
|
||||||
while ((child = next_device(&i)) && !error)
|
while ((child = next_device(&i)) && !error)
|
||||||
error = fn(child, data);
|
error = fn(child, data);
|
||||||
|
|
|
@ -990,6 +990,8 @@ int __init platform_bus_init(void)
|
||||||
{
|
{
|
||||||
int error;
|
int error;
|
||||||
|
|
||||||
|
early_platform_cleanup();
|
||||||
|
|
||||||
error = device_register(&platform_bus);
|
error = device_register(&platform_bus);
|
||||||
if (error)
|
if (error)
|
||||||
return error;
|
return error;
|
||||||
|
@ -1020,3 +1022,240 @@ u64 dma_get_required_mask(struct device *dev)
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(dma_get_required_mask);
|
EXPORT_SYMBOL_GPL(dma_get_required_mask);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
static __initdata LIST_HEAD(early_platform_driver_list);
|
||||||
|
static __initdata LIST_HEAD(early_platform_device_list);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* early_platform_driver_register
|
||||||
|
* @edrv: early_platform driver structure
|
||||||
|
* @buf: string passed from early_param()
|
||||||
|
*/
|
||||||
|
int __init early_platform_driver_register(struct early_platform_driver *epdrv,
|
||||||
|
char *buf)
|
||||||
|
{
|
||||||
|
unsigned long index;
|
||||||
|
int n;
|
||||||
|
|
||||||
|
/* Simply add the driver to the end of the global list.
|
||||||
|
* Drivers will by default be put on the list in compiled-in order.
|
||||||
|
*/
|
||||||
|
if (!epdrv->list.next) {
|
||||||
|
INIT_LIST_HEAD(&epdrv->list);
|
||||||
|
list_add_tail(&epdrv->list, &early_platform_driver_list);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If the user has specified device then make sure the driver
|
||||||
|
* gets prioritized. The driver of the last device specified on
|
||||||
|
* command line will be put first on the list.
|
||||||
|
*/
|
||||||
|
n = strlen(epdrv->pdrv->driver.name);
|
||||||
|
if (buf && !strncmp(buf, epdrv->pdrv->driver.name, n)) {
|
||||||
|
list_move(&epdrv->list, &early_platform_driver_list);
|
||||||
|
|
||||||
|
if (!strcmp(buf, epdrv->pdrv->driver.name))
|
||||||
|
epdrv->requested_id = -1;
|
||||||
|
else if (buf[n] == '.' && strict_strtoul(&buf[n + 1], 10,
|
||||||
|
&index) == 0)
|
||||||
|
epdrv->requested_id = index;
|
||||||
|
else
|
||||||
|
epdrv->requested_id = EARLY_PLATFORM_ID_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* early_platform_add_devices - add a numbers of early platform devices
|
||||||
|
* @devs: array of early platform devices to add
|
||||||
|
* @num: number of early platform devices in array
|
||||||
|
*/
|
||||||
|
void __init early_platform_add_devices(struct platform_device **devs, int num)
|
||||||
|
{
|
||||||
|
struct device *dev;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
/* simply add the devices to list */
|
||||||
|
for (i = 0; i < num; i++) {
|
||||||
|
dev = &devs[i]->dev;
|
||||||
|
|
||||||
|
if (!dev->devres_head.next) {
|
||||||
|
INIT_LIST_HEAD(&dev->devres_head);
|
||||||
|
list_add_tail(&dev->devres_head,
|
||||||
|
&early_platform_device_list);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* early_platform_driver_register_all
|
||||||
|
* @class_str: string to identify early platform driver class
|
||||||
|
*/
|
||||||
|
void __init early_platform_driver_register_all(char *class_str)
|
||||||
|
{
|
||||||
|
/* The "class_str" parameter may or may not be present on the kernel
|
||||||
|
* command line. If it is present then there may be more than one
|
||||||
|
* matching parameter.
|
||||||
|
*
|
||||||
|
* Since we register our early platform drivers using early_param()
|
||||||
|
* we need to make sure that they also get registered in the case
|
||||||
|
* when the parameter is missing from the kernel command line.
|
||||||
|
*
|
||||||
|
* We use parse_early_options() to make sure the early_param() gets
|
||||||
|
* called at least once. The early_param() may be called more than
|
||||||
|
* once since the name of the preferred device may be specified on
|
||||||
|
* the kernel command line. early_platform_driver_register() handles
|
||||||
|
* this case for us.
|
||||||
|
*/
|
||||||
|
parse_early_options(class_str);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* early_platform_match
|
||||||
|
* @edrv: early platform driver structure
|
||||||
|
* @id: id to match against
|
||||||
|
*/
|
||||||
|
static __init struct platform_device *
|
||||||
|
early_platform_match(struct early_platform_driver *epdrv, int id)
|
||||||
|
{
|
||||||
|
struct platform_device *pd;
|
||||||
|
|
||||||
|
list_for_each_entry(pd, &early_platform_device_list, dev.devres_head)
|
||||||
|
if (platform_match(&pd->dev, &epdrv->pdrv->driver))
|
||||||
|
if (pd->id == id)
|
||||||
|
return pd;
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* early_platform_left
|
||||||
|
* @edrv: early platform driver structure
|
||||||
|
* @id: return true if id or above exists
|
||||||
|
*/
|
||||||
|
static __init int early_platform_left(struct early_platform_driver *epdrv,
|
||||||
|
int id)
|
||||||
|
{
|
||||||
|
struct platform_device *pd;
|
||||||
|
|
||||||
|
list_for_each_entry(pd, &early_platform_device_list, dev.devres_head)
|
||||||
|
if (platform_match(&pd->dev, &epdrv->pdrv->driver))
|
||||||
|
if (pd->id >= id)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* early_platform_driver_probe_id
|
||||||
|
* @class_str: string to identify early platform driver class
|
||||||
|
* @id: id to match against
|
||||||
|
* @nr_probe: number of platform devices to successfully probe before exiting
|
||||||
|
*/
|
||||||
|
static int __init early_platform_driver_probe_id(char *class_str,
|
||||||
|
int id,
|
||||||
|
int nr_probe)
|
||||||
|
{
|
||||||
|
struct early_platform_driver *epdrv;
|
||||||
|
struct platform_device *match;
|
||||||
|
int match_id;
|
||||||
|
int n = 0;
|
||||||
|
int left = 0;
|
||||||
|
|
||||||
|
list_for_each_entry(epdrv, &early_platform_driver_list, list) {
|
||||||
|
/* only use drivers matching our class_str */
|
||||||
|
if (strcmp(class_str, epdrv->class_str))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (id == -2) {
|
||||||
|
match_id = epdrv->requested_id;
|
||||||
|
left = 1;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
match_id = id;
|
||||||
|
left += early_platform_left(epdrv, id);
|
||||||
|
|
||||||
|
/* skip requested id */
|
||||||
|
switch (epdrv->requested_id) {
|
||||||
|
case EARLY_PLATFORM_ID_ERROR:
|
||||||
|
case EARLY_PLATFORM_ID_UNSET:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
if (epdrv->requested_id == id)
|
||||||
|
match_id = EARLY_PLATFORM_ID_UNSET;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (match_id) {
|
||||||
|
case EARLY_PLATFORM_ID_ERROR:
|
||||||
|
pr_warning("%s: unable to parse %s parameter\n",
|
||||||
|
class_str, epdrv->pdrv->driver.name);
|
||||||
|
/* fall-through */
|
||||||
|
case EARLY_PLATFORM_ID_UNSET:
|
||||||
|
match = NULL;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
match = early_platform_match(epdrv, match_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (match) {
|
||||||
|
if (epdrv->pdrv->probe(match))
|
||||||
|
pr_warning("%s: unable to probe %s early.\n",
|
||||||
|
class_str, match->name);
|
||||||
|
else
|
||||||
|
n++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (n >= nr_probe)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (left)
|
||||||
|
return n;
|
||||||
|
else
|
||||||
|
return -ENODEV;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* early_platform_driver_probe
|
||||||
|
* @class_str: string to identify early platform driver class
|
||||||
|
* @nr_probe: number of platform devices to successfully probe before exiting
|
||||||
|
* @user_only: only probe user specified early platform devices
|
||||||
|
*/
|
||||||
|
int __init early_platform_driver_probe(char *class_str,
|
||||||
|
int nr_probe,
|
||||||
|
int user_only)
|
||||||
|
{
|
||||||
|
int k, n, i;
|
||||||
|
|
||||||
|
n = 0;
|
||||||
|
for (i = -2; n < nr_probe; i++) {
|
||||||
|
k = early_platform_driver_probe_id(class_str, i, nr_probe - n);
|
||||||
|
|
||||||
|
if (k < 0)
|
||||||
|
break;
|
||||||
|
|
||||||
|
n += k;
|
||||||
|
|
||||||
|
if (user_only)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* early_platform_cleanup - clean up early platform code
|
||||||
|
*/
|
||||||
|
void __init early_platform_cleanup(void)
|
||||||
|
{
|
||||||
|
struct platform_device *pd, *pd2;
|
||||||
|
|
||||||
|
/* clean up the devres list used to chain devices */
|
||||||
|
list_for_each_entry_safe(pd, pd2, &early_platform_device_list,
|
||||||
|
dev.devres_head) {
|
||||||
|
list_del(&pd->dev.devres_head);
|
||||||
|
memset(&pd->dev.devres_head, 0, sizeof(pd->dev.devres_head));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -147,5 +147,6 @@ static void __exit hilscher_exit_module(void)
|
||||||
module_init(hilscher_init_module);
|
module_init(hilscher_init_module);
|
||||||
module_exit(hilscher_exit_module);
|
module_exit(hilscher_exit_module);
|
||||||
|
|
||||||
|
MODULE_DEVICE_TABLE(pci, hilscher_pci_ids);
|
||||||
MODULE_LICENSE("GPL v2");
|
MODULE_LICENSE("GPL v2");
|
||||||
MODULE_AUTHOR("Hans J. Koch, Benedikt Spranger");
|
MODULE_AUTHOR("Hans J. Koch, Benedikt Spranger");
|
||||||
|
|
|
@ -648,14 +648,14 @@ static unsigned mounts_poll(struct file *file, poll_table *wait)
|
||||||
{
|
{
|
||||||
struct proc_mounts *p = file->private_data;
|
struct proc_mounts *p = file->private_data;
|
||||||
struct mnt_namespace *ns = p->ns;
|
struct mnt_namespace *ns = p->ns;
|
||||||
unsigned res = 0;
|
unsigned res = POLLIN | POLLRDNORM;
|
||||||
|
|
||||||
poll_wait(file, &ns->poll, wait);
|
poll_wait(file, &ns->poll, wait);
|
||||||
|
|
||||||
spin_lock(&vfsmount_lock);
|
spin_lock(&vfsmount_lock);
|
||||||
if (p->event != ns->event) {
|
if (p->event != ns->event) {
|
||||||
p->event = ns->event;
|
p->event = ns->event;
|
||||||
res = POLLERR;
|
res |= POLLERR | POLLPRI;
|
||||||
}
|
}
|
||||||
spin_unlock(&vfsmount_lock);
|
spin_unlock(&vfsmount_lock);
|
||||||
|
|
||||||
|
|
|
@ -446,11 +446,11 @@ static unsigned int sysfs_poll(struct file *filp, poll_table *wait)
|
||||||
if (buffer->event != atomic_read(&od->event))
|
if (buffer->event != atomic_read(&od->event))
|
||||||
goto trigger;
|
goto trigger;
|
||||||
|
|
||||||
return 0;
|
return DEFAULT_POLLMASK;
|
||||||
|
|
||||||
trigger:
|
trigger:
|
||||||
buffer->needs_read_fill = 1;
|
buffer->needs_read_fill = 1;
|
||||||
return POLLERR|POLLPRI;
|
return DEFAULT_POLLMASK|POLLERR|POLLPRI;
|
||||||
}
|
}
|
||||||
|
|
||||||
void sysfs_notify_dirent(struct sysfs_dirent *sd)
|
void sysfs_notify_dirent(struct sysfs_dirent *sd)
|
||||||
|
@ -667,6 +667,7 @@ struct sysfs_schedule_callback_struct {
|
||||||
struct work_struct work;
|
struct work_struct work;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static struct workqueue_struct *sysfs_workqueue;
|
||||||
static DEFINE_MUTEX(sysfs_workq_mutex);
|
static DEFINE_MUTEX(sysfs_workq_mutex);
|
||||||
static LIST_HEAD(sysfs_workq);
|
static LIST_HEAD(sysfs_workq);
|
||||||
static void sysfs_schedule_callback_work(struct work_struct *work)
|
static void sysfs_schedule_callback_work(struct work_struct *work)
|
||||||
|
@ -715,11 +716,20 @@ int sysfs_schedule_callback(struct kobject *kobj, void (*func)(void *),
|
||||||
mutex_lock(&sysfs_workq_mutex);
|
mutex_lock(&sysfs_workq_mutex);
|
||||||
list_for_each_entry_safe(ss, tmp, &sysfs_workq, workq_list)
|
list_for_each_entry_safe(ss, tmp, &sysfs_workq, workq_list)
|
||||||
if (ss->kobj == kobj) {
|
if (ss->kobj == kobj) {
|
||||||
|
module_put(owner);
|
||||||
mutex_unlock(&sysfs_workq_mutex);
|
mutex_unlock(&sysfs_workq_mutex);
|
||||||
return -EAGAIN;
|
return -EAGAIN;
|
||||||
}
|
}
|
||||||
mutex_unlock(&sysfs_workq_mutex);
|
mutex_unlock(&sysfs_workq_mutex);
|
||||||
|
|
||||||
|
if (sysfs_workqueue == NULL) {
|
||||||
|
sysfs_workqueue = create_workqueue("sysfsd");
|
||||||
|
if (sysfs_workqueue == NULL) {
|
||||||
|
module_put(owner);
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ss = kmalloc(sizeof(*ss), GFP_KERNEL);
|
ss = kmalloc(sizeof(*ss), GFP_KERNEL);
|
||||||
if (!ss) {
|
if (!ss) {
|
||||||
module_put(owner);
|
module_put(owner);
|
||||||
|
@ -735,7 +745,7 @@ int sysfs_schedule_callback(struct kobject *kobj, void (*func)(void *),
|
||||||
mutex_lock(&sysfs_workq_mutex);
|
mutex_lock(&sysfs_workq_mutex);
|
||||||
list_add_tail(&ss->workq_list, &sysfs_workq);
|
list_add_tail(&ss->workq_list, &sysfs_workq);
|
||||||
mutex_unlock(&sysfs_workq_mutex);
|
mutex_unlock(&sysfs_workq_mutex);
|
||||||
schedule_work(&ss->work);
|
queue_work(sysfs_workqueue, &ss->work);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(sysfs_schedule_callback);
|
EXPORT_SYMBOL_GPL(sysfs_schedule_callback);
|
||||||
|
|
|
@ -70,7 +70,7 @@ extern int ddebug_remove_module(char *mod_name);
|
||||||
DEBUG_HASH2, __LINE__, _DPRINTK_FLAGS_DEFAULT }; \
|
DEBUG_HASH2, __LINE__, _DPRINTK_FLAGS_DEFAULT }; \
|
||||||
if (__dynamic_dbg_enabled(descriptor)) \
|
if (__dynamic_dbg_enabled(descriptor)) \
|
||||||
dev_printk(KERN_DEBUG, dev, \
|
dev_printk(KERN_DEBUG, dev, \
|
||||||
KBUILD_MODNAME ": " pr_fmt(fmt),\
|
KBUILD_MODNAME ": " fmt, \
|
||||||
##__VA_ARGS__); \
|
##__VA_ARGS__); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
|
|
|
@ -247,6 +247,7 @@ struct obs_kernel_param {
|
||||||
|
|
||||||
/* Relies on boot_command_line being set */
|
/* Relies on boot_command_line being set */
|
||||||
void __init parse_early_param(void);
|
void __init parse_early_param(void);
|
||||||
|
void __init parse_early_options(char *cmdline);
|
||||||
#endif /* __ASSEMBLY__ */
|
#endif /* __ASSEMBLY__ */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -377,6 +377,15 @@ static inline char *pack_hex_byte(char *buf, u8 byte)
|
||||||
#define pr_cont(fmt, ...) \
|
#define pr_cont(fmt, ...) \
|
||||||
printk(KERN_CONT fmt, ##__VA_ARGS__)
|
printk(KERN_CONT fmt, ##__VA_ARGS__)
|
||||||
|
|
||||||
|
/* pr_devel() should produce zero code unless DEBUG is defined */
|
||||||
|
#ifdef DEBUG
|
||||||
|
#define pr_devel(fmt, ...) \
|
||||||
|
printk(KERN_DEBUG pr_fmt(fmt), ##__VA_ARGS__)
|
||||||
|
#else
|
||||||
|
#define pr_devel(fmt, ...) \
|
||||||
|
({ if (0) printk(KERN_DEBUG pr_fmt(fmt), ##__VA_ARGS__); 0; })
|
||||||
|
#endif
|
||||||
|
|
||||||
/* If you are writing a driver, please use dev_dbg instead */
|
/* If you are writing a driver, please use dev_dbg instead */
|
||||||
#if defined(DEBUG)
|
#if defined(DEBUG)
|
||||||
#define pr_debug(fmt, ...) \
|
#define pr_debug(fmt, ...) \
|
||||||
|
|
|
@ -77,4 +77,46 @@ extern int platform_driver_probe(struct platform_driver *driver,
|
||||||
#define platform_get_drvdata(_dev) dev_get_drvdata(&(_dev)->dev)
|
#define platform_get_drvdata(_dev) dev_get_drvdata(&(_dev)->dev)
|
||||||
#define platform_set_drvdata(_dev,data) dev_set_drvdata(&(_dev)->dev, (data))
|
#define platform_set_drvdata(_dev,data) dev_set_drvdata(&(_dev)->dev, (data))
|
||||||
|
|
||||||
|
/* early platform driver interface */
|
||||||
|
struct early_platform_driver {
|
||||||
|
const char *class_str;
|
||||||
|
struct platform_driver *pdrv;
|
||||||
|
struct list_head list;
|
||||||
|
int requested_id;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define EARLY_PLATFORM_ID_UNSET -2
|
||||||
|
#define EARLY_PLATFORM_ID_ERROR -3
|
||||||
|
|
||||||
|
extern int early_platform_driver_register(struct early_platform_driver *epdrv,
|
||||||
|
char *buf);
|
||||||
|
extern void early_platform_add_devices(struct platform_device **devs, int num);
|
||||||
|
|
||||||
|
static inline int is_early_platform_device(struct platform_device *pdev)
|
||||||
|
{
|
||||||
|
return !pdev->dev.driver;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern void early_platform_driver_register_all(char *class_str);
|
||||||
|
extern int early_platform_driver_probe(char *class_str,
|
||||||
|
int nr_probe, int user_only);
|
||||||
|
extern void early_platform_cleanup(void);
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef MODULE
|
||||||
|
#define early_platform_init(class_string, platform_driver) \
|
||||||
|
static __initdata struct early_platform_driver early_driver = { \
|
||||||
|
.class_str = class_string, \
|
||||||
|
.pdrv = platform_driver, \
|
||||||
|
.requested_id = EARLY_PLATFORM_ID_UNSET, \
|
||||||
|
}; \
|
||||||
|
static int __init early_platform_driver_setup_func(char *buf) \
|
||||||
|
{ \
|
||||||
|
return early_platform_driver_register(&early_driver, buf); \
|
||||||
|
} \
|
||||||
|
early_param(class_string, early_platform_driver_setup_func)
|
||||||
|
#else /* MODULE */
|
||||||
|
#define early_platform_init(class_string, platform_driver)
|
||||||
|
#endif /* MODULE */
|
||||||
|
|
||||||
#endif /* _PLATFORM_DEVICE_H_ */
|
#endif /* _PLATFORM_DEVICE_H_ */
|
||||||
|
|
|
@ -492,6 +492,11 @@ static int __init do_early_param(char *param, char *val)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void __init parse_early_options(char *cmdline)
|
||||||
|
{
|
||||||
|
parse_args("early options", cmdline, NULL, 0, do_early_param);
|
||||||
|
}
|
||||||
|
|
||||||
/* Arch code calls this early on, or if not, just before other parsing. */
|
/* Arch code calls this early on, or if not, just before other parsing. */
|
||||||
void __init parse_early_param(void)
|
void __init parse_early_param(void)
|
||||||
{
|
{
|
||||||
|
@ -503,7 +508,7 @@ void __init parse_early_param(void)
|
||||||
|
|
||||||
/* All fall through to do_early_param. */
|
/* All fall through to do_early_param. */
|
||||||
strlcpy(tmp_cmdline, boot_command_line, COMMAND_LINE_SIZE);
|
strlcpy(tmp_cmdline, boot_command_line, COMMAND_LINE_SIZE);
|
||||||
parse_args("early options", tmp_cmdline, NULL, 0, do_early_param);
|
parse_early_options(tmp_cmdline);
|
||||||
done = 1;
|
done = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -328,7 +328,7 @@ static int __init kobject_uevent_init(void)
|
||||||
"kobject_uevent: unable to create netlink socket!\n");
|
"kobject_uevent: unable to create netlink socket!\n");
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
}
|
}
|
||||||
|
netlink_set_nonroot(NETLINK_KOBJECT_UEVENT, NL_NONROOT_RECV);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue