diff options
Diffstat (limited to 'drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c')
-rw-r--r-- | drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c | 62 |
1 files changed, 59 insertions, 3 deletions
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c index 15f2d826bb4b..3bcaa82f59b2 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c | |||
@@ -1546,6 +1546,11 @@ static void iwl_mvm_mc_iface_iterator(void *_data, u8 *mac, | |||
1546 | struct iwl_mvm_mc_iter_data *data = _data; | 1546 | struct iwl_mvm_mc_iter_data *data = _data; |
1547 | struct iwl_mvm *mvm = data->mvm; | 1547 | struct iwl_mvm *mvm = data->mvm; |
1548 | struct iwl_mcast_filter_cmd *cmd = mvm->mcast_filter_cmd; | 1548 | struct iwl_mcast_filter_cmd *cmd = mvm->mcast_filter_cmd; |
1549 | struct iwl_host_cmd hcmd = { | ||
1550 | .id = MCAST_FILTER_CMD, | ||
1551 | .flags = CMD_ASYNC, | ||
1552 | .dataflags[0] = IWL_HCMD_DFL_NOCOPY, | ||
1553 | }; | ||
1549 | int ret, len; | 1554 | int ret, len; |
1550 | 1555 | ||
1551 | /* if we don't have free ports, mcast frames will be dropped */ | 1556 | /* if we don't have free ports, mcast frames will be dropped */ |
@@ -1560,7 +1565,10 @@ static void iwl_mvm_mc_iface_iterator(void *_data, u8 *mac, | |||
1560 | memcpy(cmd->bssid, vif->bss_conf.bssid, ETH_ALEN); | 1565 | memcpy(cmd->bssid, vif->bss_conf.bssid, ETH_ALEN); |
1561 | len = roundup(sizeof(*cmd) + cmd->count * ETH_ALEN, 4); | 1566 | len = roundup(sizeof(*cmd) + cmd->count * ETH_ALEN, 4); |
1562 | 1567 | ||
1563 | ret = iwl_mvm_send_cmd_pdu(mvm, MCAST_FILTER_CMD, CMD_ASYNC, len, cmd); | 1568 | hcmd.len[0] = len; |
1569 | hcmd.data[0] = cmd; | ||
1570 | |||
1571 | ret = iwl_mvm_send_cmd(mvm, &hcmd); | ||
1564 | if (ret) | 1572 | if (ret) |
1565 | IWL_ERR(mvm, "mcast filter cmd error. ret=%d\n", ret); | 1573 | IWL_ERR(mvm, "mcast filter cmd error. ret=%d\n", ret); |
1566 | } | 1574 | } |
@@ -1635,6 +1643,12 @@ static void iwl_mvm_configure_filter(struct ieee80211_hw *hw, | |||
1635 | if (!cmd) | 1643 | if (!cmd) |
1636 | goto out; | 1644 | goto out; |
1637 | 1645 | ||
1646 | if (changed_flags & FIF_ALLMULTI) | ||
1647 | cmd->pass_all = !!(*total_flags & FIF_ALLMULTI); | ||
1648 | |||
1649 | if (cmd->pass_all) | ||
1650 | cmd->count = 0; | ||
1651 | |||
1638 | iwl_mvm_recalc_multicast(mvm); | 1652 | iwl_mvm_recalc_multicast(mvm); |
1639 | out: | 1653 | out: |
1640 | mutex_unlock(&mvm->mutex); | 1654 | mutex_unlock(&mvm->mutex); |
@@ -2563,7 +2577,7 @@ static void iwl_mvm_purge_deferred_tx_frames(struct iwl_mvm *mvm, | |||
2563 | * queues, so we should never get a second deferred | 2577 | * queues, so we should never get a second deferred |
2564 | * frame for the RA/TID. | 2578 | * frame for the RA/TID. |
2565 | */ | 2579 | */ |
2566 | iwl_mvm_start_mac_queues(mvm, info->hw_queue); | 2580 | iwl_mvm_start_mac_queues(mvm, BIT(info->hw_queue)); |
2567 | ieee80211_free_txskb(mvm->hw, skb); | 2581 | ieee80211_free_txskb(mvm->hw, skb); |
2568 | } | 2582 | } |
2569 | } | 2583 | } |
@@ -3975,6 +3989,43 @@ out_unlock: | |||
3975 | return ret; | 3989 | return ret; |
3976 | } | 3990 | } |
3977 | 3991 | ||
3992 | static void iwl_mvm_flush_no_vif(struct iwl_mvm *mvm, u32 queues, bool drop) | ||
3993 | { | ||
3994 | if (drop) { | ||
3995 | if (iwl_mvm_has_new_tx_api(mvm)) | ||
3996 | /* TODO new tx api */ | ||
3997 | WARN_ONCE(1, | ||
3998 | "Need to implement flush TX queue\n"); | ||
3999 | else | ||
4000 | iwl_mvm_flush_tx_path(mvm, | ||
4001 | iwl_mvm_flushable_queues(mvm) & queues, | ||
4002 | 0); | ||
4003 | } else { | ||
4004 | if (iwl_mvm_has_new_tx_api(mvm)) { | ||
4005 | struct ieee80211_sta *sta; | ||
4006 | int i; | ||
4007 | |||
4008 | mutex_lock(&mvm->mutex); | ||
4009 | |||
4010 | for (i = 0; i < ARRAY_SIZE(mvm->fw_id_to_mac_id); i++) { | ||
4011 | sta = rcu_dereference_protected( | ||
4012 | mvm->fw_id_to_mac_id[i], | ||
4013 | lockdep_is_held(&mvm->mutex)); | ||
4014 | if (IS_ERR_OR_NULL(sta)) | ||
4015 | continue; | ||
4016 | |||
4017 | iwl_mvm_wait_sta_queues_empty(mvm, | ||
4018 | iwl_mvm_sta_from_mac80211(sta)); | ||
4019 | } | ||
4020 | |||
4021 | mutex_unlock(&mvm->mutex); | ||
4022 | } else { | ||
4023 | iwl_trans_wait_tx_queues_empty(mvm->trans, | ||
4024 | queues); | ||
4025 | } | ||
4026 | } | ||
4027 | } | ||
4028 | |||
3978 | static void iwl_mvm_mac_flush(struct ieee80211_hw *hw, | 4029 | static void iwl_mvm_mac_flush(struct ieee80211_hw *hw, |
3979 | struct ieee80211_vif *vif, u32 queues, bool drop) | 4030 | struct ieee80211_vif *vif, u32 queues, bool drop) |
3980 | { | 4031 | { |
@@ -3985,7 +4036,12 @@ static void iwl_mvm_mac_flush(struct ieee80211_hw *hw, | |||
3985 | int i; | 4036 | int i; |
3986 | u32 msk = 0; | 4037 | u32 msk = 0; |
3987 | 4038 | ||
3988 | if (!vif || vif->type != NL80211_IFTYPE_STATION) | 4039 | if (!vif) { |
4040 | iwl_mvm_flush_no_vif(mvm, queues, drop); | ||
4041 | return; | ||
4042 | } | ||
4043 | |||
4044 | if (vif->type != NL80211_IFTYPE_STATION) | ||
3989 | return; | 4045 | return; |
3990 | 4046 | ||
3991 | /* Make sure we're done with the deferred traffic before flushing */ | 4047 | /* Make sure we're done with the deferred traffic before flushing */ |