Merge git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211-next
authorJohn W. Linville <linville@tuxdriver.com>
Wed, 25 Jun 2014 19:15:14 +0000 (15:15 -0400)
committerJohn W. Linville <linville@tuxdriver.com>
Wed, 25 Jun 2014 19:26:36 +0000 (15:26 -0400)
1  2 
drivers/net/wireless/ath/ath9k/main.c
drivers/net/wireless/mwifiex/cfg80211.c

@@@ -19,6 -19,9 +19,6 @@@
  #include "ath9k.h"
  #include "btcoex.h"
  
 -static void ath9k_set_assoc_state(struct ath_softc *sc,
 -                                struct ieee80211_vif *vif);
 -
  u8 ath9k_parse_mpdudensity(u8 mpdudensity)
  {
        /*
@@@ -60,16 -63,9 +60,16 @@@ static bool ath9k_has_pending_frames(st
  
        spin_lock_bh(&txq->axq_lock);
  
 -      if (txq->axq_depth || !list_empty(&txq->axq_acq))
 +      if (txq->axq_depth)
                pending = true;
  
 +      if (txq->mac80211_qnum >= 0) {
 +              struct list_head *list;
 +
 +              list = &sc->cur_chan->acq[txq->mac80211_qnum];
 +              if (!list_empty(list))
 +                      pending = true;
 +      }
        spin_unlock_bh(&txq->axq_lock);
        return pending;
  }
@@@ -231,22 -227,13 +231,22 @@@ static bool ath_complete_reset(struct a
        }
  
        ath9k_cmn_update_txpow(ah, sc->curtxpow,
 -                             sc->config.txpowlimit, &sc->curtxpow);
 +                             sc->cur_chan->txpower, &sc->curtxpow);
  
        clear_bit(ATH_OP_HW_RESET, &common->op_flags);
 -      ath9k_hw_set_interrupts(ah);
 -      ath9k_hw_enable_interrupts(ah);
 +      ath9k_calculate_summary_state(sc, sc->cur_chan);
 +
 +      if (!sc->cur_chan->offchannel && start) {
 +              /* restore per chanctx TSF timer */
 +              if (sc->cur_chan->tsf_val) {
 +                      u32 offset;
 +
 +                      offset = ath9k_hw_get_tsf_offset(&sc->cur_chan->tsf_ts,
 +                                                       NULL);
 +                      ath9k_hw_settsf64(ah, sc->cur_chan->tsf_val + offset);
 +              }
 +
  
 -      if (!(sc->hw->conf.flags & IEEE80211_CONF_OFFCHANNEL) && start) {
                if (!test_bit(ATH_OP_BEACONS, &common->op_flags))
                        goto work;
  
                }
        work:
                ath_restart_work(sc);
 +              ath_txq_schedule_all(sc);
 +      }
  
 -              for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) {
 -                      if (!ATH_TXQ_SETUP(sc, i))
 -                              continue;
 +      sc->gtt_cnt = 0;
  
 -                      spin_lock_bh(&sc->tx.txq[i].axq_lock);
 -                      ath_txq_schedule(sc, &sc->tx.txq[i]);
 -                      spin_unlock_bh(&sc->tx.txq[i].axq_lock);
 +      ath9k_hw_set_interrupts(ah);
 +      ath9k_hw_enable_interrupts(ah);
 +
 +      if (!ath9k_use_chanctx)
 +              ieee80211_wake_queues(sc->hw);
 +      else {
 +              if (sc->cur_chan == &sc->offchannel.chan)
 +                      ieee80211_wake_queue(sc->hw,
 +                                      sc->hw->offchannel_tx_hw_queue);
 +              else {
 +                      for (i = 0; i < IEEE80211_NUM_ACS; i++)
 +                              ieee80211_wake_queue(sc->hw,
 +                                      sc->cur_chan->hw_queue_base + i);
                }
 +              if (ah->opmode == NL80211_IFTYPE_AP)
 +                      ieee80211_wake_queue(sc->hw, sc->hw->queues - 2);
        }
  
 -      sc->gtt_cnt = 0;
 -      ieee80211_wake_queues(sc->hw);
 -
        ath9k_p2p_ps_timer(sc);
  
        return true;
  }
  
 -static int ath_reset_internal(struct ath_softc *sc, struct ath9k_channel *hchan)
 +int ath_reset_internal(struct ath_softc *sc, struct ath9k_channel *hchan)
  {
        struct ath_hw *ah = sc->sc_ah;
        struct ath_common *common = ath9k_hw_common(ah);
        tasklet_disable(&sc->intr_tq);
        spin_lock_bh(&sc->sc_pcu_lock);
  
 -      if (!(sc->hw->conf.flags & IEEE80211_CONF_OFFCHANNEL)) {
 +      if (!sc->cur_chan->offchannel) {
                fastcc = false;
 -              caldata = &sc->caldata;
 +              caldata = &sc->cur_chan->caldata;
        }
  
        if (!hchan) {
        if (!ath_prepare_reset(sc))
                fastcc = false;
  
 +      spin_lock_bh(&sc->chan_lock);
 +      sc->cur_chandef = sc->cur_chan->chandef;
 +      spin_unlock_bh(&sc->chan_lock);
 +
        ath_dbg(common, CONFIG, "Reset to %u MHz, HT40: %d fastcc: %d\n",
                hchan->channel, IS_CHAN_HT40(hchan), fastcc);
  
        }
  
        if (ath9k_hw_mci_is_enabled(sc->sc_ah) &&
 -          (sc->hw->conf.flags & IEEE80211_CONF_OFFCHANNEL))
 +          sc->cur_chan->offchannel)
                ath9k_mci_set_txpower(sc, true, false);
  
        if (!ath_complete_reset(sc, true))
@@@ -346,6 -320,98 +346,6 @@@ out
        return r;
  }
  
 -
 -/*
 - * Set/change channels.  If the channel is really being changed, it's done
 - * by reseting the chip.  To accomplish this we must first cleanup any pending
 - * DMA, then restart stuff.
 -*/
 -static int ath_set_channel(struct ath_softc *sc, struct cfg80211_chan_def *chandef)
 -{
 -      struct ath_hw *ah = sc->sc_ah;
 -      struct ath_common *common = ath9k_hw_common(ah);
 -      struct ieee80211_hw *hw = sc->hw;
 -      struct ath9k_channel *hchan;
 -      struct ieee80211_channel *chan = chandef->chan;
 -      bool offchannel;
 -      int pos = chan->hw_value;
 -      int old_pos = -1;
 -      int r;
 -
 -      if (test_bit(ATH_OP_INVALID, &common->op_flags))
 -              return -EIO;
 -
 -      offchannel = !!(hw->conf.flags & IEEE80211_CONF_OFFCHANNEL);
 -
 -      if (ah->curchan)
 -              old_pos = ah->curchan - &ah->channels[0];
 -
 -      ath_dbg(common, CONFIG, "Set channel: %d MHz width: %d\n",
 -              chan->center_freq, chandef->width);
 -
 -      /* update survey stats for the old channel before switching */
 -      spin_lock_bh(&common->cc_lock);
 -      ath_update_survey_stats(sc);
 -      spin_unlock_bh(&common->cc_lock);
 -
 -      ath9k_cmn_get_channel(hw, ah, chandef);
 -
 -      /*
 -       * If the operating channel changes, change the survey in-use flags
 -       * along with it.
 -       * Reset the survey data for the new channel, unless we're switching
 -       * back to the operating channel from an off-channel operation.
 -       */
 -      if (!offchannel && sc->cur_survey != &sc->survey[pos]) {
 -              if (sc->cur_survey)
 -                      sc->cur_survey->filled &= ~SURVEY_INFO_IN_USE;
 -
 -              sc->cur_survey = &sc->survey[pos];
 -
 -              memset(sc->cur_survey, 0, sizeof(struct survey_info));
 -              sc->cur_survey->filled |= SURVEY_INFO_IN_USE;
 -      } else if (!(sc->survey[pos].filled & SURVEY_INFO_IN_USE)) {
 -              memset(&sc->survey[pos], 0, sizeof(struct survey_info));
 -      }
 -
 -      hchan = &sc->sc_ah->channels[pos];
 -      r = ath_reset_internal(sc, hchan);
 -      if (r)
 -              return r;
 -
 -      /*
 -       * The most recent snapshot of channel->noisefloor for the old
 -       * channel is only available after the hardware reset. Copy it to
 -       * the survey stats now.
 -       */
 -      if (old_pos >= 0)
 -              ath_update_survey_nf(sc, old_pos);
 -
 -      /*
 -       * Enable radar pulse detection if on a DFS channel. Spectral
 -       * scanning and radar detection can not be used concurrently.
 -       */
 -      if (hw->conf.radar_enabled) {
 -              u32 rxfilter;
 -
 -              /* set HW specific DFS configuration */
 -              ath9k_hw_set_radar_params(ah);
 -              rxfilter = ath9k_hw_getrxfilter(ah);
 -              rxfilter |= ATH9K_RX_FILTER_PHYRADAR |
 -                              ATH9K_RX_FILTER_PHYERR;
 -              ath9k_hw_setrxfilter(ah, rxfilter);
 -              ath_dbg(common, DFS, "DFS enabled at freq %d\n",
 -                      chan->center_freq);
 -      } else {
 -              /* perform spectral scan if requested. */
 -              if (test_bit(ATH_OP_SCANNING, &common->op_flags) &&
 -                      sc->spectral_mode == SPECTRAL_CHANSCAN)
 -                      ath9k_spectral_scan_trigger(hw);
 -      }
 -
 -      return 0;
 -}
 -
  static void ath_node_attach(struct ath_softc *sc, struct ieee80211_sta *sta,
                            struct ieee80211_vif *vif)
  {
@@@ -646,8 -712,7 +646,8 @@@ static int ath9k_start(struct ieee80211
        struct ath_softc *sc = hw->priv;
        struct ath_hw *ah = sc->sc_ah;
        struct ath_common *common = ath9k_hw_common(ah);
 -      struct ieee80211_channel *curchan = hw->conf.chandef.chan;
 +      struct ieee80211_channel *curchan = sc->cur_chan->chandef.chan;
 +      struct ath_chanctx *ctx = sc->cur_chan;
        struct ath9k_channel *init_channel;
        int r;
  
        ath9k_ps_wakeup(sc);
        mutex_lock(&sc->mutex);
  
 -      init_channel = ath9k_cmn_get_channel(hw, ah, &hw->conf.chandef);
 +      init_channel = ath9k_cmn_get_channel(hw, ah, &ctx->chandef);
 +      sc->cur_chandef = hw->conf.chandef;
  
        /* Reset SERDES registers */
        ath9k_hw_configpcipowersave(ah, false);
@@@ -822,7 -886,6 +822,7 @@@ static void ath9k_stop(struct ieee80211
        struct ath_common *common = ath9k_hw_common(ah);
        bool prev_idle;
  
 +      cancel_work_sync(&sc->chanctx_work);
        mutex_lock(&sc->mutex);
  
        ath_cancel_work(sc);
        }
  
        if (!ah->curchan)
 -              ah->curchan = ath9k_cmn_get_channel(hw, ah, &hw->conf.chandef);
 +              ah->curchan = ath9k_cmn_get_channel(hw, ah,
 +                                                  &sc->cur_chan->chandef);
  
        ath9k_hw_reset(ah, ah->curchan, ah->caldata, false);
        ath9k_hw_phy_disable(ah);
@@@ -917,29 -979,18 +917,29 @@@ static void ath9k_vif_iter(void *data, 
                iter_data->has_hw_macaddr = true;
        }
  
 +      if (!vif->bss_conf.use_short_slot)
 +              iter_data->slottime = ATH9K_SLOT_TIME_20;
 +
        switch (vif->type) {
        case NL80211_IFTYPE_AP:
                iter_data->naps++;
 +              if (vif->bss_conf.enable_beacon)
 +                      iter_data->beacons = true;
                break;
        case NL80211_IFTYPE_STATION:
                iter_data->nstations++;
 +              if (vif->bss_conf.assoc && !iter_data->primary_sta)
 +                      iter_data->primary_sta = vif;
                break;
        case NL80211_IFTYPE_ADHOC:
                iter_data->nadhocs++;
 +              if (vif->bss_conf.enable_beacon)
 +                      iter_data->beacons = true;
                break;
        case NL80211_IFTYPE_MESH_POINT:
                iter_data->nmeshes++;
 +              if (vif->bss_conf.enable_beacon)
 +                      iter_data->beacons = true;
                break;
        case NL80211_IFTYPE_WDS:
                iter_data->nwds++;
        }
  }
  
 -static void ath9k_sta_vif_iter(void *data, u8 *mac, struct ieee80211_vif *vif)
 -{
 -      struct ath_softc *sc = data;
 -      struct ath_vif *avp = (void *)vif->drv_priv;
 -
 -      if (vif->type != NL80211_IFTYPE_STATION)
 -              return;
 -
 -      if (avp->primary_sta_vif)
 -              ath9k_set_assoc_state(sc, vif);
 -}
 -
  /* Called with sc->mutex held. */
 -void ath9k_calculate_iter_data(struct ieee80211_hw *hw,
 -                             struct ieee80211_vif *vif,
 +void ath9k_calculate_iter_data(struct ath_softc *sc,
 +                             struct ath_chanctx *ctx,
                               struct ath9k_vif_iter_data *iter_data)
  {
 -      struct ath_softc *sc = hw->priv;
 -      struct ath_hw *ah = sc->sc_ah;
 -      struct ath_common *common = ath9k_hw_common(ah);
 +      struct ath_vif *avp;
  
        /*
         * Pick the MAC address of the first interface as the new hardware
         */
        memset(iter_data, 0, sizeof(*iter_data));
        memset(&iter_data->mask, 0xff, ETH_ALEN);
 +      iter_data->slottime = ATH9K_SLOT_TIME_9;
 +
 +      list_for_each_entry(avp, &ctx->vifs, list)
 +              ath9k_vif_iter(iter_data, avp->vif->addr, avp->vif);
 +
 +      if (ctx == &sc->offchannel.chan) {
 +              struct ieee80211_vif *vif;
 +
 +              if (sc->offchannel.state < ATH_OFFCHANNEL_ROC_START)
 +                      vif = sc->offchannel.scan_vif;
 +              else
 +                      vif = sc->offchannel.roc_vif;
 +
 +              if (vif)
 +                      ath9k_vif_iter(iter_data, vif->addr, vif);
 +              iter_data->beacons = false;
 +      }
 +}
 +
 +static void ath9k_set_assoc_state(struct ath_softc *sc,
 +                                struct ieee80211_vif *vif, bool changed)
 +{
 +      struct ath_common *common = ath9k_hw_common(sc->sc_ah);
 +      struct ieee80211_bss_conf *bss_conf = &vif->bss_conf;
 +      unsigned long flags;
  
 -      if (vif)
 -              ath9k_vif_iter(iter_data, vif->addr, vif);
 +      set_bit(ATH_OP_PRIM_STA_VIF, &common->op_flags);
 +      /* Set the AID, BSSID and do beacon-sync only when
 +       * the HW opmode is STATION.
 +       *
 +       * But the primary bit is set above in any case.
 +       */
 +      if (sc->sc_ah->opmode != NL80211_IFTYPE_STATION)
 +              return;
 +
 +      ether_addr_copy(common->curbssid, bss_conf->bssid);
 +      common->curaid = bss_conf->aid;
 +      ath9k_hw_write_associd(sc->sc_ah);
  
 -      /* Get list of all active MAC addresses */
 -      ieee80211_iterate_active_interfaces_atomic(
 -              sc->hw, IEEE80211_IFACE_ITER_RESUME_ALL,
 -              ath9k_vif_iter, iter_data);
 +      if (changed) {
 +              common->last_rssi = ATH_RSSI_DUMMY_MARKER;
 +              sc->sc_ah->stats.avgbrssi = ATH_RSSI_DUMMY_MARKER;
  
 -      memcpy(common->macaddr, iter_data->hw_macaddr, ETH_ALEN);
 +              spin_lock_irqsave(&sc->sc_pm_lock, flags);
 +              sc->ps_flags |= PS_BEACON_SYNC | PS_WAIT_FOR_BEACON;
 +              spin_unlock_irqrestore(&sc->sc_pm_lock, flags);
 +      }
 +
 +      if (ath9k_hw_mci_is_enabled(sc->sc_ah))
 +              ath9k_mci_update_wlan_channels(sc, false);
 +
 +      ath_dbg(common, CONFIG,
 +              "Primary Station interface: %pM, BSSID: %pM\n",
 +              vif->addr, common->curbssid);
  }
  
  /* Called with sc->mutex held. */
 -static void ath9k_calculate_summary_state(struct ieee80211_hw *hw,
 -                                        struct ieee80211_vif *vif)
 +void ath9k_calculate_summary_state(struct ath_softc *sc,
 +                                 struct ath_chanctx *ctx)
  {
 -      struct ath_softc *sc = hw->priv;
        struct ath_hw *ah = sc->sc_ah;
        struct ath_common *common = ath9k_hw_common(ah);
        struct ath9k_vif_iter_data iter_data;
 -      enum nl80211_iftype old_opmode = ah->opmode;
  
 -      ath9k_calculate_iter_data(hw, vif, &iter_data);
 +      ath_chanctx_check_active(sc, ctx);
 +
 +      if (ctx != sc->cur_chan)
 +              return;
 +
 +      ath9k_ps_wakeup(sc);
 +      ath9k_calculate_iter_data(sc, ctx, &iter_data);
 +
 +      if (iter_data.has_hw_macaddr)
 +              ether_addr_copy(common->macaddr, iter_data.hw_macaddr);
  
        memcpy(common->bssidmask, iter_data.mask, ETH_ALEN);
        ath_hw_setbssidmask(common);
  
        ath9k_hw_setopmode(ah);
  
 +      ctx->switch_after_beacon = false;
        if ((iter_data.nstations + iter_data.nadhocs + iter_data.nmeshes) > 0)
                ah->imask |= ATH9K_INT_TSFOOR;
 -      else
 +      else {
                ah->imask &= ~ATH9K_INT_TSFOOR;
 +              if (iter_data.naps == 1 && iter_data.beacons)
 +                      ctx->switch_after_beacon = true;
 +      }
 +
 +      ah->imask &= ~ATH9K_INT_SWBA;
 +      if (ah->opmode == NL80211_IFTYPE_STATION) {
 +              bool changed = (iter_data.primary_sta != ctx->primary_sta);
  
 +              iter_data.beacons = true;
 +              if (iter_data.primary_sta) {
 +                      ath9k_set_assoc_state(sc, iter_data.primary_sta,
 +                                            changed);
 +                      if (!ctx->primary_sta ||
 +                          !ctx->primary_sta->bss_conf.assoc)
 +                              ctx->primary_sta = iter_data.primary_sta;
 +              } else {
 +                      ctx->primary_sta = NULL;
 +                      memset(common->curbssid, 0, ETH_ALEN);
 +                      common->curaid = 0;
 +                      ath9k_hw_write_associd(sc->sc_ah);
 +                      if (ath9k_hw_mci_is_enabled(sc->sc_ah))
 +                              ath9k_mci_update_wlan_channels(sc, true);
 +              }
 +      } else if (iter_data.beacons) {
 +              ah->imask |= ATH9K_INT_SWBA;
 +      }
        ath9k_hw_set_interrupts(ah);
  
 -      /*
 -       * If we are changing the opmode to STATION,
 -       * a beacon sync needs to be done.
 -       */
 -      if (ah->opmode == NL80211_IFTYPE_STATION &&
 -          old_opmode == NL80211_IFTYPE_AP &&
 -          test_bit(ATH_OP_PRIM_STA_VIF, &common->op_flags)) {
 -              ieee80211_iterate_active_interfaces_atomic(
 -                      sc->hw, IEEE80211_IFACE_ITER_RESUME_ALL,
 -                      ath9k_sta_vif_iter, sc);
 +      if (iter_data.beacons)
 +              set_bit(ATH_OP_BEACONS, &common->op_flags);
 +      else
 +              clear_bit(ATH_OP_BEACONS, &common->op_flags);
 +
 +      if (ah->slottime != iter_data.slottime) {
 +              ah->slottime = iter_data.slottime;
 +              ath9k_hw_init_global_settings(ah);
        }
 +
 +      if (iter_data.primary_sta)
 +              set_bit(ATH_OP_PRIM_STA_VIF, &common->op_flags);
 +      else
 +              clear_bit(ATH_OP_PRIM_STA_VIF, &common->op_flags);
 +
 +      ctx->primary_sta = iter_data.primary_sta;
 +
 +      ath9k_ps_restore(sc);
  }
  
  static int ath9k_add_interface(struct ieee80211_hw *hw,
        struct ath_common *common = ath9k_hw_common(ah);
        struct ath_vif *avp = (void *)vif->drv_priv;
        struct ath_node *an = &avp->mcast_node;
 +      int i;
  
        mutex_lock(&sc->mutex);
  
        ath_dbg(common, CONFIG, "Attach a VIF of type: %d\n", vif->type);
        sc->nvifs++;
  
 -      ath9k_ps_wakeup(sc);
 -      ath9k_calculate_summary_state(hw, vif);
 -      ath9k_ps_restore(sc);
 -
        if (ath9k_uses_beacons(vif->type))
                ath9k_beacon_assign_slot(sc, vif);
  
        avp->vif = vif;
 +      if (!ath9k_use_chanctx) {
 +              avp->chanctx = sc->cur_chan;
 +              list_add_tail(&avp->list, &avp->chanctx->vifs);
 +      }
 +      for (i = 0; i < IEEE80211_NUM_ACS; i++)
 +              vif->hw_queue[i] = i;
 +      if (vif->type == NL80211_IFTYPE_AP)
 +              vif->cab_queue = hw->queues - 2;
 +      else
 +              vif->cab_queue = IEEE80211_INVAL_HW_QUEUE;
  
        an->sc = sc;
        an->sta = NULL;
@@@ -1167,8 -1141,6 +1167,8 @@@ static int ath9k_change_interface(struc
  {
        struct ath_softc *sc = hw->priv;
        struct ath_common *common = ath9k_hw_common(sc->sc_ah);
 +      struct ath_vif *avp = (void *)vif->drv_priv;
 +      int i;
  
        mutex_lock(&sc->mutex);
  
        vif->type = new_type;
        vif->p2p = p2p;
  
 -      ath9k_ps_wakeup(sc);
 -      ath9k_calculate_summary_state(hw, vif);
 -      ath9k_ps_restore(sc);
 -
        if (ath9k_uses_beacons(vif->type))
                ath9k_beacon_assign_slot(sc, vif);
  
 +      for (i = 0; i < IEEE80211_NUM_ACS; i++)
 +              vif->hw_queue[i] = i;
 +
 +      if (vif->type == NL80211_IFTYPE_AP)
 +              vif->cab_queue = hw->queues - 2;
 +      else
 +              vif->cab_queue = IEEE80211_INVAL_HW_QUEUE;
 +
 +      ath9k_calculate_summary_state(sc, avp->chanctx);
 +
        mutex_unlock(&sc->mutex);
        return 0;
  }
@@@ -1245,12 -1211,14 +1245,12 @@@ static void ath9k_remove_interface(stru
  
        sc->nvifs--;
        sc->tx99_vif = NULL;
 +      if (!ath9k_use_chanctx)
 +              list_del(&avp->list);
  
        if (ath9k_uses_beacons(vif->type))
                ath9k_beacon_remove_slot(sc, vif);
  
 -      ath9k_ps_wakeup(sc);
 -      ath9k_calculate_summary_state(hw, NULL);
 -      ath9k_ps_restore(sc);
 -
        ath_tx_node_cleanup(sc, &avp->mcast_node);
  
        mutex_unlock(&sc->mutex);
@@@ -1377,7 -1345,7 +1377,7 @@@ static int ath9k_config(struct ieee8021
        struct ath_hw *ah = sc->sc_ah;
        struct ath_common *common = ath9k_hw_common(ah);
        struct ieee80211_conf *conf = &hw->conf;
 -      bool reset_channel = false;
 +      struct ath_chanctx *ctx = sc->cur_chan;
  
        ath9k_ps_wakeup(sc);
        mutex_lock(&sc->mutex);
                         * The chip needs a reset to properly wake up from
                         * full sleep
                         */
 -                      reset_channel = ah->chip_fullsleep;
 +                      ath_chanctx_set_channel(sc, ctx, &ctx->chandef);
                }
        }
  
                }
        }
  
 -      if ((changed & IEEE80211_CONF_CHANGE_CHANNEL) || reset_channel) {
 -              if (ath_set_channel(sc, &hw->conf.chandef) < 0) {
 -                      ath_err(common, "Unable to set channel\n");
 -                      mutex_unlock(&sc->mutex);
 -                      ath9k_ps_restore(sc);
 -                      return -EINVAL;
 -              }
 +      if (!ath9k_use_chanctx && (changed & IEEE80211_CONF_CHANGE_CHANNEL)) {
 +              ctx->offchannel = !!(conf->flags & IEEE80211_CONF_OFFCHANNEL);
 +              ath_chanctx_set_channel(sc, ctx, &hw->conf.chandef);
        }
  
        if (changed & IEEE80211_CONF_CHANGE_POWER) {
                ath_dbg(common, CONFIG, "Set power: %d\n", conf->power_level);
 -              sc->config.txpowlimit = 2 * conf->power_level;
 +              sc->cur_chan->txpower = 2 * conf->power_level;
                ath9k_cmn_update_txpow(ah, sc->curtxpow,
 -                                     sc->config.txpowlimit, &sc->curtxpow);
 +                                     sc->cur_chan->txpower, &sc->curtxpow);
        }
  
        mutex_unlock(&sc->mutex);
@@@ -1687,6 -1659,58 +1687,6 @@@ static int ath9k_set_key(struct ieee802
        return ret;
  }
  
 -static void ath9k_set_assoc_state(struct ath_softc *sc,
 -                                struct ieee80211_vif *vif)
 -{
 -      struct ath_common *common = ath9k_hw_common(sc->sc_ah);
 -      struct ath_vif *avp = (void *)vif->drv_priv;
 -      struct ieee80211_bss_conf *bss_conf = &vif->bss_conf;
 -      unsigned long flags;
 -
 -      set_bit(ATH_OP_PRIM_STA_VIF, &common->op_flags);
 -      avp->primary_sta_vif = true;
 -
 -      /*
 -       * Set the AID, BSSID and do beacon-sync only when
 -       * the HW opmode is STATION.
 -       *
 -       * But the primary bit is set above in any case.
 -       */
 -      if (sc->sc_ah->opmode != NL80211_IFTYPE_STATION)
 -              return;
 -
 -      memcpy(common->curbssid, bss_conf->bssid, ETH_ALEN);
 -      common->curaid = bss_conf->aid;
 -      ath9k_hw_write_associd(sc->sc_ah);
 -
 -      common->last_rssi = ATH_RSSI_DUMMY_MARKER;
 -      sc->sc_ah->stats.avgbrssi = ATH_RSSI_DUMMY_MARKER;
 -
 -      spin_lock_irqsave(&sc->sc_pm_lock, flags);
 -      sc->ps_flags |= PS_BEACON_SYNC | PS_WAIT_FOR_BEACON;
 -      spin_unlock_irqrestore(&sc->sc_pm_lock, flags);
 -
 -      if (ath9k_hw_mci_is_enabled(sc->sc_ah))
 -              ath9k_mci_update_wlan_channels(sc, false);
 -
 -      ath_dbg(common, CONFIG,
 -              "Primary Station interface: %pM, BSSID: %pM\n",
 -              vif->addr, common->curbssid);
 -}
 -
 -static void ath9k_bss_assoc_iter(void *data, u8 *mac, struct ieee80211_vif *vif)
 -{
 -      struct ath_softc *sc = data;
 -      struct ieee80211_bss_conf *bss_conf = &vif->bss_conf;
 -      struct ath_common *common = ath9k_hw_common(sc->sc_ah);
 -
 -      if (test_bit(ATH_OP_PRIM_STA_VIF, &common->op_flags))
 -              return;
 -
 -      if (bss_conf->assoc)
 -              ath9k_set_assoc_state(sc, vif);
 -}
 -
  void ath9k_p2p_ps_timer(void *priv)
  {
        struct ath_softc *sc = priv;
        struct ath_node *an;
        u32 tsf;
  
 -      if (!avp)
 +      del_timer_sync(&sc->sched.timer);
 +      ath9k_hw_gen_timer_stop(sc->sc_ah, sc->p2p_ps_timer);
 +      ath_chanctx_event(sc, NULL, ATH_CHANCTX_EVENT_TSF_TIMER);
 +
 +      if (!avp || avp->chanctx != sc->cur_chan)
                return;
  
        tsf = ath9k_hw_gettsf32(sc->sc_ah);
@@@ -1775,9 -1795,26 +1775,9 @@@ static void ath9k_bss_info_changed(stru
                ath_dbg(common, CONFIG, "BSSID %pM Changed ASSOC %d\n",
                        bss_conf->bssid, bss_conf->assoc);
  
 -              if (avp->primary_sta_vif && !bss_conf->assoc) {
 -                      clear_bit(ATH_OP_PRIM_STA_VIF, &common->op_flags);
 -                      avp->primary_sta_vif = false;
 -
 -                      if (ah->opmode == NL80211_IFTYPE_STATION)
 -                              clear_bit(ATH_OP_BEACONS, &common->op_flags);
 -              }
 -
 -              ieee80211_iterate_active_interfaces_atomic(
 -                      sc->hw, IEEE80211_IFACE_ITER_RESUME_ALL,
 -                      ath9k_bss_assoc_iter, sc);
 -
 -              if (!test_bit(ATH_OP_PRIM_STA_VIF, &common->op_flags) &&
 -                  ah->opmode == NL80211_IFTYPE_STATION) {
 -                      memset(common->curbssid, 0, ETH_ALEN);
 -                      common->curaid = 0;
 -                      ath9k_hw_write_associd(sc->sc_ah);
 -                      if (ath9k_hw_mci_is_enabled(sc->sc_ah))
 -                              ath9k_mci_update_wlan_channels(sc, true);
 -              }
 +              ath9k_calculate_summary_state(sc, avp->chanctx);
 +              if (bss_conf->assoc)
 +                      ath_chanctx_event(sc, vif, ATH_CHANCTX_EVENT_ASSOC);
        }
  
        if (changed & BSS_CHANGED_IBSS) {
        }
  
        if ((changed & BSS_CHANGED_BEACON_ENABLED) ||
 -          (changed & BSS_CHANGED_BEACON_INT))
 +          (changed & BSS_CHANGED_BEACON_INT)) {
 +              if (changed & BSS_CHANGED_BEACON_ENABLED)
 +                      ath9k_calculate_summary_state(sc, avp->chanctx);
                ath9k_beacon_config(sc, vif, changed);
 +      }
  
 -      if (changed & BSS_CHANGED_ERP_SLOT) {
 +      if ((avp->chanctx == sc->cur_chan) &&
 +          (changed & BSS_CHANGED_ERP_SLOT)) {
                if (bss_conf->use_short_slot)
                        slottime = 9;
                else
@@@ -1997,32 -2030,25 +1997,32 @@@ static bool ath9k_has_tx_pending(struc
  
  static void ath9k_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
                        u32 queues, bool drop)
 +{
 +      struct ath_softc *sc = hw->priv;
 +
 +      mutex_lock(&sc->mutex);
 +      __ath9k_flush(hw, queues, drop);
 +      mutex_unlock(&sc->mutex);
 +}
 +
 +void __ath9k_flush(struct ieee80211_hw *hw, u32 queues, bool drop)
  {
        struct ath_softc *sc = hw->priv;
        struct ath_hw *ah = sc->sc_ah;
        struct ath_common *common = ath9k_hw_common(ah);
        int timeout = HZ / 5; /* 200 ms */
        bool drain_txq;
 +      int i;
  
 -      mutex_lock(&sc->mutex);
        cancel_delayed_work_sync(&sc->tx_complete_work);
  
        if (ah->ah_flags & AH_UNPLUGGED) {
                ath_dbg(common, ANY, "Device has been unplugged!\n");
 -              mutex_unlock(&sc->mutex);
                return;
        }
  
        if (test_bit(ATH_OP_INVALID, &common->op_flags)) {
                ath_dbg(common, ANY, "Device not present\n");
 -              mutex_unlock(&sc->mutex);
                return;
        }
  
                        ath_reset(sc);
  
                ath9k_ps_restore(sc);
 -              ieee80211_wake_queues(hw);
 +              for (i = 0; i < IEEE80211_NUM_ACS; i++) {
 +                      ieee80211_wake_queue(sc->hw,
 +                                           sc->cur_chan->hw_queue_base + i);
 +              }
        }
  
        ieee80211_queue_delayed_work(hw, &sc->tx_complete_work, 0);
 -      mutex_unlock(&sc->mutex);
  }
  
  static bool ath9k_tx_frames_pending(struct ieee80211_hw *hw)
@@@ -2206,402 -2230,6 +2206,403 @@@ static void ath9k_sw_scan_complete(stru
        clear_bit(ATH_OP_SCANNING, &common->op_flags);
  }
  
-                        struct cfg80211_scan_request *req)
 +static int ath_scan_channel_duration(struct ath_softc *sc,
 +                                   struct ieee80211_channel *chan)
 +{
 +      struct cfg80211_scan_request *req = sc->offchannel.scan_req;
 +
 +      if (!req->n_ssids || (chan->flags & IEEE80211_CHAN_NO_IR))
 +              return (HZ / 9); /* ~110 ms */
 +
 +      return (HZ / 16); /* ~60 ms */
 +}
 +
 +static void
 +ath_scan_next_channel(struct ath_softc *sc)
 +{
 +      struct cfg80211_scan_request *req = sc->offchannel.scan_req;
 +      struct ieee80211_channel *chan;
 +
 +      if (sc->offchannel.scan_idx >= req->n_channels) {
 +              sc->offchannel.state = ATH_OFFCHANNEL_IDLE;
 +              ath_chanctx_switch(sc, ath_chanctx_get_oper_chan(sc, false),
 +                                 NULL);
 +              return;
 +      }
 +
 +      chan = req->channels[sc->offchannel.scan_idx++];
 +      sc->offchannel.duration = ath_scan_channel_duration(sc, chan);
 +      sc->offchannel.state = ATH_OFFCHANNEL_PROBE_SEND;
 +      ath_chanctx_offchan_switch(sc, chan);
 +}
 +
 +static void ath_offchannel_next(struct ath_softc *sc)
 +{
 +      struct ieee80211_vif *vif;
 +
 +      if (sc->offchannel.scan_req) {
 +              vif = sc->offchannel.scan_vif;
 +              sc->offchannel.chan.txpower = vif->bss_conf.txpower;
 +              ath_scan_next_channel(sc);
 +      } else if (sc->offchannel.roc_vif) {
 +              vif = sc->offchannel.roc_vif;
 +              sc->offchannel.chan.txpower = vif->bss_conf.txpower;
 +              sc->offchannel.duration = sc->offchannel.roc_duration;
 +              sc->offchannel.state = ATH_OFFCHANNEL_ROC_START;
 +              ath_chanctx_offchan_switch(sc, sc->offchannel.roc_chan);
 +      } else {
 +              ath_chanctx_switch(sc, ath_chanctx_get_oper_chan(sc, false),
 +                                 NULL);
 +              sc->offchannel.state = ATH_OFFCHANNEL_IDLE;
 +              if (sc->ps_idle)
 +                      ath_cancel_work(sc);
 +      }
 +}
 +
 +static void ath_roc_complete(struct ath_softc *sc, bool abort)
 +{
 +      sc->offchannel.roc_vif = NULL;
 +      sc->offchannel.roc_chan = NULL;
 +      if (!abort)
 +              ieee80211_remain_on_channel_expired(sc->hw);
 +      ath_offchannel_next(sc);
 +      ath9k_ps_restore(sc);
 +}
 +
 +static void ath_scan_complete(struct ath_softc *sc, bool abort)
 +{
 +      struct ath_common *common = ath9k_hw_common(sc->sc_ah);
 +
 +      sc->offchannel.scan_req = NULL;
 +      sc->offchannel.scan_vif = NULL;
 +      sc->offchannel.state = ATH_OFFCHANNEL_IDLE;
 +      ieee80211_scan_completed(sc->hw, abort);
 +      clear_bit(ATH_OP_SCANNING, &common->op_flags);
 +      ath_offchannel_next(sc);
 +      ath9k_ps_restore(sc);
 +}
 +
 +static void ath_scan_send_probe(struct ath_softc *sc,
 +                              struct cfg80211_ssid *ssid)
 +{
 +      struct cfg80211_scan_request *req = sc->offchannel.scan_req;
 +      struct ieee80211_vif *vif = sc->offchannel.scan_vif;
 +      struct ath_tx_control txctl = {};
 +      struct sk_buff *skb;
 +      struct ieee80211_tx_info *info;
 +      int band = sc->offchannel.chan.chandef.chan->band;
 +
 +      skb = ieee80211_probereq_get(sc->hw, vif,
 +                      ssid->ssid, ssid->ssid_len, req->ie_len);
 +      if (!skb)
 +              return;
 +
 +      info = IEEE80211_SKB_CB(skb);
 +      if (req->no_cck)
 +              info->flags |= IEEE80211_TX_CTL_NO_CCK_RATE;
 +
 +      if (req->ie_len)
 +              memcpy(skb_put(skb, req->ie_len), req->ie, req->ie_len);
 +
 +      skb_set_queue_mapping(skb, IEEE80211_AC_VO);
 +
 +      if (!ieee80211_tx_prepare_skb(sc->hw, vif, skb, band, NULL))
 +              goto error;
 +
 +      txctl.txq = sc->tx.txq_map[IEEE80211_AC_VO];
 +      txctl.force_channel = true;
 +      if (ath_tx_start(sc->hw, skb, &txctl))
 +              goto error;
 +
 +      return;
 +
 +error:
 +      ieee80211_free_txskb(sc->hw, skb);
 +}
 +
 +static void ath_scan_channel_start(struct ath_softc *sc)
 +{
 +      struct cfg80211_scan_request *req = sc->offchannel.scan_req;
 +      int i;
 +
 +      if (!(sc->cur_chan->chandef.chan->flags & IEEE80211_CHAN_NO_IR) &&
 +          req->n_ssids) {
 +              for (i = 0; i < req->n_ssids; i++)
 +                      ath_scan_send_probe(sc, &req->ssids[i]);
 +
 +      }
 +
 +      sc->offchannel.state = ATH_OFFCHANNEL_PROBE_WAIT;
 +      mod_timer(&sc->offchannel.timer, jiffies + sc->offchannel.duration);
 +}
 +
 +void ath_offchannel_channel_change(struct ath_softc *sc)
 +{
 +      switch (sc->offchannel.state) {
 +      case ATH_OFFCHANNEL_PROBE_SEND:
 +              if (!sc->offchannel.scan_req)
 +                      return;
 +
 +              if (sc->cur_chan->chandef.chan !=
 +                  sc->offchannel.chan.chandef.chan)
 +                      return;
 +
 +              ath_scan_channel_start(sc);
 +              break;
 +      case ATH_OFFCHANNEL_IDLE:
 +              if (!sc->offchannel.scan_req)
 +                      return;
 +
 +              ath_scan_complete(sc, false);
 +              break;
 +      case ATH_OFFCHANNEL_ROC_START:
 +              if (sc->cur_chan != &sc->offchannel.chan)
 +                      break;
 +
 +              sc->offchannel.state = ATH_OFFCHANNEL_ROC_WAIT;
 +              mod_timer(&sc->offchannel.timer, jiffies +
 +                        msecs_to_jiffies(sc->offchannel.duration));
 +              ieee80211_ready_on_channel(sc->hw);
 +              break;
 +      case ATH_OFFCHANNEL_ROC_DONE:
 +              ath_roc_complete(sc, false);
 +              break;
 +      default:
 +              break;
 +      }
 +}
 +
 +void ath_offchannel_timer(unsigned long data)
 +{
 +      struct ath_softc *sc = (struct ath_softc *)data;
 +      struct ath_chanctx *ctx;
 +
 +      switch (sc->offchannel.state) {
 +      case ATH_OFFCHANNEL_PROBE_WAIT:
 +              if (!sc->offchannel.scan_req)
 +                      return;
 +
 +              /* get first active channel context */
 +              ctx = ath_chanctx_get_oper_chan(sc, true);
 +              if (ctx->active) {
 +                      sc->offchannel.state = ATH_OFFCHANNEL_SUSPEND;
 +                      ath_chanctx_switch(sc, ctx, NULL);
 +                      mod_timer(&sc->offchannel.timer, jiffies + HZ / 10);
 +                      break;
 +              }
 +              /* fall through */
 +      case ATH_OFFCHANNEL_SUSPEND:
 +              if (!sc->offchannel.scan_req)
 +                      return;
 +
 +              ath_scan_next_channel(sc);
 +              break;
 +      case ATH_OFFCHANNEL_ROC_START:
 +      case ATH_OFFCHANNEL_ROC_WAIT:
 +              ctx = ath_chanctx_get_oper_chan(sc, false);
 +              sc->offchannel.state = ATH_OFFCHANNEL_ROC_DONE;
 +              ath_chanctx_switch(sc, ctx, NULL);
 +              break;
 +      default:
 +              break;
 +      }
 +}
 +
 +static int ath9k_hw_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
++                       struct ieee80211_scan_request *hw_req)
 +{
++      struct cfg80211_scan_request *req = &hw_req->req;
 +      struct ath_softc *sc = hw->priv;
 +      struct ath_common *common = ath9k_hw_common(sc->sc_ah);
 +      int ret = 0;
 +
 +      mutex_lock(&sc->mutex);
 +
 +      if (WARN_ON(sc->offchannel.scan_req)) {
 +              ret = -EBUSY;
 +              goto out;
 +      }
 +
 +      ath9k_ps_wakeup(sc);
 +      set_bit(ATH_OP_SCANNING, &common->op_flags);
 +      sc->offchannel.scan_vif = vif;
 +      sc->offchannel.scan_req = req;
 +      sc->offchannel.scan_idx = 0;
 +
 +      if (sc->offchannel.state == ATH_OFFCHANNEL_IDLE)
 +              ath_offchannel_next(sc);
 +
 +out:
 +      mutex_unlock(&sc->mutex);
 +
 +      return ret;
 +}
 +
 +static void ath9k_cancel_hw_scan(struct ieee80211_hw *hw,
 +                               struct ieee80211_vif *vif)
 +{
 +      struct ath_softc *sc = hw->priv;
 +
 +      mutex_lock(&sc->mutex);
 +      del_timer_sync(&sc->offchannel.timer);
 +      ath_scan_complete(sc, true);
 +      mutex_unlock(&sc->mutex);
 +}
 +
 +static int ath9k_remain_on_channel(struct ieee80211_hw *hw,
 +                                 struct ieee80211_vif *vif,
 +                                 struct ieee80211_channel *chan, int duration,
 +                                 enum ieee80211_roc_type type)
 +{
 +      struct ath_softc *sc = hw->priv;
 +      int ret = 0;
 +
 +      mutex_lock(&sc->mutex);
 +
 +      if (WARN_ON(sc->offchannel.roc_vif)) {
 +              ret = -EBUSY;
 +              goto out;
 +      }
 +
 +      ath9k_ps_wakeup(sc);
 +      sc->offchannel.roc_vif = vif;
 +      sc->offchannel.roc_chan = chan;
 +      sc->offchannel.roc_duration = duration;
 +
 +      if (sc->offchannel.state == ATH_OFFCHANNEL_IDLE)
 +              ath_offchannel_next(sc);
 +
 +out:
 +      mutex_unlock(&sc->mutex);
 +
 +      return ret;
 +}
 +
 +static int ath9k_cancel_remain_on_channel(struct ieee80211_hw *hw)
 +{
 +      struct ath_softc *sc = hw->priv;
 +
 +      mutex_lock(&sc->mutex);
 +
 +      del_timer_sync(&sc->offchannel.timer);
 +
 +      if (sc->offchannel.roc_vif) {
 +              if (sc->offchannel.state >= ATH_OFFCHANNEL_ROC_START)
 +                      ath_roc_complete(sc, true);
 +      }
 +
 +      mutex_unlock(&sc->mutex);
 +
 +      return 0;
 +}
 +
 +static int ath9k_add_chanctx(struct ieee80211_hw *hw,
 +                           struct ieee80211_chanctx_conf *conf)
 +{
 +      struct ath_softc *sc = hw->priv;
 +      struct ath_chanctx *ctx, **ptr;
 +      int pos;
 +
 +      mutex_lock(&sc->mutex);
 +
 +      ath_for_each_chanctx(sc, ctx) {
 +              if (ctx->assigned)
 +                      continue;
 +
 +              ptr = (void *) conf->drv_priv;
 +              *ptr = ctx;
 +              ctx->assigned = true;
 +              pos = ctx - &sc->chanctx[0];
 +              ctx->hw_queue_base = pos * IEEE80211_NUM_ACS;
 +              ath_chanctx_set_channel(sc, ctx, &conf->def);
 +              mutex_unlock(&sc->mutex);
 +              return 0;
 +      }
 +      mutex_unlock(&sc->mutex);
 +      return -ENOSPC;
 +}
 +
 +
 +static void ath9k_remove_chanctx(struct ieee80211_hw *hw,
 +                               struct ieee80211_chanctx_conf *conf)
 +{
 +      struct ath_softc *sc = hw->priv;
 +      struct ath_chanctx *ctx = ath_chanctx_get(conf);
 +
 +      mutex_lock(&sc->mutex);
 +      ctx->assigned = false;
 +      ctx->hw_queue_base = -1;
 +      ath_chanctx_event(sc, NULL, ATH_CHANCTX_EVENT_UNASSIGN);
 +      mutex_unlock(&sc->mutex);
 +}
 +
 +static void ath9k_change_chanctx(struct ieee80211_hw *hw,
 +                               struct ieee80211_chanctx_conf *conf,
 +                               u32 changed)
 +{
 +      struct ath_softc *sc = hw->priv;
 +      struct ath_chanctx *ctx = ath_chanctx_get(conf);
 +
 +      mutex_lock(&sc->mutex);
 +      ath_chanctx_set_channel(sc, ctx, &conf->def);
 +      mutex_unlock(&sc->mutex);
 +}
 +
 +static int ath9k_assign_vif_chanctx(struct ieee80211_hw *hw,
 +                                  struct ieee80211_vif *vif,
 +                                  struct ieee80211_chanctx_conf *conf)
 +{
 +      struct ath_softc *sc = hw->priv;
 +      struct ath_vif *avp = (void *)vif->drv_priv;
 +      struct ath_chanctx *ctx = ath_chanctx_get(conf);
 +      int i;
 +
 +      mutex_lock(&sc->mutex);
 +      avp->chanctx = ctx;
 +      list_add_tail(&avp->list, &ctx->vifs);
 +      ath9k_calculate_summary_state(sc, ctx);
 +      for (i = 0; i < IEEE80211_NUM_ACS; i++)
 +              vif->hw_queue[i] = ctx->hw_queue_base + i;
 +      mutex_unlock(&sc->mutex);
 +
 +      return 0;
 +}
 +
 +static void ath9k_unassign_vif_chanctx(struct ieee80211_hw *hw,
 +                                     struct ieee80211_vif *vif,
 +                                     struct ieee80211_chanctx_conf *conf)
 +{
 +      struct ath_softc *sc = hw->priv;
 +      struct ath_vif *avp = (void *)vif->drv_priv;
 +      struct ath_chanctx *ctx = ath_chanctx_get(conf);
 +      int ac;
 +
 +      mutex_lock(&sc->mutex);
 +      avp->chanctx = NULL;
 +      list_del(&avp->list);
 +      ath9k_calculate_summary_state(sc, ctx);
 +      for (ac = 0; ac < IEEE80211_NUM_ACS; ac++)
 +              vif->hw_queue[ac] = IEEE80211_INVAL_HW_QUEUE;
 +      mutex_unlock(&sc->mutex);
 +}
 +
 +void ath9k_fill_chanctx_ops(void)
 +{
 +      if (!ath9k_use_chanctx)
 +              return;
 +
 +      ath9k_ops.hw_scan = ath9k_hw_scan;
 +      ath9k_ops.cancel_hw_scan = ath9k_cancel_hw_scan;
 +      ath9k_ops.remain_on_channel  = ath9k_remain_on_channel;
 +      ath9k_ops.cancel_remain_on_channel = ath9k_cancel_remain_on_channel;
 +      ath9k_ops.add_chanctx        = ath9k_add_chanctx;
 +      ath9k_ops.remove_chanctx     = ath9k_remove_chanctx;
 +      ath9k_ops.change_chanctx     = ath9k_change_chanctx;
 +      ath9k_ops.assign_vif_chanctx = ath9k_assign_vif_chanctx;
 +      ath9k_ops.unassign_vif_chanctx = ath9k_unassign_vif_chanctx;
 +      ath9k_ops.mgd_prepare_tx = ath9k_chanctx_force_active;
 +}
 +
  struct ieee80211_ops ath9k_ops = {
        .tx                 = ath9k_tx,
        .start              = ath9k_start,
@@@ -42,6 -42,36 +42,6 @@@ static const struct ieee80211_iface_com
        .beacon_int_infra_match = true,
  };
  
 -static const struct ieee80211_regdomain mwifiex_world_regdom_custom = {
 -      .n_reg_rules = 7,
 -      .alpha2 =  "99",
 -      .reg_rules = {
 -              /* Channel 1 - 11 */
 -              REG_RULE(2412-10, 2462+10, 40, 3, 20, 0),
 -              /* Channel 12 - 13 */
 -              REG_RULE(2467-10, 2472+10, 20, 3, 20,
 -                       NL80211_RRF_NO_IR),
 -              /* Channel 14 */
 -              REG_RULE(2484-10, 2484+10, 20, 3, 20,
 -                       NL80211_RRF_NO_IR |
 -                       NL80211_RRF_NO_OFDM),
 -              /* Channel 36 - 48 */
 -              REG_RULE(5180-10, 5240+10, 40, 3, 20,
 -                       NL80211_RRF_NO_IR),
 -              /* Channel 149 - 165 */
 -              REG_RULE(5745-10, 5825+10, 40, 3, 20,
 -                       NL80211_RRF_NO_IR),
 -              /* Channel 52 - 64 */
 -              REG_RULE(5260-10, 5320+10, 40, 3, 30,
 -                       NL80211_RRF_NO_IR |
 -                       NL80211_RRF_DFS),
 -              /* Channel 100 - 140 */
 -              REG_RULE(5500-10, 5700+10, 40, 3, 30,
 -                       NL80211_RRF_NO_IR |
 -                       NL80211_RRF_DFS),
 -      }
 -};
 -
  /*
   * This function maps the nl802.11 channel type into driver channel type.
   *
@@@ -121,6 -151,7 +121,6 @@@ mwifiex_form_mgmt_frame(struct sk_buff 
        u8 addr[ETH_ALEN] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
        u16 pkt_len;
        u32 tx_control = 0, pkt_type = PKT_TYPE_MGMT;
 -      struct timeval tv;
  
        pkt_len = len + ETH_ALEN;
  
               len - sizeof(struct ieee80211_hdr_3addr));
  
        skb->priority = LOW_PRIO_TID;
 -      do_gettimeofday(&tv);
 -      skb->tstamp = timeval_to_ktime(tv);
 +      __net_timestamp(skb);
  
        return 0;
  }
@@@ -2451,16 -2483,6 +2451,16 @@@ static int mwifiex_cfg80211_suspend(str
                mef_entry->filter[filt_num].filt_type = TYPE_EQ;
                if (filt_num)
                        mef_entry->filter[filt_num].filt_action = TYPE_OR;
 +
 +              filt_num++;
 +              mef_entry->filter[filt_num].repeat = 16;
 +              memcpy(mef_entry->filter[filt_num].byte_seq, priv->curr_addr,
 +                     ETH_ALEN);
 +              mef_entry->filter[filt_num].byte_seq[MWIFIEX_MEF_MAX_BYTESEQ] =
 +                                                              ETH_ALEN;
 +              mef_entry->filter[filt_num].offset = 56;
 +              mef_entry->filter[filt_num].filt_type = TYPE_EQ;
 +              mef_entry->filter[filt_num].filt_action = TYPE_OR;
        }
  
        if (!mef_cfg.criteria)
@@@ -2609,7 -2631,8 +2609,8 @@@ static in
  mwifiex_cfg80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev,
                           const u8 *peer, u8 action_code, u8 dialog_token,
                           u16 status_code, u32 peer_capability,
-                          const u8 *extra_ies, size_t extra_ies_len)
+                          bool initiator, const u8 *extra_ies,
+                          size_t extra_ies_len)
  {
        struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
        int ret;
@@@ -2894,6 -2917,12 +2895,6 @@@ int mwifiex_register_cfg80211(struct mw
                wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS |
                                WIPHY_FLAG_TDLS_EXTERNAL_SETUP;
  
 -      wiphy->regulatory_flags |=
 -                      REGULATORY_CUSTOM_REG |
 -                      REGULATORY_STRICT_REG;
 -
 -      wiphy_apply_custom_regulatory(wiphy, &mwifiex_world_regdom_custom);
 -
  #ifdef CONFIG_PM
        wiphy->wowlan = &mwifiex_wowlan_support;
  #endif