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/math.h> 11 #include <linux/module.h> 12 #include <linux/scmi_protocol.h> 13 14 #include "common.h" 15 #include "notify.h" 16 17 /* Updated only after ALL the mandatory features for that version are merged */ 18 #define SCMI_PROTOCOL_SUPPORTED_VERSION 0x20001 19 20 #define SCMI_BASE_NUM_SOURCES 1 21 #define SCMI_BASE_MAX_CMD_ERR_COUNT 1024 22 23 enum scmi_base_protocol_cmd { 24 BASE_DISCOVER_VENDOR = 0x3, 25 BASE_DISCOVER_SUB_VENDOR = 0x4, 26 BASE_DISCOVER_IMPLEMENT_VERSION = 0x5, 27 BASE_DISCOVER_LIST_PROTOCOLS = 0x6, 28 BASE_DISCOVER_AGENT = 0x7, 29 BASE_NOTIFY_ERRORS = 0x8, 30 BASE_SET_DEVICE_PERMISSIONS = 0x9, 31 BASE_SET_PROTOCOL_PERMISSIONS = 0xa, 32 BASE_RESET_AGENT_CONFIGURATION = 0xb, 33 }; 34 35 struct scmi_msg_resp_base_attributes { 36 u8 num_protocols; 37 u8 num_agents; 38 __le16 reserved; 39 }; 40 41 struct scmi_msg_resp_base_discover_agent { 42 __le32 agent_id; 43 u8 name[SCMI_SHORT_NAME_MAX_SIZE]; 44 }; 45 46 struct scmi_msg_base_error_notify { 47 __le32 event_control; 48 #define BASE_TP_NOTIFY_ALL BIT(0) 49 }; 50 51 struct scmi_base_error_notify_payld { 52 __le32 agent_id; 53 __le32 error_status; 54 #define IS_FATAL_ERROR(x) ((x) & BIT(31)) 55 #define ERROR_CMD_COUNT(x) FIELD_GET(GENMASK(9, 0), (x)) 56 __le64 msg_reports[SCMI_BASE_MAX_CMD_ERR_COUNT]; 57 }; 58 59 /** 60 * scmi_base_attributes_get() - gets the implementation details 61 * that are associated with the base protocol. 62 * 63 * @ph: SCMI protocol handle 64 * 65 * Return: 0 on success, else appropriate SCMI error. 66 */ 67 static int scmi_base_attributes_get(const struct scmi_protocol_handle *ph) 68 { 69 int ret; 70 struct scmi_xfer *t; 71 struct scmi_msg_resp_base_attributes *attr_info; 72 struct scmi_revision_info *rev = ph->get_priv(ph); 73 74 ret = ph->xops->xfer_get_init(ph, PROTOCOL_ATTRIBUTES, 75 0, sizeof(*attr_info), &t); 76 if (ret) 77 return ret; 78 79 ret = ph->xops->do_xfer(ph, t); 80 if (!ret) { 81 attr_info = t->rx.buf; 82 rev->num_protocols = attr_info->num_protocols; 83 rev->num_agents = attr_info->num_agents; 84 } 85 86 ph->xops->xfer_put(ph, t); 87 88 return ret; 89 } 90 91 /** 92 * scmi_base_vendor_id_get() - gets vendor/subvendor identifier ASCII string. 93 * 94 * @ph: SCMI protocol handle 95 * @sub_vendor: specify true if sub-vendor ID is needed 96 * 97 * Return: 0 on success, else appropriate SCMI error. 98 */ 99 static int 100 scmi_base_vendor_id_get(const struct scmi_protocol_handle *ph, bool sub_vendor) 101 { 102 u8 cmd; 103 int ret, size; 104 char *vendor_id; 105 struct scmi_xfer *t; 106 struct scmi_revision_info *rev = ph->get_priv(ph); 107 108 if (sub_vendor) { 109 cmd = BASE_DISCOVER_SUB_VENDOR; 110 vendor_id = rev->sub_vendor_id; 111 size = ARRAY_SIZE(rev->sub_vendor_id); 112 } else { 113 cmd = BASE_DISCOVER_VENDOR; 114 vendor_id = rev->vendor_id; 115 size = ARRAY_SIZE(rev->vendor_id); 116 } 117 118 ret = ph->xops->xfer_get_init(ph, cmd, 0, size, &t); 119 if (ret) 120 return ret; 121 122 ret = ph->xops->do_xfer(ph, t); 123 if (!ret) 124 strscpy(vendor_id, t->rx.buf, size); 125 126 ph->xops->xfer_put(ph, t); 127 128 return ret; 129 } 130 131 /** 132 * scmi_base_implementation_version_get() - gets a vendor-specific 133 * implementation 32-bit version. The format of the version number is 134 * vendor-specific 135 * 136 * @ph: SCMI protocol handle 137 * 138 * Return: 0 on success, else appropriate SCMI error. 139 */ 140 static int 141 scmi_base_implementation_version_get(const struct scmi_protocol_handle *ph) 142 { 143 int ret; 144 __le32 *impl_ver; 145 struct scmi_xfer *t; 146 struct scmi_revision_info *rev = ph->get_priv(ph); 147 148 ret = ph->xops->xfer_get_init(ph, BASE_DISCOVER_IMPLEMENT_VERSION, 149 0, sizeof(*impl_ver), &t); 150 if (ret) 151 return ret; 152 153 ret = ph->xops->do_xfer(ph, t); 154 if (!ret) { 155 impl_ver = t->rx.buf; 156 rev->impl_ver = le32_to_cpu(*impl_ver); 157 } 158 159 ph->xops->xfer_put(ph, t); 160 161 return ret; 162 } 163 164 /** 165 * scmi_base_implementation_list_get() - gets the list of protocols it is 166 * OSPM is allowed to access 167 * 168 * @ph: SCMI protocol handle 169 * @protocols_imp: pointer to hold the list of protocol identifiers 170 * 171 * Return: 0 on success, else appropriate SCMI error. 172 */ 173 static int 174 scmi_base_implementation_list_get(const struct scmi_protocol_handle *ph, 175 u8 *protocols_imp) 176 { 177 u8 *list; 178 int ret, loop; 179 struct scmi_xfer *t; 180 __le32 *num_skip, *num_ret; 181 u32 tot_num_ret = 0, loop_num_ret; 182 struct device *dev = ph->dev; 183 struct scmi_revision_info *rev = ph->get_priv(ph); 184 185 ret = ph->xops->xfer_get_init(ph, BASE_DISCOVER_LIST_PROTOCOLS, 186 sizeof(*num_skip), 0, &t); 187 if (ret) 188 return ret; 189 190 num_skip = t->tx.buf; 191 num_ret = t->rx.buf; 192 list = t->rx.buf + sizeof(*num_ret); 193 194 do { 195 size_t real_list_sz; 196 u32 calc_list_sz; 197 198 /* Set the number of protocols to be skipped/already read */ 199 *num_skip = cpu_to_le32(tot_num_ret); 200 201 ret = ph->xops->do_xfer(ph, t); 202 if (ret) 203 break; 204 205 loop_num_ret = le32_to_cpu(*num_ret); 206 if (!loop_num_ret) 207 break; 208 209 if (loop_num_ret > rev->num_protocols - tot_num_ret) { 210 dev_err(dev, 211 "No. Returned protocols > Total protocols.\n"); 212 break; 213 } 214 215 if (t->rx.len < (sizeof(u32) * 2)) { 216 dev_err(dev, "Truncated reply - rx.len:%zd\n", 217 t->rx.len); 218 ret = -EPROTO; 219 break; 220 } 221 222 real_list_sz = t->rx.len - sizeof(u32); 223 calc_list_sz = round_up(loop_num_ret, 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 char name[SCMI_SHORT_NAME_MAX_SIZE]; 379 struct device *dev = ph->dev; 380 struct scmi_revision_info *rev = scmi_revision_area_get(ph); 381 382 rev->major_ver = PROTOCOL_REV_MAJOR(ph->version); 383 rev->minor_ver = PROTOCOL_REV_MINOR(ph->version); 384 ph->set_priv(ph, rev); 385 386 ret = scmi_base_attributes_get(ph); 387 if (ret) 388 return ret; 389 390 prot_imp = devm_kcalloc(dev, rev->num_protocols, sizeof(u8), 391 GFP_KERNEL); 392 if (!prot_imp) 393 return -ENOMEM; 394 395 scmi_base_vendor_id_get(ph, false); 396 scmi_base_vendor_id_get(ph, true); 397 scmi_base_implementation_version_get(ph); 398 scmi_base_implementation_list_get(ph, prot_imp); 399 400 scmi_setup_protocol_implemented(ph, prot_imp); 401 402 dev_info(dev, "SCMI Protocol v%d.%d '%s:%s' Firmware version 0x%x\n", 403 rev->major_ver, rev->minor_ver, rev->vendor_id, 404 rev->sub_vendor_id, rev->impl_ver); 405 dev_dbg(dev, "Found %d protocol(s) %d agent(s)\n", rev->num_protocols, 406 rev->num_agents); 407 408 for (id = 0; id < rev->num_agents; id++) { 409 scmi_base_discover_agent_get(ph, id, name); 410 dev_dbg(dev, "Agent %d: %s\n", id, name); 411 } 412 413 return 0; 414 } 415 416 static const struct scmi_protocol scmi_base = { 417 .id = SCMI_PROTOCOL_BASE, 418 .owner = NULL, 419 .instance_init = &scmi_base_protocol_init, 420 .ops = NULL, 421 .events = &base_protocol_events, 422 .supported_version = SCMI_PROTOCOL_SUPPORTED_VERSION, 423 }; 424 425 DEFINE_SCMI_PROTOCOL_REGISTER_UNREGISTER(base, scmi_base) 426