Linux wireless drivers development
 help / color / mirror / Atom feed
* [PATCH] wifi: ath11k: run ahb shutdown() teardown only on WCN6750
@ 2026-08-07  9:48 André Valentin
  2026-08-07 15:34 ` Jeff Johnson
  2026-08-08 21:35 ` [PATCH v2] " André Valentin
  0 siblings, 2 replies; 6+ messages in thread
From: André Valentin @ 2026-08-07  9:48 UTC (permalink / raw)
  To: Jeff Johnson
  Cc: avalentin, linux-wireless, ath11k, Kalle Valo, stable,
	Manikanta Pubbisetty

The AHB shutdown() callback was introduced solely for WCN6750, which has
to stop DMA before the SMMU is torn down at system reboot/shutdown. It
was registered unconditionally in the shared ath11k_ahb_driver, so it also
runs on the IPQ AHB targets (IPQ8074/IPQ6018/IPQ5018), which never had a
shutdown() handler before and have no such SMMU requirement.

On IPQ6018 the shutdown teardown stops the WCSS Q6 remote processor
firmware. Stopping the Q6 firmware leaves shared WCSS state such that the
boot ROM (SBL1) hangs during DDR training on the following warm reset;
only a cold (power-on) reset recovers. A plain reboot therefore never
comes back and needs a physical power cycle.

This was pinned by bisecting the teardown at reboot: skipping
ath11k_qmi_firmware_stop() (i.e. not stopping the Q6) is what lets the
warm reset train DDR and boot normally, whereas none of the q6v5 power,
reset or clock steps reproduce it on their own.

Restrict the shutdown() teardown to WCN6750, restoring the pre-regression
behaviour for the IPQ AHB targets. On reboot/shutdown the whole SoC is
reset by the boot chain, which re-initializes the WCSS from scratch, so no
teardown is needed there. Module removal (rmmod / remove()) is unchanged.

Verified on a MikroTik Chateau 5G R17 ax (IPQ6018): before, a plain reboot
froze in SBL1 at "sbl1_ddr_set_params"; after, SBL1 reaches "SBL1, End",
trains DDR and boots the kernel across repeated reboots.

Fixes: ac41c2b642b1 ("wifi: ath11k: Register shutdown handler for WCN6750")
Cc: stable@vger.kernel.org
Cc: Manikanta Pubbisetty <quic_mpubbise@quicinc.com>
Signed-off-by: André Valentin <avalentin@marcant.net>
---
 drivers/net/wireless/ath/ath11k/ahb.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/drivers/net/wireless/ath/ath11k/ahb.c b/drivers/net/wireless/ath/ath11k/ahb.c
index 1e1dea4..749d8bf 100644
--- a/drivers/net/wireless/ath/ath11k/ahb.c
+++ b/drivers/net/wireless/ath/ath11k/ahb.c
@@ -1288,6 +1288,18 @@ static void ath11k_ahb_shutdown(struct platform_device *pdev)
 	 * remove() is invoked during rmmod & shutdown() during
 	 * system reboot/shutdown.
 	 */
+
+	/* The shutdown() callback was added for WCN6750, which has to stop DMA
+	 * before the SMMU is torn down. The other AHB targets (IPQ8074/IPQ6018/
+	 * IPQ5018) have no such requirement, and running the teardown here stops
+	 * the WCSS Q6 firmware, which leaves shared state that hangs the boot ROM
+	 * (SBL1) during DDR training on the following warm reset -- only a cold
+	 * (power-on) reset recovers. Skip it on those targets; the SoC reset
+	 * re-initializes the WCSS from scratch.
+	 */
+	if (ab->hw_rev != ATH11K_HW_WCN6750_HW10)
+		return;
+
 	ath11k_ahb_remove_prepare(ab);
 
 	if (!(test_bit(ATH11K_FLAG_REGISTERED, &ab->dev_flags)))

base-commit: f9a2394a23482bfd330911e9c8295b71724feacd
-- 
2.47.3


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* Re: [PATCH] wifi: ath11k: run ahb shutdown() teardown only on WCN6750
  2026-08-07  9:48 [PATCH] wifi: ath11k: run ahb shutdown() teardown only on WCN6750 André Valentin
