diff options
Diffstat (limited to 'drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c')
-rw-r--r-- | drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c | 59 |
1 files changed, 45 insertions, 14 deletions
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c index baf7404c137d..607d5d564928 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c @@ -1099,6 +1099,8 @@ int __iwl_mvm_mac_start(struct iwl_mvm *mvm) iwl_dbg_tlv_time_point(&mvm->fwrt, IWL_FW_INI_TIME_POINT_PERIODIC, NULL); + mvm->last_reset_or_resume_time_jiffies = jiffies; + if (ret && test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status)) { /* Something went wrong - we need to finish some cleanup * that normally iwl_mvm_mac_restart_complete() below @@ -4610,6 +4612,16 @@ static int iwl_mvm_pre_channel_switch(struct ieee80211_hw *hw, break; case NL80211_IFTYPE_STATION: + /* + * We haven't configured the firmware to be associated yet since + * we don't know the dtim period. In this case, the firmware can't + * track the beacons. + */ + if (!vif->bss_conf.assoc || !vif->bss_conf.dtim_period) { + ret = -EBUSY; + goto out_unlock; + } + if (chsw->delay > IWL_MAX_CSA_BLOCK_TX) schedule_delayed_work(&mvmvif->csa_work, 0); @@ -5134,28 +5146,50 @@ static void iwl_mvm_mac_event_callback(struct ieee80211_hw *hw, } void iwl_mvm_sync_rx_queues_internal(struct iwl_mvm *mvm, - struct iwl_mvm_internal_rxq_notif *notif, - u32 size) + enum iwl_mvm_rxq_notif_type type, + bool sync, + const void *data, u32 size) { - u32 qmask = BIT(mvm->trans->num_rx_queues) - 1; + struct { + struct iwl_rxq_sync_cmd cmd; + struct iwl_mvm_internal_rxq_notif notif; + } __packed cmd = { + .cmd.rxq_mask = cpu_to_le32(BIT(mvm->trans->num_rx_queues) - 1), + .cmd.count = + cpu_to_le32(sizeof(struct iwl_mvm_internal_rxq_notif) + + size), + .notif.type = type, + .notif.sync = sync, + }; + struct iwl_host_cmd hcmd = { + .id = WIDE_ID(DATA_PATH_GROUP, TRIGGER_RX_QUEUES_NOTIF_CMD), + .data[0] = &cmd, + .len[0] = sizeof(cmd), + .data[1] = data, + .len[1] = size, + .flags = sync ? 0 : CMD_ASYNC, + }; int ret; + /* size must be a multiple of DWORD */ + if (WARN_ON(cmd.cmd.count & cpu_to_le32(3))) + return; if (!iwl_mvm_has_new_rx_api(mvm)) return; - if (notif->sync) { - notif->cookie = mvm->queue_sync_cookie; + if (sync) { + cmd.notif.cookie = mvm->queue_sync_cookie; mvm->queue_sync_state = (1 << mvm->trans->num_rx_queues) - 1; } - ret = iwl_mvm_notify_rx_queue(mvm, qmask, notif, size, !notif->sync); + ret = iwl_mvm_send_cmd(mvm, &hcmd); if (ret) { IWL_ERR(mvm, "Failed to trigger RX queues sync (%d)\n", ret); goto out; } - if (notif->sync) { + if (sync) { lockdep_assert_held(&mvm->mutex); ret = wait_event_timeout(mvm->rx_sync_waitq, READ_ONCE(mvm->queue_sync_state) == 0 || @@ -5167,21 +5201,18 @@ void iwl_mvm_sync_rx_queues_internal(struct iwl_mvm *mvm, } out: - mvm->queue_sync_state = 0; - if (notif->sync) + if (sync) { + mvm->queue_sync_state = 0; mvm->queue_sync_cookie++; + } } static void iwl_mvm_sync_rx_queues(struct ieee80211_hw *hw) { struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); - struct iwl_mvm_internal_rxq_notif data = { - .type = IWL_MVM_RXQ_EMPTY, - .sync = 1, - }; mutex_lock(&mvm->mutex); - iwl_mvm_sync_rx_queues_internal(mvm, &data, sizeof(data)); + iwl_mvm_sync_rx_queues_internal(mvm, IWL_MVM_RXQ_EMPTY, true, NULL, 0); mutex_unlock(&mvm->mutex); } |