2009-07-21 11:14:11

by Alan Jenkins

[permalink] [raw]
Subject: [PATCH] hp-wmi: improve rfkill support

1) Add support for reading the hardware blocked state. Previously
we read a combination of the hardware and software blocked states,
reporting it as the software blocked state. This caused some
confusing behaviour.

2) The software state is persistent, mark it as such.

3) Check rfkill in the resume handler. Both the hard and soft
blocked states may change over hibernation.

Signed-off-by: Alan Jenkins <[email protected]>
Tested-by: Maciej Rutecki <[email protected]>
---

This code is the combination of two patches tested by Maciej.
There are no changes to that code, only an updated changelog.

I tested wifi on the G7000. Maciej tested wifi and bluetooth.
wwan is as yet untested; we are assuming the interface follows
the same pattern as wifi and bluetooth.

drivers/platform/x86/hp-wmi.c | 139 +++++++++++++++++++++++++----------------
1 files changed, 84 insertions(+), 55 deletions(-)

diff --git a/drivers/platform/x86/hp-wmi.c b/drivers/platform/x86/hp-wmi.c
index ca50856..adb26d3 100644
--- a/drivers/platform/x86/hp-wmi.c
+++ b/drivers/platform/x86/hp-wmi.c
@@ -51,6 +51,12 @@ MODULE_ALIAS("wmi:5FB7F034-2C63-45e9-BE91-3D44E2C707E4");
#define HPWMI_WIRELESS_QUERY 0x5
#define HPWMI_HOTKEY_QUERY 0xc

+enum hp_wmi_radio {
+ HPWMI_WIFI = 0,
+ HPWMI_BLUETOOTH = 1,
+ HPWMI_WWAN = 2,
+};
+
static int __init hp_wmi_bios_setup(struct platform_device *device);
static int __exit hp_wmi_bios_remove(struct platform_device *device);
static int hp_wmi_resume_handler(struct platform_device *device);
@@ -170,8 +176,8 @@ static int hp_wmi_tablet_state(void)

static int hp_wmi_set_block(void *data, bool blocked)
{
- unsigned long b = (unsigned long) data;
- int query = BIT(b + 8) | ((!blocked) << b);
+ enum hp_wmi_radio r = (enum hp_wmi_radio) data;
+ int query = BIT(r + 8) | ((!blocked) << r);

return hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, 1, query);
}
@@ -180,31 +186,23 @@ static const struct rfkill_ops hp_wmi_rfkill_ops = {
.set_block = hp_wmi_set_block,
};

-static bool hp_wmi_wifi_state(void)
+static bool hp_wmi_get_sw_state(enum hp_wmi_radio r)
{
int wireless = hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, 0, 0);
+ int mask = 0x200 << (r * 8);

- if (wireless & 0x100)
+ if (wireless & mask)
return false;
else
return true;
}

-static bool hp_wmi_bluetooth_state(void)
+static bool hp_wmi_get_hw_state(enum hp_wmi_radio r)
{
int wireless = hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, 0, 0);
+ int mask = 0x800 << (r * 8);

- if (wireless & 0x10000)
- return false;
- else
- return true;
-}
-
-static bool hp_wmi_wwan_state(void)
-{
- int wireless = hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, 0, 0);
-
- if (wireless & 0x1000000)
+ if (wireless & mask)
return false;
else
return true;
@@ -329,49 +327,55 @@ static void hp_wmi_notify(u32 value, void *context)
struct acpi_buffer response = { ACPI_ALLOCATE_BUFFER, NULL };
static struct key_entry *key;
union acpi_object *obj;
+ int eventcode;

wmi_get_event_data(value, &response);

obj = (union acpi_object *)response.pointer;

