Ver Fonte

qcacld-3.0: Add peer ops support for SON

Add support for below SON peer ops:

PEER_SET_KICKOUT
PEER_SET_EXT_STATS
PEER_REQ_INST_STAT
PEER_GET_MAX_MCS

Change-Id: Iafadd17d6a13cfbba2884e50a0432c34115cd7f7
CRs-Fixed: 3141862
Rachit Kankane há 3 anos atrás
pai
commit
95c7d2ecf8

+ 29 - 0
components/son/dispatcher/inc/son_api.h

@@ -206,6 +206,35 @@ QDF_STATUS
 wlan_son_register_mlme_deliver_cb(struct wlan_objmgr_psoc *psoc,
 				  mlme_deliver_cb cb,
 				  enum SON_MLME_DELIVER_CB_TYPE type);
+/**
+ * wlan_son_peer_ext_stat_enable() - sends EXT stats command to FW
+ * @pdev: pointer to pdev
+ * @mac_addr: MAC address of the target peer
+ * @vdev: Pointer to vdev
+ * @stats_count: Stats count
+ * @enable: Enable / disable ext stats
+ *
+ * Return: QDF_STATUS_SUCCESS on success else failure
+ */
+QDF_STATUS wlan_son_peer_ext_stat_enable(struct wlan_objmgr_pdev *pdev,
+					 uint8_t *mac_addr,
+					 struct wlan_objmgr_vdev *vdev,
+					 uint32_t stats_count,
+					 uint32_t enable);
+
+/**
+ * wlan_son_peer_req_inst_stats() - Requests for instantaneous stats for
+ *				    the target mac_addr from FW via
+ *				    WMI_REQUEST_STATS_CMDID.
+ * @pdev: pointer to pdev
+ * @mac_addr: MAC address of the target peer
+ * @vdev: Pointer to vdev
+ *
+ * Return: QDF_STATUS_SUCCESS on success else failure
+ */
+QDF_STATUS wlan_son_peer_req_inst_stats(struct wlan_objmgr_pdev *pdev,
+					uint8_t *mac_addr,
+					struct wlan_objmgr_vdev *vdev);
 
 /**
  * wlan_son_get_chan_flag() - get chan flag

+ 59 - 0
components/son/dispatcher/src/son_api.c

@@ -91,6 +91,65 @@ static void wlan_son_is_he_supported(struct wlan_objmgr_psoc *psoc,
 }
 #endif /*WLAN_FEATURE_11AX*/
 
+QDF_STATUS wlan_son_peer_ext_stat_enable(struct wlan_objmgr_pdev *pdev,
+					 uint8_t *mac_addr,
+					 struct wlan_objmgr_vdev *vdev,
+					 uint32_t stats_count,
+					 uint32_t enable)
+{
+	struct wlan_lmac_if_tx_ops *tx_ops;
+	struct wlan_objmgr_psoc *psoc;
+
+	if (!pdev) {
+		qdf_err("invalid pdev");
+		return QDF_STATUS_E_NULL_VALUE;
+	}
+	psoc = wlan_pdev_get_psoc(pdev);
+	if (!psoc) {
+		qdf_err("invalid psoc");
+		return QDF_STATUS_E_NULL_VALUE;
+	}
+	tx_ops = wlan_psoc_get_lmac_if_txops(psoc);
+	if (!tx_ops) {
+		qdf_err("invalid tx_ops");
+		return QDF_STATUS_E_NULL_VALUE;
+	}
+	if (tx_ops->son_tx_ops.peer_ext_stats_enable)
+		return tx_ops->son_tx_ops.peer_ext_stats_enable(pdev,
+								mac_addr, vdev,
+								stats_count,
+								enable);
+
+	return QDF_STATUS_E_NULL_VALUE;
+}
+
+QDF_STATUS wlan_son_peer_req_inst_stats(struct wlan_objmgr_pdev *pdev,
+					uint8_t *mac_addr,
+					struct wlan_objmgr_vdev *vdev)
+{
+	struct wlan_lmac_if_tx_ops *tx_ops;
+	struct wlan_objmgr_psoc *psoc;
+
+	if (!pdev) {
+		qdf_err("invalid pdev");
+		return QDF_STATUS_E_NULL_VALUE;
+	}
+	psoc = wlan_pdev_get_psoc(pdev);
+	if (!psoc) {
+		qdf_err("invalid psoc");
+		return QDF_STATUS_E_NULL_VALUE;
+	}
+	tx_ops = wlan_psoc_get_lmac_if_txops(psoc);
+	if (!tx_ops) {
+		qdf_err("invalid tx_ops");
+		return QDF_STATUS_E_NULL_VALUE;
+	}
+	if (tx_ops->son_tx_ops.son_send_null)
+		return tx_ops->son_tx_ops.son_send_null(pdev, mac_addr, vdev);
+
+	return QDF_STATUS_E_NULL_VALUE;
+}
+
 uint32_t wlan_son_get_chan_flag(struct wlan_objmgr_pdev *pdev,
 				qdf_freq_t freq, bool flag_160,
 				struct ch_params *chan_params)

