Add support for driver blocklist by environment variable

Drivers can be blocked from loading via `POWER_PROFILE_DAEMON_DRIVER_BLOCK`
which is a comma separated value listing the drivers to block.

This is an escape hatch in case CPU or platform driver are failing and a user
would like to block them.
This commit is contained in:
Mario Limonciello 2024-01-04 07:33:19 -06:00 committed by Kate Hsuan
parent 61f7650e35
commit bec7dfdf34
2 changed files with 77 additions and 0 deletions

View file

@ -871,6 +871,23 @@ stop_profile_drivers (PpdApp *data)
g_clear_object (&data->platform_driver);
}
static gboolean
driver_blocked (PpdDriver *driver)
{
guint i;
const gchar *driver_name = ppd_driver_get_driver_name (driver);
const gchar *env = g_getenv ("POWER_PROFILE_DAEMON_DRIVER_BLOCK");
g_autofree gchar **drivers = NULL;
if (env == NULL)
return FALSE;
drivers = g_strsplit (env, ",", -1);
for (i = 0; drivers[i] != NULL; i++) {
if (g_strcmp0 (drivers[i], driver_name) == 0)
return TRUE;
}
return FALSE;
}
static void
start_profile_drivers (PpdApp *data)
{
@ -887,6 +904,10 @@ start_profile_drivers (PpdApp *data)
PpdProbeResult result;
g_debug ("Handling driver '%s'", ppd_driver_get_driver_name (driver));
if (driver_blocked (driver)) {
g_debug ("Driver '%s' is blocked, skipping", ppd_driver_get_driver_name (driver));
continue;
}
if (PPD_IS_DRIVER_CPU (data->cpu_driver) && PPD_IS_DRIVER_CPU (driver)) {
g_debug ("CPU driver '%s' already probed, skipping driver '%s'",

View file

@ -653,6 +653,62 @@ class Tests(dbusmock.DBusTestCase):
self.stop_daemon()
def test_driver_blocklist(self):
'''Test driver blocklist works'''
# Create 2 CPUs with preferences
dir1 = os.path.join(self.testbed.get_root_dir(), "sys/devices/system/cpu/cpufreq/policy0/")
os.makedirs(dir1)
with open(os.path.join(dir1, 'scaling_governor'), 'w') as f:
f.write('powersave\n')
prefs1 = os.path.join(dir1, "energy_performance_preference")
with open(prefs1, 'w') as f:
f.write("performance\n")
dir2 = os.path.join(self.testbed.get_root_dir(), "sys/devices/system/cpu/cpufreq/policy1/")
os.makedirs(dir2)
with open(os.path.join(dir2, 'scaling_governor'), 'w') as f:
f.write('powersave\n')
prefs2 = os.path.join(dir2, "energy_performance_preference")
with open(prefs2, 'w') as f:
f.write("performance\n")
# Create AMD P-State configuration
pstate_dir = os.path.join(self.testbed.get_root_dir(), "sys/devices/system/cpu/amd_pstate")
os.makedirs(pstate_dir)
with open(os.path.join(pstate_dir, "status"), 'w') as status:
status.write("active\n")
# create ACPI platform profile
self.create_platform_profile()
profile = os.path.join(self.testbed.get_root_dir(), "sys/firmware/acpi/platform_profile")
# desktop PM profile
dir3 = os.path.join(self.testbed.get_root_dir(), "sys/firmware/acpi/")
os.makedirs(dir3, exist_ok=True)
with open(os.path.join(dir3, "pm_profile"), 'w') as pm_profile:
pm_profile.write("1\n")
# block platform profile
os.environ['POWER_PROFILE_DAEMON_DRIVER_BLOCK'] = 'platform_profile'
# Verify that only amd-pstate is loaded
self.start_daemon()
profiles = self.get_dbus_property('Profiles')
self.assertEqual(len(profiles), 3)
self.assertEqual(profiles[0]['CpuDriver'], 'amd_pstate')
self.assertEqual(profiles[0]['PlatformDriver'], 'placeholder')
self.stop_daemon()
# block both drivers
os.environ['POWER_PROFILE_DAEMON_DRIVER_BLOCK'] = 'amd_pstate,platform_profile'
# Verify that only placeholder is loaded
self.start_daemon()
profiles = self.get_dbus_property('Profiles')
self.assertEqual(len(profiles), 2)
self.assertEqual(profiles[0]['PlatformDriver'], 'placeholder')
def test_multi_driver_flows(self):
'''Test corner cases associated with multiple drivers'''