Merge remote-tracking branch 'wireless-next/master' into iwlwifi-next
authorEmmanuel Grumbach <emmanuel.grumbach@intel.com>
Sun, 23 Nov 2014 17:56:35 +0000 (19:56 +0200)
committerEmmanuel Grumbach <emmanuel.grumbach@intel.com>
Sun, 23 Nov 2014 17:56:35 +0000 (19:56 +0200)
1  2 
drivers/net/wireless/iwlwifi/mvm/fw.c
drivers/net/wireless/iwlwifi/mvm/mac80211.c
drivers/net/wireless/iwlwifi/mvm/mvm.h
drivers/net/wireless/iwlwifi/mvm/ops.c
drivers/net/wireless/iwlwifi/pcie/trans.c

index 8c96e5af75f7e51136407a37a99ac0e48e4212cf,eb03943f846326207061a2ed63e95df09af93caf..f12b43d65f66884851699c65c19f1f4364013e62
@@@ -227,10 -227,6 +227,10 @@@ static int iwl_mvm_load_ucode_wait_aliv
        st_fwrd_space.addr = mvm->sf_space.addr;
        st_fwrd_space.size = mvm->sf_space.size;
        ret = iwl_trans_update_sf(mvm->trans, &st_fwrd_space);
 +      if (ret) {
 +              IWL_ERR(mvm, "Failed to update SF size. ret %d\n", ret);
 +              return ret;
 +      }
  
        iwl_trans_fw_alive(mvm->trans, alive_data.scd_base_addr);
  
@@@ -288,7 -284,7 +288,7 @@@ int iwl_run_init_mvm_ucode(struct iwl_m
  
        lockdep_assert_held(&mvm->mutex);
  
-       if (WARN_ON_ONCE(mvm->init_ucode_complete))
+       if (WARN_ON_ONCE(mvm->init_ucode_complete || mvm->calibrating))
                return 0;
  
        iwl_init_notification_wait(&mvm->notif_wait,
                goto out;
        }
  
+       mvm->calibrating = true;
        /* Send TX valid antennas before triggering calibrations */
        ret = iwl_send_tx_ant_cfg(mvm, mvm->fw->valid_tx_ant);
        if (ret)
                        MVM_UCODE_CALIB_TIMEOUT);
        if (!ret)
                mvm->init_ucode_complete = true;
+       if (ret && iwl_mvm_is_radio_killed(mvm)) {
+               IWL_DEBUG_RF_KILL(mvm, "RFKILL while calibrating.\n");
+               ret = 1;
+       }
        goto out;
  
  error:
        iwl_remove_notification(&mvm->notif_wait, &calib_wait);
  out:
