In a later patch, we'll modify the depex of
"ArmPkg/Drivers/CpuDxe/CpuDxe.inf" (currently "AFTER gArmGicDxeFileGuid")
to "gHardwareInterruptProtocolGuid OR gHardwareInterrupt2ProtocolGuid".

Considering platforms that include "ArmPkg/Drivers/CpuDxe/CpuDxe.inf",
there are two classes:

(1) The platform gets its gHardwareInterruptProtocolGuid or
    gHardwareInterrupt2ProtocolGuid instance from
    "ArmPkg/Drivers/ArmGic/ArmGicDxe.inf". For such platforms, the
    upcoming CpuDxe change is not a problem, because commit 61a7b0ec634f
    made ArmGicDxe wait for the CPU Arch Protocol with a protocol notify.

(2) The platform gets its hardware interrupt protocol(s) from a different
    driver that has a hard depex on the CPU Arch Protocol. The upcoming
    CpuDxe change would lead to a loop in the DXE dispatch order.

In the edk2 tree, only "BeagleBoardPkg/BeagleBoardPkg.dsc" falls in class
(2), and the driver in question is "Omap35xxPkg/InterruptDxe". Port (most
of) commit 61a7b0ec634f to it.

Cc: Ard Biesheuvel <ard.biesheu...@linaro.org>
Cc: Leif Lindholm <leif.lindh...@linaro.org>
Cc: Steve Capper <steve.cap...@linaro.org>
Cc: Supreeth Venkatesh <supreeth.venkat...@arm.com>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Laszlo Ersek <ler...@redhat.com>
---

Notes:
    build-tested only, as part of BeagleBoardPkg

 Omap35xxPkg/InterruptDxe/InterruptDxe.inf    |  6 +-
 Omap35xxPkg/InterruptDxe/HardwareInterrupt.c | 81 +++++++++++++++-----
 2 files changed, 66 insertions(+), 21 deletions(-)

diff --git a/Omap35xxPkg/InterruptDxe/InterruptDxe.inf 
b/Omap35xxPkg/InterruptDxe/InterruptDxe.inf
index 6deb8c3f675c..61ad89af2758 100644
--- a/Omap35xxPkg/InterruptDxe/InterruptDxe.inf
+++ b/Omap35xxPkg/InterruptDxe/InterruptDxe.inf
@@ -41,14 +41,14 @@ [LibraryClasses]
   PrintLib
   UefiDriverEntryPoint
   IoLib
   ArmLib
 
 [Protocols]
-  gHardwareInterruptProtocolGuid
-  gEfiCpuArchProtocolGuid
+  gHardwareInterruptProtocolGuid  ## PRODUCES
+  gEfiCpuArchProtocolGuid         ## CONSUMES ## NOTIFY
 
 [FixedPcd.common]
   gEmbeddedTokenSpaceGuid.PcdInterruptBaseAddress
 
 [Depex]
-  gEfiCpuArchProtocolGuid
+  TRUE
diff --git a/Omap35xxPkg/InterruptDxe/HardwareInterrupt.c 
b/Omap35xxPkg/InterruptDxe/HardwareInterrupt.c
index 09e22b5921b0..2ddc7c0566d0 100644
--- a/Omap35xxPkg/InterruptDxe/HardwareInterrupt.c
+++ b/Omap35xxPkg/InterruptDxe/HardwareInterrupt.c
@@ -293,12 +293,60 @@ EFI_HARDWARE_INTERRUPT_PROTOCOL 
gHardwareInterruptProtocol = {
   EnableInterruptSource,
   DisableInterruptSource,
   GetInterruptSourceState,
   EndOfInterrupt
 };
 
