9
9
#include <linux/module.h>
10
10
#include <linux/notifier.h>
11
11
#include <linux/kernel.h>
12
+ #include <net/sock.h>
12
13
#include <net/genetlink.h>
13
14
#include <uapi/linux/thermal.h>
14
15
@@ -49,6 +50,11 @@ static const struct nla_policy thermal_genl_policy[THERMAL_GENL_ATTR_MAX + 1] =
49
50
[THERMAL_GENL_ATTR_CPU_CAPABILITY_ID ] = { .type = NLA_U32 },
50
51
[THERMAL_GENL_ATTR_CPU_CAPABILITY_PERFORMANCE ] = { .type = NLA_U32 },
51
52
[THERMAL_GENL_ATTR_CPU_CAPABILITY_EFFICIENCY ] = { .type = NLA_U32 },
53
+
54
+ /* Thresholds */
55
+ [THERMAL_GENL_ATTR_THRESHOLD ] = { .type = NLA_NESTED },
56
+ [THERMAL_GENL_ATTR_THRESHOLD_TEMP ] = { .type = NLA_U32 },
57
+ [THERMAL_GENL_ATTR_THRESHOLD_DIRECTION ] = { .type = NLA_U32 },
52
58
};
53
59
54
60
struct param {
@@ -62,6 +68,8 @@ struct param {
62
68
int trip_type ;
63
69
int trip_hyst ;
64
70
int temp ;
71
+ int prev_temp ;
72
+ int direction ;
65
73
int cdev_state ;
66
74
int cdev_max_state ;
67
75
struct thermal_genl_cpu_caps * cpu_capabilities ;
@@ -234,6 +242,34 @@ static int thermal_genl_event_cpu_capability_change(struct param *p)
234
242
return - EMSGSIZE ;
235
243
}
236
244
245
+ static int thermal_genl_event_threshold_add (struct param * p )
246
+ {
247
+ if (nla_put_u32 (p -> msg , THERMAL_GENL_ATTR_TZ_ID , p -> tz_id ) ||
248
+ nla_put_u32 (p -> msg , THERMAL_GENL_ATTR_THRESHOLD_TEMP , p -> temp ) ||
249
+ nla_put_u32 (p -> msg , THERMAL_GENL_ATTR_THRESHOLD_DIRECTION , p -> direction ))
250
+ return - EMSGSIZE ;
251
+
252
+ return 0 ;
253
+ }
254
+
255
+ static int thermal_genl_event_threshold_flush (struct param * p )
256
+ {
257
+ if (nla_put_u32 (p -> msg , THERMAL_GENL_ATTR_TZ_ID , p -> tz_id ))
258
+ return - EMSGSIZE ;
259
+
260
+ return 0 ;
261
+ }
262
+
263
+ static int thermal_genl_event_threshold_up (struct param * p )
264
+ {
265
+ if (nla_put_u32 (p -> msg , THERMAL_GENL_ATTR_TZ_ID , p -> tz_id ) ||
266
+ nla_put_u32 (p -> msg , THERMAL_GENL_ATTR_TZ_PREV_TEMP , p -> prev_temp ) ||
267
+ nla_put_u32 (p -> msg , THERMAL_GENL_ATTR_TZ_TEMP , p -> temp ))
268
+ return - EMSGSIZE ;
269
+
270
+ return 0 ;
271
+ }
272
+
237
273
int thermal_genl_event_tz_delete (struct param * p )
238
274
__attribute__((alias ("thermal_genl_event_tz" )));
239
275
@@ -246,6 +282,12 @@ int thermal_genl_event_tz_disable(struct param *p)
246
282
int thermal_genl_event_tz_trip_down (struct param * p )
247
283
__attribute__((alias ("thermal_genl_event_tz_trip_up" )));
248
284
285
+ int thermal_genl_event_threshold_delete (struct param * p )
286
+ __attribute__((alias ("thermal_genl_event_threshold_add" )));
287
+
288
+ int thermal_genl_event_threshold_down (struct param * p )
289
+ __attribute__((alias ("thermal_genl_event_threshold_up" )));
290
+
249
291
static cb_t event_cb [] = {
250
292
[THERMAL_GENL_EVENT_TZ_CREATE ] = thermal_genl_event_tz_create ,
251
293
[THERMAL_GENL_EVENT_TZ_DELETE ] = thermal_genl_event_tz_delete ,
@@ -259,6 +301,11 @@ static cb_t event_cb[] = {
259
301
[THERMAL_GENL_EVENT_CDEV_STATE_UPDATE ] = thermal_genl_event_cdev_state_update ,
260
302
[THERMAL_GENL_EVENT_TZ_GOV_CHANGE ] = thermal_genl_event_gov_change ,
261
303
[THERMAL_GENL_EVENT_CPU_CAPABILITY_CHANGE ] = thermal_genl_event_cpu_capability_change ,
304
+ [THERMAL_GENL_EVENT_THRESHOLD_ADD ] = thermal_genl_event_threshold_add ,
305
+ [THERMAL_GENL_EVENT_THRESHOLD_DELETE ] = thermal_genl_event_threshold_delete ,
306
+ [THERMAL_GENL_EVENT_THRESHOLD_FLUSH ] = thermal_genl_event_threshold_flush ,
307
+ [THERMAL_GENL_EVENT_THRESHOLD_DOWN ] = thermal_genl_event_threshold_down ,
308
+ [THERMAL_GENL_EVENT_THRESHOLD_UP ] = thermal_genl_event_threshold_up ,
262
309
};
263
310
264
311
/*
@@ -401,6 +448,43 @@ int thermal_genl_cpu_capability_event(int count,
401
448
}
402
449
EXPORT_SYMBOL_GPL (thermal_genl_cpu_capability_event );
403
450
451
+ int thermal_notify_threshold_add (const struct thermal_zone_device * tz ,
452
+ int temperature , int direction )
453
+ {
454
+ struct param p = { .tz_id = tz -> id , .temp = temperature , .direction = direction };
455
+
456
+ return thermal_genl_send_event (THERMAL_GENL_EVENT_THRESHOLD_ADD , & p );
457
+ }
458
+
459
+ int thermal_notify_threshold_delete (const struct thermal_zone_device * tz ,
460
+ int temperature , int direction )
461
+ {
462
+ struct param p = { .tz_id = tz -> id , .temp = temperature , .direction = direction };
463
+
464
+ return thermal_genl_send_event (THERMAL_GENL_EVENT_THRESHOLD_DELETE , & p );
465
+ }
466
+
467
+ int thermal_notify_threshold_flush (const struct thermal_zone_device * tz )
468
+ {
469
+ struct param p = { .tz_id = tz -> id };
470
+
471
+ return thermal_genl_send_event (THERMAL_GENL_EVENT_THRESHOLD_FLUSH , & p );
472
+ }
473
+
474
+ int thermal_notify_threshold_down (const struct thermal_zone_device * tz )
475
+ {
476
+ struct param p = { .tz_id = tz -> id , .temp = tz -> temperature , .prev_temp = tz -> last_temperature };
477
+
478
+ return thermal_genl_send_event (THERMAL_GENL_EVENT_THRESHOLD_DOWN , & p );
479
+ }
480
+
481
+ int thermal_notify_threshold_up (const struct thermal_zone_device * tz )
482
+ {
483
+ struct param p = { .tz_id = tz -> id , .temp = tz -> temperature , .prev_temp = tz -> last_temperature };
484
+
485
+ return thermal_genl_send_event (THERMAL_GENL_EVENT_THRESHOLD_UP , & p );
486
+ }
487
+
404
488
/*************************** Command encoding ********************************/
405
489
406
490
static int __thermal_genl_cmd_tz_get_id (struct thermal_zone_device * tz ,
@@ -563,12 +647,128 @@ static int thermal_genl_cmd_cdev_get(struct param *p)
563
647
return ret ;
564
648
}
565
649
650
+ static int __thermal_genl_cmd_threshold_get (struct user_threshold * threshold , void * arg )
651
+ {
652
+ struct sk_buff * msg = arg ;
653
+
654
+ if (nla_put_u32 (msg , THERMAL_GENL_ATTR_THRESHOLD_TEMP , threshold -> temperature ) ||
655
+ nla_put_u32 (msg , THERMAL_GENL_ATTR_THRESHOLD_DIRECTION , threshold -> direction ))
656
+ return -1 ;
657
+
658
+ return 0 ;
659
+ }
660
+
661
+ static int thermal_genl_cmd_threshold_get (struct param * p )
662
+ {
663
+ struct sk_buff * msg = p -> msg ;
664
+ struct nlattr * start_trip ;
665
+ int id , ret ;
666
+
667
+ if (!p -> attrs [THERMAL_GENL_ATTR_TZ_ID ])
668
+ return - EINVAL ;
669
+
670
+ id = nla_get_u32 (p -> attrs [THERMAL_GENL_ATTR_TZ_ID ]);
671
+
672
+ CLASS (thermal_zone_get_by_id , tz )(id );
673
+ if (!tz )
674
+ return - EINVAL ;
675
+
676
+ start_trip = nla_nest_start (msg , THERMAL_GENL_ATTR_THRESHOLD );
677
+ if (!start_trip )
678
+ return - EMSGSIZE ;
679
+
680
+ ret = thermal_thresholds_for_each (tz , __thermal_genl_cmd_threshold_get , msg );
681
+ if (ret )
682
+ return - EMSGSIZE ;
683
+
684
+ nla_nest_end (msg , start_trip );
685
+
686
+ return 0 ;
687
+ }
688
+
689
+ static int thermal_genl_cmd_threshold_add (struct param * p )
690
+ {
691
+ int id , temp , direction ;
692
+
693
+ if (!capable (CAP_SYS_ADMIN ))
694
+ return - EPERM ;
695
+
696
+ if (!p -> attrs [THERMAL_GENL_ATTR_TZ_ID ] ||
697
+ !p -> attrs [THERMAL_GENL_ATTR_THRESHOLD_TEMP ] ||
698
+ !p -> attrs [THERMAL_GENL_ATTR_THRESHOLD_DIRECTION ])
699
+ return - EINVAL ;
700
+
701
+ id = nla_get_u32 (p -> attrs [THERMAL_GENL_ATTR_TZ_ID ]);
702
+ temp = nla_get_u32 (p -> attrs [THERMAL_GENL_ATTR_THRESHOLD_TEMP ]);
703
+ direction = nla_get_u32 (p -> attrs [THERMAL_GENL_ATTR_THRESHOLD_DIRECTION ]);
704
+
705
+ CLASS (thermal_zone_get_by_id , tz )(id );
706
+ if (!tz )
707
+ return - EINVAL ;
708
+
709
+ guard (thermal_zone )(tz );
710
+
711
+ return thermal_thresholds_add (tz , temp , direction );
712
+ }
713
+
714
+ static int thermal_genl_cmd_threshold_delete (struct param * p )
715
+ {
716
+ int id , temp , direction ;
717
+
718
+ if (!capable (CAP_SYS_ADMIN ))
719
+ return - EPERM ;
720
+
721
+ if (!p -> attrs [THERMAL_GENL_ATTR_TZ_ID ] ||
722
+ !p -> attrs [THERMAL_GENL_ATTR_THRESHOLD_TEMP ] ||
723
+ !p -> attrs [THERMAL_GENL_ATTR_THRESHOLD_DIRECTION ])
724
+ return - EINVAL ;
725
+
726
+ id = nla_get_u32 (p -> attrs [THERMAL_GENL_ATTR_TZ_ID ]);
727
+ temp = nla_get_u32 (p -> attrs [THERMAL_GENL_ATTR_THRESHOLD_TEMP ]);
728
+ direction = nla_get_u32 (p -> attrs [THERMAL_GENL_ATTR_THRESHOLD_DIRECTION ]);
729
+
730
+ CLASS (thermal_zone_get_by_id , tz )(id );
731
+ if (!tz )
732
+ return - EINVAL ;
733
+
734
+ guard (thermal_zone )(tz );
735
+
736
+ return thermal_thresholds_delete (tz , temp , direction );
737
+ }
738
+
739
+ static int thermal_genl_cmd_threshold_flush (struct param * p )
740
+ {
741
+ int id ;
742
+
743
+ if (!capable (CAP_SYS_ADMIN ))
744
+ return - EPERM ;
745
+
746
+ if (!p -> attrs [THERMAL_GENL_ATTR_TZ_ID ])
747
+ return - EINVAL ;
748
+
749
+ id = nla_get_u32 (p -> attrs [THERMAL_GENL_ATTR_TZ_ID ]);
750
+
751
+ CLASS (thermal_zone_get_by_id , tz )(id );
752
+ if (!tz )
753
+ return - EINVAL ;
754
+
755
+ guard (thermal_zone )(tz );
756
+
757
+ thermal_thresholds_flush (tz );
758
+
759
+ return 0 ;
760
+ }
761
+
566
762
static cb_t cmd_cb [] = {
567
- [THERMAL_GENL_CMD_TZ_GET_ID ] = thermal_genl_cmd_tz_get_id ,
568
- [THERMAL_GENL_CMD_TZ_GET_TRIP ] = thermal_genl_cmd_tz_get_trip ,
569
- [THERMAL_GENL_CMD_TZ_GET_TEMP ] = thermal_genl_cmd_tz_get_temp ,
570
- [THERMAL_GENL_CMD_TZ_GET_GOV ] = thermal_genl_cmd_tz_get_gov ,
571
- [THERMAL_GENL_CMD_CDEV_GET ] = thermal_genl_cmd_cdev_get ,
763
+ [THERMAL_GENL_CMD_TZ_GET_ID ] = thermal_genl_cmd_tz_get_id ,
764
+ [THERMAL_GENL_CMD_TZ_GET_TRIP ] = thermal_genl_cmd_tz_get_trip ,
765
+ [THERMAL_GENL_CMD_TZ_GET_TEMP ] = thermal_genl_cmd_tz_get_temp ,
766
+ [THERMAL_GENL_CMD_TZ_GET_GOV ] = thermal_genl_cmd_tz_get_gov ,
767
+ [THERMAL_GENL_CMD_CDEV_GET ] = thermal_genl_cmd_cdev_get ,
768
+ [THERMAL_GENL_CMD_THRESHOLD_GET ] = thermal_genl_cmd_threshold_get ,
769
+ [THERMAL_GENL_CMD_THRESHOLD_ADD ] = thermal_genl_cmd_threshold_add ,
770
+ [THERMAL_GENL_CMD_THRESHOLD_DELETE ] = thermal_genl_cmd_threshold_delete ,
771
+ [THERMAL_GENL_CMD_THRESHOLD_FLUSH ] = thermal_genl_cmd_threshold_flush ,
572
772
};
573
773
574
774
static int thermal_genl_cmd_dumpit (struct sk_buff * skb ,
@@ -679,6 +879,26 @@ static const struct genl_small_ops thermal_genl_ops[] = {
679
879
.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP ,
680
880
.dumpit = thermal_genl_cmd_dumpit ,
681
881
},
882
+ {
883
+ .cmd = THERMAL_GENL_CMD_THRESHOLD_GET ,
884
+ .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP ,
885
+ .doit = thermal_genl_cmd_doit ,
886
+ },
887
+ {
888
+ .cmd = THERMAL_GENL_CMD_THRESHOLD_ADD ,
889
+ .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP ,
890
+ .doit = thermal_genl_cmd_doit ,
891
+ },
892
+ {
893
+ .cmd = THERMAL_GENL_CMD_THRESHOLD_DELETE ,
894
+ .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP ,
895
+ .doit = thermal_genl_cmd_doit ,
896
+ },
897
+ {
898
+ .cmd = THERMAL_GENL_CMD_THRESHOLD_FLUSH ,
899
+ .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP ,
900
+ .doit = thermal_genl_cmd_doit ,
901
+ },
682
902
};
683
903
684
904
static struct genl_family thermal_genl_family __ro_after_init = {
@@ -691,7 +911,7 @@ static struct genl_family thermal_genl_family __ro_after_init = {
691
911
.unbind = thermal_genl_unbind ,
692
912
.small_ops = thermal_genl_ops ,
693
913
.n_small_ops = ARRAY_SIZE (thermal_genl_ops ),
694
- .resv_start_op = THERMAL_GENL_CMD_CDEV_GET + 1 ,
914
+ .resv_start_op = __THERMAL_GENL_CMD_MAX ,
695
915
.mcgrps = thermal_genl_mcgrps ,
696
916
.n_mcgrps = ARRAY_SIZE (thermal_genl_mcgrps ),
697
917
};
0 commit comments