diff options
author | Michael Sevakis <jethead71@rockbox.org> | 2008-03-12 10:03:52 +0000 |
---|---|---|
committer | Michael Sevakis <jethead71@rockbox.org> | 2008-03-12 10:03:52 +0000 |
commit | 06a5299aff38ba25c7742ae6293c588e38445f8b (patch) | |
tree | 5f8c3121882ba9c8d6317d1ce7fb5a07d3a99f5c | |
parent | 2f5a37de5c45333453169ffe0b90e0f380d1cd50 (diff) | |
download | rockbox-06a5299aff38ba25c7742ae6293c588e38445f8b.tar.gz rockbox-06a5299aff38ba25c7742ae6293c588e38445f8b.zip |
Do some crackdown on kernel object reinitialization after they could be in use and use before initialization. For c200/e200: Be sure fat cache and ata locks are acquired in the proper order during hot swapping. Delay hotswap monitoring until after initial file mounting (address 2nd kobj concern + possible call of fat driver before init).
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@16636 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r-- | firmware/common/disk.c | 5 | ||||
-rw-r--r-- | firmware/drivers/audio/as3514.c | 3 | ||||
-rw-r--r-- | firmware/drivers/fat.c | 19 | ||||
-rw-r--r-- | firmware/export/fat.h | 4 | ||||
-rw-r--r-- | firmware/target/arm/i2c-pp.c | 3 | ||||
-rw-r--r-- | firmware/target/arm/sandisk/ata-c200_e200.c | 65 | ||||
-rw-r--r-- | firmware/target/arm/wmcodec-pp.c | 3 |
7 files changed, 73 insertions, 29 deletions
diff --git a/firmware/common/disk.c b/firmware/common/disk.c index 3d4dd3dc1d..c6200ba286 100644 --- a/firmware/common/disk.c +++ b/firmware/common/disk.c | |||
@@ -104,7 +104,7 @@ int disk_mount_all(void) | |||
104 | int mounted; | 104 | int mounted; |
105 | int i; | 105 | int i; |
106 | 106 | ||
107 | #ifdef HAVE_MMC | 107 | #if defined(HAVE_MMC) || defined(HAVE_HOTSWAP) |
108 | card_enable_monitoring(false); | 108 | card_enable_monitoring(false); |
109 | #endif | 109 | #endif |
110 | 110 | ||
@@ -118,10 +118,9 @@ int disk_mount_all(void) | |||
118 | { | 118 | { |
119 | mounted += disk_mount(1); /* try 2nd "drive", too */ | 119 | mounted += disk_mount(1); /* try 2nd "drive", too */ |
120 | } | 120 | } |
121 | #ifdef HAVE_MMC | 121 | |
122 | card_enable_monitoring(true); | 122 | card_enable_monitoring(true); |
123 | #endif | 123 | #endif |
124 | #endif | ||
125 | 124 | ||
126 | return mounted; | 125 | return mounted; |
127 | } | 126 | } |
diff --git a/firmware/drivers/audio/as3514.c b/firmware/drivers/audio/as3514.c index 08d4d538a4..d51341d8c3 100644 --- a/firmware/drivers/audio/as3514.c +++ b/firmware/drivers/audio/as3514.c | |||
@@ -132,9 +132,6 @@ void audiohw_init(void) | |||
132 | { | 132 | { |
133 | unsigned int i; | 133 | unsigned int i; |
134 | 134 | ||
135 | /* reset I2C */ | ||
136 | i2c_init(); | ||
137 | |||
138 | /* normal outputs for CDI and I2S pin groups */ | 135 | /* normal outputs for CDI and I2S pin groups */ |
139 | DEV_INIT2 &= ~0x300; | 136 | DEV_INIT2 &= ~0x300; |
140 | 137 | ||
diff --git a/firmware/drivers/fat.c b/firmware/drivers/fat.c index 9dd27cf72a..f3374fc4c4 100644 --- a/firmware/drivers/fat.c +++ b/firmware/drivers/fat.c | |||
@@ -172,6 +172,7 @@ struct bpb | |||
172 | }; | 172 | }; |
173 | 173 | ||
174 | static struct bpb fat_bpbs[NUM_VOLUMES]; /* mounted partition info */ | 174 | static struct bpb fat_bpbs[NUM_VOLUMES]; /* mounted partition info */ |
175 | static bool initialized = false; | ||
175 | 176 | ||
176 | static int update_fsinfo(IF_MV_NONVOID(struct bpb* fat_bpb)); | 177 | static int update_fsinfo(IF_MV_NONVOID(struct bpb* fat_bpb)); |
177 | static int flush_fat(IF_MV_NONVOID(struct bpb* fat_bpb)); | 178 | static int flush_fat(IF_MV_NONVOID(struct bpb* fat_bpb)); |
@@ -202,6 +203,18 @@ static char fat_cache_sectors[FAT_CACHE_SIZE][SECTOR_SIZE]; | |||
202 | static struct fat_cache_entry fat_cache[FAT_CACHE_SIZE]; | 203 | static struct fat_cache_entry fat_cache[FAT_CACHE_SIZE]; |
203 | static struct mutex cache_mutex NOCACHEBSS_ATTR; | 204 | static struct mutex cache_mutex NOCACHEBSS_ATTR; |
204 | 205 | ||
206 | #ifdef HAVE_HOTSWAP | ||
207 | void fat_lock(void) | ||
208 | { | ||
209 | mutex_lock(&cache_mutex); | ||
210 | } | ||
211 | |||
212 | void fat_unlock(void) | ||
213 | { | ||
214 | mutex_unlock(&cache_mutex); | ||
215 | } | ||
216 | #endif | ||
217 | |||
205 | static long cluster2sec(IF_MV2(struct bpb* fat_bpb,) long cluster) | 218 | static long cluster2sec(IF_MV2(struct bpb* fat_bpb,) long cluster) |
206 | { | 219 | { |
207 | #ifndef HAVE_MULTIVOLUME | 220 | #ifndef HAVE_MULTIVOLUME |
@@ -240,7 +253,11 @@ void fat_init(void) | |||
240 | { | 253 | { |
241 | unsigned int i; | 254 | unsigned int i; |
242 | 255 | ||
243 | mutex_init(&cache_mutex); | 256 | if (!initialized) |
257 | { | ||
258 | initialized = true; | ||
259 | mutex_init(&cache_mutex); | ||
260 | } | ||
244 | 261 | ||
245 | /* mark the FAT cache as unused */ | 262 | /* mark the FAT cache as unused */ |
246 | for(i = 0;i < FAT_CACHE_SIZE;i++) | 263 | for(i = 0;i < FAT_CACHE_SIZE;i++) |
diff --git a/firmware/export/fat.h b/firmware/export/fat.h index 0dfd395ea7..3cf2923b78 100644 --- a/firmware/export/fat.h +++ b/firmware/export/fat.h | |||
@@ -82,6 +82,10 @@ struct fat_dir | |||
82 | unsigned char sectorcache[3][SECTOR_SIZE]; | 82 | unsigned char sectorcache[3][SECTOR_SIZE]; |
83 | }; | 83 | }; |
84 | 84 | ||
85 | #ifdef HAVE_HOTSWAP | ||
86 | extern void fat_lock(void); | ||
87 | extern void fat_unlock(void); | ||
88 | #endif | ||
85 | 89 | ||
86 | extern void fat_init(void); | 90 | extern void fat_init(void); |
87 | extern int fat_mount(IF_MV2(int volume,) IF_MV2(int drive,) long startsector); | 91 | extern int fat_mount(IF_MV2(int volume,) IF_MV2(int drive,) long startsector); |
diff --git a/firmware/target/arm/i2c-pp.c b/firmware/target/arm/i2c-pp.c index b8e3869907..092a59be84 100644 --- a/firmware/target/arm/i2c-pp.c +++ b/firmware/target/arm/i2c-pp.c | |||
@@ -187,6 +187,7 @@ int pp_i2c_send(unsigned int addr, int data0, int data1) | |||
187 | void i2c_init(void) | 187 | void i2c_init(void) |
188 | { | 188 | { |
189 | /* From ipodlinux */ | 189 | /* From ipodlinux */ |
190 | mutex_init(&i2c_mtx); | ||
190 | 191 | ||
191 | #ifdef IPOD_MINI | 192 | #ifdef IPOD_MINI |
192 | /* GPIO port C disable port 0x10 */ | 193 | /* GPIO port C disable port 0x10 */ |
@@ -231,7 +232,5 @@ void i2c_init(void) | |||
231 | #endif | 232 | #endif |
232 | #endif | 233 | #endif |
233 | 234 | ||
234 | mutex_init(&i2c_mtx); | ||
235 | |||
236 | i2c_readbyte(0x8, 0); | 235 | i2c_readbyte(0x8, 0); |
237 | } | 236 | } |
diff --git a/firmware/target/arm/sandisk/ata-c200_e200.c b/firmware/target/arm/sandisk/ata-c200_e200.c index 150b08fd92..99a00358ff 100644 --- a/firmware/target/arm/sandisk/ata-c200_e200.c +++ b/firmware/target/arm/sandisk/ata-c200_e200.c | |||
@@ -16,7 +16,7 @@ | |||
16 | * KIND, either express or implied. | 16 | * KIND, either express or implied. |
17 | * | 17 | * |
18 | ****************************************************************************/ | 18 | ****************************************************************************/ |
19 | #include "ata.h" | 19 | #include "fat.h" |
20 | #include "hotswap-target.h" | 20 | #include "hotswap-target.h" |
21 | #include "ata-target.h" | 21 | #include "ata-target.h" |
22 | #include "ata_idle_notify.h" | 22 | #include "ata_idle_notify.h" |
@@ -29,8 +29,8 @@ | |||
29 | #include "panic.h" | 29 | #include "panic.h" |
30 | #include "usb.h" | 30 | #include "usb.h" |
31 | 31 | ||
32 | #define BLOCK_SIZE (512) | 32 | #define BLOCK_SIZE 512 |
33 | #define SECTOR_SIZE (512) | 33 | #define SECTOR_SIZE 512 |
34 | #define BLOCKS_PER_BANK 0x7a7800 | 34 | #define BLOCKS_PER_BANK 0x7a7800 |
35 | 35 | ||
36 | #define STATUS_REG (*(volatile unsigned int *)(0x70008204)) | 36 | #define STATUS_REG (*(volatile unsigned int *)(0x70008204)) |
@@ -1045,22 +1045,33 @@ static void sd_thread(void) | |||
1045 | { | 1045 | { |
1046 | #ifdef HAVE_HOTSWAP | 1046 | #ifdef HAVE_HOTSWAP |
1047 | case SYS_HOTSWAP_INSERTED: | 1047 | case SYS_HOTSWAP_INSERTED: |
1048 | mutex_lock(&sd_mtx); /* Lock-out card activity */ | ||
1049 | card_info[1].initialized = 0; | ||
1050 | sd_status[1].retry = 0; | ||
1051 | disk_unmount(1); /* Force remount */ | ||
1052 | disk_mount(1); /* mount microSD card */ | ||
1053 | queue_broadcast(SYS_FS_CHANGED, 0); | ||
1054 | mutex_unlock(&sd_mtx); | ||
1055 | break; | ||
1056 | |||
1057 | case SYS_HOTSWAP_EXTRACTED: | 1048 | case SYS_HOTSWAP_EXTRACTED: |
1058 | mutex_lock(&sd_mtx); /* Lock-out card activity */ | 1049 | fat_lock(); /* lock-out FAT activity first - |
1059 | card_info[1].initialized = 0; | 1050 | prevent deadlocking via disk_mount that |
1051 | would cause a reverse-order attempt with | ||
1052 | another thread */ | ||
1053 | mutex_lock(&sd_mtx); /* lock-out card activity - direct calls | ||
1054 | into driver that bypass the fat cache */ | ||
1055 | |||
1056 | /* We now have exclusive control of fat cache and ata */ | ||
1057 | |||
1058 | disk_unmount(1); /* release "by force", ensure file | ||
1059 | descriptors aren't leaked and any busy | ||
1060 | ones are invalid if mounting */ | ||
1061 | |||
1062 | /* Force card init for new card, re-init for re-inserted one or | ||
1063 | * clear if the last attempt to init failed with an error. */ | ||
1064 | card_info[1].initialized = 0; | ||
1060 | sd_status[1].retry = 0; | 1065 | sd_status[1].retry = 0; |
1061 | disk_unmount(1); /* release "by force" */ | 1066 | |
1067 | if (ev.id == SYS_HOTSWAP_INSERTED) | ||
1068 | disk_mount(1); | ||
1069 | |||
1062 | queue_broadcast(SYS_FS_CHANGED, 0); | 1070 | queue_broadcast(SYS_FS_CHANGED, 0); |
1071 | |||
1072 | /* Access is now safe */ | ||
1063 | mutex_unlock(&sd_mtx); | 1073 | mutex_unlock(&sd_mtx); |
1074 | fat_unlock(); | ||
1064 | break; | 1075 | break; |
1065 | #endif | 1076 | #endif |
1066 | case SYS_TIMEOUT: | 1077 | case SYS_TIMEOUT: |
@@ -1135,6 +1146,28 @@ void ata_enable(bool on) | |||
1135 | } | 1146 | } |
1136 | } | 1147 | } |
1137 | 1148 | ||
1149 | #ifdef HAVE_HOTSWAP | ||
1150 | void card_enable_monitoring(bool on) | ||
1151 | { | ||
1152 | if (on) | ||
1153 | { | ||
1154 | #ifdef SANSA_E200 | ||
1155 | GPIO_SET_BITWISE(GPIOA_INT_EN, 0x80); | ||
1156 | #elif defined(SANSA_C200) | ||
1157 | GPIO_SET_BITWISE(GPIOL_INT_EN, 0x08); | ||
1158 | #endif | ||
1159 | } | ||
1160 | else | ||
1161 | { | ||
1162 | #ifdef SANSA_E200 | ||
1163 | GPIO_CLEAR_BITWISE(GPIOA_INT_EN, 0x80); | ||
1164 | #elif defined(SANSA_C200) | ||
1165 | GPIO_CLEAR_BITWISE(GPIOL_INT_EN, 0x08); | ||
1166 | #endif | ||
1167 | } | ||
1168 | } | ||
1169 | #endif | ||
1170 | |||
1138 | int ata_init(void) | 1171 | int ata_init(void) |
1139 | { | 1172 | { |
1140 | int ret = 0; | 1173 | int ret = 0; |
@@ -1193,7 +1226,6 @@ int ata_init(void) | |||
1193 | GPIOA_INT_LEV = (0x80 << 8) | (~GPIOA_INPUT_VAL & 0x80); | 1226 | GPIOA_INT_LEV = (0x80 << 8) | (~GPIOA_INPUT_VAL & 0x80); |
1194 | 1227 | ||
1195 | GPIOA_INT_CLR = 0x80; | 1228 | GPIOA_INT_CLR = 0x80; |
1196 | GPIO_SET_BITWISE(GPIOA_INT_EN, 0x80); | ||
1197 | #elif defined SANSA_C200 | 1229 | #elif defined SANSA_C200 |
1198 | CPU_INT_EN = HI_MASK; | 1230 | CPU_INT_EN = HI_MASK; |
1199 | CPU_HI_INT_EN = GPIO2_MASK; | 1231 | CPU_HI_INT_EN = GPIO2_MASK; |
@@ -1201,7 +1233,6 @@ int ata_init(void) | |||
1201 | GPIOL_INT_LEV = (0x08 << 8) | (~GPIOL_INPUT_VAL & 0x08); | 1233 | GPIOL_INT_LEV = (0x08 << 8) | (~GPIOL_INPUT_VAL & 0x08); |
1202 | 1234 | ||
1203 | GPIOL_INT_CLR = 0x08; | 1235 | GPIOL_INT_CLR = 0x08; |
1204 | GPIO_SET_BITWISE(GPIOL_INT_EN, 0x08); | ||
1205 | #endif | 1236 | #endif |
1206 | #endif | 1237 | #endif |
1207 | } | 1238 | } |
diff --git a/firmware/target/arm/wmcodec-pp.c b/firmware/target/arm/wmcodec-pp.c index 3bd9d7fd2b..cfdd311c52 100644 --- a/firmware/target/arm/wmcodec-pp.c +++ b/firmware/target/arm/wmcodec-pp.c | |||
@@ -41,9 +41,6 @@ | |||
41 | * Initialise the PP I2C and I2S. | 41 | * Initialise the PP I2C and I2S. |
42 | */ | 42 | */ |
43 | void audiohw_init(void) { | 43 | void audiohw_init(void) { |
44 | /* reset I2C */ | ||
45 | i2c_init(); | ||
46 | |||
47 | #ifdef CPU_PP502x | 44 | #ifdef CPU_PP502x |
48 | /* normal outputs for CDI and I2S pin groups */ | 45 | /* normal outputs for CDI and I2S pin groups */ |
49 | DEV_INIT2 &= ~0x300; | 46 | DEV_INIT2 &= ~0x300; |