diff options
author | Emmanuel Grumbach <emmanuel.grumbach@intel.com> | 2019-06-24 13:57:34 +0300 |
---|---|---|
committer | Johannes Berg <johannes.berg@intel.com> | 2019-07-30 18:34:12 +0200 |
commit | c61b655a88a54d8690c1e134c47bc3f6d40d2dc3 (patch) | |
tree | 0e8ef82186ba0fee7501ea82e327b1f4b7c6de2d /drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c | |
parent | 6b2dbce549bb513316823af34e92f0bb2e0dbd55 (diff) |
iwlwifi: mvm: add a new RSS sync notification for NSSN sync
We will soon be using a new notification that will be
initiated by the driver, sent to the firmware and sent
back to all the RSS queues by the firmware. This new
notification will be useful to synchronize the NSSN across
all the queues.
For now, don't send the notification, just add the code to
handle it. Later patch will add the code to actually send
it.
While at it, validate the baid coming from the firmware to
avoid accessing an array with a bad index in the driver.
Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
Signed-off-by: Luca Coelho <luciano.coelho@intel.com>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Diffstat (limited to 'drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c')
-rw-r--r-- | drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c | 84 |
1 files changed, 52 insertions, 32 deletions
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c b/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c index 64f950501287..bf097329efa2 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c @@ -665,8 +665,51 @@ out: rcu_read_unlock(); } -void iwl_mvm_rx_queue_notif(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb, - int queue) +static void iwl_mvm_release_frames_from_notif(struct iwl_mvm *mvm, + struct napi_struct *napi, + u8 baid, u16 nssn, int queue) +{ + struct ieee80211_sta *sta; + struct iwl_mvm_reorder_buffer *reorder_buf; + struct iwl_mvm_baid_data *ba_data; + + IWL_DEBUG_HT(mvm, "Frame release notification for BAID %u, NSSN %d\n", + baid, nssn); + + if (WARN_ON_ONCE(baid == IWL_RX_REORDER_DATA_INVALID_BAID || + baid >= ARRAY_SIZE(mvm->baid_map))) + return; + + rcu_read_lock(); + + ba_data = rcu_dereference(mvm->baid_map[baid]); + if (WARN_ON_ONCE(!ba_data)) + goto out; + + sta = rcu_dereference(mvm->fw_id_to_mac_id[ba_data->sta_id]); + if (WARN_ON_ONCE(IS_ERR_OR_NULL(sta))) + goto out; + + reorder_buf = &ba_data->reorder_buf[queue]; + + spin_lock_bh(&reorder_buf->lock); + iwl_mvm_release_frames(mvm, sta, napi, ba_data, reorder_buf, nssn); + spin_unlock_bh(&reorder_buf->lock); + +out: + rcu_read_unlock(); +} + +static void iwl_mvm_nssn_sync(struct iwl_mvm *mvm, + struct napi_struct *napi, int queue, + const struct iwl_mvm_nssn_sync_data *data) +{ + iwl_mvm_release_frames_from_notif(mvm, napi, data->baid, + data->nssn, queue); +} + +void iwl_mvm_rx_queue_notif(struct iwl_mvm *mvm, struct napi_struct *napi, + struct iwl_rx_cmd_buffer *rxb, int queue) { struct iwl_rx_packet *pkt = rxb_addr(rxb); struct iwl_rxq_sync_notification *notif; @@ -687,6 +730,10 @@ void iwl_mvm_rx_queue_notif(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb, case IWL_MVM_RXQ_NOTIF_DEL_BA: iwl_mvm_del_ba(mvm, queue, (void *)internal_notif->data); break; + case IWL_MVM_RXQ_NSSN_SYNC: + iwl_mvm_nssn_sync(mvm, napi, queue, + (void *)internal_notif->data); + break; default: WARN_ONCE(1, "Invalid identifier %d", internal_notif->type); } @@ -1840,40 +1887,13 @@ void iwl_mvm_rx_monitor_no_data(struct iwl_mvm *mvm, struct napi_struct *napi, out: rcu_read_unlock(); } + void iwl_mvm_rx_frame_release(struct iwl_mvm *mvm, struct napi_struct *napi, struct iwl_rx_cmd_buffer *rxb, int queue) { struct iwl_rx_packet *pkt = rxb_addr(rxb); struct iwl_frame_release *release = (void *)pkt->data; - struct ieee80211_sta *sta; - struct iwl_mvm_reorder_buffer *reorder_buf; - struct iwl_mvm_baid_data *ba_data; - - int baid = release->baid; - IWL_DEBUG_HT(mvm, "Frame release notification for BAID %u, NSSN %d\n", - release->baid, le16_to_cpu(release->nssn)); - - if (WARN_ON_ONCE(baid == IWL_RX_REORDER_DATA_INVALID_BAID)) - return; - - rcu_read_lock(); - - ba_data = rcu_dereference(mvm->baid_map[baid]); - if (WARN_ON_ONCE(!ba_data)) - goto out; - - sta = rcu_dereference(mvm->fw_id_to_mac_id[ba_data->sta_id]); - if (WARN_ON_ONCE(IS_ERR_OR_NULL(sta))) - goto out; - - reorder_buf = &ba_data->reorder_buf[queue]; - - spin_lock_bh(&reorder_buf->lock); - iwl_mvm_release_frames(mvm, sta, napi, ba_data, reorder_buf, - le16_to_cpu(release->nssn)); - spin_unlock_bh(&reorder_buf->lock); - -out: - rcu_read_unlock(); + iwl_mvm_release_frames_from_notif(mvm, napi, release->baid, + le16_to_cpu(release->nssn), queue); } |