diff --git a/src/Ryujinx.Input.SDL2/SDL2GamepadDriver.cs b/src/Ryujinx.Input.SDL2/SDL2GamepadDriver.cs
index 0e3a130117..c741493c1a 100644
--- a/src/Ryujinx.Input.SDL2/SDL2GamepadDriver.cs
+++ b/src/Ryujinx.Input.SDL2/SDL2GamepadDriver.cs
@@ -9,8 +9,18 @@ namespace Ryujinx.Input.SDL2
     {
         private readonly Dictionary<int, string> _gamepadsInstanceIdsMapping;
         private readonly List<string> _gamepadsIds;
+        private readonly object _lock = new object();
 
-        public ReadOnlySpan<string> GamepadsIds => _gamepadsIds.ToArray();
+        public ReadOnlySpan<string> GamepadsIds
+        {
+            get
+            {
+                lock (_lock)
+                {
+                    return _gamepadsIds.ToArray();
+                }
+            }
+        }
 
         public string DriverName => "SDL2";
 
@@ -35,28 +45,39 @@ namespace Ryujinx.Input.SDL2
             }
         }
 
-        private static string GenerateGamepadId(int joystickIndex)
+        private string GenerateGamepadId(int joystickIndex)
         {
             Guid guid = SDL_JoystickGetDeviceGUID(joystickIndex);
 
+            // Add a unique identifier to the start of the GUID in case of duplicates.
+
             if (guid == Guid.Empty)
             {
                 return null;
             }
 
-            return joystickIndex + "-" + guid;
-        }
+            string id;
 
-        private static int GetJoystickIndexByGamepadId(string id)
-        {
-            string[] data = id.Split("-");
-
-            if (data.Length != 6 || !int.TryParse(data[0], out int joystickIndex))
+            lock (_lock)
             {
-                return -1;
+                int guidIndex = 0;
+                id = guidIndex + "-" + guid;
+
+                while (_gamepadsIds.Contains(id))
+                {
+                    id = (++guidIndex) + "-" + guid;
+                }
             }
 
-            return joystickIndex;
+            return id;
+        }
+
+        private int GetJoystickIndexByGamepadId(string id)
+        {
+            lock (_lock)
+            {
+                return _gamepadsIds.IndexOf(id);
+            }
         }
 
         private void HandleJoyStickDisconnected(int joystickInstanceId)
@@ -64,7 +85,11 @@ namespace Ryujinx.Input.SDL2
             if (_gamepadsInstanceIdsMapping.TryGetValue(joystickInstanceId, out string id))
             {
                 _gamepadsInstanceIdsMapping.Remove(joystickInstanceId);
-                _gamepadsIds.Remove(id);
+
+                lock (_lock)
+                {
+                    _gamepadsIds.Remove(id);
+                }
 
                 OnGamepadDisconnected?.Invoke(id);
             }
@@ -74,6 +99,13 @@ namespace Ryujinx.Input.SDL2
         {
             if (SDL_IsGameController(joystickDeviceId) == SDL_bool.SDL_TRUE)
             {
+                if (_gamepadsInstanceIdsMapping.ContainsKey(joystickInstanceId))
+                {
+                    // Sometimes a JoyStick connected event fires after the app starts even though it was connected before
+                    // so it is rejected to avoid doubling the entries.
+                    return;
+                }
+
                 string id = GenerateGamepadId(joystickDeviceId);
 
                 if (id == null)
@@ -81,16 +113,12 @@ namespace Ryujinx.Input.SDL2
                     return;
                 }
 
-                // Sometimes a JoyStick connected event fires after the app starts even though it was connected before
-                // so it is rejected to avoid doubling the entries.
-                if (_gamepadsIds.Contains(id))
-                {
-                    return;
-                }
-
                 if (_gamepadsInstanceIdsMapping.TryAdd(joystickInstanceId, id))
                 {
-                    _gamepadsIds.Add(id);
+                    lock (_lock)
+                    {
+                        _gamepadsIds.Add(id);
+                    }
 
                     OnGamepadConnected?.Invoke(id);
                 }
@@ -110,7 +138,10 @@ namespace Ryujinx.Input.SDL2
                     OnGamepadDisconnected?.Invoke(id);
                 }
 
