hc
2023-12-11 d2ccde1c8e90d38cee87a1b0309ad2827f3fd30d
kernel/drivers/firmware/arm_scmi/base.c
....@@ -5,7 +5,16 @@
55 * Copyright (C) 2018 ARM Ltd.
66 */
77
8
+#define pr_fmt(fmt) "SCMI Notifications BASE - " fmt
9
+
10
+#include <linux/module.h>
11
+#include <linux/scmi_protocol.h>
12
+
813 #include "common.h"
14
+#include "notify.h"
15
+
16
+#define SCMI_BASE_NUM_SOURCES 1
17
+#define SCMI_BASE_MAX_CMD_ERR_COUNT 1024
918
1019 enum scmi_base_protocol_cmd {
1120 BASE_DISCOVER_VENDOR = 0x3,
....@@ -14,6 +23,9 @@
1423 BASE_DISCOVER_LIST_PROTOCOLS = 0x6,
1524 BASE_DISCOVER_AGENT = 0x7,
1625 BASE_NOTIFY_ERRORS = 0x8,
26
+ BASE_SET_DEVICE_PERMISSIONS = 0x9,
27
+ BASE_SET_PROTOCOL_PERMISSIONS = 0xa,
28
+ BASE_RESET_AGENT_CONFIGURATION = 0xb,
1729 };
1830
1931 struct scmi_msg_resp_base_attributes {
....@@ -22,34 +34,47 @@
2234 __le16 reserved;
2335 };
2436
37
+struct scmi_msg_base_error_notify {
38
+ __le32 event_control;
39
+#define BASE_TP_NOTIFY_ALL BIT(0)
40
+};
41
+
42
+struct scmi_base_error_notify_payld {
43
+ __le32 agent_id;
44
+ __le32 error_status;
45
+#define IS_FATAL_ERROR(x) ((x) & BIT(31))
46
+#define ERROR_CMD_COUNT(x) FIELD_GET(GENMASK(9, 0), (x))
47
+ __le64 msg_reports[SCMI_BASE_MAX_CMD_ERR_COUNT];
48
+};
49
+
2550 /**
2651 * scmi_base_attributes_get() - gets the implementation details
2752 * that are associated with the base protocol.
2853 *
29
- * @handle: SCMI entity handle
54
+ * @ph: SCMI protocol handle
3055 *
3156 * Return: 0 on success, else appropriate SCMI error.
3257 */
33
-static int scmi_base_attributes_get(const struct scmi_handle *handle)
58
+static int scmi_base_attributes_get(const struct scmi_protocol_handle *ph)
3459 {
3560 int ret;
3661 struct scmi_xfer *t;
3762 struct scmi_msg_resp_base_attributes *attr_info;
38
- struct scmi_revision_info *rev = handle->version;
63
+ struct scmi_revision_info *rev = ph->get_priv(ph);
3964
40
- ret = scmi_xfer_get_init(handle, PROTOCOL_ATTRIBUTES,
41
- SCMI_PROTOCOL_BASE, 0, sizeof(*attr_info), &t);
65
+ ret = ph->xops->xfer_get_init(ph, PROTOCOL_ATTRIBUTES,
66
+ 0, sizeof(*attr_info), &t);
4267 if (ret)
4368 return ret;
4469
45
- ret = scmi_do_xfer(handle, t);
70
+ ret = ph->xops->do_xfer(ph, t);
4671 if (!ret) {
4772 attr_info = t->rx.buf;
4873 rev->num_protocols = attr_info->num_protocols;
4974 rev->num_agents = attr_info->num_agents;
5075 }
5176
52
- scmi_xfer_put(handle, t);
77
+ ph->xops->xfer_put(ph, t);
5378
5479 return ret;
5580 }
....@@ -57,19 +82,20 @@
5782 /**
5883 * scmi_base_vendor_id_get() - gets vendor/subvendor identifier ASCII string.
5984 *
60
- * @handle: SCMI entity handle
85
+ * @ph: SCMI protocol handle
6186 * @sub_vendor: specify true if sub-vendor ID is needed
6287 *
6388 * Return: 0 on success, else appropriate SCMI error.
6489 */
6590 static int
66
-scmi_base_vendor_id_get(const struct scmi_handle *handle, bool sub_vendor)
91
+scmi_base_vendor_id_get(const struct scmi_protocol_handle *ph, bool sub_vendor)
6792 {
6893 u8 cmd;
6994 int ret, size;
7095 char *vendor_id;
7196 struct scmi_xfer *t;
72
- struct scmi_revision_info *rev = handle->version;
97
+ struct scmi_revision_info *rev = ph->get_priv(ph);
98
+
7399
74100 if (sub_vendor) {
75101 cmd = BASE_DISCOVER_SUB_VENDOR;
....@@ -81,15 +107,15 @@
81107 size = ARRAY_SIZE(rev->vendor_id);
82108 }
83109
84
- ret = scmi_xfer_get_init(handle, cmd, SCMI_PROTOCOL_BASE, 0, size, &t);
110
+ ret = ph->xops->xfer_get_init(ph, cmd, 0, size, &t);
85111 if (ret)
86112 return ret;
87113
88
- ret = scmi_do_xfer(handle, t);
114
+ ret = ph->xops->do_xfer(ph, t);
89115 if (!ret)
90116 memcpy(vendor_id, t->rx.buf, size);
91117
92
- scmi_xfer_put(handle, t);
118
+ ph->xops->xfer_put(ph, t);
93119
94120 return ret;
95121 }
....@@ -99,30 +125,30 @@
99125 * implementation 32-bit version. The format of the version number is
100126 * vendor-specific
101127 *
102
- * @handle: SCMI entity handle
128
+ * @ph: SCMI protocol handle
103129 *
104130 * Return: 0 on success, else appropriate SCMI error.
105131 */
106132 static int
107
-scmi_base_implementation_version_get(const struct scmi_handle *handle)
133
+scmi_base_implementation_version_get(const struct scmi_protocol_handle *ph)
108134 {
109135 int ret;
110136 __le32 *impl_ver;
111137 struct scmi_xfer *t;
112
- struct scmi_revision_info *rev = handle->version;
138
+ struct scmi_revision_info *rev = ph->get_priv(ph);
113139
114
- ret = scmi_xfer_get_init(handle, BASE_DISCOVER_IMPLEMENT_VERSION,
115
- SCMI_PROTOCOL_BASE, 0, sizeof(*impl_ver), &t);
140
+ ret = ph->xops->xfer_get_init(ph, BASE_DISCOVER_IMPLEMENT_VERSION,
141
+ 0, sizeof(*impl_ver), &t);
116142 if (ret)
117143 return ret;
118144
119
- ret = scmi_do_xfer(handle, t);
145
+ ret = ph->xops->do_xfer(ph, t);
120146 if (!ret) {
121147 impl_ver = t->rx.buf;
122148 rev->impl_ver = le32_to_cpu(*impl_ver);
123149 }
124150
125
- scmi_xfer_put(handle, t);
151
+ ph->xops->xfer_put(ph, t);
126152
127153 return ret;
128154 }
....@@ -131,23 +157,24 @@
131157 * scmi_base_implementation_list_get() - gets the list of protocols it is
132158 * OSPM is allowed to access
133159 *
134
- * @handle: SCMI entity handle
160
+ * @ph: SCMI protocol handle
135161 * @protocols_imp: pointer to hold the list of protocol identifiers
136162 *
137163 * Return: 0 on success, else appropriate SCMI error.
138164 */
139
-static int scmi_base_implementation_list_get(const struct scmi_handle *handle,
140
- u8 *protocols_imp)
165
+static int
166
+scmi_base_implementation_list_get(const struct scmi_protocol_handle *ph,
167
+ u8 *protocols_imp)
141168 {
142169 u8 *list;
143170 int ret, loop;
144171 struct scmi_xfer *t;
145172 __le32 *num_skip, *num_ret;
146173 u32 tot_num_ret = 0, loop_num_ret;
147
- struct device *dev = handle->dev;
174
+ struct device *dev = ph->dev;
148175
149
- ret = scmi_xfer_get_init(handle, BASE_DISCOVER_LIST_PROTOCOLS,
150
- SCMI_PROTOCOL_BASE, sizeof(*num_skip), 0, &t);
176
+ ret = ph->xops->xfer_get_init(ph, BASE_DISCOVER_LIST_PROTOCOLS,
177
+ sizeof(*num_skip), 0, &t);
151178 if (ret)
152179 return ret;
153180
....@@ -159,12 +186,12 @@
159186 /* Set the number of protocols to be skipped/already read */
160187 *num_skip = cpu_to_le32(tot_num_ret);
161188
162
- ret = scmi_do_xfer(handle, t);
189
+ ret = ph->xops->do_xfer(ph, t);
163190 if (ret)
164191 break;
165192
166193 loop_num_ret = le32_to_cpu(*num_ret);
167
- if (tot_num_ret + loop_num_ret > MAX_PROTOCOLS_IMP) {
194
+ if (loop_num_ret > MAX_PROTOCOLS_IMP - tot_num_ret) {
168195 dev_err(dev, "No. of Protocol > MAX_PROTOCOLS_IMP");
169196 break;
170197 }
....@@ -173,9 +200,11 @@
173200 protocols_imp[tot_num_ret + loop] = *(list + loop);
174201
175202 tot_num_ret += loop_num_ret;
203
+
204
+ ph->xops->reset_rx_to_maxsz(ph, t);
176205 } while (loop_num_ret);
177206
178
- scmi_xfer_put(handle, t);
207
+ ph->xops->xfer_put(ph, t);
179208
180209 return ret;
181210 }
....@@ -183,7 +212,7 @@
183212 /**
184213 * scmi_base_discover_agent_get() - discover the name of an agent
185214 *
186
- * @handle: SCMI entity handle
215
+ * @ph: SCMI protocol handle
187216 * @id: Agent identifier
188217 * @name: Agent identifier ASCII string
189218 *
....@@ -192,40 +221,124 @@
192221 *
193222 * Return: 0 on success, else appropriate SCMI error.
194223 */
195
-static int scmi_base_discover_agent_get(const struct scmi_handle *handle,
224
+static int scmi_base_discover_agent_get(const struct scmi_protocol_handle *ph,
196225 int id, char *name)
197226 {
198227 int ret;
199228 struct scmi_xfer *t;
200229
201
- ret = scmi_xfer_get_init(handle, BASE_DISCOVER_AGENT,
202
- SCMI_PROTOCOL_BASE, sizeof(__le32),
203
- SCMI_MAX_STR_SIZE, &t);
230
+ ret = ph->xops->xfer_get_init(ph, BASE_DISCOVER_AGENT,
231
+ sizeof(__le32), SCMI_MAX_STR_SIZE, &t);
204232 if (ret)
205233 return ret;
206234
207235 put_unaligned_le32(id, t->tx.buf);
208236
209
- ret = scmi_do_xfer(handle, t);
237
+ ret = ph->xops->do_xfer(ph, t);
210238 if (!ret)
211239 strlcpy(name, t->rx.buf, SCMI_MAX_STR_SIZE);
212240
213
- scmi_xfer_put(handle, t);
241
+ ph->xops->xfer_put(ph, t);
214242
215243 return ret;
216244 }
217245
218
-int scmi_base_protocol_init(struct scmi_handle *h)
246
+static int scmi_base_error_notify(const struct scmi_protocol_handle *ph,
247
+ bool enable)
248
+{
249
+ int ret;
250
+ u32 evt_cntl = enable ? BASE_TP_NOTIFY_ALL : 0;
251
+ struct scmi_xfer *t;
252
+ struct scmi_msg_base_error_notify *cfg;
253
+
254
+ ret = ph->xops->xfer_get_init(ph, BASE_NOTIFY_ERRORS,
255
+ sizeof(*cfg), 0, &t);
256
+ if (ret)
257
+ return ret;
258
+
259
+ cfg = t->tx.buf;
260
+ cfg->event_control = cpu_to_le32(evt_cntl);
261
+
262
+ ret = ph->xops->do_xfer(ph, t);
263
+
264
+ ph->xops->xfer_put(ph, t);
265
+ return ret;
266
+}
267
+
268
+static int scmi_base_set_notify_enabled(const struct scmi_protocol_handle *ph,
269
+ u8 evt_id, u32 src_id, bool enable)
270
+{
271
+ int ret;
272
+
273
+ ret = scmi_base_error_notify(ph, enable);
274
+ if (ret)
275
+ pr_debug("FAIL_ENABLED - evt[%X] ret:%d\n", evt_id, ret);
276
+
277
+ return ret;
278
+}
279
+
280
+static void *scmi_base_fill_custom_report(const struct scmi_protocol_handle *ph,
281
+ u8 evt_id, ktime_t timestamp,
282
+ const void *payld, size_t payld_sz,
283
+ void *report, u32 *src_id)
284
+{
285
+ int i;
286
+ const struct scmi_base_error_notify_payld *p = payld;
287
+ struct scmi_base_error_report *r = report;
288
+
289
+ /*
290
+ * BaseError notification payload is variable in size but
291
+ * up to a maximum length determined by the struct ponted by p.
292
+ * Instead payld_sz is the effective length of this notification
293
+ * payload so cannot be greater of the maximum allowed size as
294
+ * pointed by p.
295
+ */
296
+ if (evt_id != SCMI_EVENT_BASE_ERROR_EVENT || sizeof(*p) < payld_sz)
297
+ return NULL;
298
+
299
+ r->timestamp = timestamp;
300
+ r->agent_id = le32_to_cpu(p->agent_id);
301
+ r->fatal = IS_FATAL_ERROR(le32_to_cpu(p->error_status));
302
+ r->cmd_count = ERROR_CMD_COUNT(le32_to_cpu(p->error_status));
303
+ for (i = 0; i < r->cmd_count; i++)
304
+ r->reports[i] = le64_to_cpu(p->msg_reports[i]);
305
+ *src_id = 0;
306
+
307
+ return r;
308
+}
309
+
310
+static const struct scmi_event base_events[] = {
311
+ {
312
+ .id = SCMI_EVENT_BASE_ERROR_EVENT,
313
+ .max_payld_sz = sizeof(struct scmi_base_error_notify_payld),
314
+ .max_report_sz = sizeof(struct scmi_base_error_report) +
315
+ SCMI_BASE_MAX_CMD_ERR_COUNT * sizeof(u64),
316
+ },
317
+};
318
+
319
+static const struct scmi_event_ops base_event_ops = {
320
+ .set_notify_enabled = scmi_base_set_notify_enabled,
321
+ .fill_custom_report = scmi_base_fill_custom_report,
322
+};
323
+
324
+static const struct scmi_protocol_events base_protocol_events = {
325
+ .queue_sz = 4 * SCMI_PROTO_QUEUE_SZ,
326
+ .ops = &base_event_ops,
327
+ .evts = base_events,
328
+ .num_events = ARRAY_SIZE(base_events),
329
+ .num_sources = SCMI_BASE_NUM_SOURCES,
330
+};
331
+
332
+static int scmi_base_protocol_init(const struct scmi_protocol_handle *ph)
219333 {
220334 int id, ret;
221335 u8 *prot_imp;
222336 u32 version;
223337 char name[SCMI_MAX_STR_SIZE];
224
- const struct scmi_handle *handle = h;
225
- struct device *dev = handle->dev;
226
- struct scmi_revision_info *rev = handle->version;
338
+ struct device *dev = ph->dev;
339
+ struct scmi_revision_info *rev = scmi_get_revision_area(ph);
227340
228
- ret = scmi_version_get(handle, SCMI_PROTOCOL_BASE, &version);
341
+ ret = ph->xops->version_get(ph, &version);
229342 if (ret)
230343 return ret;
231344
....@@ -235,13 +348,15 @@
235348
236349 rev->major_ver = PROTOCOL_REV_MAJOR(version),
237350 rev->minor_ver = PROTOCOL_REV_MINOR(version);
351
+ ph->set_priv(ph, rev);
238352
239
- scmi_base_attributes_get(handle);
240
- scmi_base_vendor_id_get(handle, false);
241
- scmi_base_vendor_id_get(handle, true);
242
- scmi_base_implementation_version_get(handle);
243
- scmi_base_implementation_list_get(handle, prot_imp);
244
- scmi_setup_protocol_implemented(handle, prot_imp);
353
+ scmi_base_attributes_get(ph);
354
+ scmi_base_vendor_id_get(ph, false);
355
+ scmi_base_vendor_id_get(ph, true);
356
+ scmi_base_implementation_version_get(ph);
357
+ scmi_base_implementation_list_get(ph, prot_imp);
358
+
359
+ scmi_setup_protocol_implemented(ph, prot_imp);
245360
246361 dev_info(dev, "SCMI Protocol v%d.%d '%s:%s' Firmware version 0x%x\n",
247362 rev->major_ver, rev->minor_ver, rev->vendor_id,
....@@ -250,9 +365,19 @@
250365 rev->num_agents);
251366
252367 for (id = 0; id < rev->num_agents; id++) {
253
- scmi_base_discover_agent_get(handle, id, name);
368
+ scmi_base_discover_agent_get(ph, id, name);
254369 dev_dbg(dev, "Agent %d: %s\n", id, name);
255370 }
256371
257372 return 0;
258373 }
374
+
375
+static const struct scmi_protocol scmi_base = {
376
+ .id = SCMI_PROTOCOL_BASE,
377
+ .owner = NULL,
378
+ .init_instance = &scmi_base_protocol_init,
379
+ .ops = NULL,
380
+ .events = &base_protocol_events,
381
+};
382
+
383
+DEFINE_SCMI_PROTOCOL_REGISTER_UNREGISTER(base, scmi_base)