- if (obj && obj->type == ACPI_TYPE_BUFFER && obj->buffer.length == 8) {
- int eventcode = *((u8 *) obj->buffer.pointer);
- if (eventcode == 0x4)
- eventcode = hp_wmi_perform_query(HPWMI_HOTKEY_QUERY, 0,
- 0);
- key = hp_wmi_get_entry_by_scancode(eventcode);
- if (key) {
- switch (key->type) {
- case KE_KEY:
- input_report_key(hp_wmi_input_dev,
- key->keycode, 1);
- input_sync(hp_wmi_input_dev);
- input_report_key(hp_wmi_input_dev,
- key->keycode, 0);
- input_sync(hp_wmi_input_dev);
- break;
- }
- } else if (eventcode == 0x1) {
- input_report_switch(hp_wmi_input_dev, SW_DOCK,
- hp_wmi_dock_state());
- input_report_switch(hp_wmi_input_dev, SW_TABLET_MODE,
- hp_wmi_tablet_state());
+ if (!obj || obj->type != ACPI_TYPE_BUFFER || obj->buffer.length != 8) {
+ printk(KERN_INFO "HP WMI: Unknown response received\n");
+ return;
+ }
+
+ eventcode = *((u8 *) obj->buffer.pointer);
+ if (eventcode == 0x4)
+ eventcode = hp_wmi_perform_query(HPWMI_HOTKEY_QUERY, 0,
+ 0);
+ key = hp_wmi_get_entry_by_scancode(eventcode);
+ if (key) {
+ switch (key->type) {
+ case KE_KEY:
+ input_report_key(hp_wmi_input_dev,
+ key->keycode, 1);
+ input_sync(hp_wmi_input_dev);
+ input_report_key(hp_wmi_input_dev,
+ key->keycode, 0);
input_sync(hp_wmi_input_dev);
- } else if (eventcode == 0x5) {
- if (wifi_rfkill)
- rfkill_set_sw_state(wifi_rfkill,
- hp_wmi_wifi_state());
- if (bluetooth_rfkill)
- rfkill_set_sw_state(bluetooth_rfkill,
- hp_wmi_bluetooth_state());
- if (wwan_rfkill)
- rfkill_set_sw_state(wwan_rfkill,
- hp_wmi_wwan_state());
- } else
- printk(KERN_INFO "HP WMI: Unknown key pressed - %x\n",
- eventcode);
+ break;
+ }
+ } else if (eventcode == 0x1) {
+ input_report_switch(hp_wmi_input_dev, SW_DOCK,
+ hp_wmi_dock_state());
+ input_report_switch(hp_wmi_input_dev, SW_TABLET_MODE,
+ hp_wmi_tablet_state());
+ input_sync(hp_wmi_input_dev);
+ } else if (eventcode == 0x5) {
+ if (wifi_rfkill)
+ rfkill_set_states(wifi_rfkill,
+ hp_wmi_get_sw_state(HPWMI_WIFI),
+ hp_wmi_get_hw_state(HPWMI_WIFI));
+ if (bluetooth_rfkill)
+ rfkill_set_states(bluetooth_rfkill,
+ hp_wmi_get_sw_state(HPWMI_BLUETOOTH),
+ hp_wmi_get_hw_state(HPWMI_BLUETOOTH));
+ if (wwan_rfkill)
+ rfkill_set_states(wwan_rfkill,
+ hp_wmi_get_sw_state(HPWMI_WWAN),
+ hp_wmi_get_hw_state(HPWMI_WWAN));
} else
- printk(KERN_INFO "HP WMI: Unknown response received\n");
+ printk(KERN_INFO "HP WMI: Unknown key pressed - %x\n",
+ eventcode);
}

static int __init hp_wmi_input_setup(void)
@@ -450,7 +454,11 @@ static int __init hp_wmi_bios_setup(struct platform_device *device)
wifi_rfkill = rfkill_alloc("hp-wifi", &device->dev,
RFKILL_TYPE_WLAN,
&hp_wmi_rfkill_ops,
- (void *) 0);
+ (void *) HPWMI_WIFI);
+ rfkill_init_sw_state(wifi_rfkill,
+ hp_wmi_get_sw_state(HPWMI_WIFI));
+ rfkill_set_hw_state(wifi_rfkill,
+ hp_wmi_get_hw_state(HPWMI_WIFI));
err = rfkill_register(wifi_rfkill);
if (err)
goto register_wifi_error;
@@ -460,7 +468,11 @@ static int __init hp_wmi_bios_setup(struct platform_device *device)
bluetooth_rfkill = rfkill_alloc("hp-bluetooth", &device->dev,
RFKILL_TYPE_BLUETOOTH,
&hp_wmi_rfkill_ops,
- (void *) 1);
+ (void *) HPWMI_BLUETOOTH);
+ rfkill_init_sw_state(bluetooth_rfkill,
+ hp_wmi_get_sw_state(HPWMI_BLUETOOTH));
+ rfkill_set_hw_state(bluetooth_rfkill,
+ hp_wmi_get_hw_state(HPWMI_BLUETOOTH));
err = rfkill_register(bluetooth_rfkill);
if (err)
goto register_bluetooth_error;
@@ -470,7 +482,11 @@ static int __init hp_wmi_bios_setup(struct platform_device *device)
wwan_rfkill = rfkill_alloc("hp-wwan", &device->dev,
RFKILL_TYPE_WWAN,
&hp_wmi_rfkill_ops,
- (void *) 2);
+ (void *) HPWMI_WWAN);
+ rfkill_init_sw_state(wwan_rfkill,
+ hp_wmi_get_sw_state(HPWMI_WWAN));
+ rfkill_set_hw_state(wwan_rfkill,
+ hp_wmi_get_hw_state(HPWMI_WWAN));
err = rfkill_register(wwan_rfkill);
if (err)
goto register_wwan_err;
@@ -526,6 +542,19 @@ static int hp_wmi_resume_handler(struct platform_device *device)
hp_wmi_tablet_state());
input_sync(hp_wmi_input_dev);

