qcacmn: Add PNO changes for converged scan
Adds PNO related changes for converged scan
Change-Id: Ia18e48645d511134698777b334348d68daf2dbee
CRs-Fixed: 1095299
diff --git a/umac/scan/core/src/wlan_scan_main.c b/umac/scan/core/src/wlan_scan_main.c
index 2c7d425..09475f4 100644
--- a/umac/scan/core/src/wlan_scan_main.c
+++ b/umac/scan/core/src/wlan_scan_main.c
@@ -70,3 +70,53 @@
return status;
}
+
+QDF_STATUS wlan_scan_vdev_created_notification(struct wlan_objmgr_vdev *vdev,
+ void *arg_list)
+{
+ struct scan_vdev_obj *scan_vdev_obj;
+ QDF_STATUS status = QDF_STATUS_SUCCESS;
+
+ scan_vdev_obj = qdf_mem_malloc(sizeof(struct scan_vdev_obj));
+ if (scan_vdev_obj == NULL) {
+ scm_err("Failed to allocate memory");
+ return QDF_STATUS_E_NOMEM;
+ }
+
+ /* Attach scan private date to psoc */
+ status = wlan_objmgr_vdev_component_obj_attach(vdev,
+ WLAN_UMAC_COMP_SCAN, (void *)scan_vdev_obj,
+ QDF_STATUS_SUCCESS);
+ if (QDF_IS_STATUS_ERROR(status)) {
+ scm_err("Failed to attach vdev scan component");
+ qdf_mem_free(scan_vdev_obj);
+ } else {
+ scm_info("vdev scan object attach successful");
+ }
+
+ return status;
+}
+
+QDF_STATUS wlan_scan_vdev_destroyed_notification(
+ struct wlan_objmgr_vdev *vdev,
+ void *arg_list)
+{
+ void *scan_vdev_obj = NULL;
+ QDF_STATUS status = QDF_STATUS_SUCCESS;
+
+ scan_vdev_obj = wlan_objmgr_vdev_get_comp_private_obj(vdev,
+ WLAN_UMAC_COMP_SCAN);
+ if (!scan_vdev_obj) {
+ scm_err("Failed to detach scan in vdev ctx");
+ return QDF_STATUS_E_FAILURE;
+ }
+
+ status = wlan_objmgr_vdev_component_obj_detach(vdev,
+ WLAN_UMAC_COMP_SCAN, scan_vdev_obj);
+ if (QDF_IS_STATUS_ERROR(status))
+ scm_err("Failed to detach vdev scan component");
+
+ qdf_mem_free(scan_vdev_obj);
+
+ return status;
+}
diff --git a/umac/scan/core/src/wlan_scan_main.h b/umac/scan/core/src/wlan_scan_main.h
index 89426e8..1af2771 100644
--- a/umac/scan/core/src/wlan_scan_main.h
+++ b/umac/scan/core/src/wlan_scan_main.h
@@ -148,6 +148,39 @@
};
/**
+ * struct scan_vdev_obj - scan vdev obj
+ * @pno_match_evt_received: pno match received
+ * @pno_in_progress: pno in progress
+ */
+struct scan_vdev_obj {
+ bool pno_match_evt_received;
+ bool pno_in_progress;
+};
+
+/**
+ * struct pno_def_config - def configuration for PNO
+ * @channel_prediction: config PNO channel prediction feature status
+ * @top_k_num_of_channels: def top K number of channels are used for tanimoto
+ * distance calculation.
+ * @stationary_thresh: def threshold val to determine that STA is stationary.
+ * @pnoscan_adaptive_dwell_mode: def adaptive dwelltime mode for pno scan
+ * @channel_prediction_full_scan: def periodic timer upon which full scan needs
+ * to be triggered.
+ * @pno_wake_lock: pno wake lock
+ * @pno_cb: callback to call on PNO completion
+ */
+struct pno_def_config {
+ bool channel_prediction;
+ uint8_t top_k_num_of_channels;
+ uint8_t stationary_thresh;
+ enum scan_dwelltime_adaptive_mode adaptive_dwell_mode;
+ uint32_t channel_prediction_full_scan;
+ qdf_wake_lock_t pno_wake_lock;
+ struct cb_handler pno_cb;
+};
+
+
+/**
* struct scan_default_params - default scan parameters to be used
* @active_dwell: default active dwell time
* @passive_dwell:default passive dwell time
@@ -310,6 +343,7 @@
struct scan_requester_info requesters[WLAN_MAX_REQUESTORS];
struct global_scan_ev_handlers global_evhandlers;
struct pdev_scan_info pdev_info[WLAN_UMAC_MAX_PDEVS];
+ struct pno_def_config pno_cfg;
};
/**
@@ -355,6 +389,20 @@
}
/**
+ * wlan_get_vdev_scan_obj() - private API to get scan object vdev
+ * @vdev: vdev object
+ *
+ * Return: scan object
+ */
+static inline struct scan_vdev_obj *
+wlan_get_vdev_scan_obj(struct wlan_objmgr_vdev *vdev)
+{
+ return (struct scan_vdev_obj *)
+ wlan_objmgr_vdev_get_comp_private_obj(vdev,
+ WLAN_UMAC_COMP_SCAN);
+}
+
+/**
* wlan_scan_vdev_get_pdev_id)() - private API to get pdev id from vdev object
* @vdev: vdev object
*
@@ -434,4 +482,25 @@
*/
QDF_STATUS wlan_scan_psoc_destroyed_notification(struct wlan_objmgr_psoc *psoc,
void *arg_list);
+
+/**
+ * wlan_scan_vdev_created_notification() - scan psoc create handler
+ * @vdev: vdev object
+ * @arg_list: Argument list
+ *
+ * Return: QDF_STATUS
+ */
+QDF_STATUS wlan_scan_vdev_created_notification(struct wlan_objmgr_vdev *vdev,
+ void *arg_list);
+
+/**
+ * wlan_scan_vdev_destroyed_notification() - scan psoc delete handler
+ * @vdev: vdev object
+ * @arg_list: Argument list
+ *
+ * Return: QDF_STATUS
+ */
+QDF_STATUS wlan_scan_vdev_destroyed_notification(struct wlan_objmgr_vdev *vdev,
+ void *arg_list);
+
#endif
diff --git a/umac/scan/core/src/wlan_scan_manager.c b/umac/scan/core/src/wlan_scan_manager.c
index 7ee03cc..4d5ef4e 100644
--- a/umac/scan/core/src/wlan_scan_manager.c
+++ b/umac/scan/core/src/wlan_scan_manager.c
@@ -26,6 +26,9 @@
#include "wlan_scan_main.h"
#include "wlan_scan_manager.h"
#include "wlan_utility.h"
+#ifdef FEATURE_WLAN_SCAN_PNO
+#include <host_diag_core_event.h>
+#endif
static QDF_STATUS
scm_free_scan_request_mem(struct scan_start_request *req)
@@ -485,6 +488,64 @@
return status;
}
+#ifdef FEATURE_WLAN_SCAN_PNO
+static QDF_STATUS
+scm_pno_event_handler(struct wlan_objmgr_vdev *vdev,
+ struct scan_event *event)
+{
+ struct scan_vdev_obj *scan_vdev_obj;
+ struct wlan_scan_obj *scan_psoc_obj;
+ scan_event_handler pno_cb;
+ void *cb_arg;
+
+ scan_vdev_obj = wlan_get_vdev_scan_obj(vdev);
+ scan_psoc_obj = wlan_vdev_get_scan_obj(vdev);
+ if (!scan_vdev_obj || !scan_psoc_obj) {
+ scm_err("null scan_vdev_obj %p scan_obj %p",
+ scan_vdev_obj, scan_psoc_obj);
+ return QDF_STATUS_E_INVAL;
+ }
+
+ switch (event->type) {
+ case SCAN_EVENT_TYPE_NLO_COMPLETE:
+ if (!scan_vdev_obj->pno_match_evt_received)
+ return QDF_STATUS_SUCCESS;
+ qdf_wake_lock_release(&scan_psoc_obj->pno_cfg.pno_wake_lock,
+ WIFI_POWER_EVENT_WAKELOCK_PNO);
+ qdf_wake_lock_timeout_acquire(
+ &scan_psoc_obj->pno_cfg.pno_wake_lock,
+ SCAN_PNO_SCAN_COMPLETE_WAKE_LOCK_TIMEOUT);
+ scan_vdev_obj->pno_match_evt_received = false;
+ break;
+ case SCAN_EVENT_TYPE_NLO_MATCH:
+ scan_vdev_obj->pno_match_evt_received = true;
+ qdf_wake_lock_timeout_acquire(
+ &scan_psoc_obj->pno_cfg.pno_wake_lock,
+ SCAN_PNO_MATCH_WAKE_LOCK_TIMEOUT);
+ return QDF_STATUS_SUCCESS;
+ default:
+ return QDF_STATUS_E_INVAL;
+ }
+ qdf_spin_lock_bh(&scan_psoc_obj->lock);
+ pno_cb = scan_psoc_obj->pno_cfg.pno_cb.func;
+ cb_arg = scan_psoc_obj->pno_cfg.pno_cb.arg;
+ qdf_spin_unlock_bh(&scan_psoc_obj->lock);
+
+ if (pno_cb)
+ pno_cb(vdev, event, cb_arg);
+
+ return QDF_STATUS_SUCCESS;
+}
+#else
+
+static QDF_STATUS
+scm_pno_event_handler(struct wlan_objmgr_vdev *vdev,
+ struct scan_event *event)
+{
+ return QDF_STATUS_SUCCESS;
+}
+#endif
+
QDF_STATUS
scm_scan_event_handler(struct scheduler_msg *msg)
{
@@ -510,12 +571,17 @@
case SCAN_EVENT_TYPE_DEQUEUED:
scm_release_serialization_command(vdev, event->scan_id);
break;
+ case SCAN_EVENT_TYPE_NLO_COMPLETE:
+ case SCAN_EVENT_TYPE_NLO_MATCH:
+ scm_pno_event_handler(vdev, event);
+ goto exit;
default:
break;
}
/* Notify all interested parties */
scm_scan_post_event(vdev, event);
+exit:
/* free event info memory */
qdf_mem_free(event_info);
wlan_objmgr_vdev_release_ref(vdev, WLAN_SCAN_ID);
diff --git a/umac/scan/dispatcher/inc/wlan_scan_public_structs.h b/umac/scan/dispatcher/inc/wlan_scan_public_structs.h
index b60e57a..00ff1ec 100644
--- a/umac/scan/dispatcher/inc/wlan_scan_public_structs.h
+++ b/umac/scan/dispatcher/inc/wlan_scan_public_structs.h
@@ -692,6 +692,7 @@
* @SCAN_EVENT_TYPE_SUSPENDED: scan got suspended
* @SCAN_EVENT_TYPE_RESUMED: scan resumed
* @SCAN_EVENT_TYPE_NLO_COMPLETE: NLO completed
+ * @SCAN_EVENT_TYPE_NLO_MATCH: NLO match event
* @SCAN_EVENT_TYPE_INVALID: invalid request
* @SCAN_EVENT_TYPE_GPIO_TIMEOUT: gpio timeout
* @SCAN_EVENT_TYPE_RADIO_MEASUREMENT_START: radio measurement start
@@ -713,6 +714,7 @@
SCAN_EVENT_TYPE_SUSPENDED,
SCAN_EVENT_TYPE_RESUMED,
SCAN_EVENT_TYPE_NLO_COMPLETE,
+ SCAN_EVENT_TYPE_NLO_MATCH,
SCAN_EVENT_TYPE_INVALID,
SCAN_EVENT_TYPE_GPIO_TIMEOUT,
SCAN_EVENT_TYPE_RADIO_MEASUREMENT_START,
@@ -819,10 +821,110 @@
SCAN_CB_TYPE_UPDATE_BCN,
};
+/* Set PNO */
+#define SCAN_PNO_MAX_PLAN_REQUEST 2
+#define SCAN_PNO_MAX_NETW_CHANNELS_EX 60
+#define SCAN_PNO_MAX_SUPP_NETWORKS 16
+#define SCAN_PNO_DEF_SLOW_SCAN_MULTIPLIER 6
+#define SCAN_PNO_DEF_SCAN_TIMER_REPEAT 20
+#define SCAN_PNO_MATCH_WAKE_LOCK_TIMEOUT (5 * 1000) /* in msec */
+#ifdef CONFIG_SLUB_DEBUG_ON
+#define SCAN_PNO_SCAN_COMPLETE_WAKE_LOCK_TIMEOUT (2 * 1000) /* in msec */
+#else
+#define SCAN_PNO_SCAN_COMPLETE_WAKE_LOCK_TIMEOUT (1 * 1000) /* in msec */
+#endif /* CONFIG_SLUB_DEBUG_ON */
+
+#define SCAN_PNO_CHANNEL_PREDICTION 0
+#define SCAN_TOP_K_NUM_OF_CHANNELS 3
+#define SCAN_STATIONARY_THRESHOLD 10
+#define SCAN_CHANNEL_PREDICTION_FULL_SCAN_MS 60000
+#define SCAN_ADAPTIVE_PNOSCAN_DWELL_MODE 0
+
/**
- * struct pno_scan_req_params - forward declaration
+ * enum ssid_bc_type - SSID broadcast type
+ * @SSID_BC_TYPE_UNKNOWN: Broadcast unknown
+ * @SSID_BC_TYPE_NORMAL: Broadcast normal
+ * @SSID_BC_TYPE_HIDDEN: Broadcast hidden
*/
-struct pno_scan_req_params;
+enum ssid_bc_type {
+ SSID_BC_TYPE_UNKNOWN = 0,
+ SSID_BC_TYPE_NORMAL = 1,
+ SSID_BC_TYPE_HIDDEN = 2,
+};
+
+/**
+ * struct pno_nw_type - pno nw type
+ * @ssid: ssid
+ * @authentication: authentication type
+ * @encryption: encryption type
+ * @bcastNetwType: broadcast nw type
+ * @ucChannelCount: uc channel count
+ * @aChannels: pno channel
+ * @rssiThreshold: rssi threshold
+ */
+struct pno_nw_type {
+ struct wlan_ssid ssid;
+ uint32_t authentication;
+ uint32_t encryption;
+ uint32_t bc_new_type;
+ uint8_t channel_cnt;
+ uint32_t channels[SCAN_PNO_MAX_NETW_CHANNELS_EX];
+ int32_t rssi_thresh;
+};
+
+/**
+ * struct pno_scan_req_params - PNO Scan request structure
+ * @networks_cnt: Number of networks
+ * @vdev_id: vdev id
+ * @fast_scan_period: Fast Scan period
+ * @slow_scan_period: Slow scan period
+ * @delay_start_time: delay in seconds to use before starting the first scan
+ * @fast_scan_max_cycles: Fast scan max cycles
+ * @pno_channel_prediction: PNO channel prediction feature status
+ * @uint32_t active_dwell_time: active dwell time
+ * @uint32_t passive_dwell_time: passive dwell time
+ * @top_k_num_of_channels: top K number of channels are used for tanimoto
+ * distance calculation.
+ * @stationary_thresh: threshold value to determine that the STA is stationary.
+ * @adaptive_dwell_mode: adaptive dwelltime mode for pno scan
+ * @channel_prediction_full_scan: periodic timer upon which a full scan needs
+ * to be triggered.
+ * @networks_list: Preferred network list
+ */
+struct pno_scan_req_params {
+ uint32_t networks_cnt;
+ uint32_t vdev_id;
+ uint32_t fast_scan_period;
+ uint32_t slow_scan_period;
+ uint32_t delay_start_time;
+ uint32_t fast_scan_max_cycles;
+ uint32_t active_dwell_time;
+ uint32_t passive_dwell_time;
+ uint32_t pno_channel_prediction;
+ uint32_t top_k_num_of_channels;
+ uint32_t stationary_thresh;
+ enum scan_dwelltime_adaptive_mode adaptive_dwell_mode;
+ uint32_t channel_prediction_full_scan;
+ struct pno_nw_type networks_list[SCAN_PNO_MAX_SUPP_NETWORKS];
+};
+
+/**
+ * struct pno_user_cfg - user configuration required for PNO
+ * @channel_prediction: config PNO channel prediction feature status
+ * @top_k_num_of_channels: def top K number of channels are used for tanimoto
+ * distance calculation.
+ * @stationary_thresh: def threshold val to determine that STA is stationary.
+ * @pnoscan_adaptive_dwell_mode: def adaptive dwelltime mode for pno scan
+ * @channel_prediction_full_scan: def periodic timer upon which full scan needs
+ * to be triggered.
+ */
+struct pno_user_cfg {
+ bool channel_prediction;
+ uint8_t top_k_num_of_channels;
+ uint8_t stationary_thresh;
+ enum scan_dwelltime_adaptive_mode adaptive_dwell_mode;
+ uint32_t channel_prediction_full_scan;
+};
/**
* struct scan_user_cfg - user configuration required for for scan
@@ -835,6 +937,7 @@
* @conc_idle_time: default concurrent idle time
* @scan_cache_aging_time: default scan cache aging time
* @scan_dwell_time_mode: Adaptive dweltime mode
+ * @pno_cfg: Pno related config params
*/
struct scan_user_cfg {
uint32_t active_dwell;
@@ -846,6 +949,7 @@
uint32_t conc_idle_time;
uint32_t scan_cache_aging_time;
enum scan_dwelltime_adaptive_mode scan_dwell_time_mode;
+ struct pno_user_cfg pno_cfg;
};
/**
diff --git a/umac/scan/dispatcher/inc/wlan_scan_tgt_api.h b/umac/scan/dispatcher/inc/wlan_scan_tgt_api.h
index d3506b9..985f40c 100644
--- a/umac/scan/dispatcher/inc/wlan_scan_tgt_api.h
+++ b/umac/scan/dispatcher/inc/wlan_scan_tgt_api.h
@@ -49,37 +49,6 @@
enum mgmt_frame_type frm_type);
/**
- * tgt_scan_nlo_complete_evt_handler() - The callbeack registered
- * to WMI for PNO complete
- * @handle: psoc handle
- * @event: event handler
- * @len: length of data
- *
- * This function handles NLO scan completion event.
- *
- * Return: 0 for success or error code.
- */
-
-QDF_STATUS
-tgt_scan_nlo_complete_evt_handler(void *handle, uint8_t *event,
- uint32_t len);
-
-/**
- * tgt_nlo_match_evt_handler() - nlo match event handler
- * @handle: psoc handle
- * @event: event data
- * @len: data length
- *
- * Record NLO match event comes from FW. It's a indication that
- * one of the profile is matched.
- *
- * Return: 0 for success or error code.
- */
-QDF_STATUS
-tgt_nlo_match_evt_handler(void *handle, uint8_t *event,
- uint32_t len);
-
-/**
* tgt_scan_event_handler() - The callbeack registered to WMI for scan events
* @psoc: psoc handle
* @event_info: event info
@@ -93,6 +62,30 @@
tgt_scan_event_handler(struct wlan_objmgr_psoc *psoc,
struct scan_event_info *event_info);
+#ifdef FEATURE_WLAN_SCAN_PNO
+
+/**
+ * tgt_scan_pno_start() - invoke lmac send PNO start req
+ * @vdev: vdev pointer
+ * @req: pno req params
+ *
+ * Return: 0 for success or error code.
+ */
+QDF_STATUS tgt_scan_pno_start(struct wlan_objmgr_vdev *vdev,
+ struct pno_scan_req_params *req);
+
+/**
+ * tgt_scan_pno_stop() - invoke lmac send PNO stop req
+ * @vdev: vdev pointer
+ * @vdev_id: pno req params
+ *
+ * Return: 0 for success or error code.
+ */
+QDF_STATUS tgt_scan_pno_stop(struct wlan_objmgr_vdev *vdev,
+ uint8_t vdev_id);
+
+#endif
+
/**
* tgt_scan_start() - invoke lmac scan start
* @req: scan request object
diff --git a/umac/scan/dispatcher/inc/wlan_scan_ucfg_api.h b/umac/scan/dispatcher/inc/wlan_scan_ucfg_api.h
index aeb5232..018dbac 100644
--- a/umac/scan/dispatcher/inc/wlan_scan_ucfg_api.h
+++ b/umac/scan/dispatcher/inc/wlan_scan_ucfg_api.h
@@ -88,8 +88,80 @@
wlan_scan_id
ucfg_scan_get_scan_id(struct wlan_objmgr_psoc *psoc);
+#ifdef FEATURE_WLAN_SCAN_PNO
+/**
+ * ucfg_scan_pno_start() - Public API to start PNO
+ * @vdev: vdev pointer
+ * @req: pno req params
+ *
+ * Return: 0 for success or error code.
+ */
+QDF_STATUS ucfg_scan_pno_start(struct wlan_objmgr_vdev *vdev,
+struct pno_scan_req_params *req);
/**
+ * ucfg_scan_pno_stop() - Public API to stop PNO
+ * @vdev: vdev pointer
+ * @req: pno req params
+ *
+ * Return: 0 for success or error code.
+ */
+QDF_STATUS ucfg_scan_pno_stop(struct wlan_objmgr_vdev *vdev);
+
+/**
+ * ucfg_scan_get_pno_in_progress() - Public API to check if pno is in progress
+ * @vdev: vdev pointer
+ *
+ * Return: true if pno in progress else false.
+ */
+bool ucfg_scan_get_pno_in_progress(struct wlan_objmgr_vdev *vdev);
+
+/**
+ * ucfg_scan_get_pno_match() - Public API to check if pno matched
+ * @vdev: vdev pointer
+ *
+ * Return: true if pno matched else false.
+ */
+bool ucfg_scan_get_pno_match(struct wlan_objmgr_vdev *vdev);
+
+/**
+ * ucfg_scan_register_pno_cb() - register pno cb
+ * @psoc: psoc object
+ * @event_cb: callback function pointer
+ * @arg: argument to @event_cb
+ *
+ * Return: QDF_STATUS
+ */
+QDF_STATUS
+ucfg_scan_register_pno_cb(struct wlan_objmgr_psoc *psoc,
+ scan_event_handler event_cb, void *arg);
+
+/**
+ * ucfg_scan_get_pno_def_params() - get the defaults pno params
+ * @vdev: vdev object
+ * @req: pno request object
+ *
+ * Return: QDF_STATUS_SUCCESS or error code
+ */
+QDF_STATUS
+ucfg_scan_get_pno_def_params(struct wlan_objmgr_vdev *vdev,
+ struct pno_scan_req_params *req);
+
+#else
+
+static inline bool
+ucfg_scan_get_pno_in_progress(struct wlan_objmgr_vdev *vdev)
+{
+ return false;
+}
+
+static inline bool
+ucfg_scan_get_pno_match(struct wlan_objmgr_vdev *vdev)
+{
+ return false;
+}
+#endif /* FEATURE_WLAN_SCAN_PNO */
+/**
* ucfg_scan_start() - Public API to start a scan
* @req: start scan req params
*
diff --git a/umac/scan/dispatcher/src/wlan_scan_tgt_api.c b/umac/scan/dispatcher/src/wlan_scan_tgt_api.c
index c4cef8c..169b758 100644
--- a/umac/scan/dispatcher/src/wlan_scan_tgt_api.c
+++ b/umac/scan/dispatcher/src/wlan_scan_tgt_api.c
@@ -59,28 +59,39 @@
return &((psoc->soc_cb.rx_ops.scan));
}
-QDF_STATUS
-tgt_scan_nlo_complete_evt_handler(void *handle, uint8_t *event,
- uint32_t len)
+#ifdef FEATURE_WLAN_SCAN_PNO
+
+QDF_STATUS tgt_scan_pno_start(struct wlan_objmgr_vdev *vdev,
+ struct pno_scan_req_params *req)
{
- /*
- * Convert the tlv/non tlv data to struct scan_event
- * (SCM_EVENT_NLO_COMPLETE) (same as WIN does by calling a win API) and
- * Post msg to target_if queue
- */
+ struct wlan_lmac_if_scan_tx_ops *scan_ops = NULL;
+ struct wlan_objmgr_psoc *psoc = wlan_vdev_get_psoc(vdev);
+
+ scan_ops = wlan_vdev_get_scan_txops(vdev);
+ /* invoke wmi_unified_pno_start_cmd() */
+ QDF_ASSERT(scan_ops->pno_start);
+ if (scan_ops->pno_start)
+ return scan_ops->pno_start(psoc, req);
+
return QDF_STATUS_SUCCESS;
}
-QDF_STATUS
-tgt_nlo_match_evt_handler(void *handle, uint8_t *event,
- uint32_t len)
+QDF_STATUS tgt_scan_pno_stop(struct wlan_objmgr_vdev *vdev,
+ uint8_t vdev_id)
{
- /*
- * Convert the tlv/non tlv data to comman data
- * and set the pno match received flag in vdev scan info
- */
+ struct wlan_lmac_if_scan_tx_ops *scan_ops = NULL;
+ struct wlan_objmgr_psoc *psoc = wlan_vdev_get_psoc(vdev);
+
+ scan_ops = wlan_vdev_get_scan_txops(vdev);
+
+ /* invoke wmi_unified_pno_stop_cmd() */
+ QDF_ASSERT(scan_ops->pno_stop);
+ if (scan_ops->pno_stop)
+ return scan_ops->pno_stop(psoc, vdev_id);
+
return QDF_STATUS_SUCCESS;
}
+#endif
QDF_STATUS
tgt_scan_start(struct scan_start_request *req)
diff --git a/umac/scan/dispatcher/src/wlan_scan_ucfg_api.c b/umac/scan/dispatcher/src/wlan_scan_ucfg_api.c
index bdd36ac..173d1d4 100644
--- a/umac/scan/dispatcher/src/wlan_scan_ucfg_api.c
+++ b/umac/scan/dispatcher/src/wlan_scan_ucfg_api.c
@@ -78,12 +78,33 @@
status = wlan_objmgr_register_psoc_destroy_handler(WLAN_UMAC_COMP_SCAN,
wlan_scan_psoc_destroyed_notification, NULL);
+ if (QDF_IS_STATUS_ERROR(status)) {
+ scm_err("Failed to create psoc delete handler");
+ goto fail_psoc_destroy;
+ }
+ scm_info("scan psoc create and delete handler registered with objmgr");
+
+ status = wlan_objmgr_register_vdev_create_handler(WLAN_UMAC_COMP_SCAN,
+ wlan_scan_vdev_created_notification, NULL);
+ if (QDF_IS_STATUS_ERROR(status)) {
+ scm_err("Failed to register vdev create handler");
+ goto fail_pdev_create;
+ }
+
+ status = wlan_objmgr_register_vdev_destroy_handler(WLAN_UMAC_COMP_SCAN,
+ wlan_scan_vdev_destroyed_notification, NULL);
if (QDF_IS_STATUS_SUCCESS(status)) {
- scm_info("scan create and delete handler registered with objmgr");
+ scm_info("scan vdev create and delete handler registered with objmgr");
return QDF_STATUS_SUCCESS;
}
- scm_err("Failed to create psoc delete handler");
+ scm_err("Failed to destroy vdev delete handler");
+ wlan_objmgr_unregister_vdev_create_handler(WLAN_UMAC_COMP_SCAN,
+ wlan_scan_vdev_created_notification, NULL);
+fail_pdev_create:
+ wlan_objmgr_unregister_psoc_destroy_handler(WLAN_UMAC_COMP_SCAN,
+ wlan_scan_psoc_destroyed_notification, NULL);
+fail_psoc_destroy:
wlan_objmgr_unregister_psoc_create_handler(WLAN_UMAC_COMP_SCAN,
wlan_scan_psoc_created_notification, NULL);
fail_create_psoc:
@@ -105,9 +126,206 @@
if (status != QDF_STATUS_SUCCESS)
scm_err("Failed to unregister psoc delete handler");
+ status = wlan_objmgr_unregister_vdev_create_handler(WLAN_UMAC_COMP_SCAN,
+ wlan_scan_vdev_created_notification, NULL);
+ if (status != QDF_STATUS_SUCCESS)
+ scm_err("Failed to unregister vdev create handler");
+
+ status = wlan_objmgr_unregister_vdev_destroy_handler(
+ WLAN_UMAC_COMP_SCAN,
+ wlan_scan_vdev_destroyed_notification, NULL);
+ if (status != QDF_STATUS_SUCCESS)
+ scm_err("Failed to unregister vdev delete handler");
+
return status;
}
+#ifdef FEATURE_WLAN_SCAN_PNO
+
+QDF_STATUS ucfg_scan_pno_start(struct wlan_objmgr_vdev *vdev,
+ struct pno_scan_req_params *req)
+{
+ struct scan_vdev_obj *scan_vdev_obj;
+ QDF_STATUS status;
+
+ scan_vdev_obj = wlan_get_vdev_scan_obj(vdev);
+ if (!scan_vdev_obj) {
+ scm_err("null scan_vdev_obj");
+ return QDF_STATUS_E_INVAL;
+ }
+ if (scan_vdev_obj->pno_in_progress) {
+ scm_err("pno already in progress");
+ return QDF_STATUS_E_ALREADY;
+ }
+
+ status = tgt_scan_pno_start(vdev, req);
+ if (QDF_IS_STATUS_ERROR(status))
+ scm_err("pno start failed");
+ else
+ scan_vdev_obj->pno_in_progress = true;
+
+ return status;
+}
+
+QDF_STATUS ucfg_scan_pno_stop(struct wlan_objmgr_vdev *vdev)
+{
+ struct scan_vdev_obj *scan_vdev_obj;
+ QDF_STATUS status;
+
+ scan_vdev_obj = wlan_get_vdev_scan_obj(vdev);
+ if (!scan_vdev_obj) {
+ scm_err("null scan_vdev_obj");
+ return QDF_STATUS_E_INVAL;
+ }
+ if (!scan_vdev_obj->pno_in_progress) {
+ scm_err("pno already stopped");
+ return QDF_STATUS_E_ALREADY;
+ }
+
+ status = tgt_scan_pno_stop(vdev, wlan_vdev_get_id(vdev));
+ if (QDF_IS_STATUS_ERROR(status))
+ scm_err("pno start failed");
+ else
+ scan_vdev_obj->pno_in_progress = false;
+
+ return status;
+}
+
+bool ucfg_scan_get_pno_in_progress(struct wlan_objmgr_vdev *vdev)
+{
+ struct scan_vdev_obj *scan_vdev_obj;
+
+ scan_vdev_obj = wlan_get_vdev_scan_obj(vdev);
+ if (!scan_vdev_obj) {
+ scm_err("null scan_vdev_obj");
+ return false;
+ }
+
+ return scan_vdev_obj->pno_in_progress;
+}
+
+bool ucfg_scan_get_pno_match(struct wlan_objmgr_vdev *vdev)
+{
+ struct scan_vdev_obj *scan_vdev_obj;
+
+ scan_vdev_obj = wlan_get_vdev_scan_obj(vdev);
+ if (!scan_vdev_obj) {
+ scm_err("null scan_vdev_obj");
+ return false;
+ }
+
+ return scan_vdev_obj->pno_match_evt_received;
+}
+
+static QDF_STATUS
+wlan_pno_global_init(struct pno_def_config *pno_def)
+{
+ qdf_wake_lock_create(&pno_def->pno_wake_lock, "wlan_pno_wl");
+ pno_def->channel_prediction = SCAN_PNO_CHANNEL_PREDICTION;
+ pno_def->top_k_num_of_channels = SCAN_TOP_K_NUM_OF_CHANNELS;
+ pno_def->stationary_thresh = SCAN_STATIONARY_THRESHOLD;
+ pno_def->channel_prediction_full_scan =
+ SCAN_CHANNEL_PREDICTION_FULL_SCAN_MS;
+ pno_def->adaptive_dwell_mode = SCAN_ADAPTIVE_PNOSCAN_DWELL_MODE;
+
+ return QDF_STATUS_SUCCESS;
+}
+
+static QDF_STATUS
+wlan_pno_global_deinit(struct pno_def_config *pno_def)
+{
+ qdf_wake_lock_destroy(&pno_def->pno_wake_lock);
+
+ return QDF_STATUS_SUCCESS;
+}
+
+QDF_STATUS
+ucfg_scan_get_pno_def_params(struct wlan_objmgr_vdev *vdev,
+ struct pno_scan_req_params *req)
+{
+ struct scan_default_params *scan_def;
+ struct wlan_scan_obj *scan = wlan_vdev_get_scan_obj(vdev);
+ struct pno_def_config *pno_def;
+
+ if (!vdev | !req | !scan) {
+ scm_err("vdev: 0x%p, req: 0x%p scan_obj: 0x%p",
+ vdev, req, scan);
+ return QDF_STATUS_E_INVAL;
+ }
+
+ scan_def = wlan_vdev_get_def_scan_params(vdev);
+ pno_def = &scan->pno_cfg;
+
+ req->active_dwell_time = scan_def->active_dwell;
+ req->passive_dwell_time = scan_def->passive_dwell;
+
+ req->adaptive_dwell_mode = pno_def->adaptive_dwell_mode;
+
+ req->pno_channel_prediction = pno_def->adaptive_dwell_mode;
+ req->top_k_num_of_channels = pno_def->top_k_num_of_channels;
+ req->stationary_thresh = pno_def->stationary_thresh;
+ req->channel_prediction_full_scan =
+ pno_def->channel_prediction_full_scan;
+
+ return QDF_STATUS_SUCCESS;
+}
+
+static QDF_STATUS ucfg_scan_update_pno_config(struct pno_def_config *pno,
+ struct pno_user_cfg *pno_cfg)
+{
+ pno->channel_prediction = pno_cfg->channel_prediction;
+ pno->top_k_num_of_channels = pno_cfg->top_k_num_of_channels;
+ pno->stationary_thresh = pno_cfg->stationary_thresh;
+ pno->adaptive_dwell_mode = pno_cfg->adaptive_dwell_mode;
+ pno->channel_prediction_full_scan =
+ pno_cfg->channel_prediction_full_scan;
+
+ return QDF_STATUS_SUCCESS;
+}
+
+QDF_STATUS
+ucfg_scan_register_pno_cb(struct wlan_objmgr_psoc *psoc,
+ scan_event_handler event_cb, void *arg)
+{
+ struct wlan_scan_obj *scan;
+
+ if (!psoc) {
+ scm_err("null psoc");
+ return QDF_STATUS_E_INVAL;
+ }
+ scan = wlan_psoc_get_scan_obj(psoc);
+ qdf_spin_lock_bh(&scan->lock);
+ scan->pno_cfg.pno_cb.func = event_cb;
+ scan->pno_cfg.pno_cb.arg = arg;
+ qdf_spin_unlock_bh(&scan->lock);
+ scm_info("event_cb: 0x%p, arg: 0x%p", event_cb, arg);
+
+ return QDF_STATUS_SUCCESS;
+}
+
+#else
+
+static inline QDF_STATUS
+wlan_pno_global_init(struct pno_def_config *pno_def)
+{
+ return QDF_STATUS_SUCCESS;
+}
+static inline QDF_STATUS
+wlan_pno_global_deinit(struct pno_def_config *pno_def)
+{
+ return QDF_STATUS_SUCCESS;
+}
+
+static inline QDF_STATUS
+ucfg_scan_update_pno_config(struct pno_def_config *pno,
+ struct pno_user_cfg *pno_cfg)
+{
+ return QDF_STATUS_SUCCESS;
+}
+
+#endif
+
+
QDF_STATUS
ucfg_scan_start(struct scan_start_request *req)
{
@@ -378,7 +596,7 @@
/* init scan id seed */
qdf_atomic_init(&scan_obj->scan_ids);
- return QDF_STATUS_SUCCESS;
+ return wlan_pno_global_init(&scan_obj->pno_cfg);
}
static QDF_STATUS
@@ -713,7 +931,8 @@
scan_def->scan_cache_aging_time = scan_cfg->scan_cache_aging_time;
scan_def->adaptive_dwell_time_mode = scan_cfg->scan_dwell_time_mode;
- return QDF_STATUS_SUCCESS;
+ return ucfg_scan_update_pno_config(&scan_obj->pno_cfg,
+ &scan_cfg->pno_cfg);
}
QDF_STATUS
@@ -754,6 +973,7 @@
return QDF_STATUS_E_FAILURE;
}
qdf_spinlock_destroy(&scan_obj->lock);
+ wlan_pno_global_deinit(&scan_obj->pno_cfg);
return QDF_STATUS_SUCCESS;
}
diff --git a/umac/scan/dispatcher/src/wlan_scan_utils_api.c b/umac/scan/dispatcher/src/wlan_scan_utils_api.c
index 8f76d9e..eb940b4 100644
--- a/umac/scan/dispatcher/src/wlan_scan_utils_api.c
+++ b/umac/scan/dispatcher/src/wlan_scan_utils_api.c
@@ -42,6 +42,7 @@
[SCAN_EVENT_TYPE_SUSPENDED] = "SUSPENDED",
[SCAN_EVENT_TYPE_RESUMED] = "RESUMED",
[SCAN_EVENT_TYPE_NLO_COMPLETE] = "NLO_COMPLETE",
+ [SCAN_EVENT_TYPE_NLO_MATCH] = "NLO_MATCH",
[SCAN_EVENT_TYPE_INVALID] = "INVALID",
[SCAN_EVENT_TYPE_GPIO_TIMEOUT] = "GPIO_TIMEOUT",
[SCAN_EVENT_TYPE_RADIO_MEASUREMENT_START] =