brintos

brintos / linux-shallow public Read only

0
0
Text · 4.2 KiB · d199a19 Raw
184 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * event.c - exporting ACPI events via procfs4 *5 *  Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com>6 *  Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>7 *8 */9 10#define pr_fmt(fmt) "ACPI: " fmt11 12#include <linux/spinlock.h>13#include <linux/export.h>14#include <linux/proc_fs.h>15#include <linux/init.h>16#include <linux/poll.h>17#include <linux/gfp.h>18#include <linux/acpi.h>19#include <net/netlink.h>20#include <net/genetlink.h>21 22#include "internal.h"23 24/* ACPI notifier chain */25static BLOCKING_NOTIFIER_HEAD(acpi_chain_head);26 27int acpi_notifier_call_chain(struct acpi_device *dev, u32 type, u32 data)28{29	struct acpi_bus_event event;30 31	strcpy(event.device_class, dev->pnp.device_class);32	strcpy(event.bus_id, dev->pnp.bus_id);33	event.type = type;34	event.data = data;35	return (blocking_notifier_call_chain(&acpi_chain_head, 0, (void *)&event)36			== NOTIFY_BAD) ? -EINVAL : 0;37}38EXPORT_SYMBOL(acpi_notifier_call_chain);39 40int register_acpi_notifier(struct notifier_block *nb)41{42	return blocking_notifier_chain_register(&acpi_chain_head, nb);43}44EXPORT_SYMBOL(register_acpi_notifier);45 46int unregister_acpi_notifier(struct notifier_block *nb)47{48	return blocking_notifier_chain_unregister(&acpi_chain_head, nb);49}50EXPORT_SYMBOL(unregister_acpi_notifier);51 52#ifdef CONFIG_NET53static unsigned int acpi_event_seqnum;54struct acpi_genl_event {55	acpi_device_class device_class;56	char bus_id[15];57	u32 type;58	u32 data;59};60 61/* attributes of acpi_genl_family */62enum {63	ACPI_GENL_ATTR_UNSPEC,64	ACPI_GENL_ATTR_EVENT,	/* ACPI event info needed by user space */65	__ACPI_GENL_ATTR_MAX,66};67#define ACPI_GENL_ATTR_MAX (__ACPI_GENL_ATTR_MAX - 1)68 69/* commands supported by the acpi_genl_family */70enum {71	ACPI_GENL_CMD_UNSPEC,72	ACPI_GENL_CMD_EVENT,	/* kernel->user notifications for ACPI events */73	__ACPI_GENL_CMD_MAX,74};75#define ACPI_GENL_CMD_MAX (__ACPI_GENL_CMD_MAX - 1)76 77#define ACPI_GENL_FAMILY_NAME		"acpi_event"78#define ACPI_GENL_VERSION		0x0179#define ACPI_GENL_MCAST_GROUP_NAME 	"acpi_mc_group"80 81static const struct genl_multicast_group acpi_event_mcgrps[] = {82	{ .name = ACPI_GENL_MCAST_GROUP_NAME, },83};84 85static struct genl_family acpi_event_genl_family __ro_after_init = {86	.module = THIS_MODULE,87	.name = ACPI_GENL_FAMILY_NAME,88	.version = ACPI_GENL_VERSION,89	.maxattr = ACPI_GENL_ATTR_MAX,90	.mcgrps = acpi_event_mcgrps,91	.n_mcgrps = ARRAY_SIZE(acpi_event_mcgrps),92};93 94int acpi_bus_generate_netlink_event(const char *device_class,95				      const char *bus_id,96				      u8 type, int data)97{98	struct sk_buff *skb;99	struct nlattr *attr;100	struct acpi_genl_event *event;101	void *msg_header;102	int size;103 104	/* allocate memory */105	size = nla_total_size(sizeof(struct acpi_genl_event)) +106	    nla_total_size(0);107 108	skb = genlmsg_new(size, GFP_ATOMIC);109	if (!skb)110		return -ENOMEM;111 112	/* add the genetlink message header */113	msg_header = genlmsg_put(skb, 0, acpi_event_seqnum++,114				 &acpi_event_genl_family, 0,115				 ACPI_GENL_CMD_EVENT);116	if (!msg_header) {117		nlmsg_free(skb);118		return -ENOMEM;119	}120 121	/* fill the data */122	attr =123	    nla_reserve(skb, ACPI_GENL_ATTR_EVENT,124			sizeof(struct acpi_genl_event));125	if (!attr) {126		nlmsg_free(skb);127		return -EINVAL;128	}129 130	event = nla_data(attr);131	memset(event, 0, sizeof(struct acpi_genl_event));132 133	strscpy(event->device_class, device_class, sizeof(event->device_class));134	strscpy(event->bus_id, bus_id, sizeof(event->bus_id));135	event->type = type;136	event->data = data;137 138	/* send multicast genetlink message */139	genlmsg_end(skb, msg_header);140 141	genlmsg_multicast(&acpi_event_genl_family, skb, 0, 0, GFP_ATOMIC);142	return 0;143}144 145EXPORT_SYMBOL(acpi_bus_generate_netlink_event);146 147static int __init acpi_event_genetlink_init(void)148{149	return genl_register_family(&acpi_event_genl_family);150}151 152#else153int acpi_bus_generate_netlink_event(const char *device_class,154				      const char *bus_id,155				      u8 type, int data)156{157	return 0;158}159 160EXPORT_SYMBOL(acpi_bus_generate_netlink_event);161 162static int acpi_event_genetlink_init(void)163{164	return -ENODEV;165}166#endif167 168static int __init acpi_event_init(void)169{170	int error;171 172	if (acpi_disabled)173		return 0;174 175	/* create genetlink for acpi event */176	error = acpi_event_genetlink_init();177	if (error)178		pr_warn("Failed to create genetlink family for ACPI event\n");179 180	return 0;181}182 183fs_initcall(acpi_event_init);184