[edk2-devel] [PATCH v3 14/28] Ampere: PCIe: Add PciHostBridgeLib library instance

Ard Biesheuvel ardb at kernel.org
Fri Sep 24 13:12:11 UTC 2021


On Wed, 15 Sept 2021 at 18:00, Nhi Pham <nhi at os.amperecomputing.com> wrote:
>
> From: Vu Nguyen <vunguyen at os.amperecomputing.com>
>
> Provides the number of supported RootBridges and the resource allocated
> for each RootBridge. These information are essential to the HostBridge
> driver to initialize the PCIe subsystem.
>
> Cc: Thang Nguyen <thang at os.amperecomputing.com>
> Cc: Chuong Tran <chuong at os.amperecomputing.com>
> Cc: Phong Vo <phong at os.amperecomputing.com>
> Cc: Leif Lindholm <leif at nuviainc.com>
> Cc: Michael D Kinney <michael.d.kinney at intel.com>
> Cc: Ard Biesheuvel <ardb+tianocore at kernel.org>
> Cc: Nate DeSimone <nathaniel.l.desimone at intel.com>
>
> Signed-off-by: Vu Nguyen <vunguyen at os.amperecomputing.com>

This looks ok to me, although I will note the code that patches the
_STA methods in the DSDT according to which host bridges actually
exist in the system should not typically live in a library. However,
this particular library is designed to be incorporated only by
PciHostBridgeDxe so in this case, I can live with it.

Reviewed-by: Ard Biesheuvel <ardb at kernel.org>

