GmmLib changes to support dynamic list of Adapters

diff --git a/Source/GmmLib/GlobalInfo/GmmInfo.cpp b/Source/GmmLib/GlobalInfo/GmmInfo.cpp
index 80d286e..61b5930 100644
--- a/Source/GmmLib/GlobalInfo/GmmInfo.cpp
+++ b/Source/GmmLib/GlobalInfo/GmmInfo.cpp
@@ -39,11 +39,31 @@
 
 /////////////////////////////////////////////////////////////////////////////////////
 /// GMM lib DLL Multi Adapter Functions
+/// 1. This is the main holder of the Gmmlib Context
+/// 2. There is only one Multi-Adpater Context object created per process.
+/// 3. Gmmlib dll is loaded only once per process, This done by the first UMD client
+///    requesting Libcontext on a first Adpater to be registered with Gmmlib.
+/// 4. Gmmlib dll is Unloaded only once per process, this is done by the last client
+///    destroying the LibContext on the only last registered Adapter with Gmmlib.
+/// 5. The LibContext for an Adapter is same across all the N clients and is always
+///    equal.
+/// 6. The ClientContext for all the N clients on particaluar Adapter is unique and
+///    never equal.
+/// 7  Ex: N UMD clients querying GmmLib for an GPU Adapter's Properties will have the
+///    Same/Single LibContext and Unique N ClientContexts for that same adpater, on
+///    same process.
+/// 8. GmmLib is dynamically scalable for any number of GPU Adapters and any number
+///    of Clients per Adapter.
+/// 9. In Multiprocessing, for a process, the Gmmlib Multi-Adpater Context
+///    object is protected/syncronized using the Lock/UnLockMAContextSyncMutex
+/// 9. In Multiprocessing, for a process with Gmmlib Multi-Adpater Context the
+///    LibContetxt is protected/syncronized using Lock/unLockSingletonContextSyncMutex
 /////////////////////////////////////////////////////////////////////////////////////
 GMM_MA_LIB_CONTEXT *pGmmMALibContext = NULL;
 
 /////////////////////////////////////////////////////////////////////////////////////
 /// Function to create GmmMultiAdapterContext Object
+/// Called only during dll load time.
 /// Since Linux doesnt have DLL Main equivalent, adding __attribute__((constructor))
 /// for this GmmCreateMultiAdapterContext()
 /////////////////////////////////////////////////////////////////////////////////////
@@ -51,12 +71,15 @@
 {
     if(!pGmmMALibContext)
     {
-        pGmmMALibContext = new GMM_MA_LIB_CONTEXT();
+        // This is called only during dll load
+        // Initializes the MA context.
+	pGmmMALibContext = new GMM_MA_LIB_CONTEXT();
     }
 }
 
 /////////////////////////////////////////////////////////////////////////////////////
 /// Function to Destroy GmmMultiAdapterContext Object
+/// Called Only during Dll Unload.
 /// Since Linux doesnt have DLL Main equivalent, adding __attribute__((destructor))
 /// for this GmmDestroyMultiAdapterContext()
 /////////////////////////////////////////////////////////////////////////////////////