@ 2026-08-07 15:34 ` Jeff Johnson
  2026-08-07 15:39   ` Jeff Johnson
  2026-08-08 21:35 ` [PATCH v2] " André Valentin
  1 sibling, 1 reply; 6+ messages in thread
From: Jeff Johnson @ 2026-08-07 15:34 UTC (permalink / raw)
  To: André Valentin, Jeff Johnson
  Cc: linux-wireless, ath11k, Kalle Valo, stable, Manikanta Pubbisetty

On 8/7/2026 2:48 AM, André Valentin wrote:
> The AHB shutdown() callback was introduced solely for WCN6750, which has
> to stop DMA before the SMMU is torn down at system reboot/shutdown. It
> was registered unconditionally in the shared ath11k_ahb_driver, so it also
> runs on the IPQ AHB targets (IPQ8074/IPQ6018/IPQ5018), which never had a
> shutdown() handler before and have no such SMMU requirement.
> 
> On IPQ6018 the shutdown teardown stops the WCSS Q6 remote processor
> firmware. Stopping the Q6 firmware leaves shared WCSS state such that the
> boot ROM (SBL1) hangs during DDR training on the following warm reset;
> only a cold (power-on) reset recovers. A plain reboot therefore never
> comes back and needs a physical power cycle.
> 
> This was pinned by bisecting the teardown at reboot: skipping
> ath11k_qmi_firmware_stop() (i.e. not stopping the Q6) is what lets the
> warm reset train DDR and boot normally, whereas none of the q6v5 power,
> reset or clock steps reproduce it on their own.
> 
> Restrict the shutdown() teardown to WCN6750, restoring the pre-regression
> behaviour for the IPQ AHB targets. On reboot/shutdown the whole SoC is
> reset by the boot chain, which re-initializes the WCSS from scratch, so no
> teardown is needed there. Module removal (rmmod / remove()) is unchanged.
> 
> Verified on a MikroTik Chateau 5G R17 ax (IPQ6018): before, a plain reboot
> froze in SBL1 at "sbl1_ddr_set_params"; after, SBL1 reaches "SBL1, End",
> trains DDR and boots the kernel across repeated reboots.
> 
> Fixes: ac41c2b642b1 ("wifi: ath11k: Register shutdown handler for WCN6750")
> Cc: stable@vger.kernel.org
> Cc: Manikanta Pubbisetty <quic_mpubbise@quicinc.com>
> Signed-off-by: André Valentin <avalentin@marcant.net>
> ---
>  drivers/net/wireless/ath/ath11k/ahb.c | 12 ++++++++++++
>  1 file changed, 12 insertions(+)
> 
> diff --git a/drivers/net/wireless/ath/ath11k/ahb.c b/drivers/net/wireless/ath/ath11k/ahb.c
> index 1e1dea4..749d8bf 100644
> --- a/drivers/net/wireless/ath/ath11k/ahb.c
> +++ b/drivers/net/wireless/ath/ath11k/ahb.c
> @@ -1288,6 +1288,18 @@ static void ath11k_ahb_shutdown(struct platform_device *pdev)
>  	 * remove() is invoked during rmmod & shutdown() during
>  	 * system reboot/shutdown.
>  	 */
> +
> +	/* The shutdown() callback was added for WCN6750, which has to stop DMA
> +	 * before the SMMU is torn down. The other AHB targets (IPQ8074/IPQ6018/
> +	 * IPQ5018) have no such requirement, and running the teardown here stops
> +	 * the WCSS Q6 firmware, which leaves shared state that hangs the boot ROM
> +	 * (SBL1) during DDR training on the following warm reset -- only a cold
> +	 * (power-on) reset recovers. Skip it on those targets; the SoC reset
> +	 * re-initializes the WCSS from scratch.
> +	 */
> +	if (ab->hw_rev != ATH11K_HW_WCN6750_HW10)
> +		return;

this is not the correct approach per the driver architecture.
all hardware-specific operations should be driven via the hw_params structure.

/jeff

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH] wifi: ath11k: run ahb shutdown() teardown only on WCN6750
  2026-08-07 15:34 ` Jeff Johnson