+ if (wifi_rfkill)
+ rfkill_set_states(wifi_rfkill,
+ hp_wmi_get_sw_state(HPWMI_WIFI),
+ hp_wmi_get_hw_state(HPWMI_WIFI));
+ if (bluetooth_rfkill)
+ rfkill_set_states(bluetooth_rfkill,
+ hp_wmi_get_sw_state(HPWMI_BLUETOOTH),
+ hp_wmi_get_hw_state(HPWMI_BLUETOOTH));
+ if (wwan_rfkill)
+ rfkill_set_states(wwan_rfkill,
+ hp_wmi_get_sw_state(HPWMI_WWAN),
+ hp_wmi_get_hw_state(HPWMI_WWAN));
+
return 0;
}

--
1.6.3.2


2009-07-21 11:26:11

by Matthew Garrett

[permalink] [raw]
Subject: Re: [PATCH] hp-wmi: improve rfkill support

On Tue, Jul 21, 2009 at 12:14:01PM +0100, Alan Jenkins wrote:
> 1) Add support for reading the hardware blocked state. Previously
> we read a combination of the hardware and software blocked states,
> reporting it as the software blocked state. This caused some
> confusing behaviour.
>
> 2) The software state is persistent, mark it as such.
>
> 3) Check rfkill in the resume handler. Both the hard and soft
> blocked states may change over hibernation.
>
> Signed-off-by: Alan Jenkins <[email protected]>
> Tested-by: Maciej Rutecki <[email protected]>
Acked-by: Matthew Garrett <[email protected]>

--
Matthew Garrett | [email protected]

2009-07-23 15:31:48

by Maciej Rutecki

[permalink] [raw]
Subject: Re: [PATCH] hp-wmi: improve rfkill support

2009/7/21 Alan Jenkins <[email protected]>:
> 1) Add support for reading the hardware blocked state.  Previously
>   we read a combination of the hardware and software blocked states,
>   reporting it as the software blocked state.  This caused some
>   confusing behaviour.
>
> 2) The software state is persistent, mark it as such.
>
> 3) Check rfkill in the resume handler.  Both the hard and soft
>   blocked states may change over hibernation.
>
> Signed-off-by: Alan Jenkins <[email protected]>
> Tested-by: Maciej Rutecki <[email protected]>

It's this patch is added to -rc4? I one case I have strange behaviour.

Before disable by button:
root@gumis:/home/maciek/Desktop# rfkill list
2: hp-wifi: Wireless LAN
Soft blocked: no
Hard blocked: no
3: hp-bluetooth: Bluetooth
Soft blocked: no
Hard blocked: no
16: hci0: Bluetooth
Soft blocked: no
Hard blocked: no
17: phy7: Wireless LAN
Soft blocked: no
Hard blocked: no

Disable by button:
root@gumis:/home/maciek/Desktop# rfkill list
2: hp-wifi: Wireless LAN
Soft blocked: yes
Hard blocked: no
3: hp-bluetooth: Bluetooth
Soft blocked: yes
Hard blocked: no
17: phy7: Wireless LAN
Soft blocked: no
Hard blocked: yes

I do s2disk. After resume from suspend to disk (still disabled by button):
root@gumis:/home/maciek/Desktop# rfkill list
2: hp-wifi: Wireless LAN
Soft blocked: yes
Hard blocked: no
3: hp-bluetooth: Bluetooth
Soft blocked: yes
Hard blocked: no
18: phy8: Wireless LAN
Soft blocked: no
Hard blocked: yes

Try enable by button:
root@gumis:/home/maciek/Desktop# rfkill list
2: hp-wifi: Wireless LAN
Soft blocked: yes
Hard blocked: no
3: hp-bluetooth: Bluetooth
Soft blocked: yes
Hard blocked: no
18: phy8: Wireless LAN
Soft blocked: no
Hard blocked: yes

