From 79329c8f7cc8ae3092c6b1a89f43d7f66a12a468 Mon Sep 17 00:00:00 2001 From: Marcin Bukat Date: Thu, 24 Sep 2026 00:30:51 +0200 Subject: [PATCH] rk27xx: don't return from SD transfers with the lock held sd_read_sectors() and sd_write_sectors() take sd_mtx and power the controller, then check the requested range and return -1 on failure - leaving the mutex held and the controller on. Check the range first. With no card present numblocks is 0, so every request takes that path. Rockbox mutexes are recursive for the owning thread, so the first thread to touch the SD drive keeps working, and every other thread that does blocks forever. Co-Authored-By: Claude Opus 5.5 Change-Id: I16c2be3bde5c62946fdedaabe115b6c4bc330467 --- firmware/target/arm/rk27xx/sd-rk27xx.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/firmware/target/arm/rk27xx/sd-rk27xx.c b/firmware/target/arm/rk27xx/sd-rk27xx.c index a49e8e5c43..02180d9faa 100644 --- a/firmware/target/arm/rk27xx/sd-rk27xx.c +++ b/firmware/target/arm/rk27xx/sd-rk27xx.c @@ -464,12 +464,15 @@ int sd_read_sectors(IF_MD(int drive,) sector_t start, int count, int cnt, ret = 0; unsigned char *dst; - mutex_lock(&sd_mtx); - enable_controller(true); - + /* Checked before taking the lock: returning from after it left sd_mtx + * held and the controller powered. With no card numblocks is 0, so + * that was every request. */ if (count <= 0 || start + count > card_info.numblocks) return -1; + mutex_lock(&sd_mtx); + enable_controller(true); + if(!(card_info.ocr & (1<<30))) start <<= 9; /* not SDHC */ @@ -602,12 +605,15 @@ int sd_write_sectors(IF_MD(int drive,) sector_t start, int count, unsigned char *src; /* bool card_selected = false; */ - mutex_lock(&sd_mtx); - enable_controller(true); - + /* Checked before taking the lock: returning from after it left sd_mtx + * held and the controller powered. With no card numblocks is 0, so + * that was every request. */ if (count <= 0 || start + count > card_info.numblocks) return -1; + mutex_lock(&sd_mtx); + enable_controller(true); + if(!(card_info.ocr & (1<<30))) start <<= 9; /* not SDHC */