[PATCH v2 11/22] vga_switcheroo: Generate hotplug event on handler and proxy registration
Lukas Wunner
lukas at wunner.de
Wed Aug 12 04:39:54 PDT 2015
On laptops which require the handler to switch DDC lines, already
registered clients must reprobe their connectors if the handler
registers late. This is the case on pre-retina MacBook Pros,
which use a gmux controller as handler.
Based (loosely) on a patch by Matthew Garrett <mjg59 at srcf.ucam.org>
who used an additional driver callback rather than generating a
hotplug event:
http://lists.freedesktop.org/archives/dri-devel/2014-June/060941.html
Matthew Garrett invoked the driver callback in vga_switcheroo_enable().
On pre-retina MacBook Pros, this delayed reprobing until a second gpu
registers, which may never happen if its driver is not installed or
blacklisted. The MacBook Pro 2011 in particular suffers from widespread
gpu soldering issues due to overheating, eventually rendering it
unusable with OS X. Folks are solving this by moving to Linux and
disabling the discrete gpu entirely. In those cases we can't wait
for a second gpu to register, we do need to reprobe as soon as the
handler registers:
https://ifixit.org/blog/6882/why-i-drilled-holes-in-my-macbook-pro-and-put-it-in-the-oven/#comment-26745
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/vga/vga_switcheroo.c | 34 ++++++++++++++++++++++++++++++++++
1 file changed, 34 insertions(+)
diff --git a/drivers/gpu/vga/vga_switcheroo.c b/drivers/gpu/vga/vga_switcheroo.c
index 8027c9f..94b0b6f 100644
--- a/drivers/gpu/vga/vga_switcheroo.c
+++ b/drivers/gpu/vga/vga_switcheroo.c
@@ -18,6 +18,8 @@
- can_switch - check if the device is in a position to switch now
*/
+#include <drm/drm_crtc_helper.h>
+
#include <linux/module.h>
#include <linux/seq_file.h>
#include <linux/uaccess.h>
@@ -35,6 +37,7 @@
struct vga_switcheroo_client {
struct pci_dev *pdev;
struct fb_info *fb_info;
+ struct work_struct reprobe_work;
int pwr_state;
const struct vga_switcheroo_client_ops *ops;
int id;
@@ -106,6 +109,30 @@ static void vga_switcheroo_enable(void)
vgasr_priv.active = true;
}
+static void vga_switcheroo_reprobe_client(struct work_struct *work)
+{
+ struct vga_switcheroo_client *client =
+ container_of(work, struct vga_switcheroo_client, reprobe_work);
+ void (*generate_hotplug_event)(struct drm_device *);
+
+ generate_hotplug_event = symbol_get(drm_kms_helper_hotplug_event);
+ if (!generate_hotplug_event)
+ return;
+
+ generate_hotplug_event(pci_get_drvdata(client->pdev));
+}
+
+static void vga_switcheroo_reprobe_inactive_clients(void)
+{
+ struct vga_switcheroo_client *client;
+
+ list_for_each_entry(client, &vgasr_priv.clients, list)
+ if (!client->active && client_is_vga(client)) {
+ cancel_work_sync(&client->reprobe_work);
+ schedule_work(&client->reprobe_work);
+ }
+}
+
int vga_switcheroo_register_handler(struct vga_switcheroo_handler *handler)
{
mutex_lock(&vgasr_mutex);
@@ -115,11 +142,17 @@ int vga_switcheroo_register_handler(struct vga_switcheroo_handler *handler)
}
vgasr_priv.handler = handler;
+
if (vga_switcheroo_ready()) {
printk(KERN_INFO "vga_switcheroo: enabled\n");
vga_switcheroo_enable();
}
mutex_unlock(&vgasr_mutex);
+
+ /* clients which registered before the handler must reprobe */
+ if (vgasr_priv.handler->switch_ddc)
+ vga_switcheroo_reprobe_inactive_clients();
+
return 0;
}
EXPORT_SYMBOL(vga_switcheroo_register_handler);
@@ -153,6 +186,7 @@ static int register_client(struct pci_dev *pdev,
client->id = id;
client->active = active;
client->driver_power_control = driver_power_control;
+ INIT_WORK(&client->reprobe_work, vga_switcheroo_reprobe_client);
mutex_lock(&vgasr_mutex);
list_add_tail(&client->list, &vgasr_priv.clients);
--
1.8.5.2 (Apple Git-48)
More information about the dri-devel
mailing list