Browse Source

qcacmn: Implement send DELBA per HTT event

Is some cases, FW wants to adjust BA session parameters
FW sends a HTT event and HOST helps to send out DELBA
and modify BA win size in the next round of ADDBA req/resp
exchange to reduce following RX AMPDU aggr-size

Change-Id: I97777ff59a18346f2cd4e2e562c8ae6acdcd69d7
CRs-Fixed: 2644641
Yu Tian 5 years ago
parent
commit
8abdbcc616
5 changed files with 117 additions and 0 deletions
  1. 21 0
      dp/wifi3.0/dp_htt.c
  2. 6 0
      dp/wifi3.0/dp_htt.h
  3. 83 0
      dp/wifi3.0/dp_peer.c
  4. 4 0
      dp/wifi3.0/dp_peer.h
  5. 3 0
      dp/wifi3.0/dp_types.h

+ 21 - 0
dp/wifi3.0/dp_htt.c

@@ -4347,6 +4347,27 @@ static void dp_htt_t2h_msg_handler(void *context, HTC_PACKET *pkt)
 						 is_wds);
 						 is_wds);
 			break;
 			break;
 		}
 		}
+	case HTT_T2H_MSG_TYPE_RX_DELBA:
+		{
+			uint16_t peer_id;
+			uint8_t tid;
+			uint8_t win_sz;
+			QDF_STATUS status;
+
+			peer_id = HTT_RX_DELBA_PEER_ID_GET(*msg_word);
+			tid = HTT_RX_DELBA_TID_GET(*msg_word);
+			win_sz = HTT_RX_DELBA_WIN_SIZE_GET(*msg_word);
+
+			status = dp_rx_delba_ind_handler(
+				soc->dp_soc,
+				peer_id, tid, win_sz);
+
+			QDF_TRACE(QDF_MODULE_ID_TXRX,
+				  QDF_TRACE_LEVEL_INFO,
+				  FL("DELBA PeerID %d BAW %d TID %d stat %d"),
+				  peer_id, win_sz, tid, status);
+			break;
+		}
 	default:
 	default:
 		break;
 		break;
 	};
 	};

+ 6 - 0
dp/wifi3.0/dp_htt.h