@ 2026-08-07 15:39   ` Jeff Johnson
  0 siblings, 0 replies; 6+ messages in thread
From: Jeff Johnson @ 2026-08-07 15:39 UTC (permalink / raw)
  To: André Valentin, Jeff Johnson
  Cc: linux-wireless, ath11k, Kalle Valo, stable, Manikanta Pubbisetty

On 8/7/2026 8:34 AM, Jeff Johnson wrote:
> On 8/7/2026 2:48 AM, André Valentin wrote:
>> The AHB shutdown() callback was introduced solely for WCN6750, which has
>> to stop DMA before the SMMU is torn down at system reboot/shutdown. It
>> was registered unconditionally in the shared ath11k_ahb_driver, so it also
>> runs on the IPQ AHB targets (IPQ8074/IPQ6018/IPQ5018), which never had a
>> shutdown() handler before and have no such SMMU requirement.
>>
>> On IPQ6018 the shutdown teardown stops the WCSS Q6 remote processor
>> firmware. Stopping the Q6 firmware leaves shared WCSS state such that the
>> boot ROM (SBL1) hangs during DDR training on the following warm reset;
>> only a cold (power-on) reset recovers. A plain reboot therefore never
>> comes back and needs a physical power cycle.
>>
>> This was pinned by bisecting the teardown at reboot: skipping
>> ath11k_qmi_firmware_stop() (i.e. not stopping the Q6) is what lets the
>> warm reset train DDR and boot normally, whereas none of the q6v5 power,
>> reset or clock steps reproduce it on their own.
>>
>> Restrict the shutdown() teardown to WCN6750, restoring the pre-regression
>> behaviour for the IPQ AHB targets. On reboot/shutdown the whole SoC is
>> reset by the boot chain, which re-initializes the WCSS from scratch, so no
>> teardown is needed there. Module removal (rmmod / remove()) is unchanged.
>>
>> Verified on a MikroTik Chateau 5G R17 ax (IPQ6018): before, a plain reboot
>> froze in SBL1 at "sbl1_ddr_set_params"; after, SBL1 reaches "SBL1, End",
>> trains DDR and boots the kernel across repeated reboots.
>>
>> Fixes: ac41c2b642b1 ("wifi: ath11k: Register shutdown handler for WCN6750")
>> Cc: stable@vger.kernel.org
>> Cc: Manikanta Pubbisetty <quic_mpubbise@quicinc.com>
>> Signed-off-by: André Valentin <avalentin@marcant.net>
>> ---
>>  drivers/net/wireless/ath/ath11k/ahb.c | 12 ++++++++++++
>>  1 file changed, 12 insertions(+)
>>
>> diff --git a/drivers/net/wireless/ath/ath11k/ahb.c b/drivers/net/wireless/ath/ath11k/ahb.c
>> index 1e1dea4..749d8bf 100644
>> --- a/drivers/net/wireless/ath/ath11k/ahb.c
>> +++ b/drivers/net/wireless/ath/ath11k/ahb.c
>> @@ -1288,6 +1288,18 @@ static void ath11k_ahb_shutdown(struct platform_device *pdev)
>>  	 * remove() is invoked during rmmod & shutdown() during
>>  	 * system reboot/shutdown.
>>  	 */
>> +
>> +	/* The shutdown() callback was added for WCN6750, which has to stop DMA
>> +	 * before the SMMU is torn down. The other AHB targets (IPQ8074/IPQ6018/
>> +	 * IPQ5018) have no such requirement, and running the teardown here stops
>> +	 * the WCSS Q6 firmware, which leaves shared state that hangs the boot ROM
>> +	 * (SBL1) during DDR training on the following warm reset -- only a cold
>> +	 * (power-on) reset recovers. Skip it on those targets; the SoC reset
>> +	 * re-initializes the WCSS from scratch.
>> +	 */
>> +	if (ab->hw_rev != ATH11K_HW_WCN6750_HW10)
>> +		return;
> 
> this is not the correct approach per the driver architecture.
> all hardware-specific operations should be driven via the hw_params structure.
> 
> /jeff

+ Mani's current e-mail address @oss.qualcomm.com

^ permalink raw reply	[flat|nested] 6+ messages in thread

* [PATCH v2] wifi: ath11k: run ahb shutdown() teardown only on WCN6750
  2026-08-07  9:48 [PATCH] wifi: ath11k: run ahb shutdown() teardown only on WCN6750 André Valentin
  2026-08-07 15:34 ` Jeff Johnson
