Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Pull netlink into release branch

Len Brown 0d090b68 b4b613fd

+152 -8
+4
drivers/acpi/bus.c
··· 292 292 if (!device) 293 293 return -EINVAL; 294 294 295 + if (acpi_bus_generate_genetlink_event(device, type, data)) 296 + printk(KERN_WARNING PREFIX 297 + "Failed to generate an ACPI event via genetlink!\n"); 298 + 295 299 /* drop event on the floor if no one's listening */ 296 300 if (!event_is_open) 297 301 return 0;
+146 -7
drivers/acpi/event.c
··· 11 11 #include <linux/init.h> 12 12 #include <linux/poll.h> 13 13 #include <acpi/acpi_drivers.h> 14 + #include <net/netlink.h> 15 + #include <net/genetlink.h> 14 16 15 17 #define _COMPONENT ACPI_SYSTEM_COMPONENT 16 18 ACPI_MODULE_NAME("event"); ··· 49 47 static char str[ACPI_MAX_STRING]; 50 48 static int chars_remaining = 0; 51 49 static char *ptr; 52 - 53 50 54 51 if (!chars_remaining) { 55 52 memset(&event, 0, sizeof(struct acpi_bus_event)); ··· 107 106 .poll = acpi_system_poll_event, 108 107 }; 109 108 109 + #ifdef CONFIG_NET 110 + unsigned int acpi_event_seqnum; 111 + struct acpi_genl_event { 112 + acpi_device_class device_class; 113 + char bus_id[15]; 114 + u32 type; 115 + u32 data; 116 + }; 117 + 118 + /* attributes of acpi_genl_family */ 119 + enum { 120 + ACPI_GENL_ATTR_UNSPEC, 121 + ACPI_GENL_ATTR_EVENT, /* ACPI event info needed by user space */ 122 + __ACPI_GENL_ATTR_MAX, 123 + }; 124 + #define ACPI_GENL_ATTR_MAX (__ACPI_GENL_ATTR_MAX - 1) 125 + 126 + /* commands supported by the acpi_genl_family */ 127 + enum { 128 + ACPI_GENL_CMD_UNSPEC, 129 + ACPI_GENL_CMD_EVENT, /* kernel->user notifications for ACPI events */ 130 + __ACPI_GENL_CMD_MAX, 131 + }; 132 + #define ACPI_GENL_CMD_MAX (__ACPI_GENL_CMD_MAX - 1) 133 + 134 + #define ACPI_GENL_FAMILY_NAME "acpi_event" 135 + #define ACPI_GENL_VERSION 0x01 136 + #define ACPI_GENL_MCAST_GROUP_NAME "acpi_mc_group" 137 + 138 + static struct genl_family acpi_event_genl_family = { 139 + .id = GENL_ID_GENERATE, 140 + .name = ACPI_GENL_FAMILY_NAME, 141 + .version = ACPI_GENL_VERSION, 142 + .maxattr = ACPI_GENL_ATTR_MAX, 143 + }; 144 + 145 + static struct genl_multicast_group acpi_event_mcgrp = { 146 + .name = ACPI_GENL_MCAST_GROUP_NAME, 147 + }; 148 + 149 + int acpi_bus_generate_genetlink_event(struct acpi_device *device, 150 + u8 type, int data) 151 + { 152 + struct sk_buff *skb; 153 + struct nlattr *attr; 154 + struct acpi_genl_event *event; 155 + void *msg_header; 156 + int size; 157 + int result; 158 + 159 + /* allocate memory */ 160 + size = nla_total_size(sizeof(struct acpi_genl_event)) + 161 + nla_total_size(0); 162 + 163 + skb = genlmsg_new(size, GFP_ATOMIC); 164 + if (!skb) 165 + return -ENOMEM; 166 + 167 + /* add the genetlink message header */ 168 + msg_header = genlmsg_put(skb, 0, acpi_event_seqnum++, 169 + &acpi_event_genl_family, 0, 170 + ACPI_GENL_CMD_EVENT); 171 + if (!msg_header) { 172 + nlmsg_free(skb); 173 + return -ENOMEM; 174 + } 175 + 176 + /* fill the data */ 177 + attr = 178 + nla_reserve(skb, ACPI_GENL_ATTR_EVENT, 179 + sizeof(struct acpi_genl_event)); 180 + if (!attr) { 181 + nlmsg_free(skb); 182 + return -EINVAL; 183 + } 184 + 185 + event = nla_data(attr); 186 + if (!event) { 187 + nlmsg_free(skb); 188 + return -EINVAL; 189 + } 190 + 191 + memset(event, 0, sizeof(struct acpi_genl_event)); 192 + 193 + strcpy(event->device_class, device->pnp.device_class); 194 + strcpy(event->bus_id, device->dev.bus_id); 195 + event->type = type; 196 + event->data = data; 197 + 198 + /* send multicast genetlink message */ 199 + result = genlmsg_end(skb, msg_header); 200 + if (result < 0) { 201 + nlmsg_free(skb); 202 + return result; 203 + } 204 + 205 + result = 206 + genlmsg_multicast(skb, 0, acpi_event_mcgrp.id, GFP_ATOMIC); 207 + if (result) 208 + ACPI_DEBUG_PRINT((ACPI_DB_INFO, 209 + "Failed to send a Genetlink message!\n")); 210 + return 0; 211 + } 212 + 213 + static int acpi_event_genetlink_init(void) 214 + { 215 + int result; 216 + 217 + result = genl_register_family(&acpi_event_genl_family); 218 + if (result) 219 + return result; 220 + 221 + result = genl_register_mc_group(&acpi_event_genl_family, 222 + &acpi_event_mcgrp); 223 + if (result) 224 + genl_unregister_family(&acpi_event_genl_family); 225 + 226 + return result; 227 + } 228 + 229 + #else 230 + int acpi_bus_generate_genetlink_event(struct acpi_device *device, u8 type, 231 + int data) 232 + { 233 + return 0; 234 + } 235 + 236 + static int acpi_event_genetlink_init(void) 237 + { 238 + return -ENODEV; 239 + } 240 + #endif 241 + 110 242 static int __init acpi_event_init(void) 111 243 { 112 244 struct proc_dir_entry *entry; 113 245 int error = 0; 114 246 115 - 116 247 if (acpi_disabled) 117 248 return 0; 249 + 250 + /* create genetlink for acpi event */ 251 + error = acpi_event_genetlink_init(); 252 + if (error) 253 + printk(KERN_WARNING PREFIX 254 + "Failed to create genetlink family for ACPI event\n"); 118 255 119 256 /* 'event' [R] */ 120 257 entry = create_proc_entry("event", S_IRUSR, acpi_root_dir); 121 258 if (entry) 122 259 entry->proc_fops = &acpi_system_event_ops; 123 - else { 124 - error = -ENODEV; 125 - } 126 - return error; 260 + else 261 + return -ENODEV; 262 + 263 + return 0; 127 264 } 128 265 129 - subsys_initcall(acpi_event_init); 266 + fs_initcall(acpi_event_init);
+2 -1
include/acpi/acpi_bus.h
··· 321 321 }; 322 322 323 323 extern struct kset acpi_subsys; 324 - 324 + extern int acpi_bus_generate_genetlink_event(struct acpi_device *device, 325 + u8 type, int data); 325 326 /* 326 327 * External Functions 327 328 */