Merge tag 'mac80211-next-for-davem-2016-02-26' into next2
authorEmmanuel Grumbach <emmanuel.grumbach@intel.com>
Sat, 27 Feb 2016 19:59:03 +0000 (21:59 +0200)
committerEmmanuel Grumbach <emmanuel.grumbach@intel.com>
Sat, 27 Feb 2016 19:59:03 +0000 (21:59 +0200)
Here's another round of updates for -next:
 * big A-MSDU RX performance improvement (avoid linearize of paged RX)
 * rfkill changes: cleanups, documentation, platform properties
 * basic PBSS support in cfg80211
 * MU-MIMO action frame processing support
 * BlockAck reordering & duplicate detection offload support
 * various cleanups & little fixes

1  2 
drivers/net/wireless/intel/iwlwifi/dvm/mac80211.c
drivers/net/wireless/intel/iwlwifi/mvm/d3.c
drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
drivers/net/wireless/intel/iwlwifi/mvm/tx.c

index 4db4cb7aa73aa8593b0a3061281ab2c013885690,151721e4040c9dc67951eb60fbf21fc19f187429..c63ea79571ff5f0d6b0bbfd07b4a6faba42f1593
@@@ -396,7 -396,7 +396,7 @@@ static int iwlagn_mac_suspend(struct ie
        iwl_write32(priv->trans, CSR_UCODE_DRV_GP1_SET,
                    CSR_UCODE_DRV_GP1_BIT_D3_CFG_COMPLETE);
  
 -      iwl_trans_d3_suspend(priv->trans, false);
 +      iwl_trans_d3_suspend(priv->trans, false, true);
  
        goto out;
  
@@@ -469,7 -469,7 +469,7 @@@ static int iwlagn_mac_resume(struct iee
        /* we'll clear ctx->vif during iwlagn_prepare_restart() */
        vif = ctx->vif;
  
 -      ret = iwl_trans_d3_resume(priv->trans, &d3_status, false);
 +      ret = iwl_trans_d3_resume(priv->trans, &d3_status, false, true);
        if (ret)
                goto out_unlock;
  
@@@ -732,12 -732,15 +732,15 @@@ static inline bool iwl_enable_tx_ampdu(
  
  static int iwlagn_mac_ampdu_action(struct ieee80211_hw *hw,
                                   struct ieee80211_vif *vif,
-                                  enum ieee80211_ampdu_mlme_action action,
-                                  struct ieee80211_sta *sta, u16 tid, u16 *ssn,
-                                  u8 buf_size, bool amsdu)
+                                  struct ieee80211_ampdu_params *params)
  {
        struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw);
        int ret = -EINVAL;
+       struct ieee80211_sta *sta = params->sta;
+       enum ieee80211_ampdu_mlme_action action = params->action;
+       u16 tid = params->tid;
+       u16 *ssn = &params->ssn;
+       u8 buf_size = params->buf_size;
        struct iwl_station_priv *sta_priv = (void *) sta->drv_priv;
  
        IWL_DEBUG_HT(priv, "A-MPDU action on addr %pM tid %d\n",
index 346376187ef849455ae1b60da0039cc2e48fd633,93e49586121440a68ff2fa60691f4b5ce3a9eecc..5214482a04030fc3ca0325891c7e9c8f9873b420
@@@ -7,7 -7,6 +7,7 @@@
   *
   * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
   * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
 + * Copyright(c) 2016   Intel Deutschland GmbH
   *
   * This program is free software; you can redistribute it and/or modify
   * it under the terms of version 2 of the GNU General Public License as
@@@ -34,7 -33,6 +34,7 @@@
   *
   * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
   * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
 + * Copyright(c) 2016   Intel Deutschland GmbH
   * All rights reserved.
   *
   * Redistribution and use in source and binary forms, with or without
@@@ -251,16 -249,19 +251,19 @@@ static void iwl_mvm_wowlan_program_keys
                return;
        case WLAN_CIPHER_SUITE_TKIP:
                if (sta) {
+                       u64 pn64;
                        tkip_sc = data->rsc_tsc->all_tsc_rsc.tkip.unicast_rsc;
                        tkip_tx_sc = &data->rsc_tsc->all_tsc_rsc.tkip.tsc;
  
                        rx_p1ks = data->tkip->rx_uni;
  
-                       ieee80211_get_key_tx_seq(key, &seq);
-                       tkip_tx_sc->iv16 = cpu_to_le16(seq.tkip.iv16);
-                       tkip_tx_sc->iv32 = cpu_to_le32(seq.tkip.iv32);
+                       pn64 = atomic64_read(&key->tx_pn);
+                       tkip_tx_sc->iv16 = cpu_to_le16(TKIP_PN_TO_IV16(pn64));
+                       tkip_tx_sc->iv32 = cpu_to_le32(TKIP_PN_TO_IV32(pn64));
  
-                       ieee80211_get_tkip_p1k_iv(key, seq.tkip.iv32, p1k);
+                       ieee80211_get_tkip_p1k_iv(key, TKIP_PN_TO_IV32(pn64),
+                                                 p1k);
                        iwl_mvm_convert_p1k(p1k, data->tkip->tx.p1k);
  
                        memcpy(data->tkip->mic_keys.tx,
@@@ -853,8 -854,7 +856,8 @@@ iwl_mvm_get_wowlan_config(struct iwl_mv
        wowlan_config_cmd->is_11n_connection =
                                        ap_sta->ht_cap.ht_supported;
        wowlan_config_cmd->flags = ENABLE_L3_FILTERING |
 -              ENABLE_NBNS_FILTERING | ENABLE_DHCP_FILTERING;
 +              ENABLE_NBNS_FILTERING | ENABLE_DHCP_FILTERING |
 +              ENABLE_STORE_BEACON;
  
        /* Query the last used seqno and set it */
        ret = iwl_mvm_get_last_nonqos_seq(mvm, vif);
@@@ -1026,18 -1026,14 +1029,18 @@@ iwl_mvm_wowlan_config(struct iwl_mvm *m
                      struct ieee80211_sta *ap_sta)
  {
        int ret;
 +      bool unified_image = fw_has_capa(&mvm->fw->ucode_capa,
 +                                       IWL_UCODE_TLV_CAPA_CNSLDTD_D3_D0_IMG);
  
 -      ret = iwl_mvm_switch_to_d3(mvm);
 -      if (ret)
 -              return ret;
 +      if (!unified_image) {
 +              ret = iwl_mvm_switch_to_d3(mvm);
 +              if (ret)
 +                      return ret;
  
 -      ret = iwl_mvm_d3_reprogram(mvm, vif, ap_sta);
 -      if (ret)
 -              return ret;
 +              ret = iwl_mvm_d3_reprogram(mvm, vif, ap_sta);
 +              if (ret)
 +                      return ret;
 +      }
  
        if (!iwlwifi_mod_params.sw_crypto) {
                /*
@@@ -1079,14 -1075,10 +1082,14 @@@ iwl_mvm_netdetect_config(struct iwl_mv
  {
        struct iwl_wowlan_config_cmd wowlan_config_cmd = {};
        int ret;
 +      bool unified_image = fw_has_capa(&mvm->fw->ucode_capa,
 +                                       IWL_UCODE_TLV_CAPA_CNSLDTD_D3_D0_IMG);
  
 -      ret = iwl_mvm_switch_to_d3(mvm);
 -      if (ret)
 -              return ret;
 +      if (!unified_image) {
 +              ret = iwl_mvm_switch_to_d3(mvm);
 +              if (ret)
 +                      return ret;
 +      }
  
        /* rfkill release can be either for wowlan or netdetect */
        if (wowlan->rfkill_release)
@@@ -1162,8 -1154,6 +1165,8 @@@ static int __iwl_mvm_suspend(struct iee
        };
        int ret;
        int len __maybe_unused;
 +      bool unified_image = fw_has_capa(&mvm->fw->ucode_capa,
 +                                       IWL_UCODE_TLV_CAPA_CNSLDTD_D3_D0_IMG);
  
        if (!wowlan) {
                /*
  
        clear_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status);
  
 -      iwl_trans_d3_suspend(mvm->trans, test);
 +      iwl_trans_d3_suspend(mvm->trans, test, !unified_image);
   out:
        if (ret < 0) {
                iwl_mvm_ref(mvm, IWL_MVM_REF_UCODE_DOWN);
@@@ -1312,7 -1302,7 +1315,7 @@@ int iwl_mvm_suspend(struct ieee80211_h
                __set_bit(D0I3_DEFER_WAKEUP, &mvm->d0i3_suspend_flags);
                mutex_unlock(&mvm->d0i3_suspend_mutex);
  
 -              iwl_trans_d3_suspend(trans, false);
 +              iwl_trans_d3_suspend(trans, false, false);
  
                return 0;
        }
@@@ -1614,7 -1604,9 +1617,9 @@@ static void iwl_mvm_d3_update_keys(stru
                case WLAN_CIPHER_SUITE_TKIP:
                        iwl_mvm_tkip_sc_to_seq(&sc->tkip.tsc, &seq);
                        iwl_mvm_set_tkip_rx_seq(sc->tkip.unicast_rsc, key);
-                       ieee80211_set_key_tx_seq(key, &seq);
+                       atomic64_set(&key->tx_pn,
+                                    (u64)seq.tkip.iv16 |
+                                    ((u64)seq.tkip.iv32 << 16));
                        break;
                }
  
@@@ -2054,14 -2046,9 +2059,14 @@@ static void iwl_mvm_d3_disconnect_iter(
  static int __iwl_mvm_resume(struct iwl_mvm *mvm, bool test)
  {
        struct ieee80211_vif *vif = NULL;
 -      int ret;
 +      int ret = 1;
        enum iwl_d3_status d3_status;
        bool keep = false;
 +      bool unified_image = fw_has_capa(&mvm->fw->ucode_capa,
 +                                       IWL_UCODE_TLV_CAPA_CNSLDTD_D3_D0_IMG);
 +
 +      u32 flags = CMD_ASYNC | CMD_HIGH_PRIO | CMD_SEND_IN_IDLE |
 +                                  CMD_WAKE_UP_TRANS;
  
        mutex_lock(&mvm->mutex);
  
        if (IS_ERR_OR_NULL(vif))
                goto err;
  
 -      ret = iwl_trans_d3_resume(mvm->trans, &d3_status, test);
 +      ret = iwl_trans_d3_resume(mvm->trans, &d3_status, test, !unified_image);
        if (ret)
                goto err;
  
@@@ -2113,28 -2100,17 +2118,28 @@@ out_iterate
                        iwl_mvm_d3_disconnect_iter, keep ? vif : NULL);
  
  out:
 -      /* return 1 to reconfigure the device */
 +      if (unified_image && !ret) {
 +              ret = iwl_mvm_send_cmd_pdu(mvm, D0I3_END_CMD, flags, 0, NULL);
 +              if (!ret) /* D3 ended successfully - no need to reset device */
 +                      return 0;
 +      }
 +
 +      /*
 +       * Reconfigure the device in one of the following cases:
 +       * 1. We are not using a unified image
 +       * 2. We are using a unified image but had an error while exiting D3
 +       */
        set_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status);
        set_bit(IWL_MVM_STATUS_D3_RECONFIG, &mvm->status);
 -
 -      /* We always return 1, which causes mac80211 to do a reconfig
 -       * with IEEE80211_RECONFIG_TYPE_RESTART.  This type of
 -       * reconfig calls iwl_mvm_restart_complete(), where we unref
 -       * the IWL_MVM_REF_UCODE_DOWN, so we need to take the
 -       * reference here.
 +      /*
 +       * When switching images we return 1, which causes mac80211
 +       * to do a reconfig with IEEE80211_RECONFIG_TYPE_RESTART.
 +       * This type of reconfig calls iwl_mvm_restart_complete(),
 +       * where we unref the IWL_MVM_REF_UCODE_DOWN, so we need
 +       * to take the reference here.
         */
        iwl_mvm_ref(mvm, IWL_MVM_REF_UCODE_DOWN);
 +
        return 1;
  }
  
@@@ -2151,7 -2127,7 +2156,7 @@@ static int iwl_mvm_resume_d0i3(struct i
        enum iwl_d3_status d3_status;
        struct iwl_trans *trans = mvm->trans;
  
 -      iwl_trans_d3_resume(trans, &d3_status, false);
 +      iwl_trans_d3_resume(trans, &d3_status, false, false);
  
        /*
         * make sure to clear D0I3_DEFER_WAKEUP before
index 01476f5456956b199b262d58efa840eda62dbdb2,2b532925781aafe6675b0705e0226413becd25fc..53156810185d432a1192061ee1c39ede81112a40
@@@ -837,13 -837,16 +837,16 @@@ iwl_mvm_ampdu_check_trigger(struct iwl_
  
  static int iwl_mvm_mac_ampdu_action(struct ieee80211_hw *hw,
                                    struct ieee80211_vif *vif,
-                                   enum ieee80211_ampdu_mlme_action action,
-                                   struct ieee80211_sta *sta, u16 tid,
-                                   u16 *ssn, u8 buf_size, bool amsdu)
+                                   struct ieee80211_ampdu_params *params)
  {
        struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
        int ret;
        bool tx_agg_ref = false;
+       struct ieee80211_sta *sta = params->sta;
+       enum ieee80211_ampdu_mlme_action action = params->action;
+       u16 tid = params->tid;
+       u16 *ssn = &params->ssn;
+       u8 buf_size = params->buf_size;
  
        IWL_DEBUG_HT(mvm, "A-MPDU action on addr %pM tid %d: action %d\n",
                     sta->addr, tid, action);
                        ret = -EINVAL;
                        break;
                }
 -              ret = iwl_mvm_sta_rx_agg(mvm, sta, tid, *ssn, true);
 +              ret = iwl_mvm_sta_rx_agg(mvm, sta, tid, *ssn, true, buf_size);
                break;
        case IEEE80211_AMPDU_RX_STOP:
 -              ret = iwl_mvm_sta_rx_agg(mvm, sta, tid, 0, false);
 +              ret = iwl_mvm_sta_rx_agg(mvm, sta, tid, 0, false, buf_size);
                break;
        case IEEE80211_AMPDU_TX_START:
                if (!iwl_enable_tx_ampdu(mvm->cfg)) {
@@@ -2582,7 -2585,7 +2585,7 @@@ static int iwl_mvm_mac_set_key(struct i
        switch (key->cipher) {
        case WLAN_CIPHER_SUITE_TKIP:
                key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC;
-               key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
+               key->flags |= IEEE80211_KEY_FLAG_PUT_IV_SPACE;
                break;
        case WLAN_CIPHER_SUITE_CCMP:
                key->flags |= IEEE80211_KEY_FLAG_PUT_IV_SPACE;
index 5d73db2534a0a24a54d9edd07c341bc28822a7de,ca1e485a6adc9b5dc9f9863e31f4714bc47d565c..caec54ba617a12e6b8bf8f3172425a493f15a26c
@@@ -299,6 -299,8 +299,8 @@@ static void iwl_mvm_set_tx_cmd_crypto(s
  
        case WLAN_CIPHER_SUITE_TKIP:
                tx_cmd->sec_ctl = TX_CMD_SEC_TKIP;
+               pn = atomic64_inc_return(&keyconf->tx_pn);
+               ieee80211_tkip_add_iv(crypto_hdr, keyconf, pn);
                ieee80211_get_tkip_p2k(keyconf, skb_frag, tx_cmd->key);
                break;
  
@@@ -736,37 -738,6 +738,37 @@@ static void iwl_mvm_hwrate_to_tx_status
        iwl_mvm_hwrate_to_tx_rate(rate_n_flags, info->band, r);
  }
  
 +static void iwl_mvm_tx_status_check_trigger(struct iwl_mvm *mvm,
 +                                          u32 status)
 +{
 +      struct iwl_fw_dbg_trigger_tlv *trig;
 +      struct iwl_fw_dbg_trigger_tx_status *status_trig;
 +      int i;
 +
 +      if (!iwl_fw_dbg_trigger_enabled(mvm->fw, FW_DBG_TRIGGER_TX_STATUS))
 +              return;
 +
 +      trig = iwl_fw_dbg_get_trigger(mvm->fw, FW_DBG_TRIGGER_TX_STATUS);
 +      status_trig = (void *)trig->data;
 +
 +      if (!iwl_fw_dbg_trigger_check_stop(mvm, NULL, trig))
 +              return;
 +
 +      for (i = 0; i < ARRAY_SIZE(status_trig->statuses); i++) {
 +              /* don't collect on status 0 */
 +              if (!status_trig->statuses[i].status)
 +                      break;
 +
 +              if (status_trig->statuses[i].status != (status & TX_STATUS_MSK))
 +                      continue;
 +
 +              iwl_mvm_fw_dbg_collect_trig(mvm, trig,
 +                                          "Tx status %d was received",
 +                                          status & TX_STATUS_MSK);
 +              break;
 +      }
 +}
 +
  static void iwl_mvm_rx_tx_cmd_single(struct iwl_mvm *mvm,
                                     struct iwl_rx_packet *pkt)
  {
                        break;
                }
  
 +              iwl_mvm_tx_status_check_trigger(mvm, status);
 +
                info->status.rates[0].count = tx_resp->failure_frame + 1;
                iwl_mvm_hwrate_to_tx_status(le32_to_cpu(tx_resp->initial_rate),
                                            info);