Nothing change (LED, wireless and bluetooth don't work). To enable it
I use this script rfkill.sh (I must use rfkill program):

#!/bin/sh
PROGRAM=/usr/local/sbin/rfkill
WIFI=`$PROGRAM list | grep -E 'Wireless|Bluetooth' | cut -d ':' -f 1`

for DEVICE in $WIFI; do
echo $DEVICE
$PROGRAM unblock $DEVICE
done

Then works OK:
root@gumis:/home/maciek/Desktop# ./rfkill.sh
2
3
18
root@gumis:/home/maciek/Desktop# rfkill list
2: hp-wifi: Wireless LAN
Soft blocked: no
Hard blocked: no
3: hp-bluetooth: Bluetooth
Soft blocked: no
Hard blocked: no
18: phy8: Wireless LAN
Soft blocked: no
Hard blocked: no
19: hci0: Bluetooth
Soft blocked: no
Hard blocked: no

It's normal behaviour?

--
Maciej Rutecki
http://www.maciek.unixy.pl

2009-07-23 18:27:36

by Alan Jenkins

[permalink] [raw]
Subject: Re: [PATCH] hp-wmi: improve rfkill support

Maciej Rutecki wrote:
> 2009/7/21 Alan Jenkins <[email protected]>:
>
>> 1) Add support for reading the hardware blocked state. Previously
>> we read a combination of the hardware and software blocked states,
>> reporting it as the software blocked state. This caused some
>> confusing behaviour.
>>
>> 2) The software state is persistent, mark it as such.
>>
>> 3) Check rfkill in the resume handler. Both the hard and soft
>> blocked states may change over hibernation.
>>
>> Signed-off-by: Alan Jenkins <[email protected]>
>> Tested-by: Maciej Rutecki <[email protected]>
>>
>
> It's this patch is added to -rc4?

No.
<http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Ftorvalds%2Flinux-2.6.git&a=search&h=HEAD&st=commit&s=hp-wmi>

I didn't submit it for 2.6.31 because I didn't think it fixed a regression.

> I one case I have strange behaviour.
>
> Before disable by button:
> root@gumis:/home/maciek/Desktop# rfkill list
> 2: hp-wifi: Wireless LAN
> Soft blocked: no
> Hard blocked: no
> 3: hp-bluetooth: Bluetooth
> Soft blocked: no
> Hard blocked: no
> 16: hci0: Bluetooth
> Soft blocked: no
> Hard blocked: no
> 17: phy7: Wireless LAN
> Soft blocked: no
> Hard blocked: no
>
> Disable by button:
> root@gumis:/home/maciek/Desktop# rfkill list
> 2: hp-wifi: Wireless LAN
> Soft blocked: yes
> Hard blocked: no
> 3: hp-bluetooth: Bluetooth
> Soft blocked: yes
> Hard blocked: no
> 17: phy7: Wireless LAN
> Soft blocked: no
> Hard blocked: yes
>
> I do s2disk. After resume from suspend to disk (still disabled by button):
> root@gumis:/home/maciek/Desktop# rfkill list
> 2: hp-wifi: Wireless LAN
> Soft blocked: yes
> Hard blocked: no
> 3: hp-bluetooth: Bluetooth
> Soft blocked: yes
> Hard blocked: no
> 18: phy8: Wireless LAN
> Soft blocked: no
> Hard blocked: yes
>
> Try enable by button:
> root@gumis:/home/maciek/Desktop# rfkill list
> 2: hp-wifi: Wireless LAN
> Soft blocked: yes
> Hard blocked: no
> 3: hp-bluetooth: Bluetooth
> Soft blocked: yes
> Hard blocked: no
> 18: phy8: Wireless LAN
> Soft blocked: no
> Hard blocked: yes
>
> Nothing change (LED, wireless and bluetooth don't work). To enable it
> I use this script rfkill.sh (I must use rfkill program):
>
> #!/bin/sh
> PROGRAM=/usr/local/sbin/rfkill
> WIFI=`$PROGRAM list | grep -E 'Wireless|Bluetooth' | cut -d ':' -f 1`
>
> for DEVICE in $WIFI; do
> echo $DEVICE
> $PROGRAM unblock $DEVICE
> done
>
> Then works OK:
> root@gumis:/home/maciek/Desktop# ./rfkill.sh
> 2
> 3
> 18
> root@gumis:/home/maciek/Desktop# rfkill list
> 2: hp-wifi: Wireless LAN
> Soft blocked: no
> Hard blocked: no
> 3: hp-bluetooth: Bluetooth
> Soft blocked: no
> Hard blocked: no
> 18: phy8: Wireless LAN
> Soft blocked: no
> Hard blocked: no
> 19: hci0: Bluetooth
> Soft blocked: no
> Hard blocked: no
>
> It's normal behaviour?
>

That's a bug. You're saying this is in -rc4, without applying my patch?

I think I know exactly what is happening. Apply my patch, and it will
go away :-).

