[PATCH] dell-laptop: defer dell_rfkill_update to worker thread

Chase Douglas chase.douglas at canonical.com
Mon Apr 12 15:40:21 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