]> git.proxmox.com Git - mirror_edk2.git/commitdiff
EmbeddedPkg/MmcDxe: Card Presence Detect Race Condition
authoroliviermartin <oliviermartin@6f19259b-4bc3-4df7-8a09-765794883524>
Tue, 30 Aug 2011 18:02:38 +0000 (18:02 +0000)
committeroliviermartin <oliviermartin@6f19259b-4bc3-4df7-8a09-765794883524>
Tue, 30 Aug 2011 18:02:38 +0000 (18:02 +0000)
The MMC driver defaults to assume a card is not present.  It then starts a timer in MmcDxeInitialize to check for card presence every 200ms.

However it does not immediately check to see if a card is present so if the EFI driver connection process occurs less than 200ms after the driver load, the connection process for partition
or filesystem drivers will fail because MediaPresent still is FALSE.  To resolve this race condition, we need to immediately perform the presence check in the Start routine.

EmbeddedPkg/MmcDxe: Media ID Handling

Initialize the MMC device on Start or when presence changes instead of doing it on the Block IO calls. This way the layered drivers can be stopped and rebuilt with new Media IDs instead of
experiencing errors on calls to Block IO.

Proposed-by: Eugene Cohen (HP)
Reviewed-by: oliviermartin
git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@12237 6f19259b-4bc3-4df7-8a09-765794883524

EmbeddedPkg/Universal/MmcDxe/Mmc.c
EmbeddedPkg/Universal/MmcDxe/Mmc.h
EmbeddedPkg/Universal/MmcDxe/MmcBlockIo.c

index cfa9a51f50773b3d65c42cf6e50179ad61d32ad9..48d32513d40915882819a6133879f9cbd73c989c 100644 (file)
@@ -299,6 +299,9 @@ MmcDriverBindingStart (
     InsertMmcHost (MmcHostInstance);\r
 \r
     MmcHostInstance->Initialized = FALSE;\r
     InsertMmcHost (MmcHostInstance);\r
 \r
     MmcHostInstance->Initialized = FALSE;\r
+\r
+    // Detect card presence now\r
+    CheckCardsCallback (NULL, NULL);\r
   }\r
 \r
   return EFI_SUCCESS;\r
   }\r
 \r
   return EFI_SUCCESS;\r
@@ -366,6 +369,10 @@ CheckCardsCallback (
       MmcHostInstance->BlockIo.Media->MediaPresent = !MmcHostInstance->Initialized;\r
       MmcHostInstance->Initialized = !MmcHostInstance->Initialized;\r
 \r
       MmcHostInstance->BlockIo.Media->MediaPresent = !MmcHostInstance->Initialized;\r
       MmcHostInstance->Initialized = !MmcHostInstance->Initialized;\r
 \r
+      if(MmcHostInstance->BlockIo.Media->MediaPresent) {\r
+        InitializeMmcDevice(MmcHostInstance);\r
+      }\r
+\r
       Status = gBS->ReinstallProtocolInterface (\r
                     (MmcHostInstance->MmcHandle),\r
                     &gEfiBlockIoProtocolGuid,\r
       Status = gBS->ReinstallProtocolInterface (\r
                     (MmcHostInstance->MmcHandle),\r
                     &gEfiBlockIoProtocolGuid,\r
@@ -382,6 +389,7 @@ CheckCardsCallback (
   }\r
 }\r
 \r
   }\r
 }\r
 \r