+ 32 - 0
core/hdd/src/wlan_hdd_son.c

@@ -2372,6 +2372,37 @@ static QDF_STATUS hdd_son_get_peer_capability(struct wlan_objmgr_vdev *vdev,
 	return QDF_STATUS_SUCCESS;
 }
 
+uint32_t hdd_son_get_peer_max_mcs_idx(struct wlan_objmgr_vdev *vdev,
+				      struct wlan_objmgr_peer *peer)
+{
+	uint32_t ret = 0;
+	struct hdd_station_info *sta_info = NULL;
+	struct hdd_adapter *adapter = NULL;
+
+	adapter = wlan_hdd_get_adapter_from_objmgr(vdev);
+	if (!adapter) {
+		hdd_err("null adapter");
+		return ret;
+	}
+
+	sta_info = hdd_get_sta_info_by_mac(&adapter->sta_info_list,
+					   peer->macaddr,
+					   STA_INFO_SOFTAP_GET_STA_INFO);
+	if (!sta_info) {
+		hdd_err("sta_info NULL");
+		return ret;
+	}
+
+	ret = sta_info->max_mcs_idx;
+
+	hdd_put_sta_info_ref(&adapter->sta_info_list, &sta_info, true,
+			     STA_INFO_SOFTAP_GET_STA_INFO);
+	hdd_debug("Peer " QDF_MAC_ADDR_FMT " max MCS index: %u",
+		  QDF_MAC_ADDR_REF(peer->macaddr), ret);
+
+	return ret;
+}
+
 void hdd_son_register_callbacks(struct hdd_context *hdd_ctx)
 {
 	struct son_callbacks cb_obj = {0};
@@ -2409,6 +2440,7 @@ void hdd_son_register_callbacks(struct hdd_context *hdd_ctx)
 	cb_obj.os_if_get_acs_report = hdd_son_get_acs_report;
 	cb_obj.os_if_get_node_info = hdd_son_get_node_info;
 	cb_obj.os_if_get_peer_capability = hdd_son_get_peer_capability;
+	cb_obj.os_if_get_peer_max_mcs_idx = hdd_son_get_peer_max_mcs_idx;
 
 	os_if_son_register_hdd_callbacks(hdd_ctx->psoc, &cb_obj);
 

+ 17 - 0
core/hdd/src/wlan_hdd_son.h

@@ -112,6 +112,15 @@ int hdd_son_send_get_wifi_generic_command(struct wiphy *wiphy,
 					  struct wireless_dev *wdev,
 					  struct nlattr **tb);
 
+/**
+ * hdd_son_get_peer_max_mcs_idx() - Get peer max mcs index
+ * @vdev: vdev object
+ * @peer: peer obj
+ *
+ * Return: number of max mcs on succes or 0 on failure
+ */
+uint32_t hdd_son_get_peer_max_mcs_idx(struct wlan_objmgr_vdev *vdev,
+				      struct wlan_objmgr_peer *peer);
 #else
 
 static inline void hdd_son_register_callbacks(struct hdd_context *hdd_ctx)
@@ -161,5 +170,13 @@ int hdd_son_send_get_wifi_generic_command(struct wiphy *wiphy,
 {
 	return -EINVAL;
 }
+
+static inline
+uint32_t hdd_son_get_peer_max_mcs_idx(struct wlan_objmgr_vdev *vdev,
+				      struct wlan_objmgr_peer *peer)
+{
+	return 0;
+}
+
 #endif /* WLAN_FEATURE_SON */
 #endif

+ 6 - 0
core/wma/inc/wma.h

@@ -290,6 +290,12 @@
 #define WMA_DEFAULT_HW_MODE_INDEX 0xFFFF
 #define TWO_THIRD (2/3)
 
+#ifdef WLAN_FEATURE_SON
+#define WMA_SON_MAX_PEER_EXT_STATS 16
+#else
+#define WMA_SON_MAX_PEER_EXT_STATS 0
+#endif
+
 /**
  * WMA hardware mode list bit-mask definitions.
  * Bits 4:0, 31:29 are unused.

+ 1 - 0
core/wma/src/wma_main.c

@@ -6923,6 +6923,7 @@ int wma_rx_service_ready_ext_event(void *handle, uint8_t *event,
 		wlan_res_cfg->pktcapture_support = true;
 	else
 		wlan_res_cfg->pktcapture_support = false;
+	wlan_res_cfg->max_peer_ext_stats = WMA_SON_MAX_PEER_EXT_STATS;
 
 	if (wmi_service_enabled(wmi_handle,
 				wmi_service_sae_eapol_offload_support))

+ 13 - 0
os_if/son/inc/os_if_son.h

@@ -68,6 +68,7 @@
  * @os_if_get_acs_report: Gets the ACS report
  * @os_if_get_node_info: Gets the datarate info for node
  * @os_if_get_peer_capability: Gets peer capability
+ * @os_if_get_peer_max_mcs_idx: Gets peer max MCS index
  */
 struct son_callbacks {
 	uint32_t (*os_if_is_acs_in_progress)(struct wlan_objmgr_vdev *vdev);
@@ -133,6 +134,8 @@ struct son_callbacks {
 	QDF_STATUS (*os_if_get_peer_capability)(struct wlan_objmgr_vdev *vdev,
 						struct wlan_objmgr_peer *peer,
 						wlan_peer_cap *cap);
+	uint32_t (*os_if_get_peer_max_mcs_idx)(struct wlan_objmgr_vdev *vdev,
+					       struct wlan_objmgr_peer *peer);
 };
 
 /**
@@ -764,4 +767,14 @@ int os_if_son_parse_generic_nl_cmd(struct wiphy *wiphy,
 QDF_STATUS os_if_son_get_node_datarate_info(struct wlan_objmgr_vdev *vdev,
 					    uint8_t *mac_addr,
 					    wlan_node_info *node_info);
+
+/**
+ * os_if_son_get_peer_max_mcs_idx() - Get max mcs index of the peer
+ * @vdev: vdev obj
+ * @peer: peer obj
+ *
+ * Return: max mcs index on success / 0 on failure
+ */
+uint32_t os_if_son_get_peer_max_mcs_idx(struct wlan_objmgr_vdev *vdev,
+					struct wlan_objmgr_peer *peer);
 #endif

+ 61 - 0
os_if/son/src/os_if_son.c

@@ -975,6 +975,9 @@ QDF_STATUS os_if_son_peer_ops(struct wlan_objmgr_peer *peer,
 	struct wlan_objmgr_pdev *pdev;
 	struct wlan_objmgr_psoc *psoc;
 	QDF_STATUS status = QDF_STATUS_SUCCESS;
+	struct qdf_mac_addr mac;
+	int ret_val;
+	static uint32_t peer_ext_stats_count;
 
 	if (!peer) {
 		osif_err("null peer");
@@ -1000,6 +1003,18 @@ QDF_STATUS os_if_son_peer_ops(struct wlan_objmgr_peer *peer,
 	osif_debug("type %d", type);
 	/* All PEER MLME operations exported to SON component */
 	switch (type) {
+	/* SET/CLR API start */
+	case PEER_SET_KICKOUT:
+		qdf_mem_copy(&mac.bytes, peer->macaddr, QDF_MAC_ADDR_SIZE);
+		ret_val =
+		    g_son_os_if_cb.os_if_kickout_mac(vdev->vdev_objmgr.vdev_id,
+						     &mac);
+		if (ret_val) {
+			osif_err("Failed to kickout peer " QDF_MAC_ADDR_FMT,
+				 QDF_MAC_ADDR_REF(peer->macaddr));
+			return QDF_STATUS_E_INVAL;
+		}
+		break;
 	case PEER_SET_KICKOUT_ALLOW:
 		if (!in) {
 			osif_err("invalid input parameter");
@@ -1007,6 +1022,38 @@ QDF_STATUS os_if_son_peer_ops(struct wlan_objmgr_peer *peer,
 		}
 		status = ucfg_son_set_peer_kickout_allow(vdev, peer,
 							 in->enable);
+		osif_debug("kickout allow %d, status %d", in->enable, status);
+		break;
+	case PEER_SET_EXT_STATS:
+		if (!in)
+			return QDF_STATUS_E_INVAL;
+		ret_val = wlan_peer_mlme_flag_get(peer, WLAN_PEER_F_EXT_STATS);
+		osif_debug("Enable: %d peer_ext_stats_count: %u ret_val: %d",
+			   in->enable, peer_ext_stats_count, ret_val);
+		if ((!!ret_val) != in->enable) {
+			status =
+			     wlan_son_peer_ext_stat_enable(pdev, peer->macaddr,
+							   vdev,
+							   peer_ext_stats_count,
+							   in->enable);
+			osif_debug("status: %u", status);
+			if (status == QDF_STATUS_SUCCESS) {
+				peer_ext_stats_count++;
+				wlan_peer_mlme_flag_set(peer,
+							WLAN_PEER_F_EXT_STATS);
+			} else {
+				if (peer_ext_stats_count)
+					peer_ext_stats_count--;
+				wlan_peer_mlme_flag_clear
+						(peer, WLAN_PEER_F_EXT_STATS);
+			}
+		}
+		break;
+	case PEER_REQ_INST_STAT:
+		status = wlan_son_peer_req_inst_stats(pdev, peer->macaddr,
+						      vdev);
+		if (status != QDF_STATUS_SUCCESS)
+			osif_err("Type: %d is failed", type);
 		break;
 	case PEER_GET_CAPABILITY:
 		if (!out)
@@ -1014,6 +1061,11 @@ QDF_STATUS os_if_son_peer_ops(struct wlan_objmgr_peer *peer,
 		status = os_if_son_get_peer_capability(vdev, peer,
 						       &out->peercap);
 		break;
+	case PEER_GET_MAX_MCS:
+		if (!out)
+			return QDF_STATUS_E_INVAL;
+		out->mcs = os_if_son_get_peer_max_mcs_idx(vdev, peer);
+		break;
 	default:
 		osif_err("invalid type: %d", type);
 		status = QDF_STATUS_E_INVAL;
@@ -1644,3 +1696,12 @@ QDF_STATUS os_if_son_get_node_datarate_info(struct wlan_objmgr_vdev *vdev,
 	}
 	return status;
 }
+
+uint32_t os_if_son_get_peer_max_mcs_idx(struct wlan_objmgr_vdev *vdev,
+					struct wlan_objmgr_peer *peer)
+{
+	if (g_son_os_if_cb.os_if_get_peer_max_mcs_idx)
+		return g_son_os_if_cb.os_if_get_peer_max_mcs_idx(vdev, peer);
+
+	return 0;
+}