Message ID | 20250107212702.169493-6-john.ogness@linutronix.de |
---|---|
State | New |
Headers | show |
Series | convert 8250 to nbcon | expand |
Hi John, On 07/01/2025 21:27, John Ogness wrote: > Implement the necessary callbacks to switch the 8250 console driver > to perform as an nbcon console. > > Add implementations for the nbcon console callbacks: > > ->write_atomic() > ->write_thread() > ->device_lock() > ->device_unlock() > > and add CON_NBCON to the initial @flags. > > All register access in the callbacks are within unsafe sections. > The ->write_atomic() and ->write_thread() callbacks allow safe > handover/takeover per byte and add a preceding newline if they > take over from another context mid-line. > > For the ->write_atomic() callback, a new irq_work is used to defer > modem control since it may be called from a context that does not > allow waking up tasks. > > Note: A new __serial8250_clear_IER() is introduced for direct > clearing of UART_IER. This will allow to restore the lockdep > check to serial8250_clear_IER() in a follow-up commit. > > Signed-off-by: John Ogness <john.ogness@linutronix.de> I have noticed a suspend regression on -next for some of our 32-bit Tegra (ARM) devices (Tegra20, Tegra30 and Tegra124). Bisect is pointing to this commit and reverting this on top of -next (along with reverting "serial: 8250: Revert "drop lockdep annotation from serial8250_clear_IER()") fixes the issue. So far I have not dug in any further. Unfortunately, I don't have any logs to see if there is some crash or something happening but I will see if there is any more info I can get. Thanks Jon
On 2025-01-15, Jon Hunter <jonathanh@nvidia.com> wrote: > I have noticed a suspend regression on -next for some of our 32-bit > Tegra (ARM) devices (Tegra20, Tegra30 and Tegra124). Bisect is pointing > to this commit and reverting this on top of -next (along with reverting > "serial: 8250: Revert "drop lockdep annotation from > serial8250_clear_IER()") fixes the issue. So far I have not dug in any > further. Unfortunately, I don't have any logs to see if there is some > crash or something happening but I will see if there is any more info I > can get. Do you at least know if it is failing to suspend or failing to resume (based on power consumption)? John
On 15/01/2025 16:54, John Ogness wrote: > On 2025-01-15, Jon Hunter <jonathanh@nvidia.com> wrote: >> I have noticed a suspend regression on -next for some of our 32-bit >> Tegra (ARM) devices (Tegra20, Tegra30 and Tegra124). Bisect is pointing >> to this commit and reverting this on top of -next (along with reverting >> "serial: 8250: Revert "drop lockdep annotation from >> serial8250_clear_IER()") fixes the issue. So far I have not dug in any >> further. Unfortunately, I don't have any logs to see if there is some >> crash or something happening but I will see if there is any more info I >> can get. > > Do you at least know if it is failing to suspend or failing to resume > (based on power consumption)? Unfortunately, I don't. These are farm boards and so nothing local I can get my hands on. For some reason all the serial console logs are not available and so I am going to talk to the farm team about fixing that because we should at least have serial logs. Thanks Jon
On 2025-01-16, Jon Hunter <jonathanh@nvidia.com> wrote: >> Do you at least know if it is failing to suspend or failing to resume >> (based on power consumption)? > > > Unfortunately, I don't. These are farm boards and so nothing local I can > get my hands on. For some reason all the serial console logs are not > available and so I am going to talk to the farm team about fixing that > because we should at least have serial logs. Can you confirm that the board is actually booting? The suspend code for 8250_tegra.c is quite simple. I am wondering if the farm tests are failing somewhere else, such as the atomic printing during early boot. John
On 16/01/2025 10:38, John Ogness wrote: > On 2025-01-16, Jon Hunter <jonathanh@nvidia.com> wrote: >>> Do you at least know if it is failing to suspend or failing to resume >>> (based on power consumption)? >> >> >> Unfortunately, I don't. These are farm boards and so nothing local I can >> get my hands on. For some reason all the serial console logs are not >> available and so I am going to talk to the farm team about fixing that >> because we should at least have serial logs. > > Can you confirm that the board is actually booting? The suspend code for > 8250_tegra.c is quite simple. I am wondering if the farm tests are > failing somewhere else, such as the atomic printing during early boot. Yes they are all booting fine. I have an independent boot test and that is passing. It is just the suspend test that is failing. Thanks Jon
On Thu, Jan 16, 2025 at 10:41:08AM +0000, Jon Hunter wrote: > > On 16/01/2025 10:38, John Ogness wrote: > > On 2025-01-16, Jon Hunter <jonathanh@nvidia.com> wrote: > > > > Do you at least know if it is failing to suspend or failing to resume > > > > (based on power consumption)? > > > > > > > > > Unfortunately, I don't. These are farm boards and so nothing local I can > > > get my hands on. For some reason all the serial console logs are not > > > available and so I am going to talk to the farm team about fixing that > > > because we should at least have serial logs. > > > > Can you confirm that the board is actually booting? The suspend code for > > 8250_tegra.c is quite simple. I am wondering if the farm tests are > > failing somewhere else, such as the atomic printing during early boot. > > > Yes they are all booting fine. I have an independent boot test and that is > passing. It is just the suspend test that is failing. I was able to capture logs, but unfortunately they don't provide much insight either. On the first try it doesn't suspend and goes back to userspace after a second or so: --- >8 --- -sh-5.1# rtcwake --device /dev/rtc1 --mode mem --seconds 5 rtcwake: assuming RTC uses UTC ... rtcwake: wakeup from "mem" using /dev/rtc1 at Thu Jan 1 00:01:00 1970 [ 36.332486] PM: suspend entry (deep) [ 36.332832] Filesystems sync: 0.000 seconds [ 36.369331] +1.8V_RUN_CAM: disabling [ 36.373884] +2.8V_RUN_CAM: disabling [ 36.375571] +1.2V_RUN_CAM_FRONT: disabling [ 36.380359] +1.05V_RUN_CAM_REAR: disabling [ 36.387399] +3.3V_RUN_TOUCH: disabling [ 36.390808] +2.8V_RUN_CAM_AF: disabling [ 36.393621] +1.8V_RUN_VPP_FUSE: disabling [ 36.408218] Freezing user space processes [ 36.413660] Freezing user space processes completed (elapsed 0.005 seconds) [ 36.413680] OOM killer disabled. [ 36.413693] Freezing remaining freezable tasks [ 36.415033] Freezing remaining freezable tasks completed (elapsed 0.001 seconds) [ 36.428474] drm drm: [drm:drm_client_dev_suspend] fbdev: ret=0 [ 36.428527] drm drm: [drm:drm_atomic_state_init] Allocated atomic state 2e5cd010 [ 36.428547] drm drm: [drm:drm_atomic_get_crtc_state] Added [CRTC:47:crtc-0] 6a6be0ef state to 2e5cd010 [ 36.428561] drm drm: [drm:drm_atomic_get_crtc_state] Added [CRTC:63:crtc-1] 00d818c2 state to 2e5cd010 [ 36.428574] drm drm: [drm:drm_atomic_get_plane_state] Added [PLANE:32:plane-0] 4e145b7d state to 2e5cd010 [ 36.428587] drm drm: [drm:drm_atomic_get_plane_state] Added [PLANE:36:plane-1] dbf67d12 state to 2e5cd010 [ 36.428597] drm drm: [drm:drm_atomic_get_plane_state] Added [PLANE:40:plane-2] 763d8809 state to 2e5cd010 [ 36.428608] drm drm: [drm:drm_atomic_get_plane_state] Added [PLANE:44:plane-3] b6eabcf1 state to 2e5cd010 [ 36.428617] drm drm: [drm:drm_atomic_get_plane_state] Added [PLANE:48:plane-4] 7863878c state to 2e5cd010 [ 36.428628] drm drm: [drm:drm_atomic_get_plane_state] Added [PLANE:52:plane-5] 54b8029c state to 2e5cd010 [ 36.428638] drm drm: [drm:drm_atomic_get_plane_state] Added [PLANE:56:plane-6] 364063af state to 2e5cd010 [ 36.428648] drm drm: [drm:drm_atomic_get_plane_state] Added [PLANE:60:plane-7] e1c11dfb state to 2e5cd010 [ 36.428662] drm drm: [drm:drm_atomic_get_connector_state] Added [CONNECTOR:65:HDMI-A-1] 5cb32770 state to 2e5cd010 [ 36.428674] drm drm: [drm:drm_atomic_state_init] Allocated atomic state 832943c7 [ 36.428682] drm drm: [drm:drm_atomic_get_crtc_state] Added [CRTC:47:crtc-0] f09cf73d state to 832943c7 [ 36.428691] drm drm: [drm:drm_atomic_add_affected_planes] Adding all current planes for [CRTC:47:crtc-0] to 832943c7 [ 36.428700] drm drm: [drm:drm_atomic_add_affected_connectors] Adding all current connectors for [CRTC:47:crtc-0] to 832943c7 [ 36.428711] drm drm: [drm:drm_atomic_get_crtc_state] Added [CRTC:63:crtc-1] 2700922c state to 832943c7 [ 36.428720] drm drm: [drm:drm_atomic_add_affected_planes] Adding all current planes for [CRTC:63:crtc-1] to 832943c7 [ 36.428727] drm drm: [drm:drm_atomic_add_affected_connectors] Adding all current connectors for [CRTC:63:crtc-1] to 832943c7 [ 36.428737] drm drm: [drm:drm_atomic_check_only] checking 832943c7 [ 36.428759] drm drm: [drm:drm_atomic_commit] committing 832943c7 [ 36.428881] drm drm: [drm:drm_atomic_state_default_clear] Clearing atomic state 832943c7 [ 36.428897] drm drm: [drm:__drm_atomic_state_free] Freeing atomic state 832943c7 [ 36.429085] r8169 0000:01:00.0 eth0: Link is Down [ 36.713236] Disabling non-boot CPUs ... -sh-5.1# --- >8 --- A second attempt soft-hangs: --- >8 --- -sh-5.1# rtcwake --device /dev/rtc1 --mode mem --seconds 5 rtcwake: assuming RTC uses UTC ... rtcwake: wakeup from "mem" using /dev/rtc1 at Thu Jan 1 00:01:10 1970 --- >8 --- Where "soft-hang" means it doesn't do anything after this and I can't SIGINT out of it or anything. However, the serial seems to still be responsive. Thierry
On Mon, Jan 20, 2025 at 05:23:26PM +0100, Thierry Reding wrote: > On Thu, Jan 16, 2025 at 10:41:08AM +0000, Jon Hunter wrote: > > > > On 16/01/2025 10:38, John Ogness wrote: > > > On 2025-01-16, Jon Hunter <jonathanh@nvidia.com> wrote: > > > > > Do you at least know if it is failing to suspend or failing to resume > > > > > (based on power consumption)? > > > > > > > > > > > > Unfortunately, I don't. These are farm boards and so nothing local I can > > > > get my hands on. For some reason all the serial console logs are not > > > > available and so I am going to talk to the farm team about fixing that > > > > because we should at least have serial logs. > > > > > > Can you confirm that the board is actually booting? The suspend code for > > > 8250_tegra.c is quite simple. I am wondering if the farm tests are > > > failing somewhere else, such as the atomic printing during early boot. > > > > > > Yes they are all booting fine. I have an independent boot test and that is > > passing. It is just the suspend test that is failing. > > I was able to capture logs, but unfortunately they don't provide much > insight either. On the first try it doesn't suspend and goes back to > userspace after a second or so: > > --- >8 --- > -sh-5.1# rtcwake --device /dev/rtc1 --mode mem --seconds 5 > rtcwake: assuming RTC uses UTC ... > rtcwake: wakeup from "mem" using /dev/rtc1 at Thu Jan 1 00:01:00 1970 > [ 36.332486] PM: suspend entry (deep) > [ 36.332832] Filesystems sync: 0.000 seconds > [ 36.369331] +1.8V_RUN_CAM: disabling > [ 36.373884] +2.8V_RUN_CAM: disabling > [ 36.375571] +1.2V_RUN_CAM_FRONT: disabling > [ 36.380359] +1.05V_RUN_CAM_REAR: disabling > [ 36.387399] +3.3V_RUN_TOUCH: disabling > [ 36.390808] +2.8V_RUN_CAM_AF: disabling > [ 36.393621] +1.8V_RUN_VPP_FUSE: disabling > [ 36.408218] Freezing user space processes > [ 36.413660] Freezing user space processes completed (elapsed 0.005 seconds) > [ 36.413680] OOM killer disabled. > [ 36.413693] Freezing remaining freezable tasks > [ 36.415033] Freezing remaining freezable tasks completed (elapsed 0.001 seconds) > [ 36.428474] drm drm: [drm:drm_client_dev_suspend] fbdev: ret=0 > [ 36.428527] drm drm: [drm:drm_atomic_state_init] Allocated atomic state 2e5cd010 > [ 36.428547] drm drm: [drm:drm_atomic_get_crtc_state] Added [CRTC:47:crtc-0] 6a6be0ef state to 2e5cd010 > [ 36.428561] drm drm: [drm:drm_atomic_get_crtc_state] Added [CRTC:63:crtc-1] 00d818c2 state to 2e5cd010 > [ 36.428574] drm drm: [drm:drm_atomic_get_plane_state] Added [PLANE:32:plane-0] 4e145b7d state to 2e5cd010 > [ 36.428587] drm drm: [drm:drm_atomic_get_plane_state] Added [PLANE:36:plane-1] dbf67d12 state to 2e5cd010 > [ 36.428597] drm drm: [drm:drm_atomic_get_plane_state] Added [PLANE:40:plane-2] 763d8809 state to 2e5cd010 > [ 36.428608] drm drm: [drm:drm_atomic_get_plane_state] Added [PLANE:44:plane-3] b6eabcf1 state to 2e5cd010 > [ 36.428617] drm drm: [drm:drm_atomic_get_plane_state] Added [PLANE:48:plane-4] 7863878c state to 2e5cd010 > [ 36.428628] drm drm: [drm:drm_atomic_get_plane_state] Added [PLANE:52:plane-5] 54b8029c state to 2e5cd010 > [ 36.428638] drm drm: [drm:drm_atomic_get_plane_state] Added [PLANE:56:plane-6] 364063af state to 2e5cd010 > [ 36.428648] drm drm: [drm:drm_atomic_get_plane_state] Added [PLANE:60:plane-7] e1c11dfb state to 2e5cd010 > [ 36.428662] drm drm: [drm:drm_atomic_get_connector_state] Added [CONNECTOR:65:HDMI-A-1] 5cb32770 state to 2e5cd010 > [ 36.428674] drm drm: [drm:drm_atomic_state_init] Allocated atomic state 832943c7 > [ 36.428682] drm drm: [drm:drm_atomic_get_crtc_state] Added [CRTC:47:crtc-0] f09cf73d state to 832943c7 > [ 36.428691] drm drm: [drm:drm_atomic_add_affected_planes] Adding all current planes for [CRTC:47:crtc-0] to 832943c7 > [ 36.428700] drm drm: [drm:drm_atomic_add_affected_connectors] Adding all current connectors for [CRTC:47:crtc-0] to 832943c7 > [ 36.428711] drm drm: [drm:drm_atomic_get_crtc_state] Added [CRTC:63:crtc-1] 2700922c state to 832943c7 > [ 36.428720] drm drm: [drm:drm_atomic_add_affected_planes] Adding all current planes for [CRTC:63:crtc-1] to 832943c7 > [ 36.428727] drm drm: [drm:drm_atomic_add_affected_connectors] Adding all current connectors for [CRTC:63:crtc-1] to 832943c7 > [ 36.428737] drm drm: [drm:drm_atomic_check_only] checking 832943c7 > [ 36.428759] drm drm: [drm:drm_atomic_commit] committing 832943c7 > [ 36.428881] drm drm: [drm:drm_atomic_state_default_clear] Clearing atomic state 832943c7 > [ 36.428897] drm drm: [drm:__drm_atomic_state_free] Freeing atomic state 832943c7 > [ 36.429085] r8169 0000:01:00.0 eth0: Link is Down > [ 36.713236] Disabling non-boot CPUs ... > -sh-5.1# > --- >8 --- > > A second attempt soft-hangs: > > --- >8 --- > -sh-5.1# rtcwake --device /dev/rtc1 --mode mem --seconds 5 > rtcwake: assuming RTC uses UTC ... > rtcwake: wakeup from "mem" using /dev/rtc1 at Thu Jan 1 00:01:10 1970 > --- >8 --- > > Where "soft-hang" means it doesn't do anything after this and I can't > SIGINT out of it or anything. However, the serial seems to still be > responsive. To clarify, this was on top of next-20250120 and reverting the patches that Jon mentioned suspend/resume is fixed for me as well. I do have a local device that I can test on, so if there's any patches you want me to try, or any options to enable to get more information, please let me know. Thanks, Thierry
Hi John, On 20/01/2025 16:34, Thierry Reding wrote: > On Mon, Jan 20, 2025 at 05:23:26PM +0100, Thierry Reding wrote: >> On Thu, Jan 16, 2025 at 10:41:08AM +0000, Jon Hunter wrote: >>> >>> On 16/01/2025 10:38, John Ogness wrote: >>>> On 2025-01-16, Jon Hunter <jonathanh@nvidia.com> wrote: >>>>>> Do you at least know if it is failing to suspend or failing to resume >>>>>> (based on power consumption)? >>>>> >>>>> >>>>> Unfortunately, I don't. These are farm boards and so nothing local I can >>>>> get my hands on. For some reason all the serial console logs are not >>>>> available and so I am going to talk to the farm team about fixing that >>>>> because we should at least have serial logs. >>>> >>>> Can you confirm that the board is actually booting? The suspend code for >>>> 8250_tegra.c is quite simple. I am wondering if the farm tests are >>>> failing somewhere else, such as the atomic printing during early boot. >>> >>> >>> Yes they are all booting fine. I have an independent boot test and that is >>> passing. It is just the suspend test that is failing. >> >> I was able to capture logs, but unfortunately they don't provide much >> insight either. On the first try it doesn't suspend and goes back to >> userspace after a second or so: >> >> --- >8 --- >> -sh-5.1# rtcwake --device /dev/rtc1 --mode mem --seconds 5 >> rtcwake: assuming RTC uses UTC ... >> rtcwake: wakeup from "mem" using /dev/rtc1 at Thu Jan 1 00:01:00 1970 >> [ 36.332486] PM: suspend entry (deep) >> [ 36.332832] Filesystems sync: 0.000 seconds >> [ 36.369331] +1.8V_RUN_CAM: disabling >> [ 36.373884] +2.8V_RUN_CAM: disabling >> [ 36.375571] +1.2V_RUN_CAM_FRONT: disabling >> [ 36.380359] +1.05V_RUN_CAM_REAR: disabling >> [ 36.387399] +3.3V_RUN_TOUCH: disabling >> [ 36.390808] +2.8V_RUN_CAM_AF: disabling >> [ 36.393621] +1.8V_RUN_VPP_FUSE: disabling >> [ 36.408218] Freezing user space processes >> [ 36.413660] Freezing user space processes completed (elapsed 0.005 seconds) >> [ 36.413680] OOM killer disabled. >> [ 36.413693] Freezing remaining freezable tasks >> [ 36.415033] Freezing remaining freezable tasks completed (elapsed 0.001 seconds) >> [ 36.428474] drm drm: [drm:drm_client_dev_suspend] fbdev: ret=0 >> [ 36.428527] drm drm: [drm:drm_atomic_state_init] Allocated atomic state 2e5cd010 >> [ 36.428547] drm drm: [drm:drm_atomic_get_crtc_state] Added [CRTC:47:crtc-0] 6a6be0ef state to 2e5cd010 >> [ 36.428561] drm drm: [drm:drm_atomic_get_crtc_state] Added [CRTC:63:crtc-1] 00d818c2 state to 2e5cd010 >> [ 36.428574] drm drm: [drm:drm_atomic_get_plane_state] Added [PLANE:32:plane-0] 4e145b7d state to 2e5cd010 >> [ 36.428587] drm drm: [drm:drm_atomic_get_plane_state] Added [PLANE:36:plane-1] dbf67d12 state to 2e5cd010 >> [ 36.428597] drm drm: [drm:drm_atomic_get_plane_state] Added [PLANE:40:plane-2] 763d8809 state to 2e5cd010 >> [ 36.428608] drm drm: [drm:drm_atomic_get_plane_state] Added [PLANE:44:plane-3] b6eabcf1 state to 2e5cd010 >> [ 36.428617] drm drm: [drm:drm_atomic_get_plane_state] Added [PLANE:48:plane-4] 7863878c state to 2e5cd010 >> [ 36.428628] drm drm: [drm:drm_atomic_get_plane_state] Added [PLANE:52:plane-5] 54b8029c state to 2e5cd010 >> [ 36.428638] drm drm: [drm:drm_atomic_get_plane_state] Added [PLANE:56:plane-6] 364063af state to 2e5cd010 >> [ 36.428648] drm drm: [drm:drm_atomic_get_plane_state] Added [PLANE:60:plane-7] e1c11dfb state to 2e5cd010 >> [ 36.428662] drm drm: [drm:drm_atomic_get_connector_state] Added [CONNECTOR:65:HDMI-A-1] 5cb32770 state to 2e5cd010 >> [ 36.428674] drm drm: [drm:drm_atomic_state_init] Allocated atomic state 832943c7 >> [ 36.428682] drm drm: [drm:drm_atomic_get_crtc_state] Added [CRTC:47:crtc-0] f09cf73d state to 832943c7 >> [ 36.428691] drm drm: [drm:drm_atomic_add_affected_planes] Adding all current planes for [CRTC:47:crtc-0] to 832943c7 >> [ 36.428700] drm drm: [drm:drm_atomic_add_affected_connectors] Adding all current connectors for [CRTC:47:crtc-0] to 832943c7 >> [ 36.428711] drm drm: [drm:drm_atomic_get_crtc_state] Added [CRTC:63:crtc-1] 2700922c state to 832943c7 >> [ 36.428720] drm drm: [drm:drm_atomic_add_affected_planes] Adding all current planes for [CRTC:63:crtc-1] to 832943c7 >> [ 36.428727] drm drm: [drm:drm_atomic_add_affected_connectors] Adding all current connectors for [CRTC:63:crtc-1] to 832943c7 >> [ 36.428737] drm drm: [drm:drm_atomic_check_only] checking 832943c7 >> [ 36.428759] drm drm: [drm:drm_atomic_commit] committing 832943c7 >> [ 36.428881] drm drm: [drm:drm_atomic_state_default_clear] Clearing atomic state 832943c7 >> [ 36.428897] drm drm: [drm:__drm_atomic_state_free] Freeing atomic state 832943c7 >> [ 36.429085] r8169 0000:01:00.0 eth0: Link is Down >> [ 36.713236] Disabling non-boot CPUs ... >> -sh-5.1# >> --- >8 --- >> >> A second attempt soft-hangs: >> >> --- >8 --- >> -sh-5.1# rtcwake --device /dev/rtc1 --mode mem --seconds 5 >> rtcwake: assuming RTC uses UTC ... >> rtcwake: wakeup from "mem" using /dev/rtc1 at Thu Jan 1 00:01:10 1970 >> --- >8 --- >> >> Where "soft-hang" means it doesn't do anything after this and I can't >> SIGINT out of it or anything. However, the serial seems to still be >> responsive. > > To clarify, this was on top of next-20250120 and reverting the patches > that Jon mentioned suspend/resume is fixed for me as well. > > I do have a local device that I can test on, so if there's any patches > you want me to try, or any options to enable to get more information, > please let me know. Any feedback on this? Our boards are still broken with this change. Thanks! Jon
On Mon 2025-01-27 14:54:25, Jon Hunter wrote: > Hi John, > > On 20/01/2025 16:34, Thierry Reding wrote: > > On Mon, Jan 20, 2025 at 05:23:26PM +0100, Thierry Reding wrote: > > > On Thu, Jan 16, 2025 at 10:41:08AM +0000, Jon Hunter wrote: > > > > > > > > On 16/01/2025 10:38, John Ogness wrote: > > > > > On 2025-01-16, Jon Hunter <jonathanh@nvidia.com> wrote: > > > > > > > Do you at least know if it is failing to suspend or failing to resume > > > > > > > (based on power consumption)? > > > > > > > > > > > > > > > > > > Unfortunately, I don't. These are farm boards and so nothing local I can > > > > > > get my hands on. For some reason all the serial console logs are not > > > > > > available and so I am going to talk to the farm team about fixing that > > > > > > because we should at least have serial logs. > > > > > > > > > > Can you confirm that the board is actually booting? The suspend code for > > > > > 8250_tegra.c is quite simple. I am wondering if the farm tests are > > > > > failing somewhere else, such as the atomic printing during early boot. > > > > > > > > > > > > Yes they are all booting fine. I have an independent boot test and that is > > > > passing. It is just the suspend test that is failing. > > > > > > I was able to capture logs, but unfortunately they don't provide much > > > insight either. On the first try it doesn't suspend and goes back to > > > userspace after a second or so: > > > > > > --- >8 --- > > > -sh-5.1# rtcwake --device /dev/rtc1 --mode mem --seconds 5 > > > rtcwake: assuming RTC uses UTC ... > > > rtcwake: wakeup from "mem" using /dev/rtc1 at Thu Jan 1 00:01:00 1970 > > > [ 36.332486] PM: suspend entry (deep) > > > [ 36.332832] Filesystems sync: 0.000 seconds > > > [ 36.369331] +1.8V_RUN_CAM: disabling > > > [ 36.373884] +2.8V_RUN_CAM: disabling > > > [ 36.375571] +1.2V_RUN_CAM_FRONT: disabling > > > [ 36.380359] +1.05V_RUN_CAM_REAR: disabling > > > [ 36.387399] +3.3V_RUN_TOUCH: disabling > > > [ 36.390808] +2.8V_RUN_CAM_AF: disabling > > > [ 36.393621] +1.8V_RUN_VPP_FUSE: disabling > > > [ 36.408218] Freezing user space processes > > > [ 36.413660] Freezing user space processes completed (elapsed 0.005 seconds) > > > [ 36.413680] OOM killer disabled. > > > [ 36.413693] Freezing remaining freezable tasks > > > [ 36.415033] Freezing remaining freezable tasks completed (elapsed 0.001 seconds) > > > [ 36.428474] drm drm: [drm:drm_client_dev_suspend] fbdev: ret=0 > > > [ 36.428527] drm drm: [drm:drm_atomic_state_init] Allocated atomic state 2e5cd010 > > > [ 36.428547] drm drm: [drm:drm_atomic_get_crtc_state] Added [CRTC:47:crtc-0] 6a6be0ef state to 2e5cd010 > > > [ 36.428561] drm drm: [drm:drm_atomic_get_crtc_state] Added [CRTC:63:crtc-1] 00d818c2 state to 2e5cd010 > > > [ 36.428574] drm drm: [drm:drm_atomic_get_plane_state] Added [PLANE:32:plane-0] 4e145b7d state to 2e5cd010 > > > [ 36.428587] drm drm: [drm:drm_atomic_get_plane_state] Added [PLANE:36:plane-1] dbf67d12 state to 2e5cd010 > > > [ 36.428597] drm drm: [drm:drm_atomic_get_plane_state] Added [PLANE:40:plane-2] 763d8809 state to 2e5cd010 > > > [ 36.428608] drm drm: [drm:drm_atomic_get_plane_state] Added [PLANE:44:plane-3] b6eabcf1 state to 2e5cd010 > > > [ 36.428617] drm drm: [drm:drm_atomic_get_plane_state] Added [PLANE:48:plane-4] 7863878c state to 2e5cd010 > > > [ 36.428628] drm drm: [drm:drm_atomic_get_plane_state] Added [PLANE:52:plane-5] 54b8029c state to 2e5cd010 > > > [ 36.428638] drm drm: [drm:drm_atomic_get_plane_state] Added [PLANE:56:plane-6] 364063af state to 2e5cd010 > > > [ 36.428648] drm drm: [drm:drm_atomic_get_plane_state] Added [PLANE:60:plane-7] e1c11dfb state to 2e5cd010 > > > [ 36.428662] drm drm: [drm:drm_atomic_get_connector_state] Added [CONNECTOR:65:HDMI-A-1] 5cb32770 state to 2e5cd010 > > > [ 36.428674] drm drm: [drm:drm_atomic_state_init] Allocated atomic state 832943c7 > > > [ 36.428682] drm drm: [drm:drm_atomic_get_crtc_state] Added [CRTC:47:crtc-0] f09cf73d state to 832943c7 > > > [ 36.428691] drm drm: [drm:drm_atomic_add_affected_planes] Adding all current planes for [CRTC:47:crtc-0] to 832943c7 > > > [ 36.428700] drm drm: [drm:drm_atomic_add_affected_connectors] Adding all current connectors for [CRTC:47:crtc-0] to 832943c7 > > > [ 36.428711] drm drm: [drm:drm_atomic_get_crtc_state] Added [CRTC:63:crtc-1] 2700922c state to 832943c7 > > > [ 36.428720] drm drm: [drm:drm_atomic_add_affected_planes] Adding all current planes for [CRTC:63:crtc-1] to 832943c7 > > > [ 36.428727] drm drm: [drm:drm_atomic_add_affected_connectors] Adding all current connectors for [CRTC:63:crtc-1] to 832943c7 > > > [ 36.428737] drm drm: [drm:drm_atomic_check_only] checking 832943c7 > > > [ 36.428759] drm drm: [drm:drm_atomic_commit] committing 832943c7 > > > [ 36.428881] drm drm: [drm:drm_atomic_state_default_clear] Clearing atomic state 832943c7 > > > [ 36.428897] drm drm: [drm:__drm_atomic_state_free] Freeing atomic state 832943c7 > > > [ 36.429085] r8169 0000:01:00.0 eth0: Link is Down > > > [ 36.713236] Disabling non-boot CPUs ... > > > -sh-5.1# > > > --- >8 --- > > > > > > A second attempt soft-hangs: > > > > > > --- >8 --- > > > -sh-5.1# rtcwake --device /dev/rtc1 --mode mem --seconds 5 > > > rtcwake: assuming RTC uses UTC ... > > > rtcwake: wakeup from "mem" using /dev/rtc1 at Thu Jan 1 00:01:10 1970 > > > --- >8 --- > > > > > > Where "soft-hang" means it doesn't do anything after this and I can't > > > SIGINT out of it or anything. However, the serial seems to still be > > > responsive. > > > > To clarify, this was on top of next-20250120 and reverting the patches > > that Jon mentioned suspend/resume is fixed for me as well. > > > > I do have a local device that I can test on, so if there's any patches > > you want me to try, or any options to enable to get more information, > > please let me know. > > > Any feedback on this? Our boards are still broken with this change. AFAIK, this patch has been reverted in linux-next last week, see https://lore.kernel.org/r/84wmenqm03.fsf@jogness.linutronix.de John had a training. I believe that he would look at these suspend-related problems before sending another revision of the patchset. Best Regards, Petr
diff --git a/drivers/tty/serial/8250/8250_core.c b/drivers/tty/serial/8250/8250_core.c index 2b70e82dffeb..3d5a2183ff13 100644 --- a/drivers/tty/serial/8250/8250_core.c +++ b/drivers/tty/serial/8250/8250_core.c @@ -388,12 +388,34 @@ void __init serial8250_register_ports(struct uart_driver *drv, struct device *de #ifdef CONFIG_SERIAL_8250_CONSOLE -static void univ8250_console_write(struct console *co, const char *s, - unsigned int count) +static void univ8250_console_write_atomic(struct console *co, + struct nbcon_write_context *wctxt) { struct uart_8250_port *up = &serial8250_ports[co->index]; - serial8250_console_write(up, s, count); + serial8250_console_write(up, wctxt, true); +} + +static void univ8250_console_write_thread(struct console *co, + struct nbcon_write_context *wctxt) +{ + struct uart_8250_port *up = &serial8250_ports[co->index]; + + serial8250_console_write(up, wctxt, false); +} + +static void univ8250_console_device_lock(struct console *co, unsigned long *flags) +{ + struct uart_port *up = &serial8250_ports[co->index].port; + + __uart_port_lock_irqsave(up, flags); +} + +static void univ8250_console_device_unlock(struct console *co, unsigned long flags) +{ + struct uart_port *up = &serial8250_ports[co->index].port; + + __uart_port_unlock_irqrestore(up, flags); } static int univ8250_console_setup(struct console *co, char *options) @@ -494,12 +516,15 @@ static int univ8250_console_match(struct console *co, char *name, int idx, static struct console univ8250_console = { .name = "ttyS", - .write = univ8250_console_write, + .write_atomic = univ8250_console_write_atomic, + .write_thread = univ8250_console_write_thread, + .device_lock = univ8250_console_device_lock, + .device_unlock = univ8250_console_device_unlock, .device = uart_console_device, .setup = univ8250_console_setup, .exit = univ8250_console_exit, .match = univ8250_console_match, - .flags = CON_PRINTBUFFER | CON_ANYTIME, + .flags = CON_PRINTBUFFER | CON_ANYTIME | CON_NBCON, .index = -1, .data = &serial8250_reg, }; diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c index d7976a21cca9..08466cf10d73 100644 --- a/drivers/tty/serial/8250/8250_port.c +++ b/drivers/tty/serial/8250/8250_port.c @@ -711,7 +711,12 @@ static void serial8250_set_sleep(struct uart_8250_port *p, int sleep) serial8250_rpm_put(p); } -static void serial8250_clear_IER(struct uart_8250_port *up) +/* + * Only to be used directly by the callback helper serial8250_console_write(), + * which may not require the port lock. Use serial8250_clear_IER() instead for + * all other cases. + */ +static void __serial8250_clear_IER(struct uart_8250_port *up) { if (up->capabilities & UART_CAP_UUE) serial_out(up, UART_IER, UART_IER_UUE); @@ -719,6 +724,11 @@ static void serial8250_clear_IER(struct uart_8250_port *up) serial_out(up, UART_IER, 0); } +static inline void serial8250_clear_IER(struct uart_8250_port *up) +{ + __serial8250_clear_IER(up); +} + #ifdef CONFIG_SERIAL_8250_RSA /* * Attempts to turn on the RSA FIFO. Returns zero on failure. @@ -1406,9 +1416,6 @@ void serial8250_em485_stop_tx(struct uart_8250_port *p, bool toggle_ier) { unsigned char mcr = serial8250_in_MCR(p); - /* Port locked to synchronize UART_IER access against the console. */ - lockdep_assert_held_once(&p->port.lock); - if (p->port.rs485.flags & SER_RS485_RTS_AFTER_SEND) mcr |= UART_MCR_RTS; else @@ -1424,6 +1431,16 @@ void serial8250_em485_stop_tx(struct uart_8250_port *p, bool toggle_ier) serial8250_clear_and_reinit_fifos(p); if (toggle_ier) { + /* + * Port locked to synchronize UART_IER access against + * the console. The lockdep_assert must be restricted + * to this condition because only here is it + * guaranteed that the port lock is held. The other + * hardware access in this function is synchronized + * by console ownership. + */ + lockdep_assert_held_once(&p->port.lock); + p->ier |= UART_IER_RLSI | UART_IER_RDI; serial_port_out(&p->port, UART_IER, p->ier); } @@ -3303,7 +3320,11 @@ EXPORT_SYMBOL_GPL(serial8250_set_defaults); static void serial8250_console_putchar(struct uart_port *port, unsigned char ch) { + struct uart_8250_port *up = up_to_u8250p(port); + serial_port_out(port, UART_TX, ch); + + up->console_line_ended = (ch == '\n'); } static void serial8250_console_wait_putchar(struct uart_port *port, unsigned char ch) @@ -3340,11 +3361,22 @@ static void serial8250_console_restore(struct uart_8250_port *up) serial8250_out_MCR(up, up->mcr | UART_MCR_DTR | UART_MCR_RTS); } -static void fifo_wait_for_lsr(struct uart_8250_port *up, unsigned int count) +static void fifo_wait_for_lsr(struct uart_8250_port *up, + struct nbcon_write_context *wctxt, + unsigned int count) { unsigned int i; for (i = 0; i < count; i++) { + /* + * Pass the ownership as quickly as possible to a higher + * priority context. Otherwise, its attempt to take over + * the ownership might timeout. The new owner will wait + * for UART_LSR_THRE before reusing the fifo. + */ + if (!nbcon_can_proceed(wctxt)) + return; + if (wait_for_lsr(up, UART_LSR_THRE)) return; } @@ -3357,20 +3389,29 @@ static void fifo_wait_for_lsr(struct uart_8250_port *up, unsigned int count) * to get empty. */ static void serial8250_console_fifo_write(struct uart_8250_port *up, - const char *s, unsigned int count) + struct nbcon_write_context *wctxt) { - const char *end = s + count; unsigned int fifosize = up->tx_loadsz; struct uart_port *port = &up->port; + const char *s = wctxt->outbuf; + const char *end = s + wctxt->len; unsigned int tx_count = 0; bool cr_sent = false; unsigned int i; while (s != end) { /* Allow timeout for each byte of a possibly full FIFO */ - fifo_wait_for_lsr(up, fifosize); + fifo_wait_for_lsr(up, wctxt, fifosize); + /* + * Fill the FIFO. If a handover or takeover occurs, writing + * must be aborted since wctxt->outbuf and wctxt->len are no + * longer valid. + */ for (i = 0; i < fifosize && s != end; ++i) { + if (!nbcon_enter_unsafe(wctxt)) + return; + if (*s == '\n' && !cr_sent) { serial8250_console_putchar(port, '\r'); cr_sent = true; @@ -3378,6 +3419,8 @@ static void serial8250_console_fifo_write(struct uart_8250_port *up, serial8250_console_putchar(port, *s++); cr_sent = false; } + + nbcon_exit_unsafe(wctxt); } tx_count = i; } @@ -3386,39 +3429,57 @@ static void serial8250_console_fifo_write(struct uart_8250_port *up, * Allow timeout for each byte written since the caller will only wait * for UART_LSR_BOTH_EMPTY using the timeout of a single character */ - fifo_wait_for_lsr(up, tx_count); + fifo_wait_for_lsr(up, wctxt, tx_count); +} + +static void serial8250_console_byte_write(struct uart_8250_port *up, + struct nbcon_write_context *wctxt) +{ + struct uart_port *port = &up->port; + const char *s = wctxt->outbuf; + const char *end = s + wctxt->len; + + /* + * Write out the message. If a handover or takeover occurs, writing + * must be aborted since wctxt->outbuf and wctxt->len are no longer + * valid. + */ + while (s != end) { + if (!nbcon_enter_unsafe(wctxt)) + return; + + uart_console_write(port, s++, 1, serial8250_console_wait_putchar); + + nbcon_exit_unsafe(wctxt); + } } /* - * Print a string to the serial port trying not to disturb - * any possible real use of the port... - * - * The console_lock must be held when we get here. + * Print a string to the serial port trying not to disturb + * any possible real use of the port... * - * Doing runtime PM is really a bad idea for the kernel console. - * Thus, we assume the function is called when device is powered up. + * Doing runtime PM is really a bad idea for the kernel console. + * Thus, assume it is called when device is powered up. */ -void serial8250_console_write(struct uart_8250_port *up, const char *s, - unsigned int count) +void serial8250_console_write(struct uart_8250_port *up, + struct nbcon_write_context *wctxt, + bool is_atomic) { struct uart_8250_em485 *em485 = up->em485; struct uart_port *port = &up->port; - unsigned long flags; - unsigned int ier, use_fifo; - int locked = 1; - - touch_nmi_watchdog(); + unsigned int ier; + bool use_fifo; - if (oops_in_progress) - locked = uart_port_trylock_irqsave(port, &flags); - else - uart_port_lock_irqsave(port, &flags); + if (!nbcon_enter_unsafe(wctxt)) + return; /* - * First save the IER then disable the interrupts + * First, save the IER, then disable the interrupts. The special + * variant to clear the IER is used because console printing may + * occur without holding the port lock. */ ier = serial_port_in(port, UART_IER); - serial8250_clear_IER(up); + __serial8250_clear_IER(up); /* check scratch reg to see if port powered off during system sleep */ if (up->canary && (up->canary != serial_port_in(port, UART_SCR))) { @@ -3432,6 +3493,18 @@ void serial8250_console_write(struct uart_8250_port *up, const char *s, mdelay(port->rs485.delay_rts_before_send); } + /* If ownership was lost, no writing is allowed */ + if (!nbcon_can_proceed(wctxt)) + goto skip_write; + + /* + * If console printer did not fully output the previous line, it must + * have been handed or taken over. Insert a newline in order to + * maintain clean output. + */ + if (!up->console_line_ended) + uart_console_write(port, "\n", 1, serial8250_console_wait_putchar); + use_fifo = (up->capabilities & UART_CAP_FIFO) && /* * BCM283x requires to check the fifo @@ -3452,10 +3525,23 @@ void serial8250_console_write(struct uart_8250_port *up, const char *s, */ !(up->port.flags & UPF_CONS_FLOW); + nbcon_exit_unsafe(wctxt); + if (likely(use_fifo)) - serial8250_console_fifo_write(up, s, count); + serial8250_console_fifo_write(up, wctxt); else - uart_console_write(port, s, count, serial8250_console_wait_putchar); + serial8250_console_byte_write(up, wctxt); +skip_write: + /* + * If ownership was lost, this context must reacquire ownership and + * re-enter the unsafe section in order to perform final actions + * (such as re-enabling interrupts). + */ + if (!nbcon_can_proceed(wctxt)) { + do { + nbcon_reacquire_nobuf(wctxt); + } while (!nbcon_enter_unsafe(wctxt)); + } /* * Finally, wait for transmitter to become empty @@ -3478,11 +3564,18 @@ void serial8250_console_write(struct uart_8250_port *up, const char *s, * call it if we have saved something in the saved flags * while processing with interrupts off. */ - if (up->msr_saved_flags) - serial8250_modem_status(up); + if (up->msr_saved_flags) { + /* + * For atomic, it must be deferred to irq_work because this + * may be a context that does not permit waking up tasks. + */ + if (is_atomic) + irq_work_queue(&up->modem_status_work); + else + serial8250_modem_status(up); + } - if (locked) - uart_port_unlock_irqrestore(port, flags); + nbcon_exit_unsafe(wctxt); } static unsigned int probe_baud(struct uart_port *port) @@ -3500,8 +3593,24 @@ static unsigned int probe_baud(struct uart_port *port) return (port->uartclk / 16) / quot; } +/* + * irq_work handler to perform modem control. Only triggered via + * ->write_atomic() callback because it may be in a scheduler or + * NMI context, unable to wake tasks. + */ +static void modem_status_handler(struct irq_work *iwp) +{ + struct uart_8250_port *up = container_of(iwp, struct uart_8250_port, modem_status_work); + struct uart_port *port = &up->port; + + uart_port_lock(port); + serial8250_modem_status(up); + uart_port_unlock(port); +} + int serial8250_console_setup(struct uart_port *port, char *options, bool probe) { + struct uart_8250_port *up = up_to_u8250p(port); int baud = 9600; int bits = 8; int parity = 'n'; @@ -3511,6 +3620,9 @@ int serial8250_console_setup(struct uart_port *port, char *options, bool probe) if (!port->iobase && !port->membase) return -ENODEV; + up->console_line_ended = true; + init_irq_work(&up->modem_status_work, modem_status_handler); + if (options) uart_parse_options(options, &baud, &parity, &bits, &flow); else if (probe) diff --git a/include/linux/serial_8250.h b/include/linux/serial_8250.h index 144de7a7948d..57875c37023a 100644 --- a/include/linux/serial_8250.h +++ b/include/linux/serial_8250.h @@ -150,8 +150,17 @@ struct uart_8250_port { #define LSR_SAVE_FLAGS UART_LSR_BRK_ERROR_BITS u16 lsr_saved_flags; u16 lsr_save_mask; + + /* + * Track when a console line has been fully written to the + * hardware, i.e. true when the most recent byte written to + * UART_TX by the console was '\n'. + */ + bool console_line_ended; + #define MSR_SAVE_FLAGS UART_MSR_ANY_DELTA unsigned char msr_saved_flags; + struct irq_work modem_status_work; struct uart_8250_dma *dma; const struct uart_8250_ops *ops; @@ -202,8 +211,8 @@ void serial8250_tx_chars(struct uart_8250_port *up); unsigned int serial8250_modem_status(struct uart_8250_port *up); void serial8250_init_port(struct uart_8250_port *up); void serial8250_set_defaults(struct uart_8250_port *up); -void serial8250_console_write(struct uart_8250_port *up, const char *s, - unsigned int count); +void serial8250_console_write(struct uart_8250_port *up, + struct nbcon_write_context *wctxt, bool in_atomic); int serial8250_console_setup(struct uart_port *port, char *options, bool probe); int serial8250_console_exit(struct uart_port *port);
Implement the necessary callbacks to switch the 8250 console driver to perform as an nbcon console. Add implementations for the nbcon console callbacks: ->write_atomic() ->write_thread() ->device_lock() ->device_unlock() and add CON_NBCON to the initial @flags. All register access in the callbacks are within unsafe sections. The ->write_atomic() and ->write_thread() callbacks allow safe handover/takeover per byte and add a preceding newline if they take over from another context mid-line. For the ->write_atomic() callback, a new irq_work is used to defer modem control since it may be called from a context that does not allow waking up tasks. Note: A new __serial8250_clear_IER() is introduced for direct clearing of UART_IER. This will allow to restore the lockdep check to serial8250_clear_IER() in a follow-up commit. Signed-off-by: John Ogness <john.ogness@linutronix.de> --- drivers/tty/serial/8250/8250_core.c | 35 +++++- drivers/tty/serial/8250/8250_port.c | 180 ++++++++++++++++++++++------ include/linux/serial_8250.h | 13 +- 3 files changed, 187 insertions(+), 41 deletions(-)