Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

regulator: event: Add regulator netlink event support

This commit introduces netlink event support to the regulator subsystem.

Changes:
- Introduce event.c and regnl.h for netlink event handling.
- Implement reg_generate_netlink_event to broadcast regulator events.
- Update Makefile to include the new event.c file.

Signed-off-by: Naresh Solanki <naresh.solanki@9elements.com>
Link: https://lore.kernel.org/r/20231205105207.1262928-1-naresh.solanki@9elements.com
Signed-off-by: Mark Brown <broonie@kernel.org>

authored by

Naresh Solanki and committed by
Mark Brown
16e5ac12 753e4d5c

+224 -47
+10
drivers/regulator/Kconfig
··· 56 56 57 57 If unsure, say no. 58 58 59 + config REGULATOR_NETLINK_EVENTS 60 + bool "Enable support for receiving regulator events via netlink" 61 + depends on NET 62 + help 63 + Enabling this option allows the kernel to broadcast regulator events using 64 + the netlink mechanism. User-space applications can subscribe to these events 65 + for real-time updates on various regulator events. 66 + 67 + If unsure, say no. 68 + 59 69 config REGULATOR_88PG86X 60 70 tristate "Marvell 88PG86X voltage regulators" 61 71 depends on I2C
+1
drivers/regulator/Makefile
··· 5 5 6 6 7 7 obj-$(CONFIG_REGULATOR) += core.o dummy.o fixed-helper.o helpers.o devres.o irq_helpers.o 8 + obj-$(CONFIG_REGULATOR_NETLINK_EVENTS) += event.o 8 9 obj-$(CONFIG_OF) += of_regulator.o 9 10 obj-$(CONFIG_REGULATOR_FIXED_VOLTAGE) += fixed.o 10 11 obj-$(CONFIG_REGULATOR_VIRTUAL_CONSUMER) += virtual.o
+18 -1
drivers/regulator/core.c
··· 33 33 34 34 #include "dummy.h" 35 35 #include "internal.h" 36 + #include "regnl.h" 36 37 37 38 static DEFINE_WW_CLASS(regulator_ww_class); 38 39 static DEFINE_MUTEX(regulator_nesting_mutex); ··· 4855 4854 unsigned long event, void *data) 4856 4855 { 4857 4856 /* call rdev chain first */ 4858 - return blocking_notifier_call_chain(&rdev->notifier, event, data); 4857 + int ret = blocking_notifier_call_chain(&rdev->notifier, event, data); 4858 + 4859 + if (IS_REACHABLE(CONFIG_REGULATOR_NETLINK_EVENTS)) { 4860 + struct device *parent = rdev->dev.parent; 4861 + const char *rname = rdev_get_name(rdev); 4862 + char name[32]; 4863 + 4864 + /* Avoid duplicate debugfs directory names */ 4865 + if (parent && rname == rdev->desc->name) { 4866 + snprintf(name, sizeof(name), "%s-%s", dev_name(parent), 4867 + rname); 4868 + rname = name; 4869 + } 4870 + reg_generate_netlink_event(rname, event); 4871 + } 4872 + 4873 + return ret; 4859 4874 } 4860 4875 4861 4876 int _regulator_bulk_get(struct device *dev, int num_consumers,
+91
drivers/regulator/event.c
··· 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 + &reg_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(&reg_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(&reg_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);
+13
drivers/regulator/regnl.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0-or-later */ 2 + /* 3 + * Regulator event over netlink 4 + * 5 + * Author: Naresh Solanki <Naresh.Solanki@9elements.com> 6 + */ 7 + 8 + #ifndef __REGULATOR_EVENT_H 9 + #define __REGULATOR_EVENT_H 10 + 11 + int reg_generate_netlink_event(const char *reg_name, u64 event); 12 + 13 + #endif
+1 -46
include/linux/regulator/consumer.h
··· 33 33 34 34 #include <linux/err.h> 35 35 #include <linux/suspend.h> 36 + #include <regulator/regulator.h> 36 37 37 38 struct device; 38 39 struct notifier_block; ··· 84 83 #define REGULATOR_MODE_NORMAL 0x2 85 84 #define REGULATOR_MODE_IDLE 0x4 86 85 #define REGULATOR_MODE_STANDBY 0x8 87 - 88 - /* 89 - * Regulator notifier events. 90 - * 91 - * UNDER_VOLTAGE Regulator output is under voltage. 92 - * OVER_CURRENT Regulator output current is too high. 93 - * REGULATION_OUT Regulator output is out of regulation. 94 - * FAIL Regulator output has failed. 95 - * OVER_TEMP Regulator over temp. 96 - * FORCE_DISABLE Regulator forcibly shut down by software. 97 - * VOLTAGE_CHANGE Regulator voltage changed. 98 - * Data passed is old voltage cast to (void *). 99 - * DISABLE Regulator was disabled. 100 - * PRE_VOLTAGE_CHANGE Regulator is about to have voltage changed. 101 - * Data passed is "struct pre_voltage_change_data" 102 - * ABORT_VOLTAGE_CHANGE Regulator voltage change failed for some reason. 103 - * Data passed is old voltage cast to (void *). 104 - * PRE_DISABLE Regulator is about to be disabled 105 - * ABORT_DISABLE Regulator disable failed for some reason 106 - * 107 - * NOTE: These events can be OR'ed together when passed into handler. 108 - */ 109 - 110 - #define REGULATOR_EVENT_UNDER_VOLTAGE 0x01 111 - #define REGULATOR_EVENT_OVER_CURRENT 0x02 112 - #define REGULATOR_EVENT_REGULATION_OUT 0x04 113 - #define REGULATOR_EVENT_FAIL 0x08 114 - #define REGULATOR_EVENT_OVER_TEMP 0x10 115 - #define REGULATOR_EVENT_FORCE_DISABLE 0x20 116 - #define REGULATOR_EVENT_VOLTAGE_CHANGE 0x40 117 - #define REGULATOR_EVENT_DISABLE 0x80 118 - #define REGULATOR_EVENT_PRE_VOLTAGE_CHANGE 0x100 119 - #define REGULATOR_EVENT_ABORT_VOLTAGE_CHANGE 0x200 120 - #define REGULATOR_EVENT_PRE_DISABLE 0x400 121 - #define REGULATOR_EVENT_ABORT_DISABLE 0x800 122 - #define REGULATOR_EVENT_ENABLE 0x1000 123 - /* 124 - * Following notifications should be emitted only if detected condition 125 - * is such that the HW is likely to still be working but consumers should 126 - * take a recovery action to prevent problems esacalating into errors. 127 - */ 128 - #define REGULATOR_EVENT_UNDER_VOLTAGE_WARN 0x2000 129 - #define REGULATOR_EVENT_OVER_CURRENT_WARN 0x4000 130 - #define REGULATOR_EVENT_OVER_VOLTAGE_WARN 0x8000 131 - #define REGULATOR_EVENT_OVER_TEMP_WARN 0x10000 132 - #define REGULATOR_EVENT_WARN_MASK 0x1E000 133 86 134 87 /* 135 88 * Regulator errors that can be queried using regulator_get_error_flags
+90
include/uapi/regulator/regulator.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ 2 + /* 3 + * Regulator uapi header 4 + * 5 + * Author: Naresh Solanki <Naresh.Solanki@9elements.com> 6 + */ 7 + 8 + #ifndef _UAPI_REGULATOR_H 9 + #define _UAPI_REGULATOR_H 10 + 11 + #ifdef __KERNEL__ 12 + #include <linux/types.h> 13 + #else 14 + #include <stdint.h> 15 + #endif 16 + 17 + /* 18 + * Regulator notifier events. 19 + * 20 + * UNDER_VOLTAGE Regulator output is under voltage. 21 + * OVER_CURRENT Regulator output current is too high. 22 + * REGULATION_OUT Regulator output is out of regulation. 23 + * FAIL Regulator output has failed. 24 + * OVER_TEMP Regulator over temp. 25 + * FORCE_DISABLE Regulator forcibly shut down by software. 26 + * VOLTAGE_CHANGE Regulator voltage changed. 27 + * Data passed is old voltage cast to (void *). 28 + * DISABLE Regulator was disabled. 29 + * PRE_VOLTAGE_CHANGE Regulator is about to have voltage changed. 30 + * Data passed is "struct pre_voltage_change_data" 31 + * ABORT_VOLTAGE_CHANGE Regulator voltage change failed for some reason. 32 + * Data passed is old voltage cast to (void *). 33 + * PRE_DISABLE Regulator is about to be disabled 34 + * ABORT_DISABLE Regulator disable failed for some reason 35 + * 36 + * NOTE: These events can be OR'ed together when passed into handler. 37 + */ 38 + 39 + #define REGULATOR_EVENT_UNDER_VOLTAGE 0x01 40 + #define REGULATOR_EVENT_OVER_CURRENT 0x02 41 + #define REGULATOR_EVENT_REGULATION_OUT 0x04 42 + #define REGULATOR_EVENT_FAIL 0x08 43 + #define REGULATOR_EVENT_OVER_TEMP 0x10 44 + #define REGULATOR_EVENT_FORCE_DISABLE 0x20 45 + #define REGULATOR_EVENT_VOLTAGE_CHANGE 0x40 46 + #define REGULATOR_EVENT_DISABLE 0x80 47 + #define REGULATOR_EVENT_PRE_VOLTAGE_CHANGE 0x100 48 + #define REGULATOR_EVENT_ABORT_VOLTAGE_CHANGE 0x200 49 + #define REGULATOR_EVENT_PRE_DISABLE 0x400 50 + #define REGULATOR_EVENT_ABORT_DISABLE 0x800 51 + #define REGULATOR_EVENT_ENABLE 0x1000 52 + /* 53 + * Following notifications should be emitted only if detected condition 54 + * is such that the HW is likely to still be working but consumers should 55 + * take a recovery action to prevent problems esacalating into errors. 56 + */ 57 + #define REGULATOR_EVENT_UNDER_VOLTAGE_WARN 0x2000 58 + #define REGULATOR_EVENT_OVER_CURRENT_WARN 0x4000 59 + #define REGULATOR_EVENT_OVER_VOLTAGE_WARN 0x8000 60 + #define REGULATOR_EVENT_OVER_TEMP_WARN 0x10000 61 + #define REGULATOR_EVENT_WARN_MASK 0x1E000 62 + 63 + struct reg_genl_event { 64 + char reg_name[32]; 65 + uint64_t event; 66 + }; 67 + 68 + /* attributes of reg_genl_family */ 69 + enum { 70 + REG_GENL_ATTR_UNSPEC, 71 + REG_GENL_ATTR_EVENT, /* reg event info needed by user space */ 72 + __REG_GENL_ATTR_MAX, 73 + }; 74 + 75 + #define REG_GENL_ATTR_MAX (__REG_GENL_ATTR_MAX - 1) 76 + 77 + /* commands supported by the reg_genl_family */ 78 + enum { 79 + REG_GENL_CMD_UNSPEC, 80 + REG_GENL_CMD_EVENT, /* kernel->user notifications for reg events */ 81 + __REG_GENL_CMD_MAX, 82 + }; 83 + 84 + #define REG_GENL_CMD_MAX (__REG_GENL_CMD_MAX - 1) 85 + 86 + #define REG_GENL_FAMILY_NAME "reg_event" 87 + #define REG_GENL_VERSION 0x01 88 + #define REG_GENL_MCAST_GROUP_NAME "reg_mc_group" 89 + 90 + #endif /* _UAPI_REGULATOR_H */