I'm not sure this is a new bug though. It might be triggered by the big
rfkill rewrite, but I don't see how that could happen. Can you confirm
if this happens in 2.6.30?

Thanks
Alan

2009-07-23 19:28:22

by Frans Pop

[permalink] [raw]
Subject: Re: [PATCH] hp-wmi: improve rfkill support

Alan Jenkins wrote:
> 1) Add support for reading the hardware blocked state. Previously
> we read a combination of the hardware and software blocked states,
> reporting it as the software blocked state. This caused some
> confusing behaviour.
>
> 2) The software state is persistent, mark it as such.
>
> 3) Check rfkill in the resume handler. Both the hard and soft
> blocked states may change over hibernation.

I've added this to my local branch for .31 for my HP 2510p.
Light testing (linux only) showed no problems with .31-rc4.

One question: is it expected that pressing the hardware kill switch only
enables the block for phy0? I guess it's probably sufficient.

$ ./rfkill list # after pressing hardware switch
0: phy0: Wireless LAN
Soft blocked: no
Hard blocked: yes
1: hp-wifi: Wireless LAN
Soft blocked: no
Hard blocked: no
2: hp-bluetooth: Bluetooth
Soft blocked: no
Hard blocked: no

Looks like with bluetooth soft-blocked the wireless leds blink on wifi
network traffic, while with bluetooth unblocked it stays on permanently.

Cheers,
FJP

2009-07-23 19:36:19

by Maciej Rutecki

[permalink] [raw]
Subject: Re: [PATCH] hp-wmi: improve rfkill support

2009/7/23 Alan Jenkins <[email protected]>:

>
> That's a bug.  You're saying this is in -rc4, without applying my patch?

Yes

>
> I think I know exactly what is happening.  Apply my patch, and it will go
> away :-).

Yes. I add Your patch to -rc4 and rfkill works OK:
Enable by button:
root@gumis:/home/maciek# rfkill list
0: phy0: Wireless LAN
Soft blocked: no
Hard blocked: no
1: hci0: Bluetooth
Soft blocked: no
Hard blocked: no
2: hp-wifi: Wireless LAN
Soft blocked: no
Hard blocked: no
3: hp-bluetooth: Bluetooth
Soft blocked: no
Hard blocked: no

Disable by button:
root@gumis:/home/maciek# rfkill list
0: phy0: Wireless LAN
Soft blocked: no
Hard blocked: yes
2: hp-wifi: Wireless LAN
Soft blocked: no
Hard blocked: no
3: hp-bluetooth: Bluetooth
Soft blocked: no
Hard blocked: no

After resume from s2disk:
root@gumis:/home/maciek# rfkill list
2: hp-wifi: Wireless LAN
Soft blocked: no
Hard blocked: no
3: hp-bluetooth: Bluetooth
Soft blocked: no
Hard blocked: no
4: phy1: Wireless LAN
Soft blocked: no
Hard blocked: yes

(are some differences after and before s2disk)

Enable by button:
root@gumis:/home/maciek# rfkill list
2: hp-wifi: Wireless LAN
Soft blocked: no
Hard blocked: no
3: hp-bluetooth: Bluetooth
Soft blocked: no
Hard blocked: no
4: phy1: Wireless LAN
Soft blocked: no
Hard blocked: no
5: hci0: Bluetooth
Soft blocked: no
Hard blocked: no

And wifi/bluetooth works without manual enable. Thanks.

>
> I'm not sure this is a new bug though.  It might be triggered by the big
> rfkill rewrite, but I don't see how that could happen.  Can you confirm if
> this happens in 2.6.30?

2.6.30 works OK

>
> Thanks
> Alan
>


Regards
--
Maciej Rutecki
http://www.maciek.unixy.pl

2009-12-10 04:53:23

by Len Brown

[permalink] [raw]
Subject: Re: [PATCH] hp-wmi: improve rfkill support

applied

thanks,
Len Brown, Intel Open Source Technology Center