|
@@ -4713,6 +4713,12 @@ hdd_alloc_station_adapter(struct hdd_context *hdd_ctx, tSirMacAddr mac_addr,
|
|
|
if (QDF_IS_STATUS_ERROR(qdf_status))
|
|
|
goto free_net_dev;
|
|
|
|
|
|
+ qdf_status = hdd_monitor_mode_qdf_create_event(adapter, session_type);
|
|
|
+ if (QDF_IS_STATUS_ERROR(qdf_status)) {
|
|
|
+ hdd_err_rl("create monitor mode vdve up event failed");
|
|
|
+ goto free_net_dev;
|
|
|
+ }
|
|
|
+
|
|
|
init_completion(&adapter->vdev_destroy_event);
|
|
|
|
|
|
adapter->offloads_configured = false;
|
|
@@ -6396,6 +6402,9 @@ QDF_STATUS hdd_stop_adapter(struct hdd_context *hdd_ctx,
|
|
|
wlan_hdd_scan_abort(adapter);
|
|
|
hdd_deregister_hl_netdev_fc_timer(adapter);
|
|
|
hdd_deregister_tx_flow_control(adapter);
|
|
|
+ status = hdd_monitor_mode_vdev_status(adapter);
|
|
|
+ if (QDF_IS_STATUS_ERROR(status))
|
|
|
+ hdd_err_rl("stop failed montior mode");
|
|
|
sme_delete_mon_session(mac_handle, adapter->vdev_id);
|
|
|
hdd_vdev_destroy(adapter);
|
|
|
break;
|
|
@@ -7313,16 +7322,53 @@ int wlan_hdd_set_mon_chan(struct hdd_adapter *adapter, qdf_freq_t freq,
|
|
|
return -EINVAL;
|
|
|
}
|
|
|
|
|
|
+ if (adapter->monitor_mode_vdev_up_in_progress) {
|
|
|
+ hdd_err_rl("monitor mode vdev up in progress");
|
|
|
+ return -EBUSY;
|
|
|
+ }
|
|
|
+
|
|
|
+ status = qdf_event_reset(&adapter->qdf_monitor_mode_vdev_up_event);
|
|
|
+ if (QDF_IS_STATUS_ERROR(status)) {
|
|
|
+ hdd_err_rl("failed to reinit monitor mode vdev up event");
|
|
|
+ return qdf_status_to_os_return(status);
|
|
|
+ }
|
|
|
+ adapter->monitor_mode_vdev_up_in_progress = true;
|
|
|
+
|
|
|
status = sme_roam_channel_change_req(hdd_ctx->mac_handle,
|
|
|
bssid, &roam_profile.ch_params,
|
|
|
&roam_profile);
|
|
|
if (status) {
|
|
|
hdd_err("Status: %d Failed to set sme_roam Channel for monitor mode",
|
|
|
status);
|
|
|
+ adapter->monitor_mode_vdev_up_in_progress = false;
|
|
|
+ return qdf_status_to_os_return(status);
|
|
|
}
|
|
|
|
|
|
adapter->mon_chan_freq = freq;
|
|
|
adapter->mon_bandwidth = bandwidth;
|
|
|
+
|
|
|
+ /* block on a completion variable until vdev up success*/
|
|
|
+ status = qdf_wait_for_event_completion(
|
|
|
+ &adapter->qdf_monitor_mode_vdev_up_event,
|
|
|
+ WLAN_MONITOR_MODE_VDEV_UP_EVT);
|
|
|
+ if (QDF_IS_STATUS_ERROR(status)) {
|
|
|
+ hdd_err_rl("monitor vdev up event time out vdev id: %d",
|
|
|
+ adapter->vdev_id);
|
|
|
+ if (adapter->qdf_monitor_mode_vdev_up_event.force_set)
|
|
|
+ /*
|
|
|
+ * SSR/PDR has caused shutdown, which has
|
|
|
+ * forcefully set the event.
|
|
|
+ */
|
|
|
+ hdd_err_rl("monitor mode vdev up event forcefully set");
|
|
|
+ else if (status == QDF_STATUS_E_TIMEOUT)
|
|
|
+ hdd_err("monitor mode vdev up timed out");
|
|
|
+ else
|
|
|
+ hdd_err_rl("Failed monitor mode vdev up(status-%d)",
|
|
|
+ status);
|
|
|
+
|
|
|
+ adapter->monitor_mode_vdev_up_in_progress = false;
|
|
|
+ }
|
|
|
+
|
|
|
return qdf_status_to_os_return(status);
|
|
|
}
|
|
|
#endif
|
|
@@ -13557,6 +13603,10 @@ int hdd_register_cb(struct hdd_context *hdd_ctx)
|
|
|
|
|
|
sme_set_oem_data_event_handler_cb(mac_handle, hdd_oem_event_handler_cb);
|
|
|
sme_set_roam_scan_ch_event_cb(mac_handle, hdd_get_roam_scan_ch_cb);
|
|
|
+ status = sme_set_monitor_mode_cb(mac_handle,
|
|
|
+ hdd_sme_monitor_mode_callback);
|
|
|
+ if (QDF_IS_STATUS_ERROR(status))
|
|
|
+ hdd_err_rl("Register monitor mode callback failed");
|
|
|
|
|
|
hdd_exit();
|
|
|
|
|
@@ -16777,6 +16827,84 @@ wlan_hdd_add_monitor_check(struct hdd_context *hdd_ctx,
|
|
|
}
|
|
|
#endif /* WLAN_FEATURE_PKT_CAPTURE */
|
|
|
|
|
|
+
|
|
|
+#ifdef FEATURE_MONITOR_MODE_SUPPORT
|
|
|
+
|
|
|
+void hdd_sme_monitor_mode_callback(uint8_t vdev_id)
|
|
|
+{
|
|
|
+ struct hdd_adapter *adapter;
|
|
|
+ struct hdd_context *hdd_ctx;
|
|
|
+
|
|
|
+ hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
|
|
|
+ if (!hdd_ctx) {
|
|
|
+ hdd_err_rl("Invalid HDD_CTX");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ adapter = hdd_get_adapter_by_vdev(hdd_ctx, vdev_id);
|
|
|
+ if (!adapter) {
|
|
|
+ hdd_err_rl("NULL adapter");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (adapter->magic != WLAN_HDD_ADAPTER_MAGIC) {
|
|
|
+ hdd_err_rl("Invalid magic");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (adapter->magic == WLAN_HDD_ADAPTER_MAGIC)
|
|
|
+ qdf_event_set(&adapter->qdf_monitor_mode_vdev_up_event);
|
|
|
+
|
|
|
+ hdd_debug("monitor mode vdev up completed");
|
|
|
+ adapter->monitor_mode_vdev_up_in_progress = false;
|
|
|
+}
|
|
|
+
|
|
|
+QDF_STATUS hdd_monitor_mode_qdf_create_event(struct hdd_adapter *adapter,
|
|
|
+ uint8_t session_type)
|
|
|
+{
|
|
|
+ QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
|
|
|
+
|
|
|
+ if (session_type == QDF_MONITOR_MODE) {
|
|
|
+ qdf_status = qdf_event_create(
|
|
|
+ &adapter->qdf_monitor_mode_vdev_up_event);
|
|
|
+ }
|
|
|
+ return qdf_status;
|
|
|
+}
|
|
|
+
|
|
|
+QDF_STATUS hdd_monitor_mode_vdev_status(struct hdd_adapter *adapter)
|
|
|
+{
|
|
|
+ QDF_STATUS status = QDF_STATUS_SUCCESS;
|
|
|
+
|
|
|
+ if (!adapter->monitor_mode_vdev_up_in_progress)
|
|
|
+ return status;
|
|
|
+
|
|
|
+ /* block on a completion variable until vdev up success*/
|
|
|
+ status = qdf_wait_for_event_completion(
|
|
|
+ &adapter->qdf_monitor_mode_vdev_up_event,
|
|
|
+ WLAN_MONITOR_MODE_VDEV_UP_EVT);
|
|
|
+ if (QDF_IS_STATUS_ERROR(status)) {
|
|
|
+ hdd_err_rl("monitor mode vdev up event time out vdev id: %d",
|
|
|
+ adapter->vdev_id);
|
|
|
+ if (adapter->qdf_monitor_mode_vdev_up_event.force_set)
|
|
|
+ /*
|
|
|
+ * SSR/PDR has caused shutdown, which has
|
|
|
+ * forcefully set the event.
|
|
|
+ */
|
|
|
+ hdd_err_rl("monitor mode vdev up event forcefully set");
|
|
|
+ else if (status == QDF_STATUS_E_TIMEOUT)
|
|
|
+ hdd_err_rl("mode vdev up event timed out");
|
|
|
+ else
|
|
|
+ hdd_err_rl("Failed to wait for monitor vdev up(status-%d)",
|
|
|
+ status);
|
|
|
+
|
|
|
+ adapter->monitor_mode_vdev_up_in_progress = false;
|
|
|
+ return status;
|
|
|
+ }
|
|
|
+
|
|
|
+ return QDF_STATUS_SUCCESS;
|
|
|
+}
|
|
|
+#endif
|
|
|
+
|
|
|
#ifdef CONFIG_WLAN_DEBUG_CRASH_INJECT
|
|
|
int hdd_crash_inject(struct hdd_adapter *adapter, uint32_t v1, uint32_t v2)
|
|
|
{
|