@ 2026-08-08 21:35 ` André Valentin
  2026-08-10 19:05   ` Jeff Johnson
  2026-08-10 19:28   ` [PATCH v3] " André Valentin
  1 sibling, 2 replies; 6+ messages in thread
From: André Valentin @ 2026-08-08 21:35 UTC (permalink / raw)
  To: Jeff Johnson
  Cc: linux-wireless, ath11k, Kalle Valo, avalentin, stable,
	Manikanta Pubbisetty

The AHB shutdown() callback was added solely for WCN6750, which must stop
DMA before the SMMU is torn down at system reboot/shutdown. It was
registered unconditionally in the shared
ath11k_ahb_driver, so it also runs on the IPQ AHB targets (IPQ8074/
IPQ6018/IPQ5018), which never had a shutdown() handler before and have no
such SMMU requirement.

The commit message claimed the change "will not impact other AHB ath11k
devices", but it does: on IPQ6018 the teardown stops the WCSS Q6 remote
processor firmware, which leaves shared WCSS state such that the boot ROM
hangs during DDR training on the following warm reset -- only a cold
(power-on) reset recovers, so a plain reboot never comes back and needs a
physical power cycle. This was pinned by bisecting the teardown: skipping
ath11k_qmi_firmware_stop() (i.e. not stopping the Q6) is what lets the
warm reset train DDR and boot normally, whereas none of the q6v5 power,
reset or clock steps reproduce it on their own.

Restrict the shutdown() teardown to WCN6750 via hw_params, restoring the
pre-regression behaviour for the IPQ AHB targets: they simply have no
shutdown() teardown again, exactly as they did for years before that
change, and on reboot/shutdown the SoC reset re-initializes the WCSS from
scratch. WCN6750 keeps the teardown. Module removal (rmmod / remove()) is
unchanged for all targets.

Verified on a MikroTik Chateau 5G R17 ax (IPQ6018): before, a plain
reboot froze in the boot ROM during DDR training; after, it trains DDR
and boots the kernel across repeated reboots.

Fixes: ac41c2b642b1 ("wifi: ath11k: Register shutdown handler for WCN6750")
Cc: stable@vger.kernel.org
Cc: Manikanta Pubbisetty <manikanta.pubbisetty@oss.qualcomm.com>
Signed-off-by: André Valentin <avalentin@marcant.net>
---
Changes in v2 (per Jeff Johnson's review):
- Drive the difference from hw_params instead of comparing ab->hw_rev in
  ath11k_ahb_shutdown(): add shutdown_teardown, set only for WCN6750.
- Frame it as restoring the pre-regression behaviour for the IPQ AHB
  targets (no shutdown() teardown), rather than a per-SoC quirk.

v1: https://lore.kernel.org/linux-wireless/20260807094858.1548216-1-avalentin@marcant.net/

 drivers/net/wireless/ath/ath11k/ahb.c  | 11 +++++++++++
 drivers/net/wireless/ath/ath11k/core.c |  1 +
 drivers/net/wireless/ath/ath11k/hw.h   |  4 ++++
 3 files changed, 16 insertions(+)

diff --git a/drivers/net/wireless/ath/ath11k/ahb.c b/drivers/net/wireless/ath/ath11k/ahb.c
index 1e1dea4..5d71ff4 100644
--- a/drivers/net/wireless/ath/ath11k/ahb.c
+++ b/drivers/net/wireless/ath/ath11k/ahb.c
@@ -1288,6 +1288,17 @@ static void ath11k_ahb_shutdown(struct platform_device *pdev)
 	 * remove() is invoked during rmmod & shutdown() during
 	 * system reboot/shutdown.
 	 */
+
+	/* The teardown below is only needed on WCN6750 (stop DMA before the
+	 * SMMU is torn down). It was registered for all AHB targets, but on
+	 * the IPQ SoCs it stops the WCSS Q6 firmware and leaves shared state
+	 * that hangs the boot ROM during DDR training on the next warm reset;
+	 * they never had a shutdown() teardown before and the SoC reset
+	 * re-initializes the WCSS from scratch, so skip it there.
+	 */
+	if (!ab->hw_params.shutdown_teardown)
+		return;
+
 	ath11k_ahb_remove_prepare(ab);
 
 	if (!(test_bit(ATH11K_FLAG_REGISTERED, &ab->dev_flags)))
diff --git a/drivers/net/wireless/ath/ath11k/core.c b/drivers/net/wireless/ath/ath11k/core.c
index 8dacc87..c6df829 100644
--- a/drivers/net/wireless/ath/ath11k/core.c
+++ b/drivers/net/wireless/ath/ath11k/core.c
@@ -578,6 +578,7 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
 	{
 		.name = "wcn6750 hw1.0",
 		.hw_rev = ATH11K_HW_WCN6750_HW10,
+		.shutdown_teardown = true,
 		.fw = {
 			.dir = "WCN6750/hw1.0",
 			.board_size = 256 * 1024,
diff --git a/drivers/net/wireless/ath/ath11k/hw.h b/drivers/net/wireless/ath/ath11k/hw.h
index 4996536..8279eb4 100644
--- a/drivers/net/wireless/ath/ath11k/hw.h
+++ b/drivers/net/wireless/ath/ath11k/hw.h
@@ -231,6 +231,10 @@ struct ath11k_hw_params {
 	bool cfr_support;
 	u32 cfr_num_stream_bufs;
 	u32 cfr_stream_buf_size;
+	/* run the ahb shutdown() teardown; only WCN6750 needs it, to stop
+	 * DMA before the SMMU is torn down at reboot/shutdown
+	 */
+	bool shutdown_teardown;
 };
 
 struct ath11k_hw_ops {

base-commit: f9a2394a23482bfd330911e9c8295b71724feacd
-- 
2.47.3


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* Re: [PATCH v2] wifi: ath11k: run ahb shutdown() teardown only on WCN6750
  2026-08-08 21:35 ` [PATCH v2] " André Valentin
