From 2b190e76def5233c542f6025b4a133b1d4bd1a37 Mon Sep 17 00:00:00 2001 From: Roel Kluin Date: Sat, 17 Jan 2009 15:51:27 +0100 Subject: panasonic-laptop: fix X[ ARRAY_SIZE(X) ] Ensure pcc->keymap[ ARRAY_SIZE(pcc->keymap) ] does not occur. Signed-off-by: Roel Kluin Signed-off-by: Len Brown --- drivers/platform/x86/panasonic-laptop.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/platform') diff --git a/drivers/platform/x86/panasonic-laptop.c b/drivers/platform/x86/panasonic-laptop.c index f30db367c82..c47a44dcb70 100644 --- a/drivers/platform/x86/panasonic-laptop.c +++ b/drivers/platform/x86/panasonic-laptop.c @@ -507,7 +507,7 @@ static void acpi_pcc_generate_keyinput(struct pcc_acpi *pcc) hkey_num = result & 0xf; - if (hkey_num < 0 || hkey_num > ARRAY_SIZE(pcc->keymap)) { + if (hkey_num < 0 || hkey_num >= ARRAY_SIZE(pcc->keymap)) { ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "hotkey number out of range: %d\n", hkey_num)); -- cgit v1.2.3 From a9df80c5094ed2bac94f4a0d085651f44d549854 Mon Sep 17 00:00:00 2001 From: Corentin Chary Date: Tue, 20 Jan 2009 16:17:40 +0100 Subject: eeepc-laptop: split eeepc_backlight_exit() eeepc_backlight_exit() was doing rfkill and input stuff, which is a nonsense. This patch add two specific exit functions, one for input and one for rfkill. Signed-off-by: Corentin Chary Signed-off-by: Len Brown --- drivers/platform/x86/eeepc-laptop.c | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) (limited to 'drivers/platform') diff --git a/drivers/platform/x86/eeepc-laptop.c b/drivers/platform/x86/eeepc-laptop.c index 9d93cb971e5..66d611b225f 100644 --- a/drivers/platform/x86/eeepc-laptop.c +++ b/drivers/platform/x86/eeepc-laptop.c @@ -737,13 +737,21 @@ static void eeepc_backlight_exit(void) { if (eeepc_backlight_device) backlight_device_unregister(eeepc_backlight_device); - if (ehotk->inputdev) - input_unregister_device(ehotk->inputdev); + eeepc_backlight_device = NULL; +} + +static void eeepc_rfkill_exit(void) +{ if (ehotk->eeepc_wlan_rfkill) rfkill_unregister(ehotk->eeepc_wlan_rfkill); if (ehotk->eeepc_bluetooth_rfkill) rfkill_unregister(ehotk->eeepc_bluetooth_rfkill); - eeepc_backlight_device = NULL; +} + +static void eeepc_input_exit(void) +{ + if (ehotk->inputdev) + input_unregister_device(ehotk->inputdev); } static void eeepc_hwmon_exit(void) @@ -762,6 +770,8 @@ static void eeepc_hwmon_exit(void) static void __exit eeepc_laptop_exit(void) { eeepc_backlight_exit(); + eeepc_rfkill_exit(); + eeepc_input_exit(); eeepc_hwmon_exit(); acpi_bus_unregister_driver(&eeepc_hotk_driver); sysfs_remove_group(&platform_device->dev.kobj, @@ -865,6 +875,8 @@ fail_platform_driver: fail_hwmon: eeepc_backlight_exit(); fail_backlight: + eeepc_input_exit(); + eeepc_rfkill_exit(); return result; } -- cgit v1.2.3 From 1021e2119eb33a990a2b9ff1410805dd9bdf7997 Mon Sep 17 00:00:00 2001 From: Corentin Chary Date: Tue, 20 Jan 2009 16:17:41 +0100 Subject: asus_acpi: Add R1F support Add R1F support Signed-off-by: Corentin Chary Signed-off-by: Len Brown --- drivers/platform/x86/asus_acpi.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) (limited to 'drivers/platform') diff --git a/drivers/platform/x86/asus_acpi.c b/drivers/platform/x86/asus_acpi.c index 1e74988c7b2..d63f26e666a 100644 --- a/drivers/platform/x86/asus_acpi.c +++ b/drivers/platform/x86/asus_acpi.c @@ -143,6 +143,7 @@ struct asus_hotk { S1300N, S5200N*/ A4S, /* Z81sp */ F3Sa, /* (Centrino) */ + R1F, END_MODEL } model; /* Models currently supported */ u16 event_count[128]; /* Count for each event TODO make this better */ @@ -420,7 +421,18 @@ static struct model_data model_conf[END_MODEL] = { .display_get = "\\ADVG", .display_set = "SDSP", }, - + { + .name = "R1F", + .mt_bt_switch = "BLED", + .mt_mled = "MLED", + .mt_wled = "WLED", + .mt_lcd_switch = "\\Q10", + .lcd_status = "\\GP06", + .brightness_set = "SPLV", + .brightness_get = "GPLV", + .display_set = "SDSP", + .display_get = "\\INFB" + } }; /* procdir we use */ @@ -1165,6 +1177,8 @@ static int asus_model_match(char *model) return W3V; else if (strncmp(model, "W5A", 3) == 0) return W5A; + else if (strncmp(model, "R1F", 3) == 0) + return R1F; else if (strncmp(model, "A4S", 3) == 0) return A4S; else if (strncmp(model, "F3Sa", 4) == 0) -- cgit v1.2.3 From 2a7dc0d8c60325e9bf820900bf919430e5a419ab Mon Sep 17 00:00:00 2001 From: Corentin Chary Date: Tue, 20 Jan 2009 16:17:42 +0100 Subject: asus-laptop: use generic netlink interface To be prepared for /proc/acpi/event removal we export events also through generic netlink interface. Signed-off-by: Corentin Chary Signed-off-by: Len Brown --- drivers/platform/x86/asus-laptop.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers/platform') diff --git a/drivers/platform/x86/asus-laptop.c b/drivers/platform/x86/asus-laptop.c index 8fb8b359104..1b7a28c1da7 100644 --- a/drivers/platform/x86/asus-laptop.c +++ b/drivers/platform/x86/asus-laptop.c @@ -738,8 +738,9 @@ static void asus_hotk_notify(acpi_handle handle, u32 event, void *data) lcd_blank(FB_BLANK_POWERDOWN); } - acpi_bus_generate_proc_event(hotk->device, event, - hotk->event_count[event % 128]++); + acpi_bus_generate_netlink_event(hotk->device->pnp.device_class, + dev_name(&hotk->device->dev), event, + hotk->event_count[event % 128]++); return; } -- cgit v1.2.3 From 034ce90a8d1051deaeb31bae7f26ff1440a5b988 Mon Sep 17 00:00:00 2001 From: Corentin Chary Date: Tue, 20 Jan 2009 16:17:43 +0100 Subject: asus-laptop: hotkeys via the generic input interface This patch is based on eeepc-laptop.c and the patchs from Nicolas Trangez and Daniel Nascimento (mainly for the keymap). Signed-off-by: Corentin Chary Signed-off-by: Len Brown --- drivers/platform/x86/asus-laptop.c | 155 ++++++++++++++++++++++++++++++++++++- 1 file changed, 154 insertions(+), 1 deletion(-) (limited to 'drivers/platform') diff --git a/drivers/platform/x86/asus-laptop.c b/drivers/platform/x86/asus-laptop.c index 1b7a28c1da7..53dbfb42062 100644 --- a/drivers/platform/x86/asus-laptop.c +++ b/drivers/platform/x86/asus-laptop.c @@ -46,6 +46,7 @@ #include #include #include +#include #define ASUS_LAPTOP_VERSION "0.42" @@ -181,6 +182,8 @@ struct asus_hotk { u8 light_level; //light sensor level u8 light_switch; //light sensor switch value u16 event_count[128]; //count for each event TODO make this better + struct input_dev *inputdev; + u16 *keycode_map; }; /* @@ -250,6 +253,37 @@ ASUS_LED(rled, "record"); ASUS_LED(pled, "phone"); ASUS_LED(gled, "gaming"); +struct key_entry { + char type; + u8 code; + u16 keycode; +}; + +enum { KE_KEY, KE_END }; + +static struct key_entry asus_keymap[] = { + {KE_KEY, 0x30, KEY_VOLUMEUP}, + {KE_KEY, 0x31, KEY_VOLUMEDOWN}, + {KE_KEY, 0x32, KEY_MUTE}, + {KE_KEY, 0x33, KEY_SWITCHVIDEOMODE}, + {KE_KEY, 0x34, KEY_SWITCHVIDEOMODE}, + {KE_KEY, 0x40, KEY_PREVIOUSSONG}, + {KE_KEY, 0x41, KEY_NEXTSONG}, + {KE_KEY, 0x43, KEY_STOP}, + {KE_KEY, 0x45, KEY_PLAYPAUSE}, + {KE_KEY, 0x50, KEY_EMAIL}, + {KE_KEY, 0x51, KEY_WWW}, + {KE_KEY, 0x5C, BTN_EXTRA}, /* Performance */ + {KE_KEY, 0x5D, KEY_WLAN}, + {KE_KEY, 0x61, KEY_SWITCHVIDEOMODE}, + {KE_KEY, 0x6B, BTN_TOUCH}, /* Lock Mouse */ + {KE_KEY, 0x82, KEY_CAMERA}, + {KE_KEY, 0x8A, KEY_TV}, + {KE_KEY, 0x95, KEY_MEDIA}, + {KE_KEY, 0x99, KEY_PHONE}, + {KE_END, 0}, +}; + /* * This function evaluates an ACPI method, given an int as parameter, the * method is searched within the scope of the handle, can be NULL. The output @@ -720,8 +754,68 @@ static ssize_t store_gps(struct device *dev, struct device_attribute *attr, return store_status(buf, count, NULL, GPS_ON); } +/* + * Hotkey functions + */ +static struct key_entry *asus_get_entry_by_scancode(int code) +{ + struct key_entry *key; + + for (key = asus_keymap; key->type != KE_END; key++) + if (code == key->code) + return key; + + return NULL; +} + +static struct key_entry *asus_get_entry_by_keycode(int code) +{ + struct key_entry *key; + + for (key = asus_keymap; key->type != KE_END; key++) + if (code == key->keycode && key->type == KE_KEY) + return key; + + return NULL; +} + +static int asus_getkeycode(struct input_dev *dev, int scancode, int *keycode) +{ + struct key_entry *key = asus_get_entry_by_scancode(scancode); + + if (key && key->type == KE_KEY) { + *keycode = key->keycode; + return 0; + } + + return -EINVAL; +} + +static int asus_setkeycode(struct input_dev *dev, int scancode, int keycode) +{ + struct key_entry *key; + int old_keycode; + + if (keycode < 0 || keycode > KEY_MAX) + return -EINVAL; + + key = asus_get_entry_by_scancode(scancode); + if (key && key->type == KE_KEY) { + old_keycode = key->keycode; + key->keycode = keycode; + set_bit(keycode, dev->keybit); + if (!asus_get_entry_by_keycode(old_keycode)) + clear_bit(old_keycode, dev->keybit); + return 0; + } + + return -EINVAL; +} + static void asus_hotk_notify(acpi_handle handle, u32 event, void *data) { + static struct key_entry *key; + /* TODO Find a better way to handle events count. */ if (!hotk) return; @@ -742,7 +836,20 @@ static void asus_hotk_notify(acpi_handle handle, u32 event, void *data) dev_name(&hotk->device->dev), event, hotk->event_count[event % 128]++); - return; + if (hotk->inputdev) { + key = asus_get_entry_by_scancode(event); + if (!key) + return ; + + switch (key->type) { + case KE_KEY: + input_report_key(hotk->inputdev, key->keycode, 1); + input_sync(hotk->inputdev); + input_report_key(hotk->inputdev, key->keycode, 0); + input_sync(hotk->inputdev); + break; + } + } } #define ASUS_CREATE_DEVICE_ATTR(_name) \ @@ -960,6 +1067,38 @@ static int asus_hotk_get_info(void) return AE_OK; } +static int asus_input_init(void) +{ + const struct key_entry *key; + int result; + + hotk->inputdev = input_allocate_device(); + if (!hotk->inputdev) { + printk(ASUS_INFO "Unable to allocate input device\n"); + return 0; + } + hotk->inputdev->name = "Asus Laptop extra buttons"; + hotk->inputdev->phys = ASUS_HOTK_FILE "/input0"; + hotk->inputdev->id.bustype = BUS_HOST; + hotk->inputdev->getkeycode = asus_getkeycode; + hotk->inputdev->setkeycode = asus_setkeycode; + + for (key = asus_keymap; key->type != KE_END; key++) { + switch (key->type) { + case KE_KEY: + set_bit(EV_KEY, hotk->inputdev->evbit); + set_bit(key->keycode, hotk->inputdev->keybit); + break; + } + } + result = input_register_device(hotk->inputdev); + if (result) { + printk(ASUS_INFO "Unable to register input device\n"); + input_free_device(hotk->inputdev); + } + return result; +} + static int asus_hotk_check(void) { int result = 0; @@ -1092,10 +1231,17 @@ static void asus_led_exit(void) ASUS_LED_UNREGISTER(gled); } +static void asus_input_exit(void) +{ + if (hotk->inputdev) + input_unregister_device(hotk->inputdev); +} + static void __exit asus_laptop_exit(void) { asus_backlight_exit(); asus_led_exit(); + asus_input_exit(); acpi_bus_unregister_driver(&asus_hotk_driver); sysfs_remove_group(&asuspf_device->dev.kobj, &asuspf_attribute_group); @@ -1217,6 +1363,10 @@ static int __init asus_laptop_init(void) printk(ASUS_INFO "Brightness ignored, must be controlled by " "ACPI video driver\n"); + result = asus_input_init(); + if (result) + goto fail_input; + result = asus_led_init(dev); if (result) goto fail_led; @@ -1256,6 +1406,9 @@ static int __init asus_laptop_init(void) asus_led_exit(); fail_led: + asus_input_exit(); + + fail_input: asus_backlight_exit(); fail_backlight: -- cgit v1.2.3 From 12d6f35b0ff1f446d465e95e9a2fe187263479ef Mon Sep 17 00:00:00 2001 From: Corentin Chary Date: Tue, 20 Jan 2009 16:17:44 +0100 Subject: asus-laptop: update Kconfig for input layer Update Kconfig, now asus-laptop use the input layer. Signed-off-by: Corentin Chary Signed-off-by: Len Brown --- drivers/platform/x86/Kconfig | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/platform') diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig index 1a266d4ab5f..94363115a42 100644 --- a/drivers/platform/x86/Kconfig +++ b/drivers/platform/x86/Kconfig @@ -42,6 +42,7 @@ config ASUS_LAPTOP depends on LEDS_CLASS depends on NEW_LEDS depends on BACKLIGHT_CLASS_DEVICE + depends on INPUT ---help--- This is the new Linux driver for Asus laptops. It may also support some MEDION, JVC or VICTOR laptops. It makes all the extra buttons generate -- cgit v1.2.3 From ed6f44215374d94c35cbe98b582d004b9a3f5fbe Mon Sep 17 00:00:00 2001 From: Corentin Chary Date: Tue, 20 Jan 2009 16:17:45 +0100 Subject: asus-laptop: fix label indentation Fix the label indentation Signed-off-by: Corentin Chary Signed-off-by: Len Brown --- drivers/platform/x86/asus-laptop.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'drivers/platform') diff --git a/drivers/platform/x86/asus-laptop.c b/drivers/platform/x86/asus-laptop.c index 53dbfb42062..56af6cf385b 100644 --- a/drivers/platform/x86/asus-laptop.c +++ b/drivers/platform/x86/asus-laptop.c @@ -1184,7 +1184,7 @@ static int asus_hotk_add(struct acpi_device *device) /* GPS is on by default */ write_status(NULL, 1, GPS_ON); - end: +end: if (result) { kfree(hotk->name); kfree(hotk); @@ -1393,25 +1393,25 @@ static int __init asus_laptop_init(void) return 0; - fail_sysfs: +fail_sysfs: platform_device_del(asuspf_device); - fail_platform_device2: +fail_platform_device2: platform_device_put(asuspf_device); - fail_platform_device1: +fail_platform_device1: platform_driver_unregister(&asuspf_driver); - fail_platform_driver: +fail_platform_driver: asus_led_exit(); - fail_led: +fail_led: asus_input_exit(); - fail_input: +fail_input: asus_backlight_exit(); - fail_backlight: +fail_backlight: return result; } -- cgit v1.2.3 From b5f6f26550700445dcc125bbf75b9104e779d353 Mon Sep 17 00:00:00 2001 From: Matthew Garrett Date: Tue, 20 Jan 2009 16:17:46 +0100 Subject: eeepc-laptop: Add support for extended hotkeys Newer Eees have extra hotkeys above the function keys. This patch adds support for sending them through the input layer. Signed-off-by: Matthew Garrett Signed-off-by: Corentin Chary Signed-off-by: Len Brown --- drivers/platform/x86/eeepc-laptop.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers/platform') diff --git a/drivers/platform/x86/eeepc-laptop.c b/drivers/platform/x86/eeepc-laptop.c index 66d611b225f..d153871fd5a 100644 --- a/drivers/platform/x86/eeepc-laptop.c +++ b/drivers/platform/x86/eeepc-laptop.c @@ -161,6 +161,10 @@ static struct key_entry eeepc_keymap[] = { {KE_KEY, 0x13, KEY_MUTE }, {KE_KEY, 0x14, KEY_VOLUMEDOWN }, {KE_KEY, 0x15, KEY_VOLUMEUP }, + {KE_KEY, 0x1a, KEY_COFFEE }, + {KE_KEY, 0x1b, KEY_ZOOM }, + {KE_KEY, 0x1c, KEY_PROG2 }, + {KE_KEY, 0x1d, KEY_PROG3 }, {KE_KEY, 0x30, KEY_SWITCHVIDEOMODE }, {KE_KEY, 0x31, KEY_SWITCHVIDEOMODE }, {KE_KEY, 0x32, KEY_SWITCHVIDEOMODE }, -- cgit v1.2.3 From c9ddf8fede1271bde0a512fa94f77c4cb1ef4040 Mon Sep 17 00:00:00 2001 From: Matthew Garrett Date: Tue, 20 Jan 2009 16:17:47 +0100 Subject: eeepc-laptop: Check return values from rfkill_register Error out if rfkill registration fails, and also set the default system state appropriately on boot Signed-off-by: Matthew Garrett Signed-off-by: Corentin Chary Signed-off-by: Len Brown --- drivers/platform/x86/eeepc-laptop.c | 51 +++++++++++++++++++++++++++---------- 1 file changed, 37 insertions(+), 14 deletions(-) (limited to 'drivers/platform') diff --git a/drivers/platform/x86/eeepc-laptop.c b/drivers/platform/x86/eeepc-laptop.c index d153871fd5a..21e5206ed28 100644 --- a/drivers/platform/x86/eeepc-laptop.c +++ b/drivers/platform/x86/eeepc-laptop.c @@ -562,7 +562,7 @@ static int eeepc_hotk_add(struct acpi_device *device) ehotk->device = device; result = eeepc_hotk_check(); if (result) - goto end; + goto ehotk_fail; status = acpi_install_notify_handler(ehotk->handle, ACPI_SYSTEM_NOTIFY, eeepc_hotk_notify, ehotk); if (ACPI_FAILURE(status)) @@ -573,18 +573,25 @@ static int eeepc_hotk_add(struct acpi_device *device) RFKILL_TYPE_WLAN); if (!ehotk->eeepc_wlan_rfkill) - goto end; + goto wlan_fail; ehotk->eeepc_wlan_rfkill->name = "eeepc-wlan"; ehotk->eeepc_wlan_rfkill->toggle_radio = eeepc_wlan_rfkill_set; ehotk->eeepc_wlan_rfkill->get_state = eeepc_wlan_rfkill_state; - if (get_acpi(CM_ASL_WLAN) == 1) + if (get_acpi(CM_ASL_WLAN) == 1) { ehotk->eeepc_wlan_rfkill->state = RFKILL_STATE_UNBLOCKED; - else + rfkill_set_default(RFKILL_TYPE_WLAN, + RFKILL_STATE_UNBLOCKED); + } else { ehotk->eeepc_wlan_rfkill->state = RFKILL_STATE_SOFT_BLOCKED; - rfkill_register(ehotk->eeepc_wlan_rfkill); + rfkill_set_default(RFKILL_TYPE_WLAN, + RFKILL_STATE_SOFT_BLOCKED); + } + result = rfkill_register(ehotk->eeepc_wlan_rfkill); + if (result) + goto wlan_fail; } if (get_acpi(CM_ASL_BLUETOOTH) != -1) { @@ -592,27 +599,43 @@ static int eeepc_hotk_add(struct acpi_device *device) rfkill_allocate(&device->dev, RFKILL_TYPE_BLUETOOTH); if (!ehotk->eeepc_bluetooth_rfkill) - goto end; + goto bluetooth_fail; ehotk->eeepc_bluetooth_rfkill->name = "eeepc-bluetooth"; ehotk->eeepc_bluetooth_rfkill->toggle_radio = eeepc_bluetooth_rfkill_set; ehotk->eeepc_bluetooth_rfkill->get_state = eeepc_bluetooth_rfkill_state; - if (get_acpi(CM_ASL_BLUETOOTH) == 1) + if (get_acpi(CM_ASL_BLUETOOTH) == 1) { ehotk->eeepc_bluetooth_rfkill->state = RFKILL_STATE_UNBLOCKED; - else + rfkill_set_default(RFKILL_TYPE_BLUETOOTH, + RFKILL_STATE_UNBLOCKED); + } else { ehotk->eeepc_bluetooth_rfkill->state = RFKILL_STATE_SOFT_BLOCKED; - rfkill_register(ehotk->eeepc_bluetooth_rfkill); - } + rfkill_set_default(RFKILL_TYPE_BLUETOOTH, + RFKILL_STATE_SOFT_BLOCKED); + } - end: - if (result) { - kfree(ehotk); - ehotk = NULL; + result = rfkill_register(ehotk->eeepc_bluetooth_rfkill); + if (result) + goto bluetooth_fail; } + return 0; + + bluetooth_fail: + if (ehotk->eeepc_bluetooth_rfkill) + rfkill_free(ehotk->eeepc_bluetooth_rfkill); + rfkill_unregister(ehotk->eeepc_wlan_rfkill); + ehotk->eeepc_wlan_rfkill = NULL; + wlan_fail: + if (ehotk->eeepc_wlan_rfkill) + rfkill_free(ehotk->eeepc_wlan_rfkill); + ehotk_fail: + kfree(ehotk); + ehotk = NULL; + return result; } -- cgit v1.2.3 From 5740294ca3a9b113fe146f2826effb69ca50008d Mon Sep 17 00:00:00 2001 From: Matthew Garrett Date: Tue, 20 Jan 2009 16:17:48 +0100 Subject: eeepc-laptop: Implement rfkill hotplugging in eeepc-laptop The Eee implements rfkill 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 eeepc-laptop driver. Tested successfully on a 700, 900 and 901. Signed-off-by: Matthew Garrett Signed-off-by: Corentin Chary Signed-off-by: Len Brown --- drivers/platform/x86/eeepc-laptop.c | 83 +++++++++++++++++++++++++++++++++++++ 1 file changed, 83 insertions(+) (limited to 'drivers/platform') diff --git a/drivers/platform/x86/eeepc-laptop.c b/drivers/platform/x86/eeepc-laptop.c index 21e5206ed28..66655d2b4ce 100644 --- a/drivers/platform/x86/eeepc-laptop.c +++ b/drivers/platform/x86/eeepc-laptop.c @@ -30,6 +30,7 @@ #include #include #include +#include #define EEEPC_LAPTOP_VERSION "0.1" @@ -517,6 +518,41 @@ static void notify_brn(void) bd->props.brightness = read_brightness(bd); } +static void eeepc_rfkill_notify(acpi_handle handle, u32 event, void *data) +{ + struct pci_dev *dev; + struct pci_bus *bus = pci_find_bus(0, 1); + + if (event != ACPI_NOTIFY_BUS_CHECK) + return; + + if (!bus) { + printk(EEEPC_WARNING "Unable to find PCI bus 1?\n"); + return; + } + + if (get_acpi(CM_ASL_WLAN) == 1) { + dev = pci_get_slot(bus, 0); + if (dev) { + /* Device already present */ + pci_dev_put(dev); + return; + } + dev = pci_scan_single_device(bus, 0); + if (dev) { + pci_bus_assign_resources(bus); + if (pci_bus_add_device(dev)) + printk(EEEPC_ERR "Unable to hotplug wifi\n"); + } + } else { + dev = pci_get_slot(bus, 0); + if (dev) { + pci_remove_bus_device(dev); + pci_dev_put(dev); + } + } +} + static void eeepc_hotk_notify(acpi_handle handle, u32 event, void *data) { static struct key_entry *key; @@ -543,6 +579,45 @@ static void eeepc_hotk_notify(acpi_handle handle, u32 event, void *data) } } +static int eeepc_register_rfkill_notifier(char *node) +{ + acpi_status status = AE_OK; + 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, + NULL); + if (ACPI_FAILURE(status)) + printk(EEEPC_WARNING + "Failed to register notify on %s\n", node); + } else + return -ENODEV; + + return 0; +} + +static void eeepc_unregister_rfkill_notifier(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)) + printk(EEEPC_ERR + "Error removing rfkill notify handler %s\n", + node); + } +} + static int eeepc_hotk_add(struct acpi_device *device) { acpi_status status = AE_OK; @@ -622,6 +697,10 @@ static int eeepc_hotk_add(struct acpi_device *device) if (result) goto bluetooth_fail; } + + eeepc_register_rfkill_notifier("\\_SB.PCI0.P0P6"); + eeepc_register_rfkill_notifier("\\_SB.PCI0.P0P7"); + return 0; bluetooth_fail: @@ -649,6 +728,10 @@ static int eeepc_hotk_remove(struct acpi_device *device, int type) eeepc_hotk_notify); if (ACPI_FAILURE(status)) printk(EEEPC_ERR "Error removing notify handler\n"); + + eeepc_unregister_rfkill_notifier("\\_SB.PCI0.P0P6"); + eeepc_unregister_rfkill_notifier("\\_SB.PCI0.P0P7"); + kfree(ehotk); return 0; } -- cgit v1.2.3 From 2b25c9f01aa58d48129b2f93748dfb5d1f7ab0a2 Mon Sep 17 00:00:00 2001 From: Corentin Chary Date: Tue, 20 Jan 2009 16:17:49 +0100 Subject: eeepc-laptop: use netlink interface To be prepared for /proc/acpi/event removal we export events also through generic netlink interface. Signed-off-by: Corentin Chary Signed-off-by: Len Brown --- drivers/platform/x86/eeepc-laptop.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers/platform') diff --git a/drivers/platform/x86/eeepc-laptop.c b/drivers/platform/x86/eeepc-laptop.c index 66655d2b4ce..4348d9909bb 100644 --- a/drivers/platform/x86/eeepc-laptop.c +++ b/drivers/platform/x86/eeepc-laptop.c @@ -560,8 +560,9 @@ static void eeepc_hotk_notify(acpi_handle handle, u32 event, void *data) return; if (event >= NOTIFY_BRN_MIN && event <= NOTIFY_BRN_MAX) notify_brn(); - acpi_bus_generate_proc_event(ehotk->device, event, - ehotk->event_count[event % 128]++); + acpi_bus_generate_netlink_event(ehotk->device->pnp.device_class, + dev_name(&ehotk->device->dev), event, + ehotk->event_count[event % 128]++); if (ehotk->inputdev) { key = eepc_get_entry_by_scancode(event); if (key) { -- cgit v1.2.3 From 44f0606d52d98ff05b3b62bb694821857e36819d Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Wed, 4 Feb 2009 15:12:07 -0800 Subject: hp-wmi: fix error path in hp_wmi_bios_setup() The error-path code can call rfkill_unregister() with a pointer which does not contain the result of a call to rfkill_register(). It goes BUG(). Addresses http://bugzilla.kernel.org/show_bug.cgi?id=12560. Cc: Frans Pop Cc: Larry Finger Cc: Len Brown Acked-by: Matthew Garrett Reported-by: Helge Deller Testted-by: Helge Deller Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/platform/x86/hp-wmi.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers/platform') diff --git a/drivers/platform/x86/hp-wmi.c b/drivers/platform/x86/hp-wmi.c index de91ddab0a8..f41135f2fb2 100644 --- a/drivers/platform/x86/hp-wmi.c +++ b/drivers/platform/x86/hp-wmi.c @@ -463,9 +463,11 @@ static int __init hp_wmi_bios_setup(struct platform_device *device) return 0; register_wwan_err: - rfkill_unregister(bluetooth_rfkill); + if (bluetooth_rfkill) + rfkill_unregister(bluetooth_rfkill); register_bluetooth_error: - rfkill_unregister(wifi_rfkill); + if (wifi_rfkill) + rfkill_unregister(wifi_rfkill); add_sysfs_error: cleanup_sysfs(device); return err; -- cgit v1.2.3 From 7695fb04aca62e2d8a7ca6ede50f6211e1d71e53 Mon Sep 17 00:00:00 2001 From: Darren Salt Date: Sat, 7 Feb 2009 01:02:07 -0500 Subject: eeepc-laptop: fix oops when changing backlight brightness during eeepc-laptop init I got the following oops while changing the backlight brightness during startup. When it happens, it prevents use of the hotkeys, Fn-Fx, and the lid button. It's a clear use-before-init, as I verified by testing with an appropriately-placed "else printk". BUG: unable to handle kernel NULL pointer dereference at 00000000 *pde = 00000000 Oops: 0002 [#1] PREEMPT SMP Pid: 160, comm: kacpi_notify Not tainted (2.6.28.1-eee901 #4) 901 EIP: 0060:[] [] eeepc_hotk_notify+26/da EFLAGS: 00010246 CPU: 1 Using defaults from ksymoops -t elf32-i386 -a i386 EAX: 00000009 EBX: 00000000 ECX: 00000009 EDX: f70dbf64 ESI: 00000029 EDI: f7335188 EBP: c02112c9 ESP: f70dbf80 DS: 007b ES: 007b FS: 00d8 GS: 0000 SS: 0068 f70731e0 f73acd50 c02164ac f7335180 f70aa040 c02112e6 f733518c c012b62f f70aa044 f70aa040 c012bdba f70aa04c 00000000 c012be6e 00000000 f70bdf80 c012e198 f70dbfc4 f70dbfc4 f70aa040 c012bdba 00000000 c012e0c9 c012e091 Call Trace: [] ? acpi_ev_notify_dispatch+4c/55 [] ? acpi_os_execute_deferred+1d/25 [] ? run_workqueue+71/f1 [] ? worker_thread+0/bf [] ? worker_thread+b4/bf [] ? autoremove_wake_function+0/2b [] ? worker_thread+0/bf [] ? kthread+38/5f [] ? kthread+0/5f [] ? kernel_thread_helper+7/10 Code: 00 00 00 00 c3 83 3d 60 5c 50 c0 00 56 89 d6 53 0f 84 c4 00 00 00 8d 42 e0 83 f8 0f 77 0f 8b 1d 68 5c 50 c0 89 d8 e8 a9 fa ff ff <89> 03 8b 1d 60 5c 50 c0 89 f2 83 e2 7f 0f b7 4c 53 10 8d 41 01 Signed-off-by: Darren Salt Signed-off-by: Andrew Morton Signed-off-by: Len Brown --- drivers/platform/x86/eeepc-laptop.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/platform') diff --git a/drivers/platform/x86/eeepc-laptop.c b/drivers/platform/x86/eeepc-laptop.c index 9d93cb971e5..8fb983f5629 100644 --- a/drivers/platform/x86/eeepc-laptop.c +++ b/drivers/platform/x86/eeepc-laptop.c @@ -510,7 +510,8 @@ static int eeepc_hotk_check(void) static void notify_brn(void) { struct backlight_device *bd = eeepc_backlight_device; - bd->props.brightness = read_brightness(bd); + if (bd) + bd->props.brightness = read_brightness(bd); } static void eeepc_hotk_notify(acpi_handle handle, u32 event, void *data) -- cgit v1.2.3