event.c revision 9ee85241fdaab358dff1d8647f20a478cfa512a1
11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * event.c - exporting ACPI events via procfs 31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com> 51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com> 61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/spinlock.h> 101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/proc_fs.h> 111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/init.h> 121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/poll.h> 131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <acpi/acpi_drivers.h> 14864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui#include <net/netlink.h> 15864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui#include <net/genetlink.h> 161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define _COMPONENT ACPI_SYSTEM_COMPONENT 18f52fd66d2ea794010c2d7536cf8e6abed0ac4947Len BrownACPI_MODULE_NAME("event"); 191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2014e04fb34ffa82ee61ae69f98d8fca12d2e8e31cLen Brown#ifdef CONFIG_ACPI_PROC_EVENT 211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Global vars for handling event proc entry */ 221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic DEFINE_SPINLOCK(acpi_system_event_lock); 234be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brownint event_is_open = 0; 244be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brownextern struct list_head acpi_bus_event_list; 254be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brownextern wait_queue_head_t acpi_bus_event_queue; 261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 274be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brownstatic int acpi_system_open_event(struct inode *inode, struct file *file) 281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 29c65ade4dc8b486e8c8b9b0a6399789a5428e2039Pavel Machek spin_lock_irq(&acpi_system_event_lock); 301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 31c65ade4dc8b486e8c8b9b0a6399789a5428e2039Pavel Machek if (event_is_open) 321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto out_busy; 331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds event_is_open = 1; 351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 36c65ade4dc8b486e8c8b9b0a6399789a5428e2039Pavel Machek spin_unlock_irq(&acpi_system_event_lock); 371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 394be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown out_busy: 40c65ade4dc8b486e8c8b9b0a6399789a5428e2039Pavel Machek spin_unlock_irq(&acpi_system_event_lock); 411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EBUSY; 421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic ssize_t 454be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brownacpi_system_read_event(struct file *file, char __user * buffer, size_t count, 464be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown loff_t * ppos) 471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 484be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown int result = 0; 494be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown struct acpi_bus_event event; 504be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown static char str[ACPI_MAX_STRING]; 514be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown static int chars_remaining = 0; 524be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown static char *ptr; 531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!chars_remaining) { 551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds memset(&event, 0, sizeof(struct acpi_bus_event)); 561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((file->f_flags & O_NONBLOCK) 581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds && (list_empty(&acpi_bus_event_list))) 59d550d98d3317378d93a4869db204725d270ec812Patrick Mochel return -EAGAIN; 601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds result = acpi_bus_receive_event(&event); 625cc9eeef9a9567acdfc2f6943f24381bf460f008Pavel Machek if (result) 63d550d98d3317378d93a4869db204725d270ec812Patrick Mochel return result; 641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 654be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown chars_remaining = sprintf(str, "%s %s %08x %08x\n", 664be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown event.device_class ? event. 674be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown device_class : "<unknown>", 684be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown event.bus_id ? event. 694be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown bus_id : "<unknown>", event.type, 704be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown event.data); 711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ptr = str; 721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (chars_remaining < count) { 751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds count = chars_remaining; 761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (copy_to_user(buffer, ptr, count)) 79d550d98d3317378d93a4869db204725d270ec812Patrick Mochel return -EFAULT; 801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *ppos += count; 821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds chars_remaining -= count; 831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ptr += count; 841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 85d550d98d3317378d93a4869db204725d270ec812Patrick Mochel return count; 861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 884be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brownstatic int acpi_system_close_event(struct inode *inode, struct file *file) 891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 904be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown spin_lock_irq(&acpi_system_event_lock); 911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds event_is_open = 0; 924be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown spin_unlock_irq(&acpi_system_event_lock); 931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 964be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brownstatic unsigned int acpi_system_poll_event(struct file *file, poll_table * wait) 971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds poll_wait(file, &acpi_bus_event_queue, wait); 991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!list_empty(&acpi_bus_event_list)) 1001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return POLLIN | POLLRDNORM; 1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 1021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 104d75080328affb4b268da430b7074cc8139cc662aArjan van de Venstatic const struct file_operations acpi_system_event_ops = { 1054be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown .open = acpi_system_open_event, 1064be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown .read = acpi_system_read_event, 1074be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown .release = acpi_system_close_event, 1084be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown .poll = acpi_system_poll_event, 1091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 11014e04fb34ffa82ee61ae69f98d8fca12d2e8e31cLen Brown#endif /* CONFIG_ACPI_PROC_EVENT */ 1111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1129ee85241fdaab358dff1d8647f20a478cfa512a1Zhang Rui/* ACPI notifier chain */ 1139ee85241fdaab358dff1d8647f20a478cfa512a1Zhang RuiBLOCKING_NOTIFIER_HEAD(acpi_chain_head); 1149ee85241fdaab358dff1d8647f20a478cfa512a1Zhang Rui 1159ee85241fdaab358dff1d8647f20a478cfa512a1Zhang Ruiint acpi_notifier_call_chain(struct acpi_device *dev, u32 type, u32 data) 1169ee85241fdaab358dff1d8647f20a478cfa512a1Zhang Rui{ 1179ee85241fdaab358dff1d8647f20a478cfa512a1Zhang Rui struct acpi_bus_event event; 1189ee85241fdaab358dff1d8647f20a478cfa512a1Zhang Rui 1199ee85241fdaab358dff1d8647f20a478cfa512a1Zhang Rui strcpy(event.device_class, dev->pnp.device_class); 1209ee85241fdaab358dff1d8647f20a478cfa512a1Zhang Rui strcpy(event.bus_id, dev->pnp.bus_id); 1219ee85241fdaab358dff1d8647f20a478cfa512a1Zhang Rui event.type = type; 1229ee85241fdaab358dff1d8647f20a478cfa512a1Zhang Rui event.data = data; 1239ee85241fdaab358dff1d8647f20a478cfa512a1Zhang Rui return (blocking_notifier_call_chain(&acpi_chain_head, 0, (void *)&event) 1249ee85241fdaab358dff1d8647f20a478cfa512a1Zhang Rui == NOTIFY_BAD) ? -EINVAL : 0; 1259ee85241fdaab358dff1d8647f20a478cfa512a1Zhang Rui} 1269ee85241fdaab358dff1d8647f20a478cfa512a1Zhang RuiEXPORT_SYMBOL(acpi_notifier_call_chain); 1279ee85241fdaab358dff1d8647f20a478cfa512a1Zhang Rui 1289ee85241fdaab358dff1d8647f20a478cfa512a1Zhang Ruiint register_acpi_notifier(struct notifier_block *nb) 1299ee85241fdaab358dff1d8647f20a478cfa512a1Zhang Rui{ 1309ee85241fdaab358dff1d8647f20a478cfa512a1Zhang Rui return blocking_notifier_chain_register(&acpi_chain_head, nb); 1319ee85241fdaab358dff1d8647f20a478cfa512a1Zhang Rui} 1329ee85241fdaab358dff1d8647f20a478cfa512a1Zhang RuiEXPORT_SYMBOL(register_acpi_notifier); 1339ee85241fdaab358dff1d8647f20a478cfa512a1Zhang Rui 1349ee85241fdaab358dff1d8647f20a478cfa512a1Zhang Ruiint unregister_acpi_notifier(struct notifier_block *nb) 1359ee85241fdaab358dff1d8647f20a478cfa512a1Zhang Rui{ 1369ee85241fdaab358dff1d8647f20a478cfa512a1Zhang Rui return blocking_notifier_chain_unregister(&acpi_chain_head, nb); 1379ee85241fdaab358dff1d8647f20a478cfa512a1Zhang Rui} 1389ee85241fdaab358dff1d8647f20a478cfa512a1Zhang RuiEXPORT_SYMBOL(unregister_acpi_notifier); 1399ee85241fdaab358dff1d8647f20a478cfa512a1Zhang Rui 140864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui#ifdef CONFIG_NET 141e13d87473284131a7ead8121d5d29345101f68a4Adrian Bunkstatic unsigned int acpi_event_seqnum; 142864bdfb912e372670b5b2541dac9d273a4a7722aZhang Ruistruct acpi_genl_event { 143864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui acpi_device_class device_class; 144864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui char bus_id[15]; 145864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui u32 type; 146864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui u32 data; 147864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui}; 148864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui 149864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui/* attributes of acpi_genl_family */ 150864bdfb912e372670b5b2541dac9d273a4a7722aZhang Ruienum { 151864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui ACPI_GENL_ATTR_UNSPEC, 152864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui ACPI_GENL_ATTR_EVENT, /* ACPI event info needed by user space */ 153864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui __ACPI_GENL_ATTR_MAX, 154864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui}; 155864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui#define ACPI_GENL_ATTR_MAX (__ACPI_GENL_ATTR_MAX - 1) 156864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui 157864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui/* commands supported by the acpi_genl_family */ 158864bdfb912e372670b5b2541dac9d273a4a7722aZhang Ruienum { 159864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui ACPI_GENL_CMD_UNSPEC, 160864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui ACPI_GENL_CMD_EVENT, /* kernel->user notifications for ACPI events */ 161864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui __ACPI_GENL_CMD_MAX, 162864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui}; 163864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui#define ACPI_GENL_CMD_MAX (__ACPI_GENL_CMD_MAX - 1) 164864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui 1659c977a453ed62396d067b75f3f272b3fb1ea3accZhang Rui#define ACPI_GENL_FAMILY_NAME "acpi_event" 1669c977a453ed62396d067b75f3f272b3fb1ea3accZhang Rui#define ACPI_GENL_VERSION 0x01 1679c977a453ed62396d067b75f3f272b3fb1ea3accZhang Rui#define ACPI_GENL_MCAST_GROUP_NAME "acpi_mc_group" 168864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui 169864bdfb912e372670b5b2541dac9d273a4a7722aZhang Ruistatic struct genl_family acpi_event_genl_family = { 170864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui .id = GENL_ID_GENERATE, 1719c977a453ed62396d067b75f3f272b3fb1ea3accZhang Rui .name = ACPI_GENL_FAMILY_NAME, 172864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui .version = ACPI_GENL_VERSION, 173864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui .maxattr = ACPI_GENL_ATTR_MAX, 174864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui}; 175864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui 1769c977a453ed62396d067b75f3f272b3fb1ea3accZhang Ruistatic struct genl_multicast_group acpi_event_mcgrp = { 1779c977a453ed62396d067b75f3f272b3fb1ea3accZhang Rui .name = ACPI_GENL_MCAST_GROUP_NAME, 178864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui}; 179864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui 180962ce8ca0604af0c3c5609f7613d4ec5fcfac623Zhang Ruiint acpi_bus_generate_netlink_event(const char *device_class, 181962ce8ca0604af0c3c5609f7613d4ec5fcfac623Zhang Rui const char *bus_id, 182864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui u8 type, int data) 183864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui{ 184864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui struct sk_buff *skb; 185864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui struct nlattr *attr; 186864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui struct acpi_genl_event *event; 187864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui void *msg_header; 188864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui int size; 189864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui int result; 190864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui 191864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui /* allocate memory */ 192864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui size = nla_total_size(sizeof(struct acpi_genl_event)) + 193864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui nla_total_size(0); 194864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui 195864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui skb = genlmsg_new(size, GFP_ATOMIC); 196864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui if (!skb) 197864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui return -ENOMEM; 198864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui 199864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui /* add the genetlink message header */ 200864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui msg_header = genlmsg_put(skb, 0, acpi_event_seqnum++, 201864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui &acpi_event_genl_family, 0, 202864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui ACPI_GENL_CMD_EVENT); 203864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui if (!msg_header) { 204864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui nlmsg_free(skb); 205864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui return -ENOMEM; 206864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui } 207864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui 208864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui /* fill the data */ 209864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui attr = 210864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui nla_reserve(skb, ACPI_GENL_ATTR_EVENT, 211864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui sizeof(struct acpi_genl_event)); 212864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui if (!attr) { 213864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui nlmsg_free(skb); 214864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui return -EINVAL; 215864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui } 216864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui 217864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui event = nla_data(attr); 218864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui if (!event) { 219864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui nlmsg_free(skb); 220864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui return -EINVAL; 221864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui } 222864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui 223864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui memset(event, 0, sizeof(struct acpi_genl_event)); 224864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui 225962ce8ca0604af0c3c5609f7613d4ec5fcfac623Zhang Rui strcpy(event->device_class, device_class); 226962ce8ca0604af0c3c5609f7613d4ec5fcfac623Zhang Rui strcpy(event->bus_id, bus_id); 227864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui event->type = type; 228864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui event->data = data; 229864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui 230864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui /* send multicast genetlink message */ 231864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui result = genlmsg_end(skb, msg_header); 232864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui if (result < 0) { 233864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui nlmsg_free(skb); 234864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui return result; 235864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui } 236864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui 237864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui result = 2389c977a453ed62396d067b75f3f272b3fb1ea3accZhang Rui genlmsg_multicast(skb, 0, acpi_event_mcgrp.id, GFP_ATOMIC); 239864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui if (result) 240864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui ACPI_DEBUG_PRINT((ACPI_DB_INFO, 241864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui "Failed to send a Genetlink message!\n")); 242864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui return 0; 243864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui} 244864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui 245962ce8ca0604af0c3c5609f7613d4ec5fcfac623Zhang RuiEXPORT_SYMBOL(acpi_bus_generate_netlink_event); 246962ce8ca0604af0c3c5609f7613d4ec5fcfac623Zhang Rui 247864bdfb912e372670b5b2541dac9d273a4a7722aZhang Ruistatic int acpi_event_genetlink_init(void) 248864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui{ 249864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui int result; 250864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui 251864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui result = genl_register_family(&acpi_event_genl_family); 252864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui if (result) 253864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui return result; 254864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui 2559c977a453ed62396d067b75f3f272b3fb1ea3accZhang Rui result = genl_register_mc_group(&acpi_event_genl_family, 2569c977a453ed62396d067b75f3f272b3fb1ea3accZhang Rui &acpi_event_mcgrp); 257864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui if (result) 258864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui genl_unregister_family(&acpi_event_genl_family); 259864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui 260864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui return result; 261864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui} 262864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui 263864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui#else 2643e069ee0c30d6f28b79e409ef2df1ffa427897aeLen Brownint acpi_bus_generate_netlink_event(const char *device_class, 2653e069ee0c30d6f28b79e409ef2df1ffa427897aeLen Brown const char *bus_id, 2663e069ee0c30d6f28b79e409ef2df1ffa427897aeLen Brown u8 type, int data) 267864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui{ 268864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui return 0; 269864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui} 270864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui 27166baf327ae5d4c17e75d1f501145e79eaeeaf649Henrique de Moraes HolschuhEXPORT_SYMBOL(acpi_bus_generate_netlink_event); 272962ce8ca0604af0c3c5609f7613d4ec5fcfac623Zhang Rui 273864bdfb912e372670b5b2541dac9d273a4a7722aZhang Ruistatic int acpi_event_genetlink_init(void) 274864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui{ 275864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui return -ENODEV; 276864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui} 277864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui#endif 278864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui 2791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int __init acpi_event_init(void) 2801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 28114e04fb34ffa82ee61ae69f98d8fca12d2e8e31cLen Brown#ifdef CONFIG_ACPI_PROC_EVENT 2824be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown struct proc_dir_entry *entry; 28314e04fb34ffa82ee61ae69f98d8fca12d2e8e31cLen Brown#endif 2841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int error = 0; 2851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (acpi_disabled) 287d550d98d3317378d93a4869db204725d270ec812Patrick Mochel return 0; 2881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 289864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui /* create genetlink for acpi event */ 290864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui error = acpi_event_genetlink_init(); 291864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui if (error) 292864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui printk(KERN_WARNING PREFIX 293864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui "Failed to create genetlink family for ACPI event\n"); 294864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui 29514e04fb34ffa82ee61ae69f98d8fca12d2e8e31cLen Brown#ifdef CONFIG_ACPI_PROC_EVENT 2961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 'event' [R] */ 2971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds entry = create_proc_entry("event", S_IRUSR, acpi_root_dir); 2981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (entry) 2991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds entry->proc_fops = &acpi_system_event_ops; 300864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui else 301864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui return -ENODEV; 30214e04fb34ffa82ee61ae69f98d8fca12d2e8e31cLen Brown#endif 303864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui 304864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui return 0; 3051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 307864bdfb912e372670b5b2541dac9d273a4a7722aZhang Ruifs_initcall(acpi_event_init); 308