* [RFC 1/5] Revert "mac80211: cleanup suspend/resume on mesh mode"
2013-09-13 10:36 [RFC 0/5] mac80211/iwlwifi: quiesce before restart hw Stanislaw Gruszka
@ 2013-09-13 10:36 ` Stanislaw Gruszka
2013-09-13 10:36 ` [RFC 2/5] Revert "mac80211: cleanup suspend/resume on ibss mode" Stanislaw Gruszka
` (4 subsequent siblings)
5 siblings, 0 replies; 10+ messages in thread
From: Stanislaw Gruszka @ 2013-09-13 10:36 UTC (permalink / raw)
To: ilw; +Cc: linux-wireless
This reverts commit 690205f18fd069898c70d743f498ba42798e5c4e.
---
net/mac80211/ieee80211_i.h | 2 ++
net/mac80211/mesh.c | 57 ++++++++++++++++++++++++++++++++++++++++++++--
net/mac80211/mesh.h | 12 ++++++++++
net/mac80211/mesh_plink.c | 27 +++++++++++++++++++++-
net/mac80211/sta_info.h | 2 ++
5 files changed, 97 insertions(+), 3 deletions(-)
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index b618651..4b7ef89 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -543,6 +543,8 @@ struct ieee80211_if_mesh {
struct timer_list mesh_path_timer;
struct timer_list mesh_path_root_timer;
+ unsigned long timers_running;
+
unsigned long wrkq_flags;
unsigned long mbss_changed;
diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c
index 707ac61..e131293 100644
--- a/net/mac80211/mesh.c
+++ b/net/mac80211/mesh.c
@@ -13,6 +13,10 @@
#include "ieee80211_i.h"
#include "mesh.h"
+#define TMR_RUNNING_HK 0
+#define TMR_RUNNING_MP 1
+#define TMR_RUNNING_MPR 2
+
static int mesh_allocated;
static struct kmem_cache *rm_cache;
@@ -46,6 +50,11 @@ static void ieee80211_mesh_housekeeping_timer(unsigned long data)
set_bit(MESH_WORK_HOUSEKEEPING, &ifmsh->wrkq_flags);
+ if (local->quiescing) {
+ set_bit(TMR_RUNNING_HK, &ifmsh->timers_running);
+ return;
+ }
+
ieee80211_queue_work(&local->hw, &sdata->work);
}
@@ -472,8 +481,15 @@ static void ieee80211_mesh_path_timer(unsigned long data)
{
struct ieee80211_sub_if_data *sdata =
(struct ieee80211_sub_if_data *) data;
+ struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
+ struct ieee80211_local *local = sdata->local;
- ieee80211_queue_work(&sdata->local->hw, &sdata->work);
+ if (local->quiescing) {
+ set_bit(TMR_RUNNING_MP, &ifmsh->timers_running);
+ return;
+ }
+
+ ieee80211_queue_work(&local->hw, &sdata->work);
}
static void ieee80211_mesh_path_root_timer(unsigned long data)
@@ -481,10 +497,16 @@ static void ieee80211_mesh_path_root_timer(unsigned long data)
struct ieee80211_sub_if_data *sdata =
(struct ieee80211_sub_if_data *) data;
struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
+ struct ieee80211_local *local = sdata->local;
set_bit(MESH_WORK_ROOT, &ifmsh->wrkq_flags);
- ieee80211_queue_work(&sdata->local->hw, &sdata->work);
+ if (local->quiescing) {
+ set_bit(TMR_RUNNING_MPR, &ifmsh->timers_running);
+ return;
+ }
+
+ ieee80211_queue_work(&local->hw, &sdata->work);
}
void ieee80211_mesh_root_setup(struct ieee80211_if_mesh *ifmsh)
@@ -602,6 +624,35 @@ static void ieee80211_mesh_rootpath(struct ieee80211_sub_if_data *sdata)
round_jiffies(TU_TO_EXP_TIME(interval)));
}
+#ifdef CONFIG_PM
+void ieee80211_mesh_quiesce(struct ieee80211_sub_if_data *sdata)
+{
+ struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
+
+ /* use atomic bitops in case all timers fire at the same time */
+
+ if (del_timer_sync(&ifmsh->housekeeping_timer))
+ set_bit(TMR_RUNNING_HK, &ifmsh->timers_running);
+ if (del_timer_sync(&ifmsh->mesh_path_timer))
+ set_bit(TMR_RUNNING_MP, &ifmsh->timers_running);
+ if (del_timer_sync(&ifmsh->mesh_path_root_timer))
+ set_bit(TMR_RUNNING_MPR, &ifmsh->timers_running);
+}
+
+void ieee80211_mesh_restart(struct ieee80211_sub_if_data *sdata)
+{
+ struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
+
+ if (test_and_clear_bit(TMR_RUNNING_HK, &ifmsh->timers_running))
+ add_timer(&ifmsh->housekeeping_timer);
+ if (test_and_clear_bit(TMR_RUNNING_MP, &ifmsh->timers_running))
+ add_timer(&ifmsh->mesh_path_timer);
+ if (test_and_clear_bit(TMR_RUNNING_MPR, &ifmsh->timers_running))
+ add_timer(&ifmsh->mesh_path_root_timer);
+ ieee80211_mesh_root_setup(ifmsh);
+}
+#endif
+
static int
ieee80211_mesh_build_beacon(struct ieee80211_if_mesh *ifmsh)
{
@@ -810,6 +861,8 @@ void ieee80211_stop_mesh(struct ieee80211_sub_if_data *sdata)
local->fif_other_bss--;
atomic_dec(&local->iff_allmultis);
ieee80211_configure_filter(local);
+
+ sdata->u.mesh.timers_running = 0;
}
static void
diff --git a/net/mac80211/mesh.h b/net/mac80211/mesh.h
index 2bc7fd2..6fd6ed6 100644
--- a/net/mac80211/mesh.h
+++ b/net/mac80211/mesh.h
@@ -315,6 +315,8 @@ void mesh_path_timer(unsigned long data);
void mesh_path_flush_by_nexthop(struct sta_info *sta);
void mesh_path_discard_frame(struct ieee80211_sub_if_data *sdata,
struct sk_buff *skb);
+void mesh_path_quiesce(struct ieee80211_sub_if_data *sdata);
+void mesh_path_restart(struct ieee80211_sub_if_data *sdata);
void mesh_path_tx_root_frame(struct ieee80211_sub_if_data *sdata);
bool mesh_action_is_path_sel(struct ieee80211_mgmt *mgmt);
@@ -359,12 +361,22 @@ static inline bool mesh_path_sel_is_hwmp(struct ieee80211_sub_if_data *sdata)
void ieee80211_mesh_notify_scan_completed(struct ieee80211_local *local);
+void ieee80211_mesh_quiesce(struct ieee80211_sub_if_data *sdata);
+void ieee80211_mesh_restart(struct ieee80211_sub_if_data *sdata);
+void mesh_plink_quiesce(struct sta_info *sta);
+void mesh_plink_restart(struct sta_info *sta);
void mesh_path_flush_by_iface(struct ieee80211_sub_if_data *sdata);
void mesh_sync_adjust_tbtt(struct ieee80211_sub_if_data *sdata);
void ieee80211s_stop(void);
#else
static inline void
ieee80211_mesh_notify_scan_completed(struct ieee80211_local *local) {}
+static inline void ieee80211_mesh_quiesce(struct ieee80211_sub_if_data *sdata)
+{}
+static inline void ieee80211_mesh_restart(struct ieee80211_sub_if_data *sdata)
+{}
+static inline void mesh_plink_quiesce(struct sta_info *sta) {}
+static inline void mesh_plink_restart(struct sta_info *sta) {}
static inline bool mesh_path_sel_is_hwmp(struct ieee80211_sub_if_data *sdata)
{ return false; }
static inline void mesh_path_flush_by_iface(struct ieee80211_sub_if_data *sdata)
diff --git a/net/mac80211/mesh_plink.c b/net/mac80211/mesh_plink.c
index 6b65d50..2b18cc6 100644
--- a/net/mac80211/mesh_plink.c
+++ b/net/mac80211/mesh_plink.c
@@ -540,8 +540,10 @@ static void mesh_plink_timer(unsigned long data)
*/
sta = (struct sta_info *) data;
- if (sta->sdata->local->quiescing)
+ if (sta->sdata->local->quiescing) {
+ sta->plink_timer_was_running = true;
return;
+ }
spin_lock_bh(&sta->lock);
if (sta->ignore_plink_timer) {
@@ -602,6 +604,29 @@ static void mesh_plink_timer(unsigned long data)
}
}
+#ifdef CONFIG_PM
+void mesh_plink_quiesce(struct sta_info *sta)
+{
+ if (!ieee80211_vif_is_mesh(&sta->sdata->vif))
+ return;
+
+ /* no kernel mesh sta timers have been initialized */
+ if (sta->sdata->u.mesh.security != IEEE80211_MESH_SEC_NONE)
+ return;
+
+ if (del_timer_sync(&sta->plink_timer))
+ sta->plink_timer_was_running = true;
+}
+
+void mesh_plink_restart(struct sta_info *sta)
+{
+ if (sta->plink_timer_was_running) {
+ add_timer(&sta->plink_timer);
+ sta->plink_timer_was_running = false;
+ }
+}
+#endif
+
static inline void mesh_plink_timer_set(struct sta_info *sta, int timeout)
{
sta->plink_timer.expires = jiffies + (HZ * timeout / 1000);
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h
index 4208dbd..3e750c7 100644
--- a/net/mac80211/sta_info.h
+++ b/net/mac80211/sta_info.h
@@ -282,6 +282,7 @@ struct sta_ampdu_mlme {
* @plink_state: peer link state
* @plink_timeout: timeout of peer link
* @plink_timer: peer link watch timer
+ * @plink_timer_was_running: used by suspend/resume to restore timers
* @t_offset: timing offset relative to this host
* @t_offset_setpoint: reference timing offset of this sta to be used when
* calculating clockdrift
@@ -388,6 +389,7 @@ struct sta_info {
__le16 reason;
u8 plink_retries;
bool ignore_plink_timer;
+ bool plink_timer_was_running;
enum nl80211_plink_state plink_state;
u32 plink_timeout;
struct timer_list plink_timer;
--
1.8.3.1
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [RFC 2/5] Revert "mac80211: cleanup suspend/resume on ibss mode"
2013-09-13 10:36 [RFC 0/5] mac80211/iwlwifi: quiesce before restart hw Stanislaw Gruszka
2013-09-13 10:36 ` [RFC 1/5] Revert "mac80211: cleanup suspend/resume on mesh mode" Stanislaw Gruszka
@ 2013-09-13 10:36 ` Stanislaw Gruszka
2013-09-13 10:36 ` [RFC 3/5] Revert "mac80211: cleanup suspend/resume on managed mode" Stanislaw Gruszka
` (3 subsequent siblings)
5 siblings, 0 replies; 10+ messages in thread
From: Stanislaw Gruszka @ 2013-09-13 10:36 UTC (permalink / raw)
To: ilw; +Cc: linux-wireless
This reverts commit a61829437e68c8b2036cf5005ed0e875451c9120.
---
net/mac80211/ibss.c | 29 ++++++++++++++++++++++++++++-
net/mac80211/ieee80211_i.h | 4 ++++
2 files changed, 32 insertions(+), 1 deletion(-)
diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c
index a12afe7..91d1b29 100644
--- a/net/mac80211/ibss.c
+++ b/net/mac80211/ibss.c
@@ -1155,9 +1155,36 @@ static void ieee80211_ibss_timer(unsigned long data)
{
struct ieee80211_sub_if_data *sdata =
(struct ieee80211_sub_if_data *) data;
+ struct ieee80211_if_ibss *ifibss = &sdata->u.ibss;
+ struct ieee80211_local *local = sdata->local;
- ieee80211_queue_work(&sdata->local->hw, &sdata->work);
+ if (local->quiescing) {
+ ifibss->timer_running = true;
+ return;
+ }
+
+ ieee80211_queue_work(&local->hw, &sdata->work);
+}
+
+#ifdef CONFIG_PM
+void ieee80211_ibss_quiesce(struct ieee80211_sub_if_data *sdata)
+{
+ struct ieee80211_if_ibss *ifibss = &sdata->u.ibss;
+
+ if (del_timer_sync(&ifibss->timer))
+ ifibss->timer_running = true;
+}
+
+void ieee80211_ibss_restart(struct ieee80211_sub_if_data *sdata)
+{
+ struct ieee80211_if_ibss *ifibss = &sdata->u.ibss;
+
+ if (ifibss->timer_running) {
+ add_timer(&ifibss->timer);
+ ifibss->timer_running = false;
+ }
}
+#endif
void ieee80211_ibss_setup_sdata(struct ieee80211_sub_if_data *sdata)
{
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 4b7ef89..96ac8f8 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -492,6 +492,8 @@ struct ieee80211_if_ibss {
u32 basic_rates;
+ bool timer_running;
+
bool fixed_bssid;
bool fixed_channel;
bool privacy;
@@ -1329,6 +1331,8 @@ void ieee80211_ibss_rx_no_sta(struct ieee80211_sub_if_data *sdata,
int ieee80211_ibss_join(struct ieee80211_sub_if_data *sdata,
struct cfg80211_ibss_params *params);
int ieee80211_ibss_leave(struct ieee80211_sub_if_data *sdata);
+void ieee80211_ibss_quiesce(struct ieee80211_sub_if_data *sdata);
+void ieee80211_ibss_restart(struct ieee80211_sub_if_data *sdata);
void ieee80211_ibss_work(struct ieee80211_sub_if_data *sdata);
void ieee80211_ibss_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
struct sk_buff *skb);
--
1.8.3.1
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [RFC 3/5] Revert "mac80211: cleanup suspend/resume on managed mode"
2013-09-13 10:36 [RFC 0/5] mac80211/iwlwifi: quiesce before restart hw Stanislaw Gruszka
2013-09-13 10:36 ` [RFC 1/5] Revert "mac80211: cleanup suspend/resume on mesh mode" Stanislaw Gruszka
2013-09-13 10:36 ` [RFC 2/5] Revert "mac80211: cleanup suspend/resume on ibss mode" Stanislaw Gruszka
@ 2013-09-13 10:36 ` Stanislaw Gruszka
2013-09-13 10:36 ` [RFC 4/5] mac80211: add generic quiesce procedure Stanislaw Gruszka
` (2 subsequent siblings)
5 siblings, 0 replies; 10+ messages in thread
From: Stanislaw Gruszka @ 2013-09-13 10:36 UTC (permalink / raw)
To: ilw; +Cc: linux-wireless
This reverts commit 9b7d72c1041ec5b20b24af487a98f71d8ff1555e.
Conflicts:
net/mac80211/ieee80211_i.h
net/mac80211/mlme.c
---
net/mac80211/ieee80211_i.h | 3 +++
net/mac80211/mlme.c | 63 ++++++++++++++++++++++++++++++++++++++++++++--
2 files changed, 64 insertions(+), 2 deletions(-)
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 96ac8f8..c5878af 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -402,6 +402,7 @@ struct ieee80211_if_managed {
u16 aid;
+ unsigned long timers_running; /* used for quiesce/restart */
bool powersave; /* powersave requested for this iface */
bool broken_ap; /* AP is broken -- turn off powersave */
bool have_beacon;
@@ -1313,6 +1314,8 @@ void ieee80211_recalc_ps_vif(struct ieee80211_sub_if_data *sdata);
int ieee80211_max_network_latency(struct notifier_block *nb,
unsigned long data, void *dummy);
int ieee80211_set_arp_filter(struct ieee80211_sub_if_data *sdata);
+void ieee80211_sta_quiesce(struct ieee80211_sub_if_data *sdata);
+void ieee80211_sta_restart(struct ieee80211_sub_if_data *sdata);
void ieee80211_sta_work(struct ieee80211_sub_if_data *sdata);
void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
struct sk_buff *skb);
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index 86e4ad5..b308855 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -92,6 +92,9 @@ MODULE_PARM_DESC(probe_wait_ms,
*/
#define IEEE80211_SIGNAL_AVE_MIN_COUNT 4
+#define TMR_RUNNING_TIMER 0
+#define TMR_RUNNING_CHANSW 1
+
/*
* We can have multiple work items (and connection probing)
* scheduling this timer, but we need to take care to only
@@ -988,8 +991,14 @@ static void ieee80211_chswitch_timer(unsigned long data)
{
struct ieee80211_sub_if_data *sdata =
(struct ieee80211_sub_if_data *) data;
+ struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
+
+ if (sdata->local->quiescing) {
+ set_bit(TMR_RUNNING_CHANSW, &ifmgd->timers_running);
+ return;
+ }
- ieee80211_queue_work(&sdata->local->hw, &sdata->u.mgd.chswitch_work);
+ ieee80211_queue_work(&sdata->local->hw, &ifmgd->chswitch_work);
}
static void
@@ -1922,6 +1931,8 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
del_timer_sync(&sdata->u.mgd.timer);
del_timer_sync(&sdata->u.mgd.chswitch_timer);
+ sdata->u.mgd.timers_running = 0;
+
sdata->vif.bss_conf.dtim_period = 0;
sdata->vif.bss_conf.beacon_rate = NULL;
@@ -3315,8 +3326,15 @@ static void ieee80211_sta_timer(unsigned long data)
{
struct ieee80211_sub_if_data *sdata =
(struct ieee80211_sub_if_data *) data;
+ struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
+ struct ieee80211_local *local = sdata->local;
+
+ if (local->quiescing) {
+ set_bit(TMR_RUNNING_TIMER, &ifmgd->timers_running);
+ return;
+ }
- ieee80211_queue_work(&sdata->local->hw, &sdata->work);
+ ieee80211_queue_work(&local->hw, &sdata->work);
}
static void ieee80211_sta_connection_lost(struct ieee80211_sub_if_data *sdata,
@@ -3661,6 +3679,37 @@ static void ieee80211_restart_sta_timer(struct ieee80211_sub_if_data *sdata)
}
#ifdef CONFIG_PM
+void ieee80211_sta_quiesce(struct ieee80211_sub_if_data *sdata)
+{
+ struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
+
+ /*
+ * Stop timers before deleting work items, as timers
+ * could race and re-add the work-items. They will be
+ * re-established on connection.
+ */
+ del_timer_sync(&ifmgd->conn_mon_timer);
+ del_timer_sync(&ifmgd->bcn_mon_timer);
+
+ /*
+ * we need to use atomic bitops for the running bits
+ * only because both timers might fire at the same
+ * time -- the code here is properly synchronised.
+ */
+
+ cancel_work_sync(&ifmgd->request_smps_work);
+
+ cancel_work_sync(&ifmgd->monitor_work);
+ cancel_work_sync(&ifmgd->beacon_connection_loss_work);
+ cancel_work_sync(&ifmgd->csa_connection_drop_work);
+ if (del_timer_sync(&ifmgd->timer))
+ set_bit(TMR_RUNNING_TIMER, &ifmgd->timers_running);
+
+ if (del_timer_sync(&ifmgd->chswitch_timer))
+ set_bit(TMR_RUNNING_CHANSW, &ifmgd->timers_running);
+ cancel_work_sync(&ifmgd->chswitch_work);
+}
+
void ieee80211_sta_restart(struct ieee80211_sub_if_data *sdata)
{
struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
@@ -3682,6 +3731,16 @@ void ieee80211_sta_restart(struct ieee80211_sub_if_data *sdata)
return;
}
sdata_unlock(sdata);
+
+ if (test_and_clear_bit(TMR_RUNNING_TIMER, &ifmgd->timers_running))
+ add_timer(&ifmgd->timer);
+ if (test_and_clear_bit(TMR_RUNNING_CHANSW, &ifmgd->timers_running))
+ add_timer(&ifmgd->chswitch_timer);
+ ieee80211_sta_reset_beacon_monitor(sdata);
+
+ mutex_lock(&sdata->local->mtx);
+ ieee80211_restart_sta_timer(sdata);
+ mutex_unlock(&sdata->local->mtx);
}
#endif
--
1.8.3.1
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [RFC 4/5] mac80211: add generic quiesce procedure
2013-09-13 10:36 [RFC 0/5] mac80211/iwlwifi: quiesce before restart hw Stanislaw Gruszka
` (2 preceding siblings ...)
2013-09-13 10:36 ` [RFC 3/5] Revert "mac80211: cleanup suspend/resume on managed mode" Stanislaw Gruszka
@ 2013-09-13 10:36 ` Stanislaw Gruszka
2013-09-13 11:13 ` Johannes Berg
2013-09-13 10:36 ` [RFC 5/5] iwlwifi: quiesce mac80211 before fw restart Stanislaw Gruszka
2013-09-15 8:31 ` [Ilw] [RFC 0/5] mac80211/iwlwifi: quiesce before restart hw Grumbach, Emmanuel
5 siblings, 1 reply; 10+ messages in thread
From: Stanislaw Gruszka @ 2013-09-13 10:36 UTC (permalink / raw)
To: ilw; +Cc: linux-wireless
Add function ieee80211_quiesce() end export it to allow be used by
drivers. It is intended to be used before restart_hw to stop mac80211
timers/works . Reverse quiesce on ieee80211_reconfig().
Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
---
include/net/mac80211.h | 10 ++++++++++
net/mac80211/ibss.c | 2 --
net/mac80211/main.c | 33 +++++++++++++++++++++++++++++++++
net/mac80211/mesh.c | 2 --
net/mac80211/mlme.c | 2 --
net/mac80211/util.c | 19 ++++++++++++++++++-
6 files changed, 61 insertions(+), 7 deletions(-)
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index 4be8785..a428ee7 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -3054,6 +3054,16 @@ void ieee80211_unregister_hw(struct ieee80211_hw *hw);
void ieee80211_free_hw(struct ieee80211_hw *hw);
/**
+ * ieee80211_quiesce - quiesce hardware
+ *
+ * Call this function to stop pending mac80211 activities before
+ * restarting hardware by ieee80211_restart_hw().
+ *
+ * @hw: the hardware to quiesce
+ */
+void ieee80211_quiesce(struct ieee80211_hw *hw);
+
+/**
* ieee80211_restart_hw - restart hardware completely
*
* Call this function when the hardware was restarted for some reason
diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c
index 91d1b29..bf2b5a9 100644
--- a/net/mac80211/ibss.c
+++ b/net/mac80211/ibss.c
@@ -1166,7 +1166,6 @@ static void ieee80211_ibss_timer(unsigned long data)
ieee80211_queue_work(&local->hw, &sdata->work);
}
-#ifdef CONFIG_PM
void ieee80211_ibss_quiesce(struct ieee80211_sub_if_data *sdata)
{
struct ieee80211_if_ibss *ifibss = &sdata->u.ibss;
@@ -1184,7 +1183,6 @@ void ieee80211_ibss_restart(struct ieee80211_sub_if_data *sdata)
ifibss->timer_running = false;
}
}
-#endif
void ieee80211_ibss_setup_sdata(struct ieee80211_sub_if_data *sdata)
{
diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index 21d5d44..978f364 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -263,6 +263,39 @@ static void ieee80211_restart_work(struct work_struct *work)
rtnl_unlock();
}
+/* return value indicates whether the driver should be further notified */
+void ieee80211_quiesce(struct ieee80211_hw *hw)
+{
+ struct ieee80211_local *local = hw_to_local(hw);
+ struct ieee80211_sub_if_data *sdata;
+
+ local->quiescing = true;
+
+ list_for_each_entry(sdata, &local->interfaces, list) {
+ if (!ieee80211_sdata_running(sdata))
+ continue;
+
+ switch (sdata->vif.type) {
+ case NL80211_IFTYPE_STATION:
+ ieee80211_sta_quiesce(sdata);
+ break;
+ case NL80211_IFTYPE_ADHOC:
+ ieee80211_ibss_quiesce(sdata);
+ break;
+ case NL80211_IFTYPE_MESH_POINT:
+ ieee80211_mesh_quiesce(sdata);
+ break;
+ default:
+ break;
+ }
+
+ cancel_work_sync(&sdata->work);
+ }
+
+ local->quiescing = false;
+}
+EXPORT_SYMBOL(ieee80211_quiesce);
+
void ieee80211_restart_hw(struct ieee80211_hw *hw)
{
struct ieee80211_local *local = hw_to_local(hw);
diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c
index e131293..b950d8d 100644
--- a/net/mac80211/mesh.c
+++ b/net/mac80211/mesh.c
@@ -624,7 +624,6 @@ static void ieee80211_mesh_rootpath(struct ieee80211_sub_if_data *sdata)
round_jiffies(TU_TO_EXP_TIME(interval)));
}
-#ifdef CONFIG_PM
void ieee80211_mesh_quiesce(struct ieee80211_sub_if_data *sdata)
{
struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
@@ -651,7 +650,6 @@ void ieee80211_mesh_restart(struct ieee80211_sub_if_data *sdata)
add_timer(&ifmsh->mesh_path_root_timer);
ieee80211_mesh_root_setup(ifmsh);
}
-#endif
static int
ieee80211_mesh_build_beacon(struct ieee80211_if_mesh *ifmsh)
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index b308855..66cec97 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -3678,7 +3678,6 @@ static void ieee80211_restart_sta_timer(struct ieee80211_sub_if_data *sdata)
}
}
-#ifdef CONFIG_PM
void ieee80211_sta_quiesce(struct ieee80211_sub_if_data *sdata)
{
struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
@@ -3742,7 +3741,6 @@ void ieee80211_sta_restart(struct ieee80211_sub_if_data *sdata)
ieee80211_restart_sta_timer(sdata);
mutex_unlock(&sdata->local->mtx);
}
-#endif
/* interface setup */
void ieee80211_sta_setup_sdata(struct ieee80211_sub_if_data *sdata)
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index e1b34a1..ee5a0b4 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -1742,11 +1742,28 @@ int ieee80211_reconfig(struct ieee80211_local *local)
list_for_each_entry(sdata, &local->interfaces, list) {
if (!ieee80211_sdata_running(sdata))
continue;
- if (sdata->vif.type == NL80211_IFTYPE_STATION)
+
+ switch (sdata->vif.type) {
+ case NL80211_IFTYPE_STATION:
ieee80211_sta_restart(sdata);
+ break;
+ case NL80211_IFTYPE_ADHOC:
+ ieee80211_ibss_restart(sdata);
+ break;
+ case NL80211_IFTYPE_MESH_POINT:
+ ieee80211_mesh_restart(sdata);
+ break;
+ default:
+ break;
+ }
}
mod_timer(&local->sta_cleanup, jiffies + 1);
+
+ mutex_lock(&local->sta_mtx);
+ list_for_each_entry(sta, &local->sta_list, list)
+ mesh_plink_restart(sta);
+ mutex_unlock(&local->sta_mtx);
#else
WARN_ON(1);
#endif
--
1.8.3.1
^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: [RFC 4/5] mac80211: add generic quiesce procedure
2013-09-13 10:36 ` [RFC 4/5] mac80211: add generic quiesce procedure Stanislaw Gruszka
@ 2013-09-13 11:13 ` Johannes Berg
2013-09-13 11:26 ` Stanislaw Gruszka
0 siblings, 1 reply; 10+ messages in thread
From: Johannes Berg @ 2013-09-13 11:13 UTC (permalink / raw)
To: Stanislaw Gruszka; +Cc: ilw, linux-wireless
On Fri, 2013-09-13 at 12:36 +0200, Stanislaw Gruszka wrote:
> Add function ieee80211_quiesce() end export it to allow be used by
> drivers. It is intended to be used before restart_hw to stop mac80211
> timers/works . Reverse quiesce on ieee80211_reconfig().
Why can't this be done inside restart_hw()?
johannes
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [RFC 4/5] mac80211: add generic quiesce procedure
2013-09-13 11:13 ` Johannes Berg
@ 2013-09-13 11:26 ` Stanislaw Gruszka
0 siblings, 0 replies; 10+ messages in thread
From: Stanislaw Gruszka @ 2013-09-13 11:26 UTC (permalink / raw)
To: Johannes Berg; +Cc: ilw, linux-wireless
On Fri, Sep 13, 2013 at 01:13:57PM +0200, Johannes Berg wrote:
> On Fri, 2013-09-13 at 12:36 +0200, Stanislaw Gruszka wrote:
> > Add function ieee80211_quiesce() end export it to allow be used by
> > drivers. It is intended to be used before restart_hw to stop mac80211
> > timers/works . Reverse quiesce on ieee80211_reconfig().
>
> Why can't this be done inside restart_hw()?
iwlwifi stop device before call restart_hw() and we need to
quiesce before iwlwifi stop device (like done in patch 5).
Stanislaw
^ permalink raw reply [flat|nested] 10+ messages in thread
* [RFC 5/5] iwlwifi: quiesce mac80211 before fw restart
2013-09-13 10:36 [RFC 0/5] mac80211/iwlwifi: quiesce before restart hw Stanislaw Gruszka
` (3 preceding siblings ...)
2013-09-13 10:36 ` [RFC 4/5] mac80211: add generic quiesce procedure Stanislaw Gruszka
@ 2013-09-13 10:36 ` Stanislaw Gruszka
2013-09-15 8:31 ` [Ilw] [RFC 0/5] mac80211/iwlwifi: quiesce before restart hw Grumbach, Emmanuel
5 siblings, 0 replies; 10+ messages in thread
From: Stanislaw Gruszka @ 2013-09-13 10:36 UTC (permalink / raw)
To: ilw; +Cc: linux-wireless
Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
---
drivers/net/wireless/iwlwifi/dvm/mac80211.c | 1 +
drivers/net/wireless/iwlwifi/dvm/main.c | 4 +++-
2 files changed, 4 insertions(+), 1 deletion(-)
diff --git a/drivers/net/wireless/iwlwifi/dvm/mac80211.c b/drivers/net/wireless/iwlwifi/dvm/mac80211.c
index cae4d31..e819e5b 100644
--- a/drivers/net/wireless/iwlwifi/dvm/mac80211.c
+++ b/drivers/net/wireless/iwlwifi/dvm/mac80211.c
@@ -393,6 +393,7 @@ static int iwlagn_mac_suspend(struct ieee80211_hw *hw,
error:
priv->wowlan = false;
+ ieee80211_quiesce(priv->hw);
iwlagn_prepare_restart(priv);
ieee80211_restart_hw(priv->hw);
out:
diff --git a/drivers/net/wireless/iwlwifi/dvm/main.c b/drivers/net/wireless/iwlwifi/dvm/main.c
index 7aad766..2e0fbea 100644
--- a/drivers/net/wireless/iwlwifi/dvm/main.c
+++ b/drivers/net/wireless/iwlwifi/dvm/main.c
@@ -975,10 +975,12 @@ static void iwl_bg_restart(struct work_struct *data)
return;
if (test_and_clear_bit(STATUS_FW_ERROR, &priv->status)) {
+ iwl_cancel_deferred_work(priv);
+ if (priv->mac80211_registered)
+ ieee80211_quiesce(priv->hw);
mutex_lock(&priv->mutex);
iwlagn_prepare_restart(priv);
mutex_unlock(&priv->mutex);
- iwl_cancel_deferred_work(priv);
if (priv->mac80211_registered)
ieee80211_restart_hw(priv->hw);
else
--
1.8.3.1
^ permalink raw reply related [flat|nested] 10+ messages in thread
* RE: [Ilw] [RFC 0/5] mac80211/iwlwifi: quiesce before restart hw
2013-09-13 10:36 [RFC 0/5] mac80211/iwlwifi: quiesce before restart hw Stanislaw Gruszka
` (4 preceding siblings ...)
2013-09-13 10:36 ` [RFC 5/5] iwlwifi: quiesce mac80211 before fw restart Stanislaw Gruszka
@ 2013-09-15 8:31 ` Grumbach, Emmanuel
2013-09-16 14:10 ` Stanislaw Gruszka
5 siblings, 1 reply; 10+ messages in thread
From: Grumbach, Emmanuel @ 2013-09-15 8:31 UTC (permalink / raw)
To: Stanislaw Gruszka, ilw@linux.intel.com; +Cc: linux-wireless@vger.kernel.org
> Here is continuation of short discussion I started here:
> http://marc.info/?l=linux-wireless&m=137724899704012&w=2
>
> I made patches which do quiesce and that can be used by iwlwifi restart
> procedure to avoid calling iwlwifi methods by mac80211 while firmware is not
> alive.
>
> But honestly, I'm not happy with that work. It does not fix root of the
> problem (microcode errors/hangs) and seems to be just to much
> complication to avoid warnings, which are consequence of firmware
> malfunction. So I just prefer to remove WARN_ONCE(trans->state !=
> IWL_TRANS_FW_ALIVE) and replace it by ordinary IWL_WARN(), which does
> not generate auto bug reports.
>
> Regarding firmware problems debugging, perhaps ftrace can be used for
> that. iwlwifi has already tracing capabilities. Allow to gather log using trace-
> cmd and call tracing_off() when firmware error will happen, perhaps will
> allow to debug firmware problems efficiently.
> If you think that's right we could add WARN_ONCE on firmware error to have
> automatic bug reports. Then we could ask user for the trace to debug and
> solve the issue. Would that work for you?
>
Yes - definitely. We have enough debug information in place in other places. Patch is coming (will go through regular tunnel).
BTW - I guess a dump_stack doesn't trigger the abrt, does it?
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [Ilw] [RFC 0/5] mac80211/iwlwifi: quiesce before restart hw
2013-09-15 8:31 ` [Ilw] [RFC 0/5] mac80211/iwlwifi: quiesce before restart hw Grumbach, Emmanuel
@ 2013-09-16 14:10 ` Stanislaw Gruszka
0 siblings, 0 replies; 10+ messages in thread
From: Stanislaw Gruszka @ 2013-09-16 14:10 UTC (permalink / raw)
To: Grumbach, Emmanuel; +Cc: ilw@linux.intel.com, linux-wireless@vger.kernel.org
On Sun, Sep 15, 2013 at 08:31:34AM +0000, Grumbach, Emmanuel wrote:
> BTW - I guess a dump_stack doesn't trigger the abrt, does it?
No, dump_stack does not trigger abrt, WARN* or BUG_ON (from process
context) is required for that.
Thanks
Stanislaw
^ permalink raw reply [flat|nested] 10+ messages in thread