Compare commits

..

No commits in common. 'acpi-pr3' and 'master' have entirely different histories.

@ -165,9 +165,3 @@ issues on this module in the issue tracker and provide the following details:
Upload the generated tarball on the above Launchpad URL and provide a link to Upload the generated tarball on the above Launchpad URL and provide a link to
the comment containing your report. the comment containing your report.
TODO
----
With the new PCI device approach, if load_state=0, then starting bumblebeed will
unload bbswitch. Fix Bumblebee not to unload the module when the PM method is
bbswitch and the loaded module is bbswitch.

@ -8,16 +8,6 @@
* # echo ON > /proc/acpi/bbswitch * # echo ON > /proc/acpi/bbswitch
* Get status * Get status
* # cat /proc/acpi/bbswitch * # cat /proc/acpi/bbswitch
*
* Note: only one PCI driver (bbswitch, nouveau, etc.) can bind to a PCI device.
* When turning a device OFF, bbswitch tries to bind itself to the PCI device.
* When turning a device ON, bbswitch unbinds a device (if it was bound) before
* returning from the write.
*
* TODO is this true?
* The new dual module approach is used to allow for backwards compatibility,
* Bumblebee unloads any driver that is loaded for a device, that would however
* result in unloading the main bbswitch module.
*/ */
/* /*
* Copyright (C) 2011-2013 Bumblebee Project * Copyright (C) 2011-2013 Bumblebee Project
@ -207,26 +197,6 @@ static int bbswitch_optimus_dsm(void) {
return 0; return 0;
} }
// Windows 8/8.1/10 do not use DSM to put the device in D3cold state,
// instead it disables power resources on the parent PCIe port device.
static bool has_pr3_support(void) {
acpi_handle parent_handle;
struct acpi_device *ad = NULL;
if (ACPI_FAILURE(acpi_get_parent(dis_handle, &parent_handle))) {
pr_warn("Failed to obtain the parent device\n");
return false;
}
acpi_bus_get_device(parent_handle, &ad);
if (!ad) {
pr_warn("Failed to obtain an ACPI device for handle\n");
return false;
}
return ad->power.flags.power_resources;
}
static int bbswitch_acpi_off(void) { static int bbswitch_acpi_off(void) {
if (dsm_type == DSM_TYPE_NVIDIA) { if (dsm_type == DSM_TYPE_NVIDIA) {
char args[] = {2, 0, 0, 0}; char args[] = {2, 0, 0, 0};
@ -466,9 +436,7 @@ static int __init bbswitch_init(void) {
return -ENODEV; return -ENODEV;
} }
if (has_pr3_support()) { if (!skip_optimus_dsm &&
pr_info("skipping _DSM as _PR3 support is detected\n");
} else if (!skip_optimus_dsm &&
has_dsm_func(acpi_optimus_dsm_muid, 0x100, 0x1A)) { has_dsm_func(acpi_optimus_dsm_muid, 0x100, 0x1A)) {
dsm_type = DSM_TYPE_OPTIMUS; dsm_type = DSM_TYPE_OPTIMUS;
pr_info("detected an Optimus _DSM function\n"); pr_info("detected an Optimus _DSM function\n");

@ -1,100 +0,0 @@
/*
* TODO merge into main bbswitch module.
* TODO on ON call device_release_driver
* TODO how to bind to a specific device from kernel space? Can't use
* driver_probe_device (https://lkml.org/lkml/2014/2/14/628). Maybe use
* driver_override or new_id/bind/remove_id from userspace?
*/
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/pci.h>
#include <linux/module.h>
#include <linux/pm_runtime.h>
#include <linux/delay.h>
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Toggle the discrete graphics card (PCI driver)");
MODULE_AUTHOR("Peter Wu <peter@lekensteyn.nl>");
static int bbswitch_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
{
/* TODO how to discover devices? */
/* Prevent kernel from detaching the PCI device for some devices that
* generate hotplug events. The graphics card is typically not physically
* removable. */
pci_ignore_hotplug(dev);
pm_runtime_set_active(&dev->dev); /* clear any errors */
/* Use autosuspend to avoid lspci waking up the device multiple times. */
pm_runtime_set_autosuspend_delay(&dev->dev, 2000);
pm_runtime_use_autosuspend(&dev->dev);
pm_runtime_allow(&dev->dev);
pm_runtime_put_autosuspend(&dev->dev);
return 0;
}
static void bbswitch_pci_remove(struct pci_dev *dev)
{
pm_runtime_get_noresume(&dev->dev);
pm_runtime_dont_use_autosuspend(&dev->dev);
pm_runtime_forbid(&dev->dev);
}
static int bbswitch_runtime_suspend(struct device *dev) {
struct pci_dev *pdev = to_pci_dev(dev);
pr_info("disabling discrete graphics\n");
/* TODO if _PR3 is not supported, call Optimus DSM here. */
/* TODO for v1 Optimus, call DSM here. */
/* Save state now that the device is still awake, makes PCI layer happy */
pci_save_state(pdev);
/* TODO if _PR3 is supported, should this be PCI_D3hot? */
pci_set_power_state(pdev, PCI_D3cold);
return 0;
}
static int bbswitch_runtime_resume(struct device *dev) {
pr_info("enabling discrete graphics\n");
/* TODO for v1 Optimus, call DSM here. */
/* Nothing to do for Optimus, the PCI layer already moved into D0 state. */
return 0;
}
static struct dev_pm_ops bbswitch_pm_ops = {
.runtime_suspend = bbswitch_runtime_suspend,
.runtime_resume = bbswitch_runtime_resume,
/* No runtime_idle callback, the default zero delay is sufficient. */
};
static struct pci_driver bbswitch_pci_driver = {
.name = KBUILD_MODNAME,
.id_table = NULL, /* will be added dynamically */
.probe = bbswitch_pci_probe,
.remove = bbswitch_pci_remove,
.driver.pm = &bbswitch_pm_ops,
};
static int __init bbswitch_dev_init(void) {
int ret;
ret = pci_register_driver(&bbswitch_pci_driver);
#if 0
ret = pci_add_dynid(&bbswitch_pci_driver, PCI_VENDOR_ID_NVIDIA, PCI_ANY_ID,
PCI_ANY_ID, PCI_ANY_ID, PCI_BASE_CLASS_DISPLAY << 16, 0xff0000);
#endif
return ret;
}
static void __exit bbswitch_dev_exit(void) {
pci_unregister_driver(&bbswitch_pci_driver);
}
module_init(bbswitch_dev_init);
module_exit(bbswitch_dev_exit);
/* vim: set sw=4 ts=4 et: */
Loading…
Cancel
Save