diff options
author | R.Durgadoss <durgadoss.r@intel.com> | 2010-10-26 18:03:29 -0400 |
---|---|---|
committer | Len Brown <len.brown@intel.com> | 2011-01-12 00:08:35 -0500 |
commit | 4cb18728709683c91a5f6f8d5f337bfb498b089a (patch) | |
tree | 26edef8257934247a7b5fe74ac33d54e1a0ad71b /drivers/thermal/thermal_sys.c | |
parent | e8a7e48bb248a1196484d3f8afa53bded2b24e71 (diff) |
thermal: Add event notification to thermal framework
This patch adds event notification support to the generic
thermal sysfs framework in the kernel. The notification is in the
form of a netlink event.
Signed-off-by: R.Durgadoss <durgadoss.r@intel.com>
Signed-off-by: Len Brown <len.brown@intel.com>
Diffstat (limited to 'drivers/thermal/thermal_sys.c')
-rw-r--r-- | drivers/thermal/thermal_sys.c | 103 |
1 files changed, 102 insertions, 1 deletions
diff --git a/drivers/thermal/thermal_sys.c b/drivers/thermal/thermal_sys.c index 13c72c629329..760e045c93c8 100644 --- a/drivers/thermal/thermal_sys.c +++ b/drivers/thermal/thermal_sys.c | |||
@@ -32,6 +32,8 @@ | |||
32 | #include <linux/thermal.h> | 32 | #include <linux/thermal.h> |
33 | #include <linux/spinlock.h> | 33 | #include <linux/spinlock.h> |
34 | #include <linux/reboot.h> | 34 | #include <linux/reboot.h> |
35 | #include <net/netlink.h> | ||
36 | #include <net/genetlink.h> | ||
35 | 37 | ||
36 | MODULE_AUTHOR("Zhang Rui"); | 38 | MODULE_AUTHOR("Zhang Rui"); |
37 | MODULE_DESCRIPTION("Generic thermal management sysfs support"); | 39 | MODULE_DESCRIPTION("Generic thermal management sysfs support"); |
@@ -58,6 +60,22 @@ static LIST_HEAD(thermal_tz_list); | |||
58 | static LIST_HEAD(thermal_cdev_list); | 60 | static LIST_HEAD(thermal_cdev_list); |
59 | static DEFINE_MUTEX(thermal_list_lock); | 61 | static DEFINE_MUTEX(thermal_list_lock); |
60 | 62 | ||
63 | static unsigned int thermal_event_seqnum; | ||
64 | |||
65 | static struct genl_family thermal_event_genl_family = { | ||
66 | .id = GENL_ID_GENERATE, | ||
67 | .name = THERMAL_GENL_FAMILY_NAME, | ||
68 | .version = THERMAL_GENL_VERSION, | ||
69 | .maxattr = THERMAL_GENL_ATTR_MAX, | ||
70 | }; | ||
71 | |||
72 | static struct genl_multicast_group thermal_event_mcgrp = { | ||
73 | .name = THERMAL_GENL_MCAST_GROUP_NAME, | ||
74 | }; | ||
75 | |||
76 | static int genetlink_init(void); | ||
77 | static void genetlink_exit(void); | ||
78 | |||
61 | static int get_idr(struct idr *idr, struct mutex *lock, int *id) | 79 | static int get_idr(struct idr *idr, struct mutex *lock, int *id) |
62 | { | 80 | { |
63 | int err; | 81 | int err; |
@@ -1214,6 +1232,82 @@ void thermal_zone_device_unregister(struct thermal_zone_device *tz) | |||
1214 | 1232 | ||
1215 | EXPORT_SYMBOL(thermal_zone_device_unregister); | 1233 | EXPORT_SYMBOL(thermal_zone_device_unregister); |
1216 | 1234 | ||
1235 | int generate_netlink_event(u32 orig, enum events event) | ||
1236 | { | ||
1237 | struct sk_buff *skb; | ||
1238 | struct nlattr *attr; | ||
1239 | struct thermal_genl_event *thermal_event; | ||
1240 | void *msg_header; | ||
1241 | int size; | ||
1242 | int result; | ||
1243 | |||
1244 | /* allocate memory */ | ||
1245 | size = nla_total_size(sizeof(struct thermal_genl_event)) + \ | ||
1246 | nla_total_size(0); | ||
1247 | |||
1248 | skb = genlmsg_new(size, GFP_ATOMIC); | ||
1249 | if (!skb) | ||
1250 | return -ENOMEM; | ||
1251 | |||
1252 | /* add the genetlink message header */ | ||
1253 | msg_header = genlmsg_put(skb, 0, thermal_event_seqnum++, | ||
1254 | &thermal_event_genl_family, 0, | ||
1255 | THERMAL_GENL_CMD_EVENT); | ||
1256 | if (!msg_header) { | ||
1257 | nlmsg_free(skb); | ||
1258 | return -ENOMEM; | ||
1259 | } | ||
1260 | |||
1261 | /* fill the data */ | ||
1262 | attr = nla_reserve(skb, THERMAL_GENL_ATTR_EVENT, \ | ||
1263 | sizeof(struct thermal_genl_event)); | ||
1264 | |||
1265 | if (!attr) { | ||
1266 | nlmsg_free(skb); | ||
1267 | return -EINVAL; | ||
1268 | } | ||
1269 | |||
1270 | thermal_event = nla_data(attr); | ||
1271 | if (!thermal_event) { | ||
1272 | nlmsg_free(skb); | ||
1273 | return -EINVAL; | ||
1274 | } | ||
1275 | |||
1276 | memset(thermal_event, 0, sizeof(struct thermal_genl_event)); | ||
1277 | |||
1278 | thermal_event->orig = orig; | ||
1279 | thermal_event->event = event; | ||
1280 | |||
1281 | /* send multicast genetlink message */ | ||
1282 | result = genlmsg_end(skb, msg_header); | ||
1283 | if (result < 0) { | ||
1284 | nlmsg_free(skb); | ||
1285 | return result; | ||
1286 | } | ||
1287 | |||
1288 | result = genlmsg_multicast(skb, 0, thermal_event_mcgrp.id, GFP_ATOMIC); | ||
1289 | if (result) | ||
1290 | printk(KERN_INFO "failed to send netlink event:%d", result); | ||
1291 | |||
1292 | return result; | ||
1293 | } | ||
1294 | EXPORT_SYMBOL(generate_netlink_event); | ||
1295 | |||
1296 | static int genetlink_init(void) | ||
1297 | { | ||
1298 | int result; | ||
1299 | |||
1300 | result = genl_register_family(&thermal_event_genl_family); | ||
1301 | if (result) | ||
1302 | return result; | ||
1303 | |||
1304 | result = genl_register_mc_group(&thermal_event_genl_family, | ||
1305 | &thermal_event_mcgrp); | ||
1306 | if (result) | ||
1307 | genl_unregister_family(&thermal_event_genl_family); | ||
1308 | return result; | ||
1309 | } | ||
1310 | |||
1217 | static int __init thermal_init(void) | 1311 | static int __init thermal_init(void) |
1218 | { | 1312 | { |
1219 | int result = 0; | 1313 | int result = 0; |
@@ -1225,9 +1319,15 @@ static int __init thermal_init(void) | |||
1225 | mutex_destroy(&thermal_idr_lock); | 1319 | mutex_destroy(&thermal_idr_lock); |
1226 | mutex_destroy(&thermal_list_lock); | 1320 | mutex_destroy(&thermal_list_lock); |
1227 | } | 1321 | } |
1322 | result = genetlink_init(); | ||
1228 | return result; | 1323 | return result; |
1229 | } | 1324 | } |
1230 | 1325 | ||
1326 | static void genetlink_exit(void) | ||
1327 | { | ||
1328 | genl_unregister_family(&thermal_event_genl_family); | ||
1329 | } | ||
1330 | |||
1231 | static void __exit thermal_exit(void) | 1331 | static void __exit thermal_exit(void) |
1232 | { | 1332 | { |
1233 | class_unregister(&thermal_class); | 1333 | class_unregister(&thermal_class); |
@@ -1235,7 +1335,8 @@ static void __exit thermal_exit(void) | |||
1235 | idr_destroy(&thermal_cdev_idr); | 1335 | idr_destroy(&thermal_cdev_idr); |
1236 | mutex_destroy(&thermal_idr_lock); | 1336 | mutex_destroy(&thermal_idr_lock); |
1237 | mutex_destroy(&thermal_list_lock); | 1337 | mutex_destroy(&thermal_list_lock); |
1338 | genetlink_exit(); | ||
1238 | } | 1339 | } |
1239 | 1340 | ||
1240 | subsys_initcall(thermal_init); | 1341 | fs_initcall(thermal_init); |
1241 | module_exit(thermal_exit); | 1342 | module_exit(thermal_exit); |