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 12 #include "regnl.h" 13 14 static unsigned int reg_event_seqnum; 15 16 static const struct genl_multicast_group reg_event_mcgrps[] = { 17 { .name = REG_GENL_MCAST_GROUP_NAME, }, 18 }; 19 20 static struct genl_family reg_event_genl_family __ro_after_init = { 21 .module = THIS_MODULE, 22 .name = REG_GENL_FAMILY_NAME, 23 .version = REG_GENL_VERSION, 24 .maxattr = REG_GENL_ATTR_MAX, 25 .mcgrps = reg_event_mcgrps, 26 .n_mcgrps = ARRAY_SIZE(reg_event_mcgrps), 27 }; 28 29 int reg_generate_netlink_event(const char *reg_name, u64 event) 30 { 31 struct sk_buff *skb; 32 struct nlattr *attr; 33 struct reg_genl_event *edata; 34 void *msg_header; 35 int size; 36 37 /* allocate memory */ 38 size = nla_total_size(sizeof(struct reg_genl_event)) + 39 nla_total_size(0); 40 41 skb = genlmsg_new(size, GFP_ATOMIC); 42 if (!skb) 43 return -ENOMEM; 44 45 /* add the genetlink message header */ 46 msg_header = genlmsg_put(skb, 0, reg_event_seqnum++, 47 ®_event_genl_family, 0, 48 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