32 Commits
v0.2 ... v0.4.2

Author SHA1 Message Date
979fbcf552 Merge branch 'develop' 2012-04-26 12:59:41 +02:00
d12ce73a0d Update to version 0.4.2, update NEWS 2012-04-26 12:56:47 +02:00
0d1429e8bb Fix documentation error (Closes GH-16) 2012-04-26 12:49:14 +02:00
af91008deb Fix formatting of arguments on case of ACPI failure (GH-12) 2012-03-01 21:53:52 +01:00
e13e6ffc54 Fix null deref when ACPI method call failed (GH-12) 2012-03-01 13:18:24 +01:00
f034252a13 Don't share buffer for muid/args, it'll be overwritten 2012-02-29 00:49:34 +01:00
647e3dddea Buffer overflow by one byte 2012-02-29 00:30:14 +01:00
804773eb22 Fix misuse of sizeof which trims arguments/muid (GH-12) 2012-02-29 00:10:32 +01:00
7c30e38bd1 Revert "Add support for WMMX method"
This reverts commit 11ddd3469f.
2012-01-28 10:57:04 +01:00
e321debb5b Revert "Support Optimus machines through WMMX (GH-2)"
This reverts commit 0ec41fa2da.
2012-01-28 10:57:03 +01:00
f4c2fadaf5 Revert "Load module dependency on make load: wmi"
This reverts commit fd74ba5bd8.
2012-01-28 10:56:58 +01:00
fd74ba5bd8 Load module dependency on make load: wmi 2012-01-24 14:33:21 +01:00
0ec41fa2da Support Optimus machines through WMMX (GH-2)
This should finally support machines like the Lenovo Y570. WMMX methods should
be more reliable than direct DSM probing so let's try that before calling DSM
directly.
2012-01-24 14:30:53 +01:00
7fd02221b2 Print version on load 2012-01-24 00:04:41 +01:00
11ddd3469f Add support for WMMX method
This should support at least the Lenovo Ideapad Y470 and Y570. It probes the
WMMX method before calling the _DSM method directly since that method should
work for all machines that support the NVIDIA DSM.
2012-01-23 23:52:27 +01:00
4f73396ba7 Add easier way to use DKMS 2012-01-21 15:02:11 +01:00
8c0c5aa863 Allow everyone to get the status of the card (Closes GH-8) 2012-01-21 12:30:41 +01:00
d5ff9a1fb9 Merge branch 'develop' 2012-01-16 17:24:47 +01:00
b0712e5185 Update to version 0.4.1, update NEWS 2012-01-16 17:23:20 +01:00
2d1effc903 Fix a harmless error message 2012-01-16 12:19:36 +01:00
c1dd7140df Merge branch 'develop' 2012-01-15 17:18:45 +01:00
8bd07d14af Bump to version 0.4, update NEWS 2012-01-15 17:18:14 +01:00
ebf86f0617 Detect 3D controllers as gfx device too (GH-3) 2012-01-15 16:35:07 +01:00
a904b442af Add debug message in case no ACPI handle is found 2012-01-15 10:43:44 +01:00
fd4dabf37e Merge branch 'develop' 2012-01-14 23:18:54 +01:00
c8b303c36c Add NEWS file, bump version to 0.3 2012-01-14 23:16:45 +01:00
9f0ae8f723 Ignore files generated from build 2012-01-14 22:54:33 +01:00
031bcfe8a6 Update README with module options 2012-01-14 22:49:46 +01:00
5e297c27ad Add note that a driver must not be loaded if the card is off 2012-01-14 22:13:55 +01:00
358ce15bc1 Probe for nvidia DSM on Intel ACPI handle (GH-4) 2012-01-14 19:58:56 +01:00
04cdd2d5f9 Update instructions with request for ACPI handle mapping 2012-01-14 17:15:23 +01:00
6ed65463c8 Update README with request for machine information 2012-01-14 11:14:43 +01:00
5 changed files with 168 additions and 25 deletions

7
.gitignore vendored Normal file
View File

@ -0,0 +1,7 @@
*.cmd
.tmp_versions
Module.symvers
*.ko
*.mod.c
*.o
modules.order

24
Makefile.dkms Normal file
View File

@ -0,0 +1,24 @@
modname := bbswitch
DKMS := dkms
modver := $(shell awk -F'"' '/define *BBSWITCH_VERSION/{print $$2}' < bbswitch.c)
# directory in which generated files are stored
DKMS_DEST := /usr/src/$(modname)-$(modver)
all: install
src_install:
mkdir -p '$(DKMS_DEST)'
cp Makefile bbswitch.c '$(DKMS_DEST)'
sed 's/#MODULE_VERSION#/$(modver)/' dkms/dkms.conf > '$(DKMS_DEST)/dkms.conf'
build: src_install
$(DKMS) build 'bbswitch/$(modver)'
install: build
$(DKMS) install 'bbswitch/$(modver)'
uninstall:
$(DKMS) remove bbswitch/$(modver) --all
.PHONY: all src_install build install uninstall