+       mvm->calibrating = false;
        if (iwlmvm_mod_params.init_dbg && !mvm->nvm_data) {
                /* we want to debug INIT and we have no NVM - fake */
                mvm->nvm_data = kzalloc(sizeof(struct iwl_nvm_data) +
index ed2c219cf5434225c69e180dc446a28759981504,57325589ee5bcba07d315983e517b3e73ff82499..92e1810864b1f654a6b6b85c48394cc2d5dc1930
@@@ -254,26 -254,6 +254,26 @@@ static void iwl_mvm_unref_all_except(st
        spin_unlock_bh(&mvm->refs_lock);
  }
  
 +bool iwl_mvm_ref_taken(struct iwl_mvm *mvm)
 +{
 +      int i;
 +      bool taken = false;
 +
 +      if (!iwl_mvm_is_d0i3_supported(mvm))
 +              return true;
 +
 +      spin_lock_bh(&mvm->refs_lock);
 +      for (i = 0; i < IWL_MVM_REF_COUNT; i++) {
 +              if (mvm->refs[i]) {
 +                      taken = true;
 +                      break;
 +              }
 +      }
 +      spin_unlock_bh(&mvm->refs_lock);
 +
 +      return taken;
 +}
 +
  int iwl_mvm_ref_sync(struct iwl_mvm *mvm, enum iwl_mvm_ref_type ref_type)
  {
        iwl_mvm_ref(mvm, ref_type);
@@@ -839,17 -819,13 +839,18 @@@ void iwl_mvm_fw_error_dump(struct iwl_m
  
  static void iwl_mvm_restart_cleanup(struct iwl_mvm *mvm)
  {
 -      iwl_mvm_fw_error_dump(mvm);
 +      /* clear the D3 reconfig, we only need it to avoid dumping a
 +       * firmware coredump on reconfiguration, we shouldn't do that
 +       * on D3->D0 transition
 +       */
 +      if (!test_and_clear_bit(IWL_MVM_STATUS_D3_RECONFIG, &mvm->status))
 +              iwl_mvm_fw_error_dump(mvm);
  
        iwl_trans_stop_device(mvm->trans);
  
        mvm->scan_status = IWL_MVM_SCAN_NONE;
        mvm->ps_disabled = false;
+       mvm->calibrating = false;
  
        /* just in case one was running */
        ieee80211_remain_on_channel_expired(mvm->hw);
@@@ -920,9 -896,8 +921,8 @@@ static int iwl_mvm_mac_start(struct iee
        return ret;
  }
  
- static void iwl_mvm_mac_restart_complete(struct ieee80211_hw *hw)
+ static void iwl_mvm_restart_complete(struct iwl_mvm *mvm)
  {
-       struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
        int ret;
  
        mutex_lock(&mvm->mutex);
        mutex_unlock(&mvm->mutex);
  }
  
+ static void
+ iwl_mvm_mac_reconfig_complete(struct ieee80211_hw *hw,
+                             enum ieee80211_reconfig_type reconfig_type)
+ {
+       struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
+       switch (reconfig_type) {
+       case IEEE80211_RECONFIG_TYPE_RESTART:
+               iwl_mvm_restart_complete(mvm);
+               break;
+       case IEEE80211_RECONFIG_TYPE_SUSPEND:
+               break;
+       }
+ }
  void __iwl_mvm_mac_stop(struct iwl_mvm *mvm)
  {
        lockdep_assert_held(&mvm->mutex);
@@@ -3083,7 -3073,7 +3098,7 @@@ const struct ieee80211_ops iwl_mvm_hw_o
        .tx = iwl_mvm_mac_tx,
        .ampdu_action = iwl_mvm_mac_ampdu_action,
        .start = iwl_mvm_mac_start,
-       .restart_complete = iwl_mvm_mac_restart_complete,
+       .reconfig_complete = iwl_mvm_mac_reconfig_complete,
        .stop = iwl_mvm_mac_stop,
        .add_interface = iwl_mvm_mac_add_interface,
        .remove_interface = iwl_mvm_mac_remove_interface,
index 7d2c5289464bad62fc8361447f30467678735575,d015fac06a62ae2fc144b38ffbebe59d060b5617..09b49b407a5bd705efe7e617d610d8a430b89466
@@@ -548,6 -548,7 +548,7 @@@ struct iwl_mvm 
        enum iwl_ucode_type cur_ucode;
        bool ucode_loaded;
        bool init_ucode_complete;
+       bool calibrating;
        u32 error_event_table;
        u32 log_event_table;
        u32 umac_error_event_table;
@@@ -750,7 -751,6 +751,7 @@@ enum iwl_mvm_status 
        IWL_MVM_STATUS_IN_HW_RESTART,
        IWL_MVM_STATUS_IN_D0I3,
        IWL_MVM_STATUS_ROC_AUX_RUNNING,
 +      IWL_MVM_STATUS_D3_RECONFIG,
  };
  
  static inline bool iwl_mvm_is_radio_killed(struct iwl_mvm *mvm)
@@@ -832,16 -832,6 +833,16 @@@ int __must_check iwl_mvm_send_cmd_pdu_s
  int iwl_mvm_tx_skb(struct iwl_mvm *mvm, struct sk_buff *skb,
                   struct ieee80211_sta *sta);
  int iwl_mvm_tx_skb_non_sta(struct iwl_mvm *mvm, struct sk_buff *skb);
 +void iwl_mvm_set_tx_cmd(struct iwl_mvm *mvm, struct sk_buff *skb,
 +                      struct iwl_tx_cmd *tx_cmd,
 +                      struct ieee80211_tx_info *info, u8 sta_id);
 +void iwl_mvm_set_tx_cmd_crypto(struct iwl_mvm *mvm,
 +                             struct ieee80211_tx_info *info,
 +                             struct iwl_tx_cmd *tx_cmd,
 +                             struct sk_buff *skb_frag);
 +void iwl_mvm_set_tx_cmd_rate(struct iwl_mvm *mvm, struct iwl_tx_cmd *tx_cmd,
 +                          struct ieee80211_tx_info *info,
 +                          struct ieee80211_sta *sta, __le16 fc);
  #ifdef CONFIG_IWLWIFI_DEBUG
  const char *iwl_mvm_get_tx_fail_reason(u32 status);
  #else
@@@ -911,8 -901,6 +912,8 @@@ void iwl_mvm_phy_ctxt_ref(struct iwl_mv
  void iwl_mvm_phy_ctxt_unref(struct iwl_mvm *mvm,
                            struct iwl_mvm_phy_ctxt *ctxt);
  int iwl_mvm_phy_ctx_count(struct iwl_mvm *mvm);
 +u8 iwl_mvm_get_channel_width(struct cfg80211_chan_def *chandef);
 +u8 iwl_mvm_get_ctrl_pos(struct cfg80211_chan_def *chandef);
  
  /* MAC (virtual interface) programming */
  int iwl_mvm_mac_ctxt_init(struct iwl_mvm *mvm, struct ieee80211_vif *vif);
@@@ -1071,7 -1059,6 +1072,7 @@@ int iwl_mvm_send_proto_offload(struct i
  void iwl_mvm_ref(struct iwl_mvm *mvm, enum iwl_mvm_ref_type ref_type);
  void iwl_mvm_unref(struct iwl_mvm *mvm, enum iwl_mvm_ref_type ref_type);
  int iwl_mvm_ref_sync(struct iwl_mvm *mvm, enum iwl_mvm_ref_type ref_type);
 +bool iwl_mvm_ref_taken(struct iwl_mvm *mvm);
  void iwl_mvm_d0i3_enable_tx(struct iwl_mvm *mvm, __le16 *qos_seq);
  int _iwl_mvm_exit_d0i3(struct iwl_mvm *mvm);
  
@@@ -1087,14 -1074,12 +1088,14 @@@ u16 iwl_mvm_coex_agg_time_limit(struct 
                                struct ieee80211_sta *sta);
  bool iwl_mvm_bt_coex_is_mimo_allowed(struct iwl_mvm *mvm,
                                     struct ieee80211_sta *sta);
 +bool iwl_mvm_bt_coex_is_ant_avail(struct iwl_mvm *mvm, u8 ant);
  bool iwl_mvm_bt_coex_is_shared_ant_avail(struct iwl_mvm *mvm);
  bool iwl_mvm_bt_coex_is_tpc_allowed(struct iwl_mvm *mvm,
                                    enum ieee80211_band band);
  u8 iwl_mvm_bt_coex_tx_prio(struct iwl_mvm *mvm, struct ieee80211_hdr *hdr,
                           struct ieee80211_tx_info *info, u8 ac);
  
 +bool iwl_mvm_bt_coex_is_ant_avail_old(struct iwl_mvm *mvm, u8 ant);
  bool iwl_mvm_bt_coex_is_shared_ant_avail_old(struct iwl_mvm *mvm);
  void iwl_mvm_bt_coex_vif_change_old(struct iwl_mvm *mvm);
  int iwl_send_bt_init_conf_old(struct iwl_mvm *mvm);
@@@ -1210,10 -1195,6 +1211,10 @@@ bool iwl_mvm_is_idle(struct iwl_mvm *mv
  
  /* Thermal management and CT-kill */
  void iwl_mvm_tt_tx_backoff(struct iwl_mvm *mvm, u32 backoff);
 +void iwl_mvm_tt_temp_changed(struct iwl_mvm *mvm, u32 temp);
 +int iwl_mvm_temp_notif(struct iwl_mvm *mvm,
 +                     struct iwl_rx_cmd_buffer *rxb,
 +                     struct iwl_device_cmd *cmd);
  void iwl_mvm_tt_handler(struct iwl_mvm *mvm);
  void iwl_mvm_tt_initialize(struct iwl_mvm *mvm, u32 min_backoff);
  void iwl_mvm_tt_exit(struct iwl_mvm *mvm);
index 8664f617f6e78177edb4200cccadac7be7c6c16d,7a9578567f4f0853a0e560fb05c7ebb6377492c1..53a5a29897b4632a83960cfe8b47fd1ce3487fb4
@@@ -254,8 -254,6 +254,8 @@@ static const struct iwl_rx_handlers iwl
        RX_HANDLER(REPLY_ERROR, iwl_mvm_rx_fw_error, false),
        RX_HANDLER(PSM_UAPSD_AP_MISBEHAVING_NOTIFICATION,
                   iwl_mvm_power_uapsd_misbehaving_ap_notif, false),
 +      RX_HANDLER(DTS_MEASUREMENT_NOTIFICATION, iwl_mvm_temp_notif, true),
 +
  };
  #undef RX_HANDLER
  #define CMD(x) [x] = #x
@@@ -429,6 -427,7 +429,7 @@@ iwl_op_mode_mvm_start(struct iwl_trans 
        }
        mvm->sf_state = SF_UNINIT;
        mvm->low_latency_agg_frame_limit = 6;
+       mvm->cur_ucode = IWL_UCODE_INIT;
  
        mutex_init(&mvm->mutex);
        mutex_init(&mvm->d0i3_suspend_mutex);
  
                mutex_lock(&mvm->mutex);
                err = iwl_run_init_mvm_ucode(mvm, true);
 -              iwl_trans_stop_device(trans);
 +              if (!err || !iwlmvm_mod_params.init_dbg)
 +                      iwl_trans_stop_device(trans);
                mutex_unlock(&mvm->mutex);
                /* returns 0 if successful, 1 if success but in rfkill */
                if (err < 0 && !iwlmvm_mod_params.init_dbg) {
@@@ -760,6 -758,7 +761,7 @@@ void iwl_mvm_set_hw_ctkill_state(struc
  static bool iwl_mvm_set_hw_rfkill_state(struct iwl_op_mode *op_mode, bool state)
  {
        struct iwl_mvm *mvm = IWL_OP_MODE_GET_MVM(op_mode);
+       bool calibrating = ACCESS_ONCE(mvm->calibrating);
  
        if (state)
                set_bit(IWL_MVM_STATUS_HW_RFKILL, &mvm->status);
  
        wiphy_rfkill_set_hw_state(mvm->hw->wiphy, iwl_mvm_is_radio_killed(mvm));
  
-       return state && mvm->cur_ucode != IWL_UCODE_INIT;
+       /* iwl_run_init_mvm_ucode is waiting for results, abort it */
+       if (calibrating)
+               iwl_abort_notification_waits(&mvm->notif_wait);
+       /*
+        * Stop the device if we run OPERATIONAL firmware or if we are in the
+        * middle of the calibrations.
+        */
+       return state && (mvm->cur_ucode != IWL_UCODE_INIT || calibrating);
  }
  
  static void iwl_mvm_free_skb(struct iwl_op_mode *op_mode, struct sk_buff *skb)
@@@ -1043,19 -1050,6 +1053,19 @@@ static int iwl_mvm_enter_d0i3(struct iw
        set_bit(IWL_MVM_STATUS_IN_D0I3, &mvm->status);
        synchronize_net();
  
 +      /*
 +       * iwl_mvm_ref_sync takes a reference before checking the flag.
 +       * so by checking there is no held reference we prevent a state
 +       * in which iwl_mvm_ref_sync continues successfully while we
 +       * configure the firmware to enter d0i3
 +       */
 +      if (iwl_mvm_ref_taken(mvm)) {
 +              IWL_DEBUG_RPM(mvm->trans, "abort d0i3 due to taken ref\n");
 +              clear_bit(IWL_MVM_STATUS_IN_D0I3, &mvm->status);
 +              wake_up(&mvm->d0i3_exit_waitq);
 +              return 1;
 +      }
 +
        ieee80211_iterate_active_interfaces_atomic(mvm->hw,
                                                   IEEE80211_IFACE_ITER_NORMAL,
                                                   iwl_mvm_enter_d0i3_iterator,
index 12cb427b742ac8105b3b6cf60fc18dd51b545f97,ea8efed25c6abadbe97001ce04e7823f2da8d157..ee2ec516e30c3f42ab88ced72879f7d3455ded75
@@@ -512,9 -512,6 +512,9 @@@ static int iwl_pcie_set_hw_ready(struc
                           CSR_HW_IF_CONFIG_REG_BIT_NIC_READY,
                           HW_READY_TIMEOUT);
  
 +      if (ret >= 0)
 +              iwl_set_bit(trans, CSR_MBOX_SET_REG, CSR_MBOX_SET_REG_OS_ALIVE);
 +
        IWL_DEBUG_INFO(trans, "hardware%s ready\n", ret < 0 ? " not" : "");
        return ret;
  }
@@@ -916,7 -913,8 +916,8 @@@ static void iwl_trans_pcie_stop_device(
         * restart. So don't process again if the device is
         * already dead.
         */
-       if (test_bit(STATUS_DEVICE_ENABLED, &trans->status)) {
+       if (test_and_clear_bit(STATUS_DEVICE_ENABLED, &trans->status)) {
+               IWL_DEBUG_INFO(trans, "DEVICE_ENABLED bit was set and is now cleared\n");
                iwl_pcie_tx_stop(trans);
                iwl_pcie_rx_stop(trans);
  
        /* clear all status bits */
        clear_bit(STATUS_SYNC_HCMD_ACTIVE, &trans->status);
        clear_bit(STATUS_INT_ENABLED, &trans->status);
-       clear_bit(STATUS_DEVICE_ENABLED, &trans->status);
        clear_bit(STATUS_TPOWER_PMI, &trans->status);
        clear_bit(STATUS_RFKILL, &trans->status);
  
@@@ -1034,9 -1031,6 +1034,9 @@@ static int iwl_trans_pcie_d3_resume(str
        iwl_set_bit(trans, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
        iwl_set_bit(trans, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE);
  
 +      if (trans->cfg->device_family == IWL_DEVICE_FAMILY_8000)
 +              udelay(2);
 +
        ret = iwl_poll_bit(trans, CSR_GP_CNTRL,
                           CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY,
                           CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY,
@@@ -1239,8 -1233,6 +1239,8 @@@ static bool iwl_trans_pcie_grab_nic_acc
        /* this bit wakes up the NIC */
        __iwl_trans_pcie_set_bit(trans, CSR_GP_CNTRL,
                                 CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
 +      if (trans->cfg->device_family == IWL_DEVICE_FAMILY_8000)
 +              udelay(2);
  
        /*
         * These bits say the device is running, and should keep running for
@@@ -1906,8 -1898,7 +1906,7 @@@ static u32 iwl_trans_pcie_dump_prph(str
                int reg;
                __le32 *val;
  
-               prph_len += sizeof(*data) + sizeof(*prph) +
-                       num_bytes_in_chunk;
+               prph_len += sizeof(**data) + sizeof(*prph) + num_bytes_in_chunk;
  
                (*data)->type = cpu_to_le32(IWL_FW_ERROR_DUMP_PRPH);
                (*data)->len = cpu_to_le32(sizeof(*prph) +