|
@@ -29,6 +29,7 @@
|
|
|
#include "wlan_hdd_cfr.h"
|
|
|
#include "wlan_cfr_ucfg_api.h"
|
|
|
#include "wlan_hdd_object_manager.h"
|
|
|
+#include "wlan_cmn.h"
|
|
|
|
|
|
const struct nla_policy cfr_config_policy[
|
|
|
QCA_WLAN_VENDOR_ATTR_PEER_CFR_MAX + 1] = {
|
|
@@ -442,7 +443,7 @@ wlan_cfg80211_peer_cfr_capture_cfg_adrastea(struct hdd_adapter *adapter,
|
|
|
}
|
|
|
|
|
|
vdev = adapter->vdev;
|
|
|
- status = wlan_objmgr_vdev_try_get_ref(vdev, WLAN_CFR_ID);
|
|
|
+ status = hdd_objmgr_get_vdev_by_user(vdev, WLAN_CFR_ID);
|
|
|
if (QDF_IS_STATUS_ERROR(status)) {
|
|
|
hdd_err("failed to get vdev");
|
|
|
return status;
|
|
@@ -451,21 +452,21 @@ wlan_cfg80211_peer_cfr_capture_cfg_adrastea(struct hdd_adapter *adapter,
|
|
|
pdev = wlan_vdev_get_pdev(vdev);
|
|
|
if (!pdev) {
|
|
|
hdd_err("failed to get pdev");
|
|
|
- wlan_objmgr_vdev_release_ref(vdev, WLAN_CFR_ID);
|
|
|
+ hdd_objmgr_put_vdev_by_user(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);
|
|
|
+ hdd_objmgr_put_vdev_by_user(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);
|
|
|
+ hdd_objmgr_put_vdev_by_user(vdev, WLAN_CFR_ID);
|
|
|
return QDF_STATUS_E_INVAL;
|
|
|
}
|
|
|
|
|
@@ -514,10 +515,140 @@ wlan_cfg80211_peer_cfr_capture_cfg_adrastea(struct hdd_adapter *adapter,
|
|
|
}
|
|
|
exit:
|
|
|
wlan_objmgr_peer_release_ref(peer, WLAN_CFR_ID);
|
|
|
- wlan_objmgr_vdev_release_ref(vdev, WLAN_CFR_ID);
|
|
|
+ hdd_objmgr_put_vdev_by_user(vdev, WLAN_CFR_ID);
|
|
|
+
|
|
|
+ return status;
|
|
|
+}
|
|
|
+#elif defined(WLAN_CFR_DBR)
|
|
|
+static enum
|
|
|
+phy_ch_width convert_capture_bw(enum nl80211_chan_width capture_bw)
|
|
|
+{
|
|
|
+ switch (capture_bw) {
|
|
|
+ case NL80211_CHAN_WIDTH_20_NOHT:
|
|
|
+ case NL80211_CHAN_WIDTH_20:
|
|
|
+ return CH_WIDTH_20MHZ;
|
|
|
+ case NL80211_CHAN_WIDTH_40:
|
|
|
+ return CH_WIDTH_40MHZ;
|
|
|
+ case NL80211_CHAN_WIDTH_80:
|
|
|
+ return CH_WIDTH_80MHZ;
|
|
|
+ case NL80211_CHAN_WIDTH_80P80:
|
|
|
+ return CH_WIDTH_80P80MHZ;
|
|
|
+ case NL80211_CHAN_WIDTH_160:
|
|
|
+ return CH_WIDTH_160MHZ;
|
|
|
+ case NL80211_CHAN_WIDTH_5:
|
|
|
+ return CH_WIDTH_5MHZ;
|
|
|
+ case NL80211_CHAN_WIDTH_10:
|
|
|
+ return CH_WIDTH_10MHZ;
|
|
|
+ default:
|
|
|
+ hdd_err("invalid capture bw");
|
|
|
+ return CH_WIDTH_INVALID;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+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;
|
|
|
+ int id;
|
|
|
+
|
|
|
+ id = QCA_WLAN_VENDOR_ATTR_CFR_PEER_MAC_ADDR;
|
|
|
+ if (!tb[id]) {
|
|
|
+ hdd_err("peer mac addr not given");
|
|
|
+ return QDF_STATUS_E_INVAL;
|
|
|
+ }
|
|
|
+
|
|
|
+ nla_memcpy(peer_addr.bytes, tb[id],
|
|
|
+ QDF_MAC_ADDR_SIZE);
|
|
|
+
|
|
|
+ id = QCA_WLAN_VENDOR_ATTR_PEER_CFR_ENABLE;
|
|
|
+ if (tb[id])
|
|
|
+ is_start_capture = nla_get_flag(tb[id]);
|
|
|
+
|
|
|
+ vdev = adapter->vdev;
|
|
|
+ status = hdd_objmgr_get_vdev_by_user(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");
|
|
|
+ hdd_objmgr_put_vdev_by_user(vdev, WLAN_CFR_ID);
|
|
|
+ return QDF_STATUS_E_INVAL;
|
|
|
+ }
|
|
|
+
|
|
|
+ psoc = wlan_vdev_get_psoc(vdev);
|
|
|
+ if (!psoc) {
|
|
|
+ hdd_err("Failed to get psoc");
|
|
|
+ hdd_objmgr_put_vdev_by_user(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");
|
|
|
+ hdd_objmgr_put_vdev_by_user(vdev, WLAN_CFR_ID);
|
|
|
+ return QDF_STATUS_E_INVAL;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (is_start_capture) {
|
|
|
+ id = QCA_WLAN_VENDOR_ATTR_PEER_CFR_PERIODICITY;
|
|
|
+ if (tb[id]) {
|
|
|
+ params.period = nla_get_u32(tb[id]);
|
|
|
+ hdd_debug("params.periodicity %d", params.period);
|
|
|
+ /* Set the periodic CFR */
|
|
|
+ if (params.period)
|
|
|
+ ucfg_cfr_set_timer(pdev, params.period);
|
|
|
+ }
|
|
|
+ id = QCA_WLAN_VENDOR_ATTR_PEER_CFR_METHOD;
|
|
|
+ if (tb[id]) {
|
|
|
+ params.method = nla_get_u8(tb[id]);
|
|
|
+ /* 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;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ id = QCA_WLAN_VENDOR_ATTR_PEER_CFR_BANDWIDTH;
|
|
|
+ if (tb[id]) {
|
|
|
+ params.bandwidth = nla_get_u8(tb[id]);
|
|
|
+ params.bandwidth = convert_capture_bw(params.bandwidth);
|
|
|
+ if (params.bandwidth > NL80211_CHAN_WIDTH_80) {
|
|
|
+ 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);
|
|
|
+ ucfg_cfr_stop_indication(vdev);
|
|
|
+ }
|
|
|
+exit:
|
|
|
+ wlan_objmgr_peer_release_ref(peer, WLAN_CFR_ID);
|
|
|
+ hdd_objmgr_put_vdev_by_user(vdev, WLAN_CFR_ID);
|
|
|
|
|
|
return status;
|
|
|
}
|
|
|
+
|
|
|
#else
|
|
|
static QDF_STATUS
|
|
|
wlan_cfg80211_peer_cfr_capture_cfg_adrastea(struct hdd_adapter *adapter,
|