@@ -66,7 +89,8 @@
     {
         // Before destroying GmmMultiAdapterContext, check if all the Adapters have
         // their GmmLibContext destroyed.
-        if(!pGmmMALibContext->GetNumAdapters())
+        // At this point the linked list is empty and pHeadNode = NULL & NumAdapter=0.
+	if(!pGmmMALibContext->GetNumAdapters())
         {
             delete pGmmMALibContext;
             pGmmMALibContext = NULL;
@@ -129,7 +153,8 @@
     GMM_STATUS SyncLockStatus = pGmmMALibContext->LockMAContextSyncMutex();
     if(SyncLockStatus == GMM_SUCCESS)
     {
-        Status = pGmmMALibContext->IntializeAdapterInfo(sBdf);
+        // Create the dynamic vectored linked list to register each new BDF.
+	Status = pGmmMALibContext->IntializeAdapterInfo(sBdf);
         if(GMM_SUCCESS != Status)
         {
             pGmmMALibContext->UnLockMAContextSyncMutex();
@@ -139,11 +164,14 @@
         int32_t ContextRefCount = pGmmMALibContext->IncrementRefCount(sBdf);
         if(ContextRefCount)
         {
-            pGmmMALibContext->UnLockMAContextSyncMutex();
+            // The requested Adapter is already registered.
+            // Do not create new LibContext.
+            // Use the one already created.
+	    pGmmMALibContext->UnLockMAContextSyncMutex();
             return GMM_SUCCESS;
         }
-
-        pGmmLibContext = new GMM_LIB_CONTEXT();
+        // Requested Adapter is new, Lets create a new LibContext
+	pGmmLibContext = new GMM_LIB_CONTEXT();
         if(!pGmmLibContext)
         {
             pGmmMALibContext->DecrementRefCount(sBdf);
@@ -156,7 +184,7 @@
 
 #if LHDM
         // Intialize SingletonContext Data.
-        // ProcessHeap creation requires size and GfxAddress parameters. These parameters are contants
+        // ProcessHeap creation requires size and GfxAddress parameters. These parameters are constants
         // and are given by GMM lib internally by PageTableMgr. Hence pHeapObj should be created here at the
         // time of SingletonContext creation. But untill all UMD clients have moved to GMM DLL, then we will
         // create this here.
@@ -189,7 +217,7 @@
 /////////////////////////////////////////////////////////////////////////////////////
 /// GMM lib DLL function for deleting the Singleton Context.
 /// Reference Count will be decremented and once the reference count reaches 0,
-/// Singleton Context will be freeed in memory
+/// Singleton Context will be freed in memory
 ///
 /// @param[in] sbdf: Adapter's BDF info that needs its SingletonContext to be freed
 /////////////////////////////////////////////////////////////////////////////////////
@@ -202,13 +230,21 @@
         GMM_STATUS SyncLockStatus = pGmmMALibContext->LockMAContextSyncMutex();
         if(SyncLockStatus == GMM_SUCCESS)
         {
+            // Decrement the Refcount on sBdf
             int32_t ContextRefCount = pGmmMALibContext->DecrementRefCount(sBdf);
+
+            // Refount = 0, It means that it the last client on this adapter
+            // Lets free the LibContext and the Adapter Node
             if(!ContextRefCount && pGmmMALibContext->GetAdapterLibContext(sBdf))
             {
                 pGmmMALibContext->GetAdapterLibContext(sBdf)->DestroyContext();
+                // Delete/free the LibContext object
                 delete pGmmMALibContext->GetAdapterLibContext(sBdf);
+                // Delete/free the AdapterNode from the Linked List
                 pGmmMALibContext->ReleaseAdapterInfo(sBdf);
             }
+            // RefCount !=0
+            // Retain the same LibContext and the Adapter Node
 
             pGmmMALibContext->UnLockMAContextSyncMutex();
         }
@@ -222,30 +258,20 @@
 /////////////////////////////////////////////////////////////////////////////////////
 GmmLib::GmmMultiAdapterContext::GmmMultiAdapterContext()
 {
-    uint32_t i = 0;
-
-    memset(AdapterInfo, 0, sizeof(AdapterInfo));
-    NumAdapters = 0;
+    NumAdapters     = 0;
     pCpuReserveBase = NULL;
     CpuReserveSize  = 0;
+    // The Multi-Adapter Initialization is done dynamiclly using a Single Linked list Vector
+    // pHeadNode points to the root node of the linked list and registers the first
+    // adapter received from UMD.
+    // Initializing to NULL at DLL load.
+    pHeadNode = NULL;
 
+    // Initializes the GmmLib::GmmMultiAdapterContext sync Mutex
+    // This is required whenever any update has to be done Multiadapter context
+    // This includes Addition, deletion and search operations of the GMM_ADAPTER_INFO linked list
 
-    for(i = 0; i < MAX_NUM_ADAPTERS; i++)
-    {
-        // Initiaze bdf to 0xFF, as {0,0,0} can be valid bdf
-        AdapterInfo[i].sBdf = {0xFF, 0xFF, 0xFF, 0};
-#ifdef _WIN32
-        AdapterInfo[i].SyncMutex = ::CreateMutex(NULL, FALSE, NULL);
-#else
-        AdapterInfo[i].SyncMutex = PTHREAD_MUTEX_INITIALIZER;
-#endif // _WIN32
-    }
-
-#ifdef _WIN32
-    MAContextSyncMutex = ::CreateMutex(NULL, FALSE, NULL);
-#else
-    MAContextSyncMutex           = PTHREAD_MUTEX_INITIALIZER;
-#endif // _WIN32
+    MAContextSyncMutex = PTHREAD_MUTEX_INITIALIZER;
 }
 
 /////////////////////////////////////////////////////////////////////////////////////
@@ -253,30 +279,8 @@
 /////////////////////////////////////////////////////////////////////////////////////
 GmmLib::GmmMultiAdapterContext::~GmmMultiAdapterContext()
 {
-    uint32_t i = 0;
-
-    for(i = 0; i < MAX_NUM_ADAPTERS; i++)
-    {
-#ifdef _WIN32
-        if(AdapterInfo[i].SyncMutex)
-        {
-            ::CloseHandle(AdapterInfo[i].SyncMutex);
-            AdapterInfo[i].SyncMutex = NULL;
-        }
-#else
-        pthread_mutex_destroy(&AdapterInfo[i].SyncMutex);
-#endif // _WIN32
-    }
-
-#ifdef _WIN32
-    if(MAContextSyncMutex)
-    {
-        ::CloseHandle(MAContextSyncMutex);
-        MAContextSyncMutex = NULL;
-    }
-#else
+// Un-initializes the GmmLib::GmmMultiAdapterContext sync Mutex
     pthread_mutex_destroy(&MAContextSyncMutex);
-#endif // _WIN32
 }
 
 /////////////////////////////////////////////////////////////////////////////////////
@@ -287,40 +291,103 @@
 /////////////////////////////////////////////////////////////////////////////////////
 GMM_STATUS GMM_STDCALL GmmLib::GmmMultiAdapterContext::IntializeAdapterInfo(ADAPTER_BDF sBdf)
 {
-    GMM_STATUS Status = GMM_SUCCESS;
-    uint32_t   i      = 0;
+    GMM_STATUS        Status = GMM_SUCCESS;
+    uint32_t          i      = 0;
+    GMM_ADAPTER_INFO *pNode = NULL, *pPrev = NULL;
 
-    for(i = 0; i < MAX_NUM_ADAPTERS; i++)
+    // Create the Root Node
+    // If the list is empty, this is the first adapter initialization. This node will
+    // be root node of the list. Any further Adapter additions will be appeneded to this
+    // list i.e pNext
+    if(!pHeadNode)
     {
-        if((sBdf.Bus == AdapterInfo[i].sBdf.Bus) &&
-           (sBdf.Device == AdapterInfo[i].sBdf.Device) &&
-           (sBdf.Function == AdapterInfo[i].sBdf.Function))
+        pNode = (GMM_ADAPTER_INFO *)malloc(sizeof(GMM_ADAPTER_INFO));
+        if(pNode)
         {
-            break;
-        }
-    }
+            NumAdapters++;
 
-    if(i < MAX_NUM_ADAPTERS)
-    {
-        // Already intialized, do nothing
-    }
-    else
-    {
-        // error check if NumAdapters is greater than MAX_NUM_ADAPTERS, then fail this call
-        if(NumAdapters == MAX_NUM_ADAPTERS)
-        {
-            Status = GMM_ERROR;
+            pNode->sBdf.Bus      = sBdf.Bus;
+            pNode->sBdf.Device   = sBdf.Device;
+            pNode->sBdf.Function = sBdf.Function;
+
+            //Protect this adapter node with the sync mutex. Initialize sync mutex
+            pNode->SyncMutex     = PTHREAD_MUTEX_INITIALIZER;
+
+            pNode->pGmmLibContext = NULL;
+            pNode->RefCount       = 0;
+            pNode->pNext          = NULL;
+
+            pHeadNode = pNode;
         }
         else
         {
-            // Search for a free slot in the AdapterInfo Array to add this BDF
-            ADAPTER_BDF FreeSlotBdf = {0xFF, 0xFF, 0xFF, 0};
-            uint32_t    AdapterIdx  = GetAdapterIndex(FreeSlotBdf);
+            // No memory for new node, return error
+            Status = GMM_ERROR;
+        }
+    }
+    else
+    {
+        // This happens if atleast 1 adapter is still registered in a Gmmlib
+        // MA context.
 
-            AdapterInfo[AdapterIdx].sBdf.Bus      = sBdf.Bus;
-            AdapterInfo[AdapterIdx].sBdf.Device   = sBdf.Device;
-            AdapterInfo[AdapterIdx].sBdf.Function = sBdf.Function;
-            NumAdapters++;
+        pNode = pHeadNode;
+        // Check if the Adapter Node already exists in the list
+        // Search the list if the Adapter is already registerted or not.
+        while(pNode)
+        {
+            if((sBdf.Bus == pNode->sBdf.Bus) &&
+               (sBdf.Device == pNode->sBdf.Device) &&
+               (sBdf.Function == pNode->sBdf.Function))
+            {
+                break;
+            }
+            else
+            {
+                pPrev = pNode;
+                pNode = pNode->pNext;
+            }
+        }
+
+        // New Adapter adding to the list, add it to the end
+        // After search, If pNode = NULL, It means that
+        // The requested adapter is not yet registered before. An UMD might have
+        // requested this for the first time on a new GPU adpater, Or
+        // Requested Adapter LibContext have been already destroyed/Un-registered
+        // for the same adpater before.
+        if(!pNode)
+        {
+            pNode = (GMM_ADAPTER_INFO *)malloc(sizeof(GMM_ADAPTER_INFO));
+            if(pNode)
+            {
+                NumAdapters++;
+
+                pNode->sBdf.Bus      = sBdf.Bus;
+                pNode->sBdf.Device   = sBdf.Device;
+                pNode->sBdf.Function = sBdf.Function;
+
+                //Protect this adapter node with the sync mutex. Initialize sync mutex
+                pNode->SyncMutex = PTHREAD_MUTEX_INITIALIZER;
+
+                pNode->pGmmLibContext = NULL;
+                pNode->RefCount       = 0;
+                pNode->pNext          = NULL;
+
+                // Add the new node at the end
+                // Appending the newly created Adapter Node to the end of the list.
+                pPrev->pNext = pNode;
+            }
+            else
+            {
+                // No memory for new node, return error
+                Status = GMM_ERROR;
+            }
+        }
+        else // Adapter node already exists in the list
+        {
+            // Already intialized, do nothing
+            // Adapter is already active in MA context.
+            // Going forward, Lets just incremnent the number of clients using this libContext
+            // i.e Increment the RefCount in on this sBdf Adapter Node
         }
     }
 
@@ -328,19 +395,65 @@
 }
 
 /////////////////////////////////////////////////////////////////////////////////////
-/// Member function of GmmMultiAdapterContext class for releasing Adapter details
+/// Member function of GmmMultiAdapterContext class for releasing Adapter Node
 ///
 /// @param[in]  sBdf       : Adpater Bus, Device and Fucntion details
-/// @return     GMM_STATUS
+/// @return     Void       : Deletes the Adpter Node either at Head, Tail or in between
 /////////////////////////////////////////////////////////////////////////////////////
 void GMM_STDCALL GmmLib::GmmMultiAdapterContext::ReleaseAdapterInfo(ADAPTER_BDF sBdf)
 {
-    uint32_t AdapterIdx = GetAdapterIndex(sBdf);
-    if(AdapterIdx < MAX_NUM_ADAPTERS)
+    GMM_ADAPTER_INFO *pNode = NULL, *pPrev = NULL;
+
+    pNode = pHeadNode;
+
+    // Search the linked list for the node with the sBdf value to be freed
+    while(pNode)
     {
-        AdapterInfo[AdapterIdx].sBdf           = {0xFF, 0xFF, 0xFF, 0};
-        AdapterInfo[AdapterIdx].pGmmLibContext = NULL;
-        NumAdapters--;
+        if((sBdf.Bus == pNode->sBdf.Bus) &&
+           (sBdf.Device == pNode->sBdf.Device) &&
+           (sBdf.Function == pNode->sBdf.Function))
+        {
+            // If sBdf was registered as the first Node i.e HeadNode
+            // Delete the first Node and make the second node as HeadNode
+            if(pNode == pHeadNode)
+            {
+                pHeadNode = pNode->pNext;
+            }
+            else
+            {
+                // If Adapter sBdf was registered as second Node or any in-between node or the Tail Node,
+                // Delete this Adapter Node and connect the adjacent Nodes if second or Middle
+                // i.e pNode->pNext != NULL,
+                // Or
+                // Completely delete the tail Node, i.e. pNode->pNext = NULL, if its a Tail Node.
+                pPrev->pNext = pNode->pNext;
+            }
+            // Decrement the Adapter Node count tracker variable
+            NumAdapters--;
+
+            break;
+        }
+        else
+        {
+            // If sBdf is not registered as this pNode, then search next Node
+            // Do this till the end of the list if necessary
+            pPrev = pNode;
+            pNode = pNode->pNext;
+        }
+    }
+
+    // Free the deleted Node above.
+    // This can either be HeadNode, TailNode or Any node between Head and Tail
+    if(pNode)
+    {
+        pNode->pGmmLibContext = NULL;
+        pNode->pNext          = NULL;
+        pNode->RefCount       = 0;
+
+        // Close the Mutex protecting thsi Adapter node
+        pthread_mutex_destroy(&pNode->SyncMutex);
+
+        free(pNode);
     }
 }
 
@@ -374,14 +487,17 @@
 //////////////////////////////////////////////////////////////////////////////////////
 GmmLib::Context *GMM_STDCALL GmmLib::GmmMultiAdapterContext::GetAdapterLibContext(ADAPTER_BDF sBdf)
 {
-    uint32_t AdapterIdx = GetAdapterIndex(sBdf);
-    if(AdapterIdx < MAX_NUM_ADAPTERS)
+    GMM_ADAPTER_INFO *pNode = NULL;
+
+    //Search the list and get the Adapter Node
+    pNode = (GMM_ADAPTER_INFO *)GetAdapterNode(sBdf);
+    if(pNode)
     {
-        return AdapterInfo[AdapterIdx].pGmmLibContext;
+        return pNode->pGmmLibContext;
     }
     else
     {
-        return NULL;
+        return NULL; //return Null if not found
     }
 }
 
@@ -394,10 +510,12 @@
 /////////////////////////////////////////////////////////////////////////////////////
 void GMM_STDCALL GmmLib::GmmMultiAdapterContext::SetAdapterLibContext(ADAPTER_BDF sBdf, GmmLib::Context *pGmmLibContext)
 {
-    uint32_t AdapterIdx = GetAdapterIndex(sBdf);
-    if(AdapterIdx < MAX_NUM_ADAPTERS)
+    GMM_ADAPTER_INFO *pNode = NULL;
+
+    pNode = (GMM_ADAPTER_INFO *)GetAdapterNode(sBdf);
+    if(pNode)
     {
-        AdapterInfo[AdapterIdx].pGmmLibContext = pGmmLibContext;
+        pNode->pGmmLibContext = pGmmLibContext;
     }
 }
 
@@ -453,17 +571,19 @@
 }
 
 /////////////////////////////////////////////////////////////////////////////////////
-/// Member function of GmmMultiAdapterContext class for Locking Adpater's Mutex
+/// Member function of GmmMultiAdapterContext class for Locking Adpater Node Mutex
 /// SyncMutex to protect access of GmmLibContext
 ///
 /// @return     GMM_STATUS.
 /////////////////////////////////////////////////////////////////////////////////////
 GMM_STATUS GMM_STDCALL GmmLib::GmmMultiAdapterContext::LockSingletonContextSyncMutex(ADAPTER_BDF sBdf)
 {
-    uint32_t AdapterIdx = GetAdapterIndex(sBdf);
-    if(AdapterIdx < MAX_NUM_ADAPTERS)
+    GMM_ADAPTER_INFO *pNode = NULL;
+
+    pNode = (GMM_ADAPTER_INFO *)GetAdapterNode(sBdf);
+    if(pNode)
     {
-        GMM_MUTEX_HANDLE SyncMutex = AdapterInfo[AdapterIdx].SyncMutex;
+        GMM_MUTEX_HANDLE SyncMutex = pNode->SyncMutex;
 
         if(SyncMutex)
         {
@@ -483,17 +603,19 @@
 }
 
 /////////////////////////////////////////////////////////////////////////////////////
-/// Member function of GmmMultiAdapterContext class for UnLocking Adpater's Mutex
+/// Member function of GmmMultiAdapterContext class for UnLocking Adpater Node Mutex
 /// SyncMutex to protect access of GmmLibContext
 ///
 /// @return     GMM_STATUS.
 /////////////////////////////////////////////////////////////////////////////////////
 GMM_STATUS GMM_STDCALL GmmLib::GmmMultiAdapterContext::UnlockSingletonContextSyncMutex(ADAPTER_BDF sBdf)
 {
-    uint32_t AdapterIdx = GetAdapterIndex(sBdf);
-    if(AdapterIdx < MAX_NUM_ADAPTERS)
+    GMM_ADAPTER_INFO *pNode = NULL;
+
+    pNode = (GMM_ADAPTER_INFO *)GetAdapterNode(sBdf);
+    if(pNode)
     {
-        GMM_MUTEX_HANDLE SyncMutex = AdapterInfo[AdapterIdx].SyncMutex;
+        GMM_MUTEX_HANDLE SyncMutex = pNode->SyncMutex;
         if(SyncMutex)
         {
             ::ReleaseMutex(SyncMutex);
@@ -541,11 +663,14 @@
 /////////////////////////////////////////////////////////////////////////////////////
 GMM_STATUS GMM_STDCALL GmmLib::GmmMultiAdapterContext::LockSingletonContextSyncMutex(ADAPTER_BDF sBdf)
 {
-    uint32_t AdapterIdx = GetAdapterIndex(sBdf);
-    if(AdapterIdx < MAX_NUM_ADAPTERS)
+
+    GMM_ADAPTER_INFO *pNode = NULL;
+
+    pNode = (GMM_ADAPTER_INFO *)GetAdapterNode(sBdf);
+    if(pNode)
     {
-        pthread_mutex_lock(&AdapterInfo[AdapterIdx].SyncMutex);
-        return GMM_SUCCESS;
+        pthread_mutex_lock(&(pNode->SyncMutex));
+	return GMM_SUCCESS;
     }
     else
     {
@@ -560,11 +685,13 @@
 /////////////////////////////////////////////////////////////////////////////////////
 GMM_STATUS GMM_STDCALL GmmLib::GmmMultiAdapterContext::UnlockSingletonContextSyncMutex(ADAPTER_BDF sBdf)
 {
-    uint32_t AdapterIdx = GetAdapterIndex(sBdf);
-    if(AdapterIdx < MAX_NUM_ADAPTERS)
+    GMM_ADAPTER_INFO *pNode = NULL;
+
+    pNode = (GMM_ADAPTER_INFO *)GetAdapterNode(sBdf);
+    if(pNode)
     {
-        pthread_mutex_unlock(&AdapterInfo[AdapterIdx].SyncMutex);
-        return GMM_SUCCESS;
+        pthread_mutex_unlock(&(pNode->SyncMutex));
+	return GMM_SUCCESS;
     }
     else
     {
@@ -575,21 +702,62 @@
 #endif //#ifdef _WIN32
 
 /////////////////////////////////////////////////////////////////////////////////////
-/// Member function of GmmMultiAdapterContext class for Incrementing Adpater's Ref
+/// Member function of GmmMultiAdapterContext class for returning the Adapter Node
+///
+/// @param[in]  sBdf       : Adpater Bus, Device and Fucntion details
+/// @return     Adpater Node corresponding the given BDF or return NULL if not found
+/////////////////////////////////////////////////////////////////////////////////////
+void *GMM_STDCALL GmmLib::GmmMultiAdapterContext::GetAdapterNode(ADAPTER_BDF sBdf)
+{
+    GMM_ADAPTER_INFO *pNode = NULL;
+
+    pNode = pHeadNode;
+    // Search the entire linked list if the Adapter Node with sBdf is found or not
+    while(pNode)
+    {
+        if((sBdf.Bus == pNode->sBdf.Bus) &&
+           (sBdf.Device == pNode->sBdf.Device) &&
+           (sBdf.Function == pNode->sBdf.Function))
+        {
+            // Yes, Found!. This is the Adapter Node
+            // pNode != NULL, will be valid pointer.
+            break;
+        }
+        else
+        {
+            // Not found, Search Next
+            // pNode = NULL if traversed till the tail and not found
+            pNode = pNode->pNext;
+        }
+    }
+
+    return pNode;
+}
+
+
+/////////////////////////////////////////////////////////////////////////////////////
+/// Member function of GmmMultiAdapterContext class for Incrementing Adpater Node Ref
 /// Count
+/// RefCount indicates the number of UMD clients using a particaluar Adapter.
+/// RefCount is incremented when a client requests LibContext on already registered
+/// adapter.
+/// RefCount = 0, when no clients are using an adapter's LibContext
+/// RefCount > 0, when at least one client is using the adapter's LibContext
+//
 /// @param1     sBdf        Adpater's Bus, Device and Fucntion
 /// @return     Current value of the ref count.
 /////////////////////////////////////////////////////////////////////////////////////
 int32_t GMM_STDCALL GmmLib::GmmMultiAdapterContext::IncrementRefCount(ADAPTER_BDF sBdf)
 {
-    uint32_t AdapterIdx = GetAdapterIndex(sBdf);
-    if(AdapterIdx < MAX_NUM_ADAPTERS)
-    {
-        int32_t *Ref = &AdapterInfo[AdapterIdx].RefCount;
+    GMM_ADAPTER_INFO *pNode = NULL;
 
-#if defined(_WIN32)
-        return (InterlockedIncrement((LONG *)Ref) - 1); //InterLockedIncrement() returns incremented value
-#elif defined(__linux__) 
+    pNode = (GMM_ADAPTER_INFO *)GetAdapterNode(sBdf);
+    if(pNode)
+    {
+        int32_t *Ref = &pNode->RefCount;
+
+#if defined(__linux__)
+        // returns 0 only when registering the first client
         return (__sync_fetch_and_add(Ref, 1));
 #endif
     }
@@ -602,16 +770,24 @@
 /////////////////////////////////////////////////////////////////////////////////////
 /// Member function of GmmMultiAdapterContext class for Decrementing Adpater's Ref
 /// Count
+/// RefCount indicates the number of UMD clients using a particaluar Adapter.
+/// RefCount is decremented when a clients requests LibContext destroy on already
+/// registered adapter.
+/// RefCount = 0, when no clients are using an adapter's LibContext
+/// RefCount > 0, when at least one client is using the adapter's LibContext
+//
 /// @param1     sBdf        Adpater's Bus, Device and Fucntion
 /// @return     Current value of the ref count.
 /////////////////////////////////////////////////////////////////////////////////////
 int32_t GMM_STDCALL GmmLib::GmmMultiAdapterContext::DecrementRefCount(ADAPTER_BDF sBdf)
 {
-    uint32_t AdapterIdx = GetAdapterIndex(sBdf);
-    if(AdapterIdx < MAX_NUM_ADAPTERS)
+    GMM_ADAPTER_INFO *pNode = NULL;
+
+    pNode = (GMM_ADAPTER_INFO *)GetAdapterNode(sBdf);
+    if(pNode)
     {
-        int32_t *Ref          = &AdapterInfo[AdapterIdx].RefCount;
-        int      CurrentValue = 0;
+        int32_t *Ref          = &pNode->RefCount;
+	int      CurrentValue = 0;
         int      TargetValue  = 0;
         do
         {
diff --git a/Source/GmmLib/inc/External/Common/GmmInfo.h b/Source/GmmLib/inc/External/Common/GmmInfo.h
index e7361c8..0524c48 100644
--- a/Source/GmmLib/inc/External/Common/GmmInfo.h
+++ b/Source/GmmLib/inc/External/Common/GmmInfo.h
@@ -580,6 +580,8 @@
     int32_t             RefCount;                           // Ref Count for the number of Gmm UMD Lib process Singleton Context created per Process
     GMM_MUTEX_HANDLE    SyncMutex;                          // SyncMutex to protect access of Gmm UMD Lib process Singleton Context 
     ADAPTER_BDF         sBdf;                               // Adpater's Bus, Device and Function info for which Gmm UMD Lib process Singleton Context is created
+    _GMM_ADAPTER_INFO_  *pNext;                             // Linked List Next pointer to point to the Next Adapter node in the List
+
 }GMM_ADAPTER_INFO;
     
 ////////////////////////////////////////////////////////////////////////////////////
@@ -589,12 +591,15 @@
     class NON_PAGED_SECTION GmmMultiAdapterContext : public GmmMemAllocator
     {
     private:
-        GMM_ADAPTER_INFO                AdapterInfo[MAX_NUM_ADAPTERS];
+        GMM_ADAPTER_INFO                AdapterInfo[MAX_NUM_ADAPTERS];// For Static Initialization of adapter.
         GMM_MUTEX_HANDLE                MAContextSyncMutex;         // SyncMutex to protect access of GmmMultiAdpaterContext
         uint32_t                        NumAdapters;
 	void*                           pCpuReserveBase;
 	uint64_t                        CpuReserveSize;
-
+        GMM_ADAPTER_INFO                *pHeadNode;// For dynamic Initialization of adapter.
+                                                   // The Multi-Adapter Initialization is done dynamiclly using a Linked list Vector
+                                                   // pHeadNode points to the root node of the linked list and registers the first
+                                                   // adapter received from UMD.
     public:
         //Constructors and destructors
         GmmMultiAdapterContext();
@@ -614,6 +619,7 @@
         int32_t GMM_STDCALL             DecrementRefCount(ADAPTER_BDF sBdf);
         GMM_STATUS GMM_STDCALL          LockSingletonContextSyncMutex(ADAPTER_BDF sBdf);
         GMM_STATUS GMM_STDCALL          UnlockSingletonContextSyncMutex(ADAPTER_BDF sBdf);
+        void *GMM_STDCALL               GetAdapterNode(ADAPTER_BDF sBdf); // Replacemet for GetAdapterIndex, now get adapter info from a node in the linked list
     }; // GmmMultiAdapterContext
 
 } //namespace