vga-switcheroo clients may wish to know whether they are currently
active, i.e., whether the mux is currently switched to the client
in question. Add an in-kernel API to test whether a vga-switcheroo
client, as identified by PCI device, is actively switched.

Signed-off-by: Daniel Dadap <dda...@nvidia.com>
---
 drivers/gpu/vga/vga_switcheroo.c | 38 +++++++++++++++++++++++++++++++-
 include/linux/vga_switcheroo.h   |  2 ++
 2 files changed, 39 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/vga/vga_switcheroo.c b/drivers/gpu/vga/vga_switcheroo.c
index cf3c7024dafa..a4fc78c4bf4f 100644
--- a/drivers/gpu/vga/vga_switcheroo.c
+++ b/drivers/gpu/vga/vga_switcheroo.c
@@ -99,7 +99,13 @@
  * @id: client identifier. Determining the id requires the handler,
  *     so gpus are initially assigned VGA_SWITCHEROO_UNKNOWN_ID
  *     and later given their true id in vga_switcheroo_enable()
- * @active: whether the outputs are currently switched to this client
+ * @active: whether the client is currently active: this is unset for the
+ *     currently active client before preparing for a mux switch, and set
+ *     for the newly active client after completing all post-switch actions.
+ * @switched: whether the outputs are physically switched to the client:
+ *     this is unset for the currently switched client immediately before
+ *     switching the mux, and set for the newly switched client immediately
+ *     after switching the mux.
  * @driver_power_control: whether power state is controlled by the driver's
  *     runtime pm. If true, writing ON and OFF to the vga_switcheroo debugfs
  *     interface is a no-op so as not to interfere with runtime pm
@@ -117,6 +123,7 @@ struct vga_switcheroo_client {
        const struct vga_switcheroo_client_ops *ops;
        enum vga_switcheroo_client_id id;
        bool active;
+       bool switched;
        bool driver_power_control;
        struct list_head list;
        struct pci_dev *vga_dev;
@@ -306,6 +313,7 @@ static int register_client(struct pci_dev *pdev,
        client->ops = ops;
        client->id = id;
        client->active = active;
+       client->switched = active;
        client->driver_power_control = driver_power_control;
        client->vga_dev = vga_dev;
 
@@ -748,11 +756,13 @@ static int vga_switchto_stage2(struct 
vga_switcheroo_client *new_client,
        if (new_client->fb_info)
                fbcon_remap_all(new_client->fb_info);
 
+       active->switched = false;
        mutex_lock(&vgasr_priv.mux_hw_lock);
        ret = vgasr_priv.handler->switchto(new_client->id);
        mutex_unlock(&vgasr_priv.mux_hw_lock);
        if (ret)
                return ret;
+       new_client->switched = true;
 
        if (new_client->ops->reprobe)
                new_client->ops->reprobe(new_client->pdev);
@@ -1111,3 +1121,29 @@ void vga_switcheroo_fini_domain_pm_ops(struct device 
*dev)
        dev_pm_domain_set(dev, NULL);
 }
 EXPORT_SYMBOL(vga_switcheroo_fini_domain_pm_ops);
+
+/**
+ * vga_switcheroo_is_client_active() - test if a device is the active client
+ * @pdev: vga client device
+ *
+ * Check whether the mux is switched to the switcheroo client associated with
+ * the given PCI device. Assumes that mux is always switched to the device in
+ * question when switcheroo is inactive, and that the mux is switched away if
+ * no matching client is registered.
+ */
+bool vga_switcheroo_is_client_active(struct pci_dev *pdev)
+{
+       if (vgasr_priv.active) {
+               struct vga_switcheroo_client *client;
+
+               client = find_client_from_pci(&vgasr_priv.clients, pdev);
+
+               if (client)
+                       return client->switched;
+               else
+                       return false;
+       } else {
+               return true;
+       }
+}
+EXPORT_SYMBOL(vga_switcheroo_is_client_active);
diff --git a/include/linux/vga_switcheroo.h b/include/linux/vga_switcheroo.h
index 7e6ac0114d55..63e6d6e5786e 100644
--- a/include/linux/vga_switcheroo.h
+++ b/include/linux/vga_switcheroo.h
@@ -173,6 +173,7 @@ enum vga_switcheroo_state 
vga_switcheroo_get_client_state(struct pci_dev *dev);
 
 int vga_switcheroo_init_domain_pm_ops(struct device *dev, struct dev_pm_domain 
*domain);
 void vga_switcheroo_fini_domain_pm_ops(struct device *dev);
+bool vga_switcheroo_is_client_active(struct pci_dev *pdev);
 #else
 
 static inline void vga_switcheroo_unregister_client(struct pci_dev *dev) {}
@@ -194,6 +195,7 @@ static inline enum vga_switcheroo_state 
vga_switcheroo_get_client_state(struct p
 
 static inline int vga_switcheroo_init_domain_pm_ops(struct device *dev, struct 
dev_pm_domain *domain) { return -EINVAL; }
 static inline void vga_switcheroo_fini_domain_pm_ops(struct device *dev) {}
+static inline bool vga_switcheroo_is_client_active(struct pci_dev *pdev) { 
return true; }
 
 #endif
 #endif /* _LINUX_VGA_SWITCHEROO_H_ */
-- 
2.18.4

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

Reply via email to