Bläddra i källkod

qcacmn: Add support for WDS source port learning

Add or update WDS peer entry whenever source address of the
received pkt does not match with the peer table entries.

Change-Id: I7798a5b795777451f534be7d25d5f9b930f5c305
CRs-Fixed: 1117405
Ishank Jain 8 år sedan
förälder
incheckning
2bf04b40c0
6 ändrade filer med 227 tillägg och 1 borttagningar
  1. 8 0
      dp/inc/cdp_txrx_ops.h
  2. 1 1
      dp/wifi3.0/dp_rx.c
  3. 52 0
      dp/wifi3.0/dp_rx.h
  4. 13 0
      dp/wifi3.0/dp_rx_err.c
  5. 50 0
      dp/wifi3.0/hal_rx.h
  6. 103 0
      wmi/src/wmi_unified_tlv.c

+ 8 - 0
dp/inc/cdp_txrx_ops.h

@@ -496,6 +496,14 @@ struct ol_if_ops {
 	int (*peer_unref_delete)(void *ol_soc_handle, uint8_t vdev_id,
 			uint8_t *peer_macaddr);
 	bool (*is_hw_dbs_2x2_capable)(void);
+	int (*peer_add_wds_entry)(void *ol_soc_handle,
+			const uint8_t *dest_macaddr, uint8_t *peer_macaddr,
+			uint32_t flags);
+	int (*peer_update_wds_entry)(void *ol_soc_handle,
+			uint8_t *dest_macaddr, uint8_t *peer_macaddr,
+			uint32_t flags);
+	void (*peer_del_wds_entry)(void *ol_soc_handle,
+			uint8_t *wds_macaddr);
 
 	/* TODO: Add any other control path calls required to OL_IF/WMA layer */
 };

+ 1 - 1
dp/wifi3.0/dp_rx.c

@@ -486,8 +486,8 @@ done:
 					qdf_nbuf_data(nbuf), 128, false);
 #endif /* NAPIER_EMULATION */
 
-			/* TODO */
 			/* WDS Source Port Learning */
+			dp_rx_wds_srcport_learn(soc, rx_tlv_hdr, peer, nbuf);
 
 			/* Intrabss-fwd */
 			if (dp_rx_intrabss_fwd(soc, peer, rx_tlv_hdr, nbuf))

+ 52 - 0
dp/wifi3.0/dp_rx.h

@@ -21,6 +21,7 @@
 
 #include "hal_rx.h"
 #include "dp_tx.h"
+#include "dp_peer.h"
 
 #ifdef RXDMA_OPTIMIZATION
 #define RX_BUFFER_ALIGNMENT     128
@@ -161,6 +162,57 @@ void dp_rx_add_to_free_desc_list(union dp_rx_desc_list_elem_t **head,
 
 }
 
