PciRebalanceMmio32.c 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  1. /** @file
  2. @copyright
  3. Copyright 1999 - 2021 Intel Corporation. <BR>
  4. SPDX-License-Identifier: BSD-2-Clause-Patent
  5. **/
  6. #include <Guid/SocketPciResourceData.h>
  7. #include <Guid/SocketIioVariable.h>
  8. #include <Protocol/IioUds.h>
  9. #include "PciHostBridge.h"
  10. #include "PciRootBridge.h"
  11. #include "PciRebalance.h"
  12. extern EFI_IIO_UDS_PROTOCOL *mIioUds;
  13. /**
  14. Adjust resource assignments among sockets to fit the low
  15. MMIO resources (32-bit addresses) from the PCI(e) devices in the system
  16. @param[in,out] SocketResources - CPU_RESOURCE structure pointer that stores all resources need per socket
  17. @param[in] ResourceType - Type of resource that requires alignment
  18. @param[in] ValidSockets - Number of Valid Sockets, need it to calculate how resources need to be splitted
  19. @retval EFI_SUCCESS - Succeed.
  20. @retval EFI_OUT_OF_RESOURCES - Not enough resources to be adjusted within the socket.
  21. */
  22. EFI_STATUS
  23. AdjustSocketMmioL (
  24. IN OUT CPU_RESOURCE *SocketResources,
  25. IN UINT8 ResourceType,
  26. IN UINT8 ValidSockets
  27. )
  28. {
  29. CONST UINT8 LastSocket = ValidSockets - 1;
  30. UINT8 Socket;
  31. UINT8 Stack;
  32. UINT8 LastStack;
  33. UINT64 Take;
  34. UINT32 UboxMmioSize;
  35. UINT64 ResourceSize;
  36. UINT64 TotalResourceSize;
  37. UINT32 TempMmioBase;
  38. UINT32 TempMmioLimit;
  39. Take = 0;
  40. UboxMmioSize = mIioUds->IioUdsPtr->PlatformData.UboxMmioSize;
  41. //
  42. // Get first and last MMIOL address
  43. //
  44. TempMmioBase = mIioUds->IioUdsPtr->PlatformData.PlatGlobalMmio32Base;
  45. TempMmioLimit = mIioUds->IioUdsPtr->PlatformData.PlatGlobalMmio32Limit;
  46. //
  47. // Find all the extra space left
  48. //
  49. for (Socket = 0; Socket < ValidSockets; Socket++) {
  50. if ((SocketResources[Socket].MmiolResourceNeeds == 0) && (SocketResources[Socket].MmiolResourcesLeft != 0)) {
  51. Take += SocketResources[Socket].MmiolResourcesLeft + 1;
  52. SocketResources[Socket].MmiolResourcesLeft = 0;
  53. }
  54. }
  55. //
  56. // Give space to sockets that needs more space favoring first come first served
  57. //
  58. for (Socket = 0; Socket < ValidSockets; Socket++) {
  59. if ((SocketResources[Socket].MmiolResourceNeeds != 0) && (Take >= SocketResources[Socket].MmiolResourceNeeds)) {
  60. Take -= SocketResources[Socket].MmiolResourceNeeds;
  61. DEBUG((DEBUG_ERROR, "SocketResources[%x].MmiolResourceNeeds = %x\n", Socket, SocketResources[Socket].MmiolResourceNeeds));
  62. SocketResources[Socket].MmiolResourceNeeds = 0;
  63. }
  64. }
  65. //
  66. // Give away leftover resources
  67. //
  68. LastStack = LastStackOfSocket (LastSocket);
  69. if (Take != 0) {
  70. if (SocketResources[LastSocket].StackRes[LastStack].MmiolLength != 0) {
  71. SocketResources[LastSocket].StackRes[LastStack].MmiolLength += (UINT32)Take;
  72. } else{
  73. SocketResources[LastSocket].StackRes[LastStack].MmiolLength += ((UINT32)Take - 1);
  74. }
  75. }
  76. //
  77. // Verify all resource requested can fit into the systems address range.
  78. //
  79. TotalResourceSize = 0;
  80. for (Socket = 0; Socket < ValidSockets; Socket++) {
  81. LastStackWithResources (&SocketResources[Socket], Socket, ResourceType, &LastStack, &ResourceSize);
  82. TotalResourceSize += ResourceSize + UboxMmioSize;
  83. }
  84. DEBUG ((DEBUG_INFO, "Total Request MMIOL Range = %08Xh\n", TotalResourceSize));
  85. DEBUG ((DEBUG_INFO, "Total System MMIOL Range = %08Xh\n", (TempMmioLimit - TempMmioBase + 1)));
  86. if (TotalResourceSize > (TempMmioLimit - TempMmioBase + 1)) {
  87. //
  88. // Not enough system resources to support the request.
  89. // Remove all request to update NVRAM variable for this resource type.
  90. //
  91. for (Socket = 0; Socket < ValidSockets; Socket ++) {
  92. for (Stack = 0; Stack < MAX_IIO_STACK; Stack ++) {
  93. if (!(mIioUds->IioUdsPtr->PlatformData.CpuQpiInfo[Socket].stackPresentBitmap & (1 << Stack))) {
  94. continue;
  95. }
  96. SocketResources[Socket].StackRes[Stack].MmiolUpdate = 0;
  97. }
  98. }
  99. DEBUG ((DEBUG_ERROR, "[PCI] ERROR: Out of adjustable MMIOL resources. Can't adjust across sockets\n"));
  100. return EFI_OUT_OF_RESOURCES;
  101. }
  102. DEBUG ((DEBUG_ERROR, "Assigning new socket MMIOL range...\n"));
  103. for (Socket = 0, TempMmioLimit = TempMmioBase - 1; Socket < ValidSockets; Socket ++) {
  104. SocketResources[Socket].MmiolBase = TempMmioLimit + 1;
  105. //
  106. // Update the stacks base and limit values.
  107. //
  108. for (Stack = 0; Stack < MAX_IIO_STACK; Stack++) {
  109. if (!(mIioUds->IioUdsPtr->PlatformData.CpuQpiInfo[Socket].stackPresentBitmap & (1 << Stack))) {
  110. SocketResources[Socket].StackRes[Stack].MmiolBase = 0;
  111. SocketResources[Socket].StackRes[Stack].MmiolLimit = 0;
  112. } else {
  113. SocketResources[Socket].StackRes[Stack].MmiolBase = TempMmioLimit + 1;
  114. if (SocketResources[Socket].StackRes[Stack].MmiolLength != 0) {
  115. //
  116. // MmiolLength is actually length-1, so we should move TempMmioLimit by MmiolLength+1,
  117. // but only when it is >0, i.e. only for stack that has resources.
  118. //
  119. TempMmioLimit += SocketResources[Socket].StackRes[Stack].MmiolLength + 1;
  120. SocketResources[Socket].StackRes[Stack].MmiolLimit = TempMmioLimit;
  121. } else {
  122. SocketResources[Socket].StackRes[Stack].MmiolLimit = SocketResources[Socket].StackRes[Stack].MmiolBase;
  123. }
  124. SocketResources[Socket].StackRes[Stack].MmiolUpdate = 1;
  125. }
  126. DEBUG ((DEBUG_ERROR, "SocketResources[%x].StackRes[%x].MmiolBase = %X newLength = %x\n", Socket, Stack,
  127. SocketResources[Socket].StackRes[Stack].MmiolBase, SocketResources[Socket].StackRes[Stack].MmiolLength));
  128. DEBUG ((DEBUG_ERROR, "SocketResources[%x].StackRes[%x].MmiolLimit = %X\n", Socket, Stack,
  129. SocketResources[Socket].StackRes[Stack].MmiolLimit));
  130. DEBUG ((DEBUG_ERROR, "SocketResources[%x].StackRes[%x].MmiolUpdate= %d\n", Socket, Stack,
  131. SocketResources[Socket].StackRes[Stack].MmiolUpdate));
  132. } // for (Stack...)
  133. //
  134. // In the socket resources there can be UBOX, unfortunatelly not exposed in stackPresentBitmap
  135. // so it has to be handled with such uguly hacks.
  136. //
  137. TempMmioLimit += UboxMmioSize;
  138. SocketResources[Socket].MmiolLimit = TempMmioLimit;
  139. } // for (Socket...)
  140. return EFI_SUCCESS;
  141. }