···292292 if (!device)293293 return -EINVAL;294294295295+ if (acpi_bus_generate_genetlink_event(device, type, data))296296+ printk(KERN_WARNING PREFIX297297+ "Failed to generate an ACPI event via genetlink!\n");298298+295299 /* drop event on the floor if no one's listening */296300 if (!event_is_open)297301 return 0;
+146-7
drivers/acpi/event.c
···1111#include <linux/init.h>1212#include <linux/poll.h>1313#include <acpi/acpi_drivers.h>1414+#include <net/netlink.h>1515+#include <net/genetlink.h>14161517#define _COMPONENT ACPI_SYSTEM_COMPONENT1618ACPI_MODULE_NAME("event");···4947 static char str[ACPI_MAX_STRING];5048 static int chars_remaining = 0;5149 static char *ptr;5252-53505451 if (!chars_remaining) {5552 memset(&event, 0, sizeof(struct acpi_bus_event));···107106 .poll = acpi_system_poll_event,108107};109108109109+#ifdef CONFIG_NET110110+unsigned int acpi_event_seqnum;111111+struct acpi_genl_event {112112+ acpi_device_class device_class;113113+ char bus_id[15];114114+ u32 type;115115+ u32 data;116116+};117117+118118+/* attributes of acpi_genl_family */119119+enum {120120+ ACPI_GENL_ATTR_UNSPEC,121121+ ACPI_GENL_ATTR_EVENT, /* ACPI event info needed by user space */122122+ __ACPI_GENL_ATTR_MAX,123123+};124124+#define ACPI_GENL_ATTR_MAX (__ACPI_GENL_ATTR_MAX - 1)125125+126126+/* commands supported by the acpi_genl_family */127127+enum {128128+ ACPI_GENL_CMD_UNSPEC,129129+ ACPI_GENL_CMD_EVENT, /* kernel->user notifications for ACPI events */130130+ __ACPI_GENL_CMD_MAX,131131+};132132+#define ACPI_GENL_CMD_MAX (__ACPI_GENL_CMD_MAX - 1)133133+134134+#define ACPI_GENL_FAMILY_NAME "acpi_event"135135+#define ACPI_GENL_VERSION 0x01136136+#define ACPI_GENL_MCAST_GROUP_NAME "acpi_mc_group"137137+138138+static struct genl_family acpi_event_genl_family = {139139+ .id = GENL_ID_GENERATE,140140+ .name = ACPI_GENL_FAMILY_NAME,141141+ .version = ACPI_GENL_VERSION,142142+ .maxattr = ACPI_GENL_ATTR_MAX,143143+};144144+145145+static struct genl_multicast_group acpi_event_mcgrp = {146146+ .name = ACPI_GENL_MCAST_GROUP_NAME,147147+};148148+149149+int acpi_bus_generate_genetlink_event(struct acpi_device *device,150150+ u8 type, int data)151151+{152152+ struct sk_buff *skb;153153+ struct nlattr *attr;154154+ struct acpi_genl_event *event;155155+ void *msg_header;156156+ int size;157157+ int result;158158+159159+ /* allocate memory */160160+ size = nla_total_size(sizeof(struct acpi_genl_event)) +161161+ nla_total_size(0);162162+163163+ skb = genlmsg_new(size, GFP_ATOMIC);164164+ if (!skb)165165+ return -ENOMEM;166166+167167+ /* add the genetlink message header */168168+ msg_header = genlmsg_put(skb, 0, acpi_event_seqnum++,169169+ &acpi_event_genl_family, 0,170170+ ACPI_GENL_CMD_EVENT);171171+ if (!msg_header) {172172+ nlmsg_free(skb);173173+ return -ENOMEM;174174+ }175175+176176+ /* fill the data */177177+ attr =178178+ nla_reserve(skb, ACPI_GENL_ATTR_EVENT,179179+ sizeof(struct acpi_genl_event));180180+ if (!attr) {181181+ nlmsg_free(skb);182182+ return -EINVAL;183183+ }184184+185185+ event = nla_data(attr);186186+ if (!event) {187187+ nlmsg_free(skb);188188+ return -EINVAL;189189+ }190190+191191+ memset(event, 0, sizeof(struct acpi_genl_event));192192+193193+ strcpy(event->device_class, device->pnp.device_class);194194+ strcpy(event->bus_id, device->dev.bus_id);195195+ event->type = type;196196+ event->data = data;197197+198198+ /* send multicast genetlink message */199199+ result = genlmsg_end(skb, msg_header);200200+ if (result < 0) {201201+ nlmsg_free(skb);202202+ return result;203203+ }204204+205205+ result =206206+ genlmsg_multicast(skb, 0, acpi_event_mcgrp.id, GFP_ATOMIC);207207+ if (result)208208+ ACPI_DEBUG_PRINT((ACPI_DB_INFO,209209+ "Failed to send a Genetlink message!\n"));210210+ return 0;211211+}212212+213213+static int acpi_event_genetlink_init(void)214214+{215215+ int result;216216+217217+ result = genl_register_family(&acpi_event_genl_family);218218+ if (result)219219+ return result;220220+221221+ result = genl_register_mc_group(&acpi_event_genl_family,222222+ &acpi_event_mcgrp);223223+ if (result)224224+ genl_unregister_family(&acpi_event_genl_family);225225+226226+ return result;227227+}228228+229229+#else230230+int acpi_bus_generate_genetlink_event(struct acpi_device *device, u8 type,231231+ int data)232232+{233233+ return 0;234234+}235235+236236+static int acpi_event_genetlink_init(void)237237+{238238+ return -ENODEV;239239+}240240+#endif241241+110242static int __init acpi_event_init(void)111243{112244 struct proc_dir_entry *entry;113245 int error = 0;114246115115-116247 if (acpi_disabled)117248 return 0;249249+250250+ /* create genetlink for acpi event */251251+ error = acpi_event_genetlink_init();252252+ if (error)253253+ printk(KERN_WARNING PREFIX254254+ "Failed to create genetlink family for ACPI event\n");118255119256 /* 'event' [R] */120257 entry = create_proc_entry("event", S_IRUSR, acpi_root_dir);121258 if (entry)122259 entry->proc_fops = &acpi_system_event_ops;123123- else {124124- error = -ENODEV;125125- }126126- return error;260260+ else261261+ return -ENODEV;262262+263263+ return 0;127264}128265129129-subsys_initcall(acpi_event_init);266266+fs_initcall(acpi_event_init);
+2-1
include/acpi/acpi_bus.h
···321321};322322323323extern struct kset acpi_subsys;324324-324324+extern int acpi_bus_generate_genetlink_event(struct acpi_device *device,325325+ u8 type, int data);325326/*326327 * External Functions327328 */