On 15/7/26 18:07, Tao Ding wrote:
During SDMA transfers, the controller raises an interrupt at buffer boundaries
to request a system address update. The host driver will rewrite the SDHC_SYSAD 
register.
(according to PartA2_SD_Host_Controller_Simplified_Specification_Ver2.00.pdf 
section 2.2.1)
However, the current code will ignore write operations to SDHC_SYSAD.

To fix this bug, when SDMA encounters a boundary, a state is set to record it.
In this state, SDHC_SYSAD can be written. In other cases, it is still protected 
by TRANSFERRING_DATA.

Meanwhile, a subsection has been added for migration.

Suggested-by: Bin Meng <[email protected]>
Signed-off-by: Tao Ding <[email protected]>
---


+static bool sdhci_sdma_transfer_active(SDHCIState *s)
+{
+    return TRANSFERRING_DATA(s->prnsts) &&
+            (s->trnmod & SDHC_TRNS_DMA) &&
+            s->blkcnt &&
+            (s->blksize & BLOCK_SIZE_MASK) &&
+            SDHC_DMA_TYPE(s->hostctl1) == SDHC_CTRL_SDMA;
+}

@@ -1185,7 +1198,7 @@ sdhci_write(void *opaque, hwaddr offset, uint64_t val, 
unsigned size)
switch (offset & ~0x3) {
      case SDHC_SYSAD:
-        if (!TRANSFERRING_DATA(s->prnsts)) {
+        if (!TRANSFERRING_DATA(s->prnsts) || s->sdma_boundary_paused) {
              s->sdmasysad = (s->sdmasysad & mask) | value;
              MASKED_WRITE(s->sdmasysad, mask, value);
              /* Writing to last byte of sdmasysad might trigger transfer */

So the SYSAD write-protection guard didn't account for the
boundary-pause state, silently dropping the driver's continuation write
and stalling SDMA transfers forever once a boundary was crossed, OK.

Series queued!

Reply via email to