All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 1/3] ath10k: fix ar->rx_channel updating logic
@ 2015-06-03 10:16 ` Michal Kazior
  0 siblings, 0 replies; 8+ messages in thread
From: Michal Kazior @ 2015-06-03 10:16 UTC (permalink / raw)
  To: ath10k; +Cc: linux-wireless, Michal Kazior

Channel contexts aren't iterable until after
they've been added to the driver. The code assumed
otherwise.

This problem could result in:

 * rx_channel being NULL and forcing Rx path to go
   the slow way to get channel on QCA988X,

 * report incorrect channel when running
   multi-channel on QCA61X4 hw2.1,

 * report incorrect channel after AP channel
   switch.

Fixes: 500ff9f9389d ("ath10k: implement chanctx API")
Signed-off-by: Michal Kazior <michal.kazior@tieto.com>
---
 drivers/net/wireless/ath/ath10k/mac.c | 22 +++++++++++++++++-----
 1 file changed, 17 insertions(+), 5 deletions(-)

diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c
index f4de71721f7d..fe53b1f5e6c9 100644
--- a/drivers/net/wireless/ath/ath10k/mac.c
+++ b/drivers/net/wireless/ath/ath10k/mac.c
@@ -6144,7 +6144,10 @@ static int ath10k_ampdu_action(struct ieee80211_hw *hw,
 }
 
 static void
-ath10k_mac_update_rx_channel(struct ath10k *ar)
+ath10k_mac_update_rx_channel(struct ath10k *ar,
+			     struct ieee80211_chanctx_conf *ctx,
+			     struct ieee80211_vif_chanctx_switch *vifs,
+			     int n_vifs)
 {
 	struct cfg80211_chan_def *def = NULL;
 
@@ -6154,6 +6157,9 @@ ath10k_mac_update_rx_channel(struct ath10k *ar)
 	lockdep_assert_held(&ar->conf_mutex);
 	lockdep_assert_held(&ar->data_lock);
 
+	WARN_ON(ctx && vifs);
+	WARN_ON(vifs && n_vifs != 1);
+
 	/* FIXME: Sort of an optimization and a workaround. Peers and vifs are
 	 * on a linked list now. Doing a lookup peer -> vif -> chanctx for each
 	 * ppdu on Rx may reduce performance on low-end systems. It should be
@@ -6165,11 +6171,17 @@ ath10k_mac_update_rx_channel(struct ath10k *ar)
 	 * affected much.
 	 */
 	rcu_read_lock();
-	if (ath10k_mac_num_chanctxs(ar) == 1) {
+	if (!ctx && ath10k_mac_num_chanctxs(ar) == 1) {
 		ieee80211_iter_chan_contexts_atomic(ar->hw,
 					ath10k_mac_get_any_chandef_iter,
 					&def);
+
+		if (vifs)
+			def = &vifs[0].new_ctx->def;
+
 		ar->rx_channel = def->chan;
+	} else if (ctx && ath10k_mac_num_chanctxs(ar) == 0) {
+		ar->rx_channel = ctx->def.chan;
 	} else {
 		ar->rx_channel = NULL;
 	}
@@ -6204,7 +6216,7 @@ ath10k_mac_op_add_chanctx(struct ieee80211_hw *hw,
 
 	spin_lock_bh(&ar->data_lock);
 	ath10k_mac_chan_ctx_init(ar, arctx, ctx);
-	ath10k_mac_update_rx_channel(ar);
+	ath10k_mac_update_rx_channel(ar, ctx, NULL, 0);
 	spin_unlock_bh(&ar->data_lock);
 
 	ath10k_recalc_radar_detection(ar);
@@ -6228,7 +6240,7 @@ ath10k_mac_op_remove_chanctx(struct ieee80211_hw *hw,
 	mutex_lock(&ar->conf_mutex);
 
 	spin_lock_bh(&ar->data_lock);
-	ath10k_mac_update_rx_channel(ar);
+	ath10k_mac_update_rx_channel(ar, NULL, NULL, 0);
 	spin_unlock_bh(&ar->data_lock);
 
 	ath10k_recalc_radar_detection(ar);
@@ -6413,7 +6425,7 @@ ath10k_mac_op_switch_vif_chanctx(struct ieee80211_hw *hw,
 		 */
 		arctx_old->conf = *vifs[i].new_ctx;
 	}
-	ath10k_mac_update_rx_channel(ar);
+	ath10k_mac_update_rx_channel(ar, NULL, vifs, n_vifs);
 	spin_unlock_bh(&ar->data_lock);
 
 	/* FIXME: Reconfigure only affected vifs */
-- 
2.1.4


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

* [PATCH 1/3] ath10k: fix ar->rx_channel updating logic
@ 2015-06-03 10:16 ` Michal Kazior
  0 siblings, 0 replies; 8+ messages in thread
From: Michal Kazior @ 2015-06-03 10:16 UTC (permalink / raw)
  To: ath10k; +Cc: linux-wireless, Michal Kazior

Channel contexts aren't iterable until after
they've been added to the driver. The code assumed
otherwise.

This problem could result in:

 * rx_channel being NULL and forcing Rx path to go
   the slow way to get channel on QCA988X,

 * report incorrect channel when running
   multi-channel on QCA61X4 hw2.1,

 * report incorrect channel after AP channel
   switch.

Fixes: 500ff9f9389d ("ath10k: implement chanctx API")
Signed-off-by: Michal Kazior <michal.kazior@tieto.com>
---
 drivers/net/wireless/ath/ath10k/mac.c | 22 +++++++++++++++++-----
 1 file changed, 17 insertions(+), 5 deletions(-)

diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c
index f4de71721f7d..fe53b1f5e6c9 100644
--- a/drivers/net/wireless/ath/ath10k/mac.c
+++ b/drivers/net/wireless/ath/ath10k/mac.c
@@ -6144,7 +6144,10 @@ static int ath10k_ampdu_action(struct ieee80211_hw *hw,
 }
 
 static void
-ath10k_mac_update_rx_channel(struct ath10k *ar)
+ath10k_mac_update_rx_channel(struct ath10k *ar,
+			     struct ieee80211_chanctx_conf *ctx,
+			     struct ieee80211_vif_chanctx_switch *vifs,
+			     int n_vifs)
 {
 	struct cfg80211_chan_def *def = NULL;
 
@@ -6154,6 +6157,9 @@ ath10k_mac_update_rx_channel(struct ath10k *ar)
 	lockdep_assert_held(&ar->conf_mutex);
 	lockdep_assert_held(&ar->data_lock);
 
+	WARN_ON(ctx && vifs);
+	WARN_ON(vifs && n_vifs != 1);
+
 	/* FIXME: Sort of an optimization and a workaround. Peers and vifs are
 	 * on a linked list now. Doing a lookup peer -> vif -> chanctx for each
 	 * ppdu on Rx may reduce performance on low-end systems. It should be
@@ -6165,11 +6171,17 @@ ath10k_mac_update_rx_channel(struct ath10k *ar)
 	 * affected much.
 	 */
 	rcu_read_lock();
-	if (ath10k_mac_num_chanctxs(ar) == 1) {
+	if (!ctx && ath10k_mac_num_chanctxs(ar) == 1) {
 		ieee80211_iter_chan_contexts_atomic(ar->hw,
 					ath10k_mac_get_any_chandef_iter,
 					&def);
+
+		if (vifs)
+			def = &vifs[0].new_ctx->def;
+
 		ar->rx_channel = def->chan;
+	} else if (ctx && ath10k_mac_num_chanctxs(ar) == 0) {
+		ar->rx_channel = ctx->def.chan;
 	} else {
 		ar->rx_channel = NULL;
 	}
@@ -6204,7 +6216,7 @@ ath10k_mac_op_add_chanctx(struct ieee80211_hw *hw,
 
 	spin_lock_bh(&ar->data_lock);
 	ath10k_mac_chan_ctx_init(ar, arctx, ctx);
-	ath10k_mac_update_rx_channel(ar);
+	ath10k_mac_update_rx_channel(ar, ctx, NULL, 0);
 	spin_unlock_bh(&ar->data_lock);
 
 	ath10k_recalc_radar_detection(ar);
@@ -6228,7 +6240,7 @@ ath10k_mac_op_remove_chanctx(struct ieee80211_hw *hw,
 	mutex_lock(&ar->conf_mutex);
 
 	spin_lock_bh(&ar->data_lock);
-	ath10k_mac_update_rx_channel(ar);
+	ath10k_mac_update_rx_channel(ar, NULL, NULL, 0);
 	spin_unlock_bh(&ar->data_lock);
 
 	ath10k_recalc_radar_detection(ar);
@@ -6413,7 +6425,7 @@ ath10k_mac_op_switch_vif_chanctx(struct ieee80211_hw *hw,
 		 */
 		arctx_old->conf = *vifs[i].new_ctx;
 	}
-	ath10k_mac_update_rx_channel(ar);
+	ath10k_mac_update_rx_channel(ar, NULL, vifs, n_vifs);
 	spin_unlock_bh(&ar->data_lock);
 
 	/* FIXME: Reconfigure only affected vifs */
-- 
2.1.4


_______________________________________________
ath10k mailing list
ath10k@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/ath10k

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

* [PATCH 2/3] ath10k: remove ath10k_chanctx struct
  2015-06-03 10:16 ` Michal Kazior
@ 2015-06-03 10:16   ` Michal Kazior
  -1 siblings, 0 replies; 8+ messages in thread
From: Michal Kazior @ 2015-06-03 10:16 UTC (permalink / raw)
  To: ath10k; +Cc: linux-wireless, Michal Kazior

In practice there's no point in having a copy of
chanctx_conf.

Most of the time the channel pointer (and band
along with it) is accessed and this can't change
after a chanctx is created because switching is
done using explicit chanctx swapping via
switch_vif_chanctx().

The only thing that can change within a
chanctx_conf and is used by the driver is
radar_enabled and channel width. These are however
always accessed in adequate mac80211 callback
context which guarantees safe access to the
chanctx data.

Signed-off-by: Michal Kazior <michal.kazior@tieto.com>
---
 drivers/net/wireless/ath/ath10k/core.h |  9 ------
 drivers/net/wireless/ath/ath10k/mac.c  | 53 ++++------------------------------
 2 files changed, 6 insertions(+), 56 deletions(-)

diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h
index 45f9603a0868..78094f23c9dd 100644
--- a/drivers/net/wireless/ath/ath10k/core.h
+++ b/drivers/net/wireless/ath/ath10k/core.h
@@ -284,15 +284,6 @@ struct ath10k_sta {
 #endif
 };
 
-struct ath10k_chanctx {
-	/* Used to story copy of chanctx_conf to avoid inconsistencies. Ideally
-	 * mac80211 should allow some sort of explicit locking to guarantee
-	 * that the publicly available chanctx_conf can be accessed safely at
-	 * all times.
-	 */
-	struct ieee80211_chanctx_conf conf;
-};
-
 #define ATH10K_VDEV_SETUP_TIMEOUT_HZ (5*HZ)
 
 enum ath10k_beacon_state {
diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c
index fe53b1f5e6c9..b60369f78940 100644
--- a/drivers/net/wireless/ath/ath10k/mac.c
+++ b/drivers/net/wireless/ath/ath10k/mac.c
@@ -6188,25 +6188,11 @@ ath10k_mac_update_rx_channel(struct ath10k *ar,
 	rcu_read_unlock();
 }
 
-static void
-ath10k_mac_chan_ctx_init(struct ath10k *ar,
-			 struct ath10k_chanctx *arctx,
-			 struct ieee80211_chanctx_conf *conf)
-{
-	lockdep_assert_held(&ar->conf_mutex);
-	lockdep_assert_held(&ar->data_lock);
-
-	memset(arctx, 0, sizeof(*arctx));
-
-	arctx->conf = *conf;
-}
-
 static int
 ath10k_mac_op_add_chanctx(struct ieee80211_hw *hw,
 			  struct ieee80211_chanctx_conf *ctx)
 {
 	struct ath10k *ar = hw->priv;
-	struct ath10k_chanctx *arctx = (void *)ctx->drv_priv;
 
 	ath10k_dbg(ar, ATH10K_DBG_MAC,
 		   "mac chanctx add freq %hu width %d ptr %p\n",
@@ -6215,7 +6201,6 @@ ath10k_mac_op_add_chanctx(struct ieee80211_hw *hw,
 	mutex_lock(&ar->conf_mutex);
 
 	spin_lock_bh(&ar->data_lock);
-	ath10k_mac_chan_ctx_init(ar, arctx, ctx);
 	ath10k_mac_update_rx_channel(ar, ctx, NULL, 0);
 	spin_unlock_bh(&ar->data_lock);
 
@@ -6255,16 +6240,12 @@ ath10k_mac_op_change_chanctx(struct ieee80211_hw *hw,
 			     u32 changed)
 {
 	struct ath10k *ar = hw->priv;
-	struct ath10k_chanctx *arctx = (void *)ctx->drv_priv;
 
 	mutex_lock(&ar->conf_mutex);
 
 	ath10k_dbg(ar, ATH10K_DBG_MAC,
-		   "mac chanctx change freq %hu->%hu width %d->%d ptr %p changed %x\n",
-		   arctx->conf.def.chan->center_freq,
-		   ctx->def.chan->center_freq,
-		   arctx->conf.def.width, ctx->def.width,
-		   ctx, changed);
+		   "mac chanctx change freq %hu width %d ptr %p changed %x\n",
+		   ctx->def.chan->center_freq, ctx->def.width, ctx, changed);
 
 	/* This shouldn't really happen because channel switching should use
 	 * switch_vif_chanctx().
@@ -6272,10 +6253,6 @@ ath10k_mac_op_change_chanctx(struct ieee80211_hw *hw,
 	if (WARN_ON(changed & IEEE80211_CHANCTX_CHANGE_CHANNEL))
 		goto unlock;
 
-	spin_lock_bh(&ar->data_lock);
-	arctx->conf = *ctx;
-	spin_unlock_bh(&ar->data_lock);
-
 	ath10k_recalc_radar_detection(ar);
 
 	/* FIXME: How to configure Rx chains properly? */
@@ -6295,7 +6272,6 @@ ath10k_mac_op_assign_vif_chanctx(struct ieee80211_hw *hw,
 				 struct ieee80211_chanctx_conf *ctx)
 {
 	struct ath10k *ar = hw->priv;
-	struct ath10k_chanctx *arctx = (void *)ctx->drv_priv;
 	struct ath10k_vif *arvif = (void *)vif->drv_priv;
 	int ret;
 
@@ -6310,11 +6286,11 @@ ath10k_mac_op_assign_vif_chanctx(struct ieee80211_hw *hw,
 		return -EBUSY;
 	}
 
-	ret = ath10k_vdev_start(arvif, &arctx->conf.def);
+	ret = ath10k_vdev_start(arvif, &ctx->def);
 	if (ret) {
 		ath10k_warn(ar, "failed to start vdev %i addr %pM on freq %d: %d\n",
 			    arvif->vdev_id, vif->addr,
-			    arctx->conf.def.chan->center_freq, ret);
+			    ctx->def.chan->center_freq, ret);
 		goto err;
 	}
 
@@ -6389,7 +6365,6 @@ ath10k_mac_op_switch_vif_chanctx(struct ieee80211_hw *hw,
 {
 	struct ath10k *ar = hw->priv;
 	struct ath10k_vif *arvif;
-	struct ath10k_chanctx *arctx_new, *arctx_old;
 	int i;
 
 	mutex_lock(&ar->conf_mutex);
@@ -6401,29 +6376,14 @@ ath10k_mac_op_switch_vif_chanctx(struct ieee80211_hw *hw,
 	spin_lock_bh(&ar->data_lock);
 	for (i = 0; i < n_vifs; i++) {
 		arvif = ath10k_vif_to_arvif(vifs[i].vif);
-		arctx_new = (void *)vifs[i].new_ctx->drv_priv;
-		arctx_old = (void *)vifs[i].old_ctx->drv_priv;
 
 		ath10k_dbg(ar, ATH10K_DBG_MAC,
-			   "mac chanctx switch vdev_id %i freq %hu->%hu width %d->%d ptr %p->%p\n",
+			   "mac chanctx switch vdev_id %i freq %hu->%hu width %d->%d\n",
 			   arvif->vdev_id,
 			   vifs[i].old_ctx->def.chan->center_freq,
 			   vifs[i].new_ctx->def.chan->center_freq,
 			   vifs[i].old_ctx->def.width,
-			   vifs[i].new_ctx->def.width,
-			   arctx_old, arctx_new);
-
-		if (mode == CHANCTX_SWMODE_SWAP_CONTEXTS) {
-			ath10k_mac_chan_ctx_init(ar, arctx_new,
-						 vifs[i].new_ctx);
-		}
-
-		arctx_new->conf = *vifs[i].new_ctx;
-
-		/* FIXME: ath10k_mac_chan_reconfigure() uses current, i.e. not
-		 * yet updated chanctx_conf pointer.
-		 */
-		arctx_old->conf = *vifs[i].new_ctx;
+			   vifs[i].new_ctx->def.width);
 	}
 	ath10k_mac_update_rx_channel(ar, NULL, vifs, n_vifs);
 	spin_unlock_bh(&ar->data_lock);
@@ -6926,7 +6886,6 @@ int ath10k_mac_register(struct ath10k *ar)
 
 	ar->hw->vif_data_size = sizeof(struct ath10k_vif);
 	ar->hw->sta_data_size = sizeof(struct ath10k_sta);
-	ar->hw->chanctx_data_size = sizeof(struct ath10k_chanctx);
 
 	ar->hw->max_listen_interval = ATH10K_MAX_HW_LISTEN_INTERVAL;
 
-- 
2.1.4


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

* [PATCH 2/3] ath10k: remove ath10k_chanctx struct
@ 2015-06-03 10:16   ` Michal Kazior
  0 siblings, 0 replies; 8+ messages in thread
From: Michal Kazior @ 2015-06-03 10:16 UTC (permalink / raw)
  To: ath10k; +Cc: linux-wireless, Michal Kazior

In practice there's no point in having a copy of
chanctx_conf.

Most of the time the channel pointer (and band
along with it) is accessed and this can't change
after a chanctx is created because switching is
done using explicit chanctx swapping via
switch_vif_chanctx().

The only thing that can change within a
chanctx_conf and is used by the driver is
radar_enabled and channel width. These are however
always accessed in adequate mac80211 callback
context which guarantees safe access to the
chanctx data.

Signed-off-by: Michal Kazior <michal.kazior@tieto.com>
---
 drivers/net/wireless/ath/ath10k/core.h |  9 ------
 drivers/net/wireless/ath/ath10k/mac.c  | 53 ++++------------------------------
 2 files changed, 6 insertions(+), 56 deletions(-)

diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h
index 45f9603a0868..78094f23c9dd 100644
--- a/drivers/net/wireless/ath/ath10k/core.h
+++ b/drivers/net/wireless/ath/ath10k/core.h
@@ -284,15 +284,6 @@ struct ath10k_sta {
 #endif
 };
 
-struct ath10k_chanctx {
-	/* Used to story copy of chanctx_conf to avoid inconsistencies. Ideally
-	 * mac80211 should allow some sort of explicit locking to guarantee
-	 * that the publicly available chanctx_conf can be accessed safely at
-	 * all times.
-	 */
-	struct ieee80211_chanctx_conf conf;
-};
-
 #define ATH10K_VDEV_SETUP_TIMEOUT_HZ (5*HZ)
 
 enum ath10k_beacon_state {
diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c
index fe53b1f5e6c9..b60369f78940 100644
--- a/drivers/net/wireless/ath/ath10k/mac.c
+++ b/drivers/net/wireless/ath/ath10k/mac.c
@@ -6188,25 +6188,11 @@ ath10k_mac_update_rx_channel(struct ath10k *ar,
 	rcu_read_unlock();
 }
 
-static void
-ath10k_mac_chan_ctx_init(struct ath10k *ar,
-			 struct ath10k_chanctx *arctx,
-			 struct ieee80211_chanctx_conf *conf)
-{
-	lockdep_assert_held(&ar->conf_mutex);
-	lockdep_assert_held(&ar->data_lock);
-
-	memset(arctx, 0, sizeof(*arctx));
-
-	arctx->conf = *conf;
-}
-
 static int
 ath10k_mac_op_add_chanctx(struct ieee80211_hw *hw,
 			  struct ieee80211_chanctx_conf *ctx)
 {
 	struct ath10k *ar = hw->priv;
-	struct ath10k_chanctx *arctx = (void *)ctx->drv_priv;
 
 	ath10k_dbg(ar, ATH10K_DBG_MAC,
 		   "mac chanctx add freq %hu width %d ptr %p\n",
@@ -6215,7 +6201,6 @@ ath10k_mac_op_add_chanctx(struct ieee80211_hw *hw,
 	mutex_lock(&ar->conf_mutex);
 
 	spin_lock_bh(&ar->data_lock);
-	ath10k_mac_chan_ctx_init(ar, arctx, ctx);
 	ath10k_mac_update_rx_channel(ar, ctx, NULL, 0);
 	spin_unlock_bh(&ar->data_lock);
 
@@ -6255,16 +6240,12 @@ ath10k_mac_op_change_chanctx(struct ieee80211_hw *hw,
 			     u32 changed)
 {
 	struct ath10k *ar = hw->priv;
-	struct ath10k_chanctx *arctx = (void *)ctx->drv_priv;
 
 	mutex_lock(&ar->conf_mutex);
 
 	ath10k_dbg(ar, ATH10K_DBG_MAC,
-		   "mac chanctx change freq %hu->%hu width %d->%d ptr %p changed %x\n",
-		   arctx->conf.def.chan->center_freq,
-		   ctx->def.chan->center_freq,
-		   arctx->conf.def.width, ctx->def.width,
-		   ctx, changed);
+		   "mac chanctx change freq %hu width %d ptr %p changed %x\n",
+		   ctx->def.chan->center_freq, ctx->def.width, ctx, changed);
 
 	/* This shouldn't really happen because channel switching should use
 	 * switch_vif_chanctx().
@@ -6272,10 +6253,6 @@ ath10k_mac_op_change_chanctx(struct ieee80211_hw *hw,
 	if (WARN_ON(changed & IEEE80211_CHANCTX_CHANGE_CHANNEL))
 		goto unlock;
 
-	spin_lock_bh(&ar->data_lock);
-	arctx->conf = *ctx;
-	spin_unlock_bh(&ar->data_lock);
-
 	ath10k_recalc_radar_detection(ar);
 
 	/* FIXME: How to configure Rx chains properly? */
@@ -6295,7 +6272,6 @@ ath10k_mac_op_assign_vif_chanctx(struct ieee80211_hw *hw,
 				 struct ieee80211_chanctx_conf *ctx)
 {
 	struct ath10k *ar = hw->priv;
-	struct ath10k_chanctx *arctx = (void *)ctx->drv_priv;
 	struct ath10k_vif *arvif = (void *)vif->drv_priv;
 	int ret;
 
@@ -6310,11 +6286,11 @@ ath10k_mac_op_assign_vif_chanctx(struct ieee80211_hw *hw,
 		return -EBUSY;
 	}
 
-	ret = ath10k_vdev_start(arvif, &arctx->conf.def);
+	ret = ath10k_vdev_start(arvif, &ctx->def);
 	if (ret) {
 		ath10k_warn(ar, "failed to start vdev %i addr %pM on freq %d: %d\n",
 			    arvif->vdev_id, vif->addr,
-			    arctx->conf.def.chan->center_freq, ret);
+			    ctx->def.chan->center_freq, ret);
 		goto err;
 	}
 
@@ -6389,7 +6365,6 @@ ath10k_mac_op_switch_vif_chanctx(struct ieee80211_hw *hw,
 {
 	struct ath10k *ar = hw->priv;
 	struct ath10k_vif *arvif;
-	struct ath10k_chanctx *arctx_new, *arctx_old;
 	int i;
 
 	mutex_lock(&ar->conf_mutex);
@@ -6401,29 +6376,14 @@ ath10k_mac_op_switch_vif_chanctx(struct ieee80211_hw *hw,
 	spin_lock_bh(&ar->data_lock);
 	for (i = 0; i < n_vifs; i++) {
 		arvif = ath10k_vif_to_arvif(vifs[i].vif);
-		arctx_new = (void *)vifs[i].new_ctx->drv_priv;
-		arctx_old = (void *)vifs[i].old_ctx->drv_priv;
 
 		ath10k_dbg(ar, ATH10K_DBG_MAC,
-			   "mac chanctx switch vdev_id %i freq %hu->%hu width %d->%d ptr %p->%p\n",
+			   "mac chanctx switch vdev_id %i freq %hu->%hu width %d->%d\n",
 			   arvif->vdev_id,
 			   vifs[i].old_ctx->def.chan->center_freq,
 			   vifs[i].new_ctx->def.chan->center_freq,
 			   vifs[i].old_ctx->def.width,
-			   vifs[i].new_ctx->def.width,
-			   arctx_old, arctx_new);
-
-		if (mode == CHANCTX_SWMODE_SWAP_CONTEXTS) {
-			ath10k_mac_chan_ctx_init(ar, arctx_new,
-						 vifs[i].new_ctx);
-		}
-
-		arctx_new->conf = *vifs[i].new_ctx;
-
-		/* FIXME: ath10k_mac_chan_reconfigure() uses current, i.e. not
-		 * yet updated chanctx_conf pointer.
-		 */
-		arctx_old->conf = *vifs[i].new_ctx;
+			   vifs[i].new_ctx->def.width);
 	}
 	ath10k_mac_update_rx_channel(ar, NULL, vifs, n_vifs);
 	spin_unlock_bh(&ar->data_lock);
@@ -6926,7 +6886,6 @@ int ath10k_mac_register(struct ath10k *ar)
 
 	ar->hw->vif_data_size = sizeof(struct ath10k_vif);
 	ar->hw->sta_data_size = sizeof(struct ath10k_sta);
-	ar->hw->chanctx_data_size = sizeof(struct ath10k_chanctx);
 
 	ar->hw->max_listen_interval = ATH10K_MAX_HW_LISTEN_INTERVAL;
 
-- 
2.1.4


_______________________________________________
ath10k mailing list
ath10k@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/ath10k

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

* [PATCH 3/3] ath10k: fix channel switching
  2015-06-03 10:16 ` Michal Kazior
@ 2015-06-03 10:16   ` Michal Kazior
  -1 siblings, 0 replies; 8+ messages in thread
From: Michal Kazior @ 2015-06-03 10:16 UTC (permalink / raw)
  To: ath10k; +Cc: linux-wireless, Michal Kazior

In the midst of chanctx patch review channel
switching became broken which I failed to notice
until now.

Function ath10k_mac_vif_chan() reports current
chandef which isn't updated until after
switch_vif_chanctx() is returned from.
Consequently the driver just restarted operation
on channels it was residing already instead of
switching to the new ones.

Fixes: 500ff9f9389d ("ath10k: implement chanctx API")
Signed-off-by: Michal Kazior <michal.kazior@tieto.com>
---
 drivers/net/wireless/ath/ath10k/mac.c | 142 +++++++++++++++-------------------
 1 file changed, 62 insertions(+), 80 deletions(-)

diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c
index b60369f78940..e834a9d2fffd 100644
--- a/drivers/net/wireless/ath/ath10k/mac.c
+++ b/drivers/net/wireless/ath/ath10k/mac.c
@@ -3949,83 +3949,6 @@ static int ath10k_config_ps(struct ath10k *ar)
 	return ret;
 }
 
-static void ath10k_mac_chan_reconfigure(struct ath10k *ar)
-{
-	struct ath10k_vif *arvif;
-	struct cfg80211_chan_def def;
-	int ret;
-
-	lockdep_assert_held(&ar->conf_mutex);
-
-	ath10k_dbg(ar, ATH10K_DBG_MAC, "mac chan reconfigure\n");
-
-	/* First stop monitor interface. Some FW versions crash if there's a
-	 * lone monitor interface. */
-	if (ar->monitor_started)
-		ath10k_monitor_stop(ar);
-
-	list_for_each_entry(arvif, &ar->arvifs, list) {
-		if (!arvif->is_started)
-			continue;
-
-		if (!arvif->is_up)
-			continue;
-
-		if (arvif->vdev_type == WMI_VDEV_TYPE_MONITOR)
-			continue;
-
-		ret = ath10k_wmi_vdev_down(ar, arvif->vdev_id);
-		if (ret) {
-			ath10k_warn(ar, "failed to down vdev %d: %d\n",
-				    arvif->vdev_id, ret);
-			continue;
-		}
-	}
-
-	/* all vdevs are downed now - attempt to restart and re-up them */
-
-	list_for_each_entry(arvif, &ar->arvifs, list) {
-		if (!arvif->is_started)
-			continue;
-
-		if (arvif->vdev_type == WMI_VDEV_TYPE_MONITOR)
-			continue;
-
-		ret = ath10k_mac_setup_bcn_tmpl(arvif);
-		if (ret)
-			ath10k_warn(ar, "failed to update bcn tmpl during csa: %d\n",
-				    ret);
-
-		ret = ath10k_mac_setup_prb_tmpl(arvif);
-		if (ret)
-			ath10k_warn(ar, "failed to update prb tmpl during csa: %d\n",
-				    ret);
-
-		if (WARN_ON(ath10k_mac_vif_chan(arvif->vif, &def)))
-			continue;
-
-		ret = ath10k_vdev_restart(arvif, &def);
-		if (ret) {
-			ath10k_warn(ar, "failed to restart vdev %d: %d\n",
-				    arvif->vdev_id, ret);
-			continue;
-		}
-
-		if (!arvif->is_up)
-			continue;
-
-		ret = ath10k_wmi_vdev_up(arvif->ar, arvif->vdev_id, arvif->aid,
-					 arvif->bssid);
-		if (ret) {
-			ath10k_warn(ar, "failed to bring vdev up %d: %d\n",
-				    arvif->vdev_id, ret);
-			continue;
-		}
-	}
-
-	ath10k_monitor_recalc(ar);
-}
-
 static int ath10k_mac_txpower_setup(struct ath10k *ar, int txpower)
 {
 	int ret;
@@ -6365,6 +6288,7 @@ ath10k_mac_op_switch_vif_chanctx(struct ieee80211_hw *hw,
 {
 	struct ath10k *ar = hw->priv;
 	struct ath10k_vif *arvif;
+	int ret;
 	int i;
 
 	mutex_lock(&ar->conf_mutex);
@@ -6373,7 +6297,12 @@ ath10k_mac_op_switch_vif_chanctx(struct ieee80211_hw *hw,
 		   "mac chanctx switch n_vifs %d mode %d\n",
 		   n_vifs, mode);
 
-	spin_lock_bh(&ar->data_lock);
+	/* First stop monitor interface. Some FW versions crash if there's a
+	 * lone monitor interface.
+	 */
+	if (ar->monitor_started)
+		ath10k_monitor_stop(ar);
+
 	for (i = 0; i < n_vifs; i++) {
 		arvif = ath10k_vif_to_arvif(vifs[i].vif);
 
@@ -6384,12 +6313,65 @@ ath10k_mac_op_switch_vif_chanctx(struct ieee80211_hw *hw,
 			   vifs[i].new_ctx->def.chan->center_freq,
 			   vifs[i].old_ctx->def.width,
 			   vifs[i].new_ctx->def.width);
+
+		if (WARN_ON(!arvif->is_started))
+			continue;
+
+		if (WARN_ON(!arvif->is_up))
+			continue;
+
+		ret = ath10k_wmi_vdev_down(ar, arvif->vdev_id);
+		if (ret) {
+			ath10k_warn(ar, "failed to down vdev %d: %d\n",
+				    arvif->vdev_id, ret);
+			continue;
+		}
 	}
+
+	/* All relevant vdevs are downed and associated channel resources
+	 * should be available for the channel switch now.
+	 */
+
+	spin_lock_bh(&ar->data_lock);
 	ath10k_mac_update_rx_channel(ar, NULL, vifs, n_vifs);
 	spin_unlock_bh(&ar->data_lock);
 
-	/* FIXME: Reconfigure only affected vifs */
-	ath10k_mac_chan_reconfigure(ar);
+	for (i = 0; i < n_vifs; i++) {
+		arvif = ath10k_vif_to_arvif(vifs[i].vif);
+
+		if (WARN_ON(!arvif->is_started))
+			continue;
+
+		if (WARN_ON(!arvif->is_up))
+			continue;
+
+		ret = ath10k_mac_setup_bcn_tmpl(arvif);
+		if (ret)
+			ath10k_warn(ar, "failed to update bcn tmpl during csa: %d\n",
+				    ret);
+
+		ret = ath10k_mac_setup_prb_tmpl(arvif);
+		if (ret)
+			ath10k_warn(ar, "failed to update prb tmpl during csa: %d\n",
+				    ret);
+
+		ret = ath10k_vdev_restart(arvif, &vifs[i].new_ctx->def);
+		if (ret) {
+			ath10k_warn(ar, "failed to restart vdev %d: %d\n",
+				    arvif->vdev_id, ret);
+			continue;
+		}
+
+		ret = ath10k_wmi_vdev_up(arvif->ar, arvif->vdev_id, arvif->aid,
+					 arvif->bssid);
+		if (ret) {
+			ath10k_warn(ar, "failed to bring vdev up %d: %d\n",
+				    arvif->vdev_id, ret);
+			continue;
+		}
+	}
+
+	ath10k_monitor_recalc(ar);
 
 	mutex_unlock(&ar->conf_mutex);
 	return 0;
-- 
2.1.4


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

* [PATCH 3/3] ath10k: fix channel switching
@ 2015-06-03 10:16   ` Michal Kazior
  0 siblings, 0 replies; 8+ messages in thread
From: Michal Kazior @ 2015-06-03 10:16 UTC (permalink / raw)
  To: ath10k; +Cc: linux-wireless, Michal Kazior

In the midst of chanctx patch review channel
switching became broken which I failed to notice
until now.

Function ath10k_mac_vif_chan() reports current
chandef which isn't updated until after
switch_vif_chanctx() is returned from.
Consequently the driver just restarted operation
on channels it was residing already instead of
switching to the new ones.

Fixes: 500ff9f9389d ("ath10k: implement chanctx API")
Signed-off-by: Michal Kazior <michal.kazior@tieto.com>
---
 drivers/net/wireless/ath/ath10k/mac.c | 142 +++++++++++++++-------------------
 1 file changed, 62 insertions(+), 80 deletions(-)

diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c
index b60369f78940..e834a9d2fffd 100644
--- a/drivers/net/wireless/ath/ath10k/mac.c
+++ b/drivers/net/wireless/ath/ath10k/mac.c
@@ -3949,83 +3949,6 @@ static int ath10k_config_ps(struct ath10k *ar)
 	return ret;
 }
 
-static void ath10k_mac_chan_reconfigure(struct ath10k *ar)
-{
-	struct ath10k_vif *arvif;
-	struct cfg80211_chan_def def;
-	int ret;
-
-	lockdep_assert_held(&ar->conf_mutex);
-
-	ath10k_dbg(ar, ATH10K_DBG_MAC, "mac chan reconfigure\n");
-
-	/* First stop monitor interface. Some FW versions crash if there's a
-	 * lone monitor interface. */
-	if (ar->monitor_started)
-		ath10k_monitor_stop(ar);
-
-	list_for_each_entry(arvif, &ar->arvifs, list) {
-		if (!arvif->is_started)
-			continue;
-
-		if (!arvif->is_up)
-			continue;
-
-		if (arvif->vdev_type == WMI_VDEV_TYPE_MONITOR)
-			continue;
-
-		ret = ath10k_wmi_vdev_down(ar, arvif->vdev_id);
-		if (ret) {
-			ath10k_warn(ar, "failed to down vdev %d: %d\n",
-				    arvif->vdev_id, ret);
-			continue;
-		}
-	}
-
-	/* all vdevs are downed now - attempt to restart and re-up them */
-
-	list_for_each_entry(arvif, &ar->arvifs, list) {
-		if (!arvif->is_started)
-			continue;
-
-		if (arvif->vdev_type == WMI_VDEV_TYPE_MONITOR)
-			continue;
-
-		ret = ath10k_mac_setup_bcn_tmpl(arvif);
-		if (ret)
-			ath10k_warn(ar, "failed to update bcn tmpl during csa: %d\n",
-				    ret);
-
-		ret = ath10k_mac_setup_prb_tmpl(arvif);
-		if (ret)
-			ath10k_warn(ar, "failed to update prb tmpl during csa: %d\n",
-				    ret);
-
-		if (WARN_ON(ath10k_mac_vif_chan(arvif->vif, &def)))
-			continue;
-
-		ret = ath10k_vdev_restart(arvif, &def);
-		if (ret) {
-			ath10k_warn(ar, "failed to restart vdev %d: %d\n",
-				    arvif->vdev_id, ret);
-			continue;
-		}
-
-		if (!arvif->is_up)
-			continue;
-
-		ret = ath10k_wmi_vdev_up(arvif->ar, arvif->vdev_id, arvif->aid,
-					 arvif->bssid);
-		if (ret) {
-			ath10k_warn(ar, "failed to bring vdev up %d: %d\n",
-				    arvif->vdev_id, ret);
-			continue;
-		}
-	}
-
-	ath10k_monitor_recalc(ar);
-}
-
 static int ath10k_mac_txpower_setup(struct ath10k *ar, int txpower)
 {
 	int ret;
@@ -6365,6 +6288,7 @@ ath10k_mac_op_switch_vif_chanctx(struct ieee80211_hw *hw,
 {
 	struct ath10k *ar = hw->priv;
 	struct ath10k_vif *arvif;
+	int ret;
 	int i;
 
 	mutex_lock(&ar->conf_mutex);
@@ -6373,7 +6297,12 @@ ath10k_mac_op_switch_vif_chanctx(struct ieee80211_hw *hw,
 		   "mac chanctx switch n_vifs %d mode %d\n",
 		   n_vifs, mode);
 
-	spin_lock_bh(&ar->data_lock);
+	/* First stop monitor interface. Some FW versions crash if there's a
+	 * lone monitor interface.
+	 */
+	if (ar->monitor_started)
+		ath10k_monitor_stop(ar);
+
 	for (i = 0; i < n_vifs; i++) {
 		arvif = ath10k_vif_to_arvif(vifs[i].vif);
 
@@ -6384,12 +6313,65 @@ ath10k_mac_op_switch_vif_chanctx(struct ieee80211_hw *hw,
 			   vifs[i].new_ctx->def.chan->center_freq,
 			   vifs[i].old_ctx->def.width,
 			   vifs[i].new_ctx->def.width);
+
+		if (WARN_ON(!arvif->is_started))
+			continue;
+
+		if (WARN_ON(!arvif->is_up))
+			continue;
+
+		ret = ath10k_wmi_vdev_down(ar, arvif->vdev_id);
+		if (ret) {
+			ath10k_warn(ar, "failed to down vdev %d: %d\n",
+				    arvif->vdev_id, ret);
+			continue;
+		}
 	}
+
+	/* All relevant vdevs are downed and associated channel resources
+	 * should be available for the channel switch now.
+	 */
+
+	spin_lock_bh(&ar->data_lock);
 	ath10k_mac_update_rx_channel(ar, NULL, vifs, n_vifs);
 	spin_unlock_bh(&ar->data_lock);
 
-	/* FIXME: Reconfigure only affected vifs */
-	ath10k_mac_chan_reconfigure(ar);
+	for (i = 0; i < n_vifs; i++) {
+		arvif = ath10k_vif_to_arvif(vifs[i].vif);
+
+		if (WARN_ON(!arvif->is_started))
+			continue;
+
+		if (WARN_ON(!arvif->is_up))
+			continue;
+
+		ret = ath10k_mac_setup_bcn_tmpl(arvif);
+		if (ret)
+			ath10k_warn(ar, "failed to update bcn tmpl during csa: %d\n",
+				    ret);
+
+		ret = ath10k_mac_setup_prb_tmpl(arvif);
+		if (ret)
+			ath10k_warn(ar, "failed to update prb tmpl during csa: %d\n",
+				    ret);
+
+		ret = ath10k_vdev_restart(arvif, &vifs[i].new_ctx->def);
+		if (ret) {
+			ath10k_warn(ar, "failed to restart vdev %d: %d\n",
+				    arvif->vdev_id, ret);
+			continue;
+		}
+
+		ret = ath10k_wmi_vdev_up(arvif->ar, arvif->vdev_id, arvif->aid,
+					 arvif->bssid);
+		if (ret) {
+			ath10k_warn(ar, "failed to bring vdev up %d: %d\n",
+				    arvif->vdev_id, ret);
+			continue;
+		}
+	}
+
+	ath10k_monitor_recalc(ar);
 
 	mutex_unlock(&ar->conf_mutex);
 	return 0;
-- 
2.1.4


_______________________________________________
ath10k mailing list
ath10k@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/ath10k

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

* Re: [PATCH 1/3] ath10k: fix ar->rx_channel updating logic
  2015-06-03 10:16 ` Michal Kazior
@ 2015-06-09 10:50   ` Kalle Valo
  -1 siblings, 0 replies; 8+ messages in thread
From: Kalle Valo @ 2015-06-09 10:50 UTC (permalink / raw)
  To: Michal Kazior; +Cc: ath10k, linux-wireless

Michal Kazior <michal.kazior@tieto.com> writes:

> Channel contexts aren't iterable until after
> they've been added to the driver. The code assumed
> otherwise.
>
> This problem could result in:
>
>  * rx_channel being NULL and forcing Rx path to go
>    the slow way to get channel on QCA988X,
>
>  * report incorrect channel when running
>    multi-channel on QCA61X4 hw2.1,
>
>  * report incorrect channel after AP channel
>    switch.
>
> Fixes: 500ff9f9389d ("ath10k: implement chanctx API")
> Signed-off-by: Michal Kazior <michal.kazior@tieto.com>

Thanks, all three patches applied.

-- 
Kalle Valo

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

* Re: [PATCH 1/3] ath10k: fix ar->rx_channel updating logic
@ 2015-06-09 10:50   ` Kalle Valo
  0 siblings, 0 replies; 8+ messages in thread
From: Kalle Valo @ 2015-06-09 10:50 UTC (permalink / raw)
  To: Michal Kazior; +Cc: linux-wireless, ath10k

Michal Kazior <michal.kazior@tieto.com> writes:

> Channel contexts aren't iterable until after
> they've been added to the driver. The code assumed
> otherwise.
>
> This problem could result in:
>
>  * rx_channel being NULL and forcing Rx path to go
>    the slow way to get channel on QCA988X,
>
>  * report incorrect channel when running
>    multi-channel on QCA61X4 hw2.1,
>
>  * report incorrect channel after AP channel
>    switch.
>
> Fixes: 500ff9f9389d ("ath10k: implement chanctx API")
> Signed-off-by: Michal Kazior <michal.kazior@tieto.com>

Thanks, all three patches applied.

-- 
Kalle Valo

_______________________________________________
ath10k mailing list
ath10k@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/ath10k

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

end of thread, other threads:[~2015-06-09 10:50 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-06-03 10:16 [PATCH 1/3] ath10k: fix ar->rx_channel updating logic Michal Kazior
2015-06-03 10:16 ` Michal Kazior
2015-06-03 10:16 ` [PATCH 2/3] ath10k: remove ath10k_chanctx struct Michal Kazior
2015-06-03 10:16   ` Michal Kazior
2015-06-03 10:16 ` [PATCH 3/3] ath10k: fix channel switching Michal Kazior
2015-06-03 10:16   ` Michal Kazior
2015-06-09 10:50 ` [PATCH 1/3] ath10k: fix ar->rx_channel updating logic Kalle Valo
2015-06-09 10:50   ` Kalle Valo

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.