From: Jinjian Song <jinjian.song@fibocom.com>
To: ryazanov.s.a@gmail.com, Jinjian Song <jinjian.song@fibocom.com>,
chandrashekar.devegowda@intel.com,
chiranjeevi.rapolu@linux.intel.com, haijun.liu@mediatek.com,
ricardo.martinez@linux.intel.com, loic.poulain@linaro.org,
johannes@sipsolutions.net, davem@davemloft.net,
edumazet@google.com, kuba@kernel.org, pabeni@redhat.com
Cc: andrew+netdev@lunn.ch, angelogioacchino.delregno@collabora.com,
corbet@lwn.net, danielwinkler@google.com, helgaas@kernel.org,
horms@kernel.org, korneld@google.com,
linux-arm-kernel@lists.infradead.org, linux-doc@vger.kernel.org,
linux-kernel@vger.kernel.org, linux-mediatek@lists.infradead.org,
matthias.bgg@gmail.com, netdev@vger.kernel.org
Subject: Re: [net v2] net: wwan: t7xx: Fix FSM command timeout issue
Date: Fri, 20 Dec 2024 16:50:27 +0800 [thread overview]
Message-ID: <20241220085027.7692-1-jinjian.song@fibocom.com> (raw)
In-Reply-To: <da90f64c-260a-4329-87bf-1f9ff20a5951@gmail.com>
From: Sergey Ryazanov <ryazanov.s.a@gmail.com>
>> Fixes: d785ed945de6 ("net: wwan: t7xx: PCIe reset rescan")
>
>The completion waiting was introduced in a different commit. I believe,
>the fix tag should be 13e920d93e37 ("net: wwan: t7xx: Add core components")
>
Got it.
[...]
>> if (cmd->flag & FSM_CMD_FLAG_WAIT_FOR_COMPLETION) {
>> *cmd->ret = result;
>
>The memory for the result storage is allocated on the stack as well. And
>writing it unconditionally can cause unexpected consequences.
>
Got it.
[...]
>> wait_ret = wait_for_completion_timeout(&done,
>> msecs_to_jiffies(FSM_CMD_TIMEOUT_MS));
>> - if (!wait_ret)
>> + if (!wait_ret) {
>> + cmd->done = NULL;
>
>We cannot access the command memory here, since fsm_finish_command()
>could release it already.
>
Got it.
[...]
>Here we have an ownership transfer problem and a driver author has tried
>to solve it, but as noticed, we are still experiencing issues in case of
>timeout.
>
>The command completion routine should not release the command memory
>unconditionally. Looks like the references counting approach should help
>us here. E.g.
>1. grab a reference before we put a command into the queue
>1.1. grab an extra reference if we are going to wait the completion
>2. release the reference as soon as we are done with the command execution
>3. in case of completion waiting release the reference as soon as we are
>done with waiting due to completion or timeout
>
>Could you try the following patch? Please note, besides the reference
>counter introduction it also moves completion and result storage inside
>the command structure as advised by the completion documentation.
>
Hi Sergey,
Yes, the patch works fine, needs some minor modifications, could we
feedback to the driver author to merge these changes.
diff --git a/drivers/net/wwan/t7xx/t7xx_state_monitor.c b/drivers/net/wwan/t7xx/t7xx_state_monitor.c
index 3931c7a13f5a..265c40b29f56 100644
--- a/drivers/net/wwan/t7xx/t7xx_state_monitor.c
+++ b/drivers/net/wwan/t7xx/t7xx_state_monitor.c
@@ -104,14 +104,20 @@ void t7xx_fsm_broadcast_state(struct t7xx_fsm_ctl *ctl, enum md_state state)
fsm_state_notify(ctl->md, state);
}
+static void fsm_release_command(struct kref *ref)
+{
+ struct t7xx_fsm_command *cmd = container_of(ref, typeof(*cmd), refcnt);
+ kfree(cmd);
+}
+
static void fsm_finish_command(struct t7xx_fsm_ctl *ctl, struct t7xx_fsm_command *cmd, int result)
{
if (cmd->flag & FSM_CMD_FLAG_WAIT_FOR_COMPLETION) {
- *cmd->ret = result;
- complete_all(cmd->done);
+ cmd->result = result;
+ complete_all(&cmd->done);
}
- kfree(cmd);
+ kref_put(&cmd->refcnt, fsm_release_command);
}
static void fsm_del_kf_event(struct t7xx_fsm_event *event)
@@ -475,7 +481,6 @@ static int fsm_main_thread(void *data)
int t7xx_fsm_append_cmd(struct t7xx_fsm_ctl *ctl, enum t7xx_fsm_cmd_state cmd_id, unsigned int flag)
{
- DECLARE_COMPLETION_ONSTACK(done);
struct t7xx_fsm_command *cmd;
unsigned long flags;
int ret;
@@ -487,11 +492,13 @@ int t7xx_fsm_append_cmd(struct t7xx_fsm_ctl *ctl, enum t7xx_fsm_cmd_state cmd_id
INIT_LIST_HEAD(&cmd->entry);
cmd->cmd_id = cmd_id;
cmd->flag = flag;
+ kref_init(&cmd->refcnt);
if (flag & FSM_CMD_FLAG_WAIT_FOR_COMPLETION) {
- cmd->done = &done;
- cmd->ret = &ret;
+ init_completion(&cmd->done);
+ kref_get(&cmd->refcnt);
}
+ kref_get(&cmd->refcnt);
spin_lock_irqsave(&ctl->command_lock, flags);
list_add_tail(&cmd->entry, &ctl->command_queue);
spin_unlock_irqrestore(&ctl->command_lock, flags);
@@ -501,11 +508,11 @@ int t7xx_fsm_append_cmd(struct t7xx_fsm_ctl *ctl, enum t7xx_fsm_cmd_state cmd_id
if (flag & FSM_CMD_FLAG_WAIT_FOR_COMPLETION) {
unsigned long wait_ret;
- wait_ret = wait_for_completion_timeout(&done,
+ wait_ret = wait_for_completion_timeout(&cmd->done,
msecs_to_jiffies(FSM_CMD_TIMEOUT_MS));
- if (!wait_ret)
- return -ETIMEDOUT;
+ ret = wait_ret ? cmd->result : -ETIMEDOUT;
+ kref_put(&cmd->refcnt, fsm_release_command);
return ret;
}
diff --git a/drivers/net/wwan/t7xx/t7xx_state_monitor.h b/drivers/net/wwan/t7xx/t7xx_state_monitor.h
index 7b0a9baf488c..6e0601bb752e 100644
--- a/drivers/net/wwan/t7xx/t7xx_state_monitor.h
+++ b/drivers/net/wwan/t7xx/t7xx_state_monitor.h
@@ -110,8 +110,9 @@ struct t7xx_fsm_command {
struct list_head entry;
enum t7xx_fsm_cmd_state cmd_id;
unsigned int flag;
- struct completion *done;
- int *ret;
+ struct completion done;
+ int result;
+ struct kref refcnt;
};
struct t7xx_fsm_notifier {
Thanks.
Jinjian,
Best Regards.
next prev parent reply other threads:[~2024-12-20 8:51 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-12-13 6:47 [net v2] net: wwan: t7xx: Fix FSM command timeout issue Jinjian Song
2024-12-15 2:17 ` Sergey Ryazanov
2024-12-16 13:53 ` Jinjian Song
2024-12-20 8:50 ` Jinjian Song [this message]
2024-12-22 21:04 ` Sergey Ryazanov
2024-12-23 2:24 ` Jinjian Song
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20241220085027.7692-1-jinjian.song@fibocom.com \
--to=jinjian.song@fibocom.com \
--cc=andrew+netdev@lunn.ch \
--cc=angelogioacchino.delregno@collabora.com \
--cc=chandrashekar.devegowda@intel.com \
--cc=chiranjeevi.rapolu@linux.intel.com \
--cc=corbet@lwn.net \
--cc=danielwinkler@google.com \
--cc=davem@davemloft.net \
--cc=edumazet@google.com \
--cc=haijun.liu@mediatek.com \
--cc=helgaas@kernel.org \
--cc=horms@kernel.org \
--cc=johannes@sipsolutions.net \
--cc=korneld@google.com \
--cc=kuba@kernel.org \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=linux-doc@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-mediatek@lists.infradead.org \
--cc=loic.poulain@linaro.org \
--cc=matthias.bgg@gmail.com \
--cc=netdev@vger.kernel.org \
--cc=pabeni@redhat.com \
--cc=ricardo.martinez@linux.intel.com \
--cc=ryazanov.s.a@gmail.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox