Skip to content

Commit 0cd3bde

Browse files
Jinjian-Songgregkh
authored andcommitted
net: wwan: t7xx: Fix FSM command timeout issue
[ Upstream commit 4f619d5 ] When driver processes the internal state change command, it use an asynchronous thread to process the command operation. If the main thread detects that the task has timed out, the asynchronous thread will panic when executing the completion notification because the main thread completion object has been released. BUG: unable to handle page fault for address: fffffffffffffff8 PGD 1f283a067 P4D 1f283a067 PUD 1f283c067 PMD 0 Oops: 0000 [#1] PREEMPT SMP NOPTI RIP: 0010:complete_all+0x3e/0xa0 [...] Call Trace: <TASK> ? __die_body+0x68/0xb0 ? page_fault_oops+0x379/0x3e0 ? exc_page_fault+0x69/0xa0 ? asm_exc_page_fault+0x22/0x30 ? complete_all+0x3e/0xa0 fsm_main_thread+0xa3/0x9c0 [mtk_t7xx (HASH:1400 5)] ? __pfx_autoremove_wake_function+0x10/0x10 kthread+0xd8/0x110 ? __pfx_fsm_main_thread+0x10/0x10 [mtk_t7xx (HASH:1400 5)] ? __pfx_kthread+0x10/0x10 ret_from_fork+0x38/0x50 ? __pfx_kthread+0x10/0x10 ret_from_fork_asm+0x1b/0x30 </TASK> [...] CR2: fffffffffffffff8 ---[ end trace 0000000000000000 ]--- Use the reference counter to ensure safe release as Sergey suggests: https://lore.kernel.org/all/[email protected]/ Fixes: 13e920d ("net: wwan: t7xx: Add core components") Signed-off-by: Jinjian Song <[email protected]> Acked-by: Sergey Ryazanov <[email protected]> Link: https://patch.msgid.link/[email protected] Signed-off-by: Jakub Kicinski <[email protected]> Signed-off-by: Sasha Levin <[email protected]>
1 parent 313474b commit 0cd3bde

File tree

2 files changed

+20
-11
lines changed

2 files changed

+20
-11
lines changed

drivers/net/wwan/t7xx/t7xx_state_monitor.c

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -97,14 +97,21 @@ void t7xx_fsm_broadcast_state(struct t7xx_fsm_ctl *ctl, enum md_state state)
9797
fsm_state_notify(ctl->md, state);
9898
}
9999

100+
static void fsm_release_command(struct kref *ref)
101+
{
102+
struct t7xx_fsm_command *cmd = container_of(ref, typeof(*cmd), refcnt);
103+
104+
kfree(cmd);
105+
}
106+
100107
static void fsm_finish_command(struct t7xx_fsm_ctl *ctl, struct t7xx_fsm_command *cmd, int result)
101108
{
102109
if (cmd->flag & FSM_CMD_FLAG_WAIT_FOR_COMPLETION) {
103-
*cmd->ret = result;
104-
complete_all(cmd->done);
110+
cmd->result = result;
111+
complete_all(&cmd->done);
105112
}
106113

107-
kfree(cmd);
114+
kref_put(&cmd->refcnt, fsm_release_command);
108115
}
109116

110117
static void fsm_del_kf_event(struct t7xx_fsm_event *event)
@@ -396,7 +403,6 @@ static int fsm_main_thread(void *data)
396403

397404
int t7xx_fsm_append_cmd(struct t7xx_fsm_ctl *ctl, enum t7xx_fsm_cmd_state cmd_id, unsigned int flag)
398405
{
399-
DECLARE_COMPLETION_ONSTACK(done);
400406
struct t7xx_fsm_command *cmd;
401407
unsigned long flags;
402408
int ret;
@@ -408,11 +414,13 @@ int t7xx_fsm_append_cmd(struct t7xx_fsm_ctl *ctl, enum t7xx_fsm_cmd_state cmd_id
408414
INIT_LIST_HEAD(&cmd->entry);
409415
cmd->cmd_id = cmd_id;
410416
cmd->flag = flag;
417+
kref_init(&cmd->refcnt);
411418
if (flag & FSM_CMD_FLAG_WAIT_FOR_COMPLETION) {
412-
cmd->done = &done;
413-
cmd->ret = &ret;
419+
init_completion(&cmd->done);
420+
kref_get(&cmd->refcnt);
414421
}
415422

423+
kref_get(&cmd->refcnt);
416424
spin_lock_irqsave(&ctl->command_lock, flags);
417425
list_add_tail(&cmd->entry, &ctl->command_queue);
418426
spin_unlock_irqrestore(&ctl->command_lock, flags);
@@ -422,11 +430,11 @@ int t7xx_fsm_append_cmd(struct t7xx_fsm_ctl *ctl, enum t7xx_fsm_cmd_state cmd_id
422430
if (flag & FSM_CMD_FLAG_WAIT_FOR_COMPLETION) {
423431
unsigned long wait_ret;
424432

425-
wait_ret = wait_for_completion_timeout(&done,
433+
wait_ret = wait_for_completion_timeout(&cmd->done,
426434
msecs_to_jiffies(FSM_CMD_TIMEOUT_MS));
427-
if (!wait_ret)
428-
return -ETIMEDOUT;
429435

436+
ret = wait_ret ? cmd->result : -ETIMEDOUT;
437+
kref_put(&cmd->refcnt, fsm_release_command);
430438
return ret;
431439
}
432440

drivers/net/wwan/t7xx/t7xx_state_monitor.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -109,8 +109,9 @@ struct t7xx_fsm_command {
109109
struct list_head entry;
110110
enum t7xx_fsm_cmd_state cmd_id;
111111
unsigned int flag;
112-
struct completion *done;
113-
int *ret;
112+
struct completion done;
113+
int result;
114+
struct kref refcnt;
114115
};
115116

116117
struct t7xx_fsm_notifier {

0 commit comments

Comments
 (0)