All of lore.kernel.org
 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: 25+ 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 ` Jack Wu
2026-11-05  7:56 ` [PATCH v11 1/6] net: wwan: t9xx: Add PCIe core Jack Wu via B4 Relay
2026-11-05  7:56   ` Jack Wu
2026-11-10 11:03   ` netdev-bot+sashiko
2026-11-11  8:54     ` Wu. JackBB (GSM)
2026-11-12 22:07   ` Brian Norris
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   ` Jack Wu
2026-11-05  7:56 ` [PATCH v11 3/6] net: wwan: t9xx: Add control DMA interface Jack Wu via B4 Relay
2026-11-05  7:56   ` Jack Wu
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-05  7:56   ` Jack Wu
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-05  7:56   ` Jack Wu
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-05  7:56   ` Jack Wu
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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.