event.c revision 9c977a453ed62396d067b75f3f272b3fb1ea3acc
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
201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Global vars for handling event proc entry */
211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic DEFINE_SPINLOCK(acpi_system_event_lock);
224be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brownint event_is_open = 0;
234be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brownextern struct list_head acpi_bus_event_list;
244be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brownextern wait_queue_head_t acpi_bus_event_queue;
251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
264be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brownstatic int acpi_system_open_event(struct inode *inode, struct file *file)
271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
28c65ade4dc8b486e8c8b9b0a6399789a5428e2039Pavel Machek	spin_lock_irq(&acpi_system_event_lock);
291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
30c65ade4dc8b486e8c8b9b0a6399789a5428e2039Pavel Machek	if (event_is_open)
311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto out_busy;
321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	event_is_open = 1;
341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
35c65ade4dc8b486e8c8b9b0a6399789a5428e2039Pavel Machek	spin_unlock_irq(&acpi_system_event_lock);
361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
384be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown      out_busy:
39c65ade4dc8b486e8c8b9b0a6399789a5428e2039Pavel Machek	spin_unlock_irq(&acpi_system_event_lock);
401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return -EBUSY;
411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic ssize_t
444be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brownacpi_system_read_event(struct file *file, char __user * buffer, size_t count,
454be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown		       loff_t * ppos)
461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
474be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown	int result = 0;
484be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown	struct acpi_bus_event event;
494be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown	static char str[ACPI_MAX_STRING];
504be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown	static int chars_remaining = 0;
514be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown	static char *ptr;
521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!chars_remaining) {
541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		memset(&event, 0, sizeof(struct acpi_bus_event));
551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if ((file->f_flags & O_NONBLOCK)
571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		    && (list_empty(&acpi_bus_event_list)))
58d550d98d3317378d93a4869db204725d270ec812Patrick Mochel			return -EAGAIN;
591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		result = acpi_bus_receive_event(&event);
615cc9eeef9a9567acdfc2f6943f24381bf460f008Pavel Machek		if (result)
62d550d98d3317378d93a4869db204725d270ec812Patrick Mochel			return result;
631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
644be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown		chars_remaining = sprintf(str, "%s %s %08x %08x\n",
654be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown					  event.device_class ? event.
664be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown					  device_class : "<unknown>",
674be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown					  event.bus_id ? event.
684be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown					  bus_id : "<unknown>", event.type,
694be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown					  event.data);
701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ptr = str;
711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (chars_remaining < count) {
741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		count = chars_remaining;
751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (copy_to_user(buffer, ptr, count))
78d550d98d3317378d93a4869db204725d270ec812Patrick Mochel		return -EFAULT;
791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	*ppos += count;
811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	chars_remaining -= count;
821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ptr += count;
831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
84d550d98d3317378d93a4869db204725d270ec812Patrick Mochel	return count;
851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
874be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brownstatic int acpi_system_close_event(struct inode *inode, struct file *file)
881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
894be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown	spin_lock_irq(&acpi_system_event_lock);
901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	event_is_open = 0;
914be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown	spin_unlock_irq(&acpi_system_event_lock);
921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
954be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brownstatic unsigned int acpi_system_poll_event(struct file *file, poll_table * wait)
961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	poll_wait(file, &acpi_bus_event_queue, wait);
981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!list_empty(&acpi_bus_event_list))
991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return POLLIN | POLLRDNORM;
1001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
103d75080328affb4b268da430b7074cc8139cc662aArjan van de Venstatic const struct file_operations acpi_system_event_ops = {
1044be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown	.open = acpi_system_open_event,
1054be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown	.read = acpi_system_read_event,
1064be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown	.release = acpi_system_close_event,
1074be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown	.poll = acpi_system_poll_event,
1081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
1091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
110864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui#ifdef CONFIG_NET
111864bdfb912e372670b5b2541dac9d273a4a7722aZhang Ruiunsigned int acpi_event_seqnum;
112864bdfb912e372670b5b2541dac9d273a4a7722aZhang Ruistruct acpi_genl_event {
113864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui	acpi_device_class device_class;
114864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui	char bus_id[15];
115864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui	u32 type;
116864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui	u32 data;
117864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui};
118864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui
119864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui/* attributes of acpi_genl_family */
120864bdfb912e372670b5b2541dac9d273a4a7722aZhang Ruienum {
121864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui	ACPI_GENL_ATTR_UNSPEC,
122864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui	ACPI_GENL_ATTR_EVENT,	/* ACPI event info needed by user space */
123864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui	__ACPI_GENL_ATTR_MAX,
124864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui};
125864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui#define ACPI_GENL_ATTR_MAX (__ACPI_GENL_ATTR_MAX - 1)
126864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui
127864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui/* commands supported by the acpi_genl_family */
128864bdfb912e372670b5b2541dac9d273a4a7722aZhang Ruienum {
129864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui	ACPI_GENL_CMD_UNSPEC,
130864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui	ACPI_GENL_CMD_EVENT,	/* kernel->user notifications for ACPI events */
131864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui	__ACPI_GENL_CMD_MAX,
132864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui};
133864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui#define ACPI_GENL_CMD_MAX (__ACPI_GENL_CMD_MAX - 1)
134864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui
1359c977a453ed62396d067b75f3f272b3fb1ea3accZhang Rui#define ACPI_GENL_FAMILY_NAME		"acpi_event"
1369c977a453ed62396d067b75f3f272b3fb1ea3accZhang Rui#define ACPI_GENL_VERSION		0x01
1379c977a453ed62396d067b75f3f272b3fb1ea3accZhang Rui#define ACPI_GENL_MCAST_GROUP_NAME 	"acpi_mc_group"
138864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui
139864bdfb912e372670b5b2541dac9d273a4a7722aZhang Ruistatic struct genl_family acpi_event_genl_family = {
140864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui	.id = GENL_ID_GENERATE,
1419c977a453ed62396d067b75f3f272b3fb1ea3accZhang Rui	.name = ACPI_GENL_FAMILY_NAME,
142864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui	.version = ACPI_GENL_VERSION,
143864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui	.maxattr = ACPI_GENL_ATTR_MAX,
144864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui};
145864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui
1469c977a453ed62396d067b75f3f272b3fb1ea3accZhang Ruistatic struct genl_multicast_group acpi_event_mcgrp = {
1479c977a453ed62396d067b75f3f272b3fb1ea3accZhang Rui	.name = ACPI_GENL_MCAST_GROUP_NAME,
148864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui};
149864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui
150864bdfb912e372670b5b2541dac9d273a4a7722aZhang Ruiint acpi_bus_generate_genetlink_event(struct acpi_device *device,
151864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui				      u8 type, int data)
152864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui{
153864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui	struct sk_buff *skb;
154864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui	struct nlattr *attr;
155864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui	struct acpi_genl_event *event;
156864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui	void *msg_header;
157864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui	int size;
158864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui	int result;
159864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui
160864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui	/* allocate memory */
161864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui	size = nla_total_size(sizeof(struct acpi_genl_event)) +
162864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui	    nla_total_size(0);
163864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui
164864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui	skb = genlmsg_new(size, GFP_ATOMIC);
165864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui	if (!skb)
166864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui		return -ENOMEM;
167864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui
168864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui	/* add the genetlink message header */
169864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui	msg_header = genlmsg_put(skb, 0, acpi_event_seqnum++,
170864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui				 &acpi_event_genl_family, 0,
171864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui				 ACPI_GENL_CMD_EVENT);
172864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui	if (!msg_header) {
173864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui		nlmsg_free(skb);
174864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui		return -ENOMEM;
175864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui	}
176864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui
177864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui	/* fill the data */
178864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui	attr =
179864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui	    nla_reserve(skb, ACPI_GENL_ATTR_EVENT,
180864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui			sizeof(struct acpi_genl_event));
181864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui	if (!attr) {
182864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui		nlmsg_free(skb);
183864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui		return -EINVAL;
184864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui	}
185864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui
186864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui	event = nla_data(attr);
187864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui	if (!event) {
188864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui		nlmsg_free(skb);
189864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui		return -EINVAL;
190864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui	}
191864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui
192864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui	memset(event, 0, sizeof(struct acpi_genl_event));
193864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui
194864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui	strcpy(event->device_class, device->pnp.device_class);
195864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui	strcpy(event->bus_id, device->dev.bus_id);
196864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui	event->type = type;
197864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui	event->data = data;
198864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui
199864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui	/* send multicast genetlink message */
200864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui	result = genlmsg_end(skb, msg_header);
201864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui	if (result < 0) {
202864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui		nlmsg_free(skb);
203864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui		return result;
204864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui	}
205864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui
206864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui	result =
2079c977a453ed62396d067b75f3f272b3fb1ea3accZhang Rui	    genlmsg_multicast(skb, 0, acpi_event_mcgrp.id, GFP_ATOMIC);
208864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui	if (result)
209864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui		ACPI_DEBUG_PRINT((ACPI_DB_INFO,
210864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui				  "Failed to send a Genetlink message!\n"));
211864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui	return 0;
212864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui}
213864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui
214864bdfb912e372670b5b2541dac9d273a4a7722aZhang Ruistatic int acpi_event_genetlink_init(void)
215864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui{
216864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui	int result;
217864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui
218864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui	result = genl_register_family(&acpi_event_genl_family);
219864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui	if (result)
220864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui		return result;
221864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui
2229c977a453ed62396d067b75f3f272b3fb1ea3accZhang Rui	result = genl_register_mc_group(&acpi_event_genl_family,
2239c977a453ed62396d067b75f3f272b3fb1ea3accZhang Rui					&acpi_event_mcgrp);
224864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui	if (result)
225864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui		genl_unregister_family(&acpi_event_genl_family);
226864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui
227864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui	return result;
228864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui}
229864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui
230864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui#else
231864bdfb912e372670b5b2541dac9d273a4a7722aZhang Ruiint acpi_bus_generate_genetlink_event(struct acpi_device *device, u8 type,
232864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui				      int data)
233864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui{
234864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui	return 0;
235864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui}
236864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui
237864bdfb912e372670b5b2541dac9d273a4a7722aZhang Ruistatic int acpi_event_genetlink_init(void)
238864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui{
239864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui	return -ENODEV;
240864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui}
241864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui#endif
242864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui
2431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int __init acpi_event_init(void)
2441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2454be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown	struct proc_dir_entry *entry;
2461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int error = 0;
2471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (acpi_disabled)
249d550d98d3317378d93a4869db204725d270ec812Patrick Mochel		return 0;
2501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
251864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui	/* create genetlink for acpi event */
252864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui	error = acpi_event_genetlink_init();
253864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui	if (error)
254864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui		printk(KERN_WARNING PREFIX
255864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui		       "Failed to create genetlink family for ACPI event\n");
256864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui
2571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* 'event' [R] */
2581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	entry = create_proc_entry("event", S_IRUSR, acpi_root_dir);
2591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (entry)
2601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		entry->proc_fops = &acpi_system_event_ops;
261864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui	else
262864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui		return -ENODEV;
263864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui
264864bdfb912e372670b5b2541dac9d273a4a7722aZhang Rui	return 0;
2651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
267864bdfb912e372670b5b2541dac9d273a4a7722aZhang Ruifs_initcall(acpi_event_init);
268