summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Sevakis <jethead71@rockbox.org>2008-03-12 10:03:52 +0000
committerMichael Sevakis <jethead71@rockbox.org>2008-03-12 10:03:52 +0000
commit06a5299aff38ba25c7742ae6293c588e38445f8b (patch)
tree5f8c3121882ba9c8d6317d1ce7fb5a07d3a99f5c
parent2f5a37de5c45333453169ffe0b90e0f380d1cd50 (diff)
downloadrockbox-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.c5
-rw-r--r--firmware/drivers/audio/as3514.c3
-rw-r--r--firmware/drivers/fat.c19
-rw-r--r--firmware/export/fat.h4
-rw-r--r--firmware/target/arm/i2c-pp.c3
-rw-r--r--firmware/target/arm/sandisk/ata-c200_e200.c65
-rw-r--r--firmware/target/arm/wmcodec-pp.c3
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
174static struct bpb fat_bpbs[NUM_VOLUMES]; /* mounted partition info */ 174static struct bpb fat_bpbs[NUM_VOLUMES]; /* mounted partition info */
175static bool initialized = false;
175 176
176static int update_fsinfo(IF_MV_NONVOID(struct bpb* fat_bpb)); 177static int update_fsinfo(IF_MV_NONVOID(struct bpb* fat_bpb));
177static int flush_fat(IF_MV_NONVOID(struct bpb* fat_bpb)); 178static int flush_fat(IF_MV_NONVOID(struct bpb* fat_bpb));
@@ -202,6 +203,18 @@ static char fat_cache_sectors[FAT_CACHE_SIZE][SECTOR_SIZE];
202static struct fat_cache_entry fat_cache[FAT_CACHE_SIZE]; 203static struct fat_cache_entry fat_cache[FAT_CACHE_SIZE];
203static struct mutex cache_mutex NOCACHEBSS_ATTR; 204static struct mutex cache_mutex NOCACHEBSS_ATTR;
204 205
206#ifdef HAVE_HOTSWAP
207void fat_lock(void)
208{
209 mutex_lock(&cache_mutex);
210}
211
212void fat_unlock(void)
213{
214 mutex_unlock(&cache_mutex);
215}
216#endif
217
205static long cluster2sec(IF_MV2(struct bpb* fat_bpb,) long cluster) 218static 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
86extern void fat_lock(void);
87extern void fat_unlock(void);
88#endif
85 89
86extern void fat_init(void); 90extern void fat_init(void);
87extern int fat_mount(IF_MV2(int volume,) IF_MV2(int drive,) long startsector); 91extern 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)
187void i2c_init(void) 187void 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
1150void 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
1138int ata_init(void) 1171int 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 */
43void audiohw_init(void) { 43void 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;