|
@@ -25,12 +25,16 @@
|
|
|
#include "wlan_nan_api.h"
|
|
|
#include "target_if_nan.h"
|
|
|
#include "scheduler_api.h"
|
|
|
+#include "wlan_policy_mgr_api.h"
|
|
|
+#include "wlan_osif_request_manager.h"
|
|
|
#include "wlan_serialization_api.h"
|
|
|
#include "wlan_objmgr_cmn.h"
|
|
|
+#include "wlan_tdls_ucfg_api.h"
|
|
|
#include "wlan_objmgr_global_obj.h"
|
|
|
#include "wlan_objmgr_psoc_obj.h"
|
|
|
#include "wlan_objmgr_pdev_obj.h"
|
|
|
#include "wlan_objmgr_vdev_obj.h"
|
|
|
+#include "qdf_platform.h"
|
|
|
|
|
|
QDF_STATUS nan_set_discovery_state(struct wlan_objmgr_psoc *psoc,
|
|
|
enum nan_disc_state new_state)
|
|
@@ -485,26 +489,82 @@ static QDF_STATUS nan_handle_end_ind(
|
|
|
return QDF_STATUS_SUCCESS;
|
|
|
}
|
|
|
|
|
|
-static QDF_STATUS nan_handle_enable_rsp(struct nan_event_params *evt_params)
|
|
|
+static QDF_STATUS nan_handle_enable_rsp(struct nan_event_params *nan_event)
|
|
|
{
|
|
|
struct nan_psoc_priv_obj *psoc_nan_obj;
|
|
|
struct wlan_objmgr_psoc *psoc;
|
|
|
+ QDF_STATUS status;
|
|
|
|
|
|
- psoc = evt_params->psoc;
|
|
|
+ psoc = nan_event->psoc;
|
|
|
psoc_nan_obj = nan_get_psoc_priv_obj(psoc);
|
|
|
if (!psoc_nan_obj) {
|
|
|
nan_err("psoc_nan_obj is NULL");
|
|
|
return QDF_STATUS_E_NULL_VALUE;
|
|
|
}
|
|
|
|
|
|
- if (evt_params->is_nan_enable_success)
|
|
|
- nan_set_discovery_state(evt_params->psoc, NAN_DISC_ENABLED);
|
|
|
- else
|
|
|
- nan_set_discovery_state(evt_params->psoc, NAN_DISC_DISABLED);
|
|
|
+ if (nan_event->is_nan_enable_success) {
|
|
|
+ status = nan_set_discovery_state(nan_event->psoc,
|
|
|
+ NAN_DISC_ENABLED);
|
|
|
+
|
|
|
+ if (QDF_IS_STATUS_SUCCESS(status)) {
|
|
|
+ psoc_nan_obj->nan_disc_mac_id = nan_event->mac_id;
|
|
|
+ policy_mgr_update_nan_vdev_mac_info(nan_event->psoc,
|
|
|
+ NAN_PSEUDO_VDEV_ID,
|
|
|
+ nan_event->mac_id);
|
|
|
+
|
|
|
+ policy_mgr_incr_active_session(psoc, QDF_NAN_DISC_MODE,
|
|
|
+ NAN_PSEUDO_VDEV_ID);
|
|
|
+
|
|
|
+ } else {
|
|
|
+ /*
|
|
|
+ * State set to DISABLED OR DISABLE_IN_PROGRESS, try to
|
|
|
+ * restore the single MAC mode.
|
|
|
+ */
|
|
|
+ psoc_nan_obj->nan_social_channel = 0;
|
|
|
+ policy_mgr_check_n_start_opportunistic_timer(psoc);
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ /* NAN Enable has failed, restore changes */
|
|
|
+ psoc_nan_obj->nan_social_channel = 0;
|
|
|
+ nan_set_discovery_state(nan_event->psoc, NAN_DISC_DISABLED);
|
|
|
+ policy_mgr_check_n_start_opportunistic_timer(psoc);
|
|
|
+ }
|
|
|
|
|
|
return QDF_STATUS_SUCCESS;
|
|
|
}
|
|
|
|
|
|
+static QDF_STATUS nan_handle_disable_ind(struct nan_event_params *nan_event)
|
|
|
+{
|
|
|
+ struct nan_psoc_priv_obj *psoc_nan_obj;
|
|
|
+ struct wlan_objmgr_psoc *psoc;
|
|
|
+ QDF_STATUS status;
|
|
|
+
|
|
|
+ psoc = nan_event->psoc;
|
|
|
+ psoc_nan_obj = nan_get_psoc_priv_obj(psoc);
|
|
|
+ if (!psoc_nan_obj) {
|
|
|
+ nan_err("psoc_nan_obj is NULL");
|
|
|
+ return QDF_STATUS_E_NULL_VALUE;
|
|
|
+ }
|
|
|
+
|
|
|
+ status = nan_set_discovery_state(nan_event->psoc,
|
|
|
+ NAN_DISC_DISABLED);
|
|
|
+ if (QDF_IS_STATUS_SUCCESS(status)) {
|
|
|
+ policy_mgr_decr_session_set_pcl(psoc, QDF_NAN_DISC_MODE,
|
|
|
+ NAN_PSEUDO_VDEV_ID);
|
|
|
+
|
|
|
+ if (psoc_nan_obj->is_explicit_disable &&
|
|
|
+ psoc_nan_obj->cb_obj.ucfg_explicit_disable_cb)
|
|
|
+ psoc_nan_obj->cb_obj.ucfg_explicit_disable_cb(
|
|
|
+ psoc_nan_obj->disable_context);
|
|
|
+ } else {
|
|
|
+ /* Should not happen, NAN state can always be disabled */
|
|
|
+ nan_err("Cannot set NAN state to disabled!");
|
|
|
+ return QDF_STATUS_E_FAILURE;
|
|
|
+ }
|
|
|
+
|
|
|
+ return status;
|
|
|
+}
|
|
|
+
|
|
|
static QDF_STATUS nan_handle_schedule_update(
|
|
|
struct nan_datapath_sch_update_event *ind)
|
|
|
{
|
|
@@ -556,8 +616,7 @@ QDF_STATUS nan_discovery_event_handler(struct scheduler_msg *msg)
|
|
|
nan_handle_enable_rsp(nan_event);
|
|
|
break;
|
|
|
case nan_event_id_disable_ind:
|
|
|
- nan_set_discovery_state(nan_event->psoc,
|
|
|
- NAN_DISC_DISABLED);
|
|
|
+ nan_handle_disable_ind(nan_event);
|
|
|
break;
|
|
|
case nan_event_id_generic_rsp:
|
|
|
case nan_event_id_error_rsp:
|
|
@@ -626,10 +685,82 @@ QDF_STATUS nan_datapath_event_handler(struct scheduler_msg *pe_msg)
|
|
|
return status;
|
|
|
}
|
|
|
|
|
|
+bool nan_is_enable_allowed(struct wlan_objmgr_psoc *psoc, uint8_t nan_chan)
|
|
|
+{
|
|
|
+ if (!psoc) {
|
|
|
+ nan_err("psoc object object is NULL");
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ return (NAN_DISC_DISABLED == nan_get_discovery_state(psoc) &&
|
|
|
+ policy_mgr_allow_concurrency(psoc, PM_NAN_DISC_MODE, nan_chan,
|
|
|
+ HW_MODE_20_MHZ));
|
|
|
+}
|
|
|
+
|
|
|
QDF_STATUS nan_discovery_pre_enable(struct wlan_objmgr_psoc *psoc,
|
|
|
uint8_t nan_social_channel)
|
|
|
{
|
|
|
- return nan_set_discovery_state(psoc, NAN_DISC_ENABLE_IN_PROGRESS);
|
|
|
+ QDF_STATUS status = QDF_STATUS_E_INVAL;
|
|
|
+ struct wlan_objmgr_pdev *pdev = NULL;
|
|
|
+ struct wlan_objmgr_vdev *vdev = NULL;
|
|
|
+ uint8_t vdev_id;
|
|
|
+
|
|
|
+ status = nan_set_discovery_state(psoc, NAN_DISC_ENABLE_IN_PROGRESS);
|
|
|
+
|
|
|
+ if (QDF_IS_STATUS_ERROR(status)) {
|
|
|
+ nan_err("Unable to set NAN Disc State to ENABLE_IN_PROGRESS");
|
|
|
+ goto pre_enable_failure;
|
|
|
+ }
|
|
|
+
|
|
|
+ policy_mgr_stop_opportunistic_timer(psoc);
|
|
|
+
|
|
|
+ if (policy_mgr_is_hw_mode_change_in_progress(psoc)) {
|
|
|
+ status = policy_mgr_wait_for_connection_update(psoc);
|
|
|
+ if (!QDF_IS_STATUS_SUCCESS(status)) {
|
|
|
+ nan_err("Failed to wait for connection update");
|
|
|
+ goto pre_enable_failure;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ pdev = wlan_objmgr_get_pdev_by_id(psoc, 0, WLAN_NAN_ID);
|
|
|
+ if (!pdev) {
|
|
|
+ nan_err("null pdev");
|
|
|
+ status = QDF_STATUS_E_INVAL;
|
|
|
+ goto pre_enable_failure;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* Piggyback on any available vdev for policy manager update */
|
|
|
+ vdev = wlan_objmgr_pdev_get_first_vdev(pdev, WLAN_NAN_ID);
|
|
|
+ if (!vdev) {
|
|
|
+ nan_err("No vdev is up yet, unable to proceed!");
|
|
|
+ status = QDF_STATUS_E_INVAL;
|
|
|
+ goto pre_enable_failure;
|
|
|
+ }
|
|
|
+ vdev_id = wlan_vdev_get_id(vdev);
|
|
|
+
|
|
|
+ status = policy_mgr_update_and_wait_for_connection_update(psoc, vdev_id,
|
|
|
+ nan_social_channel,
|
|
|
+ POLICY_MGR_UPDATE_REASON_NAN_DISCOVERY);
|
|
|
+ if (QDF_IS_STATUS_ERROR(status)) {
|
|
|
+ nan_err("Failed to set or wait for HW mode change");
|
|
|
+ goto pre_enable_failure;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* Try to teardown TDLS links, but do not wait */
|
|
|
+ status = ucfg_tdls_teardown_links(vdev);
|
|
|
+ if (QDF_IS_STATUS_ERROR(status))
|
|
|
+ nan_err("Failed to teardown TDLS links");
|
|
|
+
|
|
|
+pre_enable_failure:
|
|
|
+ if (vdev)
|
|
|
+ wlan_objmgr_vdev_release_ref(vdev, WLAN_NAN_ID);
|
|
|
+ if (pdev)
|
|
|
+ wlan_objmgr_pdev_release_ref(pdev, WLAN_NAN_ID);
|
|
|
+
|
|
|
+ if (QDF_IS_STATUS_ERROR(status))
|
|
|
+ nan_set_discovery_state(psoc, NAN_DISC_DISABLED);
|
|
|
+
|
|
|
+ return status;
|
|
|
}
|
|
|
|
|
|
static QDF_STATUS nan_discovery_disable_req(struct nan_disable_req *req)
|
|
@@ -666,12 +797,15 @@ static QDF_STATUS nan_discovery_enable_req(struct nan_enable_req *req)
|
|
|
struct wlan_nan_tx_ops *tx_ops;
|
|
|
|
|
|
/*
|
|
|
- * State was already set to Disable in progress by a
|
|
|
- * disable request, drop the Enable request and move
|
|
|
- * back to Disabled state.
|
|
|
+ * State was already set to Disable in progress by a disable request,
|
|
|
+ * drop the Enable request, start opportunistic timer and move back to
|
|
|
+ * the Disabled state.
|
|
|
*/
|
|
|
- if (NAN_DISC_DISABLE_IN_PROGRESS == nan_get_discovery_state(req->psoc))
|
|
|
+ if (NAN_DISC_DISABLE_IN_PROGRESS ==
|
|
|
+ nan_get_discovery_state(req->psoc)) {
|
|
|
+ policy_mgr_check_n_start_opportunistic_timer(req->psoc);
|
|
|
return nan_set_discovery_state(req->psoc, NAN_DISC_DISABLED);
|
|
|
+ }
|
|
|
|
|
|
psoc_nan_obj = nan_get_psoc_priv_obj(req->psoc);
|
|
|
if (!psoc_nan_obj) {
|
|
@@ -679,6 +813,11 @@ static QDF_STATUS nan_discovery_enable_req(struct nan_enable_req *req)
|
|
|
return QDF_STATUS_E_NULL_VALUE;
|
|
|
}
|
|
|
|
|
|
+ if (req->social_chan_2g)
|
|
|
+ psoc_nan_obj->nan_social_channel = req->social_chan_2g;
|
|
|
+ else
|
|
|
+ psoc_nan_obj->nan_social_channel = req->social_chan_5g;
|
|
|
+
|
|
|
tx_ops = &psoc_nan_obj->tx_ops;
|
|
|
if (!tx_ops->nan_discovery_req_tx) {
|
|
|
nan_err("NAN Discovery tx op is NULL");
|
|
@@ -770,5 +909,28 @@ QDF_STATUS
|
|
|
wlan_nan_get_connection_info(struct wlan_objmgr_psoc *psoc,
|
|
|
struct policy_mgr_vdev_entry_info *conn_info)
|
|
|
{
|
|
|
+ struct nan_psoc_priv_obj *psoc_nan_obj;
|
|
|
+
|
|
|
+ if (!psoc) {
|
|
|
+ nan_err("psoc obj is NULL");
|
|
|
+ return QDF_STATUS_E_NULL_VALUE;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (nan_get_discovery_state(psoc) != NAN_DISC_ENABLED) {
|
|
|
+ nan_err("NAN State needs to be Enabled");
|
|
|
+ return QDF_STATUS_E_INVAL;
|
|
|
+ }
|
|
|
+
|
|
|
+ psoc_nan_obj = nan_get_psoc_priv_obj(psoc);
|
|
|
+ if (!psoc_nan_obj) {
|
|
|
+ nan_err("psoc_nan_obj is null");
|
|
|
+ return QDF_STATUS_E_NULL_VALUE;
|
|
|
+ }
|
|
|
+
|
|
|
+ conn_info->mhz = wlan_chan_to_freq(psoc_nan_obj->nan_social_channel);
|
|
|
+ conn_info->mac_id = psoc_nan_obj->nan_disc_mac_id;
|
|
|
+ conn_info->chan_width = CH_WIDTH_20MHZ;
|
|
|
+ conn_info->type = WMI_VDEV_TYPE_NAN;
|
|
|
+
|
|
|
return QDF_STATUS_SUCCESS;
|
|
|
}
|