linux-wireless.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [RFC 0/5] mac80211/iwlwifi: quiesce before restart hw
@ 2013-09-13 10:36 Stanislaw Gruszka
  2013-09-13 10:36 ` [RFC 1/5] Revert "mac80211: cleanup suspend/resume on mesh mode" Stanislaw Gruszka
                   ` (5 more replies)
  0 siblings, 6 replies; 10+ messages in thread
From: Stanislaw Gruszka @ 2013-09-13 10:36 UTC (permalink / raw)
  To: ilw; +Cc: linux-wireless

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?

Stanislaw Gruszka (5):
  Revert "mac80211: cleanup suspend/resume on mesh mode"
  Revert "mac80211: cleanup suspend/resume on ibss mode"
  Revert "mac80211: cleanup suspend/resume on managed mode"
  mac80211: add generic quiesce procedure
  iwlwifi: quiesce mac80211 before fw restart

 drivers/net/wireless/iwlwifi/dvm/mac80211.c |  1 +
 drivers/net/wireless/iwlwifi/dvm/main.c     |  4 +-
 include/net/mac80211.h                      | 10 +++++
 net/mac80211/ibss.c                         | 27 +++++++++++-
 net/mac80211/ieee80211_i.h                  |  9 ++++
 net/mac80211/main.c                         | 33 +++++++++++++++
 net/mac80211/mesh.c                         | 55 +++++++++++++++++++++++-
 net/mac80211/mesh.h                         | 12 ++++++
 net/mac80211/mesh_plink.c                   | 27 +++++++++++-
 net/mac80211/mlme.c                         | 65 +++++++++++++++++++++++++++--
 net/mac80211/sta_info.h                     |  2 +
 net/mac80211/util.c                         | 19 ++++++++-
 12 files changed, 254 insertions(+), 10 deletions(-)

-- 
1.8.3.1


^ permalink raw reply	[flat|nested] 10+ messages in thread

* [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

* [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: [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

* 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

end of thread, other threads:[~2013-09-16 14:12 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
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 ` [RFC 3/5] Revert "mac80211: cleanup suspend/resume on managed mode" Stanislaw Gruszka
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
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
2013-09-16 14:10   ` Stanislaw Gruszka

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).