From 864bdfb912e372670b5b2541dac9d273a4a7722a Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Tue, 19 Jun 2007 11:40:03 +0800 Subject: ACPI: Export events via generic netlink Upon ACPI events, send an "acpi_event" via Generic Netlink. This is in addition to /proc/acpi/event, which remains intact for now. Thanks to Jamal for his great help. Signed-off-by: Zhang Rui Signed-off-by: Len Brown --- drivers/acpi/bus.c | 4 ++ drivers/acpi/event.c | 166 ++++++++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 163 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index e5084ececb6..6b2658c9624 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c @@ -292,6 +292,10 @@ int acpi_bus_generate_event(struct acpi_device *device, u8 type, int data) if (!device) return -EINVAL; + if (acpi_bus_generate_genetlink_event(device, type, data)) + printk(KERN_WARNING PREFIX + "Failed to generate an ACPI event via genetlink!\n"); + /* drop event on the floor if no one's listening */ if (!event_is_open) return 0; diff --git a/drivers/acpi/event.c b/drivers/acpi/event.c index 3b23562e6f9..98627b02f54 100644 --- a/drivers/acpi/event.c +++ b/drivers/acpi/event.c @@ -11,6 +11,8 @@ #include #include #include +#include +#include #define _COMPONENT ACPI_SYSTEM_COMPONENT ACPI_MODULE_NAME("event"); @@ -48,7 +50,6 @@ acpi_system_read_event(struct file *file, char __user * buffer, size_t count, static int chars_remaining = 0; static char *ptr; - if (!chars_remaining) { memset(&event, 0, sizeof(struct acpi_bus_event)); @@ -106,23 +107,174 @@ static const struct file_operations acpi_system_event_ops = { .poll = acpi_system_poll_event, }; +#ifdef CONFIG_NET +unsigned int acpi_event_seqnum; +struct acpi_genl_event { + acpi_device_class device_class; + char bus_id[15]; + u32 type; + u32 data; +}; + +/* attributes of acpi_genl_family */ +enum { + ACPI_GENL_ATTR_UNSPEC, + ACPI_GENL_ATTR_EVENT, /* ACPI event info needed by user space */ + __ACPI_GENL_ATTR_MAX, +}; +#define ACPI_GENL_ATTR_MAX (__ACPI_GENL_ATTR_MAX - 1) + +/* commands supported by the acpi_genl_family */ +enum { + ACPI_GENL_CMD_UNSPEC, + ACPI_GENL_CMD_EVENT, /* kernel->user notifications for ACPI events */ + __ACPI_GENL_CMD_MAX, +}; +#define ACPI_GENL_CMD_MAX (__ACPI_GENL_CMD_MAX - 1) + +#define ACPI_GENL_NAME "acpi_event" +#define ACPI_GENL_VERSION 0x01 + +static struct genl_family acpi_event_genl_family = { + .id = GENL_ID_GENERATE, + .name = ACPI_GENL_NAME, + .version = ACPI_GENL_VERSION, + .maxattr = ACPI_GENL_ATTR_MAX, +}; + +/* .doit: standard command callback */ +static int acpi_genl_cmd_event(struct sk_buff *skb, struct genl_info *info) +{ + struct acpi_genl_event *event = info->userhdr; + + if (!event) + ACPI_DEBUG_PRINT((ACPI_DB_WARN, "ACPI event: NULL\n")); + + return 0; +} + +static struct genl_ops acpi_event_genl_ops = { + .cmd = ACPI_GENL_CMD_EVENT, + .doit = acpi_genl_cmd_event, +}; + +int acpi_bus_generate_genetlink_event(struct acpi_device *device, + u8 type, int data) +{ + struct sk_buff *skb; + struct nlattr *attr; + struct acpi_genl_event *event; + void *msg_header; + int size; + int result; + + /* allocate memory */ + size = nla_total_size(sizeof(struct acpi_genl_event)) + + nla_total_size(0); + + skb = genlmsg_new(size, GFP_ATOMIC); + if (!skb) + return -ENOMEM; + + /* add the genetlink message header */ + msg_header = genlmsg_put(skb, 0, acpi_event_seqnum++, + &acpi_event_genl_family, 0, + ACPI_GENL_CMD_EVENT); + if (!msg_header) { + nlmsg_free(skb); + return -ENOMEM; + } + + /* fill the data */ + attr = + nla_reserve(skb, ACPI_GENL_ATTR_EVENT, + sizeof(struct acpi_genl_event)); + if (!attr) { + nlmsg_free(skb); + return -EINVAL; + } + + event = nla_data(attr); + if (!event) { + nlmsg_free(skb); + return -EINVAL; + } + + memset(event, 0, sizeof(struct acpi_genl_event)); + + strcpy(event->device_class, device->pnp.device_class); + strcpy(event->bus_id, device->dev.bus_id); + event->type = type; + event->data = data; + + /* send multicast genetlink message */ + result = genlmsg_end(skb, msg_header); + if (result < 0) { + nlmsg_free(skb); + return result; + } + + result = + genlmsg_multicast(skb, 0, acpi_event_genl_family.id, GFP_ATOMIC); + if (result) + ACPI_DEBUG_PRINT((ACPI_DB_INFO, + "Failed to send a Genetlink message!\n")); + return 0; +} +EXPORT_SYMBOL(acpi_bus_generate_genetlink_event); + +static int acpi_event_genetlink_init(void) +{ + int result; + + result = genl_register_family(&acpi_event_genl_family); + if (result) + return result; + + result = + genl_register_ops(&acpi_event_genl_family, &acpi_event_genl_ops); + if (result) + genl_unregister_family(&acpi_event_genl_family); + + return result; +} + +#else +int acpi_bus_generate_genetlink_event(struct acpi_device *device, u8 type, + int data) +{ + return 0; +} +EXPORT_SYMBOL(acpi_bus_generate_genetlink_event); + +static int acpi_event_genetlink_init(void) +{ + return -ENODEV; +} +#endif + static int __init acpi_event_init(void) { struct proc_dir_entry *entry; int error = 0; - if (acpi_disabled) return 0; + /* create genetlink for acpi event */ + error = acpi_event_genetlink_init(); + if (error) + printk(KERN_WARNING PREFIX + "Failed to create genetlink family for ACPI event\n"); + /* 'event' [R] */ entry = create_proc_entry("event", S_IRUSR, acpi_root_dir); if (entry) entry->proc_fops = &acpi_system_event_ops; - else { - error = -ENODEV; - } - return error; + else + return -ENODEV; + + return 0; } -subsys_initcall(acpi_event_init); +fs_initcall(acpi_event_init); -- cgit v1.2.3 From b563d6f30d937510e02541930b1558d0f5759413 Mon Sep 17 00:00:00 2001 From: Len Brown Date: Tue, 3 Jul 2007 15:32:23 -0400 Subject: ACPI: netlink: remove unnecessary EXPORT_SYMBOL Signed-off-by: Len Brown --- drivers/acpi/event.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/acpi/event.c b/drivers/acpi/event.c index 98627b02f54..de4def9b551 100644 --- a/drivers/acpi/event.c +++ b/drivers/acpi/event.c @@ -221,7 +221,6 @@ int acpi_bus_generate_genetlink_event(struct acpi_device *device, "Failed to send a Genetlink message!\n")); return 0; } -EXPORT_SYMBOL(acpi_bus_generate_genetlink_event); static int acpi_event_genetlink_init(void) { @@ -245,7 +244,6 @@ int acpi_bus_generate_genetlink_event(struct acpi_device *device, u8 type, { return 0; } -EXPORT_SYMBOL(acpi_bus_generate_genetlink_event); static int acpi_event_genetlink_init(void) { -- cgit v1.2.3 From 9c977a453ed62396d067b75f3f272b3fb1ea3acc Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Fri, 20 Jul 2007 16:41:14 +0800 Subject: ACPI: export ACPI events via acpi_mc_group multicast group This is an incremental patch for the recent genetlink multicast changes. Now ACPI events are exported via generic netlink multicast group. Thanks for Johannes' help on developing this patch Signed-off-by: Zhang Rui Signed-off-by: Len Brown --- drivers/acpi/event.c | 29 +++++++++-------------------- 1 file changed, 9 insertions(+), 20 deletions(-) (limited to 'drivers') diff --git a/drivers/acpi/event.c b/drivers/acpi/event.c index de4def9b551..dfa5853b17f 100644 --- a/drivers/acpi/event.c +++ b/drivers/acpi/event.c @@ -132,30 +132,19 @@ enum { }; #define ACPI_GENL_CMD_MAX (__ACPI_GENL_CMD_MAX - 1) -#define ACPI_GENL_NAME "acpi_event" -#define ACPI_GENL_VERSION 0x01 +#define ACPI_GENL_FAMILY_NAME "acpi_event" +#define ACPI_GENL_VERSION 0x01 +#define ACPI_GENL_MCAST_GROUP_NAME "acpi_mc_group" static struct genl_family acpi_event_genl_family = { .id = GENL_ID_GENERATE, - .name = ACPI_GENL_NAME, + .name = ACPI_GENL_FAMILY_NAME, .version = ACPI_GENL_VERSION, .maxattr = ACPI_GENL_ATTR_MAX, }; -/* .doit: standard command callback */ -static int acpi_genl_cmd_event(struct sk_buff *skb, struct genl_info *info) -{ - struct acpi_genl_event *event = info->userhdr; - - if (!event) - ACPI_DEBUG_PRINT((ACPI_DB_WARN, "ACPI event: NULL\n")); - - return 0; -} - -static struct genl_ops acpi_event_genl_ops = { - .cmd = ACPI_GENL_CMD_EVENT, - .doit = acpi_genl_cmd_event, +static struct genl_multicast_group acpi_event_mcgrp = { + .name = ACPI_GENL_MCAST_GROUP_NAME, }; int acpi_bus_generate_genetlink_event(struct acpi_device *device, @@ -215,7 +204,7 @@ int acpi_bus_generate_genetlink_event(struct acpi_device *device, } result = - genlmsg_multicast(skb, 0, acpi_event_genl_family.id, GFP_ATOMIC); + genlmsg_multicast(skb, 0, acpi_event_mcgrp.id, GFP_ATOMIC); if (result) ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Failed to send a Genetlink message!\n")); @@ -230,8 +219,8 @@ static int acpi_event_genetlink_init(void) if (result) return result; - result = - genl_register_ops(&acpi_event_genl_family, &acpi_event_genl_ops); + result = genl_register_mc_group(&acpi_event_genl_family, + &acpi_event_mcgrp); if (result) genl_unregister_family(&acpi_event_genl_family); -- cgit v1.2.3