[PATCH] dell-laptop: defer dell_rfkill_update to worker thread
Chase Douglas
chase.douglas at canonical.com
Mon Apr 12 15:08:34 UTC 2010
This patch applies on top of UBUNTU SAUCE patches that are not
upstream. I don't know the status of the upstreaming of those patches,
but this should come along if/when that happens. The changes would
likely be too large for -stable, so I don't think there's much to be
gained there.
-- Chase
On Mon, Apr 12, 2010 at 7:20 AM, Stefan Bader
<stefan.bader at canonical.com> wrote:
> Am I correct in assuming, this is intended for upstreaming? Will you propose
> stable when submitting it?
> Patch looks sensible in general.
>
> -Stefan
>
> Chase Douglas wrote:
>> From: Chase Douglas <cndougla at emerald.redvoodoo.org>
>>
>> dell_rfkill_update fires an SMI, which must occur on cpu 0. Thus, if called
>> on a different cpu, the task will block. Since it's called in hard irq
>> context, we must defer this to the worker thread.
>>
>> It is potentially possible that two rfkill key events could be processed
>> before the work completes on the first. The second event is dropped with a
>> KERN_NOTICE message.
>>
>> BugLink: http://bugs.launchpad.net/bugs/555261
>>
>> Signed-off-by: Chase Douglas <chase.douglas at canonical.com>
>> ---
>> drivers/platform/x86/dell-laptop.c | 9 +++++++--
>> 1 files changed, 7 insertions(+), 2 deletions(-)
>>
>> diff --git a/drivers/platform/x86/dell-laptop.c b/drivers/platform/x86/dell-laptop.c
>> index 8bf7ac7..15d96a0 100644
>> --- a/drivers/platform/x86/dell-laptop.c
>> +++ b/drivers/platform/x86/dell-laptop.c
>> @@ -288,8 +288,10 @@ static const struct rfkill_ops dell_rfkill_ops = {
>> /*
>> * Called for each KEY_WLAN key press event. Note that a physical
>> * rf-kill switch change also causes the BIOS to emit a KEY_WLAN.
>> + *
>> + * dell_rfkill_set may block, so schedule it on a worker thread.
>> */
>> -static void dell_rfkill_update(void)
>> +static void dell_rfkill_update(struct work_struct *work)
>> {
>> hw_switch_status ^= BIT(HW_SWITCH_MASK);
>> if (wifi_rfkill && (hw_switch_status & BIT(WLAN_SWITCH_MASK))) {
>> @@ -307,6 +309,7 @@ static void dell_rfkill_update(void)
>> dell_rfkill_set((void*)3, rfkill_blocked(wwan_rfkill));
>> }
>> }
>> +DECLARE_WORK(dell_rfkill_update_work, &dell_rfkill_update);
>>
>> static int dell_setup_rfkill(void)
>> {
>> @@ -431,7 +434,9 @@ static bool dell_input_filter(struct input_handle *handle, unsigned int type,
>> unsigned int code, int value)
>> {
>> if (type == EV_KEY && code == KEY_WLAN && value == 1) {
>> - dell_rfkill_update();
>> + if (!schedule_work(&dell_rfkill_update_work))
>> + printk(KERN_NOTICE "rfkill switch handling already "
>> + "scheduled, dropping this event\n");
>> return 1;
>> }
>>
>
>
More information about the kernel-team
mailing list