From e1fbf346c7c56d6b2f9d835d297bcb088baaff3a Mon Sep 17 00:00:00 2001 From: Matthew Garrett Date: Fri, 31 Jul 2009 03:25:38 +0100 Subject: dell-laptop: Fix rfkill state queries The current code in dell-laptop is confused about the hardware rfkill state. Fix it up such that it's always reported correctly. Signed-off-by: Matthew Garrett Tested-by: Tim Gardner Signed-off-by: Len Brown --- drivers/platform/x86/dell-laptop.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/platform') diff --git a/drivers/platform/x86/dell-laptop.c b/drivers/platform/x86/dell-laptop.c index 74909c4aaee..906111152b0 100644 --- a/drivers/platform/x86/dell-laptop.c +++ b/drivers/platform/x86/dell-laptop.c @@ -197,8 +197,8 @@ static void dell_rfkill_query(struct rfkill *rfkill, void *data) dell_send_request(&buffer, 17, 11); status = buffer.output[1]; - if (status & BIT(bit)) - rfkill_set_hw_state(rfkill, !!(status & BIT(16))); + rfkill_set_sw_state(rfkill, !!(status & BIT(bit))); + rfkill_set_hw_state(rfkill, !(status & BIT(16))); } static const struct rfkill_ops dell_rfkill_ops = { -- cgit v1.2.3 From 71e9dc73cb6b1351bdd5f732cef5dbef411b3219 Mon Sep 17 00:00:00 2001 From: Alan Jenkins Date: Wed, 19 Aug 2009 15:06:47 +0100 Subject: dell-laptop: fix a use-after-free error on the failure path dell_setup_rfkill() already cleans up the rfkill devices on failure. So if it returns an error, we should not try to unregister the rfkill devices. Signed-off-by: Alan Jenkins Acked-by: Matthew Garrett Signed-off-by: Len Brown --- drivers/platform/x86/dell-laptop.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'drivers/platform') diff --git a/drivers/platform/x86/dell-laptop.c b/drivers/platform/x86/dell-laptop.c index 906111152b0..d791ef93c1f 100644 --- a/drivers/platform/x86/dell-laptop.c +++ b/drivers/platform/x86/dell-laptop.c @@ -330,7 +330,7 @@ static int __init dell_init(void) if (ret) { printk(KERN_WARNING "dell-laptop: Unable to setup rfkill\n"); - goto out; + goto fail_rfkill; } #ifdef CONFIG_ACPI @@ -358,7 +358,7 @@ static int __init dell_init(void) if (IS_ERR(dell_backlight_device)) { ret = PTR_ERR(dell_backlight_device); dell_backlight_device = NULL; - goto out; + goto fail_backlight; } dell_backlight_device->props.max_brightness = max_intensity; @@ -368,13 +368,15 @@ static int __init dell_init(void) } return 0; -out: + +fail_backlight: if (wifi_rfkill) rfkill_unregister(wifi_rfkill); if (bluetooth_rfkill) rfkill_unregister(bluetooth_rfkill); if (wwan_rfkill) rfkill_unregister(wwan_rfkill); +fail_rfkill: kfree(da_tokens); return ret; } -- cgit v1.2.3 From 4311bb230e0f7e4daa5fd5bc0cc536e2bd1eff20 Mon Sep 17 00:00:00 2001 From: Alan Jenkins Date: Wed, 19 Aug 2009 15:06:48 +0100 Subject: dell-laptop: fix rfkill memory leak on unload and failure paths rfkill_unregister() should always be followed by rfkill_destroy(). Signed-off-by: Alan Jenkins Acked-by: Matthew Garrett Signed-off-by: Len Brown --- drivers/platform/x86/dell-laptop.c | 30 ++++++++++++++++++------------ 1 file changed, 18 insertions(+), 12 deletions(-) (limited to 'drivers/platform') diff --git a/drivers/platform/x86/dell-laptop.c b/drivers/platform/x86/dell-laptop.c index d791ef93c1f..94139d530c7 100644 --- a/drivers/platform/x86/dell-laptop.c +++ b/drivers/platform/x86/dell-laptop.c @@ -268,6 +268,22 @@ err_wifi: return ret; } +static void dell_cleanup_rfkill(void) +{ + if (wifi_rfkill) { + rfkill_unregister(wifi_rfkill); + rfkill_destroy(wifi_rfkill); + } + if (bluetooth_rfkill) { + rfkill_unregister(bluetooth_rfkill); + rfkill_destroy(bluetooth_rfkill); + } + if (wwan_rfkill) { + rfkill_unregister(wwan_rfkill); + rfkill_destroy(wwan_rfkill); + } +} + static int dell_send_intensity(struct backlight_device *bd) { struct calling_interface_buffer buffer; @@ -370,12 +386,7 @@ static int __init dell_init(void) return 0; fail_backlight: - if (wifi_rfkill) - rfkill_unregister(wifi_rfkill); - if (bluetooth_rfkill) - rfkill_unregister(bluetooth_rfkill); - if (wwan_rfkill) - rfkill_unregister(wwan_rfkill); + dell_cleanup_rfkill(); fail_rfkill: kfree(da_tokens); return ret; @@ -384,12 +395,7 @@ fail_rfkill: static void __exit dell_exit(void) { backlight_device_unregister(dell_backlight_device); - if (wifi_rfkill) - rfkill_unregister(wifi_rfkill); - if (bluetooth_rfkill) - rfkill_unregister(bluetooth_rfkill); - if (wwan_rfkill) - rfkill_unregister(wwan_rfkill); + dell_cleanup_rfkill(); } module_init(dell_init); -- cgit v1.2.3 From ada3248a5d38654b33b0ae2eabe1d7e3d9a9ffce Mon Sep 17 00:00:00 2001 From: Alan Jenkins Date: Wed, 19 Aug 2009 15:06:49 +0100 Subject: dell-laptop: create a platform device as a parent for the rfkill devices etc. dell-laptop may not need to export any sysfs files, but it should still create a platform device as a parent for the rfkill and backlight devices. Otherwise sysfs will display these as "virtual" devices, with no connection to either physical hardware or the dell-laptop module. Apparently this is useful for hardware detection. Signed-off-by: Alan Jenkins Acked-by: Matthew Garrett Signed-off-by: Len Brown --- drivers/platform/x86/dell-laptop.c | 38 ++++++++++++++++++++++++++++++++++---- 1 file changed, 34 insertions(+), 4 deletions(-) (limited to 'drivers/platform') diff --git a/drivers/platform/x86/dell-laptop.c b/drivers/platform/x86/dell-laptop.c index 94139d530c7..a4ce64244f6 100644 --- a/drivers/platform/x86/dell-laptop.c +++ b/drivers/platform/x86/dell-laptop.c @@ -58,6 +58,14 @@ static int da_command_code; static int da_num_tokens; static struct calling_interface_token *da_tokens; +static struct platform_driver platform_driver = { + .driver = { + .name = "dell-laptop", + .owner = THIS_MODULE, + } +}; + +static struct platform_device *platform_device; static struct backlight_device *dell_backlight_device; static struct rfkill *wifi_rfkill; static struct rfkill *bluetooth_rfkill; @@ -217,7 +225,8 @@ static int dell_setup_rfkill(void) status = buffer.output[1]; if ((status & (1<<2|1<<8)) == (1<<2|1<<8)) { - wifi_rfkill = rfkill_alloc("dell-wifi", NULL, RFKILL_TYPE_WLAN, + wifi_rfkill = rfkill_alloc("dell-wifi", &platform_device->dev, + RFKILL_TYPE_WLAN, &dell_rfkill_ops, (void *) 1); if (!wifi_rfkill) { ret = -ENOMEM; @@ -229,7 +238,8 @@ static int dell_setup_rfkill(void) } if ((status & (1<<3|1<<9)) == (1<<3|1<<9)) { - bluetooth_rfkill = rfkill_alloc("dell-bluetooth", NULL, + bluetooth_rfkill = rfkill_alloc("dell-bluetooth", + &platform_device->dev, RFKILL_TYPE_BLUETOOTH, &dell_rfkill_ops, (void *) 2); if (!bluetooth_rfkill) { @@ -242,7 +252,9 @@ static int dell_setup_rfkill(void) } if ((status & (1<<4|1<<10)) == (1<<4|1<<10)) { - wwan_rfkill = rfkill_alloc("dell-wwan", NULL, RFKILL_TYPE_WWAN, + wwan_rfkill = rfkill_alloc("dell-wwan", + &platform_device->dev, + RFKILL_TYPE_WWAN, &dell_rfkill_ops, (void *) 3); if (!wwan_rfkill) { ret = -ENOMEM; @@ -342,6 +354,18 @@ static int __init dell_init(void) return -ENODEV; } + ret = platform_driver_register(&platform_driver); + if (ret) + goto fail_platform_driver; + platform_device = platform_device_alloc("dell-laptop", -1); + if (!platform_device) { + ret = -ENOMEM; + goto fail_platform_device1; + } + ret = platform_device_add(platform_device); + if (ret) + goto fail_platform_device2; + ret = dell_setup_rfkill(); if (ret) { @@ -368,7 +392,7 @@ static int __init dell_init(void) if (max_intensity) { dell_backlight_device = backlight_device_register( "dell_backlight", - NULL, NULL, + &platform_device->dev, NULL, &dell_ops); if (IS_ERR(dell_backlight_device)) { @@ -388,6 +412,12 @@ static int __init dell_init(void) fail_backlight: dell_cleanup_rfkill(); fail_rfkill: + platform_device_del(platform_device); +fail_platform_device2: + platform_device_put(platform_device); +fail_platform_device1: + platform_driver_unregister(&platform_driver); +fail_platform_driver: kfree(da_tokens); return ret; } -- cgit v1.2.3 From 4788df4cf44fd14847d37f88daea649f01c01017 Mon Sep 17 00:00:00 2001 From: Alan Jenkins Date: Wed, 19 Aug 2009 15:06:50 +0100 Subject: dell-laptop: add __init to init functions Signed-off-by: Alan Jenkins Acked-by: Matthew Garrett Signed-off-by: Len Brown --- drivers/platform/x86/dell-laptop.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/platform') diff --git a/drivers/platform/x86/dell-laptop.c b/drivers/platform/x86/dell-laptop.c index a4ce64244f6..3780994dc8f 100644 --- a/drivers/platform/x86/dell-laptop.c +++ b/drivers/platform/x86/dell-laptop.c @@ -82,7 +82,7 @@ static const struct dmi_system_id __initdata dell_device_table[] = { { } }; -static void parse_da_table(const struct dmi_header *dm) +static void __init parse_da_table(const struct dmi_header *dm) { /* Final token is a terminator, so we don't want to copy it */ int tokens = (dm->length-11)/sizeof(struct calling_interface_token)-1; @@ -111,7 +111,7 @@ static void parse_da_table(const struct dmi_header *dm) da_num_tokens += tokens; } -static void find_tokens(const struct dmi_header *dm, void *dummy) +static void __init find_tokens(const struct dmi_header *dm, void *dummy) { switch (dm->type) { case 0xd4: /* Indexed IO */ @@ -214,7 +214,7 @@ static const struct rfkill_ops dell_rfkill_ops = { .query = dell_rfkill_query, }; -static int dell_setup_rfkill(void) +static int __init dell_setup_rfkill(void) { struct calling_interface_buffer buffer; int status; -- cgit v1.2.3