0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #define pr_fmt(fmt) "ACPI: " fmt
0011
0012 #include <linux/spinlock.h>
0013 #include <linux/export.h>
0014 #include <linux/proc_fs.h>
0015 #include <linux/init.h>
0016 #include <linux/poll.h>
0017 #include <linux/gfp.h>
0018 #include <linux/acpi.h>
0019 #include <net/netlink.h>
0020 #include <net/genetlink.h>
0021
0022 #include "internal.h"
0023
0024
0025 static BLOCKING_NOTIFIER_HEAD(acpi_chain_head);
0026
0027 int acpi_notifier_call_chain(struct acpi_device *dev, u32 type, u32 data)
0028 {
0029 struct acpi_bus_event event;
0030
0031 strcpy(event.device_class, dev->pnp.device_class);
0032 strcpy(event.bus_id, dev->pnp.bus_id);
0033 event.type = type;
0034 event.data = data;
0035 return (blocking_notifier_call_chain(&acpi_chain_head, 0, (void *)&event)
0036 == NOTIFY_BAD) ? -EINVAL : 0;
0037 }
0038 EXPORT_SYMBOL(acpi_notifier_call_chain);
0039
0040 int register_acpi_notifier(struct notifier_block *nb)
0041 {
0042 return blocking_notifier_chain_register(&acpi_chain_head, nb);
0043 }
0044 EXPORT_SYMBOL(register_acpi_notifier);
0045
0046 int unregister_acpi_notifier(struct notifier_block *nb)
0047 {
0048 return blocking_notifier_chain_unregister(&acpi_chain_head, nb);
0049 }
0050 EXPORT_SYMBOL(unregister_acpi_notifier);
0051
0052 #ifdef CONFIG_NET
0053 static unsigned int acpi_event_seqnum;
0054 struct acpi_genl_event {
0055 acpi_device_class device_class;
0056 char bus_id[15];
0057 u32 type;
0058 u32 data;
0059 };
0060
0061
0062 enum {
0063 ACPI_GENL_ATTR_UNSPEC,
0064 ACPI_GENL_ATTR_EVENT,
0065 __ACPI_GENL_ATTR_MAX,
0066 };
0067 #define ACPI_GENL_ATTR_MAX (__ACPI_GENL_ATTR_MAX - 1)
0068
0069
0070 enum {
0071 ACPI_GENL_CMD_UNSPEC,
0072 ACPI_GENL_CMD_EVENT,
0073 __ACPI_GENL_CMD_MAX,
0074 };
0075 #define ACPI_GENL_CMD_MAX (__ACPI_GENL_CMD_MAX - 1)
0076
0077 #define ACPI_GENL_FAMILY_NAME "acpi_event"
0078 #define ACPI_GENL_VERSION 0x01
0079 #define ACPI_GENL_MCAST_GROUP_NAME "acpi_mc_group"
0080
0081 static const struct genl_multicast_group acpi_event_mcgrps[] = {
0082 { .name = ACPI_GENL_MCAST_GROUP_NAME, },
0083 };
0084
0085 static struct genl_family acpi_event_genl_family __ro_after_init = {
0086 .module = THIS_MODULE,
0087 .name = ACPI_GENL_FAMILY_NAME,
0088 .version = ACPI_GENL_VERSION,
0089 .maxattr = ACPI_GENL_ATTR_MAX,
0090 .mcgrps = acpi_event_mcgrps,
0091 .n_mcgrps = ARRAY_SIZE(acpi_event_mcgrps),
0092 };
0093
0094 int acpi_bus_generate_netlink_event(const char *device_class,
0095 const char *bus_id,
0096 u8 type, int data)
0097 {
0098 struct sk_buff *skb;
0099 struct nlattr *attr;
0100 struct acpi_genl_event *event;
0101 void *msg_header;
0102 int size;
0103
0104
0105 size = nla_total_size(sizeof(struct acpi_genl_event)) +
0106 nla_total_size(0);
0107
0108 skb = genlmsg_new(size, GFP_ATOMIC);
0109 if (!skb)
0110 return -ENOMEM;
0111
0112
0113 msg_header = genlmsg_put(skb, 0, acpi_event_seqnum++,
0114 &acpi_event_genl_family, 0,
0115 ACPI_GENL_CMD_EVENT);
0116 if (!msg_header) {
0117 nlmsg_free(skb);
0118 return -ENOMEM;
0119 }
0120
0121
0122 attr =
0123 nla_reserve(skb, ACPI_GENL_ATTR_EVENT,
0124 sizeof(struct acpi_genl_event));
0125 if (!attr) {
0126 nlmsg_free(skb);
0127 return -EINVAL;
0128 }
0129
0130 event = nla_data(attr);
0131 memset(event, 0, sizeof(struct acpi_genl_event));
0132
0133 strscpy(event->device_class, device_class, sizeof(event->device_class));
0134 strscpy(event->bus_id, bus_id, sizeof(event->bus_id));
0135 event->type = type;
0136 event->data = data;
0137
0138
0139 genlmsg_end(skb, msg_header);
0140
0141 genlmsg_multicast(&acpi_event_genl_family, skb, 0, 0, GFP_ATOMIC);
0142 return 0;
0143 }
0144
0145 EXPORT_SYMBOL(acpi_bus_generate_netlink_event);
0146
0147 static int __init acpi_event_genetlink_init(void)
0148 {
0149 return genl_register_family(&acpi_event_genl_family);
0150 }
0151
0152 #else
0153 int acpi_bus_generate_netlink_event(const char *device_class,
0154 const char *bus_id,
0155 u8 type, int data)
0156 {
0157 return 0;
0158 }
0159
0160 EXPORT_SYMBOL(acpi_bus_generate_netlink_event);
0161
0162 static int acpi_event_genetlink_init(void)
0163 {
0164 return -ENODEV;
0165 }
0166 #endif
0167
0168 static int __init acpi_event_init(void)
0169 {
0170 int error;
0171
0172 if (acpi_disabled)
0173 return 0;
0174
0175
0176 error = acpi_event_genetlink_init();
0177 if (error)
0178 pr_warn("Failed to create genetlink family for ACPI event\n");
0179
0180 return 0;
0181 }
0182
0183 fs_initcall(acpi_event_init);