aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorR.Durgadoss <durgadoss.r@intel.com>2010-10-26 18:03:29 -0400
committerLen Brown <len.brown@intel.com>2011-01-12 00:08:35 -0500
commit4cb18728709683c91a5f6f8d5f337bfb498b089a (patch)
tree26edef8257934247a7b5fe74ac33d54e1a0ad71b /drivers
parente8a7e48bb248a1196484d3f8afa53bded2b24e71 (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')
-rw-r--r--drivers/thermal/Kconfig1
-rw-r--r--drivers/thermal/thermal_sys.c103
2 files changed, 103 insertions, 1 deletions
diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig
index bf7c687519ef..f7a5dba3ca23 100644
--- a/drivers/thermal/Kconfig
+++ b/drivers/thermal/Kconfig
@@ -4,6 +4,7 @@
4 4
5menuconfig THERMAL 5menuconfig THERMAL
6 tristate "Generic Thermal sysfs driver" 6 tristate "Generic Thermal sysfs driver"
7 depends on NET
7 help 8 help
8 Generic Thermal Sysfs driver offers a generic mechanism for 9 Generic Thermal Sysfs driver offers a generic mechanism for
9 thermal management. Usually it's made up of one or more thermal 10 thermal management. Usually it's made up of one or more thermal
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
36MODULE_AUTHOR("Zhang Rui"); 38MODULE_AUTHOR("Zhang Rui");
37MODULE_DESCRIPTION("Generic thermal management sysfs support"); 39MODULE_DESCRIPTION("Generic thermal management sysfs support");
@@ -58,6 +60,22 @@ static LIST_HEAD(thermal_tz_list);
58static LIST_HEAD(thermal_cdev_list); 60static LIST_HEAD(thermal_cdev_list);
59static DEFINE_MUTEX(thermal_list_lock); 61static DEFINE_MUTEX(thermal_list_lock);
60 62
63static unsigned int thermal_event_seqnum;
64
65static 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
72static struct genl_multicast_group thermal_event_mcgrp = {
73 .name = THERMAL_GENL_MCAST_GROUP_NAME,
74};
75
76static int genetlink_init(void);
77static void genetlink_exit(void);
78
61static int get_idr(struct idr *idr, struct mutex *lock, int *id) 79static 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
1215EXPORT_SYMBOL(thermal_zone_device_unregister); 1233EXPORT_SYMBOL(thermal_zone_device_unregister);
1216 1234
1235int 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}
1294EXPORT_SYMBOL(generate_netlink_event);
1295
1296static 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
1217static int __init thermal_init(void) 1311static 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
1326static void genetlink_exit(void)
1327{
1328 genl_unregister_family(&thermal_event_genl_family);
1329}
1330
1231static void __exit thermal_exit(void) 1331static 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
1240subsys_initcall(thermal_init); 1341fs_initcall(thermal_init);
1241module_exit(thermal_exit); 1342module_exit(thermal_exit);