drivers/gpu/vga/vga_switcheroo.c
Source file repositories/reference/linux-study-clean/drivers/gpu/vga/vga_switcheroo.c
File Facts
- System
- Linux kernel
- Corpus path
drivers/gpu/vga/vga_switcheroo.c- Extension
.c- Size
- 33621 bytes
- Lines
- 1078
- Domain
- Driver Families
- Bucket
- drivers/gpu
- Inferred role
- Driver Families: operation-table or driver-model contract
- Status
- pattern implementation candidate
Why This File Exists
Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.
- Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.
- Defines an operation table; this is where Linux turns generic core objects into subsystem-specific behavior.
- Touches user memory; correctness depends on fault-safe copying and privilege boundary handling.
- Uses kernel synchronization; read lock ordering, sleepability, and interrupt context assumptions before translating.
- Allocates kernel memory; connect allocation flags and lifetime to context constraints.
- Defines or uses C structs; map object ownership, embedded links, reference counts, and lock ownership.
Dependency Surface
linux/apple-gmux.hlinux/debugfs.hlinux/fb.hlinux/fs.hlinux/module.hlinux/pci.hlinux/pm_domain.hlinux/pm_runtime.hlinux/seq_file.hlinux/uaccess.hlinux/vgaarb.hlinux/vga_switcheroo.h
Detected Declarations
struct vga_switcheroo_clientstruct vgasr_privfunction vga_switcheroo_readyfunction vga_switcheroo_enablefunction list_for_each_entryfunction list_for_each_entryfunction vga_switcheroo_register_handlerfunction vga_switcheroo_unregister_handlerfunction vga_switcheroo_handler_flagsfunction register_clientfunction clientfunction clientfunction find_client_from_pcifunction find_client_from_idfunction find_active_clientfunction vga_switcheroo_client_probe_deferfunction vga_switcheroo_pwr_statefunction vga_switcheroo_get_client_statefunction vga_switcheroo_unregister_clientfunction vga_switcheroo_client_fb_setfunction vga_switcheroo_lock_ddcfunction vga_switcheroo_unlock_ddcfunction processesfunction vga_switcheroo_debugfs_openfunction vga_switchonfunction vga_switchofffunction set_audio_statefunction vga_switchto_stage1function vga_switchto_stage2function check_can_switchfunction list_for_each_entryfunction vga_switcheroo_debugfs_writefunction list_for_each_entryfunction list_for_each_entryfunction vga_switcheroo_debugfs_finifunction vga_switcheroo_debugfs_initfunction vga_switcheroo_process_delayed_switchfunction device_link_addfunction vga_switcheroo_runtime_suspendfunction vga_switcheroo_runtime_resumefunction vga_switcheroo_init_domain_pm_opsfunction vga_switcheroo_fini_domain_pm_opsexport vga_switcheroo_register_handlerexport vga_switcheroo_unregister_handlerexport vga_switcheroo_handler_flagsexport vga_switcheroo_register_clientexport vga_switcheroo_register_audio_clientexport vga_switcheroo_client_probe_defer
Annotated Snippet
static const struct file_operations vga_switcheroo_debugfs_fops = {
.owner = THIS_MODULE,
.open = vga_switcheroo_debugfs_open,
.write = vga_switcheroo_debugfs_write,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
};
static void vga_switcheroo_debugfs_fini(struct vgasr_priv *priv)
{
debugfs_remove_recursive(priv->debugfs_root);
priv->debugfs_root = NULL;
}
static void vga_switcheroo_debugfs_init(struct vgasr_priv *priv)
{
/* already initialised */
if (priv->debugfs_root)
return;
priv->debugfs_root = debugfs_create_dir("vgaswitcheroo", NULL);
debugfs_create_file("switch", 0644, priv->debugfs_root, NULL,
&vga_switcheroo_debugfs_fops);
}
/**
* vga_switcheroo_process_delayed_switch() - helper for delayed switching
*
* Process a delayed switch if one is pending.
*
* Return: 0 on success. -EINVAL if no delayed switch is pending, if the client
* has unregistered in the meantime or if there are other clients blocking the
* switch. If the actual switch fails, an error is reported and 0 is returned.
*/
int vga_switcheroo_process_delayed_switch(void)
{
struct vga_switcheroo_client *client;
int ret;
int err = -EINVAL;
mutex_lock(&vgasr_mutex);
if (!vgasr_priv.delayed_switch_active)
goto err;
pr_info("processing delayed switch to %d\n",
vgasr_priv.delayed_client_id);
client = find_client_from_id(&vgasr_priv.clients,
vgasr_priv.delayed_client_id);
if (!client || !check_can_switch())
goto err;
ret = vga_switchto_stage2(client);
if (ret)
pr_err("delayed switching failed stage 2 %d\n", ret);
vgasr_priv.delayed_switch_active = false;
err = 0;
err:
mutex_unlock(&vgasr_mutex);
return err;
}
EXPORT_SYMBOL(vga_switcheroo_process_delayed_switch);
/**
* DOC: Driver power control
*
* In this mode of use, the discrete GPU automatically powers up and down at
* the discretion of the driver's runtime pm. On muxed machines, the user may
* still influence the muxer state by way of the debugfs interface, however
* the ON and OFF commands become a no-op for the discrete GPU.
*
* This mode is the default on Nvidia HybridPower/Optimus and ATI PowerXpress.
* Specifying nouveau.runpm=0, radeon.runpm=0 or amdgpu.runpm=0 on the kernel
* command line disables it.
*
* After the GPU has been suspended, the handler needs to be called to cut
* power to the GPU. Likewise it needs to reinstate power before the GPU
* can resume. This is achieved by vga_switcheroo_init_domain_pm_ops(),
* which augments the GPU's suspend/resume functions by the requisite
* calls to the handler.
*
* When the audio device resumes, the GPU needs to be woken. This is achieved
* by a PCI quirk which calls device_link_add() to declare a dependency on the
* GPU. That way, the GPU is kept awake whenever and as long as the audio
* device is in use.
*
* On muxed machines, if the mux is initially switched to the discrete GPU,
Annotation
- Immediate include surface: `linux/apple-gmux.h`, `linux/debugfs.h`, `linux/fb.h`, `linux/fs.h`, `linux/module.h`, `linux/pci.h`, `linux/pm_domain.h`, `linux/pm_runtime.h`.
- Detected declarations: `struct vga_switcheroo_client`, `struct vgasr_priv`, `function vga_switcheroo_ready`, `function vga_switcheroo_enable`, `function list_for_each_entry`, `function list_for_each_entry`, `function vga_switcheroo_register_handler`, `function vga_switcheroo_unregister_handler`, `function vga_switcheroo_handler_flags`, `function register_client`.
- Atlas domain: Driver Families / drivers/gpu.
- Implementation status: pattern implementation candidate.
- This snippet crosses the user/kernel memory boundary; validate fault handling and access checks before translating the pattern.
- Synchronization appears in or near this file; preserve lock ordering, sleepability, and interrupt-context constraints.
Implementation Notes
- This generated page is the file-by-file coverage layer; curated subsystem chapters should link here when they synthesize a multi-file control flow.
- Core OS pages should be promoted from atlas-only to deep-reviewed when they explain data structures, invariants, locking, lifecycle, and C implementation snippets.
- Driver-family pages are intentionally pattern-oriented unless they are part of the selected PCIe/NVMe representative device path.