diff --git a/Kbuild b/Kbuild index aea1c37772f0..8826161db710 100644 --- a/Kbuild +++ b/Kbuild @@ -240,6 +240,10 @@ ifeq ($(CONFIG_QCACLD_FEATURE_MPTA_HELPER), y) HDD_OBJS += $(HDD_SRC_DIR)/wlan_hdd_mpta_helper.o endif +ifeq ($(CONFIG_WLAN_BCN_RECV_FEATURE), y) +HDD_OBJS += $(HDD_SRC_DIR)/wlan_hdd_bcn_recv.o +endif + ###### OSIF_SYNC ######## SYNC_DIR := os_if/sync SYNC_INC_DIR := $(SYNC_DIR)/inc @@ -2536,6 +2540,9 @@ cppflags-$(CONFIG_WLAN_NUD_TRACKING) += -DWLAN_NUD_TRACKING #Flag to enable set and get disable channel list feature cppflags-$(CONFIG_DISABLE_CHANNEL_LIST) += -DDISABLE_CHANNEL_LIST +#Flag to enable/disable WIPS feature +cppflags-$(CONFIG_WLAN_BCN_RECV_FEATURE) += -DWLAN_BCN_RECV_FEATURE + #Flag to enable/disable LTE COEX support cppflags-$(CONFIG_LTE_COEX) += -DLTE_COEX diff --git a/configs/default_defconfig b/configs/default_defconfig index e13ecb1c76e7..470994a85756 100644 --- a/configs/default_defconfig +++ b/configs/default_defconfig @@ -613,6 +613,9 @@ CONFIG_WLAN_WBUFF := y #Flag to enable set and get disable channel list feature CONFIG_DISABLE_CHANNEL_LIST :=y +#Flag to enable beacon receive feature +CONFIG_WLAN_BCN_RECV_FEATURE := y + #Flag to enable LTE COEX feature CONFIG_LTE_COEX := y diff --git a/core/hdd/inc/wlan_hdd_bcn_recv.h b/core/hdd/inc/wlan_hdd_bcn_recv.h new file mode 100644 index 000000000000..b169a30ae857 --- /dev/null +++ b/core/hdd/inc/wlan_hdd_bcn_recv.h @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2019 The Linux Foundation. All rights reserved. + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/** + * DOC: feature_bcn_recv + * Feature for receiving beacons of connected AP and sending select + * params to upper layer via vendor event + */ + +#ifdef WLAN_BCN_RECV_FEATURE + +struct wireless_dev; +struct wiphy; + +/** + * wlan_hdd_cfg80211_bcn_rcv_start() - Process bcn recv start ind + * @wiphy: Pointer to wireless phy + * @wdev: Pointer to wireless device + * @data: Pointer to data + * @data_len: Length of @data + * + * Wrapper function of __wlan_hdd_cfg80211_bcn_rcv_start() + * + * Return: 0 on success, negative errno on failure + */ +int wlan_hdd_cfg80211_bcn_rcv_start(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, int data_len); + +#define BCN_RECV_FEATURE_VENDOR_COMMANDS \ +{ \ + .info.vendor_id = QCA_NL80211_VENDOR_ID, \ + .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_BEACON_REPORTING, \ + .flags = WIPHY_VENDOR_CMD_NEED_WDEV | \ + WIPHY_VENDOR_CMD_NEED_RUNNING, \ + .doit = wlan_hdd_cfg80211_bcn_rcv_start \ +}, +#else +#define BCN_RECV_FEATURE_VENDOR_COMMANDS +#endif + diff --git a/core/hdd/src/wlan_hdd_bcn_recv.c b/core/hdd/src/wlan_hdd_bcn_recv.c new file mode 100644 index 000000000000..dda46a014262 --- /dev/null +++ b/core/hdd/src/wlan_hdd_bcn_recv.c @@ -0,0 +1,127 @@ +/* + * Copyright (c) 2019 The Linux Foundation. All rights reserved. + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/** + * DOC: wlan_hdd_bcn_recv.c + * Feature for receiving beacons of connected AP and sending select + * params to upper layer via vendor event + */ + +#include +#include +#include "wlan_osif_priv.h" +#include "qdf_trace.h" +#include "wlan_hdd_main.h" +#include "osif_sync.h" +#include "wlan_hdd_bcn_recv.h" + +static const struct nla_policy +beacon_reporting_params[QCA_WLAN_VENDOR_ATTR_BEACON_REPORTING_MAX + 1] = { + [QCA_WLAN_VENDOR_ATTR_BEACON_REPORTING_OP_TYPE] = {.type = NLA_U8}, + [QCA_WLAN_VENDOR_ATTR_BEACON_REPORTING_ACTIVE_REPORTING] = {.type = + NLA_FLAG}, + [QCA_WLAN_VENDOR_ATTR_BEACON_REPORTING_PERIOD] = {.type = NLA_U8}, +}; + +/** + * __wlan_hdd_cfg80211_bcn_rcv_start() - enable/disable beacon reporting + * indication + * @wiphy: Pointer to wireless phy + * @wdev: Pointer to wireless device + * @data: Pointer to data + * @data_len: Length of @data + * + * This function is used to enable/disable asynchronous beacon + * reporting feature using vendor commands. + * + * Return: 0 on success, negative errno on failure + */ +static int __wlan_hdd_cfg80211_bcn_rcv_start(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, int data_len) +{ + struct hdd_context *hdd_ctx = wiphy_priv(wiphy); + struct net_device *dev = wdev->netdev; + struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev); + struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_BEACON_REPORTING_MAX + 1]; + uint32_t bcn_report; + int errno; + QDF_STATUS qdf_status = QDF_STATUS_SUCCESS; + + hdd_enter_dev(dev); + + errno = hdd_validate_adapter(adapter); + if (errno) + return errno; + + if (adapter->device_mode != QDF_STA_MODE) { + hdd_err("Command not allowed as device not in STA mode"); + return -EINVAL; + } + + errno = + wlan_cfg80211_nla_parse(tb, + QCA_WLAN_VENDOR_ATTR_BEACON_REPORTING_MAX, + data, data_len, beacon_reporting_params); + if (errno) { + hdd_err("Invalid ATTR"); + return -EINVAL; + } + + /* Parse and fetch OP Type */ + if (!tb[QCA_WLAN_VENDOR_ATTR_BEACON_REPORTING_OP_TYPE]) { + hdd_err("attr beacon report OP type failed"); + return -EINVAL; + } + + bcn_report = + nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_BEACON_REPORTING_OP_TYPE]); + hdd_debug("Bcn Report: OP type:%d", bcn_report); + + if (bcn_report == QCA_WLAN_VENDOR_BEACON_REPORTING_OP_START) { + /* Vendor event is intended for Start*/ + qdf_status = + sme_handle_bcn_recv_start(hdd_ctx->mac_handle, + adapter->vdev_id); + if (QDF_IS_STATUS_ERROR(qdf_status)) + hdd_err("beacon receive start failed with status=%d", + qdf_status); + } + + errno = qdf_status_to_os_return(qdf_status); + return errno; +} + +int wlan_hdd_cfg80211_bcn_rcv_start(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, int data_len) +{ + int errno; + struct osif_vdev_sync *vdev_sync; + + errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync); + if (errno) + return errno; + + errno = __wlan_hdd_cfg80211_bcn_rcv_start(wiphy, wdev, + data, data_len); + + osif_vdev_sync_op_stop(vdev_sync); + + return errno; +} diff --git a/core/hdd/src/wlan_hdd_cfg80211.c b/core/hdd/src/wlan_hdd_cfg80211.c index b0deb827de94..3c536884099b 100644 --- a/core/hdd/src/wlan_hdd_cfg80211.c +++ b/core/hdd/src/wlan_hdd_cfg80211.c @@ -139,6 +139,7 @@ #include "wlan_cfg80211_crypto.h" #include "wlan_scan_ucfg_api.h" #include "wlan_hdd_coex_config.h" +#include "wlan_hdd_bcn_recv.h" #define g_mode_rates_size (12) #define a_mode_rates_size (8) @@ -12992,6 +12993,7 @@ const struct wiphy_vendor_command hdd_wiphy_vendor_commands[] = { }, #endif FEATURE_SAR_LIMITS_VENDOR_COMMANDS + BCN_RECV_FEATURE_VENDOR_COMMANDS { .info.vendor_id = QCA_NL80211_VENDOR_ID, diff --git a/core/sme/inc/csr_internal.h b/core/sme/inc/csr_internal.h index 4be42fb87b88..d457c3a322da 100644 --- a/core/sme/inc/csr_internal.h +++ b/core/sme/inc/csr_internal.h @@ -564,6 +564,7 @@ struct csr_disconnect_stats { /** * struct csr_roam_session - CSR per-vdev context * @vdev_id: ID of the vdev for which this entry is applicable + * @is_bcn_recv_start: Allow to process bcn recv indication */ struct csr_roam_session { union { @@ -637,6 +638,9 @@ struct csr_roam_session { enum csr_roaming_reason roamingReason; bool fCancelRoaming; qdf_mc_timer_t hTimerRoaming; +#ifdef WLAN_BCN_RECV_FEATURE + bool is_bcn_recv_start; +#endif /* the roamResult that is used when the roaming timer fires */ eCsrRoamResult roamResult; /* This is the reason code for join(assoc) failure */ diff --git a/core/sme/inc/sme_api.h b/core/sme/inc/sme_api.h index 9e91bffc7f6b..c5c7ab0287b7 100644 --- a/core/sme/inc/sme_api.h +++ b/core/sme/inc/sme_api.h @@ -1547,6 +1547,21 @@ QDF_STATUS sme_update_mimo_power_save(mac_handle_t mac_handle, uint8_t is_ht_smps_enabled, uint8_t ht_smps_mode, bool send_smps_action); +#ifdef WLAN_BCN_RECV_FEATURE +/** + * sme_handle_bcn_recv_start() - Enable fw to start sending + * beacons of the current connected AP + * @mac_handle: Opaque handle to the global MAC context + * @vdev_id: SME session id + * + * This function remove beacon filter. It allow fw to send + * all beacons from connected peer to driver. + * + * Return: QDF_STATUS enumeration + */ +QDF_STATUS sme_handle_bcn_recv_start(mac_handle_t mac_handle, + uint32_t vdev_id); +#endif QDF_STATUS sme_add_beacon_filter(mac_handle_t mac_handle, uint32_t session_id, uint32_t *ie_map); diff --git a/core/sme/src/common/sme_api.c b/core/sme/src/common/sme_api.c index c502c10323f4..10fe9e5423ed 100644 --- a/core/sme/src/common/sme_api.c +++ b/core/sme/src/common/sme_api.c @@ -12614,6 +12614,54 @@ QDF_STATUS sme_update_mimo_power_save(mac_handle_t mac_handle, return QDF_STATUS_SUCCESS; } +#ifdef WLAN_BCN_RECV_FEATURE +QDF_STATUS sme_handle_bcn_recv_start(mac_handle_t mac_handle, + uint32_t vdev_id) +{ + struct mac_context *mac_ctx = MAC_CONTEXT(mac_handle); + struct csr_roam_session *session; + QDF_STATUS status; + + if (!CSR_IS_SESSION_VALID(mac_ctx, vdev_id)) { + sme_err("CSR session not valid: %d", vdev_id); + return QDF_STATUS_E_FAILURE; + } + + session = CSR_GET_SESSION(mac_ctx, vdev_id); + if (!session) { + sme_err("vdev_id %d not found", vdev_id); + return QDF_STATUS_E_FAILURE; + } + + status = sme_acquire_global_lock(&mac_ctx->sme); + if (QDF_IS_STATUS_SUCCESS(status)) { + if (session->is_bcn_recv_start) { + sme_release_global_lock(&mac_ctx->sme); + sme_err("Beacon receive already started"); + return QDF_STATUS_SUCCESS; + } + session->is_bcn_recv_start = true; + sme_release_global_lock(&mac_ctx->sme); + + /* + * Remove beacon filter. It allows fw to send all + * beacons of connected AP to driver. + */ + status = sme_remove_beacon_filter(mac_handle, vdev_id); + if (!QDF_IS_STATUS_SUCCESS(status)) { + status = sme_acquire_global_lock(&mac_ctx->sme); + if (QDF_IS_STATUS_SUCCESS(status)) { + session->is_bcn_recv_start = false; + sme_release_global_lock(&mac_ctx->sme); + } + sme_err("sme_remove_beacon_filter() failed"); + } + } + + return status; +} +#endif + /** * sme_add_beacon_filter() - set the beacon filter configuration * @mac_handle: The handle returned by macOpen