AMSv2 SD: Fix card insert lockups in USB mode. First, get rid of infinite loops and retry those a limited number of times-- no explaination for their dubious existence was offered in the source. Second, SD thread was no longer monitoring inserts (and it wouldn't really matter if it were). Thus, .initialized was reported as '1' despite the new card needing reinit.

git-svn-id: svn://svn.rockbox.org/rockbox/trunk@29169 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
Michael Sevakis 2011-01-29 16:54:36 +00:00
parent 7436e7ab41
commit e9749d1b93

View file

@ -334,9 +334,6 @@ static tCardInfo card_info[NUM_DRIVES];
/* for compatibility */ /* for compatibility */
static long last_disk_activity = -1; static long last_disk_activity = -1;
#define MIN_YIELD_PERIOD 5 /* ticks */
static long next_yield = 0;
static long sd_stack [(DEFAULT_STACK_SIZE*2 + 0x200)/sizeof(long)]; static long sd_stack [(DEFAULT_STACK_SIZE*2 + 0x200)/sizeof(long)];
static const char sd_thread_name[] = "ata/sd"; static const char sd_thread_name[] = "ata/sd";
static struct mutex sd_mtx SHAREDBSS_ATTR; static struct mutex sd_mtx SHAREDBSS_ATTR;
@ -470,10 +467,18 @@ static int sd_wait_for_tran_state(const int drive)
{ {
unsigned long response; unsigned long response;
unsigned int timeout = current_tick + 5*HZ; unsigned int timeout = current_tick + 5*HZ;
int cmd_retry = 10;
while (1) while (1)
{ {
while(!(send_cmd(drive, SD_SEND_STATUS, card_info[drive].rca, MCI_RESP, &response))); while (!send_cmd(drive, SD_SEND_STATUS, card_info[drive].rca, MCI_RESP,
&response) && cmd_retry > 0)
{
cmd_retry--;
}
if (cmd_retry <= 0)
return -1;
if (((response >> 9) & 0xf) == SD_TRAN) if (((response >> 9) & 0xf) == SD_TRAN)
return 0; return 0;
@ -481,11 +486,7 @@ static int sd_wait_for_tran_state(const int drive)
if(TIME_AFTER(current_tick, timeout)) if(TIME_AFTER(current_tick, timeout))
return -10 * ((response >> 9) & 0xf); return -10 * ((response >> 9) & 0xf);
if (TIME_AFTER(current_tick, next_yield)) last_disk_activity = current_tick;
{
yield();
next_yield = current_tick + MIN_YIELD_PERIOD;
}
} }
} }
@ -669,11 +670,13 @@ static void sd_thread(void)
*/ */
if (microsd_init) if (microsd_init)
queue_broadcast(SYS_FS_CHANGED, 0); queue_broadcast(SYS_FS_CHANGED, 0);
sd_enable(false);
/* Access is now safe */ /* Access is now safe */
mutex_unlock(&sd_mtx); mutex_unlock(&sd_mtx);
fat_unlock(); fat_unlock();
sd_enable(false); }
}
break; break;
#endif #endif
case SYS_TIMEOUT: case SYS_TIMEOUT:
@ -681,16 +684,10 @@ static void sd_thread(void)
{ {
idle_notified = false; idle_notified = false;
} }
else else if (!idle_notified)
{ {
/* never let a timer wrap confuse us */ call_storage_idle_notifys(false);
next_yield = current_tick; idle_notified = true;
if (!idle_notified)
{
call_storage_idle_notifys(false);
idle_notified = true;
}
} }
break; break;
@ -825,7 +822,10 @@ static int sd_transfer_sectors(IF_MD2(int drive,) unsigned long start,
const int drive = 0; const int drive = 0;
#endif #endif
bool aligned = !((uintptr_t)buf & (CACHEALIGN_SIZE - 1)); bool aligned = !((uintptr_t)buf & (CACHEALIGN_SIZE - 1));
int const retry_all_max = 1;
int retry_all = 0;
int const retry_data_max = 100; /* Generous, methinks */
int retry_data;
mutex_lock(&sd_mtx); mutex_lock(&sd_mtx);
#ifndef BOOTLOADER #ifndef BOOTLOADER
@ -833,6 +833,21 @@ static int sd_transfer_sectors(IF_MD2(int drive,) unsigned long start,
led(true); led(true);
#endif #endif
if(count < 0) /* XXX: why is it signed ? */
{
ret = -18;
goto sd_transfer_error_no_dma;
}
/* skip SanDisk OF */
if (drive == INTERNAL_AS3525)
start += AMS_OF_SIZE;
/* no need for complete retry on main, just SD */
if (drive == SD_SLOT_AS3525)
retry_all = retry_all_max;
sd_transfer_retry_with_reinit:
if (card_info[drive].initialized <= 0) if (card_info[drive].initialized <= 0)
{ {
ret = sd_init_card(drive); ret = sd_init_card(drive);
@ -840,21 +855,12 @@ static int sd_transfer_sectors(IF_MD2(int drive,) unsigned long start,
goto sd_transfer_error_no_dma; goto sd_transfer_error_no_dma;
} }
if(count < 0) /* XXX: why is it signed ? */
{
ret = -18;
goto sd_transfer_error_no_dma;
}
if((start+count) > card_info[drive].numblocks) if((start+count) > card_info[drive].numblocks)
{ {
ret = -19; ret = -19;
goto sd_transfer_error_no_dma; goto sd_transfer_error_no_dma;
} }
/* skip SanDisk OF */
if (drive == INTERNAL_AS3525)
start += AMS_OF_SIZE;
/* CMD7 w/rca: Select card to put it in TRAN state */ /* CMD7 w/rca: Select card to put it in TRAN state */
if(!send_cmd(drive, SD_SELECT_CARD, card_info[drive].rca, MCI_NO_RESP, NULL)) if(!send_cmd(drive, SD_SELECT_CARD, card_info[drive].rca, MCI_NO_RESP, NULL))
{ {
@ -862,7 +868,6 @@ static int sd_transfer_sectors(IF_MD2(int drive,) unsigned long start,
goto sd_transfer_error_no_dma; goto sd_transfer_error_no_dma;
} }
last_disk_activity = current_tick;
dma_retain(); dma_retain();
if(aligned) if(aligned)
@ -874,12 +879,15 @@ static int sd_transfer_sectors(IF_MD2(int drive,) unsigned long start,
} }
const int cmd = write ? SD_WRITE_MULTIPLE_BLOCK : SD_READ_MULTIPLE_BLOCK; const int cmd = write ? SD_WRITE_MULTIPLE_BLOCK : SD_READ_MULTIPLE_BLOCK;
retry_data = retry_data_max;
do while (1)
{ {
void *dma_buf; void *dma_buf;
unsigned int transfer = count; unsigned int transfer = count;
last_disk_activity = current_tick;
if(aligned) if(aligned)
{ {
dma_buf = AS3525_PHYSICAL_ADDR(buf); dma_buf = AS3525_PHYSICAL_ADDR(buf);
@ -947,15 +955,21 @@ static int sd_transfer_sectors(IF_MD2(int drive,) unsigned long start,
buf += transfer * SD_BLOCK_SIZE; buf += transfer * SD_BLOCK_SIZE;
start += transfer; start += transfer;
count -= transfer; count -= transfer;
if (count > 0)
continue;
} }
else /* reset controller if we had an error */ else /* reset controller if we had an error */
{ {
MCI_CTRL |= (FIFO_RESET|DMA_RESET); MCI_CTRL |= (FIFO_RESET|DMA_RESET);
while(MCI_CTRL & (FIFO_RESET|DMA_RESET)) while(MCI_CTRL & (FIFO_RESET|DMA_RESET))
; ;
if (--retry_data >= 0)
continue;
} }
} while(retry || count); break;
}
dma_release(); dma_release();
@ -967,22 +981,29 @@ static int sd_transfer_sectors(IF_MD2(int drive,) unsigned long start,
goto sd_transfer_error; goto sd_transfer_error;
} }
while (1)
{
#ifndef BOOTLOADER #ifndef BOOTLOADER
sd_enable(false); sd_enable(false);
led(false); led(false);
#endif #endif
mutex_unlock(&sd_mtx); mutex_unlock(&sd_mtx);
return 0; return ret;
sd_transfer_error: sd_transfer_error:
dma_release();
dma_release();
sd_transfer_error_no_dma: sd_transfer_error_no_dma:
card_info[drive].initialized = 0;
card_info[drive].initialized = 0; /* .initialized might have been >= 0 but now stale if the ata sd thread
mutex_unlock(&sd_mtx); * isn't handling an insert because of USB */
return ret; if (--retry_all >= 0)
{
ret = 0;
goto sd_transfer_retry_with_reinit;
}
}
} }
int sd_read_sectors(IF_MD2(int drive,) unsigned long start, int count, int sd_read_sectors(IF_MD2(int drive,) unsigned long start, int count,