+/**
+ * dp_rx_wds_srcport_learn() - Add or update the STA PEER which
+ *				is behind the WDS repeater.
+ *
+ * @soc: core txrx main context
+ * @rx_tlv_hdr: base address of RX TLV header
+ * @ta_peer: WDS repeater peer
+ * @nbuf: rx pkt
+ *
+ * Return: void:
+ */
+#ifndef CONFIG_MCL
+static inline void
+dp_rx_wds_srcport_learn(struct dp_soc *soc,
+			 uint8_t *rx_tlv_hdr,
+			 struct dp_peer *ta_peer,
+			 qdf_nbuf_t nbuf)
+{
+	uint16_t sa_sw_peer_id = hal_rx_msdu_end_sa_sw_peer_id_get(rx_tlv_hdr);
+	uint32_t flags = IEEE80211_NODE_F_WDS_HM;
+	uint32_t ret = 0;
+	uint8_t wds_src_mac[IEEE80211_ADDR_LEN];
+
+	memcpy(wds_src_mac, (qdf_nbuf_data(nbuf) + IEEE80211_ADDR_LEN),
+		IEEE80211_ADDR_LEN);
+
+	if (!hal_rx_msdu_end_sa_is_valid_get(rx_tlv_hdr)) {
+		ret = soc->cdp_soc.ol_ops->peer_add_wds_entry(
+						soc->osif_soc,
+						wds_src_mac,
+						ta_peer->mac_addr.raw,
+						flags);
+	} else if (sa_sw_peer_id != ta_peer->peer_ids[0]) {
+		ret = soc->cdp_soc.ol_ops->peer_update_wds_entry(
+						soc->osif_soc,
+						wds_src_mac,
+						ta_peer->mac_addr.raw,
+						flags);
+	}
+	return;
+}
+#else
+static inline void
+dp_rx_wds_srcport_learn(struct dp_soc *soc,
+			 uint8_t *rx_tlv_hdr,
+			 struct dp_peer *ta_peer,
+			 qdf_nbuf_t nbuf)
+{
+}
+#endif
+
 #define DP_RX_LIST_APPEND(head, tail, elem) \
 do {                                                \
 	if (!(head)) {                              \

+ 13 - 0
dp/wifi3.0/dp_rx_err.c

@@ -260,6 +260,7 @@ dp_rx_null_q_desc_handle(struct dp_soc *soc, struct dp_rx_desc *rx_desc,
 	uint16_t peer_id = 0xFFFF;
 	struct dp_peer *peer = NULL;
 	uint32_t sgi, rate_mcs, tid;
+	uint32_t peer_mdata;
 
 	rx_bufs_used++;
 
@@ -309,6 +310,18 @@ dp_rx_null_q_desc_handle(struct dp_soc *soc, struct dp_rx_desc *rx_desc,
 		"%s: %d, SGI: %d, rate_mcs: %d, tid: %d",
 		__func__, __LINE__, sgi, rate_mcs, tid);
 
+	peer_mdata = hal_rx_mpdu_peer_meta_data_get(rx_desc->rx_buf_start);
+	peer_id = DP_PEER_METADATA_PEER_ID_GET(peer_mdata);
+	peer = dp_peer_find_by_id(soc, peer_id);
+
+	if (!peer) {
+		qdf_nbuf_free(nbuf);
+		goto fail;
+	}
+
+	/* WDS Source Port Learning */
+	dp_rx_wds_srcport_learn(soc, rx_desc->rx_buf_start, peer, nbuf);
+
 	/*
 	 * Advance the packet start pointer by total size of
 	 * pre-header TLV's

+ 50 - 0
dp/wifi3.0/hal_rx.h

@@ -611,6 +611,56 @@ hal_rx_msdu_end_l3_hdr_padding_get(uint8_t *buf)
 	return l3_header_padding;
 }
 
+#define HAL_RX_MSDU_END_SA_IS_VALID_GET(_rx_msdu_end)	\
+	(_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_msdu_end,	\
+		RX_MSDU_END_5_SA_IS_VALID_OFFSET)),	\
+		RX_MSDU_END_5_SA_IS_VALID_MASK,		\
+		RX_MSDU_END_5_SA_IS_VALID_LSB))
+
+ /**
+ * hal_rx_msdu_end_sa_is_valid_get(): API to get the
+ * sa_is_valid bit from rx_msdu_end TLV
+ *
+ * @ buf: pointer to the start of RX PKT TLV headers
+ * Return: sa_is_valid bit
+ */
+static inline uint8_t
+hal_rx_msdu_end_sa_is_valid_get(uint8_t *buf)
+{
+	struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf;
+	struct rx_msdu_end *msdu_end = &pkt_tlvs->msdu_end_tlv.rx_msdu_end;
+	uint8_t sa_is_valid;
+
+	sa_is_valid = HAL_RX_MSDU_END_SA_IS_VALID_GET(msdu_end);
+
+	return sa_is_valid;
+}
+
+#define HAL_RX_MSDU_END_SA_SW_PEER_ID_GET(_rx_msdu_end)		\
+	(_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_msdu_end,		\
+		RX_MSDU_END_16_SA_SW_PEER_ID_OFFSET)),		\
+		RX_MSDU_END_16_SA_SW_PEER_ID_MASK,		\
+		RX_MSDU_END_16_SA_SW_PEER_ID_LSB))
+
+ /**
+ * hal_rx_msdu_end_sa_sw_peer_id_get(): API to get the
+ * sa_sw_peer_id from rx_msdu_end TLV
+ *
+ * @ buf: pointer to the start of RX PKT TLV headers
+ * Return: sa_sw_peer_id index
+ */
+static inline uint32_t
+hal_rx_msdu_end_sa_sw_peer_id_get(uint8_t *buf)
+{
+	struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf;
+	struct rx_msdu_end *msdu_end = &pkt_tlvs->msdu_end_tlv.rx_msdu_end;
+	uint32_t sa_sw_peer_id;
+
+	sa_sw_peer_id = HAL_RX_MSDU_END_SA_SW_PEER_ID_GET(msdu_end);
+
+	return sa_sw_peer_id;
+}
+
 #define HAL_RX_MSDU_START_MSDU_LEN_GET(_rx_msdu_start)		\
 	(_HAL_MS((*_OFFSET_TO_WORD_PTR(_rx_msdu_start,		\
 		RX_MSDU_START_1_MSDU_LENGTH_OFFSET)),		\

+ 103 - 0
wmi/src/wmi_unified_tlv.c

@@ -838,6 +838,106 @@ QDF_STATUS send_peer_rx_reorder_queue_remove_cmd_tlv(wmi_unified_t wmi,
 	return QDF_STATUS_SUCCESS;
 }
 
+/**
+ * send_peer_add_wds_entry_cmd_tlv() - send peer add command to fw
+ * @wmi_handle: wmi handle
+ * @param: pointer holding peer details
+ *
+ * Return: 0 for success or error code
+ */
+static QDF_STATUS send_peer_add_wds_entry_cmd_tlv(wmi_unified_t wmi_handle,
+					struct peer_add_wds_entry_params *param)
+{
+	wmi_peer_add_wds_entry_cmd_fixed_param *cmd;
+	wmi_buf_t buf;
+	int len = sizeof(*cmd);
+
+	buf = wmi_buf_alloc(wmi_handle, len);
+	if (!buf) {
+		qdf_print("%s: wmi_buf_alloc failed\n", __func__);
+		return QDF_STATUS_E_FAILURE;
+	}
+	cmd = (wmi_peer_add_wds_entry_cmd_fixed_param *) wmi_buf_data(buf);
+	WMITLV_SET_HDR(&cmd->tlv_header,
+			WMITLV_TAG_STRUC_wmi_peer_add_wds_entry_cmd_fixed_param,
+			WMITLV_GET_STRUCT_TLVLEN
+				(wmi_peer_add_wds_entry_cmd_fixed_param));
+	WMI_CHAR_ARRAY_TO_MAC_ADDR(param->dest_addr, &cmd->wds_macaddr);
+	WMI_CHAR_ARRAY_TO_MAC_ADDR(param->peer_addr, &cmd->peer_macaddr);
+	cmd->flags = param->flags;
+
+	return wmi_unified_cmd_send(wmi_handle, buf, len,
+			WMI_PEER_ADD_WDS_ENTRY_CMDID);
+}
+
+/**
+ * send_peer_del_wds_entry_cmd_non_tlv() - send peer delete command to fw
+ * @wmi_handle: wmi handle
+ * @param: pointer holding peer details
+ *
+ * Return: 0 for success or error code
+ */
+static QDF_STATUS send_peer_del_wds_entry_cmd_tlv(wmi_unified_t wmi_handle,
+					struct peer_del_wds_entry_params *param)
+{
+	wmi_peer_remove_wds_entry_cmd_fixed_param *cmd;
+	wmi_buf_t buf;
+	int len = sizeof(*cmd);
+
+	buf = wmi_buf_alloc(wmi_handle, len);
+	if (!buf) {
+		qdf_print("%s: wmi_buf_alloc failed\n", __func__);
+		return QDF_STATUS_E_NOMEM;
+	}
+	cmd = (wmi_peer_remove_wds_entry_cmd_fixed_param *)wmi_buf_data(buf);
+	WMITLV_SET_HDR(&cmd->tlv_header,
+			WMITLV_TAG_STRUC_wmi_peer_remove_wds_entry_cmd_fixed_param,
+			WMITLV_GET_STRUCT_TLVLEN
+				(wmi_peer_remove_wds_entry_cmd_fixed_param));
+	WMI_CHAR_ARRAY_TO_MAC_ADDR(param->dest_addr, &cmd->wds_macaddr);
+	return wmi_unified_cmd_send(wmi_handle, buf, len,
+			WMI_PEER_REMOVE_WDS_ENTRY_CMDID);
+}
+
+/**
+ * send_peer_update_wds_entry_cmd_non_tlv() - send peer update command to fw
+ * @wmi_handle: wmi handle
+ * @param: pointer holding peer details
+ *
+ * Return: 0 for success or error code
+ */
+static QDF_STATUS send_peer_update_wds_entry_cmd_tlv(wmi_unified_t wmi_handle,
+				struct peer_update_wds_entry_params *param)
+{
+	wmi_peer_update_wds_entry_cmd_fixed_param *cmd;
+	wmi_buf_t buf;
+	int len = sizeof(*cmd);
+
+	buf = wmi_buf_alloc(wmi_handle, len);
+	if (!buf) {
+		qdf_print("%s: wmi_buf_alloc failed\n", __func__);
+		return QDF_STATUS_E_NOMEM;
+	}
+
+	/* wmi_buf_alloc returns zeroed command buffer */
+	cmd = (wmi_peer_update_wds_entry_cmd_fixed_param *)wmi_buf_data(buf);
+	WMITLV_SET_HDR(&cmd->tlv_header,
+			WMITLV_TAG_STRUC_wmi_peer_update_wds_entry_cmd_fixed_param,
+			WMITLV_GET_STRUCT_TLVLEN
+				(wmi_peer_update_wds_entry_cmd_fixed_param));
+	cmd->flags = (param->flags) ? WMI_WDS_FLAG_STATIC : 0;
+	if (param->wds_macaddr)
+		WMI_CHAR_ARRAY_TO_MAC_ADDR(param->wds_macaddr,
+				&cmd->wds_macaddr);
+	if (param->peer_macaddr)
+		WMI_CHAR_ARRAY_TO_MAC_ADDR(param->peer_macaddr,
+				&cmd->peer_macaddr);
+	return wmi_unified_cmd_send(wmi_handle, buf, len,
+			WMI_PEER_UPDATE_WDS_ENTRY_CMDID);
+}
+
+
+
 /**
  * send_green_ap_ps_cmd_tlv() - enable green ap powersave command
  * @wmi_handle: wmi handle
@@ -14075,6 +14175,9 @@ struct wmi_ops tlv_ops =  {
 		send_peer_rx_reorder_queue_setup_cmd_tlv,
 	.send_peer_rx_reorder_queue_remove_cmd =
 		send_peer_rx_reorder_queue_remove_cmd_tlv,
+	.send_peer_add_wds_entry_cmd = send_peer_add_wds_entry_cmd_tlv,
+	.send_peer_del_wds_entry_cmd = send_peer_del_wds_entry_cmd_tlv,
+	.send_peer_update_wds_entry_cmd = send_peer_update_wds_entry_cmd_tlv,
 	.send_green_ap_ps_cmd = send_green_ap_ps_cmd_tlv,
 	.send_pdev_utf_cmd = send_pdev_utf_cmd_tlv,
 	.send_pdev_param_cmd = send_pdev_param_cmd_tlv,