iwlwifi: mvm: utilize the frame release infrastructure
authorSara Sharon <sara.sharon@intel.com>
Sun, 28 Feb 2016 13:41:47 +0000 (15:41 +0200)
committerLuca Coelho <luciano.coelho@intel.com>
Tue, 10 May 2016 19:14:43 +0000 (22:14 +0300)
The firmware will send frame release notification in order
to release "stuck" frames on a queue where no more frames
arrive on.
Upon receiving the message the driver shall indicate the frames
up to the NSSN.

Signed-off-by: Sara Sharon <sara.sharon@intel.com>
Signed-off-by: Luca Coelho <luciano.coelho@intel.com>
drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
drivers/net/wireless/intel/iwlwifi/mvm/ops.c
drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c

index 3c331bd..6eaf21a 100644 (file)
@@ -1304,7 +1304,7 @@ void iwl_mvm_rx_rx_mpdu(struct iwl_mvm *mvm, struct napi_struct *napi,
 void iwl_mvm_rx_phy_cmd_mq(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb);
 void iwl_mvm_rx_mpdu_mq(struct iwl_mvm *mvm, struct napi_struct *napi,
                        struct iwl_rx_cmd_buffer *rxb, int queue);
-void iwl_mvm_rx_frame_release(struct iwl_mvm *mvm,
+void iwl_mvm_rx_frame_release(struct iwl_mvm *mvm, struct napi_struct *napi,
                              struct iwl_rx_cmd_buffer *rxb, int queue);
 int iwl_mvm_notify_rx_queue(struct iwl_mvm *mvm, u32 rxq_mask,
                            const u8 *data, u32 count);
index 7c6a598..2ba1369 100644 (file)
@@ -932,7 +932,7 @@ static void iwl_mvm_rx(struct iwl_op_mode *op_mode,
        if (likely(pkt->hdr.cmd == REPLY_RX_MPDU_CMD))
                iwl_mvm_rx_rx_mpdu(mvm, napi, rxb);
        else if (pkt->hdr.cmd == FRAME_RELEASE)
-               iwl_mvm_rx_frame_release(mvm, rxb, 0);
+               iwl_mvm_rx_frame_release(mvm, napi, rxb, 0);
        else if (pkt->hdr.cmd == REPLY_RX_PHY_CMD)
                iwl_mvm_rx_rx_phy_cmd(mvm, rxb);
        else
@@ -1634,7 +1634,7 @@ static void iwl_mvm_rx_mq_rss(struct iwl_op_mode *op_mode,
        struct iwl_rx_packet *pkt = rxb_addr(rxb);
 
        if (unlikely(pkt->hdr.cmd == FRAME_RELEASE))
-               iwl_mvm_rx_frame_release(mvm, rxb, queue);
+               iwl_mvm_rx_frame_release(mvm, napi, rxb, queue);
        else if (unlikely(pkt->hdr.cmd == RX_QUEUES_NOTIFICATION &&
                          pkt->hdr.group_id == DATA_PATH_GROUP))
                iwl_mvm_rx_queue_notif(mvm, rxb, queue);
index ed187af..0da93b5 100644 (file)
@@ -900,8 +900,37 @@ void iwl_mvm_rx_mpdu_mq(struct iwl_mvm *mvm, struct napi_struct *napi,
        rcu_read_unlock();
 }
 
-void iwl_mvm_rx_frame_release(struct iwl_mvm *mvm,
+void iwl_mvm_rx_frame_release(struct iwl_mvm *mvm, struct napi_struct *napi,
                              struct iwl_rx_cmd_buffer *rxb, int queue)
 {
-       /* TODO */
+       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;
+
+       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, reorder_buf,
+                              le16_to_cpu(release->nssn));
+       spin_unlock_bh(&reorder_buf->lock);
+
+out:
+       rcu_read_unlock();
 }