Skip to content

Commit

Permalink
Merge branch 'acpi-modules'
Browse files Browse the repository at this point in the history
* acpi-modules:
  platform: introduce OF style 'modalias' support for platform bus
  ACPI: fix module autoloading for ACPI enumerated devices
  ACPI: add module autoloading support for ACPI enumerated devices
  ACPI: fix create_modalias() return value handling
  • Loading branch information
Rafael J. Wysocki committed Jan 17, 2014
2 parents 8341ecc + b9f7306 commit bc411b8
Show file tree
Hide file tree
Showing 7 changed files with 127 additions and 7 deletions.
73 changes: 67 additions & 6 deletions drivers/acpi/scan.c
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,9 @@ int acpi_scan_add_handler_with_hotplug(struct acpi_scan_handler *handler,
* Creates hid/cid(s) string needed for modalias and uevent
* e.g. on a device with hid:IBM0001 and cid:ACPI0001 you get:
* char *modalias: "acpi:IBM0001:ACPI0001"
* Return: 0: no _HID and no _CID
* -EINVAL: output error
* -ENOMEM: output is truncated
*/
static int create_modalias(struct acpi_device *acpi_dev, char *modalias,
int size)
Expand All @@ -102,8 +105,10 @@ static int create_modalias(struct acpi_device *acpi_dev, char *modalias,

list_for_each_entry(id, &acpi_dev->pnp.ids, list) {
count = snprintf(&modalias[len], size, "%s:", id->id);
if (count < 0 || count >= size)
return -EINVAL;
if (count < 0)
return EINVAL;
if (count >= size)
return -ENOMEM;
len += count;
size -= count;
}
Expand All @@ -112,15 +117,71 @@ static int create_modalias(struct acpi_device *acpi_dev, char *modalias,
return len;
}

/*
* Creates uevent modalias field for ACPI enumerated devices.
* Because the other buses does not support ACPI HIDs & CIDs.
* e.g. for a device with hid:IBM0001 and cid:ACPI0001 you get:
* "acpi:IBM0001:ACPI0001"
*/
int acpi_device_uevent_modalias(struct device *dev, struct kobj_uevent_env *env)
{
struct acpi_device *acpi_dev;
int len;

acpi_dev = ACPI_COMPANION(dev);
if (!acpi_dev)
return -ENODEV;

/* Fall back to bus specific way of modalias exporting */
if (list_empty(&acpi_dev->pnp.ids))
return -ENODEV;

if (add_uevent_var(env, "MODALIAS="))
return -ENOMEM;
len = create_modalias(acpi_dev, &env->buf[env->buflen - 1],
sizeof(env->buf) - env->buflen);
if (len <= 0)
return len;
env->buflen += len;
return 0;
}
EXPORT_SYMBOL_GPL(acpi_device_uevent_modalias);

/*
* Creates modalias sysfs attribute for ACPI enumerated devices.
* Because the other buses does not support ACPI HIDs & CIDs.
* e.g. for a device with hid:IBM0001 and cid:ACPI0001 you get:
* "acpi:IBM0001:ACPI0001"
*/
int acpi_device_modalias(struct device *dev, char *buf, int size)
{
struct acpi_device *acpi_dev;
int len;

acpi_dev = ACPI_COMPANION(dev);
if (!acpi_dev)
return -ENODEV;

/* Fall back to bus specific way of modalias exporting */
if (list_empty(&acpi_dev->pnp.ids))
return -ENODEV;

len = create_modalias(acpi_dev, buf, size -1);
if (len <= 0)
return len;
buf[len++] = '\n';
return len;
}
EXPORT_SYMBOL_GPL(acpi_device_modalias);

static ssize_t
acpi_device_modalias_show(struct device *dev, struct device_attribute *attr, char *buf) {
struct acpi_device *acpi_dev = to_acpi_device(dev);
int len;

/* Device has no HID and no CID or string is >1024 */
len = create_modalias(acpi_dev, buf, 1024);
if (len <= 0)
return 0;
return len;
buf[len++] = '\n';
return len;
}
Expand Down Expand Up @@ -839,8 +900,8 @@ static int acpi_device_uevent(struct device *dev, struct kobj_uevent_env *env)
return -ENOMEM;
len = create_modalias(acpi_dev, &env->buf[env->buflen - 1],
sizeof(env->buf) - env->buflen);
if (len >= (sizeof(env->buf) - env->buflen))
return -ENOMEM;
if (len <= 0)
return len;
env->buflen += len;
return 0;
}
Expand Down
16 changes: 15 additions & 1 deletion drivers/base/platform.c
Original file line number Diff line number Diff line change
Expand Up @@ -677,7 +677,17 @@ static ssize_t modalias_show(struct device *dev, struct device_attribute *a,
char *buf)
{
struct platform_device *pdev = to_platform_device(dev);
int len = snprintf(buf, PAGE_SIZE, "platform:%s\n", pdev->name);
int len;

len = of_device_get_modalias(dev, buf, PAGE_SIZE -1);
if (len != -ENODEV)
return len;

len = acpi_device_modalias(dev, buf, PAGE_SIZE -1);
if (len != -ENODEV)
return len;

len = snprintf(buf, PAGE_SIZE, "platform:%s\n", pdev->name);

return (len >= PAGE_SIZE) ? (PAGE_SIZE - 1) : len;
}
Expand All @@ -699,6 +709,10 @@ static int platform_uevent(struct device *dev, struct kobj_uevent_env *env)
if (rc != -ENODEV)
return rc;

rc = acpi_device_uevent_modalias(dev, env);
if (rc != -ENODEV)
return rc;

add_uevent_var(env, "MODALIAS=%s%s", PLATFORM_MODULE_PREFIX,
pdev->name);
return 0;
Expand Down
11 changes: 11 additions & 0 deletions drivers/i2c/i2c-core.c
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,11 @@ static int i2c_device_match(struct device *dev, struct device_driver *drv)
static int i2c_device_uevent(struct device *dev, struct kobj_uevent_env *env)
{
struct i2c_client *client = to_i2c_client(dev);
int rc;

rc = acpi_device_uevent_modalias(dev, env);
if (rc != -ENODEV)
return rc;

if (add_uevent_var(env, "MODALIAS=%s%s",
I2C_MODULE_PREFIX, client->name))
Expand Down Expand Up @@ -409,6 +414,12 @@ static ssize_t
show_modalias(struct device *dev, struct device_attribute *attr, char *buf)
{
struct i2c_client *client = to_i2c_client(dev);
int len;

len = acpi_device_modalias(dev, buf, PAGE_SIZE -1);
if (len != -ENODEV)
return len;

return sprintf(buf, "%s%s\n", I2C_MODULE_PREFIX, client->name);
}

Expand Down
3 changes: 3 additions & 0 deletions drivers/of/device.c
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,9 @@ ssize_t of_device_get_modalias(struct device *dev, char *str, ssize_t len)
int cplen, i;
ssize_t tsize, csize, repend;

if ((!dev) || (!dev->of_node))
return -ENODEV;

/* Name & Type */
csize = snprintf(str, len, "of:N%sT%s", dev->of_node->name,
dev->of_node->type);
Expand Down
10 changes: 10 additions & 0 deletions drivers/spi/spi.c
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,11 @@ static ssize_t
modalias_show(struct device *dev, struct device_attribute *a, char *buf)
{
const struct spi_device *spi = to_spi_device(dev);
int len;

len = acpi_device_modalias(dev, buf, PAGE_SIZE - 1);
if (len != -ENODEV)
return len;

return sprintf(buf, "%s%s\n", SPI_MODULE_PREFIX, spi->modalias);
}
Expand Down Expand Up @@ -114,6 +119,11 @@ static int spi_match_device(struct device *dev, struct device_driver *drv)
static int spi_uevent(struct device *dev, struct kobj_uevent_env *env)
{
const struct spi_device *spi = to_spi_device(dev);
int rc;

rc = acpi_device_uevent_modalias(dev, env);
if (rc != -ENODEV)
return rc;

add_uevent_var(env, "MODALIAS=%s%s", SPI_MODULE_PREFIX, spi->modalias);
return 0;
Expand Down
15 changes: 15 additions & 0 deletions include/linux/acpi.h
Original file line number Diff line number Diff line change
Expand Up @@ -416,6 +416,9 @@ static inline bool acpi_driver_match_device(struct device *dev,
return !!acpi_match_device(drv->acpi_match_table, dev);
}

int acpi_device_uevent_modalias(struct device *, struct kobj_uevent_env *);
int acpi_device_modalias(struct device *, char *, int);

#define ACPI_PTR(_ptr) (_ptr)

#else /* !CONFIG_ACPI */
Expand Down Expand Up @@ -495,6 +498,18 @@ static inline bool acpi_driver_match_device(struct device *dev,
return false;
}

static inline int acpi_device_uevent_modalias(struct device *dev,
struct kobj_uevent_env *env)
{
return -ENODEV;
}

static inline int acpi_device_modalias(struct device *dev,
char *buf, int size)
{
return -ENODEV;
}

#define ACPI_PTR(_ptr) (NULL)

#endif /* !CONFIG_ACPI */
Expand Down
6 changes: 6 additions & 0 deletions include/linux/of_device.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,12 @@ static inline int of_driver_match_device(struct device *dev,
static inline void of_device_uevent(struct device *dev,
struct kobj_uevent_env *env) { }

static inline int of_device_get_modalias(struct device *dev,
char *str, ssize_t len)
{
return -ENODEV;
}

static inline int of_device_uevent_modalias(struct device *dev,
struct kobj_uevent_env *env)
{
Expand Down

0 comments on commit bc411b8

Please sign in to comment.