FelipeMdeO opened a new pull request, #19740:
URL: https://github.com/apache/nuttx/pull/19740

   ## Summary
   
   This PR Fixes https://github.com/apache/nuttx/issues/18541
   
   `cdcuart_txempty()` in `drivers/usbdev/cdcacm.c` takes `priv->lock` to check
   `dev->disconnected`, and on the connected path falls through to a second
   `spin_lock_irqsave()` on the same lock without ever releasing the first one.
   `priv->lock` is not recursive, so on SMP the CPU wedges there.
   
   ## Impact
   
   * Is new feature added? No — bug fix.
   * Impact on user: Yes. Any SMP build using CDC/ACM deadlocks on the first
     write to the device once the host has enumerated it. Besides the hang there
     is **silent data loss**: on a 4 KB burst the write reports success while 
the
     tail never reaches the host (see Testing).
   * Impact on build: No.
   * Impact on hardware: SMP configurations only. Non-SMP builds are unaffected
     (the spinlock degenerates to an interrupt mask there).
   * Impact on documentation: No.
   * Impact on security: No.
   * Impact on compatibility: No.
   
   ## Testing
   
   **Build host:** Linux x86_64, GCC (xtensa-esp32s3-elf).
   
   **Target:** ESP32-S3-DevKitC-1, `esp32s3-devkit:nsh` plus `SMP=2`,
   `ARCH_SETJMP_H`, `SCHED_THREAD_LOCAL`, `ESP32S3_OTG`, `CDCACM`,
   `SYSTEM_CDCACM`, `SERIAL_REMOVABLE`, `DEBUG_ASSERTIONS`, `SCHED_BACKTRACE`.
   No in-tree config combines SMP with CDC/ACM, so the combination has to be
   enabled by hand.
   
   Host enumeration is required to reproduce: without it `dev->disconnected` is
   true and `cdcuart_txempty()` returns early, never reaching the second lock.
   
   Same board, same config, same driving script; only `drivers/usbdev/cdcacm.c`
   differs. The burst has to be the first write after `sercon`, since on the
   unfixed build the small `echo` already wedges the console before we get 
there.
   
   | Test on the target | Before (master) | After |
   | --- | --- | --- |
   | `echo '1' > /dev/ttyACM0` | console dead, no further input | works, 
console alive |
   | `taskset 1 "echo '1' > /dev/ttyACM0"` | console dead | works, console 
alive |
   | `dd if=/dev/zero of=/dev/ttyACM0 bs=512 count=8` | `dd` reports 4096 bytes 
copied, only **3968** arrive on the host, console dead | **4096** bytes arrive, 
console alive |
   
   The 128 missing bytes in the "before" column are the interesting part: the
   write path reports success, so the data loss is silent.
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to