mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: "Wu. JackBB (GSM)" <JackBB_Wu@compal.com>
To: "netdev-bot+sashiko@kernel.org" <netdev-bot+sashiko@kernel.org>
Cc: "loic.poulain@oss.qualcomm.com" <loic.poulain@oss.qualcomm.com>,
	"ryazanov.s.a@gmail.com" <ryazanov.s.a@gmail.com>,
	"johannes@sipsolutions.net" <johannes@sipsolutions.net>,
	"andrew+netdev@lunn.ch" <andrew+netdev@lunn.ch>,
	"davem@davemloft.net" <davem@davemloft.net>,
	"edumazet@google.com" <edumazet@google.com>,
	"kuba@kernel.org" <kuba@kernel.org>,
	"pabeni@redhat.com" <pabeni@redhat.com>,
	"wen-zhi.huang@mediatek.com" <wen-zhi.huang@mediatek.com>,
	"shi-wei.yeh@mediatek.com" <shi-wei.yeh@mediatek.com>,
	"Minano.tseng@mediatek.com" <Minano.tseng@mediatek.com>,
	"matthias.bgg@gmail.com" <matthias.bgg@gmail.com>,
	"angelogioacchino.delregno@collabora.com"
	<angelogioacchino.delregno@collabora.com>,
	"horms@kernel.org" <horms@kernel.org>,
	"corbet@lwn.net" <corbet@lwn.net>,
	"skhan@linuxfoundation.org" <skhan@linuxfoundation.org>,
	"Yu. Robert (GSM)" <robert_yu@compal.com>,
	"Chang. Jeff (GSM)" <Jeff_Chang@compal.com>,
	"linux-kernel@vger.kernel.org" <linux-kernel@vger.kernel.org>,
	"netdev@vger.kernel.org" <netdev@vger.kernel.org>,
	"linux-arm-kernel@lists.infradead.org"
	<linux-arm-kernel@lists.infradead.org>,
	"linux-mediatek@lists.infradead.org"
	<linux-mediatek@lists.infradead.org>,
	"linux-doc@vger.kernel.org" <linux-doc@vger.kernel.org>
Subject: Re: [PATCH v11 5/6] net: wwan: t9xx: Add FSM thread
Date: Wed, 11 Nov 2026 08:57:43 +0000	[thread overview]
Message-ID: <93b0facd23af4b0d9ceb0696bf97789a@compal.com> (raw)
In-Reply-To: <179430863746.994134.15827653788526776199@kernel.org>

Thanks for the review.

