1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Regulator event over netlink 4 * 5 * Author: Naresh Solanki <Naresh.Solanki@9elements.com> 6 */ 7 8 #include <regulator/regulator.h> 9 #include <net/netlink.h> 10 #include <net/genetlink.h> 11 #include <linux/atomic.h> 12 13 #include "regnl.h" 14 15 static atomic_t reg_event_seqnum = ATOMIC_INIT(0); 16 17 static const struct genl_multicast_group reg_event_mcgrps[] = { 18 { .name = REG_GENL_MCAST_GROUP_NAME, }, 19 }; 20 21 static struct genl_family reg_event_genl_family __ro_after_init = { 22 .module = THIS_MODULE, 23 .name = REG_GENL_FAMILY_NAME, 24 .version = REG_GENL_VERSION, 25 .maxattr = REG_GENL_ATTR_MAX, 26 .mcgrps = reg_event_mcgrps, 27 .n_mcgrps = ARRAY_SIZE(reg_event_mcgrps), 28 }; 29 30 int reg_generate_netlink_event(const char *reg_name, u64 event) 31 { 32 struct sk_buff *skb; 33 struct nlattr *attr; 34 struct reg_genl_event *edata; 35 void *msg_header; 36 int size; 37 38 /* allocate memory */ 39 size = nla_total_size(sizeof(struct reg_genl_event)) + 40 nla_total_size(0); 41 42 skb = genlmsg_new(size, GFP_ATOMIC); 43 if (!skb) 44 return -ENOMEM; 45 46 /* add the genetlink message header */ 47 msg_header = genlmsg_put(skb, 0, atomic_inc_return(®_event_seqnum), 48 ®_event_genl_family, 0, REG_GENL_CMD_EVENT); 49 if (!msg_header) { 50 nlmsg_free(skb); 51 return -ENOMEM; 52 } 53 54 /* fill the data */ 55 attr = nla_reserve(skb, REG_GENL_ATTR_EVENT, sizeof(struct reg_genl_event)); 56 if (!attr) { 57 nlmsg_free(skb); 58 return -EINVAL; 59 } 60 61 edata = nla_data(attr); 62 memset(edata, 0, sizeof(struct reg_genl_event)); 63 64 strscpy(edata->reg_name, reg_name, sizeof(edata->reg_name)); 65 edata->event = event; 66 67 /* send multicast genetlink message */ 68 genlmsg_end(skb, msg_header); 69 size = genlmsg_multicast(®_event_genl_family, skb, 0, 0, GFP_ATOMIC); 70 71 return size; 72 } 73 74 static int __init reg_event_genetlink_init(void) 75 { 76 return genl_register_family(®_event_genl_family); 77 } 78 79 static int __init reg_event_init(void) 80 { 81 int error; 82 83 /* create genetlink for acpi event */ 84 error = reg_event_genetlink_init(); 85 if (error) 86 pr_warn("Failed to create genetlink family for reg event\n"); 87 88 return 0; 89 } 90 91 fs_initcall(reg_event_init); 92