@ 2026-08-10 19:05   ` Jeff Johnson
  2026-08-10 19:28   ` [PATCH v3] " André Valentin
  1 sibling, 0 replies; 6+ messages in thread
From: Jeff Johnson @ 2026-08-10 19:05 UTC (permalink / raw)
  To: André Valentin, Jeff Johnson
  Cc: linux-wireless, ath11k, Kalle Valo, stable, Manikanta Pubbisetty

On 8/8/2026 2:35 PM, André Valentin wrote:
> The AHB shutdown() callback was added solely for WCN6750, which must stop
> DMA before the SMMU is torn down at system reboot/shutdown. It was
> registered unconditionally in the shared
> ath11k_ahb_driver, so it also runs on the IPQ AHB targets (IPQ8074/
> IPQ6018/IPQ5018), which never had a shutdown() handler before and have no
> such SMMU requirement.
> 
> The commit message claimed the change "will not impact other AHB ath11k
> devices", but it does: on IPQ6018 the teardown stops the WCSS Q6 remote
> processor firmware, which leaves shared WCSS state such that the boot ROM
> hangs during DDR training on the following warm reset -- only a cold
> (power-on) reset recovers, so a plain reboot never comes back and needs a
> physical power cycle. This was pinned by bisecting the teardown: skipping
> ath11k_qmi_firmware_stop() (i.e. not stopping the Q6) is what lets the
> warm reset train DDR and boot normally, whereas none of the q6v5 power,
> reset or clock steps reproduce it on their own.
> 
> Restrict the shutdown() teardown to WCN6750 via hw_params, restoring the
> pre-regression behaviour for the IPQ AHB targets: they simply have no
> shutdown() teardown again, exactly as they did for years before that
> change, and on reboot/shutdown the SoC reset re-initializes the WCSS from
> scratch. WCN6750 keeps the teardown. Module removal (rmmod / remove()) is
> unchanged for all targets.
> 
> Verified on a MikroTik Chateau 5G R17 ax (IPQ6018): before, a plain
> reboot froze in the boot ROM during DDR training; after, it trains DDR
> and boots the kernel across repeated reboots.
> 
> Fixes: ac41c2b642b1 ("wifi: ath11k: Register shutdown handler for WCN6750")
> Cc: stable@vger.kernel.org
> Cc: Manikanta Pubbisetty <manikanta.pubbisetty@oss.qualcomm.com>
> Signed-off-by: André Valentin <avalentin@marcant.net>
> ---
> Changes in v2 (per Jeff Johnson's review):
> - Drive the difference from hw_params instead of comparing ab->hw_rev in
>   ath11k_ahb_shutdown(): add shutdown_teardown, set only for WCN6750.
> - Frame it as restoring the pre-regression behaviour for the IPQ AHB
>   targets (no shutdown() teardown), rather than a per-SoC quirk.
> 
> v1: https://lore.kernel.org/linux-wireless/20260807094858.1548216-1-avalentin@marcant.net/
> 
>  drivers/net/wireless/ath/ath11k/ahb.c  | 11 +++++++++++
>  drivers/net/wireless/ath/ath11k/core.c |  1 +
>  drivers/net/wireless/ath/ath11k/hw.h   |  4 ++++
>  3 files changed, 16 insertions(+)
> 
> diff --git a/drivers/net/wireless/ath/ath11k/ahb.c b/drivers/net/wireless/ath/ath11k/ahb.c
> index 1e1dea4..5d71ff4 100644
> --- a/drivers/net/wireless/ath/ath11k/ahb.c
> +++ b/drivers/net/wireless/ath/ath11k/ahb.c
> @@ -1288,6 +1288,17 @@ static void ath11k_ahb_shutdown(struct platform_device *pdev)
>  	 * remove() is invoked during rmmod & shutdown() during
>  	 * system reboot/shutdown.
>  	 */
> +
> +	/* The teardown below is only needed on WCN6750 (stop DMA before the

1) incorrect block comment style, /* should be on a line by itself
(at one time networking had a different style, but no longer)

2) we avoid mentioning hardware in generic code. that is the whole point of
the hw_params. mention the feature not the specific hardware (since there may
be hw other than WCN6750 that have this behavior)

> +	 * SMMU is torn down). It was registered for all AHB targets, but on
> +	 * the IPQ SoCs it stops the WCSS Q6 firmware and leaves shared state
> +	 * that hangs the boot ROM during DDR training on the next warm reset;
> +	 * they never had a shutdown() teardown before and the SoC reset
> +	 * re-initializes the WCSS from scratch, so skip it there.
> +	 */
> +	if (!ab->hw_params.shutdown_teardown)
> +		return;
> +
>  	ath11k_ahb_remove_prepare(ab);
>  
>  	if (!(test_bit(ATH11K_FLAG_REGISTERED, &ab->dev_flags)))
> diff --git a/drivers/net/wireless/ath/ath11k/core.c b/drivers/net/wireless/ath/ath11k/core.c
> index 8dacc87..c6df829 100644
> --- a/drivers/net/wireless/ath/ath11k/core.c
> +++ b/drivers/net/wireless/ath/ath11k/core.c
> @@ -578,6 +578,7 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
>  	{
>  		.name = "wcn6750 hw1.0",
>  		.hw_rev = ATH11K_HW_WCN6750_HW10,
> +		.shutdown_teardown = true,

please add = false to all other records
we enforce explicitly initializing all members

>  		.fw = {
>  			.dir = "WCN6750/hw1.0",
>  			.board_size = 256 * 1024,
> diff --git a/drivers/net/wireless/ath/ath11k/hw.h b/drivers/net/wireless/ath/ath11k/hw.h
> index 4996536..8279eb4 100644
> --- a/drivers/net/wireless/ath/ath11k/hw.h
> +++ b/drivers/net/wireless/ath/ath11k/hw.h
> @@ -231,6 +231,10 @@ struct ath11k_hw_params {
>  	bool cfr_support;
>  	u32 cfr_num_stream_bufs;
>  	u32 cfr_stream_buf_size;
> +	/* run the ahb shutdown() teardown; only WCN6750 needs it, to stop

again wrong block comment style, and should not have an explicit chip
reference. describe the behavior, not which chipsets have that behavior.
only the hw_params initializer should establish the correlation of the
feature/behavior to the chipset

> +	 * DMA before the SMMU is torn down at reboot/shutdown
> +	 */
> +	bool shutdown_teardown;
>  };
>  
>  struct ath11k_hw_ops {
> 
> base-commit: f9a2394a23482bfd330911e9c8295b71724feacd


^ permalink raw reply	[flat|nested] 6+ messages in thread

* [PATCH v3] wifi: ath11k: run ahb shutdown() teardown only on WCN6750
  2026-08-08 21:35 ` [PATCH v2] " André Valentin
  2026-08-10 19:05   ` Jeff Johnson
@ 2026-08-10 19:28   ` André Valentin
  1 sibling, 0 replies; 6+ messages in thread
From: André Valentin @ 2026-08-10 19:28 UTC (permalink / raw)
  To: Jeff Johnson
  Cc: linux-wireless, ath11k, Kalle Valo, avalentin, stable,
	Manikanta Pubbisetty

The AHB shutdown() callback was added solely for WCN6750, which must stop
DMA before the SMMU is torn down at system reboot/shutdown. It was
registered unconditionally in the shared ath11k_ahb_driver, so it also
runs on the IPQ AHB targets (IPQ8074/IPQ6018/IPQ5018), which never had a
shutdown() handler before and have no such SMMU requirement.

The commit message claimed the change "will not impact other AHB ath11k
devices", but it does: on IPQ6018 the teardown stops the WCSS Q6 remote
processor firmware, which leaves shared WCSS state such that the boot ROM
hangs during DDR training on the following warm reset -- only a cold
(power-on) reset recovers, so a plain reboot never comes back and needs a
physical power cycle. This was pinned by bisecting the teardown: skipping
ath11k_qmi_firmware_stop() (i.e. not stopping the Q6) is what lets the
warm reset train DDR and boot normally, whereas none of the q6v5 power,
reset or clock steps reproduce it on their own.

Restrict the shutdown() teardown to WCN6750 via hw_params, restoring the
pre-regression behaviour for the IPQ AHB targets: they simply have no
shutdown() teardown again, exactly as they did for years before that
change, and on reboot/shutdown the SoC reset re-initializes the WCSS from
scratch. WCN6750 keeps the teardown. Module removal (rmmod / remove()) is
unchanged for all targets.

Verified on a MikroTik Chateau 5G R17 ax (IPQ6018): before, a plain
reboot froze in the boot ROM during DDR training; after, it trains DDR
and boots the kernel across repeated reboots.

Fixes: ac41c2b642b1 ("wifi: ath11k: Register shutdown handler for WCN6750")
Cc: stable@vger.kernel.org
Cc: Manikanta Pubbisetty <manikanta.pubbisetty@oss.qualcomm.com>
Signed-off-by: André Valentin <avalentin@marcant.net>
---
Changes in v3 (per Jeff Johnson's v2 review):
- ahb.c/hw.h: fix block comment style (/* on its own line) and drop the
  chip references from the generic code -- describe the behaviour, not the
  chipset; only the hw_params initializer ties it to WCN6750.
- core.c: explicitly initialize shutdown_teardown in every hw_params record
  (= false on all but WCN6750).

v2: https://lore.kernel.org/linux-wireless/20260808213551.4169863-1-avalentin@marcant.net/
v1: https://lore.kernel.org/linux-wireless/20260807094858.1548216-1-avalentin@marcant.net/

 drivers/net/wireless/ath/ath11k/ahb.c  | 10 ++++++++++
 drivers/net/wireless/ath/ath11k/core.c | 10 ++++++++++
 drivers/net/wireless/ath/ath11k/hw.h   |  7 +++++++
 3 files changed, 27 insertions(+)

diff --git a/drivers/net/wireless/ath/ath11k/ahb.c b/drivers/net/wireless/ath/ath11k/ahb.c
index 1e1dea4..18f7bff 100644
--- a/drivers/net/wireless/ath/ath11k/ahb.c
+++ b/drivers/net/wireless/ath/ath11k/ahb.c
@@ -1288,6 +1288,16 @@ static void ath11k_ahb_shutdown(struct platform_device *pdev)
 	 * remove() is invoked during rmmod & shutdown() during
 	 * system reboot/shutdown.
 	 */
+
+	/*
+	 * Only run the teardown where hw_params requests it. Where it is not
+	 * required, stopping the firmware here would leave shared state that
+	 * hangs the following warm reset, so skip it and let the SoC reset
+	 * re-initialize the hardware from scratch instead.
+	 */
+	if (!ab->hw_params.shutdown_teardown)
+		return;
+
 	ath11k_ahb_remove_prepare(ab);
 
 	if (!(test_bit(ATH11K_FLAG_REGISTERED, &ab->dev_flags)))
diff --git a/drivers/net/wireless/ath/ath11k/core.c b/drivers/net/wireless/ath/ath11k/core.c
index 8dacc87..2a10173 100644
--- a/drivers/net/wireless/ath/ath11k/core.c
+++ b/drivers/net/wireless/ath/ath11k/core.c
@@ -41,6 +41,7 @@ MODULE_PARM_DESC(ftm_mode, "Boots up in factory test mode");
 static const struct ath11k_hw_params ath11k_hw_params[] = {
 	{
 		.hw_rev = ATH11K_HW_IPQ8074,
+		.shutdown_teardown = false,
 		.name = "ipq8074 hw2.0",
 		.fw = {
 			.dir = "IPQ8074/hw2.0",
@@ -130,6 +131,7 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
 	},
 	{
 		.hw_rev = ATH11K_HW_IPQ6018_HW10,
+		.shutdown_teardown = false,
 		.name = "ipq6018 hw1.0",
 		.fw = {
 			.dir = "IPQ6018/hw1.0",
@@ -218,6 +220,7 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
 	{
 		.name = "qca6390 hw2.0",
 		.hw_rev = ATH11K_HW_QCA6390_HW20,
+		.shutdown_teardown = false,
 		.fw = {
 			.dir = "QCA6390/hw2.0",
 			.board_size = 256 * 1024,
@@ -310,6 +313,7 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
 	{
 		.name = "qcn9074 hw1.0",
 		.hw_rev = ATH11K_HW_QCN9074_HW10,
+		.shutdown_teardown = false,
 		.fw = {
 			.dir = "QCN9074/hw1.0",
 			.board_size = 256 * 1024,
@@ -396,6 +400,7 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
 	{
 		.name = "wcn6855 hw2.0",
 		.hw_rev = ATH11K_HW_WCN6855_HW20,
+		.shutdown_teardown = false,
 		.fw = {
 			.dir = "WCN6855/hw2.0",
 			.board_size = 256 * 1024,
@@ -488,6 +493,7 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
 	{
 		.name = "wcn6855 hw2.1",
 		.hw_rev = ATH11K_HW_WCN6855_HW21,
+		.shutdown_teardown = false,
 		.fw = {
 			.dir = "WCN6855/hw2.1",
 			.board_size = 256 * 1024,
@@ -578,6 +584,7 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
 	{
 		.name = "wcn6750 hw1.0",
 		.hw_rev = ATH11K_HW_WCN6750_HW10,
+		.shutdown_teardown = true,
 		.fw = {
 			.dir = "WCN6750/hw1.0",
 			.board_size = 256 * 1024,
@@ -662,6 +669,7 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
 	},
 	{
 		.hw_rev = ATH11K_HW_IPQ5018_HW10,
+		.shutdown_teardown = false,
 		.name = "ipq5018 hw1.0",
 		.fw = {
 			.dir = "IPQ5018/hw1.0",
@@ -748,6 +756,7 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
 	{
 		.name = "qca2066 hw2.1",
 		.hw_rev = ATH11K_HW_QCA2066_HW21,
+		.shutdown_teardown = false,
 		.fw = {
 			.dir = "QCA2066/hw2.1",
 			.board_size = 256 * 1024,
@@ -839,6 +848,7 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
 	{
 		.name = "qca6698aq hw2.1",
 		.hw_rev = ATH11K_HW_QCA6698AQ_HW21,
+		.shutdown_teardown = false,
 		.fw = {
 			.dir = "QCA6698AQ/hw2.1",
 			.board_size = 256 * 1024,
diff --git a/drivers/net/wireless/ath/ath11k/hw.h b/drivers/net/wireless/ath/ath11k/hw.h
index 4996536..f35bb96 100644
--- a/drivers/net/wireless/ath/ath11k/hw.h
+++ b/drivers/net/wireless/ath/ath11k/hw.h
@@ -231,6 +231,13 @@ struct ath11k_hw_params {
 	bool cfr_support;
 	u32 cfr_num_stream_bufs;
 	u32 cfr_stream_buf_size;
+	/*
+	 * Run the ahb shutdown() teardown (stop DMA before the SMMU is torn
+	 * down at reboot/shutdown). Only set where the teardown is required;
+	 * where it is not, running it would stop the firmware and leave shared
+	 * state that hangs the following warm reset.
+	 */
+	bool shutdown_teardown;
 };
 
 struct ath11k_hw_ops {

base-commit: f9a2394a23482bfd330911e9c8295b71724feacd
-- 
2.47.3


^ permalink raw reply related	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2026-08-10 19:29 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-08-07  9:48 [PATCH] wifi: ath11k: run ahb shutdown() teardown only on WCN6750 André Valentin
2026-08-07 15:34 ` Jeff Johnson
2026-08-07 15:39   ` Jeff Johnson
2026-08-08 21:35 ` [PATCH v2] " André Valentin
2026-08-10 19:05   ` Jeff Johnson
2026-08-10 19:28   ` [PATCH v3] " André Valentin

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox