diff options
Diffstat (limited to 'drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c')
| -rw-r--r-- | drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c | 260 |
1 files changed, 167 insertions, 93 deletions
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c index 45122dafe922..bcde1ba0f1c8 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c @@ -6,8 +6,8 @@ * GPL LICENSE SUMMARY * * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. - * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH - * Copyright(c) 2016 Intel Deutschland GmbH + * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH + * Copyright(c) 2016 - 2017 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 @@ -33,7 +33,8 @@ * BSD LICENSE * * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. - * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH + * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH + * Copyright(c) 2016 - 2017 Intel Deutschland GmbH * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -83,7 +84,7 @@ #include "iwl-eeprom-parse.h" #include "iwl-phy-db.h" #include "testmode.h" -#include "iwl-fw-error-dump.h" +#include "fw/error-dump.h" #include "iwl-prph.h" #include "iwl-nvm-parse.h" #include "fw-dbg.h" @@ -463,6 +464,13 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm) IEEE80211_RADIOTAP_MCS_HAVE_STBC; hw->radiotap_vht_details |= IEEE80211_RADIOTAP_VHT_KNOWN_STBC | IEEE80211_RADIOTAP_VHT_KNOWN_BEAMFORMED; + + hw->radiotap_timestamp.units_pos = + IEEE80211_RADIOTAP_TIMESTAMP_UNIT_US | + IEEE80211_RADIOTAP_TIMESTAMP_SPOS_PLCP_SIG_ACQ; + /* this is the case for CCK frames, it's better (only 8) for OFDM */ + hw->radiotap_timestamp.accuracy = 22; + hw->rate_control_algorithm = "iwl-mvm-rs"; hw->uapsd_queues = IWL_MVM_UAPSD_QUEUES; hw->uapsd_max_sp_len = IWL_UAPSD_MAX_SP; @@ -485,7 +493,7 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm) * firmware will interpret some mgmt packets, so enabling it * with software crypto isn't safe). */ - if (!iwlwifi_mod_params.sw_crypto) { + if (!iwlwifi_mod_params.swcrypto) { ieee80211_hw_set(hw, MFP_CAPABLE); mvm->ciphers[hw->wiphy->n_cipher_suites] = WLAN_CIPHER_SUITE_AES_CMAC; @@ -612,7 +620,7 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm) else hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT; - hw->wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN; + hw->wiphy->max_sched_scan_reqs = 1; hw->wiphy->max_sched_scan_ssids = PROBE_OPTION_MAX; hw->wiphy->max_match_sets = IWL_SCAN_MAX_PROFILES; /* we create the 802.11 header and zero length SSID IE. */ @@ -670,7 +678,7 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm) hw->wiphy->wowlan = &mvm->wowlan; } - if (mvm->fw->img[IWL_UCODE_WOWLAN].sec[0].len && + if (mvm->fw->img[IWL_UCODE_WOWLAN].num_sec && mvm->trans->ops->d3_suspend && mvm->trans->ops->d3_resume && device_can_wakeup(mvm->trans->dev)) { @@ -679,7 +687,7 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm) WIPHY_WOWLAN_EAP_IDENTITY_REQ | WIPHY_WOWLAN_RFKILL_RELEASE | WIPHY_WOWLAN_NET_DETECT; - if (!iwlwifi_mod_params.sw_crypto) + if (!iwlwifi_mod_params.swcrypto) mvm->wowlan.flags |= WIPHY_WOWLAN_SUPPORTS_GTK_REKEY | WIPHY_WOWLAN_GTK_REKEY_FAILURE | WIPHY_WOWLAN_4WAY_HANDSHAKE; @@ -727,6 +735,7 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm) ret = ieee80211_register_hw(mvm->hw); if (ret) iwl_mvm_leds_exit(mvm); + mvm->init_status |= IWL_MVM_INIT_STATUS_REG_HW_INIT_COMPLETE; if (mvm->cfg->vht_mu_mimo_supported) wiphy_ext_feature_set(hw->wiphy, @@ -759,7 +768,7 @@ static bool iwl_mvm_defer_tx(struct iwl_mvm *mvm, goto out; mvmsta = iwl_mvm_sta_from_mac80211(sta); - if (mvmsta->sta_id == IWL_MVM_STATION_COUNT || + if (mvmsta->sta_id == IWL_MVM_INVALID_STA || mvmsta->sta_id != mvm->d0i3_ap_sta_id) goto out; @@ -1003,7 +1012,7 @@ static void iwl_mvm_cleanup_iterator(void *data, u8 *mac, struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); mvmvif->uploaded = false; - mvmvif->ap_sta_id = IWL_MVM_STATION_COUNT; + mvmvif->ap_sta_id = IWL_MVM_INVALID_STA; spin_lock_bh(&mvm->time_event_lock); iwl_mvm_te_clear_data(mvm, &mvmvif->time_event_data); @@ -1046,7 +1055,7 @@ static void iwl_mvm_restart_cleanup(struct iwl_mvm *mvm) ieee80211_iterate_interfaces(mvm->hw, 0, iwl_mvm_cleanup_iterator, mvm); mvm->p2p_device_vif = NULL; - mvm->d0i3_ap_sta_id = IWL_MVM_STATION_COUNT; + mvm->d0i3_ap_sta_id = IWL_MVM_INVALID_STA; iwl_mvm_reset_phy_ctxts(mvm); memset(mvm->fw_key_table, 0, sizeof(mvm->fw_key_table)); @@ -1203,8 +1212,6 @@ void __iwl_mvm_mac_stop(struct iwl_mvm *mvm) /* the fw is stopped, the aux sta is dead: clean up driver state */ iwl_mvm_del_aux_sta(mvm); - iwl_free_fw_paging(mvm); - /* * Clear IN_HW_RESTART flag when stopping the hw (as restart_complete() * won't be called in this case). @@ -1237,6 +1244,17 @@ static void iwl_mvm_mac_stop(struct ieee80211_hw *hw) flush_work(&mvm->d0i3_exit_work); flush_work(&mvm->async_handlers_wk); flush_work(&mvm->add_stream_wk); + + /* + * Lock and clear the firmware running bit here already, so that + * new commands coming in elsewhere, e.g. from debugfs, will not + * be able to proceed. This is important here because one of those + * debugfs files causes the fw_dump_wk to be triggered, and if we + * don't stop debugfs accesses before canceling that it could be + * retriggered after we flush it but before we've cleared the bit. + */ + clear_bit(IWL_MVM_STATUS_FIRMWARE_RUNNING, &mvm->status); + cancel_delayed_work_sync(&mvm->fw_dump_wk); cancel_delayed_work_sync(&mvm->cs_tx_unblock_dwork); cancel_delayed_work_sync(&mvm->scan_timeout_dwork); @@ -1346,6 +1364,18 @@ static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw, goto out_release; } + if (iwl_mvm_is_dqa_supported(mvm)) { + /* + * Only queue for this station is the mcast queue, + * which shouldn't be in TFD mask anyway + */ + ret = iwl_mvm_allocate_int_sta(mvm, &mvmvif->mcast_sta, + 0, vif->type, + IWL_STA_MULTICAST); + if (ret) + goto out_release; + } + iwl_mvm_vif_dbgfs_register(mvm, vif); goto out_unlock; } @@ -1433,7 +1463,7 @@ static void iwl_mvm_prepare_mac_removal(struct iwl_mvm *mvm, { u32 tfd_msk = iwl_mvm_mac_get_queues_mask(vif); - if (tfd_msk) { + if (tfd_msk && !iwl_mvm_is_dqa_supported(mvm)) { /* * mac80211 first removes all the stations of the vif and * then removes the vif. When it removes a station it also @@ -1442,6 +1472,8 @@ static void iwl_mvm_prepare_mac_removal(struct iwl_mvm *mvm, * of these AMPDU sessions are properly closed. * We still need to take care of the shared queues of the vif. * Flush them here. + * For DQA mode there is no need - broacast and multicast queue + * are flushed separately. */ mutex_lock(&mvm->mutex); iwl_mvm_flush_tx_path(mvm, tfd_msk, 0); @@ -1460,7 +1492,7 @@ static void iwl_mvm_prepare_mac_removal(struct iwl_mvm *mvm, * already marked as draining, so to complete the draining, we * just need to wait until the transport is empty. */ - iwl_trans_wait_tx_queue_empty(mvm->trans, tfd_msk); + iwl_trans_wait_tx_queues_empty(mvm->trans, tfd_msk); } if (vif->type == NL80211_IFTYPE_P2P_DEVICE) { @@ -1511,6 +1543,7 @@ static void iwl_mvm_mac_remove_interface(struct ieee80211_hw *hw, mvm->noa_duration = 0; } #endif + iwl_mvm_dealloc_int_sta(mvm, &mvmvif->mcast_sta); iwl_mvm_dealloc_bcast_sta(mvm, vif); goto out_release; } @@ -1947,7 +1980,7 @@ static void iwl_mvm_bss_info_changed_station(struct iwl_mvm *mvm, IWL_MVM_SMPS_REQ_PROT, IEEE80211_SMPS_DYNAMIC); } - } else if (mvmvif->ap_sta_id != IWL_MVM_STATION_COUNT) { + } else if (mvmvif->ap_sta_id != IWL_MVM_INVALID_STA) { /* * If update fails - SF might be running in associated * mode while disassociated - which is forbidden. @@ -1955,14 +1988,32 @@ static void iwl_mvm_bss_info_changed_station(struct iwl_mvm *mvm, WARN_ONCE(iwl_mvm_sf_update(mvm, vif, false), "Failed to update SF upon disassociation\n"); - /* remove AP station now that the MAC is unassoc */ - ret = iwl_mvm_rm_sta_id(mvm, vif, mvmvif->ap_sta_id); - if (ret) - IWL_ERR(mvm, "failed to remove AP station\n"); + /* + * If we get an assert during the connection (after the + * station has been added, but before the vif is set + * to associated), mac80211 will re-add the station and + * then configure the vif. Since the vif is not + * associated, we would remove the station here and + * this would fail the recovery. + */ + if (!test_bit(IWL_MVM_STATUS_IN_HW_RESTART, + &mvm->status)) { + /* + * Remove AP station now that + * the MAC is unassoc + */ + ret = iwl_mvm_rm_sta_id(mvm, vif, + mvmvif->ap_sta_id); + if (ret) + IWL_ERR(mvm, + "failed to remove AP station\n"); + + if (mvm->d0i3_ap_sta_id == mvmvif->ap_sta_id) + mvm->d0i3_ap_sta_id = + IWL_MVM_INVALID_STA; + mvmvif->ap_sta_id = IWL_MVM_INVALID_STA; + } - if (mvm->d0i3_ap_sta_id == mvmvif->ap_sta_id) - mvm->d0i3_ap_sta_id = IWL_MVM_STATION_COUNT; - mvmvif->ap_sta_id = IWL_MVM_STATION_COUNT; /* remove quota for this interface */ ret = iwl_mvm_update_quotas(mvm, false, NULL); if (ret) @@ -2003,16 +2054,16 @@ static void iwl_mvm_bss_info_changed_station(struct iwl_mvm *mvm, if (fw_has_capa(&mvm->fw->ucode_capa, IWL_UCODE_TLV_CAPA_UMAC_SCAN)) iwl_mvm_config_scan(mvm); - } else if (changes & BSS_CHANGED_BEACON_INFO) { + } + + if (changes & BSS_CHANGED_BEACON_INFO) { /* - * We received a beacon _after_ association so + * We received a beacon from the associated AP so * remove the session protection. */ iwl_mvm_remove_time_event(mvm, mvmvif, &mvmvif->time_event_data); - } - if (changes & BSS_CHANGED_BEACON_INFO) { iwl_mvm_sf_update(mvm, vif, false); WARN_ON(iwl_mvm_enable_beacon_filter(mvm, vif, 0)); } @@ -2093,27 +2144,15 @@ static int iwl_mvm_start_ap_ibss(struct ieee80211_hw *hw, if (ret) goto out_remove; + ret = iwl_mvm_add_mcast_sta(mvm, vif); + if (ret) + goto out_unbind; + /* Send the bcast station. At this stage the TBTT and DTIM time events * are added and applied to the scheduler */ ret = iwl_mvm_send_add_bcast_sta(mvm, vif); if (ret) - goto out_unbind; - - /* enable the multicast queue, now that we have a station for it */ - if (iwl_mvm_is_dqa_supported(mvm)) { - unsigned int wdg_timeout = - iwl_mvm_get_wd_timeout(mvm, vif, false, false); - struct iwl_trans_txq_scd_cfg cfg = { - .fifo = IWL_MVM_TX_FIFO_MCAST, - .sta_id = mvmvif->bcast_sta.sta_id, - .tid = IWL_MAX_TID_COUNT, - .aggregate = false, - .frame_limit = IWL_FRAME_LIMIT, - }; - - iwl_mvm_enable_txq(mvm, vif->cab_queue, vif->cab_queue, 0, - &cfg, wdg_timeout); - } + goto out_rm_mcast; /* must be set before quota calculations */ mvmvif->ap_ibss_active = true; @@ -2143,6 +2182,8 @@ out_quota_failed: iwl_mvm_power_update_mac(mvm); mvmvif->ap_ibss_active = false; iwl_mvm_send_rm_bcast_sta(mvm, vif); +out_rm_mcast: + iwl_mvm_rm_mcast_sta(mvm, vif); out_unbind: iwl_mvm_binding_remove_vif(mvm, vif); out_remove: @@ -2188,7 +2229,20 @@ static void iwl_mvm_stop_ap_ibss(struct ieee80211_hw *hw, iwl_mvm_mac_ctxt_changed(mvm, mvm->p2p_device_vif, false, NULL); iwl_mvm_update_quotas(mvm, false, NULL); + + /* + * This is not very nice, but the simplest: + * For older FWs removing the mcast sta before the bcast station may + * cause assert 0x2b00. + * This is fixed in later FW (which will stop beaconing when removing + * bcast station). + * So make the order of removal depend on the TLV + */ + if (!fw_has_api(&mvm->fw->ucode_capa, IWL_UCODE_TLV_API_STA_TYPE)) + iwl_mvm_rm_mcast_sta(mvm, vif); iwl_mvm_send_rm_bcast_sta(mvm, vif); + if (fw_has_api(&mvm->fw->ucode_capa, IWL_UCODE_TLV_API_STA_TYPE)) + iwl_mvm_rm_mcast_sta(mvm, vif); iwl_mvm_binding_remove_vif(mvm, vif); iwl_mvm_power_update_mac(mvm); @@ -2330,7 +2384,7 @@ iwl_mvm_mac_release_buffered_frames(struct ieee80211_hw *hw, { struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); - /* Called when we need to transmit (a) frame(s) from agg queue */ + /* Called when we need to transmit (a) frame(s) from agg or dqa queue */ iwl_mvm_sta_modify_sleep_tx_count(mvm, sta, reason, num_frames, tids, more_data, true); @@ -2349,13 +2403,17 @@ static void __iwl_mvm_mac_sta_notify(struct ieee80211_hw *hw, for (tid = 0; tid < IWL_MAX_TID_COUNT; tid++) { struct iwl_mvm_tid_data *tid_data = &mvmsta->tid_data[tid]; - if (tid_data->state != IWL_AGG_ON && + if (!iwl_mvm_is_dqa_supported(mvm) && + tid_data->state != IWL_AGG_ON && tid_data->state != IWL_EMPTYING_HW_QUEUE_DELBA) continue; + if (tid_data->txq_id == IWL_MVM_INVALID_QUEUE) + continue; + __set_bit(tid_data->txq_id, &txqs); - if (iwl_mvm_tid_queued(tid_data) == 0) + if (iwl_mvm_tid_queued(mvm, tid_data) == 0) continue; __set_bit(tid, &tids); @@ -2378,7 +2436,7 @@ static void __iwl_mvm_mac_sta_notify(struct ieee80211_hw *hw, */ break; case STA_NOTIFY_AWAKE: - if (WARN_ON(mvmsta->sta_id == IWL_MVM_STATION_COUNT)) + if (WARN_ON(mvmsta->sta_id == IWL_MVM_INVALID_STA)) break; if (txqs) @@ -2411,7 +2469,7 @@ void iwl_mvm_sta_pm_notif(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb) return; rcu_read_lock(); - sta = mvm->fw_id_to_mac_id[notif->sta_id]; + sta = rcu_dereference(mvm->fw_id_to_mac_id[notif->sta_id]); if (WARN_ON(IS_ERR_OR_NULL(sta))) { rcu_read_unlock(); return; @@ -2547,6 +2605,7 @@ static int iwl_mvm_mac_sta_state(struct ieee80211_hw *hw, { struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); + struct iwl_mvm_sta *mvm_sta = iwl_mvm_sta_from_mac80211(sta); int ret; IWL_DEBUG_MAC80211(mvm, "station %pM state change %d->%d\n", @@ -2575,8 +2634,6 @@ static int iwl_mvm_mac_sta_state(struct ieee80211_hw *hw, if (old_state == IEEE80211_STA_NONE && new_state == IEEE80211_STA_NOTEXIST && iwl_mvm_is_dqa_supported(mvm)) { - struct iwl_mvm_sta *mvm_sta = iwl_mvm_sta_from_mac80211(sta); - iwl_mvm_purge_deferred_tx_frames(mvm, mvm_sta); flush_work(&mvm->add_stream_wk); @@ -2587,6 +2644,9 @@ static int iwl_mvm_mac_sta_state(struct ieee80211_hw *hw, } mutex_lock(&mvm->mutex); + /* track whether or not the station is associated */ + mvm_sta->associated = new_state >= IEEE80211_STA_ASSOC; + if (old_state == IEEE80211_STA_NOTEXIST && new_state == IEEE80211_STA_NONE) { /* @@ -2636,11 +2696,10 @@ static int iwl_mvm_mac_sta_state(struct ieee80211_hw *hw, mvmvif->ap_assoc_sta_count++; iwl_mvm_mac_ctxt_changed(mvm, vif, false, NULL); } + + iwl_mvm_rs_rate_init(mvm, sta, mvmvif->phy_ctxt->channel->band, + true); ret = iwl_mvm_update_sta(mvm, vif, sta); - if (ret == 0) - iwl_mvm_rs_rate_init(mvm, sta, - mvmvif->phy_ctxt->channel->band, - true); } else if (old_state == IEEE80211_STA_ASSOC && new_state == IEEE80211_STA_AUTHORIZED) { @@ -2829,7 +2888,7 @@ static int iwl_mvm_mac_set_key(struct ieee80211_hw *hw, int ret; u8 key_offset; - if (iwlwifi_mod_params.sw_crypto) { + if (iwlwifi_mod_params.swcrypto) { IWL_DEBUG_MAC80211(mvm, "leave - hwcrypto disabled\n"); return -EOPNOTSUPP; } @@ -2842,7 +2901,8 @@ static int iwl_mvm_mac_set_key(struct ieee80211_hw *hw, case WLAN_CIPHER_SUITE_CCMP: case WLAN_CIPHER_SUITE_GCMP: case WLAN_CIPHER_SUITE_GCMP_256: - key->flags |= IEEE80211_KEY_FLAG_PUT_IV_SPACE; + if (!iwl_mvm_has_new_tx_api(mvm)) + key->flags |= IEEE80211_KEY_FLAG_PUT_IV_SPACE; break; case WLAN_CIPHER_SUITE_AES_CMAC: case WLAN_CIPHER_SUITE_BIP_GMAC_128: @@ -2888,8 +2948,13 @@ static int iwl_mvm_mac_set_key(struct ieee80211_hw *hw, ret = -EOPNOTSUPP; else ret = 0; - key->hw_key_idx = STA_KEY_IDX_INVALID; - break; + + if (key->cipher != WLAN_CIPHER_SUITE_GCMP && + key->cipher != WLAN_CIPHER_SUITE_GCMP_256 && + !iwl_mvm_has_new_tx_api(mvm)) { + key->hw_key_idx = STA_KEY_IDX_INVALID; + break; + } } /* During FW restart, in order to restore the state as it was, @@ -3690,6 +3755,13 @@ static int iwl_mvm_switch_vif_chanctx(struct ieee80211_hw *hw, return ret; } +static int iwl_mvm_tx_last_beacon(struct ieee80211_hw *hw) +{ + struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); + + return mvm->ibss_manager; +} + static int iwl_mvm_set_tim(struct ieee80211_hw *hw, struct ieee80211_sta *sta, bool set) @@ -3720,7 +3792,8 @@ static int __iwl_mvm_mac_testmode_cmd(struct iwl_mvm *mvm, int err; u32 noa_duration; - err = nla_parse(tb, IWL_MVM_TM_ATTR_MAX, data, len, iwl_mvm_tm_policy); + err = nla_parse(tb, IWL_MVM_TM_ATTR_MAX, data, len, iwl_mvm_tm_policy, + NULL); if (err) return err; @@ -3947,7 +4020,7 @@ static void iwl_mvm_mac_flush(struct ieee80211_hw *hw, mvmvif = iwl_mvm_vif_from_mac80211(vif); /* flush the AP-station and all TDLS peers */ - for (i = 0; i < IWL_MVM_STATION_COUNT; i++) { + for (i = 0; i < ARRAY_SIZE(mvm->fw_id_to_mac_id); i++) { sta = rcu_dereference_protected(mvm->fw_id_to_mac_id[i], lockdep_is_held(&mvm->mutex)); if (IS_ERR_OR_NULL(sta)) @@ -3960,21 +4033,23 @@ static void iwl_mvm_mac_flush(struct ieee80211_hw *hw, /* make sure only TDLS peers or the AP are flushed */ WARN_ON(i != mvmvif->ap_sta_id && !sta->tdls); - msk |= mvmsta->tfd_queue_msk; + if (drop) { + if (iwl_mvm_flush_sta(mvm, mvmsta, false, 0)) + IWL_ERR(mvm, "flush request fail\n"); + } else { + msk |= mvmsta->tfd_queue_msk; + if (iwl_mvm_has_new_tx_api(mvm)) + iwl_mvm_wait_sta_queues_empty(mvm, mvmsta); + } } - if (drop) { - if (iwl_mvm_flush_tx_path(mvm, msk, 0)) - IWL_ERR(mvm, "flush request fail\n"); - mutex_unlock(&mvm->mutex); - } else { - mutex_unlock(&mvm->mutex); + mutex_unlock(&mvm->mutex); - /* this can take a while, and we may need/want other operations - * to succeed while doing this, so do it without the mutex held - */ - iwl_trans_wait_tx_queue_empty(mvm->trans, msk); - } + /* this can take a while, and we may need/want other operations + * to succeed while doing this, so do it without the mutex held + */ + if (!drop && !iwl_mvm_has_new_tx_api(mvm)) + iwl_trans_wait_tx_queues_empty(mvm->trans, msk); } static int iwl_mvm_mac_get_survey(struct ieee80211_hw *hw, int idx, @@ -3995,7 +4070,7 @@ static int iwl_mvm_mac_get_survey(struct ieee80211_hw *hw, int idx, mutex_lock(&mvm->mutex); - if (mvm->ucode_loaded) { + if (iwl_mvm_firmware_running(mvm)) { ret = iwl_mvm_request_statistics(mvm, false); if (ret) goto out; @@ -4076,11 +4151,11 @@ static void iwl_mvm_event_mlme_callback(struct iwl_mvm *mvm, struct ieee80211_vif *vif, const struct ieee80211_event *event) { -#define CHECK_MLME_TRIGGER(_mvm, _trig, _buf, _cnt, _fmt...) \ +#define CHECK_MLME_TRIGGER(_cnt, _fmt...) \ do { \ - if ((_cnt) && --(_cnt)) \ + if ((trig_mlme->_cnt) && --(trig_mlme->_cnt)) \ break; \ - iwl_mvm_fw_dbg_collect_trig(_mvm, _trig, _fmt);\ + iwl_mvm_fw_dbg_collect_trig(mvm, trig, _fmt); \ } while (0) struct iwl_fw_dbg_trigger_tlv *trig; @@ -4096,31 +4171,25 @@ static void iwl_mvm_event_mlme_callback(struct iwl_mvm *mvm, if (event->u.mlme.data == ASSOC_EVENT) { if (event->u.mlme.status == MLME_DENIED) - CHECK_MLME_TRIGGER(mvm, trig, buf, - trig_mlme->stop_assoc_denied, + CHECK_MLME_TRIGGER(stop_assoc_denied, "DENIED ASSOC: reason %d", event->u.mlme.reason); else if (event->u.mlme.status == MLME_TIMEOUT) - CHECK_MLME_TRIGGER(mvm, trig, buf, - trig_mlme->stop_assoc_timeout, + CHECK_MLME_TRIGGER(stop_assoc_timeout, "ASSOC TIMEOUT"); } else if (event->u.mlme.data == AUTH_EVENT) { if (event->u.mlme.status == MLME_DENIED) - CHECK_MLME_TRIGGER(mvm, trig, buf, - trig_mlme->stop_auth_denied, + CHECK_MLME_TRIGGER(stop_auth_denied, "DENIED AUTH: reason %d", event->u.mlme.reason); else if (event->u.mlme.status == MLME_TIMEOUT) - CHECK_MLME_TRIGGER(mvm, trig, buf, - trig_mlme->stop_auth_timeout, + CHECK_MLME_TRIGGER(stop_auth_timeout, "AUTH TIMEOUT"); } else if (event->u.mlme.data == DEAUTH_RX_EVENT) { - CHECK_MLME_TRIGGER(mvm, trig, buf, - trig_mlme->stop_rx_deauth, + CHECK_MLME_TRIGGER(stop_rx_deauth, "DEAUTH RX %d", event->u.mlme.reason); } else if (event->u.mlme.data == DEAUTH_TX_EVENT) { - CHECK_MLME_TRIGGER(mvm, trig, buf, - trig_mlme->stop_tx_deauth, + CHECK_MLME_TRIGGER(stop_tx_deauth, "DEAUTH TX %d", event->u.mlme.reason); } #undef CHECK_MLME_TRIGGER @@ -4204,7 +4273,8 @@ void iwl_mvm_sync_rx_queues_internal(struct iwl_mvm *mvm, lockdep_assert_held(&mvm->mutex); - if (!iwl_mvm_has_new_rx_api(mvm)) + /* TODO - remove a000 disablement when we have RXQ config API */ + if (!iwl_mvm_has_new_rx_api(mvm) || iwl_mvm_has_new_tx_api(mvm)) return; notif->cookie = mvm->queue_sync_cookie; @@ -4219,11 +4289,13 @@ void iwl_mvm_sync_rx_queues_internal(struct iwl_mvm *mvm, goto out; } - if (notif->sync) + if (notif->sync) { ret = wait_event_timeout(mvm->rx_sync_waitq, - atomic_read(&mvm->queue_sync_counter) == 0, + atomic_read(&mvm->queue_sync_counter) == 0 || + iwl_mvm_is_radio_killed(mvm), HZ); - WARN_ON_ONCE(!ret); + WARN_ON_ONCE(!ret && !iwl_mvm_is_radio_killed(mvm)); + } out: atomic_set(&mvm->queue_sync_counter, 0); @@ -4287,6 +4359,8 @@ const struct ieee80211_ops iwl_mvm_hw_ops = { .join_ibss = iwl_mvm_start_ap_ibss, .leave_ibss = iwl_mvm_stop_ap_ibss, + .tx_last_beacon = iwl_mvm_tx_last_beacon, + .set_tim = iwl_mvm_set_tim, .channel_switch = iwl_mvm_channel_switch, |