[PATCH] dell-laptop: defer dell_rfkill_update to worker thread
Stefan Bader
stefan.bader at canonical.com
Mon Apr 12 14:20:42 UTC 2010
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