+/**\r
+ Return feature dependence result.\r
+\r
+ @param[in] CpuFeature Pointer to CPU feature.\r
+ @param[in] Before Check before dependence or after.\r
+\r
+ @retval return the dependence result.\r
+**/\r
+CPU_FEATURE_DEPENDENCE_TYPE\r
+DetectFeatureScope (\r
+ IN CPU_FEATURES_ENTRY *CpuFeature,\r
+ IN BOOLEAN Before\r
+ )\r
+{\r
+ if (Before) {\r
+ if (CpuFeature->PackageBeforeFeatureBitMask != NULL) {\r
+ return PackageDepType;\r
+ }\r
+\r
+ if (CpuFeature->CoreBeforeFeatureBitMask != NULL) {\r
+ return CoreDepType;\r
+ }\r
+\r
+ if (CpuFeature->BeforeFeatureBitMask != NULL) {\r
+ return ThreadDepType;\r
+ }\r
+\r
+ return NoneDepType;\r
+ }\r
+\r
+ if (CpuFeature->PackageAfterFeatureBitMask != NULL) {\r
+ return PackageDepType;\r
+ }\r
+\r
+ if (CpuFeature->CoreAfterFeatureBitMask != NULL) {\r
+ return CoreDepType;\r
+ }\r
+\r
+ if (CpuFeature->AfterFeatureBitMask != NULL) {\r
+ return ThreadDepType;\r
+ }\r
+\r
+ return NoneDepType;\r
+}\r
+\r
+/**\r
+ Clear dependence for the specified type.\r
+\r
+ @param[in] CurrentFeature Cpu feature need to clear.\r
+ @param[in] Before Before or after dependence relationship.\r
+\r
+**/\r
+VOID\r
+ClearFeatureScope (\r
+ IN CPU_FEATURES_ENTRY *CpuFeature,\r
+ IN BOOLEAN Before\r
+ )\r
+{\r
+ if (Before) {\r
+ if (CpuFeature->BeforeFeatureBitMask != NULL) {\r
+ FreePool (CpuFeature->BeforeFeatureBitMask);\r
+ CpuFeature->BeforeFeatureBitMask = NULL;\r
+ }\r
+ if (CpuFeature->CoreBeforeFeatureBitMask != NULL) {\r
+ FreePool (CpuFeature->CoreBeforeFeatureBitMask);\r
+ CpuFeature->CoreBeforeFeatureBitMask = NULL;\r
+ }\r
+ if (CpuFeature->PackageBeforeFeatureBitMask != NULL) {\r
+ FreePool (CpuFeature->PackageBeforeFeatureBitMask);\r
+ CpuFeature->PackageBeforeFeatureBitMask = NULL;\r
+ }\r
+ } else {\r
+ if (CpuFeature->PackageAfterFeatureBitMask != NULL) {\r
+ FreePool (CpuFeature->PackageAfterFeatureBitMask);\r
+ CpuFeature->PackageAfterFeatureBitMask = NULL;\r
+ }\r
+ if (CpuFeature->CoreAfterFeatureBitMask != NULL) {\r
+ FreePool (CpuFeature->CoreAfterFeatureBitMask);\r
+ CpuFeature->CoreAfterFeatureBitMask = NULL;\r
+ }\r
+ if (CpuFeature->AfterFeatureBitMask != NULL) {\r
+ FreePool (CpuFeature->AfterFeatureBitMask);\r
+ CpuFeature->AfterFeatureBitMask = NULL;\r
+ }\r
+ }\r
+}\r
+\r
+/**\r
+ Base on dependence relationship to asjust feature dependence.\r
+\r
+ ONLY when the feature before(or after) the find feature also has \r
+ dependence with the find feature. In this case, driver need to base\r
+ on dependce relationship to decide how to insert current feature and\r
+ adjust the feature dependence.\r
+\r
+ @param[in] PreviousFeature CPU feature current before the find one.\r
+ @param[in] CurrentFeature Cpu feature need to adjust.\r
+ @param[in] Before Before or after dependence relationship.\r
+\r
+ @retval TRUE means the current feature dependence has been adjusted.\r
+\r
+ @retval FALSE means the previous feature dependence has been adjusted.\r
+ or previous feature has no dependence with the find one.\r
+\r
+**/\r
+BOOLEAN\r
+AdjustFeaturesDependence (\r
+ IN OUT CPU_FEATURES_ENTRY *PreviousFeature,\r
+ IN OUT CPU_FEATURES_ENTRY *CurrentFeature,\r
+ IN BOOLEAN Before\r
+ )\r
+{\r
+ CPU_FEATURE_DEPENDENCE_TYPE PreDependType;\r
+ CPU_FEATURE_DEPENDENCE_TYPE CurrentDependType;\r
+\r
+ PreDependType = DetectFeatureScope(PreviousFeature, Before);\r
+ CurrentDependType = DetectFeatureScope(CurrentFeature, Before);\r
+\r
+ //\r
+ // If previous feature has no dependence with the find featue.\r
+ // return FALSE.\r
+ //\r
+ if (PreDependType == NoneDepType) {\r
+ return FALSE;\r
+ }\r
+\r
+ //\r
+ // If both feature have dependence, keep the one which needs use more \r
+ // processors and clear the dependence for the other one.\r
+ //\r
+ if (PreDependType >= CurrentDependType) {\r
+ ClearFeatureScope (CurrentFeature, Before);\r
+ return TRUE;\r
+ } else {\r
+ ClearFeatureScope (PreviousFeature, Before);\r
+ return FALSE;\r
+ }\r
+}\r
+\r
+/**\r
+ Base on dependence relationship to asjust feature order.\r
+\r
+ @param[in] FeatureList Pointer to CPU feature list\r
+ @param[in] FindEntry The entry this feature depend on.\r
+ @param[in] CurrentEntry The entry for this feature.\r
+ @param[in] Before Before or after dependence relationship.\r
+\r
+**/\r
+VOID\r
+AdjustEntry (\r
+ IN LIST_ENTRY *FeatureList,\r
+ IN OUT LIST_ENTRY *FindEntry,\r
+ IN OUT LIST_ENTRY *CurrentEntry,\r
+ IN BOOLEAN Before\r
+ )\r
+{\r
+ LIST_ENTRY *PreviousEntry;\r
+ CPU_FEATURES_ENTRY *PreviousFeature;\r
+ CPU_FEATURES_ENTRY *CurrentFeature;\r
+\r
+ //\r
+ // For CPU feature which has core or package type dependence, later code need to insert\r
+ // AcquireSpinLock/ReleaseSpinLock logic to sequency the execute order.\r
+ // So if driver finds both feature A and B need to execute before feature C, driver will\r
+ // base on dependence type of feature A and B to update the logic here.\r
+ // For example, feature A has package type dependence and feature B has core type dependence,\r
+ // because package type dependence need to wait for more processors which has strong dependence\r
+ // than core type dependence. So driver will adjust the feature order to B -> A -> C. and driver \r
+ // will remove the feature dependence in feature B. \r
+ // Driver just needs to make sure before feature C been executed, feature A has finished its task\r
+ // in all all thread. Feature A finished in all threads also means feature B have finshed in all\r
+ // threads.\r
+ //\r
+ if (Before) {\r
+ PreviousEntry = GetPreviousNode (FeatureList, FindEntry);\r
+ } else {\r\r
+ PreviousEntry = GetNextNode (FeatureList, FindEntry);\r
+ }\r
+\r
+ CurrentFeature = CPU_FEATURE_ENTRY_FROM_LINK (CurrentEntry);\r
+ RemoveEntryList (CurrentEntry);\r
+\r
+ if (IsNull (FeatureList, PreviousEntry)) {\r
+ //\r
+ // If not exist the previous or next entry, just insert the current entry.\r
+ //\r
+ if (Before) {\r
+ InsertTailList (FindEntry, CurrentEntry);\r
+ } else {\r
+ InsertHeadList (FindEntry, CurrentEntry);\r
+ }\r
+ } else {\r
+ //\r
+ // If exist the previous or next entry, need to check it before insert curent entry.\r
+ //\r
+ PreviousFeature = CPU_FEATURE_ENTRY_FROM_LINK (PreviousEntry);\r
+\r
+ if (AdjustFeaturesDependence (PreviousFeature, CurrentFeature, Before)) {\r
+ //\r
+ // Return TRUE means current feature dependence has been cleared and the previous\r
+ // feature dependence has been kept and used. So insert current feature before (or after)\r
+ // the previous feature.\r
+ //\r
+ if (Before) {\r
+ InsertTailList (PreviousEntry, CurrentEntry);\r
+ } else {\r
+ InsertHeadList (PreviousEntry, CurrentEntry);\r
+ }\r
+ } else {\r
+ if (Before) {\r
+ InsertTailList (FindEntry, CurrentEntry);\r
+ } else {\r
+ InsertHeadList (FindEntry, CurrentEntry);\r
+ }\r
+ }\r
+ }\r
+}\r\r
+\r
+/**\r
+ Checks and adjusts current CPU features per dependency relationship.\r
+\r
+ @param[in] FeatureList Pointer to CPU feature list\r
+ @param[in] CurrentEntry Pointer to current checked CPU feature\r
+ @param[in] FeatureMask The feature bit mask.\r
+\r
+ @retval return Swapped info.\r
+**/\r
+BOOLEAN\r
+InsertToBeforeEntry (\r
+ IN LIST_ENTRY *FeatureList,\r
+ IN LIST_ENTRY *CurrentEntry,\r
+ IN UINT8 *FeatureMask\r
+ )\r
+{\r
+ LIST_ENTRY *CheckEntry;\r
+ CPU_FEATURES_ENTRY *CheckFeature;\r
+ BOOLEAN Swapped;\r
+\r
+ Swapped = FALSE;\r
+\r
+ //\r
+ // Check all features dispatched before this entry\r
+ //\r
+ CheckEntry = GetFirstNode (FeatureList);\r
+ while (CheckEntry != CurrentEntry) {\r
+ CheckFeature = CPU_FEATURE_ENTRY_FROM_LINK (CheckEntry);\r
+ if (IsBitMaskMatchCheck (CheckFeature->FeatureMask, FeatureMask)) {\r
+ AdjustEntry (FeatureList, CheckEntry, CurrentEntry, TRUE);\r
+ Swapped = TRUE;\r
+ break;\r
+ }\r
+ CheckEntry = CheckEntry->ForwardLink;\r
+ }\r
+\r
+ return Swapped;\r
+}\r
+\r
+/**\r
+ Checks and adjusts current CPU features per dependency relationship.\r
+\r
+ @param[in] FeatureList Pointer to CPU feature list\r
+ @param[in] CurrentEntry Pointer to current checked CPU feature\r
+ @param[in] FeatureMask The feature bit mask.\r
+\r
+ @retval return Swapped info.\r
+**/\r
+BOOLEAN\r
+InsertToAfterEntry (\r
+ IN LIST_ENTRY *FeatureList,\r
+ IN LIST_ENTRY *CurrentEntry,\r
+ IN UINT8 *FeatureMask\r
+ )\r
+{\r
+ LIST_ENTRY *CheckEntry;\r
+ CPU_FEATURES_ENTRY *CheckFeature;\r
+ BOOLEAN Swapped;\r
+\r
+ Swapped = FALSE;\r
+\r
+ //\r
+ // Check all features dispatched after this entry\r
+ //\r
+ CheckEntry = GetNextNode (FeatureList, CurrentEntry);\r
+ while (!IsNull (FeatureList, CheckEntry)) {\r
+ CheckFeature = CPU_FEATURE_ENTRY_FROM_LINK (CheckEntry);\r
+ if (IsBitMaskMatchCheck (CheckFeature->FeatureMask, FeatureMask)) {\r
+ AdjustEntry (FeatureList, CheckEntry, CurrentEntry, FALSE);\r
+ Swapped = TRUE;\r
+ break;\r
+ }\r
+ CheckEntry = CheckEntry->ForwardLink;\r
+ }\r
+\r
+ return Swapped;\r
+}\r
+\r