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

Configure Feed

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

firmware: arm_scmi: Account for failed debug initialization

When the SCMI debug subsystem fails to initialize, the related debug root
will be missing, and the underlying descriptor will be NULL.

Handle this fault condition in the SCMI debug helpers that maintain
metrics counters.

Fixes: 0b3d48c4726e ("firmware: arm_scmi: Track basic SCMI communication debug metrics")
Signed-off-by: Cristian Marussi <cristian.marussi@arm.com>
Message-Id: <20251014115346.2391418-1-cristian.marussi@arm.com>
Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>

authored by

Cristian Marussi and committed by
Sudeep Holla
2290ab43 3a866087

+35 -33
+21 -3
drivers/firmware/arm_scmi/common.h
··· 309 309 SCMI_DEBUG_COUNTERS_LAST 310 310 }; 311 311 312 - static inline void scmi_inc_count(atomic_t *arr, int stat) 312 + /** 313 + * struct scmi_debug_info - Debug common info 314 + * @top_dentry: A reference to the top debugfs dentry 315 + * @name: Name of this SCMI instance 316 + * @type: Type of this SCMI instance 317 + * @is_atomic: Flag to state if the transport of this instance is atomic 318 + * @counters: An array of atomic_c's used for tracking statistics (if enabled) 319 + */ 320 + struct scmi_debug_info { 321 + struct dentry *top_dentry; 322 + const char *name; 323 + const char *type; 324 + bool is_atomic; 325 + atomic_t counters[SCMI_DEBUG_COUNTERS_LAST]; 326 + }; 327 + 328 + static inline void scmi_inc_count(struct scmi_debug_info *dbg, int stat) 313 329 { 314 - if (IS_ENABLED(CONFIG_ARM_SCMI_DEBUG_COUNTERS)) 315 - atomic_inc(&arr[stat]); 330 + if (IS_ENABLED(CONFIG_ARM_SCMI_DEBUG_COUNTERS)) { 331 + if (dbg) 332 + atomic_inc(&dbg->counters[stat]); 333 + } 316 334 } 317 335 318 336 static inline void scmi_dec_count(atomic_t *arr, int stat)
+14 -30
drivers/firmware/arm_scmi/driver.c
··· 116 116 #define ph_to_pi(h) container_of(h, struct scmi_protocol_instance, ph) 117 117 118 118 /** 119 - * struct scmi_debug_info - Debug common info 120 - * @top_dentry: A reference to the top debugfs dentry 121 - * @name: Name of this SCMI instance 122 - * @type: Type of this SCMI instance 123 - * @is_atomic: Flag to state if the transport of this instance is atomic 124 - * @counters: An array of atomic_c's used for tracking statistics (if enabled) 125 - */ 126 - struct scmi_debug_info { 127 - struct dentry *top_dentry; 128 - const char *name; 129 - const char *type; 130 - bool is_atomic; 131 - atomic_t counters[SCMI_DEBUG_COUNTERS_LAST]; 132 - }; 133 - 134 - /** 135 119 * struct scmi_info - Structure representing a SCMI instance 136 120 * 137 121 * @id: A sequence number starting from zero identifying this instance ··· 1018 1034 spin_unlock_irqrestore(&minfo->xfer_lock, flags); 1019 1035 1020 1036 scmi_bad_message_trace(cinfo, msg_hdr, MSG_UNEXPECTED); 1021 - scmi_inc_count(info->dbg->counters, ERR_MSG_UNEXPECTED); 1037 + scmi_inc_count(info->dbg, ERR_MSG_UNEXPECTED); 1022 1038 1023 1039 return xfer; 1024 1040 } ··· 1046 1062 msg_type, xfer_id, msg_hdr, xfer->state); 1047 1063 1048 1064 scmi_bad_message_trace(cinfo, msg_hdr, MSG_INVALID); 1049 - scmi_inc_count(info->dbg->counters, ERR_MSG_INVALID); 1065 + scmi_inc_count(info->dbg, ERR_MSG_INVALID); 1050 1066 1051 1067 /* On error the refcount incremented above has to be dropped */ 1052 1068 __scmi_xfer_put(minfo, xfer); ··· 1091 1107 PTR_ERR(xfer)); 1092 1108 1093 1109 scmi_bad_message_trace(cinfo, msg_hdr, MSG_NOMEM); 1094 - scmi_inc_count(info->dbg->counters, ERR_MSG_NOMEM); 1110 + scmi_inc_count(info->dbg, ERR_MSG_NOMEM); 1095 1111 1096 1112 scmi_clear_channel(info, cinfo); 1097 1113 return; ··· 1107 1123 trace_scmi_msg_dump(info->id, cinfo->id, xfer->hdr.protocol_id, 1108 1124 xfer->hdr.id, "NOTI", xfer->hdr.seq, 1109 1125 xfer->hdr.status, xfer->rx.buf, xfer->rx.len); 1110 - scmi_inc_count(info->dbg->counters, NOTIFICATION_OK); 1126 + scmi_inc_count(info->dbg, NOTIFICATION_OK); 1111 1127 1112 1128 scmi_notify(cinfo->handle, xfer->hdr.protocol_id, 1113 1129 xfer->hdr.id, xfer->rx.buf, xfer->rx.len, ts); ··· 1167 1183 if (xfer->hdr.type == MSG_TYPE_DELAYED_RESP) { 1168 1184 scmi_clear_channel(info, cinfo); 1169 1185 complete(xfer->async_done); 1170 - scmi_inc_count(info->dbg->counters, DELAYED_RESPONSE_OK); 1186 + scmi_inc_count(info->dbg, DELAYED_RESPONSE_OK); 1171 1187 } else { 1172 1188 complete(&xfer->done); 1173 - scmi_inc_count(info->dbg->counters, RESPONSE_OK); 1189 + scmi_inc_count(info->dbg, RESPONSE_OK); 1174 1190 } 1175 1191 1176 1192 if (IS_ENABLED(CONFIG_ARM_SCMI_RAW_MODE_SUPPORT)) { ··· 1280 1296 "timed out in resp(caller: %pS) - polling\n", 1281 1297 (void *)_RET_IP_); 1282 1298 ret = -ETIMEDOUT; 1283 - scmi_inc_count(info->dbg->counters, XFERS_RESPONSE_POLLED_TIMEOUT); 1299 + scmi_inc_count(info->dbg, XFERS_RESPONSE_POLLED_TIMEOUT); 1284 1300 } 1285 1301 } 1286 1302 ··· 1305 1321 "RESP" : "resp", 1306 1322 xfer->hdr.seq, xfer->hdr.status, 1307 1323 xfer->rx.buf, xfer->rx.len); 1308 - scmi_inc_count(info->dbg->counters, RESPONSE_POLLED_OK); 1324 + scmi_inc_count(info->dbg, RESPONSE_POLLED_OK); 1309 1325 1310 1326 if (IS_ENABLED(CONFIG_ARM_SCMI_RAW_MODE_SUPPORT)) { 1311 1327 scmi_raw_message_report(info->raw, xfer, ··· 1320 1336 dev_err(dev, "timed out in resp(caller: %pS)\n", 1321 1337 (void *)_RET_IP_); 1322 1338 ret = -ETIMEDOUT; 1323 - scmi_inc_count(info->dbg->counters, XFERS_RESPONSE_TIMEOUT); 1339 + scmi_inc_count(info->dbg, XFERS_RESPONSE_TIMEOUT); 1324 1340 } 1325 1341 } 1326 1342 ··· 1404 1420 !is_transport_polling_capable(info->desc)) { 1405 1421 dev_warn_once(dev, 1406 1422 "Polling mode is not supported by transport.\n"); 1407 - scmi_inc_count(info->dbg->counters, SENT_FAIL_POLLING_UNSUPPORTED); 1423 + scmi_inc_count(info->dbg, SENT_FAIL_POLLING_UNSUPPORTED); 1408 1424 return -EINVAL; 1409 1425 } 1410 1426 1411 1427 cinfo = idr_find(&info->tx_idr, pi->proto->id); 1412 1428 if (unlikely(!cinfo)) { 1413 - scmi_inc_count(info->dbg->counters, SENT_FAIL_CHANNEL_NOT_FOUND); 1429 + scmi_inc_count(info->dbg, SENT_FAIL_CHANNEL_NOT_FOUND); 1414 1430 return -EINVAL; 1415 1431 } 1416 1432 /* True ONLY if also supported by transport. */ ··· 1445 1461 ret = info->desc->ops->send_message(cinfo, xfer); 1446 1462 if (ret < 0) { 1447 1463 dev_dbg(dev, "Failed to send message %d\n", ret); 1448 - scmi_inc_count(info->dbg->counters, SENT_FAIL); 1464 + scmi_inc_count(info->dbg, SENT_FAIL); 1449 1465 return ret; 1450 1466 } 1451 1467 1452 1468 trace_scmi_msg_dump(info->id, cinfo->id, xfer->hdr.protocol_id, 1453 1469 xfer->hdr.id, "CMND", xfer->hdr.seq, 1454 1470 xfer->hdr.status, xfer->tx.buf, xfer->tx.len); 1455 - scmi_inc_count(info->dbg->counters, SENT_OK); 1471 + scmi_inc_count(info->dbg, SENT_OK); 1456 1472 1457 1473 ret = scmi_wait_for_message_response(cinfo, xfer); 1458 1474 if (!ret && xfer->hdr.status) { 1459 1475 ret = scmi_to_linux_errno(xfer->hdr.status); 1460 - scmi_inc_count(info->dbg->counters, ERR_PROTOCOL); 1476 + scmi_inc_count(info->dbg, ERR_PROTOCOL); 1461 1477 } 1462 1478 1463 1479 if (info->desc->ops->mark_txdone)