summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/base/platform.c23
-rw-r--r--include/linux/mod_devicetable.h9
-rw-r--r--include/linux/platform_device.h6
-rw-r--r--scripts/mod/file2alias.c12
4 files changed, 49 insertions, 1 deletions
diff --git a/drivers/base/platform.c b/drivers/base/platform.c
index 62a8768d96b..ec993aa6a2c 100644
--- a/drivers/base/platform.c
+++ b/drivers/base/platform.c
@@ -584,10 +584,25 @@ static int platform_uevent(struct device *dev, struct kobj_uevent_env *env)
{
struct platform_device *pdev = to_platform_device(dev);
- add_uevent_var(env, "MODALIAS=platform:%s", pdev->name);
+ add_uevent_var(env, "MODALIAS=%s%s", PLATFORM_MODULE_PREFIX,
+ (pdev->id_entry) ? pdev->id_entry->name : pdev->name);
return 0;
}
+static const struct platform_device_id *platform_match_id(
+ struct platform_device_id *id,
+ struct platform_device *pdev)
+{
+ while (id->name[0]) {
+ if (strcmp(pdev->name, id->name) == 0) {
+ pdev->id_entry = id;
+ return id;
+ }
+ id++;
+ }
+ return NULL;
+}
+
/**
* platform_match - bind platform device to platform driver.
* @dev: device.
@@ -604,7 +619,13 @@ static int platform_uevent(struct device *dev, struct kobj_uevent_env *env)
static int platform_match(struct device *dev, struct device_driver *drv)
{
struct platform_device *pdev = to_platform_device(dev);
+ struct platform_driver *pdrv = to_platform_driver(drv);
+
+ /* match against the id table first */
+ if (pdrv->id_table)
+ return platform_match_id(pdrv->id_table, pdev) != NULL;
+ /* fall-back to driver name match */
return (strcmp(pdev->name, drv->name) == 0);
}
diff --git a/include/linux/mod_devicetable.h b/include/linux/mod_devicetable.h
index fde86671f48..1bf5900ffe4 100644
--- a/include/linux/mod_devicetable.h
+++ b/include/linux/mod_devicetable.h
@@ -454,4 +454,13 @@ struct dmi_system_id {
#define DMI_MATCH(a, b) { a, b }
+#define PLATFORM_NAME_SIZE 20
+#define PLATFORM_MODULE_PREFIX "platform:"
+
+struct platform_device_id {
+ char name[PLATFORM_NAME_SIZE];
+ kernel_ulong_t driver_data
+ __attribute__((aligned(sizeof(kernel_ulong_t))));
+};
+
#endif /* LINUX_MOD_DEVICETABLE_H */
diff --git a/include/linux/platform_device.h b/include/linux/platform_device.h
index 9a342699c60..76aef7be32a 100644
--- a/include/linux/platform_device.h
+++ b/include/linux/platform_device.h
@@ -12,6 +12,7 @@
#define _PLATFORM_DEVICE_H_
#include <linux/device.h>
+#include <linux/mod_devicetable.h>
struct platform_device {
const char * name;
@@ -19,8 +20,12 @@ struct platform_device {
struct device dev;
u32 num_resources;
struct resource * resource;
+
+ struct platform_device_id *id_entry;
};
+#define platform_get_device_id(pdev) ((pdev)->id_entry)
+
#define to_platform_device(x) container_of((x), struct platform_device, dev)
extern int platform_device_register(struct platform_device *);
@@ -56,6 +61,7 @@ struct platform_driver {
int (*resume_early)(struct platform_device *);
int (*resume)(struct platform_device *);
struct device_driver driver;
+ struct platform_device_id *id_table;
};
extern int platform_driver_register(struct platform_driver *);
diff --git a/scripts/mod/file2alias.c b/scripts/mod/file2alias.c
index 4eea60b1693..a3344285ccf 100644
--- a/scripts/mod/file2alias.c
+++ b/scripts/mod/file2alias.c
@@ -710,6 +710,14 @@ static int do_dmi_entry(const char *filename, struct dmi_system_id *id,
strcat(alias, ":");
return 1;
}
+
+static int do_platform_entry(const char *filename,
+ struct platform_device_id *id, char *alias)
+{
+ sprintf(alias, PLATFORM_MODULE_PREFIX "%s", id->name);
+ return 1;
+}
+
/* Ignore any prefix, eg. some architectures prepend _ */
static inline int sym_is(const char *symbol, const char *name)
{
@@ -849,6 +857,10 @@ void handle_moddevtable(struct module *mod, struct elf_info *info,
do_table(symval, sym->st_size,
sizeof(struct dmi_system_id), "dmi",
do_dmi_entry, mod);
+ else if (sym_is(symname, "__mod_platform_device_table"))
+ do_table(symval, sym->st_size,
+ sizeof(struct platform_device_id), "platform",
+ do_platform_entry, mod);
free(zeros);
}