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.

Dependency Surface

Detected Declarations

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

Implementation Notes