intel-gfx.lists.freedesktop.org archive mirror
 help / color / mirror / Atom feed
From: Daniel Dadap <ddadap@nvidia.com>
To: <dri-devel@lists.freedesktop.org>, <lukas@wunner.de>,
	<intel-gfx@lists.freedesktop.org>, <jani.nikula@linux.intel.com>,
	<joonas.lahtinen@linux.intel.com>, <rodrigo.vivi@intel.com>
Cc: Daniel Dadap <ddadap@nvidia.com>
Subject: [Intel-gfx] [PATCH 1/6] vga-switcheroo: add new "immediate" switch event type
Date: Mon, 27 Jul 2020 15:51:07 -0500	[thread overview]
Message-ID: <20200727205112.27698-2-ddadap@nvidia.com> (raw)
In-Reply-To: <20200727205112.27698-1-ddadap@nvidia.com>

vga-switcheroo supports the following types of mux switch events:

* standard: checks the clients' can_switch() callbacks and switches
  the mux if the client drivers report that they are prepared for a
  switch. Also uses client and handler callbacks to manage power on
  the GPUs and reprobe display outputs.
* deferred: registers the intent to perform a mux switch and defers
  it until the client drivers no longer have any active modesetting
  clients. Performs the equivalent of a standard switch when clients
  are ready.
* mux-only: switches the mux immediately without testing can_switch
  first and without calling any of the client or handler callbacks
  for power management and reprobing.

In order to support additional use cases involving dynamic switching
of display muxes, add a new type of "immediate" switch event which
skips the can_switch test and power management hooks, but still calls
the reprobe hook. This switch event type uses 'I' as a prefix for its
commands, similar to the existing 'D' pefix for the deferred commands
and 'M' for the mux-only commands.

Signed-off-by: Daniel Dadap <ddadap@nvidia.com>
---
 drivers/gpu/vga/vga_switcheroo.c | 86 +++++++++++++++++++++-----------
 1 file changed, 58 insertions(+), 28 deletions(-)

diff --git a/drivers/gpu/vga/vga_switcheroo.c b/drivers/gpu/vga/vga_switcheroo.c
index 087304b1a5d7..cf3c7024dafa 100644
--- a/drivers/gpu/vga/vga_switcheroo.c
+++ b/drivers/gpu/vga/vga_switcheroo.c
@@ -631,16 +631,23 @@ EXPORT_SYMBOL(vga_switcheroo_unlock_ddc);
  * * DDIS: Delayed switch to the discrete graphics device.
  * * MIGD: Mux-only switch to the integrated graphics device.
  *   Does not remap console or change the power state of either gpu.
+ *   Does not call into any client-supplied callbacks, e.g. reprobe.
  *   If the integrated GPU is currently off, the screen will turn black.
  *   If it is on, the screen will show whatever happens to be in VRAM.
  *   Either way, the user has to blindly enter the command to switch back.
  * * MDIS: Mux-only switch to the discrete graphics device.
+ * * IIGD: Immediate switch to the integrated graphics device.
+ *   Does not test for active user space processes utilizing the device
+ *   files of the GPU or audio device. Does not change the power state of
+ *   either gpu. The console is remapped and client-provided callbacks
+ *   such as reprobe are called.
+ *  * IDIS: Immediate switch to the discrete graphics device.
  *
  * For GPUs whose power state is controlled by the driver's runtime pm,
  * the ON and OFF commands are a no-op (see next section).
  *
- * For muxless machines, the IGD/DIS, DIGD/DDIS and MIGD/MDIS commands
- * should not be used.
+ * For muxless machines, the IGD/DIS, DIGD/DDIS, MIGD/MDIS and IIGD/IDIS
+ * commands should not be used.
  */
 
 static int vga_switcheroo_show(struct seq_file *m, void *v)
@@ -704,7 +711,8 @@ static void set_audio_state(enum vga_switcheroo_client_id id,
 }
 
 /* stage one happens before delay */
