summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Sevakis <jethead71@rockbox.org>2008-01-18 12:32:03 +0000
committerMichael Sevakis <jethead71@rockbox.org>2008-01-18 12:32:03 +0000
commit3b36b98ff8dea187bd6c25174978da4f7b5e3231 (patch)
tree7cd2467638206b6e3aa167bd64cae85af5f1bcca
parent536b5a0482454d3e3104f2a77a29d37319bc845c (diff)
downloadrockbox-3b36b98ff8dea187bd6c25174978da4f7b5e3231.zip
rockbox-3b36b98ff8dea187bd6c25174978da4f7b5e3231.tar.gz
rockbox-3b36b98ff8dea187bd6c25174978da4f7b5e3231.tar.bz2
rockbox-3b36b98ff8dea187bd6c25174978da4f7b5e3231.tar.xz
Properly serialize ata_init with other threads. Fix a bug that always initialized the lock on every call to ata_init - that should be a one time init or else the lock could be corrupted on connect.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@16104 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r--firmware/drivers/ata.c24
-rw-r--r--firmware/target/arm/sandisk/ata-c200_e200.c13
2 files changed, 23 insertions, 14 deletions
diff --git a/firmware/drivers/ata.c b/firmware/drivers/ata.c
index 67aab8a..1b91768 100644
--- a/firmware/drivers/ata.c
+++ b/firmware/drivers/ata.c
@@ -1128,12 +1128,18 @@ static int init_and_check(bool hard_reset)
int ata_init(void)
{
- int rc;
- bool coldstart = ata_is_coldstart();
- /* must be called before ata_device_init() */
+ int rc = 0;
+ bool coldstart;
- spinlock_init(&ata_spinlock IF_COP(, SPINLOCK_TASK_SWITCH));
+ if ( !initialized ) {
+ spinlock_init(&ata_spinlock IF_COP(, SPINLOCK_TASK_SWITCH));
+ queue_init(&ata_queue, true);
+ }
+
+ spinlock_lock(&ata_spinlock);
+ /* must be called before ata_device_init() */
+ coldstart = ata_is_coldstart();
ata_led(false);
ata_device_init();
sleeping = false;
@@ -1143,6 +1149,9 @@ int ata_init(void)
#endif
if ( !initialized ) {
+ /* First call won't have multiple thread contention */
+ spinlock_unlock(&ata_spinlock);
+
if (!ide_powered()) /* somebody has switched it off */
{
ide_power_enable(true);
@@ -1202,8 +1211,6 @@ int ata_init(void)
if (rc)
return -60 + rc;
- queue_init(&ata_queue, true);
-
last_disk_activity = current_tick;
create_thread(ata_thread, ata_stack,
sizeof(ata_stack), 0, ata_thread_name
@@ -1214,9 +1221,10 @@ int ata_init(void)
}
rc = set_multiple_mode(multisectors);
if (rc)
- return -70 + rc;
+ rc = -70 + rc;
- return 0;
+ spinlock_unlock(&ata_spinlock);
+ return rc;
}
#if (CONFIG_LED == LED_REAL)
diff --git a/firmware/target/arm/sandisk/ata-c200_e200.c b/firmware/target/arm/sandisk/ata-c200_e200.c
index 5a7577f..ef2bad3 100644
--- a/firmware/target/arm/sandisk/ata-c200_e200.c
+++ b/firmware/target/arm/sandisk/ata-c200_e200.c
@@ -1149,17 +1149,17 @@ int ata_init(void)
{
int ret = 0;
+ if (!initialized)
+ spinlock_init(&sd_spin IF_COP(, SPINLOCK_TASK_SWITCH));
+
+ spinlock_lock(&sd_spin);
+
ata_led(false);
- /* NOTE: This init isn't dual core safe */
if (!initialized)
{
initialized = true;
- spinlock_init(&sd_spin IF_COP(, SPINLOCK_TASK_SWITCH));
-
- spinlock_lock(&sd_spin);
-
/* init controller */
outl(inl(0x70000088) & ~(0x4), 0x70000088);
outl(inl(0x7000008c) & ~(0x4), 0x7000008c);
@@ -1213,9 +1213,10 @@ int ata_init(void)
GPIOL_INT_EN |= 0x08;
#endif
#endif
- spinlock_unlock(&sd_spin);
}
+ spinlock_unlock(&sd_spin);
+
return ret;
}