Skip to content

Commit 71a5970

Browse files
committed
Merge tag 'scmi-fixes-6.18' of git://git.kernel.org/pub/scm/linux/kernel/git/sudeep.holla/linux into arm/fixes
Arm SCMI fixes for v6.18 This series contains a set of small, focused fixes that address robustness and lifecycle issues in the Arm SCMI core and debug support, ensuring safer handling of debug initialization failures, correct flag management in raw mode, and consistent inflight counter tracking. Brief summary: - Fix raw xfer flag clearing - Skip RAW debug initialization on failure - Make inflight counter helpers null-safe, preventing crashes if debug initialization fails - Account for failed debug initialization globally There is no functional change for standard SCMI operation, but these fixes improve stability in debug and raw modes, particularly in error paths. * tag 'scmi-fixes-6.18' of git://git.kernel.org/pub/scm/linux/kernel/git/sudeep.holla/linux: firmware: arm_scmi: Fix premature SCMI_XFER_FLAG_IS_RAW clearing in raw mode firmware: arm_scmi: Skip RAW initialization on failure include: trace: Fix inflight count helper on failed initialization firmware: arm_scmi: Account for failed debug initialization Signed-off-by: Arnd Bergmann <[email protected]>
2 parents f4cb028 + 20b93a0 commit 71a5970

2 files changed

Lines changed: 47 additions & 44 deletions

File tree

drivers/firmware/arm_scmi/common.h

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -309,16 +309,36 @@ enum debug_counters {
309309
SCMI_DEBUG_COUNTERS_LAST
310310
};
311311

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)
313329
{
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+
}
316334
}
317335

318-
static inline void scmi_dec_count(atomic_t *arr, int stat)
336+
static inline void scmi_dec_count(struct scmi_debug_info *dbg, int stat)
319337
{
320-
if (IS_ENABLED(CONFIG_ARM_SCMI_DEBUG_COUNTERS))
321-
atomic_dec(&arr[stat]);
338+
if (IS_ENABLED(CONFIG_ARM_SCMI_DEBUG_COUNTERS)) {
339+
if (dbg)
340+
atomic_dec(&dbg->counters[stat]);
341+
}
322342
}
323343

324344
enum scmi_bad_msg {

drivers/firmware/arm_scmi/driver.c

Lines changed: 21 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -115,22 +115,6 @@ struct scmi_protocol_instance {
115115

116116
#define ph_to_pi(h) container_of(h, struct scmi_protocol_instance, ph)
117117

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-
134118
/**
135119
* struct scmi_info - Structure representing a SCMI instance
136120
*
@@ -610,7 +594,7 @@ scmi_xfer_inflight_register_unlocked(struct scmi_xfer *xfer,
610594
/* Set in-flight */
611595
set_bit(xfer->hdr.seq, minfo->xfer_alloc_table);
612596
hash_add(minfo->pending_xfers, &xfer->node, xfer->hdr.seq);
613-
scmi_inc_count(info->dbg->counters, XFERS_INFLIGHT);
597+
scmi_inc_count(info->dbg, XFERS_INFLIGHT);
614598

615599
xfer->pending = true;
616600
}
@@ -819,8 +803,9 @@ __scmi_xfer_put(struct scmi_xfers_info *minfo, struct scmi_xfer *xfer)
819803
hash_del(&xfer->node);
820804
xfer->pending = false;
821805

822-
scmi_dec_count(info->dbg->counters, XFERS_INFLIGHT);
806+
scmi_dec_count(info->dbg, XFERS_INFLIGHT);
823807
}
808+
xfer->flags = 0;
824809
hlist_add_head(&xfer->node, &minfo->free_xfers);
825810
}
826811
spin_unlock_irqrestore(&minfo->xfer_lock, flags);
@@ -839,8 +824,6 @@ void scmi_xfer_raw_put(const struct scmi_handle *handle, struct scmi_xfer *xfer)
839824
{
840825
struct scmi_info *info = handle_to_scmi_info(handle);
841826

842-
xfer->flags &= ~SCMI_XFER_FLAG_IS_RAW;
843-
xfer->flags &= ~SCMI_XFER_FLAG_CHAN_SET;
844827
return __scmi_xfer_put(&info->tx_minfo, xfer);
845828
}
846829

@@ -1034,7 +1017,7 @@ scmi_xfer_command_acquire(struct scmi_chan_info *cinfo, u32 msg_hdr)
10341017
spin_unlock_irqrestore(&minfo->xfer_lock, flags);
10351018

10361019
scmi_bad_message_trace(cinfo, msg_hdr, MSG_UNEXPECTED);
1037-
scmi_inc_count(info->dbg->counters, ERR_MSG_UNEXPECTED);
1020+
scmi_inc_count(info->dbg, ERR_MSG_UNEXPECTED);
10381021

10391022
return xfer;
10401023
}
@@ -1062,7 +1045,7 @@ scmi_xfer_command_acquire(struct scmi_chan_info *cinfo, u32 msg_hdr)
10621045
msg_type, xfer_id, msg_hdr, xfer->state);
10631046

10641047
scmi_bad_message_trace(cinfo, msg_hdr, MSG_INVALID);
1065-
scmi_inc_count(info->dbg->counters, ERR_MSG_INVALID);
1048+
scmi_inc_count(info->dbg, ERR_MSG_INVALID);
10661049

10671050
/* On error the refcount incremented above has to be dropped */
10681051
__scmi_xfer_put(minfo, xfer);
@@ -1107,7 +1090,7 @@ static void scmi_handle_notification(struct scmi_chan_info *cinfo,
11071090
PTR_ERR(xfer));
11081091

11091092
scmi_bad_message_trace(cinfo, msg_hdr, MSG_NOMEM);
1110-
scmi_inc_count(info->dbg->counters, ERR_MSG_NOMEM);
1093+
scmi_inc_count(info->dbg, ERR_MSG_NOMEM);
11111094

