[rt2x00-users] [PATCH] rt2x00: Fix sleep-while-atomic bug in powersaving code.

Ivo Van Doorn ivdoorn at gmail.com
Tue Nov 15 02:18:17 EST 2011


On Sat, Nov 12, 2011 at 7:10 PM, Gertjan van Wingerde
<gwingerde at gmail.com> wrote:
> The generic powersaving code that determines after reception of a frame
> whether the device should go back to sleep or whether is could stay
> awake was calling rt2x00lib_config directly from RX tasklet context.
> On a number of the devices this call can actually sleep, due to having
> to confirm that the sleeping commands have been executed successfully.
>
> Fix this by moving the call to rt2x00lib_config to a workqueue call.
>
> This fixes bug https://bugzilla.redhat.com/show_bug.cgi?id=731672
>
> Tested-by: Tomas Trnka <tomastrnka at gmx.com>
> Signed-off-by: Gertjan van Wingerde <gwingerde at gmail.com>
> Cc: <stable at vger.kernel.org>

Acked-by: Ivo van Doorn <IvDoorn at gmail.com>

> ---
>  drivers/net/wireless/rt2x00/rt2x00.h    |    1 +
>  drivers/net/wireless/rt2x00/rt2x00dev.c |   22 ++++++++++++++++++++--
>  2 files changed, 21 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h
> index 2ec5c00..99ff12d 100644
> --- a/drivers/net/wireless/rt2x00/rt2x00.h
> +++ b/drivers/net/wireless/rt2x00/rt2x00.h
> @@ -943,6 +943,7 @@ struct rt2x00_dev {
>         * Powersaving work
>         */
>        struct delayed_work autowakeup_work;
> +       struct work_struct sleep_work;
>
>        /*
>         * Data queue arrays for RX, TX, Beacon and ATIM.
> diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c
> index e1fb2a8..edd317f 100644
> --- a/drivers/net/wireless/rt2x00/rt2x00dev.c
> +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c
> @@ -465,6 +465,23 @@ static u8 *rt2x00lib_find_ie(u8 *data, unsigned int len, u8 ie)
>        return NULL;
>  }
>
> +static void rt2x00lib_sleep(struct work_struct *work)
> +{
> +       struct rt2x00_dev *rt2x00dev =
> +           container_of(work, struct rt2x00_dev, sleep_work);
> +
> +       if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags))
> +               return;
> +
> +       /*
> +        * Check again is powersaving is enabled, to prevent races from delayed
> +        * work execution.
> +        */
> +       if (!test_bit(CONFIG_POWERSAVING, &rt2x00dev->flags))
> +               rt2x00lib_config(rt2x00dev, &rt2x00dev->hw->conf,
> +                                IEEE80211_CONF_CHANGE_PS);
> +}
> +
>  static void rt2x00lib_rxdone_check_ps(struct rt2x00_dev *rt2x00dev,
>                                      struct sk_buff *skb,
>                                      struct rxdone_entry_desc *rxdesc)
> @@ -512,8 +529,7 @@ static void rt2x00lib_rxdone_check_ps(struct rt2x00_dev *rt2x00dev,
>        cam |= (tim_ie->bitmap_ctrl & 0x01);
>
>        if (!cam && !test_bit(CONFIG_POWERSAVING, &rt2x00dev->flags))
> -               rt2x00lib_config(rt2x00dev, &rt2x00dev->hw->conf,
> -                                IEEE80211_CONF_CHANGE_PS);
> +               queue_work(rt2x00dev->workqueue, &rt2x00dev->sleep_work);
>  }
>
>  static int rt2x00lib_rxdone_read_signal(struct rt2x00_dev *rt2x00dev,
> @@ -1141,6 +1157,7 @@ int rt2x00lib_probe_dev(struct rt2x00_dev *rt2x00dev)
>
>        INIT_WORK(&rt2x00dev->intf_work, rt2x00lib_intf_scheduled);
>        INIT_DELAYED_WORK(&rt2x00dev->autowakeup_work, rt2x00lib_autowakeup);
> +       INIT_WORK(&rt2x00dev->sleep_work, rt2x00lib_sleep);
>
>        /*
>         * Let the driver probe the device to detect the capabilities.
> @@ -1197,6 +1214,7 @@ void rt2x00lib_remove_dev(struct rt2x00_dev *rt2x00dev)
>         */
>        cancel_work_sync(&rt2x00dev->intf_work);
>        cancel_delayed_work_sync(&rt2x00dev->autowakeup_work);
> +       cancel_work_sync(&rt2x00dev->sleep_work);
>        if (rt2x00_is_usb(rt2x00dev)) {
>                del_timer_sync(&rt2x00dev->txstatus_timer);
>                cancel_work_sync(&rt2x00dev->rxdone_work);
> --
> 1.7.7
>
>
> _______________________________________________
> users mailing list
> users at rt2x00.serialmonkey.com
> http://rt2x00.serialmonkey.com/mailman/listinfo/users_rt2x00.serialmonkey.com
>



More information about the users mailing list