diff options
Diffstat (limited to 'drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c')
-rw-r--r-- | drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c | 43 |
1 files changed, 36 insertions, 7 deletions
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c index 525b26e0f65e..3f37fb64e71c 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c | |||
@@ -1623,6 +1623,7 @@ static void iwl_mvm_recalc_multicast(struct iwl_mvm *mvm) | |||
1623 | struct iwl_mvm_mc_iter_data iter_data = { | 1623 | struct iwl_mvm_mc_iter_data iter_data = { |
1624 | .mvm = mvm, | 1624 | .mvm = mvm, |
1625 | }; | 1625 | }; |
1626 | int ret; | ||
1626 | 1627 | ||
1627 | lockdep_assert_held(&mvm->mutex); | 1628 | lockdep_assert_held(&mvm->mutex); |
1628 | 1629 | ||
@@ -1632,6 +1633,22 @@ static void iwl_mvm_recalc_multicast(struct iwl_mvm *mvm) | |||
1632 | ieee80211_iterate_active_interfaces_atomic( | 1633 | ieee80211_iterate_active_interfaces_atomic( |
1633 | mvm->hw, IEEE80211_IFACE_ITER_NORMAL, | 1634 | mvm->hw, IEEE80211_IFACE_ITER_NORMAL, |
1634 | iwl_mvm_mc_iface_iterator, &iter_data); | 1635 | iwl_mvm_mc_iface_iterator, &iter_data); |
1636 | |||
1637 | /* | ||
1638 | * Send a (synchronous) ech command so that we wait for the | ||
1639 | * multiple asynchronous MCAST_FILTER_CMD commands sent by | ||
1640 | * the interface iterator. Otherwise, we might get here over | ||
1641 | * and over again (by userspace just sending a lot of these) | ||
1642 | * and the CPU can send them faster than the firmware can | ||
1643 | * process them. | ||
1644 | * Note that the CPU is still faster - but with this we'll | ||
1645 | * actually send fewer commands overall because the CPU will | ||
1646 | * not schedule the work in mac80211 as frequently if it's | ||
1647 | * still running when rescheduled (possibly multiple times). | ||
1648 | */ | ||
1649 | ret = iwl_mvm_send_cmd_pdu(mvm, ECHO_CMD, 0, 0, NULL); | ||
1650 | if (ret) | ||
1651 | IWL_ERR(mvm, "Failed to synchronize multicast groups update\n"); | ||
1635 | } | 1652 | } |
1636 | 1653 | ||
1637 | static u64 iwl_mvm_prepare_multicast(struct ieee80211_hw *hw, | 1654 | static u64 iwl_mvm_prepare_multicast(struct ieee80211_hw *hw, |
@@ -2880,7 +2897,7 @@ static int iwl_mvm_mac_sta_state(struct ieee80211_hw *hw, | |||
2880 | 2897 | ||
2881 | /* this would be a mac80211 bug ... but don't crash */ | 2898 | /* this would be a mac80211 bug ... but don't crash */ |
2882 | if (WARN_ON_ONCE(!mvmvif->phy_ctxt)) | 2899 | if (WARN_ON_ONCE(!mvmvif->phy_ctxt)) |
2883 | return -EINVAL; | 2900 | return test_bit(IWL_MVM_STATUS_HW_RESTART_REQUESTED, &mvm->status) ? 0 : -EINVAL; |
2884 | 2901 | ||
2885 | /* | 2902 | /* |
2886 | * If we are in a STA removal flow and in DQA mode: | 2903 | * If we are in a STA removal flow and in DQA mode: |
@@ -3496,6 +3513,7 @@ static int iwl_mvm_roc(struct ieee80211_hw *hw, | |||
3496 | struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); | 3513 | struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); |
3497 | struct cfg80211_chan_def chandef; | 3514 | struct cfg80211_chan_def chandef; |
3498 | struct iwl_mvm_phy_ctxt *phy_ctxt; | 3515 | struct iwl_mvm_phy_ctxt *phy_ctxt; |
3516 | bool band_change_removal; | ||
3499 | int ret, i; | 3517 | int ret, i; |
3500 | 3518 | ||
3501 | IWL_DEBUG_MAC80211(mvm, "enter (%d, %d, %d)\n", channel->hw_value, | 3519 | IWL_DEBUG_MAC80211(mvm, "enter (%d, %d, %d)\n", channel->hw_value, |
@@ -3565,19 +3583,30 @@ static int iwl_mvm_roc(struct ieee80211_hw *hw, | |||
3565 | cfg80211_chandef_create(&chandef, channel, NL80211_CHAN_NO_HT); | 3583 | cfg80211_chandef_create(&chandef, channel, NL80211_CHAN_NO_HT); |
3566 | 3584 | ||
3567 | /* | 3585 | /* |
3568 | * Change the PHY context configuration as it is currently referenced | 3586 | * Check if the remain-on-channel is on a different band and that |
3569 | * only by the P2P Device MAC | 3587 | * requires context removal, see iwl_mvm_phy_ctxt_changed(). If |
3588 | * so, we'll need to release and then re-configure here, since we | ||
3589 | * must not remove a PHY context that's part of a binding. | ||
3570 | */ | 3590 | */ |
3571 | if (mvmvif->phy_ctxt->ref == 1) { | 3591 | band_change_removal = |
3592 | fw_has_capa(&mvm->fw->ucode_capa, | ||
3593 | IWL_UCODE_TLV_CAPA_BINDING_CDB_SUPPORT) && | ||
3594 | mvmvif->phy_ctxt->channel->band != chandef.chan->band; | ||
3595 | |||
3596 | if (mvmvif->phy_ctxt->ref == 1 && !band_change_removal) { | ||
3597 | /* | ||
3598 | * Change the PHY context configuration as it is currently | ||
3599 | * referenced only by the P2P Device MAC (and we can modify it) | ||
3600 | */ | ||
3572 | ret = iwl_mvm_phy_ctxt_changed(mvm, mvmvif->phy_ctxt, | 3601 | ret = iwl_mvm_phy_ctxt_changed(mvm, mvmvif->phy_ctxt, |
3573 | &chandef, 1, 1); | 3602 | &chandef, 1, 1); |
3574 | if (ret) | 3603 | if (ret) |
3575 | goto out_unlock; | 3604 | goto out_unlock; |
3576 | } else { | 3605 | } else { |
3577 | /* | 3606 | /* |
3578 | * The PHY context is shared with other MACs. Need to remove the | 3607 | * The PHY context is shared with other MACs (or we're trying to |
3579 | * P2P Device from the binding, allocate an new PHY context and | 3608 | * switch bands), so remove the P2P Device from the binding, |
3580 | * create a new binding | 3609 | * allocate an new PHY context and create a new binding. |
3581 | */ | 3610 | */ |
3582 | phy_ctxt = iwl_mvm_get_free_phy_ctxt(mvm); | 3611 | phy_ctxt = iwl_mvm_get_free_phy_ctxt(mvm); |
3583 | if (!phy_ctxt) { | 3612 | if (!phy_ctxt) { |