@@ -95,6 +95,12 @@ int htt_wbm_event_record(struct htt_logger *h, uint8_t tx_status,
 #define HTT_PPDU_DESC_MAX_DEPTH 16
 #define HTT_PPDU_DESC_MAX_DEPTH 16
 #define DP_SCAN_PEER_ID 0xFFFF
 #define DP_SCAN_PEER_ID 0xFFFF
 
 
+#define HTT_RX_DELBA_WIN_SIZE_M    0x0000FC00
+#define HTT_RX_DELBA_WIN_SIZE_S    10
+
+#define HTT_RX_DELBA_WIN_SIZE_GET(word)		\
+	(((word) & HTT_RX_DELBA_WIN_SIZE_M) >> HTT_RX_DELBA_WIN_SIZE_S)
+
 /*
 /*
  * Set the base misclist size to HTT copy engine source ring size
  * Set the base misclist size to HTT copy engine source ring size
  * to guarantee that a packet on the misclist wont be freed while it
  * to guarantee that a packet on the misclist wont be freed while it

+ 83 - 0
dp/wifi3.0/dp_peer.c

@@ -2812,6 +2812,8 @@ static void dp_check_ba_buffersize(struct dp_peer *peer,
 	}
 	}
 }
 }
 
 
+#define DP_RX_BA_SESSION_DISABLE  1
+
 /*
 /*
  * dp_addba_requestprocess_wifi3() - Process ADDBA request from peer
  * dp_addba_requestprocess_wifi3() - Process ADDBA request from peer
  *
  *
@@ -2863,6 +2865,25 @@ int dp_addba_requestprocess_wifi3(struct cdp_soc_t *cdp_soc,
 		status = QDF_STATUS_E_FAILURE;
 		status = QDF_STATUS_E_FAILURE;
 		goto fail;
 		goto fail;
 	}
 	}
+
+	if (rx_tid->rx_ba_win_size_override == DP_RX_BA_SESSION_DISABLE) {
+		QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_INFO,
+			  "%s disable BA session",
+			    __func__);
+
+		buffersize = 1;
+	} else if (rx_tid->rx_ba_win_size_override) {
+		QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_INFO,
+			  "%s override BA win to %d", __func__,
+			      rx_tid->rx_ba_win_size_override);
+
+		buffersize = rx_tid->rx_ba_win_size_override;
+	} else {
+		QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_INFO,
+			  "%s restore BA win %d based on addba req",
+			    __func__, buffersize);
+	}
+
 	dp_check_ba_buffersize(peer, tid, buffersize);
 	dp_check_ba_buffersize(peer, tid, buffersize);
 
 
 	if (dp_rx_tid_setup_wifi3(peer, tid,
 	if (dp_rx_tid_setup_wifi3(peer, tid,
@@ -2882,6 +2903,9 @@ int dp_addba_requestprocess_wifi3(struct cdp_soc_t *cdp_soc,
 	else
 	else
 		rx_tid->statuscode = IEEE80211_STATUS_SUCCESS;
 		rx_tid->statuscode = IEEE80211_STATUS_SUCCESS;
 
 
+	if (rx_tid->rx_ba_win_size_override == DP_RX_BA_SESSION_DISABLE)
+		rx_tid->statuscode = IEEE80211_STATUS_REFUSED;
+
 	qdf_spin_unlock_bh(&rx_tid->tid_lock);
 	qdf_spin_unlock_bh(&rx_tid->tid_lock);
 
 
 fail:
 fail:
@@ -3279,6 +3303,65 @@ dp_rx_sec_ind_handler(struct dp_soc *soc, uint16_t peer_id,
 	dp_peer_unref_del_find_by_id(peer);
 	dp_peer_unref_del_find_by_id(peer);
 }
 }
 
 
+QDF_STATUS
+dp_rx_delba_ind_handler(void *soc_handle, uint16_t peer_id,
+			uint8_t tid, uint16_t win_sz)
+{
+	struct dp_soc *soc = (struct dp_soc *)soc_handle;
+	struct dp_peer *peer;
+	struct dp_rx_tid *rx_tid;
+	QDF_STATUS status = QDF_STATUS_SUCCESS;
+
+	peer = dp_peer_find_by_id(soc, peer_id);
+
+	if (!peer) {
+		QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
+			  "Couldn't find peer from ID %d",
+			  peer_id);
+		return QDF_STATUS_E_FAILURE;
+	}
+
+	qdf_assert_always(tid < DP_MAX_TIDS);
+
+	rx_tid = &peer->rx_tid[tid];
+
+	if (rx_tid->hw_qdesc_vaddr_unaligned) {
+		if (!rx_tid->delba_tx_status) {
+			QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_INFO,
+				  "%s: PEER_ID: %d TID: %d, BA win: %d ",
+				  __func__, peer_id, tid, win_sz);
+
+			qdf_spin_lock_bh(&rx_tid->tid_lock);
+
+			rx_tid->delba_tx_status = 1;
+
+			rx_tid->rx_ba_win_size_override =
+			    qdf_min((uint16_t)63, win_sz);
+
+			rx_tid->delba_rcode =
+			    IEEE80211_REASON_QOS_SETUP_REQUIRED;
+
+			qdf_spin_unlock_bh(&rx_tid->tid_lock);
+
+			if (soc->cdp_soc.ol_ops->send_delba)
+				soc->cdp_soc.ol_ops->send_delba(
+					peer->vdev->pdev->soc->ctrl_psoc,
+					peer->vdev->vdev_id,
+					peer->mac_addr.raw,
+					tid,
+					rx_tid->delba_rcode);
+		}
+	} else {
+		QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
+			  "BA session is not setup for TID:%d ", tid);
+		status = QDF_STATUS_E_FAILURE;
+	}
+
+	dp_peer_unref_del_find_by_id(peer);
+
+	return status;
+}
+
 #ifdef DP_PEER_EXTENDED_API
 #ifdef DP_PEER_EXTENDED_API
 QDF_STATUS dp_register_peer(struct cdp_soc_t *soc_hdl, uint8_t pdev_id,
 QDF_STATUS dp_register_peer(struct cdp_soc_t *soc_hdl, uint8_t pdev_id,
 			    struct ol_txrx_desc_type *sta_desc)
 			    struct ol_txrx_desc_type *sta_desc)

+ 4 - 0
dp/wifi3.0/dp_peer.h

@@ -100,6 +100,10 @@ void dp_rx_peer_unmap_handler(struct dp_soc *soc, uint16_t peer_id,
 void dp_rx_sec_ind_handler(struct dp_soc *soc, uint16_t peer_id,
 void dp_rx_sec_ind_handler(struct dp_soc *soc, uint16_t peer_id,
 			   enum cdp_sec_type sec_type, int is_unicast,
 			   enum cdp_sec_type sec_type, int is_unicast,
 			   u_int32_t *michael_key, u_int32_t *rx_pn);
 			   u_int32_t *michael_key, u_int32_t *rx_pn);
+
+QDF_STATUS dp_rx_delba_ind_handler(void *soc_handle, uint16_t peer_id,
+				   uint8_t tid, uint16_t win_sz);
+
 uint8_t dp_get_peer_mac_addr_frm_id(struct cdp_soc_t *soc_handle,
 uint8_t dp_get_peer_mac_addr_frm_id(struct cdp_soc_t *soc_handle,
 		uint16_t peer_id, uint8_t *peer_mac);
 		uint16_t peer_id, uint8_t *peer_mac);
 
 

+ 3 - 0
dp/wifi3.0/dp_types.h

@@ -600,6 +600,9 @@ struct dp_rx_tid {
 	/* Delba reason code for retries */
 	/* Delba reason code for retries */
 	uint8_t delba_rcode;
 	uint8_t delba_rcode;
 
 
+	/* Coex Override preserved windows size 1 based */
+	uint16_t rx_ba_win_size_override;
+
 #ifdef WLAN_PEER_JITTER
 #ifdef WLAN_PEER_JITTER
 	/* Tx Jitter stats */
 	/* Tx Jitter stats */
 	uint32_t tx_avg_jitter;
 	uint32_t tx_avg_jitter;