Commit 30493587 authored by Ben Avison's avatar Ben Avison
Browse files

Fix for disc error 08 immediately after module reinit on Raspberry Pi B+ and 2

Detail:
  On these boards, because there's no card-detect line, SDIODriver only
  issues the UnitAttached and UnitDetached service calls in its module
  init/final code and when one of the rescan SWIs are called (usually by
  SDFS). The "maybe-changed" timer is implemented within SDFS; when it has
  elapsed, any DiscOp will try to select a card with the last-known-good ID
  in that slot; if this fails (because there's no card, or the card has
  changed, or even if the same card has been removed and reinserted) SDFS
  will get SDIODriver to rescan the slot, at which point SDFS is re-entered
  via the UnitAttached service call, which resets the "maybe-changed" timer
  to 1 second.

  The problem was that SDFS reused the same function that handles
  Service_SDIOUnitAttached during its module initialisation, so for the
  first second of SDFS's life, it believed the card ID which it was
  informed of by SDIODriver is valid and has been accessed within the last
  second. Except that if the card has actually been removed and reinserted,
  the command issued by SDFS ends up timing out, resulting in disc error 08.
Admin:
  Tested on Pi B+ (assumed identical behaviour on Pi 2)

Version 0.08. Tagged as 'SDFS-0_08'
parent 7592adfe
/* (0.07)
/* (0.08)
*
* This file is automatically maintained by srccommit, do not edit manually.
* Last processed by srccommit version: 1.1.
*
*/
#define Module_MajorVersion_CMHG 0.07
#define Module_MajorVersion_CMHG 0.08
#define Module_MinorVersion_CMHG
#define Module_Date_CMHG 02 Feb 2015
#define Module_MajorVersion "0.07"
#define Module_Version 7
#define Module_MajorVersion "0.08"
#define Module_Version 8
#define Module_MinorVersion ""
#define Module_Date "02 Feb 2015"
......@@ -18,6 +18,6 @@
#define Module_ComponentName "SDFS"
#define Module_ComponentPath "cddl/RiscOS/Sources/FileSys/SDFS/SDFS"
#define Module_FullVersion "0.07"
#define Module_HelpVersion "0.07 (02 Feb 2015)"
#define Module_LibraryVersionInfo "0:7"
#define Module_FullVersion "0.08"
#define Module_HelpVersion "0.08 (02 Feb 2015)"
#define Module_LibraryVersionInfo "0:8"
......@@ -283,7 +283,8 @@ static low_level_error_t transfer_with_retries(uint32_t reason,
}
/* Some cards seem to need to be deselected and reselected after errors */
dr->needs_reselect = true;
if (e.oserror->errnum != ErrorNumber_SDFSExtEscape)
dr->needs_reselect = true;
if (transferred)
++retries; /* At least some data transferred, so it's not fair to decrement the retry count when we loop */
......@@ -420,6 +421,7 @@ low_level_error_t discop(uint32_t reason,
}
else
{
dr->slot_claimed = true;
dprintf("Need to probe for card presence\n");
bool rescan_needed = !dr->card_inserted;
if (dr->card_inserted)
......
......@@ -212,7 +212,8 @@ _kernel_oserror *module_initialise(const char *cmd_tail, int podule_base, void *
(unit_spec[1] & SDIOEnumerate_FICMask) >> SDIOEnumerate_FICShift,
unit_spec[1] & SDIOEnumerate_WriteProtect,
unit_spec[1] & SDIOEnumerate_MMC,
(uint64_t) unit_size[1] << 32 | unit_size[0]);
(uint64_t) unit_size[1] << 32 | unit_size[0],
true);
}
}
}
......@@ -290,7 +291,8 @@ void module_service(int service_number, _kernel_swi_regs *r, void *pw)
(r->r[3] & SDIOUnitAttached_FICMask) >> SDIOUnitAttached_FICShift,
r->r[3] & SDIOUnitAttached_WriteProtect,
r->r[3] & SDIOUnitAttached_MMC,
(uint64_t) r->r[5] << 32 | (uint32_t) r->r[4]);
(uint64_t) r->r[5] << 32 | (uint32_t) r->r[4],
false);
break;
case Service_SDIOUnitDetached:
......@@ -514,7 +516,7 @@ int module_tickerv_handler(_kernel_swi_regs *r, void *pw)
{
spin_lock(&g_drive[drive].certainty_lock);
uint32_t old_value = g_drive[drive].certainty;
if (old_value > 0)
if (old_value > 0 && !g_drive[drive].slot_claimed)
g_drive[drive].certainty = old_value - 1;
spin_unlock(&g_drive[drive].certainty_lock);
}
......
......@@ -102,7 +102,7 @@ void service_SDIOSlotDetached(uint32_t bus, uint32_t slot, bool integrated, bool
spinrw_write_unlock(&g_drive_lock);
}
void service_SDIOUnitAttached(uint32_t bus, uint32_t slot, uint32_t rca, uint32_t unit, uint32_t fic, bool writeprotect, bool mmc, uint64_t capacity)
void service_SDIOUnitAttached(uint32_t bus, uint32_t slot, uint32_t rca, uint32_t unit, uint32_t fic, bool writeprotect, bool mmc, uint64_t capacity, bool called_from_init)
{
IGNORE(fic);
......@@ -219,7 +219,7 @@ void service_SDIOUnitAttached(uint32_t bus, uint32_t slot, uint32_t rca, uint32_
g_drive[i].rca = rca;
barrier(); /* because we may read these from the background */
spin_lock(&g_drive[i].certainty_lock);
g_drive[i].certainty = FAITH;
g_drive[i].certainty = called_from_init ? 0 : FAITH;
spin_unlock(&g_drive[i].certainty_lock);
spin_lock(&g_drive[i].sequence_lock);
g_drive[i].card_inserted = true;
......@@ -365,28 +365,24 @@ void service_SDIOSlotReleased(uint32_t bus, uint32_t slot)
if (g_drive[i].slot_attached)
{
barrier();
if (g_drive[i].card_inserted)
/* Our behaviour doesn't depend upon whether card_inserted is true or not */
if (g_drive[i].bus == bus && g_drive[i].slot == slot)
{
barrier();
if (g_drive[i].bus == bus && g_drive[i].slot == slot)
if (g_drive[i].slot_claimed)
/* This just means we've finished using this drive ourselves */
g_drive[i].slot_claimed = false;
else
{
if (g_drive[i].slot_claimed)
/* This just means we've finished using this drive ourselves */
g_drive[i].slot_claimed = false;
else
{
/* Someone else has been using this slot, or we've just finished
* using a different drive in the same slot. Disable optimisations
* for the next time we use this drive. */
g_drive[i].needs_reselect = true;
g_drive[i].needs_wait = true;
}
/* Someone else has been using this slot, or we've just finished
* using a different drive in the same slot. Disable optimisations
* for the next time we use this drive. */
g_drive[i].needs_reselect = true;
g_drive[i].needs_wait = true;
}
}
if (g_drive[i].bus == bus && g_drive[i].slot == slot)
{
dprintf("Slot attached to drive %u being released, so reset timeout\n", i);
spin_lock(&g_drive[i].certainty_lock);
g_drive[i].certainty = FAITH;
spin_unlock(&g_drive[i].certainty_lock);
}
}
}
......
......@@ -32,7 +32,7 @@
void service_SDIOSlotAttached(uint32_t bus, uint32_t slot, bool integrated, bool no_card_detect, bool integrated_mem);
void service_SDIOSlotDetached(uint32_t bus, uint32_t slot, bool integrated, bool no_card_detect, bool integrated_mem);
void service_SDIOUnitAttached(uint32_t bus, uint32_t slot, uint32_t rca, uint32_t unit, uint32_t fic, bool writeprotect, bool mmc, uint64_t capacity);
void service_SDIOUnitAttached(uint32_t bus, uint32_t slot, uint32_t rca, uint32_t unit, uint32_t fic, bool writeprotect, bool mmc, uint64_t capacity, bool called_from_init);
void service_SDIOUnitDetached(uint32_t bus, uint32_t slot, uint32_t rca, uint32_t unit, uint32_t fic, bool writeprotect, bool mmc);
void service_SDIOSlotReleased(uint32_t bus, uint32_t slot);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment