From: Thomas Zimmermann <tzimmermann@suse.de>
To: lukas@wunner.de, jfalempe@redhat.com, alexander.deucher@amd.com,
christian.koenig@amd.com, airlied@gmail.com, simona@ffwll.ch,
maarten.lankhorst@linux.intel.com, mripard@kernel.org,
jani.nikula@linux.intel.com, joonas.lahtinen@linux.intel.com,
rodrigo.vivi@intel.com, tursulin@ursulin.net, lyude@redhat.com,
dakr@kernel.org, deller@gmx.de
Cc: dri-devel@lists.freedesktop.org, amd-gfx@lists.freedesktop.org,
intel-gfx@lists.freedesktop.org, nouveau@lists.freedesktop.org,
linux-fbdev@vger.kernel.org, sashiko-reviews@lists.linux.dev,
Thomas Zimmermann <tzimmermann@suse.de>
Subject: [PATCH v2 5/7] drm: Implement struct vga_switcheroo_client_ops.pre_switch
Date: Thu, 9 Jul 2026 11:16:01 +0200 [thread overview]
Message-ID: <20260709092215.168172-6-tzimmermann@suse.de> (raw)
In-Reply-To: <20260709092215.168172-1-tzimmermann@suse.de>
Call drm_client_dev_acquire_outputs() from vga_switcheroo's pre_switch
callback. Pushes fbcon updates from vga_switcheroo into DRM's fbdev
emulation. This affects amdgpu, i915, nouveau and radeon. No other
drivers implement vga_switcheroo.
Also remove the calls to vga_switcheroo_client_fb_set() from fbcon. It
is called from the DRM client's hotplug and sets the fbcon's framebuffer
at vga_switcheroo. Running pre_switch and hotplug concurrently could
result in a deadlock between clientlist_mutex and vgasr_mutex. Hence
clean up fbcon here as well.
Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
Reviewed-by: Lyude Paul <lyude@redhat.com> # nouveau
---
drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 8 ++++++++
drivers/gpu/drm/i915/i915_switcheroo.c | 10 ++++++++++
drivers/gpu/drm/nouveau/nouveau_vga.c | 9 +++++++++
drivers/gpu/drm/radeon/radeon_device.c | 8 ++++++++
drivers/video/fbdev/core/fbcon.c | 8 --------
5 files changed, 35 insertions(+), 8 deletions(-)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
index 78c96c7102e4..87a59a79a019 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
@@ -1699,10 +1699,18 @@ static bool amdgpu_switcheroo_can_switch(struct pci_dev *pdev)
return atomic_read(&dev->open_count) == 0;
}
+static void amdgpu_switcheroo_pre_switch(struct pci_dev *pdev)
+{
+ struct drm_device *dev = pci_get_drvdata(pdev);
+
+ drm_client_dev_acquire_outputs(dev);
+}
+
static const struct vga_switcheroo_client_ops amdgpu_switcheroo_ops = {
.set_gpu_state = amdgpu_switcheroo_set_state,
.reprobe = NULL,
.can_switch = amdgpu_switcheroo_can_switch,
+ .pre_switch = amdgpu_switcheroo_pre_switch,
};
/**
diff --git a/drivers/gpu/drm/i915/i915_switcheroo.c b/drivers/gpu/drm/i915/i915_switcheroo.c
index 7e0791024282..6b306ece0556 100644
--- a/drivers/gpu/drm/i915/i915_switcheroo.c
+++ b/drivers/gpu/drm/i915/i915_switcheroo.c
@@ -5,6 +5,7 @@
#include <linux/vga_switcheroo.h>
+#include <drm/drm_client_event.h>
#include <drm/drm_print.h>
#include "display/intel_display_device.h"
@@ -58,10 +59,19 @@ static bool i915_switcheroo_can_switch(struct pci_dev *pdev)
atomic_read(&i915->drm.open_count) == 0;
}
+static void i915_switcheroo_pre_switch(struct pci_dev *pdev)
+{
+ struct drm_i915_private *i915 = pdev_to_i915(pdev);
+
+ if (i915 && intel_display_device_present(i915->display))
+ drm_client_dev_acquire_outputs(&i915->drm);
+}
+
static const struct vga_switcheroo_client_ops i915_switcheroo_ops = {
.set_gpu_state = i915_switcheroo_set_state,
.reprobe = NULL,
.can_switch = i915_switcheroo_can_switch,
+ .pre_switch = i915_switcheroo_pre_switch,
};
int i915_switcheroo_register(struct drm_i915_private *i915)
diff --git a/drivers/gpu/drm/nouveau/nouveau_vga.c b/drivers/gpu/drm/nouveau/nouveau_vga.c
index a6c375a24154..2d2d08be8fbe 100644
--- a/drivers/gpu/drm/nouveau/nouveau_vga.c
+++ b/drivers/gpu/drm/nouveau/nouveau_vga.c
@@ -76,11 +76,20 @@ nouveau_switcheroo_can_switch(struct pci_dev *pdev)
return atomic_read(&drm->dev->open_count) == 0;
}
+static void
+nouveau_switcheroo_pre_switch(struct pci_dev *pdev)
+{
+ struct nouveau_drm *drm = pci_get_drvdata(pdev);
+
+ drm_client_dev_acquire_outputs(drm->dev);
+}
+
static const struct vga_switcheroo_client_ops
nouveau_switcheroo_ops = {
.set_gpu_state = nouveau_switcheroo_set_state,
.reprobe = nouveau_switcheroo_reprobe,
.can_switch = nouveau_switcheroo_can_switch,
+ .pre_switch = nouveau_switcheroo_pre_switch,
};
void
diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c
index 705c012fcf9e..8697a9eb5d13 100644
--- a/drivers/gpu/drm/radeon/radeon_device.c
+++ b/drivers/gpu/drm/radeon/radeon_device.c
@@ -1258,10 +1258,18 @@ static bool radeon_switcheroo_can_switch(struct pci_dev *pdev)
return atomic_read(&dev->open_count) == 0;
}
+static void radeon_switcheroo_pre_switch(struct pci_dev *pdev)
+{
+ struct drm_device *dev = pci_get_drvdata(pdev);
+
+ drm_client_dev_acquire_outputs(dev);
+}
+
static const struct vga_switcheroo_client_ops radeon_switcheroo_ops = {
.set_gpu_state = radeon_switcheroo_set_state,
.reprobe = NULL,
.can_switch = radeon_switcheroo_can_switch,
+ .pre_switch = radeon_switcheroo_pre_switch,
};
/**
diff --git a/drivers/video/fbdev/core/fbcon.c b/drivers/video/fbdev/core/fbcon.c
index 9f5c4c101581..974c7dcf5251 100644
--- a/drivers/video/fbdev/core/fbcon.c
+++ b/drivers/video/fbdev/core/fbcon.c
@@ -78,7 +78,6 @@
#include <linux/interrupt.h>
#include <linux/crc32.h> /* For counting font checksums */
#include <linux/uaccess.h>
-#include <linux/vga_switcheroo.h>
#include <asm/irq.h>
#include "fbcon.h"
@@ -2851,9 +2850,6 @@ void fbcon_fb_unregistered(struct fb_info *info)
console_lock();
- if (info->device && dev_is_pci(info->device))
- vga_switcheroo_client_fb_set(to_pci_dev(info->device), NULL);
-
fbcon_registered_fb[info->node] = NULL;
fbcon_num_registered_fb--;
@@ -2987,10 +2983,6 @@ static int do_fb_registered(struct fb_info *info)
}
}
- /* Set the fb info for vga_switcheroo clients. Does nothing otherwise. */
- if (info->device && dev_is_pci(info->device))
- vga_switcheroo_client_fb_set(to_pci_dev(info->device), info);
-
return ret;
}
--
2.54.0
WARNING: multiple messages have this Message-ID (diff)
From: Thomas Zimmermann <tzimmermann@suse.de>
To: lukas@wunner.de, jfalempe@redhat.com, alexander.deucher@amd.com,
christian.koenig@amd.com, airlied@gmail.com, simona@ffwll.ch,
maarten.lankhorst@linux.intel.com, mripard@kernel.org,
jani.nikula@linux.intel.com, joonas.lahtinen@linux.intel.com,
rodrigo.vivi@intel.com, tursulin@ursulin.net, lyude@redhat.com,
dakr@kernel.org, deller@gmx.de
Cc: dri-devel@lists.freedesktop.org, amd-gfx@lists.freedesktop.org,
intel-gfx@lists.freedesktop.org, nouveau@lists.freedesktop.org,
linux-fbdev@vger.kernel.org, sashiko-reviews@lists.linux.dev
Subject: [PATCH v2 5/7] drm: Implement struct vga_switcheroo_client_ops.pre_switch
Date: Thu, 9 Jul 2026 11:16:01 +0200 [thread overview]
Message-ID: <20260709092215.168172-6-tzimmermann@suse.de> (raw)
In-Reply-To: <20260709092215.168172-1-tzimmermann@suse.de>
Call drm_client_dev_acquire_outputs() from vga_switcheroo's pre_switch
callback. Pushes fbcon updates from vga_switcheroo into DRM's fbdev
emulation. This affects amdgpu, i915, nouveau and radeon. No other
drivers implement vga_switcheroo.
Also remove the calls to vga_switcheroo_client_fb_set() from fbcon. It
is called from the DRM client's hotplug and sets the fbcon's framebuffer
at vga_switcheroo. Running pre_switch and hotplug concurrently could
result in a deadlock between clientlist_mutex and vgasr_mutex. Hence
clean up fbcon here as well.
Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
Reviewed-by: Lyude Paul <lyude@redhat.com> # nouveau
---
drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 8 ++++++++
drivers/gpu/drm/i915/i915_switcheroo.c | 10 ++++++++++
drivers/gpu/drm/nouveau/nouveau_vga.c | 9 +++++++++
drivers/gpu/drm/radeon/radeon_device.c | 8 ++++++++
drivers/video/fbdev/core/fbcon.c | 8 --------
5 files changed, 35 insertions(+), 8 deletions(-)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
index 78c96c7102e4..87a59a79a019 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
@@ -1699,10 +1699,18 @@ static bool amdgpu_switcheroo_can_switch(struct pci_dev *pdev)
return atomic_read(&dev->open_count) == 0;
}
+static void amdgpu_switcheroo_pre_switch(struct pci_dev *pdev)
+{
+ struct drm_device *dev = pci_get_drvdata(pdev);
+
+ drm_client_dev_acquire_outputs(dev);
+}
+
static const struct vga_switcheroo_client_ops amdgpu_switcheroo_ops = {
.set_gpu_state = amdgpu_switcheroo_set_state,
.reprobe = NULL,
.can_switch = amdgpu_switcheroo_can_switch,
+ .pre_switch = amdgpu_switcheroo_pre_switch,
};
/**
diff --git a/drivers/gpu/drm/i915/i915_switcheroo.c b/drivers/gpu/drm/i915/i915_switcheroo.c
index 7e0791024282..6b306ece0556 100644
--- a/drivers/gpu/drm/i915/i915_switcheroo.c
+++ b/drivers/gpu/drm/i915/i915_switcheroo.c
@@ -5,6 +5,7 @@
#include <linux/vga_switcheroo.h>
+#include <drm/drm_client_event.h>
#include <drm/drm_print.h>
#include "display/intel_display_device.h"
@@ -58,10 +59,19 @@ static bool i915_switcheroo_can_switch(struct pci_dev *pdev)
atomic_read(&i915->drm.open_count) == 0;
}
+static void i915_switcheroo_pre_switch(struct pci_dev *pdev)
+{
+ struct drm_i915_private *i915 = pdev_to_i915(pdev);
+
+ if (i915 && intel_display_device_present(i915->display))
+ drm_client_dev_acquire_outputs(&i915->drm);
+}
+
static const struct vga_switcheroo_client_ops i915_switcheroo_ops = {
.set_gpu_state = i915_switcheroo_set_state,
.reprobe = NULL,
.can_switch = i915_switcheroo_can_switch,
+ .pre_switch = i915_switcheroo_pre_switch,
};
int i915_switcheroo_register(struct drm_i915_private *i915)
diff --git a/drivers/gpu/drm/nouveau/nouveau_vga.c b/drivers/gpu/drm/nouveau/nouveau_vga.c
index a6c375a24154..2d2d08be8fbe 100644
--- a/drivers/gpu/drm/nouveau/nouveau_vga.c
+++ b/drivers/gpu/drm/nouveau/nouveau_vga.c
@@ -76,11 +76,20 @@ nouveau_switcheroo_can_switch(struct pci_dev *pdev)
return atomic_read(&drm->dev->open_count) == 0;
}
+static void
+nouveau_switcheroo_pre_switch(struct pci_dev *pdev)
+{
+ struct nouveau_drm *drm = pci_get_drvdata(pdev);
+
+ drm_client_dev_acquire_outputs(drm->dev);
+}
+
static const struct vga_switcheroo_client_ops
nouveau_switcheroo_ops = {
.set_gpu_state = nouveau_switcheroo_set_state,
.reprobe = nouveau_switcheroo_reprobe,
.can_switch = nouveau_switcheroo_can_switch,
+ .pre_switch = nouveau_switcheroo_pre_switch,
};
void
diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c
index 705c012fcf9e..8697a9eb5d13 100644
--- a/drivers/gpu/drm/radeon/radeon_device.c
+++ b/drivers/gpu/drm/radeon/radeon_device.c
@@ -1258,10 +1258,18 @@ static bool radeon_switcheroo_can_switch(struct pci_dev *pdev)
return atomic_read(&dev->open_count) == 0;
}
+static void radeon_switcheroo_pre_switch(struct pci_dev *pdev)
+{
+ struct drm_device *dev = pci_get_drvdata(pdev);
+
+ drm_client_dev_acquire_outputs(dev);
+}
+
static const struct vga_switcheroo_client_ops radeon_switcheroo_ops = {
.set_gpu_state = radeon_switcheroo_set_state,
.reprobe = NULL,
.can_switch = radeon_switcheroo_can_switch,
+ .pre_switch = radeon_switcheroo_pre_switch,
};
/**
diff --git a/drivers/video/fbdev/core/fbcon.c b/drivers/video/fbdev/core/fbcon.c
index 9f5c4c101581..974c7dcf5251 100644
--- a/drivers/video/fbdev/core/fbcon.c
+++ b/drivers/video/fbdev/core/fbcon.c
@@ -78,7 +78,6 @@
#include <linux/interrupt.h>
#include <linux/crc32.h> /* For counting font checksums */
#include <linux/uaccess.h>
-#include <linux/vga_switcheroo.h>
#include <asm/irq.h>
#include "fbcon.h"
@@ -2851,9 +2850,6 @@ void fbcon_fb_unregistered(struct fb_info *info)
console_lock();
- if (info->device && dev_is_pci(info->device))
- vga_switcheroo_client_fb_set(to_pci_dev(info->device), NULL);
-
fbcon_registered_fb[info->node] = NULL;
fbcon_num_registered_fb--;
@@ -2987,10 +2983,6 @@ static int do_fb_registered(struct fb_info *info)
}
}
- /* Set the fb info for vga_switcheroo clients. Does nothing otherwise. */
- if (info->device && dev_is_pci(info->device))
- vga_switcheroo_client_fb_set(to_pci_dev(info->device), info);
-
return ret;
}
--
2.54.0
next prev parent reply other threads:[~2026-07-09 9:22 UTC|newest]
Thread overview: 22+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-07-09 9:15 [PATCH v2 0/7] vga_switcheroo, drm: Push fbcon handling into DRM clients Thomas Zimmermann
2026-07-09 9:15 ` Thomas Zimmermann
2026-07-09 9:15 ` [PATCH v2 1/7] drm/edid: Include <linux/fb.h> Thomas Zimmermann
2026-07-09 9:15 ` Thomas Zimmermann
2026-07-09 9:15 ` [PATCH v2 2/7] drm/client: Add acquire_outputs callback; implement for fbdev emulation Thomas Zimmermann
2026-07-09 9:15 ` Thomas Zimmermann
2026-07-09 9:15 ` [PATCH v2 3/7] vga_switcheroo: Add pre_switch callback to client ops Thomas Zimmermann
2026-07-09 9:15 ` Thomas Zimmermann
2026-07-09 9:16 ` [PATCH v2 4/7] vga_switcheroo: Add post_switch " Thomas Zimmermann
2026-07-09 9:16 ` Thomas Zimmermann
2026-07-09 9:31 ` sashiko-bot
2026-07-09 9:16 ` Thomas Zimmermann [this message]
2026-07-09 9:16 ` [PATCH v2 5/7] drm: Implement struct vga_switcheroo_client_ops.pre_switch Thomas Zimmermann
2026-07-09 9:36 ` sashiko-bot
2026-07-09 10:38 ` Thomas Zimmermann
2026-07-09 9:16 ` [PATCH v2 6/7] drm: Implement vga_switcheroo_client_ops.post_switch Thomas Zimmermann
2026-07-09 9:16 ` Thomas Zimmermann
2026-07-09 9:16 ` [PATCH v2 7/7] vga-switcheroo: Remove unused interfaces Thomas Zimmermann
2026-07-09 9:16 ` Thomas Zimmermann
2026-07-09 9:32 ` sashiko-bot
2026-07-09 11:08 ` ✓ i915.CI.BAT: success for vga_switcheroo, drm: Push fbcon handling into DRM clients (rev2) Patchwork
2026-07-10 6:15 ` ✗ i915.CI.Full: failure " Patchwork
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260709092215.168172-6-tzimmermann@suse.de \
--to=tzimmermann@suse.de \
--cc=airlied@gmail.com \
--cc=alexander.deucher@amd.com \
--cc=amd-gfx@lists.freedesktop.org \
--cc=christian.koenig@amd.com \
--cc=dakr@kernel.org \
--cc=deller@gmx.de \
--cc=dri-devel@lists.freedesktop.org \
--cc=intel-gfx@lists.freedesktop.org \
--cc=jani.nikula@linux.intel.com \
--cc=jfalempe@redhat.com \
--cc=joonas.lahtinen@linux.intel.com \
--cc=linux-fbdev@vger.kernel.org \
--cc=lukas@wunner.de \
--cc=lyude@redhat.com \
--cc=maarten.lankhorst@linux.intel.com \
--cc=mripard@kernel.org \
--cc=nouveau@lists.freedesktop.org \
--cc=rodrigo.vivi@intel.com \
--cc=sashiko-reviews@lists.linux.dev \
--cc=simona@ffwll.ch \
--cc=tursulin@ursulin.net \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.