28
NEWS Normal file
View File

@ -0,0 +1,28 @@
Version 0.4.2 - 26 April 2012
* Fixed a documentation error on unload_state.
* Added Makefile.dkms and documentation for easier installation using DKMS.
* Make /proc/acpi/bbswitch world-writable
* Fix NULL pointer dereference when reporting a failure during ACPI method
evaluation.
Version 0.4.1 - 16 January 2012
* Corrected a small error that yielded an confusing error message "The discrete
card could not be enabled by a _DSM call"
Version 0.4 - 15 January 2012
* Support for models that have a "3D controller" instead of "VGA compatible
controller".
Version 0.3 - 14 January 2012
* Support for models that have the nvidia DSM method on the integrated Intel
video card instead of the nvidia one. This includes at the Acer Travelmate
8472TG and Acer Aspire 5745G.
Version 0.2 - 2 January 2012
* Initial release, adding a kernel module that can disable discrete nvidia cards
on Optimus systems.

View File

@ -38,10 +38,16 @@ information.
DKMS support
------------
Change `#MODULE_VERSION#` to the current version of bbswitch. Copy the
Makefile, C source and dkms.conf file to `/usr/src/bbswitch-VERSION/` (replace
VERSION with the current version of bbswitch which has been inserted for
`#MODULE_VERSION#`.
If you have DKMS installed, you can install bbswitch in such a way that it
survives kernel upgrades. It is recommended to remove older versions of bbswitch
by running `dkms remove bbswitch/OLDVERSION --all` as root. To install the new
version, simply run:
# make -f Makefile.dkms
To uninstall it, run:
# make -f Makefile.dkms uninstall
Usage
-----
@ -64,6 +70,43 @@ unload the driver,
$ dmesg |tail -1
bbswitch: device 0000:01:00.0 is in use by driver 'nouveau', refusing OFF
Do **not** attempt to load a driver while the card is off or the card won't be
usable until the PCI configuration space has been recovered (for example, after
writing the contents manually or rebooting).
### Module options
The module has some options that control the behavior on loading and unloading:
`load_state` and `unload_state`. Valid values are `-1`, `0` and `1` meaning "do
not change the card state", "turn the card off" and "turn the card on"
respectively. For example, if you want to have `bbswitch` disable the card
immediately when loading the module while enabling the card on unload, load the
module with:
# modprobe bbswitch load_state=0 unload_state=1
The `unload_state` value can be changed on runtime, the above command yields the
same behavior as:
# modprobe bbswitch load_state=0
# echo 1 | tee /sys/module/bbswitch/parameters/unload_state
If not explictly set, the default behavior is not to change the power state of
the discrete video card which equals to `load_state=-1 unload_state=-1`.
### Disable card on boot
These options can be useful to disable the card on boot time. Depending on your
distribution, `/etc/modules`, `/etc/modules.conf` or some other file can be used
to load modules on boot time. Adding the below line to the file makes the card
get disabled on boot:
bbswitch load_state=0
You have to update your initial ramdisk (initrd) for the changes propagate to
the boot process. On Debian and Ubuntu, this can performed by running
`update-initramfs -u` as root.
Reporting bugs
--------------
@ -73,6 +116,21 @@ issues on this module in the issue tracker and provide the following details:
- The output of `dmesg | grep -C 10 bbswitch:`
- The kernel version `uname -a`
- Your distribution and version (if applicable)
- The output of `lspci -d10de: -vvv`
- The version of your Xorg and the driver
- The output of `acpidump` (run it as root, e.g. `sudo acpidump > acpidump.txt`)
- Submit your machine information on https://bugs.launchpad.net/bugs/752542;
the instructions are listed in the bug description. Summary: install the
packages containing `dmidecode`, `acpidump` and `iasl` and then run:
wget http://lekensteyn.nl/files/get-acpi-info.sh
sh get-acpi-info.sh
- Information about the ACPI handles associated with PCI devices. Since this is
a kernel module, you'll need kernel headers, gcc and automake. Commands:
git clone git://github.com/Lekensteyn/acpi-stuff.git --depth 1
cd acpi-stuff/acpi_dump_info
make
sudo make load
cat /proc/acpi/dump_info
Upload the generated tarball on the above Launchpad URL and provide a link to
the comment containing your report.

View File

@ -16,10 +16,12 @@
#include <linux/suspend.h>
#include <linux/seq_file.h>
#define BBSWITCH_VERSION "0.4.2"
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Toggle the discrete graphics card");
MODULE_AUTHOR("Peter Lekensteyn <lekensteyn@gmail.com>");
MODULE_VERSION("0.2");
MODULE_VERSION(BBSWITCH_VERSION);
enum {
CARD_UNCHANGED = -1,
@ -69,12 +71,11 @@ static struct notifier_block nb;
/* whether the card was off before suspend or not; on: 0, off: 1 */
int dis_before_suspend_disabled;
static char *buffer_to_string(const char buffer[], char *target) {
static char *buffer_to_string(const char *buffer, size_t n, char *target) {
int i;
for (i=0; i<sizeof(buffer); i++) {
sprintf(target + i * 5, "%02X,", buffer[i]);
for (i=0; i<n; i++) {
snprintf(target + i * 5, 5 * (n - i), "0x%02X,", buffer ? buffer[i] & 0xFF : 0);
}
target[sizeof(buffer) * 5] = '\0';
return target;
}
@ -110,12 +111,13 @@ static int acpi_call_dsm(acpi_handle handle, const char muid[16], int revid,
err = acpi_evaluate_object(handle, "_DSM", &input, &output);
if (err) {
char tmp[5 * max(sizeof(muid), sizeof(args))];
char muid_str[5 * 16];
char args_str[5 * 4];
printk(KERN_WARNING "bbswitch: failed to evaluate _DSM {%s} %X %X"
printk(KERN_WARNING "bbswitch: failed to evaluate _DSM {%s} 0x%X 0x%X"
" {%s}: %s\n",
buffer_to_string(muid, tmp), revid, func,
buffer_to_string(args, tmp), acpi_format_exception(err));
buffer_to_string(muid, 16, muid_str), revid, func,
buffer_to_string(args, 4, args_str), acpi_format_exception(err));
return err;
}
@ -190,7 +192,7 @@ static int bbswitch_acpi_on(void) {
char args[] = {1, 0, 0, 0};
u32 result = 0;
if (!acpi_call_dsm(dis_handle, acpi_nvidia_dsm_muid, 0x102, 0x3, args,
if (acpi_call_dsm(dis_handle, acpi_nvidia_dsm_muid, 0x102, 0x3, args,
&result)) {
// failure
return 1;
@ -328,20 +330,35 @@ static struct file_operations bbswitch_fops = {
static int __init bbswitch_init(void) {
struct proc_dir_entry *acpi_entry;
struct pci_dev *pdev = NULL;
int class = PCI_CLASS_DISPLAY_VGA << 8;
acpi_handle igd_handle = NULL;
while ((pdev = pci_get_class(class, pdev)) != NULL) {
printk(KERN_INFO "bbswitch: version %s\n", BBSWITCH_VERSION);
while ((pdev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, pdev)) != NULL) {
struct acpi_buffer buf = { ACPI_ALLOCATE_BUFFER, NULL };
acpi_handle handle;
int pci_class = pdev->class >> 8;
handle = DEVICE_ACPI_HANDLE(&pdev->dev);
if (!handle)
if (pci_class != PCI_CLASS_DISPLAY_VGA &&
pci_class != PCI_CLASS_DISPLAY_3D)
continue;
if (pdev->vendor != PCI_VENDOR_ID_INTEL) {
handle = DEVICE_ACPI_HANDLE(&pdev->dev);
if (!handle) {
printk(KERN_WARNING "bbswitch: cannot find ACPI handle for VGA"
" device %s\n", dev_name(&pdev->dev));
continue;
}
acpi_get_name(handle, ACPI_FULL_PATHNAME, &buf);
if (pdev->vendor == PCI_VENDOR_ID_INTEL) {
igd_handle = handle;
printk(KERN_INFO "bbswitch: Found integrated VGA device %s: %s\n",
dev_name(&pdev->dev), (char *)buf.pointer);
} else {
dis_dev = pdev;
dis_handle = handle;
acpi_get_name(handle, ACPI_FULL_PATHNAME, &buf);
printk(KERN_INFO "bbswitch: Found discrete VGA device %s: %s\n",
dev_name(&pdev->dev), (char *)buf.pointer);
}
@ -360,11 +377,20 @@ static int __init bbswitch_init(void) {
dsm_type = DSM_TYPE_NVIDIA;
printk(KERN_INFO "bbswitch: detected a nVidia _DSM function\n");
} else {
printk(KERN_ERR "bbswitch: No suitable _DSM call found.\n");
return -ENODEV;
/* At least two Acer machines are known to use the intel ACPI handle
* with the legacy nvidia DSM */
dis_handle = igd_handle;
if (has_dsm_func(acpi_nvidia_dsm_muid, 0x102, 0x3)) {
dsm_type = DSM_TYPE_NVIDIA;
printk(KERN_INFO "bbswitch: detected a nVidia _DSM function on the"
" integrated video card\n");
} else {
printk(KERN_ERR "bbswitch: No suitable _DSM call found.\n");
return -ENODEV;
}
}
acpi_entry = proc_create("bbswitch", 0660, acpi_root_dir, &bbswitch_fops);
acpi_entry = proc_create("bbswitch", 0664, acpi_root_dir, &bbswitch_fops);
if (acpi_entry == NULL) {
printk(KERN_ERR "bbswitch: Couldn't create proc entry\n");
return -ENOMEM;