d80211: make sleeping in hw->config possible
Subsystems (2)
PATCH 1/1 d80211: make sleeping in hw->config possible
Hi John,
Please apply this to wireless-dev.
--
This patch makes sleeping in the hw->config callback possible by removing the only atomic caller. The atomic caller was a timer and is replaced by a workqueue.
In general, allowing to sleep in the config callback is a good thing. bcm43xx must be able to sleep here, as it is required to lock a mutex.
But there are other good reasons to sleep here. We might want to sleep for a grace period on channel switch, for example.
net/d80211/ieee80211.c +1 -2
@@ -4327,8 +4327,7 @@del_timer_sync (&local->rate_limit_timer);if (local->stat_time)del_timer_sync (&local->stat_timer); -if (local->scan_timer.data) -del_timer_sync (&local->scan_timer); +cancel_rearming_delayed_work (&local->scan_work);ieee80211_rx_bss_list_deinit (dev);rtnl_lock ();
net/d80211/ieee80211_i.h +2 -1
@@ -17,6 +17,7 @@#include <linux/list.h> #include <linux/netdevice.h> #include <linux/skbuff.h> +#include <linux/workqueue.h> #include "ieee80211_key.h" #include "sta_info.h"
@@ -407,7 +408,7 @@int scan_channel_idx;enum {SCAN_SET_CHANNEL ,SCAN_SEND_PROBE } scan_state;unsigned long last_scan_completed; -struct timer_list scan_timer; +struct work_struct scan_work;int scan_oper_channel;int scan_oper_channel_val;int scan_oper_power_level;
net/d80211/ieee80211_iface.c +2 -2
@@ -271,8 +271,8 @@case IEEE80211_IF_TYPE_STA :case IEEE80211_IF_TYPE_IBSS :del_timer_sync (&sdata->u.sta.timer); -if (local->scan_timer.data == (unsigned long ) sdata->dev) -del_timer_sync (&local->scan_timer); +if (local->scan_work.data == sdata->dev) +cancel_rearming_delayed_work (&local->scan_work);kfree (sdata->u.sta.extra_ie); sdata->u.sta.extra_ie =NULL ;kfree (sdata->u.sta.assocreq_ies);
net/d80211/ieee80211_sta.c +14 -18
@@ -2422,15 +2422,16 @@ } -static void ieee80211_sta_scan_timer (unsigned long ptr) +static void ieee80211_sta_scan_work (void *_data) { -struct net_device *dev = (struct net_device *) ptr; +struct net_device *dev = _data;struct ieee80211_local *local = dev->ieee80211_ptr;struct ieee80211_sub_if_data *sdata =IEEE80211_DEV_TO_SUB_IF (dev);struct ieee80211_hw_modes *mode;struct ieee80211_channel *chan;int skip;union iwreq_data wrqu; +unsigned long next_delay =0 ;if (!local->sta_scanning)return ;
@@ -2498,29 +2499,27 @@ local->scan_channel_idx =0 ; } -if (skip) { - local->scan_timer.expires = jiffies; +if (skip)break ; - } - local->scan_timer.expires = jiffies +IEEE80211_PROBE_DELAY ; + next_delay =IEEE80211_PROBE_DELAY ; local->scan_state =SCAN_SEND_PROBE ;break ;case SCAN_SEND_PROBE :if (ieee80211_active_scan (local)) {ieee80211_send_probe_req (dev,NULL , local->scan_ssid, local->scan_ssid_len); - local->scan_timer.expires = - jiffies +IEEE80211_CHANNEL_TIME ; - }else { - local->scan_timer.expires = - jiffies +IEEE80211_PASSIVE_CHANNEL_TIME ; - } + next_delay =IEEE80211_CHANNEL_TIME ; + }else + next_delay =IEEE80211_PASSIVE_CHANNEL_TIME ; local->scan_state =SCAN_SET_CHANNEL ;break ; } -add_timer (&local->scan_timer); +if (next_delay) +schedule_delayed_work (&local->scan_work, next_delay); +else +schedule_work (&local->scan_work); }
@@ -2569,11 +2568,8 @@ local->scan_state =SCAN_SET_CHANNEL ; local->scan_hw_mode_idx =0 ; local->scan_channel_idx =0 ; -init_timer (&local->scan_timer); - local->scan_timer.data = (unsigned long ) dev; - local->scan_timer.function = ieee80211_sta_scan_timer; - local->scan_timer.expires = jiffies +1 ; -add_timer (&local->scan_timer); +INIT_WORK (&local->scan_work, ieee80211_sta_scan_work, dev); +schedule_work (&local->scan_work);return 0 ; }
Signature · 1 line
Greetings Michael.
Hi,
Quoted 8 lines
Please apply this to wireless-dev.
--
This patch makes sleeping in the
hw->configcallback possible by removing the only atomic caller. The atomic caller was a timer and is replaced by a workqueue.
Quoted 5 lines
In general, allowing to sleep in the config callback is a good thing. bcm43xx must be able to sleep here, as it is required to lock a mutex.
But there are other good reasons to sleep here. We might want to sleep for a grace period on channel switch, for example.
Excellent work.
Sleeping in hw->config is a much desired feature for rt2x00 as well, this is especially beneficial for the USB drivers who always need sleeping.
Ivo
net/d80211/ieee80211.c line 4333
Quoted 13 lines · you
===================================================================
net/d80211/ieee80211.c +1
-2@@ -4327,8 +4327,7 @@del_timer_sync (&local->rate_limit_timer);if (local->stat_time)del_timer_sync (&local->stat_timer); -if (local->scan_timer.data) -del_timer_sync (&local->scan_timer); +cancel_rearming_delayed_work (&local->scan_work);ieee80211_rx_bss_list_deinit (dev);rtnl_lock ();
There seems to be a problem. It sometimes loops inside of cancel_rearming_delayed_work forever. So I tried to fix it like this:
if (local->scan_work.data) cancel_rearming_delayed_work(&local->scan_work);
This fixes the case where we don't scan (have no STA), so don't initialize the work struct.
But it still loops infinite, sometimes.
Any suggestions?
Signature · 1 line
Greetings Michael.