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> 10214f2c90b970e098e75cf719c0c5b0f1fe69b716Paul Gortmaker#include <linux/export.h> 111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/proc_fs.h> 121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/init.h> 131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/poll.h> 145a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/gfp.h> 151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <acpi/acpi_drivers.h> 16864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui#include <net/netlink.h> 17864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui#include <net/genetlink.h> 181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 19a192a9580bcc41692be1f36b77c3b681827f566aLen Brown#include "internal.h" 20a192a9580bcc41692be1f36b77c3b681827f566aLen Brown 211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define _COMPONENT ACPI_SYSTEM_COMPONENT 22f52fd66d2ea794010c2d7536cf8e6abed0ac4947Len BrownACPI_MODULE_NAME("event"); 231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2414e04fb34ffa82ee61ae69f98d8fca12d2e8e31cLen Brown#ifdef CONFIG_ACPI_PROC_EVENT 251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Global vars for handling event proc entry */ 261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic DEFINE_SPINLOCK(acpi_system_event_lock); 274be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brownint event_is_open = 0; 284be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brownextern struct list_head acpi_bus_event_list; 294be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brownextern wait_queue_head_t acpi_bus_event_queue; 301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 314be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brownstatic int acpi_system_open_event(struct inode *inode, struct file *file) 321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 33c65ade4dc8b486e8c8b9b0a6399789a5428e2039Pavel Machek spin_lock_irq(&acpi_system_event_lock); 341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 35c65ade4dc8b486e8c8b9b0a6399789a5428e2039Pavel Machek if (event_is_open) 361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto out_busy; 371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds event_is_open = 1; 391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 40c65ade4dc8b486e8c8b9b0a6399789a5428e2039Pavel Machek spin_unlock_irq(&acpi_system_event_lock); 411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 434be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown out_busy: 44c65ade4dc8b486e8c8b9b0a6399789a5428e2039Pavel Machek spin_unlock_irq(&acpi_system_event_lock); 451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EBUSY; 461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic ssize_t 494be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brownacpi_system_read_event(struct file *file, char __user * buffer, size_t count, 504be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown loff_t * ppos) 511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 524be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown int result = 0; 534be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown struct acpi_bus_event event; 544be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown static char str[ACPI_MAX_STRING]; 554be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown static int chars_remaining = 0; 564be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown static char *ptr; 571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!chars_remaining) { 591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds memset(&event, 0, sizeof(struct acpi_bus_event)); 601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((file->f_flags & O_NONBLOCK) 621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds && (list_empty(&acpi_bus_event_list))) 63d550d98d3317378d93a4869db204725d270ec812Patrick Mochel return -EAGAIN; 641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds result = acpi_bus_receive_event(&event); 665cc9eeef9a9567acdfc2f6943f24381bf460f008Pavel Machek if (result) 67d550d98d3317378d93a4869db204725d270ec812Patrick Mochel return result; 681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 694be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown chars_remaining = sprintf(str, "%s %s %08x %08x\n", 704be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown event.device_class ? event. 714be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown device_class : "<unknown>", 724be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown event.bus_id ? event. 734be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown bus_id : "<unknown>", event.type, 744be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown event.data); 751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ptr = str; 761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (chars_remaining < count) { 791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds count = chars_remaining; 801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (copy_to_user(buffer, ptr, count)) 83d550d98d3317378d93a4869db204725d270ec812Patrick Mochel return -EFAULT; 841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *ppos += count; 861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds chars_remaining -= count; 871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ptr += count; 881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 89d550d98d3317378d93a4869db204725d270ec812Patrick Mochel return count; 901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 924be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brownstatic int acpi_system_close_event(struct inode *inode, struct file *file) 931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 944be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown spin_lock_irq(&acpi_system_event_lock); 951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds event_is_open = 0; 964be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown spin_unlock_irq(&acpi_system_event_lock); 971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1004be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brownstatic unsigned int acpi_system_poll_event(struct file *file, poll_table * wait) 1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds poll_wait(file, &acpi_bus_event_queue, wait); 1031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!list_empty(&acpi_bus_event_list)) 1041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return POLLIN | POLLRDNORM; 1051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 1061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 108d75080328affb4b268da430b7074cc8139cc662aArjan van de Venstatic const struct file_operations acpi_system_event_ops = { 109cf7acfab032ff262f42954328cdfd20a5d9aaaacDenis V. Lunev .owner = THIS_MODULE, 1104be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown .open = acpi_system_open_event, 1114be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown .read = acpi_system_read_event, 1124be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown .release = acpi_system_close_event, 1134be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown .poll = acpi_system_poll_event, 1146038f373a3dc1f1c26496e60b6c40b164716f07eArnd Bergmann .llseek = default_llseek, 1151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 11614e04fb34ffa82ee61ae69f98d8fca12d2e8e31cLen Brown#endif /* CONFIG_ACPI_PROC_EVENT */ 1171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1189ee85241fdaab358dff1d8647f20a478cfa512a1Zhang Rui/* ACPI notifier chain */ 119c8e773fa4f6a999a80d9fa3836f412e259ab6fa1Adrian Bunkstatic BLOCKING_NOTIFIER_HEAD(acpi_chain_head); 1209ee85241fdaab358dff1d8647f20a478cfa512a1Zhang Rui 1219ee85241fdaab358dff1d8647f20a478cfa512a1Zhang Ruiint acpi_notifier_call_chain(struct acpi_device *dev, u32 type, u32 data) 1229ee85241fdaab358dff1d8647f20a478cfa512a1Zhang Rui{ 1239ee85241fdaab358dff1d8647f20a478cfa512a1Zhang Rui struct acpi_bus_event event; 1249ee85241fdaab358dff1d8647f20a478cfa512a1Zhang Rui 1259ee85241fdaab358dff1d8647f20a478cfa512a1Zhang Rui strcpy(event.device_class, dev->pnp.device_class); 1269ee85241fdaab358dff1d8647f20a478cfa512a1Zhang Rui strcpy(event.bus_id, dev->pnp.bus_id); 1279ee85241fdaab358dff1d8647f20a478cfa512a1Zhang Rui event.type = type; 1289ee85241fdaab358dff1d8647f20a478cfa512a1Zhang Rui event.data = data; 1299ee85241fdaab358dff1d8647f20a478cfa512a1Zhang Rui return (blocking_notifier_call_chain(&acpi_chain_head, 0, (void *)&event) 1309ee85241fdaab358dff1d8647f20a478cfa512a1Zhang Rui == NOTIFY_BAD) ? -EINVAL : 0; 1319ee85241fdaab358dff1d8647f20a478cfa512a1Zhang Rui} 1329ee85241fdaab358dff1d8647f20a478cfa512a1Zhang RuiEXPORT_SYMBOL(acpi_notifier_call_chain); 1339ee85241fdaab358dff1d8647f20a478cfa512a1Zhang Rui 1349ee85241fdaab358dff1d8647f20a478cfa512a1Zhang Ruiint register_acpi_notifier(struct notifier_block *nb) 1359ee85241fdaab358dff1d8647f20a478cfa512a1Zhang Rui{ 1369ee85241fdaab358dff1d8647f20a478cfa512a1Zhang Rui return blocking_notifier_chain_register(&acpi_chain_head, nb); 1379ee85241fdaab358dff1d8647f20a478cfa512a1Zhang Rui} 1389ee85241fdaab358dff1d8647f20a478cfa512a1Zhang RuiEXPORT_SYMBOL(register_acpi_notifier); 1399ee85241fdaab358dff1d8647f20a478cfa512a1Zhang Rui 1409ee85241fdaab358dff1d8647f20a478cfa512a1Zhang Ruiint unregister_acpi_notifier(struct notifier_block *nb) 1419ee85241fdaab358dff1d8647f20a478cfa512a1Zhang Rui{ 1429ee85241fdaab358dff1d8647f20a478cfa512a1Zhang Rui return blocking_notifier_chain_unregister(&acpi_chain_head, nb); 1439ee85241fdaab358dff1d8647f20a478cfa512a1Zhang Rui} 1449ee85241fdaab358dff1d8647f20a478cfa512a1Zhang RuiEXPORT_SYMBOL(unregister_acpi_notifier); 1459ee85241fdaab358dff1d8647f20a478cfa512a1Zhang Rui 146864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui#ifdef CONFIG_NET 147e13d87473284131a7ead8121d5d29345101f68a4Adrian Bunkstatic unsigned int acpi_event_seqnum; 148864bdfb912e372670b5b2541dac9d273a4a7722aZhang Ruistruct acpi_genl_event { 149864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui acpi_device_class device_class; 150864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui char bus_id[15]; 151864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui u32 type; 152864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui u32 data; 153864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui}; 154864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui 155864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui/* attributes of acpi_genl_family */ 156864bdfb912e372670b5b2541dac9d273a4a7722aZhang Ruienum { 157864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui ACPI_GENL_ATTR_UNSPEC, 158864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui ACPI_GENL_ATTR_EVENT, /* ACPI event info needed by user space */ 159864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui __ACPI_GENL_ATTR_MAX, 160864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui}; 161864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui#define ACPI_GENL_ATTR_MAX (__ACPI_GENL_ATTR_MAX - 1) 162864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui 163864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui/* commands supported by the acpi_genl_family */ 164864bdfb912e372670b5b2541dac9d273a4a7722aZhang Ruienum { 165864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui ACPI_GENL_CMD_UNSPEC, 166864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui ACPI_GENL_CMD_EVENT, /* kernel->user notifications for ACPI events */ 167864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui __ACPI_GENL_CMD_MAX, 168864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui}; 169864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui#define ACPI_GENL_CMD_MAX (__ACPI_GENL_CMD_MAX - 1) 170864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui 1719c977a453ed62396d067b75f3f272b3fb1ea3accZhang Rui#define ACPI_GENL_FAMILY_NAME "acpi_event" 1729c977a453ed62396d067b75f3f272b3fb1ea3accZhang Rui#define ACPI_GENL_VERSION 0x01 1739c977a453ed62396d067b75f3f272b3fb1ea3accZhang Rui#define ACPI_GENL_MCAST_GROUP_NAME "acpi_mc_group" 174864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui 175864bdfb912e372670b5b2541dac9d273a4a7722aZhang Ruistatic struct genl_family acpi_event_genl_family = { 176864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui .id = GENL_ID_GENERATE, 1779c977a453ed62396d067b75f3f272b3fb1ea3accZhang Rui .name = ACPI_GENL_FAMILY_NAME, 178864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui .version = ACPI_GENL_VERSION, 179864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui .maxattr = ACPI_GENL_ATTR_MAX, 180864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui}; 181864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui 1829c977a453ed62396d067b75f3f272b3fb1ea3accZhang Ruistatic struct genl_multicast_group acpi_event_mcgrp = { 1839c977a453ed62396d067b75f3f272b3fb1ea3accZhang Rui .name = ACPI_GENL_MCAST_GROUP_NAME, 184864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui}; 185864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui 186962ce8ca0604af0c3c5609f7613d4ec5fcfac623Zhang Ruiint acpi_bus_generate_netlink_event(const char *device_class, 187962ce8ca0604af0c3c5609f7613d4ec5fcfac623Zhang Rui const char *bus_id, 188864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui u8 type, int data) 189864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui{ 190864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui struct sk_buff *skb; 191864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui struct nlattr *attr; 192864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui struct acpi_genl_event *event; 193864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui void *msg_header; 194864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui int size; 195864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui int result; 196864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui 197864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui /* allocate memory */ 198864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui size = nla_total_size(sizeof(struct acpi_genl_event)) + 199864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui nla_total_size(0); 200864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui 201864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui skb = genlmsg_new(size, GFP_ATOMIC); 202864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui if (!skb) 203864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui return -ENOMEM; 204864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui 205864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui /* add the genetlink message header */ 206864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui msg_header = genlmsg_put(skb, 0, acpi_event_seqnum++, 207864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui &acpi_event_genl_family, 0, 208864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui ACPI_GENL_CMD_EVENT); 209864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui if (!msg_header) { 210864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui nlmsg_free(skb); 211864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui return -ENOMEM; 212864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui } 213864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui 214864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui /* fill the data */ 215864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui attr = 216864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui nla_reserve(skb, ACPI_GENL_ATTR_EVENT, 217864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui sizeof(struct acpi_genl_event)); 218864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui if (!attr) { 219864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui nlmsg_free(skb); 220864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui return -EINVAL; 221864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui } 222864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui 223864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui event = nla_data(attr); 224864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui if (!event) { 225864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui nlmsg_free(skb); 226864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui return -EINVAL; 227864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui } 228864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui 229864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui memset(event, 0, sizeof(struct acpi_genl_event)); 230864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui 231962ce8ca0604af0c3c5609f7613d4ec5fcfac623Zhang Rui strcpy(event->device_class, device_class); 232962ce8ca0604af0c3c5609f7613d4ec5fcfac623Zhang Rui strcpy(event->bus_id, bus_id); 233864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui event->type = type; 234864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui event->data = data; 235864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui 236864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui /* send multicast genetlink message */ 237864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui result = genlmsg_end(skb, msg_header); 238864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui if (result < 0) { 239864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui nlmsg_free(skb); 240864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui return result; 241864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui } 242864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui 243ff491a7334acfd74e515c896632e37e401f52676Pablo Neira Ayuso genlmsg_multicast(skb, 0, acpi_event_mcgrp.id, GFP_ATOMIC); 244864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui return 0; 245864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui} 246864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui 247962ce8ca0604af0c3c5609f7613d4ec5fcfac623Zhang RuiEXPORT_SYMBOL(acpi_bus_generate_netlink_event); 248962ce8ca0604af0c3c5609f7613d4ec5fcfac623Zhang Rui 249864bdfb912e372670b5b2541dac9d273a4a7722aZhang Ruistatic int acpi_event_genetlink_init(void) 250864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui{ 251864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui int result; 252864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui 253864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui result = genl_register_family(&acpi_event_genl_family); 254864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui if (result) 255864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui return result; 256864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui 2579c977a453ed62396d067b75f3f272b3fb1ea3accZhang Rui result = genl_register_mc_group(&acpi_event_genl_family, 2589c977a453ed62396d067b75f3f272b3fb1ea3accZhang Rui &acpi_event_mcgrp); 259864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui if (result) 260864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui genl_unregister_family(&acpi_event_genl_family); 261864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui 262864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui return result; 263864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui} 264864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui 265864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui#else 2663e069ee0c30d6f28b79e409ef2df1ffa427897aeLen Brownint acpi_bus_generate_netlink_event(const char *device_class, 2673e069ee0c30d6f28b79e409ef2df1ffa427897aeLen Brown const char *bus_id, 2683e069ee0c30d6f28b79e409ef2df1ffa427897aeLen Brown u8 type, int data) 269864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui{ 270864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui return 0; 271864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui} 272864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui 27366baf327ae5d4c17e75d1f501145e79eaeeaf649Henrique de Moraes HolschuhEXPORT_SYMBOL(acpi_bus_generate_netlink_event); 274962ce8ca0604af0c3c5609f7613d4ec5fcfac623Zhang Rui 275864bdfb912e372670b5b2541dac9d273a4a7722aZhang Ruistatic int acpi_event_genetlink_init(void) 276864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui{ 277864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui return -ENODEV; 278864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui} 279864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui#endif 280864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui 2811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int __init acpi_event_init(void) 2821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 28314e04fb34ffa82ee61ae69f98d8fca12d2e8e31cLen Brown#ifdef CONFIG_ACPI_PROC_EVENT 2844be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown struct proc_dir_entry *entry; 28514e04fb34ffa82ee61ae69f98d8fca12d2e8e31cLen Brown#endif 2861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int error = 0; 2871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (acpi_disabled) 289d550d98d3317378d93a4869db204725d270ec812Patrick Mochel return 0; 2901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 291864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui /* create genetlink for acpi event */ 292864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui error = acpi_event_genetlink_init(); 293864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui if (error) 294864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui printk(KERN_WARNING PREFIX 295864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui "Failed to create genetlink family for ACPI event\n"); 296864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui 29714e04fb34ffa82ee61ae69f98d8fca12d2e8e31cLen Brown#ifdef CONFIG_ACPI_PROC_EVENT 2981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 'event' [R] */ 299cf7acfab032ff262f42954328cdfd20a5d9aaaacDenis V. Lunev entry = proc_create("event", S_IRUSR, acpi_root_dir, 300cf7acfab032ff262f42954328cdfd20a5d9aaaacDenis V. Lunev &acpi_system_event_ops); 301cf7acfab032ff262f42954328cdfd20a5d9aaaacDenis V. Lunev if (!entry) 302864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui return -ENODEV; 30314e04fb34ffa82ee61ae69f98d8fca12d2e8e31cLen Brown#endif 304864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui 305864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui return 0; 3061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 308864bdfb912e372670b5b2541dac9d273a4a7722aZhang Ruifs_initcall(acpi_event_init); 309