* [PATCH 1/2] net: wwan: iosm: Properly check for valid exec stage in ipc_mmio_init()
@ 2024-12-29 16:46 Maciej S. Szmigiero
2024-12-29 16:46 ` [PATCH 2/2] net: wwan: iosm: Fix hibernation by re-binding the driver around it Maciej S. Szmigiero
2025-01-03 2:50 ` [PATCH 1/2] net: wwan: iosm: Properly check for valid exec stage in ipc_mmio_init() patchwork-bot+netdevbpf
0 siblings, 2 replies; 4+ messages in thread
From: Maciej S. Szmigiero @ 2024-12-29 16:46 UTC (permalink / raw)
To: M Chetan Kumar, Loic Poulain, Sergey Ryazanov, Johannes Berg
Cc: Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni, netdev, linux-kernel
ipc_mmio_init() used the post-decrement operator in its loop continuing
condition of "retries" counter being "> 0", which meant that when this
condition caused loop exit "retries" counter reached -1.
But the later valid exec stage failure check only tests for "retries"
counter being exactly zero, so it didn't trigger in this case (but
would wrongly trigger if the code reaches a valid exec stage in the
very last loop iteration).
Fix this by using the pre-decrement operator instead, so the loop counter
is exactly zero on valid exec stage failure.
Fixes: dc0514f5d828 ("net: iosm: mmio scratchpad")
Signed-off-by: Maciej S. Szmigiero <mail@maciej.szmigiero.name>
---
drivers/net/wwan/iosm/iosm_ipc_mmio.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/net/wwan/iosm/iosm_ipc_mmio.c b/drivers/net/wwan/iosm/iosm_ipc_mmio.c
index 63eb08c43c05..6764c13530b9 100644
--- a/drivers/net/wwan/iosm/iosm_ipc_mmio.c
+++ b/drivers/net/wwan/iosm/iosm_ipc_mmio.c
@@ -104,7 +104,7 @@ struct iosm_mmio *ipc_mmio_init(void __iomem *mmio, struct device *dev)
break;
msleep(20);
- } while (retries-- > 0);
+ } while (--retries > 0);
if (!retries) {
dev_err(ipc_mmio->dev, "invalid exec stage %X", stage);
^ permalink raw reply related [flat|nested] 4+ messages in thread* [PATCH 2/2] net: wwan: iosm: Fix hibernation by re-binding the driver around it
2024-12-29 16:46 [PATCH 1/2] net: wwan: iosm: Properly check for valid exec stage in ipc_mmio_init() Maciej S. Szmigiero
@ 2024-12-29 16:46 ` Maciej S. Szmigiero
2025-01-04 16:48 ` Jakub Kicinski
2025-01-03 2:50 ` [PATCH 1/2] net: wwan: iosm: Properly check for valid exec stage in ipc_mmio_init() patchwork-bot+netdevbpf
1 sibling, 1 reply; 4+ messages in thread
From: Maciej S. Szmigiero @ 2024-12-29 16:46 UTC (permalink / raw)
To: M Chetan Kumar, Loic Poulain, Sergey Ryazanov, Johannes Berg
Cc: Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni, netdev, linux-kernel
Currently, the driver is seriously broken with respect to the
hibernation (S4): after image restore the device is back into
IPC_MEM_EXEC_STAGE_BOOT (which AFAIK means bootloader stage) and needs
full re-launch of the rest of its firmware, but the driver restore
handler treats the device as merely sleeping and just sends it a
wake-up command.
This wake-up command times out but device nodes (/dev/wwan*) remain
accessible.
However attempting to use them causes the bootloader to crash and
enter IPC_MEM_EXEC_STAGE_CD_READY stage (which apparently means "a crash
dump is ready").
It seems that the device cannot be re-initialized from this crashed
stage without toggling some reset pin (on my test platform that's
apparently what the device _RST ACPI method does).
While it would theoretically be possible to rewrite the driver to tear
down the whole MUX / IPC layers on hibernation (so the bootloader does
not crash from improper access) and then re-launch the device on
restore this would require significant refactoring of the driver
(believe me, I've tried), since there are quite a few assumptions
hard-coded in the driver about the device never being partially
de-initialized (like channels other than devlink cannot be closed,
for example).
Probably this would also need some programming guide for this hardware.
Considering that the driver seems orphaned [1] and other people are
hitting this issue too [2] fix it by simply unbinding the PCI driver
before hibernation and re-binding it after restore, much like
USB_QUIRK_RESET_RESUME does for USB devices that exhibit a similar
problem.
Tested on XMM7360 in HP EliteBook 855 G7 both with s2idle (which uses
the existing suspend / resume handlers) and S4 (which uses the new code).
[1]: https://lore.kernel.org/all/c248f0b4-2114-4c61-905f-466a786bdebb@leemhuis.info/
[2]:
https://github.com/xmm7360/xmm7360-pci/issues/211#issuecomment-1804139413
Signed-off-by: Maciej S. Szmigiero <mail@maciej.szmigiero.name>
---
drivers/net/wwan/iosm/iosm_ipc_pcie.c | 57 ++++++++++++++++++++++++++-
1 file changed, 56 insertions(+), 1 deletion(-)
diff --git a/drivers/net/wwan/iosm/iosm_ipc_pcie.c b/drivers/net/wwan/iosm/iosm_ipc_pcie.c
index 04517bd3325a..fe5981a27a10 100644
--- a/drivers/net/wwan/iosm/iosm_ipc_pcie.c
+++ b/drivers/net/wwan/iosm/iosm_ipc_pcie.c
@@ -6,6 +6,7 @@
#include <linux/acpi.h>
#include <linux/bitfield.h>
#include <linux/module.h>
+#include <linux/suspend.h>
#include <net/rtnetlink.h>
#include "iosm_ipc_imem.h"
@@ -448,7 +449,61 @@ static struct pci_driver iosm_ipc_driver = {
},
.id_table = iosm_ipc_ids,
};
-module_pci_driver(iosm_ipc_driver);
+
+static bool pci_registered;
+
+static int pm_notify(struct notifier_block *nb, unsigned long mode, void *_unused)
+{
+ if (mode == PM_HIBERNATION_PREPARE || mode == PM_RESTORE_PREPARE) {
+ if (pci_registered) {
+ pci_unregister_driver(&iosm_ipc_driver);
+ pci_registered = false;
+ }
+ } else if (mode == PM_POST_HIBERNATION || mode == PM_POST_RESTORE) {
+ if (!pci_registered) {
+ int ret;
+
+ ret = pci_register_driver(&iosm_ipc_driver);
+ if (ret) {
+ pr_err(KBUILD_MODNAME ": unable to re-register PCI driver: %d\n",
+ ret);
+ } else {
+ pci_registered = true;
+ }
+ }
+ }
+
+ return 0;
+}
+
+static struct notifier_block pm_notifier = {
+ .notifier_call = pm_notify,
+};
+
+static int __init iosm_ipc_driver_init(void)
+{
+ int ret;
+
+ ret = pci_register_driver(&iosm_ipc_driver);
+ if (ret)
+ return ret;
+
+ pci_registered = true;
+
+ register_pm_notifier(&pm_notifier);
+
+ return 0;
+}
+module_init(iosm_ipc_driver_init);
+
+static void __exit iosm_ipc_driver_exit(void)
+{
+ if (pci_registered)
+ pci_unregister_driver(&iosm_ipc_driver);
+
+ unregister_pm_notifier(&pm_notifier);
+}
+module_exit(iosm_ipc_driver_exit);
int ipc_pcie_addr_map(struct iosm_pcie *ipc_pcie, unsigned char *data,
size_t size, dma_addr_t *mapping, int direction)
^ permalink raw reply related [flat|nested] 4+ messages in thread* Re: [PATCH 2/2] net: wwan: iosm: Fix hibernation by re-binding the driver around it
2024-12-29 16:46 ` [PATCH 2/2] net: wwan: iosm: Fix hibernation by re-binding the driver around it Maciej S. Szmigiero
@ 2025-01-04 16:48 ` Jakub Kicinski
0 siblings, 0 replies; 4+ messages in thread
From: Jakub Kicinski @ 2025-01-04 16:48 UTC (permalink / raw)
To: Maciej S. Szmigiero
Cc: M Chetan Kumar, Loic Poulain, Sergey Ryazanov, Johannes Berg,
Andrew Lunn, David S. Miller, Eric Dumazet, Paolo Abeni, netdev,
linux-kernel
On Sun, 29 Dec 2024 17:46:59 +0100 Maciej S. Szmigiero wrote:
> + if (pci_registered)
> + pci_unregister_driver(&iosm_ipc_driver);
> +
> + unregister_pm_notifier(&pm_notifier);
The ordering here should be inverted so that you're sure notifier can't
run in parallel.
But I think the notifier is an overkill, there's gotta be an op that
runs. pci_driver::shutdown ? dev_pm_ops::freeze / thaw ?
If you repost please make sure to CC the PCI list, folks there will
know how hibernation is supposed to be handled for sure. Note that
patch 1 is already in Linus's tree so repost just patch 2.
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH 1/2] net: wwan: iosm: Properly check for valid exec stage in ipc_mmio_init()
2024-12-29 16:46 [PATCH 1/2] net: wwan: iosm: Properly check for valid exec stage in ipc_mmio_init() Maciej S. Szmigiero
2024-12-29 16:46 ` [PATCH 2/2] net: wwan: iosm: Fix hibernation by re-binding the driver around it Maciej S. Szmigiero
@ 2025-01-03 2:50 ` patchwork-bot+netdevbpf
1 sibling, 0 replies; 4+ messages in thread
From: patchwork-bot+netdevbpf @ 2025-01-03 2:50 UTC (permalink / raw)
To: Maciej S. Szmigiero
Cc: m.chetan.kumar, loic.poulain, ryazanov.s.a, johannes,
andrew+netdev, davem, edumazet, kuba, pabeni, netdev,
linux-kernel
Hello:
This series was applied to netdev/net.git (main)
by Jakub Kicinski <kuba@kernel.org>:
On Sun, 29 Dec 2024 17:46:58 +0100 you wrote:
> ipc_mmio_init() used the post-decrement operator in its loop continuing
> condition of "retries" counter being "> 0", which meant that when this
> condition caused loop exit "retries" counter reached -1.
>
> But the later valid exec stage failure check only tests for "retries"
> counter being exactly zero, so it didn't trigger in this case (but
> would wrongly trigger if the code reaches a valid exec stage in the
> very last loop iteration).
>
> [...]
Here is the summary with links:
- [1/2] net: wwan: iosm: Properly check for valid exec stage in ipc_mmio_init()
https://git.kernel.org/netdev/net/c/a7af435df0e0
- [2/2] net: wwan: iosm: Fix hibernation by re-binding the driver around it
(no matching commit)
You are awesome, thank you!
--
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2025-01-04 16:48 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-12-29 16:46 [PATCH 1/2] net: wwan: iosm: Properly check for valid exec stage in ipc_mmio_init() Maciej S. Szmigiero
2024-12-29 16:46 ` [PATCH 2/2] net: wwan: iosm: Fix hibernation by re-binding the driver around it Maciej S. Szmigiero
2025-01-04 16:48 ` Jakub Kicinski
2025-01-03 2:50 ` [PATCH 1/2] net: wwan: iosm: Properly check for valid exec stage in ipc_mmio_init() patchwork-bot+netdevbpf
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).