|
7 | 7 | * Generic netlink for thermal management framework
|
8 | 8 | */
|
9 | 9 | #include <linux/module.h>
|
| 10 | +#include <linux/notifier.h> |
10 | 11 | #include <linux/kernel.h>
|
11 | 12 | #include <net/genetlink.h>
|
12 | 13 | #include <uapi/linux/thermal.h>
|
13 | 14 |
|
14 | 15 | #include "thermal_core.h"
|
15 | 16 |
|
16 |
| -enum thermal_genl_multicast_groups { |
17 |
| - THERMAL_GENL_SAMPLING_GROUP = 0, |
18 |
| - THERMAL_GENL_EVENT_GROUP = 1, |
19 |
| -}; |
20 |
| - |
21 | 17 | static const struct genl_multicast_group thermal_genl_mcgrps[] = {
|
22 | 18 | [THERMAL_GENL_SAMPLING_GROUP] = { .name = THERMAL_GENL_SAMPLING_GROUP_NAME, },
|
23 | 19 | [THERMAL_GENL_EVENT_GROUP] = { .name = THERMAL_GENL_EVENT_GROUP_NAME, },
|
@@ -75,6 +71,7 @@ struct param {
|
75 | 71 | typedef int (*cb_t)(struct param *);
|
76 | 72 |
|
77 | 73 | static struct genl_family thermal_gnl_family;
|
| 74 | +static BLOCKING_NOTIFIER_HEAD(thermal_genl_chain); |
78 | 75 |
|
79 | 76 | static int thermal_group_has_listeners(enum thermal_genl_multicast_groups group)
|
80 | 77 | {
|
@@ -645,6 +642,27 @@ static int thermal_genl_cmd_doit(struct sk_buff *skb,
|
645 | 642 | return ret;
|
646 | 643 | }
|
647 | 644 |
|
| 645 | +static int thermal_genl_bind(int mcgrp) |
| 646 | +{ |
| 647 | + struct thermal_genl_notify n = { .mcgrp = mcgrp }; |
| 648 | + |
| 649 | + if (WARN_ON_ONCE(mcgrp > THERMAL_GENL_MAX_GROUP)) |
| 650 | + return -EINVAL; |
| 651 | + |
| 652 | + blocking_notifier_call_chain(&thermal_genl_chain, THERMAL_NOTIFY_BIND, &n); |
| 653 | + return 0; |
| 654 | +} |
| 655 | + |
| 656 | +static void thermal_genl_unbind(int mcgrp) |
| 657 | +{ |
| 658 | + struct thermal_genl_notify n = { .mcgrp = mcgrp }; |
| 659 | + |
| 660 | + if (WARN_ON_ONCE(mcgrp > THERMAL_GENL_MAX_GROUP)) |
| 661 | + return; |
| 662 | + |
| 663 | + blocking_notifier_call_chain(&thermal_genl_chain, THERMAL_NOTIFY_UNBIND, &n); |
| 664 | +} |
| 665 | + |
648 | 666 | static const struct genl_small_ops thermal_genl_ops[] = {
|
649 | 667 | {
|
650 | 668 | .cmd = THERMAL_GENL_CMD_TZ_GET_ID,
|
@@ -679,13 +697,25 @@ static struct genl_family thermal_gnl_family __ro_after_init = {
|
679 | 697 | .version = THERMAL_GENL_VERSION,
|
680 | 698 | .maxattr = THERMAL_GENL_ATTR_MAX,
|
681 | 699 | .policy = thermal_genl_policy,
|
| 700 | + .bind = thermal_genl_bind, |
| 701 | + .unbind = thermal_genl_unbind, |
682 | 702 | .small_ops = thermal_genl_ops,
|
683 | 703 | .n_small_ops = ARRAY_SIZE(thermal_genl_ops),
|
684 | 704 | .resv_start_op = THERMAL_GENL_CMD_CDEV_GET + 1,
|
685 | 705 | .mcgrps = thermal_genl_mcgrps,
|
686 | 706 | .n_mcgrps = ARRAY_SIZE(thermal_genl_mcgrps),
|
687 | 707 | };
|
688 | 708 |
|
| 709 | +int thermal_genl_register_notifier(struct notifier_block *nb) |
| 710 | +{ |
| 711 | + return blocking_notifier_chain_register(&thermal_genl_chain, nb); |
| 712 | +} |
| 713 | + |
| 714 | +int thermal_genl_unregister_notifier(struct notifier_block *nb) |
| 715 | +{ |
| 716 | + return blocking_notifier_chain_unregister(&thermal_genl_chain, nb); |
| 717 | +} |
| 718 | + |
689 | 719 | int __init thermal_netlink_init(void)
|
690 | 720 | {
|
691 | 721 | return genl_register_family(&thermal_gnl_family);
|
|
0 commit comments