Skip to content

Commit

Permalink
ath10k: handle IEEE80211_CHANCTX_CHANGE_WIDTH properly
Browse files Browse the repository at this point in the history
Vdevs associated with a given chanctx should be
restarted if the bandwidth changes. Otherwise
traffic may cease.

This is known to fix STA CSA with bandwidths wider
than 20MHz.

Signed-off-by: Michal Kazior <michal.kazior@tieto.com>
Signed-off-by: Kalle Valo <kvalo@qca.qualcomm.com>
  • Loading branch information
Michal Kazior authored and Kalle Valo committed Sep 17, 2015
1 parent 7be6d1b commit 9713e3d
Showing 1 changed file with 64 additions and 0 deletions.
64 changes: 64 additions & 0 deletions drivers/net/wireless/ath/ath10k/mac.c
Original file line number Diff line number Diff line change
Expand Up @@ -6408,12 +6408,52 @@ ath10k_mac_op_remove_chanctx(struct ieee80211_hw *hw,
mutex_unlock(&ar->conf_mutex);
}

struct ath10k_mac_change_chanctx_arg {
struct ieee80211_chanctx_conf *ctx;
struct ieee80211_vif_chanctx_switch *vifs;
int n_vifs;
int next_vif;
};

static void
ath10k_mac_change_chanctx_cnt_iter(void *data, u8 *mac,
struct ieee80211_vif *vif)
{
struct ath10k_mac_change_chanctx_arg *arg = data;

if (rcu_access_pointer(vif->chanctx_conf) != arg->ctx)
return;

arg->n_vifs++;
}

static void
ath10k_mac_change_chanctx_fill_iter(void *data, u8 *mac,
struct ieee80211_vif *vif)
{
struct ath10k_mac_change_chanctx_arg *arg = data;
struct ieee80211_chanctx_conf *ctx;

ctx = rcu_access_pointer(vif->chanctx_conf);
if (ctx != arg->ctx)
return;

if (WARN_ON(arg->next_vif == arg->n_vifs))
return;

arg->vifs[arg->next_vif].vif = vif;
arg->vifs[arg->next_vif].old_ctx = ctx;
arg->vifs[arg->next_vif].new_ctx = ctx;
arg->next_vif++;
}

static void
ath10k_mac_op_change_chanctx(struct ieee80211_hw *hw,
struct ieee80211_chanctx_conf *ctx,
u32 changed)
{
struct ath10k *ar = hw->priv;
struct ath10k_mac_change_chanctx_arg arg = { .ctx = ctx };

mutex_lock(&ar->conf_mutex);

Expand All @@ -6427,6 +6467,30 @@ ath10k_mac_op_change_chanctx(struct ieee80211_hw *hw,
if (WARN_ON(changed & IEEE80211_CHANCTX_CHANGE_CHANNEL))
goto unlock;

if (changed & IEEE80211_CHANCTX_CHANGE_WIDTH) {
ieee80211_iterate_active_interfaces_atomic(
hw,
IEEE80211_IFACE_ITER_NORMAL,
ath10k_mac_change_chanctx_cnt_iter,
&arg);
if (arg.n_vifs == 0)
goto radar;

arg.vifs = kcalloc(arg.n_vifs, sizeof(arg.vifs[0]),
GFP_KERNEL);
if (!arg.vifs)
goto radar;

ieee80211_iterate_active_interfaces_atomic(
hw,
IEEE80211_IFACE_ITER_NORMAL,
ath10k_mac_change_chanctx_fill_iter,
&arg);
ath10k_mac_update_vif_chan(ar, arg.vifs, arg.n_vifs);
kfree(arg.vifs);
}

radar:
ath10k_recalc_radar_detection(ar);

/* FIXME: How to configure Rx chains properly? */
Expand Down

0 comments on commit 9713e3d

Please sign in to comment.