[PATCH v2 05/22] vga_switcheroo: Lock/unlock DDC lines
Lukas Wunner
lukas at wunner.de
Wed Aug 12 04:35:46 PDT 2015
From: Dave Airlie <airlied at gmail.com>
Replace vga_switcheroo_switch_ddc() with vga_switcheroo_lock_ddc()
and vga_switcheroo_unlock_ddc(), move mutex from drm_get_edid() to
vga_switcheroo.c
Motivation for these changes according to Dave Airlie:
"I can't figure out why I didn't like this, but I rewrote this way
back to lock/unlock the ddc lines, bits are contained in this WIP
mess. I think I'd prefer something like that otherwise the interface
got really ugly."
http://lists.freedesktop.org/archives/dri-devel/2014-June/061629.html
Original commit by Dave Airlie contained additional experimental
and unused code. Reduced to the bare minimum and amended with this
commit message by Lukas Wunner <lukas at wunner.de>
Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=88861
Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=61115
Tested-by: Paul Hordiienko <pvt.gord at gmail.com>
[MBP 6,2 2010 intel ILK + nvidia GT216 pre-retina]
Tested-by: William Brown <william at blackhats.net.au>
[MBP 8,2 2011 intel SNB + amd turks pre-retina]
Tested-by: Lukas Wunner <lukas at wunner.de>
[MBP 9,1 2012 intel IVB + nvidia GK107 pre-retina]
Tested-by: Bruno Bierbaumer <bruno at bierbaumer.net>
[MBP 11,3 2013 intel HSW + nvidia GK107 retina -- work in progress]
Signed-off-by: Lukas Wunner <lukas at wunner.de>
---
drivers/gpu/drm/drm_edid.c | 16 ++------------
drivers/gpu/vga/vga_switcheroo.c | 46 ++++++++++++++++++++++++++++++++++++++--
include/linux/vga_switcheroo.h | 3 ++-
3 files changed, 48 insertions(+), 17 deletions(-)
diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
index 2424aef..505eed1 100644
--- a/drivers/gpu/drm/drm_edid.c
+++ b/drivers/gpu/drm/drm_edid.c
@@ -88,8 +88,6 @@ struct detailed_mode_closure {
#define LEVEL_GTF2 2
#define LEVEL_CVT 3
-static DEFINE_MUTEX(drm_edid_mutex);
-
static struct edid_quirk {
char vendor[4];
int product_id;
@@ -1380,16 +1378,8 @@ struct edid *drm_get_edid(struct drm_connector *connector,
struct i2c_adapter *adapter)
{
struct edid *edid;
- struct pci_dev *pdev = connector->dev->pdev;
- struct pci_dev *active_pdev = NULL;
-
- mutex_lock(&drm_edid_mutex);
- if (pdev) {
- active_pdev = vga_switcheroo_get_active_client();
- if (active_pdev != pdev)
- vga_switcheroo_switch_ddc(pdev);
- }
+ vga_switcheroo_lock_ddc(connector->dev->pdev);
if (!drm_probe_ddc(adapter))
return NULL;
@@ -1398,10 +1388,8 @@ struct edid *drm_get_edid(struct drm_connector *connector,
if (edid)
drm_get_displayid(connector, edid);
- if (active_pdev && active_pdev != pdev)
- vga_switcheroo_switch_ddc(active_pdev);
+ vga_switcheroo_unlock_ddc(connector->dev->pdev);
- mutex_unlock(&drm_edid_mutex);
return edid;
}
EXPORT_SYMBOL(drm_get_edid);
diff --git a/drivers/gpu/vga/vga_switcheroo.c b/drivers/gpu/vga/vga_switcheroo.c
index 620c4ac..0223020 100644
--- a/drivers/gpu/vga/vga_switcheroo.c
+++ b/drivers/gpu/vga/vga_switcheroo.c
@@ -57,6 +57,9 @@ struct vgasr_priv {
struct list_head clients;
struct vga_switcheroo_handler *handler;
+
+ struct mutex ddc_lock;
+ struct pci_dev *old_ddc_owner;
};
#define ID_BIT_AUDIO 0x100
@@ -70,6 +73,7 @@ static void vga_switcheroo_debugfs_fini(struct vgasr_priv *priv);
/* only one switcheroo per system */
static struct vgasr_priv vgasr_priv = {
.clients = LIST_HEAD_INIT(vgasr_priv.clients),
+ .ddc_lock = __MUTEX_INITIALIZER(vgasr_priv.ddc_lock),
};
static bool vga_switcheroo_ready(void)
@@ -270,8 +274,9 @@ void vga_switcheroo_client_fb_set(struct pci_dev *pdev,
}
EXPORT_SYMBOL(vga_switcheroo_client_fb_set);
-int vga_switcheroo_switch_ddc(struct pci_dev *pdev)
+int vga_switcheroo_lock_ddc(struct pci_dev *pdev)
{
+ struct vga_switcheroo_client *client;
int ret = 0;
int id;
@@ -283,6 +288,18 @@ int vga_switcheroo_switch_ddc(struct pci_dev *pdev)
}
if (vgasr_priv.handler->switch_ddc) {
+ mutex_lock(&vgasr_priv.ddc_lock);
+
+ client = find_active_client(&vgasr_priv.clients);
+ if (!client) {
+ mutex_unlock(&vgasr_priv.ddc_lock);
+ ret = -ENODEV;
+ goto out;
+ }
+ vgasr_priv.old_ddc_owner = client->pdev;
+ if (client->pdev == pdev)
+ goto out;
+
id = vgasr_priv.handler->get_client_id(pdev);
ret = vgasr_priv.handler->switch_ddc(id);
}
@@ -291,7 +308,32 @@ out:
mutex_unlock(&vgasr_mutex);
return ret;
}
-EXPORT_SYMBOL(vga_switcheroo_switch_ddc);
+EXPORT_SYMBOL(vga_switcheroo_lock_ddc);
+
+int vga_switcheroo_unlock_ddc(struct pci_dev *pdev)
+{
+ int ret = 0;
+ int id;
+ mutex_lock(&vgasr_mutex);
+
+ if (!vgasr_priv.handler) {
+ ret = -ENODEV;
+ goto out;
+ }
+
+ if (vgasr_priv.handler->switch_ddc) {
+ if (vgasr_priv.old_ddc_owner != pdev) {
+ id = vgasr_priv.handler->get_client_id(vgasr_priv.old_ddc_owner);
+ ret = vgasr_priv.handler->switch_ddc(id);
+ }
+ vgasr_priv.old_ddc_owner = NULL;
+ mutex_unlock(&vgasr_priv.ddc_lock);
+ }
+out:
+ mutex_unlock(&vgasr_mutex);
+ return ret;
+}
+EXPORT_SYMBOL(vga_switcheroo_unlock_ddc);
static int vga_switcheroo_show(struct seq_file *m, void *v)
{
diff --git a/include/linux/vga_switcheroo.h b/include/linux/vga_switcheroo.h
index c81a686..352bef3 100644
--- a/include/linux/vga_switcheroo.h
+++ b/include/linux/vga_switcheroo.h
@@ -55,7 +55,8 @@ int vga_switcheroo_register_audio_client(struct pci_dev *pdev,
void vga_switcheroo_client_fb_set(struct pci_dev *dev,
struct fb_info *info);
-int vga_switcheroo_switch_ddc(struct pci_dev *pdev);
+int vga_switcheroo_lock_ddc(struct pci_dev *pdev);
+int vga_switcheroo_unlock_ddc(struct pci_dev *pdev);
int vga_switcheroo_register_handler(struct vga_switcheroo_handler *handler);
void vga_switcheroo_unregister_handler(void);
--
1.8.5.2 (Apple Git-48)
More information about the dri-devel
mailing list