event.c revision a192a9580bcc41692be1f36b77c3b681827f566a
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 17a192a9580bcc41692be1f36b77c3b681827f566aLen Brown#include "internal.h" 18a192a9580bcc41692be1f36b77c3b681827f566aLen Brown 191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define _COMPONENT ACPI_SYSTEM_COMPONENT 20f52fd66d2ea794010c2d7536cf8e6abed0ac4947Len BrownACPI_MODULE_NAME("event"); 211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2214e04fb34ffa82ee61ae69f98d8fca12d2e8e31cLen Brown#ifdef CONFIG_ACPI_PROC_EVENT 231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Global vars for handling event proc entry */ 241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic DEFINE_SPINLOCK(acpi_system_event_lock); 254be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brownint event_is_open = 0; 264be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brownextern struct list_head acpi_bus_event_list; 274be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brownextern wait_queue_head_t acpi_bus_event_queue; 281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 294be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brownstatic int acpi_system_open_event(struct inode *inode, struct file *file) 301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 31c65ade4dc8b486e8c8b9b0a6399789a5428e2039Pavel Machek spin_lock_irq(&acpi_system_event_lock); 321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 33c65ade4dc8b486e8c8b9b0a6399789a5428e2039Pavel Machek if (event_is_open) 341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto out_busy; 351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds event_is_open = 1; 371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 38c65ade4dc8b486e8c8b9b0a6399789a5428e2039Pavel Machek spin_unlock_irq(&acpi_system_event_lock); 391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 414be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown out_busy: 42c65ade4dc8b486e8c8b9b0a6399789a5428e2039Pavel Machek spin_unlock_irq(&acpi_system_event_lock); 431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EBUSY; 441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic ssize_t 474be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brownacpi_system_read_event(struct file *file, char __user * buffer, size_t count, 484be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown loff_t * ppos) 491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 504be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown int result = 0; 514be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown struct acpi_bus_event event; 524be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown static char str[ACPI_MAX_STRING]; 534be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown static int chars_remaining = 0; 544be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown static char *ptr; 551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!chars_remaining) { 571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds memset(&event, 0, sizeof(struct acpi_bus_event)); 581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((file->f_flags & O_NONBLOCK) 601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds && (list_empty(&acpi_bus_event_list))) 61d550d98d3317378d93a4869db204725d270ec812Patrick Mochel return -EAGAIN; 621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds result = acpi_bus_receive_event(&event); 645cc9eeef9a9567acdfc2f6943f24381bf460f008Pavel Machek if (result) 65d550d98d3317378d93a4869db204725d270ec812Patrick Mochel return result; 661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 674be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown chars_remaining = sprintf(str, "%s %s %08x %08x\n", 684be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown event.device_class ? event. 694be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown device_class : "<unknown>", 704be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown event.bus_id ? event. 714be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown bus_id : "<unknown>", event.type, 724be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown event.data); 731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ptr = str; 741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (chars_remaining < count) { 771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds count = chars_remaining; 781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (copy_to_user(buffer, ptr, count)) 81d550d98d3317378d93a4869db204725d270ec812Patrick Mochel return -EFAULT; 821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *ppos += count; 841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds chars_remaining -= count; 851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ptr += count; 861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 87d550d98d3317378d93a4869db204725d270ec812Patrick Mochel return count; 881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 904be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brownstatic int acpi_system_close_event(struct inode *inode, struct file *file) 911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 924be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown spin_lock_irq(&acpi_system_event_lock); 931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds event_is_open = 0; 944be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown spin_unlock_irq(&acpi_system_event_lock); 951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 984be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brownstatic unsigned int acpi_system_poll_event(struct file *file, poll_table * wait) 991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds poll_wait(file, &acpi_bus_event_queue, wait); 1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!list_empty(&acpi_bus_event_list)) 1021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return POLLIN | POLLRDNORM; 1031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 1041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 106d75080328affb4b268da430b7074cc8139cc662aArjan van de Venstatic const struct file_operations acpi_system_event_ops = { 107cf7acfab032ff262f42954328cdfd20a5d9aaaacDenis V. Lunev .owner = THIS_MODULE, 1084be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown .open = acpi_system_open_event, 1094be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown .read = acpi_system_read_event, 1104be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown .release = acpi_system_close_event, 1114be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown .poll = acpi_system_poll_event, 1121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 11314e04fb34ffa82ee61ae69f98d8fca12d2e8e31cLen Brown#endif /* CONFIG_ACPI_PROC_EVENT */ 1141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1159ee85241fdaab358dff1d8647f20a478cfa512a1Zhang Rui/* ACPI notifier chain */ 116c8e773fa4f6a999a80d9fa3836f412e259ab6fa1Adrian Bunkstatic BLOCKING_NOTIFIER_HEAD(acpi_chain_head); 1179ee85241fdaab358dff1d8647f20a478cfa512a1Zhang Rui 1189ee85241fdaab358dff1d8647f20a478cfa512a1Zhang Ruiint acpi_notifier_call_chain(struct acpi_device *dev, u32 type, u32 data) 1199ee85241fdaab358dff1d8647f20a478cfa512a1Zhang Rui{ 1209ee85241fdaab358dff1d8647f20a478cfa512a1Zhang Rui struct acpi_bus_event event; 1219ee85241fdaab358dff1d8647f20a478cfa512a1Zhang Rui 1229ee85241fdaab358dff1d8647f20a478cfa512a1Zhang Rui strcpy(event.device_class, dev->pnp.device_class); 1239ee85241fdaab358dff1d8647f20a478cfa512a1Zhang Rui strcpy(event.bus_id, dev->pnp.bus_id); 1249ee85241fdaab358dff1d8647f20a478cfa512a1Zhang Rui event.type = type; 1259ee85241fdaab358dff1d8647f20a478cfa512a1Zhang Rui event.data = data; 1269ee85241fdaab358dff1d8647f20a478cfa512a1Zhang Rui return (blocking_notifier_call_chain(&acpi_chain_head, 0, (void *)&event) 1279ee85241fdaab358dff1d8647f20a478cfa512a1Zhang Rui == NOTIFY_BAD) ? -EINVAL : 0; 1289ee85241fdaab358dff1d8647f20a478cfa512a1Zhang Rui} 1299ee85241fdaab358dff1d8647f20a478cfa512a1Zhang RuiEXPORT_SYMBOL(acpi_notifier_call_chain); 1309ee85241fdaab358dff1d8647f20a478cfa512a1Zhang Rui 1319ee85241fdaab358dff1d8647f20a478cfa512a1Zhang Ruiint register_acpi_notifier(struct notifier_block *nb) 1329ee85241fdaab358dff1d8647f20a478cfa512a1Zhang Rui{ 1339ee85241fdaab358dff1d8647f20a478cfa512a1Zhang Rui return blocking_notifier_chain_register(&acpi_chain_head, nb); 1349ee85241fdaab358dff1d8647f20a478cfa512a1Zhang Rui} 1359ee85241fdaab358dff1d8647f20a478cfa512a1Zhang RuiEXPORT_SYMBOL(register_acpi_notifier); 1369ee85241fdaab358dff1d8647f20a478cfa512a1Zhang Rui 1379ee85241fdaab358dff1d8647f20a478cfa512a1Zhang Ruiint unregister_acpi_notifier(struct notifier_block *nb) 1389ee85241fdaab358dff1d8647f20a478cfa512a1Zhang Rui{ 1399ee85241fdaab358dff1d8647f20a478cfa512a1Zhang Rui return blocking_notifier_chain_unregister(&acpi_chain_head, nb); 1409ee85241fdaab358dff1d8647f20a478cfa512a1Zhang Rui} 1419ee85241fdaab358dff1d8647f20a478cfa512a1Zhang RuiEXPORT_SYMBOL(unregister_acpi_notifier); 1429ee85241fdaab358dff1d8647f20a478cfa512a1Zhang Rui 143864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui#ifdef CONFIG_NET 144e13d87473284131a7ead8121d5d29345101f68a4Adrian Bunkstatic unsigned int acpi_event_seqnum; 145864bdfb912e372670b5b2541dac9d273a4a7722aZhang Ruistruct acpi_genl_event { 146864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui acpi_device_class device_class; 147864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui char bus_id[15]; 148864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui u32 type; 149864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui u32 data; 150864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui}; 151864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui 152864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui/* attributes of acpi_genl_family */ 153864bdfb912e372670b5b2541dac9d273a4a7722aZhang Ruienum { 154864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui ACPI_GENL_ATTR_UNSPEC, 155864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui ACPI_GENL_ATTR_EVENT, /* ACPI event info needed by user space */ 156864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui __ACPI_GENL_ATTR_MAX, 157864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui}; 158864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui#define ACPI_GENL_ATTR_MAX (__ACPI_GENL_ATTR_MAX - 1) 159864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui 160864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui/* commands supported by the acpi_genl_family */ 161864bdfb912e372670b5b2541dac9d273a4a7722aZhang Ruienum { 162864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui ACPI_GENL_CMD_UNSPEC, 163864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui ACPI_GENL_CMD_EVENT, /* kernel->user notifications for ACPI events */ 164864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui __ACPI_GENL_CMD_MAX, 165864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui}; 166864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui#define ACPI_GENL_CMD_MAX (__ACPI_GENL_CMD_MAX - 1) 167864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui 1689c977a453ed62396d067b75f3f272b3fb1ea3accZhang Rui#define ACPI_GENL_FAMILY_NAME "acpi_event" 1699c977a453ed62396d067b75f3f272b3fb1ea3accZhang Rui#define ACPI_GENL_VERSION 0x01 1709c977a453ed62396d067b75f3f272b3fb1ea3accZhang Rui#define ACPI_GENL_MCAST_GROUP_NAME "acpi_mc_group" 171864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui 172864bdfb912e372670b5b2541dac9d273a4a7722aZhang Ruistatic struct genl_family acpi_event_genl_family = { 173864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui .id = GENL_ID_GENERATE, 1749c977a453ed62396d067b75f3f272b3fb1ea3accZhang Rui .name = ACPI_GENL_FAMILY_NAME, 175864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui .version = ACPI_GENL_VERSION, 176864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui .maxattr = ACPI_GENL_ATTR_MAX, 177864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui}; 178864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui 1799c977a453ed62396d067b75f3f272b3fb1ea3accZhang Ruistatic struct genl_multicast_group acpi_event_mcgrp = { 1809c977a453ed62396d067b75f3f272b3fb1ea3accZhang Rui .name = ACPI_GENL_MCAST_GROUP_NAME, 181864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui}; 182864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui 183962ce8ca0604af0c3c5609f7613d4ec5fcfac623Zhang Ruiint acpi_bus_generate_netlink_event(const char *device_class, 184962ce8ca0604af0c3c5609f7613d4ec5fcfac623Zhang Rui const char *bus_id, 185864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui u8 type, int data) 186864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui{ 187864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui struct sk_buff *skb; 188864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui struct nlattr *attr; 189864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui struct acpi_genl_event *event; 190864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui void *msg_header; 191864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui int size; 192864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui int result; 193864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui 194864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui /* allocate memory */ 195864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui size = nla_total_size(sizeof(struct acpi_genl_event)) + 196864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui nla_total_size(0); 197864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui 198864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui skb = genlmsg_new(size, GFP_ATOMIC); 199864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui if (!skb) 200864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui return -ENOMEM; 201864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui 202864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui /* add the genetlink message header */ 203864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui msg_header = genlmsg_put(skb, 0, acpi_event_seqnum++, 204864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui &acpi_event_genl_family, 0, 205864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui ACPI_GENL_CMD_EVENT); 206864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui if (!msg_header) { 207864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui nlmsg_free(skb); 208864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui return -ENOMEM; 209864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui } 210864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui 211864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui /* fill the data */ 212864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui attr = 213864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui nla_reserve(skb, ACPI_GENL_ATTR_EVENT, 214864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui sizeof(struct acpi_genl_event)); 215864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui if (!attr) { 216864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui nlmsg_free(skb); 217864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui return -EINVAL; 218864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui } 219864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui 220864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui event = nla_data(attr); 221864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui if (!event) { 222864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui nlmsg_free(skb); 223864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui return -EINVAL; 224864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui } 225864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui 226864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui memset(event, 0, sizeof(struct acpi_genl_event)); 227864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui 228962ce8ca0604af0c3c5609f7613d4ec5fcfac623Zhang Rui strcpy(event->device_class, device_class); 229962ce8ca0604af0c3c5609f7613d4ec5fcfac623Zhang Rui strcpy(event->bus_id, bus_id); 230864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui event->type = type; 231864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui event->data = data; 232864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui 233864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui /* send multicast genetlink message */ 234864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui result = genlmsg_end(skb, msg_header); 235864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui if (result < 0) { 236864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui nlmsg_free(skb); 237864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui return result; 238864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui } 239864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui 240ff491a7334acfd74e515c896632e37e401f52676Pablo Neira Ayuso genlmsg_multicast(skb, 0, acpi_event_mcgrp.id, GFP_ATOMIC); 241864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui return 0; 242864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui} 243864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui 244962ce8ca0604af0c3c5609f7613d4ec5fcfac623Zhang RuiEXPORT_SYMBOL(acpi_bus_generate_netlink_event); 245962ce8ca0604af0c3c5609f7613d4ec5fcfac623Zhang Rui 246864bdfb912e372670b5b2541dac9d273a4a7722aZhang Ruistatic int acpi_event_genetlink_init(void) 247864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui{ 248864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui int result; 249864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui 250864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui result = genl_register_family(&acpi_event_genl_family); 251864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui if (result) 252864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui return result; 253864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui 2549c977a453ed62396d067b75f3f272b3fb1ea3accZhang Rui result = genl_register_mc_group(&acpi_event_genl_family, 2559c977a453ed62396d067b75f3f272b3fb1ea3accZhang Rui &acpi_event_mcgrp); 256864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui if (result) 257864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui genl_unregister_family(&acpi_event_genl_family); 258864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui 259864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui return result; 260864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui} 261864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui 262864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui#else 2633e069ee0c30d6f28b79e409ef2df1ffa427897aeLen Brownint acpi_bus_generate_netlink_event(const char *device_class, 2643e069ee0c30d6f28b79e409ef2df1ffa427897aeLen Brown const char *bus_id, 2653e069ee0c30d6f28b79e409ef2df1ffa427897aeLen Brown u8 type, int data) 266864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui{ 267864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui return 0; 268864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui} 269864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui 27066baf327ae5d4c17e75d1f501145e79eaeeaf649Henrique de Moraes HolschuhEXPORT_SYMBOL(acpi_bus_generate_netlink_event); 271962ce8ca0604af0c3c5609f7613d4ec5fcfac623Zhang Rui 272864bdfb912e372670b5b2541dac9d273a4a7722aZhang Ruistatic int acpi_event_genetlink_init(void) 273864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui{ 274864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui return -ENODEV; 275864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui} 276864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui#endif 277864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui 2781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int __init acpi_event_init(void) 2791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 28014e04fb34ffa82ee61ae69f98d8fca12d2e8e31cLen Brown#ifdef CONFIG_ACPI_PROC_EVENT 2814be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown struct proc_dir_entry *entry; 28214e04fb34ffa82ee61ae69f98d8fca12d2e8e31cLen Brown#endif 2831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int error = 0; 2841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (acpi_disabled) 286d550d98d3317378d93a4869db204725d270ec812Patrick Mochel return 0; 2871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 288864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui /* create genetlink for acpi event */ 289864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui error = acpi_event_genetlink_init(); 290864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui if (error) 291864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui printk(KERN_WARNING PREFIX 292864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui "Failed to create genetlink family for ACPI event\n"); 293864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui 29414e04fb34ffa82ee61ae69f98d8fca12d2e8e31cLen Brown#ifdef CONFIG_ACPI_PROC_EVENT 2951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 'event' [R] */ 296cf7acfab032ff262f42954328cdfd20a5d9aaaacDenis V. Lunev entry = proc_create("event", S_IRUSR, acpi_root_dir, 297cf7acfab032ff262f42954328cdfd20a5d9aaaacDenis V. Lunev &acpi_system_event_ops); 298cf7acfab032ff262f42954328cdfd20a5d9aaaacDenis V. Lunev if (!entry) 299864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui return -ENODEV; 30014e04fb34ffa82ee61ae69f98d8fca12d2e8e31cLen Brown#endif 301864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui 302864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui return 0; 3031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 305864bdfb912e372670b5b2541dac9d273a4a7722aZhang Ruifs_initcall(acpi_event_init); 306