event.c revision a192a9580bcc41692be1f36b77c3b681827f566a
1bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo/*
2bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo * event.c - exporting ACPI events via procfs
3bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo *
4bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo *  Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com>
5bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo *  Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
6bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo *
7bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo */
8bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo
9bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo#include <linux/spinlock.h>
10bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo#include <linux/proc_fs.h>
11bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo#include <linux/init.h>
12bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo#include <linux/poll.h>
13bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo#include <acpi/acpi_drivers.h>
14bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo#include <net/netlink.h>
15bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo#include <net/genetlink.h>
16bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo
17bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo#include "internal.h"
18bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo
19bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo#define _COMPONENT		ACPI_SYSTEM_COMPONENT
20bdcd81707973cf8aa9305337166f8ee842a050d4Kalle ValoACPI_MODULE_NAME("event");
21bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo
22bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo#ifdef CONFIG_ACPI_PROC_EVENT
236765d0aa5ff5b92098f5e571f26904106eae6ff3Vasanthakumar Thiagarajan/* Global vars for handling event proc entry */
24bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valostatic DEFINE_SPINLOCK(acpi_system_event_lock);
256765d0aa5ff5b92098f5e571f26904106eae6ff3Vasanthakumar Thiagarajanint event_is_open = 0;
26bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valoextern struct list_head acpi_bus_event_list;
27bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valoextern wait_queue_head_t acpi_bus_event_queue;
28bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo
29f5938f249a08a4e6c9046fa095be00db664158ccVasanthakumar Thiagarajanstatic int acpi_system_open_event(struct inode *inode, struct file *file)
30bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo{
31bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo	spin_lock_irq(&acpi_system_event_lock);
32bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo
33bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo	if (event_is_open)
34bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo		goto out_busy;
35bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo
36bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo	event_is_open = 1;
37bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo
38bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo	spin_unlock_irq(&acpi_system_event_lock);
39bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo	return 0;
40bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo
41bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo      out_busy:
42bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo	spin_unlock_irq(&acpi_system_event_lock);
43bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo	return -EBUSY;
44bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo}
45bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo
46bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valostatic ssize_t
47bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valoacpi_system_read_event(struct file *file, char __user * buffer, size_t count,
48bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo		       loff_t * ppos)
49bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo{
50bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo	int result = 0;
51bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo	struct acpi_bus_event event;
52bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo	static char str[ACPI_MAX_STRING];
53bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo	static int chars_remaining = 0;
54bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo	static char *ptr;
55bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo
56bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo	if (!chars_remaining) {
57bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo		memset(&event, 0, sizeof(struct acpi_bus_event));
58bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo
59bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo		if ((file->f_flags & O_NONBLOCK)
60bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo		    && (list_empty(&acpi_bus_event_list)))
61bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo			return -EAGAIN;
62bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo
63bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo		result = acpi_bus_receive_event(&event);
64bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo		if (result)
653c774bbab78435e349de2c88fc6e054716f8f2eaJouni Malinen			return result;
663c774bbab78435e349de2c88fc6e054716f8f2eaJouni Malinen
67bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo		chars_remaining = sprintf(str, "%s %s %08x %08x\n",
68bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo					  event.device_class ? event.
69bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo					  device_class : "<unknown>",
70bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo					  event.bus_id ? event.
71bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo					  bus_id : "<unknown>", event.type,
72bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo					  event.data);
73bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo		ptr = str;
74bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo	}
75bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo
76bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo	if (chars_remaining < count) {
77bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo		count = chars_remaining;
78bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo	}
79bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo
80bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo	if (copy_to_user(buffer, ptr, count))
81bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo		return -EFAULT;
82bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo
83bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo	*ppos += count;
84bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo	chars_remaining -= count;
85bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo	ptr += count;
86bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo
87bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo	return count;
88bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo}
89bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo
90bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valostatic int acpi_system_close_event(struct inode *inode, struct file *file)
91bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo{
92bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo	spin_lock_irq(&acpi_system_event_lock);
93bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo	event_is_open = 0;
94bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo	spin_unlock_irq(&acpi_system_event_lock);
95bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo	return 0;
96bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo}
97bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo
98bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valostatic unsigned int acpi_system_poll_event(struct file *file, poll_table * wait)
99bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo{
100bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo	poll_wait(file, &acpi_bus_event_queue, wait);
101bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo	if (!list_empty(&acpi_bus_event_list))
102bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo		return POLLIN | POLLRDNORM;
103bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo	return 0;
104bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo}
105bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo
106bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valostatic const struct file_operations acpi_system_event_ops = {
107bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo	.owner = THIS_MODULE,
108bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo	.open = acpi_system_open_event,
109bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo	.read = acpi_system_read_event,
110bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo	.release = acpi_system_close_event,
111bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo	.poll = acpi_system_poll_event,
112bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo};
113bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo#endif	/* CONFIG_ACPI_PROC_EVENT */
114bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo
115bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo/* ACPI notifier chain */
116bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valostatic BLOCKING_NOTIFIER_HEAD(acpi_chain_head);
117bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo
118bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valoint acpi_notifier_call_chain(struct acpi_device *dev, u32 type, u32 data)
119bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo{
120bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo	struct acpi_bus_event event;
121bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo
122bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo	strcpy(event.device_class, dev->pnp.device_class);
123bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo	strcpy(event.bus_id, dev->pnp.bus_id);
124bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo	event.type = type;
125bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo	event.data = data;
126bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo	return (blocking_notifier_call_chain(&acpi_chain_head, 0, (void *)&event)
127bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo                        == NOTIFY_BAD) ? -EINVAL : 0;
128bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo}
129bdcd81707973cf8aa9305337166f8ee842a050d4Kalle ValoEXPORT_SYMBOL(acpi_notifier_call_chain);
130bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo
131bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valoint register_acpi_notifier(struct notifier_block *nb)
132bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo{
133bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo	return blocking_notifier_chain_register(&acpi_chain_head, nb);
134bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo}
135bdcd81707973cf8aa9305337166f8ee842a050d4Kalle ValoEXPORT_SYMBOL(register_acpi_notifier);
136bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo
137bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valoint unregister_acpi_notifier(struct notifier_block *nb)
138bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo{
139bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo	return blocking_notifier_chain_unregister(&acpi_chain_head, nb);
140bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo}
141bdcd81707973cf8aa9305337166f8ee842a050d4Kalle ValoEXPORT_SYMBOL(unregister_acpi_notifier);
142bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo
143bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo#ifdef CONFIG_NET
144bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valostatic unsigned int acpi_event_seqnum;
145bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valostruct acpi_genl_event {
146bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo	acpi_device_class device_class;
147bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo	char bus_id[15];
148bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo	u32 type;
149bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo	u32 data;
150bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo};
151bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo
152bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo/* attributes of acpi_genl_family */
153bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valoenum {
154bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo	ACPI_GENL_ATTR_UNSPEC,
155bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo	ACPI_GENL_ATTR_EVENT,	/* ACPI event info needed by user space */
156bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo	__ACPI_GENL_ATTR_MAX,
157bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo};
158bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo#define ACPI_GENL_ATTR_MAX (__ACPI_GENL_ATTR_MAX - 1)
159bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo
160bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo/* commands supported by the acpi_genl_family */
161bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valoenum {
162bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo	ACPI_GENL_CMD_UNSPEC,
163bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo	ACPI_GENL_CMD_EVENT,	/* kernel->user notifications for ACPI events */
164bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo	__ACPI_GENL_CMD_MAX,
165bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo};
166bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo#define ACPI_GENL_CMD_MAX (__ACPI_GENL_CMD_MAX - 1)
167bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo
168bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo#define ACPI_GENL_FAMILY_NAME		"acpi_event"
169bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo#define ACPI_GENL_VERSION		0x01
170bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo#define ACPI_GENL_MCAST_GROUP_NAME 	"acpi_mc_group"
171bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo
172bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valostatic struct genl_family acpi_event_genl_family = {
173bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo	.id = GENL_ID_GENERATE,
174bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo	.name = ACPI_GENL_FAMILY_NAME,
175bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo	.version = ACPI_GENL_VERSION,
176bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo	.maxattr = ACPI_GENL_ATTR_MAX,
177bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo};
178bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo
179bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valostatic struct genl_multicast_group acpi_event_mcgrp = {
180bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo	.name = ACPI_GENL_MCAST_GROUP_NAME,
181bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo};
182bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo
183b142b91401b8e39671db74bd4fe89f281f4c2978Vasanthakumar Thiagarajanint acpi_bus_generate_netlink_event(const char *device_class,
184bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo				      const char *bus_id,
185bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo				      u8 type, int data)
186bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo{
187bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo	struct sk_buff *skb;
188bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo	struct nlattr *attr;
189bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo	struct acpi_genl_event *event;
190bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo	void *msg_header;
191bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo	int size;
192bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo	int result;
193b142b91401b8e39671db74bd4fe89f281f4c2978Vasanthakumar Thiagarajan
194b142b91401b8e39671db74bd4fe89f281f4c2978Vasanthakumar Thiagarajan	/* allocate memory */
195b142b91401b8e39671db74bd4fe89f281f4c2978Vasanthakumar Thiagarajan	size = nla_total_size(sizeof(struct acpi_genl_event)) +
196bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo	    nla_total_size(0);
197b142b91401b8e39671db74bd4fe89f281f4c2978Vasanthakumar Thiagarajan
198bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo	skb = genlmsg_new(size, GFP_ATOMIC);
199bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo	if (!skb)
200bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo		return -ENOMEM;
201bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo
202bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo	/* add the genetlink message header */
203bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo	msg_header = genlmsg_put(skb, 0, acpi_event_seqnum++,
204b142b91401b8e39671db74bd4fe89f281f4c2978Vasanthakumar Thiagarajan				 &acpi_event_genl_family, 0,
205bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo				 ACPI_GENL_CMD_EVENT);
206bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo	if (!msg_header) {
207bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo		nlmsg_free(skb);
208bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo		return -ENOMEM;
209bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo	}
210bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo
211bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo	/* fill the data */
212bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo	attr =
213bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo	    nla_reserve(skb, ACPI_GENL_ATTR_EVENT,
214bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo			sizeof(struct acpi_genl_event));
215bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo	if (!attr) {
216bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo		nlmsg_free(skb);
217bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo		return -EINVAL;
218bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo	}
219bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo
220bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo	event = nla_data(attr);
221bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo	if (!event) {
222b142b91401b8e39671db74bd4fe89f281f4c2978Vasanthakumar Thiagarajan		nlmsg_free(skb);
223b142b91401b8e39671db74bd4fe89f281f4c2978Vasanthakumar Thiagarajan		return -EINVAL;
224b142b91401b8e39671db74bd4fe89f281f4c2978Vasanthakumar Thiagarajan	}
225bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo
226bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo	memset(event, 0, sizeof(struct acpi_genl_event));
227bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo
228bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo	strcpy(event->device_class, device_class);
229bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo	strcpy(event->bus_id, bus_id);
230bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo	event->type = type;
231bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo	event->data = data;
232bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo
233bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo	/* send multicast genetlink message */
234bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo	result = genlmsg_end(skb, msg_header);
235bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo	if (result < 0) {
236bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo		nlmsg_free(skb);
237addb44be036dd5fc814be770ec4b90f08c820e76Kalle Valo		return result;
238addb44be036dd5fc814be770ec4b90f08c820e76Kalle Valo	}
239bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo
240addb44be036dd5fc814be770ec4b90f08c820e76Kalle Valo	genlmsg_multicast(skb, 0, acpi_event_mcgrp.id, GFP_ATOMIC);
241bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo	return 0;
242addb44be036dd5fc814be770ec4b90f08c820e76Kalle Valo}
243bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo
244bdcd81707973cf8aa9305337166f8ee842a050d4Kalle ValoEXPORT_SYMBOL(acpi_bus_generate_netlink_event);
245addb44be036dd5fc814be770ec4b90f08c820e76Kalle Valo
246addb44be036dd5fc814be770ec4b90f08c820e76Kalle Valostatic int acpi_event_genetlink_init(void)
247addb44be036dd5fc814be770ec4b90f08c820e76Kalle Valo{
248bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo	int result;
249bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo
250addb44be036dd5fc814be770ec4b90f08c820e76Kalle Valo	result = genl_register_family(&acpi_event_genl_family);
251addb44be036dd5fc814be770ec4b90f08c820e76Kalle Valo	if (result)
252addb44be036dd5fc814be770ec4b90f08c820e76Kalle Valo		return result;
253addb44be036dd5fc814be770ec4b90f08c820e76Kalle Valo
254addb44be036dd5fc814be770ec4b90f08c820e76Kalle Valo	result = genl_register_mc_group(&acpi_event_genl_family,
255addb44be036dd5fc814be770ec4b90f08c820e76Kalle Valo					&acpi_event_mcgrp);
256bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo	if (result)
257bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo		genl_unregister_family(&acpi_event_genl_family);
258addb44be036dd5fc814be770ec4b90f08c820e76Kalle Valo
259bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo	return result;
260bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo}
261bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo
262bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo#else
263bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valoint acpi_bus_generate_netlink_event(const char *device_class,
264bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo				      const char *bus_id,
265f9ea0753a18448a5e92369317b6ac061fe1275bfVasanthakumar Thiagarajan				      u8 type, int data)
266bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo{
267addb44be036dd5fc814be770ec4b90f08c820e76Kalle Valo	return 0;
268bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo}
269bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo
270addb44be036dd5fc814be770ec4b90f08c820e76Kalle ValoEXPORT_SYMBOL(acpi_bus_generate_netlink_event);
271addb44be036dd5fc814be770ec4b90f08c820e76Kalle Valo
272addb44be036dd5fc814be770ec4b90f08c820e76Kalle Valostatic int acpi_event_genetlink_init(void)
273addb44be036dd5fc814be770ec4b90f08c820e76Kalle Valo{
274addb44be036dd5fc814be770ec4b90f08c820e76Kalle Valo	return -ENODEV;
275addb44be036dd5fc814be770ec4b90f08c820e76Kalle Valo}
276bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo#endif
277bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo
278bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valostatic int __init acpi_event_init(void)
279bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo{
280addb44be036dd5fc814be770ec4b90f08c820e76Kalle Valo#ifdef CONFIG_ACPI_PROC_EVENT
281bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo	struct proc_dir_entry *entry;
282bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo#endif
283addb44be036dd5fc814be770ec4b90f08c820e76Kalle Valo	int error = 0;
284bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo
285addb44be036dd5fc814be770ec4b90f08c820e76Kalle Valo	if (acpi_disabled)
286addb44be036dd5fc814be770ec4b90f08c820e76Kalle Valo		return 0;
287bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo
288addb44be036dd5fc814be770ec4b90f08c820e76Kalle Valo	/* create genetlink for acpi event */
289addb44be036dd5fc814be770ec4b90f08c820e76Kalle Valo	error = acpi_event_genetlink_init();
290addb44be036dd5fc814be770ec4b90f08c820e76Kalle Valo	if (error)
291addb44be036dd5fc814be770ec4b90f08c820e76Kalle Valo		printk(KERN_WARNING PREFIX
292addb44be036dd5fc814be770ec4b90f08c820e76Kalle Valo		       "Failed to create genetlink family for ACPI event\n");
293addb44be036dd5fc814be770ec4b90f08c820e76Kalle Valo
294addb44be036dd5fc814be770ec4b90f08c820e76Kalle Valo#ifdef CONFIG_ACPI_PROC_EVENT
295bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo	/* 'event' [R] */
296bdcd81707973cf8aa9305337166f8ee842a050d4Kalle Valo	entry = proc_create("event", S_IRUSR, acpi_root_dir,
297addb44be036dd5fc814be770ec4b90f08c820e76Kalle Valo			    &acpi_system_event_ops);
298addb44be036dd5fc814be770ec4b90f08c820e76Kalle Valo	if (!entry)
299addb44be036dd5fc814be770ec4b90f08c820e76Kalle Valo		return -ENODEV;
300addb44be036dd5fc814be770ec4b90f08c820e76Kalle Valo#endif
301addb44be036dd5fc814be770ec4b90f08c820e76Kalle Valo
302f9ea0753a18448a5e92369317b6ac061fe1275bfVasanthakumar Thiagarajan	return 0;
303f9ea0753a18448a5e92369317b6ac061fe1275bfVasanthakumar Thiagarajan}
304addb44be036dd5fc814be770ec4b90f08c820e76Kalle Valo
305addb44be036dd5fc814be770ec4b90f08c820e76Kalle Valofs_initcall(acpi_event_init);
306addb44be036dd5fc814be770ec4b90f08c820e76Kalle Valo