mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-28 02:32:09 -04:00
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
13 changed files with 378 additions and 9 deletions
|
|
@ -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,
|
||||
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);
|
||||
|
|
|
|||
|
|
@ -1142,6 +1142,9 @@ int device_for_each_child(struct device *parent, void *data,
|
|||
struct device *child;
|
||||
int error = 0;
|
||||
|
||||
if (!parent->p)
|
||||
return 0;
|
||||
|
||||
klist_iter_init(&parent->p->klist_children, &i);
|
||||
while ((child = next_device(&i)) && !error)
|
||||
error = fn(child, data);
|
||||
|
|
|
|||
|
|
@ -990,6 +990,8 @@ int __init platform_bus_init(void)
|
|||
{
|
||||
int error;
|
||||
|
||||
early_platform_cleanup();
|
||||
|
||||
error = device_register(&platform_bus);
|
||||
if (error)
|
||||
return error;
|
||||
|
|
@ -1020,3 +1022,240 @@ u64 dma_get_required_mask(struct device *dev)
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(dma_get_required_mask);
|
||||
#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_exit(hilscher_exit_module);
|
||||
|
||||
MODULE_DEVICE_TABLE(pci, hilscher_pci_ids);
|
||||
MODULE_LICENSE("GPL v2");
|
||||
MODULE_AUTHOR("Hans J. Koch, Benedikt Spranger");
|
||||
|
|
|
|||
Loading…
Reference in a new issue