> Should this case also check the host's configured type?
>
> Every host query entry is version 0. The entries the host never configured
> are zero, because the fsm comes from devm_kzalloc(). So the version test is
> always true. Any feature the device marks BACKWARD_COMPAT gets promoted to
> RTFT_TYPE_MUST_SUPPORT, even when the host set it to NOT_EXIST or
> NOT_SUPPORT. The MUST_SUPPORT case returns -EPROTO for that host config,
> and the OPTIONAL case downgrades it.
>
> In mtk_fsm_hs_info_init_by_hsid(), the MD handshake leaves
> query_ft_set[QUERY_RTFT_ID_SAP_PORT_ENUM] as NOT_EXIST. The SAP handshake
> leaves query_ft_set[QUERY_RTFT_ID_MD_PORT_ENUM] as NOT_EXIST. Both slots
> have a handler in query_rtft_action[]. So mtk_fsm_parse_hs2_msg() would
> run mtk_port_status_update() on port data the host never asked for:
>
>     if (cur_ft_spt == RTFT_TYPE_MUST_SUPPORT && query_rtft_action[ft_id]) {
>         if (!data_len) {
>             ...
>             ret = -EPROTO;
>             break;
>         }
>
> If that entry has data_len == 0, the whole HS2 fails with -EPROTO. No HS3
> is sent and the FSM never reaches READY.
>
> The comment says the host's type is ignored because it "can be the older
> of the two". That is about versions. Does it really cover a host that
> never queried the feature, or one that explicitly refused it?

No functional change; v12 rewrites the comment to state what
BACKWARD_COMPAT means rather than talking about versions.

This was discussed in the v10 thread: BACKWARD_COMPAT is the device's
promise that a host which does not know the feature, or knows an older
version of it, can still use it.  The host's NOT_EXIST slot means
exactly "this host does not know the feature", so the device's
declaration decides by design.  The action it enables validates its own
input.  A device that declares a feature it insists on and then sends no
data for it is breaking the protocol, and failing that handshake with
-EPROTO is the intended result; the same happens for PORT_ENUM that the
host did ask for.

> This skips the feature_query header without checking head_pattern or
> tail_pattern. It then runs query_rtft_action[] on the entries, and
> mtk_port_status_update() writes port->enable. The FEATURE_QUERY_PATTERN
> check on the same skb only runs later:
>
> mtk_fsm_startup_act()
>   mtk_fsm_parse_hs2_msg()          <- actions applied
>   mtk_fsm_send_hs3_msg()
>     mtk_fsm_append_rtft_entries()  <- -EPROTO on bad patterns
>
> So an HS2 with a bad header but valid entries updates the port table
> first, and only then is rejected. mtk_fsm_startup_act() goes to hs_err
> and re-arms the channel. The port enable state from the rejected message
> stays in place, and any port the retried HS2 does not list keeps that
> value.
>
> Could the pattern check move into mtk_fsm_parse_hs2_msg(), before any
> action runs?

No change.  A rejected HS2 never gets an HS3 and the FSM does not reach
READY, and port->enable is only consumed at READY. A port left enabled
by a rejected HS2 is also not specific to the pattern check: a later
entry, or the HS3 write, can fail after the action ran in the same way.
That residue is answered under patch 6, where port->enable is consumed.

> Once READY is refused here, how does the FSM recover?
>
> This returns directly and does not go through hs_err, so no handshake
> channel is re-armed. Both channels were masked by their HS1 handlers. No
> further STARTUP can arrive, and the FSM stays in BOOTUP until the driver
> is rebound.
>
> One way to get here is a DEV_CFG_MD_ONLY device. mtk_fsm_idle_evt_handler()
> sets hs_done_flag to the MD bits only, but it still unmasks both channels:
>
>     for (hs_id = 0; hs_id < HS_ID_MAX; hs_id++)
>         mtk_fsm_unmask_ext_evt(fsm, fsm->hs_info[hs_id].mhccif_ch);
>
> If a SAP HS1 arrives and mtk_cldma_dev_init(CLDMA0) fails,
> hif_err[MTK_FSM_HIF_USER_CLDMA0] stays set. When the MD handshake
> completes, READY is refused for good, even though SAP is not required in
> that configuration. Can firmware send a SAP HS1 in MD-only mode?

No functional change; the commit message will describe how a refused
READY recovers.

A CLDMA init failure leaves that side's control port unable to open, so
that side's own HS1 fails through hs_err, which re-arms its channel; the
next HS1 re-runs the init and overwrites the slot.  In MD-only mode both
channels stay armed on purpose: masking SAP on the host side would leave
firmware that does send a SAP HS1 in that mode without a reply.

> Separately, the comment above mtk_fsm_hif_err_record() says:
>
>     so a retried init that succeeds clears the failure it recorded before.
>
> The MTK_FSM_HIF_USER_CTRL slot is only written by
> mtk_ctrl_trans_fsm_state_handler(), on the transition to FSM_STATE_ON.
> mtk_fsm_dev_add_act() allows that transition only once, from
> FSM_STATE_INVALID. Is there any retry path for that slot?

No functional change; v12 rewords that sentence to say that a retried
CLDMA init clears its slot, while a CTRL failure is final for the bind.
There is no retry for the CTRL slot by design: if the transport plane
could not be created, no handshake can complete anyway, and refusing
READY is the intended outcome.

> The commit message says "the FSM advances to READY only after both
> complete". It does not mention the MD-only case or the hif_err gate.

Will fix the commit message in v12: an MD-only device needs only the MD
handshake for READY, and READY is refused when a transport init that the
handshake triggered has failed.

> This isn't a bug, but this thread is not parked. It was only created by
> kthread_create() and never woken, and nothing in mtk_fsm.c calls
> kthread_park().
>
> The comment in mtk_pci_dev_exit() has the same problem:
>
>     /* Close the event gate and park the FSM thread before the transport
>      * plane it drives is torn down.
>      */
>     mtk_fsm_stop(mdev);
>
> mtk_fsm_stop() clears fsm->fsm_handler and calls kthread_stop() and
> put_task_struct(). The thread is terminated, not parked.

Will fix in v12: both comments will say the thread is stopped.

> The is_stopping test only runs after the start address has been read.
> If that address was zero, mtk_cldma_hw_recovery() has also already
> re-armed the whole instance by this point. Shouldn't a queue that
> err_work owns be turned away before any of that?
>
> Take a queue whose stop timed out in mtk_cldma_err_tx_one(). It keeps
> is_stopping set and tx_started true. Later, a stop timeout in another
> queue's mtk_cldma_txq_free() or mtk_cldma_rxq_free() resets the
> instance. mtk_cldma_rearm_queues() then skips this queue on purpose and
> leaves its start address at 0. The next mtk_cldma_tx() on it goes:
>
> mtk_cldma_tx()
>   mtk_cldma_start_xfer()
>     mtk_cldma_get_tx_start_addr()  <- reads 0
>     mtk_cldma_hw_recovery()
>       mtk_cldma_rearm_queues()     <- instance re-armed again
>     returns -EIO                   <- tx_started is still true
>   mtk_cldma_stop_queue()
>   mtk_cldma_txq_flush(..., -EIO)
>
> A U64_MAX read on a dead link takes the same early -EIO exit. The same
> thing can also happen while mtk_cldma_err_tx_one() is still polling its
> stop, if the device lost its queue state along with the error.
>
> The error is -EIO, not -EPIPE, so the new -EPIPE check in
> mtk_cldma_tx() does not catch it. mtk_cldma_tx() then stops the queue,
> clears tx_started and flushes the ring itself. Meanwhile
> mtk_cldma_err_tx_one() is either doing the same thing or has decided
> to keep those requests. The flushed TRBs complete with -EIO, not the
> -EPIPE that recovery promises. Nothing clears is_stopping afterwards,
> so the queue keeps refusing new submissions.

Will fix in v12: mtk_cldma_start_xfer() tests is_stopping under
ring_lock before reading the start address, so a queue that err_work
owns returns -EPIPE without triggering recovery.  The check before the
kick stays, since that is the one ordered against err_work.

> There is also a gap in the other direction. If the stop inside
> mtk_cldma_tx() times out, it keeps the requests just as
> mtk_cldma_err_tx_one() does, but it never sets is_stopping. So
> mtk_cldma_submit_tx() keeps publishing HWO descriptors into a ring the
> device may still be walking. That is exactly what is_stopping was
> added to prevent.
>
> Would it work to test is_stopping under ring_lock before the start
> address read and the recovery? The stop-timeout path in mtk_cldma_tx()
> could then set is_stopping the same way err_work does.

No functional change; v12 rewords the comment on that path to say the
queue is left running with its requests.

is_stopping guards the window between a stop and the flush that unmaps
the ring.  When the stop in mtk_cldma_tx() times out it neither flushes
nor unmaps, and tx_started stays set, so the queue simply stays in
service; descriptors published afterwards are ordinary producer activity
on mapped buffers.  Setting is_stopping there would turn a possibly
transient start failure into a channel that refuses everything until it
is closed, since nothing would clear the flag.

> What clears is_stopping after this return? The only place that clears it
> is the end of a later mtk_cldma_err_tx_one() pass whose stop succeeds, and
> that pass needs a new QUEUE_ERROR.
>
> Another queue's stop can later time out in mtk_cldma_txq_free() or
> mtk_cldma_rxq_free(). The instance is then reset with
> mtk_cldma_drv_reset(), so the engine is idle. But mtk_cldma_rearm_queues()
> skips this queue:
>
>     if (txq->is_stopping) {
>         /* Being stopped: restarting it would let the
>          * device walk buffers the stopper is unmapping.
>          */
>     } else if (...
>
> It programs no start address and issues no START. It does not flush the
> kept requests, and it does not clear the flag. QUEUE_ERROR is unmasked,
> but a reset queue that is not started will not raise one, so err_work
> never runs for it again.
>
> After that, mtk_cldma_submit_tx() keeps returning -EPIPE. The kept TRBs
> stay incomplete until the channel is closed via mtk_cldma_txq_free(),
> even though the reset made it safe to flush them. Is that intended? The
> comment's "until an instance re-arm" suggests the re-arm should recover
> this queue.

Will fix the comment in v12 so that "until an instance re-arm" applies
only to the QUEUE_ERROR mask, which the re-arm does lift; the behaviour
stays.  The re-arm cannot tell a stop that failed from an err_work pass
that is still stopping and flushing the same queue, and clearing the
flag there would let start_xfer() kick the queue while that pass unmaps
it.  The kept requests are completed or leaked by txq_free() at close,
as the commit message states.

--
Jack

  reply	other threads:[~2026-11-11  8:57 UTC|newest]

Thread overview: 17+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-11-05  7:56 [PATCH v11 0/6] net: wwan: t9xx: Add MediaTek T9XX WWAN driver Jack Wu via B4 Relay
2026-11-05  7:56 ` [PATCH v11 1/6] net: wwan: t9xx: Add PCIe core Jack Wu via B4 Relay
2026-11-10 11:03   ` netdev-bot+sashiko
2026-11-11  8:54     ` Wu. JackBB (GSM)
2026-11-05  7:56 ` [PATCH v11 2/6] net: wwan: t9xx: Add control plane transaction layer framework Jack Wu via B4 Relay
2026-11-05  7:56 ` [PATCH v11 3/6] net: wwan: t9xx: Add control DMA interface Jack Wu via B4 Relay
2026-11-10 11:03   ` netdev-bot+sashiko
2026-11-11  8:56     ` Wu. JackBB (GSM)
2026-11-05  7:56 ` [PATCH v11 4/6] net: wwan: t9xx: Add control port Jack Wu via B4 Relay
2026-11-10 11:03   ` netdev-bot+sashiko
2026-11-11  8:57     ` Wu. JackBB (GSM)
2026-11-05  7:56 ` [PATCH v11 5/6] net: wwan: t9xx: Add FSM thread Jack Wu via B4 Relay
2026-11-10 11:03   ` netdev-bot+sashiko
2026-11-11  8:57     ` Wu. JackBB (GSM) [this message]
2026-11-05  7:56 ` [PATCH v11 6/6] net: wwan: t9xx: Add AT & MBIM WWAN ports Jack Wu via B4 Relay
2026-11-10 11:03   ` netdev-bot+sashiko
2026-11-11  8:58     ` Wu. JackBB (GSM)

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=93b0facd23af4b0d9ceb0696bf97789a@compal.com \
    --to=jackbb_wu@compal.com \
    --cc=Jeff_Chang@compal.com \
    --cc=Minano.tseng@mediatek.com \
    --cc=andrew+netdev@lunn.ch \
    --cc=angelogioacchino.delregno@collabora.com \
    --cc=corbet@lwn.net \
    --cc=davem@davemloft.net \
    --cc=edumazet@google.com \
    --cc=horms@kernel.org \
    --cc=johannes@sipsolutions.net \
    --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@oss.qualcomm.com \
    --cc=matthias.bgg@gmail.com \
    --cc=netdev-bot+sashiko@kernel.org \
    --cc=netdev@vger.kernel.org \
    --cc=pabeni@redhat.com \
    --cc=robert_yu@compal.com \
    --cc=ryazanov.s.a@gmail.com \
    --cc=shi-wei.yeh@mediatek.com \
    --cc=skhan@linuxfoundation.org \
    --cc=wen-zhi.huang@mediatek.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

all inboxes | Powered by JetHome®