From: Dave Airlie <airlied@xxxxxxxxx> 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@xxxxxxxxx> 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@xxxxxxxxx> [MBP 6,2 2010 intel ILK + nvidia GT216 pre-retina] Tested-by: William Brown <william@xxxxxxxxxxxxxxxx> [MBP 8,2 2011 intel SNB + amd turks pre-retina] Tested-by: Lukas Wunner <lukas@xxxxxxxxx> [MBP 9,1 2012 intel IVB + nvidia GK107 pre-retina] Tested-by: Bruno Bierbaumer <bruno@xxxxxxxxxxxxxx> [MBP 11,3 2013 intel HSW + nvidia GK107 retina -- work in progress] Signed-off-by: Lukas Wunner <lukas@xxxxxxxxx> --- 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) _______________________________________________ dri-devel mailing list dri-devel@xxxxxxxxxxxxxxxxxxxxx http://lists.freedesktop.org/mailman/listinfo/dri-devel