|
@@ -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;
|
|
@@ -6144,7 +6067,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 +6080,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,36 +6094,28 @@ 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;
|
|
|
}
|
|
|
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",
|
|
@@ -6203,8 +6124,7 @@ 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);
|
|
|
+ ath10k_mac_update_rx_channel(ar, ctx, NULL, 0);
|
|
|
spin_unlock_bh(&ar->data_lock);
|
|
|
|
|
|
ath10k_recalc_radar_detection(ar);
|
|
@@ -6228,7 +6148,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);
|
|
@@ -6243,16 +6163,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().
|
|
@@ -6260,10 +6176,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? */
|
|
@@ -6283,7 +6195,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;
|
|
|
|
|
@@ -6298,11 +6209,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;
|
|
|
}
|
|
|
|
|
@@ -6377,7 +6288,7 @@ 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 ret;
|
|
|
int i;
|
|
|
|
|
|
mutex_lock(&ar->conf_mutex);
|
|
@@ -6386,38 +6297,81 @@ 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);
|
|
|
- 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);
|
|
|
+ vifs[i].new_ctx->def.width);
|
|
|
|
|
|
- if (mode == CHANCTX_SWMODE_SWAP_CONTEXTS) {
|
|
|
- ath10k_mac_chan_ctx_init(ar, arctx_new,
|
|
|
- vifs[i].new_ctx);
|
|
|
- }
|
|
|
+ if (WARN_ON(!arvif->is_started))
|
|
|
+ continue;
|
|
|
|
|
|
- arctx_new->conf = *vifs[i].new_ctx;
|
|
|
+ if (WARN_ON(!arvif->is_up))
|
|
|
+ continue;
|
|
|
|
|
|
- /* FIXME: ath10k_mac_chan_reconfigure() uses current, i.e. not
|
|
|
- * yet updated chanctx_conf pointer.
|
|
|
- */
|
|
|
- arctx_old->conf = *vifs[i].new_ctx;
|
|
|
+ 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;
|
|
|
+ }
|
|
|
}
|
|
|
- ath10k_mac_update_rx_channel(ar);
|
|
|
+
|
|
|
+ /* 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;
|
|
@@ -6914,7 +6868,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;
|
|
|
|