2011-02-06 12:28:58

by Corentin Chary

[permalink] [raw]
Subject: [PATCH v2 00/18] eeepc-wmi updates

Hi Matthew,

Thanks to a generous donator, I was able to buy an Eeepc 1000H. It really
easier to make patch when you have the hardware :).

These patches add some features to eeepc-wmi that where already available in
eeepc-laptop (wimax, camera, cardr, wlan hotplug) and some new features
(backlight power).

You may want to take a look at "eeepc-wmi: add hotplug code for Eeepc 1000H"
and "eeepc-wmi: serialize access to wmi method" since you wrote the original
patch for eeepc-laptop.

It's probably way to late for 2.6.38, so let's queue them for 2.6.39. Anyway
if disitribution want to backport some patches, it should be easy to do with
any kernel >= 2.6.34.

Thanks,

Since v1:
* Fixed "eeepc-wmi: support backlight power (bl_power) attribute"
* Added 4 new patchs

Corentin Chary (18):
eeepc-wmi: reorder keymap
eeepc-wmi: add wlan key found on 1015P
eeepc-wmi: add hotplug code for Eeepc 1000H
eeepc-wmi: serialize access to wmi method
eeepc-wmi: return proper error code in eeepc_rfkill_set()
eeepc-wmi: add an helper using simple return codes
eeepc-wmi: add hibernate/resume callbacks
eeepc-wmi: switch to platform_create_bundle()
eeepc-wmi: reorder defines
eeepc-wmi: use the presence bit correctly
eeepc-wmi: add camera and card reader support
eeepc-wmi: add wimax support
eeepc-wmi: set the right key code for 0xe9
eeepc-wmi: support backlight power (bl_power) attribute
eeepc-wmi: respect wireless_hotplug setting
eeepc-wmi: real touchpad led device id is 0x001000012
eeepc-wmi: add touchpad sysfs file
eeepc-wmi: reorder device ids

Documentation/ABI/testing/sysfs-platform-eeepc-wmi | 21 +
drivers/platform/x86/eeepc-wmi.c | 771 ++++++++++++++++----
2 files changed, 663 insertions(+), 129 deletions(-)

--
1.7.4.rc3


2011-02-06 12:29:10

by Corentin Chary

[permalink] [raw]
Subject: [PATCH v2 01/18] eeepc-wmi: reorder keymap

Signed-off-by: Corentin Chary <[email protected]>
---
drivers/platform/x86/eeepc-wmi.c | 14 +++++++-------
1 files changed, 7 insertions(+), 7 deletions(-)

diff --git a/drivers/platform/x86/eeepc-wmi.c b/drivers/platform/x86/eeepc-wmi.c
index 4d38f98..350b7bc 100644
--- a/drivers/platform/x86/eeepc-wmi.c
+++ b/drivers/platform/x86/eeepc-wmi.c
@@ -74,18 +74,18 @@ MODULE_ALIAS("wmi:"EEEPC_WMI_MGMT_GUID);

static const struct key_entry eeepc_wmi_keymap[] = {
/* Sleep already handled via generic ACPI code */
- { KE_KEY, 0x5d, { KEY_WLAN } },
- { KE_KEY, 0x32, { KEY_MUTE } },
- { KE_KEY, 0x31, { KEY_VOLUMEDOWN } },
- { KE_KEY, 0x30, { KEY_VOLUMEUP } },
{ KE_IGNORE, NOTIFY_BRNDOWN_MIN, { KEY_BRIGHTNESSDOWN } },
{ KE_IGNORE, NOTIFY_BRNUP_MIN, { KEY_BRIGHTNESSUP } },
- { KE_KEY, 0xcc, { KEY_SWITCHVIDEOMODE } },
+ { KE_KEY, 0x30, { KEY_VOLUMEUP } },
+ { KE_KEY, 0x31, { KEY_VOLUMEDOWN } },
+ { KE_KEY, 0x32, { KEY_MUTE } },
+ { KE_KEY, 0x5c, { KEY_F15 } },
+ { KE_KEY, 0x5d, { KEY_WLAN } },
{ KE_KEY, 0x6b, { KEY_F13 } }, /* Disable Touchpad */
+ { KE_KEY, 0xcc, { KEY_SWITCHVIDEOMODE } },
+ { KE_KEY, 0xe0, { KEY_PROG1 } },
{ KE_KEY, 0xe1, { KEY_F14 } },
{ KE_KEY, 0xe9, { KEY_DISPLAY_OFF } },
- { KE_KEY, 0xe0, { KEY_PROG1 } },
- { KE_KEY, 0x5c, { KEY_F15 } },
{ KE_END, 0},
};

--
1.7.4.rc3

2011-02-06 12:29:13

by Corentin Chary

[permalink] [raw]
Subject: [PATCH v2 02/18] eeepc-wmi: add wlan key found on 1015P

Signed-off-by: Corentin Chary <[email protected]>
---
drivers/platform/x86/eeepc-wmi.c | 1 +
1 files changed, 1 insertions(+), 0 deletions(-)