-                _gamepadsIds.Clear();
+                lock (_lock)
+                {
+                    _gamepadsIds.Clear();
+                }
 
                 SDL2Driver.Instance.Dispose();
             }
@@ -131,11 +162,6 @@ namespace Ryujinx.Input.SDL2
                 return null;
             }
 
-            if (id != GenerateGamepadId(joystickIndex))
-            {
-                return null;
-            }
-
             IntPtr gamepadHandle = SDL_GameControllerOpen(joystickIndex);
 
             if (gamepadHandle == IntPtr.Zero)
diff --git a/src/Ryujinx.Input/HLE/NpadManager.cs b/src/Ryujinx.Input/HLE/NpadManager.cs
index 25887748f8..5ae73bda19 100644
--- a/src/Ryujinx.Input/HLE/NpadManager.cs
+++ b/src/Ryujinx.Input/HLE/NpadManager.cs
@@ -5,6 +5,7 @@ using Ryujinx.HLE.HOS.Services.Hid;
 using System;
 using System.Collections.Generic;
 using System.Diagnostics;
+using System.Linq;
 using System.Runtime.CompilerServices;
 using CemuHookClient = Ryujinx.Input.Motion.CemuHook.Client;
 using ControllerType = Ryujinx.Common.Configuration.Hid.ControllerType;
@@ -69,7 +70,20 @@ namespace Ryujinx.Input.HLE
         private void HandleOnGamepadDisconnected(string obj)
         {
             // Force input reload
-            ReloadConfiguration(_inputConfig, _enableKeyboard, _enableMouse);
+            lock (_lock)
+            {
+                // Forcibly disconnect any controllers with this ID.
+                for (int i = 0; i < _controllers.Length; i++)
+                {
+                    if (_controllers[i]?.Id == obj)
+                    {
+                        _controllers[i]?.Dispose();
+                        _controllers[i] = null;
+                    }
+                }
+
+                ReloadConfiguration(_inputConfig, _enableKeyboard, _enableMouse);
+            }
         }
 
         private void HandleOnGamepadConnected(string id)
@@ -106,31 +120,48 @@ namespace Ryujinx.Input.HLE
         {
             lock (_lock)
             {
-                for (int i = 0; i < _controllers.Length; i++)
-                {
-                    _controllers[i]?.Dispose();
-                    _controllers[i] = null;
-                }
+                NpadController[] oldControllers = _controllers.ToArray();
 
                 List<InputConfig> validInputs = new();
 
                 foreach (InputConfig inputConfigEntry in inputConfig)
                 {
-                    NpadController controller = new(_cemuHookClient);
+                    NpadController controller;
+                    int index = (int)inputConfigEntry.PlayerIndex;
+
+                    if (oldControllers[index] != null)
+                    {
+                        // Try reuse the existing controller.
+                        controller = oldControllers[index];
+                        oldControllers[index] = null;
+                    }
+                    else
+                    {
+                        controller = new(_cemuHookClient);
+                    }
 
                     bool isValid = DriverConfigurationUpdate(ref controller, inputConfigEntry);
 
                     if (!isValid)
                     {
+                        _controllers[index] = null;
                         controller.Dispose();
                     }
                     else
                     {
-                        _controllers[(int)inputConfigEntry.PlayerIndex] = controller;
+                        _controllers[index] = controller;
                         validInputs.Add(inputConfigEntry);
                     }
                 }
 
+                for (int i = 0; i < oldControllers.Length; i++)
+                {
+                    // Disconnect any controllers that weren't reused by the new configuration.
+
+                    oldControllers[i]?.Dispose();
+                    oldControllers[i] = null;
+                }
+
                 _inputConfig = inputConfig;
                 _enableKeyboard = enableKeyboard;
                 _enableMouse = enableMouse;