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

Merge tag 'scmi-updates-5.9' of git://git.kernel.org/pub/scm/linux/kernel/git/sudeep.holla/linux into arm/drivers

ARM SCMI/SCPI updates for v5.9

The main addition for this time is the support for platform notifications.
SCMI protocol specification allows the platform to signal events to the
interested agents via notification messages. We are adding support for
the dispatch and delivery of such notifications to the interested users
inside the kernel.

Other than that, there are minor changes like checking and using the
fast_switch capability quering the firmware instead of doing it
unconditionally(using polling mode transfer), cosmetic trace update,
use of HAVE_ARM_SMCCC_DISCOVERY instead of ARM_PSCI_FW and a fix in
scmi clock registration logic for all the clocks with discrete rates.

* tag 'scmi-updates-5.9' of git://git.kernel.org/pub/scm/linux/kernel/git/sudeep.holla/linux:
firmware: arm_scmi: Remove fixed size fields from reports/scmi_event_header
firmware: arm_scmi: Remove unneeded __packed attribute
firmware: arm_scmi: Remove zero-length array in SCMI notifications
firmware: arm_scmi: Provide a missing function param description
clk: scmi: Fix min and max rate when registering clocks with discrete rates
firmware: arm_scmi: Keep the discrete clock rates sorted
firmware: arm_scmi: Add base notifications support
firmware: arm_scmi: Add reset notifications support
firmware: arm_scmi: Add sensor notifications support
firmware: arm_scmi: Add perf notifications support
firmware: arm_scmi: Add power notifications support
firmware: arm_scmi: Enable notification core
firmware: arm_scmi: Add notification dispatch and delivery
firmware: arm_scmi: Add notification callbacks-registration
firmware: arm_scmi: Add notification protocol-registration
firmware: arm_scmi: Fix SCMI genpd domain probing
firmware: arm_scmi: Use HAVE_ARM_SMCCC_DISCOVERY instead of ARM_PSCI_FW
cpufreq: arm_scmi: Set fast_switch_possible conditionally
firmware: arm_scmi: Add fast_switch_possible() interface
firmware: arm_scmi: Use signed integer to report transfer status

Link: https://lore.kernel.org/r/20200713161410.12324-1-sudeep.holla@arm.com
Signed-off-by: Arnd Bergmann <arnd@arndb.de>

