diff options
author | Michael Sevakis <jethead71@rockbox.org> | 2017-03-15 01:51:54 -0400 |
---|---|---|
committer | Michael Sevakis <jethead71@rockbox.org> | 2017-10-26 14:35:41 -0400 |
commit | 1654efc31339972d0e6bd41a499fcffc0a45822e (patch) | |
tree | 5fb7f59ab918a3694608bb1138c2c52fb47698c3 /firmware/target/arm/imx233/sdmmc-imx233.c | |
parent | 7807934a271e9eb7b045cdcd89ba70fb59a91d69 (diff) | |
download | rockbox-1654efc31339972d0e6bd41a499fcffc0a45822e.tar.gz rockbox-1654efc31339972d0e6bd41a499fcffc0a45822e.zip |
Unify storage threads into one
* Editing a bunch of drivers' thread routines in order to
implement a new feature is tedious.
* No matter the number of storage drivers, they share one thread.
No extra threads needed for CONFIG_STORAGE_MULTI.
* Each has an event callback called by the storage thread.
* A default callback is provided to fake sleeping in order to
trigger idle callbacks. It could also do other default processing.
Changes to it will be part of driver code without editing each
one.
* Drivers may sleep and wake as they please as long as they give
a low pulse on their storage bit to ask to go into sleep mode.
Idle callback is called on its behalf and driver immediately put
into sleep mode.
* Drivers may indicate they are to continue receiving events in
USB mode, otherwise they receve nothing until disconnect (they
do receive SYS_USB_DISCONNECTED no matter what).
* Rework a few things to keep the callback implementation sane
and maintainable. ata.c was dreadful with all those bools; make
it a state machine and easier to follow. Remove last_user_activity;
it has no purpose that isn't served by keeping the disk active
through last_disk_activity instead.
* Even-out stack sizes partly because of a lack of a decent place
to define them by driver or SoC or whatever; it doesn't seem too
critical to do that anyway. Many are simply too large while at
least one isn't really adequate. They may be individually
overridden if necessary (figure out where). The thread uses the
greatest size demanded. Newer file code is much more frugal with
stack space. I barely see use crack 50% after idle callbacks
(usually mid-40s). Card insert/eject doesn't demand much.
* No forcing of idle callbacks. If it isn't necessary for one or
more non-disk storage types, it really isn't any more necessary for
disk storage. Besides, it makes the whole thing easier to implement.
Change-Id: Id30c284d82a8af66e47f2cfe104c52cbd8aa7215
Diffstat (limited to 'firmware/target/arm/imx233/sdmmc-imx233.c')
-rw-r--r-- | firmware/target/arm/imx233/sdmmc-imx233.c | 190 |
1 files changed, 81 insertions, 109 deletions
diff --git a/firmware/target/arm/imx233/sdmmc-imx233.c b/firmware/target/arm/imx233/sdmmc-imx233.c index d3dabafecb..af090e8a07 100644 --- a/firmware/target/arm/imx233/sdmmc-imx233.c +++ b/firmware/target/arm/imx233/sdmmc-imx233.c | |||
@@ -217,9 +217,6 @@ static struct sdmmc_status_t sdmmc_status[SDMMC_NUM_DRIVES]; | |||
217 | #define SDMMC_STATUS(drive) sdmmc_status[drive] | 217 | #define SDMMC_STATUS(drive) sdmmc_status[drive] |
218 | 218 | ||
219 | /* sd only */ | 219 | /* sd only */ |
220 | static long sdmmc_stack[(DEFAULT_STACK_SIZE*2 + 0x200)/sizeof(long)]; | ||
221 | static const char sdmmc_thread_name[] = "sdmmc"; | ||
222 | static struct event_queue sdmmc_queue; | ||
223 | #if CONFIG_STORAGE & STORAGE_SD | 220 | #if CONFIG_STORAGE & STORAGE_SD |
224 | static int sd_first_drive; | 221 | static int sd_first_drive; |
225 | static unsigned _sd_num_drives; | 222 | static unsigned _sd_num_drives; |
@@ -260,10 +257,38 @@ static void sdmmc_detect_callback(int ssp) | |||
260 | { | 257 | { |
261 | /* This is called only if the state was stable for 300ms - check state | 258 | /* This is called only if the state was stable for 300ms - check state |
262 | * and post appropriate event. */ | 259 | * and post appropriate event. */ |
263 | if(imx233_ssp_sdmmc_detect(ssp)) | 260 | long evid = imx233_ssp_sdmmc_detect(ssp) ? |
264 | queue_broadcast(SYS_HOTSWAP_INSERTED, 0); | 261 | SYS_HOTSWAP_INSERTED : SYS_HOTSWAP_EXTRACTED; |
265 | else | 262 | |
266 | queue_broadcast(SYS_HOTSWAP_EXTRACTED, 0); | 263 | /* Have to reverse lookup the ssp */ |
264 | for (unsigned drive = 0; drive < SDMMC_NUM_DRIVES; drive++) | ||
265 | { | ||
266 | if (SDMMC_SSP(drive) != ssp) | ||
267 | continue; | ||
268 | |||
269 | int first_drive, *map; | ||
270 | switch (SDMMC_MODE(drive)) | ||
271 | { | ||
272 | #if (CONFIG_STORAGE & STORAGE_MMC) | ||
273 | case MMC_MODE: | ||
274 | first_drive = mmc_first_drive; | ||
275 | map = mmc_map; | ||
276 | break; | ||
277 | #endif | ||
278 | #if (CONFIG_STORAGE & STORAGE_SD) | ||
279 | case SD_MODE: | ||
280 | first_drive = sd_first_drive; | ||
281 | map = sd_map; | ||
282 | break; | ||
283 | #endif | ||
284 | default: | ||
285 | continue; | ||
286 | } | ||
287 | |||
288 | /* message requires logical drive number as data */ | ||
289 | queue_broadcast(evid, first_drive + map[drive]); | ||
290 | } | ||
291 | |||
267 | imx233_ssp_sdmmc_setup_detect(ssp, true, sdmmc_detect_callback, false, | 292 | imx233_ssp_sdmmc_setup_detect(ssp, true, sdmmc_detect_callback, false, |
268 | imx233_ssp_sdmmc_is_detect_inverted(ssp)); | 293 | imx233_ssp_sdmmc_is_detect_inverted(ssp)); |
269 | } | 294 | } |
@@ -483,7 +508,48 @@ static int init_sd_card(int drive) | |||
483 | 508 | ||
484 | return 0; | 509 | return 0; |
485 | } | 510 | } |
486 | #endif | 511 | |
512 | int sd_event(long id, intptr_t data) | ||
513 | { | ||
514 | int rc = 0; | ||
515 | |||
516 | switch (id) | ||
517 | { | ||
518 | #ifdef HAVE_HOTSWAP | ||
519 | case SYS_HOTSWAP_INSERTED: | ||
520 | case SYS_HOTSWAP_EXTRACTED:; | ||
521 | const int drive = sd_map[data]; | ||
522 | |||
523 | /* Skip non-removable drivers */ | ||
524 | if(!sdmmc_removable(drive)) | ||
525 | { | ||
526 | rc = -1; | ||
527 | break; | ||
528 | } | ||
529 | |||
530 | mutex_lock(&mutex[drive]); /* lock-out card activity */ | ||
531 | |||
532 | /* Force card init for new card, re-init for re-inserted one or | ||
533 | * clear if the last attempt to init failed with an error. */ | ||
534 | SDMMC_INFO(drive).initialized = 0; | ||
535 | |||
536 | if(id == SYS_HOTSWAP_INSERTED) | ||
537 | rc = init_drive(drive); | ||
538 | |||
539 | /* unlock card */ | ||
540 | mutex_unlock(&mutex[drive]); | ||
541 | /* Access is now safe */ | ||
542 | break; | ||
543 | #endif /* HAVE_HOTSWAP */ | ||
544 | default: | ||
545 | rc = storage_event_default_handler(id, data, sd_last_disk_activity(), | ||
546 | STORAGE_SD); | ||
547 | break; | ||
548 | } | ||
549 | |||
550 | return rc; | ||
551 | } | ||
552 | #endif /* CONFIG_STORAGE & STORAGE_SD */ | ||
487 | 553 | ||
488 | #if CONFIG_STORAGE & STORAGE_MMC | 554 | #if CONFIG_STORAGE & STORAGE_MMC |
489 | static int init_mmc_drive(int drive) | 555 | static int init_mmc_drive(int drive) |
@@ -573,7 +639,13 @@ static int init_mmc_drive(int drive) | |||
573 | 639 | ||
574 | return 0; | 640 | return 0; |
575 | } | 641 | } |
576 | #endif | 642 | |
643 | int mmc_event(long id, intptr_t data) | ||
644 | { | ||
645 | return storage_event_default_handler(id, data, mmc_last_disk_activity(), | ||
646 | STORAGE_MMC); | ||
647 | } | ||
648 | #endif /* CONFIG_STORAGE & STORAGE_MMC */ | ||
577 | 649 | ||
578 | /* low-level function, don't call directly! */ | 650 | /* low-level function, don't call directly! */ |
579 | static int __xfer_sectors(int drive, unsigned long start, int count, void *buf, bool read) | 651 | static int __xfer_sectors(int drive, unsigned long start, int count, void *buf, bool read) |
@@ -770,98 +842,6 @@ static int init_drive(int drive) | |||
770 | return 0; | 842 | return 0; |
771 | } | 843 | } |
772 | 844 | ||
773 | static void sdmmc_thread(void) NORETURN_ATTR; | ||
774 | static void sdmmc_thread(void) | ||
775 | { | ||
776 | struct queue_event ev; | ||
777 | bool idle_notified = false; | ||
778 | int timeout = 0; | ||
779 | |||
780 | while (1) | ||
781 | { | ||
782 | queue_wait_w_tmo(&sdmmc_queue, &ev, HZ); | ||
783 | |||
784 | switch(ev.id) | ||
785 | { | ||
786 | #if CONFIG_STORAGE & STORAGE_SD | ||
787 | case SYS_HOTSWAP_INSERTED: | ||
788 | case SYS_HOTSWAP_EXTRACTED: | ||
789 | { | ||
790 | int microsd_init = ev.id == SYS_HOTSWAP_INSERTED ? 0 : 1; | ||
791 | |||
792 | /* We now have exclusive control of fat cache and sd. | ||
793 | * Release "by force", ensure file | ||
794 | * descriptors aren't leaked and any busy | ||
795 | * ones are invalid if mounting. */ | ||
796 | for(unsigned sd_drive = 0; sd_drive < _sd_num_drives; sd_drive++) | ||
797 | { | ||
798 | int drive = sd_map[sd_drive]; | ||
799 | /* Skip non-removable drivers */ | ||
800 | if(!sdmmc_removable(drive)) | ||
801 | continue; | ||
802 | |||
803 | disk_unmount(sd_first_drive + sd_drive); | ||
804 | |||
805 | mutex_lock(&mutex[drive]); /* lock-out card activity */ | ||
806 | |||
807 | /* Force card init for new card, re-init for re-inserted one or | ||
808 | * clear if the last attempt to init failed with an error. */ | ||
809 | SDMMC_INFO(sd_map[sd_drive]).initialized = 0; | ||
810 | |||
811 | int rc = -1; | ||
812 | if(ev.id == SYS_HOTSWAP_INSERTED) | ||
813 | { | ||
814 | rc = init_drive(drive); | ||
815 | if(rc < 0) /* initialisation failed */ | ||
816 | panicf("%s init failed : %d", SDMMC_CONF(sd_map[sd_drive]).name, rc); | ||
817 | } | ||
818 | |||
819 | /* unlock card */ | ||
820 | mutex_unlock(&mutex[drive]); | ||
821 | |||
822 | if (rc >= 0) | ||
823 | microsd_init += disk_mount(sd_first_drive + sd_drive); /* 0 if fail */ | ||
824 | } | ||
825 | /* Access is now safe */ | ||
826 | /* | ||
827 | * One or more mounts succeeded, or this was an EXTRACTED event, | ||
828 | * in both cases notify the system about the changed filesystems | ||
829 | */ | ||
830 | if(microsd_init) | ||
831 | queue_broadcast(SYS_FS_CHANGED, 0); | ||
832 | |||
833 | break; | ||
834 | } | ||
835 | #endif | ||
836 | case SYS_TIMEOUT: | ||
837 | #if CONFIG_STORAGE & STORAGE_SD | ||
838 | timeout = MAX(timeout, sd_last_disk_activity()+(3*HZ)); | ||
839 | #endif | ||
840 | #if CONFIG_STORAGE & STORAGE_MMC | ||
841 | timeout = MAX(timeout, mmc_last_disk_activity()+(3*HZ)); | ||
842 | #endif | ||
843 | if(TIME_BEFORE(current_tick, timeout)) | ||
844 | { | ||
845 | idle_notified = false; | ||
846 | } | ||
847 | else | ||
848 | { | ||
849 | if(!idle_notified) | ||
850 | { | ||
851 | call_storage_idle_notifys(false); | ||
852 | idle_notified = true; | ||
853 | } | ||
854 | } | ||
855 | break; | ||
856 | case SYS_USB_CONNECTED: | ||
857 | usb_acknowledge(SYS_USB_CONNECTED_ACK); | ||
858 | /* Wait until the USB cable is extracted again */ | ||
859 | usb_wait_for_disconnect(&sdmmc_queue); | ||
860 | break; | ||
861 | } | ||
862 | } | ||
863 | } | ||
864 | |||
865 | static int sdmmc_init(void) | 845 | static int sdmmc_init(void) |
866 | { | 846 | { |
867 | static int is_initialized = false; | 847 | static int is_initialized = false; |
@@ -871,10 +851,6 @@ static int sdmmc_init(void) | |||
871 | for(unsigned drive = 0; drive < SDMMC_NUM_DRIVES; drive++) | 851 | for(unsigned drive = 0; drive < SDMMC_NUM_DRIVES; drive++) |
872 | mutex_init(&mutex[drive]); | 852 | mutex_init(&mutex[drive]); |
873 | 853 | ||
874 | queue_init(&sdmmc_queue, true); | ||
875 | create_thread(sdmmc_thread, sdmmc_stack, sizeof(sdmmc_stack), 0, | ||
876 | sdmmc_thread_name IF_PRIO(, PRIORITY_USER_INTERFACE) IF_COP(, CPU)); | ||
877 | |||
878 | for(unsigned drive = 0; drive < SDMMC_NUM_DRIVES; drive++) | 854 | for(unsigned drive = 0; drive < SDMMC_NUM_DRIVES; drive++) |
879 | { | 855 | { |
880 | if(sdmmc_removable(drive)) | 856 | if(sdmmc_removable(drive)) |
@@ -1024,10 +1000,6 @@ void mmc_enable(bool on) | |||
1024 | (void) on; | 1000 | (void) on; |
1025 | } | 1001 | } |
1026 | 1002 | ||
1027 | void mmc_sleep(void) | ||
1028 | { | ||
1029 | } | ||
1030 | |||
1031 | void mmc_sleepnow(void) | 1003 | void mmc_sleepnow(void) |
1032 | { | 1004 | { |
1033 | } | 1005 | } |