+STATIC VOID *mCpuArchProtocolNotifyEventRegistration;
+
+STATIC
+VOID
+EFIAPI
+CpuArchEventProtocolNotify (
+  IN  EFI_EVENT       Event,
+  IN  VOID            *Context
+  )
+{
+  EFI_CPU_ARCH_PROTOCOL   *Cpu;
+  EFI_STATUS              Status;
+
+  //
+  // Get the CPU protocol that this driver requires.
+  //
+  Status = gBS->LocateProtocol (&gEfiCpuArchProtocolGuid, NULL, (VOID **)&Cpu);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "%a: gBS->LocateProtocol() - %r\n", __FUNCTION__,
+      Status));
+    ASSERT (FALSE);
+    return;
+  }
+
+  //
+  // Unregister the default exception handler.
+  //
+  Status = Cpu->RegisterInterruptHandler (Cpu, EXCEPT_ARM_IRQ, NULL);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "%a: Cpu->RegisterInterruptHandler() - %r\n",
+      __FUNCTION__, Status));
+    ASSERT (FALSE);
+    return;
+  }
+
+  //
+  // Register to receive interrupts
+  //
+  Status = Cpu->RegisterInterruptHandler (Cpu, EXCEPT_ARM_IRQ,
+                  IrqInterruptHandler);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "%a: Cpu->RegisterInterruptHandler() - %r\n",
+      __FUNCTION__, Status));
+    ASSERT (FALSE);
+    return;
+  }
+}
+
 /**
   Initialize the state information for the CPU Architectural Protocol
 
   @param  ImageHandle   of the loaded driver
   @param  SystemTable   Pointer to the System Table
 
@@ -311,13 +359,13 @@ EFI_STATUS
 InterruptDxeInitialize (
   IN EFI_HANDLE         ImageHandle,
   IN EFI_SYSTEM_TABLE   *SystemTable
   )
 {
   EFI_STATUS  Status;
-  EFI_CPU_ARCH_PROTOCOL   *Cpu;
+  EFI_EVENT   CpuArchEvent;
 
   // Make sure the Interrupt Controller Protocol is not already installed in 
the system.
   ASSERT_PROTOCOL_ALREADY_INSTALLED (NULL, &gHardwareInterruptProtocolGuid);
 
   // Make sure all interrupts are disabled by default.
   MmioWrite32 (INTCPS_MIR(0), 0xFFFFFFFF);
@@ -328,30 +376,27 @@ InterruptDxeInitialize (
   Status = gBS->InstallMultipleProtocolInterfaces(&gHardwareInterruptHandle,
                                                   
&gHardwareInterruptProtocolGuid,   &gHardwareInterruptProtocol,
                                                   NULL);
   ASSERT_EFI_ERROR(Status);
 
   //
-  // Get the CPU protocol that this driver requires.
-  //
-  Status = gBS->LocateProtocol(&gEfiCpuArchProtocolGuid, NULL, (VOID **)&Cpu);
-  ASSERT_EFI_ERROR(Status);
-
-  //
-  // Unregister the default exception handler.
-  //
-  Status = Cpu->RegisterInterruptHandler(Cpu, EXCEPT_ARM_IRQ, NULL);
-  ASSERT_EFI_ERROR(Status);
-
-  //
-  // Register to receive interrupts
-  //
-  Status = Cpu->RegisterInterruptHandler(Cpu, EXCEPT_ARM_IRQ, 
IrqInterruptHandler);
-  ASSERT_EFI_ERROR(Status);
+  // Install the interrupt handler as soon as the CPU arch protocol appears.
+  //
+  CpuArchEvent = EfiCreateProtocolNotifyEvent (
+                   &gEfiCpuArchProtocolGuid,
+                   TPL_CALLBACK,
+                   CpuArchEventProtocolNotify,
+                   NULL,
+                   &mCpuArchProtocolNotifyEventRegistration
+                   );
+  ASSERT (CpuArchEvent != NULL);
 
   // Register for an ExitBootServicesEvent
   Status = gBS->CreateEvent(EVT_SIGNAL_EXIT_BOOT_SERVICES, TPL_NOTIFY, 
ExitBootServicesEvent, NULL, &EfiExitBootServicesEvent);
-  ASSERT_EFI_ERROR(Status);
+  if (EFI_ERROR (Status)) {
+    ASSERT_EFI_ERROR (Status);
+    gBS->CloseEvent (CpuArchEvent);
+  }
 
   return Status;
 }
 
-- 
2.14.1.3.gb7cf6e02401b


_______________________________________________
edk2-devel mailing list
edk2-devel@lists.01.org
https://lists.01.org/mailman/listinfo/edk2-devel

Reply via email to