> ---
>  Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dsc.inc                        |   1 +
>  Silicon/Ampere/AmpereAltraPkg/Library/PciHostBridgeLib/PciHostBridgeLib.inf |  48 +++
>  Silicon/Ampere/AmpereAltraPkg/Library/PciHostBridgeLib/PciHostBridgeLib.c   | 378 ++++++++++++++++++++
>  3 files changed, 427 insertions(+)
>
> diff --git a/Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dsc.inc b/Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dsc.inc
> index d4e1b84c0276..dc66b711aba8 100644
> --- a/Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dsc.inc
> +++ b/Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dsc.inc
> @@ -228,6 +228,7 @@ [LibraryClasses.common.DXE_DRIVER]
>    PerformanceLib|MdeModulePkg/Library/DxePerformanceLib/DxePerformanceLib.inf
>    MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf
>    FlashLib|Silicon/Ampere/AmpereAltraPkg/Library/FlashLib/FlashLib.inf
> +  PciHostBridgeLib|Silicon/Ampere/AmpereAltraPkg/Library/PciHostBridgeLib/PciHostBridgeLib.inf
>
>  [LibraryClasses.common.UEFI_APPLICATION]
>    UefiDecompressLib|MdePkg/Library/BaseUefiDecompressLib/BaseUefiTianoCustomDecompressLib.inf
> diff --git a/Silicon/Ampere/AmpereAltraPkg/Library/PciHostBridgeLib/PciHostBridgeLib.inf b/Silicon/Ampere/AmpereAltraPkg/Library/PciHostBridgeLib/PciHostBridgeLib.inf
> new file mode 100644
> index 000000000000..a8ee0c2b9278
> --- /dev/null
> +++ b/Silicon/Ampere/AmpereAltraPkg/Library/PciHostBridgeLib/PciHostBridgeLib.inf
> @@ -0,0 +1,48 @@
> +## @file
> +#
> +# Copyright (c) 2021, Ampere Computing LLC. All rights reserved.<BR>
> +#
> +# SPDX-License-Identifier: BSD-2-Clause-Patent
> +#
> +##
> +
> +[Defines]
> +  INF_VERSION                    = 0x0001001B
> +  BASE_NAME                      = PciHostBridgeLib
> +  FILE_GUID                      = 9D0522E5-B5FD-4E3F-9D10-52AE221FA314
> +  MODULE_TYPE                    = DXE_DRIVER
> +  VERSION_STRING                 = 1.0
> +  LIBRARY_CLASS                  = PciHostBridgeLib|DXE_DRIVER
> +  CONSTRUCTOR                    = HostBridgeConstructor
> +
> +[Sources]
> +  PciHostBridgeLib.c
> +
> +[Packages]
> +  ArmPkg/ArmPkg.dec
> +  EmbeddedPkg/EmbeddedPkg.dec
> +  MdeModulePkg/MdeModulePkg.dec
> +  MdePkg/MdePkg.dec
> +  Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dec
> +  Silicon/Ampere/AmpereSiliconPkg/AmpereSiliconPkg.dec
> +
> +[LibraryClasses]
> +  Ac01PcieLib
> +  AcpiLib
> +  BaseLib
> +  BaseMemoryLib
> +  DebugLib
> +  DevicePathLib
> +  IoLib
> +  MemoryAllocationLib
> +  PrintLib
> +  UefiBootServicesTableLib
> +
> +[Guids]
> +  gEfiEventReadyToBootGuid
> +
> +[Protocols]
> +  gEfiCpuIo2ProtocolGuid          ## CONSUMES
> +
> +[Depex]
> +  gEfiCpuIo2ProtocolGuid
> diff --git a/Silicon/Ampere/AmpereAltraPkg/Library/PciHostBridgeLib/PciHostBridgeLib.c b/Silicon/Ampere/AmpereAltraPkg/Library/PciHostBridgeLib/PciHostBridgeLib.c
> new file mode 100644
> index 000000000000..281f20b4bb63
> --- /dev/null
> +++ b/Silicon/Ampere/AmpereAltraPkg/Library/PciHostBridgeLib/PciHostBridgeLib.c
> @@ -0,0 +1,378 @@
> +/** @file
> +  PCI Host Bridge Library instance for Ampere Altra-based platforms.
> +
> +  Copyright (c) 2021, Ampere Computing LLC. All rights reserved.<BR>
> +
> +  SPDX-License-Identifier: BSD-2-Clause-Patent
> +
> +**/
> +
> +#include <PiDxe.h>
> +
> +#include <Guid/EventGroup.h>
> +#include <IndustryStandard/Acpi.h>
> +#include <Library/Ac01PcieLib.h>
> +#include <Library/AcpiLib.h>
> +#include <Library/BaseMemoryLib.h>
> +#include <Library/DebugLib.h>
> +#include <Library/DevicePathLib.h>
> +#include <Library/MemoryAllocationLib.h>
> +#include <Library/PcdLib.h>
> +#include <Library/PciHostBridgeLib.h>
> +#include <Library/PrintLib.h>
> +#include <Library/UefiBootServicesTableLib.h>
> +#include <Protocol/PciHostBridgeResourceAllocation.h>
> +#include <Protocol/PciRootBridgeIo.h>
> +
> +#include <Ac01PcieCommon.h>
> +
> +GLOBAL_REMOVE_IF_UNREFERENCED
> +STATIC CHAR16 CONST * CONST mPciHostBridgeLibAcpiAddressSpaceTypeStr[] = {
> +  L"Mem", L"I/O", L"Bus"
> +};
> +
> +#pragma pack(1)
> +typedef struct {
> +  ACPI_HID_DEVICE_PATH     AcpiDevicePath;
> +  EFI_DEVICE_PATH_PROTOCOL EndDevicePath;
> +} EFI_PCI_ROOT_BRIDGE_DEVICE_PATH;
> +#pragma pack ()
> +
> +STATIC EFI_PCI_ROOT_BRIDGE_DEVICE_PATH mEfiPciRootBridgeDevicePath = {
> +  {
> +    {
> +      ACPI_DEVICE_PATH,
> +      ACPI_DP,
> +      {
> +        (UINT8)(sizeof (ACPI_HID_DEVICE_PATH)),
> +        (UINT8)((sizeof (ACPI_HID_DEVICE_PATH)) >> 8)
> +      }
> +    },
> +    EISA_PNP_ID (0x0A08), // PCIe
> +    0
> +  }, {
> +    END_DEVICE_PATH_TYPE,
> +    END_ENTIRE_DEVICE_PATH_SUBTYPE,
> +    {
> +      END_DEVICE_PATH_LENGTH,
> +      0
> +    }
> +  }
> +};
> +
> +STATIC PCI_ROOT_BRIDGE mRootBridgeTemplate = {
> +  0,                                              // Segment
> +  0,                                              // Supports
> +  0,                                              // Attributes
> +  TRUE,                                           // DmaAbove4G
> +  FALSE,                                          // NoExtendedConfigSpace
> +  FALSE,                                          // ResourceAssigned
> +  EFI_PCI_HOST_BRIDGE_MEM64_DECODE,
> +  {
> +    // Bus
> +    0,
> +    0
> +  }, {
> +    // Io
> +    0,
> +    0,
> +    0
> +  }, {
> +    // Mem
> +    MAX_UINT64,
> +    0,
> +    0
> +  }, {
> +    // MemAbove4G
> +    MAX_UINT64,
> +    0,
> +    0
> +  }, {
> +    // PMem
> +    MAX_UINT64,
> +    0,
> +    0
> +  }, {
> +    // PMemAbove4G
> +    MAX_UINT64,
> +    0,
> +    0
> +  },
> +  (EFI_DEVICE_PATH_PROTOCOL *)&mEfiPciRootBridgeDevicePath
> +};
> +
> +UINT8           mRootBridgeCount = 0;
> +PCI_ROOT_BRIDGE *mRootBridges = NULL;
> +
> +EFI_STATUS
> +UpdateStatusMethodObject (
> +  EFI_ACPI_SDT_PROTOCOL   *AcpiSdtProtocol,
> +  EFI_ACPI_HANDLE         TableHandle,
> +  CHAR8                   *AsciiObjectPath,
> +  CHAR8                   ReturnValue
> +  )
> +{
> +  EFI_STATUS            Status;
> +  EFI_ACPI_HANDLE       ObjectHandle;
> +  EFI_ACPI_DATA_TYPE    DataType;
> +  CHAR8                 *Buffer;
> +  UINTN                 DataSize;
> +
> +  Status = AcpiSdtProtocol->FindPath (TableHandle, AsciiObjectPath, &ObjectHandle);
> +  if (EFI_ERROR (Status) || ObjectHandle == NULL) {
> +    return EFI_SUCCESS;
> +  }
> +  ASSERT (ObjectHandle != NULL);
> +
> +  Status = AcpiSdtProtocol->GetOption (ObjectHandle, 2, &DataType, (VOID *)&Buffer, &DataSize);
> +  if (!EFI_ERROR (Status) && Buffer[2] == AML_BYTE_PREFIX) {
> +    //
> +    // Only patch when the initial value is byte object.
> +    //
> +    Buffer[3] = ReturnValue;
> +  }
> +
> +  AcpiSdtProtocol->Close (ObjectHandle);
> +  return Status;
> +}
> +
> +/**
> +  This function will be called when ReadyToBoot event is signaled.
> +
> +  @param Event   signaled event
> +  @param Context calling context
> +
> +  @retval VOID
> +**/
> +VOID
> +EFIAPI
> +PciHostBridgeReadyToBootEvent (
> +  EFI_EVENT Event,
> +  VOID      *Context
> +  )
> +{
> +  EFI_STATUS                    Status;
> +  EFI_ACPI_SDT_PROTOCOL         *AcpiSdtProtocol;
> +  EFI_ACPI_DESCRIPTION_HEADER   *Table;
> +  UINTN                         TableKey;
> +  UINTN                         TableIndex;
> +  EFI_ACPI_HANDLE               TableHandle;
> +  CHAR8                         NodePath[256];
> +  UINTN                         Count;
> +  UINTN                         Idx1;
> +  UINTN                         Idx2;
> +
> +  Count = 0;
> +
> +  Status = gBS->LocateProtocol (
> +                  &gEfiAcpiSdtProtocolGuid,
> +                  NULL,
> +                  (VOID **)&AcpiSdtProtocol
> +                  );
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((DEBUG_ERROR, "Unable to locate ACPI table protocol\n"));
> +    return;
> +  }
> +
> +  TableIndex = 0;
> +  Status = AcpiLocateTableBySignature (
> +             AcpiSdtProtocol,
> +             EFI_ACPI_6_3_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE,
> +             &TableIndex,
> +             &Table,
> +             &TableKey
> +             );
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((DEBUG_ERROR, "%a %d Status = %r \n", __FUNCTION__, __LINE__, Status));
> +    ASSERT_EFI_ERROR (Status);
> +    return;
> +  }
> +
> +  Status = AcpiSdtProtocol->OpenSdt (TableKey, &TableHandle);
> +  if (EFI_ERROR (Status)) {
> +    ASSERT_EFI_ERROR (Status);
> +    AcpiSdtProtocol->Close (TableHandle);
> +    return;
> +  }
> +
> +  for (Idx1 = 0; Idx1 < Ac01PcieGetTotalHBs (); Idx1++) {
> +    for (Idx2 = 0; Idx2 < Ac01PcieGetTotalRBsPerHB (Idx1); Idx2++) {
> +      AsciiSPrint (NodePath, sizeof (NodePath), "\\_SB.PCI%X._STA", Count);
> +      if (Ac01PcieCheckRootBridgeDisabled (Idx1, Idx2)) {
> +        UpdateStatusMethodObject (AcpiSdtProtocol, TableHandle, NodePath, 0x0);
> +      } else {
> +        UpdateStatusMethodObject (AcpiSdtProtocol, TableHandle, NodePath, 0xf);
> +      }
> +      Count++;
> +    }
> +  }
> +
> +  AcpiSdtProtocol->Close (TableHandle);
> +  AcpiUpdateChecksum ((UINT8 *)Table, Table->Length);
> +
> +  //
> +  // Close the event, so it will not be signalled again.
> +  //
> +  gBS->CloseEvent (Event);
> +}
> +
> +EFI_STATUS
> +HostBridgeConstructor (
> +  IN EFI_HANDLE        ImageHandle,
> +  IN EFI_SYSTEM_TABLE  *SystemTable
> +  )
> +{
> +  EFI_STATUS                      Status;
> +  UINT8                           Index;
> +  EFI_PCI_ROOT_BRIDGE_DEVICE_PATH *DevicePath;
> +  EFI_EVENT                       EvtReadyToBoot;
> +
> +  mRootBridges = AllocatePool (Ac01PcieGetTotalHBs () * sizeof (PCI_ROOT_BRIDGE));
> +  if (mRootBridges == NULL) {
> +    return EFI_OUT_OF_RESOURCES;
> +  }
> +
> +  Status = Ac01PcieSetup ();
> +  if (EFI_ERROR (Status)) {
> +    return Status;
> +  }
> +
> +  for (Index = 0; Index < Ac01PcieGetTotalHBs (); Index++) {
> +    CopyMem (&mRootBridges[mRootBridgeCount], &mRootBridgeTemplate, sizeof (PCI_ROOT_BRIDGE));
> +
> +    Status = Ac01PcieSetupRootBridge (Index, 0, (VOID *)&mRootBridges[mRootBridgeCount]);
> +    if (EFI_ERROR (Status)) {
> +      continue;
> +    }
> +    mRootBridges[mRootBridgeCount].Segment = Ac01PcieGetRootBridgeSegmentNumber (Index, 0);
> +
> +    DevicePath = AllocateCopyPool (
> +                   sizeof (EFI_PCI_ROOT_BRIDGE_DEVICE_PATH),
> +                   (VOID *)&mEfiPciRootBridgeDevicePath
> +                   );
> +    if (DevicePath == NULL) {
> +      continue;
> +    }
> +
> +    //
> +    // Embedded RC Index to the DevicePath
> +    // This will be used later by the platform NotifyPhase()
> +    //
> +    DevicePath->AcpiDevicePath.UID = Index;
> +
> +    mRootBridges[mRootBridgeCount].DevicePath = (EFI_DEVICE_PATH_PROTOCOL *)DevicePath;
> +    mRootBridgeCount++;
> +  }
> +
> +  Ac01PcieEnd ();
> +
> +  //
> +  // Register event to fixup ACPI table
> +  //
> +  Status = gBS->CreateEventEx (
> +                  EVT_NOTIFY_SIGNAL,                 // Type,
> +                  TPL_NOTIFY,                        // NotifyTpl
> +                  PciHostBridgeReadyToBootEvent,     // NotifyFunction
> +                  NULL,                              // NotifyContext
> +                  &gEfiEventReadyToBootGuid,         // EventGroup
> +                  &EvtReadyToBoot                    // Event
> +                  );
> +  ASSERT_EFI_ERROR (Status);
> +
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  Return all the root bridge instances in an array.
> +
> +  @param Count  Return the count of root bridge instances.
> +
> +  @return All the root bridge instances in an array.
> +          The array should be passed into PciHostBridgeFreeRootBridges()
> +          when it's not used.
> +**/
> +PCI_ROOT_BRIDGE *
> +EFIAPI
> +PciHostBridgeGetRootBridges (
> +  UINTN *Count
> +  )
> +{
> +  *Count = mRootBridgeCount;
> +  return mRootBridges;
> +}
> +
> +/**
> +  Free the root bridge instances array returned from PciHostBridgeGetRootBridges().
> +
> +  @param Bridges The root bridge instances array.
> +  @param Count   The count of the array.
> +**/
> +VOID
> +EFIAPI
> +PciHostBridgeFreeRootBridges (
> +  PCI_ROOT_BRIDGE *Bridges,
> +  UINTN           Count
> +  )
> +{
> +  //
> +  // Unsupported
> +  //
> +}
> +
> +/**
> +  Inform the platform that the resource conflict happens.
> +
> +  @param HostBridgeHandle Handle of the Host Bridge.
> +  @param Configuration    Pointer to PCI I/O and PCI memory resource
> +                          descriptors. The Configuration contains the resources
> +                          for all the root bridges. The resource for each root
> +                          bridge is terminated with END descriptor and an
> +                          additional END is appended indicating the end of the
> +                          entire resources. The resource descriptor field
> +                          values follow the description in
> +                          EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
> +                          .SubmitResources().
> +**/
> +VOID
> +EFIAPI
> +PciHostBridgeResourceConflict (
> +  EFI_HANDLE                        HostBridgeHandle,
> +  VOID                              *Configuration
> +  )
> +{
> +  EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptor;
> +  UINTN                             RootBridgeIndex;
> +  DEBUG ((DEBUG_ERROR, "PciHostBridge: Resource conflict happens!\n"));
> +
> +  RootBridgeIndex = 0;
> +  Descriptor = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Configuration;
> +  while (Descriptor->Desc == ACPI_ADDRESS_SPACE_DESCRIPTOR) {
> +    DEBUG ((DEBUG_ERROR, "RootBridge[%d]:\n", RootBridgeIndex++));
> +    for (; Descriptor->Desc == ACPI_ADDRESS_SPACE_DESCRIPTOR; Descriptor++) {
> +      ASSERT (Descriptor->ResType <
> +              (sizeof (mPciHostBridgeLibAcpiAddressSpaceTypeStr) /
> +               sizeof (mPciHostBridgeLibAcpiAddressSpaceTypeStr[0])
> +               )
> +              );
> +      DEBUG ((DEBUG_ERROR, " %s: Length/Alignment = 0x%lx / 0x%lx\n",
> +              mPciHostBridgeLibAcpiAddressSpaceTypeStr[Descriptor->ResType],
> +              Descriptor->AddrLen, Descriptor->AddrRangeMax
> +              ));
> +      if (Descriptor->ResType == ACPI_ADDRESS_SPACE_TYPE_MEM) {
> +        DEBUG ((DEBUG_ERROR, "     Granularity/SpecificFlag = %ld / %02x%s\n",
> +                Descriptor->AddrSpaceGranularity, Descriptor->SpecificFlag,
> +                ((Descriptor->SpecificFlag &
> +                  EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE
> +                  ) != 0) ? L" (Prefetchable)" : L""
> +                ));
> +      }
> +    }
> +    //
> +    // Skip the END descriptor for root bridge
> +    //
> +    ASSERT (Descriptor->Desc == ACPI_END_TAG_DESCRIPTOR);
> +    Descriptor = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)(
> +                   (EFI_ACPI_END_TAG_DESCRIPTOR *)Descriptor + 1
> +                   );
> +  }
> +}
> --
> 2.17.1
>


-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#81104): https://edk2.groups.io/g/devel/message/81104
Mute This Topic: https://groups.io/mt/85631180/1813853
Group Owner: devel+owner at edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [edk2-devel-archive at redhat.com]
-=-=-=-=-=-=-=-=-=-=-=-





More information about the edk2-devel-archive mailing list