Skip to content

Instantly share code, notes, and snippets.

@Drakulix
Last active November 2, 2019 18:59
Show Gist options
  • Save Drakulix/1064a8e18f6feab6a604 to your computer and use it in GitHub Desktop.
Save Drakulix/1064a8e18f6feab6a604 to your computer and use it in GitHub Desktop.
Apple Gmux DebugFS
diff -uprN linux-3.16.1-org/drivers/platform/x86/apple-gmux.c linux-3.16.1-patched/drivers/platform/x86/apple-gmux.c
--- a/drivers/platform/x86/apple-gmux.c 2014-08-14 04:36:35.000000000 +0200
+++ b/drivers/platform/x86/apple-gmux.c 2014-09-10 17:12:47.000000000 +0200
@@ -22,6 +22,10 @@
#include <linux/delay.h>
#include <linux/pci.h>
#include <linux/vga_switcheroo.h>
+#include <linux/seq_file.h>
+#include <linux/uaccess.h>
+#include <linux/fs.h>
+#include <linux/debugfs.h>
#include <acpi/video.h>
#include <asm/io.h>
@@ -39,10 +43,17 @@ struct apple_gmux_data {
enum vga_switcheroo_client_id resume_client_id;
enum vga_switcheroo_state power_state;
struct completion powerchange_done;
+
+ /*debugfs data*/
+ struct dentry *debugfs_root;
+ struct dentry *switch_file;
};
static struct apple_gmux_data *apple_gmux_data;
+static int apple_gmux_debugfs_init(struct apple_gmux_data *gmux_data);
+static void apple_gmux_debugfs_fini(struct apple_gmux_data *gmux_data);
+
/*
* gmux port offsets. Many of these are not yet used, but may be in the
* future, and it's useful to have them documented here anyhow.
@@ -560,6 +571,7 @@ static int gmux_probe(struct pnp_dev *pn
init_completion(&gmux_data->powerchange_done);
apple_gmux_data = gmux_data;
gmux_enable_interrupts(gmux_data);
+ apple_gmux_debugfs_init(gmux_data);
return 0;
@@ -584,6 +596,8 @@ static void gmux_remove(struct pnp_dev *
{
struct apple_gmux_data *gmux_data = pnp_get_drvdata(pnp);
+ apple_gmux_debugfs_fini(gmux_data);
+
vga_switcheroo_unregister_handler();
gmux_disable_interrupts(gmux_data);
if (gmux_data->gpe >= 0) {
@@ -604,6 +618,94 @@ static void gmux_remove(struct pnp_dev *
apple_bl_register();
}
+static int apple_gmux_show(struct seq_file *m, void *v)
+{
+ seq_printf(m, "Active Device: %s\nDiscrete Powered: %s\n",
+ gmux_active_client(apple_gmux_data) == VGA_SWITCHEROO_DIS ? "DIS" : "IGD",
+ apple_gmux_data->power_state == VGA_SWITCHEROO_ON ? "ON" : "OFF"
+ );
+ return 0;
+}
+
+static int apple_gmux_debugfs_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, apple_gmux_show, NULL);
+}
+
+static ssize_t
+apple_gmux_debugfs_write(struct file *filp, const char __user *ubuf,
+ size_t cnt, loff_t *ppos)
+{
+ char usercmd[64];
+ if (cnt > 63)
+ cnt = 63;
+
+ if (copy_from_user(usercmd, ubuf, cnt))
+ return -EFAULT;
+
+ /*switch to IGD*/
+ if (strncmp(usercmd, "IGD", 3) == 0)
+ gmux_switchto(VGA_SWITCHEROO_IGD);
+
+ /*switch to DIS*/
+ if (strncmp(usercmd, "DIS", 3) == 0)
+ gmux_switchto(VGA_SWITCHEROO_DIS);
+
+ /*change power state*/
+ if (strncmp(usercmd, "OFF", 3) == 0)
+ gmux_set_discrete_state(apple_gmux_data, VGA_SWITCHEROO_OFF);
+
+ if (strncmp(usercmd, "ON", 2) == 0)
+ gmux_set_discrete_state(apple_gmux_data, VGA_SWITCHEROO_ON);
+
+ return cnt;
+}
+
+static const struct file_operations apple_gmux_debugfs_fops = {
+ .owner = THIS_MODULE,
+ .open = apple_gmux_debugfs_open,
+ .write = apple_gmux_debugfs_write,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
+
+static void apple_gmux_debugfs_fini(struct apple_gmux_data *gmux_data)
+{
+ if (gmux_data->switch_file) {
+ debugfs_remove(gmux_data->switch_file);
+ gmux_data->switch_file = NULL;
+ }
+ if (gmux_data->debugfs_root) {
+ debugfs_remove(gmux_data->debugfs_root);
+ gmux_data->debugfs_root = NULL;
+ }
+}
+
+static int apple_gmux_debugfs_init(struct apple_gmux_data *gmux_data)
+{
+ /* already initialised */
+ if (gmux_data->debugfs_root)
+ return 0;
+ gmux_data->debugfs_root = debugfs_create_dir("applegmux", NULL);
+
+ if (!gmux_data->debugfs_root) {
+ printk(KERN_ERR "apple_gmux: Cannot create /sys/kernel/debug/applegmux\n");
+ goto fail;
+ }
+
+ gmux_data->switch_file = debugfs_create_file("switch", 0644,
+ gmux_data->debugfs_root, NULL, &apple_gmux_debugfs_fops);
+ if (!gmux_data->switch_file) {
+ printk(KERN_ERR "apple_gmux: cannot create /sys/kernel/debug/applegmux/switch\n");
+ goto fail;
+ }
+ return 0;
+fail:
+ apple_gmux_debugfs_fini(gmux_data);
+ return -1;
+}
+
static const struct pnp_device_id gmux_device_ids[] = {
{"APP000B", 0},
{"", 0}
@nathanielwarner
Copy link

Hi- I'm having trouble getting the patch to work (using kernel 4.0.4 from kernel.org). I save the raw text (https://gist.githubusercontent.com/Drakulix/1064a8e18f6feab6a604/raw/4a210c93e0c2099b11c62030e43f05c3275221ad/0001-apple_gmux-Add-sys-debugfs) into a file called "apple-gmux-fix.patch" in the kernel source directory. I run "patch -p1 > apple-gmux-fix.patch" and it reports patching one file successfully. I can compile, install, and boot the kernel normally (https://wiki.archlinux.org/index.php/Kernels/Compilation/Traditional). However, there is no directory "/sys/kernel/debug/apple_gmux". Do you know what I could be doing wrong?

@akatrevorjay
Copy link

Hi, have you submitted this to the kernel? It's about time this got released!

@WellDone2094
Copy link

Hi, i'm trying to apply this patch as well, anyone can help me?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment