Skip to content

Commit 8948ca1

Browse files
committed
vga_switcheroo: Deduplicate power state tracking
If DRM drivers use runtime PM, they currently notify vga_switcheroo whenever they ->runtime_suspend or ->runtime_resume to update vga_switcheroo's internal power state tracking. That's essentially a duplication of a functionality performed by the PM core as it already tracks the GPU's power state and vga_switcheroo can always query it. Introduce a new internal helper vga_switcheroo_pwr_state() which does just that if runtime PM is used, or falls back to vga_switcheroo's internal power state tracking if manual power control is used. Drop a redundant power state check in set_audio_state() while at it. This removes one of the two purposes of the notification mechanism implemented by vga_switcheroo_set_dynamic_switch(). The other one is power management of the audio device and we'll remove that next. Cc: Dave Airlie <[email protected]> Cc: Ben Skeggs <[email protected]> Cc: Takashi Iwai <[email protected]> Cc: Alex Deucher <[email protected]> Cc: Rafael J. Wysocki <[email protected]> Reviewed-by: Peter Wu <[email protected]> Tested-by: Kai Heng Feng <[email protected]> # AMD PowerXpress Tested-by: Mike Lothian <[email protected]> # AMD PowerXpress Tested-by: Denis Lisov <[email protected]> # Nvidia Optimus Tested-by: Peter Wu <[email protected]> # Nvidia Optimus Tested-by: Lukas Wunner <[email protected]> # MacBook Pro Signed-off-by: Lukas Wunner <[email protected]> Link: https://patchwork.freedesktop.org/patch/msgid/0aa49d735b988aa04524a8dc339582ace33f0f94.1520068884.git.lukas@wunner.de
1 parent dcac86b commit 8948ca1

File tree

1 file changed

+23
-12
lines changed

1 file changed

+23
-12
lines changed

drivers/gpu/vga/vga_switcheroo.c

Lines changed: 23 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,8 @@
9292
* struct vga_switcheroo_client - registered client
9393
* @pdev: client pci device
9494
* @fb_info: framebuffer to which console is remapped on switching
95-
* @pwr_state: current power state
95+
* @pwr_state: current power state if manual power control is used.
96+
* For driver power control, call vga_switcheroo_pwr_state().
9697
* @ops: client callbacks
9798
* @id: client identifier. Determining the id requires the handler,
9899
* so gpus are initially assigned VGA_SWITCHEROO_UNKNOWN_ID
@@ -406,6 +407,19 @@ bool vga_switcheroo_client_probe_defer(struct pci_dev *pdev)
406407
}
407408
EXPORT_SYMBOL(vga_switcheroo_client_probe_defer);
408409

410+
static enum vga_switcheroo_state
411+
vga_switcheroo_pwr_state(struct vga_switcheroo_client *client)
412+
{
413+
if (client->driver_power_control)
414+
if (pm_runtime_enabled(&client->pdev->dev) &&
415+
pm_runtime_active(&client->pdev->dev))
416+
return VGA_SWITCHEROO_ON;
417+
else
418+
return VGA_SWITCHEROO_OFF;
419+
else
420+
return client->pwr_state;
421+
}
422+
409423
/**
410424
* vga_switcheroo_get_client_state() - obtain power state of a given client
411425
* @pdev: client pci device
@@ -425,7 +439,7 @@ enum vga_switcheroo_state vga_switcheroo_get_client_state(struct pci_dev *pdev)
425439
if (!client)
426440
ret = VGA_SWITCHEROO_NOT_FOUND;
427441
else
428-
ret = client->pwr_state;
442+
ret = vga_switcheroo_pwr_state(client);
429443
mutex_unlock(&vgasr_mutex);
430444
return ret;
431445
}
@@ -598,7 +612,7 @@ static int vga_switcheroo_show(struct seq_file *m, void *v)
598612
client_is_vga(client) ? "" : "-Audio",
599613
client->active ? '+' : ' ',
600614
client->driver_power_control ? "Dyn" : "",
601-
client->pwr_state ? "Pwr" : "Off",
615+
vga_switcheroo_pwr_state(client) ? "Pwr" : "Off",
602616
pci_name(client->pdev));
603617
i++;
604618
}
@@ -641,7 +655,7 @@ static void set_audio_state(enum vga_switcheroo_client_id id,
641655
struct vga_switcheroo_client *client;
642656

643657
client = find_client_from_id(&vgasr_priv.clients, id | ID_BIT_AUDIO);
644-
if (client && client->pwr_state != state) {
658+
if (client) {
645659
client->ops->set_gpu_state(client->pdev, state);
646660
client->pwr_state = state;
647661
}
@@ -656,7 +670,7 @@ static int vga_switchto_stage1(struct vga_switcheroo_client *new_client)
656670
if (!active)
657671
return 0;
658672

659-
if (new_client->pwr_state == VGA_SWITCHEROO_OFF)
673+
if (vga_switcheroo_pwr_state(new_client) == VGA_SWITCHEROO_OFF)
660674
vga_switchon(new_client);
661675

662676
vga_set_default_device(new_client->pdev);
@@ -695,7 +709,7 @@ static int vga_switchto_stage2(struct vga_switcheroo_client *new_client)
695709
if (new_client->ops->reprobe)
696710
new_client->ops->reprobe(new_client->pdev);
697711

698-
if (active->pwr_state == VGA_SWITCHEROO_ON)
712+
if (vga_switcheroo_pwr_state(active) == VGA_SWITCHEROO_ON)
699713
vga_switchoff(active);
700714

701715
set_audio_state(new_client->id, VGA_SWITCHEROO_ON);
@@ -940,8 +954,7 @@ EXPORT_SYMBOL(vga_switcheroo_process_delayed_switch);
940954
* command line disables it.
941955
*
942956
* When the driver decides to power up or down, it notifies vga_switcheroo
943-
* thereof so that it can (a) power the audio device on the GPU up or down,
944-
* and (b) update its internal power state representation for the device.
957+
* thereof so that it can power the audio device on the GPU up or down.
945958
* This is achieved by vga_switcheroo_set_dynamic_switch().
946959
*
947960
* After the GPU has been suspended, the handler needs to be called to cut
@@ -985,9 +998,8 @@ static void vga_switcheroo_power_switch(struct pci_dev *pdev,
985998
*
986999
* Helper for GPUs whose power state is controlled by the driver's runtime pm.
9871000
* When the driver decides to power up or down, it notifies vga_switcheroo
988-
* thereof using this helper so that it can (a) power the audio device on
989-
* the GPU up or down, and (b) update its internal power state representation
990-
* for the device.
1001+
* thereof using this helper so that it can power the audio device on the GPU
1002+
* up or down.
9911003
*/
9921004
void vga_switcheroo_set_dynamic_switch(struct pci_dev *pdev,
9931005
enum vga_switcheroo_state dynamic)
@@ -1001,7 +1013,6 @@ void vga_switcheroo_set_dynamic_switch(struct pci_dev *pdev,
10011013
return;
10021014
}
10031015

1004-
client->pwr_state = dynamic;
10051016
set_audio_state(client->id, dynamic);
10061017
mutex_unlock(&vgasr_mutex);
10071018
}

0 commit comments

Comments
 (0)