+2258 -49
+19 -3
drivers/clk/clk-scmi.c
··· 103 103 static int scmi_clk_ops_init(struct device *dev, struct scmi_clk *sclk) 104 104 { 105 105 int ret; 106 + unsigned long min_rate, max_rate; 107 + 106 108 struct clk_init_data init = { 107 109 .flags = CLK_GET_RATE_NOCACHE, 108 110 .num_parents = 0, ··· 114 112 115 113 sclk->hw.init = &init; 116 114 ret = devm_clk_hw_register(dev, &sclk->hw); 117 - if (!ret) 118 - clk_hw_set_rate_range(&sclk->hw, sclk->info->range.min_rate, 119 - sclk->info->range.max_rate); 115 + if (ret) 116 + return ret; 117 + 118 + if (sclk->info->rate_discrete) { 119 + int num_rates = sclk->info->list.num_rates; 120 + 121 + if (num_rates <= 0) 122 + return -EINVAL; 123 + 124 + min_rate = sclk->info->list.rates[0]; 125 + max_rate = sclk->info->list.rates[num_rates - 1]; 126 + } else { 127 + min_rate = sclk->info->range.min_rate; 128 + max_rate = sclk->info->range.max_rate; 129 + } 130 + 131 + clk_hw_set_rate_range(&sclk->hw, min_rate, max_rate); 120 132 return ret; 121 133 } 122 134
+2 -1
drivers/cpufreq/scmi-cpufreq.c
··· 198 198 199 199 policy->cpuinfo.transition_latency = latency; 200 200 201 - policy->fast_switch_possible = true; 201 + policy->fast_switch_possible = 202 + handle->perf_ops->fast_switch_possible(handle, cpu_dev); 202 203 203 204 em_register_perf_domain(policy->cpus, nr_opp, &em_cb); 204 205
+2 -2
drivers/firmware/arm_scmi/Makefile
··· 1 1 # SPDX-License-Identifier: GPL-2.0-only 2 2 obj-y = scmi-bus.o scmi-driver.o scmi-protocols.o scmi-transport.o 3 3 scmi-bus-y = bus.o 4 - scmi-driver-y = driver.o 4 + scmi-driver-y = driver.o notify.o 5 5 scmi-transport-y = shmem.o 6 6 scmi-transport-$(CONFIG_MAILBOX) += mailbox.o 7 - scmi-transport-$(CONFIG_ARM_PSCI_FW) += smc.o 7 + scmi-transport-$(CONFIG_HAVE_ARM_SMCCC_DISCOVERY) += smc.o 8 8 scmi-protocols-y = base.o clock.o perf.o power.o reset.o sensors.o 9 9 obj-$(CONFIG_ARM_SCMI_POWER_DOMAIN) += scmi_pm_domain.o
+104 -4
drivers/firmware/arm_scmi/base.c
··· 5 5 * Copyright (C) 2018 ARM Ltd. 6 6 */ 7 7 8 + #define pr_fmt(fmt) "SCMI Notifications BASE - " fmt 9 + 10 + #include <linux/scmi_protocol.h> 11 + 8 12 #include "common.h" 13 + #include "notify.h" 14 + 15 + #define SCMI_BASE_NUM_SOURCES 1 16 + #define SCMI_BASE_MAX_CMD_ERR_COUNT 1024 9 17 10 18 enum scmi_base_protocol_cmd { 11 19 BASE_DISCOVER_VENDOR = 0x3, ··· 27 19 BASE_RESET_AGENT_CONFIGURATION = 0xb, 28 20 }; 29 21 30 - enum scmi_base_protocol_notify { 31 - BASE_ERROR_EVENT = 0x0, 32 - }; 33 - 34 22 struct scmi_msg_resp_base_attributes { 35 23 u8 num_protocols; 36 24 u8 num_agents; 37 25 __le16 reserved; 26 + }; 27 + 28 + struct scmi_msg_base_error_notify { 29 + __le32 event_control; 30 + #define BASE_TP_NOTIFY_ALL BIT(0) 31 + }; 32 + 33 + struct scmi_base_error_notify_payld { 34 + __le32 agent_id; 35 + __le32 error_status; 36 + #define IS_FATAL_ERROR(x) ((x) & BIT(31)) 37 + #define ERROR_CMD_COUNT(x) FIELD_GET(GENMASK(9, 0), (x)) 38 + __le64 msg_reports[SCMI_BASE_MAX_CMD_ERR_COUNT]; 38 39 }; 39 40 40 41 /** ··· 239 222 return ret; 240 223 } 241 224 225 + static int scmi_base_error_notify(const struct scmi_handle *handle, bool enable) 226 + { 227 + int ret; 228 + u32 evt_cntl = enable ? BASE_TP_NOTIFY_ALL : 0; 229 + struct scmi_xfer *t; 230 + struct scmi_msg_base_error_notify *cfg; 231 + 232 + ret = scmi_xfer_get_init(handle, BASE_NOTIFY_ERRORS, 233 + SCMI_PROTOCOL_BASE, sizeof(*cfg), 0, &t); 234 + if (ret) 235 + return ret; 236 + 237 + cfg = t->tx.buf; 238 + cfg->event_control = cpu_to_le32(evt_cntl); 239 + 240 + ret = scmi_do_xfer(handle, t); 241 + 242 + scmi_xfer_put(handle, t); 243 + return ret; 244 + } 245 + 246 + static int scmi_base_set_notify_enabled(const struct scmi_handle *handle, 247 + u8 evt_id, u32 src_id, bool enable) 248 + { 249 + int ret; 250 + 251 + ret = scmi_base_error_notify(handle, enable); 252 + if (ret) 253 + pr_debug("FAIL_ENABLED - evt[%X] ret:%d\n", evt_id, ret); 254 + 255 + return ret; 256 + } 257 + 258 + static void *scmi_base_fill_custom_report(const struct scmi_handle *handle, 259 + u8 evt_id, ktime_t timestamp, 260 + const void *payld, size_t payld_sz, 261 + void *report, u32 *src_id) 262 + { 263 + int i; 264 + const struct scmi_base_error_notify_payld *p = payld; 265 + struct scmi_base_error_report *r = report; 266 + 267 + /* 268 + * BaseError notification payload is variable in size but 269 + * up to a maximum length determined by the struct ponted by p. 270 + * Instead payld_sz is the effective length of this notification 271 + * payload so cannot be greater of the maximum allowed size as 272 + * pointed by p. 273 + */ 274 + if (evt_id != SCMI_EVENT_BASE_ERROR_EVENT || sizeof(*p) < payld_sz) 275 + return NULL; 276 + 277 + r->timestamp = timestamp; 278 + r->agent_id = le32_to_cpu(p->agent_id); 279 + r->fatal = IS_FATAL_ERROR(le32_to_cpu(p->error_status)); 280 + r->cmd_count = ERROR_CMD_COUNT(le32_to_cpu(p->error_status)); 281 + for (i = 0; i < r->cmd_count; i++) 282 + r->reports[i] = le64_to_cpu(p->msg_reports[i]); 283 + *src_id = 0; 284 + 285 + return r; 286 + } 287 + 288 + static const struct scmi_event base_events[] = { 289 + { 290 + .id = SCMI_EVENT_BASE_ERROR_EVENT, 291 + .max_payld_sz = sizeof(struct scmi_base_error_notify_payld), 292 + .max_report_sz = sizeof(struct scmi_base_error_report) + 293 + SCMI_BASE_MAX_CMD_ERR_COUNT * sizeof(u64), 294 + }, 295 + }; 296 + 297 + static const struct scmi_event_ops base_event_ops = { 298 + .set_notify_enabled = scmi_base_set_notify_enabled, 299 + .fill_custom_report = scmi_base_fill_custom_report, 300 + }; 301 + 242 302 int scmi_base_protocol_init(struct scmi_handle *h) 243 303 { 244 304 int id, ret; ··· 349 255 rev->sub_vendor_id, rev->impl_ver); 350 256 dev_dbg(dev, "Found %d protocol(s) %d agent(s)\n", rev->num_protocols, 351 257 rev->num_agents); 258 + 259 + scmi_register_protocol_events(handle, SCMI_PROTOCOL_BASE, 260 + (4 * SCMI_PROTO_QUEUE_SZ), 261 + &base_event_ops, base_events, 262 + ARRAY_SIZE(base_events), 263 + SCMI_BASE_NUM_SOURCES); 352 264 353 265 for (id = 0; id < rev->num_agents; id++) { 354 266 scmi_base_discover_agent_get(handle, id, name);
+18 -2
drivers/firmware/arm_scmi/clock.c
··· 5 5 * Copyright (C) 2018 ARM Ltd. 6 6 */ 7 7 8 + #include <linux/sort.h> 9 + 8 10 #include "common.h" 9 11 10 12 enum scmi_clock_protocol_cmd { ··· 123 121 return ret; 124 122 } 125 123 124 + static int rate_cmp_func(const void *_r1, const void *_r2) 125 + { 126 + const u64 *r1 = _r1, *r2 = _r2; 127 + 128 + if (*r1 < *r2) 129 + return -1; 130 + else if (*r1 == *r2) 131 + return 0; 132 + else 133 + return 1; 134 + } 135 + 126 136 static int 127 137 scmi_clock_describe_rates_get(const struct scmi_handle *handle, u32 clk_id, 128 138 struct scmi_clock_info *clk) 129 139 { 130 - u64 *rate; 140 + u64 *rate = 0; 131 141 int ret, cnt; 132 142 bool rate_discrete = false; 133 143 u32 tot_rate_cnt = 0, rates_flag; ··· 198 184 */ 199 185 } while (num_returned && num_remaining); 200 186 201 - if (rate_discrete) 187 + if (rate_discrete && rate) { 202 188 clk->list.num_rates = tot_rate_cnt; 189 + sort(rate, tot_rate_cnt, sizeof(*rate), rate_cmp_func, NULL); 190 + } 203 191 204 192 clk->rate_discrete = rate_discrete; 205 193
+4
drivers/firmware/arm_scmi/common.h
··· 6 6 * 7 7 * Copyright (C) 2018 ARM Ltd. 8 8 */ 9 + #ifndef _SCMI_COMMON_H 10 + #define _SCMI_COMMON_H 9 11 10 12 #include <linux/bitfield.h> 11 13 #include <linux/completion.h> ··· 237 235 void shmem_clear_channel(struct scmi_shared_mem __iomem *shmem); 238 236 bool shmem_poll_done(struct scmi_shared_mem __iomem *shmem, 239 237 struct scmi_xfer *xfer); 238 + 239 + #endif /* _SCMI_COMMON_H */
+12 -3
drivers/firmware/arm_scmi/driver.c
··· 26 26 #include <linux/slab.h> 27 27 28 28 #include "common.h" 29 + #include "notify.h" 29 30 30 31 #define CREATE_TRACE_POINTS 31 32 #include <trace/events/scmi.h> ··· 209 208 struct device *dev = cinfo->dev; 210 209 struct scmi_info *info = handle_to_scmi_info(cinfo->handle); 211 210 struct scmi_xfers_info *minfo = &info->rx_minfo; 211 + ktime_t ts; 212 212 213 + ts = ktime_get_boottime(); 213 214 xfer = scmi_xfer_get(cinfo->handle, minfo); 214 215 if (IS_ERR(xfer)) { 215 216 dev_err(dev, "failed to get free message slot (%ld)\n", ··· 224 221 scmi_dump_header_dbg(dev, &xfer->hdr); 225 222 info->desc->ops->fetch_notification(cinfo, info->desc->max_msg_size, 226 223 xfer); 224 + scmi_notify(cinfo->handle, xfer->hdr.protocol_id, 225 + xfer->hdr.id, xfer->rx.buf, xfer->rx.len, ts); 227 226 228 227 trace_scmi_rx_done(xfer->transfer_id, xfer->hdr.id, 229 228 xfer->hdr.protocol_id, xfer->hdr.seq, ··· 397 392 info->desc->ops->mark_txdone(cinfo, ret); 398 393 399 394 trace_scmi_xfer_end(xfer->transfer_id, xfer->hdr.id, 400 - xfer->hdr.protocol_id, xfer->hdr.seq, 401 - xfer->hdr.status); 395 + xfer->hdr.protocol_id, xfer->hdr.seq, ret); 402 396 403 397 return ret; 404 398 } ··· 793 789 if (ret) 794 790 return ret; 795 791 792 + if (scmi_notification_init(handle)) 793 + dev_err(dev, "SCMI Notifications NOT available.\n"); 794 + 796 795 ret = scmi_base_protocol_init(handle); 797 796 if (ret) { 798 797 dev_err(dev, "unable to communicate with SCMI(%d)\n", ret); ··· 837 830 int ret = 0; 838 831 struct scmi_info *info = platform_get_drvdata(pdev); 839 832 struct idr *idr = &info->tx_idr; 833 + 834 + scmi_notification_exit(&info->handle); 840 835 841 836 mutex_lock(&scmi_list_mutex); 842 837 if (info->users) ··· 910 901 /* Each compatible listed below must have descriptor associated with it */ 911 902 static const struct of_device_id scmi_of_match[] = { 912 903 { .compatible = "arm,scmi", .data = &scmi_mailbox_desc }, 913 - #ifdef CONFIG_ARM_PSCI_FW 904 + #ifdef CONFIG_HAVE_ARM_SMCCC_DISCOVERY 914 905 { .compatible = "arm,scmi-smc", .data = &scmi_smc_desc}, 915 906 #endif 916 907 { /* Sentinel */ },
+1526
drivers/firmware/arm_scmi/notify.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* 3 + * System Control and Management Interface (SCMI) Notification support 4 + * 5 + * Copyright (C) 2020 ARM Ltd. 6 + */ 7 + /** 8 + * DOC: Theory of operation 9 + * 10 + * SCMI Protocol specification allows the platform to signal events to 11 + * interested agents via notification messages: this is an implementation 12 + * of the dispatch and delivery of such notifications to the interested users 13 + * inside the Linux kernel. 14 + * 15 + * An SCMI Notification core instance is initialized for each active platform 16 + * instance identified by the means of the usual &struct scmi_handle. 17 + * 18 + * Each SCMI Protocol implementation, during its initialization, registers with 19 + * this core its set of supported events using scmi_register_protocol_events(): 20 + * all the needed descriptors are stored in the &struct registered_protocols and 21 + * &struct registered_events arrays. 22 + * 23 + * Kernel users interested in some specific event can register their callbacks 24 + * providing the usual notifier_block descriptor, since this core implements 25 + * events' delivery using the standard Kernel notification chains machinery. 26 + * 27 + * Given the number of possible events defined by SCMI and the extensibility 28 + * of the SCMI Protocol itself, the underlying notification chains are created 29 + * and destroyed dynamically on demand depending on the number of users 30 + * effectively registered for an event, so that no support structures or chains 31 + * are allocated until at least one user has registered a notifier_block for 32 + * such event. Similarly, events' generation itself is enabled at the platform 33 + * level only after at least one user has registered, and it is shutdown after 34 + * the last user for that event has gone. 35 + * 36 + * All users provided callbacks and allocated notification-chains are stored in 37 + * the @registered_events_handlers hashtable. Callbacks' registration requests 38 + * for still to be registered events are instead kept in the dedicated common 39 + * hashtable @pending_events_handlers. 40 + * 41 + * An event is identified univocally by the tuple (proto_id, evt_id, src_id) 42 + * and is served by its own dedicated notification chain; information contained 43 + * in such tuples is used, in a few different ways, to generate the needed 44 + * hash-keys. 45 + * 46 + * Here proto_id and evt_id are simply the protocol_id and message_id numbers 47 + * as described in the SCMI Protocol specification, while src_id represents an 48 + * optional, protocol dependent, source identifier (like domain_id, perf_id 49 + * or sensor_id and so forth). 50 + * 51 + * Upon reception of a notification message from the platform the SCMI RX ISR 52 + * passes the received message payload and some ancillary information (including 53 + * an arrival timestamp in nanoseconds) to the core via @scmi_notify() which 54 + * pushes the event-data itself on a protocol-dedicated kfifo queue for further 55 + * deferred processing as specified in @scmi_events_dispatcher(). 56 + * 57 + * Each protocol has it own dedicated work_struct and worker which, once kicked 58 + * by the ISR, takes care to empty its own dedicated queue, deliverying the 59 + * queued items into the proper notification-chain: notifications processing can 60 + * proceed concurrently on distinct workers only between events belonging to 61 + * different protocols while delivery of events within the same protocol is 62 + * still strictly sequentially ordered by time of arrival. 63 + * 64 + * Events' information is then extracted from the SCMI Notification messages and 65 + * conveyed, converted into a custom per-event report struct, as the void *data 66 + * param to the user callback provided by the registered notifier_block, so that 67 + * from the user perspective his callback will look invoked like: 68 + * 69 + * int user_cb(struct notifier_block *nb, unsigned long event_id, void *report) 70 + * 71 + */ 72 + 73 + #define dev_fmt(fmt) "SCMI Notifications - " fmt 74 + #define pr_fmt(fmt) "SCMI Notifications - " fmt 75 + 76 + #include <linux/bitfield.h> 77 + #include <linux/bug.h> 78 + #include <linux/compiler.h> 79 + #include <linux/device.h> 80 + #include <linux/err.h> 81 + #include <linux/hashtable.h> 82 + #include <linux/kernel.h> 83 + #include <linux/ktime.h> 84 + #include <linux/kfifo.h> 85 + #include <linux/list.h> 86 + #include <linux/mutex.h> 87 + #include <linux/notifier.h> 88 + #include <linux/refcount.h> 89 + #include <linux/scmi_protocol.h> 90 + #include <linux/slab.h> 91 + #include <linux/types.h> 92 + #include <linux/workqueue.h> 93 + 94 + #include "notify.h" 95 + 96 + #define SCMI_MAX_PROTO 256 97 + 98 + #define PROTO_ID_MASK GENMASK(31, 24) 99 + #define EVT_ID_MASK GENMASK(23, 16) 100 + #define SRC_ID_MASK GENMASK(15, 0) 101 + 102 + /* 103 + * Builds an unsigned 32bit key from the given input tuple to be used 104 + * as a key in hashtables. 105 + */ 106 + #define MAKE_HASH_KEY(p, e, s) \ 107 + (FIELD_PREP(PROTO_ID_MASK, (p)) | \ 108 + FIELD_PREP(EVT_ID_MASK, (e)) | \ 109 + FIELD_PREP(SRC_ID_MASK, (s))) 110 + 111 + #define MAKE_ALL_SRCS_KEY(p, e) MAKE_HASH_KEY((p), (e), SRC_ID_MASK) 112 + 113 + /* 114 + * Assumes that the stored obj includes its own hash-key in a field named 'key': 115 + * with this simplification this macro can be equally used for all the objects' 116 + * types hashed by this implementation. 117 + * 118 + * @__ht: The hashtable name 119 + * @__obj: A pointer to the object type to be retrieved from the hashtable; 120 + * it will be used as a cursor while scanning the hastable and it will 121 + * be possibly left as NULL when @__k is not found 122 + * @__k: The key to search for 123 + */ 124 + #define KEY_FIND(__ht, __obj, __k) \ 125 + ({ \ 126 + typeof(__k) k_ = __k; \ 127 + typeof(__obj) obj_; \ 128 + \ 129 + hash_for_each_possible((__ht), obj_, hash, k_) \ 130 + if (obj_->key == k_) \ 131 + break; \ 132 + __obj = obj_; \ 133 + }) 134 + 135 + #define KEY_XTRACT_PROTO_ID(key) FIELD_GET(PROTO_ID_MASK, (key)) 136 + #define KEY_XTRACT_EVT_ID(key) FIELD_GET(EVT_ID_MASK, (key)) 137 + #define KEY_XTRACT_SRC_ID(key) FIELD_GET(SRC_ID_MASK, (key)) 138 + 139 + /* 140 + * A set of macros used to access safely @registered_protocols and 141 + * @registered_events arrays; these are fixed in size and each entry is possibly 142 + * populated at protocols' registration time and then only read but NEVER 143 + * modified or removed. 144 + */ 145 + #define SCMI_GET_PROTO(__ni, __pid) \ 146 + ({ \ 147 + typeof(__ni) ni_ = __ni; \ 148 + struct scmi_registered_events_desc *__pd = NULL; \ 149 + \ 150 + if (ni_) \ 151 + __pd = READ_ONCE(ni_->registered_protocols[(__pid)]); \ 152 + __pd; \ 153 + }) 154 + 155 + #define SCMI_GET_REVT_FROM_PD(__pd, __eid) \ 156 + ({ \ 157 + typeof(__pd) pd_ = __pd; \ 158 + typeof(__eid) eid_ = __eid; \ 159 + struct scmi_registered_event *__revt = NULL; \ 160 + \ 161 + if (pd_ && eid_ < pd_->num_events) \ 162 + __revt = READ_ONCE(pd_->registered_events[eid_]); \ 163 + __revt; \ 164 + }) 165 + 166 + #define SCMI_GET_REVT(__ni, __pid, __eid) \ 167 + ({ \ 168 + struct scmi_registered_event *__revt; \ 169 + struct scmi_registered_events_desc *__pd; \ 170 + \ 171 + __pd = SCMI_GET_PROTO((__ni), (__pid)); \ 172 + __revt = SCMI_GET_REVT_FROM_PD(__pd, (__eid)); \ 173 + __revt; \ 174 + }) 175 + 176 + /* A couple of utility macros to limit cruft when calling protocols' helpers */ 177 + #define REVT_NOTIFY_SET_STATUS(revt, eid, sid, state) \ 178 + ({ \ 179 + typeof(revt) r = revt; \ 180 + r->proto->ops->set_notify_enabled(r->proto->ni->handle, \ 181 + (eid), (sid), (state)); \ 182 + }) 183 + 184 + #define REVT_NOTIFY_ENABLE(revt, eid, sid) \ 185 + REVT_NOTIFY_SET_STATUS((revt), (eid), (sid), true) 186 + 187 + #define REVT_NOTIFY_DISABLE(revt, eid, sid) \ 188 + REVT_NOTIFY_SET_STATUS((revt), (eid), (sid), false) 189 + 190 + #define REVT_FILL_REPORT(revt, ...) \ 191 + ({ \ 192 + typeof(revt) r = revt; \ 193 + r->proto->ops->fill_custom_report(r->proto->ni->handle, \ 194 + __VA_ARGS__); \ 195 + }) 196 + 197 + #define SCMI_PENDING_HASH_SZ 4 198 + #define SCMI_REGISTERED_HASH_SZ 6 199 + 200 + struct scmi_registered_events_desc; 201 + 202 + /** 203 + * struct scmi_notify_instance - Represents an instance of the notification 204 + * core 205 + * @gid: GroupID used for devres 206 + * @handle: A reference to the platform instance 207 + * @init_work: A work item to perform final initializations of pending handlers 208 + * @notify_wq: A reference to the allocated Kernel cmwq 209 + * @pending_mtx: A mutex to protect @pending_events_handlers 210 + * @registered_protocols: A statically allocated array containing pointers to 211 + * all the registered protocol-level specific information 212 + * related to events' handling 213 + * @pending_events_handlers: An hashtable containing all pending events' 214 + * handlers descriptors 215 + * 216 + * Each platform instance, represented by a handle, has its own instance of 217 + * the notification subsystem represented by this structure. 218 + */ 219 + struct scmi_notify_instance { 220 + void *gid; 221 + struct scmi_handle *handle; 222 + struct work_struct init_work; 223 + struct workqueue_struct *notify_wq; 224 + /* lock to protect pending_events_handlers */ 225 + struct mutex pending_mtx; 226 + struct scmi_registered_events_desc **registered_protocols; 227 + DECLARE_HASHTABLE(pending_events_handlers, SCMI_PENDING_HASH_SZ); 228 + }; 229 + 230 + /** 231 + * struct events_queue - Describes a queue and its associated worker 232 + * @sz: Size in bytes of the related kfifo 233 + * @kfifo: A dedicated Kernel kfifo descriptor 234 + * @notify_work: A custom work item bound to this queue 235 + * @wq: A reference to the associated workqueue 236 + * 237 + * Each protocol has its own dedicated events_queue descriptor. 238 + */ 239 + struct events_queue { 240 + size_t sz; 241 + struct kfifo kfifo; 242 + struct work_struct notify_work; 243 + struct workqueue_struct *wq; 244 + }; 245 + 246 + /** 247 + * struct scmi_event_header - A utility header 248 + * @timestamp: The timestamp, in nanoseconds (boottime), which was associated 249 + * to this event as soon as it entered the SCMI RX ISR 250 + * @payld_sz: Effective size of the embedded message payload which follows 251 + * @evt_id: Event ID (corresponds to the Event MsgID for this Protocol) 252 + * @payld: A reference to the embedded event payload 253 + * 254 + * This header is prepended to each received event message payload before 255 + * queueing it on the related &struct events_queue. 256 + */ 257 + struct scmi_event_header { 258 + ktime_t timestamp; 259 + size_t payld_sz; 260 + unsigned char evt_id; 261 + unsigned char payld[]; 262 + }; 263 + 264 + struct scmi_registered_event; 265 + 266 + /** 267 + * struct scmi_registered_events_desc - Protocol Specific information 268 + * @id: Protocol ID 269 + * @ops: Protocol specific and event-related operations 270 + * @equeue: The embedded per-protocol events_queue 271 + * @ni: A reference to the initialized instance descriptor 272 + * @eh: A reference to pre-allocated buffer to be used as a scratch area by the 273 + * deferred worker when fetching data from the kfifo 274 + * @eh_sz: Size of the pre-allocated buffer @eh 275 + * @in_flight: A reference to an in flight &struct scmi_registered_event 276 + * @num_events: Number of events in @registered_events 277 + * @registered_events: A dynamically allocated array holding all the registered 278 + * events' descriptors, whose fixed-size is determined at 279 + * compile time. 280 + * @registered_mtx: A mutex to protect @registered_events_handlers 281 + * @registered_events_handlers: An hashtable containing all events' handlers 282 + * descriptors registered for this protocol 283 + * 284 + * All protocols that register at least one event have their protocol-specific 285 + * information stored here, together with the embedded allocated events_queue. 286 + * These descriptors are stored in the @registered_protocols array at protocol 287 + * registration time. 288 + * 289 + * Once these descriptors are successfully registered, they are NEVER again 290 + * removed or modified since protocols do not unregister ever, so that, once 291 + * we safely grab a NON-NULL reference from the array we can keep it and use it. 292 + */ 293 + struct scmi_registered_events_desc { 294 + u8 id; 295 + const struct scmi_event_ops *ops; 296 + struct events_queue equeue; 297 + struct scmi_notify_instance *ni; 298 + struct scmi_event_header *eh; 299 + size_t eh_sz; 300 + void *in_flight; 301 + int num_events; 302 + struct scmi_registered_event **registered_events; 303 + /* mutex to protect registered_events_handlers */ 304 + struct mutex registered_mtx; 305 + DECLARE_HASHTABLE(registered_events_handlers, SCMI_REGISTERED_HASH_SZ); 306 + }; 307 + 308 + /** 309 + * struct scmi_registered_event - Event Specific Information 310 + * @proto: A reference to the associated protocol descriptor 311 + * @evt: A reference to the associated event descriptor (as provided at 312 + * registration time) 313 + * @report: A pre-allocated buffer used by the deferred worker to fill a 314 + * customized event report 315 + * @num_sources: The number of possible sources for this event as stated at 316 + * events' registration time 317 + * @sources: A reference to a dynamically allocated array used to refcount the 318 + * events' enable requests for all the existing sources 319 + * @sources_mtx: A mutex to serialize the access to @sources 320 + * 321 + * All registered events are represented by one of these structures that are 322 + * stored in the @registered_events array at protocol registration time. 323 + * 324 + * Once these descriptors are successfully registered, they are NEVER again 325 + * removed or modified since protocols do not unregister ever, so that once we 326 + * safely grab a NON-NULL reference from the table we can keep it and use it. 327 + */ 328 + struct scmi_registered_event { 329 + struct scmi_registered_events_desc *proto; 330 + const struct scmi_event *evt; 331 + void *report; 332 + u32 num_sources; 333 + refcount_t *sources; 334 + /* locking to serialize the access to sources */ 335 + struct mutex sources_mtx; 336 + }; 337 + 338 + /** 339 + * struct scmi_event_handler - Event handler information 340 + * @key: The used hashkey 341 + * @users: A reference count for number of active users for this handler 342 + * @r_evt: A reference to the associated registered event; when this is NULL 343 + * this handler is pending, which means that identifies a set of 344 + * callbacks intended to be attached to an event which is still not 345 + * known nor registered by any protocol at that point in time 346 + * @chain: The notification chain dedicated to this specific event tuple 347 + * @hash: The hlist_node used for collision handling 348 + * @enabled: A boolean which records if event's generation has been already 349 + * enabled for this handler as a whole 350 + * 351 + * This structure collects all the information needed to process a received 352 + * event identified by the tuple (proto_id, evt_id, src_id). 353 + * These descriptors are stored in a per-protocol @registered_events_handlers 354 + * table using as a key a value derived from that tuple. 355 + */ 356 + struct scmi_event_handler { 357 + u32 key; 358 + refcount_t users; 359 + struct scmi_registered_event *r_evt; 360 + struct blocking_notifier_head chain; 361 + struct hlist_node hash; 362 + bool enabled; 363 + }; 364 + 365 + #define IS_HNDL_PENDING(hndl) (!(hndl)->r_evt) 366 + 367 + static struct scmi_event_handler * 368 + scmi_get_active_handler(struct scmi_notify_instance *ni, u32 evt_key); 369 + static void scmi_put_active_handler(struct scmi_notify_instance *ni, 370 + struct scmi_event_handler *hndl); 371 + static void scmi_put_handler_unlocked(struct scmi_notify_instance *ni, 372 + struct scmi_event_handler *hndl); 373 + 374 + /** 375 + * scmi_lookup_and_call_event_chain() - Lookup the proper chain and call it 376 + * @ni: A reference to the notification instance to use 377 + * @evt_key: The key to use to lookup the related notification chain 378 + * @report: The customized event-specific report to pass down to the callbacks 379 + * as their *data parameter. 380 + */ 381 + static inline void 382 + scmi_lookup_and_call_event_chain(struct scmi_notify_instance *ni, 383 + u32 evt_key, void *report) 384 + { 385 + int ret; 386 + struct scmi_event_handler *hndl; 387 + 388 + /* 389 + * Here ensure the event handler cannot vanish while using it. 390 + * It is legitimate, though, for an handler not to be found at all here, 391 + * e.g. when it has been unregistered by the user after some events had 392 + * already been queued. 393 + */ 394 + hndl = scmi_get_active_handler(ni, evt_key); 395 + if (!hndl) 396 + return; 397 + 398 + ret = blocking_notifier_call_chain(&hndl->chain, 399 + KEY_XTRACT_EVT_ID(evt_key), 400 + report); 401 + /* Notifiers are NOT supposed to cut the chain ... */ 402 + WARN_ON_ONCE(ret & NOTIFY_STOP_MASK); 403 + 404 + scmi_put_active_handler(ni, hndl); 405 + } 406 + 407 + /** 408 + * scmi_process_event_header() - Dequeue and process an event header 409 + * @eq: The queue to use 410 + * @pd: The protocol descriptor to use 411 + * 412 + * Read an event header from the protocol queue into the dedicated scratch 413 + * buffer and looks for a matching registered event; in case an anomalously 414 + * sized read is detected just flush the queue. 415 + * 416 + * Return: 417 + * * a reference to the matching registered event when found 418 + * * ERR_PTR(-EINVAL) when NO registered event could be found 419 + * * NULL when the queue is empty 420 + */ 421 + static inline struct scmi_registered_event * 422 + scmi_process_event_header(struct events_queue *eq, 423 + struct scmi_registered_events_desc *pd) 424 + { 425 + unsigned int outs; 426 + struct scmi_registered_event *r_evt; 427 + 428 + outs = kfifo_out(&eq->kfifo, pd->eh, 429 + sizeof(struct scmi_event_header)); 430 + if (!outs) 431 + return NULL; 432 + if (outs != sizeof(struct scmi_event_header)) { 433 + dev_err(pd->ni->handle->dev, "corrupted EVT header. Flush.\n"); 434 + kfifo_reset_out(&eq->kfifo); 435 + return NULL; 436 + } 437 + 438 + r_evt = SCMI_GET_REVT_FROM_PD(pd, pd->eh->evt_id); 439 + if (!r_evt) 440 + r_evt = ERR_PTR(-EINVAL); 441 + 442 + return r_evt; 443 + } 444 + 445 + /** 446 + * scmi_process_event_payload() - Dequeue and process an event payload 447 + * @eq: The queue to use 448 + * @pd: The protocol descriptor to use 449 + * @r_evt: The registered event descriptor to use 450 + * 451 + * Read an event payload from the protocol queue into the dedicated scratch 452 + * buffer, fills a custom report and then look for matching event handlers and 453 + * call them; skip any unknown event (as marked by scmi_process_event_header()) 454 + * and in case an anomalously sized read is detected just flush the queue. 455 + * 456 + * Return: False when the queue is empty 457 + */ 458 + static inline bool 459 + scmi_process_event_payload(struct events_queue *eq, 460 + struct scmi_registered_events_desc *pd, 461 + struct scmi_registered_event *r_evt) 462 + { 463 + u32 src_id, key; 464 + unsigned int outs; 465 + void *report = NULL; 466 + 467 + outs = kfifo_out(&eq->kfifo, pd->eh->payld, pd->eh->payld_sz); 468 + if (!outs) 469 + return false; 470 + 471 + /* Any in-flight event has now been officially processed */ 472 + pd->in_flight = NULL; 473 + 474 + if (outs != pd->eh->payld_sz) { 475 + dev_err(pd->ni->handle->dev, "corrupted EVT Payload. Flush.\n"); 476 + kfifo_reset_out(&eq->kfifo); 477 + return false; 478 + } 479 + 480 + if (IS_ERR(r_evt)) { 481 + dev_warn(pd->ni->handle->dev, 482 + "SKIP UNKNOWN EVT - proto:%X evt:%d\n", 483 + pd->id, pd->eh->evt_id); 484 + return true; 485 + } 486 + 487 + report = REVT_FILL_REPORT(r_evt, pd->eh->evt_id, pd->eh->timestamp, 488 + pd->eh->payld, pd->eh->payld_sz, 489 + r_evt->report, &src_id); 490 + if (!report) { 491 + dev_err(pd->ni->handle->dev, 492 + "report not available - proto:%X evt:%d\n", 493 + pd->id, pd->eh->evt_id); 494 + return true; 495 + } 496 + 497 + /* At first search for a generic ALL src_ids handler... */ 498 + key = MAKE_ALL_SRCS_KEY(pd->id, pd->eh->evt_id); 499 + scmi_lookup_and_call_event_chain(pd->ni, key, report); 500 + 501 + /* ...then search for any specific src_id */ 502 + key = MAKE_HASH_KEY(pd->id, pd->eh->evt_id, src_id); 503 + scmi_lookup_and_call_event_chain(pd->ni, key, report); 504 + 505 + return true; 506 + } 507 + 508 + /** 509 + * scmi_events_dispatcher() - Common worker logic for all work items. 510 + * @work: The work item to use, which is associated to a dedicated events_queue 511 + * 512 + * Logic: 513 + * 1. dequeue one pending RX notification (queued in SCMI RX ISR context) 514 + * 2. generate a custom event report from the received event message 515 + * 3. lookup for any registered ALL_SRC_IDs handler: 516 + * - > call the related notification chain passing in the report 517 + * 4. lookup for any registered specific SRC_ID handler: 518 + * - > call the related notification chain passing in the report 519 + * 520 + * Note that: 521 + * * a dedicated per-protocol kfifo queue is used: in this way an anomalous 522 + * flood of events cannot saturate other protocols' queues. 523 + * * each per-protocol queue is associated to a distinct work_item, which 524 + * means, in turn, that: 525 + * + all protocols can process their dedicated queues concurrently 526 + * (since notify_wq:max_active != 1) 527 + * + anyway at most one worker instance is allowed to run on the same queue 528 + * concurrently: this ensures that we can have only one concurrent 529 + * reader/writer on the associated kfifo, so that we can use it lock-less 530 + * 531 + * Context: Process context. 532 + */ 533 + static void scmi_events_dispatcher(struct work_struct *work) 534 + { 535 + struct events_queue *eq; 536 + struct scmi_registered_events_desc *pd; 537 + struct scmi_registered_event *r_evt; 538 + 539 + eq = container_of(work, struct events_queue, notify_work); 540 + pd = container_of(eq, struct scmi_registered_events_desc, equeue); 541 + /* 542 + * In order to keep the queue lock-less and the number of memcopies 543 + * to the bare minimum needed, the dispatcher accounts for the 544 + * possibility of per-protocol in-flight events: i.e. an event whose 545 + * reception could end up being split across two subsequent runs of this 546 + * worker, first the header, then the payload. 547 + */ 548 + do { 549 + if (!pd->in_flight) { 550 + r_evt = scmi_process_event_header(eq, pd); 551 + if (!r_evt) 552 + break; 553 + pd->in_flight = r_evt; 554 + } else { 555 + r_evt = pd->in_flight; 556 + } 557 + } while (scmi_process_event_payload(eq, pd, r_evt)); 558 + } 559 + 560 + /** 561 + * scmi_notify() - Queues a notification for further deferred processing 562 + * @handle: The handle identifying the platform instance from which the 563 + * dispatched event is generated 564 + * @proto_id: Protocol ID 565 + * @evt_id: Event ID (msgID) 566 + * @buf: Event Message Payload (without the header) 567 + * @len: Event Message Payload size 568 + * @ts: RX Timestamp in nanoseconds (boottime) 569 + * 570 + * Context: Called in interrupt context to queue a received event for 571 + * deferred processing. 572 + * 573 + * Return: 0 on Success 574 + */ 575 + int scmi_notify(const struct scmi_handle *handle, u8 proto_id, u8 evt_id, 576 + const void *buf, size_t len, ktime_t ts) 577 + { 578 + struct scmi_registered_event *r_evt; 579 + struct scmi_event_header eh; 580 + struct scmi_notify_instance *ni; 581 + 582 + /* Ensure notify_priv is updated */ 583 + smp_rmb(); 584 + if (!handle->notify_priv) 585 + return 0; 586 + ni = handle->notify_priv; 587 + 588 + r_evt = SCMI_GET_REVT(ni, proto_id, evt_id); 589 + if (!r_evt) 590 + return -EINVAL; 591 + 592 + if (len > r_evt->evt->max_payld_sz) { 593 + dev_err(handle->dev, "discard badly sized message\n"); 594 + return -EINVAL; 595 + } 596 + if (kfifo_avail(&r_evt->proto->equeue.kfifo) < sizeof(eh) + len) { 597 + dev_warn(handle->dev, 598 + "queue full, dropping proto_id:%d evt_id:%d ts:%lld\n", 599 + proto_id, evt_id, ktime_to_ns(ts)); 600 + return -ENOMEM; 601 + } 602 + 603 + eh.timestamp = ts; 604 + eh.evt_id = evt_id; 605 + eh.payld_sz = len; 606 + /* 607 + * Header and payload are enqueued with two distinct kfifo_in() (so non 608 + * atomic), but this situation is handled properly on the consumer side 609 + * with in-flight events tracking. 610 + */ 611 + kfifo_in(&r_evt->proto->equeue.kfifo, &eh, sizeof(eh)); 612 + kfifo_in(&r_evt->proto->equeue.kfifo, buf, len); 613 + /* 614 + * Don't care about return value here since we just want to ensure that 615 + * a work is queued all the times whenever some items have been pushed 616 + * on the kfifo: 617 + * - if work was already queued it will simply fail to queue a new one 618 + * since it is not needed 619 + * - if work was not queued already it will be now, even in case work 620 + * was in fact already running: this behavior avoids any possible race 621 + * when this function pushes new items onto the kfifos after the 622 + * related executing worker had already determined the kfifo to be 623 + * empty and it was terminating. 624 + */ 625 + queue_work(r_evt->proto->equeue.wq, 626 + &r_evt->proto->equeue.notify_work); 627 + 628 + return 0; 629 + } 630 + 631 + /** 632 + * scmi_kfifo_free() - Devres action helper to free the kfifo 633 + * @kfifo: The kfifo to free 634 + */ 635 + static void scmi_kfifo_free(void *kfifo) 636 + { 637 + kfifo_free((struct kfifo *)kfifo); 638 + } 639 + 640 + /** 641 + * scmi_initialize_events_queue() - Allocate/Initialize a kfifo buffer 642 + * @ni: A reference to the notification instance to use 643 + * @equeue: The events_queue to initialize 644 + * @sz: Size of the kfifo buffer to allocate 645 + * 646 + * Allocate a buffer for the kfifo and initialize it. 647 + * 648 + * Return: 0 on Success 649 + */ 650 + static int scmi_initialize_events_queue(struct scmi_notify_instance *ni, 651 + struct events_queue *equeue, size_t sz) 652 + { 653 + int ret; 654 + 655 + if (kfifo_alloc(&equeue->kfifo, sz, GFP_KERNEL)) 656 + return -ENOMEM; 657 + /* Size could have been roundup to power-of-two */ 658 + equeue->sz = kfifo_size(&equeue->kfifo); 659 + 660 + ret = devm_add_action_or_reset(ni->handle->dev, scmi_kfifo_free, 661 + &equeue->kfifo); 662 + if (ret) 663 + return ret; 664 + 665 + INIT_WORK(&equeue->notify_work, scmi_events_dispatcher); 666 + equeue->wq = ni->notify_wq; 667 + 668 + return ret; 669 + } 670 + 671 + /** 672 + * scmi_allocate_registered_events_desc() - Allocate a registered events' 673 + * descriptor 674 + * @ni: A reference to the &struct scmi_notify_instance notification instance 675 + * to use 676 + * @proto_id: Protocol ID 677 + * @queue_sz: Size of the associated queue to allocate 678 + * @eh_sz: Size of the event header scratch area to pre-allocate 679 + * @num_events: Number of events to support (size of @registered_events) 680 + * @ops: Pointer to a struct holding references to protocol specific helpers 681 + * needed during events handling 682 + * 683 + * It is supposed to be called only once for each protocol at protocol 684 + * initialization time, so it warns if the requested protocol is found already 685 + * registered. 686 + * 687 + * Return: The allocated and registered descriptor on Success 688 + */ 689 + static struct scmi_registered_events_desc * 690 + scmi_allocate_registered_events_desc(struct scmi_notify_instance *ni, 691 + u8 proto_id, size_t queue_sz, size_t eh_sz, 692 + int num_events, 693 + const struct scmi_event_ops *ops) 694 + { 695 + int ret; 696 + struct scmi_registered_events_desc *pd; 697 + 698 + /* Ensure protocols are up to date */ 699 + smp_rmb(); 700 + if (WARN_ON(ni->registered_protocols[proto_id])) 701 + return ERR_PTR(-EINVAL); 702 + 703 + pd = devm_kzalloc(ni->handle->dev, sizeof(*pd), GFP_KERNEL); 704 + if (!pd) 705 + return ERR_PTR(-ENOMEM); 706 + pd->id = proto_id; 707 + pd->ops = ops; 708 + pd->ni = ni; 709 + 710 + ret = scmi_initialize_events_queue(ni, &pd->equeue, queue_sz); 711 + if (ret) 712 + return ERR_PTR(ret); 713 + 714 + pd->eh = devm_kzalloc(ni->handle->dev, eh_sz, GFP_KERNEL); 715 + if (!pd->eh) 716 + return ERR_PTR(-ENOMEM); 717 + pd->eh_sz = eh_sz; 718 + 719 + pd->registered_events = devm_kcalloc(ni->handle->dev, num_events, 720 + sizeof(char *), GFP_KERNEL); 721 + if (!pd->registered_events) 722 + return ERR_PTR(-ENOMEM); 723 + pd->num_events = num_events; 724 + 725 + /* Initialize per protocol handlers table */ 726 + mutex_init(&pd->registered_mtx); 727 + hash_init(pd->registered_events_handlers); 728 + 729 + return pd; 730 + } 731 + 732 + /** 733 + * scmi_register_protocol_events() - Register Protocol Events with the core 734 + * @handle: The handle identifying the platform instance against which the 735 + * the protocol's events are registered 736 + * @proto_id: Protocol ID 737 + * @queue_sz: Size in bytes of the associated queue to be allocated 738 + * @ops: Protocol specific event-related operations 739 + * @evt: Event descriptor array 740 + * @num_events: Number of events in @evt array 741 + * @num_sources: Number of possible sources for this protocol on this 742 + * platform. 743 + * 744 + * Used by SCMI Protocols initialization code to register with the notification 745 + * core the list of supported events and their descriptors: takes care to 746 + * pre-allocate and store all needed descriptors, scratch buffers and event 747 + * queues. 748 + * 749 + * Return: 0 on Success 750 + */ 751 + int scmi_register_protocol_events(const struct scmi_handle *handle, 752 + u8 proto_id, size_t queue_sz, 753 + const struct scmi_event_ops *ops, 754 + const struct scmi_event *evt, int num_events, 755 + int num_sources) 756 + { 757 + int i; 758 + size_t payld_sz = 0; 759 + struct scmi_registered_events_desc *pd; 760 + struct scmi_notify_instance *ni; 761 + 762 + if (!ops || !evt) 763 + return -EINVAL; 764 + 765 + /* Ensure notify_priv is updated */ 766 + smp_rmb(); 767 + if (!handle->notify_priv) 768 + return -ENOMEM; 769 + ni = handle->notify_priv; 770 + 771 + /* Attach to the notification main devres group */ 772 + if (!devres_open_group(ni->handle->dev, ni->gid, GFP_KERNEL)) 773 + return -ENOMEM; 774 + 775 + for (i = 0; i < num_events; i++) 776 + payld_sz = max_t(size_t, payld_sz, evt[i].max_payld_sz); 777 + payld_sz += sizeof(struct scmi_event_header); 778 + 779 + pd = scmi_allocate_registered_events_desc(ni, proto_id, queue_sz, 780 + payld_sz, num_events, ops); 781 + if (IS_ERR(pd)) 782 + goto err; 783 + 784 + for (i = 0; i < num_events; i++, evt++) { 785 + struct scmi_registered_event *r_evt; 786 + 787 + r_evt = devm_kzalloc(ni->handle->dev, sizeof(*r_evt), 788 + GFP_KERNEL); 789 + if (!r_evt) 790 + goto err; 791 + r_evt->proto = pd; 792 + r_evt->evt = evt; 793 + 794 + r_evt->sources = devm_kcalloc(ni->handle->dev, num_sources, 795 + sizeof(refcount_t), GFP_KERNEL); 796 + if (!r_evt->sources) 797 + goto err; 798 + r_evt->num_sources = num_sources; 799 + mutex_init(&r_evt->sources_mtx); 800 + 801 + r_evt->report = devm_kzalloc(ni->handle->dev, 802 + evt->max_report_sz, GFP_KERNEL); 803 + if (!r_evt->report) 804 + goto err; 805 + 806 + pd->registered_events[i] = r_evt; 807 + /* Ensure events are updated */ 808 + smp_wmb(); 809 + dev_dbg(handle->dev, "registered event - %lX\n", 810 + MAKE_ALL_SRCS_KEY(r_evt->proto->id, r_evt->evt->id)); 811 + } 812 + 813 + /* Register protocol and events...it will never be removed */ 814 + ni->registered_protocols[proto_id] = pd; 815 + /* Ensure protocols are updated */ 816 + smp_wmb(); 817 + 818 + devres_close_group(ni->handle->dev, ni->gid); 819 + 820 + /* 821 + * Finalize any pending events' handler which could have been waiting 822 + * for this protocol's events registration. 823 + */ 824 + schedule_work(&ni->init_work); 825 + 826 + return 0; 827 + 828 + err: 829 + dev_warn(handle->dev, "Proto:%X - Registration Failed !\n", proto_id); 830 + /* A failing protocol registration does not trigger full failure */ 831 + devres_close_group(ni->handle->dev, ni->gid); 832 + 833 + return -ENOMEM; 834 + } 835 + 836 + /** 837 + * scmi_allocate_event_handler() - Allocate Event handler 838 + * @ni: A reference to the notification instance to use 839 + * @evt_key: 32bit key uniquely bind to the event identified by the tuple 840 + * (proto_id, evt_id, src_id) 841 + * 842 + * Allocate an event handler and related notification chain associated with 843 + * the provided event handler key. 844 + * Note that, at this point, a related registered_event is still to be 845 + * associated to this handler descriptor (hndl->r_evt == NULL), so the handler 846 + * is initialized as pending. 847 + * 848 + * Context: Assumes to be called with @pending_mtx already acquired. 849 + * Return: the freshly allocated structure on Success 850 + */ 851 + static struct scmi_event_handler * 852 + scmi_allocate_event_handler(struct scmi_notify_instance *ni, u32 evt_key) 853 + { 854 + struct scmi_event_handler *hndl; 855 + 856 + hndl = kzalloc(sizeof(*hndl), GFP_KERNEL); 857 + if (!hndl) 858 + return NULL; 859 + hndl->key = evt_key; 860 + BLOCKING_INIT_NOTIFIER_HEAD(&hndl->chain); 861 + refcount_set(&hndl->users, 1); 862 + /* New handlers are created pending */ 863 + hash_add(ni->pending_events_handlers, &hndl->hash, hndl->key); 864 + 865 + return hndl; 866 + } 867 + 868 + /** 869 + * scmi_free_event_handler() - Free the provided Event handler 870 + * @hndl: The event handler structure to free 871 + * 872 + * Context: Assumes to be called with proper locking acquired depending 873 + * on the situation. 874 + */ 875 + static void scmi_free_event_handler(struct scmi_event_handler *hndl) 876 + { 877 + hash_del(&hndl->hash); 878 + kfree(hndl); 879 + } 880 + 881 + /** 882 + * scmi_bind_event_handler() - Helper to attempt binding an handler to an event 883 + * @ni: A reference to the notification instance to use 884 + * @hndl: The event handler to bind 885 + * 886 + * If an associated registered event is found, move the handler from the pending 887 + * into the registered table. 888 + * 889 + * Context: Assumes to be called with @pending_mtx already acquired. 890 + * 891 + * Return: 0 on Success 892 + */ 893 + static inline int scmi_bind_event_handler(struct scmi_notify_instance *ni, 894 + struct scmi_event_handler *hndl) 895 + { 896 + struct scmi_registered_event *r_evt; 897 + 898 + r_evt = SCMI_GET_REVT(ni, KEY_XTRACT_PROTO_ID(hndl->key), 899 + KEY_XTRACT_EVT_ID(hndl->key)); 900 + if (!r_evt) 901 + return -EINVAL; 902 + 903 + /* Remove from pending and insert into registered */ 904 + hash_del(&hndl->hash); 905 + hndl->r_evt = r_evt; 906 + mutex_lock(&r_evt->proto->registered_mtx); 907 + hash_add(r_evt->proto->registered_events_handlers, 908 + &hndl->hash, hndl->key); 909 + mutex_unlock(&r_evt->proto->registered_mtx); 910 + 911 + return 0; 912 + } 913 + 914 + /** 915 + * scmi_valid_pending_handler() - Helper to check pending status of handlers 916 + * @ni: A reference to the notification instance to use 917 + * @hndl: The event handler to check 918 + * 919 + * An handler is considered pending when its r_evt == NULL, because the related 920 + * event was still unknown at handler's registration time; anyway, since all 921 + * protocols register their supported events once for all at protocols' 922 + * initialization time, a pending handler cannot be considered valid anymore if 923 + * the underlying event (which it is waiting for), belongs to an already 924 + * initialized and registered protocol. 925 + * 926 + * Return: 0 on Success 927 + */ 928 + static inline int scmi_valid_pending_handler(struct scmi_notify_instance *ni, 929 + struct scmi_event_handler *hndl) 930 + { 931 + struct scmi_registered_events_desc *pd; 932 + 933 + if (!IS_HNDL_PENDING(hndl)) 934 + return -EINVAL; 935 + 936 + pd = SCMI_GET_PROTO(ni, KEY_XTRACT_PROTO_ID(hndl->key)); 937 + if (pd) 938 + return -EINVAL; 939 + 940 + return 0; 941 + } 942 + 943 + /** 944 + * scmi_register_event_handler() - Register whenever possible an Event handler 945 + * @ni: A reference to the notification instance to use 946 + * @hndl: The event handler to register 947 + * 948 + * At first try to bind an event handler to its associated event, then check if 949 + * it was at least a valid pending handler: if it was not bound nor valid return 950 + * false. 951 + * 952 + * Valid pending incomplete bindings will be periodically retried by a dedicated 953 + * worker which is kicked each time a new protocol completes its own 954 + * registration phase. 955 + * 956 + * Context: Assumes to be called with @pending_mtx acquired. 957 + * 958 + * Return: 0 on Success 959 + */ 960 + static int scmi_register_event_handler(struct scmi_notify_instance *ni, 961 + struct scmi_event_handler *hndl) 962 + { 963 + int ret; 964 + 965 + ret = scmi_bind_event_handler(ni, hndl); 966 + if (!ret) { 967 + dev_dbg(ni->handle->dev, "registered NEW handler - key:%X\n", 968 + hndl->key); 969 + } else { 970 + ret = scmi_valid_pending_handler(ni, hndl); 971 + if (!ret) 972 + dev_dbg(ni->handle->dev, 973 + "registered PENDING handler - key:%X\n", 974 + hndl->key); 975 + } 976 + 977 + return ret; 978 + } 979 + 980 + /** 981 + * __scmi_event_handler_get_ops() - Utility to get or create an event handler 982 + * @ni: A reference to the notification instance to use 983 + * @evt_key: The event key to use 984 + * @create: A boolean flag to specify if a handler must be created when 985 + * not already existent 986 + * 987 + * Search for the desired handler matching the key in both the per-protocol 988 + * registered table and the common pending table: 989 + * * if found adjust users refcount 990 + * * if not found and @create is true, create and register the new handler: 991 + * handler could end up being registered as pending if no matching event 992 + * could be found. 993 + * 994 + * An handler is guaranteed to reside in one and only one of the tables at 995 + * any one time; to ensure this the whole search and create is performed 996 + * holding the @pending_mtx lock, with @registered_mtx additionally acquired 997 + * if needed. 998 + * 999 + * Note that when a nested acquisition of these mutexes is needed the locking 1000 + * order is always (same as in @init_work): 1001 + * 1. pending_mtx 1002 + * 2. registered_mtx 1003 + * 1004 + * Events generation is NOT enabled right after creation within this routine 1005 + * since at creation time we usually want to have all setup and ready before 1006 + * events really start flowing. 1007 + * 1008 + * Return: A properly refcounted handler on Success, NULL on Failure 1009 + */ 1010 + static inline struct scmi_event_handler * 1011 + __scmi_event_handler_get_ops(struct scmi_notify_instance *ni, 1012 + u32 evt_key, bool create) 1013 + { 1014 + struct scmi_registered_event *r_evt; 1015 + struct scmi_event_handler *hndl = NULL; 1016 + 1017 + r_evt = SCMI_GET_REVT(ni, KEY_XTRACT_PROTO_ID(evt_key), 1018 + KEY_XTRACT_EVT_ID(evt_key)); 1019 + 1020 + mutex_lock(&ni->pending_mtx); 1021 + /* Search registered events at first ... if possible at all */ 1022 + if (r_evt) { 1023 + mutex_lock(&r_evt->proto->registered_mtx); 1024 + hndl = KEY_FIND(r_evt->proto->registered_events_handlers, 1025 + hndl, evt_key); 1026 + if (hndl) 1027 + refcount_inc(&hndl->users); 1028 + mutex_unlock(&r_evt->proto->registered_mtx); 1029 + } 1030 + 1031 + /* ...then amongst pending. */ 1032 + if (!hndl) { 1033 + hndl = KEY_FIND(ni->pending_events_handlers, hndl, evt_key); 1034 + if (hndl) 1035 + refcount_inc(&hndl->users); 1036 + } 1037 + 1038 + /* Create if still not found and required */ 1039 + if (!hndl && create) { 1040 + hndl = scmi_allocate_event_handler(ni, evt_key); 1041 + if (hndl && scmi_register_event_handler(ni, hndl)) { 1042 + dev_dbg(ni->handle->dev, 1043 + "purging UNKNOWN handler - key:%X\n", 1044 + hndl->key); 1045 + /* this hndl can be only a pending one */ 1046 + scmi_put_handler_unlocked(ni, hndl); 1047 + hndl = NULL; 1048 + } 1049 + } 1050 + mutex_unlock(&ni->pending_mtx); 1051 + 1052 + return hndl; 1053 + } 1054 + 1055 + static struct scmi_event_handler * 1056 + scmi_get_handler(struct scmi_notify_instance *ni, u32 evt_key) 1057 + { 1058 + return __scmi_event_handler_get_ops(ni, evt_key, false); 1059 + } 1060 + 1061 + static struct scmi_event_handler * 1062 + scmi_get_or_create_handler(struct scmi_notify_instance *ni, u32 evt_key) 1063 + { 1064 + return __scmi_event_handler_get_ops(ni, evt_key, true); 1065 + } 1066 + 1067 + /** 1068 + * scmi_get_active_handler() - Helper to get active handlers only 1069 + * @ni: A reference to the notification instance to use 1070 + * @evt_key: The event key to use 1071 + * 1072 + * Search for the desired handler matching the key only in the per-protocol 1073 + * table of registered handlers: this is called only from the dispatching path 1074 + * so want to be as quick as possible and do not care about pending. 1075 + * 1076 + * Return: A properly refcounted active handler 1077 + */ 1078 + static struct scmi_event_handler * 1079 + scmi_get_active_handler(struct scmi_notify_instance *ni, u32 evt_key) 1080 + { 1081 + struct scmi_registered_event *r_evt; 1082 + struct scmi_event_handler *hndl = NULL; 1083 + 1084 + r_evt = SCMI_GET_REVT(ni, KEY_XTRACT_PROTO_ID(evt_key), 1085 + KEY_XTRACT_EVT_ID(evt_key)); 1086 + if (r_evt) { 1087 + mutex_lock(&r_evt->proto->registered_mtx); 1088 + hndl = KEY_FIND(r_evt->proto->registered_events_handlers, 1089 + hndl, evt_key); 1090 + if (hndl) 1091 + refcount_inc(&hndl->users); 1092 + mutex_unlock(&r_evt->proto->registered_mtx); 1093 + } 1094 + 1095 + return hndl; 1096 + } 1097 + 1098 + /** 1099 + * __scmi_enable_evt() - Enable/disable events generation 1100 + * @r_evt: The registered event to act upon 1101 + * @src_id: The src_id to act upon 1102 + * @enable: The action to perform: true->Enable, false->Disable 1103 + * 1104 + * Takes care of proper refcounting while performing enable/disable: handles 1105 + * the special case of ALL sources requests by itself. 1106 + * Returns successfully if at least one of the required src_id has been 1107 + * successfully enabled/disabled. 1108 + * 1109 + * Return: 0 on Success 1110 + */ 1111 + static inline int __scmi_enable_evt(struct scmi_registered_event *r_evt, 1112 + u32 src_id, bool enable) 1113 + { 1114 + int retvals = 0; 1115 + u32 num_sources; 1116 + refcount_t *sid; 1117 + 1118 + if (src_id == SRC_ID_MASK) { 1119 + src_id = 0; 1120 + num_sources = r_evt->num_sources; 1121 + } else if (src_id < r_evt->num_sources) { 1122 + num_sources = 1; 1123 + } else { 1124 + return -EINVAL; 1125 + } 1126 + 1127 + mutex_lock(&r_evt->sources_mtx); 1128 + if (enable) { 1129 + for (; num_sources; src_id++, num_sources--) { 1130 + int ret = 0; 1131 + 1132 + sid = &r_evt->sources[src_id]; 1133 + if (refcount_read(sid) == 0) { 1134 + ret = REVT_NOTIFY_ENABLE(r_evt, r_evt->evt->id, 1135 + src_id); 1136 + if (!ret) 1137 + refcount_set(sid, 1); 1138 + } else { 1139 + refcount_inc(sid); 1140 + } 1141 + retvals += !ret; 1142 + } 1143 + } else { 1144 + for (; num_sources; src_id++, num_sources--) { 1145 + sid = &r_evt->sources[src_id]; 1146 + if (refcount_dec_and_test(sid)) 1147 + REVT_NOTIFY_DISABLE(r_evt, 1148 + r_evt->evt->id, src_id); 1149 + } 1150 + retvals = 1; 1151 + } 1152 + mutex_unlock(&r_evt->sources_mtx); 1153 + 1154 + return retvals ? 0 : -EINVAL; 1155 + } 1156 + 1157 + static int scmi_enable_events(struct scmi_event_handler *hndl) 1158 + { 1159 + int ret = 0; 1160 + 1161 + if (!hndl->enabled) { 1162 + ret = __scmi_enable_evt(hndl->r_evt, 1163 + KEY_XTRACT_SRC_ID(hndl->key), true); 1164 + if (!ret) 1165 + hndl->enabled = true; 1166 + } 1167 + 1168 + return ret; 1169 + } 1170 + 1171 + static int scmi_disable_events(struct scmi_event_handler *hndl) 1172 + { 1173 + int ret = 0; 1174 + 1175 + if (hndl->enabled) { 1176 + ret = __scmi_enable_evt(hndl->r_evt, 1177 + KEY_XTRACT_SRC_ID(hndl->key), false); 1178 + if (!ret) 1179 + hndl->enabled = false; 1180 + } 1181 + 1182 + return ret; 1183 + } 1184 + 1185 + /** 1186 + * scmi_put_handler_unlocked() - Put an event handler 1187 + * @ni: A reference to the notification instance to use 1188 + * @hndl: The event handler to act upon 1189 + * 1190 + * After having got exclusive access to the registered handlers hashtable, 1191 + * update the refcount and if @hndl is no more in use by anyone: 1192 + * * ask for events' generation disabling 1193 + * * unregister and free the handler itself 1194 + * 1195 + * Context: Assumes all the proper locking has been managed by the caller. 1196 + */ 1197 + static void scmi_put_handler_unlocked(struct scmi_notify_instance *ni, 1198 + struct scmi_event_handler *hndl) 1199 + { 1200 + if (refcount_dec_and_test(&hndl->users)) { 1201 + if (!IS_HNDL_PENDING(hndl)) 1202 + scmi_disable_events(hndl); 1203 + scmi_free_event_handler(hndl); 1204 + } 1205 + } 1206 + 1207 + static void scmi_put_handler(struct scmi_notify_instance *ni, 1208 + struct scmi_event_handler *hndl) 1209 + { 1210 + struct scmi_registered_event *r_evt = hndl->r_evt; 1211 + 1212 + mutex_lock(&ni->pending_mtx); 1213 + if (r_evt) 1214 + mutex_lock(&r_evt->proto->registered_mtx); 1215 + 1216 + scmi_put_handler_unlocked(ni, hndl); 1217 + 1218 + if (r_evt) 1219 + mutex_unlock(&r_evt->proto->registered_mtx); 1220 + mutex_unlock(&ni->pending_mtx); 1221 + } 1222 + 1223 + static void scmi_put_active_handler(struct scmi_notify_instance *ni, 1224 + struct scmi_event_handler *hndl) 1225 + { 1226 + struct scmi_registered_event *r_evt = hndl->r_evt; 1227 + 1228 + mutex_lock(&r_evt->proto->registered_mtx); 1229 + scmi_put_handler_unlocked(ni, hndl); 1230 + mutex_unlock(&r_evt->proto->registered_mtx); 1231 + } 1232 + 1233 + /** 1234 + * scmi_event_handler_enable_events() - Enable events associated to an handler 1235 + * @hndl: The Event handler to act upon 1236 + * 1237 + * Return: 0 on Success 1238 + */ 1239 + static int scmi_event_handler_enable_events(struct scmi_event_handler *hndl) 1240 + { 1241 + if (scmi_enable_events(hndl)) { 1242 + pr_err("Failed to ENABLE events for key:%X !\n", hndl->key); 1243 + return -EINVAL; 1244 + } 1245 + 1246 + return 0; 1247 + } 1248 + 1249 + /** 1250 + * scmi_register_notifier() - Register a notifier_block for an event 1251 + * @handle: The handle identifying the platform instance against which the 1252 + * callback is registered 1253 + * @proto_id: Protocol ID 1254 + * @evt_id: Event ID 1255 + * @src_id: Source ID, when NULL register for events coming form ALL possible 1256 + * sources 1257 + * @nb: A standard notifier block to register for the specified event 1258 + * 1259 + * Generic helper to register a notifier_block against a protocol event. 1260 + * 1261 + * A notifier_block @nb will be registered for each distinct event identified 1262 + * by the tuple (proto_id, evt_id, src_id) on a dedicated notification chain 1263 + * so that: 1264 + * 1265 + * (proto_X, evt_Y, src_Z) --> chain_X_Y_Z 1266 + * 1267 + * @src_id meaning is protocol specific and identifies the origin of the event 1268 + * (like domain_id, sensor_id and so forth). 1269 + * 1270 + * @src_id can be NULL to signify that the caller is interested in receiving 1271 + * notifications from ALL the available sources for that protocol OR simply that 1272 + * the protocol does not support distinct sources. 1273 + * 1274 + * As soon as one user for the specified tuple appears, an handler is created, 1275 + * and that specific event's generation is enabled at the platform level, unless 1276 + * an associated registered event is found missing, meaning that the needed 1277 + * protocol is still to be initialized and the handler has just been registered 1278 + * as still pending. 1279 + * 1280 + * Return: 0 on Success 1281 + */ 1282 + static int scmi_register_notifier(const struct scmi_handle *handle, 1283 + u8 proto_id, u8 evt_id, u32 *src_id, 1284 + struct notifier_block *nb) 1285 + { 1286 + int ret = 0; 1287 + u32 evt_key; 1288 + struct scmi_event_handler *hndl; 1289 + struct scmi_notify_instance *ni; 1290 + 1291 + /* Ensure notify_priv is updated */ 1292 + smp_rmb(); 1293 + if (!handle->notify_priv) 1294 + return -ENODEV; 1295 + ni = handle->notify_priv; 1296 + 1297 + evt_key = MAKE_HASH_KEY(proto_id, evt_id, 1298 + src_id ? *src_id : SRC_ID_MASK); 1299 + hndl = scmi_get_or_create_handler(ni, evt_key); 1300 + if (!hndl) 1301 + return -EINVAL; 1302 + 1303 + blocking_notifier_chain_register(&hndl->chain, nb); 1304 + 1305 + /* Enable events for not pending handlers */ 1306 + if (!IS_HNDL_PENDING(hndl)) { 1307 + ret = scmi_event_handler_enable_events(hndl); 1308 + if (ret) 1309 + scmi_put_handler(ni, hndl); 1310 + } 1311 + 1312 + return ret; 1313 + } 1314 + 1315 + /** 1316 + * scmi_unregister_notifier() - Unregister a notifier_block for an event 1317 + * @handle: The handle identifying the platform instance against which the 1318 + * callback is unregistered 1319 + * @proto_id: Protocol ID 1320 + * @evt_id: Event ID 1321 + * @src_id: Source ID 1322 + * @nb: The notifier_block to unregister 1323 + * 1324 + * Takes care to unregister the provided @nb from the notification chain 1325 + * associated to the specified event and, if there are no more users for the 1326 + * event handler, frees also the associated event handler structures. 1327 + * (this could possibly cause disabling of event's generation at platform level) 1328 + * 1329 + * Return: 0 on Success 1330 + */ 1331 + static int scmi_unregister_notifier(const struct scmi_handle *handle, 1332 + u8 proto_id, u8 evt_id, u32 *src_id, 1333 + struct notifier_block *nb) 1334 + { 1335 + u32 evt_key; 1336 + struct scmi_event_handler *hndl; 1337 + struct scmi_notify_instance *ni; 1338 + 1339 + /* Ensure notify_priv is updated */ 1340 + smp_rmb(); 1341 + if (!handle->notify_priv) 1342 + return -ENODEV; 1343 + ni = handle->notify_priv; 1344 + 1345 + evt_key = MAKE_HASH_KEY(proto_id, evt_id, 1346 + src_id ? *src_id : SRC_ID_MASK); 1347 + hndl = scmi_get_handler(ni, evt_key); 1348 + if (!hndl) 1349 + return -EINVAL; 1350 + 1351 + /* 1352 + * Note that this chain unregistration call is safe on its own 1353 + * being internally protected by an rwsem. 1354 + */ 1355 + blocking_notifier_chain_unregister(&hndl->chain, nb); 1356 + scmi_put_handler(ni, hndl); 1357 + 1358 + /* 1359 + * This balances the initial get issued in @scmi_register_notifier. 1360 + * If this notifier_block happened to be the last known user callback 1361 + * for this event, the handler is here freed and the event's generation 1362 + * stopped. 1363 + * 1364 + * Note that, an ongoing concurrent lookup on the delivery workqueue 1365 + * path could still hold the refcount to 1 even after this routine 1366 + * completes: in such a case it will be the final put on the delivery 1367 + * path which will finally free this unused handler. 1368 + */ 1369 + scmi_put_handler(ni, hndl); 1370 + 1371 + return 0; 1372 + } 1373 + 1374 + /** 1375 + * scmi_protocols_late_init() - Worker for late initialization 1376 + * @work: The work item to use associated to the proper SCMI instance 1377 + * 1378 + * This kicks in whenever a new protocol has completed its own registration via 1379 + * scmi_register_protocol_events(): it is in charge of scanning the table of 1380 + * pending handlers (registered by users while the related protocol was still 1381 + * not initialized) and finalizing their initialization whenever possible; 1382 + * invalid pending handlers are purged at this point in time. 1383 + */ 1384 + static void scmi_protocols_late_init(struct work_struct *work) 1385 + { 1386 + int bkt; 1387 + struct scmi_event_handler *hndl; 1388 + struct scmi_notify_instance *ni; 1389 + struct hlist_node *tmp; 1390 + 1391 + ni = container_of(work, struct scmi_notify_instance, init_work); 1392 + 1393 + /* Ensure protocols and events are up to date */ 1394 + smp_rmb(); 1395 + 1396 + mutex_lock(&ni->pending_mtx); 1397 + hash_for_each_safe(ni->pending_events_handlers, bkt, tmp, hndl, hash) { 1398 + int ret; 1399 + 1400 + ret = scmi_bind_event_handler(ni, hndl); 1401 + if (!ret) { 1402 + dev_dbg(ni->handle->dev, 1403 + "finalized PENDING handler - key:%X\n", 1404 + hndl->key); 1405 + ret = scmi_event_handler_enable_events(hndl); 1406 + } else { 1407 + ret = scmi_valid_pending_handler(ni, hndl); 1408 + } 1409 + if (ret) { 1410 + dev_dbg(ni->handle->dev, 1411 + "purging PENDING handler - key:%X\n", 1412 + hndl->key); 1413 + /* this hndl can be only a pending one */ 1414 + scmi_put_handler_unlocked(ni, hndl); 1415 + } 1416 + } 1417 + mutex_unlock(&ni->pending_mtx); 1418 + } 1419 + 1420 + /* 1421 + * notify_ops are attached to the handle so that can be accessed 1422 + * directly from an scmi_driver to register its own notifiers. 1423 + */ 1424 + static struct scmi_notify_ops notify_ops = { 1425 + .register_event_notifier = scmi_register_notifier, 1426 + .unregister_event_notifier = scmi_unregister_notifier, 1427 + }; 1428 + 1429 + /** 1430 + * scmi_notification_init() - Initializes Notification Core Support 1431 + * @handle: The handle identifying the platform instance to initialize 1432 + * 1433 + * This function lays out all the basic resources needed by the notification 1434 + * core instance identified by the provided handle: once done, all of the 1435 + * SCMI Protocols can register their events with the core during their own 1436 + * initializations. 1437 + * 1438 + * Note that failing to initialize the core notifications support does not 1439 + * cause the whole SCMI Protocols stack to fail its initialization. 1440 + * 1441 + * SCMI Notification Initialization happens in 2 steps: 1442 + * * initialization: basic common allocations (this function) 1443 + * * registration: protocols asynchronously come into life and registers their 1444 + * own supported list of events with the core; this causes 1445 + * further per-protocol allocations 1446 + * 1447 + * Any user's callback registration attempt, referring a still not registered 1448 + * event, will be registered as pending and finalized later (if possible) 1449 + * by scmi_protocols_late_init() work. 1450 + * This allows for lazy initialization of SCMI Protocols due to late (or 1451 + * missing) SCMI drivers' modules loading. 1452 + * 1453 + * Return: 0 on Success 1454 + */ 1455 + int scmi_notification_init(struct scmi_handle *handle) 1456 + { 1457 + void *gid; 1458 + struct scmi_notify_instance *ni; 1459 + 1460 + gid = devres_open_group(handle->dev, NULL, GFP_KERNEL); 1461 + if (!gid) 1462 + return -ENOMEM; 1463 + 1464 + ni = devm_kzalloc(handle->dev, sizeof(*ni), GFP_KERNEL); 1465 + if (!ni) 1466 + goto err; 1467 + 1468 + ni->gid = gid; 1469 + ni->handle = handle; 1470 + 1471 + ni->notify_wq = alloc_workqueue("scmi_notify", 1472 + WQ_UNBOUND | WQ_FREEZABLE | WQ_SYSFS, 1473 + 0); 1474 + if (!ni->notify_wq) 1475 + goto err; 1476 + 1477 + ni->registered_protocols = devm_kcalloc(handle->dev, SCMI_MAX_PROTO, 1478 + sizeof(char *), GFP_KERNEL); 1479 + if (!ni->registered_protocols) 1480 + goto err; 1481 + 1482 + mutex_init(&ni->pending_mtx); 1483 + hash_init(ni->pending_events_handlers); 1484 + 1485 + INIT_WORK(&ni->init_work, scmi_protocols_late_init); 1486 + 1487 + handle->notify_ops = &notify_ops; 1488 + handle->notify_priv = ni; 1489 + /* Ensure handle is up to date */ 1490 + smp_wmb(); 1491 + 1492 + dev_info(handle->dev, "Core Enabled.\n"); 1493 + 1494 + devres_close_group(handle->dev, ni->gid); 1495 + 1496 + return 0; 1497 + 1498 + err: 1499 + dev_warn(handle->dev, "Initialization Failed.\n"); 1500 + devres_release_group(handle->dev, NULL); 1501 + return -ENOMEM; 1502 + } 1503 + 1504 + /** 1505 + * scmi_notification_exit() - Shutdown and clean Notification core 1506 + * @handle: The handle identifying the platform instance to shutdown 1507 + */ 1508 + void scmi_notification_exit(struct scmi_handle *handle) 1509 + { 1510 + struct scmi_notify_instance *ni; 1511 + 1512 + /* Ensure notify_priv is updated */ 1513 + smp_rmb(); 1514 + if (!handle->notify_priv) 1515 + return; 1516 + ni = handle->notify_priv; 1517 + 1518 + handle->notify_priv = NULL; 1519 + /* Ensure handle is up to date */ 1520 + smp_wmb(); 1521 + 1522 + /* Destroy while letting pending work complete */ 1523 + destroy_workqueue(ni->notify_wq); 1524 + 1525 + devres_release_group(ni->handle->dev, ni->gid); 1526 + }
+68
drivers/firmware/arm_scmi/notify.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + /* 3 + * System Control and Management Interface (SCMI) Message Protocol 4 + * notification header file containing some definitions, structures 5 + * and function prototypes related to SCMI Notification handling. 6 + * 7 + * Copyright (C) 2020 ARM Ltd. 8 + */ 9 + #ifndef _SCMI_NOTIFY_H 10 + #define _SCMI_NOTIFY_H 11 + 12 + #include <linux/device.h> 13 + #include <linux/ktime.h> 14 + #include <linux/types.h> 15 + 16 + #define SCMI_PROTO_QUEUE_SZ 4096 17 + 18 + /** 19 + * struct scmi_event - Describes an event to be supported 20 + * @id: Event ID 21 + * @max_payld_sz: Max possible size for the payload of a notification message 22 + * @max_report_sz: Max possible size for the report of a notification message 23 + * 24 + * Each SCMI protocol, during its initialization phase, can describe the events 25 + * it wishes to support in a few struct scmi_event and pass them to the core 26 + * using scmi_register_protocol_events(). 27 + */ 28 + struct scmi_event { 29 + u8 id; 30 + size_t max_payld_sz; 31 + size_t max_report_sz; 32 + }; 33 + 34 + /** 35 + * struct scmi_event_ops - Protocol helpers called by the notification core. 36 + * @set_notify_enabled: Enable/disable the required evt_id/src_id notifications 37 + * using the proper custom protocol commands. 38 + * Return 0 on Success 39 + * @fill_custom_report: fills a custom event report from the provided 40 + * event message payld identifying the event 41 + * specific src_id. 42 + * Return NULL on failure otherwise @report now fully 43 + * populated 44 + * 45 + * Context: Helpers described in &struct scmi_event_ops are called only in 46 + * process context. 47 + */ 48 + struct scmi_event_ops { 49 + int (*set_notify_enabled)(const struct scmi_handle *handle, 50 + u8 evt_id, u32 src_id, bool enabled); 51 + void *(*fill_custom_report)(const struct scmi_handle *handle, 52 + u8 evt_id, ktime_t timestamp, 53 + const void *payld, size_t payld_sz, 54 + void *report, u32 *src_id); 55 + }; 56 + 57 + int scmi_notification_init(struct scmi_handle *handle); 58 + void scmi_notification_exit(struct scmi_handle *handle); 59 + 60 + int scmi_register_protocol_events(const struct scmi_handle *handle, 61 + u8 proto_id, size_t queue_sz, 62 + const struct scmi_event_ops *ops, 63 + const struct scmi_event *evt, int num_events, 64 + int num_sources); 65 + int scmi_notify(const struct scmi_handle *handle, u8 proto_id, u8 evt_id, 66 + const void *buf, size_t len, ktime_t ts); 67 + 68 + #endif /* _SCMI_NOTIFY_H */
+146 -5
drivers/firmware/arm_scmi/perf.c
··· 5 5 * Copyright (C) 2018 ARM Ltd. 6 6 */ 7 7 8 + #define pr_fmt(fmt) "SCMI Notifications PERF - " fmt 9 + 8 10 #include <linux/bits.h> 9 11 #include <linux/of.h> 10 12 #include <linux/io.h> 11 13 #include <linux/io-64-nonatomic-hi-lo.h> 12 14 #include <linux/platform_device.h> 13 15 #include <linux/pm_opp.h> 16 + #include <linux/scmi_protocol.h> 14 17 #include <linux/sort.h> 15 18 16 19 #include "common.h" 20 + #include "notify.h" 17 21 18 22 enum scmi_performance_protocol_cmd { 19 23 PERF_DOMAIN_ATTRIBUTES = 0x3, ··· 29 25 PERF_NOTIFY_LIMITS = 0x9, 30 26 PERF_NOTIFY_LEVEL = 0xa, 31 27 PERF_DESCRIBE_FASTCHANNEL = 0xb, 32 - }; 33 - 34 - enum scmi_performance_protocol_notify { 35 - PERFORMANCE_LIMITS_CHANGED = 0x0, 36 - PERFORMANCE_LEVEL_CHANGED = 0x1, 37 28 }; 38 29 39 30 struct scmi_opp { ··· 83 84 struct scmi_perf_notify_level_or_limits { 84 85 __le32 domain; 85 86 __le32 notify_enable; 87 + }; 88 + 89 + struct scmi_perf_limits_notify_payld { 90 + __le32 agent_id; 91 + __le32 domain_id; 92 + __le32 range_max; 93 + __le32 range_min; 94 + }; 95 + 96 + struct scmi_perf_level_notify_payld { 97 + __le32 agent_id; 98 + __le32 domain_id; 99 + __le32 performance_level; 86 100 }; 87 101 88 102 struct scmi_msg_resp_perf_describe_levels { ··· 168 156 u64 stats_addr; 169 157 u32 stats_size; 170 158 struct perf_dom_info *dom_info; 159 + }; 160 + 161 + static enum scmi_performance_protocol_cmd evt_2_cmd[] = { 162 + PERF_NOTIFY_LIMITS, 163 + PERF_NOTIFY_LEVEL, 171 164 }; 172 165 173 166 static int scmi_perf_attributes_get(const struct scmi_handle *handle, ··· 505 488 return scmi_perf_mb_level_get(handle, domain, level, poll); 506 489 } 507 490 491 + static int scmi_perf_level_limits_notify(const struct scmi_handle *handle, 492 + u32 domain, int message_id, 493 + bool enable) 494 + { 495 + int ret; 496 + struct scmi_xfer *t; 497 + struct scmi_perf_notify_level_or_limits *notify; 498 + 499 + ret = scmi_xfer_get_init(handle, message_id, SCMI_PROTOCOL_PERF, 500 + sizeof(*notify), 0, &t); 501 + if (ret) 502 + return ret; 503 + 504 + notify = t->tx.buf; 505 + notify->domain = cpu_to_le32(domain); 506 + notify->notify_enable = enable ? cpu_to_le32(BIT(0)) : 0; 507 + 508 + ret = scmi_do_xfer(handle, t); 509 + 510 + scmi_xfer_put(handle, t); 511 + return ret; 512 + } 513 + 508 514 static bool scmi_perf_fc_size_is_valid(u32 msg, u32 size) 509 515 { 510 516 if ((msg == PERF_LEVEL_GET || msg == PERF_LEVEL_SET) && size == 4) ··· 737 697 return ret; 738 698 } 739 699 700 + static bool scmi_fast_switch_possible(const struct scmi_handle *handle, 701 + struct device *dev) 702 + { 703 + struct perf_dom_info *dom; 704 + struct scmi_perf_info *pi = handle->perf_priv; 705 + 706 + dom = pi->dom_info + scmi_dev_domain_id(dev); 707 + 708 + return dom->fc_info && dom->fc_info->level_set_addr; 709 + } 710 + 740 711 static struct scmi_perf_ops perf_ops = { 741 712 .limits_set = scmi_perf_limits_set, 742 713 .limits_get = scmi_perf_limits_get, ··· 759 708 .freq_set = scmi_dvfs_freq_set, 760 709 .freq_get = scmi_dvfs_freq_get, 761 710 .est_power_get = scmi_dvfs_est_power_get, 711 + .fast_switch_possible = scmi_fast_switch_possible, 712 + }; 713 + 714 + static int scmi_perf_set_notify_enabled(const struct scmi_handle *handle, 715 + u8 evt_id, u32 src_id, bool enable) 716 + { 717 + int ret, cmd_id; 718 + 719 + if (evt_id >= ARRAY_SIZE(evt_2_cmd)) 720 + return -EINVAL; 721 + 722 + cmd_id = evt_2_cmd[evt_id]; 723 + ret = scmi_perf_level_limits_notify(handle, src_id, cmd_id, enable); 724 + if (ret) 725 + pr_debug("FAIL_ENABLED - evt[%X] dom[%d] - ret:%d\n", 726 + evt_id, src_id, ret); 727 + 728 + return ret; 729 + } 730 + 731 + static void *scmi_perf_fill_custom_report(const struct scmi_handle *handle, 732 + u8 evt_id, ktime_t timestamp, 733 + const void *payld, size_t payld_sz, 734 + void *report, u32 *src_id) 735 + { 736 + void *rep = NULL; 737 + 738 + switch (evt_id) { 739 + case SCMI_EVENT_PERFORMANCE_LIMITS_CHANGED: 740 + { 741 + const struct scmi_perf_limits_notify_payld *p = payld; 742 + struct scmi_perf_limits_report *r = report; 743 + 744 + if (sizeof(*p) != payld_sz) 745 + break; 746 + 747 + r->timestamp = timestamp; 748 + r->agent_id = le32_to_cpu(p->agent_id); 749 + r->domain_id = le32_to_cpu(p->domain_id); 750 + r->range_max = le32_to_cpu(p->range_max); 751 + r->range_min = le32_to_cpu(p->range_min); 752 + *src_id = r->domain_id; 753 + rep = r; 754 + break; 755 + } 756 + case SCMI_EVENT_PERFORMANCE_LEVEL_CHANGED: 757 + { 758 + const struct scmi_perf_level_notify_payld *p = payld; 759 + struct scmi_perf_level_report *r = report; 760 + 761 + if (sizeof(*p) != payld_sz) 762 + break; 763 + 764 + r->timestamp = timestamp; 765 + r->agent_id = le32_to_cpu(p->agent_id); 766 + r->domain_id = le32_to_cpu(p->domain_id); 767 + r->performance_level = le32_to_cpu(p->performance_level); 768 + *src_id = r->domain_id; 769 + rep = r; 770 + break; 771 + } 772 + default: 773 + break; 774 + } 775 + 776 + return rep; 777 + } 778 + 779 + static const struct scmi_event perf_events[] = { 780 + { 781 + .id = SCMI_EVENT_PERFORMANCE_LIMITS_CHANGED, 782 + .max_payld_sz = sizeof(struct scmi_perf_limits_notify_payld), 783 + .max_report_sz = sizeof(struct scmi_perf_limits_report), 784 + }, 785 + { 786 + .id = SCMI_EVENT_PERFORMANCE_LEVEL_CHANGED, 787 + .max_payld_sz = sizeof(struct scmi_perf_level_notify_payld), 788 + .max_report_sz = sizeof(struct scmi_perf_level_report), 789 + }, 790 + }; 791 + 792 + static const struct scmi_event_ops perf_event_ops = { 793 + .set_notify_enabled = scmi_perf_set_notify_enabled, 794 + .fill_custom_report = scmi_perf_fill_custom_report, 762 795 }; 763 796 764 797 static int scmi_perf_protocol_init(struct scmi_handle *handle) ··· 876 741 if (dom->perf_fastchannels) 877 742 scmi_perf_domain_init_fc(handle, domain, &dom->fc_info); 878 743 } 744 + 745 + scmi_register_protocol_events(handle, 746 + SCMI_PROTOCOL_PERF, SCMI_PROTO_QUEUE_SZ, 747 + &perf_event_ops, perf_events, 748 + ARRAY_SIZE(perf_events), 749 + pinfo->num_domains); 879 750 880 751 pinfo->version = version; 881 752 handle->perf_ops = &perf_ops;
+86 -6
drivers/firmware/arm_scmi/power.c
··· 5 5 * Copyright (C) 2018 ARM Ltd. 6 6 */ 7 7 8 + #define pr_fmt(fmt) "SCMI Notifications POWER - " fmt 9 + 10 + #include <linux/scmi_protocol.h> 11 + 8 12 #include "common.h" 13 + #include "notify.h" 9 14 10 15 enum scmi_power_protocol_cmd { 11 16 POWER_DOMAIN_ATTRIBUTES = 0x3, 12 17 POWER_STATE_SET = 0x4, 13 18 POWER_STATE_GET = 0x5, 14 19 POWER_STATE_NOTIFY = 0x6, 15 - POWER_STATE_CHANGE_REQUESTED_NOTIFY = 0x7, 16 - }; 17 - 18 - enum scmi_power_protocol_notify { 19 - POWER_STATE_CHANGED = 0x0, 20 - POWER_STATE_CHANGE_REQUESTED = 0x1, 21 20 }; 22 21 23 22 struct scmi_msg_resp_power_attributes { ··· 45 46 struct scmi_power_state_notify { 46 47 __le32 domain; 47 48 __le32 notify_enable; 49 + }; 50 + 51 + struct scmi_power_state_notify_payld { 52 + __le32 agent_id; 53 + __le32 domain_id; 54 + __le32 power_state; 48 55 }; 49 56 50 57 struct power_dom_info { ··· 191 186 .state_get = scmi_power_state_get, 192 187 }; 193 188 189 + static int scmi_power_request_notify(const struct scmi_handle *handle, 190 + u32 domain, bool enable) 191 + { 192 + int ret; 193 + struct scmi_xfer *t; 194 + struct scmi_power_state_notify *notify; 195 + 196 + ret = scmi_xfer_get_init(handle, POWER_STATE_NOTIFY, 197 + SCMI_PROTOCOL_POWER, sizeof(*notify), 0, &t); 198 + if (ret) 199 + return ret; 200 + 201 + notify = t->tx.buf; 202 + notify->domain = cpu_to_le32(domain); 203 + notify->notify_enable = enable ? cpu_to_le32(BIT(0)) : 0; 204 + 205 + ret = scmi_do_xfer(handle, t); 206 + 207 + scmi_xfer_put(handle, t); 208 + return ret; 209 + } 210 + 211 + static int scmi_power_set_notify_enabled(const struct scmi_handle *handle, 212 + u8 evt_id, u32 src_id, bool enable) 213 + { 214 + int ret; 215 + 216 + ret = scmi_power_request_notify(handle, src_id, enable); 217 + if (ret) 218 + pr_debug("FAIL_ENABLE - evt[%X] dom[%d] - ret:%d\n", 219 + evt_id, src_id, ret); 220 + 221 + return ret; 222 + } 223 + 224 + static void *scmi_power_fill_custom_report(const struct scmi_handle *handle, 225 + u8 evt_id, ktime_t timestamp, 226 + const void *payld, size_t payld_sz, 227 + void *report, u32 *src_id) 228 + { 229 + const struct scmi_power_state_notify_payld *p = payld; 230 + struct scmi_power_state_changed_report *r = report; 231 + 232 + if (evt_id != SCMI_EVENT_POWER_STATE_CHANGED || sizeof(*p) != payld_sz) 233 + return NULL; 234 + 235 + r->timestamp = timestamp; 236 + r->agent_id = le32_to_cpu(p->agent_id); 237 + r->domain_id = le32_to_cpu(p->domain_id); 238 + r->power_state = le32_to_cpu(p->power_state); 239 + *src_id = r->domain_id; 240 + 241 + return r; 242 + } 243 + 244 + static const struct scmi_event power_events[] = { 245 + { 246 + .id = SCMI_EVENT_POWER_STATE_CHANGED, 247 + .max_payld_sz = sizeof(struct scmi_power_state_notify_payld), 248 + .max_report_sz = 249 + sizeof(struct scmi_power_state_changed_report), 250 + }, 251 + }; 252 + 253 + static const struct scmi_event_ops power_event_ops = { 254 + .set_notify_enabled = scmi_power_set_notify_enabled, 255 + .fill_custom_report = scmi_power_fill_custom_report, 256 + }; 257 + 194 258 static int scmi_power_protocol_init(struct scmi_handle *handle) 195 259 { 196 260 int domain; ··· 287 213 288 214 scmi_power_domain_attributes_get(handle, domain, dom); 289 215 } 216 + 217 + scmi_register_protocol_events(handle, 218 + SCMI_PROTOCOL_POWER, SCMI_PROTO_QUEUE_SZ, 219 + &power_event_ops, power_events, 220 + ARRAY_SIZE(power_events), 221 + pinfo->num_domains); 290 222 291 223 pinfo->version = version; 292 224 handle->power_ops = &power_ops;
+92 -4
drivers/firmware/arm_scmi/reset.c
··· 5 5 * Copyright (C) 2019 ARM Ltd. 6 6 */ 7 7 8 + #define pr_fmt(fmt) "SCMI Notifications RESET - " fmt 9 + 10 + #include <linux/scmi_protocol.h> 11 + 8 12 #include "common.h" 13 + #include "notify.h" 9 14 10 15 enum scmi_reset_protocol_cmd { 11 16 RESET_DOMAIN_ATTRIBUTES = 0x3, 12 17 RESET = 0x4, 13 18 RESET_NOTIFY = 0x5, 14 - }; 15 - 16 - enum scmi_reset_protocol_notify { 17 - RESET_ISSUED = 0x0, 18 19 }; 19 20 20 21 #define NUM_RESET_DOMAIN_MASK 0xffff ··· 39 38 #define ARCH_RESET_TYPE BIT(31) 40 39 #define COLD_RESET_STATE BIT(0) 41 40 #define ARCH_COLD_RESET (ARCH_RESET_TYPE | COLD_RESET_STATE) 41 + }; 42 + 43 + struct scmi_msg_reset_notify { 44 + __le32 id; 45 + __le32 event_control; 46 + #define RESET_TP_NOTIFY_ALL BIT(0) 47 + }; 48 + 49 + struct scmi_reset_issued_notify_payld { 50 + __le32 agent_id; 51 + __le32 domain_id; 52 + __le32 reset_state; 42 53 }; 43 54 44 55 struct reset_dom_info { ··· 203 190 .deassert = scmi_reset_domain_deassert, 204 191 }; 205 192 193 + static int scmi_reset_notify(const struct scmi_handle *handle, u32 domain_id, 194 + bool enable) 195 + { 196 + int ret; 197 + u32 evt_cntl = enable ? RESET_TP_NOTIFY_ALL : 0; 198 + struct scmi_xfer *t; 199 + struct scmi_msg_reset_notify *cfg; 200 + 201 + ret = scmi_xfer_get_init(handle, RESET_NOTIFY, 202 + SCMI_PROTOCOL_RESET, sizeof(*cfg), 0, &t); 203 + if (ret) 204 + return ret; 205 + 206 + cfg = t->tx.buf; 207 + cfg->id = cpu_to_le32(domain_id); 208 + cfg->event_control = cpu_to_le32(evt_cntl); 209 + 210 + ret = scmi_do_xfer(handle, t); 211 + 212 + scmi_xfer_put(handle, t); 213 + return ret; 214 + } 215 + 216 + static int scmi_reset_set_notify_enabled(const struct scmi_handle *handle, 217 + u8 evt_id, u32 src_id, bool enable) 218 + { 219 + int ret; 220 + 221 + ret = scmi_reset_notify(handle, src_id, enable); 222 + if (ret) 223 + pr_debug("FAIL_ENABLED - evt[%X] dom[%d] - ret:%d\n", 224 + evt_id, src_id, ret); 225 + 226 + return ret; 227 + } 228 + 229 + static void *scmi_reset_fill_custom_report(const struct scmi_handle *handle, 230 + u8 evt_id, ktime_t timestamp, 231 + const void *payld, size_t payld_sz, 232 + void *report, u32 *src_id) 233 + { 234 + const struct scmi_reset_issued_notify_payld *p = payld; 235 + struct scmi_reset_issued_report *r = report; 236 + 237 + if (evt_id != SCMI_EVENT_RESET_ISSUED || sizeof(*p) != payld_sz) 238 + return NULL; 239 + 240 + r->timestamp = timestamp; 241 + r->agent_id = le32_to_cpu(p->agent_id); 242 + r->domain_id = le32_to_cpu(p->domain_id); 243 + r->reset_state = le32_to_cpu(p->reset_state); 244 + *src_id = r->domain_id; 245 + 246 + return r; 247 + } 248 + 249 + static const struct scmi_event reset_events[] = { 250 + { 251 + .id = SCMI_EVENT_RESET_ISSUED, 252 + .max_payld_sz = sizeof(struct scmi_reset_issued_notify_payld), 253 + .max_report_sz = sizeof(struct scmi_reset_issued_report), 254 + }, 255 + }; 256 + 257 + static const struct scmi_event_ops reset_event_ops = { 258 + .set_notify_enabled = scmi_reset_set_notify_enabled, 259 + .fill_custom_report = scmi_reset_fill_custom_report, 260 + }; 261 + 206 262 static int scmi_reset_protocol_init(struct scmi_handle *handle) 207 263 { 208 264 int domain; ··· 299 217 300 218 scmi_reset_domain_attributes_get(handle, domain, dom); 301 219 } 220 + 221 + scmi_register_protocol_events(handle, 222 + SCMI_PROTOCOL_RESET, SCMI_PROTO_QUEUE_SZ, 223 + &reset_event_ops, reset_events, 224 + ARRAY_SIZE(reset_events), 225 + pinfo->num_domains); 302 226 303 227 pinfo->version = version; 304 228 handle->reset_ops = &reset_ops;
+6 -6
drivers/firmware/arm_scmi/scmi_pm_domain.c
··· 85 85 for (i = 0; i < num_domains; i++, scmi_pd++) { 86 86 u32 state; 87 87 88 - domains[i] = &scmi_pd->genpd; 88 + if (handle->power_ops->state_get(handle, i, &state)) { 89 + dev_warn(dev, "failed to get state for domain %d\n", i); 90 + continue; 91 + } 89 92 90 93 scmi_pd->domain = i; 91 94 scmi_pd->handle = handle; ··· 97 94 scmi_pd->genpd.power_off = scmi_pd_power_off; 98 95 scmi_pd->genpd.power_on = scmi_pd_power_on; 99 96 100 - if (handle->power_ops->state_get(handle, i, &state)) { 101 - dev_warn(dev, "failed to get state for domain %d\n", i); 102 - continue; 103 - } 104 - 105 97 pm_genpd_init(&scmi_pd->genpd, NULL, 106 98 state == SCMI_POWER_STATE_GENERIC_OFF); 99 + 100 + domains[i] = &scmi_pd->genpd; 107 101 } 108 102 109 103 scmi_pd_data->domains = domains;
+64 -5
drivers/firmware/arm_scmi/sensors.c
··· 5 5 * Copyright (C) 2018 ARM Ltd. 6 6 */ 7 7 8 + #define pr_fmt(fmt) "SCMI Notifications SENSOR - " fmt 9 + 10 + #include <linux/scmi_protocol.h> 11 + 8 12 #include "common.h" 13 + #include "notify.h" 9 14 10 15 enum scmi_sensor_protocol_cmd { 11 16 SENSOR_DESCRIPTION_GET = 0x3, 12 17 SENSOR_TRIP_POINT_NOTIFY = 0x4, 13 18 SENSOR_TRIP_POINT_CONFIG = 0x5, 14 19 SENSOR_READING_GET = 0x6, 15 - }; 16 - 17 - enum scmi_sensor_protocol_notify { 18 - SENSOR_TRIP_POINT_EVENT = 0x0, 19 20 }; 20 21 21 22 struct scmi_msg_resp_sensor_attributes { ··· 70 69 __le32 id; 71 70 __le32 flags; 72 71 #define SENSOR_READ_ASYNC BIT(0) 72 + }; 73 + 74 + struct scmi_sensor_trip_notify_payld { 75 + __le32 agent_id; 76 + __le32 sensor_id; 77 + __le32 trip_point_desc; 73 78 }; 74 79 75 80 struct sensors_info { ··· 278 271 static struct scmi_sensor_ops sensor_ops = { 279 272 .count_get = scmi_sensor_count_get, 280 273 .info_get = scmi_sensor_info_get, 281 - .trip_point_notify = scmi_sensor_trip_point_notify, 282 274 .trip_point_config = scmi_sensor_trip_point_config, 283 275 .reading_get = scmi_sensor_reading_get, 276 + }; 277 + 278 + static int scmi_sensor_set_notify_enabled(const struct scmi_handle *handle, 279 + u8 evt_id, u32 src_id, bool enable) 280 + { 281 + int ret; 282 + 283 + ret = scmi_sensor_trip_point_notify(handle, src_id, enable); 284 + if (ret) 285 + pr_debug("FAIL_ENABLED - evt[%X] dom[%d] - ret:%d\n", 286 + evt_id, src_id, ret); 287 + 288 + return ret; 289 + } 290 + 291 + static void *scmi_sensor_fill_custom_report(const struct scmi_handle *handle, 292 + u8 evt_id, ktime_t timestamp, 293 + const void *payld, size_t payld_sz, 294 + void *report, u32 *src_id) 295 + { 296 + const struct scmi_sensor_trip_notify_payld *p = payld; 297 + struct scmi_sensor_trip_point_report *r = report; 298 + 299 + if (evt_id != SCMI_EVENT_SENSOR_TRIP_POINT_EVENT || 300 + sizeof(*p) != payld_sz) 301 + return NULL; 302 + 303 + r->timestamp = timestamp; 304 + r->agent_id = le32_to_cpu(p->agent_id); 305 + r->sensor_id = le32_to_cpu(p->sensor_id); 306 + r->trip_point_desc = le32_to_cpu(p->trip_point_desc); 307 + *src_id = r->sensor_id; 308 + 309 + return r; 310 + } 311 + 312 + static const struct scmi_event sensor_events[] = { 313 + { 314 + .id = SCMI_EVENT_SENSOR_TRIP_POINT_EVENT, 315 + .max_payld_sz = sizeof(struct scmi_sensor_trip_notify_payld), 316 + .max_report_sz = sizeof(struct scmi_sensor_trip_point_report), 317 + }, 318 + }; 319 + 320 + static const struct scmi_event_ops sensor_event_ops = { 321 + .set_notify_enabled = scmi_sensor_set_notify_enabled, 322 + .fill_custom_report = scmi_sensor_fill_custom_report, 284 323 }; 285 324 286 325 static int scmi_sensors_protocol_init(struct scmi_handle *handle) ··· 351 298 return -ENOMEM; 352 299 353 300 scmi_sensor_description_get(handle, sinfo); 301 + 302 + scmi_register_protocol_events(handle, 303 + SCMI_PROTOCOL_SENSOR, SCMI_PROTO_QUEUE_SZ, 304 + &sensor_event_ops, sensor_events, 305 + ARRAY_SIZE(sensor_events), 306 + sinfo->num_sensors); 354 307 355 308 sinfo->version = version; 356 309 handle->sensor_ops = &sensor_ops;
+1
drivers/firmware/arm_scmi/smc.c
··· 21 21 * 22 22 * @cinfo: SCMI channel info 23 23 * @shmem: Transmit/Receive shared memory area 24 + * @shmem_lock: Lock to protect access to Tx/Rx shared memory area 24 25 * @func_id: smc/hvc call function id 25 26 */ 26 27
+105 -5
include/linux/scmi_protocol.h
··· 9 9 #define _LINUX_SCMI_PROTOCOL_H 10 10 11 11 #include <linux/device.h> 12 + #include <linux/notifier.h> 12 13 #include <linux/types.h> 13 14 14 15 #define SCMI_MAX_STR_SIZE 16 ··· 119 118 unsigned long *rate, bool poll); 120 119 int (*est_power_get)(const struct scmi_handle *handle, u32 domain, 121 120 unsigned long *rate, unsigned long *power); 121 + bool (*fast_switch_possible)(const struct scmi_handle *handle, 122 + struct device *dev); 122 123 }; 123 124 124 125 /** ··· 176 173 * 177 174 * @count_get: get the count of sensors provided by SCMI 178 175 * @info_get: get the information of the specified sensor 179 - * @trip_point_notify: control notifications on cross-over events for 180 - * the trip-points 181 176 * @trip_point_config: selects and configures a trip-point of interest 182 177 * @reading_get: gets the current value of the sensor 183 178 */ 184 179 struct scmi_sensor_ops { 185 180 int (*count_get)(const struct scmi_handle *handle); 186 - 187 181 const struct scmi_sensor_info *(*info_get) 188 182 (const struct scmi_handle *handle, u32 sensor_id); 189 - int (*trip_point_notify)(const struct scmi_handle *handle, 190 - u32 sensor_id, bool enable); 191 183 int (*trip_point_config)(const struct scmi_handle *handle, 192 184 u32 sensor_id, u8 trip_id, u64 trip_value); 193 185 int (*reading_get)(const struct scmi_handle *handle, u32 sensor_id, ··· 210 212 }; 211 213 212 214 /** 215 + * struct scmi_notify_ops - represents notifications' operations provided by 216 + * SCMI core 217 + * @register_event_notifier: Register a notifier_block for the requested event 218 + * @unregister_event_notifier: Unregister a notifier_block for the requested 219 + * event 220 + * 221 + * A user can register/unregister its own notifier_block against the wanted 222 + * platform instance regarding the desired event identified by the 223 + * tuple: (proto_id, evt_id, src_id) using the provided register/unregister 224 + * interface where: 225 + * 226 + * @handle: The handle identifying the platform instance to use 227 + * @proto_id: The protocol ID as in SCMI Specification 228 + * @evt_id: The message ID of the desired event as in SCMI Specification 229 + * @src_id: A pointer to the desired source ID if different sources are 230 + * possible for the protocol (like domain_id, sensor_id...etc) 231 + * 232 + * @src_id can be provided as NULL if it simply does NOT make sense for 233 + * the protocol at hand, OR if the user is explicitly interested in 234 + * receiving notifications from ANY existent source associated to the 235 + * specified proto_id / evt_id. 236 + * 237 + * Received notifications are finally delivered to the registered users, 238 + * invoking the callback provided with the notifier_block *nb as follows: 239 + * 240 + * int user_cb(nb, evt_id, report) 241 + * 242 + * with: 243 + * 244 + * @nb: The notifier block provided by the user 245 + * @evt_id: The message ID of the delivered event 246 + * @report: A custom struct describing the specific event delivered 247 + */ 248 + struct scmi_notify_ops { 249 + int (*register_event_notifier)(const struct scmi_handle *handle, 250 + u8 proto_id, u8 evt_id, u32 *src_id, 251 + struct notifier_block *nb); 252 + int (*unregister_event_notifier)(const struct scmi_handle *handle, 253 + u8 proto_id, u8 evt_id, u32 *src_id, 254 + struct notifier_block *nb); 255 + }; 256 + 257 + /** 213 258 * struct scmi_handle - Handle returned to ARM SCMI clients for usage. 214 259 * 215 260 * @dev: pointer to the SCMI device ··· 262 221 * @clk_ops: pointer to set of clock protocol operations 263 222 * @sensor_ops: pointer to set of sensor protocol operations 264 223 * @reset_ops: pointer to set of reset protocol operations 224 + * @notify_ops: pointer to set of notifications related operations 265 225 * @perf_priv: pointer to private data structure specific to performance 266 226 * protocol(for internal use only) 267 227 * @clk_priv: pointer to private data structure specific to clock ··· 273 231 * protocol(for internal use only) 274 232 * @reset_priv: pointer to private data structure specific to reset 275 233 * protocol(for internal use only) 234 + * @notify_priv: pointer to private data structure specific to notifications 235 + * (for internal use only) 276 236 */ 277 237 struct scmi_handle { 278 238 struct device *dev; ··· 284 240 struct scmi_power_ops *power_ops; 285 241 struct scmi_sensor_ops *sensor_ops; 286 242 struct scmi_reset_ops *reset_ops; 243 + struct scmi_notify_ops *notify_ops; 287 244 /* for protocol internal use */ 288 245 void *perf_priv; 289 246 void *clk_priv; 290 247 void *power_priv; 291 248 void *sensor_priv; 292 249 void *reset_priv; 250 + void *notify_priv; 293 251 }; 294 252 295 253 enum scmi_std_protocol { ··· 369 323 typedef int (*scmi_prot_init_fn_t)(struct scmi_handle *); 370 324 int scmi_protocol_register(int protocol_id, scmi_prot_init_fn_t fn); 371 325 void scmi_protocol_unregister(int protocol_id); 326 + 327 + /* SCMI Notification API - Custom Event Reports */ 328 + enum scmi_notification_events { 329 + SCMI_EVENT_POWER_STATE_CHANGED = 0x0, 330 + SCMI_EVENT_PERFORMANCE_LIMITS_CHANGED = 0x0, 331 + SCMI_EVENT_PERFORMANCE_LEVEL_CHANGED = 0x1, 332 + SCMI_EVENT_SENSOR_TRIP_POINT_EVENT = 0x0, 333 + SCMI_EVENT_RESET_ISSUED = 0x0, 334 + SCMI_EVENT_BASE_ERROR_EVENT = 0x0, 335 + }; 336 + 337 + struct scmi_power_state_changed_report { 338 + ktime_t timestamp; 339 + unsigned int agent_id; 340 + unsigned int domain_id; 341 + unsigned int power_state; 342 + }; 343 + 344 + struct scmi_perf_limits_report { 345 + ktime_t timestamp; 346 + unsigned int agent_id; 347 + unsigned int domain_id; 348 + unsigned int range_max; 349 + unsigned int range_min; 350 + }; 351 + 352 + struct scmi_perf_level_report { 353 + ktime_t timestamp; 354 + unsigned int agent_id; 355 + unsigned int domain_id; 356 + unsigned int performance_level; 357 + }; 358 + 359 + struct scmi_sensor_trip_point_report { 360 + ktime_t timestamp; 361 + unsigned int agent_id; 362 + unsigned int sensor_id; 363 + unsigned int trip_point_desc; 364 + }; 365 + 366 + struct scmi_reset_issued_report { 367 + ktime_t timestamp; 368 + unsigned int agent_id; 369 + unsigned int domain_id; 370 + unsigned int reset_state; 371 + }; 372 + 373 + struct scmi_base_error_report { 374 + ktime_t timestamp; 375 + unsigned int agent_id; 376 + bool fatal; 377 + unsigned int cmd_count; 378 + unsigned long long reports[]; 379 + }; 372 380 373 381 #endif /* _LINUX_SCMI_PROTOCOL_H */
+3 -3
include/trace/events/scmi.h
··· 35 35 36 36 TRACE_EVENT(scmi_xfer_end, 37 37 TP_PROTO(int transfer_id, u8 msg_id, u8 protocol_id, u16 seq, 38 - u32 status), 38 + int status), 39 39 TP_ARGS(transfer_id, msg_id, protocol_id, seq, status), 40 40 41 41 TP_STRUCT__entry( ··· 43 43 __field(u8, msg_id) 44 44 __field(u8, protocol_id) 45 45 __field(u16, seq) 46 - __field(u32, status) 46 + __field(int, status) 47 47 ), 48 48 49 49 TP_fast_assign( ··· 54 54 __entry->status = status; 55 55 ), 56 56 57 - TP_printk("transfer_id=%d msg_id=%u protocol_id=%u seq=%u status=%u", 57 + TP_printk("transfer_id=%d msg_id=%u protocol_id=%u seq=%u status=%d", 58 58 __entry->transfer_id, __entry->msg_id, __entry->protocol_id, 59 59 __entry->seq, __entry->status) 60 60 );