From 07fd1a8fe90c753bea7a38af4e18d75f673a0b93 Mon Sep 17 00:00:00 2001 From: Surabhi Vishnoi Date: Tue, 28 Apr 2020 11:52:55 +0530 Subject: [PATCH] qcacld-3.0: Add support to handle CFR vendor command for adrastea Adrastea target expects different attributes in vendor command QCA_NL80211_VENDOR_SUBCMD_PEER_CFR_CAPTURE_CFG. So add an api to parse the vendor command QCA_NL80211_VENDOR_SUBCMD_PEER_CFR_CAPTURE_CFG which will be called based on CFR version type. Change-Id: I965b3cd6b93a288f1074ea0c09306cfff9f6ced0 CRs-Fixed: 2687075 --- core/hdd/inc/wlan_hdd_cfr.h | 1 + core/hdd/src/wlan_hdd_cfr.c | 120 +++++++++++++++++++++++++++++++++++- 2 files changed, 120 insertions(+), 1 deletion(-) diff --git a/core/hdd/inc/wlan_hdd_cfr.h b/core/hdd/inc/wlan_hdd_cfr.h index ed3b206e7b59..7f46df447bec 100644 --- a/core/hdd/inc/wlan_hdd_cfr.h +++ b/core/hdd/inc/wlan_hdd_cfr.h @@ -27,6 +27,7 @@ #ifdef WLAN_CFR_ENABLE #define HDD_INVALID_GROUP_ID 16 +#define LEGACY_CFR_VERSION 1 #define ENHANCED_CFR_VERSION 2 /** diff --git a/core/hdd/src/wlan_hdd_cfr.c b/core/hdd/src/wlan_hdd_cfr.c index 765dcf5cc9ac..294c1ae25ca6 100644 --- a/core/hdd/src/wlan_hdd_cfr.c +++ b/core/hdd/src/wlan_hdd_cfr.c @@ -281,6 +281,119 @@ wlan_cfg80211_cfr_set_config(struct wlan_objmgr_vdev *vdev, return 0; } +#ifdef WLAN_CFR_ADRASTEA +static QDF_STATUS +wlan_cfg80211_peer_cfr_capture_cfg_adrastea(struct hdd_adapter *adapter, + struct nlattr **tb) +{ + struct cfr_capture_params params = { 0 }; + struct wlan_objmgr_vdev *vdev; + struct wlan_objmgr_pdev *pdev; + struct wlan_objmgr_peer *peer; + struct wlan_objmgr_psoc *psoc; + struct qdf_mac_addr peer_addr; + bool is_start_capture = false; + QDF_STATUS status = QDF_STATUS_SUCCESS; + + if (!tb[QCA_WLAN_VENDOR_ATTR_CFR_PEER_MAC_ADDR]) { + hdd_err("peer mac addr not given"); + return QDF_STATUS_E_INVAL; + } + + nla_memcpy(peer_addr.bytes, tb[QCA_WLAN_VENDOR_ATTR_CFR_PEER_MAC_ADDR], + QDF_MAC_ADDR_SIZE); + + if (tb[QCA_WLAN_VENDOR_ATTR_PEER_CFR_ENABLE]) { + is_start_capture = nla_get_flag(tb[ + QCA_WLAN_VENDOR_ATTR_PEER_CFR_ENABLE]); + } + + vdev = adapter->vdev; + status = wlan_objmgr_vdev_try_get_ref(vdev, WLAN_CFR_ID); + if (QDF_IS_STATUS_ERROR(status)) { + hdd_err("failed to get vdev"); + return status; + } + + pdev = wlan_vdev_get_pdev(vdev); + if (!pdev) { + hdd_err("failed to get pdev"); + wlan_objmgr_vdev_release_ref(vdev, WLAN_CFR_ID); + return QDF_STATUS_E_INVAL; + } + + psoc = wlan_vdev_get_psoc(vdev); + if (!psoc) { + hdd_err("Failed to get psoc"); + wlan_objmgr_vdev_release_ref(vdev, WLAN_CFR_ID); + return QDF_STATUS_E_INVAL; + } + + peer = wlan_objmgr_get_peer_by_mac(psoc, peer_addr.bytes, WLAN_CFR_ID); + if (!peer) { + hdd_err("No peer object found"); + wlan_objmgr_vdev_release_ref(vdev, WLAN_CFR_ID); + return QDF_STATUS_E_INVAL; + } + + if (is_start_capture) { + if (tb[QCA_WLAN_VENDOR_ATTR_PEER_CFR_PERIODICITY]) { + params.period = nla_get_u32(tb[ + QCA_WLAN_VENDOR_ATTR_PEER_CFR_PERIODICITY]); + hdd_debug("params.periodicity %d", params.period); + /* Set the periodic CFR */ + if (params.period) + ucfg_cfr_set_timer(pdev, params.period); + } + + if (tb[QCA_WLAN_VENDOR_ATTR_PEER_CFR_METHOD]) { + params.method = nla_get_u8(tb[ + QCA_WLAN_VENDOR_ATTR_PEER_CFR_METHOD]); + /* Adrastea supports only QOS NULL METHOD */ + if (params.method != + QCA_WLAN_VENDOR_CFR_METHOD_QOS_NULL) { + hdd_err_rl("invalid capture method %d", + params.method); + status = QDF_STATUS_E_INVAL; + goto exit; + } + } + + if (tb[QCA_WLAN_VENDOR_ATTR_PEER_CFR_BANDWIDTH]) { + params.bandwidth = nla_get_u8(tb[ + QCA_WLAN_VENDOR_ATTR_PEER_CFR_BANDWIDTH]); + /* Adrastea supports only 20Mhz bandwidth CFR capture */ + if (params.bandwidth != NL80211_CHAN_WIDTH_20_NOHT) { + hdd_err_rl("invalid capture bandwidth %d", + params.bandwidth); + status = QDF_STATUS_E_INVAL; + goto exit; + } + } + ucfg_cfr_start_capture(pdev, peer, ¶ms); + } else { + /* Disable the periodic CFR if enabled */ + if (ucfg_cfr_get_timer(pdev)) + ucfg_cfr_set_timer(pdev, 0); + + /* Disable the peer CFR capture */ + ucfg_cfr_stop_capture(pdev, peer); + } +exit: + wlan_objmgr_peer_release_ref(peer, WLAN_CFR_ID); + wlan_objmgr_vdev_release_ref(vdev, WLAN_CFR_ID); + + return status; +} +#else +static QDF_STATUS +wlan_cfg80211_peer_cfr_capture_cfg_adrastea(struct hdd_adapter *adapter, + struct nlattr **tb) +{ + return QDF_STATUS_E_NOSUPPORT; +} +#endif + static int wlan_cfg80211_peer_enh_cfr_capture(struct hdd_adapter *adapter, struct nlattr **tb) @@ -352,6 +465,7 @@ wlan_cfg80211_peer_cfr_capture_cfg(struct wiphy *wiphy, { struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_PEER_CFR_MAX + 1]; uint8_t version = 0; + QDF_STATUS status; if (wlan_cfg80211_nla_parse( tb, @@ -367,7 +481,11 @@ wlan_cfg80211_peer_cfr_capture_cfg(struct wiphy *wiphy, version = nla_get_u8(tb[ QCA_WLAN_VENDOR_ATTR_PEER_CFR_VERSION]); hdd_debug("version %d", version); - if (version != ENHANCED_CFR_VERSION) { + if (version == LEGACY_CFR_VERSION) { + status = wlan_cfg80211_peer_cfr_capture_cfg_adrastea( + adapter, tb); + return qdf_status_to_os_return(status); + } else if (version != ENHANCED_CFR_VERSION) { hdd_err("unsupported version"); return -EFAULT; }