qcacld-3.0: Add support for STA + monitor mode

In mission mode, add support for virtual add/del monitor
mode interface. In addition to STA vdev, create and maintain
a new vdev for monitor interface.

Change-Id: I91ea8e56976cce92f9b1ae308d4bd0fb30815366
CRs-Fixed: 2818499
This commit is contained in:
Amruta Kulkarni 2020-11-12 15:39:04 -08:00 • committed by snandini
commit fd9f26cb8e
13 changed files with 307 additions and 233 deletions

View file

@ -175,7 +175,7 @@ target_if_register_mgmt_data_offload_event(struct wlan_objmgr_psoc *psoc)
}
wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
if (ucfg_pkt_capture_get_mode(psoc) &&
if ((ucfg_pkt_capture_get_mode(psoc) != PACKET_CAPTURE_MODE_DISABLE) &&
wmi_service_enabled(wmi_handle,
wmi_service_packet_capture_support)) {
uint8_t status;

View file

@ -1005,8 +1005,8 @@ ol_tx_completion_handler(ol_txrx_pdev_handle pdev,
msg_word_header, &msg_word_payload, num_msdus);
}
if ((ucfg_pkt_capture_get_mode((void *)soc->psoc) &
PKT_CAPTURE_MODE_DATA_ONLY))
if ((ucfg_pkt_capture_get_mode((void *)soc->psoc) ==
PACKET_CAPTURE_MODE_DATA_ONLY))
pkt_capture_txcomp_hdr_list =
ucfg_pkt_capture_tx_get_txcomplete_data_hdr(
msg_word,

View file

@ -1061,6 +1061,8 @@ struct hdd_chan_change_params {
* @dfs: dfs context to prevent/allow runtime pm
* @connect: connect context to prevent/allow runtime pm
* @user: user context to prevent/allow runtime pm
* @is_user_wakelock_acquired: boolean to check if user wakelock status
* @monitor_mode: monitor mode context to prevent/allow runtime pm
*
* Runtime PM control for underlying activities
*/
@ -1069,6 +1071,7 @@ struct hdd_runtime_pm_context {
qdf_runtime_lock_t connect;
qdf_runtime_lock_t user;
bool is_user_wakelock_acquired;
qdf_runtime_lock_t monitor_mode;
};
/*
@ -1754,6 +1757,7 @@ struct hdd_adapter_ops_history {
* @qos_cpu_mask: voted cpu core mask
* @adapter_ops_wq: High priority workqueue for handling adapter operations
* @multi_client_thermal_mitigation: Multi client thermal mitigation by fw
* @disconnect_for_sta_mon_conc: disconnect if sta monitor intf concurrency
*/
struct hdd_context {
struct wlan_objmgr_psoc *psoc;
@ -2095,6 +2099,7 @@ struct hdd_context {
#ifdef FEATURE_WPSS_THERMAL_MITIGATION
bool multi_client_thermal_mitigation;
#endif
bool disconnect_for_sta_mon_conc;
};
/**
@ -2604,6 +2609,11 @@ void hdd_deinit_adapter(struct hdd_context *hdd_ctx,
QDF_STATUS hdd_stop_adapter(struct hdd_context *hdd_ctx,
struct hdd_adapter *adapter);
/**
* hdd_set_station_ops() - update net_device ops
* @dev: Handle to struct net_device to be updated.
* Return: None
*/
void hdd_set_station_ops(struct net_device *dev);
/**
@ -4540,7 +4550,57 @@ QDF_STATUS hdd_common_roam_callback(struct wlan_objmgr_psoc *psoc,
eCsrRoamResult roam_result);
#ifdef WLAN_FEATURE_PKT_CAPTURE
/**
* wlan_hdd_is_mon_concurrency() - check if MONITOR and STA concurrency
* is UP when packet capture mode is enabled.
*
* Return: True - if STA and monitor concurrency is there, else False
*
*/
bool wlan_hdd_is_mon_concurrency(void);
/**
* wlan_hdd_del_monitor() - delete monitor interface
* @hdd_ctx: pointer to hdd context
* @adapter: adapter to be deleted
* @rtnl_held: rtnl lock held
*
* This function is invoked to delete monitor interface.
*
* Return: None
*/
void wlan_hdd_del_monitor(struct hdd_context *hdd_ctx,
struct hdd_adapter *adapter, bool rtnl_held);
/**
* wlan_hdd_del_p2p_interface() - delete p2p interface
* @hdd_ctx: pointer to hdd context
*
* This function is invoked to delete p2p interface.
*
* Return: None
*/
void
wlan_hdd_del_p2p_interface(struct hdd_context *hdd_ctx);
#else
static inline
void wlan_hdd_del_monitor(struct hdd_context *hdd_ctx,
struct hdd_adapter *adapter, bool rtnl_held)
{
}
static inline
bool wlan_hdd_is_mon_concurrency(void)
{
return false;
}
static inline
void wlan_hdd_del_p2p_interface(struct hdd_context *hdd_ctx)
{
}
#endif /* WLAN_FEATURE_PKT_CAPTURE */
/**
* wlan_hdd_is_session_type_monitor() - check if session type is MONITOR
* @session_type: session type
@ -4550,15 +4610,6 @@ QDF_STATUS hdd_common_roam_callback(struct wlan_objmgr_psoc *psoc,
*/
bool wlan_hdd_is_session_type_monitor(uint8_t session_type);
/**
* wlan_hdd_check_mon_concurrency() - check if MONITOR and STA concurrency
* is UP when packet capture mode is enabled.
*
* Return: True - if STA and monitor concurrency is there, else False
*
*/
bool wlan_hdd_check_mon_concurrency(void);
/**
* wlan_hdd_add_monitor_check() - check for monitor intf and add if needed
* @hdd_ctx: pointer to hdd context
@ -4575,47 +4626,6 @@ int wlan_hdd_add_monitor_check(struct hdd_context *hdd_ctx,
const char *name, bool rtnl_held,
unsigned char name_assign_type);
/**
* wlan_hdd_del_monitor() - delete monitor interface
* @hdd_ctx: pointer to hdd context
* @adapter: adapter to be deleted
* @rtnl_held: rtnl lock held
*
* This function is invoked to delete monitor interface.
*
* Return: None
*/
void wlan_hdd_del_monitor(struct hdd_context *hdd_ctx,
struct hdd_adapter *adapter, bool rtnl_held);
#else
static inline
bool wlan_hdd_is_session_type_monitor(uint8_t session_type)
{
return false;
}
static inline
bool wlan_hdd_check_mon_concurrency(void)
{
return false;
}
static inline
int wlan_hdd_add_monitor_check(struct hdd_context *hdd_ctx,
struct hdd_adapter **adapter,
const char *name, bool rtnl_held,
unsigned char name_assign_type)
{
return 0;
}
static inline
void wlan_hdd_del_monitor(struct hdd_context *hdd_ctx,
struct hdd_adapter *adapter, bool rtnl_held)
{
}
#endif /* WLAN_FEATURE_PKT_CAPTURE */
#ifdef CONFIG_WLAN_DEBUG_CRASH_INJECT
/**
* hdd_crash_inject() - Inject a crash

View file

@ -1830,7 +1830,7 @@ static QDF_STATUS hdd_dis_connect_handler(struct hdd_adapter *adapter,
struct net_device *dev = adapter->dev;
struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
struct hdd_station_ctx *sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter);
bool sendDisconInd = true;
bool send_discon_ind = true;
mac_handle_t mac_handle;
struct wlan_ies disconnect_ies = {0};
bool from_ap = false;
@ -1878,8 +1878,13 @@ static QDF_STATUS hdd_dis_connect_handler(struct hdd_adapter *adapter,
sta_ctx->conn_info.conn_state) ||
(eConnectionState_Connecting ==
sta_ctx->conn_info.conn_state)) {
hdd_debug("HDD has initiated a disconnect, no need to send disconnect indication to kernel");
sendDisconInd = false;
if (hdd_ctx->disconnect_for_sta_mon_conc) {
hdd_debug("Disconnect triggered by HDD to add monitor intf notify kernel");
hdd_ctx->disconnect_for_sta_mon_conc = false;
} else {
hdd_debug("HDD has initiated a disconnect, don't send disconnect indication to kernel");
send_discon_ind = false;
}
} else {
INIT_COMPLETION(adapter->disconnect_comp_var);
hdd_conn_set_connection_state(adapter,
@ -1917,7 +1922,7 @@ static QDF_STATUS hdd_dis_connect_handler(struct hdd_adapter *adapter,
* Only send indication to kernel if not initiated
* by kernel
*/
if (sendDisconInd) {
if (send_discon_ind) {
int reason = WLAN_REASON_UNSPECIFIED;
if (roam_info && roam_info->disconnect_ies) {

View file

@ -17051,7 +17051,10 @@ static int __wlan_hdd_cfg80211_change_iface(struct wiphy *wiphy,
if (errno)
return errno;
if (wlan_hdd_check_mon_concurrency())
if (wlan_hdd_is_mon_concurrency())
return -EINVAL;
if (policy_mgr_is_sta_mon_concurrency(hdd_ctx->psoc))
return -EINVAL;
qdf_mtrace(QDF_MODULE_ID_HDD, QDF_MODULE_ID_HDD,
@ -18431,7 +18434,8 @@ void hdd_select_cbmode(struct hdd_adapter *adapter, qdf_freq_t oper_freq,
wlan_reg_set_channel_params_for_freq(hdd_ctx->pdev, oper_freq,
sec_ch_freq, ch_params);
if (cds_get_conparam() == QDF_GLOBAL_MONITOR_MODE)
if (cds_get_conparam() == QDF_GLOBAL_MONITOR_MODE ||
policy_mgr_is_sta_mon_concurrency(hdd_ctx->psoc))
hdd_mon_select_cbmode(adapter, oper_freq, ch_params);
}
@ -20650,6 +20654,9 @@ static int __wlan_hdd_cfg80211_connect(struct wiphy *wiphy,
if (0 != status)
return status;
if (policy_mgr_is_sta_mon_concurrency(hdd_ctx->psoc))
return -EINVAL;
if (req->bssid)
bssid = req->bssid;
else if (bssid_hint)

View file

@ -5130,6 +5130,13 @@ int wlan_hdd_cfg80211_start_bss(struct hdd_adapter *adapter,
hdd_enter();
ret = wlan_hdd_validate_context(hdd_ctx);
if (ret != 0)
return ret;
if (policy_mgr_is_sta_mon_concurrency(hdd_ctx->psoc))
return -EINVAL;
hdd_notify_teardown_tdls_links(hdd_ctx->psoc);
ucfg_mlme_get_sap_force_11n_for_11ac(hdd_ctx->psoc,

View file

@ -1428,6 +1428,7 @@ static void hdd_runtime_suspend_context_init(struct hdd_context *hdd_ctx)
qdf_runtime_lock_init(&ctx->dfs);
qdf_runtime_lock_init(&ctx->connect);
qdf_runtime_lock_init(&ctx->user);
qdf_runtime_lock_init(&ctx->monitor_mode);
ctx->is_user_wakelock_acquired = false;
@ -1447,6 +1448,7 @@ static void hdd_runtime_suspend_context_deinit(struct hdd_context *hdd_ctx)
if (ctx->is_user_wakelock_acquired)
qdf_runtime_pm_allow_suspend(&ctx->user);
qdf_runtime_lock_deinit(&ctx->monitor_mode);
qdf_runtime_lock_deinit(&ctx->user);
qdf_runtime_lock_deinit(&ctx->connect);
qdf_runtime_lock_deinit(&ctx->dfs);
@ -2742,7 +2744,8 @@ static int __hdd_mon_open(struct net_device *dev)
hdd_mon_mode_ether_setup(dev);
if (con_mode == QDF_GLOBAL_MONITOR_MODE) {
if (con_mode == QDF_GLOBAL_MONITOR_MODE ||
ucfg_mlme_is_sta_mon_conc_supported(hdd_ctx->psoc)) {
ret = hdd_trigger_psoc_idle_restart(hdd_ctx);
if (ret) {
hdd_err("Failed to start WLAN modules return");
@ -2750,7 +2753,8 @@ static int __hdd_mon_open(struct net_device *dev)
}
hdd_err("hdd_wlan_start_modules() successful !");
if (!test_bit(SME_SESSION_OPENED, &adapter->event_flags)) {
if ((!test_bit(SME_SESSION_OPENED, &adapter->event_flags)) ||
(policy_mgr_is_sta_mon_concurrency(hdd_ctx->psoc))) {
ret = hdd_start_adapter(adapter);
if (ret) {
hdd_err("Failed to start adapter :%d",
@ -2763,6 +2767,15 @@ static int __hdd_mon_open(struct net_device *dev)
set_bit(DEVICE_IFACE_OPENED, &adapter->event_flags);
}
if (con_mode != QDF_GLOBAL_MONITOR_MODE &&
ucfg_mlme_is_sta_mon_conc_supported(hdd_ctx->psoc)) {
hdd_info("Acquire wakelock for STA + monitor mode");
qdf_wake_lock_acquire(&hdd_ctx->monitor_mode_wakelock,
WIFI_POWER_EVENT_WAKELOCK_MONITOR_MODE);
qdf_runtime_pm_prevent_suspend(
&hdd_ctx->runtime_context.monitor_mode);
}
ret = hdd_set_mon_rx_cb(dev);
if (!ret)
@ -4358,12 +4371,15 @@ static int __hdd_stop(struct net_device *dev)
if (adapter->device_mode == QDF_STA_MODE) {
hdd_lpass_notify_stop(hdd_ctx);
if (ucfg_pkt_capture_get_mode(hdd_ctx->psoc))
if (ucfg_pkt_capture_get_mode(hdd_ctx->psoc) !=
PACKET_CAPTURE_MODE_DISABLE)
hdd_close_monitor_interface(hdd_ctx);
}
if (wlan_hdd_is_session_type_monitor(adapter->device_mode) &&
adapter->vdev) {
adapter->vdev &&
ucfg_pkt_capture_get_mode(hdd_ctx->psoc) !=
PACKET_CAPTURE_MODE_DISABLE) {
ucfg_pkt_capture_deregister_callbacks(adapter->vdev);
hdd_objmgr_put_vdev(adapter->vdev);
adapter->vdev = NULL;
@ -5044,16 +5060,21 @@ static const struct net_device_ops wlan_mon_drv_ops = {
.ndo_get_stats = hdd_get_stats,
};
#ifdef WLAN_FEATURE_TSF_PTP
/**
* hdd_set_station_ops() - update net_device ops for monitor mode
* hdd_set_mon_ops() - update net_device ops for monitor mode
* @dev: Handle to struct net_device to be updated.
* Return: None
*/
static void hdd_set_mon_ops(struct net_device *dev)
{
dev->netdev_ops = &wlan_mon_drv_ops;
}
#ifdef WLAN_FEATURE_TSF_PTP
void hdd_set_station_ops(struct net_device *dev)
{
if (cds_get_conparam() == QDF_GLOBAL_MONITOR_MODE) {
dev->netdev_ops = &wlan_mon_drv_ops;
hdd_set_mon_ops(dev);
} else {
dev->netdev_ops = &wlan_drv_ops;
dev->ethtool_ops = &wlan_ethtool_ops;
@ -5063,7 +5084,7 @@ void hdd_set_station_ops(struct net_device *dev)
void hdd_set_station_ops(struct net_device *dev)
{
if (cds_get_conparam() == QDF_GLOBAL_MONITOR_MODE)
dev->netdev_ops = &wlan_mon_drv_ops;
hdd_set_mon_ops(dev);
else
dev->netdev_ops = &wlan_drv_ops;
}
@ -5082,6 +5103,9 @@ void hdd_set_station_ops(struct net_device *dev)
dev->netdev_ops = &wlan_drv_ops;
}
#endif
static void hdd_set_mon_ops(struct net_device *dev)
{
}
#endif
#ifdef WLAN_FEATURE_PKT_CAPTURE
@ -5177,10 +5201,15 @@ hdd_alloc_station_adapter(struct hdd_context *hdd_ctx, tSirMacAddr mac_addr,
qdf_mem_copy(adapter->mac_addr.bytes, mac_addr, sizeof(tSirMacAddr));
dev->watchdog_timeo = HDD_TX_TIMEOUT;
if (wlan_hdd_is_session_type_monitor(session_type))
hdd_set_pktcapture_ops(adapter->dev);
else
if (wlan_hdd_is_session_type_monitor(session_type)) {
if (ucfg_pkt_capture_get_mode(hdd_ctx->psoc) !=
PACKET_CAPTURE_MODE_DISABLE)
hdd_set_pktcapture_ops(adapter->dev);
if (ucfg_mlme_is_sta_mon_conc_supported(hdd_ctx->psoc))
hdd_set_mon_ops(adapter->dev);
} else {
hdd_set_station_ops(adapter->dev);
}
hdd_dev_setup_destructor(dev);
dev->ieee80211_ptr = &adapter->wdev;
@ -6970,7 +6999,8 @@ QDF_STATUS hdd_stop_adapter(struct hdd_context *hdd_ctx,
hdd_destroy_adapter_sysfs_files(adapter);
if (adapter->device_mode == QDF_STA_MODE &&
ucfg_pkt_capture_get_mode(hdd_ctx->psoc))
ucfg_pkt_capture_get_mode(hdd_ctx->psoc) !=
PACKET_CAPTURE_MODE_DISABLE)
hdd_del_monitor_interface(hdd_ctx);
if (adapter->vdev_id != WLAN_UMAC_VDEV_ID_MAX)
@ -7101,14 +7131,28 @@ QDF_STATUS hdd_stop_adapter(struct hdd_context *hdd_ctx,
case QDF_MONITOR_MODE:
if (wlan_hdd_is_session_type_monitor(QDF_MONITOR_MODE) &&
adapter->vdev) {
adapter->vdev &&
ucfg_pkt_capture_get_mode(hdd_ctx->psoc) !=
PACKET_CAPTURE_MODE_DISABLE) {
ucfg_pkt_capture_deregister_callbacks(adapter->vdev);
hdd_objmgr_put_vdev(adapter->vdev);
adapter->vdev = NULL;
}
if (wlan_hdd_is_session_type_monitor(QDF_MONITOR_MODE) &&
ucfg_mlme_is_sta_mon_conc_supported(hdd_ctx->psoc)) {
hdd_info("Release wakelock for STA + monitor mode!");
qdf_runtime_pm_allow_suspend(
&hdd_ctx->runtime_context.monitor_mode);
qdf_wake_lock_release(&hdd_ctx->monitor_mode_wakelock,
WIFI_POWER_EVENT_WAKELOCK_MONITOR_MODE);
}
wlan_hdd_scan_abort(adapter);
hdd_deregister_hl_netdev_fc_timer(adapter);
hdd_deregister_tx_flow_control(adapter);
status = hdd_disable_monitor_mode();
if (QDF_IS_STATUS_ERROR(status))
hdd_err_rl("datapath reset failed for montior mode");
hdd_set_idle_ps_config(hdd_ctx, true);
status = hdd_monitor_mode_vdev_status(adapter);
if (QDF_IS_STATUS_ERROR(status))
hdd_err_rl("stop failed montior mode");
@ -8066,7 +8110,8 @@ int wlan_hdd_set_mon_chan(struct hdd_adapter *adapter, qdf_freq_t freq,
enum phy_ch_width ch_width;
int ret;
if (hdd_get_conparam() != QDF_GLOBAL_MONITOR_MODE) {
if ((hdd_get_conparam() != QDF_GLOBAL_MONITOR_MODE) &&
(!policy_mgr_is_sta_mon_concurrency(hdd_ctx->psoc))) {
hdd_err("Not supported, device is not in monitor mode");
return -EINVAL;
}
@ -8322,7 +8367,8 @@ QDF_STATUS hdd_start_all_adapters(struct hdd_context *hdd_ctx)
case QDF_MONITOR_MODE:
if (wlan_hdd_is_session_type_monitor(
QDF_MONITOR_MODE) &&
ucfg_pkt_capture_get_mode(hdd_ctx->psoc)) {
ucfg_pkt_capture_get_mode(hdd_ctx->psoc) !=
PACKET_CAPTURE_MODE_DISABLE) {
vdev = hdd_objmgr_get_vdev(adapter);
if (vdev) {
ucfg_pkt_capture_register_callbacks(
@ -18202,40 +18248,7 @@ void hdd_hidden_ssid_enable_roaming(hdd_handle_t hdd_handle, uint8_t vdev_id)
}
#ifdef WLAN_FEATURE_PKT_CAPTURE
/**
* wlan_hdd_is_session_type_monitor() - check if session type is MONITOR
* @session_type: session type
*
* Return: True - if session type for adapter is monitor, else False
*
*/
bool wlan_hdd_is_session_type_monitor(uint8_t session_type)
{
struct hdd_context *hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
if (!hdd_ctx) {
cds_err("HDD context is NULL");
return false;
}
if (ucfg_pkt_capture_get_mode(hdd_ctx->psoc) &&
cds_get_conparam() != QDF_GLOBAL_MONITOR_MODE &&
session_type == QDF_MONITOR_MODE)
return true;
else
return false;
}
/**
* wlan_hdd_check_mon_concurrency() - check if MONITOR and STA concurrency
* is UP when packet capture mode is enabled.
* @void
*
* Return: True - if STA and monitor concurrency is there, else False
*
*/
bool wlan_hdd_check_mon_concurrency(void)
bool wlan_hdd_is_mon_concurrency(void)
{
struct hdd_context *hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
@ -18244,7 +18257,8 @@ bool wlan_hdd_check_mon_concurrency(void)
return -EINVAL;
}
if (ucfg_pkt_capture_get_mode(hdd_ctx->psoc)) {
if (ucfg_pkt_capture_get_mode(hdd_ctx->psoc) !=
PACKET_CAPTURE_MODE_DISABLE) {
if (policy_mgr_get_concurrency_mode(hdd_ctx->psoc) ==
(QDF_STA_MASK | QDF_MONITOR_MASK)) {
hdd_err("STA + MON mode is UP");
@ -18254,16 +18268,6 @@ bool wlan_hdd_check_mon_concurrency(void)
return false;
}
/**
* wlan_hdd_del_monitor() - delete monitor interface
* @hdd_ctx: pointer to hdd context
* @adapter: adapter to be deleted
* @rtnl_held: rtnl lock held
*
* This function is invoked to delete monitor interface.
*
* Return: None
*/
void wlan_hdd_del_monitor(struct hdd_context *hdd_ctx,
struct hdd_adapter *adapter, bool rtnl_held)
{
@ -18280,17 +18284,46 @@ void wlan_hdd_del_monitor(struct hdd_context *hdd_ctx,
hdd_open_p2p_interface(hdd_ctx);
}
/**
* wlan_hdd_add_monitor_check() - check for monitor intf and add if needed
* @hdd_ctx: pointer to hdd context
* @adapter: output pointer to hold created monitor adapter
* @name: name of the interface
* @rtnl_held: True if RTNL lock is held
* @name_assign_type: the name of assign type of the netdev
*
* Return: 0 - on success
* err code - on failure
*/
void
wlan_hdd_del_p2p_interface(struct hdd_context *hdd_ctx)
{
struct hdd_adapter *adapter = NULL, *next_adapter = NULL;
struct osif_vdev_sync *vdev_sync;
hdd_for_each_adapter_dev_held_safe(hdd_ctx, adapter, next_adapter) {
if (adapter->device_mode == QDF_P2P_CLIENT_MODE ||
adapter->device_mode == QDF_P2P_DEVICE_MODE ||
adapter->device_mode == QDF_P2P_GO_MODE) {
vdev_sync = osif_vdev_sync_unregister(adapter->dev);
if (vdev_sync)
osif_vdev_sync_wait_for_ops(vdev_sync);
hdd_clean_up_interface(hdd_ctx, adapter);
if (vdev_sync)
osif_vdev_sync_destroy(vdev_sync);
}
}
}
#endif /* WLAN_FEATURE_PKT_CAPTURE */
bool wlan_hdd_is_session_type_monitor(uint8_t session_type)
{
struct hdd_context *hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
if (!hdd_ctx) {
cds_err("HDD context is NULL");
return false;
}
if (cds_get_conparam() != QDF_GLOBAL_MONITOR_MODE &&
session_type == QDF_MONITOR_MODE)
return true;
else
return false;
}
int
wlan_hdd_add_monitor_check(struct hdd_context *hdd_ctx,
struct hdd_adapter **adapter,
@ -18299,86 +18332,50 @@ wlan_hdd_add_monitor_check(struct hdd_context *hdd_ctx,
{
struct hdd_adapter *sta_adapter;
struct hdd_adapter *mon_adapter;
uint32_t mode;
int errno;
uint8_t num_open_session = 0;
QDF_STATUS status;
/* if no interface is up do not add monitor mode */
if (!hdd_is_any_interface_open(hdd_ctx))
return -EINVAL;
/*
* If add interface request is for monitor mode, then it can run in
* parallel with only one station interface.
* If there is no existing station interface return error
*/
if (QDF_STATUS_SUCCESS != policy_mgr_mode_specific_num_open_sessions(
hdd_ctx->psoc,
QDF_MONITOR_MODE,
&num_open_session))
return -EINVAL;
if (num_open_session) {
hdd_err("monitor mode already exists, only one is possible");
return -EBUSY;
}
/* Ensure there is only one station interface */
if (QDF_STATUS_SUCCESS != policy_mgr_mode_specific_num_open_sessions(
hdd_ctx->psoc,
QDF_STA_MODE,
&num_open_session))
return -EINVAL;
if (num_open_session != 1) {
hdd_err("cannot add monitor mode, due to %u sta interfaces",
num_open_session);
return -EINVAL;
}
sta_adapter = hdd_get_adapter(hdd_ctx, QDF_STA_MODE);
if (!sta_adapter) {
hdd_err("No station adapter");
return -EINVAL;
}
if (QDF_STATUS_SUCCESS != policy_mgr_mode_specific_num_open_sessions(
hdd_ctx->psoc,
QDF_SAP_MODE,
&num_open_session))
status = policy_mgr_check_mon_concurrency(hdd_ctx->psoc);
if (QDF_IS_STATUS_ERROR(status))
return -EINVAL;
if (num_open_session) {
hdd_err("cannot add monitor mode, due to SAP concurrency");
if (hdd_is_connection_in_progress(NULL, NULL)) {
hdd_err("cannot add monitor mode, Connection in progress");
return -EINVAL;
}
/* delete p2p interface */
for (mode = QDF_P2P_CLIENT_MODE; mode <= QDF_P2P_DEVICE_MODE; mode++) {
struct hdd_adapter *adapter;
num_open_session = policy_mgr_mode_specific_connection_count(
hdd_ctx->psoc,
PM_STA_MODE,
NULL);
if (mode == QDF_FTM_MODE ||
mode == QDF_MONITOR_MODE)
continue;
adapter = hdd_get_adapter(hdd_ctx, mode);
if (adapter) {
struct osif_vdev_sync *vdev_sync;
vdev_sync = osif_vdev_sync_unregister(adapter->dev);
if (vdev_sync)
osif_vdev_sync_wait_for_ops(vdev_sync);
wlan_hdd_release_intf_addr(hdd_ctx,
adapter->mac_addr.bytes);
hdd_stop_adapter(hdd_ctx, adapter);
hdd_deinit_adapter(hdd_ctx, adapter, true);
hdd_close_adapter(hdd_ctx, adapter, rtnl_held);
if (vdev_sync)
osif_vdev_sync_destroy(vdev_sync);
if (num_open_session == 1) {
hdd_ctx->disconnect_for_sta_mon_conc = true;
/* Try disconnecting if already in connected state */
errno = wlan_hdd_try_disconnect(sta_adapter,
REASON_UNSPEC_FAILURE);
if (errno > 0) {
hdd_err("Failed to disconnect the existing connection");
return -EALREADY;
}
}
if (ucfg_pkt_capture_get_mode(hdd_ctx->psoc) !=
PACKET_CAPTURE_MODE_DISABLE)
wlan_hdd_del_p2p_interface(hdd_ctx);
mon_adapter = hdd_open_adapter(hdd_ctx, QDF_MONITOR_MODE, name,
wlan_hdd_get_intf_addr(
hdd_ctx,
@ -18386,15 +18383,18 @@ wlan_hdd_add_monitor_check(struct hdd_context *hdd_ctx,
name_assign_type, rtnl_held);
if (!mon_adapter) {
hdd_err("hdd_open_adapter failed");
hdd_open_p2p_interface(hdd_ctx);
if (ucfg_pkt_capture_get_mode(hdd_ctx->psoc) !=
PACKET_CAPTURE_MODE_DISABLE)
hdd_open_p2p_interface(hdd_ctx);
return -EINVAL;
}
if (mon_adapter)
hdd_set_idle_ps_config(hdd_ctx, false);
*adapter = mon_adapter;
return 0;
}
#endif /* WLAN_FEATURE_PKT_CAPTURE */
#ifdef FEATURE_MONITOR_MODE_SUPPORT

View file

@ -173,6 +173,9 @@ static int __wlan_hdd_cfg80211_remain_on_channel(struct wiphy *wiphy,
return -EINVAL;
}
if (policy_mgr_is_sta_mon_concurrency(hdd_ctx->psoc))
return -EINVAL;
if (wlan_hdd_validate_vdev_id(adapter->vdev_id))
return -EINVAL;
@ -711,7 +714,10 @@ struct wireless_dev *__wlan_hdd_add_virtual_intf(struct wiphy *wiphy,
if (ret)
return ERR_PTR(ret);
if (wlan_hdd_check_mon_concurrency())
if (policy_mgr_is_sta_mon_concurrency(hdd_ctx->psoc))
return ERR_PTR(-EINVAL);
if (wlan_hdd_is_mon_concurrency())
return ERR_PTR(-EINVAL);
qdf_mtrace(QDF_MODULE_ID_HDD, QDF_MODULE_ID_HDD,
@ -727,6 +733,7 @@ struct wireless_dev *__wlan_hdd_add_virtual_intf(struct wiphy *wiphy,
case QDF_P2P_GO_MODE:
case QDF_P2P_CLIENT_MODE:
case QDF_STA_MODE:
case QDF_MONITOR_MODE:
break;
default:
mode = QDF_STA_MODE;
@ -750,16 +757,23 @@ struct wireless_dev *__wlan_hdd_add_virtual_intf(struct wiphy *wiphy,
}
adapter = NULL;
if ((ucfg_pkt_capture_get_mode(hdd_ctx->psoc)) &&
(type == NL80211_IFTYPE_MONITOR)) {
ret = wlan_hdd_add_monitor_check(hdd_ctx, &adapter, name,
true, name_assign_type);
if (ret)
return ERR_PTR(-EINVAL);
if (type == NL80211_IFTYPE_MONITOR) {
if (ucfg_mlme_is_sta_mon_conc_supported(hdd_ctx->psoc) ||
ucfg_pkt_capture_get_mode(hdd_ctx->psoc) !=
PACKET_CAPTURE_MODE_DISABLE) {
ret = wlan_hdd_add_monitor_check(hdd_ctx,
&adapter, name, true,
name_assign_type);
if (ret)
return ERR_PTR(-EINVAL);
if (adapter) {
hdd_exit();
return adapter->dev->ieee80211_ptr;
if (adapter) {
hdd_exit();
return adapter->dev->ieee80211_ptr;
}
} else {
hdd_err("Adding monitor interface not supported");
return ERR_PTR(-EINVAL);
}
}
@ -883,8 +897,8 @@ struct wireless_dev *wlan_hdd_add_virtual_intf(struct wiphy *wiphy,
}
#endif
static void hdd_clean_up_sap_interface(struct hdd_context *hdd_ctx,
struct hdd_adapter *adapter)
static void hdd_clean_up_interface(struct hdd_context *hdd_ctx,
struct hdd_adapter *adapter)
{
wlan_hdd_release_intf_addr(hdd_ctx,
adapter->mac_addr.bytes);
@ -931,13 +945,15 @@ int __wlan_hdd_del_virtual_intf(struct wiphy *wiphy, struct wireless_dev *wdev)
if (adapter->device_mode == QDF_SAP_MODE &&
wlan_sap_is_pre_cac_active(hdd_ctx->mac_handle)) {
hdd_clean_up_sap_interface(hdd_ctx, adapter);
hdd_clean_up_interface(hdd_ctx, adapter);
hdd_clean_up_pre_cac_interface(hdd_ctx);
} else if (wlan_hdd_is_session_type_monitor(
adapter->device_mode)) {
adapter->device_mode) &&
ucfg_pkt_capture_get_mode(hdd_ctx->psoc) !=
PACKET_CAPTURE_MODE_DISABLE) {
wlan_hdd_del_monitor(hdd_ctx, adapter, TRUE);
} else {
hdd_clean_up_sap_interface(hdd_ctx, adapter);
hdd_clean_up_interface(hdd_ctx, adapter);
}
if (!hdd_is_any_interface_open(hdd_ctx))

View file

@ -1487,7 +1487,8 @@ QDF_STATUS hdd_wlan_shutdown(void)
dp_txrx_resume(cds_get_context(QDF_MODULE_ID_SOC));
if (ucfg_pkt_capture_get_mode(hdd_ctx->psoc)) {
if (ucfg_pkt_capture_get_mode(hdd_ctx->psoc) !=
PACKET_CAPTURE_MODE_DISABLE) {
adapter = hdd_get_adapter(hdd_ctx, QDF_MONITOR_MODE);
if (adapter) {
vdev = hdd_objmgr_get_vdev(adapter);
@ -1903,7 +1904,8 @@ static int __wlan_hdd_cfg80211_resume_wlan(struct wiphy *wiphy)
if (hdd_ctx->enable_dp_rx_threads)
dp_txrx_resume(cds_get_context(QDF_MODULE_ID_SOC));
if (ucfg_pkt_capture_get_mode(hdd_ctx->psoc)) {
if (ucfg_pkt_capture_get_mode(hdd_ctx->psoc) !=
PACKET_CAPTURE_MODE_DISABLE) {
adapter = hdd_get_adapter(hdd_ctx, QDF_MONITOR_MODE);
if (adapter) {
vdev = hdd_objmgr_get_vdev(adapter);
@ -2147,7 +2149,8 @@ static int __wlan_hdd_cfg80211_suspend_wlan(struct wiphy *wiphy,
goto resume_ol_rx;
}
if (ucfg_pkt_capture_get_mode(hdd_ctx->psoc)) {
if (ucfg_pkt_capture_get_mode(hdd_ctx->psoc) !=
PACKET_CAPTURE_MODE_DISABLE) {
adapter = hdd_get_adapter(hdd_ctx, QDF_MONITOR_MODE);
if (adapter) {
vdev = hdd_objmgr_get_vdev(adapter);
@ -2182,7 +2185,8 @@ resume_dp_thread:
dp_txrx_resume(cds_get_context(QDF_MODULE_ID_SOC));
/* Resume packet capture MON thread */
if (ucfg_pkt_capture_get_mode(hdd_ctx->psoc)) {
if (ucfg_pkt_capture_get_mode(hdd_ctx->psoc) !=
PACKET_CAPTURE_MODE_DISABLE) {
adapter = hdd_get_adapter(hdd_ctx, QDF_MONITOR_MODE);
if (adapter) {
vdev = hdd_objmgr_get_vdev(adapter);

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2017-2019 The Linux Foundation. All rights reserved.
* Copyright (c) 2017-2020 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
@ -25,15 +25,8 @@
#include <cds_utils.h>
#include "wlan_hdd_rx_monitor.h"
#include "ol_txrx.h"
#include "cdp_txrx_mon.h"
/**
* hdd_rx_monitor_callback(): Callback function for receive monitor mode
* @vdev: Handle to vdev object
* @mpdu: pointer to mpdu to be delivered to os
* @rx_status: receive status
*
* Returns: None
*/
void hdd_rx_monitor_callback(ol_osif_vdev_handle context,
qdf_nbuf_t rxbuf,
void *rx_status)
@ -95,29 +88,12 @@ void hdd_rx_monitor_callback(ol_osif_vdev_handle context,
}
}
/**
* hdd_monitor_set_rx_monitor_cb(): Set rx monitor mode callback function
* @txrx: pointer to txrx ops
* @rx_monitor_cb: pointer to callback function
*
* Returns: None
*/
void hdd_monitor_set_rx_monitor_cb(struct ol_txrx_ops *txrx,
ol_txrx_rx_mon_fp rx_monitor_cb)
{
txrx->rx.mon = rx_monitor_cb;
}
/**
* hdd_enable_monitor_mode() - Enable monitor mode
* @dev: Pointer to the net_device structure
*
* This function invokes cdp interface API to enable
* monitor mode configuration on the hardware. In this
* case sends HTT messages to FW to setup hardware rings
*
* Return: 0 for success; non-zero for failure
*/
int hdd_enable_monitor_mode(struct net_device *dev)
{
void *soc = cds_get_context(QDF_MODULE_ID_SOC);
@ -131,3 +107,10 @@ int hdd_enable_monitor_mode(struct net_device *dev)
return cdp_set_monitor_mode(soc, vdev_id, false);
}
int hdd_disable_monitor_mode(void)
{
void *soc = cds_get_context(QDF_MODULE_ID_SOC);
return cdp_reset_monitor_mode(soc, OL_TXRX_PDEV_ID, false);
}

View file

@ -23,14 +23,49 @@ struct ol_txrx_ops;
#if defined(QCA_WIFI_QCA6290) || defined(QCA_WIFI_QCA6390) || \
defined(QCA_WIFI_QCA6490) || defined(QCA_WIFI_QCA6750)
/**
* hdd_rx_monitor_callback(): Callback function for receive monitor mode
* @vdev: Handle to vdev object
* @mpdu: pointer to mpdu to be delivered to os
* @rx_status: receive status
*
* Returns: None
*/
void hdd_monitor_set_rx_monitor_cb(struct ol_txrx_ops *txrx,
ol_txrx_rx_mon_fp rx_monitor_cb);
/**
* hdd_monitor_set_rx_monitor_cb(): Set rx monitor mode callback function
* @txrx: pointer to txrx ops
* @rx_monitor_cb: pointer to callback function
*
* Returns: None
*/
void hdd_rx_monitor_callback(ol_osif_vdev_handle vdev,
qdf_nbuf_t mpdu,
void *rx_status);
/**
* hdd_enable_monitor_mode() - Enable monitor mode
* @dev: Pointer to the net_device structure
*
* This function invokes cdp interface API to enable
* monitor mode configuration on the hardware. In this
* case sends HTT messages to FW to setup hardware rings
*
* Return: 0 for success; non-zero for failure
*/
int hdd_enable_monitor_mode(struct net_device *dev);
/**
* hdd_disable_monitor_mode() - Disable monitor mode
*
* This function invokes cdp interface API to disable
* monitor mode configuration on the hardware. In this
* case sends HTT messages to FW to reset hardware rings
*
* Return: 0 for success; non-zero for failure
*/
int hdd_disable_monitor_mode(void);
#else
static inline void hdd_monitor_set_rx_monitor_cb(struct ol_txrx_ops *txrx,
ol_txrx_rx_mon_fp rx_monitor_cb){ }
@ -41,6 +76,12 @@ static inline int hdd_enable_monitor_mode(struct net_device *dev)
{
return 0;
}
static inline int hdd_disable_monitor_mode(void)
{
return 0;
}
#endif /* CONFIG_LITHIUM */
#endif /* __WLAN_HDD_RX_MONITOR_H */

View file

@ -1210,7 +1210,7 @@ static QDF_STATUS pe_handle_mgmt_frame(struct wlan_objmgr_psoc *psoc,
int ret;
/* skip offload packets */
if (ucfg_pkt_capture_get_mode(psoc) &&
if ((ucfg_pkt_capture_get_mode(psoc) != PACKET_CAPTURE_MODE_DISABLE) &&
mgmt_rx_params->status & WMI_RX_OFFLOAD_MON_MODE) {
qdf_nbuf_free(buf);
return QDF_STATUS_SUCCESS;

View file

@ -6842,7 +6842,8 @@ int wma_rx_service_ready_ext_event(void *handle, uint8_t *event,
wma_update_num_peers_tids(wma_handle, wlan_res_cfg);
}
if (ucfg_pkt_capture_get_mode(wma_handle->psoc) &&
if ((ucfg_pkt_capture_get_mode(wma_handle->psoc) !=
PACKET_CAPTURE_MODE_DISABLE) &&
wmi_service_enabled(wmi_handle,
wmi_service_packet_capture_support))
wlan_res_cfg->pktcapture_support = true;