-static int vga_switchto_stage1(struct vga_switcheroo_client *new_client)
+static int vga_switchto_stage1(struct vga_switcheroo_client *new_client,
+			       bool power_control)
 {
 	struct vga_switcheroo_client *active;
 
@@ -712,7 +720,8 @@ static int vga_switchto_stage1(struct vga_switcheroo_client *new_client)
 	if (!active)
 		return 0;
 
-	if (vga_switcheroo_pwr_state(new_client) == VGA_SWITCHEROO_OFF)
+	if (power_control &&
+	    vga_switcheroo_pwr_state(new_client) == VGA_SWITCHEROO_OFF)
 		vga_switchon(new_client);
 
 	vga_set_default_device(new_client->pdev);
@@ -720,7 +729,8 @@ static int vga_switchto_stage1(struct vga_switcheroo_client *new_client)
 }
 
 /* post delay */
-static int vga_switchto_stage2(struct vga_switcheroo_client *new_client)
+static int vga_switchto_stage2(struct vga_switcheroo_client *new_client,
+			       bool power_control)
 {
 	int ret;
 	struct vga_switcheroo_client *active;
@@ -747,7 +757,8 @@ static int vga_switchto_stage2(struct vga_switcheroo_client *new_client)
 	if (new_client->ops->reprobe)
 		new_client->ops->reprobe(new_client->pdev);
 
-	if (vga_switcheroo_pwr_state(active) == VGA_SWITCHEROO_ON)
+	if (power_control &&
+	    vga_switcheroo_pwr_state(active) == VGA_SWITCHEROO_ON)
 		vga_switchoff(active);
 
 	/* let HDA controller autoresume if GPU uses driver power control */
@@ -779,6 +790,7 @@ vga_switcheroo_debugfs_write(struct file *filp, const char __user *ubuf,
 	int ret;
 	bool delay = false, can_switch;
 	bool just_mux = false;
+	bool immediate_switch = false;
 	enum vga_switcheroo_client_id client_id = VGA_SWITCHEROO_UNKNOWN_ID;
 	struct vga_switcheroo_client *client = NULL;
 
@@ -822,30 +834,48 @@ vga_switcheroo_debugfs_write(struct file *filp, const char __user *ubuf,
 		goto out;
 	}
 
-	/* request a delayed switch - test can we switch now */
-	if (strncmp(usercmd, "DIGD", 4) == 0) {
-		client_id = VGA_SWITCHEROO_IGD;
-		delay = true;
-	}
-
-	if (strncmp(usercmd, "DDIS", 4) == 0) {
-		client_id = VGA_SWITCHEROO_DIS;
-		delay = true;
-	}
 
+	/* normal switch request */
 	if (strncmp(usercmd, "IGD", 3) == 0)
 		client_id = VGA_SWITCHEROO_IGD;
 
 	if (strncmp(usercmd, "DIS", 3) == 0)
 		client_id = VGA_SWITCHEROO_DIS;
 
-	if (strncmp(usercmd, "MIGD", 4) == 0) {
-		just_mux = true;
-		client_id = VGA_SWITCHEROO_IGD;
-	}
-	if (strncmp(usercmd, "MDIS", 4) == 0) {
-		just_mux = true;
-		client_id = VGA_SWITCHEROO_DIS;
+	if (client_id == VGA_SWITCHEROO_UNKNOWN_ID) {
+		switch (usercmd[0]) {
+		case 'D':
+			/*
+			 * request a delayed switch -
+			 * test can we switch now
+			 */
+			delay = true;
+			break;
+		case 'I':
+			/*
+			 * switch immediately -
+			 * ignore can switch test;
+			 * communicate switch to clients
+			 */
+			immediate_switch = true;
+			break;
+		case 'M':
+			/*
+			 * switch immediately -
+			 * ignore can switch test;
+			 * do not communicate switch to clients
+			 */
+			just_mux = true;
+			break;
+		default:
+			goto out;
+		}
+
+		if (strncmp(usercmd + 1, "IGD", 3) == 0)
+			client_id = VGA_SWITCHEROO_IGD;
+
+		if (strncmp(usercmd + 1, "DIS", 3) == 0)
+			client_id = VGA_SWITCHEROO_DIS;
 	}
 
 	if (client_id == VGA_SWITCHEROO_UNKNOWN_ID)
@@ -867,17 +897,17 @@ vga_switcheroo_debugfs_write(struct file *filp, const char __user *ubuf,
 		goto out;
 
 	/* okay we want a switch - test if devices are willing to switch */
-	can_switch = check_can_switch();
+	can_switch = immediate_switch || check_can_switch();
 
 	if (can_switch == false && delay == false)
 		goto out;
 
 	if (can_switch) {
-		ret = vga_switchto_stage1(client);
+		ret = vga_switchto_stage1(client, !immediate_switch);
 		if (ret)
 			pr_err("switching failed stage 1 %d\n", ret);
 
-		ret = vga_switchto_stage2(client);
+		ret = vga_switchto_stage2(client, !immediate_switch);
 		if (ret)
 			pr_err("switching failed stage 2 %d\n", ret);
 
@@ -886,7 +916,7 @@ vga_switcheroo_debugfs_write(struct file *filp, const char __user *ubuf,
 		vgasr_priv.delayed_switch_active = true;
 		vgasr_priv.delayed_client_id = client_id;
 
-		ret = vga_switchto_stage1(client);
+		ret = vga_switchto_stage1(client, !immediate_switch);
 		if (ret)
 			pr_err("delayed switching stage 1 failed %d\n", ret);
 	}
@@ -951,7 +981,7 @@ int vga_switcheroo_process_delayed_switch(void)
 	if (!client || !check_can_switch())
 		goto err;
 
-	ret = vga_switchto_stage2(client);
+	ret = vga_switchto_stage2(client, true);
 	if (ret)
 		pr_err("delayed switching failed stage 2 %d\n", ret);
 
-- 
2.18.4

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

  reply	other threads:[~2020-07-27 21:35 UTC|newest]

Thread overview: 12+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
     [not found] <ba78cd19-45ad-b17e-5174-256cc11f36c2%40nvidia.com>
2020-07-27 20:51 ` [Intel-gfx] [PATCH 0/6] vga-switcheroo: initial dynamic mux switch support Daniel Dadap
2020-07-27 20:51   ` Daniel Dadap [this message]
2020-07-27 20:51   ` [Intel-gfx] [PATCH 2/6] vga-switcheroo: Add a way to test for the active client Daniel Dadap
2020-07-27 20:51   ` [Intel-gfx] [PATCH 3/6] vga-switcheroo: notify clients of pending/completed switch events Daniel Dadap
2020-07-27 20:51   ` [Intel-gfx] [PATCH 4/6] i915: implement vga-switcheroo reprobe() callback Daniel Dadap
2020-07-27 20:51   ` [Intel-gfx] [PATCH 5/6] i915: fail atomic commit when muxed away Daniel Dadap
2020-07-27 20:51   ` [Intel-gfx] [PATCH 6/6] i915: bail out of eDP link training while mux-switched away Daniel Dadap
2020-07-28  9:32   ` [Intel-gfx] [PATCH 0/6] vga-switcheroo: initial dynamic mux switch support daniel
2020-07-27 22:05 ` [Intel-gfx] ✗ Fi.CI.CHECKPATCH: warning for series starting with [1/6] vga-switcheroo: add new "immediate" switch event type Patchwork
2020-07-27 22:06 ` [Intel-gfx] ✗ Fi.CI.SPARSE: " Patchwork
2020-07-27 22:36 ` [Intel-gfx] ✓ Fi.CI.BAT: success " Patchwork
2020-07-28  0:45 ` [Intel-gfx] ✗ Fi.CI.IGT: 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=20200727205112.27698-2-ddadap@nvidia.com \
    --to=ddadap@nvidia.com \
    --cc=dri-devel@lists.freedesktop.org \
    --cc=intel-gfx@lists.freedesktop.org \
    --cc=jani.nikula@linux.intel.com \
    --cc=joonas.lahtinen@linux.intel.com \
    --cc=lukas@wunner.de \
    --cc=rodrigo.vivi@intel.com \
    /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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).