11121095
scmi_clear_channel(info, cinfo);
11131096
return;
@@ -1123,7 +1106,7 @@ static void scmi_handle_notification(struct scmi_chan_info *cinfo,
11231106
trace_scmi_msg_dump(info->id, cinfo->id, xfer->hdr.protocol_id,
11241107
xfer->hdr.id, "NOTI", xfer->hdr.seq,
11251108
xfer->hdr.status, xfer->rx.buf, xfer->rx.len);
1126-
scmi_inc_count(info->dbg->counters, NOTIFICATION_OK);
1109+
scmi_inc_count(info->dbg, NOTIFICATION_OK);
11271110

11281111
scmi_notify(cinfo->handle, xfer->hdr.protocol_id,
11291112
xfer->hdr.id, xfer->rx.buf, xfer->rx.len, ts);
@@ -1183,10 +1166,10 @@ static void scmi_handle_response(struct scmi_chan_info *cinfo,
11831166
if (xfer->hdr.type == MSG_TYPE_DELAYED_RESP) {
11841167
scmi_clear_channel(info, cinfo);
11851168
complete(xfer->async_done);
1186-
scmi_inc_count(info->dbg->counters, DELAYED_RESPONSE_OK);
1169+
scmi_inc_count(info->dbg, DELAYED_RESPONSE_OK);
11871170
} else {
11881171
complete(&xfer->done);
1189-
scmi_inc_count(info->dbg->counters, RESPONSE_OK);
1172+
scmi_inc_count(info->dbg, RESPONSE_OK);
11901173
}
11911174

11921175
if (IS_ENABLED(CONFIG_ARM_SCMI_RAW_MODE_SUPPORT)) {
@@ -1296,7 +1279,7 @@ static int scmi_wait_for_reply(struct device *dev, const struct scmi_desc *desc,
12961279
"timed out in resp(caller: %pS) - polling\n",
12971280
(void *)_RET_IP_);
12981281
ret = -ETIMEDOUT;
1299-
scmi_inc_count(info->dbg->counters, XFERS_RESPONSE_POLLED_TIMEOUT);
1282+
scmi_inc_count(info->dbg, XFERS_RESPONSE_POLLED_TIMEOUT);
13001283
}
13011284
}
13021285

@@ -1321,7 +1304,7 @@ static int scmi_wait_for_reply(struct device *dev, const struct scmi_desc *desc,
13211304
"RESP" : "resp",
13221305
xfer->hdr.seq, xfer->hdr.status,
13231306
xfer->rx.buf, xfer->rx.len);
1324-
scmi_inc_count(info->dbg->counters, RESPONSE_POLLED_OK);
1307+
scmi_inc_count(info->dbg, RESPONSE_POLLED_OK);
13251308

13261309
if (IS_ENABLED(CONFIG_ARM_SCMI_RAW_MODE_SUPPORT)) {
13271310
scmi_raw_message_report(info->raw, xfer,
@@ -1336,7 +1319,7 @@ static int scmi_wait_for_reply(struct device *dev, const struct scmi_desc *desc,
13361319
dev_err(dev, "timed out in resp(caller: %pS)\n",
13371320
(void *)_RET_IP_);
13381321
ret = -ETIMEDOUT;
1339-
scmi_inc_count(info->dbg->counters, XFERS_RESPONSE_TIMEOUT);
1322+
scmi_inc_count(info->dbg, XFERS_RESPONSE_TIMEOUT);
13401323
}
13411324
}
13421325

@@ -1420,13 +1403,13 @@ static int do_xfer(const struct scmi_protocol_handle *ph,
14201403
!is_transport_polling_capable(info->desc)) {
14211404
dev_warn_once(dev,
14221405
"Polling mode is not supported by transport.\n");
1423-
scmi_inc_count(info->dbg->counters, SENT_FAIL_POLLING_UNSUPPORTED);
1406+
scmi_inc_count(info->dbg, SENT_FAIL_POLLING_UNSUPPORTED);
14241407
return -EINVAL;
14251408
}
14261409

14271410
cinfo = idr_find(&info->tx_idr, pi->proto->id);
14281411
if (unlikely(!cinfo)) {
1429-
scmi_inc_count(info->dbg->counters, SENT_FAIL_CHANNEL_NOT_FOUND);
1412+
scmi_inc_count(info->dbg, SENT_FAIL_CHANNEL_NOT_FOUND);
14301413
return -EINVAL;
14311414
}
14321415
/* True ONLY if also supported by transport. */
@@ -1461,19 +1444,19 @@ static int do_xfer(const struct scmi_protocol_handle *ph,
14611444
ret = info->desc->ops->send_message(cinfo, xfer);
14621445
if (ret < 0) {
14631446
dev_dbg(dev, "Failed to send message %d\n", ret);
1464-
scmi_inc_count(info->dbg->counters, SENT_FAIL);
1447+
scmi_inc_count(info->dbg, SENT_FAIL);
14651448
return ret;
14661449
}
14671450

14681451
trace_scmi_msg_dump(info->id, cinfo->id, xfer->hdr.protocol_id,
14691452
xfer->hdr.id, "CMND", xfer->hdr.seq,
14701453
xfer->hdr.status, xfer->tx.buf, xfer->tx.len);
1471-
scmi_inc_count(info->dbg->counters, SENT_OK);
1454+
scmi_inc_count(info->dbg, SENT_OK);
14721455

14731456
ret = scmi_wait_for_message_response(cinfo, xfer);
14741457
if (!ret && xfer->hdr.status) {
14751458
ret = scmi_to_linux_errno(xfer->hdr.status);
1476-
scmi_inc_count(info->dbg->counters, ERR_PROTOCOL);
1459+
scmi_inc_count(info->dbg, ERR_PROTOCOL);
14771460
}
14781461

14791462
if (info->desc->ops->mark_txdone)
@@ -3044,9 +3027,6 @@ static int scmi_debugfs_raw_mode_setup(struct scmi_info *info)
30443027
u8 channels[SCMI_MAX_CHANNELS] = {};
30453028
DECLARE_BITMAP(protos, SCMI_MAX_CHANNELS) = {};
30463029

3047-
if (!info->dbg)
3048-
return -EINVAL;
3049-
30503030
/* Enumerate all channels to collect their ids */
30513031
idr_for_each_entry(&info->tx_idr, cinfo, id) {
30523032
/*
@@ -3218,7 +3198,7 @@ static int scmi_probe(struct platform_device *pdev)
32183198
if (!info->dbg)
32193199
dev_warn(dev, "Failed to setup SCMI debugfs.\n");
32203200

3221-
if (IS_ENABLED(CONFIG_ARM_SCMI_RAW_MODE_SUPPORT)) {
3201+
if (info->dbg && IS_ENABLED(CONFIG_ARM_SCMI_RAW_MODE_SUPPORT)) {
32223202
ret = scmi_debugfs_raw_mode_setup(info);
32233203
if (!coex) {
32243204
if (ret)
@@ -3423,6 +3403,9 @@ int scmi_inflight_count(const struct scmi_handle *handle)
34233403
if (IS_ENABLED(CONFIG_ARM_SCMI_DEBUG_COUNTERS)) {
34243404
struct scmi_info *info = handle_to_scmi_info(handle);
34253405

3406+
if (!info->dbg)
3407+
return 0;
3408+
34263409
return atomic_read(&info->dbg->counters[XFERS_INFLIGHT]);
34273410
} else {
34283411
return 0;

0 commit comments

Comments
 (0)