diff --git a/drivers/platform/x86/eeepc-wmi.c b/drivers/platform/x86/eeepc-wmi.c
index 350b7bc..0d8217d 100644
--- a/drivers/platform/x86/eeepc-wmi.c
+++ b/drivers/platform/x86/eeepc-wmi.c
@@ -82,6 +82,7 @@ static const struct key_entry eeepc_wmi_keymap[] = {
{ KE_KEY, 0x5c, { KEY_F15 } },
{ KE_KEY, 0x5d, { KEY_WLAN } },
{ KE_KEY, 0x6b, { KEY_F13 } }, /* Disable Touchpad */
+ { KE_KEY, 0x88, { KEY_WLAN } },
{ KE_KEY, 0xcc, { KEY_SWITCHVIDEOMODE } },
{ KE_KEY, 0xe0, { KEY_PROG1 } },
{ KE_KEY, 0xe1, { KEY_F14 } },
--
1.7.4.rc3

2011-02-06 12:29:19

by Corentin Chary

[permalink] [raw]
Subject: [PATCH v2 03/18] eeepc-wmi: add hotplug code for Eeepc 1000H

Implement wireless like hotplug handling (code stolen from eeepc-laptop).

Reminder: on some models rfkill is implemented by logically unplugging the
wireless card from the PCI bus. Despite sending ACPI notifications, this does
not appear to be implemented using standard ACPI hotplug - nor does the
firmware provide the _OSC method required to support native PCIe hotplug.
The only sensible choice appears to be to handle the hotplugging directly in
the platform driver.

Signed-off-by: Corentin Chary <[email protected]>
---
drivers/platform/x86/eeepc-wmi.c | 274 +++++++++++++++++++++++++++++++++++++-
1 files changed, 273 insertions(+), 1 deletions(-)

diff --git a/drivers/platform/x86/eeepc-wmi.c b/drivers/platform/x86/eeepc-wmi.c
index 0d8217d..01bc2b3 100644
--- a/drivers/platform/x86/eeepc-wmi.c
+++ b/drivers/platform/x86/eeepc-wmi.c
@@ -37,9 +37,12 @@
#include <linux/backlight.h>
#include <linux/leds.h>
#include <linux/rfkill.h>
+#include <linux/pci.h>
+#include <linux/pci_hotplug.h>
#include <linux/debugfs.h>
#include <linux/seq_file.h>
#include <linux/platform_device.h>
+#include <linux/dmi.h>
#include <acpi/acpi_bus.h>
#include <acpi/acpi_drivers.h>

@@ -72,6 +75,14 @@ MODULE_ALIAS("wmi:"EEEPC_WMI_MGMT_GUID);
#define EEEPC_WMI_DEVID_BLUETOOTH 0x00010013
#define EEEPC_WMI_DEVID_WWAN3G 0x00010019

+static bool hotplug_wireless;
+
+module_param(hotplug_wireless, bool, 0444);
+MODULE_PARM_DESC(hotplug_wireless,
+ "Enable hotplug for wireless device. "
+ "If your laptop needs that, please report to "
+ "[email protected].");
+
static const struct key_entry eeepc_wmi_keymap[] = {
/* Sleep already handled via generic ACPI code */
{ KE_IGNORE, NOTIFY_BRNDOWN_MIN, { KEY_BRIGHTNESSDOWN } },
@@ -109,6 +120,8 @@ struct eeepc_wmi_debug {
};

struct eeepc_wmi {
+ bool hotplug_wireless;
+
struct input_dev *inputdev;
struct backlight_device *backlight_device;
struct platform_device *platform_device;
@@ -122,6 +135,9 @@ struct eeepc_wmi {
struct rfkill *bluetooth_rfkill;
struct rfkill *wwan3g_rfkill;

+ struct hotplug_slot *hotplug_slot;
+ struct mutex hotplug_lock;
+
struct eeepc_wmi_debug debug;
};

@@ -177,7 +193,8 @@ static acpi_status eeepc_wmi_get_devstate(u32 dev_id, u32 *retval)
u32 tmp;

status = wmi_evaluate_method(EEEPC_WMI_MGMT_GUID,
- 1, EEEPC_WMI_METHODID_DSTS, &input, &output);
+ 1, EEEPC_WMI_METHODID_DSTS,
+ &input, &output);

if (ACPI_FAILURE(status))
return status;
@@ -334,6 +351,206 @@ static void eeepc_wmi_led_exit(struct eeepc_wmi *eeepc)
}

/*
+ * PCI hotplug (for wlan rfkill)
+ */
+static bool eeepc_wlan_rfkill_blocked(struct eeepc_wmi *eeepc)
+{
+ u32 retval;
+ acpi_status status;
+
+ status = eeepc_wmi_get_devstate(EEEPC_WMI_DEVID_WLAN, &retval);
+
+ if (ACPI_FAILURE(status))
+ return false;
+
+ return !(retval & 0x1);
+}
+
+static void eeepc_rfkill_hotplug(struct eeepc_wmi *eeepc)
+{
+ struct pci_dev *dev;
+ struct pci_bus *bus;
+ bool blocked = eeepc_wlan_rfkill_blocked(eeepc);
+ bool absent;
+ u32 l;
+
+ if (eeepc->wlan_rfkill)
+ rfkill_set_sw_state(eeepc->wlan_rfkill, blocked);
+
+ mutex_lock(&eeepc->hotplug_lock);
+
+ if (eeepc->hotplug_slot) {
+ bus = pci_find_bus(0, 1);
+ if (!bus) {
+ pr_warning("Unable to find PCI bus 1?\n");
+ goto out_unlock;
+ }
+
+ if (pci_bus_read_config_dword(bus, 0, PCI_VENDOR_ID, &l)) {
+ pr_err("Unable to read PCI config space?\n");
+ goto out_unlock;
+ }
+ absent = (l == 0xffffffff);
+
+ if (blocked != absent) {
+ pr_warning("BIOS says wireless lan is %s, "
+ "but the pci device is %s\n",
+ blocked ? "blocked" : "unblocked",
+ absent ? "absent" : "present");
+ pr_warning("skipped wireless hotplug as probably "
+ "inappropriate for this model\n");
+ goto out_unlock;
+ }
+
+ if (!blocked) {
+ dev = pci_get_slot(bus, 0);
+ if (dev) {
+ /* Device already present */
+ pci_dev_put(dev);
+ goto out_unlock;
+ }
+ dev = pci_scan_single_device(bus, 0);
+ if (dev) {
+ pci_bus_assign_resources(bus);
+ if (pci_bus_add_device(dev))
+ pr_err("Unable to hotplug wifi\n");
+ }
+ } else {
+ dev = pci_get_slot(bus, 0);
+ if (dev) {
+ pci_remove_bus_device(dev);
+ pci_dev_put(dev);
+ }
+ }
+ }
+
+out_unlock:
+ mutex_unlock(&eeepc->hotplug_lock);
+}
+
+static void eeepc_rfkill_notify(acpi_handle handle, u32 event, void *data)
+{
+ struct eeepc_wmi *eeepc = data;
+
+ if (event != ACPI_NOTIFY_BUS_CHECK)
+ return;
+
+ eeepc_rfkill_hotplug(eeepc);
+}
+
+static int eeepc_register_rfkill_notifier(struct eeepc_wmi *eeepc,
+ char *node)
+{
+ acpi_status status;
+ acpi_handle handle;
+
+ status = acpi_get_handle(NULL, node, &handle);
+
+ if (ACPI_SUCCESS(status)) {
+ status = acpi_install_notify_handler(handle,
+ ACPI_SYSTEM_NOTIFY,
+ eeepc_rfkill_notify,
+ eeepc);
+ if (ACPI_FAILURE(status))
+ pr_warning("Failed to register notify on %s\n", node);
+ } else
+ return -ENODEV;
+
+ return 0;
+}
+
+static void eeepc_unregister_rfkill_notifier(struct eeepc_wmi *eeepc,
+ char *node)
+{
+ acpi_status status = AE_OK;
+ acpi_handle handle;
+
+ status = acpi_get_handle(NULL, node, &handle);
+
+ if (ACPI_SUCCESS(status)) {
+ status = acpi_remove_notify_handler(handle,
+ ACPI_SYSTEM_NOTIFY,
+ eeepc_rfkill_notify);
+ if (ACPI_FAILURE(status))
+ pr_err("Error removing rfkill notify handler %s\n",
+ node);
+ }
+}
+
+static int eeepc_get_adapter_status(struct hotplug_slot *hotplug_slot,
+ u8 *value)
+{
+ u32 retval;
+ acpi_status status;
+
+ status = eeepc_wmi_get_devstate(EEEPC_WMI_DEVID_WLAN, &retval);
+
+ if (ACPI_FAILURE(status))
+ return -EIO;
+
+ if (!retval || retval == 0x00060000)
+ return -ENODEV;
+ else
+ *value = (retval & 0x1);
+
+ return 0;
+}
+
+static void eeepc_cleanup_pci_hotplug(struct hotplug_slot *hotplug_slot)
+{
+ kfree(hotplug_slot->info);
+ kfree(hotplug_slot);
+}
+
+static struct hotplug_slot_ops eeepc_hotplug_slot_ops = {
+ .owner = THIS_MODULE,
+ .get_adapter_status = eeepc_get_adapter_status,
+ .get_power_status = eeepc_get_adapter_status,
+};
+
+static int eeepc_setup_pci_hotplug(struct eeepc_wmi *eeepc)
+{
+ int ret = -ENOMEM;
+ struct pci_bus *bus = pci_find_bus(0, 1);
+
+ if (!bus) {
+ pr_err("Unable to find wifi PCI bus\n");
+ return -ENODEV;
+ }
+
+ eeepc->hotplug_slot = kzalloc(sizeof(struct hotplug_slot), GFP_KERNEL);
+ if (!eeepc->hotplug_slot)
+ goto error_slot;
+
+ eeepc->hotplug_slot->info = kzalloc(sizeof(struct hotplug_slot_info),
+ GFP_KERNEL);
+ if (!eeepc->hotplug_slot->info)
+ goto error_info;
+
+ eeepc->hotplug_slot->private = eeepc;
+ eeepc->hotplug_slot->release = &eeepc_cleanup_pci_hotplug;
+ eeepc->hotplug_slot->ops = &eeepc_hotplug_slot_ops;
+ eeepc_get_adapter_status(eeepc->hotplug_slot,
+ &eeepc->hotplug_slot->info->adapter_status);
+
+ ret = pci_hp_register(eeepc->hotplug_slot, bus, 0, "eeepc-wifi");
+ if (ret) {
+ pr_err("Unable to register hotplug slot - %d\n", ret);
+ goto error_register;
+ }
+
+ return 0;
+
+error_register:
+ kfree(eeepc->hotplug_slot->info);
+error_info:
+ kfree(eeepc->hotplug_slot);
+ eeepc->hotplug_slot = NULL;
+error_slot:
+ return ret;
+}
+
+/*
* Rfkill devices
*/
static int eeepc_rfkill_set(void *data, bool blocked)
@@ -404,11 +621,22 @@ static int eeepc_new_rfkill(struct eeepc_wmi *eeepc,

static void eeepc_wmi_rfkill_exit(struct eeepc_wmi *eeepc)
{
+ eeepc_unregister_rfkill_notifier(eeepc, "\\_SB.PCI0.P0P5");
+ eeepc_unregister_rfkill_notifier(eeepc, "\\_SB.PCI0.P0P6");
+ eeepc_unregister_rfkill_notifier(eeepc, "\\_SB.PCI0.P0P7");
if (eeepc->wlan_rfkill) {
rfkill_unregister(eeepc->wlan_rfkill);
rfkill_destroy(eeepc->wlan_rfkill);
eeepc->wlan_rfkill = NULL;
}
+ /*
+ * Refresh pci hotplug in case the rfkill state was changed after
+ * eeepc_unregister_rfkill_notifier()
+ */
+ eeepc_rfkill_hotplug(eeepc);
+ if (eeepc->hotplug_slot)
+ pci_hp_deregister(eeepc->hotplug_slot);
+
if (eeepc->bluetooth_rfkill) {
rfkill_unregister(eeepc->bluetooth_rfkill);
rfkill_destroy(eeepc->bluetooth_rfkill);
@@ -425,6 +653,8 @@ static int eeepc_wmi_rfkill_init(struct eeepc_wmi *eeepc)
{
int result = 0;

+ mutex_init(&eeepc->hotplug_lock);
+
result = eeepc_new_rfkill(eeepc, &eeepc->wlan_rfkill,
"eeepc-wlan", RFKILL_TYPE_WLAN,
EEEPC_WMI_DEVID_WLAN);
@@ -446,6 +676,23 @@ static int eeepc_wmi_rfkill_init(struct eeepc_wmi *eeepc)
if (result && result != -ENODEV)
goto exit;

+ result = eeepc_setup_pci_hotplug(eeepc);
+ /*
+ * If we get -EBUSY then something else is handling the PCI hotplug -
+ * don't fail in this case
+ */
+ if (result == -EBUSY)
+ result = 0;
+
+ eeepc_register_rfkill_notifier(eeepc, "\\_SB.PCI0.P0P5");
+ eeepc_register_rfkill_notifier(eeepc, "\\_SB.PCI0.P0P6");
+ eeepc_register_rfkill_notifier(eeepc, "\\_SB.PCI0.P0P7");
+ /*
+ * Refresh pci hotplug in case the rfkill state was changed during
+ * setup.
+ */
+ eeepc_rfkill_hotplug(eeepc);
+
exit:
if (result && result != -ENODEV)
eeepc_wmi_rfkill_exit(eeepc);
@@ -771,6 +1018,28 @@ error_debugfs:
/*
* WMI Driver
*/
+static void eeepc_dmi_check(struct eeepc_wmi *eeepc)
+{
+ const char *model;
+
+ model = dmi_get_system_info(DMI_PRODUCT_NAME);
+ if (!model)
+ return;
+
+ /*
+ * Whitelist for wlan hotplug
+ *
+ * Eeepc 1000H needs the current hotplug code to handle
+ * Fn+F2 correctly. We may add other Eeepc here later, but
+ * it seems that most of the laptops supported by eeepc-wmi
+ * don't need to be on this list
+ */
+ if (strcmp(model, "1000H") == 0) {
+ eeepc->hotplug_wireless = true;
+ pr_info("wlan hotplug enabled\n");
+ }
+}
+
static struct platform_device * __init eeepc_wmi_add(void)
{
struct eeepc_wmi *eeepc;
@@ -781,6 +1050,9 @@ static struct platform_device * __init eeepc_wmi_add(void)
if (!eeepc)
return ERR_PTR(-ENOMEM);

+ eeepc->hotplug_wireless = hotplug_wireless;
+ eeepc_dmi_check(eeepc);
+
/*
* Register the platform device first. It is used as a parent for the
* sub-devices below.
--
1.7.4.rc3

2011-02-06 12:29:28

by Corentin Chary

[permalink] [raw]
Subject: [PATCH v2 05/18] eeepc-wmi: return proper error code in eeepc_rfkill_set()

Signed-off-by: Corentin Chary <[email protected]>
---
drivers/platform/x86/eeepc-wmi.c | 8 +++++++-
1 files changed, 7 insertions(+), 1 deletions(-)

diff --git a/drivers/platform/x86/eeepc-wmi.c b/drivers/platform/x86/eeepc-wmi.c
index eb4c0ce..d823458 100644
--- a/drivers/platform/x86/eeepc-wmi.c
+++ b/drivers/platform/x86/eeepc-wmi.c
@@ -588,8 +588,14 @@ static int eeepc_rfkill_set(void *data, bool blocked)
{
int dev_id = (unsigned long)data;
u32 ctrl_param = !blocked;
+ acpi_status status;
+
+ status = eeepc_wmi_set_devstate(dev_id, ctrl_param, NULL);
+
+ if (ACPI_FAILURE(status))
+ return -EIO;

- return eeepc_wmi_set_devstate(dev_id, ctrl_param, NULL);
+ return 0;
}

static void eeepc_rfkill_query(struct rfkill *rfkill, void *data)
--
1.7.4.rc3

2011-02-06 12:29:35

by Corentin Chary

[permalink] [raw]
Subject: [PATCH v2 06/18] eeepc-wmi: add an helper using simple return codes

eeepc_wmi_get_devstate returns an acpi_status, so each
call need extra logic to handle the return code. This
patch add a simple getter, returning a boolean (or a
negative error code).

Signed-off-by: Corentin Chary <[email protected]>
---
drivers/platform/x86/eeepc-wmi.c | 96 +++++++++++++++----------------------
1 files changed, 39 insertions(+), 57 deletions(-)

diff --git a/drivers/platform/x86/eeepc-wmi.c b/drivers/platform/x86/eeepc-wmi.c
index d823458..de501fb 100644
--- a/drivers/platform/x86/eeepc-wmi.c
+++ b/drivers/platform/x86/eeepc-wmi.c
@@ -257,6 +257,29 @@ static acpi_status eeepc_wmi_set_devstate(u32 dev_id, u32 ctrl_param,
return status;
}

+/* Helper for special devices with magic return codes */
+static int eeepc_wmi_get_devstate_simple(u32 dev_id)
+{
+ u32 retval = 0;
+ acpi_status status;
+
+ status = eeepc_wmi_get_devstate(dev_id, &retval);
+
+ if (ACPI_FAILURE(status))
+ return -EINVAL;
+
+ /* If the device is present, DSTS will always set some bits
+ * 0x00070000 - 1110000000000000000 - device supported
+ * 0x00060000 - 1100000000000000000 - not supported
+ * 0x00020000 - 0100000000000000000 - device supported
+ * 0x00010000 - 0010000000000000000 - not supported / special mode ?
+ */
+ if (!retval || retval == 0x00060000)
+ return -ENODEV;
+
+ return retval & 0x1;
+}
+
/*
* LEDs
*/
@@ -290,23 +313,7 @@ static void tpd_led_set(struct led_classdev *led_cdev,

static int read_tpd_state(struct eeepc_wmi *eeepc)
{
- u32 retval;
- acpi_status status;
-
- status = eeepc_wmi_get_devstate(EEEPC_WMI_DEVID_TPDLED, &retval);
-
- if (ACPI_FAILURE(status))
- return -1;
- else if (!retval || retval == 0x00060000)
- /*
- * if touchpad led is present, DSTS will set some bits,
- * usually 0x00020000.
- * 0x00060000 means that the device is not supported
- */
- return -ENODEV;
- else
- /* Status is stored in the first bit */
- return retval & 0x1;
+ return eeepc_wmi_get_devstate_simple(EEEPC_WMI_DEVID_TPDLED);
}

static enum led_brightness tpd_led_get(struct led_classdev *led_cdev)
@@ -358,15 +365,11 @@ static void eeepc_wmi_led_exit(struct eeepc_wmi *eeepc)
*/
static bool eeepc_wlan_rfkill_blocked(struct eeepc_wmi *eeepc)
{
- u32 retval;
- acpi_status status;
-
- status = eeepc_wmi_get_devstate(EEEPC_WMI_DEVID_WLAN, &retval);
+ int result = eeepc_wmi_get_devstate_simple(EEEPC_WMI_DEVID_WLAN);

- if (ACPI_FAILURE(status))
+ if (result < 0)
return false;
-
- return !(retval & 0x1);
+ return !result;
}

static void eeepc_rfkill_hotplug(struct eeepc_wmi *eeepc)
@@ -494,19 +497,12 @@ static void eeepc_unregister_rfkill_notifier(struct eeepc_wmi *eeepc,
static int eeepc_get_adapter_status(struct hotplug_slot *hotplug_slot,
u8 *value)
{
- u32 retval;
- acpi_status status;
-
- status = eeepc_wmi_get_devstate(EEEPC_WMI_DEVID_WLAN, &retval);
-
- if (ACPI_FAILURE(status))
- return -EIO;
+ int result = eeepc_wmi_get_devstate_simple(EEEPC_WMI_DEVID_WLAN);

- if (!retval || retval == 0x00060000)
- return -ENODEV;
- else
- *value = (retval & 0x1);
+ if (result < 0)
+ return result;

+ *value = !!result;
return 0;
}

@@ -601,15 +597,14 @@ static int eeepc_rfkill_set(void *data, bool blocked)
static void eeepc_rfkill_query(struct rfkill *rfkill, void *data)
{
int dev_id = (unsigned long)data;
- u32 retval;
- acpi_status status;
+ int result;

- status = eeepc_wmi_get_devstate(dev_id, &retval);
+ result = eeepc_wmi_get_devstate_simple(dev_id);

- if (ACPI_FAILURE(status))
+ if (result < 0)
return ;

- rfkill_set_sw_state(rfkill, !(retval & 0x1));
+ rfkill_set_sw_state(rfkill, !result);
}

static int eeepc_rfkill_wlan_set(void *data, bool blocked)
@@ -650,23 +645,10 @@ static int eeepc_new_rfkill(struct eeepc_wmi *eeepc,
const char *name,
enum rfkill_type type, int dev_id)
{
- int result;
- u32 retval;
- acpi_status status;
-
- status = eeepc_wmi_get_devstate(dev_id, &retval);
+ int result = eeepc_wmi_get_devstate_simple(dev_id);

- if (ACPI_FAILURE(status))
- return -1;
-
- /* If the device is present, DSTS will always set some bits
- * 0x00070000 - 1110000000000000000 - device supported
- * 0x00060000 - 1100000000000000000 - not supported
- * 0x00020000 - 0100000000000000000 - device supported
- * 0x00010000 - 0010000000000000000 - not supported / special mode ?
- */
- if (!retval || retval == 0x00060000)
- return -ENODEV;
+ if (result < 0)
+ return result;

if (dev_id == EEEPC_WMI_DEVID_WLAN && eeepc->hotplug_wireless)
*rfkill = rfkill_alloc(name, &eeepc->platform_device->dev, type,
@@ -678,7 +660,7 @@ static int eeepc_new_rfkill(struct eeepc_wmi *eeepc,
if (!*rfkill)
return -EINVAL;

- rfkill_init_sw_state(*rfkill, !(retval & 0x1));
+ rfkill_init_sw_state(*rfkill, !result);
result = rfkill_register(*rfkill);
if (result) {
rfkill_destroy(*rfkill);
--
1.7.4.rc3

2011-02-06 12:29:44

by Corentin Chary

[permalink] [raw]
Subject: [PATCH v2 07/18] eeepc-wmi: add hibernate/resume callbacks

Signed-off-by: Corentin Chary <[email protected]>
---
drivers/platform/x86/eeepc-wmi.c | 49 ++++++++++++++++++++++++++++++++++++++
1 files changed, 49 insertions(+), 0 deletions(-)

diff --git a/drivers/platform/x86/eeepc-wmi.c b/drivers/platform/x86/eeepc-wmi.c
index de501fb..583ba78 100644
--- a/drivers/platform/x86/eeepc-wmi.c
+++ b/drivers/platform/x86/eeepc-wmi.c
@@ -1183,10 +1183,59 @@ static int eeepc_wmi_remove(struct platform_device *device)
return 0;
}

+/*
+ * Platform driver - hibernate/resume callbacks
+ */
+static int eeepc_hotk_thaw(struct device *device)
+{
+ struct eeepc_wmi *eeepc = dev_get_drvdata(device);
+
+ if (eeepc->wlan_rfkill) {
+ bool wlan;
+
+ /*
+ * Work around bios bug - acpi _PTS turns off the wireless led
+ * during suspend. Normally it restores it on resume, but
+ * we should kick it ourselves in case hibernation is aborted.
+ */
+ wlan = eeepc_wmi_get_devstate_simple(EEEPC_WMI_DEVID_WLAN);
+ eeepc_wmi_set_devstate(EEEPC_WMI_DEVID_WLAN, wlan, NULL);
+ }
+
+ return 0;
+}
+
+static int eeepc_hotk_restore(struct device *device)
+{
+ struct eeepc_wmi *eeepc = dev_get_drvdata(device);
+ int bl;
+
+ /* Refresh both wlan rfkill state and pci hotplug */
+ if (eeepc->wlan_rfkill)
+ eeepc_rfkill_hotplug(eeepc);
+
+ if (eeepc->bluetooth_rfkill) {
+ bl = !eeepc_wmi_get_devstate_simple(EEEPC_WMI_DEVID_BLUETOOTH);
+ rfkill_set_sw_state(eeepc->bluetooth_rfkill, bl);
+}
+ if (eeepc->wwan3g_rfkill) {
+ bl = !eeepc_wmi_get_devstate_simple(EEEPC_WMI_DEVID_WWAN3G);
+ rfkill_set_sw_state(eeepc->wwan3g_rfkill, bl);
+ }
+
+ return 0;
+}
+
+static const struct dev_pm_ops eeepc_pm_ops = {
+ .thaw = eeepc_hotk_thaw,
+ .restore = eeepc_hotk_restore,
+};
+
static struct platform_driver platform_driver = {
.driver = {
.name = EEEPC_WMI_FILE,
.owner = THIS_MODULE,
+ .pm = &eeepc_pm_ops,
},
};

--
1.7.4.rc3

2011-02-06 12:29:54

by Corentin Chary

[permalink] [raw]
Subject: [PATCH v2 09/18] eeepc-wmi: reorder defines

Signed-off-by: Corentin Chary <[email protected]>
---
drivers/platform/x86/eeepc-wmi.c | 18 +++++++++---------
1 files changed, 9 insertions(+), 9 deletions(-)

diff --git a/drivers/platform/x86/eeepc-wmi.c b/drivers/platform/x86/eeepc-wmi.c
index 1fc191b..aa9e1d1 100644
--- a/drivers/platform/x86/eeepc-wmi.c
+++ b/drivers/platform/x86/eeepc-wmi.c
@@ -60,20 +60,20 @@ MODULE_LICENSE("GPL");
MODULE_ALIAS("wmi:"EEEPC_WMI_EVENT_GUID);
MODULE_ALIAS("wmi:"EEEPC_WMI_MGMT_GUID);

-#define NOTIFY_BRNUP_MIN 0x11
-#define NOTIFY_BRNUP_MAX 0x1f
-#define NOTIFY_BRNDOWN_MIN 0x20
-#define NOTIFY_BRNDOWN_MAX 0x2e
+#define NOTIFY_BRNUP_MIN 0x11
+#define NOTIFY_BRNUP_MAX 0x1f
+#define NOTIFY_BRNDOWN_MIN 0x20
+#define NOTIFY_BRNDOWN_MAX 0x2e

-#define EEEPC_WMI_METHODID_DEVS 0x53564544
-#define EEEPC_WMI_METHODID_DSTS 0x53544344
-#define EEEPC_WMI_METHODID_CFVS 0x53564643
+#define EEEPC_WMI_METHODID_DSTS 0x53544344
+#define EEEPC_WMI_METHODID_DEVS 0x53564544
+#define EEEPC_WMI_METHODID_CFVS 0x53564643

-#define EEEPC_WMI_DEVID_BACKLIGHT 0x00050012
-#define EEEPC_WMI_DEVID_TPDLED 0x00100011
#define EEEPC_WMI_DEVID_WLAN 0x00010011
#define EEEPC_WMI_DEVID_BLUETOOTH 0x00010013
#define EEEPC_WMI_DEVID_WWAN3G 0x00010019
+#define EEEPC_WMI_DEVID_BACKLIGHT 0x00050012
+#define EEEPC_WMI_DEVID_TPDLED 0x00100011

static bool hotplug_wireless;

--
1.7.4.rc3

2011-02-06 12:29:51

by Corentin Chary

[permalink] [raw]
Subject: [PATCH v2 08/18] eeepc-wmi: switch to platform_create_bundle()

This allow to remove ~30 lines of code.

Signed-off-by: Corentin Chary <[email protected]>
---
drivers/platform/x86/eeepc-wmi.c | 75 +++++++++++---------------------------
1 files changed, 22 insertions(+), 53 deletions(-)

diff --git a/drivers/platform/x86/eeepc-wmi.c b/drivers/platform/x86/eeepc-wmi.c
index 583ba78..1fc191b 100644
--- a/drivers/platform/x86/eeepc-wmi.c
+++ b/drivers/platform/x86/eeepc-wmi.c
@@ -144,9 +144,6 @@ struct eeepc_wmi {
struct eeepc_wmi_debug debug;
};

-/* Only used in eeepc_wmi_init() and eeepc_wmi_exit() */
-static struct platform_device *platform_device;
-
static int eeepc_wmi_input_init(struct eeepc_wmi *eeepc)
{
int err;
@@ -932,33 +929,12 @@ static int eeepc_wmi_sysfs_init(struct platform_device *device)
*/
static int __init eeepc_wmi_platform_init(struct eeepc_wmi *eeepc)
{
- int err;
-
- eeepc->platform_device = platform_device_alloc(EEEPC_WMI_FILE, -1);
- if (!eeepc->platform_device)
- return -ENOMEM;
- platform_set_drvdata(eeepc->platform_device, eeepc);
-
- err = platform_device_add(eeepc->platform_device);
- if (err)
- goto fail_platform_device;
-
- err = eeepc_wmi_sysfs_init(eeepc->platform_device);
- if (err)
- goto fail_sysfs;
- return 0;
-
-fail_sysfs:
- platform_device_del(eeepc->platform_device);
-fail_platform_device:
- platform_device_put(eeepc->platform_device);
- return err;
+ return eeepc_wmi_sysfs_init(eeepc->platform_device);
}

static void eeepc_wmi_platform_exit(struct eeepc_wmi *eeepc)
{
eeepc_wmi_sysfs_exit(eeepc->platform_device);
- platform_device_unregister(eeepc->platform_device);
}

/*
@@ -1094,7 +1070,7 @@ static void eeepc_dmi_check(struct eeepc_wmi *eeepc)
}
}

-static struct platform_device * __init eeepc_wmi_add(void)
+static int __init eeepc_wmi_add(struct platform_device *pdev)
{
struct eeepc_wmi *eeepc;
acpi_status status;
@@ -1102,15 +1078,14 @@ static struct platform_device * __init eeepc_wmi_add(void)

eeepc = kzalloc(sizeof(struct eeepc_wmi), GFP_KERNEL);
if (!eeepc)
- return ERR_PTR(-ENOMEM);
+ return -ENOMEM;
+
+ eeepc->platform_device = pdev;
+ platform_set_drvdata(eeepc->platform_device, eeepc);

eeepc->hotplug_wireless = hotplug_wireless;
eeepc_dmi_check(eeepc);

- /*
- * Register the platform device first. It is used as a parent for the
- * sub-devices below.
- */
err = eeepc_wmi_platform_init(eeepc);
if (err)
goto fail_platform;
@@ -1147,7 +1122,7 @@ static struct platform_device * __init eeepc_wmi_add(void)
if (err)
goto fail_debugfs;

- return eeepc->platform_device;
+ return 0;

fail_debugfs:
wmi_remove_notify_handler(EEEPC_WMI_EVENT_GUID);
@@ -1163,10 +1138,10 @@ fail_input:
eeepc_wmi_platform_exit(eeepc);
fail_platform:
kfree(eeepc);
- return ERR_PTR(err);
+ return err;
}

-static int eeepc_wmi_remove(struct platform_device *device)
+static int __exit eeepc_wmi_remove(struct platform_device *device)
{
struct eeepc_wmi *eeepc;

@@ -1232,6 +1207,7 @@ static const struct dev_pm_ops eeepc_pm_ops = {
};

static struct platform_driver platform_driver = {
+ .remove = __exit_p(eeepc_wmi_remove),
.driver = {
.name = EEEPC_WMI_FILE,
.owner = THIS_MODULE,
@@ -1260,10 +1236,8 @@ static int __init eeepc_wmi_check_atkd(void)
return -1;
}

-static int __init eeepc_wmi_init(void)
+static int __init eeepc_wmi_probe(struct platform_device *pdev)
{
- int err;
-
if (!wmi_has_guid(EEEPC_WMI_EVENT_GUID) ||
!wmi_has_guid(EEEPC_WMI_MGMT_GUID)) {
pr_warning("No known WMI GUID found\n");
@@ -1280,29 +1254,24 @@ static int __init eeepc_wmi_init(void)
return -ENODEV;
}

- platform_device = eeepc_wmi_add();
- if (IS_ERR(platform_device)) {
- err = PTR_ERR(platform_device);
- goto fail_eeepc_wmi;
- }
+ return eeepc_wmi_add(pdev);
+}

- err = platform_driver_register(&platform_driver);
- if (err) {
- pr_warning("Unable to register platform driver\n");
- goto fail_platform_driver;
- }
+static struct platform_device *platform_device;

+static int __init eeepc_wmi_init(void)
+{
+ platform_device = platform_create_bundle(&platform_driver,
+ eeepc_wmi_probe,
+ NULL, 0, NULL, 0);
+ if (IS_ERR(platform_device))
+ return PTR_ERR(platform_device);
return 0;
-
-fail_platform_driver:
- eeepc_wmi_remove(platform_device);
-fail_eeepc_wmi:
- return err;
}

static void __exit eeepc_wmi_exit(void)
{
- eeepc_wmi_remove(platform_device);
+ platform_device_unregister(platform_device);
platform_driver_unregister(&platform_driver);
}

--
1.7.4.rc3

2011-02-06 12:30:01

by Corentin Chary

[permalink] [raw]
Subject: [PATCH v2 10/18] eeepc-wmi: use the presence bit correctly

I checked some more DSDT, and it seems that I wasn't
totally right about the meaning of DSTS return value.
Bit 0 is clearly the status of the device, and I discovered
that bit 16 is set when the device is present.

Signed-off-by: Corentin Chary <[email protected]>
---
drivers/platform/x86/eeepc-wmi.c | 13 +++++--------
1 files changed, 5 insertions(+), 8 deletions(-)

diff --git a/drivers/platform/x86/eeepc-wmi.c b/drivers/platform/x86/eeepc-wmi.c
index aa9e1d1..391c32b 100644
--- a/drivers/platform/x86/eeepc-wmi.c
+++ b/drivers/platform/x86/eeepc-wmi.c
@@ -75,6 +75,9 @@ MODULE_ALIAS("wmi:"EEEPC_WMI_MGMT_GUID);
#define EEEPC_WMI_DEVID_BACKLIGHT 0x00050012
#define EEEPC_WMI_DEVID_TPDLED 0x00100011

+#define EEEPC_WMI_DSTS_STATUS_BIT 0x00000001
+#define EEEPC_WMI_DSTS_PRESENCE_BIT 0x00010000
+
static bool hotplug_wireless;

module_param(hotplug_wireless, bool, 0444);
@@ -265,16 +268,10 @@ static int eeepc_wmi_get_devstate_simple(u32 dev_id)
if (ACPI_FAILURE(status))
return -EINVAL;

- /* If the device is present, DSTS will always set some bits
- * 0x00070000 - 1110000000000000000 - device supported
- * 0x00060000 - 1100000000000000000 - not supported
- * 0x00020000 - 0100000000000000000 - device supported
- * 0x00010000 - 0010000000000000000 - not supported / special mode ?
- */
- if (!retval || retval == 0x00060000)
+ if (!(retval & EEEPC_WMI_DSTS_PRESENCE_BIT))
return -ENODEV;

- return retval & 0x1;
+ return retval & EEEPC_WMI_DSTS_STATUS_BIT;
}

/*
--
1.7.4.rc3

2011-02-06 12:30:17

by Corentin Chary

[permalink] [raw]
Subject: [PATCH v2 14/18] eeepc-wmi: support backlight power (bl_power) attribute

Signed-off-by: Corentin Chary <[email protected]>
---
drivers/platform/x86/eeepc-wmi.c | 75 +++++++++++++++++++++++++++++++-------
1 files changed, 61 insertions(+), 14 deletions(-)

diff --git a/drivers/platform/x86/eeepc-wmi.c b/drivers/platform/x86/eeepc-wmi.c
index 75dd692..910eb00 100644
--- a/drivers/platform/x86/eeepc-wmi.c
+++ b/drivers/platform/x86/eeepc-wmi.c
@@ -73,13 +73,16 @@ MODULE_ALIAS("wmi:"EEEPC_WMI_MGMT_GUID);
#define EEEPC_WMI_DEVID_BLUETOOTH 0x00010013
#define EEEPC_WMI_DEVID_WIMAX 0x00010017
#define EEEPC_WMI_DEVID_WWAN3G 0x00010019
-#define EEEPC_WMI_DEVID_BACKLIGHT 0x00050012
+#define EEEPC_WMI_DEVID_BACKLIGHT 0x00050011
+#define EEEPC_WMI_DEVID_BRIGHTNESS 0x00050012
#define EEEPC_WMI_DEVID_CAMERA 0x00060013
#define EEEPC_WMI_DEVID_CARDREADER 0x00080013
#define EEEPC_WMI_DEVID_TPDLED 0x00100011

#define EEEPC_WMI_DSTS_STATUS_BIT 0x00000001
#define EEEPC_WMI_DSTS_PRESENCE_BIT 0x00010000
+#define EEEPC_WMI_DSTS_BRIGHTNESS_MASK 0x000000FF
+#define EEEPC_WMI_DSTS_MAX_BRIGTH_MASK 0x0000FF00

static bool hotplug_wireless;

@@ -262,7 +265,7 @@ static acpi_status eeepc_wmi_set_devstate(u32 dev_id, u32 ctrl_param,
}

/* Helper for special devices with magic return codes */
-static int eeepc_wmi_get_devstate_simple(u32 dev_id)
+static int eeepc_wmi_get_devstate_bits(u32 dev_id, u32 mask)
{
u32 retval = 0;
acpi_status status;
@@ -275,7 +278,12 @@ static int eeepc_wmi_get_devstate_simple(u32 dev_id)
if (!(retval & EEEPC_WMI_DSTS_PRESENCE_BIT))
return -ENODEV;

- return retval & EEEPC_WMI_DSTS_STATUS_BIT;
+ return retval & mask;
+}
+
+static int eeepc_wmi_get_devstate_simple(u32 dev_id)
+{
+ return eeepc_wmi_get_devstate_bits(dev_id, EEEPC_WMI_DSTS_STATUS_BIT);
}

/*
@@ -770,34 +778,53 @@ exit:
/*
* Backlight
*/
+static int read_backlight_power(void)
+{
+ int ret = eeepc_wmi_get_devstate_simple(EEEPC_WMI_DEVID_BACKLIGHT);
+
+ if (ret < 0)
+ return ret;
+
+ return ret ? FB_BLANK_UNBLANK : FB_BLANK_POWERDOWN;
+}
+
static int read_brightness(struct backlight_device *bd)
{
u32 retval;
acpi_status status;

- status = eeepc_wmi_get_devstate(EEEPC_WMI_DEVID_BACKLIGHT, &retval);
+ status = eeepc_wmi_get_devstate(EEEPC_WMI_DEVID_BRIGHTNESS, &retval);

if (ACPI_FAILURE(status))
- return -1;
+ return -EIO;
else
- return retval & 0xFF;
+ return retval & EEEPC_WMI_DSTS_BRIGHTNESS_MASK;
}

static int update_bl_status(struct backlight_device *bd)
{
-
u32 ctrl_param;
acpi_status status;
+ int power;

ctrl_param = bd->props.brightness;

- status = eeepc_wmi_set_devstate(EEEPC_WMI_DEVID_BACKLIGHT,
+ status = eeepc_wmi_set_devstate(EEEPC_WMI_DEVID_BRIGHTNESS,
ctrl_param, NULL);

if (ACPI_FAILURE(status))
- return -1;
- else
- return 0;
+ return -EIO;
+
+ power = read_backlight_power();
+ if (power != -ENODEV && bd->props.power != power) {
+ ctrl_param = !!(bd->props.power == FB_BLANK_UNBLANK);
+ status = eeepc_wmi_set_devstate(EEEPC_WMI_DEVID_BACKLIGHT,
+ ctrl_param, NULL);
+
+ if (ACPI_FAILURE(status))
+ return -EIO;
+ }
+ return 0;
}

static const struct backlight_ops eeepc_wmi_bl_ops = {
@@ -827,9 +854,29 @@ static int eeepc_wmi_backlight_init(struct eeepc_wmi *eeepc)
{
struct backlight_device *bd;
struct backlight_properties props;
+ int max;
+ int power;
+
+ max = eeepc_wmi_get_devstate_bits(EEEPC_WMI_DEVID_BRIGHTNESS,
+ EEEPC_WMI_DSTS_MAX_BRIGTH_MASK);
+ power = read_backlight_power();
+
+ if (max < 0 && power < 0) {
+ /* Try to keep the original error */
+ if (max == -ENODEV && power == -ENODEV)
+ return -ENODEV;
+ if (max != -ENODEV)
+ return max;
+ else
+ return power;
+ }
+ if (max == -ENODEV)
+ max = 0;
+ if (power == -ENODEV)
+ power = FB_BLANK_UNBLANK;

memset(&props, 0, sizeof(struct backlight_properties));
- props.max_brightness = 15;
+ props.max_brightness = max;
bd = backlight_device_register(EEEPC_WMI_FILE,
&eeepc->platform_device->dev, eeepc,
&eeepc_wmi_bl_ops, &props);
@@ -841,7 +888,7 @@ static int eeepc_wmi_backlight_init(struct eeepc_wmi *eeepc)
eeepc->backlight_device = bd;

bd->props.brightness = read_brightness(bd);
- bd->props.power = FB_BLANK_UNBLANK;
+ bd->props.power = power;
backlight_update_status(bd);

return 0;
@@ -1202,7 +1249,7 @@ static int __init eeepc_wmi_add(struct platform_device *pdev)

if (!acpi_video_backlight_support()) {
err = eeepc_wmi_backlight_init(eeepc);
- if (err)
+ if (err && err != -ENODEV)
goto fail_backlight;
} else
pr_info("Backlight controlled by ACPI video driver\n");
--
1.7.4.rc3

2011-02-06 12:30:23

by Corentin Chary

[permalink] [raw]
Subject: [PATCH v2 16/18] eeepc-wmi: real touchpad led device id is 0x001000012

Signed-off-by: Corentin Chary <[email protected]>
---
drivers/platform/x86/eeepc-wmi.c | 12 ++++++------
1 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/drivers/platform/x86/eeepc-wmi.c b/drivers/platform/x86/eeepc-wmi.c
index bc71333..ffc5889 100644
--- a/drivers/platform/x86/eeepc-wmi.c
+++ b/drivers/platform/x86/eeepc-wmi.c
@@ -77,7 +77,7 @@ MODULE_ALIAS("wmi:"EEEPC_WMI_MGMT_GUID);
#define EEEPC_WMI_DEVID_BRIGHTNESS 0x00050012
#define EEEPC_WMI_DEVID_CAMERA 0x00060013
#define EEEPC_WMI_DEVID_CARDREADER 0x00080013
-#define EEEPC_WMI_DEVID_TPDLED 0x00100011
+#define EEEPC_WMI_DEVID_TOUCHPAD_LED 0x00100012

#define EEEPC_WMI_DSTS_STATUS_BIT 0x00000001
#define EEEPC_WMI_DSTS_PRESENCE_BIT 0x00010000
@@ -303,7 +303,7 @@ static void tpd_led_update(struct work_struct *work)
eeepc = container_of(work, struct eeepc_wmi, tpd_led_work);

ctrl_param = eeepc->tpd_led_wk;
- eeepc_wmi_set_devstate(EEEPC_WMI_DEVID_TPDLED, ctrl_param, NULL);
+ eeepc_wmi_set_devstate(EEEPC_WMI_DEVID_TOUCHPAD_LED, ctrl_param, NULL);
}

static void tpd_led_set(struct led_classdev *led_cdev,
@@ -317,9 +317,9 @@ static void tpd_led_set(struct led_classdev *led_cdev,
queue_work(eeepc->led_workqueue, &eeepc->tpd_led_work);
}

-static int read_tpd_state(struct eeepc_wmi *eeepc)
+static int read_tpd_led_state(struct eeepc_wmi *eeepc)
{
- return eeepc_wmi_get_devstate_simple(EEEPC_WMI_DEVID_TPDLED);
+ return eeepc_wmi_get_devstate_simple(EEEPC_WMI_DEVID_TOUCHPAD_LED);
}

static enum led_brightness tpd_led_get(struct led_classdev *led_cdev)
@@ -328,14 +328,14 @@ static enum led_brightness tpd_led_get(struct led_classdev *led_cdev)

eeepc = container_of(led_cdev, struct eeepc_wmi, tpd_led);

- return read_tpd_state(eeepc);
+ return read_tpd_led_state(eeepc);
}

static int eeepc_wmi_led_init(struct eeepc_wmi *eeepc)
{
int rv;

- if (read_tpd_state(eeepc) < 0)
+ if (read_tpd_led_state(eeepc) < 0)
return 0;

eeepc->led_workqueue = create_singlethread_workqueue("led_workqueue");
--
1.7.4.rc3

2011-02-06 12:30:36

by Corentin Chary

[permalink] [raw]
Subject: [PATCH v2 18/18] eeepc-wmi: reorder device ids

Each device seems to be in a "group" (devid >> 16 & 0xFF).

Signed-off-by: Corentin Chary <[email protected]>
---
drivers/platform/x86/eeepc-wmi.c | 11 +++++++++++
1 files changed, 11 insertions(+), 0 deletions(-)

diff --git a/drivers/platform/x86/eeepc-wmi.c b/drivers/platform/x86/eeepc-wmi.c
index 26ed706..b0b5a8f 100644
--- a/drivers/platform/x86/eeepc-wmi.c
+++ b/drivers/platform/x86/eeepc-wmi.c
@@ -65,21 +65,32 @@ MODULE_ALIAS("wmi:"EEEPC_WMI_MGMT_GUID);
#define NOTIFY_BRNDOWN_MIN 0x20
#define NOTIFY_BRNDOWN_MAX 0x2e

+/* WMI Methods */
#define EEEPC_WMI_METHODID_DSTS 0x53544344
#define EEEPC_WMI_METHODID_DEVS 0x53564544
#define EEEPC_WMI_METHODID_CFVS 0x53564643

+/* Wireless */
#define EEEPC_WMI_DEVID_WLAN 0x00010011
#define EEEPC_WMI_DEVID_BLUETOOTH 0x00010013
#define EEEPC_WMI_DEVID_WIMAX 0x00010017
#define EEEPC_WMI_DEVID_WWAN3G 0x00010019
+
+/* Backlight and Brightness */
#define EEEPC_WMI_DEVID_BACKLIGHT 0x00050011
#define EEEPC_WMI_DEVID_BRIGHTNESS 0x00050012
+
+/* Misc */
#define EEEPC_WMI_DEVID_CAMERA 0x00060013
+
+/* Storage */
#define EEEPC_WMI_DEVID_CARDREADER 0x00080013
+
+/* Input */
#define EEEPC_WMI_DEVID_TOUCHPAD 0x00100011
#define EEEPC_WMI_DEVID_TOUCHPAD_LED 0x00100012

+/* DSTS masks */
#define EEEPC_WMI_DSTS_STATUS_BIT 0x00000001
#define EEEPC_WMI_DSTS_PRESENCE_BIT 0x00010000
#define EEEPC_WMI_DSTS_BRIGHTNESS_MASK 0x000000FF
--
1.7.4.rc3

2011-02-06 12:30:30

by Corentin Chary

[permalink] [raw]
Subject: [PATCH v2 17/18] eeepc-wmi: add touchpad sysfs file

Signed-off-by: Corentin Chary <[email protected]>
---
Documentation/ABI/testing/sysfs-platform-eeepc-wmi | 7 +++++++
drivers/platform/x86/eeepc-wmi.c | 5 +++++
2 files changed, 12 insertions(+), 0 deletions(-)

diff --git a/Documentation/ABI/testing/sysfs-platform-eeepc-wmi b/Documentation/ABI/testing/sysfs-platform-eeepc-wmi
index 9fc8d33..26acb68 100644
--- a/Documentation/ABI/testing/sysfs-platform-eeepc-wmi
+++ b/Documentation/ABI/testing/sysfs-platform-eeepc-wmi
@@ -22,3 +22,10 @@ KernelVersion: 2.6.39
Contact: "Corentin Chary" <[email protected]>
Description:
Control the card reader. 1 means on, 0 means off.
+
+What: /sys/devices/platform/eeepc-wmi/touchpad
+Date: Jan 2010
+KernelVersion: 2.6.39
+Contact: "Corentin Chary" <[email protected]>
+Description:
+ Control the card touchpad. 1 means on, 0 means off.
diff --git a/drivers/platform/x86/eeepc-wmi.c b/drivers/platform/x86/eeepc-wmi.c
index ffc5889..26ed706 100644
--- a/drivers/platform/x86/eeepc-wmi.c
+++ b/drivers/platform/x86/eeepc-wmi.c
@@ -77,6 +77,7 @@ MODULE_ALIAS("wmi:"EEEPC_WMI_MGMT_GUID);
#define EEEPC_WMI_DEVID_BRIGHTNESS 0x00050012
#define EEEPC_WMI_DEVID_CAMERA 0x00060013
#define EEEPC_WMI_DEVID_CARDREADER 0x00080013
+#define EEEPC_WMI_DEVID_TOUCHPAD 0x00100011
#define EEEPC_WMI_DEVID_TOUCHPAD_LED 0x00100012

#define EEEPC_WMI_DSTS_STATUS_BIT 0x00000001
@@ -1006,6 +1007,7 @@ static ssize_t show_sys_wmi(int devid, char *buf)
.store = store_##_name, \
}

+EEEPC_WMI_CREATE_DEVICE_ATTR(touchpad, 0644, EEEPC_WMI_DEVID_TOUCHPAD);
EEEPC_WMI_CREATE_DEVICE_ATTR(camera, 0644, EEEPC_WMI_DEVID_CAMERA);
EEEPC_WMI_CREATE_DEVICE_ATTR(cardr, 0644, EEEPC_WMI_DEVID_CARDREADER);

@@ -1036,6 +1038,7 @@ static struct attribute *platform_attributes[] = {
&dev_attr_cpufv.attr,
&dev_attr_camera.attr,
&dev_attr_cardr.attr,
+ &dev_attr_touchpad.attr,
NULL
};

@@ -1050,6 +1053,8 @@ static mode_t eeepc_sysfs_is_visible(struct kobject *kobj,
devid = EEEPC_WMI_DEVID_CAMERA;
else if (attr == &dev_attr_cardr.attr)
devid = EEEPC_WMI_DEVID_CARDREADER;
+ else if (attr == &dev_attr_touchpad.attr)
+ devid = EEEPC_WMI_DEVID_TOUCHPAD;

if (devid != -1)
supported = eeepc_wmi_get_devstate_simple(devid) != -ENODEV;
--
1.7.4.rc3

2011-02-06 12:31:15

by Corentin Chary

[permalink] [raw]
Subject: [PATCH v2 15/18] eeepc-wmi: respect wireless_hotplug setting

Signed-off-by: Corentin Chary <[email protected]>
---
drivers/platform/x86/eeepc-wmi.c | 3 +++
1 files changed, 3 insertions(+), 0 deletions(-)

diff --git a/drivers/platform/x86/eeepc-wmi.c b/drivers/platform/x86/eeepc-wmi.c
index 910eb00..bc71333 100644
--- a/drivers/platform/x86/eeepc-wmi.c
+++ b/drivers/platform/x86/eeepc-wmi.c
@@ -748,6 +748,9 @@ static int eeepc_wmi_rfkill_init(struct eeepc_wmi *eeepc)
if (result && result != -ENODEV)
goto exit;

+ if (!eeepc->hotplug_wireless)
+ goto exit;
+
result = eeepc_setup_pci_hotplug(eeepc);
/*
* If we get -EBUSY then something else is handling the PCI hotplug -
--
1.7.4.rc3

2011-02-06 12:30:11

by Corentin Chary

[permalink] [raw]
Subject: [PATCH v2 11/18] eeepc-wmi: add camera and card reader support

Signed-off-by: Corentin Chary <[email protected]>
---
Documentation/ABI/testing/sysfs-platform-eeepc-wmi | 14 +++
drivers/platform/x86/eeepc-wmi.c | 89 +++++++++++++++++++-
2 files changed, 102 insertions(+), 1 deletions(-)

diff --git a/Documentation/ABI/testing/sysfs-platform-eeepc-wmi b/Documentation/ABI/testing/sysfs-platform-eeepc-wmi
index e4b5fef..9fc8d33 100644
--- a/Documentation/ABI/testing/sysfs-platform-eeepc-wmi
+++ b/Documentation/ABI/testing/sysfs-platform-eeepc-wmi
@@ -8,3 +8,17 @@ Description:
* 0 -> Super Performance Mode
* 1 -> High Performance Mode
* 2 -> Power Saving Mode
+
+What: /sys/devices/platform/eeepc-wmi/camera
+Date: Jan 2010
+KernelVersion: 2.6.39
+Contact: "Corentin Chary" <[email protected]>
+Description:
+ Control the camera. 1 means on, 0 means off.
+
+What: /sys/devices/platform/eeepc-wmi/cardr
+Date: Jan 2010
+KernelVersion: 2.6.39
+Contact: "Corentin Chary" <[email protected]>
+Description:
+ Control the card reader. 1 means on, 0 means off.
diff --git a/drivers/platform/x86/eeepc-wmi.c b/drivers/platform/x86/eeepc-wmi.c
index 391c32b..83415dd 100644
--- a/drivers/platform/x86/eeepc-wmi.c
+++ b/drivers/platform/x86/eeepc-wmi.c
@@ -73,6 +73,8 @@ MODULE_ALIAS("wmi:"EEEPC_WMI_MGMT_GUID);
#define EEEPC_WMI_DEVID_BLUETOOTH 0x00010013
#define EEEPC_WMI_DEVID_WWAN3G 0x00010019
#define EEEPC_WMI_DEVID_BACKLIGHT 0x00050012
+#define EEEPC_WMI_DEVID_CAMERA 0x00060013
+#define EEEPC_WMI_DEVID_CARDREADER 0x00080013
#define EEEPC_WMI_DEVID_TPDLED 0x00100011

#define EEEPC_WMI_DSTS_STATUS_BIT 0x00000001
@@ -879,6 +881,70 @@ static void eeepc_wmi_notify(u32 value, void *context)
kfree(obj);
}

+/*
+ * Sys helpers
+ */
+static int parse_arg(const char *buf, unsigned long count, int *val)
+{
+ if (!count)
+ return 0;
+ if (sscanf(buf, "%i", val) != 1)
+ return -EINVAL;
+ return count;
+}
+
+static ssize_t store_sys_wmi(int devid, const char *buf, size_t count)
+{
+ acpi_status status;
+ u32 retval;
+ int rv, value;
+
+ value = eeepc_wmi_get_devstate_simple(devid);
+ if (value == -ENODEV) /* Check device presence */
+ return value;
+
+ rv = parse_arg(buf, count, &value);
+ status = eeepc_wmi_set_devstate(devid, value, &retval);
+
+ if (ACPI_FAILURE(status))
+ return -EIO;
+ return rv;
+}
+
+static ssize_t show_sys_wmi(int devid, char *buf)
+{
+ int value = eeepc_wmi_get_devstate_simple(devid);
+
+ if (value < 0)
+ return value;
+
+ return sprintf(buf, "%d\n", value);
+}
+
+#define EEEPC_WMI_CREATE_DEVICE_ATTR(_name, _mode, _cm) \
+ static ssize_t show_##_name(struct device *dev, \
+ struct device_attribute *attr, \
+ char *buf) \
+ { \
+ return show_sys_wmi(_cm, buf); \
+ } \
+ static ssize_t store_##_name(struct device *dev, \
+ struct device_attribute *attr, \
+ const char *buf, size_t count) \
+ { \
+ return store_sys_wmi(_cm, buf, count); \
+ } \
+ static struct device_attribute dev_attr_##_name = { \
+ .attr = { \
+ .name = __stringify(_name), \
+ .mode = _mode }, \
+ .show = show_##_name, \
+ .store = store_##_name, \
+ }
+
+EEEPC_WMI_CREATE_DEVICE_ATTR(camera, 0644, EEEPC_WMI_DEVID_CAMERA);
+EEEPC_WMI_CREATE_DEVICE_ATTR(cardr, 0644, EEEPC_WMI_DEVID_CARDREADER);
+
static ssize_t store_cpufv(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
@@ -904,11 +970,32 @@ static DEVICE_ATTR(cpufv, S_IRUGO | S_IWUSR, NULL, store_cpufv);

static struct attribute *platform_attributes[] = {
&dev_attr_cpufv.attr,
+ &dev_attr_camera.attr,
+ &dev_attr_cardr.attr,
NULL
};

+static mode_t eeepc_sysfs_is_visible(struct kobject *kobj,
+ struct attribute *attr,
+ int idx)
+{
+ bool supported = true;
+ int devid = -1;
+
+ if (attr == &dev_attr_camera.attr)
+ devid = EEEPC_WMI_DEVID_CAMERA;
+ else if (attr == &dev_attr_cardr.attr)
+ devid = EEEPC_WMI_DEVID_CARDREADER;
+
+ if (devid != -1)
+ supported = eeepc_wmi_get_devstate_simple(devid) != -ENODEV;
+
+ return supported ? attr->mode : 0;
+}
+
static struct attribute_group platform_attribute_group = {
- .attrs = platform_attributes
+ .is_visible = eeepc_sysfs_is_visible,
+ .attrs = platform_attributes
};

static void eeepc_wmi_sysfs_exit(struct platform_device *device)
--
1.7.4.rc3

2011-02-06 12:30:09

by Corentin Chary

[permalink] [raw]
Subject: [PATCH v2 12/18] eeepc-wmi: add wimax support

Signed-off-by: Corentin Chary <[email protected]>
---
drivers/platform/x86/eeepc-wmi.c | 20 +++++++++++++++++++-
1 files changed, 19 insertions(+), 1 deletions(-)

diff --git a/drivers/platform/x86/eeepc-wmi.c b/drivers/platform/x86/eeepc-wmi.c
index 83415dd..0db7009 100644
--- a/drivers/platform/x86/eeepc-wmi.c
+++ b/drivers/platform/x86/eeepc-wmi.c
@@ -71,6 +71,7 @@ MODULE_ALIAS("wmi:"EEEPC_WMI_MGMT_GUID);

#define EEEPC_WMI_DEVID_WLAN 0x00010011
#define EEEPC_WMI_DEVID_BLUETOOTH 0x00010013
+#define EEEPC_WMI_DEVID_WIMAX 0x00010017
#define EEEPC_WMI_DEVID_WWAN3G 0x00010019
#define EEEPC_WMI_DEVID_BACKLIGHT 0x00050012
#define EEEPC_WMI_DEVID_CAMERA 0x00060013
@@ -138,6 +139,7 @@ struct eeepc_wmi {

struct rfkill *wlan_rfkill;
struct rfkill *bluetooth_rfkill;
+ struct rfkill *wimax_rfkill;
struct rfkill *wwan3g_rfkill;

struct hotplug_slot *hotplug_slot;
@@ -691,6 +693,11 @@ static void eeepc_wmi_rfkill_exit(struct eeepc_wmi *eeepc)
rfkill_destroy(eeepc->bluetooth_rfkill);
eeepc->bluetooth_rfkill = NULL;
}
+ if (eeepc->wimax_rfkill) {
+ rfkill_unregister(eeepc->wimax_rfkill);
+ rfkill_destroy(eeepc->wimax_rfkill);
+ eeepc->wimax_rfkill = NULL;
+ }
if (eeepc->wwan3g_rfkill) {
rfkill_unregister(eeepc->wwan3g_rfkill);
rfkill_destroy(eeepc->wwan3g_rfkill);
@@ -719,6 +726,13 @@ static int eeepc_wmi_rfkill_init(struct eeepc_wmi *eeepc)
if (result && result != -ENODEV)
goto exit;

+ result = eeepc_new_rfkill(eeepc, &eeepc->wimax_rfkill,
+ "eeepc-wimax", RFKILL_TYPE_WIMAX,
+ EEEPC_WMI_DEVID_WIMAX);
+
+ if (result && result != -ENODEV)
+ goto exit;
+
result = eeepc_new_rfkill(eeepc, &eeepc->wwan3g_rfkill,
"eeepc-wwan3g", RFKILL_TYPE_WWAN,
EEEPC_WMI_DEVID_WWAN3G);
@@ -1276,7 +1290,11 @@ static int eeepc_hotk_restore(struct device *device)
if (eeepc->bluetooth_rfkill) {
bl = !eeepc_wmi_get_devstate_simple(EEEPC_WMI_DEVID_BLUETOOTH);
rfkill_set_sw_state(eeepc->bluetooth_rfkill, bl);
-}
+ }
+ if (eeepc->wimax_rfkill) {
+ bl = !eeepc_wmi_get_devstate_simple(EEEPC_WMI_DEVID_WIMAX);
+ rfkill_set_sw_state(eeepc->wimax_rfkill, bl);
+ }
if (eeepc->wwan3g_rfkill) {
bl = !eeepc_wmi_get_devstate_simple(EEEPC_WMI_DEVID_WWAN3G);
rfkill_set_sw_state(eeepc->wwan3g_rfkill, bl);
--
1.7.4.rc3

2011-02-06 12:32:35

by Corentin Chary

[permalink] [raw]
Subject: [PATCH v2 13/18] eeepc-wmi: set the right key code for 0xe9

This key should power off the backlight, not the display,
it is also used in acpi/video.c to do the same thing.

Signed-off-by: Corentin Chary <[email protected]>
---
drivers/platform/x86/eeepc-wmi.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/drivers/platform/x86/eeepc-wmi.c b/drivers/platform/x86/eeepc-wmi.c
index 0db7009..75dd692 100644
--- a/drivers/platform/x86/eeepc-wmi.c
+++ b/drivers/platform/x86/eeepc-wmi.c
@@ -103,7 +103,7 @@ static const struct key_entry eeepc_wmi_keymap[] = {
{ KE_KEY, 0xcc, { KEY_SWITCHVIDEOMODE } },
{ KE_KEY, 0xe0, { KEY_PROG1 } },
{ KE_KEY, 0xe1, { KEY_F14 } },
- { KE_KEY, 0xe9, { KEY_DISPLAY_OFF } },
+ { KE_KEY, 0xe9, { KEY_BRIGHTNESS_ZERO } },
{ KE_END, 0},
};

--
1.7.4.rc3

2011-02-06 12:33:19

by Corentin Chary

[permalink] [raw]
Subject: [PATCH v2 04/18] eeepc-wmi: serialize access to wmi method

\AMW0.WMBC, which is the main method that we use,
is not reentrant. When wireless hotpluging is enabled,
toggling the status of the wireless device using WMBC will
trigger a notification and the notification handler need to
call WMBC again to get the new status of the device, this
will trigger the following error:

ACPI Error (dswload-0802): [_T_0] Namespace lookup failure, AE_ALREADY_EXISTS
ACPI Exception: AE_ALREADY_EXISTS, During name lookup/catalog (20100428/psloop-231)
ACPI Error (psparse-0537): Method parse/execution failed [\AMW0.WMBC] (Node f7023b88), AE_ALREADY_EXISTS
ACPI: Marking method WMBC as Serialized because of AE_ALREADY_EXISTS error

Since there is currently no way to tell the acpi subsystem to mark
a method as serialized, we do it in eeepc-wmi.

Of course, we could let the first call fail, and then it would work,
but it doesn't seems really clean, and it will make the first
WMBC call return a random value.

This patch was tested on EeePc 1000H with a RaLink RT2860
wireless card using the rt2800pci driver. rt2860sta driver
seems to deadlock when we remove the pci device...

Signed-off-by: Corentin Chary <[email protected]>
---
drivers/platform/x86/eeepc-wmi.c | 78 +++++++++++++++++++++++++++++++++++---
1 files changed, 72 insertions(+), 6 deletions(-)

diff --git a/drivers/platform/x86/eeepc-wmi.c b/drivers/platform/x86/eeepc-wmi.c
index 01bc2b3..eb4c0ce 100644
--- a/drivers/platform/x86/eeepc-wmi.c
+++ b/drivers/platform/x86/eeepc-wmi.c
@@ -137,6 +137,9 @@ struct eeepc_wmi {

struct hotplug_slot *hotplug_slot;
struct mutex hotplug_lock;
+ struct mutex wmi_lock;
+ struct workqueue_struct *hotplug_workqueue;
+ struct work_struct hotplug_work;

struct eeepc_wmi_debug debug;
};
@@ -370,15 +373,19 @@ static void eeepc_rfkill_hotplug(struct eeepc_wmi *eeepc)
{
struct pci_dev *dev;
struct pci_bus *bus;
- bool blocked = eeepc_wlan_rfkill_blocked(eeepc);
+ bool blocked;
bool absent;
u32 l;

- if (eeepc->wlan_rfkill)
- rfkill_set_sw_state(eeepc->wlan_rfkill, blocked);
+ mutex_lock(&eeepc->wmi_lock);
+ blocked = eeepc_wlan_rfkill_blocked(eeepc);
+ mutex_unlock(&eeepc->wmi_lock);

mutex_lock(&eeepc->hotplug_lock);

+ if (eeepc->wlan_rfkill)
+ rfkill_set_sw_state(eeepc->wlan_rfkill, blocked);
+
if (eeepc->hotplug_slot) {
bus = pci_find_bus(0, 1);
if (!bus) {
@@ -435,7 +442,14 @@ static void eeepc_rfkill_notify(acpi_handle handle, u32 event, void *data)
if (event != ACPI_NOTIFY_BUS_CHECK)
return;

- eeepc_rfkill_hotplug(eeepc);
+ /*
+ * We can't call directly eeepc_rfkill_hotplug because most
+ * of the time WMBC is still being executed and not reetrant.
+ * There is currently no way to tell ACPICA that we want this
+ * method to be serialized, we schedule a eeepc_rfkill_hotplug
+ * call later, in a safer context.
+ */
+ queue_work(eeepc->hotplug_workqueue, &eeepc->hotplug_work);
}

static int eeepc_register_rfkill_notifier(struct eeepc_wmi *eeepc,
@@ -508,6 +522,14 @@ static struct hotplug_slot_ops eeepc_hotplug_slot_ops = {
.get_power_status = eeepc_get_adapter_status,
};

+static void eeepc_hotplug_work(struct work_struct *work)
+{
+ struct eeepc_wmi *eeepc;
+
+ eeepc = container_of(work, struct eeepc_wmi, hotplug_work);
+ eeepc_rfkill_hotplug(eeepc);
+}
+
static int eeepc_setup_pci_hotplug(struct eeepc_wmi *eeepc)
{
int ret = -ENOMEM;
@@ -518,6 +540,13 @@ static int eeepc_setup_pci_hotplug(struct eeepc_wmi *eeepc)
return -ENODEV;
}

+ eeepc->hotplug_workqueue =
+ create_singlethread_workqueue("hotplug_workqueue");
+ if (!eeepc->hotplug_workqueue)
+ goto error_workqueue;
+
+ INIT_WORK(&eeepc->hotplug_work, eeepc_hotplug_work);
+
eeepc->hotplug_slot = kzalloc(sizeof(struct hotplug_slot), GFP_KERNEL);
if (!eeepc->hotplug_slot)
goto error_slot;
@@ -547,6 +576,8 @@ error_info:
kfree(eeepc->hotplug_slot);
eeepc->hotplug_slot = NULL;
error_slot:
+ destroy_workqueue(eeepc->hotplug_workqueue);
+error_workqueue:
return ret;
}

@@ -575,6 +606,34 @@ static void eeepc_rfkill_query(struct rfkill *rfkill, void *data)
rfkill_set_sw_state(rfkill, !(retval & 0x1));
}

+static int eeepc_rfkill_wlan_set(void *data, bool blocked)
+{
+ struct eeepc_wmi *eeepc = data;
+ int ret;
+
+ /*
+ * This handler is enabled only if hotplug is enabled.
+ * In this case, the eeepc_wmi_set_devstate() will
+ * trigger a wmi notification and we need to wait
+ * this call to finish before being able to call
+ * any wmi method
+ */
+ mutex_lock(&eeepc->wmi_lock);
+ ret = eeepc_rfkill_set((void *)(long)EEEPC_WMI_DEVID_WLAN, blocked);
+ mutex_unlock(&eeepc->wmi_lock);
+ return ret;
+}
+
+static void eeepc_rfkill_wlan_query(struct rfkill *rfkill, void *data)
+{
+ eeepc_rfkill_query(rfkill, (void *)(long)EEEPC_WMI_DEVID_WLAN);
+}
+
+static const struct rfkill_ops eeepc_rfkill_wlan_ops = {
+ .set_block = eeepc_rfkill_wlan_set,
+ .query = eeepc_rfkill_wlan_query,
+};
+
static const struct rfkill_ops eeepc_rfkill_ops = {
.set_block = eeepc_rfkill_set,
.query = eeepc_rfkill_query,
@@ -603,8 +662,12 @@ static int eeepc_new_rfkill(struct eeepc_wmi *eeepc,
if (!retval || retval == 0x00060000)
return -ENODEV;

- *rfkill = rfkill_alloc(name, &eeepc->platform_device->dev, type,
- &eeepc_rfkill_ops, (void *)(long)dev_id);
+ if (dev_id == EEEPC_WMI_DEVID_WLAN && eeepc->hotplug_wireless)
+ *rfkill = rfkill_alloc(name, &eeepc->platform_device->dev, type,
+ &eeepc_rfkill_wlan_ops, eeepc);
+ else
+ *rfkill = rfkill_alloc(name, &eeepc->platform_device->dev, type,
+ &eeepc_rfkill_ops, (void *)(long)dev_id);

if (!*rfkill)
return -EINVAL;
@@ -636,6 +699,8 @@ static void eeepc_wmi_rfkill_exit(struct eeepc_wmi *eeepc)
eeepc_rfkill_hotplug(eeepc);
if (eeepc->hotplug_slot)
pci_hp_deregister(eeepc->hotplug_slot);
+ if (eeepc->hotplug_workqueue)
+ destroy_workqueue(eeepc->hotplug_workqueue);

if (eeepc->bluetooth_rfkill) {
rfkill_unregister(eeepc->bluetooth_rfkill);
@@ -654,6 +719,7 @@ static int eeepc_wmi_rfkill_init(struct eeepc_wmi *eeepc)
int result = 0;

mutex_init(&eeepc->hotplug_lock);
+ mutex_init(&eeepc->wmi_lock);

result = eeepc_new_rfkill(eeepc, &eeepc->wlan_rfkill,
"eeepc-wlan", RFKILL_TYPE_WLAN,
--
1.7.4.rc3

2011-02-07 19:39:25

by Matthew Garrett

[permalink] [raw]
Subject: Re: [PATCH v2 00/18] eeepc-wmi updates

I've applied all of these to -next, but I'd like to see some feedback
from Dmitry on the new camera keys if possible.

--
Matthew Garrett | [email protected]

2011-02-07 19:40:14

by Matthew Garrett

[permalink] [raw]
Subject: Re: [PATCH v2 00/18] eeepc-wmi updates

...which is, of course, in a different patchset. Oops!

--
Matthew Garrett | [email protected]