/** @file @copyright Copyright 1999 - 2021 Intel Corporation.
SPDX-License-Identifier: BSD-2-Clause-Patent **/ #include #include #include #include "PciHostBridge.h" #include "PciRootBridge.h" #include "PciRebalance.h" extern EFI_IIO_UDS_PROTOCOL *mIioUds; /** Adjust resource assignments among sockets to fit the low MMIO resources (32-bit addresses) from the PCI(e) devices in the system @param[in,out] SocketResources - CPU_RESOURCE structure pointer that stores all resources need per socket @param[in] ResourceType - Type of resource that requires alignment @param[in] ValidSockets - Number of Valid Sockets, need it to calculate how resources need to be splitted @retval EFI_SUCCESS - Succeed. @retval EFI_OUT_OF_RESOURCES - Not enough resources to be adjusted within the socket. */ EFI_STATUS AdjustSocketMmioL ( IN OUT CPU_RESOURCE *SocketResources, IN UINT8 ResourceType, IN UINT8 ValidSockets ) { CONST UINT8 LastSocket = ValidSockets - 1; UINT8 Socket; UINT8 Stack; UINT8 LastStack; UINT64 Take; UINT32 UboxMmioSize; UINT64 ResourceSize; UINT64 TotalResourceSize; UINT32 TempMmioBase; UINT32 TempMmioLimit; Take = 0; UboxMmioSize = mIioUds->IioUdsPtr->PlatformData.UboxMmioSize; // // Get first and last MMIOL address // TempMmioBase = mIioUds->IioUdsPtr->PlatformData.PlatGlobalMmio32Base; TempMmioLimit = mIioUds->IioUdsPtr->PlatformData.PlatGlobalMmio32Limit; // // Find all the extra space left // for (Socket = 0; Socket < ValidSockets; Socket++) { if ((SocketResources[Socket].MmiolResourceNeeds == 0) && (SocketResources[Socket].MmiolResourcesLeft != 0)) { Take += SocketResources[Socket].MmiolResourcesLeft + 1; SocketResources[Socket].MmiolResourcesLeft = 0; } } // // Give space to sockets that needs more space favoring first come first served // for (Socket = 0; Socket < ValidSockets; Socket++) { if ((SocketResources[Socket].MmiolResourceNeeds != 0) && (Take >= SocketResources[Socket].MmiolResourceNeeds)) { Take -= SocketResources[Socket].MmiolResourceNeeds; DEBUG((DEBUG_ERROR, "SocketResources[%x].MmiolResourceNeeds = %x\n", Socket, SocketResources[Socket].MmiolResourceNeeds)); SocketResources[Socket].MmiolResourceNeeds = 0; } } // // Give away leftover resources // LastStack = LastStackOfSocket (LastSocket); if (Take != 0) { if (SocketResources[LastSocket].StackRes[LastStack].MmiolLength != 0) { SocketResources[LastSocket].StackRes[LastStack].MmiolLength += (UINT32)Take; } else{ SocketResources[LastSocket].StackRes[LastStack].MmiolLength += ((UINT32)Take - 1); } } // // Verify all resource requested can fit into the systems address range. // TotalResourceSize = 0; for (Socket = 0; Socket < ValidSockets; Socket++) { LastStackWithResources (&SocketResources[Socket], Socket, ResourceType, &LastStack, &ResourceSize); TotalResourceSize += ResourceSize + UboxMmioSize; } DEBUG ((DEBUG_INFO, "Total Request MMIOL Range = %08Xh\n", TotalResourceSize)); DEBUG ((DEBUG_INFO, "Total System MMIOL Range = %08Xh\n", (TempMmioLimit - TempMmioBase + 1))); if (TotalResourceSize > (TempMmioLimit - TempMmioBase + 1)) { // // Not enough system resources to support the request. // Remove all request to update NVRAM variable for this resource type. // for (Socket = 0; Socket < ValidSockets; Socket ++) { for (Stack = 0; Stack < MAX_IIO_STACK; Stack ++) { if (!(mIioUds->IioUdsPtr->PlatformData.CpuQpiInfo[Socket].stackPresentBitmap & (1 << Stack))) { continue; } SocketResources[Socket].StackRes[Stack].MmiolUpdate = 0; } } DEBUG ((DEBUG_ERROR, "[PCI] ERROR: Out of adjustable MMIOL resources. Can't adjust across sockets\n")); return EFI_OUT_OF_RESOURCES; } DEBUG ((DEBUG_ERROR, "Assigning new socket MMIOL range...\n")); for (Socket = 0, TempMmioLimit = TempMmioBase - 1; Socket < ValidSockets; Socket ++) { SocketResources[Socket].MmiolBase = TempMmioLimit + 1; // // Update the stacks base and limit values. // for (Stack = 0; Stack < MAX_IIO_STACK; Stack++) { if (!(mIioUds->IioUdsPtr->PlatformData.CpuQpiInfo[Socket].stackPresentBitmap & (1 << Stack))) { SocketResources[Socket].StackRes[Stack].MmiolBase = 0; SocketResources[Socket].StackRes[Stack].MmiolLimit = 0; } else { SocketResources[Socket].StackRes[Stack].MmiolBase = TempMmioLimit + 1; if (SocketResources[Socket].StackRes[Stack].MmiolLength != 0) { // // MmiolLength is actually length-1, so we should move TempMmioLimit by MmiolLength+1, // but only when it is >0, i.e. only for stack that has resources. // TempMmioLimit += SocketResources[Socket].StackRes[Stack].MmiolLength + 1; SocketResources[Socket].StackRes[Stack].MmiolLimit = TempMmioLimit; } else { SocketResources[Socket].StackRes[Stack].MmiolLimit = SocketResources[Socket].StackRes[Stack].MmiolBase; } SocketResources[Socket].StackRes[Stack].MmiolUpdate = 1; } DEBUG ((DEBUG_ERROR, "SocketResources[%x].StackRes[%x].MmiolBase = %X newLength = %x\n", Socket, Stack, SocketResources[Socket].StackRes[Stack].MmiolBase, SocketResources[Socket].StackRes[Stack].MmiolLength)); DEBUG ((DEBUG_ERROR, "SocketResources[%x].StackRes[%x].MmiolLimit = %X\n", Socket, Stack, SocketResources[Socket].StackRes[Stack].MmiolLimit)); DEBUG ((DEBUG_ERROR, "SocketResources[%x].StackRes[%x].MmiolUpdate= %d\n", Socket, Stack, SocketResources[Socket].StackRes[Stack].MmiolUpdate)); } // for (Stack...) // // In the socket resources there can be UBOX, unfortunatelly not exposed in stackPresentBitmap // so it has to be handled with such uguly hacks. // TempMmioLimit += UboxMmioSize; SocketResources[Socket].MmiolLimit = TempMmioLimit; } // for (Socket...) return EFI_SUCCESS; }