+\r
 EFI_DRIVER_BINDING_PROTOCOL gMmcDriverBinding = {\r
   MmcDriverBindingSupported,\r
   MmcDriverBindingStart,\r
 EFI_DRIVER_BINDING_PROTOCOL gMmcDriverBinding = {\r
   MmcDriverBindingSupported,\r
   MmcDriverBindingStart,\r
index 2904d91484116f497791626724ef4e5e1479f010..f3b90295736ad273db2f6900fc472b54eee061ba 100644 (file)
@@ -288,4 +288,15 @@ MmcFlushBlocks (
   IN EFI_BLOCK_IO_PROTOCOL  *This\r
   );\r
 \r
   IN EFI_BLOCK_IO_PROTOCOL  *This\r
   );\r
 \r
+EFI_STATUS InitializeMmcDevice(\r
+  IN  MMC_HOST_INSTANCE   *MmcHost\r
+  );\r
+\r
+VOID\r
+EFIAPI\r
+CheckCardsCallback (\r
+  IN  EFI_EVENT   Event,\r
+  IN  VOID        *Context\r
+  );\r
+\r
 #endif\r
 #endif\r
index cc0d5bdc23c3b5fbe6f8ed8e37b3134f2039d8d6..c12411c152affd3d60f95affbdce87975f679ddd 100644 (file)
@@ -172,7 +172,6 @@ MmcGetCardStatus(
     Status = MmcHost->SendCommand(MMC_CMD13, CmdArg);\r
     if (EFI_ERROR(Status)) {\r
       DEBUG((EFI_D_ERROR, "MmcGetCardStatus(MMC_CMD13): Error and Status = %r\n", Status));\r
     Status = MmcHost->SendCommand(MMC_CMD13, CmdArg);\r
     if (EFI_ERROR(Status)) {\r
       DEBUG((EFI_D_ERROR, "MmcGetCardStatus(MMC_CMD13): Error and Status = %r\n", Status));\r
-      ASSERT(0);\r
       return Status;\r
     }\r
 \r
       return Status;\r
     }\r
 \r
@@ -305,7 +304,6 @@ MmcIdentificationMode (
 \r
   if (Timeout == 0) {\r
     DEBUG((EFI_D_ERROR, "MmcIdentificationMode(): No Card\n"));\r
 \r
   if (Timeout == 0) {\r
     DEBUG((EFI_D_ERROR, "MmcIdentificationMode(): No Card\n"));\r
-    ASSERT(0);\r
     return EFI_NO_MEDIA;\r
   } else {\r
     PrintOCR(Response[0]);\r
     return EFI_NO_MEDIA;\r
   } else {\r
     PrintOCR(Response[0]);\r
@@ -320,7 +318,6 @@ MmcIdentificationMode (
   Status = MmcHost->SendCommand(MMC_CMD2, 0);\r
   if (EFI_ERROR(Status)) {\r
     DEBUG((EFI_D_ERROR, "MmcIdentificationMode(MMC_CMD2): Error\n"));\r
   Status = MmcHost->SendCommand(MMC_CMD2, 0);\r
   if (EFI_ERROR(Status)) {\r
     DEBUG((EFI_D_ERROR, "MmcIdentificationMode(MMC_CMD2): Error\n"));\r
-    ASSERT(0);\r
     return Status;\r
   }\r
   MmcHost->ReceiveResponse(MMC_RESPONSE_TYPE_CID,Response);\r
     return Status;\r
   }\r
   MmcHost->ReceiveResponse(MMC_RESPONSE_TYPE_CID,Response);\r
@@ -363,6 +360,81 @@ MmcIdentificationMode (
   return EFI_SUCCESS;\r
 }\r
 \r
   return EFI_SUCCESS;\r
 }\r
 \r
+EFI_STATUS InitializeMmcDevice(\r
+  IN  MMC_HOST_INSTANCE   *MmcHostInstance\r
+  )\r
+{\r
+  UINT32                  Response[4];\r
+  EFI_STATUS              Status;\r
+  UINTN                   CardSize, NumBlocks, BlockSize, CmdArg;\r
+  EFI_MMC_HOST_PROTOCOL   *MmcHost;\r
+  UINTN                   BlockCount = 1;\r
+  \r
+  MmcHost = MmcHostInstance->MmcHost;\r
+\r
+  MmcIdentificationMode (MmcHostInstance);\r
+\r
+  //Send a command to get Card specific data\r
+  CmdArg = MmcHostInstance->CardInfo.RCA << 16;\r
+  Status = MmcHost->SendCommand(MMC_CMD9, CmdArg);\r
+  if (EFI_ERROR(Status)) {\r
+    DEBUG((EFI_D_ERROR, "MmcIdentificationMode(MMC_CMD9): Error, Status=%r\n", Status));\r
+    return Status;\r
+  }\r
+  //Read Response\r
+  MmcHost->ReceiveResponse(MMC_RESPONSE_TYPE_CSD,Response);\r
+  PrintCSD(Response);\r
+\r
+  if (MmcHostInstance->CardInfo.CardType == SD_CARD_2_HIGH) {\r
+    CardSize = HC_MMC_CSD_GET_DEVICESIZE(Response);\r
+    NumBlocks = ((CardSize + 1) * 1024);\r
+    BlockSize = 1 << MMC_CSD_GET_READBLLEN(Response);\r
+  } else {\r
+    CardSize = MMC_CSD_GET_DEVICESIZE(Response);\r
+    NumBlocks = (CardSize + 1) * (1 << (MMC_CSD_GET_DEVICESIZEMULT(Response) + 2));\r
+    BlockSize = 1 << MMC_CSD_GET_READBLLEN(Response);\r
+  }\r
+\r
+  //For >=2G card, BlockSize may be 1K, but the transfer size is 512 bytes.\r
+  if (BlockSize > 512) {\r
+    NumBlocks = MultU64x32(NumBlocks, BlockSize/512);\r
+    BlockSize = 512;\r
+  }\r
+\r
+  MmcHostInstance->BlockIo.Media->LastBlock    = (NumBlocks - 1);\r
+  MmcHostInstance->BlockIo.Media->BlockSize    = BlockSize;\r
+  MmcHostInstance->BlockIo.Media->ReadOnly     = MmcHost->IsReadOnly();\r
+  MmcHostInstance->BlockIo.Media->MediaPresent = TRUE;\r
+  MmcHostInstance->BlockIo.Media->MediaId++;\r
+\r
+  CmdArg = MmcHostInstance->CardInfo.RCA << 16;\r
+  Status = MmcHost->SendCommand(MMC_CMD7, CmdArg);\r
+  if (EFI_ERROR(Status)) {\r
+    DEBUG((EFI_D_ERROR, "MmcIdentificationMode(MMC_CMD7): Error and Status = %r\n", Status));\r
+    return Status;\r
+  }\r
+\r
+  Status = MmcNotifyState (MmcHostInstance, MmcTransferState);\r
+  if (EFI_ERROR(Status)) {\r
+    DEBUG((EFI_D_ERROR, "MmcIdentificationMode() : Error MmcTransferState\n"));\r
+    return Status;\r
+  }\r
+\r
+  // Set Block Length\r
+  Status = MmcHost->SendCommand(MMC_CMD16, MmcHostInstance->BlockIo.Media->BlockSize);\r
+  if (EFI_ERROR(Status)) {\r
+    DEBUG((EFI_D_ERROR, "MmcIdentificationMode(MMC_CMD16): Error MmcHostInstance->BlockIo.Media->BlockSize: %d and Error = %r\n",MmcHostInstance->BlockIo.Media->BlockSize, Status));\r
+    return Status;\r
+  }\r
+\r
+  // Block Count (not used). Could return an error for SD card\r
+  if (MmcHostInstance->CardInfo.CardType == MMC_CARD) {\r
+    MmcHost->SendCommand(MMC_CMD23, BlockCount);\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
 EFI_STATUS\r
 EFIAPI\r
 MmcReset (\r
 EFI_STATUS\r
 EFIAPI\r
 MmcReset (\r
@@ -424,7 +496,7 @@ MmcIoBlocks (
 {\r
   UINT32                  Response[4];\r
   EFI_STATUS              Status;\r
 {\r
   UINT32                  Response[4];\r
   EFI_STATUS              Status;\r
-  UINTN                   CardSize, NumBlocks, BlockSize, CmdArg;\r
+  UINTN                   CmdArg;\r
   INTN                    Timeout;\r
   UINTN                   Cmd;\r
   MMC_HOST_INSTANCE       *MmcHostInstance;\r
   INTN                    Timeout;\r
   UINTN                   Cmd;\r
   MMC_HOST_INSTANCE       *MmcHostInstance;\r
@@ -446,89 +518,13 @@ MmcIoBlocks (
     return EFI_NO_MEDIA;\r
   }\r
 \r
     return EFI_NO_MEDIA;\r
   }\r
 \r
-  // If the driver has not been initialized yet then go into Identification Mode\r
-  if (MmcHostInstance->State == MmcHwInitializationState) {\r
-    MmcIdentificationMode (MmcHostInstance);\r
-\r
-    //Send a command to get Card specific data\r
-    CmdArg = MmcHostInstance->CardInfo.RCA << 16;\r
-    Status = MmcHost->SendCommand(MMC_CMD9, CmdArg);\r
-    if (EFI_ERROR(Status)) {\r
-      DEBUG((EFI_D_ERROR, "MmcIdentificationMode(MMC_CMD9): Error, Status=%r\n", Status));\r
-      ASSERT(0);\r
-      return Status;\r
-    }\r
-    //Read Response\r
-    MmcHost->ReceiveResponse(MMC_RESPONSE_TYPE_CSD,Response);\r
-    PrintCSD(Response);\r
-\r
-    if (MmcHostInstance->CardInfo.CardType == SD_CARD_2_HIGH) {\r
-      CardSize = HC_MMC_CSD_GET_DEVICESIZE(Response);\r
-      NumBlocks = ((CardSize + 1) * 1024);\r
-      BlockSize = 1 << MMC_CSD_GET_READBLLEN(Response);\r
-    } else {\r
-      CardSize = MMC_CSD_GET_DEVICESIZE(Response);\r
-      NumBlocks = (CardSize + 1) * (1 << (MMC_CSD_GET_DEVICESIZEMULT(Response) + 2));\r
-      BlockSize = 1 << MMC_CSD_GET_READBLLEN(Response);\r
-    }\r
-\r
-    //For >=2G card, BlockSize may be 1K, but the transfer size is 512 bytes.\r
-    if (BlockSize > 512) {\r
-      NumBlocks = MultU64x32(NumBlocks, BlockSize/512);\r
-      BlockSize = 512;\r
-    }\r
-\r
-    MmcHostInstance->BlockIo.Media->LastBlock    = (NumBlocks - 1);\r
-    MmcHostInstance->BlockIo.Media->BlockSize    = BlockSize;\r
-    MmcHostInstance->BlockIo.Media->ReadOnly     = MmcHost->IsReadOnly();\r
-    MmcHostInstance->BlockIo.Media->MediaPresent = TRUE;\r
-    MmcHostInstance->BlockIo.Media->MediaId++;\r
-\r
-    CmdArg = MmcHostInstance->CardInfo.RCA << 16;\r
-    Status = MmcHost->SendCommand(MMC_CMD7, CmdArg);\r
-    if (EFI_ERROR(Status)) {\r
-      DEBUG((EFI_D_ERROR, "MmcIdentificationMode(MMC_CMD7): Error and Status = %r\n", Status));\r
-      ASSERT(0);\r
-      return Status;\r
-    }\r
-\r
-    Status = MmcNotifyState (MmcHostInstance, MmcTransferState);\r
-    if (EFI_ERROR(Status)) {\r
-      DEBUG((EFI_D_ERROR, "MmcIdentificationMode() : Error MmcTransferState\n"));\r
-      return Status;\r
-    }\r
-\r
-    // Set Block Length\r
-    Status = MmcHost->SendCommand(MMC_CMD16, This->Media->BlockSize);\r
-    if (EFI_ERROR(Status)) {\r
-      DEBUG((EFI_D_ERROR, "MmcIdentificationMode(MMC_CMD16): Error This->Media->BlockSize: %d and Error = %r\n",This->Media->BlockSize, Status));\r
-      return Status;\r
-    }\r
-\r
-    // Block Count (not used). Could return an error for SD card\r
-    if (MmcHostInstance->CardInfo.CardType == MMC_CARD) {\r
-      MmcHost->SendCommand(MMC_CMD23, BlockCount);\r
-    }\r
-  } else {\r
-    // Maybe test if the card has changed to update gMmcMedia information\r
-    if (MmcHostInstance->State == MmcTransferState) {\r
-      //DEBUG((EFI_D_ERROR, "MmcIdentificationMode() : MmcTransferState\n"));\r
-    } else if (MmcHostInstance->State == MmcStandByState) {\r
-      DEBUG((EFI_D_ERROR, "MmcIdentificationMode() : MmcStandByState\n"));\r
-    } else {\r
-      ASSERT(0);\r
-    }\r
-  }\r
-\r
   // All blocks must be within the device\r
   if ((Lba + (BufferSize / This->Media->BlockSize)) > (This->Media->LastBlock + 1)){\r
   // All blocks must be within the device\r
   if ((Lba + (BufferSize / This->Media->BlockSize)) > (This->Media->LastBlock + 1)){\r
-    ASSERT(0);\r
     return EFI_INVALID_PARAMETER;\r
   }\r
 \r
   // The buffer size must not be zero and it must be an exact multiple of the block size\r
   if ((BufferSize == 0) || ((BufferSize % This->Media->BlockSize) != 0)) {\r
     return EFI_INVALID_PARAMETER;\r
   }\r
 \r
   // The buffer size must not be zero and it must be an exact multiple of the block size\r
   if ((BufferSize == 0) || ((BufferSize % This->Media->BlockSize) != 0)) {\r
-    ASSERT(0);\r
     return EFI_BAD_BUFFER_SIZE;\r
   }\r
 \r
     return EFI_BAD_BUFFER_SIZE;\r
   }\r
 \r