1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * System Control and Management Interface (SCMI) Base Protocol 4 * 5 * Copyright (C) 2018-2021 ARM Ltd. 6 */ 7 8 #define pr_fmt(fmt) "SCMI Notifications BASE - " fmt 9 10 #include <linux/module.h> 11 #include <linux/scmi_protocol.h> 12 13 #include "common.h" 14 #include "notify.h" 15 16 /* Updated only after ALL the mandatory features for that version are merged */ 17 #define SCMI_PROTOCOL_SUPPORTED_VERSION 0x20001 18 19 #define SCMI_BASE_NUM_SOURCES 1 20 #define SCMI_BASE_MAX_CMD_ERR_COUNT 1024 21 22 enum scmi_base_protocol_cmd { 23 BASE_DISCOVER_VENDOR = 0x3, 24 BASE_DISCOVER_SUB_VENDOR = 0x4, 25 BASE_DISCOVER_IMPLEMENT_VERSION = 0x5, 26 BASE_DISCOVER_LIST_PROTOCOLS = 0x6, 27 BASE_DISCOVER_AGENT = 0x7, 28 BASE_NOTIFY_ERRORS = 0x8, 29 BASE_SET_DEVICE_PERMISSIONS = 0x9, 30 BASE_SET_PROTOCOL_PERMISSIONS = 0xa, 31 BASE_RESET_AGENT_CONFIGURATION = 0xb, 32 }; 33 34 struct scmi_msg_resp_base_attributes { 35 u8 num_protocols; 36 u8 num_agents; 37 __le16 reserved; 38 }; 39 40 struct scmi_msg_resp_base_discover_agent { 41 __le32 agent_id; 42 u8 name[SCMI_SHORT_NAME_MAX_SIZE]; 43 }; 44 45 struct scmi_msg_base_error_notify { 46 __le32 event_control; 47 #define BASE_TP_NOTIFY_ALL BIT(0) 48 }; 49 50 struct scmi_base_error_notify_payld { 51 __le32 agent_id; 52 __le32 error_status; 53 #define IS_FATAL_ERROR(x) ((x) & BIT(31)) 54 #define ERROR_CMD_COUNT(x) FIELD_GET(GENMASK(9, 0), (x)) 55 __le64 msg_reports[SCMI_BASE_MAX_CMD_ERR_COUNT]; 56 }; 57 58 /** 59 * scmi_base_attributes_get() - gets the implementation details 60 * that are associated with the base protocol. 61 * 62 * @ph: SCMI protocol handle 63 * 64 * Return: 0 on success, else appropriate SCMI error. 65 */ 66 static int scmi_base_attributes_get(const struct scmi_protocol_handle *ph) 67 { 68 int ret; 69 struct scmi_xfer *t; 70 struct scmi_msg_resp_base_attributes *attr_info; 71 struct scmi_revision_info *rev = ph->get_priv(ph); 72 73 ret = ph->xops->xfer_get_init(ph, PROTOCOL_ATTRIBUTES, 74 0, sizeof(*attr_info), &t); 75 if (ret) 76 return ret; 77 78 ret = ph->xops->do_xfer(ph, t); 79 if (!ret) { 80 attr_info = t->rx.buf; 81 rev->num_protocols = attr_info->num_protocols; 82 rev->num_agents = attr_info->num_agents; 83 } 84 85 ph->xops->xfer_put(ph, t); 86 87 return ret; 88 } 89 90 /** 91 * scmi_base_vendor_id_get() - gets vendor/subvendor identifier ASCII string. 92 * 93 * @ph: SCMI protocol handle 94 * @sub_vendor: specify true if sub-vendor ID is needed 95 * 96 * Return: 0 on success, else appropriate SCMI error. 97 */ 98 static int 99 scmi_base_vendor_id_get(const struct scmi_protocol_handle *ph, bool sub_vendor) 100 { 101 u8 cmd; 102 int ret, size; 103 char *vendor_id; 104 struct scmi_xfer *t; 105 struct scmi_revision_info *rev = ph->get_priv(ph); 106 107 if (sub_vendor) { 108 cmd = BASE_DISCOVER_SUB_VENDOR; 109 vendor_id = rev->sub_vendor_id; 110 size = ARRAY_SIZE(rev->sub_vendor_id); 111 } else { 112 cmd = BASE_DISCOVER_VENDOR; 113 vendor_id = rev->vendor_id; 114 size = ARRAY_SIZE(rev->vendor_id); 115 } 116 117 ret = ph->xops->xfer_get_init(ph, cmd, 0, size, &t); 118 if (ret) 119 return ret; 120 121 ret = ph->xops->do_xfer(ph, t); 122 if (!ret) 123 strscpy(vendor_id, t->rx.buf, size); 124 125 ph->xops->xfer_put(ph, t); 126 127 return ret; 128 } 129 130 /** 131 * scmi_base_implementation_version_get() - gets a vendor-specific 132 * implementation 32-bit version. The format of the version number is 133 * vendor-specific 134 * 135 * @ph: SCMI protocol handle 136 * 137 * Return: 0 on success, else appropriate SCMI error. 138 */ 139 static int 140 scmi_base_implementation_version_get(const struct scmi_protocol_handle *ph) 141 { 142 int ret; 143 __le32 *impl_ver; 144 struct scmi_xfer *t; 145 struct scmi_revision_info *rev = ph->get_priv(ph); 146 147 ret = ph->xops->xfer_get_init(ph, BASE_DISCOVER_IMPLEMENT_VERSION, 148 0, sizeof(*impl_ver), &t); 149 if (ret) 150 return ret; 151 152 ret = ph->xops->do_xfer(ph, t); 153 if (!ret) { 154 impl_ver = t->rx.buf; 155 rev->impl_ver = le32_to_cpu(*impl_ver); 156 } 157 158 ph->xops->xfer_put(ph, t); 159 160 return ret; 161 } 162 163 /** 164 * scmi_base_implementation_list_get() - gets the list of protocols it is 165 * OSPM is allowed to access 166 * 167 * @ph: SCMI protocol handle 168 * @protocols_imp: pointer to hold the list of protocol identifiers 169 * 170 * Return: 0 on success, else appropriate SCMI error. 171 */ 172 static int 173 scmi_base_implementation_list_get(const struct scmi_protocol_handle *ph, 174 u8 *protocols_imp) 175 { 176 u8 *list; 177 int ret, loop; 178 struct scmi_xfer *t; 179 __le32 *num_skip, *num_ret; 180 u32 tot_num_ret = 0, loop_num_ret; 181 struct device *dev = ph->dev; 182 struct scmi_revision_info *rev = ph->get_priv(ph); 183 184 ret = ph->xops->xfer_get_init(ph, BASE_DISCOVER_LIST_PROTOCOLS, 185 sizeof(*num_skip), 0, &t); 186 if (ret) 187 return ret; 188 189 num_skip = t->tx.buf; 190 num_ret = t->rx.buf; 191 list = t->rx.buf + sizeof(*num_ret); 192 193 do { 194 size_t real_list_sz; 195 u32 calc_list_sz; 196 197 /* Set the number of protocols to be skipped/already read */ 198 *num_skip = cpu_to_le32(tot_num_ret); 199 200 ret = ph->xops->do_xfer(ph, t); 201 if (ret) 202 break; 203 204 loop_num_ret = le32_to_cpu(*num_ret); 205 if (!loop_num_ret) 206 break; 207 208 if (loop_num_ret > rev->num_protocols - tot_num_ret) { 209 dev_err(dev, 210 "No. Returned protocols > Total protocols.\n"); 211 break; 212 } 213 214 if (t->rx.len < (sizeof(u32) * 2)) { 215 dev_err(dev, "Truncated reply - rx.len:%zd\n", 216 t->rx.len); 217 ret = -EPROTO; 218 break; 219 } 220 221 real_list_sz = t->rx.len - sizeof(u32); 222 calc_list_sz = (1 + (loop_num_ret - 1) / sizeof(u32)) * 223 sizeof(u32); 224 if (calc_list_sz != real_list_sz) { 225 dev_warn(dev, 226 "Malformed reply - real_sz:%zd calc_sz:%u (loop_num_ret:%d)\n", 227 real_list_sz, calc_list_sz, loop_num_ret); 228 /* 229 * Bail out if the expected list size is bigger than the 230 * total payload size of the received reply. 231 */ 232 if (calc_list_sz > real_list_sz) { 233 ret = -EPROTO; 234 break; 235 } 236 } 237 238 for (loop = 0; loop < loop_num_ret; loop++) 239 protocols_imp[tot_num_ret + loop] = *(list + loop); 240 241 tot_num_ret += loop_num_ret; 242 243 ph->xops->reset_rx_to_maxsz(ph, t); 244 } while (tot_num_ret < rev->num_protocols); 245 246 ph->xops->xfer_put(ph, t); 247 248 return ret; 249 } 250 251 /** 252 * scmi_base_discover_agent_get() - discover the name of an agent 253 * 254 * @ph: SCMI protocol handle 255 * @id: Agent identifier 256 * @name: Agent identifier ASCII string 257 * 258 * An agent id of 0 is reserved to identify the platform itself. 259 * Generally operating system is represented as "OSPM" 260 * 261 * Return: 0 on success, else appropriate SCMI error. 262 */ 263 static int scmi_base_discover_agent_get(const struct scmi_protocol_handle *ph, 264 int id, char *name) 265 { 266 int ret; 267 struct scmi_msg_resp_base_discover_agent *agent_info; 268 struct scmi_xfer *t; 269 270 ret = ph->xops->xfer_get_init(ph, BASE_DISCOVER_AGENT, 271 sizeof(__le32), sizeof(*agent_info), &t); 272 if (ret) 273 return ret; 274 275 put_unaligned_le32(id, t->tx.buf); 276 277 ret = ph->xops->do_xfer(ph, t); 278 if (!ret) { 279 agent_info = t->rx.buf; 280 strscpy(name, agent_info->name, SCMI_SHORT_NAME_MAX_SIZE); 281 } 282 283 ph->xops->xfer_put(ph, t); 284 285 return ret; 286 } 287 288 static int scmi_base_error_notify(const struct scmi_protocol_handle *ph, 289 bool enable) 290 { 291 int ret; 292 u32 evt_cntl = enable ? BASE_TP_NOTIFY_ALL : 0; 293 struct scmi_xfer *t; 294 struct scmi_msg_base_error_notify *cfg; 295 296 ret = ph->xops->xfer_get_init(ph, BASE_NOTIFY_ERRORS, 297 sizeof(*cfg), 0, &t); 298 if (ret) 299 return ret; 300 301 cfg = t->tx.buf; 302 cfg->event_control = cpu_to_le32(evt_cntl); 303 304 ret = ph->xops->do_xfer(ph, t); 305 306 ph->xops->xfer_put(ph, t); 307 return ret; 308 } 309 310 static int scmi_base_set_notify_enabled(const struct scmi_protocol_handle *ph, 311 u8 evt_id, u32 src_id, bool enable) 312 { 313 int ret; 314 315 ret = scmi_base_error_notify(ph, enable); 316 if (ret) 317 pr_debug("FAIL_ENABLED - evt[%X] ret:%d\n", evt_id, ret); 318 319 return ret; 320 } 321 322 static void *scmi_base_fill_custom_report(const struct scmi_protocol_handle *ph, 323 u8 evt_id, ktime_t timestamp, 324 const void *payld, size_t payld_sz, 325 void *report, u32 *src_id) 326 { 327 int i; 328 const struct scmi_base_error_notify_payld *p = payld; 329 struct scmi_base_error_report *r = report; 330 331 /* 332 * BaseError notification payload is variable in size but 333 * up to a maximum length determined by the struct ponted by p. 334 * Instead payld_sz is the effective length of this notification 335 * payload so cannot be greater of the maximum allowed size as 336 * pointed by p. 337 */ 338 if (evt_id != SCMI_EVENT_BASE_ERROR_EVENT || sizeof(*p) < payld_sz) 339 return NULL; 340 341 r->timestamp = timestamp; 342 r->agent_id = le32_to_cpu(p->agent_id); 343 r->fatal = IS_FATAL_ERROR(le32_to_cpu(p->error_status)); 344 r->cmd_count = ERROR_CMD_COUNT(le32_to_cpu(p->error_status)); 345 for (i = 0; i < r->cmd_count; i++) 346 r->reports[i] = le64_to_cpu(p->msg_reports[i]); 347 *src_id = 0; 348 349 return r; 350 } 351 352 static const struct scmi_event base_events[] = { 353 { 354 .id = SCMI_EVENT_BASE_ERROR_EVENT, 355 .max_payld_sz = sizeof(struct scmi_base_error_notify_payld), 356 .max_report_sz = sizeof(struct scmi_base_error_report) + 357 SCMI_BASE_MAX_CMD_ERR_COUNT * sizeof(u64), 358 }, 359 }; 360 361 static const struct scmi_event_ops base_event_ops = { 362 .set_notify_enabled = scmi_base_set_notify_enabled, 363 .fill_custom_report = scmi_base_fill_custom_report, 364 }; 365 366 static const struct scmi_protocol_events base_protocol_events = { 367 .queue_sz = 4 * SCMI_PROTO_QUEUE_SZ, 368 .ops = &base_event_ops, 369 .evts = base_events, 370 .num_events = ARRAY_SIZE(base_events), 371 .num_sources = SCMI_BASE_NUM_SOURCES, 372 }; 373 374 static int scmi_base_protocol_init(const struct scmi_protocol_handle *ph) 375 { 376 int id, ret; 377 u8 *prot_imp; 378 u32 version; 379 char name[SCMI_SHORT_NAME_MAX_SIZE]; 380 struct device *dev = ph->dev; 381 struct scmi_revision_info *rev = scmi_revision_area_get(ph); 382 383 ret = ph->xops->version_get(ph, &version); 384 if (ret) 385 return ret; 386 387 rev->major_ver = PROTOCOL_REV_MAJOR(version); 388 rev->minor_ver = PROTOCOL_REV_MINOR(version); 389 ph->set_priv(ph, rev, version); 390 391 ret = scmi_base_attributes_get(ph); 392 if (ret) 393 return ret; 394 395 prot_imp = devm_kcalloc(dev, rev->num_protocols, sizeof(u8), 396 GFP_KERNEL); 397 if (!prot_imp) 398 return -ENOMEM; 399 400 scmi_base_vendor_id_get(ph, false); 401 scmi_base_vendor_id_get(ph, true); 402 scmi_base_implementation_version_get(ph); 403 scmi_base_implementation_list_get(ph, prot_imp); 404 405 scmi_setup_protocol_implemented(ph, prot_imp); 406 407 dev_info(dev, "SCMI Protocol v%d.%d '%s:%s' Firmware version 0x%x\n", 408 rev->major_ver, rev->minor_ver, rev->vendor_id, 409 rev->sub_vendor_id, rev->impl_ver); 410 dev_dbg(dev, "Found %d protocol(s) %d agent(s)\n", rev->num_protocols, 411 rev->num_agents); 412 413 for (id = 0; id < rev->num_agents; id++) { 414 scmi_base_discover_agent_get(ph, id, name); 415 dev_dbg(dev, "Agent %d: %s\n", id, name); 416 } 417 418 return 0; 419 } 420 421 static const struct scmi_protocol scmi_base = { 422 .id = SCMI_PROTOCOL_BASE, 423 .owner = NULL, 424 .instance_init = &scmi_base_protocol_init, 425 .ops = NULL, 426 .events = &base_protocol_events, 427 .supported_version = SCMI_PROTOCOL_SUPPORTED_VERSION, 428 }; 429 430 DEFINE_SCMI_PROTOCOL_REGISTER_UNREGISTER(base, scmi_base) 431