forked from len0rd/rockbox
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
This commit is contained in:
parent
2f5a37de5c
commit
06a5299aff
7 changed files with 73 additions and 29 deletions
|
|
@ -104,7 +104,7 @@ int disk_mount_all(void)
|
||||||
int mounted;
|
int mounted;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
#ifdef HAVE_MMC
|
#if defined(HAVE_MMC) || defined(HAVE_HOTSWAP)
|
||||||
card_enable_monitoring(false);
|
card_enable_monitoring(false);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
@ -118,9 +118,8 @@ int disk_mount_all(void)
|
||||||
{
|
{
|
||||||
mounted += disk_mount(1); /* try 2nd "drive", too */
|
mounted += disk_mount(1); /* try 2nd "drive", too */
|
||||||
}
|
}
|
||||||
#ifdef HAVE_MMC
|
|
||||||
card_enable_monitoring(true);
|
card_enable_monitoring(true);
|
||||||
#endif
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return mounted;
|
return mounted;
|
||||||
|
|
|
||||||
|
|
@ -132,9 +132,6 @@ void audiohw_init(void)
|
||||||
{
|
{
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
|
|
||||||
/* reset I2C */
|
|
||||||
i2c_init();
|
|
||||||
|
|
||||||
/* normal outputs for CDI and I2S pin groups */
|
/* normal outputs for CDI and I2S pin groups */
|
||||||
DEV_INIT2 &= ~0x300;
|
DEV_INIT2 &= ~0x300;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -172,6 +172,7 @@ struct bpb
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct bpb fat_bpbs[NUM_VOLUMES]; /* mounted partition info */
|
static struct bpb fat_bpbs[NUM_VOLUMES]; /* mounted partition info */
|
||||||
|
static bool initialized = false;
|
||||||
|
|
||||||
static int update_fsinfo(IF_MV_NONVOID(struct bpb* fat_bpb));
|
static int update_fsinfo(IF_MV_NONVOID(struct bpb* fat_bpb));
|
||||||
static int flush_fat(IF_MV_NONVOID(struct bpb* fat_bpb));
|
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];
|
||||||
static struct fat_cache_entry fat_cache[FAT_CACHE_SIZE];
|
static struct fat_cache_entry fat_cache[FAT_CACHE_SIZE];
|
||||||
static struct mutex cache_mutex NOCACHEBSS_ATTR;
|
static struct mutex cache_mutex NOCACHEBSS_ATTR;
|
||||||
|
|
||||||
|
#ifdef HAVE_HOTSWAP
|
||||||
|
void fat_lock(void)
|
||||||
|
{
|
||||||
|
mutex_lock(&cache_mutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
void fat_unlock(void)
|
||||||
|
{
|
||||||
|
mutex_unlock(&cache_mutex);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static long cluster2sec(IF_MV2(struct bpb* fat_bpb,) long cluster)
|
static long cluster2sec(IF_MV2(struct bpb* fat_bpb,) long cluster)
|
||||||
{
|
{
|
||||||
#ifndef HAVE_MULTIVOLUME
|
#ifndef HAVE_MULTIVOLUME
|
||||||
|
|
@ -240,7 +253,11 @@ void fat_init(void)
|
||||||
{
|
{
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
|
|
||||||
|
if (!initialized)
|
||||||
|
{
|
||||||
|
initialized = true;
|
||||||
mutex_init(&cache_mutex);
|
mutex_init(&cache_mutex);
|
||||||
|
}
|
||||||
|
|
||||||
/* mark the FAT cache as unused */
|
/* mark the FAT cache as unused */
|
||||||
for(i = 0;i < FAT_CACHE_SIZE;i++)
|
for(i = 0;i < FAT_CACHE_SIZE;i++)
|
||||||
|
|
|
||||||
|
|
@ -82,6 +82,10 @@ struct fat_dir
|
||||||
unsigned char sectorcache[3][SECTOR_SIZE];
|
unsigned char sectorcache[3][SECTOR_SIZE];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#ifdef HAVE_HOTSWAP
|
||||||
|
extern void fat_lock(void);
|
||||||
|
extern void fat_unlock(void);
|
||||||
|
#endif
|
||||||
|
|
||||||
extern void fat_init(void);
|
extern void fat_init(void);
|
||||||
extern int fat_mount(IF_MV2(int volume,) IF_MV2(int drive,) long startsector);
|
extern int fat_mount(IF_MV2(int volume,) IF_MV2(int drive,) long startsector);
|
||||||
|
|
|
||||||
|
|
@ -187,6 +187,7 @@ int pp_i2c_send(unsigned int addr, int data0, int data1)
|
||||||
void i2c_init(void)
|
void i2c_init(void)
|
||||||
{
|
{
|
||||||
/* From ipodlinux */
|
/* From ipodlinux */
|
||||||
|
mutex_init(&i2c_mtx);
|
||||||
|
|
||||||
#ifdef IPOD_MINI
|
#ifdef IPOD_MINI
|
||||||
/* GPIO port C disable port 0x10 */
|
/* GPIO port C disable port 0x10 */
|
||||||
|
|
@ -231,7 +232,5 @@ void i2c_init(void)
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
mutex_init(&i2c_mtx);
|
|
||||||
|
|
||||||
i2c_readbyte(0x8, 0);
|
i2c_readbyte(0x8, 0);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,7 @@
|
||||||
* KIND, either express or implied.
|
* KIND, either express or implied.
|
||||||
*
|
*
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
#include "ata.h"
|
#include "fat.h"
|
||||||
#include "hotswap-target.h"
|
#include "hotswap-target.h"
|
||||||
#include "ata-target.h"
|
#include "ata-target.h"
|
||||||
#include "ata_idle_notify.h"
|
#include "ata_idle_notify.h"
|
||||||
|
|
@ -29,8 +29,8 @@
|
||||||
#include "panic.h"
|
#include "panic.h"
|
||||||
#include "usb.h"
|
#include "usb.h"
|
||||||
|
|
||||||
#define BLOCK_SIZE (512)
|
#define BLOCK_SIZE 512
|
||||||
#define SECTOR_SIZE (512)
|
#define SECTOR_SIZE 512
|
||||||
#define BLOCKS_PER_BANK 0x7a7800
|
#define BLOCKS_PER_BANK 0x7a7800
|
||||||
|
|
||||||
#define STATUS_REG (*(volatile unsigned int *)(0x70008204))
|
#define STATUS_REG (*(volatile unsigned int *)(0x70008204))
|
||||||
|
|
@ -1045,22 +1045,33 @@ static void sd_thread(void)
|
||||||
{
|
{
|
||||||
#ifdef HAVE_HOTSWAP
|
#ifdef HAVE_HOTSWAP
|
||||||
case SYS_HOTSWAP_INSERTED:
|
case SYS_HOTSWAP_INSERTED:
|
||||||
mutex_lock(&sd_mtx); /* Lock-out card activity */
|
|
||||||
card_info[1].initialized = 0;
|
|
||||||
sd_status[1].retry = 0;
|
|
||||||
disk_unmount(1); /* Force remount */
|
|
||||||
disk_mount(1); /* mount microSD card */
|
|
||||||
queue_broadcast(SYS_FS_CHANGED, 0);
|
|
||||||
mutex_unlock(&sd_mtx);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case SYS_HOTSWAP_EXTRACTED:
|
case SYS_HOTSWAP_EXTRACTED:
|
||||||
mutex_lock(&sd_mtx); /* Lock-out card activity */
|
fat_lock(); /* lock-out FAT activity first -
|
||||||
|
prevent deadlocking via disk_mount that
|
||||||
|
would cause a reverse-order attempt with
|
||||||
|
another thread */
|
||||||
|
mutex_lock(&sd_mtx); /* lock-out card activity - direct calls
|
||||||
|
into driver that bypass the fat cache */
|
||||||
|
|
||||||
|
/* We now have exclusive control of fat cache and ata */
|
||||||
|
|
||||||
|
disk_unmount(1); /* release "by force", ensure file
|
||||||
|
descriptors aren't leaked and any busy
|
||||||
|
ones are invalid if mounting */
|
||||||
|
|
||||||
|
/* Force card init for new card, re-init for re-inserted one or
|
||||||
|
* clear if the last attempt to init failed with an error. */
|
||||||
card_info[1].initialized = 0;
|
card_info[1].initialized = 0;
|
||||||
sd_status[1].retry = 0;
|
sd_status[1].retry = 0;
|
||||||
disk_unmount(1); /* release "by force" */
|
|
||||||
|
if (ev.id == SYS_HOTSWAP_INSERTED)
|
||||||
|
disk_mount(1);
|
||||||
|
|
||||||
queue_broadcast(SYS_FS_CHANGED, 0);
|
queue_broadcast(SYS_FS_CHANGED, 0);
|
||||||
|
|
||||||
|
/* Access is now safe */
|
||||||
mutex_unlock(&sd_mtx);
|
mutex_unlock(&sd_mtx);
|
||||||
|
fat_unlock();
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
case SYS_TIMEOUT:
|
case SYS_TIMEOUT:
|
||||||
|
|
@ -1135,6 +1146,28 @@ void ata_enable(bool on)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef HAVE_HOTSWAP
|
||||||
|
void card_enable_monitoring(bool on)
|
||||||
|
{
|
||||||
|
if (on)
|
||||||
|
{
|
||||||
|
#ifdef SANSA_E200
|
||||||
|
GPIO_SET_BITWISE(GPIOA_INT_EN, 0x80);
|
||||||
|
#elif defined(SANSA_C200)
|
||||||
|
GPIO_SET_BITWISE(GPIOL_INT_EN, 0x08);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
#ifdef SANSA_E200
|
||||||
|
GPIO_CLEAR_BITWISE(GPIOA_INT_EN, 0x80);
|
||||||
|
#elif defined(SANSA_C200)
|
||||||
|
GPIO_CLEAR_BITWISE(GPIOL_INT_EN, 0x08);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
int ata_init(void)
|
int ata_init(void)
|
||||||
{
|
{
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
@ -1193,7 +1226,6 @@ int ata_init(void)
|
||||||
GPIOA_INT_LEV = (0x80 << 8) | (~GPIOA_INPUT_VAL & 0x80);
|
GPIOA_INT_LEV = (0x80 << 8) | (~GPIOA_INPUT_VAL & 0x80);
|
||||||
|
|
||||||
GPIOA_INT_CLR = 0x80;
|
GPIOA_INT_CLR = 0x80;
|
||||||
GPIO_SET_BITWISE(GPIOA_INT_EN, 0x80);
|
|
||||||
#elif defined SANSA_C200
|
#elif defined SANSA_C200
|
||||||
CPU_INT_EN = HI_MASK;
|
CPU_INT_EN = HI_MASK;
|
||||||
CPU_HI_INT_EN = GPIO2_MASK;
|
CPU_HI_INT_EN = GPIO2_MASK;
|
||||||
|
|
@ -1201,7 +1233,6 @@ int ata_init(void)
|
||||||
GPIOL_INT_LEV = (0x08 << 8) | (~GPIOL_INPUT_VAL & 0x08);
|
GPIOL_INT_LEV = (0x08 << 8) | (~GPIOL_INPUT_VAL & 0x08);
|
||||||
|
|
||||||
GPIOL_INT_CLR = 0x08;
|
GPIOL_INT_CLR = 0x08;
|
||||||
GPIO_SET_BITWISE(GPIOL_INT_EN, 0x08);
|
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -41,9 +41,6 @@
|
||||||
* Initialise the PP I2C and I2S.
|
* Initialise the PP I2C and I2S.
|
||||||
*/
|
*/
|
||||||
void audiohw_init(void) {
|
void audiohw_init(void) {
|
||||||
/* reset I2C */
|
|
||||||
i2c_init();
|
|
||||||
|
|
||||||
#ifdef CPU_PP502x
|
#ifdef CPU_PP502x
|
||||||
/* normal outputs for CDI and I2S pin groups */
|
/* normal outputs for CDI and I2S pin groups */
|
||||||
DEV_INIT2 &= ~0x300;
|
DEV_INIT2 &= ~0x300;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue