Merge commit 'bf95f89d58' into wlan-cld3.driver.lnx.2.0

Change-Id: I0923b31931ebf99ef4d3a717bba279e8bade0dfb
This commit is contained in:
Linux Build Service Account 2018-12-04 17:20:13 +05:30
commit ee4ea408f6
84 changed files with 45463 additions and 473 deletions

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,302 @@
/*
* Copyright (c) 2012-2018 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.
*/
#ifndef __CFG_POLICY_MGR
#define __CFG_POLICY_MGR
#include "qdf_types.h"
/*
* <ini>
* gWlanMccToSccSwitchMode - Control SAP channel.
* @Min: 0
* @Max: 5
* @Default: 0
*
* This ini is used to override SAP channel.
* If gWlanMccToSccSwitchMode = 0: disabled.
* If gWlanMccToSccSwitchMode = 1: Enable switch.
* If gWlainMccToSccSwitchMode = 2: Force switch with SAP restart.
* If gWlainMccToSccSwitchMode = 3: Force switch without SAP restart.
* If gWlainMccToSccSwitchMode = 4: Switch using
* fav channel(s)without SAP restart.
* If gWlainMccToSccSwitchMode = 5: Force switch without SAP restart.MCC allowed
* in exceptional cases.
* If gWlainMccToSccSwitchMode = 6: Force Switch without SAP restart only in
user preffered band.
* Related: None.
*
* Supported Feature: Concurrency
*
* Usage: Internal/External
*
* </ini>
*/
#define CFG_MCC_TO_SCC_SWITCH CFG_INI_UINT(\
"gWlanMccToSccSwitchMode", \
QDF_MCC_TO_SCC_SWITCH_DISABLE, \
QDF_MCC_TO_SCC_SWITCH_MAX - 1, \
QDF_MCC_TO_SCC_SWITCH_DISABLE, \
CFG_VALUE_OR_DEFAULT, \
"Provides MCC to SCC switch mode")
/*
* <ini>
* gSystemPref - Configure wlan system preference for PCL.
* @Min: 0
* @Max: 2
* @Default: 0
*
* This ini is used to configure wlan system preference option to help
* policy manager decide on Preferred Channel List for a new connection.
* For possible values refer to enum hdd_conc_priority_mode
*
* Related: None.
*
* Supported Feature: DBS
*
* Usage: Internal/External
*
* </ini>
*/
#define CFG_CONC_SYS_PREF CFG_INI_UINT(\
"gSystemPref", 0, 2, 0, \
CFG_VALUE_OR_DEFAULT, \
"System preference to predict PCL")
/*
* <ini>
* gMaxConcurrentActiveSessions - Maximum number of concurrent connections.
* @Min: 1
* @Max: 4
* @Default: 3
*
* This ini is used to configure the maximum number of concurrent connections.
*
* Related: None.
*
* Supported Feature: Concurrency
*
* Usage: Internal/External
*
* </ini>
*/
#define CFG_MAX_CONC_CXNS CFG_INI_UINT(\
"gMaxConcurrentActiveSessions", \
1, 4, 3, \
CFG_VALUE_OR_DEFAULT, \
"Config max num allowed connections")
/*
* <ini>
* channel_select_logic_conc - Set channel selection logic
* for different concurrency combinations to DBS or inter band
* MCC. Default is DBS for STA+STA and STA+P2P.
* @Min: 0x00000000
* @Max: 0xFFFFFFFF
* @Default: 0x00000000
*
* 0 - inter-band MCC
* 1 - DBS
*
* BIT 0: STA+STA
* BIT 1: STA+P2P
* BIT 2-31: Reserved
*
* Supported Feature: STA+STA, STA+P2P
*
* Usage: External
*
* </ini>
*/
#define CFG_CHNL_SELECT_LOGIC_CONC CFG_INI_UINT(\
"channel_select_logic_conc",\
0x00000000, \
0xFFFFFFFF, \
0x00000003, \
CFG_VALUE_OR_DEFAULT, \
"Set channel selection policy for various concurrency")
/*
* <ini>
* dbs_selection_policy - Configure dbs selection policy.
* @Min: 0
* @Max: 3
* @Default: 0
*
* set band preference or Vdev preference.
* bit[0] = 0: 5G 2x2 preferred to select 2x2 5G + 1x1 2G DBS mode.
* bit[0] = 1: 2G 2x2 preferred to select 2x2 2G + 1x1 5G DBS mode.
* bit[1] = 1: vdev priority enabled. The INI "vdev_priority_list" will
* specify the vdev priority.
* bit[1] = 0: vdev priority disabled.
* This INI only take effect for Genoa dual DBS hw.
*
* Supported Feature: DBS
*
* Usage: Internal/External
*
* </ini>
*/
#define CFG_DBS_SELECTION_PLCY CFG_INI_UINT(\
"dbs_selection_policy", \
0, 3, 0, \
CFG_VALUE_OR_DEFAULT, \
"Configure dbs selection policy")
/*
* <ini>
* vdev_priority_list - Configure vdev priority list.
* @Min: 0
* @Max: 0x4444
* @Default: 0x4321
*
* @vdev_priority_list: vdev priority list
* bit[0-3]: pri_id (policy_mgr_pri_id) of highest priority
* bit[4-7]: pri_id (policy_mgr_pri_id) of second priority
* bit[8-11]: pri_id (policy_mgr_pri_id) of third priority
* bit[12-15]: pri_id (policy_mgr_pri_id) of fourth priority
* example: 0x4321 - CLI < GO < SAP < STA
* vdev priority id mapping:
* PM_STA_PRI_ID = 1,
* PM_SAP_PRI_ID = 2,
* PM_P2P_GO_PRI_ID = 3,
* PM_P2P_CLI_PRI_ID = 4,
* When the previous INI "dbs_selection_policy" bit[1]=1, which means
* the vdev 2x2 prioritization enabled. Then this INI will be used to
* specify the vdev type priority list. For example :
* dbs_selection_policy=0x2
* vdev_priority_list=0x4312
* means: default preference 2x2 band is 5G, vdev 2x2 prioritization enabled.
* And the priority list is CLI < GO < STA < SAP
*
* This INI only take effect for Genoa dual DBS hw.
*
* Supported Feature: DBS
*
* Usage: Internal/External
*
* </ini>
*/
#define CFG_VDEV_CUSTOM_PRIORITY_LIST CFG_INI_UINT(\
"vdev_priority_list", \
0, 0x4444, 0x4321, \
CFG_VALUE_OR_DEFAULT, \
"Configure vdev priority list")
/*
* <ini>
* gEnableCustomConcRule1 - Enable custom concurrency rule1.
* @Min: 0
* @Max: 1
* @Default: 0
*
* This ini is used to enable/disable custom concurrency rule1.
* If SAP comes up first and STA comes up later then SAP needs to follow STA's
* channel.
*
* Related: None.
*
* Supported Feature: Concurrency
*
* Usage: Internal/External
*
* </ini>
*/
#define CFG_ENABLE_CONC_RULE1 CFG_INI_UINT(\
"gEnableCustomConcRule1", \
0, 1, 0, \
CFG_VALUE_OR_DEFAULT, \
"Enable custom concurrency rule 1")
/*
* <ini>
* gEnableCustomConcRule2 - Enable custom concurrency rule2.
* @Min: 0
* @Max: 1
* @Default: 0
*
* This ini is used to enable/disable custom concurrency rule2.
* If P2PGO comes up first and STA comes up later then P2PGO need to follow
* STA's channel in 5Ghz. In following if condition we are just adding sanity
* check to make sure that by this time P2PGO's channel is same as STA's
* channel.
*
* Related: None.
*
* Supported Feature: Concurrency
*
* Usage: Internal/External
*
* </ini>
*/
#define CFG_ENABLE_CONC_RULE2 CFG_INI_UINT(\
"gEnableCustomConcRule2", \
0, 1, 0, \
CFG_VALUE_OR_DEFAULT, \
"Enable custom concurrency rule 2")
/*
* <ini>
* gEnableMCCAdaptiveScheduler - MCC Adaptive Scheduler feature.
* @Min: 0
* @Max: 1
* @Default: 1
*
* This ini is used to enable/disable MCC Adaptive Scheduler feature.
*
* Related: None.
*
* Supported Feature: Concurrency
*
* Usage: Internal/External
*
* </ini>
*/
#define CFG_ENABLE_MCC_ADATIVE_SCH_ENABLED_NAME CFG_INI_UINT(\
"gEnableMCCAdaptiveScheduler", \
0, 1, 1, \
CFG_VALUE_OR_DEFAULT, \
"Enable/Disable MCC Adaptive Scheduler")
/*
* <ini>
* gEnableStaConnectionIn5Ghz - To enable/disable STA connection in 5G
* @Min: 0
* @Max: 1
* @Default: 1
*
* This ini is used to enable/disable STA connection in 5G band
*
* Related: STA
*
* Supported Feature: Concurrency
*
* Usage: Internal/External
*
* </ini>
*/
#define CFG_ENABLE_STA_CONNECTION_IN_5GHZ CFG_INI_UINT(\
"gEnableStaConnectionIn5Ghz", \
0, 1, 1, \
CFG_VALUE_OR_DEFAULT, \
"Enable/Disable STA connection in 5G")
#define CFG_POLICY_MGR_ALL \
CFG(CFG_MCC_TO_SCC_SWITCH) \
CFG(CFG_CONC_SYS_PREF) \
CFG(CFG_MAX_CONC_CXNS) \
CFG(CFG_DBS_SELECTION_PLCY) \
CFG(CFG_VDEV_CUSTOM_PRIORITY_LIST) \
CFG(CFG_CHNL_SELECT_LOGIC_CONC) \
CFG(CFG_ENABLE_CONC_RULE1) \
CFG(CFG_ENABLE_CONC_RULE2) \
CFG(CFG_ENABLE_MCC_ADATIVE_SCH_ENABLED_NAME)\
CFG(CFG_ENABLE_STA_CONNECTION_IN_5GHZ)
#endif

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,181 @@
/*
* Copyright (c) 2018 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.
*/
#ifndef __WLAN_POLICY_MGR_UCFG
#define __WLAN_POLICY_MGR_UCFG
#include "wlan_objmgr_psoc_obj.h"
#include "wlan_objmgr_global_obj.h"
#include "qdf_status.h"
/**
* ucfg_policy_mgr_psoc_open() - This API sets CFGs to policy manager context
*
* This API pulls policy manager's context from PSOC and initialize the CFG
* structure of policy manager.
*
* Return: QDF_STATUS_SUCCESS up on success and any other status for failure.
*/
QDF_STATUS ucfg_policy_mgr_psoc_open(struct wlan_objmgr_psoc *psoc);
/**
* ucfg_policy_mgr_psoc_close() - This API resets CFGs for policy manager ctx
*
* This API pulls policy manager's context from PSOC and resets the CFG
* structure of policy manager.
*
* Return: QDF_STATUS_SUCCESS up on success and any other status for failure.
*/
void ucfg_policy_mgr_psoc_close(struct wlan_objmgr_psoc *psoc);
#ifdef FEATURE_WLAN_MCC_TO_SCC_SWITCH
/**
* ucfg_policy_mgr_get_mcc_scc_switch() - To mcc to scc switch setting from INI
* @psoc: pointer to psoc
* @mcc_scc_switch: value to be filled
*
* This API pulls mcc to scc switch setting which is given as part of INI and
* stored in policy manager's CFGs.
*
* Return: QDF_STATUS_SUCCESS up on success and any other status for failure.
*/
QDF_STATUS ucfg_policy_mgr_get_mcc_scc_switch(struct wlan_objmgr_psoc *psoc,
uint8_t *mcc_scc_switch);
#else
static inline
QDF_STATUS ucfg_policy_mgr_get_mcc_scc_switch(struct wlan_objmgr_psoc *psoc,
uint8_t *mcc_scc_switch)
{
return QDF_STATUS_SUCCESS;
}
#endif //FEATURE_WLAN_MCC_TO_SCC_SWITCH
/**
* ucfg_policy_mgr_get_sys_pref() - to get system preference
* @psoc: pointer to psoc
* @sys_pref: value to be filled
*
* This API pulls the system preference for policy manager to provide
* PCL
*
* Return: QDF_STATUS_SUCCESS up on success and any other status for failure.
*/
QDF_STATUS ucfg_policy_mgr_get_sys_pref(struct wlan_objmgr_psoc *psoc,
uint8_t *sys_pref);
/**
* ucfg_policy_mgr_set_sys_pref() - to set system preference
* @psoc: pointer to psoc
* @sys_pref: value to be applied as new INI setting
*
* This API is meant to override original INI setting for system pref
* with new value which is used by policy manager to provide PCL
*
* Return: QDF_STATUS_SUCCESS up on success and any other status for failure.
*/
QDF_STATUS ucfg_policy_mgr_set_sys_pref(struct wlan_objmgr_psoc *psoc,
uint8_t sys_pref);
/**
* ucfg_policy_mgr_get_max_conc_cxns() - to get max num of conc connections
* @psoc: pointer to psoc
* @max_conc_cxns: value to be filled
*
* This API pulls max number of active connections which can be allowed
*
* Return: QDF_STATUS_SUCCESS up on success and any other status for failure.
*/
QDF_STATUS ucfg_policy_mgr_get_max_conc_cxns(struct wlan_objmgr_psoc *psoc,
uint8_t *max_conc_cxns);
/**
* ucfg_policy_mgr_get_conc_rule1() - to find out if conc rule1 is enabled
* @psoc: pointer to psoc
* @conc_rule1: value to be filled
*
* This API is used to find out if conc rule-1 is enabled by user
*
* Return: QDF_STATUS_SUCCESS up on success and any other status for failure.
*/
QDF_STATUS ucfg_policy_mgr_get_conc_rule1(struct wlan_objmgr_psoc *psoc,
uint8_t *conc_rule1);
/**
* ucfg_policy_mgr_get_conc_rule2() - to find out if conc rule2 is enabled
* @psoc: pointer to psoc
* @conc_rule2: value to be filled
*
* This API is used to find out if conc rule-2 is enabled by user
*
* Return: QDF_STATUS_SUCCESS up on success and any other status for failure.
*/
QDF_STATUS ucfg_policy_mgr_get_conc_rule2(struct wlan_objmgr_psoc *psoc,
uint8_t *conc_rule2);
/**
* ucfg_policy_mgr_get_dbs_selection_plcy() - DBS HW mode selection setting
* @psoc: pointer to psoc
* @dbs_selection_plcy: value to be filled
*
* This API is used to find out DBS HW mode preference.
*
* Return: QDF_STATUS_SUCCESS up on success and any other status for failure.
*/
QDF_STATUS ucfg_policy_mgr_get_dbs_selection_plcy(struct wlan_objmgr_psoc *psoc,
uint32_t *dbs_selection_plcy);
/**
* ucfg_policy_mgr_get_vdev_priority_list() - to get vdev priority list
* @psoc: pointer to psoc
* @vdev_priority_list: value to be filled
*
* This API is used to find out vdev_priority_list setting
*
* Return: QDF_STATUS_SUCCESS up on success and any other status for failure.
*/
QDF_STATUS ucfg_policy_mgr_get_vdev_priority_list(struct wlan_objmgr_psoc *psoc,
uint32_t *vdev_priority_list);
/**
* policy_mgr_get_chnl_select_plcy() - to get channel selection policy
* @psoc: pointer to psoc
* @chnl_select_plcy: value to be filled
*
* This API is used to find out which channel selection policy has been
* configured
*
* Return: QDF_STATUS_SUCCESS up on success and any other status for failure.
*/
QDF_STATUS ucfg_policy_mgr_get_chnl_select_plcy(struct wlan_objmgr_psoc *psoc,
uint32_t *chnl_select_plcy);
/**
* policy_mgr_get_mcc_adaptive_sch() - to get mcc adaptive scheduler
* @psoc: pointer to psoc
* @enable_mcc_adaptive_sch: value to be filled
*
* This API is used to find out if mcc adaptive scheduler enabled or disabled
*
* Return: QDF_STATUS_SUCCESS up on success and any other status for failure.
*/
QDF_STATUS
ucfg_policy_mgr_get_mcc_adaptive_sch(struct wlan_objmgr_psoc *psoc,
uint8_t *enable_mcc_adaptive_sch);
/**
* ucfg_policy_mgr_get_sta_cxn_5g_band() - to get STA's connection in 5G config
*
* @psoc: pointer to psoc
* @enable_sta_cxn_5g_band: value to be filled
*
* This API is used to find out if STA connection in 5G band is allowed or
* disallowed.
*
* Return: QDF_STATUS_SUCCESS up on success and any other status for failure.
*/
QDF_STATUS ucfg_policy_mgr_get_sta_cxn_5g_band(struct wlan_objmgr_psoc *psoc,
uint8_t *enable_sta_cxn_5g_band);
#endif //__WLAN_POLICY_MGR_UCFG

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,583 @@
/*
* Copyright (c) 2012-2018 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.
*/
#ifndef WLAN_POLICY_MGR_I_H
#define WLAN_POLICY_MGR_I_H
#include "wlan_policy_mgr_api.h"
#include "qdf_event.h"
#include "qdf_mc_timer.h"
#include "qdf_lock.h"
#include "qdf_defer.h"
#include "wlan_reg_services_api.h"
#define DBS_OPPORTUNISTIC_TIME 5
#ifdef QCA_WIFI_3_0_EMU
#define CONNECTION_UPDATE_TIMEOUT 3000
#else
#define CONNECTION_UPDATE_TIMEOUT 1000
#endif
#define PM_24_GHZ_CHANNEL_6 (6)
#define PM_5_GHZ_CHANNEL_36 (36)
#define CHANNEL_SWITCH_COMPLETE_TIMEOUT (2000)
/**
* Policy Mgr hardware mode list bit-mask definitions.
* Bits 4:0, 31:29 are unused.
*
* The below definitions are added corresponding to WMI DBS HW mode
* list to make it independent of firmware changes for WMI definitions.
* Currently these definitions have dependency with BIT positions of
* the existing WMI macros. Thus, if the BIT positions are changed for
* WMI macros, then these macros' BIT definitions are also need to be
* changed.
*/
#define POLICY_MGR_HW_MODE_MAC0_TX_STREAMS_BITPOS (28)
#define POLICY_MGR_HW_MODE_MAC0_RX_STREAMS_BITPOS (24)
#define POLICY_MGR_HW_MODE_MAC1_TX_STREAMS_BITPOS (20)
#define POLICY_MGR_HW_MODE_MAC1_RX_STREAMS_BITPOS (16)
#define POLICY_MGR_HW_MODE_MAC0_BANDWIDTH_BITPOS (12)
#define POLICY_MGR_HW_MODE_MAC1_BANDWIDTH_BITPOS (8)
#define POLICY_MGR_HW_MODE_DBS_MODE_BITPOS (7)
#define POLICY_MGR_HW_MODE_AGILE_DFS_MODE_BITPOS (6)
#define POLICY_MGR_HW_MODE_SBS_MODE_BITPOS (5)
#define POLICY_MGR_HW_MODE_MAC0_BAND_BITPOS (3)
#define POLICY_MGR_HW_MODE_ID_BITPOS (0)
#define POLICY_MGR_HW_MODE_MAC0_TX_STREAMS_MASK \
(0xf << POLICY_MGR_HW_MODE_MAC0_TX_STREAMS_BITPOS)
#define POLICY_MGR_HW_MODE_MAC0_RX_STREAMS_MASK \
(0xf << POLICY_MGR_HW_MODE_MAC0_RX_STREAMS_BITPOS)
#define POLICY_MGR_HW_MODE_MAC1_TX_STREAMS_MASK \
(0xf << POLICY_MGR_HW_MODE_MAC1_TX_STREAMS_BITPOS)
#define POLICY_MGR_HW_MODE_MAC1_RX_STREAMS_MASK \
(0xf << POLICY_MGR_HW_MODE_MAC1_RX_STREAMS_BITPOS)
#define POLICY_MGR_HW_MODE_MAC0_BANDWIDTH_MASK \
(0xf << POLICY_MGR_HW_MODE_MAC0_BANDWIDTH_BITPOS)
#define POLICY_MGR_HW_MODE_MAC1_BANDWIDTH_MASK \
(0xf << POLICY_MGR_HW_MODE_MAC1_BANDWIDTH_BITPOS)
#define POLICY_MGR_HW_MODE_DBS_MODE_MASK \
(0x1 << POLICY_MGR_HW_MODE_DBS_MODE_BITPOS)
#define POLICY_MGR_HW_MODE_AGILE_DFS_MODE_MASK \
(0x1 << POLICY_MGR_HW_MODE_AGILE_DFS_MODE_BITPOS)
#define POLICY_MGR_HW_MODE_SBS_MODE_MASK \
(0x1 << POLICY_MGR_HW_MODE_SBS_MODE_BITPOS)
#define POLICY_MGR_HW_MODE_MAC0_BAND_MASK \
(0x3 << POLICY_MGR_HW_MODE_MAC0_BAND_BITPOS)
#define POLICY_MGR_HW_MODE_ID_MASK \
(0x7 << POLICY_MGR_HW_MODE_ID_BITPOS)
#define POLICY_MGR_HW_MODE_MAC0_TX_STREAMS_SET(hw_mode, value) \
WMI_SET_BITS(hw_mode, POLICY_MGR_HW_MODE_MAC0_TX_STREAMS_BITPOS,\
4, value)
#define POLICY_MGR_HW_MODE_MAC0_RX_STREAMS_SET(hw_mode, value) \
WMI_SET_BITS(hw_mode, POLICY_MGR_HW_MODE_MAC0_RX_STREAMS_BITPOS,\
4, value)
#define POLICY_MGR_HW_MODE_MAC1_TX_STREAMS_SET(hw_mode, value) \
WMI_SET_BITS(hw_mode, POLICY_MGR_HW_MODE_MAC1_TX_STREAMS_BITPOS,\
4, value)
#define POLICY_MGR_HW_MODE_MAC1_RX_STREAMS_SET(hw_mode, value) \
WMI_SET_BITS(hw_mode, POLICY_MGR_HW_MODE_MAC1_RX_STREAMS_BITPOS,\
4, value)
#define POLICY_MGR_HW_MODE_MAC0_BANDWIDTH_SET(hw_mode, value) \
WMI_SET_BITS(hw_mode, POLICY_MGR_HW_MODE_MAC0_BANDWIDTH_BITPOS,\
4, value)
#define POLICY_MGR_HW_MODE_MAC1_BANDWIDTH_SET(hw_mode, value) \
WMI_SET_BITS(hw_mode, POLICY_MGR_HW_MODE_MAC1_BANDWIDTH_BITPOS,\
4, value)
#define POLICY_MGR_HW_MODE_DBS_MODE_SET(hw_mode, value) \
WMI_SET_BITS(hw_mode, POLICY_MGR_HW_MODE_DBS_MODE_BITPOS,\
1, value)
#define POLICY_MGR_HW_MODE_AGILE_DFS_SET(hw_mode, value) \
WMI_SET_BITS(hw_mode, POLICY_MGR_HW_MODE_AGILE_DFS_MODE_BITPOS,\
1, value)
#define POLICY_MGR_HW_MODE_SBS_MODE_SET(hw_mode, value) \
WMI_SET_BITS(hw_mode, POLICY_MGR_HW_MODE_SBS_MODE_BITPOS,\
1, value)
#define POLICY_MGR_HW_MODE_MAC0_BAND_SET(hw_mode, value) \
WMI_SET_BITS(hw_mode, POLICY_MGR_HW_MODE_MAC0_BAND_BITPOS,\
2, value)
#define POLICY_MGR_HW_MODE_ID_SET(hw_mode, value) \
WMI_SET_BITS(hw_mode, POLICY_MGR_HW_MODE_ID_BITPOS,\
3, value)
#define POLICY_MGR_HW_MODE_MAC0_TX_STREAMS_GET(hw_mode) \
(((hw_mode) & POLICY_MGR_HW_MODE_MAC0_TX_STREAMS_MASK) >> \
POLICY_MGR_HW_MODE_MAC0_TX_STREAMS_BITPOS)
#define POLICY_MGR_HW_MODE_MAC0_RX_STREAMS_GET(hw_mode) \
(((hw_mode) & POLICY_MGR_HW_MODE_MAC0_RX_STREAMS_MASK) >> \
POLICY_MGR_HW_MODE_MAC0_RX_STREAMS_BITPOS)
#define POLICY_MGR_HW_MODE_MAC1_TX_STREAMS_GET(hw_mode) \
(((hw_mode) & POLICY_MGR_HW_MODE_MAC1_TX_STREAMS_MASK) >> \
POLICY_MGR_HW_MODE_MAC1_TX_STREAMS_BITPOS)
#define POLICY_MGR_HW_MODE_MAC1_RX_STREAMS_GET(hw_mode) \
(((hw_mode) & POLICY_MGR_HW_MODE_MAC1_RX_STREAMS_MASK) >> \
POLICY_MGR_HW_MODE_MAC1_RX_STREAMS_BITPOS)
#define POLICY_MGR_HW_MODE_MAC0_BANDWIDTH_GET(hw_mode) \
(((hw_mode) & POLICY_MGR_HW_MODE_MAC0_BANDWIDTH_MASK) >> \
POLICY_MGR_HW_MODE_MAC0_BANDWIDTH_BITPOS)
#define POLICY_MGR_HW_MODE_MAC1_BANDWIDTH_GET(hw_mode) \
(((hw_mode) & POLICY_MGR_HW_MODE_MAC1_BANDWIDTH_MASK) >> \
POLICY_MGR_HW_MODE_MAC1_BANDWIDTH_BITPOS)
#define POLICY_MGR_HW_MODE_DBS_MODE_GET(hw_mode) \
(((hw_mode) & POLICY_MGR_HW_MODE_DBS_MODE_MASK) >> \
POLICY_MGR_HW_MODE_DBS_MODE_BITPOS)
#define POLICY_MGR_HW_MODE_AGILE_DFS_GET(hw_mode) \
(((hw_mode) & POLICY_MGR_HW_MODE_AGILE_DFS_MODE_MASK) >> \
POLICY_MGR_HW_MODE_AGILE_DFS_MODE_BITPOS)
#define POLICY_MGR_HW_MODE_SBS_MODE_GET(hw_mode) \
(((hw_mode) & POLICY_MGR_HW_MODE_SBS_MODE_MASK) >> \
POLICY_MGR_HW_MODE_SBS_MODE_BITPOS)
#define POLICY_MGR_HW_MODE_MAC0_BAND_GET(hw_mode) \
(((hw_mode) & POLICY_MGR_HW_MODE_MAC0_BAND_MASK) >> \
POLICY_MGR_HW_MODE_MAC0_BAND_BITPOS)
#define POLICY_MGR_HW_MODE_ID_GET(hw_mode) \
(((hw_mode) & POLICY_MGR_HW_MODE_ID_MASK) >> \
POLICY_MGR_HW_MODE_ID_BITPOS)
#define POLICY_MGR_DEFAULT_HW_MODE_INDEX 0xFFFF
#define policy_mgr_alert(params...) \
QDF_TRACE_FATAL(QDF_MODULE_ID_POLICY_MGR, params)
#define policy_mgr_err(params...) \
QDF_TRACE_ERROR(QDF_MODULE_ID_POLICY_MGR, params)
#define policy_mgr_warn(params...) \
QDF_TRACE_WARN(QDF_MODULE_ID_POLICY_MGR, params)
#define policy_mgr_notice(params...) \
QDF_TRACE_INFO(QDF_MODULE_ID_POLICY_MGR, params)
#define policy_mgr_info(params...) \
QDF_TRACE_INFO(QDF_MODULE_ID_POLICY_MGR, params)
#define policy_mgr_debug(params...) \
QDF_TRACE_DEBUG(QDF_MODULE_ID_POLICY_MGR, params)
#define policymgr_nofl_alert(params...) \
QDF_TRACE_FATAL_NO_FL(QDF_MODULE_ID_POLICY_MGR, params)
#define policymgr_nofl_err(params...) \
QDF_TRACE_ERROR_NO_FL(QDF_MODULE_ID_POLICY_MGR, params)
#define policymgr_nofl_warn(params...) \
QDF_TRACE_WARN_NO_FL(QDF_MODULE_ID_POLICY_MGR, params)
#define policymgr_nofl_info(params...) \
QDF_TRACE_INFO_NO_FL(QDF_MODULE_ID_POLICY_MGR, params)
#define policymgr_nofl_debug(params...) \
QDF_TRACE_DEBUG_NO_FL(QDF_MODULE_ID_POLICY_MGR, params)
#define PM_CONC_CONNECTION_LIST_VALID_INDEX(index) \
((MAX_NUMBER_OF_CONC_CONNECTIONS > index) && \
(pm_conc_connection_list[index].in_use))
extern struct policy_mgr_conc_connection_info
pm_conc_connection_list[MAX_NUMBER_OF_CONC_CONNECTIONS];
extern const enum policy_mgr_pcl_type
first_connection_pcl_table[PM_MAX_NUM_OF_MODE]
[PM_MAX_CONC_PRIORITY_MODE];
extern pm_dbs_pcl_second_connection_table_type
*second_connection_pcl_dbs_table;
extern pm_dbs_pcl_third_connection_table_type
*third_connection_pcl_dbs_table;
extern policy_mgr_next_action_two_connection_table_type
*next_action_two_connection_table;
extern policy_mgr_next_action_three_connection_table_type
*next_action_three_connection_table;
extern policy_mgr_next_action_two_connection_table_type
*next_action_two_connection_2x2_2g_1x1_5g_table;
extern policy_mgr_next_action_three_connection_table_type
*next_action_three_connection_2x2_2g_1x1_5g_table;
extern enum policy_mgr_conc_next_action
(*policy_mgr_get_current_pref_hw_mode_ptr)
(struct wlan_objmgr_psoc *psoc);
/**
* struct sta_ap_intf_check_work_ctx - sta_ap_intf_check_work
* related info
* @psoc: pointer to PSOC object information
*/
struct sta_ap_intf_check_work_ctx {
struct wlan_objmgr_psoc *psoc;
};
/**
* struct policy_mgr_cfg - all the policy manager owned configs
* @mcc_to_scc_switch: switch to indicate MCC to SCC config
* @sys_pref: system's preference while selecting PCLs
* @max_conc_cxns: Max allowed concurrenct active connections
* @conc_rule1: concurrency rule1
* @conc_rule2: concurrency rule2
* @dbs_selection_plcy: DBS selection policy for concurrency
* @vdev_priority_list: Priority list for various vdevs
* @chnl_select_plcy: Channel selection policy
* @enable_mcc_adaptive_sch: Enable/Disable MCC adaptive scheduler
* @enable_sta_cxn_5g_band: Enable/Disable STA connection in 5G band
*/
struct policy_mgr_cfg {
uint8_t mcc_to_scc_switch;
uint8_t sys_pref;
uint8_t max_conc_cxns;
uint8_t conc_rule1;
uint8_t conc_rule2;
uint8_t enable_mcc_adaptive_sch;
uint8_t enable_sta_cxn_5g_band;
uint32_t dbs_selection_plcy;
uint32_t vdev_priority_list;
uint32_t chnl_select_plcy;
};
/**
* struct policy_mgr_psoc_priv_obj - Policy manager private data
* @psoc: pointer to PSOC object information
* @pdev: pointer to PDEV object information
* @connection_update_done_evt: qdf event to synchronize
* connection activities
* @qdf_conc_list_lock: To protect connection table
* @dbs_opportunistic_timer: Timer to drop down to Single Mac
* Mode opportunistically
* @sap_restart_chan_switch_cb: Callback for channel switch
* notification for SAP
* @sme_cbacks: callbacks to be registered by SME for
* interaction with Policy Manager
* @wma_cbacks: callbacks to be registered by SME for
* interaction with Policy Manager
* @tdls_cbacks: callbacks to be registered by SME for
* interaction with Policy Manager
* @cdp_cbacks: callbacks to be registered by SME for
* interaction with Policy Manager
* @sap_mandatory_channels: The user preferred master list on
* which SAP can be brought up. This
* mandatory channel list would be as per
* OEMs preference & conforming to the
* regulatory/other considerations
* @sap_mandatory_channels_len: Length of the SAP mandatory
* channel list
* @do_hw_mode_change: Flag to check if HW mode change is needed
* after vdev is up. Especially used after
* channel switch related vdev restart
* @concurrency_mode: active concurrency combination
* @no_of_open_sessions: Number of active vdevs
* @no_of_active_sessions: Number of active connections
* @sta_ap_intf_check_work: delayed sap restart work
* @num_dbs_hw_modes: Number of different HW modes supported
* @hw_mode: List of HW modes supported
* @old_hw_mode_index: Old HW mode from hw_mode table
* @new_hw_mode_index: New HW mode from hw_mode table
* @dual_mac_cfg: DBS configuration currenctly used by FW for
* scan & connections
* @hw_mode_change_in_progress: This is to track if HW mode
* change is in progress
* @enable_mcc_adaptive_scheduler: Enable MCC adaptive scheduler
* value from INI
* @unsafe_channel_list: LTE coex channel avoidance list
* @unsafe_channel_count: LTE coex channel avoidance list count
* @sta_ap_intf_check_work_info: Info related to sta_ap_intf_check_work
* @opportunistic_update_done_evt: qdf event to synchronize host
* & FW HW mode
*/
struct policy_mgr_psoc_priv_obj {
struct wlan_objmgr_psoc *psoc;
struct wlan_objmgr_pdev *pdev;
qdf_event_t connection_update_done_evt;
qdf_mutex_t qdf_conc_list_lock;
qdf_mc_timer_t dbs_opportunistic_timer;
struct policy_mgr_hdd_cbacks hdd_cbacks;
struct policy_mgr_sme_cbacks sme_cbacks;
struct policy_mgr_wma_cbacks wma_cbacks;
struct policy_mgr_tdls_cbacks tdls_cbacks;
struct policy_mgr_cdp_cbacks cdp_cbacks;
struct policy_mgr_dp_cbacks dp_cbacks;
bool enable_sap_mandatory_chan_list;
uint8_t sap_mandatory_channels[QDF_MAX_NUM_CHAN];
uint32_t sap_mandatory_channels_len;
bool do_hw_mode_change;
uint32_t concurrency_mode;
uint8_t no_of_open_sessions[QDF_MAX_NO_OF_MODE];
uint8_t no_of_active_sessions[QDF_MAX_NO_OF_MODE];
qdf_work_t sta_ap_intf_check_work;
uint32_t num_dbs_hw_modes;
struct dbs_hw_mode_info hw_mode;
uint32_t old_hw_mode_index;
uint32_t new_hw_mode_index;
struct dual_mac_config dual_mac_cfg;
uint32_t hw_mode_change_in_progress;
struct policy_mgr_user_cfg user_cfg;
uint16_t unsafe_channel_list[QDF_MAX_NUM_CHAN];
uint16_t unsafe_channel_count;
struct sta_ap_intf_check_work_ctx *sta_ap_intf_check_work_info;
uint8_t cur_conc_system_pref;
uint8_t sta_sap_scc_on_dfs_chan_allowed;
qdf_event_t opportunistic_update_done_evt;
qdf_event_t channel_switch_complete_evt;
send_mode_change_event_cb mode_change_cb;
uint32_t user_config_sap_channel;
struct policy_mgr_cfg cfg;
};
/**
* struct policy_mgr_mac_ss_bw_info - hw_mode_list PHY/MAC params for each MAC
* @mac_tx_stream: Max TX stream number supported on MAC
* @mac_rx_stream: Max RX stream number supported on MAC
* @mac_bw: Max bandwidth(wmi_channel_width enum type)
* @mac_band_cap: supported Band bit map(WLAN_2G_CAPABILITY = 0x1,
* WLAN_5G_CAPABILITY = 0x2)
*/
struct policy_mgr_mac_ss_bw_info {
uint32_t mac_tx_stream;
uint32_t mac_rx_stream;
uint32_t mac_bw;
uint32_t mac_band_cap;
};
struct policy_mgr_psoc_priv_obj *policy_mgr_get_context(
struct wlan_objmgr_psoc *psoc);
QDF_STATUS policy_mgr_get_updated_scan_config(
struct wlan_objmgr_psoc *psoc,
uint32_t *scan_config,
bool dbs_scan,
bool dbs_plus_agile_scan,
bool single_mac_scan_with_dfs);
QDF_STATUS policy_mgr_get_updated_fw_mode_config(
struct wlan_objmgr_psoc *psoc,
uint32_t *fw_mode_config,
bool dbs,
bool agile_dfs);
bool policy_mgr_is_dual_mac_disabled_in_ini(
struct wlan_objmgr_psoc *psoc);
/**
* policy_mgr_get_mcc_to_scc_switch_mode() - MCC to SCC
* switch mode value in the user config
* @psoc: PSOC object information
*
* MCC to SCC switch mode value in user config
*
* Return: MCC to SCC switch mode value
*/
uint32_t policy_mgr_get_mcc_to_scc_switch_mode(
struct wlan_objmgr_psoc *psoc);
bool policy_mgr_get_dbs_config(struct wlan_objmgr_psoc *psoc);
bool policy_mgr_get_agile_dfs_config(struct wlan_objmgr_psoc *psoc);
bool policy_mgr_get_dbs_scan_config(struct wlan_objmgr_psoc *psoc);
void policy_mgr_get_tx_rx_ss_from_config(enum hw_mode_ss_config mac_ss,
uint32_t *tx_ss, uint32_t *rx_ss);
int8_t policy_mgr_get_matching_hw_mode_index(
struct wlan_objmgr_psoc *psoc,
uint32_t mac0_tx_ss, uint32_t mac0_rx_ss,
enum hw_mode_bandwidth mac0_bw,
uint32_t mac1_tx_ss, uint32_t mac1_rx_ss,
enum hw_mode_bandwidth mac1_bw,
enum hw_mode_mac_band_cap mac0_band_cap,
enum hw_mode_dbs_capab dbs,
enum hw_mode_agile_dfs_capab dfs,
enum hw_mode_sbs_capab sbs);
int8_t policy_mgr_get_hw_mode_idx_from_dbs_hw_list(
struct wlan_objmgr_psoc *psoc,
enum hw_mode_ss_config mac0_ss,
enum hw_mode_bandwidth mac0_bw,
enum hw_mode_ss_config mac1_ss,
enum hw_mode_bandwidth mac1_bw,
enum hw_mode_mac_band_cap mac0_band_cap,
enum hw_mode_dbs_capab dbs,
enum hw_mode_agile_dfs_capab dfs,
enum hw_mode_sbs_capab sbs);
QDF_STATUS policy_mgr_get_old_and_new_hw_index(
struct wlan_objmgr_psoc *psoc,
uint32_t *old_hw_mode_index,
uint32_t *new_hw_mode_index);
void policy_mgr_update_conc_list(struct wlan_objmgr_psoc *psoc,
uint32_t conn_index,
enum policy_mgr_con_mode mode,
uint8_t chan,
enum hw_mode_bandwidth bw,
uint8_t mac,
enum policy_mgr_chain_mode chain_mask,
uint32_t original_nss,
uint32_t vdev_id,
bool in_use,
bool update_conn);
void policy_mgr_store_and_del_conn_info(struct wlan_objmgr_psoc *psoc,
enum policy_mgr_con_mode mode,
bool all_matching_cxn_to_del,
struct policy_mgr_conc_connection_info *info,
uint8_t *num_cxn_del);
/**
* policy_mgr_store_and_del_conn_info_by_vdev_id() - Store and del a
* connection info by vdev id
* @psoc: PSOC object information
* @vdev_id: vdev id whose entry has to be deleted
* @info: struture array pointer where the connection info will be saved
* @num_cxn_del: number of connection which are going to be deleted
*
* Saves the connection info corresponding to the provided mode
* and deleted that corresponding entry based on vdev from the
* connection info structure
*
* Return: None
*/
void policy_mgr_store_and_del_conn_info_by_vdev_id(
struct wlan_objmgr_psoc *psoc,
uint32_t vdev_id,
struct policy_mgr_conc_connection_info *info,
uint8_t *num_cxn_del);
void policy_mgr_restore_deleted_conn_info(struct wlan_objmgr_psoc *psoc,
struct policy_mgr_conc_connection_info *info,
uint8_t num_cxn_del);
void policy_mgr_update_hw_mode_conn_info(struct wlan_objmgr_psoc *psoc,
uint32_t num_vdev_mac_entries,
struct policy_mgr_vdev_mac_map *vdev_mac_map,
struct policy_mgr_hw_mode_params hw_mode);
void policy_mgr_pdev_set_hw_mode_cb(uint32_t status,
uint32_t cfgd_hw_mode_index,
uint32_t num_vdev_mac_entries,
struct policy_mgr_vdev_mac_map *vdev_mac_map,
uint8_t next_action,
enum policy_mgr_conn_update_reason reason,
uint32_t session_id, void *context);
void policy_mgr_dump_current_concurrency(struct wlan_objmgr_psoc *psoc);
/**
* policy_mgr_pdev_set_pcl() - SET PCL channel list and send to firmware
* @psoc: PSOC object information
* @mode: Adapter mode
*
* Return: None
*/
void policy_mgr_pdev_set_pcl(struct wlan_objmgr_psoc *psoc,
enum QDF_OPMODE mode);
void pm_dbs_opportunistic_timer_handler(void *data);
enum policy_mgr_con_mode policy_mgr_get_mode(uint8_t type,
uint8_t subtype);
enum hw_mode_bandwidth policy_mgr_get_bw(enum phy_ch_width chan_width);
QDF_STATUS policy_mgr_get_channel_list(struct wlan_objmgr_psoc *psoc,
enum policy_mgr_pcl_type pcl,
uint8_t *pcl_channels, uint32_t *len,
enum policy_mgr_con_mode mode,
uint8_t *pcl_weights, uint32_t weight_len);
bool policy_mgr_allow_new_home_channel(struct wlan_objmgr_psoc *psoc,
uint8_t channel, uint32_t num_connections);
bool policy_mgr_is_5g_channel_allowed(struct wlan_objmgr_psoc *psoc,
uint8_t channel, uint32_t *list,
enum policy_mgr_con_mode mode);
QDF_STATUS policy_mgr_complete_action(struct wlan_objmgr_psoc *psoc,
uint8_t new_nss, uint8_t next_action,
enum policy_mgr_conn_update_reason reason,
uint32_t session_id);
enum policy_mgr_con_mode policy_mgr_get_mode_by_vdev_id(
struct wlan_objmgr_psoc *psoc,
uint8_t vdev_id);
QDF_STATUS policy_mgr_init_connection_update(
struct policy_mgr_psoc_priv_obj *pm_ctx);
enum policy_mgr_conc_next_action
policy_mgr_get_current_pref_hw_mode_dbs_2x2(
struct wlan_objmgr_psoc *psoc);
enum policy_mgr_conc_next_action
policy_mgr_get_current_pref_hw_mode_dbs_1x1(
struct wlan_objmgr_psoc *psoc);
/**
* policy_mgr_get_current_pref_hw_mode_dual_dbs() - Get the
* current preferred hw mode
*
* Get the preferred hw mode based on the current connection combinations
*
* Return: No change (PM_NOP), (PM_SINGLE_MAC_UPGRADE),
* DBS (PM_DBS1_DOWNGRADE or PM_DBS2_DOWNGRADE)
*/
enum policy_mgr_conc_next_action
policy_mgr_get_current_pref_hw_mode_dual_dbs(
struct wlan_objmgr_psoc *psoc);
QDF_STATUS policy_mgr_reset_sap_mandatory_channels(
struct policy_mgr_psoc_priv_obj *pm_ctx);
/**
* policy_mgr_get_mode_specific_conn_info() - Get active mode specific
* channel and vdev id
* @psoc: PSOC object information
* @channel: Mode specific channel (list)
* @vdev_id: Mode specific vdev id (list)
* @mode: Connection Mode
*
* Get active mode specific channel and vdev id
*
* Return: number of connection found as per given mode
*/
uint32_t policy_mgr_get_mode_specific_conn_info(struct wlan_objmgr_psoc *psoc,
uint8_t *channel, uint8_t *vdev_id,
enum policy_mgr_con_mode mode);
/**
* policy_mgr_reg_chan_change_callback() - Callback to be
* invoked by regulatory module when valid channel list changes
* @psoc: PSOC object information
* @pdev: PDEV object information
* @chan_list: New channel list
* @avoid_freq_ind: LTE coex avoid channel list
* @arg: Information passed at registration
*
* Get updated channel list from regulatory module
*
* Return: None
*/
void policy_mgr_reg_chan_change_callback(struct wlan_objmgr_psoc *psoc,
struct wlan_objmgr_pdev *pdev,
struct regulatory_channel *chan_list,
struct avoid_freq_ind_data *avoid_freq_ind,
void *arg);
/**
* policy_mgr_nss_update() - update nss for AP vdev
* @psoc: PSOC object information
* @new_nss: new NSS value
* @next_action: Next action after nss update
* @band: update AP vdev on the Band.
* @reason: action reason
* @original_vdev_id: original request hwmode change vdev id
*
* The function will update AP vdevs on specific band.
* eg. band = POLICY_MGR_ANY will request to update all band (2g and 5g)
*
* Return: QDF_STATUS_SUCCESS, update requested successfully.
*/
QDF_STATUS policy_mgr_nss_update(struct wlan_objmgr_psoc *psoc,
uint8_t new_nss, uint8_t next_action,
enum policy_mgr_band band,
enum policy_mgr_conn_update_reason reason,
uint32_t original_vdev_id);
/**
* policy_mgr_is_concurrency_allowed() - Check for allowed
* concurrency combination
* @psoc: PSOC object information
* @mode: new connection mode
* @channel: channel on which new connection is coming up
* @bw: Bandwidth requested by the connection (optional)
*
* When a new connection is about to come up check if current
* concurrency combination including the new connection is
* allowed or not based on the HW capability, but no need to
* invoke get_pcl
*
* Return: True/False
*/
bool policy_mgr_is_concurrency_allowed(struct wlan_objmgr_psoc *psoc,
enum policy_mgr_con_mode mode,
uint8_t channel,
enum hw_mode_bandwidth bw);
#endif

View file

@ -0,0 +1,742 @@
/*
* Copyright (c) 2012-2018 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_policy_mgr_init_deinit.c
*
* WLAN Concurrenct Connection Management APIs
*
*/
/* Include files */
#include "wlan_policy_mgr_api.h"
#include "wlan_policy_mgr_tables_1x1_dbs_i.h"
#include "wlan_policy_mgr_tables_2x2_dbs_i.h"
#include "wlan_policy_mgr_tables_2x2_5g_1x1_2g.h"
#include "wlan_policy_mgr_tables_2x2_2g_1x1_5g.h"
#include "wlan_policy_mgr_i.h"
#include "qdf_types.h"
#include "qdf_trace.h"
#include "wlan_objmgr_global_obj.h"
static QDF_STATUS policy_mgr_psoc_obj_create_cb(struct wlan_objmgr_psoc *psoc,
void *data)
{
struct policy_mgr_psoc_priv_obj *policy_mgr_ctx;
policy_mgr_ctx = qdf_mem_malloc(
sizeof(struct policy_mgr_psoc_priv_obj));
if (!policy_mgr_ctx) {
policy_mgr_err("memory allocation failed");
return QDF_STATUS_E_FAILURE;
}
policy_mgr_ctx->psoc = psoc;
policy_mgr_ctx->old_hw_mode_index = POLICY_MGR_DEFAULT_HW_MODE_INDEX;
policy_mgr_ctx->new_hw_mode_index = POLICY_MGR_DEFAULT_HW_MODE_INDEX;
wlan_objmgr_psoc_component_obj_attach(psoc,
WLAN_UMAC_COMP_POLICY_MGR,
policy_mgr_ctx,
QDF_STATUS_SUCCESS);
return QDF_STATUS_SUCCESS;
}
static QDF_STATUS policy_mgr_psoc_obj_destroy_cb(struct wlan_objmgr_psoc *psoc,
void *data)
{
struct policy_mgr_psoc_priv_obj *policy_mgr_ctx;
policy_mgr_ctx = policy_mgr_get_context(psoc);
wlan_objmgr_psoc_component_obj_detach(psoc,
WLAN_UMAC_COMP_POLICY_MGR,
policy_mgr_ctx);
qdf_mem_free(policy_mgr_ctx);
return QDF_STATUS_SUCCESS;
}
static void policy_mgr_psoc_obj_status_cb(struct wlan_objmgr_psoc *psoc,
void *data, QDF_STATUS status)
{
return;
}
static QDF_STATUS policy_mgr_pdev_obj_create_cb(struct wlan_objmgr_pdev *pdev,
void *data)
{
struct policy_mgr_psoc_priv_obj *policy_mgr_ctx;
struct wlan_objmgr_psoc *psoc;
psoc = wlan_pdev_get_psoc(pdev);
policy_mgr_ctx = policy_mgr_get_context(psoc);
if (!policy_mgr_ctx) {
policy_mgr_err("invalid context");
return QDF_STATUS_E_FAILURE;
}
policy_mgr_ctx->pdev = pdev;
wlan_reg_register_chan_change_callback(psoc,
policy_mgr_reg_chan_change_callback, NULL);
return QDF_STATUS_SUCCESS;
}
static QDF_STATUS policy_mgr_pdev_obj_destroy_cb(struct wlan_objmgr_pdev *pdev,
void *data)
{
struct policy_mgr_psoc_priv_obj *policy_mgr_ctx;
struct wlan_objmgr_psoc *psoc;
psoc = wlan_pdev_get_psoc(pdev);
policy_mgr_ctx = policy_mgr_get_context(psoc);
if (!policy_mgr_ctx) {
policy_mgr_err("invalid context");
return QDF_STATUS_E_FAILURE;
}
policy_mgr_ctx->pdev = NULL;
wlan_reg_unregister_chan_change_callback(psoc,
policy_mgr_reg_chan_change_callback);
return QDF_STATUS_SUCCESS;
}
static QDF_STATUS policy_mgr_vdev_obj_create_cb(struct wlan_objmgr_vdev *vdev,
void *data)
{
return QDF_STATUS_SUCCESS;
}
static QDF_STATUS policy_mgr_vdev_obj_destroy_cb(struct wlan_objmgr_vdev *vdev,
void *data)
{
return QDF_STATUS_SUCCESS;
}
static void policy_mgr_vdev_obj_status_cb(struct wlan_objmgr_vdev *vdev,
void *data, QDF_STATUS status)
{
return;
}
QDF_STATUS policy_mgr_init(void)
{
QDF_STATUS status = QDF_STATUS_SUCCESS;
status = wlan_objmgr_register_psoc_create_handler(
WLAN_UMAC_COMP_POLICY_MGR,
policy_mgr_psoc_obj_create_cb,
NULL);
if (status != QDF_STATUS_SUCCESS) {
policy_mgr_err("Failed to register psoc obj create cback");
goto err_psoc_create;
}
status = wlan_objmgr_register_psoc_destroy_handler(
WLAN_UMAC_COMP_POLICY_MGR,
policy_mgr_psoc_obj_destroy_cb,
NULL);
if (status != QDF_STATUS_SUCCESS) {
policy_mgr_err("Failed to register psoc obj delete cback");
goto err_psoc_delete;
}
status = wlan_objmgr_register_psoc_status_handler(
WLAN_UMAC_COMP_POLICY_MGR,
policy_mgr_psoc_obj_status_cb,
NULL);
if (status != QDF_STATUS_SUCCESS) {
policy_mgr_err("Failed to register psoc obj status cback");
goto err_psoc_status;
}
status = wlan_objmgr_register_pdev_create_handler(
WLAN_UMAC_COMP_POLICY_MGR,
policy_mgr_pdev_obj_create_cb,
NULL);
if (status != QDF_STATUS_SUCCESS) {
policy_mgr_err("Failed to register pdev obj create cback");
goto err_pdev_create;
}
status = wlan_objmgr_register_pdev_destroy_handler(
WLAN_UMAC_COMP_POLICY_MGR,
policy_mgr_pdev_obj_destroy_cb,
NULL);
if (status != QDF_STATUS_SUCCESS) {
policy_mgr_err("Failed to register pdev obj delete cback");
goto err_pdev_delete;
}
status = wlan_objmgr_register_vdev_create_handler(
WLAN_UMAC_COMP_POLICY_MGR,
policy_mgr_vdev_obj_create_cb,
NULL);
if (status != QDF_STATUS_SUCCESS) {
policy_mgr_err("Failed to register vdev obj create cback");
goto err_vdev_create;
}
status = wlan_objmgr_register_vdev_destroy_handler(
WLAN_UMAC_COMP_POLICY_MGR,
policy_mgr_vdev_obj_destroy_cb,
NULL);
if (status != QDF_STATUS_SUCCESS) {
policy_mgr_err("Failed to register vdev obj delete cback");
goto err_vdev_delete;
}
status = wlan_objmgr_register_vdev_status_handler(
WLAN_UMAC_COMP_POLICY_MGR,
policy_mgr_vdev_obj_status_cb,
NULL);
if (status != QDF_STATUS_SUCCESS) {
policy_mgr_err("Failed to register vdev obj status cback");
goto err_vdev_status;
}
policy_mgr_notice("Callbacks registered with obj mgr");
return QDF_STATUS_SUCCESS;
err_vdev_status:
wlan_objmgr_unregister_vdev_destroy_handler(WLAN_UMAC_COMP_POLICY_MGR,
policy_mgr_vdev_obj_destroy_cb,
NULL);
err_vdev_delete:
wlan_objmgr_unregister_vdev_create_handler(WLAN_UMAC_COMP_POLICY_MGR,
policy_mgr_vdev_obj_create_cb,
NULL);
err_vdev_create:
wlan_objmgr_unregister_pdev_destroy_handler(WLAN_UMAC_COMP_POLICY_MGR,
policy_mgr_pdev_obj_destroy_cb,
NULL);
err_pdev_delete:
wlan_objmgr_unregister_pdev_create_handler(WLAN_UMAC_COMP_POLICY_MGR,
policy_mgr_pdev_obj_create_cb,
NULL);
err_pdev_create:
wlan_objmgr_unregister_psoc_status_handler(WLAN_UMAC_COMP_POLICY_MGR,
policy_mgr_psoc_obj_status_cb,
NULL);
err_psoc_status:
wlan_objmgr_unregister_psoc_destroy_handler(WLAN_UMAC_COMP_POLICY_MGR,
policy_mgr_psoc_obj_destroy_cb,
NULL);
err_psoc_delete:
wlan_objmgr_unregister_psoc_create_handler(WLAN_UMAC_COMP_POLICY_MGR,
policy_mgr_psoc_obj_create_cb,
NULL);
err_psoc_create:
return status;
}
QDF_STATUS policy_mgr_deinit(void)
{
QDF_STATUS status;
status = wlan_objmgr_unregister_psoc_status_handler(
WLAN_UMAC_COMP_POLICY_MGR,
policy_mgr_psoc_obj_status_cb,
NULL);
if (status != QDF_STATUS_SUCCESS)
policy_mgr_err("Failed to deregister psoc obj status cback");
status = wlan_objmgr_unregister_psoc_destroy_handler(
WLAN_UMAC_COMP_POLICY_MGR,
policy_mgr_psoc_obj_destroy_cb,
NULL);
if (status != QDF_STATUS_SUCCESS)
policy_mgr_err("Failed to deregister psoc obj delete cback");
status = wlan_objmgr_unregister_psoc_create_handler(
WLAN_UMAC_COMP_POLICY_MGR,
policy_mgr_psoc_obj_create_cb,
NULL);
if (status != QDF_STATUS_SUCCESS)
policy_mgr_err("Failed to deregister psoc obj create cback");
status = wlan_objmgr_unregister_pdev_destroy_handler(
WLAN_UMAC_COMP_POLICY_MGR,
policy_mgr_pdev_obj_destroy_cb,
NULL);
if (status != QDF_STATUS_SUCCESS)
policy_mgr_err("Failed to deregister pdev obj delete cback");
status = wlan_objmgr_unregister_pdev_create_handler(
WLAN_UMAC_COMP_POLICY_MGR,
policy_mgr_pdev_obj_create_cb,
NULL);
if (status != QDF_STATUS_SUCCESS)
policy_mgr_err("Failed to deregister pdev obj create cback");
status = wlan_objmgr_unregister_vdev_status_handler(
WLAN_UMAC_COMP_POLICY_MGR,
policy_mgr_vdev_obj_status_cb,
NULL);
if (status != QDF_STATUS_SUCCESS)
policy_mgr_err("Failed to deregister vdev obj status cback");
status = wlan_objmgr_unregister_vdev_destroy_handler(
WLAN_UMAC_COMP_POLICY_MGR,
policy_mgr_vdev_obj_destroy_cb,
NULL);
if (status != QDF_STATUS_SUCCESS)
policy_mgr_err("Failed to deregister vdev obj delete cback");
status = wlan_objmgr_unregister_vdev_create_handler(
WLAN_UMAC_COMP_POLICY_MGR,
policy_mgr_vdev_obj_create_cb,
NULL);
if (status != QDF_STATUS_SUCCESS)
policy_mgr_err("Failed to deregister vdev obj create cback");
policy_mgr_info("deregistered callbacks with obj mgr successfully");
return status;
}
QDF_STATUS policy_mgr_psoc_open(struct wlan_objmgr_psoc *psoc)
{
struct policy_mgr_psoc_priv_obj *pm_ctx;
pm_ctx = policy_mgr_get_context(psoc);
if (!pm_ctx) {
policy_mgr_err("Invalid Context");
return QDF_STATUS_E_FAILURE;
}
if (!QDF_IS_STATUS_SUCCESS(qdf_mutex_create(
&pm_ctx->qdf_conc_list_lock))) {
policy_mgr_err("Failed to init qdf_conc_list_lock");
QDF_ASSERT(0);
return QDF_STATUS_E_FAILURE;
}
return QDF_STATUS_SUCCESS;
}
QDF_STATUS policy_mgr_psoc_close(struct wlan_objmgr_psoc *psoc)
{
struct policy_mgr_psoc_priv_obj *pm_ctx;
pm_ctx = policy_mgr_get_context(psoc);
if (!pm_ctx) {
policy_mgr_err("Invalid Context");
return QDF_STATUS_E_FAILURE;
}
if (!QDF_IS_STATUS_SUCCESS(qdf_mutex_destroy(
&pm_ctx->qdf_conc_list_lock))) {
policy_mgr_err("Failed to destroy qdf_conc_list_lock");
QDF_ASSERT(0);
return QDF_STATUS_E_FAILURE;
}
if (pm_ctx->hw_mode.hw_mode_list) {
qdf_mem_free(pm_ctx->hw_mode.hw_mode_list);
pm_ctx->hw_mode.hw_mode_list = NULL;
policy_mgr_info("HW list is freed");
}
if (pm_ctx->sta_ap_intf_check_work_info) {
qdf_cancel_work(&pm_ctx->sta_ap_intf_check_work);
qdf_mem_free(pm_ctx->sta_ap_intf_check_work_info);
pm_ctx->sta_ap_intf_check_work_info = NULL;
}
return QDF_STATUS_SUCCESS;
}
QDF_STATUS policy_mgr_psoc_enable(struct wlan_objmgr_psoc *psoc)
{
QDF_STATUS status;
struct policy_mgr_psoc_priv_obj *pm_ctx;
pm_ctx = policy_mgr_get_context(psoc);
if (!pm_ctx) {
policy_mgr_err("Invalid Context");
return QDF_STATUS_E_FAILURE;
}
policy_mgr_debug("Initializing the policy manager");
/* init pm_conc_connection_list */
qdf_mem_zero(pm_conc_connection_list, sizeof(pm_conc_connection_list));
/* init dbs_opportunistic_timer */
status = qdf_mc_timer_init(&pm_ctx->dbs_opportunistic_timer,
QDF_TIMER_TYPE_SW,
pm_dbs_opportunistic_timer_handler,
(void *)psoc);
if (!QDF_IS_STATUS_SUCCESS(status)) {
policy_mgr_err("Failed to init DBS opportunistic timer");
return status;
}
/* init connection_update_done_evt */
status = policy_mgr_init_connection_update(pm_ctx);
if (!QDF_IS_STATUS_SUCCESS(status)) {
policy_mgr_err("connection_update_done_evt init failed");
return status;
}
status = qdf_event_create(&pm_ctx->opportunistic_update_done_evt);
if (!QDF_IS_STATUS_SUCCESS(status)) {
policy_mgr_err("opportunistic_update_done_evt init failed");
return status;
}
status = qdf_event_create(&pm_ctx->channel_switch_complete_evt);
if (!QDF_IS_STATUS_SUCCESS(status)) {
policy_mgr_err("channel_switch_complete_evt init failed");
return status;
}
pm_ctx->do_hw_mode_change = false;
pm_ctx->hw_mode_change_in_progress = POLICY_MGR_HW_MODE_NOT_IN_PROGRESS;
/* reset sap mandatory channels */
status = policy_mgr_reset_sap_mandatory_channels(pm_ctx);
if (QDF_IS_STATUS_ERROR(status)) {
policy_mgr_err("failed to reset mandatory channels");
return status;
}
/* init PCL table & function pointers based on HW capability */
if (policy_mgr_is_hw_dbs_2x2_capable(psoc))
policy_mgr_get_current_pref_hw_mode_ptr =
policy_mgr_get_current_pref_hw_mode_dbs_2x2;
else if (policy_mgr_is_2x2_1x1_dbs_capable(psoc))
policy_mgr_get_current_pref_hw_mode_ptr =
policy_mgr_get_current_pref_hw_mode_dual_dbs;
else
policy_mgr_get_current_pref_hw_mode_ptr =
policy_mgr_get_current_pref_hw_mode_dbs_1x1;
if (policy_mgr_is_hw_dbs_2x2_capable(psoc) ||
policy_mgr_is_2x2_1x1_dbs_capable(psoc))
second_connection_pcl_dbs_table =
&pm_second_connection_pcl_dbs_2x2_table;
else
second_connection_pcl_dbs_table =
&pm_second_connection_pcl_dbs_1x1_table;
if (policy_mgr_is_hw_dbs_2x2_capable(psoc) ||
policy_mgr_is_2x2_1x1_dbs_capable(psoc))
third_connection_pcl_dbs_table =
&pm_third_connection_pcl_dbs_2x2_table;
else
third_connection_pcl_dbs_table =
&pm_third_connection_pcl_dbs_1x1_table;
if (policy_mgr_is_hw_dbs_2x2_capable(psoc)) {
next_action_two_connection_table =
&pm_next_action_two_connection_dbs_2x2_table;
} else if (policy_mgr_is_2x2_1x1_dbs_capable(psoc)) {
next_action_two_connection_table =
&pm_next_action_two_connection_dbs_2x2_5g_1x1_2g_table;
next_action_two_connection_2x2_2g_1x1_5g_table =
&pm_next_action_two_connection_dbs_2x2_2g_1x1_5g_table;
} else {
next_action_two_connection_table =
&pm_next_action_two_connection_dbs_1x1_table;
}
if (policy_mgr_is_hw_dbs_2x2_capable(psoc)) {
next_action_three_connection_table =
&pm_next_action_three_connection_dbs_2x2_table;
} else if (policy_mgr_is_2x2_1x1_dbs_capable(psoc)) {
next_action_three_connection_table =
&pm_next_action_three_connection_dbs_2x2_5g_1x1_2g_table;
next_action_three_connection_2x2_2g_1x1_5g_table =
&pm_next_action_three_connection_dbs_2x2_2g_1x1_5g_table;
} else {
next_action_three_connection_table =
&pm_next_action_three_connection_dbs_1x1_table;
}
policy_mgr_debug("is DBS Capable %d, is SBS Capable %d",
policy_mgr_is_hw_dbs_capable(psoc),
policy_mgr_is_hw_sbs_capable(psoc));
policy_mgr_debug("is2x2 %d, is2x2+1x1 %d, is2x2_5g+1x1_2g %d, is2x2_2g+1x1_5g %d",
policy_mgr_is_hw_dbs_2x2_capable(psoc),
policy_mgr_is_2x2_1x1_dbs_capable(psoc),
policy_mgr_is_2x2_5G_1x1_2G_dbs_capable(psoc),
policy_mgr_is_2x2_2G_1x1_5G_dbs_capable(psoc));
return QDF_STATUS_SUCCESS;
}
QDF_STATUS policy_mgr_psoc_disable(struct wlan_objmgr_psoc *psoc)
{
QDF_STATUS status = QDF_STATUS_SUCCESS;
struct policy_mgr_psoc_priv_obj *pm_ctx;
pm_ctx = policy_mgr_get_context(psoc);
if (!pm_ctx) {
policy_mgr_err("Invalid Context");
return QDF_STATUS_E_FAILURE;
}
/* destroy connection_update_done_evt */
if (!QDF_IS_STATUS_SUCCESS(qdf_event_destroy
(&pm_ctx->connection_update_done_evt))) {
policy_mgr_err("Failed to destroy connection_update_done_evt");
status = QDF_STATUS_E_FAILURE;
QDF_ASSERT(0);
}
/* destroy opportunistic_update_done_evt */
if (!QDF_IS_STATUS_SUCCESS(qdf_event_destroy
(&pm_ctx->opportunistic_update_done_evt))) {
policy_mgr_err("Failed to destroy opportunistic_update_done_evt");
status = QDF_STATUS_E_FAILURE;
QDF_ASSERT(0);
}
/* destroy channel_switch_complete_evt */
if (!QDF_IS_STATUS_SUCCESS(qdf_event_destroy
(&pm_ctx->channel_switch_complete_evt))) {
policy_mgr_err("Failed to destroy channel_switch_complete evt");
status = QDF_STATUS_E_FAILURE;
QDF_ASSERT(0);
}
/* deallocate dbs_opportunistic_timer */
if (QDF_TIMER_STATE_RUNNING ==
qdf_mc_timer_get_current_state(
&pm_ctx->dbs_opportunistic_timer)) {
qdf_mc_timer_stop(&pm_ctx->dbs_opportunistic_timer);
}
if (!QDF_IS_STATUS_SUCCESS(qdf_mc_timer_destroy(
&pm_ctx->dbs_opportunistic_timer))) {
policy_mgr_err("Cannot deallocate dbs opportunistic timer");
status = QDF_STATUS_E_FAILURE;
QDF_ASSERT(0);
}
/* reset sap mandatory channels */
if (QDF_IS_STATUS_ERROR(
policy_mgr_reset_sap_mandatory_channels(pm_ctx))) {
policy_mgr_err("failed to reset sap mandatory channels");
status = QDF_STATUS_E_FAILURE;
QDF_ASSERT(0);
}
/* deinit pm_conc_connection_list */
qdf_mem_zero(pm_conc_connection_list, sizeof(pm_conc_connection_list));
return status;
}
QDF_STATUS policy_mgr_register_sme_cb(struct wlan_objmgr_psoc *psoc,
struct policy_mgr_sme_cbacks *sme_cbacks)
{
struct policy_mgr_psoc_priv_obj *pm_ctx;
pm_ctx = policy_mgr_get_context(psoc);
if (!pm_ctx) {
policy_mgr_err("Invalid Context");
return QDF_STATUS_E_FAILURE;
}
pm_ctx->sme_cbacks.sme_get_nss_for_vdev =
sme_cbacks->sme_get_nss_for_vdev;
pm_ctx->sme_cbacks.sme_get_valid_channels =
sme_cbacks->sme_get_valid_channels;
pm_ctx->sme_cbacks.sme_nss_update_request =
sme_cbacks->sme_nss_update_request;
pm_ctx->sme_cbacks.sme_pdev_set_hw_mode =
sme_cbacks->sme_pdev_set_hw_mode;
pm_ctx->sme_cbacks.sme_pdev_set_pcl =
sme_cbacks->sme_pdev_set_pcl;
pm_ctx->sme_cbacks.sme_soc_set_dual_mac_config =
sme_cbacks->sme_soc_set_dual_mac_config;
pm_ctx->sme_cbacks.sme_change_mcc_beacon_interval =
sme_cbacks->sme_change_mcc_beacon_interval;
pm_ctx->sme_cbacks.sme_get_ap_channel_from_scan =
sme_cbacks->sme_get_ap_channel_from_scan;
pm_ctx->sme_cbacks.sme_scan_result_purge =
sme_cbacks->sme_scan_result_purge;
return QDF_STATUS_SUCCESS;
}
/**
* policy_mgr_register_hdd_cb() - register HDD callbacks
* @psoc: PSOC object information
* @hdd_cbacks: function pointers from HDD
*
* API, allows HDD to register callbacks to be invoked by policy
* mgr
*
* Return: SUCCESS,
* Failure (if registration fails)
*/
QDF_STATUS policy_mgr_register_hdd_cb(struct wlan_objmgr_psoc *psoc,
struct policy_mgr_hdd_cbacks *hdd_cbacks)
{
struct policy_mgr_psoc_priv_obj *pm_ctx;
pm_ctx = policy_mgr_get_context(psoc);
if (!pm_ctx) {
policy_mgr_err("Invalid Context");
return QDF_STATUS_E_FAILURE;
}
pm_ctx->hdd_cbacks.sap_restart_chan_switch_cb =
hdd_cbacks->sap_restart_chan_switch_cb;
pm_ctx->hdd_cbacks.wlan_hdd_get_channel_for_sap_restart =
hdd_cbacks->wlan_hdd_get_channel_for_sap_restart;
pm_ctx->hdd_cbacks.get_mode_for_non_connected_vdev =
hdd_cbacks->get_mode_for_non_connected_vdev;
pm_ctx->hdd_cbacks.hdd_get_device_mode =
hdd_cbacks->hdd_get_device_mode;
pm_ctx->hdd_cbacks.hdd_wapi_security_sta_exist =
hdd_cbacks->hdd_wapi_security_sta_exist;
return QDF_STATUS_SUCCESS;
}
QDF_STATUS policy_mgr_deregister_hdd_cb(struct wlan_objmgr_psoc *psoc)
{
struct policy_mgr_psoc_priv_obj *pm_ctx;
pm_ctx = policy_mgr_get_context(psoc);
if (!pm_ctx) {
policy_mgr_err("Invalid Context");
return QDF_STATUS_E_FAILURE;
}
pm_ctx->hdd_cbacks.sap_restart_chan_switch_cb = NULL;
pm_ctx->hdd_cbacks.wlan_hdd_get_channel_for_sap_restart = NULL;
pm_ctx->hdd_cbacks.get_mode_for_non_connected_vdev = NULL;
pm_ctx->hdd_cbacks.hdd_get_device_mode = NULL;
return QDF_STATUS_SUCCESS;
}
QDF_STATUS policy_mgr_register_wma_cb(struct wlan_objmgr_psoc *psoc,
struct policy_mgr_wma_cbacks *wma_cbacks)
{
struct policy_mgr_psoc_priv_obj *pm_ctx;
pm_ctx = policy_mgr_get_context(psoc);
if (!pm_ctx) {
policy_mgr_err("Invalid Context");
return QDF_STATUS_E_FAILURE;
}
pm_ctx->wma_cbacks.wma_get_connection_info =
wma_cbacks->wma_get_connection_info;
return QDF_STATUS_SUCCESS;
}
QDF_STATUS policy_mgr_register_cdp_cb(struct wlan_objmgr_psoc *psoc,
struct policy_mgr_cdp_cbacks *cdp_cbacks)
{
struct policy_mgr_psoc_priv_obj *pm_ctx;
pm_ctx = policy_mgr_get_context(psoc);
if (!pm_ctx) {
policy_mgr_err("Invalid Context");
return QDF_STATUS_E_FAILURE;
}
pm_ctx->cdp_cbacks.cdp_update_mac_id =
cdp_cbacks->cdp_update_mac_id;
return QDF_STATUS_SUCCESS;
}
QDF_STATUS policy_mgr_register_dp_cb(struct wlan_objmgr_psoc *psoc,
struct policy_mgr_dp_cbacks *dp_cbacks)
{
struct policy_mgr_psoc_priv_obj *pm_ctx;
pm_ctx = policy_mgr_get_context(psoc);
if (!pm_ctx) {
policy_mgr_err("Invalid Context");
return QDF_STATUS_E_FAILURE;
}
pm_ctx->dp_cbacks.hdd_disable_rx_ol_in_concurrency =
dp_cbacks->hdd_disable_rx_ol_in_concurrency;
pm_ctx->dp_cbacks.hdd_set_rx_mode_rps_cb =
dp_cbacks->hdd_set_rx_mode_rps_cb;
pm_ctx->dp_cbacks.hdd_ipa_set_mcc_mode_cb =
dp_cbacks->hdd_ipa_set_mcc_mode_cb;
pm_ctx->dp_cbacks.hdd_v2_flow_pool_map =
dp_cbacks->hdd_v2_flow_pool_map;
pm_ctx->dp_cbacks.hdd_v2_flow_pool_unmap =
dp_cbacks->hdd_v2_flow_pool_unmap;
return QDF_STATUS_SUCCESS;
}
QDF_STATUS policy_mgr_register_tdls_cb(struct wlan_objmgr_psoc *psoc,
struct policy_mgr_tdls_cbacks *tdls_cbacks)
{
struct policy_mgr_psoc_priv_obj *pm_ctx;
pm_ctx = policy_mgr_get_context(psoc);
if (!pm_ctx) {
policy_mgr_err("Invalid Context");
return QDF_STATUS_E_FAILURE;
}
pm_ctx->tdls_cbacks.tdls_notify_increment_session =
tdls_cbacks->tdls_notify_increment_session;
pm_ctx->tdls_cbacks.tdls_notify_decrement_session =
tdls_cbacks->tdls_notify_decrement_session;
return QDF_STATUS_SUCCESS;
}
QDF_STATUS policy_mgr_register_mode_change_cb(struct wlan_objmgr_psoc *psoc,
send_mode_change_event_cb mode_change_cb)
{
struct policy_mgr_psoc_priv_obj *pm_ctx;
pm_ctx = policy_mgr_get_context(psoc);
if (!pm_ctx) {
policy_mgr_err("Invalid Context");
return QDF_STATUS_E_FAILURE;
}
pm_ctx->mode_change_cb = mode_change_cb;
return QDF_STATUS_SUCCESS;
}
QDF_STATUS policy_mgr_deregister_mode_change_cb(struct wlan_objmgr_psoc *psoc)
{
struct policy_mgr_psoc_priv_obj *pm_ctx;
pm_ctx = policy_mgr_get_context(psoc);
if (!pm_ctx) {
policy_mgr_err("Invalid Context");
return QDF_STATUS_E_FAILURE;
}
pm_ctx->mode_change_cb = NULL;
return QDF_STATUS_SUCCESS;
}

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,154 @@
/*
* Copyright (c) 2012-2018 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.
*/
#ifndef __WLAN_POLICY_MGR_TABLES_2X2_2G_1X1_5G_DBS_H
#define __WLAN_POLICY_MGR_TABLES_2X2_2G_1X1_5G_DBS_H
#include "wlan_policy_mgr_api.h"
/**
* next_action_two_connection_table - table which provides next
* action while a new connection is coming up, with one
* connection already in the system
*/
static policy_mgr_next_action_two_connection_table_type
pm_next_action_two_connection_dbs_2x2_2g_1x1_5g_table = {
[PM_STA_24_1x1] = {PM_NOP, PM_DBS2},
[PM_STA_24_2x2] = {PM_NOP, PM_DBS2},
[PM_STA_5_1x1] = {PM_DBS2, PM_NOP},
[PM_STA_5_2x2] = {PM_DBS2, PM_NOP},
[PM_P2P_CLI_24_1x1] = {PM_NOP, PM_DBS2},
[PM_P2P_CLI_24_2x2] = {PM_NOP, PM_DBS2},
[PM_P2P_CLI_5_1x1] = {PM_DBS2, PM_NOP},
[PM_P2P_CLI_5_2x2] = {PM_DBS2, PM_NOP},
[PM_P2P_GO_24_1x1] = {PM_NOP, PM_DBS2},
[PM_P2P_GO_24_2x2] = {PM_NOP, PM_DBS2},
[PM_P2P_GO_5_1x1] = {PM_DBS2, PM_NOP},
[PM_P2P_GO_5_2x2] = {PM_DBS2_DOWNGRADE, PM_NOP},
[PM_SAP_24_1x1] = {PM_NOP, PM_DBS2},
[PM_SAP_24_2x2] = {PM_NOP, PM_DBS2},
[PM_SAP_5_1x1] = {PM_DBS2, PM_NOP},
[PM_SAP_5_2x2] = {PM_DBS2_DOWNGRADE, PM_NOP},
[PM_IBSS_24_1x1] = {PM_NOP, PM_DBS2},
[PM_IBSS_24_2x2] = {PM_NOP, PM_DBS2},
[PM_IBSS_5_1x1] = {PM_DBS2, PM_NOP},
[PM_IBSS_5_2x2] = {PM_DBS2_DOWNGRADE, PM_NOP},
};
/**
* next_action_three_connection_table - table which provides next
* action while a new connection is coming up, with two
* connections already in the system
*/
static policy_mgr_next_action_three_connection_table_type
pm_next_action_three_connection_dbs_2x2_2g_1x1_5g_table = {
[PM_STA_SAP_SCC_24_1x1] = {PM_NOP, PM_DBS2},
[PM_STA_SAP_SCC_24_2x2] = {PM_NOP, PM_DBS2},
[PM_STA_SAP_MCC_24_1x1] = {PM_NOP, PM_DBS2},
[PM_STA_SAP_MCC_24_2x2] = {PM_NOP, PM_DBS2},
[PM_STA_SAP_SCC_5_1x1] = {PM_DBS2, PM_NOP},
[PM_STA_SAP_SCC_5_2x2] = {PM_DBS2_DOWNGRADE, PM_NOP},
[PM_STA_SAP_MCC_5_1x1] = {PM_DBS2, PM_NOP},
[PM_STA_SAP_MCC_5_2x2] = {PM_DBS2_DOWNGRADE, PM_NOP},
[PM_STA_SAP_MCC_24_5_1x1] = {PM_DBS2_DOWNGRADE, PM_DBS2_DOWNGRADE},
[PM_STA_SAP_MCC_24_5_2x2] = {PM_DBS2_DOWNGRADE, PM_DBS2_DOWNGRADE},
[PM_STA_SAP_DBS_1x1] = {PM_DBS2_DOWNGRADE, PM_DBS2_DOWNGRADE},
[PM_STA_SAP_DBS_2x2] = {PM_DBS2_DOWNGRADE, PM_DBS2_DOWNGRADE},
[PM_STA_P2P_GO_SCC_24_1x1] = {PM_NOP, PM_DBS2},
[PM_STA_P2P_GO_SCC_24_2x2] = {PM_NOP, PM_DBS2},
[PM_STA_P2P_GO_MCC_24_1x1] = {PM_NOP, PM_DBS2},
[PM_STA_P2P_GO_MCC_24_2x2] = {PM_NOP, PM_DBS2},
[PM_STA_P2P_GO_SCC_5_1x1] = {PM_DBS2, PM_NOP},
[PM_STA_P2P_GO_SCC_5_2x2] = {PM_DBS2_DOWNGRADE, PM_NOP},
[PM_STA_P2P_GO_MCC_5_1x1] = {PM_DBS2, PM_NOP},
[PM_STA_P2P_GO_MCC_5_2x2] = {PM_DBS2_DOWNGRADE, PM_NOP},
[PM_STA_P2P_GO_MCC_24_5_1x1] = {PM_DBS2_DOWNGRADE, PM_DBS2_DOWNGRADE},
[PM_STA_P2P_GO_MCC_24_5_2x2] = {PM_DBS2_DOWNGRADE, PM_DBS2_DOWNGRADE},
[PM_STA_P2P_GO_DBS_1x1] = {PM_DBS2_DOWNGRADE, PM_DBS2_DOWNGRADE},
[PM_STA_P2P_GO_DBS_2x2] = {PM_DBS2_DOWNGRADE, PM_DBS2_DOWNGRADE},
[PM_STA_P2P_CLI_SCC_24_1x1] = {PM_NOP, PM_DBS2},
[PM_STA_P2P_CLI_SCC_24_2x2] = {PM_NOP, PM_DBS2},
[PM_STA_P2P_CLI_MCC_24_1x1] = {PM_NOP, PM_DBS2},
[PM_STA_P2P_CLI_MCC_24_2x2] = {PM_NOP, PM_DBS2},
[PM_STA_P2P_CLI_SCC_5_1x1] = {PM_DBS2, PM_NOP},
[PM_STA_P2P_CLI_SCC_5_2x2] = {PM_DBS2, PM_NOP},
[PM_STA_P2P_CLI_MCC_5_1x1] = {PM_DBS2, PM_NOP},
[PM_STA_P2P_CLI_MCC_5_2x2] = {PM_DBS2, PM_NOP},
[PM_STA_P2P_CLI_MCC_24_5_1x1] = {PM_NOP, PM_DBS2},
[PM_STA_P2P_CLI_MCC_24_5_2x2] = {PM_NOP, PM_DBS2},
[PM_STA_P2P_CLI_DBS_1x1] = {PM_NOP, PM_DBS2},
[PM_STA_P2P_CLI_DBS_2x2] = {PM_NOP, PM_DBS2},
[PM_P2P_GO_P2P_CLI_SCC_24_1x1] = {PM_NOP, PM_DBS2},
[PM_P2P_GO_P2P_CLI_SCC_24_2x2] = {PM_NOP, PM_DBS2},
[PM_P2P_GO_P2P_CLI_MCC_24_1x1] = {PM_NOP, PM_DBS2},
[PM_P2P_GO_P2P_CLI_MCC_24_2x2] = {PM_NOP, PM_DBS2},
[PM_P2P_GO_P2P_CLI_SCC_5_1x1] = {PM_DBS2, PM_NOP},
[PM_P2P_GO_P2P_CLI_SCC_5_2x2] = {PM_DBS2_DOWNGRADE, PM_NOP},
[PM_P2P_GO_P2P_CLI_MCC_5_1x1] = {PM_DBS2, PM_NOP},
[PM_P2P_GO_P2P_CLI_MCC_5_2x2] = {PM_DBS2_DOWNGRADE, PM_NOP},
[PM_P2P_GO_P2P_CLI_MCC_24_5_1x1] = {PM_DBS2_DOWNGRADE,
PM_DBS2_DOWNGRADE},
[PM_P2P_GO_P2P_CLI_MCC_24_5_2x2] = {PM_DBS2_DOWNGRADE,
PM_DBS2_DOWNGRADE},
[PM_P2P_GO_P2P_CLI_DBS_1x1] = {PM_DBS2_DOWNGRADE, PM_DBS2_DOWNGRADE},
[PM_P2P_GO_P2P_CLI_DBS_2x2] = {PM_DBS2_DOWNGRADE, PM_DBS2_DOWNGRADE},
[PM_P2P_GO_SAP_SCC_24_1x1] = {PM_NOP, PM_DBS2},
[PM_P2P_GO_SAP_SCC_24_2x2] = {PM_NOP, PM_DBS2},
[PM_P2P_GO_SAP_MCC_24_1x1] = {PM_NOP, PM_DBS2},
[PM_P2P_GO_SAP_MCC_24_2x2] = {PM_NOP, PM_DBS2},
[PM_P2P_GO_SAP_SCC_5_1x1] = {PM_DBS2, PM_NOP},
[PM_P2P_GO_SAP_SCC_5_2x2] = {PM_DBS2_DOWNGRADE, PM_NOP},
[PM_P2P_GO_SAP_MCC_5_1x1] = {PM_DBS2, PM_NOP},
[PM_P2P_GO_SAP_MCC_5_2x2] = {PM_DBS2_DOWNGRADE, PM_NOP},
[PM_P2P_GO_SAP_MCC_24_5_1x1] = {PM_DBS2_DOWNGRADE, PM_DBS2_DOWNGRADE},
[PM_P2P_GO_SAP_MCC_24_5_2x2] = {PM_DBS2_DOWNGRADE, PM_DBS2_DOWNGRADE},
[PM_P2P_GO_SAP_DBS_1x1] = {PM_DBS2_DOWNGRADE, PM_DBS2_DOWNGRADE},
[PM_P2P_GO_SAP_DBS_2x2] = {PM_DBS2_DOWNGRADE, PM_DBS2_DOWNGRADE},
[PM_P2P_CLI_SAP_SCC_24_1x1] = {PM_NOP, PM_DBS2},
[PM_P2P_CLI_SAP_SCC_24_2x2] = {PM_NOP, PM_DBS2},
[PM_P2P_CLI_SAP_MCC_24_1x1] = {PM_NOP, PM_DBS2},
[PM_P2P_CLI_SAP_MCC_24_2x2] = {PM_NOP, PM_DBS2},
[PM_P2P_CLI_SAP_SCC_5_1x1] = {PM_DBS2, PM_NOP},
[PM_P2P_CLI_SAP_SCC_5_2x2] = {PM_DBS2_DOWNGRADE, PM_NOP},
[PM_P2P_CLI_SAP_MCC_5_1x1] = {PM_DBS2, PM_NOP},
[PM_P2P_CLI_SAP_MCC_5_2x2] = {PM_DBS2_DOWNGRADE, PM_NOP},
[PM_P2P_CLI_SAP_MCC_24_5_1x1] = {PM_DBS2_DOWNGRADE, PM_DBS2_DOWNGRADE},
[PM_P2P_CLI_SAP_MCC_24_5_2x2] = {PM_DBS2_DOWNGRADE, PM_DBS2_DOWNGRADE},
[PM_P2P_CLI_SAP_DBS_1x1] = {PM_DBS2_DOWNGRADE, PM_DBS2_DOWNGRADE},
[PM_P2P_CLI_SAP_DBS_2x2] = {PM_DBS2_DOWNGRADE, PM_DBS2_DOWNGRADE},
[PM_SAP_SAP_SCC_24_1x1] = {PM_NOP, PM_DBS2},
[PM_SAP_SAP_SCC_24_2x2] = {PM_NOP, PM_DBS2},
[PM_SAP_SAP_MCC_24_1x1] = {PM_NOP, PM_DBS2},
[PM_SAP_SAP_MCC_24_2x2] = {PM_NOP, PM_DBS2},
[PM_SAP_SAP_SCC_5_1x1] = {PM_DBS2, PM_NOP},
[PM_SAP_SAP_SCC_5_2x2] = {PM_DBS2_DOWNGRADE, PM_NOP},
[PM_SAP_SAP_MCC_5_1x1] = {PM_DBS2, PM_NOP},
[PM_SAP_SAP_MCC_5_2x2] = {PM_DBS2_DOWNGRADE, PM_NOP},
[PM_SAP_SAP_MCC_24_5_1x1] = {PM_DBS2_DOWNGRADE, PM_DBS2_DOWNGRADE},
[PM_SAP_SAP_MCC_24_5_2x2] = {PM_DBS2_DOWNGRADE, PM_DBS2_DOWNGRADE},
[PM_SAP_SAP_DBS_1x1] = {PM_DBS2_DOWNGRADE, PM_DBS2_DOWNGRADE},
[PM_SAP_SAP_DBS_2x2] = {PM_DBS2_DOWNGRADE, PM_DBS2_DOWNGRADE},
};
#endif

View file

@ -0,0 +1,154 @@
/*
* Copyright (c) 2012-2018 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.
*/
#ifndef __WLAN_POLICY_MGR_TABLES_2X2_5G_1X1_2G_DBS_H
#define __WLAN_POLICY_MGR_TABLES_2X2_5G_1X1_2G_DBS_H
#include "wlan_policy_mgr_api.h"
/**
* next_action_two_connection_table - table which provides next
* action while a new connection is coming up, with one
* connection already in the system
*/
static policy_mgr_next_action_two_connection_table_type
pm_next_action_two_connection_dbs_2x2_5g_1x1_2g_table = {
[PM_STA_24_1x1] = {PM_NOP, PM_DBS1},
[PM_STA_24_2x2] = {PM_NOP, PM_DBS1},
[PM_STA_5_1x1] = {PM_DBS1, PM_NOP},
[PM_STA_5_2x2] = {PM_DBS1, PM_NOP},
[PM_P2P_CLI_24_1x1] = {PM_NOP, PM_DBS1},
[PM_P2P_CLI_24_2x2] = {PM_NOP, PM_DBS1},
[PM_P2P_CLI_5_1x1] = {PM_DBS1, PM_NOP},
[PM_P2P_CLI_5_2x2] = {PM_DBS1, PM_NOP},
[PM_P2P_GO_24_1x1] = {PM_NOP, PM_DBS1},
[PM_P2P_GO_24_2x2] = {PM_NOP, PM_DBS1_DOWNGRADE},
[PM_P2P_GO_5_1x1] = {PM_DBS1, PM_NOP},
[PM_P2P_GO_5_2x2] = {PM_DBS1, PM_NOP},
[PM_SAP_24_1x1] = {PM_NOP, PM_DBS1},
[PM_SAP_24_2x2] = {PM_NOP, PM_DBS1_DOWNGRADE},
[PM_SAP_5_1x1] = {PM_DBS1, PM_NOP},
[PM_SAP_5_2x2] = {PM_DBS1, PM_NOP},
[PM_IBSS_24_1x1] = {PM_NOP, PM_DBS1},
[PM_IBSS_24_2x2] = {PM_NOP, PM_DBS1_DOWNGRADE},
[PM_IBSS_5_1x1] = {PM_DBS1, PM_NOP},
[PM_IBSS_5_2x2] = {PM_DBS1, PM_NOP},
};
/**
* next_action_three_connection_table - table which provides next
* action while a new connection is coming up, with two
* connections already in the system
*/
static policy_mgr_next_action_three_connection_table_type
pm_next_action_three_connection_dbs_2x2_5g_1x1_2g_table = {
[PM_STA_SAP_SCC_24_1x1] = {PM_NOP, PM_DBS1},
[PM_STA_SAP_SCC_24_2x2] = {PM_NOP, PM_DBS1_DOWNGRADE},
[PM_STA_SAP_MCC_24_1x1] = {PM_NOP, PM_DBS1},
[PM_STA_SAP_MCC_24_2x2] = {PM_NOP, PM_DBS1_DOWNGRADE},
[PM_STA_SAP_SCC_5_1x1] = {PM_DBS1, PM_NOP},
[PM_STA_SAP_SCC_5_2x2] = {PM_DBS1, PM_NOP},
[PM_STA_SAP_MCC_5_1x1] = {PM_DBS1, PM_NOP},
[PM_STA_SAP_MCC_5_2x2] = {PM_DBS1, PM_NOP},
[PM_STA_SAP_MCC_24_5_1x1] = {PM_DBS1_DOWNGRADE, PM_DBS1_DOWNGRADE},
[PM_STA_SAP_MCC_24_5_2x2] = {PM_DBS1_DOWNGRADE, PM_DBS1_DOWNGRADE},
[PM_STA_SAP_DBS_1x1] = {PM_DBS1_DOWNGRADE, PM_DBS1_DOWNGRADE},
[PM_STA_SAP_DBS_2x2] = {PM_DBS1_DOWNGRADE, PM_DBS1_DOWNGRADE},
[PM_STA_P2P_GO_SCC_24_1x1] = {PM_NOP, PM_DBS1},
[PM_STA_P2P_GO_SCC_24_2x2] = {PM_NOP, PM_DBS1_DOWNGRADE},
[PM_STA_P2P_GO_MCC_24_1x1] = {PM_NOP, PM_DBS1},
[PM_STA_P2P_GO_MCC_24_2x2] = {PM_NOP, PM_DBS1_DOWNGRADE},
[PM_STA_P2P_GO_SCC_5_1x1] = {PM_DBS1, PM_NOP},
[PM_STA_P2P_GO_SCC_5_2x2] = {PM_DBS1, PM_NOP},
[PM_STA_P2P_GO_MCC_5_1x1] = {PM_DBS1, PM_NOP},
[PM_STA_P2P_GO_MCC_5_2x2] = {PM_DBS1, PM_NOP},
[PM_STA_P2P_GO_MCC_24_5_1x1] = {PM_DBS1_DOWNGRADE, PM_DBS1_DOWNGRADE},
[PM_STA_P2P_GO_MCC_24_5_2x2] = {PM_DBS1_DOWNGRADE, PM_DBS1_DOWNGRADE},
[PM_STA_P2P_GO_DBS_1x1] = {PM_DBS1_DOWNGRADE, PM_DBS1_DOWNGRADE},
[PM_STA_P2P_GO_DBS_2x2] = {PM_DBS1_DOWNGRADE, PM_DBS1_DOWNGRADE},
[PM_STA_P2P_CLI_SCC_24_1x1] = {PM_NOP, PM_DBS1},
[PM_STA_P2P_CLI_SCC_24_2x2] = {PM_NOP, PM_DBS1},
[PM_STA_P2P_CLI_MCC_24_1x1] = {PM_NOP, PM_DBS1},
[PM_STA_P2P_CLI_MCC_24_2x2] = {PM_NOP, PM_DBS1},
[PM_STA_P2P_CLI_SCC_5_1x1] = {PM_DBS1, PM_NOP},
[PM_STA_P2P_CLI_SCC_5_2x2] = {PM_DBS1, PM_NOP},
[PM_STA_P2P_CLI_MCC_5_1x1] = {PM_DBS1, PM_NOP},
[PM_STA_P2P_CLI_MCC_5_2x2] = {PM_DBS1, PM_NOP},
[PM_STA_P2P_CLI_MCC_24_5_1x1] = {PM_DBS1, PM_DBS1},
[PM_STA_P2P_CLI_MCC_24_5_2x2] = {PM_DBS1, PM_DBS1},
[PM_STA_P2P_CLI_DBS_1x1] = {PM_DBS1, PM_DBS1},
[PM_STA_P2P_CLI_DBS_2x2] = {PM_DBS1, PM_DBS1},
[PM_P2P_GO_P2P_CLI_SCC_24_1x1] = {PM_NOP, PM_DBS1},
[PM_P2P_GO_P2P_CLI_SCC_24_2x2] = {PM_NOP, PM_DBS1_DOWNGRADE},
[PM_P2P_GO_P2P_CLI_MCC_24_1x1] = {PM_NOP, PM_DBS1},
[PM_P2P_GO_P2P_CLI_MCC_24_2x2] = {PM_NOP, PM_DBS1_DOWNGRADE},
[PM_P2P_GO_P2P_CLI_SCC_5_1x1] = {PM_DBS1, PM_NOP},
[PM_P2P_GO_P2P_CLI_SCC_5_2x2] = {PM_DBS1, PM_NOP},
[PM_P2P_GO_P2P_CLI_MCC_5_1x1] = {PM_DBS1, PM_NOP},
[PM_P2P_GO_P2P_CLI_MCC_5_2x2] = {PM_DBS1, PM_NOP},
[PM_P2P_GO_P2P_CLI_MCC_24_5_1x1] = {PM_DBS1_DOWNGRADE,
PM_DBS1_DOWNGRADE},
[PM_P2P_GO_P2P_CLI_MCC_24_5_2x2] = {PM_DBS1_DOWNGRADE,
PM_DBS1_DOWNGRADE},
[PM_P2P_GO_P2P_CLI_DBS_1x1] = {PM_DBS1_DOWNGRADE, PM_DBS1_DOWNGRADE},
[PM_P2P_GO_P2P_CLI_DBS_2x2] = {PM_DBS1_DOWNGRADE, PM_DBS1_DOWNGRADE},
[PM_P2P_GO_SAP_SCC_24_1x1] = {PM_NOP, PM_DBS1},
[PM_P2P_GO_SAP_SCC_24_2x2] = {PM_NOP, PM_DBS1_DOWNGRADE},
[PM_P2P_GO_SAP_MCC_24_1x1] = {PM_NOP, PM_DBS1},
[PM_P2P_GO_SAP_MCC_24_2x2] = {PM_NOP, PM_DBS1_DOWNGRADE},
[PM_P2P_GO_SAP_SCC_5_1x1] = {PM_DBS1, PM_NOP},
[PM_P2P_GO_SAP_SCC_5_2x2] = {PM_DBS1, PM_NOP},
[PM_P2P_GO_SAP_MCC_5_1x1] = {PM_DBS1, PM_NOP},
[PM_P2P_GO_SAP_MCC_5_2x2] = {PM_DBS1, PM_NOP},
[PM_P2P_GO_SAP_MCC_24_5_1x1] = {PM_DBS1_DOWNGRADE, PM_DBS1_DOWNGRADE},
[PM_P2P_GO_SAP_MCC_24_5_2x2] = {PM_DBS1_DOWNGRADE, PM_DBS1_DOWNGRADE},
[PM_P2P_GO_SAP_DBS_1x1] = {PM_DBS1_DOWNGRADE, PM_DBS1_DOWNGRADE},
[PM_P2P_GO_SAP_DBS_2x2] = {PM_DBS1_DOWNGRADE, PM_DBS1_DOWNGRADE},
[PM_P2P_CLI_SAP_SCC_24_1x1] = {PM_NOP, PM_DBS1},
[PM_P2P_CLI_SAP_SCC_24_2x2] = {PM_NOP, PM_DBS1_DOWNGRADE},
[PM_P2P_CLI_SAP_MCC_24_1x1] = {PM_NOP, PM_DBS1},
[PM_P2P_CLI_SAP_MCC_24_2x2] = {PM_NOP, PM_DBS1_DOWNGRADE},
[PM_P2P_CLI_SAP_SCC_5_1x1] = {PM_DBS1, PM_NOP},
[PM_P2P_CLI_SAP_SCC_5_2x2] = {PM_DBS1, PM_NOP},
[PM_P2P_CLI_SAP_MCC_5_1x1] = {PM_DBS1, PM_NOP},
[PM_P2P_CLI_SAP_MCC_5_2x2] = {PM_DBS1, PM_NOP},
[PM_P2P_CLI_SAP_MCC_24_5_1x1] = {PM_DBS1_DOWNGRADE, PM_DBS1_DOWNGRADE},
[PM_P2P_CLI_SAP_MCC_24_5_2x2] = {PM_DBS1_DOWNGRADE, PM_DBS1_DOWNGRADE},
[PM_P2P_CLI_SAP_DBS_1x1] = {PM_DBS1_DOWNGRADE, PM_DBS1_DOWNGRADE},
[PM_P2P_CLI_SAP_DBS_2x2] = {PM_DBS1_DOWNGRADE, PM_DBS1_DOWNGRADE},
[PM_SAP_SAP_SCC_24_1x1] = {PM_NOP, PM_DBS1},
[PM_SAP_SAP_SCC_24_2x2] = {PM_NOP, PM_DBS1_DOWNGRADE},
[PM_SAP_SAP_MCC_24_1x1] = {PM_NOP, PM_DBS1},
[PM_SAP_SAP_MCC_24_2x2] = {PM_NOP, PM_DBS1_DOWNGRADE},
[PM_SAP_SAP_SCC_5_1x1] = {PM_DBS1, PM_NOP},
[PM_SAP_SAP_SCC_5_2x2] = {PM_DBS1, PM_NOP},
[PM_SAP_SAP_MCC_5_1x1] = {PM_DBS1, PM_NOP},
[PM_SAP_SAP_MCC_5_2x2] = {PM_DBS1, PM_NOP},
[PM_SAP_SAP_MCC_24_5_1x1] = {PM_DBS1_DOWNGRADE, PM_DBS1_DOWNGRADE},
[PM_SAP_SAP_MCC_24_5_2x2] = {PM_DBS1_DOWNGRADE, PM_DBS1_DOWNGRADE},
[PM_SAP_SAP_DBS_1x1] = {PM_DBS1_DOWNGRADE, PM_DBS1_DOWNGRADE},
[PM_SAP_SAP_DBS_2x2] = {PM_DBS1_DOWNGRADE, PM_DBS1_DOWNGRADE},
};
#endif

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,900 @@
/*
* Copyright (c) 2012-2017 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.
*/
#ifndef __WLAN_POLICY_MGR_TABLES_NO_DBS_H
#define __WLAN_POLICY_MGR_TABLES_NO_DBS_H
#include "wlan_policy_mgr_api.h"
/**
* second_connection_pcl_nodbs_table - table which provides PCL
* for the 2nd connection, when we have a connection already in
* the system (with DBS not supported by HW)
*/
static const enum policy_mgr_pcl_type
second_connection_pcl_nodbs_table[PM_MAX_ONE_CONNECTION_MODE]
[PM_MAX_NUM_OF_MODE][PM_MAX_CONC_PRIORITY_MODE] = {
[PM_STA_24_1x1] = {
[PM_STA_MODE] = {PM_5G, PM_SCC_CH, PM_SCC_CH},
[PM_SAP_MODE] = {PM_SCC_CH_5G, PM_SCC_CH, PM_SCC_CH_5G},
[PM_P2P_CLIENT_MODE] = {PM_SCC_CH, PM_SCC_CH, PM_SCC_CH_5G},
[PM_P2P_GO_MODE] = {PM_SCC_CH, PM_SCC_CH, PM_SCC_CH_5G},
[PM_IBSS_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE} },
[PM_STA_24_2x2] = {
[PM_STA_MODE] = {PM_5G, PM_SCC_CH, PM_SCC_CH},
[PM_SAP_MODE] = {PM_SCC_CH_5G, PM_SCC_CH, PM_SCC_CH_5G},
[PM_P2P_CLIENT_MODE] = {PM_SCC_CH, PM_SCC_CH, PM_SCC_CH_5G},
[PM_P2P_GO_MODE] = {PM_SCC_CH, PM_SCC_CH, PM_SCC_CH_5G},
[PM_IBSS_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE} },
[PM_STA_5_1x1] = {
[PM_STA_MODE] = {PM_SCC_CH_5G, PM_SCC_CH, PM_SCC_CH_5G},
[PM_SAP_MODE] = {PM_SCC_CH_5G, PM_SCC_CH, PM_SCC_CH},
[PM_P2P_CLIENT_MODE] = {PM_SCC_CH, PM_SCC_CH, PM_SCC_CH},
[PM_P2P_GO_MODE] = {PM_SCC_CH, PM_SCC_CH, PM_SCC_CH},
[PM_IBSS_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE} },
[PM_STA_5_2x2] = {
[PM_STA_MODE] = {PM_SCC_CH_5G, PM_SCC_CH, PM_SCC_CH_5G},
[PM_SAP_MODE] = {PM_SCC_CH_5G, PM_SCC_CH, PM_SCC_CH},
[PM_P2P_CLIENT_MODE] = {PM_SCC_CH, PM_SCC_CH, PM_SCC_CH},
[PM_P2P_GO_MODE] = {PM_SCC_CH, PM_SCC_CH, PM_SCC_CH},
[PM_IBSS_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE} },
[PM_P2P_CLI_24_1x1] = {
[PM_STA_MODE] = {PM_5G, PM_SCC_CH, PM_SCC_CH},
[PM_SAP_MODE] = {PM_SCC_CH_5G, PM_SCC_CH, PM_SCC_CH_5G},
[PM_P2P_CLIENT_MODE] = {PM_5G, PM_SCC_CH, PM_SCC_CH_5G},
[PM_P2P_GO_MODE] = {PM_5G, PM_SCC_CH, PM_SCC_CH_5G},
[PM_IBSS_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE} },
[PM_P2P_CLI_24_2x2] = {
[PM_STA_MODE] = {PM_5G, PM_SCC_CH, PM_SCC_CH},
[PM_SAP_MODE] = {PM_SCC_CH_5G, PM_SCC_CH, PM_SCC_CH_5G},
[PM_P2P_CLIENT_MODE] = {PM_5G, PM_SCC_CH, PM_SCC_CH_5G},
[PM_P2P_GO_MODE] = {PM_5G, PM_SCC_CH, PM_SCC_CH_5G},
[PM_IBSS_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE} },
[PM_P2P_CLI_5_1x1] = {
[PM_STA_MODE] = {PM_SCC_CH_5G, PM_SCC_CH, PM_SCC_CH_5G},
[PM_SAP_MODE] = {PM_SCC_CH_5G, PM_SCC_CH, PM_SCC_CH},
[PM_P2P_CLIENT_MODE] = {PM_SCC_CH_5G, PM_SCC_CH, PM_SCC_CH},
[PM_P2P_GO_MODE] = {PM_SCC_CH_5G, PM_SCC_CH, PM_SCC_CH},
[PM_IBSS_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE} },
[PM_P2P_CLI_5_2x2] = {
[PM_STA_MODE] = {PM_SCC_CH_5G, PM_SCC_CH, PM_SCC_CH_5G},
[PM_SAP_MODE] = {PM_SCC_CH_5G, PM_SCC_CH, PM_SCC_CH},
[PM_P2P_CLIENT_MODE] = {PM_SCC_CH_5G, PM_SCC_CH, PM_SCC_CH},
[PM_P2P_GO_MODE] = {PM_SCC_CH_5G, PM_SCC_CH, PM_SCC_CH},
[PM_IBSS_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE} },
[PM_P2P_GO_24_1x1] = {
[PM_STA_MODE] = {PM_SCC_CH, PM_SCC_CH, PM_SCC_CH},
[PM_SAP_MODE] = {PM_SCC_CH, PM_SCC_CH, PM_SCC_CH},
[PM_P2P_CLIENT_MODE] = {PM_SCC_CH, PM_SCC_CH, PM_SCC_CH},
[PM_P2P_GO_MODE] = {PM_SCC_CH, PM_SCC_CH, PM_SCC_CH},
[PM_IBSS_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE} },
[PM_P2P_GO_24_2x2] = {
[PM_STA_MODE] = {PM_SCC_CH, PM_SCC_CH, PM_SCC_CH},
[PM_SAP_MODE] = {PM_SCC_CH, PM_SCC_CH, PM_SCC_CH},
[PM_P2P_CLIENT_MODE] = {PM_SCC_CH, PM_SCC_CH, PM_SCC_CH},
[PM_P2P_GO_MODE] = {PM_SCC_CH, PM_SCC_CH, PM_SCC_CH},
[PM_IBSS_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE} },
[PM_P2P_GO_5_1x1] = {
[PM_STA_MODE] = {PM_SCC_CH_5G, PM_SCC_CH, PM_SCC_CH},
[PM_SAP_MODE] = {PM_SCC_CH, PM_SCC_CH, PM_SCC_CH},
[PM_P2P_CLIENT_MODE] = {PM_SCC_CH, PM_SCC_CH, PM_SCC_CH},
[PM_P2P_GO_MODE] = {PM_SCC_CH, PM_SCC_CH, PM_SCC_CH},
[PM_IBSS_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE} },
[PM_P2P_GO_5_2x2] = {
[PM_STA_MODE] = {PM_SCC_CH_5G, PM_SCC_CH, PM_SCC_CH},
[PM_SAP_MODE] = {PM_SCC_CH, PM_SCC_CH, PM_SCC_CH},
[PM_P2P_CLIENT_MODE] = {PM_SCC_CH, PM_SCC_CH, PM_SCC_CH},
[PM_P2P_GO_MODE] = {PM_SCC_CH, PM_SCC_CH, PM_SCC_CH},
[PM_IBSS_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE} },
[PM_SAP_24_1x1] = {
[PM_STA_MODE] = {PM_SCC_CH, PM_SCC_CH, PM_SCC_CH},
[PM_SAP_MODE] = {PM_SCC_CH, PM_SCC_CH, PM_SCC_CH},
[PM_P2P_CLIENT_MODE] = {PM_SCC_CH, PM_SCC_CH, PM_SCC_CH},
[PM_P2P_GO_MODE] = {PM_SCC_CH, PM_SCC_CH, PM_SCC_CH},
[PM_IBSS_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE} },
[PM_SAP_24_2x2] = {
[PM_STA_MODE] = {PM_SCC_CH, PM_SCC_CH, PM_SCC_CH},
[PM_SAP_MODE] = {PM_SCC_CH, PM_SCC_CH, PM_SCC_CH},
[PM_P2P_CLIENT_MODE] = {PM_SCC_CH, PM_SCC_CH, PM_SCC_CH},
[PM_P2P_GO_MODE] = {PM_SCC_CH, PM_SCC_CH, PM_SCC_CH},
[PM_IBSS_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE} },
[PM_SAP_5_1x1] = {
[PM_STA_MODE] = {PM_SCC_CH_5G, PM_SCC_CH, PM_SCC_CH},
[PM_SAP_MODE] = {PM_SCC_CH, PM_SCC_CH, PM_SCC_CH},
[PM_P2P_CLIENT_MODE] = {PM_SCC_CH, PM_SCC_CH, PM_SCC_CH},
[PM_P2P_GO_MODE] = {PM_SCC_CH, PM_SCC_CH, PM_SCC_CH},
[PM_IBSS_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE} },
[PM_SAP_5_2x2] = {
[PM_STA_MODE] = {PM_SCC_CH_5G, PM_SCC_CH, PM_SCC_CH},
[PM_SAP_MODE] = {PM_SCC_CH, PM_SCC_CH, PM_SCC_CH},
[PM_P2P_CLIENT_MODE] = {PM_SCC_CH, PM_SCC_CH, PM_SCC_CH},
[PM_P2P_GO_MODE] = {PM_SCC_CH, PM_SCC_CH, PM_SCC_CH},
[PM_IBSS_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE} },
[PM_IBSS_24_1x1] = {
[PM_STA_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE},
[PM_SAP_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE},
[PM_P2P_CLIENT_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE},
[PM_P2P_GO_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE},
[PM_IBSS_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE} },
[PM_IBSS_24_2x2] = {
[PM_STA_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE},
[PM_SAP_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE},
[PM_P2P_CLIENT_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE},
[PM_P2P_GO_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE},
[PM_IBSS_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE} },
[PM_IBSS_5_1x1] = {
[PM_STA_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE},
[PM_SAP_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE},
[PM_P2P_CLIENT_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE},
[PM_P2P_GO_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE},
[PM_IBSS_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE} },
[PM_IBSS_5_2x2] = {
[PM_STA_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE},
[PM_SAP_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE},
[PM_P2P_CLIENT_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE},
[PM_P2P_GO_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE},
[PM_IBSS_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE} },
};
/**
* third_connection_pcl_nodbs_table - table which provides PCL
* for the 3rd connection, when we have two connections already
* in the system (with DBS not supported by HW)
*/
static const enum policy_mgr_pcl_type
third_connection_pcl_nodbs_table[PM_MAX_TWO_CONNECTION_MODE]
[PM_MAX_NUM_OF_MODE][PM_MAX_CONC_PRIORITY_MODE] = {
[PM_STA_SAP_SCC_24_1x1] = {
[PM_STA_MODE] = {PM_SCC_CH_5G, PM_SCC_CH, PM_SCC_CH},
[PM_SAP_MODE] = {PM_SCC_CH_5G, PM_SCC_CH, PM_SCC_CH},
[PM_P2P_CLIENT_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE},
[PM_P2P_GO_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE},
[PM_IBSS_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE} },
[PM_STA_SAP_SCC_24_2x2] = {
[PM_STA_MODE] = {PM_SCC_CH_5G, PM_SCC_CH, PM_SCC_CH},
[PM_SAP_MODE] = {PM_SCC_CH_5G, PM_SCC_CH, PM_SCC_CH},
[PM_P2P_CLIENT_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE},
[PM_P2P_GO_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE},
[PM_IBSS_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE} },
[PM_STA_SAP_MCC_24_1x1] = {
[PM_STA_MODE] = {PM_5G_MCC_CH, PM_MCC_CH, PM_MCC_CH},
[PM_SAP_MODE] = {PM_5G_MCC_CH, PM_MCC_CH, PM_MCC_CH},
[PM_P2P_CLIENT_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE},
[PM_P2P_GO_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE},
[PM_IBSS_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE} },
[PM_STA_SAP_MCC_24_2x2] = {
[PM_STA_MODE] = {PM_5G_MCC_CH, PM_MCC_CH, PM_MCC_CH},
[PM_SAP_MODE] = {PM_5G_MCC_CH, PM_MCC_CH, PM_MCC_CH},
[PM_P2P_CLIENT_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE},
[PM_P2P_GO_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE},
[PM_IBSS_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE} },
[PM_STA_SAP_SCC_5_1x1] = {
[PM_STA_MODE] = {PM_SCC_CH, PM_SCC_CH, PM_SCC_CH},
[PM_SAP_MODE] = {PM_SCC_CH, PM_SCC_CH, PM_SCC_CH},
[PM_P2P_CLIENT_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE},
[PM_P2P_GO_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE},
[PM_IBSS_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE} },
[PM_STA_SAP_SCC_5_2x2] = {
[PM_STA_MODE] = {PM_SCC_CH, PM_SCC_CH, PM_SCC_CH},
[PM_SAP_MODE] = {PM_SCC_CH, PM_SCC_CH, PM_SCC_CH},
[PM_P2P_CLIENT_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE},
[PM_P2P_GO_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE},
[PM_IBSS_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE} },
[PM_STA_SAP_MCC_5_1x1] = {
[PM_STA_MODE] = {PM_MCC_CH, PM_MCC_CH, PM_MCC_CH},
[PM_SAP_MODE] = {PM_MCC_CH, PM_MCC_CH, PM_MCC_CH},
[PM_P2P_CLIENT_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE},
[PM_P2P_GO_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE},
[PM_IBSS_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE} },
[PM_STA_SAP_MCC_5_2x2] = {
[PM_STA_MODE] = {PM_MCC_CH, PM_MCC_CH, PM_MCC_CH},
[PM_SAP_MODE] = {PM_MCC_CH, PM_MCC_CH, PM_MCC_CH},
[PM_P2P_CLIENT_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE},
[PM_P2P_GO_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE},
[PM_IBSS_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE} },
[PM_STA_SAP_MCC_24_5_1x1] = {
[PM_STA_MODE] = {PM_MCC_CH, PM_MCC_CH, PM_MCC_CH},
[PM_SAP_MODE] = {PM_MCC_CH, PM_MCC_CH, PM_MCC_CH},
[PM_P2P_CLIENT_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE},
[PM_P2P_GO_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE},
[PM_IBSS_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE} },
[PM_STA_SAP_MCC_24_5_2x2] = {
[PM_STA_MODE] = {PM_MCC_CH, PM_MCC_CH, PM_MCC_CH},
[PM_SAP_MODE] = {PM_MCC_CH, PM_MCC_CH, PM_MCC_CH},
[PM_P2P_CLIENT_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE},
[PM_P2P_GO_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE},
[PM_IBSS_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE} },
[PM_STA_SAP_DBS_1x1] = {
[PM_STA_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE},
[PM_SAP_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE},
[PM_P2P_CLIENT_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE},
[PM_P2P_GO_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE},
[PM_IBSS_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE} },
[PM_STA_P2P_GO_SCC_24_1x1] = {
[PM_STA_MODE] = {PM_5G, PM_SCC_CH, PM_SCC_CH},
[PM_SAP_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE},
[PM_P2P_CLIENT_MODE] = {PM_5G, PM_SCC_CH, PM_SCC_CH},
[PM_P2P_GO_MODE] = {PM_5G_SCC_CH, PM_SCC_CH, PM_SCC_CH},
[PM_IBSS_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE} },
[PM_STA_P2P_GO_SCC_24_2x2] = {
[PM_STA_MODE] = {PM_5G, PM_SCC_CH, PM_SCC_CH},
[PM_SAP_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE},
[PM_P2P_CLIENT_MODE] = {PM_5G, PM_SCC_CH, PM_SCC_CH},
[PM_P2P_GO_MODE] = {PM_5G_SCC_CH, PM_SCC_CH, PM_SCC_CH},
[PM_IBSS_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE} },
[PM_STA_P2P_GO_MCC_24_1x1] = {
[PM_STA_MODE] = {PM_5G_MCC_CH, PM_MCC_CH, PM_MCC_CH},
[PM_SAP_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE},
[PM_P2P_CLIENT_MODE] = {
PM_5G_MCC_CH, PM_MCC_CH, PM_MCC_CH},
[PM_P2P_GO_MODE] = {
PM_5G_MCC_CH, PM_MCC_CH, PM_MCC_CH},
[PM_IBSS_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE} },
[PM_STA_P2P_GO_MCC_24_2x2] = {
[PM_STA_MODE] = {PM_5G_MCC_CH, PM_MCC_CH, PM_MCC_CH},
[PM_SAP_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE},
[PM_P2P_CLIENT_MODE] = {
PM_5G_MCC_CH, PM_MCC_CH, PM_MCC_CH},
[PM_P2P_GO_MODE] = {
PM_5G_MCC_CH, PM_MCC_CH, PM_MCC_CH},
[PM_IBSS_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE} },
[PM_STA_P2P_GO_SCC_5_1x1] = {
[PM_STA_MODE] = {PM_SCC_CH, PM_SCC_CH, PM_SCC_CH},
[PM_SAP_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE},
[PM_P2P_CLIENT_MODE] = {PM_SCC_CH, PM_SCC_CH, PM_SCC_CH},
[PM_P2P_GO_MODE] = {PM_SCC_CH, PM_SCC_CH, PM_SCC_CH},
[PM_IBSS_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE} },
[PM_STA_P2P_GO_SCC_5_2x2] = {
[PM_STA_MODE] = {PM_SCC_CH, PM_SCC_CH, PM_SCC_CH},
[PM_SAP_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE},
[PM_P2P_CLIENT_MODE] = {PM_SCC_CH, PM_SCC_CH, PM_SCC_CH},
[PM_P2P_GO_MODE] = {PM_SCC_CH, PM_SCC_CH, PM_SCC_CH},
[PM_IBSS_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE} },
[PM_STA_P2P_GO_MCC_5_1x1] = {
[PM_STA_MODE] = {PM_MCC_CH, PM_MCC_CH, PM_MCC_CH},
[PM_SAP_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE},
[PM_P2P_CLIENT_MODE] = {PM_MCC_CH, PM_MCC_CH, PM_MCC_CH},
[PM_P2P_GO_MODE] = {PM_MCC_CH, PM_MCC_CH, PM_MCC_CH},
[PM_IBSS_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE} },
[PM_STA_P2P_GO_MCC_5_2x2] = {
[PM_STA_MODE] = {PM_MCC_CH, PM_MCC_CH, PM_MCC_CH},
[PM_SAP_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE},
[PM_P2P_CLIENT_MODE] = {PM_MCC_CH, PM_MCC_CH, PM_MCC_CH},
[PM_P2P_GO_MODE] = {PM_MCC_CH, PM_MCC_CH, PM_MCC_CH},
[PM_IBSS_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE} },
[PM_STA_P2P_GO_MCC_24_5_1x1] = {
[PM_STA_MODE] = {PM_MCC_CH, PM_MCC_CH, PM_MCC_CH},
[PM_SAP_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE},
[PM_P2P_CLIENT_MODE] = {PM_MCC_CH, PM_MCC_CH, PM_MCC_CH},
[PM_P2P_GO_MODE] = {PM_MCC_CH, PM_MCC_CH, PM_MCC_CH},
[PM_IBSS_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE} },
[PM_STA_P2P_GO_MCC_24_5_2x2] = {
[PM_STA_MODE] = {PM_MCC_CH, PM_MCC_CH, PM_MCC_CH},
[PM_SAP_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE},
[PM_P2P_CLIENT_MODE] = {PM_MCC_CH, PM_MCC_CH, PM_MCC_CH},
[PM_P2P_GO_MODE] = {PM_MCC_CH, PM_MCC_CH, PM_MCC_CH},
[PM_IBSS_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE} },
[PM_STA_P2P_GO_DBS_1x1] = {
[PM_STA_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE},
[PM_SAP_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE},
[PM_P2P_CLIENT_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE},
[PM_P2P_GO_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE},
[PM_IBSS_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE} },
[PM_STA_P2P_CLI_SCC_24_1x1] = {
[PM_STA_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE},
[PM_SAP_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE},
[PM_P2P_CLIENT_MODE] = {PM_5G_SCC_CH, PM_SCC_CH, PM_SCC_CH},
[PM_P2P_GO_MODE] = {PM_5G_SCC_CH, PM_SCC_CH, PM_SCC_CH},
[PM_IBSS_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE} },
[PM_STA_P2P_CLI_SCC_24_2x2] = {
[PM_STA_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE},
[PM_SAP_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE},
[PM_P2P_CLIENT_MODE] = {PM_5G_SCC_CH, PM_SCC_CH, PM_SCC_CH},
[PM_P2P_GO_MODE] = {PM_5G_SCC_CH, PM_SCC_CH, PM_SCC_CH},
[PM_IBSS_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE} },
[PM_STA_P2P_CLI_MCC_24_1x1] = {
[PM_STA_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE},
[PM_SAP_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE},
[PM_P2P_CLIENT_MODE] = {PM_5G_MCC_CH, PM_MCC_CH, PM_MCC_CH},
[PM_P2P_GO_MODE] = {PM_5G_MCC_CH, PM_MCC_CH, PM_MCC_CH},
[PM_IBSS_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE} },
[PM_STA_P2P_CLI_MCC_24_2x2] = {
[PM_STA_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE},
[PM_SAP_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE},
[PM_P2P_CLIENT_MODE] = {PM_5G_MCC_CH, PM_MCC_CH, PM_MCC_CH},
[PM_P2P_GO_MODE] = {PM_5G_MCC_CH, PM_MCC_CH, PM_MCC_CH},
[PM_IBSS_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE} },
[PM_STA_P2P_CLI_SCC_5_1x1] = {
[PM_STA_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE},
[PM_SAP_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE},
[PM_P2P_CLIENT_MODE] = {PM_SCC_CH, PM_SCC_CH, PM_SCC_CH},
[PM_P2P_GO_MODE] = {PM_SCC_CH, PM_SCC_CH, PM_SCC_CH},
[PM_IBSS_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE} },
[PM_STA_P2P_CLI_SCC_5_2x2] = {
[PM_STA_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE},
[PM_SAP_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE},
[PM_P2P_CLIENT_MODE] = {PM_SCC_CH, PM_SCC_CH, PM_SCC_CH},
[PM_P2P_GO_MODE] = {PM_SCC_CH, PM_SCC_CH, PM_SCC_CH},
[PM_IBSS_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE} },
[PM_STA_P2P_CLI_MCC_5_1x1] = {
[PM_STA_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE},
[PM_SAP_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE},
[PM_P2P_CLIENT_MODE] = {PM_MCC_CH, PM_MCC_CH, PM_MCC_CH},
[PM_P2P_GO_MODE] = {PM_MCC_CH, PM_MCC_CH, PM_MCC_CH},
[PM_IBSS_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE} },
[PM_STA_P2P_CLI_MCC_5_2x2] = {
[PM_STA_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE},
[PM_SAP_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE},
[PM_P2P_CLIENT_MODE] = {PM_MCC_CH, PM_MCC_CH, PM_MCC_CH},
[PM_P2P_GO_MODE] = {PM_MCC_CH, PM_MCC_CH, PM_MCC_CH},
[PM_IBSS_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE} },
[PM_STA_P2P_CLI_MCC_24_5_1x1] = {
[PM_STA_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE},
[PM_SAP_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE},
[PM_P2P_CLIENT_MODE] = {PM_MCC_CH, PM_MCC_CH, PM_MCC_CH},
[PM_P2P_GO_MODE] = {PM_MCC_CH, PM_MCC_CH, PM_MCC_CH},
[PM_IBSS_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE} },
[PM_STA_P2P_CLI_MCC_24_5_2x2] = {
[PM_STA_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE},
[PM_SAP_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE},
[PM_P2P_CLIENT_MODE] = {PM_MCC_CH, PM_MCC_CH, PM_MCC_CH},
[PM_P2P_GO_MODE] = {PM_MCC_CH, PM_MCC_CH, PM_MCC_CH},
[PM_IBSS_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE} },
[PM_STA_P2P_CLI_DBS_1x1] = {
[PM_STA_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE},
[PM_SAP_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE},
[PM_P2P_CLIENT_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE},
[PM_P2P_GO_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE},
[PM_IBSS_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE} },
[PM_P2P_GO_P2P_CLI_SCC_24_1x1] = {
[PM_STA_MODE] = {PM_5G, PM_SCC_CH, PM_SCC_CH},
[PM_SAP_MODE] = {PM_SCC_CH_5G, PM_SCC_CH, PM_SCC_CH},
[PM_P2P_CLIENT_MODE] = {PM_5G, PM_SCC_CH, PM_SCC_CH},
[PM_P2P_GO_MODE] = {PM_5G_SCC_CH, PM_SCC_CH, PM_SCC_CH},
[PM_IBSS_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE} },
[PM_P2P_GO_P2P_CLI_SCC_24_2x2] = {
[PM_STA_MODE] = {PM_5G, PM_SCC_CH, PM_SCC_CH},
[PM_SAP_MODE] = {PM_SCC_CH_5G, PM_SCC_CH, PM_SCC_CH},
[PM_P2P_CLIENT_MODE] = {PM_5G, PM_SCC_CH, PM_SCC_CH},
[PM_P2P_GO_MODE] = {PM_5G_SCC_CH, PM_SCC_CH, PM_SCC_CH},
[PM_IBSS_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE} },
[PM_P2P_GO_P2P_CLI_MCC_24_1x1] = {
[PM_STA_MODE] = {PM_5G_MCC_CH, PM_MCC_CH, PM_MCC_CH},
[PM_SAP_MODE] = {PM_5G_MCC_CH, PM_MCC_CH, PM_MCC_CH},
[PM_P2P_CLIENT_MODE] = {
PM_5G_MCC_CH, PM_MCC_CH, PM_MCC_CH},
[PM_P2P_GO_MODE] = {
PM_5G_MCC_CH, PM_MCC_CH, PM_MCC_CH},
[PM_IBSS_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE} },
[PM_P2P_GO_P2P_CLI_MCC_24_2x2] = {
[PM_STA_MODE] = {PM_5G_MCC_CH, PM_MCC_CH, PM_MCC_CH},
[PM_SAP_MODE] = {PM_5G_MCC_CH, PM_MCC_CH, PM_MCC_CH},
[PM_P2P_CLIENT_MODE] = {
PM_5G_MCC_CH, PM_MCC_CH, PM_MCC_CH},
[PM_P2P_GO_MODE] = {
PM_5G_MCC_CH, PM_MCC_CH, PM_MCC_CH},
[PM_IBSS_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE} },
[PM_P2P_GO_P2P_CLI_SCC_5_1x1] = {
[PM_STA_MODE] = {PM_SCC_CH, PM_SCC_CH, PM_SCC_CH},
[PM_SAP_MODE] = {PM_SCC_CH, PM_SCC_CH, PM_SCC_CH},
[PM_P2P_CLIENT_MODE] = {PM_SCC_CH, PM_SCC_CH, PM_SCC_CH},
[PM_P2P_GO_MODE] = {PM_SCC_CH, PM_SCC_CH, PM_SCC_CH},
[PM_IBSS_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE} },
[PM_P2P_GO_P2P_CLI_SCC_5_2x2] = {
[PM_STA_MODE] = {PM_SCC_CH, PM_SCC_CH, PM_SCC_CH},
[PM_SAP_MODE] = {PM_SCC_CH, PM_SCC_CH, PM_SCC_CH},
[PM_P2P_CLIENT_MODE] = {PM_SCC_CH, PM_SCC_CH, PM_SCC_CH},
[PM_P2P_GO_MODE] = {PM_SCC_CH, PM_SCC_CH, PM_SCC_CH},
[PM_IBSS_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE} },
[PM_P2P_GO_P2P_CLI_MCC_5_1x1] = {
[PM_STA_MODE] = {PM_MCC_CH, PM_MCC_CH, PM_MCC_CH},
[PM_SAP_MODE] = {PM_MCC_CH, PM_MCC_CH, PM_MCC_CH},
[PM_P2P_CLIENT_MODE] = {PM_MCC_CH, PM_MCC_CH, PM_MCC_CH},
[PM_P2P_GO_MODE] = {PM_MCC_CH, PM_MCC_CH, PM_MCC_CH},
[PM_IBSS_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE} },
[PM_P2P_GO_P2P_CLI_MCC_5_2x2] = {
[PM_STA_MODE] = {PM_MCC_CH, PM_MCC_CH, PM_MCC_CH},
[PM_SAP_MODE] = {PM_MCC_CH, PM_MCC_CH, PM_MCC_CH},
[PM_P2P_CLIENT_MODE] = {PM_MCC_CH, PM_MCC_CH, PM_MCC_CH},
[PM_P2P_GO_MODE] = {PM_MCC_CH, PM_MCC_CH, PM_MCC_CH},
[PM_IBSS_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE} },
[PM_P2P_GO_P2P_CLI_MCC_24_5_1x1] = {
[PM_STA_MODE] = {PM_MCC_CH, PM_MCC_CH, PM_MCC_CH},
[PM_SAP_MODE] = {PM_MCC_CH, PM_MCC_CH, PM_MCC_CH},
[PM_P2P_CLIENT_MODE] = {PM_MCC_CH, PM_MCC_CH, PM_MCC_CH},
[PM_P2P_GO_MODE] = {PM_MCC_CH, PM_MCC_CH, PM_MCC_CH},
[PM_IBSS_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE} },
[PM_P2P_GO_P2P_CLI_MCC_24_5_2x2] = {
[PM_STA_MODE] = {PM_MCC_CH, PM_MCC_CH, PM_MCC_CH},
[PM_SAP_MODE] = {PM_MCC_CH, PM_MCC_CH, PM_MCC_CH},
[PM_P2P_CLIENT_MODE] = {PM_MCC_CH, PM_MCC_CH, PM_MCC_CH},
[PM_P2P_GO_MODE] = {PM_MCC_CH, PM_MCC_CH, PM_MCC_CH},
[PM_IBSS_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE} },
[PM_P2P_GO_P2P_CLI_DBS_1x1] = {
[PM_STA_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE},
[PM_SAP_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE},
[PM_P2P_CLIENT_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE},
[PM_P2P_GO_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE},
[PM_IBSS_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE} },
[PM_P2P_GO_SAP_SCC_24_1x1] = {
[PM_STA_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE},
[PM_SAP_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE},
[PM_P2P_CLIENT_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE},
[PM_P2P_GO_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE},
[PM_IBSS_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE} },
[PM_P2P_GO_SAP_SCC_24_2x2] = {
[PM_STA_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE},
[PM_SAP_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE},
[PM_P2P_CLIENT_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE},
[PM_P2P_GO_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE},
[PM_IBSS_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE} },
[PM_P2P_GO_SAP_MCC_24_1x1] = {
[PM_STA_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE},
[PM_SAP_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE},
[PM_P2P_CLIENT_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE},
[PM_P2P_GO_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE},
[PM_IBSS_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE} },
[PM_P2P_GO_SAP_MCC_24_2x2] = {
[PM_STA_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE},
[PM_SAP_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE},
[PM_P2P_CLIENT_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE},
[PM_P2P_GO_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE},
[PM_IBSS_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE} },
[PM_P2P_GO_SAP_SCC_5_1x1] = {
[PM_STA_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE},
[PM_SAP_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE},
[PM_P2P_CLIENT_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE},
[PM_P2P_GO_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE},
[PM_IBSS_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE} },
[PM_P2P_GO_SAP_SCC_5_2x2] = {
[PM_STA_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE},
[PM_SAP_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE},
[PM_P2P_CLIENT_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE},
[PM_P2P_GO_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE},
[PM_IBSS_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE} },
[PM_P2P_GO_SAP_MCC_5_1x1] = {
[PM_STA_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE},
[PM_SAP_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE},
[PM_P2P_CLIENT_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE},
[PM_P2P_GO_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE},
[PM_IBSS_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE} },
[PM_P2P_GO_SAP_MCC_5_2x2] = {
[PM_STA_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE},
[PM_SAP_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE},
[PM_P2P_CLIENT_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE},
[PM_P2P_GO_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE},
[PM_IBSS_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE} },
[PM_P2P_GO_SAP_MCC_24_5_1x1] = {
[PM_STA_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE},
[PM_SAP_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE},
[PM_P2P_CLIENT_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE},
[PM_P2P_GO_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE},
[PM_IBSS_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE} },
[PM_P2P_GO_SAP_MCC_24_5_2x2] = {
[PM_STA_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE},
[PM_SAP_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE},
[PM_P2P_CLIENT_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE},
[PM_P2P_GO_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE},
[PM_IBSS_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE} },
[PM_P2P_GO_SAP_DBS_1x1] = {
[PM_STA_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE},
[PM_SAP_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE},
[PM_P2P_CLIENT_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE},
[PM_P2P_GO_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE},
[PM_IBSS_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE} },
[PM_P2P_CLI_SAP_SCC_24_1x1] = {
[PM_STA_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE},
[PM_SAP_MODE] = {PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE},
[PM_P2P_CLIENT_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE},
[PM_P2P_GO_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE},
[PM_IBSS_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE} },
[PM_P2P_CLI_SAP_SCC_24_2x2] = {
[PM_STA_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE},
[PM_SAP_MODE] = {PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE},
[PM_P2P_CLIENT_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE},
[PM_P2P_GO_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE},
[PM_IBSS_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE} },
[PM_P2P_CLI_SAP_MCC_24_1x1] = {
[PM_STA_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE},
[PM_SAP_MODE] = {PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE},
[PM_P2P_CLIENT_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE},
[PM_P2P_GO_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE},
[PM_IBSS_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE} },
[PM_P2P_CLI_SAP_MCC_24_2x2] = {
[PM_STA_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE},
[PM_SAP_MODE] = {PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE},
[PM_P2P_CLIENT_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE},
[PM_P2P_GO_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE},
[PM_IBSS_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE} },
[PM_P2P_CLI_SAP_SCC_5_1x1] = {
[PM_STA_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE},
[PM_SAP_MODE] = {PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE},
[PM_P2P_CLIENT_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE},
[PM_P2P_GO_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE},
[PM_IBSS_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE} },
[PM_P2P_CLI_SAP_SCC_5_2x2] = {
[PM_STA_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE},
[PM_SAP_MODE] = {PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE},
[PM_P2P_CLIENT_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE},
[PM_P2P_GO_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE},
[PM_IBSS_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE} },
[PM_P2P_CLI_SAP_MCC_5_1x1] = {
[PM_STA_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE},
[PM_SAP_MODE] = {PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE},
[PM_P2P_CLIENT_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE},
[PM_P2P_GO_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE},
[PM_IBSS_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE} },
[PM_P2P_CLI_SAP_MCC_5_2x2] = {
[PM_STA_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE},
[PM_SAP_MODE] = {PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE},
[PM_P2P_CLIENT_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE},
[PM_P2P_GO_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE},
[PM_IBSS_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE} },
[PM_P2P_CLI_SAP_MCC_24_5_1x1] = {
[PM_STA_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE},
[PM_SAP_MODE] = {PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE},
[PM_P2P_CLIENT_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE},
[PM_P2P_GO_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE},
[PM_IBSS_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE} },
[PM_P2P_CLI_SAP_MCC_24_5_2x2] = {
[PM_STA_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE},
[PM_SAP_MODE] = {PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE},
[PM_P2P_CLIENT_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE},
[PM_P2P_GO_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE},
[PM_IBSS_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE} },
[PM_P2P_CLI_SAP_DBS_1x1] = {
[PM_STA_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE},
[PM_SAP_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE},
[PM_P2P_CLIENT_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE},
[PM_P2P_GO_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE},
[PM_IBSS_MODE] = {
PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE, PM_MAX_PCL_TYPE} },
};
#endif

View file

@ -0,0 +1,146 @@
/*
* Copyright (c) 2018 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.
*/
#include "wlan_policy_mgr_ucfg.h"
#include "wlan_policy_mgr_i.h"
#include "cfg_ucfg_api.h"
#include "wlan_policy_mgr_api.h"
static QDF_STATUS policy_mgr_init_cfg(struct wlan_objmgr_psoc *psoc)
{
struct policy_mgr_psoc_priv_obj *pm_ctx;
struct policy_mgr_cfg *cfg;
pm_ctx = policy_mgr_get_context(psoc);
if (!pm_ctx) {
policy_mgr_err("pm_ctx is NULL");
return QDF_STATUS_E_FAILURE;
}
cfg = &pm_ctx->cfg;
cfg->mcc_to_scc_switch = cfg_get(psoc, CFG_MCC_TO_SCC_SWITCH);
cfg->sys_pref = cfg_get(psoc, CFG_CONC_SYS_PREF);
cfg->max_conc_cxns = cfg_get(psoc, CFG_MAX_CONC_CXNS);
cfg->conc_rule1 = cfg_get(psoc, CFG_ENABLE_CONC_RULE1);
cfg->conc_rule2 = cfg_get(psoc, CFG_ENABLE_CONC_RULE2);
cfg->dbs_selection_plcy = cfg_get(psoc, CFG_DBS_SELECTION_PLCY);
cfg->vdev_priority_list = cfg_get(psoc, CFG_VDEV_CUSTOM_PRIORITY_LIST);
cfg->chnl_select_plcy = cfg_get(psoc, CFG_CHNL_SELECT_LOGIC_CONC);
cfg->enable_mcc_adaptive_sch =
cfg_get(psoc, CFG_ENABLE_MCC_ADATIVE_SCH_ENABLED_NAME);
cfg->enable_sta_cxn_5g_band =
cfg_get(psoc, CFG_ENABLE_STA_CONNECTION_IN_5GHZ);
return QDF_STATUS_SUCCESS;
}
static void policy_mgr_deinit_cfg(struct wlan_objmgr_psoc *psoc)
{
struct policy_mgr_psoc_priv_obj *pm_ctx;
pm_ctx = policy_mgr_get_context(psoc);
if (!pm_ctx) {
policy_mgr_err("pm_ctx is NULL");
return;
}
qdf_mem_zero(&pm_ctx->cfg, sizeof(pm_ctx->cfg));
}
QDF_STATUS ucfg_policy_mgr_psoc_open(struct wlan_objmgr_psoc *psoc)
{
QDF_STATUS status;
status = policy_mgr_init_cfg(psoc);
if (status != QDF_STATUS_SUCCESS) {
policy_mgr_err("pm_ctx is NULL");
return status;
}
return QDF_STATUS_SUCCESS;
}
void ucfg_policy_mgr_psoc_close(struct wlan_objmgr_psoc *psoc)
{
policy_mgr_deinit_cfg(psoc);
}
QDF_STATUS ucfg_policy_mgr_get_mcc_scc_switch(struct wlan_objmgr_psoc *psoc,
uint8_t *mcc_scc_switch)
{
return policy_mgr_get_mcc_scc_switch(psoc, mcc_scc_switch);
}
QDF_STATUS ucfg_policy_mgr_get_sys_pref(struct wlan_objmgr_psoc *psoc,
uint8_t *sys_pref)
{
return policy_mgr_get_sys_pref(psoc, sys_pref);
}
QDF_STATUS ucfg_policy_mgr_set_sys_pref(struct wlan_objmgr_psoc *psoc,
uint8_t sys_pref)
{
return policy_mgr_set_sys_pref(psoc, sys_pref);
}
QDF_STATUS ucfg_policy_mgr_get_max_conc_cxns(struct wlan_objmgr_psoc *psoc,
uint8_t *max_conc_cxns)
{
return policy_mgr_get_max_conc_cxns(psoc, max_conc_cxns);;
}
QDF_STATUS ucfg_policy_mgr_get_conc_rule1(struct wlan_objmgr_psoc *psoc,
uint8_t *conc_rule1)
{
return policy_mgr_get_conc_rule1(psoc, conc_rule1);
}
QDF_STATUS ucfg_policy_mgr_get_conc_rule2(struct wlan_objmgr_psoc *psoc,
uint8_t *conc_rule2)
{
return policy_mgr_get_conc_rule2(psoc, conc_rule2);
}
QDF_STATUS ucfg_policy_mgr_get_dbs_selection_plcy(struct wlan_objmgr_psoc *psoc,
uint32_t *dbs_selection_plcy)
{
return policy_mgr_get_dbs_selection_plcy(psoc, dbs_selection_plcy);
}
QDF_STATUS ucfg_policy_mgr_get_vdev_priority_list(struct wlan_objmgr_psoc *psoc,
uint32_t *vdev_priority_list)
{
return policy_mgr_get_vdev_priority_list(psoc, vdev_priority_list);
}
QDF_STATUS ucfg_policy_mgr_get_chnl_select_plcy(struct wlan_objmgr_psoc *psoc,
uint32_t *chnl_select_plcy)
{
return policy_mgr_get_chnl_select_plcy(psoc, chnl_select_plcy);
}
QDF_STATUS ucfg_policy_mgr_get_mcc_adaptive_sch(struct wlan_objmgr_psoc *psoc,
uint8_t *mcc_adaptive_sch)
{
return policy_mgr_get_mcc_adaptive_sch(psoc, mcc_adaptive_sch);
}
QDF_STATUS ucfg_policy_mgr_get_sta_cxn_5g_band(struct wlan_objmgr_psoc *psoc,
uint8_t *enable_sta_cxn_5g_band)
{
return policy_mgr_get_sta_cxn_5g_band(psoc, enable_sta_cxn_5g_band);
}

View file

@ -181,6 +181,9 @@ QDF_STATUS mlme_cfg_on_psoc_enable(struct wlan_objmgr_psoc *psoc);
*
* Return: pointer to MLME object
*/
struct wlan_mlme_psoc_obj *mlme_get_psoc_obj(struct wlan_objmgr_psoc *psoc);
#define mlme_get_psoc_obj(psoc) mlme_get_psoc_obj_fl(psoc, __func__, __LINE__)
struct wlan_mlme_psoc_obj *mlme_get_psoc_obj_fl(struct wlan_objmgr_psoc *psoc,
const char *func,
uint32_t line);
#endif

View file

@ -28,13 +28,16 @@
#define NUM_OF_SOUNDING_DIMENSIONS 1 /*Nss - 1, (Nss = 2 for 2x2)*/
struct wlan_mlme_psoc_obj *mlme_get_psoc_obj(struct wlan_objmgr_psoc *psoc)
struct wlan_mlme_psoc_obj *mlme_get_psoc_obj_fl(struct wlan_objmgr_psoc *psoc,
const char *func, uint32_t line)
{
struct wlan_mlme_psoc_obj *mlme_obj;
mlme_obj = (struct wlan_mlme_psoc_obj *)
wlan_objmgr_psoc_get_comp_private_obj(psoc,
WLAN_UMAC_COMP_MLME);
if (!mlme_obj)
mlme_err("mlme obj is null, %s:%d", func, line);
return mlme_obj;
}
@ -585,6 +588,8 @@ static void mlme_init_timeout_cfg(struct wlan_objmgr_psoc *psoc,
cfg_get(psoc, CFG_AP_LINK_MONITOR_TIMEOUT);
timeouts->ps_data_inactivity_timeout =
cfg_get(psoc, CFG_PS_DATA_INACTIVITY_TIMEOUT);
timeouts->wmi_wq_watchdog_timeout =
cfg_get(psoc, CFG_WMI_WQ_WATCHDOG);
}
static void mlme_init_ht_cap_in_cfg(struct wlan_objmgr_psoc *psoc,
@ -850,8 +855,19 @@ static void mlme_init_rates_in_cfg(struct wlan_objmgr_psoc *psoc,
static void mlme_init_dfs_cfg(struct wlan_objmgr_psoc *psoc,
struct wlan_mlme_dfs_cfg *dfs_cfg)
{
dfs_cfg->dfs_master_capable = cfg_get(psoc,
CFG_ENABLE_DFS_MASTER_CAPABILITY);
dfs_cfg->dfs_ignore_cac = cfg_get(psoc, CFG_IGNORE_CAC);
dfs_cfg->dfs_master_capable =
cfg_get(psoc, CFG_ENABLE_DFS_MASTER_CAPABILITY);
dfs_cfg->dfs_disable_channel_switch =
cfg_get(psoc, CFG_DISABLE_DFS_CH_SWITCH);
dfs_cfg->dfs_filter_offload =
cfg_get(psoc, CFG_ENABLE_DFS_PHYERR_FILTEROFFLOAD);
dfs_cfg->dfs_prefer_non_dfs =
cfg_get(psoc, CFG_ENABLE_NON_DFS_CHAN_ON_RADAR);
dfs_cfg->dfs_beacon_tx_enhanced =
cfg_get(psoc, CFG_DFS_BEACON_TX_ENHANCED);
dfs_cfg->sap_tx_leakage_threshold =
cfg_get(psoc, CFG_SAP_TX_LEAKAGE_THRESHOLD);
}
static void mlme_init_feature_flag_in_cfg(
@ -1687,6 +1703,13 @@ static void mlme_init_wep_cfg(struct wlan_mlme_wep_cfg *wep_params)
mlme_init_wep_keys(wep_params);
}
static void mlme_init_wifi_pos_cfg(struct wlan_objmgr_psoc *psoc,
struct wlan_mlme_wifi_pos_cfg *wifi_pos_cfg)
{
wifi_pos_cfg->fine_time_meas_cap =
cfg_get(psoc, CFG_FINE_TIME_MEAS_CAPABILITY);
}
#ifdef FEATURE_WLAN_ESE
static void mlme_init_inactivity_intv(struct wlan_objmgr_psoc *psoc,
struct wlan_mlme_wmm_params *wmm_params)
@ -1844,6 +1867,7 @@ QDF_STATUS mlme_cfg_on_psoc_enable(struct wlan_objmgr_psoc *psoc)
mlme_init_power_cfg(psoc, &mlme_cfg->power);
mlme_init_oce_cfg(psoc, &mlme_cfg->oce);
mlme_init_wep_cfg(&mlme_cfg->wep_params);
mlme_init_wifi_pos_cfg(psoc, &mlme_cfg->wifi_pos_cfg);
mlme_init_wps_params_cfg(psoc, &mlme_cfg->wps_params);
return status;

View file

@ -50,6 +50,7 @@
#include "cfg_mlme_threshold.h"
#include "cfg_mlme_feature_flag.h"
#include "cfg_mlme_wep_params.h"
#include "cfg_mlme_wifi_pos.h"
/* Please Maintain Alphabetic Order here */
#define CFG_MLME_ALL \
@ -80,6 +81,7 @@
CFG_TWT_ALL \
CFG_VHT_CAPS_ALL \
CFG_WEP_PARAMS_ALL \
CFG_WIFI_POS_ALL \
CFG_WPS_ALL
#endif /* __CFG_MLME_H */

View file

@ -23,6 +23,136 @@
#ifndef __CFG_MLME_DFS_H
#define __CFG_MLME_DFS_H
/*
* <ini>
* gsap_tx_leakage_threshold - sap tx leakage threshold
* @Min: 100
* @Max: 1000
* @Default: 310
*
* customer can set this value from 100 to 1000 which means
* sap tx leakage threshold is -10db to -100db
*
* Related: none
*
* Usage: External
*
* </ini>
*/
#define CFG_SAP_TX_LEAKAGE_THRESHOLD CFG_INI_UINT( \
"gsap_tx_leakage_threshold", \
100, \
1000, \
310, \
CFG_VALUE_OR_DEFAULT, \
"sap tx leakage threshold")
/*
* <ini>
* gDfsBeaconTxEnhanced - beacon tx enhanced
* @Min: 0
* @Max: 1
* @Default: 0
*
* This ini is used to enhance dfs beacon tx
*
* Related: none
*
* Usage: External
*
* </ini>
*/
#define CFG_DFS_BEACON_TX_ENHANCED CFG_INI_BOOL( \
"gDfsBeaconTxEnhanced", \
0, \
"beacon tx enhanced")
/*
* <ini>
* gPreferNonDfsChanOnRadar - During random channel selection prefer non dfs
* @Min: 0
* @Max: 1
* @Default: 0
*
* During random channel selection prefer non dfs.
*
* Related: none
*
* Usage: External
*
* </ini>
*/
#define CFG_ENABLE_NON_DFS_CHAN_ON_RADAR CFG_INI_BOOL( \
"gPreferNonDfsChanOnRadar", \
0, \
"channel selection prefer non dfs")
/*
* <ini>
* dfsPhyerrFilterOffload - Enable dfs phyerror filtering offload in FW
* @Min: 0
* @Max: 1
* @Default: 0
*
* This ini is used to to enable dfs phyerror filtering offload to firmware
* Enabling it will cause basic phy error to be discarding in firmware.
* Related: NA.
*
* Supported Feature: DFS
*
* Usage: Internal/External
*
* </ini>
*/
#define CFG_ENABLE_DFS_PHYERR_FILTEROFFLOAD CFG_INI_BOOL( \
"dfsPhyerrFilterOffload", \
0, \
"dfs phyerror filtering offload")
/*
* <ini>
* gIgnoreCAC - Used to ignore CAC
* @Min: 0
* @Max: 1
* @Default: 0
*
* This ini is used to set default CAC
*
* Related: None
*
* Supported Feature: DFS
*
* Usage: Internal/External
*
* </ini>
*/
#define CFG_IGNORE_CAC CFG_INI_BOOL( \
"gIgnoreCAC", \
0, \
"ignore CAC on DFS channel")
/*
* <ini>
* gDisableDFSChSwitch - Disable channel switch if radar is found
* @Min: 0
* @Max: 1
* @Default: 0
*
* This ini is used to disable channel switch if radar is found
* on that channel.
* Related: NA.
*
* Supported Feature: DFS
*
* Usage: Internal
*
* </ini>
*/
#define CFG_DISABLE_DFS_CH_SWITCH CFG_INI_BOOL( \
"gDisableDFSChSwitch", \
0, \
"Disable channel switch on radar")
/*
* <ini>
* gEnableDFSMasterCap - Enable DFS master capability
@ -47,6 +177,12 @@
"DFS master mode capability")
#define CFG_DFS_ALL \
CFG(CFG_ENABLE_DFS_MASTER_CAPABILITY)
CFG(CFG_IGNORE_CAC) \
CFG(CFG_DISABLE_DFS_CH_SWITCH) \
CFG(CFG_DFS_BEACON_TX_ENHANCED) \
CFG(CFG_SAP_TX_LEAKAGE_THRESHOLD) \
CFG(CFG_ENABLE_NON_DFS_CHAN_ON_RADAR) \
CFG(CFG_ENABLE_DFS_MASTER_CAPABILITY) \
CFG(CFG_ENABLE_DFS_PHYERR_FILTEROFFLOAD)
#endif /* __CFG_MLME_DFS_H */

View file

@ -285,6 +285,32 @@
CFG_VALUE_OR_DEFAULT, \
"PS data inactivity timeout")
/*
* <ini>
* wmi_wq_watchdog - Sets timeout period for wmi watchdog bite.
* @Min: 0
* @Max: 30
* @Default: 20
*
* This ini is used to set timeout period for wmi watchdog bite. If it is
* 0 then wmi watchdog bite is disabled.
*
* Related: None
*
* Supported Feature: STA
*
* Usage: External
*
* </ini>
*/
#define CFG_WMI_WQ_WATCHDOG CFG_INI_UINT( \
"wmi_wq_watchdog", \
0, \
30, \
20, \
CFG_VALUE_OR_DEFAULT, \
"timeout period for wmi watchdog bite")
#define CFG_TIMEOUT_ALL \
CFG(CFG_JOIN_FAILURE_TIMEOUT) \
CFG(CFG_AUTH_FAILURE_TIMEOUT) \
@ -297,6 +323,7 @@
CFG(CFG_HEART_BEAT_THRESHOLD) \
CFG(CFG_AP_KEEP_ALIVE_TIMEOUT) \
CFG(CFG_AP_LINK_MONITOR_TIMEOUT) \
CFG(CFG_WMI_WQ_WATCHDOG) \
CFG(CFG_PS_DATA_INACTIVITY_TIMEOUT)
#endif /* __CFG_MLME_TIMEOUT_H */

View file

@ -0,0 +1,74 @@
/*
* Copyright (c) 2012-2018 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: This file contains centralized definitions of converged configuration.
*/
#ifndef __CFG_MLME_WIFI_POS_H
#define __CFG_MLME_WIFI_POS_H
/*
* <ini>
* gfine_time_meas_cap - fine timing measurement capability information
* @Min: 0x0000
* @Max: 0x00BD
* @Default: 0x00BD
*
* fine timing measurement capability information
*
* <----- fine_time_meas_cap (in bits) ----->
* +----------+-----+-----+------+------+-------+-------+-----+-----+
* | 8-31 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
* +----------+-----+-----+------+------+-------+-------+-----+-----+
* | reserved | SAP | SAP |P2P-GO|P2P-GO|P2P-CLI|P2P-CLI| STA | STA |
* | |resp |init |resp |init |resp |init |resp |init |
* +----------+-----+-----+------+------+-------+-------+-----+-----+
*
* resp - responder role; init- initiator role
*
* CFG_FINE_TIME_MEAS_CAPABILITY_MAX computed based on the table
* +-----------------+-----------------+-----------+
* | Device Role | Initiator | Responder |
* +-----------------+-----------------+-----------+
* | Station | Y | N |
* | P2P-CLI | Y | Y |
* | P2P-GO | Y | Y |
* | SAP | N | Y |
* +-----------------+-----------------+-----------+
*
* Related: None
*
* Supported Feature: WIFI POS
*
* Usage: Internal/External
*
* </ini>
*/
#define CFG_FINE_TIME_MEAS_CAPABILITY CFG_INI_UINT( \
"gfine_time_meas_cap", \
0x0000, \
0x00BD, \
0x00BD, \
CFG_VALUE_OR_DEFAULT, \
"fine timing measurement capability")
#define CFG_WIFI_POS_ALL \
CFG(CFG_FINE_TIME_MEAS_CAPABILITY)
#endif /* __CFG_MLME_WIFI_POS_H */

View file

@ -573,9 +573,21 @@ struct wlan_mlme_cfg_sap {
/**
* struct wlan_mlme_dfs_cfg - DFS Capabilities related config items
* @dfs_master_capable: Is DFS master mode support enabled
* @dfs_disable_channel_switch: disable channel switch on radar detection
* @dfs_ignore_cac: Disable cac
* @dfs_filter_offload: dfs filter offloaad
* @dfs_beacon_tx_enhanced: enhance dfs beacon tx
* @dfs_prefer_non_dfs: perefer non dfs channel after radar
* @sap_tx_leakage_threshold: sap tx leakage threshold
*/
struct wlan_mlme_dfs_cfg {
bool dfs_master_capable;
bool dfs_disable_channel_switch;
bool dfs_ignore_cac;
bool dfs_filter_offload;
bool dfs_beacon_tx_enhanced;
bool dfs_prefer_non_dfs;
uint32_t sap_tx_leakage_threshold;
};
/**
@ -1556,6 +1568,7 @@ struct wlan_mlme_power {
* @ap_keep_alive_timeout: AP keep alive timeout value
* @ap_link_monitor_timeout: AP link monitor timeout value
* @ps_data_inactivity_timeout: PS data inactivity timeout
* @wmi_wq_watchdog_timeout: timeout period for wmi watchdog bite
*/
struct wlan_mlme_timeout {
uint32_t join_failure_timeout;
@ -1570,6 +1583,7 @@ struct wlan_mlme_timeout {
uint32_t ap_keep_alive_timeout;
uint32_t ap_link_monitor_timeout;
uint32_t ps_data_inactivity_timeout;
uint32_t wmi_wq_watchdog_timeout;
};
/**
@ -1630,6 +1644,14 @@ struct wlan_mlme_wep_cfg {
struct mlme_cfg_str wep_default_key_4;
};
/**
* struct wlan_mlme_wifi_pos_cfg - WIFI POS configs
* @fine_time_meas_cap: fine timing measurement capability information
*/
struct wlan_mlme_wifi_pos_cfg {
uint32_t fine_time_meas_cap;
};
/**
* struct wlan_mlme_cfg - MLME config items
* @chainmask_cfg: VHT chainmask related cfg items
@ -1658,6 +1680,7 @@ struct wlan_mlme_wep_cfg {
* @acs: ACS related CFG items
* @feature_flags: Feature flag config items
* @wep_params: WEP related config items
* @wifi_pos_cfg: WIFI POS config
* @wmm_params: WMM related CFG & INI Items
* @wps_params: WPS related CFG itmes
*/
@ -1690,6 +1713,7 @@ struct wlan_mlme_cfg {
struct wlan_mlme_acs acs;
struct wlan_mlme_feature_flag feature_flags;
struct wlan_mlme_wep_cfg wep_params;
struct wlan_mlme_wifi_pos_cfg wifi_pos_cfg;
struct wlan_mlme_wmm_params wmm_params;
struct wlan_mlme_wps_params wps_params;
};

View file

@ -702,6 +702,115 @@ QDF_STATUS
ucfg_mlme_get_dfs_master_capability(struct wlan_objmgr_psoc *psoc,
bool *val);
/*
* ucfg_mlme_get_dfs_disable_channel_switch() - Get the dfs channel switch
* @psoc: pointer to psoc object
* @dfs_disable_channel_switch: Pointer to the value which will be filled
*
* Return: QDF Status
*/
QDF_STATUS
ucfg_mlme_get_dfs_disable_channel_switch(struct wlan_objmgr_psoc *psoc,
bool *dfs_disable_channel_switch);
/*
* ucfg_mlme_set_dfs_disable_channel_switch() - Set the dfs channel switch
* @psoc: pointer to psoc object
* @dfs_disable_channel_switch: Value that needs to be set.
*
* Return: QDF Status
*/
QDF_STATUS
ucfg_mlme_set_dfs_disable_channel_switch(struct wlan_objmgr_psoc *psoc,
bool dfs_disable_channel_switch);
/*
* ucfg_mlme_get_dfs_ignore_cac() - GSet the dfs ignore cac
* @psoc: pointer to psoc object
* @dfs_ignore_cac: Pointer to the value which will be filled for the caller
*
* Return: QDF Status
*/
QDF_STATUS
ucfg_mlme_get_dfs_ignore_cac(struct wlan_objmgr_psoc *psoc,
bool *dfs_ignore_cac);
/*
* ucfg_mlme_set_dfs_ignore_cac() - Set the dfs ignore cac
* @psoc: pointer to psoc object
* @dfs_ignore_cac: Value that needs to be set.
*
* Return: QDF Status
*/
QDF_STATUS
ucfg_mlme_set_dfs_ignore_cac(struct wlan_objmgr_psoc *psoc,
bool dfs_ignore_cac);
/*
* ucfg_mlme_get_sap_tx_leakage_threshold() - Get sap tx leakage threshold
* @psoc: pointer to psoc object
* @sap_tx_leakage_threshold: Pointer to the value which will be filled
*
* Return: QDF Status
*/
QDF_STATUS
ucfg_mlme_get_sap_tx_leakage_threshold(struct wlan_objmgr_psoc *psoc,
uint32_t *sap_tx_leakage_threshold);
/*
* ucfg_mlme_set_sap_tx_leakage_threshold() - Set sap tx leakage threshold
* @psoc: pointer to psoc object
* @sap_tx_leakage_threshold: Value that needs to be set.
*
* Return: QDF Status
*/
QDF_STATUS
ucfg_mlme_set_sap_tx_leakage_threshold(struct wlan_objmgr_psoc *psoc,
uint32_t sap_tx_leakage_threshold);
/*
* ucfg_mlme_get_dfs_filter_offload() - Get the dfs filter offload
* @psoc: pointer to psoc object
* @dfs_filter_offload: Pointer to the value which will be filled
*
* Return: QDF Status
*/
QDF_STATUS
ucfg_mlme_get_dfs_filter_offload(struct wlan_objmgr_psoc *psoc,
bool *dfs_filter_offload);
/*
* ucfg_mlme_set_dfs_filter_offload() - Set the dfs filter offload
* @psoc: pointer to psoc object
* @dfs_filter_offload: Value that needs to be set.
*
* Return: QDF Status
*/
QDF_STATUS
ucfg_mlme_set_dfs_filter_offload(struct wlan_objmgr_psoc *psoc,
bool dfs_filter_offload);
/**
* ucfg_mlme_get_fine_time_meas_cap() - Get fine timing measurement capability
* @psoc: pointer to psoc object
* @fine_time_meas_cap: Pointer to the value which will be filled for the caller
*
* Return: QDF Status
*/
QDF_STATUS
ucfg_mlme_get_fine_time_meas_cap(struct wlan_objmgr_psoc *psoc,
uint32_t *fine_time_meas_cap);
/**
* ucfg_mlme_set_fine_time_meas_cap() - Set fine timing measurement capability
* @psoc: pointer to psoc object
* @fine_time_meas_cap: Value to be set
*
* Return: QDF Status
*/
QDF_STATUS
ucfg_mlme_set_fine_time_meas_cap(struct wlan_objmgr_psoc *psoc,
uint32_t fine_time_meas_cap);
/**
* ucfg_mlme_get_pmkid_modes() - Get PMKID modes
* @psoc: pointer to psoc object
@ -1116,6 +1225,28 @@ QDF_STATUS
ucfg_mlme_set_fast_roam_in_concurrency_enabled(struct wlan_objmgr_psoc *psoc,
bool val);
/**
* ucfg_mlme_get_wmi_wq_watchdog_timeout() - Get timeout for wmi watchdog bite
* @psoc: pointer to psoc object
* @wmi_wq_watchdog_timeout: buffer to hold value
*
* Return: QDF Status
*/
QDF_STATUS
ucfg_mlme_get_wmi_wq_watchdog_timeout(struct wlan_objmgr_psoc *psoc,
uint32_t *wmi_wq_watchdog_timeout);
/**
* ucfg_mlme_set_wmi_wq_watchdog_timeout() - Set timeout for wmi watchdog bite
* @psoc: pointer to psoc object
* @wmi_wq_watchdog_timeout: value to be set
*
* Return: QDF Status
*/
QDF_STATUS
ucfg_mlme_set_wmi_wq_watchdog_timeout(struct wlan_objmgr_psoc *psoc,
uint32_t wmi_wq_watchdog_timeout);
/**
* ucfg_mlme_get_ps_data_inactivity_timeout() - Get data inactivity timeout
* @psoc: pointer to psoc object

View file

@ -206,6 +206,186 @@ ucfg_mlme_get_dfs_master_capability(struct wlan_objmgr_psoc *psoc,
return QDF_STATUS_SUCCESS;
}
QDF_STATUS
ucfg_mlme_get_fine_time_meas_cap(struct wlan_objmgr_psoc *psoc,
uint32_t *fine_time_meas_cap)
{
struct wlan_mlme_psoc_obj *mlme_obj;
mlme_obj = mlme_get_psoc_obj(psoc);
if (!mlme_obj) {
*fine_time_meas_cap =
cfg_default(CFG_FINE_TIME_MEAS_CAPABILITY);
return QDF_STATUS_E_INVAL;
}
*fine_time_meas_cap = mlme_obj->cfg.wifi_pos_cfg.fine_time_meas_cap;
return QDF_STATUS_SUCCESS;
}
QDF_STATUS
ucfg_mlme_set_fine_time_meas_cap(struct wlan_objmgr_psoc *psoc,
uint32_t fine_time_meas_cap)
{
struct wlan_mlme_psoc_obj *mlme_obj;
mlme_obj = mlme_get_psoc_obj(psoc);
if (!mlme_obj)
return QDF_STATUS_E_INVAL;
mlme_obj->cfg.wifi_pos_cfg.fine_time_meas_cap = fine_time_meas_cap;
return QDF_STATUS_SUCCESS;
}
QDF_STATUS
ucfg_mlme_get_dfs_disable_channel_switch(struct wlan_objmgr_psoc *psoc,
bool *dfs_disable_channel_switch)
{
struct wlan_mlme_psoc_obj *mlme_obj;
mlme_obj = mlme_get_psoc_obj(psoc);
if (!mlme_obj) {
*dfs_disable_channel_switch =
cfg_default(CFG_DISABLE_DFS_CH_SWITCH);
mlme_err("mlme obj null");
return QDF_STATUS_E_INVAL;
}
*dfs_disable_channel_switch =
mlme_obj->cfg.dfs_cfg.dfs_disable_channel_switch;
return QDF_STATUS_SUCCESS;
}
QDF_STATUS
ucfg_mlme_set_dfs_disable_channel_switch(struct wlan_objmgr_psoc *psoc,
bool dfs_disable_channel_switch)
{
struct wlan_mlme_psoc_obj *mlme_obj;
mlme_obj = mlme_get_psoc_obj(psoc);
if (!mlme_obj) {
mlme_err("mlme obj null");
return QDF_STATUS_E_INVAL;
}
mlme_obj->cfg.dfs_cfg.dfs_disable_channel_switch =
dfs_disable_channel_switch;
return QDF_STATUS_SUCCESS;
}
QDF_STATUS
ucfg_mlme_get_dfs_ignore_cac(struct wlan_objmgr_psoc *psoc,
bool *dfs_ignore_cac)
{
struct wlan_mlme_psoc_obj *mlme_obj;
mlme_obj = mlme_get_psoc_obj(psoc);
if (!mlme_obj) {
*dfs_ignore_cac = cfg_default(CFG_IGNORE_CAC);
mlme_err("mlme obj null");
return QDF_STATUS_E_INVAL;
}
*dfs_ignore_cac = mlme_obj->cfg.dfs_cfg.dfs_ignore_cac;
return QDF_STATUS_SUCCESS;
}
QDF_STATUS
ucfg_mlme_set_dfs_ignore_cac(struct wlan_objmgr_psoc *psoc,
bool dfs_ignore_cac)
{
struct wlan_mlme_psoc_obj *mlme_obj;
mlme_obj = mlme_get_psoc_obj(psoc);
if (!mlme_obj) {
mlme_err("mlme obj null");
return QDF_STATUS_E_INVAL;
}
mlme_obj->cfg.dfs_cfg.dfs_ignore_cac = dfs_ignore_cac;
return QDF_STATUS_SUCCESS;
}
QDF_STATUS
ucfg_mlme_get_sap_tx_leakage_threshold(struct wlan_objmgr_psoc *psoc,
uint32_t *sap_tx_leakage_threshold)
{
struct wlan_mlme_psoc_obj *mlme_obj;
mlme_obj = mlme_get_psoc_obj(psoc);
if (!mlme_obj) {
*sap_tx_leakage_threshold =
cfg_default(CFG_SAP_TX_LEAKAGE_THRESHOLD);
mlme_err("mlme obj null");
return QDF_STATUS_E_INVAL;
}
*sap_tx_leakage_threshold =
mlme_obj->cfg.dfs_cfg.sap_tx_leakage_threshold;
return QDF_STATUS_SUCCESS;
}
QDF_STATUS
ucfg_mlme_set_sap_tx_leakage_threshold(struct wlan_objmgr_psoc *psoc,
uint32_t sap_tx_leakage_threshold)
{
struct wlan_mlme_psoc_obj *mlme_obj;
mlme_obj = mlme_get_psoc_obj(psoc);
if (!mlme_obj) {
mlme_err("mlme obj null");
return QDF_STATUS_E_INVAL;
}
mlme_obj->cfg.dfs_cfg.sap_tx_leakage_threshold =
sap_tx_leakage_threshold;
return QDF_STATUS_SUCCESS;
}
QDF_STATUS
ucfg_mlme_get_dfs_filter_offload(struct wlan_objmgr_psoc *psoc,
bool *dfs_filter_offload)
{
struct wlan_mlme_psoc_obj *mlme_obj;
mlme_obj = mlme_get_psoc_obj(psoc);
if (!mlme_obj) {
*dfs_filter_offload =
cfg_default(CFG_ENABLE_DFS_PHYERR_FILTEROFFLOAD);
mlme_err("mlme obj null");
return QDF_STATUS_E_INVAL;
}
*dfs_filter_offload = mlme_obj->cfg.dfs_cfg.dfs_filter_offload;
return QDF_STATUS_SUCCESS;
}
QDF_STATUS
ucfg_mlme_set_dfs_filter_offload(struct wlan_objmgr_psoc *psoc,
bool dfs_filter_offload)
{
struct wlan_mlme_psoc_obj *mlme_obj;
mlme_obj = mlme_get_psoc_obj(psoc);
if (!mlme_obj) {
mlme_err("mlme obj null");
return QDF_STATUS_E_INVAL;
}
mlme_obj->cfg.dfs_cfg.dfs_filter_offload = dfs_filter_offload;
return QDF_STATUS_SUCCESS;
}
QDF_STATUS
ucfg_mlme_get_pmkid_modes(struct wlan_objmgr_psoc *psoc,
uint32_t *val)
@ -971,6 +1151,49 @@ ucfg_mlme_get_current_mcs_set(struct wlan_objmgr_psoc *psoc,
len);
}
QDF_STATUS
ucfg_mlme_get_wmi_wq_watchdog_timeout(struct wlan_objmgr_psoc *psoc,
uint32_t *wmi_wq_watchdog_timeout)
{
struct wlan_mlme_psoc_obj *mlme_obj;
mlme_obj = mlme_get_psoc_obj(psoc);
if (!mlme_obj) {
*wmi_wq_watchdog_timeout = cfg_default(CFG_WMI_WQ_WATCHDOG);
mlme_err("mlme obj null");
return QDF_STATUS_E_INVAL;
}
*wmi_wq_watchdog_timeout =
mlme_obj->cfg.timeouts.wmi_wq_watchdog_timeout;
return QDF_STATUS_SUCCESS;
}
QDF_STATUS
ucfg_mlme_set_wmi_wq_watchdog_timeout(struct wlan_objmgr_psoc *psoc,
uint32_t wmi_wq_watchdog_timeout)
{
struct wlan_mlme_psoc_obj *mlme_obj;
mlme_obj = mlme_get_psoc_obj(psoc);
if (!mlme_obj) {
mlme_err("mlme obj null");
return QDF_STATUS_E_INVAL;
}
if (!cfg_in_range(CFG_WMI_WQ_WATCHDOG, wmi_wq_watchdog_timeout)) {
mlme_err("wmi watchdog bite timeout is invalid %d",
wmi_wq_watchdog_timeout);
return QDF_STATUS_E_INVAL;
}
mlme_obj->cfg.timeouts.wmi_wq_watchdog_timeout =
wmi_wq_watchdog_timeout;
return QDF_STATUS_SUCCESS;
}
QDF_STATUS
ucfg_mlme_get_ps_data_inactivity_timeout(struct wlan_objmgr_psoc *psoc,
uint32_t *inactivity_timeout)

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,574 @@
/*
* Copyright (c) 2017-2018 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: Defines main P2P functions & structures
*/
#ifndef _WLAN_P2P_MAIN_H_
#define _WLAN_P2P_MAIN_H_
#include <qdf_trace.h>
#include <qdf_types.h>
#include <qdf_event.h>
#include <qdf_list.h>
#include <qdf_lock.h>
#include <qdf_idr.h>
#define MAX_QUEUE_LENGTH 20
#define P2P_NOA_ATTR_IND 0x1090
#define P2P_MODULE_NAME "P2P"
#define P2P_INVALID_VDEV_ID 0xFFFFFFFF
#define MAX_RANDOM_MAC_ADDRS 4
#define p2p_debug(params ...) \
QDF_TRACE_DEBUG(QDF_MODULE_ID_P2P, params)
#define p2p_info(params ...) \
QDF_TRACE_INFO(QDF_MODULE_ID_P2P, params)
#define p2p_warn(params ...) \
QDF_TRACE_WARN(QDF_MODULE_ID_P2P, params)
#define p2p_err(params ...) \
QDF_TRACE_ERROR(QDF_MODULE_ID_P2P, params)
#define p2p_alert(params ...) \
QDF_TRACE_FATAL(QDF_MODULE_ID_P2P, params)
#define p2p_nofl_debug(params ...) \
QDF_TRACE_DEBUG_NO_FL(QDF_MODULE_ID_P2P, params)
#define p2p_nofl_info(params ...) \
QDF_TRACE_INFO_NO_FL(QDF_MODULE_ID_P2P, params)
#define p2p_nofl_warn(params ...) \
QDF_TRACE_WARN_NO_FL(QDF_MODULE_ID_P2P, params)
#define p2p_nofl_err(params ...) \
QDF_TRACE_ERROR_NO_FL(QDF_MODULE_ID_P2P, params)
#define p2p_nofl_alert(params ...) \
QDF_TRACE_FATAL_NO_FL(QDF_MODULE_ID_P2P, params)
struct scheduler_msg;
struct p2p_tx_cnf;
struct p2p_rx_mgmt_frame;
struct p2p_lo_event;
struct p2p_start_param;
struct p2p_noa_info;
struct tx_action_context;
/**
* enum p2p_cmd_type - P2P request type
* @P2P_ROC_REQ: P2P roc request
* @P2P_CANCEL_ROC_REQ: Cancel P2P roc request
* @P2P_MGMT_TX: P2P tx action frame request
* @P2P_MGMT_TX_CANCEL: Cancel tx action frame request
* @P2P_CLEANUP_ROC: Cleanup roc queue
* @P2P_CLEANUP_TX: Cleanup tx mgmt queue
* @P2P_SET_RANDOM_MAC: Set Random MAC addr filter request
*/
enum p2p_cmd_type {
P2P_ROC_REQ = 0,
P2P_CANCEL_ROC_REQ,
P2P_MGMT_TX,
P2P_MGMT_TX_CANCEL,
P2P_CLEANUP_ROC,
P2P_CLEANUP_TX,
P2P_SET_RANDOM_MAC,
};
/**
* enum p2p_event_type - P2P event type
* @P2P_EVENT_SCAN_EVENT: P2P scan event
* @P2P_EVENT_MGMT_TX_ACK_CNF: P2P mgmt tx confirm frame
* @P2P_EVENT_RX_MGMT: P2P rx mgmt frame
* @P2P_EVENT_LO_STOPPED: P2P listen offload stopped event
* @P2P_EVENT_NOA: P2P noa event
* @P2P_EVENT_ADD_MAC_RSP: Set Random MAC addr event
*/
enum p2p_event_type {
P2P_EVENT_SCAN_EVENT = 0,
P2P_EVENT_MGMT_TX_ACK_CNF,
P2P_EVENT_RX_MGMT,
P2P_EVENT_LO_STOPPED,
P2P_EVENT_NOA,
P2P_EVENT_ADD_MAC_RSP,
};
/**
* struct p2p_tx_conf_event - p2p tx confirm event
* @p2p_soc_obj: p2p soc private object
* @buf: buffer address
* @status: tx status
*/
struct p2p_tx_conf_event {
struct p2p_soc_priv_obj *p2p_soc_obj;
qdf_nbuf_t nbuf;
uint32_t status;
};
/**
* struct p2p_rx_mgmt_event - p2p rx mgmt frame event
* @p2p_soc_obj: p2p soc private object
* @rx_mgmt: p2p rx mgmt frame structure
*/
struct p2p_rx_mgmt_event {
struct p2p_soc_priv_obj *p2p_soc_obj;
struct p2p_rx_mgmt_frame *rx_mgmt;
};
/**
* struct p2p_lo_stop_event - p2p listen offload stop event
* @p2p_soc_obj: p2p soc private object
* @lo_event: p2p lo stop structure
*/
struct p2p_lo_stop_event {
struct p2p_soc_priv_obj *p2p_soc_obj;
struct p2p_lo_event *lo_event;
};
/**
* struct p2p_noa_event - p2p noa event
* @p2p_soc_obj: p2p soc private object
* @noa_info: p2p noa information structure
*/
struct p2p_noa_event {
struct p2p_soc_priv_obj *p2p_soc_obj;
struct p2p_noa_info *noa_info;
};
/**
* struct p2p_mac_filter_rsp - p2p set mac filter respone
* @p2p_soc_obj: p2p soc private object
* @vdev_id: vdev id
* @status: successfully(1) or not (0)
*/
struct p2p_mac_filter_rsp {
struct p2p_soc_priv_obj *p2p_soc_obj;
uint32_t vdev_id;
uint32_t status;
};
#ifdef WLAN_FEATURE_P2P_DEBUG
/**
* enum p2p_connection_status - p2p connection status
* @P2P_NOT_ACTIVE: P2P not active status
* @P2P_GO_NEG_PROCESS: P2P GO negotiation in process
* @P2P_GO_NEG_COMPLETED: P2P GO negotiation complete
* @P2P_CLIENT_CONNECTING_STATE_1: P2P client connecting state 1
* @P2P_GO_COMPLETED_STATE: P2P GO complete state
* @P2P_CLIENT_CONNECTED_STATE_1: P2P client connected state 1
* @P2P_CLIENT_DISCONNECTED_STATE: P2P client disconnected state
* @P2P_CLIENT_CONNECTING_STATE_2: P2P client connecting state 2
* @P2P_CLIENT_COMPLETED_STATE: P2P client complete state
*/
enum p2p_connection_status {
P2P_NOT_ACTIVE,
P2P_GO_NEG_PROCESS,
P2P_GO_NEG_COMPLETED,
P2P_CLIENT_CONNECTING_STATE_1,
P2P_GO_COMPLETED_STATE,
P2P_CLIENT_CONNECTED_STATE_1,
P2P_CLIENT_DISCONNECTED_STATE,
P2P_CLIENT_CONNECTING_STATE_2,
P2P_CLIENT_COMPLETED_STATE
};
#endif
/**
* struct p2p_param - p2p parameters to be used
* @go_keepalive_period: P2P GO keep alive period
* @go_link_monitor_period: period where link is idle and
* where we send NULL frame
* @p2p_device_addr_admin: enable/disable to derive the P2P
* MAC address from the primary MAC address
* @skip_dfs_channel_p2p_search: kip DFS Channel in case of P2P Search
* @ignore_dynamic_dtim_in_p2p_mode:Ignore Dynamic Dtim in case of P2P options
*/
struct p2p_param {
uint32_t go_keepalive_period;
uint32_t go_link_monitor_period;
bool p2p_device_addr_admin;
bool skip_dfs_channel_p2p_search;
bool ignore_dynamic_dtim_in_p2p_mode;
};
/**
* struct p2p_soc_priv_obj - Per SoC p2p private object
* @soc: Pointer to SoC context
* @roc_q: Queue for pending roc requests
* @tx_q_roc: Queue for tx frames waiting for RoC
* @tx_q_ack: Queue for tx frames waiting for ack
* @scan_req_id: Scan requestor id
* @start_param: Start parameters, include callbacks and user
* data to HDD
* @cancel_roc_done: Cancel roc done event
* @cleanup_roc_done: Cleanup roc done event
* @cleanup_tx_done: Cleanup tx done event
* @roc_runtime_lock: Runtime lock for roc request
* @p2p_cb: Callbacks to protocol stack
* @cur_roc_vdev_id: Vdev id of current roc
* @p2p_idr: p2p idr
* @param: p2p parameters to be used
* @connection_status:Global P2P connection status
*/
struct p2p_soc_priv_obj {
struct wlan_objmgr_psoc *soc;
qdf_list_t roc_q;
qdf_list_t tx_q_roc;
qdf_list_t tx_q_ack;
wlan_scan_requester scan_req_id;
struct p2p_start_param *start_param;
qdf_event_t cancel_roc_done;
qdf_event_t cleanup_roc_done;
qdf_event_t cleanup_tx_done;
qdf_runtime_lock_t roc_runtime_lock;
struct p2p_protocol_callbacks p2p_cb;
uint32_t cur_roc_vdev_id;
qdf_idr p2p_idr;
struct p2p_param param;
#ifdef WLAN_FEATURE_P2P_DEBUG
enum p2p_connection_status connection_status;
#endif
};
/**
* struct action_frame_cookie - Action frame cookie item in cookie list
* @cookie_node: qdf_list_node
* @cookie: Cookie value
*/
struct action_frame_cookie {
qdf_list_node_t cookie_node;
uint64_t cookie;
};
/**
* struct action_frame_random_mac - Action Frame random mac addr &
* related attrs
* @p2p_vdev_obj: p2p vdev private obj ptr
* @in_use: Checks whether random mac is in use
* @addr: Contains random mac addr
* @freq: Channel frequency
* @clear_timer: timer to clear random mac filter
* @cookie_list: List of cookies tied with random mac
*/
struct action_frame_random_mac {
struct p2p_vdev_priv_obj *p2p_vdev_obj;
bool in_use;
uint8_t addr[QDF_MAC_ADDR_SIZE];
uint32_t freq;
qdf_mc_timer_t clear_timer;
qdf_list_t cookie_list;
};
/**
* p2p_request_mgr_callback_t() - callback to process set mac filter result
* @result: bool
* @context: callback context.
*
* Return: void
*/
typedef void (*p2p_request_mgr_callback_t)(bool result, void *context);
/**
* struct random_mac_priv - request private data struct
* @result: result of request.
*/
struct random_mac_priv {
bool result;
};
/**
* struct p2p_set_mac_filter_req - set mac addr filter cmd data structure
* @soc: soc object
* @vdev_id: vdev id
* @mac: mac address to be set
* @freq: frequency
* @set: set or clear
* @cb: callback func to be called when the request completion
* @req_cookie: cookie to be used when request completed
*/
struct p2p_set_mac_filter_req {
struct wlan_objmgr_psoc *soc;
uint32_t vdev_id;
uint8_t mac[QDF_MAC_ADDR_SIZE];
uint32_t freq;
bool set;
p2p_request_mgr_callback_t cb;
void *req_cookie;
};
/**
* struct p2p_vdev_priv_obj - Per vdev p2p private object
* @vdev: Pointer to vdev context
* @noa_info: NoA information
* @noa_status: NoA status i.e. Enabled / Disabled (TRUE/FALSE)
* @non_p2p_peer_count: Number of legacy stations connected to this GO
* @random_mac_lock: lock for random_mac list
* @random_mac: active random mac filter lists
* @pending_req: pending set mac filter request.
*/
struct p2p_vdev_priv_obj {
struct wlan_objmgr_vdev *vdev;
struct p2p_noa_info *noa_info;
bool noa_status;
uint16_t non_p2p_peer_count;
/* random address management for management action frames */
qdf_spinlock_t random_mac_lock;
struct action_frame_random_mac random_mac[MAX_RANDOM_MAC_ADDRS];
struct p2p_set_mac_filter_req pending_req;
};
/**
* struct p2p_noa_attr - p2p noa attribute
* @rsvd1: reserved bits 1
* @opps_ps: opps ps state of the AP
* @ct_win: ct window in TUs
* @index: identifies instance of NOA su element
* @rsvd2: reserved bits 2
* @noa1_count: interval count of noa1
* @noa1_duration: absent period duration of noa1
* @noa1_interval: absent period interval of noa1
* @noa1_start_time: 32 bit tsf time of noa1
* @rsvd3: reserved bits 3
* @noa2_count: interval count of noa2
* @noa2_duration: absent period duration of noa2
* @noa2_interval: absent period interval of noa2
* @noa2_start_time: 32 bit tsf time of noa2
*/
struct p2p_noa_attr {
uint32_t rsvd1:16;
uint32_t ct_win:7;
uint32_t opps_ps:1;
uint32_t index:8;
uint32_t rsvd2:24;
uint32_t noa1_count:8;
uint32_t noa1_duration;
uint32_t noa1_interval;
uint32_t noa1_start_time;
uint32_t rsvd3:24;
uint32_t noa2_count:8;
uint32_t noa2_duration;
uint32_t noa2_interval;
uint32_t noa2_start_time;
};
/**
* p2p_component_init() - P2P component initialization
*
* This function registers psoc/vdev create/delete handler.
*
* Return: QDF_STATUS_SUCCESS - in case of success
*/
QDF_STATUS p2p_component_init(void);
/**
* p2p_component_deinit() - P2P component de-init
*
* This function deregisters psoc/vdev create/delete handler.
*
* Return: QDF_STATUS_SUCCESS - in case of success
*/
QDF_STATUS p2p_component_deinit(void);
/**
* p2p_psoc_object_open() - Open P2P component
* @soc: soc context
*
* This function initialize p2p psoc object
*
* Return: QDF_STATUS_SUCCESS - in case of success
*/
QDF_STATUS p2p_psoc_object_open(struct wlan_objmgr_psoc *soc);
/**
* p2p_psoc_object_close() - Close P2P component
* @soc: soc context
*
* This function de-init p2p psoc object.
*
* Return: QDF_STATUS_SUCCESS - in case of success
*/
QDF_STATUS p2p_psoc_object_close(struct wlan_objmgr_psoc *soc);
/**
* p2p_psoc_start() - Start P2P component
* @soc: soc context
* @req: P2P start parameters
*
* This function sets up layer call back in p2p psoc object
*
* Return: QDF_STATUS_SUCCESS - in case of success
*/
QDF_STATUS p2p_psoc_start(struct wlan_objmgr_psoc *soc,
struct p2p_start_param *req);
/**
* p2p_psoc_stop() - Stop P2P component
* @soc: soc context
*
* This function clears up layer call back in p2p psoc object.
*
* Return: QDF_STATUS_SUCCESS - in case of success
*/
QDF_STATUS p2p_psoc_stop(struct wlan_objmgr_psoc *soc);
/**
* p2p_process_cmd() - Process P2P messages in OS interface queue
* @msg: message information
*
* This function is main handler for P2P messages in OS interface
* queue, it gets called by message scheduler.
*
* Return: QDF_STATUS_SUCCESS - in case of success
*/
QDF_STATUS p2p_process_cmd(struct scheduler_msg *msg);
/**
* p2p_process_evt() - Process P2P messages in target interface queue
* @msg: message information
*
* This function is main handler for P2P messages in target interface
* queue, it gets called by message scheduler.
*
* Return: QDF_STATUS_SUCCESS - in case of success
*/
QDF_STATUS p2p_process_evt(struct scheduler_msg *msg);
/**
* p2p_msg_flush_callback() - Callback used to flush P2P messages
* @msg: message information
*
* This callback will be called when scheduler flush some of P2P messages.
*
* Return: QDF_STATUS_SUCCESS - in case of success
*/
QDF_STATUS p2p_msg_flush_callback(struct scheduler_msg *msg);
/**
* p2p_event_flush_callback() - Callback used to flush P2P events
* @msg: event information
*
* This callback will be called when scheduler flush some of P2P events.
*
* Return: QDF_STATUS_SUCCESS - in case of success
*/
QDF_STATUS p2p_event_flush_callback(struct scheduler_msg *msg);
#ifdef FEATURE_P2P_LISTEN_OFFLOAD
/**
* p2p_process_lo_stop() - Process lo stop event
* @lo_stop_event: listen offload stop event information
*
* This function handles listen offload stop event and deliver this
* event to HDD layer by registered callback.
*
* Return: QDF_STATUS_SUCCESS - in case of success
*/
QDF_STATUS p2p_process_lo_stop(
struct p2p_lo_stop_event *lo_stop_event);
#else
static inline QDF_STATUS p2p_process_lo_stop(
struct p2p_lo_stop_event *lo_stop_event)
{
return QDF_STATUS_SUCCESS;
}
#endif
/**
* p2p_process_noa() - Process noa event
* @noa_event: noa event information
*
* This function handles noa event and save noa information in p2p
* vdev object.
*
* Return: QDF_STATUS_SUCCESS - in case of success
*/
QDF_STATUS p2p_process_noa(struct p2p_noa_event *noa_event);
#ifdef WLAN_FEATURE_P2P_DEBUG
/**
* p2p_status_scan() - Update P2P connection status
* @vdev: vdev context
*
* This function updates P2P connection status when scanning
*
* Return: QDF_STATUS_SUCCESS - in case of success
*/
QDF_STATUS p2p_status_scan(struct wlan_objmgr_vdev *vdev);
/**
* p2p_status_connect() - Update P2P connection status
* @vdev: vdev context
*
* This function updates P2P connection status when connecting.
*
* Return: QDF_STATUS_SUCCESS - in case of success
*/
QDF_STATUS p2p_status_connect(struct wlan_objmgr_vdev *vdev);
/**
* p2p_status_disconnect() - Update P2P connection status
* @vdev: vdev context
*
* This function updates P2P connection status when disconnecting.
*
* Return: QDF_STATUS_SUCCESS - in case of success
*/
QDF_STATUS p2p_status_disconnect(struct wlan_objmgr_vdev *vdev);
/**
* p2p_status_start_bss() - Update P2P connection status
* @vdev: vdev context
*
* This function updates P2P connection status when starting BSS.
*
* Return: QDF_STATUS_SUCCESS - in case of success
*/
QDF_STATUS p2p_status_start_bss(struct wlan_objmgr_vdev *vdev);
/**
* p2p_status_stop_bss() - Update P2P connection status
* @vdev: vdev context
*
* This function updates P2P connection status when stopping BSS.
*
* Return: QDF_STATUS_SUCCESS - in case of success
*/
QDF_STATUS p2p_status_stop_bss(struct wlan_objmgr_vdev *vdev);
#else
static inline QDF_STATUS p2p_status_scan(struct wlan_objmgr_vdev *vdev)
{
return QDF_STATUS_SUCCESS;
}
static inline QDF_STATUS p2p_status_connect(struct wlan_objmgr_vdev *vdev)
{
return QDF_STATUS_SUCCESS;
}
static inline QDF_STATUS p2p_status_disconnect(struct wlan_objmgr_vdev *vdev)
{
return QDF_STATUS_SUCCESS;
}
static inline QDF_STATUS p2p_status_start_bss(struct wlan_objmgr_vdev *vdev)
{
return QDF_STATUS_SUCCESS;
}
static inline QDF_STATUS p2p_status_stop_bss(struct wlan_objmgr_vdev *vdev)
{
return QDF_STATUS_SUCCESS;
}
#endif /* WLAN_FEATURE_P2P_DEBUG */
#endif /* _WLAN_P2P_MAIN_H_ */

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,439 @@
/*
* Copyright (c) 2017-2018 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: Defines off channel tx API & structures
*/
#ifndef _WLAN_P2P_OFF_CHAN_TX_H_
#define _WLAN_P2P_OFF_CHAN_TX_H_
#include <qdf_types.h>
#include <qdf_mc_timer.h>
#include <qdf_list.h>
#define P2P_EID_VENDOR 0xdd
#define P2P_ACTION_VENDOR_SPECIFIC_CATEGORY 0x7F
#define P2P_PUBLIC_ACTION_FRAME 0x4
#define P2P_MAC_MGMT_ACTION 0xD
#define P2P_PUBLIC_ACTION_VENDOR_SPECIFIC 0x9
#define P2P_NOA_ATTR 0xC
#define P2P_MAX_NOA_ATTR_LEN 31
#define P2P_IE_HEADER_LEN 6
#define P2P_MAX_IE_LENGTH 255
#define P2P_ACTION_OFFSET 24
#define P2P_PUBLIC_ACTION_FRAME_TYPE_OFFSET 30
#define P2P_ACTION_FRAME_TYPE_OFFSET 29
#define PROBE_RSP_IE_OFFSET 36
#define P2P_TX_PKT_MIN_HEADROOM (64)
#define P2P_OUI "\x50\x6f\x9a\x09"
#define P2P_OUI_SIZE 4
#define P2P_ACTION_FRAME_RSP_WAIT 500
#define P2P_ACTION_FRAME_ACK_WAIT 300
#define P2P_ACTION_FRAME_TX_TIMEOUT 2000
#define DST_MAC_ADDR_OFFSET 4
#define SRC_MAC_ADDR_OFFSET (DST_MAC_ADDR_OFFSET + QDF_MAC_ADDR_SIZE)
#define P2P_NOA_STREAM_ARR_SIZE (P2P_MAX_NOA_ATTR_LEN + (2 * P2P_IE_HEADER_LEN))
#define P2P_GET_TYPE_FRM_FC(__fc__) (((__fc__) & 0x0F) >> 2)
#define P2P_GET_SUBTYPE_FRM_FC(__fc__) (((__fc__) & 0xF0) >> 4)
#define WLAN_WAIT_TIME_SET_RND 100
struct p2p_soc_priv_obj;
struct cancel_roc_context;
struct p2p_tx_conf_event;
struct p2p_rx_mgmt_event;
/**
* enum p2p_frame_type - frame type
* @P2P_FRAME_MGMT: mgmt frame
* @P2P_FRAME_NOT_SUPPORT: not support frame type
*/
enum p2p_frame_type {
P2P_FRAME_MGMT = 0,
P2P_FRAME_NOT_SUPPORT,
};
/**
* enum p2p_frame_sub_type - frame sub type
* @P2P_MGMT_PROBE_REQ: probe request frame
* @P2P_MGMT_PROBE_RSP: probe response frame
* @P2P_MGMT_ACTION: action frame
* @P2P_MGMT_NOT_SUPPORT: not support sub frame type
*/
enum p2p_frame_sub_type {
P2P_MGMT_PROBE_REQ = 4,
P2P_MGMT_PROBE_RSP,
P2P_MGMT_ACTION = 13,
P2P_MGMT_NOT_SUPPORT,
};
/**
* enum p2p_public_action_type - public action frame type
* @P2P_PUBLIC_ACTION_NEG_REQ: go negotiation request frame
* @P2P_PUBLIC_ACTION_NEG_RSP: go negotiation response frame
* @P2P_PUBLIC_ACTION_NEG_CNF: go negotiation confirm frame
* @P2P_PUBLIC_ACTION_INVIT_REQ: p2p invitation request frame
* @P2P_PUBLIC_ACTION_INVIT_RSP: p2p invitation response frame
* @P2P_PUBLIC_ACTION_DEV_DIS_REQ: device discoverability request
* @P2P_PUBLIC_ACTION_DEV_DIS_RSP: device discoverability response
* @P2P_PUBLIC_ACTION_PROV_DIS_REQ: provision discovery request
* @P2P_PUBLIC_ACTION_PROV_DIS_RSP: provision discovery response
* @P2P_PUBLIC_ACTION_GAS_INIT_REQ: gas initial request,
* @P2P_PUBLIC_ACTION_GAS_INIT_RSP: gas initial response
* @P2P_PUBLIC_ACTION_GAS_COMB_REQ: gas comeback request
* @P2P_PUBLIC_ACTION_GAS_COMB_RSP: gas comeback response
* @P2P_PUBLIC_ACTION_NOT_SUPPORT: not support p2p public action frame
*/
enum p2p_public_action_type {
P2P_PUBLIC_ACTION_NEG_REQ = 0,
P2P_PUBLIC_ACTION_NEG_RSP,
P2P_PUBLIC_ACTION_NEG_CNF,
P2P_PUBLIC_ACTION_INVIT_REQ,
P2P_PUBLIC_ACTION_INVIT_RSP,
P2P_PUBLIC_ACTION_DEV_DIS_REQ,
P2P_PUBLIC_ACTION_DEV_DIS_RSP,
P2P_PUBLIC_ACTION_PROV_DIS_REQ,
P2P_PUBLIC_ACTION_PROV_DIS_RSP,
P2P_PUBLIC_ACTION_GAS_INIT_REQ = 10,
P2P_PUBLIC_ACTION_GAS_INIT_RSP,
P2P_PUBLIC_ACTION_GAS_COMB_REQ,
P2P_PUBLIC_ACTION_GAS_COMB_RSP,
P2P_PUBLIC_ACTION_NOT_SUPPORT,
};
/**
* enum p2p_action_type - p2p action frame type
* @P2P_ACTION_PRESENCE_REQ: presence request frame
* @P2P_ACTION_PRESENCE_RSP: presence response frame
* @P2P_ACTION_NOT_SUPPORT: not support action frame type
*/
enum p2p_action_type {
P2P_ACTION_PRESENCE_REQ = 1,
P2P_ACTION_PRESENCE_RSP = 2,
P2P_ACTION_NOT_SUPPORT,
};
struct p2p_frame_info {
enum p2p_frame_type type;
enum p2p_frame_sub_type sub_type;
enum p2p_public_action_type public_action_type;
enum p2p_action_type action_type;
};
/**
* struct tx_action_context - tx action frame context
* @node: Node for next element in the list
* @p2p_soc_obj: Pointer to SoC global p2p private object
* @vdev_id: Vdev id on which this request has come
* @scan_id: Scan id given by scan component for this roc req
* @roc_cookie: Cookie for remain on channel request
* @id: Identifier of this tx context
* @chan: Chan for which this tx has been requested
* @buf: tx buffer
* @buf_len: Length of tx buffer
* @off_chan: Is this off channel tx
* @no_cck: Required cck or not
* @no_ack: Required ack or not
* @duration: Duration for the RoC
* @tx_timer: RoC timer
* @frame_info: Frame type information
*/
struct tx_action_context {
qdf_list_node_t node;
struct p2p_soc_priv_obj *p2p_soc_obj;
int vdev_id;
int scan_id;
uint64_t roc_cookie;
int32_t id;
uint8_t chan;
uint8_t *buf;
int buf_len;
bool off_chan;
bool no_cck;
bool no_ack;
bool rand_mac_tx;
uint32_t duration;
qdf_mc_timer_t tx_timer;
struct p2p_frame_info frame_info;
qdf_nbuf_t nbuf;
};
/**
* p2p_rand_mac_tx_done() - process random mac mgmt tx done
* @soc: soc
* @tx_ctx: tx context
*
* This function will remove the random mac addr filter reference.
*
* Return: void
*/
void
p2p_rand_mac_tx_done(struct wlan_objmgr_psoc *soc,
struct tx_action_context *tx_ctx);
/**
* p2p_clear_mac_filter() - send clear mac addr filter cmd
* @soc: soc
* @vdev_id: vdev id
* @mac: mac addr
* @freq: freq
*
* This function send clear random mac addr filter command to p2p component
* msg core
*
* Return: QDF_STATUS_SUCCESS - if sent successfully.
* otherwise: failed.
*/
QDF_STATUS
p2p_clear_mac_filter(struct wlan_objmgr_psoc *soc, uint32_t vdev_id,
uint8_t *mac, uint32_t freq);
/**
* p2p_is_vdev_support_rand_mac() - check vdev type support random mac mgmt
* tx or not
* @vdev: vdev object
*
* Return: true: support random mac mgmt tx
* false: not support random mac mgmt tx.
*/
bool
p2p_is_vdev_support_rand_mac(struct wlan_objmgr_vdev *vdev);
/**
* p2p_dump_tx_queue() - dump tx queue
* @p2p_soc_obj: p2p soc private object
*
* This function dumps tx queue and output details about tx context in
* queue.
*
* Return: None
*/
void p2p_dump_tx_queue(struct p2p_soc_priv_obj *p2p_soc_obj);
/**
* p2p_ready_to_tx_frame() - dump tx queue
* @p2p_soc_obj: p2p soc private object
* @cookie: cookie is pointer to roc
*
* This function find out the tx context in wait for roc queue and tx
* this frame.
*
* Return: QDF_STATUS_SUCCESS - in case of success
*/
QDF_STATUS p2p_ready_to_tx_frame(struct p2p_soc_priv_obj *p2p_soc_obj,
uint64_t cookie);
/**
* p2p_cleanup_tx_sync() - Cleanup tx queue
* @p2p_soc_obj: p2p psoc private object
* @vdev: vdev object
*
* This function cleanup tx context in queue until cancellation done.
* To avoid deadlock, don't call from scheduler thread.
*
* Return: QDF_STATUS_SUCCESS - in case of success
*/
QDF_STATUS p2p_cleanup_tx_sync(
struct p2p_soc_priv_obj *p2p_soc_obj,
struct wlan_objmgr_vdev *vdev);
/**
* p2p_process_cleanup_tx_queue() - process the message to cleanup tx
* @param: pointer to cleanup parameters
*
* This function cleanup wait for roc queue and wait for ack queue.
*
* Return: QDF_STATUS_SUCCESS - in case of success
*/
QDF_STATUS p2p_process_cleanup_tx_queue(
struct p2p_cleanup_param *param);
/**
* p2p_process_mgmt_tx() - Process mgmt frame tx request
* @tx_ctx: tx context
*
* This function handles mgmt frame tx request. It will call API from
* mgmt txrx component.
*
* Return: QDF_STATUS_SUCCESS - in case of success
*/
QDF_STATUS p2p_process_mgmt_tx(struct tx_action_context *tx_ctx);
/**
* p2p_process_mgmt_tx_cancel() - Process cancel mgmt frame tx request
* @cancel_tx: cancel tx context
*
* This function cancel mgmt frame tx request by cookie.
*
* Return: QDF_STATUS_SUCCESS - in case of success
*/
QDF_STATUS p2p_process_mgmt_tx_cancel(
struct cancel_roc_context *cancel_tx);
/**
* p2p_process_mgmt_tx_ack_cnf() - Process tx ack event
* @tx_cnf_event: tx confirmation event information
*
* This function mgmt frame tx confirmation. It will deliver this
* event to up layer
*
* Return: QDF_STATUS_SUCCESS - in case of success
*/
QDF_STATUS p2p_process_mgmt_tx_ack_cnf(
struct p2p_tx_conf_event *tx_cnf_event);
/**
* p2p_process_rx_mgmt() - Process rx mgmt frame event
* @rx_mgmt_event: rx mgmt frame event information
*
* This function mgmt frame rx mgmt frame event. It will deliver this
* event to up layer
*
* Return: QDF_STATUS_SUCCESS - in case of success
*/
QDF_STATUS p2p_process_rx_mgmt(
struct p2p_rx_mgmt_event *rx_mgmt_event);
/**
* p2p_find_tx_ctx_by_nbuf() - find tx context by nbuf
* @p2p_soc_obj: p2p soc object
* @nbuf: pointer to nbuf
*
* This function finds out tx context by nbuf.
*
* Return: pointer to tx context
*/
struct tx_action_context *p2p_find_tx_ctx_by_nbuf(
struct p2p_soc_priv_obj *p2p_soc_obj, void *nbuf);
#define P2P_80211_FRM_SA_OFFSET 10
/**
* p2p_del_random_mac() - del mac fitler from given vdev rand mac list
* @soc: soc object
* @vdev_id: vdev id
* @rnd_cookie: random mac mgmt tx cookie
* @duration: timeout value to flush the addr in target.
*
* This function will del the mac addr filter from vdev random mac addr list.
* If there is no reference to mac addr, it will set a clear timer to flush it
* in target finally.
*
* Return: QDF_STATUS_SUCCESS - del successfully.
* other : failed to del the mac address entry.
*/
QDF_STATUS
p2p_del_random_mac(struct wlan_objmgr_psoc *soc, uint32_t vdev_id,
uint64_t rnd_cookie, uint32_t duration);
/**
* p2p_check_random_mac() - check random mac addr or not
* @soc: soc context
* @vdev_id: vdev id
* @random_mac_addr: mac addr to be checked
*
* This function check the input addr is random mac addr or not for vdev.
*
* Return: true if addr is random mac address else false.
*/
bool p2p_check_random_mac(struct wlan_objmgr_psoc *soc, uint32_t vdev_id,
uint8_t *random_mac_addr);
/**
* p2p_process_set_rand_mac() - process the set random mac command
* @set_filter_req: request data
*
* This function will process the set mac addr filter command.
*
* Return: QDF_STATUS_SUCCESS: if process successfully
* other: failed.
*/
QDF_STATUS p2p_process_set_rand_mac(
struct p2p_set_mac_filter_req *set_filter_req);
/**
* p2p_process_set_rand_mac_rsp() - process the set random mac response
* @resp: response date
*
* This function will process the set mac addr filter event.
*
* Return: QDF_STATUS_SUCCESS: if process successfully
* other: failed.
*/
QDF_STATUS p2p_process_set_rand_mac_rsp(struct p2p_mac_filter_rsp *resp);
/**
* p2p_del_all_rand_mac_vdev() - del all random mac filter in vdev
* @vdev: vdev object
*
* This function will del all random mac filter in vdev
*
* Return: void
*/
void p2p_del_all_rand_mac_vdev(struct wlan_objmgr_vdev *vdev);
/**
* p2p_del_all_rand_mac_soc() - del all random mac filter in soc
* @soc: soc object
*
* This function will del all random mac filter in all vdev of soc
*
* Return: void
*/
void p2p_del_all_rand_mac_soc(struct wlan_objmgr_psoc *soc);
/**
* p2p_rand_mac_tx() - handle random mac mgmt tx
* @tx_action: tx action context
*
* This function will check whether need to set random mac tx filter for a
* given mgmt tx request and do the mac addr filter process as needed.
*
* Return: void
*/
void p2p_rand_mac_tx(struct tx_action_context *tx_action);
/**
* p2p_init_random_mac_vdev() - Init random mac data for vdev
* @p2p_vdev_obj: p2p vdev private object
*
* This function will init the per vdev random mac data structure.
*
* Return: void
*/
void p2p_init_random_mac_vdev(struct p2p_vdev_priv_obj *p2p_vdev_obj);
/**
* p2p_deinit_random_mac_vdev() - Init random mac data for vdev
* @p2p_vdev_obj: p2p vdev private object
*
* This function will deinit the per vdev random mac data structure.
*
* Return: void
*/
void p2p_deinit_random_mac_vdev(struct p2p_vdev_priv_obj *p2p_vdev_obj);
#endif /* _WLAN_P2P_OFF_CHAN_TX_H_ */

View file

@ -0,0 +1,929 @@
/*
* Copyright (c) 2017-2018 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: This file contains RoC API definitions
*/
#include <wlan_mgmt_txrx_utils_api.h>
#include <wlan_scan_public_structs.h>
#include <wlan_scan_ucfg_api.h>
#include <wlan_objmgr_psoc_obj.h>
#include <wlan_objmgr_global_obj.h>
#include <wlan_objmgr_pdev_obj.h>
#include <wlan_objmgr_vdev_obj.h>
#include <wlan_policy_mgr_api.h>
#include <wlan_utility.h>
#include "wlan_p2p_public_struct.h"
#include "wlan_p2p_tgt_api.h"
#include "wlan_p2p_ucfg_api.h"
#include "wlan_p2p_roc.h"
#include "wlan_p2p_main.h"
#include "wlan_p2p_off_chan_tx.h"
/**
* p2p_mgmt_rx_ops() - register or unregister rx callback
* @psoc: psoc object
* @isregister: register if true, unregister if false
*
* This function registers or unregisters rx callback to mgmt txrx
* component.
*
* Return: QDF_STATUS_SUCCESS - in case of success
*/
static QDF_STATUS p2p_mgmt_rx_ops(struct wlan_objmgr_psoc *psoc,
bool isregister)
{
struct mgmt_txrx_mgmt_frame_cb_info frm_cb_info;
QDF_STATUS status;
p2p_debug("psoc:%pK, is register rx:%d", psoc, isregister);
frm_cb_info.frm_type = MGMT_PROBE_REQ;
frm_cb_info.mgmt_rx_cb = tgt_p2p_mgmt_frame_rx_cb;
if (isregister)
status = wlan_mgmt_txrx_register_rx_cb(psoc,
WLAN_UMAC_COMP_P2P, &frm_cb_info, 1);
else
status = wlan_mgmt_txrx_deregister_rx_cb(psoc,
WLAN_UMAC_COMP_P2P, &frm_cb_info, 1);
return status;
}
/**
* p2p_scan_start() - Start scan
* @roc_ctx: remain on channel request
*
* This function trigger a start scan request to scan component.
*
* Return: QDF_STATUS_SUCCESS - in case of success
*/
static QDF_STATUS p2p_scan_start(struct p2p_roc_context *roc_ctx)
{
QDF_STATUS status;
struct scan_start_request *req;
struct wlan_objmgr_vdev *vdev;
struct p2p_soc_priv_obj *p2p_soc_obj = roc_ctx->p2p_soc_obj;
vdev = wlan_objmgr_get_vdev_by_id_from_psoc(
p2p_soc_obj->soc, roc_ctx->vdev_id,
WLAN_P2P_ID);
if (!vdev) {
p2p_err("vdev is NULL");
return QDF_STATUS_E_INVAL;
}
req = qdf_mem_malloc(sizeof(*req));
if (!req) {
p2p_err("failed to alloc scan start request");
status = QDF_STATUS_E_NOMEM;
goto fail;
}
ucfg_scan_init_default_params(vdev, req);
roc_ctx->scan_id = ucfg_scan_get_scan_id(p2p_soc_obj->soc);
req->vdev = vdev;
req->scan_req.scan_id = roc_ctx->scan_id;
req->scan_req.p2p_scan_type = SCAN_P2P_LISTEN;
req->scan_req.scan_req_id = p2p_soc_obj->scan_req_id;
req->scan_req.chan_list.num_chan = 1;
req->scan_req.chan_list.chan[0].freq = wlan_chan_to_freq(roc_ctx->chan);
req->scan_req.dwell_time_passive = roc_ctx->duration;
req->scan_req.dwell_time_active = 0;
req->scan_req.scan_priority = SCAN_PRIORITY_HIGH;
req->scan_req.num_bssid = 1;
qdf_set_macaddr_broadcast(&req->scan_req.bssid_list[0]);
status = ucfg_scan_start(req);
p2p_debug("start scan, scan req id:%d, scan id:%d, status:%d",
p2p_soc_obj->scan_req_id, roc_ctx->scan_id, status);
fail:
wlan_objmgr_vdev_release_ref(vdev, WLAN_P2P_ID);
return status;
}
/**
* p2p_scan_abort() - Abort scan
* @roc_ctx: remain on channel request
*
* This function trigger an abort scan request to scan component.
*
* Return: QDF_STATUS_SUCCESS - in case of success
*/
static QDF_STATUS p2p_scan_abort(struct p2p_roc_context *roc_ctx)
{
QDF_STATUS status;
struct scan_cancel_request *req;
struct wlan_objmgr_vdev *vdev;
struct p2p_soc_priv_obj *p2p_soc_obj = roc_ctx->p2p_soc_obj;
p2p_debug("abort scan, scan req id:%d, scan id:%d",
p2p_soc_obj->scan_req_id, roc_ctx->scan_id);
vdev = wlan_objmgr_get_vdev_by_id_from_psoc(
p2p_soc_obj->soc, roc_ctx->vdev_id,
WLAN_P2P_ID);
if (!vdev) {
p2p_err("vdev is NULL");
return QDF_STATUS_E_INVAL;
}
req = qdf_mem_malloc(sizeof(*req));
if (!req) {
p2p_err("failed to alloc scan cancel request");
status = QDF_STATUS_E_NOMEM;
goto fail;
}
req->vdev = vdev;
req->cancel_req.requester = p2p_soc_obj->scan_req_id;
req->cancel_req.scan_id = roc_ctx->scan_id;
req->cancel_req.vdev_id = roc_ctx->vdev_id;
req->cancel_req.req_type = WLAN_SCAN_CANCEL_SINGLE;
qdf_mtrace(QDF_MODULE_ID_P2P, QDF_MODULE_ID_SCAN,
req->cancel_req.req_type,
req->vdev->vdev_objmgr.vdev_id, req->cancel_req.scan_id);
status = ucfg_scan_cancel(req);
p2p_debug("abort scan, scan req id:%d, scan id:%d, status:%d",
p2p_soc_obj->scan_req_id, roc_ctx->scan_id, status);
fail:
wlan_objmgr_vdev_release_ref(vdev, WLAN_P2P_ID);
return status;
}
/**
* p2p_send_roc_event() - Send roc event
* @roc_ctx: remain on channel request
* @evt: roc event information
*
* This function send out roc event to up layer.
*
* Return: QDF_STATUS_SUCCESS - in case of success
*/
static QDF_STATUS p2p_send_roc_event(
struct p2p_roc_context *roc_ctx, enum p2p_roc_event evt)
{
struct p2p_soc_priv_obj *p2p_soc_obj;
struct p2p_event p2p_evt;
struct p2p_start_param *start_param;
p2p_soc_obj = roc_ctx->p2p_soc_obj;
if (!p2p_soc_obj || !(p2p_soc_obj->start_param)) {
p2p_err("Invalid p2p soc object or start parameters");
return QDF_STATUS_E_INVAL;
}
start_param = p2p_soc_obj->start_param;
if (!(start_param->event_cb)) {
p2p_err("Invalid p2p event callback to up layer");
return QDF_STATUS_E_INVAL;
}
p2p_evt.vdev_id = roc_ctx->vdev_id;
p2p_evt.roc_event = evt;
p2p_evt.cookie = (uint64_t)roc_ctx->id;
p2p_evt.chan = roc_ctx->chan;
p2p_evt.duration = roc_ctx->duration;
p2p_debug("p2p soc_obj:%pK, roc_ctx:%pK, vdev_id:%d, roc_event:"
"%d, cookie:%llx, chan:%d, duration:%d", p2p_soc_obj,
roc_ctx, p2p_evt.vdev_id, p2p_evt.roc_event,
p2p_evt.cookie, p2p_evt.chan, p2p_evt.duration);
start_param->event_cb(start_param->event_cb_data, &p2p_evt);
return QDF_STATUS_SUCCESS;
}
/**
* p2p_destroy_roc_ctx() - destroy roc ctx
* @roc_ctx: remain on channel request
* @up_layer_event: if send uplayer event
* @in_roc_queue: if roc context in roc queue
*
* This function destroy roc context.
*
* Return: QDF_STATUS_SUCCESS - in case of success
*/
static QDF_STATUS p2p_destroy_roc_ctx(struct p2p_roc_context *roc_ctx,
bool up_layer_event, bool in_roc_queue)
{
QDF_STATUS status = QDF_STATUS_SUCCESS;
struct p2p_soc_priv_obj *p2p_soc_obj = roc_ctx->p2p_soc_obj;
p2p_debug("p2p_soc_obj:%pK, roc_ctx:%pK, up_layer_event:%d, in_roc_queue:%d",
p2p_soc_obj, roc_ctx, up_layer_event, in_roc_queue);
if (up_layer_event) {
if (roc_ctx->roc_state < ROC_STATE_ON_CHAN)
p2p_send_roc_event(roc_ctx, ROC_EVENT_READY_ON_CHAN);
p2p_send_roc_event(roc_ctx, ROC_EVENT_COMPLETED);
}
if (in_roc_queue) {
status = qdf_list_remove_node(&p2p_soc_obj->roc_q,
(qdf_list_node_t *)roc_ctx);
if (QDF_STATUS_SUCCESS != status)
p2p_err("Failed to remove roc req, status %d", status);
}
qdf_idr_remove(&p2p_soc_obj->p2p_idr, roc_ctx->id);
qdf_mem_free(roc_ctx);
return status;
}
/**
* p2p_execute_cancel_roc_req() - Execute cancel roc request
* @roc_ctx: remain on channel request
*
* This function stop roc timer, abort scan and unregister mgmt rx
* callbak.
*
* Return: QDF_STATUS_SUCCESS - in case of success
*/
static QDF_STATUS p2p_execute_cancel_roc_req(
struct p2p_roc_context *roc_ctx)
{
QDF_STATUS status;
struct p2p_soc_priv_obj *p2p_soc_obj = roc_ctx->p2p_soc_obj;
p2p_debug("p2p soc obj:%pK, roc ctx:%pK, vdev_id:%d, scan_id:%d, tx ctx:%pK, chan:%d, phy_mode:%d, duration:%d, roc_type:%d, roc_state:%d",
p2p_soc_obj, roc_ctx, roc_ctx->vdev_id,
roc_ctx->scan_id, roc_ctx->tx_ctx, roc_ctx->chan,
roc_ctx->phy_mode, roc_ctx->duration,
roc_ctx->roc_type, roc_ctx->roc_state);
roc_ctx->roc_state = ROC_STATE_CANCEL_IN_PROG;
qdf_event_reset(&p2p_soc_obj->cancel_roc_done);
status = qdf_mc_timer_stop(&roc_ctx->roc_timer);
if (status != QDF_STATUS_SUCCESS)
p2p_err("Failed to stop roc timer, roc %pK", roc_ctx);
status = p2p_scan_abort(roc_ctx);
if (status != QDF_STATUS_SUCCESS) {
p2p_err("Failed to abort scan, status:%d, destroy roc %pK",
status, roc_ctx);
qdf_mc_timer_destroy(&roc_ctx->roc_timer);
p2p_mgmt_rx_ops(p2p_soc_obj->soc, false);
p2p_destroy_roc_ctx(roc_ctx, true, true);
qdf_event_set(&p2p_soc_obj->cancel_roc_done);
return status;
}
return QDF_STATUS_SUCCESS;
}
/**
* p2p_roc_timeout() - Callback for roc timeout
* @pdata: pointer to p2p soc private object
*
* This function is callback for roc time out.
*
* Return: None
*/
static void p2p_roc_timeout(void *pdata)
{
struct p2p_roc_context *roc_ctx;
struct p2p_soc_priv_obj *p2p_soc_obj;
p2p_debug("p2p soc obj:%pK", pdata);
p2p_soc_obj = pdata;
if (!p2p_soc_obj) {
p2p_err("Invalid p2p soc object");
return;
}
roc_ctx = p2p_find_current_roc_ctx(p2p_soc_obj);
if (!roc_ctx) {
p2p_debug("No P2P roc is pending");
return;
}
p2p_debug("p2p soc obj:%pK, roc ctx:%pK, vdev_id:%d, scan_id:%d, tx ctx:%pK, chan:%d, phy_mode:%d, duration:%d, roc_type:%d, roc_state:%d",
roc_ctx->p2p_soc_obj, roc_ctx, roc_ctx->vdev_id,
roc_ctx->scan_id, roc_ctx->tx_ctx, roc_ctx->chan,
roc_ctx->phy_mode, roc_ctx->duration,
roc_ctx->roc_type, roc_ctx->roc_state);
if (roc_ctx->roc_state == ROC_STATE_CANCEL_IN_PROG) {
p2p_err("Cancellation already in progress");
return;
}
p2p_execute_cancel_roc_req(roc_ctx);
}
/**
* p2p_execute_roc_req() - Execute roc request
* @roc_ctx: remain on channel request
*
* This function init roc timer, start scan and register mgmt rx
* callbak.
*
* Return: QDF_STATUS_SUCCESS - in case of success
*/
static QDF_STATUS p2p_execute_roc_req(struct p2p_roc_context *roc_ctx)
{
QDF_STATUS status;
uint32_t go_num;
struct p2p_soc_priv_obj *p2p_soc_obj = roc_ctx->p2p_soc_obj;
p2p_debug("p2p soc obj:%pK, roc ctx:%pK, vdev_id:%d, scan_id:%d, tx ctx:%pK, chan:%d, phy_mode:%d, duration:%d, roc_type:%d, roc_state:%d",
p2p_soc_obj, roc_ctx, roc_ctx->vdev_id,
roc_ctx->scan_id, roc_ctx->tx_ctx, roc_ctx->chan,
roc_ctx->phy_mode, roc_ctx->duration,
roc_ctx->roc_type, roc_ctx->roc_state);
/* prevent runtime suspend */
qdf_runtime_pm_prevent_suspend(&p2p_soc_obj->roc_runtime_lock);
status = qdf_mc_timer_init(&roc_ctx->roc_timer,
QDF_TIMER_TYPE_SW, p2p_roc_timeout,
p2p_soc_obj);
if (status != QDF_STATUS_SUCCESS) {
p2p_err("failed to init roc timer, status:%d", status);
goto fail;
}
roc_ctx->roc_state = ROC_STATE_REQUESTED;
if (roc_ctx->duration < P2P_MAX_ROC_DURATION) {
go_num = policy_mgr_mode_specific_connection_count(
p2p_soc_obj->soc, PM_P2P_GO_MODE, NULL);
p2p_debug("present go number:%d", go_num);
if (go_num)
roc_ctx->duration *= P2P_ROC_DURATION_MULTI_GO_PRESENT;
else
roc_ctx->duration *= P2P_ROC_DURATION_MULTI_GO_ABSENT;
/* this is to protect too huge value if some customers
* give a higher value from supplicant
*/
if (roc_ctx->duration > P2P_MAX_ROC_DURATION)
roc_ctx->duration = P2P_MAX_ROC_DURATION;
}
status = p2p_scan_start(roc_ctx);
if (status != QDF_STATUS_SUCCESS) {
qdf_mc_timer_destroy(&roc_ctx->roc_timer);
p2p_err("Failed to start scan, status:%d", status);
goto fail;
}
fail:
if (status != QDF_STATUS_SUCCESS) {
p2p_destroy_roc_ctx(roc_ctx, true, true);
qdf_runtime_pm_allow_suspend(
&p2p_soc_obj->roc_runtime_lock);
return status;
}
p2p_soc_obj->cur_roc_vdev_id = roc_ctx->vdev_id;
status = p2p_mgmt_rx_ops(p2p_soc_obj->soc, true);
if (status != QDF_STATUS_SUCCESS)
p2p_err("Failed to register mgmt rx callback, status:%d",
status);
return status;
}
/**
* p2p_find_roc_ctx() - Find out roc context by cookie
* @p2p_soc_obj: p2p psoc private object
* @cookie: cookie is the key to find out roc context
*
* This function find out roc context by cookie from p2p psoc private
* object
*
* Return: Pointer to roc context - success
* NULL - failure
*/
static struct p2p_roc_context *p2p_find_roc_ctx(
struct p2p_soc_priv_obj *p2p_soc_obj, uint64_t cookie)
{
struct p2p_roc_context *curr_roc_ctx;
qdf_list_node_t *p_node;
QDF_STATUS status;
p2p_debug("p2p soc obj:%pK, cookie:%llx", p2p_soc_obj, cookie);
status = qdf_list_peek_front(&p2p_soc_obj->roc_q, &p_node);
while (QDF_IS_STATUS_SUCCESS(status)) {
curr_roc_ctx = qdf_container_of(p_node,
struct p2p_roc_context, node);
if ((uintptr_t) curr_roc_ctx == cookie)
return curr_roc_ctx;
status = qdf_list_peek_next(&p2p_soc_obj->roc_q,
p_node, &p_node);
}
return NULL;
}
/**
* p2p_process_scan_start_evt() - Process scan start event
* @roc_ctx: remain on channel request
*
* This function process scan start event.
*
* Return: QDF_STATUS_SUCCESS - in case of success
*/
static QDF_STATUS p2p_process_scan_start_evt(
struct p2p_roc_context *roc_ctx)
{
roc_ctx->roc_state = ROC_STATE_STARTED;
p2p_debug("scan started, roc ctx:%pK, scan id:%d",
roc_ctx, roc_ctx->scan_id);
return QDF_STATUS_SUCCESS;
}
/**
* p2p_process_ready_on_channel_evt() - Process ready on channel event
* @roc_ctx: remain on channel request
*
* This function process ready on channel event. Starts roc timer.
* Indicates this event to up layer if this is user request roc. Sends
* mgmt frame if this is off channel rx roc.
*
* Return: QDF_STATUS_SUCCESS - in case of success
*/
static QDF_STATUS p2p_process_ready_on_channel_evt(
struct p2p_roc_context *roc_ctx)
{
uint64_t cookie;
struct p2p_soc_priv_obj *p2p_soc_obj;
QDF_STATUS status;
p2p_soc_obj = roc_ctx->p2p_soc_obj;
roc_ctx->roc_state = ROC_STATE_ON_CHAN;
p2p_debug("p2p soc obj:%pK, roc ctx:%pK, vdev_id:%d, scan_id:%d, tx ctx:%pK, chan:%d, phy_mode:%d, duration:%d, roc_type:%d, roc_state:%d",
p2p_soc_obj, roc_ctx, roc_ctx->vdev_id,
roc_ctx->scan_id, roc_ctx->tx_ctx, roc_ctx->chan,
roc_ctx->phy_mode, roc_ctx->duration,
roc_ctx->roc_type, roc_ctx->roc_state);
status = qdf_mc_timer_start(&roc_ctx->roc_timer,
(roc_ctx->duration + P2P_EVENT_PROPAGATE_TIME));
if (status != QDF_STATUS_SUCCESS)
p2p_err("Remain on Channel timer start failed");
if (roc_ctx->roc_type == USER_REQUESTED) {
p2p_debug("user required roc, send roc event");
status = p2p_send_roc_event(roc_ctx,
ROC_EVENT_READY_ON_CHAN);
}
cookie = (uintptr_t)roc_ctx;
/* ready to tx frame */
p2p_ready_to_tx_frame(p2p_soc_obj, cookie);
return status;
}
/**
* p2p_process_scan_complete_evt() - Process scan complete event
* @roc_ctx: remain on channel request
*
* This function process scan complete event.
*
* Return: QDF_STATUS_SUCCESS - in case of success
*/
static QDF_STATUS p2p_process_scan_complete_evt(
struct p2p_roc_context *roc_ctx)
{
QDF_STATUS status;
qdf_list_node_t *next_node;
uint32_t size;
struct p2p_soc_priv_obj *p2p_soc_obj = roc_ctx->p2p_soc_obj;
p2p_debug("p2p soc obj:%pK, roc ctx:%pK, vdev_id:%d, scan_id:%d, tx ctx:%pK, chan:%d, phy_mode:%d, duration:%d, roc_type:%d, roc_state:%d",
p2p_soc_obj, roc_ctx, roc_ctx->vdev_id,
roc_ctx->scan_id, roc_ctx->tx_ctx, roc_ctx->chan,
roc_ctx->phy_mode, roc_ctx->duration,
roc_ctx->roc_type, roc_ctx->roc_state);
/* allow runtime suspend */
qdf_runtime_pm_allow_suspend(&p2p_soc_obj->roc_runtime_lock);
if (QDF_TIMER_STATE_RUNNING ==
qdf_mc_timer_get_current_state(&roc_ctx->roc_timer)) {
status = qdf_mc_timer_stop(&roc_ctx->roc_timer);
if (status != QDF_STATUS_SUCCESS)
p2p_err("Failed to stop roc timer");
}
status = qdf_mc_timer_destroy(&roc_ctx->roc_timer);
if (status != QDF_STATUS_SUCCESS)
p2p_err("Failed to destroy roc timer");
status = p2p_mgmt_rx_ops(p2p_soc_obj->soc, false);
p2p_soc_obj->cur_roc_vdev_id = P2P_INVALID_VDEV_ID;
if (status != QDF_STATUS_SUCCESS)
p2p_err("Failed to deregister mgmt rx callback");
if (roc_ctx->roc_type == USER_REQUESTED)
status = p2p_send_roc_event(roc_ctx,
ROC_EVENT_COMPLETED);
p2p_destroy_roc_ctx(roc_ctx, false, true);
qdf_event_set(&p2p_soc_obj->cancel_roc_done);
size = qdf_list_size(&p2p_soc_obj->roc_q);
p2p_debug("P2P roc queue size is %d", status);
if (size > 0) {
status = qdf_list_peek_front(&p2p_soc_obj->roc_q,
&next_node);
if (QDF_STATUS_SUCCESS != status) {
p2p_err("Failed to peek roc req from front, status %d",
status);
return status;
}
roc_ctx = qdf_container_of(next_node,
struct p2p_roc_context, node);
status = p2p_execute_roc_req(roc_ctx);
}
return status;
}
QDF_STATUS p2p_mgmt_rx_action_ops(struct wlan_objmgr_psoc *psoc,
bool isregister)
{
struct mgmt_txrx_mgmt_frame_cb_info frm_cb_info[2];
QDF_STATUS status;
p2p_debug("psoc:%pK, is register rx:%d", psoc, isregister);
frm_cb_info[0].frm_type = MGMT_ACTION_VENDOR_SPECIFIC;
frm_cb_info[0].mgmt_rx_cb = tgt_p2p_mgmt_frame_rx_cb;
frm_cb_info[1].frm_type = MGMT_ACTION_CATEGORY_VENDOR_SPECIFIC;
frm_cb_info[1].mgmt_rx_cb = tgt_p2p_mgmt_frame_rx_cb;
if (isregister)
status = wlan_mgmt_txrx_register_rx_cb(psoc,
WLAN_UMAC_COMP_P2P, frm_cb_info, 2);
else
status = wlan_mgmt_txrx_deregister_rx_cb(psoc,
WLAN_UMAC_COMP_P2P, frm_cb_info, 2);
return status;
}
struct p2p_roc_context *p2p_find_current_roc_ctx(
struct p2p_soc_priv_obj *p2p_soc_obj)
{
struct p2p_roc_context *roc_ctx;
qdf_list_node_t *p_node;
QDF_STATUS status;
status = qdf_list_peek_front(&p2p_soc_obj->roc_q, &p_node);
while (QDF_IS_STATUS_SUCCESS(status)) {
roc_ctx = qdf_container_of(p_node,
struct p2p_roc_context, node);
if (roc_ctx->roc_state != ROC_STATE_IDLE) {
p2p_debug("p2p soc obj:%pK, roc ctx:%pK, vdev_id"
":%d, scan_id:%d, tx ctx:%pK, chan:"
"%d, phy_mode:%d, duration:%d, "
"roc_type:%d, roc_state:%d",
roc_ctx->p2p_soc_obj, roc_ctx,
roc_ctx->vdev_id, roc_ctx->scan_id,
roc_ctx->tx_ctx, roc_ctx->chan,
roc_ctx->phy_mode, roc_ctx->duration,
roc_ctx->roc_type, roc_ctx->roc_state);
return roc_ctx;
}
status = qdf_list_peek_next(&p2p_soc_obj->roc_q,
p_node, &p_node);
}
return NULL;
}
struct p2p_roc_context *p2p_find_roc_by_tx_ctx(
struct p2p_soc_priv_obj *p2p_soc_obj, uint64_t cookie)
{
struct p2p_roc_context *curr_roc_ctx;
qdf_list_node_t *p_node;
QDF_STATUS status;
p2p_debug("p2p soc obj:%pK, cookie:%llx", p2p_soc_obj, cookie);
status = qdf_list_peek_front(&p2p_soc_obj->roc_q, &p_node);
while (QDF_IS_STATUS_SUCCESS(status)) {
curr_roc_ctx = qdf_container_of(p_node,
struct p2p_roc_context, node);
if ((uintptr_t) curr_roc_ctx->tx_ctx == cookie)
return curr_roc_ctx;
status = qdf_list_peek_next(&p2p_soc_obj->roc_q,
p_node, &p_node);
}
return NULL;
}
struct p2p_roc_context *p2p_find_roc_by_chan(
struct p2p_soc_priv_obj *p2p_soc_obj, uint8_t chan)
{
struct p2p_roc_context *roc_ctx;
qdf_list_node_t *p_node;
QDF_STATUS status;
status = qdf_list_peek_front(&p2p_soc_obj->roc_q, &p_node);
while (QDF_IS_STATUS_SUCCESS(status)) {
roc_ctx = qdf_container_of(p_node,
struct p2p_roc_context,
node);
if (roc_ctx->chan == chan) {
p2p_debug("p2p soc obj:%pK, roc ctx:%pK, vdev_id:%d, scan_id:%d, tx ctx:%pK, chan:%d, phy_mode:%d, duration:%d, roc_type:%d, roc_state:%d",
roc_ctx->p2p_soc_obj, roc_ctx,
roc_ctx->vdev_id, roc_ctx->scan_id,
roc_ctx->tx_ctx, roc_ctx->chan,
roc_ctx->phy_mode, roc_ctx->duration,
roc_ctx->roc_type, roc_ctx->roc_state);
return roc_ctx;
}
status = qdf_list_peek_next(&p2p_soc_obj->roc_q,
p_node, &p_node);
}
return NULL;
}
QDF_STATUS p2p_restart_roc_timer(struct p2p_roc_context *roc_ctx)
{
QDF_STATUS status = QDF_STATUS_E_FAILURE;
if (QDF_TIMER_STATE_RUNNING ==
qdf_mc_timer_get_current_state(&roc_ctx->roc_timer)) {
p2p_debug("roc timer is running");
status = qdf_mc_timer_stop(&roc_ctx->roc_timer);
if (status != QDF_STATUS_SUCCESS) {
p2p_err("Failed to stop roc timer");
return status;
}
status = qdf_mc_timer_start(&roc_ctx->roc_timer,
roc_ctx->duration);
if (status != QDF_STATUS_SUCCESS)
p2p_err("Remain on Channel timer start failed");
}
return status;
}
QDF_STATUS p2p_cleanup_roc_sync(
struct p2p_soc_priv_obj *p2p_soc_obj,
struct wlan_objmgr_vdev *vdev)
{
struct scheduler_msg msg = {0};
struct p2p_cleanup_param *param;
QDF_STATUS status;
uint32_t vdev_id;
if (!p2p_soc_obj) {
p2p_err("p2p soc context is NULL");
return QDF_STATUS_E_FAILURE;
}
p2p_debug("p2p_soc_obj:%pK, vdev:%pK", p2p_soc_obj, vdev);
param = qdf_mem_malloc(sizeof(*param));
if (!param) {
p2p_err("failed to allocate cleanup param");
return QDF_STATUS_E_NOMEM;
}
param->p2p_soc_obj = p2p_soc_obj;
if (vdev)
vdev_id = (uint32_t)wlan_vdev_get_id(vdev);
else
vdev_id = P2P_INVALID_VDEV_ID;
param->vdev_id = vdev_id;
qdf_event_reset(&p2p_soc_obj->cleanup_roc_done);
msg.type = P2P_CLEANUP_ROC;
msg.bodyptr = param;
msg.callback = p2p_process_cmd;
status = scheduler_post_message(QDF_MODULE_ID_P2P,
QDF_MODULE_ID_P2P,
QDF_MODULE_ID_OS_IF, &msg);
if (status != QDF_STATUS_SUCCESS) {
p2p_err("failed to post message");
qdf_mem_free(param);
return status;
}
status = qdf_wait_single_event(
&p2p_soc_obj->cleanup_roc_done,
P2P_WAIT_CLEANUP_ROC);
if (status != QDF_STATUS_SUCCESS)
p2p_err("wait for cleanup roc timeout, %d", status);
return status;
}
QDF_STATUS p2p_process_cleanup_roc_queue(
struct p2p_cleanup_param *param)
{
uint32_t vdev_id;
QDF_STATUS status, ret;
struct p2p_roc_context *roc_ctx;
qdf_list_node_t *p_node;
struct p2p_soc_priv_obj *p2p_soc_obj;
if (!param || !(param->p2p_soc_obj)) {
p2p_err("Invalid cleanup param");
return QDF_STATUS_E_FAILURE;
}
p2p_soc_obj = param->p2p_soc_obj;
vdev_id = param->vdev_id;
p2p_debug("clean up idle roc request, roc queue size:%d, vdev id:%d",
qdf_list_size(&p2p_soc_obj->roc_q), vdev_id);
status = qdf_list_peek_front(&p2p_soc_obj->roc_q, &p_node);
while (QDF_IS_STATUS_SUCCESS(status)) {
roc_ctx = qdf_container_of(p_node,
struct p2p_roc_context, node);
p2p_debug("p2p soc obj:%pK, roc ctx:%pK, vdev_id:%d, scan_id:%d, tx ctx:%pK, chan:%d, phy_mode:%d, duration:%d, roc_type:%d, roc_state:%d",
roc_ctx->p2p_soc_obj, roc_ctx,
roc_ctx->vdev_id, roc_ctx->scan_id,
roc_ctx->tx_ctx, roc_ctx->chan,
roc_ctx->phy_mode, roc_ctx->duration,
roc_ctx->roc_type, roc_ctx->roc_state);
status = qdf_list_peek_next(&p2p_soc_obj->roc_q,
p_node, &p_node);
if ((roc_ctx->roc_state == ROC_STATE_IDLE) &&
((vdev_id == P2P_INVALID_VDEV_ID) ||
(vdev_id == roc_ctx->vdev_id))) {
ret = qdf_list_remove_node(
&p2p_soc_obj->roc_q,
(qdf_list_node_t *)roc_ctx);
if (ret == QDF_STATUS_SUCCESS)
qdf_mem_free(roc_ctx);
else
p2p_err("Failed to remove roc ctx from queue");
}
}
p2p_debug("clean up started roc request, roc queue size:%d",
qdf_list_size(&p2p_soc_obj->roc_q));
status = qdf_list_peek_front(&p2p_soc_obj->roc_q, &p_node);
while (QDF_IS_STATUS_SUCCESS(status)) {
roc_ctx = qdf_container_of(p_node,
struct p2p_roc_context, node);
p2p_debug("p2p soc obj:%pK, roc ctx:%pK, vdev_id:%d, scan_id:%d, tx ctx:%pK, chan:%d, phy_mode:%d, duration:%d, roc_type:%d, roc_state:%d",
roc_ctx->p2p_soc_obj, roc_ctx, roc_ctx->vdev_id,
roc_ctx->scan_id, roc_ctx->tx_ctx, roc_ctx->chan,
roc_ctx->phy_mode, roc_ctx->duration,
roc_ctx->roc_type, roc_ctx->roc_state);
status = qdf_list_peek_next(&p2p_soc_obj->roc_q,
p_node, &p_node);
if ((roc_ctx->roc_state != ROC_STATE_IDLE) &&
((vdev_id == P2P_INVALID_VDEV_ID) ||
(vdev_id == roc_ctx->vdev_id))) {
if (roc_ctx->roc_state !=
ROC_STATE_CANCEL_IN_PROG)
p2p_execute_cancel_roc_req(roc_ctx);
ret = qdf_wait_single_event(
&p2p_soc_obj->cancel_roc_done,
P2P_WAIT_CANCEL_ROC);
p2p_debug("RoC cancellation done, return:%d", ret);
}
}
qdf_event_set(&p2p_soc_obj->cleanup_roc_done);
return QDF_STATUS_SUCCESS;
}
QDF_STATUS p2p_process_roc_req(struct p2p_roc_context *roc_ctx)
{
struct p2p_soc_priv_obj *p2p_soc_obj;
struct p2p_roc_context *curr_roc_ctx;
QDF_STATUS status;
uint32_t size;
p2p_soc_obj = roc_ctx->p2p_soc_obj;
p2p_debug("p2p soc obj:%pK, roc ctx:%pK, vdev_id:%d, scan_id:%d, tx_ctx:%pK, chan:%d, phy_mode:%d, duration:%d, roc_type:%d, roc_state:%d",
p2p_soc_obj, roc_ctx, roc_ctx->vdev_id,
roc_ctx->scan_id, roc_ctx->tx_ctx, roc_ctx->chan,
roc_ctx->phy_mode, roc_ctx->duration,
roc_ctx->roc_type, roc_ctx->roc_state);
status = qdf_list_insert_back(&p2p_soc_obj->roc_q,
&roc_ctx->node);
if (QDF_STATUS_SUCCESS != status) {
p2p_destroy_roc_ctx(roc_ctx, true, false);
p2p_debug("Failed to insert roc req, status %d", status);
return status;
}
size = qdf_list_size(&p2p_soc_obj->roc_q);
if (size == 1) {
status = p2p_execute_roc_req(roc_ctx);
} else if (size > 1) {
curr_roc_ctx = p2p_find_current_roc_ctx(p2p_soc_obj);
/*TODO, to handle extend roc */
}
return status;
}
QDF_STATUS p2p_process_cancel_roc_req(
struct cancel_roc_context *cancel_roc_ctx)
{
struct p2p_soc_priv_obj *p2p_soc_obj;
struct p2p_roc_context *curr_roc_ctx;
QDF_STATUS status;
p2p_soc_obj = cancel_roc_ctx->p2p_soc_obj;
curr_roc_ctx = p2p_find_roc_ctx(p2p_soc_obj,
cancel_roc_ctx->cookie);
p2p_debug("p2p soc obj:%pK, cookie:%llx, roc ctx:%pK",
p2p_soc_obj, cancel_roc_ctx->cookie, curr_roc_ctx);
if (!curr_roc_ctx) {
p2p_debug("Failed to find roc req by cookie, cookie %llx",
cancel_roc_ctx->cookie);
return QDF_STATUS_E_INVAL;
}
if (curr_roc_ctx->roc_state == ROC_STATE_IDLE) {
status = p2p_destroy_roc_ctx(curr_roc_ctx, true, true);
} else if (curr_roc_ctx->roc_state ==
ROC_STATE_CANCEL_IN_PROG) {
p2p_debug("Receive cancel roc req when roc req is canceling, cookie %llx",
cancel_roc_ctx->cookie);
status = QDF_STATUS_SUCCESS;
} else {
status = p2p_execute_cancel_roc_req(curr_roc_ctx);
}
return status;
}
void p2p_scan_event_cb(struct wlan_objmgr_vdev *vdev,
struct scan_event *event, void *arg)
{
struct p2p_soc_priv_obj *p2p_soc_obj;
struct p2p_roc_context *curr_roc_ctx;
p2p_debug("soc:%pK, scan event:%d", arg, event->type);
p2p_soc_obj = (struct p2p_soc_priv_obj *)arg;
if (!p2p_soc_obj) {
p2p_err("Invalid P2P context");
return;
}
curr_roc_ctx = p2p_find_current_roc_ctx(p2p_soc_obj);
if (!curr_roc_ctx) {
p2p_err("Failed to find valid P2P roc context");
return;
}
qdf_mtrace(QDF_MODULE_ID_SCAN, QDF_MODULE_ID_P2P, event->type,
event->vdev_id, event->scan_id);
switch (event->type) {
case SCAN_EVENT_TYPE_STARTED:
p2p_process_scan_start_evt(curr_roc_ctx);
break;
case SCAN_EVENT_TYPE_FOREIGN_CHANNEL:
p2p_process_ready_on_channel_evt(curr_roc_ctx);
break;
case SCAN_EVENT_TYPE_COMPLETED:
case SCAN_EVENT_TYPE_DEQUEUED:
case SCAN_EVENT_TYPE_START_FAILED:
p2p_process_scan_complete_evt(curr_roc_ctx);
break;
default:
p2p_debug("drop scan event, %d", event->type);
}
}

View file

@ -0,0 +1,247 @@
/*
* Copyright (c) 2017-2018 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: Defines RoC API & structures
*/
#ifndef _WLAN_P2P_ROC_H_
#define _WLAN_P2P_ROC_H_
#include <qdf_types.h>
#include <qdf_mc_timer.h>
#include <qdf_list.h>
#define P2P_EVENT_PROPAGATE_TIME 10
#define P2P_WAIT_CANCEL_ROC 1000
#define P2P_WAIT_CLEANUP_ROC 2000
#define P2P_MAX_ROC_DURATION 1500
#define P2P_ROC_DURATION_MULTI_GO_PRESENT 6
#define P2P_ROC_DURATION_MULTI_GO_ABSENT 10
#define P2P_ACTION_FRAME_DEFAULT_WAIT 200
struct wlan_objmgr_vdev;
struct scan_event;
/**
* enum roc_type - user requested or off channel tx
* @USER_REQUESTED: Requested by supplicant
* @OFF_CHANNEL_TX: Issued internally for off channel tx
*/
enum roc_type {
USER_REQUESTED,
OFF_CHANNEL_TX,
};
/**
* enum roc_state - P2P RoC state
* @ROC_STATE_IDLE: RoC not yet started or completed
* @ROC_STATE_REQUESTED: Sent scan command to scan manager
* @ROC_STATE_STARTED: Got started event from scan manager
* @ROC_STATE_ON_CHAN: Got foreign channel event from SCM
* @ROC_STATE_CANCEL_IN_PROG: Requested abort scan to SCM
* @ROC_STATE_INVALID: We should not come to this state
*/
enum roc_state {
ROC_STATE_IDLE = 0,
ROC_STATE_REQUESTED,
ROC_STATE_STARTED,
ROC_STATE_ON_CHAN,
ROC_STATE_CANCEL_IN_PROG,
ROC_STATE_INVALID,
};
/**
* struct p2p_roc_context - RoC request context
* @node: Node for next element in the list
* @p2p_soc_obj: Pointer to SoC global p2p private object
* @vdev_id: Vdev id on which this request has come
* @scan_id: Scan id given by scan component for this roc req
* @tx_ctx: TX context if this ROC is for tx MGMT
* @chan: Chan for which this RoC has been requested
* @phy_mode: PHY mode
* @duration: Duration for the RoC
* @roc_type: RoC type User requested or internal
* @roc_timer: RoC timer
* @roc_state: Roc state
* @id: identifier of roc
*/
struct p2p_roc_context {
qdf_list_node_t node;
struct p2p_soc_priv_obj *p2p_soc_obj;
uint32_t vdev_id;
uint32_t scan_id;
void *tx_ctx;
uint8_t chan;
uint8_t phy_mode;
uint32_t duration;
enum roc_type roc_type;
qdf_mc_timer_t roc_timer;
enum roc_state roc_state;
int32_t id;
};
/**
* struct cancel_roc_context - p2p cancel roc context
* @p2p_soc_obj: Pointer to SoC global p2p private object
* @cookie: Cookie which is given by supplicant
*/
struct cancel_roc_context {
struct p2p_soc_priv_obj *p2p_soc_obj;
uint64_t cookie;
};
/**
* struct p2p_cleanup_param - p2p cleanup parameters
* @p2p_soc_obj: Pointer to SoC global p2p private object
* @vdev_id: vdev id
*/
struct p2p_cleanup_param {
struct p2p_soc_priv_obj *p2p_soc_obj;
uint32_t vdev_id;
};
/**
* p2p_mgmt_rx_action_ops() - register or unregister rx action callback
* @psoc: psoc object
* @isregister: register if true, unregister if false
*
* This function registers or unregisters rx action frame callback to
* mgmt txrx component.
*
* Return: QDF_STATUS_SUCCESS - in case of success
*/
QDF_STATUS p2p_mgmt_rx_action_ops(struct wlan_objmgr_psoc *psoc,
bool isregister);
/**
* p2p_find_current_roc_ctx() - Find out roc context in progressing
* @p2p_soc_obj: p2p psoc private object
*
* This function finds out roc context in progressing from p2p psoc
* private object
*
* Return: Pointer to roc context - success
* NULL - failure
*/
struct p2p_roc_context *p2p_find_current_roc_ctx(
struct p2p_soc_priv_obj *p2p_soc_obj);
/**
* p2p_find_roc_by_tx_ctx() - Find out roc context by tx context
* @p2p_soc_obj: p2p psoc private object
* @cookie: cookie is the key to find out roc context
*
* This function finds out roc context by tx context from p2p psoc
* private object
*
* Return: Pointer to roc context - success
* NULL - failure
*/
struct p2p_roc_context *p2p_find_roc_by_tx_ctx(
struct p2p_soc_priv_obj *p2p_soc_obj, uint64_t cookie);
/**
* p2p_find_roc_by_chan() - Find out roc context by channel
* @p2p_soc_obj: p2p psoc private object
* @chan: channel of the ROC
*
* This function finds out roc context by channel from p2p psoc
* private object
*
* Return: Pointer to roc context - success
* NULL - failure
*/
struct p2p_roc_context *p2p_find_roc_by_chan(
struct p2p_soc_priv_obj *p2p_soc_obj, uint8_t chan);
/**
* p2p_restart_roc_timer() - Restarts roc timer
* @roc_ctx: remain on channel context
*
* This function restarts roc timer with updated duration.
*
* Return: QDF_STATUS_SUCCESS - in case of success
*/
QDF_STATUS p2p_restart_roc_timer(struct p2p_roc_context *roc_ctx);
/**
* p2p_cleanup_roc_sync() - Cleanup roc context in queue
* @p2p_soc_obj: p2p psoc private object
* @vdev: vdev object
*
* This function cleanup roc context in queue, include the roc
* context in progressing until cancellation done. To avoid deadlock,
* don't call from scheduler thread.
*
* Return: QDF_STATUS_SUCCESS - in case of success
*/
QDF_STATUS p2p_cleanup_roc_sync(
struct p2p_soc_priv_obj *p2p_soc_obj,
struct wlan_objmgr_vdev *vdev);
/**
* p2p_process_cleanup_roc_queue() - process the message to cleanup roc
* @param: pointer to cleanup parameters
*
* This function process the message to cleanup roc context in queue,
* include the roc context in progressing.
*
* Return: QDF_STATUS_SUCCESS - in case of success
*/
QDF_STATUS p2p_process_cleanup_roc_queue(
struct p2p_cleanup_param *param);
/**
* p2p_process_roc_req() - Process roc request
* @roc_ctx: roc request context
*
* This function handles roc request. It will call API from scan/mgmt
* txrx component.
*
* Return: QDF_STATUS_SUCCESS - in case of success
*/
QDF_STATUS p2p_process_roc_req(struct p2p_roc_context *roc_ctx);
/**
* p2p_process_cancel_roc_req() - Process cancel roc request
* @cancel_roc_ctx: cancel roc request context
*
* This function cancel roc request by cookie.
*
* Return: QDF_STATUS_SUCCESS - in case of success
*/
QDF_STATUS p2p_process_cancel_roc_req(
struct cancel_roc_context *cancel_roc_ctx);
/**
* p2p_scan_event_cb() - Process scan event
* @vdev: vdev associated to this scan event
* @event: event information
* @arg: registered arguments
*
* This function handles P2P scan event and deliver P2P event to HDD
* layer by registered callback.
*
* Return: None
*/
void p2p_scan_event_cb(struct wlan_objmgr_vdev *vdev,
struct scan_event *event, void *arg);
#endif /* _WLAN_P2P_ROC_H_ */

View file

@ -0,0 +1,128 @@
/*
* Copyright (c) 2018 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.
*/
#if !defined(CONFIG_P2P_H__)
#define CONFIG_P2P_H__
#include "cfg_define.h"
#include "cfg_converged.h"
#include "qdf_types.h"
/*
* <ini>
* gGoKeepAlivePeriod - P2P GO keep alive period.
* @Min: 1
* @Max: 65535
* @Default: 20
*
* This is P2P GO keep alive period.
*
* Related: None.
*
* Supported Feature: P2P
*
* Usage: Internal/External
*
* </ini>
*/
#define CFG_GO_KEEP_ALIVE_PERIOD CFG_INI_UINT( \
"gGoKeepAlivePeriod", \
1, \
65535, \
20, \
CFG_VALUE_OR_DEFAULT, \
"P2P GO keep alive period")
/*
* <ini>
* gGoLinkMonitorPeriod - period where link is idle and where
* we send NULL frame
* @Min: 3
* @Max: 50
* @Default: 10
*
* This is period where link is idle and where we send NULL frame for P2P GO.
*
* Related: None.
*
* Supported Feature: P2P
*
* Usage: Internal/External
*
* </ini>
*/
#define CFG_GO_LINK_MONITOR_PERIOD CFG_INI_UINT( \
"gGoLinkMonitorPeriod", \
3, \
50, \
10, \
CFG_VALUE_OR_DEFAULT, \
"period where link is idle and where we send NULL frame")
/*
* <ini>
* isP2pDeviceAddrAdministrated - Enables to derive the P2P MAC address from
* the primary MAC address
* @Min: 0
* @Max: 1
* @Default: 1
*
* This ini is used to enable/disable to derive the P2P MAC address from the
* primary MAC address.
*
* Related: None.
*
* Supported Feature: P2P
*
* Usage: Internal/External
*
* </ini>
*/
#define CFG_P2P_DEVICE_ADDRESS_ADMINISTRATED CFG_INI_BOOL( \
"isP2pDeviceAddrAdministrated", \
1, \
"derive the P2P MAC address from the primary MAC address")
/*
* <ini>
* gSkipDfsChannelInP2pSearch - Skip DFS Channel in case of P2P Search
* @Min: 0
* @Max: 1
* @Default: 1
*
* This ini is used to disable(skip) dfs channel in p2p search.
* Related: None.
*
* Supported Feature: DFS P2P
*
* Usage: Internal/External
*
* </ini>
*/
#define CFG_ENABLE_SKIP_DFS_IN_P2P_SEARCH CFG_INI_BOOL( \
"gSkipDfsChannelInP2pSearch", \
1, \
"skip dfs channel in p2p search")
#define CFG_P2P_ALL \
CFG(CFG_GO_KEEP_ALIVE_PERIOD) \
CFG(CFG_GO_LINK_MONITOR_PERIOD) \
CFG(CFG_P2P_DEVICE_ADDRESS_ADMINISTRATED) \
CFG(CFG_ENABLE_SKIP_DFS_IN_P2P_SEARCH)
#endif

View file

@ -0,0 +1,76 @@
/*
* Copyright (c) 2018 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: Contains p2p configures interface definitions
*/
#ifndef _WLAN_P2P_CFG_API_H_
#define _WLAN_P2P_CFG_API_H_
#include <qdf_types.h>
struct wlan_objmgr_psoc;
/**
* cfg_p2p_get_go_keepalive_period() - get go keepalive period
* @psoc: pointer to psoc object
* @period: go keepalive period
*
* This function gets go keepalive period to p2p component
*/
QDF_STATUS
cfg_p2p_get_go_keepalive_period(struct wlan_objmgr_psoc *psoc,
uint32_t *period);
/**
* cfg_p2p_get_go_link_monitor_period() - get go link monitor period
* @psoc: pointer to psoc object
* @period: go link monitor period
*
* This function gets go link monitor period to p2p component
*/
QDF_STATUS
cfg_p2p_get_go_link_monitor_period(struct wlan_objmgr_psoc *psoc,
uint32_t *period);
/**
* cfg_p2p_get_device_addr_admin() - get enable/disable p2p device
* addr administrated
* @psoc: pointer to psoc object
* @enable: enable/disable p2p device addr administrated
*
* This function gets enable/disable p2p device addr administrated
*/
QDF_STATUS
cfg_p2p_get_device_addr_admin(struct wlan_objmgr_psoc *psoc,
bool *enable);
/**
* cfg_p2p_get_skip_dfs_channel_p2p_search() - get skip dfs channel
* in p2p search
* @psoc: pointer to psoc object
* @enable: enable/disable skip dfs channel in p2p search
*
* This function gets enable/disable skip dfs channel in p2p search
*/
QDF_STATUS
cfg_p2p_get_skip_dfs_channel_p2p_search(struct wlan_objmgr_psoc *psoc,
bool *enable);
#endif /* _WLAN_P2P_CFG_API_H_ */

View file

@ -0,0 +1,272 @@
/*
* Copyright (c) 2017-2018 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: Contains p2p public data structure definations
*/
#ifndef _WLAN_P2P_PUBLIC_STRUCT_H_
#define _WLAN_P2P_PUBLIC_STRUCT_H_
#include <qdf_types.h>
#define P2P_MAX_NOA_DESC 4
/**
* struct p2p_ps_params - P2P powersave related params
* @opp_ps: opportunistic power save
* @ctwindow: CT window
* @count: count
* @duration: duration
* @interval: interval
* @single_noa_duration: single shot noa duration
* @ps_selection: power save selection
* @session_id: session id
*/
struct p2p_ps_params {
uint8_t opp_ps;
uint32_t ctwindow;
uint8_t count;
uint32_t duration;
uint32_t interval;
uint32_t single_noa_duration;
uint8_t ps_selection;
uint8_t session_id;
};
/**
* struct p2p_roc_req - P2P roc request
* @vdev_id: Vdev id on which this request has come
* @chan: Chan for which this RoC has been requested
* @phy_mode: PHY mode
* @duration: Duration for the RoC
*/
struct p2p_roc_req {
uint32_t vdev_id;
uint32_t chan;
uint32_t phy_mode;
uint32_t duration;
};
/**
* enum p2p_roc_event - P2P RoC event
* @ROC_EVENT_READY_ON_CHAN: RoC has started now
* @ROC_EVENT_COMPLETED: RoC has been completed
* @ROC_EVENT_INAVLID: Invalid event
*/
enum p2p_roc_event {
ROC_EVENT_READY_ON_CHAN = 0,
ROC_EVENT_COMPLETED,
ROC_EVENT_INAVLID,
};
/**
* struct p2p_event - p2p event
* @vdev_id: Vdev id
* @roc_event: RoC event
* @cookie: Cookie which is given to supplicant for this roc req
* @chan: Chan for which this RoC has been requested
* @duration: Duration for the RoC
*/
struct p2p_event {
uint32_t vdev_id;
enum p2p_roc_event roc_event;
uint64_t cookie;
uint32_t chan;
uint32_t duration;
};
/**
* struct p2p_rx_mgmt_frame - rx mgmt frame structure
* @frame_len: Frame length
* @rx_chan: RX channel
* @vdev_id: Vdev id
* @frm_type: Frame type
* @rx_rssi: RX rssi
* @buf: Buffer address
*/
struct p2p_rx_mgmt_frame {
uint32_t frame_len;
uint32_t rx_chan;
uint32_t vdev_id;
uint32_t frm_type;
uint32_t rx_rssi;
uint8_t buf[1];
};
/**
* struct p2p_tx_cnf - tx confirm structure
* @vdev_id: Vdev id
* @action_cookie: TX cookie for this action frame
* @buf_len: Frame length
* @status: TX status
* @buf: Buffer address
*/
struct p2p_tx_cnf {
uint32_t vdev_id;
uint64_t action_cookie;
uint32_t buf_len;
uint32_t status;
uint8_t *buf;
};
/**
* struct p2p_mgmt_tx - p2p mgmt tx structure
* @vdev_id: Vdev id
* @chan: Chan for which this RoC has been requested
* @wait: Duration for the RoC
* @len: Length of tx buffer
* @no_cck: Required cck or not
* @dont_wait_for_ack: Wait for ack or not
* @off_chan: Off channel tx or not
* @buf: TX buffer
*/
struct p2p_mgmt_tx {
uint32_t vdev_id;
uint32_t chan;
uint32_t wait;
uint32_t len;
uint32_t no_cck;
uint32_t dont_wait_for_ack;
uint32_t off_chan;
const uint8_t *buf;
};
/**
* struct p2p_set_mac_filter
* @vdev_id: Vdev id
* @mac: mac addr
* @freq: frequency
* @set: set or clear
*/
struct p2p_set_mac_filter {
uint32_t vdev_id;
uint8_t mac[QDF_MAC_ADDR_SIZE];
uint32_t freq;
bool set;
};
/**
* struct p2p_set_mac_filter_evt
* @vdev_id: Vdev id
* @status: target reported result of set mac addr filter
*/
struct p2p_set_mac_filter_evt {
uint32_t vdev_id;
uint32_t status;
};
/**
* struct p2p_ps_config
* @vdev_id: Vdev id
* @opp_ps: Opportunistic power save
* @ct_window: CT window
* @count: Count
* @duration: Duration
* @interval: Interval
* @single_noa_duration: Single shot noa duration
* @ps_selection: power save selection
*/
struct p2p_ps_config {
uint32_t vdev_id;
uint32_t opp_ps;
uint32_t ct_window;
uint32_t count;
uint32_t duration;
uint32_t interval;
uint32_t single_noa_duration;
uint32_t ps_selection;
};
/**
* struct p2p_lo_start - p2p listen offload start
* @vdev_id: Vdev id
* @ctl_flags: Control flag
* @freq: P2P listen frequency
* @period: Listen offload period
* @interval: Listen offload interval
* @count: Number listen offload intervals
* @dev_types_len: Device types length
* @probe_resp_len: Probe response template length
* @device_types: Device types
* @probe_resp_tmplt: Probe response template
*/
struct p2p_lo_start {
uint32_t vdev_id;
uint32_t ctl_flags;
uint32_t freq;
uint32_t period;
uint32_t interval;
uint32_t count;
uint32_t dev_types_len;
uint32_t probe_resp_len;
uint8_t *device_types;
uint8_t *probe_resp_tmplt;
};
/**
* struct p2p_lo_event
* @vdev_id: vdev id
* @reason_code: reason code
*/
struct p2p_lo_event {
uint32_t vdev_id;
uint32_t reason_code;
};
/**
* struct noa_descriptor - noa descriptor
* @type_count: 255: continuous schedule, 0: reserved
* @duration: Absent period duration in micro seconds
* @interval: Absent period interval in micro seconds
* @start_time: 32 bit tsf time when in starts
*/
struct noa_descriptor {
uint32_t type_count;
uint32_t duration;
uint32_t interval;
uint32_t start_time;
};
/**
* struct p2p_noa_info - p2p noa information
* @index: identifies instance of NOA su element
* @opps_ps: opps ps state of the AP
* @ct_window: ct window in TUs
* @vdev_id: vdev id
* @num_descriptors: number of NOA descriptors
* @noa_desc: noa descriptors
*/
struct p2p_noa_info {
uint32_t index;
uint32_t opps_ps;
uint32_t ct_window;
uint32_t vdev_id;
uint32_t num_desc;
struct noa_descriptor noa_desc[P2P_MAX_NOA_DESC];
};
/**
* struct p2p_protocol_callbacks - callback to non-converged driver
* @is_mgmt_protected: func to get 11w mgmt protection status
*/
struct p2p_protocol_callbacks {
bool (*is_mgmt_protected)(uint32_t vdev_id, const uint8_t *peer_addr);
};
#endif /* _WLAN_P2P_PUBLIC_STRUCT_H_ */

View file

@ -0,0 +1,208 @@
/*
* Copyright (c) 2017-2018 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: Contains p2p south bound interface definitions
*/
#ifndef _WLAN_P2P_TGT_API_H_
#define _WLAN_P2P_TGT_API_H_
#include <qdf_types.h>
#include <qdf_nbuf.h>
struct scan_event;
struct wlan_objmgr_psoc;
struct wlan_objmgr_peer;
struct p2p_noa_info;
struct p2p_lo_event;
struct mgmt_rx_event_params;
enum mgmt_frame_type;
#ifdef FEATURE_P2P_LISTEN_OFFLOAD
/**
* tgt_p2p_lo_event_cb() - Listen offload stop request
* @psoc: soc object
* @event_info: lo stop event buffer
*
* This function gets called from target interface.
*
* Return: QDF_STATUS_SUCCESS - in case of success
*/
QDF_STATUS tgt_p2p_lo_event_cb(struct wlan_objmgr_psoc *psoc,
struct p2p_lo_event *event_info);
/**
* tgt_p2p_register_lo_ev_handler() - register lo event
* @psoc: soc object
*
* p2p tgt api to register listen offload event handler.
*
* Return: QDF_STATUS_SUCCESS - in case of success
*/
QDF_STATUS tgt_p2p_register_lo_ev_handler(
struct wlan_objmgr_psoc *psoc);
/**
* tgt_p2p_unregister_lo_ev_handler() - unregister lo event
* @psoc: soc object
*
* p2p tgt api to unregister listen offload event handler.
*
* Return: QDF_STATUS_SUCCESS - in case of success
*/
QDF_STATUS tgt_p2p_unregister_lo_ev_handler(
struct wlan_objmgr_psoc *psoc);
#else
static inline QDF_STATUS tgt_p2p_register_lo_ev_handler(
struct wlan_objmgr_psoc *psoc)
{
return QDF_STATUS_SUCCESS;
}
static inline QDF_STATUS tgt_p2p_unregister_lo_ev_handler(
struct wlan_objmgr_psoc *psoc)
{
return QDF_STATUS_SUCCESS;
}
#endif
/**
* tgt_p2p_register_macaddr_rx_filter_evt_handler() - register add mac rx
* filter status event
* @psoc: soc object
* @register: register or unregister
*
* p2p tgt api to register add mac rx filter status event
*
* Return: QDF_STATUS_SUCCESS - in case of success
*/
QDF_STATUS tgt_p2p_register_macaddr_rx_filter_evt_handler(
struct wlan_objmgr_psoc *psoc, bool register);
/**
* tgt_p2p_register_noa_ev_handler() - register noa event
* @psoc: soc object
*
* p2p tgt api to register noa event handler.
*
* Return: QDF_STATUS_SUCCESS - in case of success
*/
QDF_STATUS tgt_p2p_register_noa_ev_handler(
struct wlan_objmgr_psoc *psoc);
/**
* tgt_p2p_unregister_noa_ev_handler() - unregister noa event
* @psoc: soc object
*
* p2p tgt api to unregister noa event handler.
*
* Return: QDF_STATUS_SUCCESS - in case of success
*/
QDF_STATUS tgt_p2p_unregister_noa_ev_handler(
struct wlan_objmgr_psoc *psoc);
/**
* tgt_p2p_scan_event_cb() - Callback for scan event
* @vdev: vdev object
* @event: event information
* @arg: registered arguments
*
* This function gets called from scan component when getting P2P
* scan event.
*
* Return: None
*/
void tgt_p2p_scan_event_cb(struct wlan_objmgr_vdev *vdev,
struct scan_event *event, void *arg);
/**
* tgt_p2p_mgmt_download_comp_cb() - Callback for mgmt frame tx
* complete
* @context: tx context
* @buf: buffer address
* @free: need to free or not
*
* This function gets called from mgmt tx/rx component when mgmt
* frame tx complete.
*
* Return: QDF_STATUS_SUCCESS - in case of success
*/
QDF_STATUS tgt_p2p_mgmt_download_comp_cb(void *context,
qdf_nbuf_t buf, bool free);
/**
* tgt_p2p_mgmt_ota_comp_cb() - Callback for mgmt frame tx ack
* @context: tx context
* @buf: buffer address
* @status: tx status
* @tx_compl_params: tx complete parameters
*
* This function gets called from mgmt tx/rx component when getting
* mgmt frame tx ack.
*
* Return: QDF_STATUS_SUCCESS - in case of success
*/
QDF_STATUS tgt_p2p_mgmt_ota_comp_cb(void *context, qdf_nbuf_t buf,
uint32_t status, void *tx_compl_params);
/**
* tgt_p2p_mgmt_frame_rx_cb() - Callback for rx mgmt frame
* @psoc: soc context
* @peer: peer context
* @buf: rx buffer
* @mgmt_rx_params: mgmt rx parameters
* @frm_type: frame type
*
* This function gets called from mgmt tx/rx component when rx mgmt
* frame.
*
* Return: QDF_STATUS_SUCCESS - in case of success
*/
QDF_STATUS tgt_p2p_mgmt_frame_rx_cb(struct wlan_objmgr_psoc *psoc,
struct wlan_objmgr_peer *peer, qdf_nbuf_t buf,
struct mgmt_rx_event_params *mgmt_rx_params,
enum mgmt_frame_type frm_type);
/**
* tgt_p2p_noa_event_cb() - Callback for noa event
* @psoc: soc object
* @event_info: noa event information
*
* This function gets called from target interface.
*
* Return: QDF_STATUS_SUCCESS - in case of success
*/
QDF_STATUS tgt_p2p_noa_event_cb(struct wlan_objmgr_psoc *psoc,
struct p2p_noa_info *event_info);
/**
* tgt_p2p_add_mac_addr_status_event_cb() - Callback for set mac addr filter evt
* @psoc: soc object
* @event_info: event information type of p2p_set_mac_filter_evt
*
* This function gets called from target interface.
*
* Return: QDF_STATUS_SUCCESS - in case of success
*/
QDF_STATUS
tgt_p2p_add_mac_addr_status_event_cb(
struct wlan_objmgr_psoc *psoc,
struct p2p_set_mac_filter_evt *event_info);
#endif /* _WLAN_P2P_TGT_API_H_ */

View file

@ -0,0 +1,411 @@
/*
* Copyright (c) 2017-2018 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: Contains p2p north bound interface definitions
*/
#ifndef _WLAN_P2P_UCFG_API_H_
#define _WLAN_P2P_UCFG_API_H_
#include <qdf_types.h>
struct wlan_objmgr_psoc;
struct p2p_roc_req;
struct p2p_event;
struct p2p_rx_mgmt_frame;
struct p2p_tx_cnf;
struct p2p_mgmt_tx;
struct p2p_ps_config;
struct p2p_lo_start;
struct p2p_lo_event;
/**
* p2p_rx_callback() - Callback for rx mgmt frame
* @user_data: user data associated to this rx mgmt frame.
* @rx_frame: RX mgmt frame
*
* This callback will be used to give rx frames to hdd.
*
* Return: None
*/
typedef void (*p2p_rx_callback)(void *user_data,
struct p2p_rx_mgmt_frame *rx_frame);
/**
* p2p_action_tx_cnf_callback() - Callback for tx confirmation
* @user_data: user data associated to this tx confirmation
* @tx_cnf: tx confirmation information
*
* This callback will be used to give tx mgmt frame confirmation to
* hdd.
*
* Return: None
*/
typedef void (*p2p_action_tx_cnf_callback)(void *user_data,
struct p2p_tx_cnf *tx_cnf);
/**
* p2p_lo_event_callback() - Callback for listen offload event
* @user_data: user data associated to this lo event
* @p2p_lo_event: listen offload event information
*
* This callback will be used to give listen offload event to hdd.
*
* Return: None
*/
typedef void (*p2p_lo_event_callback)(void *user_data,
struct p2p_lo_event *p2p_lo_event);
/**
* p2p_event_callback() - Callback for P2P event
* @user_data: user data associated to this p2p event
* @p2p_event: p2p event information
*
* This callback will be used to give p2p event to hdd.
*
* Return: None
*/
typedef void (*p2p_event_callback)(void *user_data,
struct p2p_event *p2p_event);
/**
* struct p2p_start_param - p2p soc start parameters. Below callbacks
* will be registered by the HDD
* @rx_callback: Function pointer to hdd rx callback. This
* function will be used to give rx frames to hdd
* @rx_cb_data: RX callback user data
* @event_cb: Founction pointer to hdd p2p event callback.
* This function will be used to give p2p event
* to hdd
* @event_cb_data: Pointer to p2p event callback user data
* @tx_cnf_cb: Function pointer to hdd tx confirm callback.
* This function will be used to give tx confirm
* to hdd
* @tx_cnf_cb_data: Pointer to p2p tx confirm callback user data
* @lo_event_cb: Founction pointer to p2p listen offload
* callback. This function will be used to give
* listen offload stopped event to hdd
* @lo_event_cb_data: Pointer to p2p listen offload callback user data
*/
struct p2p_start_param {
p2p_rx_callback rx_cb;
void *rx_cb_data;
p2p_event_callback event_cb;
void *event_cb_data;
p2p_action_tx_cnf_callback tx_cnf_cb;
void *tx_cnf_cb_data;
#ifdef FEATURE_P2P_LISTEN_OFFLOAD
p2p_lo_event_callback lo_event_cb;
void *lo_event_cb_data;
#endif
};
/**
* ucfg_p2p_init() - P2P component initialization
*
* This function gets called when dispatcher initializing.
*
* Return: QDF_STATUS_SUCCESS - in case of success
*/
QDF_STATUS ucfg_p2p_init(void);
/**
* ucfg_p2p_deinit() - P2P component de-init
*
* This function gets called when dispatcher de-init.
*
* Return: QDF_STATUS_SUCCESS - in case of success
*/
QDF_STATUS ucfg_p2p_deinit(void);
/**
* ucfg_p2p_psoc_open() - Open P2P component
* @soc: soc context
*
* This function gets called when dispatcher opening.
*
* Return: QDF_STATUS_SUCCESS - in case of success
*/
QDF_STATUS ucfg_p2p_psoc_open(struct wlan_objmgr_psoc *soc);
/**
* ucfg_p2p_psoc_close() - Close P2P component
* @soc: soc context
*
* This function gets called when dispatcher closing.
*
* Return: QDF_STATUS_SUCCESS - in case of success
*/
QDF_STATUS ucfg_p2p_psoc_close(struct wlan_objmgr_psoc *soc);
/**
* ucfg_p2p_psoc_start() - Start P2P component
* @soc: soc context
* @req: P2P start parameters
*
* This function gets called when up layer starting up.
*
* Return: QDF_STATUS_SUCCESS - in case of success
*/
QDF_STATUS ucfg_p2p_psoc_start(struct wlan_objmgr_psoc *soc,
struct p2p_start_param *req);
/**
* ucfg_p2p_psoc_stop() - Stop P2P component
* @soc: soc context
*
* This function gets called when up layer exit.
*
* Return: QDF_STATUS_SUCCESS - in case of success
*/
QDF_STATUS ucfg_p2p_psoc_stop(struct wlan_objmgr_psoc *soc);
/**
* ucfg_p2p_roc_req() - Roc request
* @soc: soc context
* @roc_req: Roc request parameters
* @cookie: return cookie to caller
*
* This function delivers roc request to P2P component.
*
* Return: QDF_STATUS_SUCCESS - in case of success
*/
QDF_STATUS ucfg_p2p_roc_req(struct wlan_objmgr_psoc *soc,
struct p2p_roc_req *roc_req, uint64_t *cookie);
/**
* ucfg_p2p_roc_cancel_req() - Cancel roc request
* @soc: soc context
* @cookie: Find out the roc request by cookie
*
* This function delivers cancel roc request to P2P component.
*
* Return: QDF_STATUS_SUCCESS - in case of success
*/
QDF_STATUS ucfg_p2p_roc_cancel_req(struct wlan_objmgr_psoc *soc,
uint64_t cookie);
/**
* ucfg_p2p_cleanup_roc_by_vdev() - Cleanup roc request by vdev
* @vdev: pointer to vdev object
*
* This function call P2P API to cleanup roc request by vdev
*
* Return: QDF_STATUS_SUCCESS - in case of success
*/
QDF_STATUS ucfg_p2p_cleanup_roc_by_vdev(struct wlan_objmgr_vdev *vdev);
/**
* ucfg_p2p_cleanup_roc_by_poc() - Cleanup roc request by psoc
* @psoc: pointer to psoc object
*
* This function call P2P API to cleanup roc request by psoc
*
* Return: QDF_STATUS_SUCCESS - in case of success
*/
QDF_STATUS ucfg_p2p_cleanup_roc_by_psoc(struct wlan_objmgr_psoc *psoc);
/**
* ucfg_p2p_cleanup_tx_by_vdev() - Cleanup tx request by vdev
* @vdev: pointer to vdev object
*
* This function call P2P API to cleanup tx action frame request by vdev
*
* Return: QDF_STATUS_SUCCESS - in case of success
*/
QDF_STATUS ucfg_p2p_cleanup_tx_by_vdev(struct wlan_objmgr_vdev *vdev);
/**
* ucfg_p2p_cleanup_tx_by_poc() - Cleanup tx request by psoc
* @psoc: pointer to psoc object
*
* This function call P2P API to cleanup tx action frame request by psoc
*
* Return: QDF_STATUS_SUCCESS - in case of success
*/
QDF_STATUS ucfg_p2p_cleanup_tx_by_psoc(struct wlan_objmgr_psoc *psoc);
/**
* ucfg_p2p_mgmt_tx() - Mgmt frame tx request
* @soc: soc context
* @mgmt_frm: TX mgmt frame parameters
* @cookie: Return the cookie to caller
*
* This function delivers mgmt frame tx request to P2P component.
*
* Return: QDF_STATUS_SUCCESS - in case of success
*/
QDF_STATUS ucfg_p2p_mgmt_tx(struct wlan_objmgr_psoc *soc,
struct p2p_mgmt_tx *mgmt_frm, uint64_t *cookie);
/**
* ucfg_p2p_mgmt_tx_cancel() - Cancel mgmt frame tx request
* @soc: soc context
* @vdev: vdev object
* @cookie: Find out the mgmt tx request by cookie
*
* This function delivers cancel mgmt frame tx request request to P2P
* component.
*
* Return: QDF_STATUS_SUCCESS - in case of success
*/
QDF_STATUS ucfg_p2p_mgmt_tx_cancel(struct wlan_objmgr_psoc *soc,
struct wlan_objmgr_vdev *vdev, uint64_t cookie);
/**
* ucfg_p2p_set_ps() - P2P set power save
* @soc: soc context
* @ps_config: power save configure
*
* This function delivers p2p power save request to P2P component.
*
* Return: QDF_STATUS_SUCCESS - in case of success
*/
QDF_STATUS ucfg_p2p_set_ps(struct wlan_objmgr_psoc *soc,
struct p2p_ps_config *ps_config);
#ifdef FEATURE_P2P_LISTEN_OFFLOAD
/**
* ucfg_p2p_lo_start() - Listen offload start request
* @soc: soc context
* @p2p_lo_start: lo start parameters
*
* This function delivers listen offload start request to P2P
* component.
*
* Return: QDF_STATUS_SUCCESS - in case of success
*/
QDF_STATUS ucfg_p2p_lo_start(struct wlan_objmgr_psoc *soc,
struct p2p_lo_start *p2p_lo_start);
/**
* ucfg_p2p_lo_stop() - Listen offload stop request
* @soc: soc context
* @vdev_id: vdev id
*
* This function delivers listen offload stop request to P2P component.
*
* Return: QDF_STATUS_SUCCESS - in case of success
*/
QDF_STATUS ucfg_p2p_lo_stop(struct wlan_objmgr_psoc *soc,
uint32_t vdev_id);
#endif
/**
* p2p_peer_authorized() - Process peer authorized event
* @vdev: vdev structure to which peer is associated
* @mac_addr: peer mac address
*
* This function handles disables noa whenever a legacy station
* complete 4-way handshake after association.
*
* Return: void
*/
void p2p_peer_authorized(struct wlan_objmgr_vdev *vdev, uint8_t *mac_addr);
/**
* ucfg_p2p_set_noa() - Disable/Enable NOA
* @soc: soc context
* @vdev_id: vdev id
* @disable_noa: TRUE - Disable NoA, FALSE - Enable NoA
*
* This function send wmi command to enable / disable NoA.
*
* Return: QDF_STATUS_SUCCESS - in case of success
*/
QDF_STATUS ucfg_p2p_set_noa(struct wlan_objmgr_psoc *soc,
uint32_t vdev_id, bool disable_noa);
/**
* ucfg_p2p_check_random_mac() - check random mac addr or not
* @soc: soc context
* @vdev_id: vdev id
* @random_mac_addr: mac addr to be checked
*
* This function check the input addr is random mac addr or not for vdev.
*
* Return: true if addr is random mac address else false.
*/
bool ucfg_p2p_check_random_mac(struct wlan_objmgr_psoc *soc, uint32_t vdev_id,
uint8_t *random_mac_addr);
/**
* ucfg_p2p_register_callbacks() - register p2p callbacks
* @soc: soc context
* @cb_obj: p2p_protocol_callbacks struct
*
* This function registers lim callbacks to p2p components to provide
* protocol information.
*
* Return: QDF_STATUS_SUCCESS - in case of success
*/
QDF_STATUS ucfg_p2p_register_callbacks(struct wlan_objmgr_psoc *soc,
struct p2p_protocol_callbacks *cb_obj);
/**
* ucfg_p2p_status_scan() - Show P2P connection status when scanning
* @vdev: vdev context
*
* This function shows P2P connection status when scanning.
*
* Return: QDF_STATUS_SUCCESS - in case of success
*/
QDF_STATUS ucfg_p2p_status_scan(struct wlan_objmgr_vdev *vdev);
/**
* ucfg_p2p_status_connect() - Update P2P connection status
* @vdev: vdev context
*
* Updates P2P connection status by up layer when connecting.
*
* Return: QDF_STATUS_SUCCESS - in case of success
*/
QDF_STATUS ucfg_p2p_status_connect(struct wlan_objmgr_vdev *vdev);
/**
* ucfg_p2p_status_disconnect() - Update P2P connection status
* @vdev: vdev context
*
* Updates P2P connection status by up layer when disconnecting.
*
* Return: QDF_STATUS_SUCCESS - in case of success
*/
QDF_STATUS ucfg_p2p_status_disconnect(struct wlan_objmgr_vdev *vdev);
/**
* ucfg_p2p_status_start_bss() - Update P2P connection status
* @vdev: vdev context
*
* Updates P2P connection status by up layer when starting bss.
*
* Return: QDF_STATUS_SUCCESS - in case of success
*/
QDF_STATUS ucfg_p2p_status_start_bss(struct wlan_objmgr_vdev *vdev);
/**
* ucfg_p2p_status_stop_bss() - Update P2P connection status
* @vdev: vdev context
*
* Updates P2P connection status by up layer when stopping bss.
*
* Return: QDF_STATUS_SUCCESS - in case of success
*/
QDF_STATUS ucfg_p2p_status_stop_bss(struct wlan_objmgr_vdev *vdev);
#endif /* _WLAN_P2P_UCFG_API_H_ */

View file

@ -0,0 +1,105 @@
/*
* Copyright (c) 2018 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: This file contains p2p configures interface definitions
*/
#include <wlan_objmgr_psoc_obj.h>
#include "wlan_p2p_public_struct.h"
#include "wlan_p2p_cfg_api.h"
#include "../../core/src/wlan_p2p_main.h"
static inline struct p2p_soc_priv_obj *
wlan_psoc_get_p2p_object(struct wlan_objmgr_psoc *psoc)
{
return wlan_objmgr_psoc_get_comp_private_obj(psoc,
WLAN_UMAC_COMP_P2P);
}
QDF_STATUS
cfg_p2p_get_go_keepalive_period(struct wlan_objmgr_psoc *psoc,
uint32_t *period)
{
struct p2p_soc_priv_obj *p2p_soc_obj;
p2p_soc_obj = wlan_psoc_get_p2p_object(psoc);
if (!p2p_soc_obj) {
*period = 0;
p2p_err("p2p psoc null");
return QDF_STATUS_E_INVAL;
}
*period = p2p_soc_obj->param.go_keepalive_period;
return QDF_STATUS_SUCCESS;
}
QDF_STATUS
cfg_p2p_get_go_link_monitor_period(struct wlan_objmgr_psoc *psoc,
uint32_t *period)
{
struct p2p_soc_priv_obj *p2p_soc_obj;
p2p_soc_obj = wlan_psoc_get_p2p_object(psoc);
if (!p2p_soc_obj) {
*period = 0;
p2p_err("p2p psoc null");
return QDF_STATUS_E_INVAL;
}
*period = p2p_soc_obj->param.go_link_monitor_period;
return QDF_STATUS_SUCCESS;
}
QDF_STATUS
cfg_p2p_get_device_addr_admin(struct wlan_objmgr_psoc *psoc,
bool *enable)
{
struct p2p_soc_priv_obj *p2p_soc_obj;
p2p_soc_obj = wlan_psoc_get_p2p_object(psoc);
if (!p2p_soc_obj) {
*enable = false;
p2p_err("p2p psoc null");
return QDF_STATUS_E_INVAL;
}
*enable = p2p_soc_obj->param.p2p_device_addr_admin;
return QDF_STATUS_SUCCESS;
}
QDF_STATUS
cfg_p2p_get_skip_dfs_channel_p2p_search(struct wlan_objmgr_psoc *psoc,
bool *enable)
{
struct p2p_soc_priv_obj *p2p_soc_obj;
p2p_soc_obj = wlan_psoc_get_p2p_object(psoc);
if (!p2p_soc_obj) {
*enable = false;
p2p_err("p2p psoc null");
return QDF_STATUS_E_INVAL;
}
*enable = p2p_soc_obj->param.skip_dfs_channel_p2p_search;
return QDF_STATUS_SUCCESS;
}

View file

@ -0,0 +1,432 @@
/*
* Copyright (c) 2017-2018 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: This file contains p2p south bound interface definitions
*/
#include <wlan_objmgr_psoc_obj.h>
#include <wlan_mgmt_txrx_utils_api.h>
#include <scheduler_api.h>
#include <wlan_objmgr_psoc_obj.h>
#include <wlan_objmgr_global_obj.h>
#include <wlan_objmgr_pdev_obj.h>
#include <wlan_objmgr_vdev_obj.h>
#include <wlan_objmgr_peer_obj.h>
#include "wlan_p2p_tgt_api.h"
#include "wlan_p2p_public_struct.h"
#include "../../core/src/wlan_p2p_main.h"
#include "../../core/src/wlan_p2p_roc.h"
#include "../../core/src/wlan_p2p_off_chan_tx.h"
#define IEEE80211_FC0_TYPE_MASK 0x0c
#define P2P_NOISE_FLOOR_DBM_DEFAULT (-96)
static inline struct wlan_lmac_if_p2p_tx_ops *
wlan_psoc_get_p2p_tx_ops(struct wlan_objmgr_psoc *psoc)
{
return &(psoc->soc_cb.tx_ops.p2p);
}
#ifdef FEATURE_P2P_LISTEN_OFFLOAD
QDF_STATUS tgt_p2p_register_lo_ev_handler(
struct wlan_objmgr_psoc *psoc)
{
struct wlan_lmac_if_p2p_tx_ops *p2p_ops;
QDF_STATUS status = QDF_STATUS_E_FAILURE;
p2p_ops = wlan_psoc_get_p2p_tx_ops(psoc);
if (p2p_ops && p2p_ops->reg_lo_ev_handler) {
status = p2p_ops->reg_lo_ev_handler(psoc, NULL);
p2p_debug("register lo event, status:%d", status);
}
return status;
}
QDF_STATUS tgt_p2p_unregister_lo_ev_handler(
struct wlan_objmgr_psoc *psoc)
{
struct wlan_lmac_if_p2p_tx_ops *p2p_ops;
QDF_STATUS status = QDF_STATUS_E_FAILURE;
p2p_ops = wlan_psoc_get_p2p_tx_ops(psoc);
if (p2p_ops && p2p_ops->unreg_lo_ev_handler) {
status = p2p_ops->unreg_lo_ev_handler(psoc, NULL);
p2p_debug("unregister lo event, status:%d", status);
}
return status;
}
QDF_STATUS tgt_p2p_lo_event_cb(struct wlan_objmgr_psoc *psoc,
struct p2p_lo_event *event_info)
{
struct p2p_lo_stop_event *lo_stop_event;
struct scheduler_msg msg = {0};
struct p2p_soc_priv_obj *p2p_soc_obj;
QDF_STATUS status;
p2p_debug("soc:%pK, event_info:%pK", psoc, event_info);
if (!psoc) {
p2p_err("psoc context passed is NULL");
if (event_info)
qdf_mem_free(event_info);
return QDF_STATUS_E_INVAL;
}
p2p_soc_obj = wlan_objmgr_psoc_get_comp_private_obj(psoc,
WLAN_UMAC_COMP_P2P);
if (!p2p_soc_obj) {
p2p_err("p2p soc object is NULL");
if (event_info)
qdf_mem_free(event_info);
return QDF_STATUS_E_INVAL;
}
if (!event_info) {
p2p_err("invalid lo stop event information");
return QDF_STATUS_E_INVAL;
}
lo_stop_event = qdf_mem_malloc(sizeof(*lo_stop_event));
if (!lo_stop_event) {
p2p_err("Failed to allocate p2p lo stop event");
qdf_mem_free(event_info);
return QDF_STATUS_E_NOMEM;
}
lo_stop_event->p2p_soc_obj = p2p_soc_obj;
lo_stop_event->lo_event = event_info;
msg.type = P2P_EVENT_LO_STOPPED;
msg.bodyptr = lo_stop_event;
msg.callback = p2p_process_evt;
msg.flush_callback = p2p_event_flush_callback;
status = scheduler_post_message(QDF_MODULE_ID_P2P,
QDF_MODULE_ID_P2P,
QDF_MODULE_ID_TARGET_IF,
&msg);
if (QDF_IS_STATUS_ERROR(status)) {
qdf_mem_free(lo_stop_event->lo_event);
qdf_mem_free(lo_stop_event);
p2p_err("post msg fail:%d", status);
}
return status;
}
#endif /* FEATURE_P2P_LISTEN_OFFLOAD */
QDF_STATUS
tgt_p2p_add_mac_addr_status_event_cb(struct wlan_objmgr_psoc *psoc,
struct p2p_set_mac_filter_evt *event_info)
{
struct p2p_mac_filter_rsp *mac_filter_rsp;
struct scheduler_msg msg = {0};
struct p2p_soc_priv_obj *p2p_soc_obj;
QDF_STATUS status;
if (!psoc) {
p2p_err("random_mac:psoc context passed is NULL");
return QDF_STATUS_E_INVAL;
}
if (!event_info) {
p2p_err("random_mac:invalid event_info");
return QDF_STATUS_E_INVAL;
}
p2p_soc_obj = wlan_objmgr_psoc_get_comp_private_obj(
psoc, WLAN_UMAC_COMP_P2P);
if (!p2p_soc_obj) {
p2p_err("random_mac:p2p soc object is NULL");
return QDF_STATUS_E_INVAL;
}
mac_filter_rsp = qdf_mem_malloc(sizeof(*mac_filter_rsp));
if (!mac_filter_rsp) {
p2p_err("random_mac:Failed to allocate mac_filter_rsp");
return QDF_STATUS_E_NOMEM;
}
mac_filter_rsp->p2p_soc_obj = p2p_soc_obj;
mac_filter_rsp->vdev_id = event_info->vdev_id;
mac_filter_rsp->status = event_info->status;
msg.type = P2P_EVENT_ADD_MAC_RSP;
msg.bodyptr = mac_filter_rsp;
msg.callback = p2p_process_evt;
status = scheduler_post_msg(QDF_MODULE_ID_TARGET_IF, &msg);
if (QDF_IS_STATUS_ERROR(status))
qdf_mem_free(mac_filter_rsp);
return status;
}
QDF_STATUS tgt_p2p_register_macaddr_rx_filter_evt_handler(
struct wlan_objmgr_psoc *psoc, bool reg)
{
struct wlan_lmac_if_p2p_tx_ops *p2p_ops;
QDF_STATUS status = QDF_STATUS_E_FAILURE;
p2p_ops = wlan_psoc_get_p2p_tx_ops(psoc);
if (p2p_ops && p2p_ops->reg_mac_addr_rx_filter_handler) {
status = p2p_ops->reg_mac_addr_rx_filter_handler(psoc, reg);
p2p_debug("register mac addr rx filter event, register %d status:%d",
reg, status);
}
return status;
}
QDF_STATUS tgt_p2p_register_noa_ev_handler(
struct wlan_objmgr_psoc *psoc)
{
struct wlan_lmac_if_p2p_tx_ops *p2p_ops;
QDF_STATUS status = QDF_STATUS_E_FAILURE;
p2p_ops = wlan_psoc_get_p2p_tx_ops(psoc);
if (p2p_ops && p2p_ops->reg_noa_ev_handler) {
status = p2p_ops->reg_noa_ev_handler(psoc, NULL);
p2p_debug("register noa event, status:%d", status);
}
return status;
}
QDF_STATUS tgt_p2p_unregister_noa_ev_handler(
struct wlan_objmgr_psoc *psoc)
{
struct wlan_lmac_if_p2p_tx_ops *p2p_ops;
QDF_STATUS status = QDF_STATUS_E_FAILURE;
p2p_ops = wlan_psoc_get_p2p_tx_ops(psoc);
if (p2p_ops && p2p_ops->unreg_noa_ev_handler) {
status = p2p_ops->unreg_noa_ev_handler(psoc, NULL);
p2p_debug("unregister noa event, status:%d", status);
}
return status;
}
void tgt_p2p_scan_event_cb(struct wlan_objmgr_vdev *vdev,
struct scan_event *event, void *arg)
{
p2p_scan_event_cb(vdev, event, arg);
}
QDF_STATUS tgt_p2p_mgmt_download_comp_cb(void *context,
qdf_nbuf_t buf, bool free)
{
p2p_debug("conext:%pK, buf:%pK, free:%d", context,
qdf_nbuf_data(buf), free);
qdf_nbuf_free(buf);
return QDF_STATUS_SUCCESS;
}
QDF_STATUS tgt_p2p_mgmt_ota_comp_cb(void *context, qdf_nbuf_t buf,
uint32_t status, void *tx_compl_params)
{
struct p2p_tx_conf_event *tx_conf_event;
struct scheduler_msg msg = {0};
QDF_STATUS ret;
p2p_debug("context:%pK, buf:%pK, status:%d, tx complete params:%pK",
context, buf, status, tx_compl_params);
if (!context) {
p2p_err("invalid context");
qdf_nbuf_free(buf);
return QDF_STATUS_E_INVAL;
}
tx_conf_event = qdf_mem_malloc(sizeof(*tx_conf_event));
if (!tx_conf_event) {
p2p_err("Failed to allocate tx cnf event");
qdf_nbuf_free(buf);
return QDF_STATUS_E_NOMEM;
}
tx_conf_event->status = status;
tx_conf_event->nbuf = buf;
tx_conf_event->p2p_soc_obj = (struct p2p_soc_priv_obj *)context;
msg.type = P2P_EVENT_MGMT_TX_ACK_CNF;
msg.bodyptr = tx_conf_event;
msg.callback = p2p_process_evt;
msg.flush_callback = p2p_event_flush_callback;
ret = scheduler_post_message(QDF_MODULE_ID_P2P,
QDF_MODULE_ID_P2P,
QDF_MODULE_ID_TARGET_IF,
&msg);
if (QDF_IS_STATUS_ERROR(ret)) {
qdf_mem_free(tx_conf_event);
qdf_nbuf_free(buf);
p2p_err("post msg fail:%d", status);
}
return ret;
}
QDF_STATUS tgt_p2p_mgmt_frame_rx_cb(struct wlan_objmgr_psoc *psoc,
struct wlan_objmgr_peer *peer, qdf_nbuf_t buf,
struct mgmt_rx_event_params *mgmt_rx_params,
enum mgmt_frame_type frm_type)
{
struct p2p_rx_mgmt_frame *rx_mgmt;
struct p2p_rx_mgmt_event *rx_mgmt_event;
struct p2p_soc_priv_obj *p2p_soc_obj;
struct scheduler_msg msg = {0};
struct wlan_objmgr_vdev *vdev;
uint32_t vdev_id;
uint8_t *pdata;
QDF_STATUS status;
p2p_debug("psoc:%pK, peer:%pK, type:%d", psoc, peer, frm_type);
if (!mgmt_rx_params) {
p2p_err("mgmt rx params is NULL");
qdf_nbuf_free(buf);
return QDF_STATUS_E_INVAL;
}
p2p_soc_obj = wlan_objmgr_psoc_get_comp_private_obj(psoc,
WLAN_UMAC_COMP_P2P);
if (!p2p_soc_obj) {
p2p_err("p2p ctx is NULL, drop this frame");
qdf_nbuf_free(buf);
return QDF_STATUS_E_FAILURE;
}
if (!peer) {
if (p2p_soc_obj->cur_roc_vdev_id == P2P_INVALID_VDEV_ID) {
p2p_err("vdev id of current roc invalid");
qdf_nbuf_free(buf);
return QDF_STATUS_E_FAILURE;
} else {
vdev_id = p2p_soc_obj->cur_roc_vdev_id;
}
} else {
vdev = wlan_peer_get_vdev(peer);
if (!vdev) {
p2p_err("vdev is NULL in peer, drop this frame");
qdf_nbuf_free(buf);
return QDF_STATUS_E_FAILURE;
}
vdev_id = wlan_vdev_get_id(vdev);
}
rx_mgmt_event = qdf_mem_malloc(sizeof(*rx_mgmt_event));
if (!rx_mgmt_event) {
p2p_err("Failed to allocate rx mgmt event");
qdf_nbuf_free(buf);
return QDF_STATUS_E_NOMEM;
}
rx_mgmt = qdf_mem_malloc(sizeof(*rx_mgmt) +
mgmt_rx_params->buf_len);
if (!rx_mgmt) {
p2p_err("Failed to allocate rx mgmt frame");
qdf_nbuf_free(buf);
return QDF_STATUS_E_NOMEM;
}
pdata = (uint8_t *)qdf_nbuf_data(buf);
rx_mgmt->frame_len = mgmt_rx_params->buf_len;
rx_mgmt->rx_chan = mgmt_rx_params->channel;
rx_mgmt->vdev_id = vdev_id;
rx_mgmt->frm_type = frm_type;
rx_mgmt->rx_rssi = mgmt_rx_params->snr +
P2P_NOISE_FLOOR_DBM_DEFAULT;
rx_mgmt_event->rx_mgmt = rx_mgmt;
rx_mgmt_event->p2p_soc_obj = p2p_soc_obj;
qdf_mem_copy(rx_mgmt->buf, pdata, mgmt_rx_params->buf_len);
msg.type = P2P_EVENT_RX_MGMT;
msg.bodyptr = rx_mgmt_event;
msg.callback = p2p_process_evt;
msg.flush_callback = p2p_event_flush_callback;
status = scheduler_post_message(QDF_MODULE_ID_P2P,
QDF_MODULE_ID_P2P,
QDF_MODULE_ID_TARGET_IF,
&msg);
if (QDF_IS_STATUS_ERROR(status)) {
qdf_mem_free(rx_mgmt_event->rx_mgmt);
qdf_mem_free(rx_mgmt_event);
p2p_err("post msg fail:%d", status);
}
qdf_nbuf_free(buf);
return status;
}
QDF_STATUS tgt_p2p_noa_event_cb(struct wlan_objmgr_psoc *psoc,
struct p2p_noa_info *event_info)
{
struct p2p_noa_event *noa_event;
struct scheduler_msg msg = {0};
struct p2p_soc_priv_obj *p2p_soc_obj;
QDF_STATUS status;
p2p_debug("soc:%pK, event_info:%pK", psoc, event_info);
if (!psoc) {
p2p_err("psoc context passed is NULL");
if (event_info)
qdf_mem_free(event_info);
return QDF_STATUS_E_INVAL;
}
p2p_soc_obj = wlan_objmgr_psoc_get_comp_private_obj(psoc,
WLAN_UMAC_COMP_P2P);
if (!p2p_soc_obj) {
p2p_err("p2p soc object is NULL");
if (event_info)
qdf_mem_free(event_info);
return QDF_STATUS_E_INVAL;
}
if (!event_info) {
p2p_err("invalid noa event information");
return QDF_STATUS_E_INVAL;
}
noa_event = qdf_mem_malloc(sizeof(*noa_event));
if (!noa_event) {
p2p_err("Failed to allocate p2p noa event");
qdf_mem_free(event_info);
return QDF_STATUS_E_NOMEM;
}
noa_event->p2p_soc_obj = p2p_soc_obj;
noa_event->noa_info = event_info;
msg.type = P2P_EVENT_NOA;
msg.bodyptr = noa_event;
msg.callback = p2p_process_evt;
msg.flush_callback = p2p_event_flush_callback;
status = scheduler_post_message(QDF_MODULE_ID_P2P,
QDF_MODULE_ID_P2P,
QDF_MODULE_ID_TARGET_IF,
&msg);
if (QDF_IS_STATUS_ERROR(status)) {
qdf_mem_free(noa_event->noa_info);
qdf_mem_free(noa_event);
p2p_err("post msg fail:%d", status);
}
return status;
}

View file

@ -0,0 +1,652 @@
/*
* Copyright (c) 2017-2018 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: This file contains p2p north bound interface definitions
*/
#include <wmi_unified_api.h>
#include <wlan_objmgr_psoc_obj.h>
#include <wlan_objmgr_vdev_obj.h>
#include <scheduler_api.h>
#include "wlan_p2p_public_struct.h"
#include "wlan_p2p_ucfg_api.h"
#include "../../core/src/wlan_p2p_main.h"
#include "../../core/src/wlan_p2p_roc.h"
#include "../../core/src/wlan_p2p_off_chan_tx.h"
static inline struct wlan_lmac_if_p2p_tx_ops *
ucfg_p2p_psoc_get_tx_ops(struct wlan_objmgr_psoc *psoc)
{
return &(psoc->soc_cb.tx_ops.p2p);
}
/**
* is_p2p_ps_allowed() - If P2P power save is allowed or not
* @vdev: vdev object
* @id: umac component id
*
* This function returns TRUE if P2P power-save is allowed
* else returns FALSE.
*
* Return: bool
*/
static bool is_p2p_ps_allowed(struct wlan_objmgr_vdev *vdev,
enum wlan_umac_comp_id id)
{
struct p2p_vdev_priv_obj *p2p_vdev_obj;
uint8_t is_p2pgo = 0;
if (!vdev) {
p2p_err("vdev:%pK", vdev);
return true;
}
p2p_vdev_obj = wlan_objmgr_vdev_get_comp_private_obj(vdev,
WLAN_UMAC_COMP_P2P);
if (wlan_vdev_mlme_get_opmode(vdev) == QDF_P2P_GO_MODE)
is_p2pgo = 1;
if (!p2p_vdev_obj || !is_p2pgo) {
p2p_err("p2p_vdev_obj:%pK is_p2pgo:%u",
p2p_vdev_obj, is_p2pgo);
return false;
}
if (p2p_vdev_obj->non_p2p_peer_count &&
p2p_vdev_obj->noa_status == false) {
p2p_debug("non_p2p_peer_count: %u, noa_status: %d",
p2p_vdev_obj->non_p2p_peer_count,
p2p_vdev_obj->noa_status);
return false;
}
return true;
}
QDF_STATUS ucfg_p2p_init(void)
{
return p2p_component_init();
}
QDF_STATUS ucfg_p2p_deinit(void)
{
return p2p_component_deinit();
}
QDF_STATUS ucfg_p2p_psoc_open(struct wlan_objmgr_psoc *soc)
{
return p2p_psoc_object_open(soc);
}
QDF_STATUS ucfg_p2p_psoc_close(struct wlan_objmgr_psoc *soc)
{
return p2p_psoc_object_close(soc);
}
QDF_STATUS ucfg_p2p_psoc_start(struct wlan_objmgr_psoc *soc,
struct p2p_start_param *req)
{
return p2p_psoc_start(soc, req);
}
QDF_STATUS ucfg_p2p_psoc_stop(struct wlan_objmgr_psoc *soc)
{
return p2p_psoc_stop(soc);
}
QDF_STATUS ucfg_p2p_roc_req(struct wlan_objmgr_psoc *soc,
struct p2p_roc_req *roc_req, uint64_t *cookie)
{
struct scheduler_msg msg = {0};
struct p2p_soc_priv_obj *p2p_soc_obj;
struct p2p_roc_context *roc_ctx;
QDF_STATUS status;
int32_t id;
p2p_debug("soc:%pK, vdev_id:%d, chan:%d, phy_mode:%d, duration:%d",
soc, roc_req->vdev_id, roc_req->chan,
roc_req->phy_mode, roc_req->duration);
if (!soc) {
p2p_err("psoc context passed is NULL");
return QDF_STATUS_E_INVAL;
}
p2p_soc_obj = wlan_objmgr_psoc_get_comp_private_obj(soc,
WLAN_UMAC_COMP_P2P);
if (!p2p_soc_obj) {
p2p_err("P2P soc object is NULL");
return QDF_STATUS_E_FAILURE;
}
roc_ctx = qdf_mem_malloc(sizeof(*roc_ctx));
if (!roc_ctx) {
p2p_err("failed to allocate p2p roc context");
return QDF_STATUS_E_NOMEM;
}
status = qdf_idr_alloc(&p2p_soc_obj->p2p_idr, roc_ctx, &id);
if (QDF_IS_STATUS_ERROR(status)) {
qdf_mem_free(roc_ctx);
p2p_err("failed to alloc idr, status %d", status);
return status;
}
*cookie = (uint64_t)id;
roc_ctx->p2p_soc_obj = p2p_soc_obj;
roc_ctx->vdev_id = roc_req->vdev_id;
roc_ctx->chan = roc_req->chan;
roc_ctx->phy_mode = roc_req->phy_mode;
roc_ctx->duration = roc_req->duration;
roc_ctx->roc_state = ROC_STATE_IDLE;
roc_ctx->roc_type = USER_REQUESTED;
roc_ctx->id = id;
msg.type = P2P_ROC_REQ;
msg.bodyptr = roc_ctx;
msg.callback = p2p_process_cmd;
status = scheduler_post_message(QDF_MODULE_ID_HDD,
QDF_MODULE_ID_P2P,
QDF_MODULE_ID_OS_IF,
&msg);
if (QDF_IS_STATUS_ERROR(status)) {
qdf_mem_free(roc_ctx);
qdf_idr_remove(&p2p_soc_obj->p2p_idr, id);
p2p_err("post msg fail:%d", status);
}
p2p_debug("cookie = 0x%llx", *cookie);
return status;
}
QDF_STATUS ucfg_p2p_roc_cancel_req(struct wlan_objmgr_psoc *soc,
uint64_t cookie)
{
struct scheduler_msg msg = {0};
struct p2p_soc_priv_obj *p2p_soc_obj;
struct cancel_roc_context *cancel_roc;
void *roc_ctx = NULL;
QDF_STATUS status;
p2p_debug("soc:%pK, cookie:0x%llx", soc, cookie);
if (!soc) {
p2p_err("psoc context passed is NULL");
return QDF_STATUS_E_INVAL;
}
p2p_soc_obj = wlan_objmgr_psoc_get_comp_private_obj(soc,
WLAN_UMAC_COMP_P2P);
if (!p2p_soc_obj) {
p2p_err("p2p soc context is NULL");
return QDF_STATUS_E_FAILURE;
}
status = qdf_idr_find(&p2p_soc_obj->p2p_idr,
cookie, &roc_ctx);
if (QDF_IS_STATUS_ERROR(status)) {
p2p_err("invalid id");
return QDF_STATUS_E_INVAL;
}
cancel_roc = qdf_mem_malloc(sizeof(*cancel_roc));
if (!cancel_roc) {
p2p_err("failed to allocate cancel p2p roc");
return QDF_STATUS_E_NOMEM;
}
cancel_roc->p2p_soc_obj = p2p_soc_obj;
cancel_roc->cookie = (uintptr_t)roc_ctx;
msg.type = P2P_CANCEL_ROC_REQ;
msg.bodyptr = cancel_roc;
msg.callback = p2p_process_cmd;
status = scheduler_post_message(QDF_MODULE_ID_HDD,
QDF_MODULE_ID_P2P,
QDF_MODULE_ID_OS_IF,
&msg);
if (QDF_IS_STATUS_ERROR(status)) {
qdf_mem_free(cancel_roc);
p2p_err("post msg fail:%d", status);
}
return status;
}
QDF_STATUS ucfg_p2p_cleanup_roc_by_vdev(struct wlan_objmgr_vdev *vdev)
{
struct p2p_soc_priv_obj *p2p_soc_obj;
struct wlan_objmgr_psoc *psoc;
p2p_debug("vdev:%pK", vdev);
if (!vdev) {
p2p_err("null vdev");
return QDF_STATUS_E_INVAL;
}
psoc = wlan_vdev_get_psoc(vdev);
if (!psoc) {
p2p_err("null psoc");
return QDF_STATUS_E_INVAL;
}
p2p_soc_obj = wlan_objmgr_psoc_get_comp_private_obj(psoc,
WLAN_UMAC_COMP_P2P);
if (!p2p_soc_obj) {
p2p_err("p2p soc context is NULL");
return QDF_STATUS_E_FAILURE;
}
return p2p_cleanup_roc_sync(p2p_soc_obj, vdev);
}
QDF_STATUS ucfg_p2p_cleanup_roc_by_psoc(struct wlan_objmgr_psoc *psoc)
{
struct p2p_soc_priv_obj *obj;
if (!psoc) {
p2p_err("null psoc");
return QDF_STATUS_E_INVAL;
}
obj = wlan_objmgr_psoc_get_comp_private_obj(psoc, WLAN_UMAC_COMP_P2P);
if (!obj) {
p2p_err("null p2p soc obj");
return QDF_STATUS_E_FAILURE;
}
return p2p_cleanup_roc_sync(obj, NULL);
}
QDF_STATUS ucfg_p2p_cleanup_tx_by_vdev(struct wlan_objmgr_vdev *vdev)
{
struct p2p_soc_priv_obj *obj;
struct wlan_objmgr_psoc *psoc;
if (!vdev) {
p2p_err("null vdev");
return QDF_STATUS_E_INVAL;
}
psoc = wlan_vdev_get_psoc(vdev);
if (!psoc) {
p2p_err("null psoc");
return QDF_STATUS_E_INVAL;
}
obj = wlan_objmgr_psoc_get_comp_private_obj(psoc, WLAN_UMAC_COMP_P2P);
if (!obj) {
p2p_err("null p2p soc obj");
return QDF_STATUS_E_FAILURE;
}
p2p_del_all_rand_mac_vdev(vdev);
return p2p_cleanup_tx_sync(obj, vdev);
}
QDF_STATUS ucfg_p2p_cleanup_tx_by_psoc(struct wlan_objmgr_psoc *psoc)
{
struct p2p_soc_priv_obj *obj;
if (!psoc) {
p2p_err("null psoc");
return QDF_STATUS_E_INVAL;
}
obj = wlan_objmgr_psoc_get_comp_private_obj(psoc, WLAN_UMAC_COMP_P2P);
if (!obj) {
p2p_err("null p2p soc obj");
return QDF_STATUS_E_FAILURE;
}
p2p_del_all_rand_mac_soc(psoc);
return p2p_cleanup_tx_sync(obj, NULL);
}
QDF_STATUS ucfg_p2p_mgmt_tx(struct wlan_objmgr_psoc *soc,
struct p2p_mgmt_tx *mgmt_frm, uint64_t *cookie)
{
struct scheduler_msg msg = {0};
struct p2p_soc_priv_obj *p2p_soc_obj;
struct tx_action_context *tx_action;
QDF_STATUS status;
int32_t id;
p2p_debug("soc:%pK, vdev_id:%d, chan:%d, wait:%d, buf_len:%d, cck:%d, no ack:%d, off chan:%d",
soc, mgmt_frm->vdev_id, mgmt_frm->chan,
mgmt_frm->wait, mgmt_frm->len, mgmt_frm->no_cck,
mgmt_frm->dont_wait_for_ack, mgmt_frm->off_chan);
if (!soc) {
p2p_err("psoc context passed is NULL");
return QDF_STATUS_E_INVAL;
}
p2p_soc_obj = wlan_objmgr_psoc_get_comp_private_obj(soc,
WLAN_UMAC_COMP_P2P);
if (!p2p_soc_obj) {
p2p_err("P2P soc context is NULL");
return QDF_STATUS_E_FAILURE;
}
tx_action = qdf_mem_malloc(sizeof(*tx_action));
if (!tx_action) {
p2p_err("Failed to allocate tx action context");
return QDF_STATUS_E_NOMEM;
}
/* return cookie just for ota ack frames */
if (mgmt_frm->dont_wait_for_ack)
id = 0;
else {
status = qdf_idr_alloc(&p2p_soc_obj->p2p_idr,
tx_action, &id);
if (QDF_IS_STATUS_ERROR(status)) {
qdf_mem_free(tx_action);
p2p_err("failed to alloc idr, status :%d", status);
return status;
}
}
*cookie = (uint64_t)id;
tx_action->p2p_soc_obj = p2p_soc_obj;
tx_action->vdev_id = mgmt_frm->vdev_id;
tx_action->chan = mgmt_frm->chan;
tx_action->duration = mgmt_frm->wait;
tx_action->buf_len = mgmt_frm->len;
tx_action->no_cck = mgmt_frm->no_cck;
tx_action->no_ack = mgmt_frm->dont_wait_for_ack;
tx_action->off_chan = mgmt_frm->off_chan;
tx_action->buf = qdf_mem_malloc(tx_action->buf_len);
if (!(tx_action->buf)) {
p2p_err("Failed to allocate buffer for action frame");
qdf_mem_free(tx_action);
return QDF_STATUS_E_NOMEM;
}
qdf_mem_copy(tx_action->buf, mgmt_frm->buf, tx_action->buf_len);
tx_action->nbuf = NULL;
tx_action->id = id;
p2p_rand_mac_tx(tx_action);
msg.type = P2P_MGMT_TX;
msg.bodyptr = tx_action;
msg.callback = p2p_process_cmd;
msg.flush_callback = p2p_msg_flush_callback;
status = scheduler_post_message(QDF_MODULE_ID_HDD,
QDF_MODULE_ID_P2P,
QDF_MODULE_ID_OS_IF,
&msg);
if (QDF_IS_STATUS_ERROR(status)) {
if (id)
qdf_idr_remove(&p2p_soc_obj->p2p_idr, id);
qdf_mem_free(tx_action->buf);
qdf_mem_free(tx_action);
p2p_err("post msg fail:%d", status);
}
return status;
}
QDF_STATUS ucfg_p2p_mgmt_tx_cancel(struct wlan_objmgr_psoc *soc,
struct wlan_objmgr_vdev *vdev, uint64_t cookie)
{
struct scheduler_msg msg = {0};
struct p2p_soc_priv_obj *p2p_soc_obj;
struct cancel_roc_context *cancel_tx;
void *tx_ctx;
QDF_STATUS status;
p2p_debug("soc:%pK, cookie:0x%llx", soc, cookie);
if (!soc) {
p2p_err("psoc context passed is NULL");
return QDF_STATUS_E_INVAL;
}
p2p_soc_obj = wlan_objmgr_psoc_get_comp_private_obj(soc,
WLAN_UMAC_COMP_P2P);
if (!p2p_soc_obj) {
p2p_err("p2p soc context is NULL");
return QDF_STATUS_E_FAILURE;
}
status = qdf_idr_find(&p2p_soc_obj->p2p_idr,
(int32_t)cookie, &tx_ctx);
if (QDF_IS_STATUS_ERROR(status)) {
p2p_debug("invalid id");
return QDF_STATUS_E_INVAL;
}
p2p_del_random_mac(soc, wlan_vdev_get_id(vdev), cookie, 20);
cancel_tx = qdf_mem_malloc(sizeof(*cancel_tx));
if (!cancel_tx) {
p2p_err("Failed to allocate cancel p2p roc");
return QDF_STATUS_E_NOMEM;
}
cancel_tx->p2p_soc_obj = p2p_soc_obj;
cancel_tx->cookie = (uintptr_t)tx_ctx;
msg.type = P2P_MGMT_TX_CANCEL;
msg.bodyptr = cancel_tx;
msg.callback = p2p_process_cmd;
status = scheduler_post_message(QDF_MODULE_ID_HDD,
QDF_MODULE_ID_P2P,
QDF_MODULE_ID_OS_IF,
&msg);
if (QDF_IS_STATUS_ERROR(status)) {
qdf_mem_free(cancel_tx);
p2p_err("post msg fail: %d", status);
}
return status;
}
bool ucfg_p2p_check_random_mac(struct wlan_objmgr_psoc *soc, uint32_t vdev_id,
uint8_t *random_mac_addr)
{
return p2p_check_random_mac(soc, vdev_id, random_mac_addr);
}
QDF_STATUS ucfg_p2p_set_ps(struct wlan_objmgr_psoc *soc,
struct p2p_ps_config *ps_config)
{
struct wlan_lmac_if_p2p_tx_ops *p2p_ops;
QDF_STATUS status = QDF_STATUS_E_FAILURE;
uint16_t obj_id;
struct wlan_objmgr_vdev *vdev;
struct p2p_ps_config go_ps_config;
p2p_debug("soc:%pK, vdev_id:%d, opp_ps:%d, ct_window:%d, count:%d, duration:%d, duration:%d, ps_selection:%d",
soc, ps_config->vdev_id, ps_config->opp_ps,
ps_config->ct_window, ps_config->count,
ps_config->duration, ps_config->single_noa_duration,
ps_config->ps_selection);
if (!soc) {
p2p_err("psoc context passed is NULL");
return QDF_STATUS_E_INVAL;
}
for (obj_id = 0; obj_id < WLAN_UMAC_PSOC_MAX_VDEVS; obj_id++) {
vdev = wlan_objmgr_get_vdev_by_id_from_psoc(soc, obj_id,
WLAN_P2P_ID);
if (vdev) {
if (is_p2p_ps_allowed(vdev, WLAN_UMAC_COMP_P2P)) {
wlan_objmgr_vdev_release_ref(vdev, WLAN_P2P_ID);
break;
}
wlan_objmgr_vdev_release_ref(vdev, WLAN_P2P_ID);
p2p_debug("skip p2p set ps vdev %d, NoA is disabled as legacy STA is connected to GO.",
obj_id);
}
}
if (obj_id >= WLAN_UMAC_PSOC_MAX_VDEVS) {
p2p_debug("No GO found!");
return QDF_STATUS_E_INVAL;
}
go_ps_config = *ps_config;
go_ps_config.vdev_id = obj_id;
p2p_ops = ucfg_p2p_psoc_get_tx_ops(soc);
if (p2p_ops->set_ps) {
status = p2p_ops->set_ps(soc, &go_ps_config);
p2p_debug("p2p set ps vdev %d, status:%d", obj_id, status);
}
return status;
}
#ifdef FEATURE_P2P_LISTEN_OFFLOAD
QDF_STATUS ucfg_p2p_lo_start(struct wlan_objmgr_psoc *soc,
struct p2p_lo_start *p2p_lo_start)
{
struct wlan_lmac_if_p2p_tx_ops *p2p_ops;
QDF_STATUS status = QDF_STATUS_E_FAILURE;
p2p_debug("soc:%pK, vdev_id:%d, ctl_flags:%d, freq:%d, period:%d, interval:%d, count:%d, dev_types_len:%d, probe_resp_len:%d, device_types:%pK, probe_resp_tmplt:%pK",
soc, p2p_lo_start->vdev_id, p2p_lo_start->ctl_flags,
p2p_lo_start->freq, p2p_lo_start->period,
p2p_lo_start->interval, p2p_lo_start->count,
p2p_lo_start->dev_types_len, p2p_lo_start->probe_resp_len,
p2p_lo_start->device_types, p2p_lo_start->probe_resp_tmplt);
if (!soc) {
p2p_err("psoc context passed is NULL");
return QDF_STATUS_E_INVAL;
}
p2p_ops = ucfg_p2p_psoc_get_tx_ops(soc);
if (p2p_ops->lo_start) {
status = p2p_ops->lo_start(soc, p2p_lo_start);
p2p_debug("p2p lo start, status:%d", status);
}
return status;
}
QDF_STATUS ucfg_p2p_lo_stop(struct wlan_objmgr_psoc *soc,
uint32_t vdev_id)
{
struct wlan_lmac_if_p2p_tx_ops *p2p_ops;
QDF_STATUS status = QDF_STATUS_E_FAILURE;
p2p_debug("soc:%pK, vdev_id:%d", soc, vdev_id);
if (!soc) {
p2p_err("psoc context passed is NULL");
return QDF_STATUS_E_INVAL;
}
p2p_ops = ucfg_p2p_psoc_get_tx_ops(soc);
if (p2p_ops->lo_stop) {
status = p2p_ops->lo_stop(soc, vdev_id);
p2p_debug("p2p lo stop, status:%d", status);
}
return status;
}
#endif
QDF_STATUS ucfg_p2p_set_noa(struct wlan_objmgr_psoc *soc,
uint32_t vdev_id, bool disable_noa)
{
struct wlan_lmac_if_p2p_tx_ops *p2p_ops;
QDF_STATUS status = QDF_STATUS_E_INVAL;
p2p_ops = ucfg_p2p_psoc_get_tx_ops(soc);
if (p2p_ops->set_noa) {
status = p2p_ops->set_noa(soc, vdev_id, disable_noa);
p2p_debug("p2p set noa, status:%d", status);
}
return status;
}
QDF_STATUS ucfg_p2p_register_callbacks(struct wlan_objmgr_psoc *soc,
struct p2p_protocol_callbacks *cb_obj)
{
struct p2p_soc_priv_obj *p2p_soc_obj;
if (!soc || !cb_obj) {
p2p_err("psoc %pM cb_obj %pM context passed is NULL", soc,
cb_obj);
return QDF_STATUS_E_INVAL;
}
p2p_soc_obj = wlan_objmgr_psoc_get_comp_private_obj(soc,
WLAN_UMAC_COMP_P2P);
if (!p2p_soc_obj) {
p2p_err("p2p soc private object is NULL");
return QDF_STATUS_E_FAILURE;
}
p2p_soc_obj->p2p_cb = *cb_obj;
return QDF_STATUS_SUCCESS;
}
QDF_STATUS ucfg_p2p_status_scan(struct wlan_objmgr_vdev *vdev)
{
if (!vdev) {
p2p_err("vdev is NULL");
return QDF_STATUS_E_INVAL;
}
return p2p_status_scan(vdev);
}
QDF_STATUS ucfg_p2p_status_connect(struct wlan_objmgr_vdev *vdev)
{
if (!vdev) {
p2p_err("vdev is NULL");
return QDF_STATUS_E_INVAL;
}
return p2p_status_connect(vdev);
}
QDF_STATUS ucfg_p2p_status_disconnect(struct wlan_objmgr_vdev *vdev)
{
if (!vdev) {
p2p_err("vdev is NULL");
return QDF_STATUS_E_INVAL;
}
return p2p_status_disconnect(vdev);
}
QDF_STATUS ucfg_p2p_status_start_bss(struct wlan_objmgr_vdev *vdev)
{
if (!vdev) {
p2p_err("vdev is NULL");
return QDF_STATUS_E_INVAL;
}
return p2p_status_start_bss(vdev);
}
QDF_STATUS ucfg_p2p_status_stop_bss(struct wlan_objmgr_vdev *vdev)
{
if (!vdev) {
p2p_err("vdev is NULL");
return QDF_STATUS_E_INVAL;
}
return p2p_status_stop_bss(vdev);
}

View file

@ -0,0 +1,140 @@
/*
* Copyright (c) 2017-2018 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: offload lmac interface APIs for P2P
*/
#ifndef _TARGET_IF_P2P_H_
#define _TARGET_IF_P2P_H_
#include <qdf_types.h>
struct wlan_objmgr_psoc;
struct p2p_ps_config;
struct p2p_lo_start;
#ifdef FEATURE_P2P_LISTEN_OFFLOAD
/**
* target_if_p2p_register_lo_event_handler() - Register lo event handler
* @psoc: soc object
* @arg: additional argument
*
* Target interface API to register P2P listen offload event handler.
*
* Return: QDF_STATUS_SUCCESS - in case of success
*/
QDF_STATUS target_if_p2p_register_lo_event_handler(
struct wlan_objmgr_psoc *psoc, void *arg);
/**
* target_if_p2p_unregister_lo_event_handler() - Unregister lo event handler
* @psoc: soc object
* @arg: additional argument
*
* Target interface API to unregister P2P listen offload event handler.
*
* Return: QDF_STATUS_SUCCESS - in case of success
*/
QDF_STATUS target_if_p2p_unregister_lo_event_handler(
struct wlan_objmgr_psoc *psoc, void *arg);
/**
* target_if_p2p_lo_start() - Start listen offload
* @psoc: soc object
* @lo_start: lo start information
*
* Target interface API to start listen offload.
*
* Return: QDF_STATUS_SUCCESS - in case of success
*/
QDF_STATUS target_if_p2p_lo_start(struct wlan_objmgr_psoc *psoc,
struct p2p_lo_start *lo_start);
/**
* target_if_p2p_lo_stop() - Stop listen offload
* @psoc: soc object
* @vdev_id: vdev id
*
* Target interface API to stop listen offload.
*
* Return: QDF_STATUS_SUCCESS - in case of success
*/
QDF_STATUS target_if_p2p_lo_stop(struct wlan_objmgr_psoc *psoc,
uint32_t vdev_id);
#endif
/**
* target_if_p2p_register_tx_ops() - Register P2P component TX OPS
* @tx_ops: lmac if transmit ops
*
* Return: None
*/
void target_if_p2p_register_tx_ops(struct wlan_lmac_if_tx_ops *tx_ops);
/**
* target_if_p2p_register_noa_event_handler() - Register noa event handler
* @psoc: soc object
* @arg: additional argument
*
* Target interface API to register P2P noa event handler.
*
* Return: QDF_STATUS_SUCCESS - in case of success
*/
QDF_STATUS target_if_p2p_register_noa_event_handler(
struct wlan_objmgr_psoc *psoc, void *arg);
/**
* target_if_p2p_unregister_noa_event_handler() - Unregister noa event handler
* @psoc: soc object
* @arg: additional argument
*
* Target interface API to unregister P2P listen offload event handler.
*
* Return: QDF_STATUS_SUCCESS - in case of success
*/
QDF_STATUS target_if_p2p_unregister_noa_event_handler(
struct wlan_objmgr_psoc *psoc, void *arg);
/**
* target_if_p2p_set_ps() - Set power save
* @psoc: soc object
* @arg: additional argument
*
* Target interface API to set power save.
*
* Return: QDF_STATUS_SUCCESS - in case of success
*/
QDF_STATUS target_if_p2p_set_ps(struct wlan_objmgr_psoc *psoc,
struct p2p_ps_config *ps_config);
/**
* target_if_p2p_set_noa() - Disable / Enable NOA
* @psoc: soc object
* @vdev_id: vdev id
* @disable_noa: TRUE - Disable NoA, FALSE - Enable NoA
*
* Target interface API to Disable / Enable P2P NOA.
*
* Return: QDF_STATUS_SUCCESS - in case of success
*/
QDF_STATUS target_if_p2p_set_noa(struct wlan_objmgr_psoc *psoc,
uint32_t vdev_id, bool disable_noa);
#endif /* _TARGET_IF_P2P_H_ */

View file

@ -0,0 +1,474 @@
/*
* Copyright (c) 2017-2018 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: offload lmac interface APIs definitions for P2P
*/
#include <wmi_unified_api.h>
#include <wlan_p2p_public_struct.h>
#include "target_if.h"
#include "target_if_p2p.h"
#include "init_deinit_lmac.h"
static inline struct wlan_lmac_if_p2p_rx_ops *
target_if_psoc_get_p2p_rx_ops(struct wlan_objmgr_psoc *psoc)
{
return &(psoc->soc_cb.rx_ops.p2p);
}
#ifdef FEATURE_P2P_LISTEN_OFFLOAD
static inline void
target_if_p2p_lo_register_tx_ops(struct wlan_lmac_if_p2p_tx_ops *p2p_tx_ops)
{
p2p_tx_ops->lo_start = target_if_p2p_lo_start;
p2p_tx_ops->lo_stop = target_if_p2p_lo_stop;
p2p_tx_ops->reg_lo_ev_handler =
target_if_p2p_register_lo_event_handler;
p2p_tx_ops->unreg_lo_ev_handler =
target_if_p2p_unregister_lo_event_handler;
}
/**
* target_p2p_lo_event_handler() - WMI callback for lo stop event
* @scn: pointer to scn
* @event_buf: event buffer
* @len: buffer length
*
* This function gets called from WMI when triggered wmi event
* wmi_p2p_lo_stop_event_id.
*
* Return: 0 - success
* others - failure
*/
static int target_p2p_lo_event_handler(ol_scn_t scn, uint8_t *data,
uint32_t datalen)
{
struct wlan_objmgr_psoc *psoc;
struct wmi_unified *wmi_handle;
struct p2p_lo_event *event_info;
struct wlan_lmac_if_p2p_rx_ops *p2p_rx_ops;
QDF_STATUS status = QDF_STATUS_E_FAILURE;
target_if_debug("scn:%pK, data:%pK, datalen:%d", scn, data, datalen);
if (!scn || !data) {
target_if_err("scn: 0x%pK, data: 0x%pK", scn, data);
return -EINVAL;
}
psoc = target_if_get_psoc_from_scn_hdl(scn);
if (!psoc) {
target_if_err("null psoc");
return -EINVAL;
}
wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
if (!wmi_handle) {
target_if_err("null wmi handle");
return -EINVAL;
}
event_info = qdf_mem_malloc(sizeof(*event_info));
if (!event_info) {
target_if_err("Failed to allocate p2p lo event");
return -ENOMEM;
}
if (wmi_extract_p2p_lo_stop_ev_param(wmi_handle, data,
event_info)) {
target_if_err("Failed to extract wmi p2p lo stop event");
qdf_mem_free(event_info);
return -EINVAL;
}
p2p_rx_ops = target_if_psoc_get_p2p_rx_ops(psoc);
if (p2p_rx_ops->lo_ev_handler) {
status = p2p_rx_ops->lo_ev_handler(psoc, event_info);
target_if_debug("call lo event handler, status:%d",
status);
} else {
qdf_mem_free(event_info);
target_if_debug("no valid lo event handler");
}
return qdf_status_to_os_return(status);
}
QDF_STATUS target_if_p2p_register_lo_event_handler(
struct wlan_objmgr_psoc *psoc, void *arg)
{
int status;
wmi_unified_t wmi_handle = lmac_get_wmi_unified_hdl(psoc);
target_if_debug("psoc:%pK, arg:%pK", psoc, arg);
if (!wmi_handle) {
target_if_err("Invalid wmi handle");
return QDF_STATUS_E_INVAL;
}
status = wmi_unified_register_event(wmi_handle,
wmi_p2p_lo_stop_event_id,
target_p2p_lo_event_handler);
target_if_debug("wmi register lo event handle, status:%d", status);
return status == 0 ? QDF_STATUS_SUCCESS : QDF_STATUS_E_FAILURE;
}
QDF_STATUS target_if_p2p_unregister_lo_event_handler(
struct wlan_objmgr_psoc *psoc, void *arg)
{
int status;
wmi_unified_t wmi_handle = lmac_get_wmi_unified_hdl(psoc);
target_if_debug("psoc:%pK, arg:%pK", psoc, arg);
if (!wmi_handle) {
target_if_err("Invalid wmi handle");
return QDF_STATUS_E_INVAL;
}
status = wmi_unified_unregister_event(wmi_handle,
wmi_p2p_lo_stop_event_id);
target_if_debug("wmi unregister lo event handle, status:%d", status);
return status == 0 ? QDF_STATUS_SUCCESS : QDF_STATUS_E_FAILURE;
}
QDF_STATUS target_if_p2p_lo_start(struct wlan_objmgr_psoc *psoc,
struct p2p_lo_start *lo_start)
{
wmi_unified_t wmi_handle = lmac_get_wmi_unified_hdl(psoc);
if (!wmi_handle) {
target_if_err("Invalid wmi handle");
return QDF_STATUS_E_INVAL;
}
if (!lo_start) {
target_if_err("lo start parameters is null");
return QDF_STATUS_E_INVAL;
}
target_if_debug("psoc:%pK, vdev_id:%d", psoc, lo_start->vdev_id);
return wmi_unified_p2p_lo_start_cmd(wmi_handle, lo_start);
}
QDF_STATUS target_if_p2p_lo_stop(struct wlan_objmgr_psoc *psoc,
uint32_t vdev_id)
{
wmi_unified_t wmi_handle = lmac_get_wmi_unified_hdl(psoc);
target_if_debug("psoc:%pK, vdev_id:%d", psoc, vdev_id);
if (!wmi_handle) {
target_if_err("Invalid wmi handle");
return QDF_STATUS_E_INVAL;
}
return wmi_unified_p2p_lo_stop_cmd(wmi_handle,
(uint8_t)vdev_id);
}
#else
static inline void
target_if_p2p_lo_register_tx_ops(struct wlan_lmac_if_p2p_tx_ops *p2p_tx_ops)
{
}
#endif /* FEATURE_P2P_LISTEN_OFFLOAD */
/**
* target_p2p_noa_event_handler() - WMI callback for noa event
* @scn: pointer to scn
* @event_buf: event buffer
* @len: buffer length
*
* This function gets called from WMI when triggered WMI event
* wmi_p2p_noa_event_id.
*
* Return: 0 - success
* others - failure
*/
static int target_p2p_noa_event_handler(ol_scn_t scn, uint8_t *data,
uint32_t datalen)
{
struct wlan_objmgr_psoc *psoc;
struct wmi_unified *wmi_handle;
struct p2p_noa_info *event_info;
struct wlan_lmac_if_p2p_rx_ops *p2p_rx_ops;
QDF_STATUS status = QDF_STATUS_E_FAILURE;
target_if_debug("scn:%pK, data:%pK, datalen:%d", scn, data, datalen);
if (!scn || !data) {
target_if_err("scn: 0x%pK, data: 0x%pK", scn, data);
return -EINVAL;
}
psoc = target_if_get_psoc_from_scn_hdl(scn);
if (!psoc) {
target_if_err("null psoc");
return -EINVAL;
}
wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
if (!wmi_handle) {
target_if_err("null wmi handle");
return -EINVAL;
}
event_info = qdf_mem_malloc(sizeof(*event_info));
if (!event_info) {
target_if_err("failed to allocate p2p noa information");
return -ENOMEM;
}
if (wmi_extract_p2p_noa_ev_param(wmi_handle, data,
event_info)) {
target_if_err("failed to extract wmi p2p noa event");
qdf_mem_free(event_info);
return -EINVAL;
}
p2p_rx_ops = target_if_psoc_get_p2p_rx_ops(psoc);
if (p2p_rx_ops->noa_ev_handler) {
status = p2p_rx_ops->noa_ev_handler(psoc, event_info);
target_if_debug("call noa event handler, status:%d",
status);
} else {
qdf_mem_free(event_info);
target_if_debug("no valid noa event handler");
}
return qdf_status_to_os_return(status);
}
QDF_STATUS target_if_p2p_register_noa_event_handler(
struct wlan_objmgr_psoc *psoc, void *arg)
{
int status;
wmi_unified_t wmi_handle = lmac_get_wmi_unified_hdl(psoc);
target_if_debug("psoc:%pK, arg:%pK", psoc, arg);
if (!wmi_handle) {
target_if_err("Invalid wmi handle");
return QDF_STATUS_E_INVAL;
}
status = wmi_unified_register_event(wmi_handle,
wmi_p2p_noa_event_id,
target_p2p_noa_event_handler);
target_if_debug("wmi register noa event handle, status:%d",
status);
return status == 0 ? QDF_STATUS_SUCCESS : QDF_STATUS_E_FAILURE;
}
QDF_STATUS target_if_p2p_unregister_noa_event_handler(
struct wlan_objmgr_psoc *psoc, void *arg)
{
int status;
wmi_unified_t wmi_handle = lmac_get_wmi_unified_hdl(psoc);
target_if_debug("psoc:%pK, arg:%pK", psoc, arg);
if (!wmi_handle) {
target_if_err("Invalid wmi handle");
return QDF_STATUS_E_INVAL;
}
status = wmi_unified_unregister_event(wmi_handle,
wmi_p2p_noa_event_id);
target_if_debug("wmi unregister noa event handle, status:%d",
status);
return status == 0 ? QDF_STATUS_SUCCESS : QDF_STATUS_E_FAILURE;
}
QDF_STATUS target_if_p2p_set_ps(struct wlan_objmgr_psoc *psoc,
struct p2p_ps_config *ps_config)
{
struct p2p_ps_params cmd;
QDF_STATUS status;
wmi_unified_t wmi_handle = lmac_get_wmi_unified_hdl(psoc);
if (!wmi_handle) {
target_if_err("Invalid wmi handle");
return QDF_STATUS_E_INVAL;
}
if (!ps_config) {
target_if_err("ps config parameters is null");
return QDF_STATUS_E_INVAL;
}
target_if_debug("psoc:%pK, vdev_id:%d, opp_ps:%d", psoc,
ps_config->vdev_id, ps_config->opp_ps);
cmd.opp_ps = ps_config->opp_ps;
cmd.ctwindow = ps_config->ct_window;
cmd.count = ps_config->count;
cmd.duration = ps_config->duration;
cmd.interval = ps_config->interval;
cmd.single_noa_duration = ps_config->single_noa_duration;
cmd.ps_selection = ps_config->ps_selection;
cmd.session_id = ps_config->vdev_id;
if (ps_config->opp_ps)
status = wmi_unified_set_p2pgo_oppps_req(wmi_handle,
&cmd);
else
status = wmi_unified_set_p2pgo_noa_req_cmd(wmi_handle,
&cmd);
if (status != QDF_STATUS_SUCCESS)
target_if_err("Failed to send set uapsd param, %d",
status);
return status;
}
QDF_STATUS target_if_p2p_set_noa(struct wlan_objmgr_psoc *psoc,
uint32_t vdev_id, bool disable_noa)
{
struct vdev_set_params param;
wmi_unified_t wmi_handle = lmac_get_wmi_unified_hdl(psoc);
if (!wmi_handle) {
target_if_err("Invalid wmi handle");
return QDF_STATUS_E_INVAL;
}
target_if_debug("psoc:%pK, vdev_id:%d disable_noa:%d",
psoc, vdev_id, disable_noa);
param.if_id = vdev_id;
param.param_id = WMI_VDEV_PARAM_DISABLE_NOA_P2P_GO;
param.param_value = (uint32_t)disable_noa;
return wmi_unified_vdev_set_param_send(wmi_handle, &param);
}
static int target_p2p_mac_rx_filter_event_handler(ol_scn_t scn, uint8_t *data,
uint32_t datalen)
{
struct wlan_objmgr_psoc *psoc;
struct wmi_unified *wmi_handle;
struct p2p_set_mac_filter_evt event_info;
struct wlan_lmac_if_p2p_rx_ops *p2p_rx_ops;
QDF_STATUS status = QDF_STATUS_E_FAILURE;
if (!scn || !data) {
target_if_err("scn: 0x%pK, data: 0x%pK", scn, data);
return -EINVAL;
}
psoc = target_if_get_psoc_from_scn_hdl(scn);
if (!psoc) {
target_if_err("null psoc");
return -EINVAL;
}
wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
if (!wmi_handle) {
target_if_err("null wmi handle");
return -EINVAL;
}
if (wmi_extract_mac_addr_rx_filter_evt_param(wmi_handle, data,
&event_info)) {
target_if_err("failed to extract wmi p2p noa event");
return -EINVAL;
}
target_if_debug("vdev_id %d status %d", event_info.vdev_id,
event_info.status);
p2p_rx_ops = target_if_psoc_get_p2p_rx_ops(psoc);
if (p2p_rx_ops && p2p_rx_ops->add_mac_addr_filter_evt_handler)
status = p2p_rx_ops->add_mac_addr_filter_evt_handler(
psoc, &event_info);
else
target_if_debug("no add mac addr filter event handler");
return qdf_status_to_os_return(status);
}
static QDF_STATUS target_if_p2p_register_macaddr_rx_filter_evt_handler(
struct wlan_objmgr_psoc *psoc, bool reg)
{
int status;
wmi_unified_t wmi_handle = lmac_get_wmi_unified_hdl(psoc);
target_if_debug("psoc:%pK, register %d mac addr rx evt", psoc, reg);
if (!wmi_handle) {
target_if_err("Invalid wmi handle");
return QDF_STATUS_E_INVAL;
}
if (reg)
status = wmi_unified_register_event(
wmi_handle,
wmi_vdev_add_macaddr_rx_filter_event_id,
target_p2p_mac_rx_filter_event_handler);
else
status = wmi_unified_unregister_event(
wmi_handle,
wmi_vdev_add_macaddr_rx_filter_event_id);
return status == 0 ? QDF_STATUS_SUCCESS : QDF_STATUS_E_FAILURE;
}
static QDF_STATUS target_if_p2p_set_mac_addr_rx_filter_cmd(
struct wlan_objmgr_psoc *psoc, struct p2p_set_mac_filter *param)
{
wmi_unified_t wmi_handle = lmac_get_wmi_unified_hdl(psoc);
if (!wmi_handle) {
target_if_err("Invalid wmi handle");
return QDF_STATUS_E_INVAL;
}
return wmi_send_set_mac_addr_rx_filter_cmd(wmi_handle, param);
}
void target_if_p2p_register_tx_ops(struct wlan_lmac_if_tx_ops *tx_ops)
{
struct wlan_lmac_if_p2p_tx_ops *p2p_tx_ops;
if (!tx_ops) {
target_if_err("lmac tx_ops is null");
return;
}
p2p_tx_ops = &tx_ops->p2p;
p2p_tx_ops->set_ps = target_if_p2p_set_ps;
p2p_tx_ops->set_noa = target_if_p2p_set_noa;
p2p_tx_ops->reg_noa_ev_handler =
target_if_p2p_register_noa_event_handler;
p2p_tx_ops->unreg_noa_ev_handler =
target_if_p2p_unregister_noa_event_handler;
p2p_tx_ops->reg_mac_addr_rx_filter_handler =
target_if_p2p_register_macaddr_rx_filter_evt_handler;
p2p_tx_ops->set_mac_addr_rx_filter_cmd =
target_if_p2p_set_mac_addr_rx_filter_cmd;
/* register P2P listen offload callbacks */
target_if_p2p_lo_register_tx_ops(p2p_tx_ops);
}

View file

@ -0,0 +1,116 @@
/*
* Copyright (c) 2017 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: offload lmac interface APIs for tdls
*
*/
#ifndef __TARGET_IF_TDLS_H__
#define __TARGET_IF_TDLS_H__
struct tdls_info;
struct wlan_objmgr_psoc;
struct tdls_peer_update_state;
struct tdls_channel_switch_params;
struct sta_uapsd_trig_params;
/**
* target_if_tdls_update_fw_state() - lmac handler to update tdls fw state
* @psoc: psoc object
* @param: tdls state parameter
*
* Return: QDF_STATUS
*/
QDF_STATUS
target_if_tdls_update_fw_state(struct wlan_objmgr_psoc *psoc,
struct tdls_info *param);
/**
* target_if_tdls_update_peer_state() - lmac handler to update tdls peer state
* @psoc: psoc object
* @peer_params: tdls peer state params
*
* Return: QDF_STATUS
*/
QDF_STATUS
target_if_tdls_update_peer_state(struct wlan_objmgr_psoc *psoc,
struct tdls_peer_update_state *peer_params);
/**
* target_if_tdls_set_offchan_mode() - lmac handler to set tdls off channel mode
* @psoc: psoc object
* @params: tdls channel swithc params
*
* Return: QDF_STATUS
*/
QDF_STATUS
target_if_tdls_set_offchan_mode(struct wlan_objmgr_psoc *psoc,
struct tdls_channel_switch_params *params);
/**
* target_if_tdls_set_uapsd() - lmac handler to set uapsd auto trigger cmd
* @psoc: psoc object
* @params: upasd parameters
*
* This function sets the trigger
* uapsd params such as service interval, delay interval
* and suspend interval which will be used by the firmware
* to send trigger frames periodically when there is no
* traffic on the transmit side.
*
* Return: QDF_STATUS
*/
QDF_STATUS
target_if_tdls_set_uapsd(struct wlan_objmgr_psoc *psoc,
struct sta_uapsd_trig_params *params);
/**
* target_if_tdls_register_event_handler() - lmac handler to register tdls event
* handler
* @psoc : psoc object
* @arg: argument passed to lmac
*
* Return: QDF_STATUS
*/
QDF_STATUS
target_if_tdls_register_event_handler(struct wlan_objmgr_psoc *psoc,
void *arg);
/**
* target_if_tdls_unregister_event_handler() - lmac handler to unregister tdls
* event handler
* @psoc : psoc object
* @arg: argument passed to lmac
*
* Return: QDF_STATUS
*/
QDF_STATUS
target_if_tdls_unregister_event_handler(struct wlan_objmgr_psoc *psoc,
void *arg);
/**
* target_if_tdls_register_tx_ops() - lmac handler to register tdls tx ops
* callback functions
* @tx_ops: wlan_lmac_if_tx_ops object
*
* Return: QDF_STATUS
*/
QDF_STATUS
target_if_tdls_register_tx_ops(struct wlan_lmac_if_tx_ops *tx_ops);
#endif

View file

@ -0,0 +1,214 @@
/*
* Copyright (c) 2017-2018 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: offload lmac interface APIs for tdls
*
*/
#include <qdf_mem.h>
#include <target_if.h>
#include <qdf_status.h>
#include <wmi_unified_api.h>
#include <wmi_unified_priv.h>
#include <wmi_unified_param.h>
#include <wlan_objmgr_psoc_obj.h>
#include <wlan_tdls_tgt_api.h>
#include <target_if_tdls.h>
#include <cdp_txrx_peer_ops.h>
#include <wlan_utility.h>
static inline struct wlan_lmac_if_tdls_rx_ops *
target_if_tdls_get_rx_ops(struct wlan_objmgr_psoc *psoc)
{
return &psoc->soc_cb.rx_ops.tdls_rx_ops;
}
static int
target_if_tdls_event_handler(ol_scn_t scn, uint8_t *data, uint32_t datalen)
{
struct wlan_objmgr_psoc *psoc;
struct wmi_unified *wmi_handle;
struct wlan_lmac_if_tdls_rx_ops *tdls_rx_ops;
struct tdls_event_info info;
QDF_STATUS status;
if (!scn || !data) {
target_if_err("scn: 0x%pK, data: 0x%pK", scn, data);
return -EINVAL;
}
psoc = target_if_get_psoc_from_scn_hdl(scn);
if (!psoc) {
target_if_err("null psoc");
return -EINVAL;
}
wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
if (!wmi_handle) {
target_if_err("null wmi_handle");
return -EINVAL;
}
if (wmi_extract_vdev_tdls_ev_param(wmi_handle, data, &info)) {
target_if_err("Failed to extract wmi tdls event");
return -EINVAL;
}
tdls_rx_ops = target_if_tdls_get_rx_ops(psoc);
if (tdls_rx_ops && tdls_rx_ops->tdls_ev_handler) {
status = tdls_rx_ops->tdls_ev_handler(psoc, &info);
if (QDF_IS_STATUS_ERROR(status)) {
target_if_err("fail to handle tdls event");
return -EINVAL;
}
}
return 0;
}
QDF_STATUS
target_if_tdls_update_fw_state(struct wlan_objmgr_psoc *psoc,
struct tdls_info *param)
{
QDF_STATUS status;
uint8_t tdls_state;
struct wmi_unified *wmi_handle;
wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
if (!wmi_handle) {
target_if_err("Invalid WMI handle");
return QDF_STATUS_E_FAILURE;
}
if (TDLS_SUPPORT_EXP_TRIG_ONLY == param->tdls_state)
tdls_state = WMI_TDLS_ENABLE_PASSIVE;
else if (TDLS_SUPPORT_IMP_MODE == param->tdls_state ||
TDLS_SUPPORT_EXT_CONTROL == param->tdls_state)
tdls_state = WMI_TDLS_ENABLE_CONNECTION_TRACKER_IN_HOST;
else
tdls_state = WMI_TDLS_DISABLE;
status = wmi_unified_update_fw_tdls_state_cmd(wmi_handle,
param, tdls_state);
target_if_debug("vdev_id %d", param->vdev_id);
return status;
}
QDF_STATUS
target_if_tdls_update_peer_state(struct wlan_objmgr_psoc *psoc,
struct tdls_peer_update_state *peer_params)
{
return QDF_STATUS_SUCCESS;
}
QDF_STATUS
target_if_tdls_set_offchan_mode(struct wlan_objmgr_psoc *psoc,
struct tdls_channel_switch_params *params)
{
QDF_STATUS status;
struct wmi_unified *wmi_handle;
wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
if (!wmi_handle) {
target_if_err("Invalid WMI handle");
return QDF_STATUS_E_FAILURE;
}
status = wmi_unified_set_tdls_offchan_mode_cmd(wmi_handle,
params);
return status;
}
QDF_STATUS
target_if_tdls_set_uapsd(struct wlan_objmgr_psoc *psoc,
struct sta_uapsd_trig_params *params)
{
QDF_STATUS ret;
struct wmi_unified *wmi_handle;
wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
if (!wmi_handle) {
target_if_err("Invalid WMI handle");
return QDF_STATUS_E_FAILURE;
}
if (!wmi_service_enabled(wmi_handle,
wmi_sta_uapsd_basic_auto_trig) ||
!wmi_service_enabled(wmi_handle,
wmi_sta_uapsd_var_auto_trig)) {
target_if_debug("Trigger uapsd is not supported vdev id %d",
params->vdevid);
return QDF_STATUS_SUCCESS;
}
ret = wmi_unified_set_sta_uapsd_auto_trig_cmd(wmi_handle,
params);
if (QDF_IS_STATUS_ERROR(ret))
target_if_err("Failed to send set uapsd param ret = %d", ret);
return ret;
}
QDF_STATUS
target_if_tdls_register_event_handler(struct wlan_objmgr_psoc *psoc,
void *arg)
{
struct wmi_unified *wmi_handle;
wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
if (!wmi_handle) {
target_if_err("null wmi_handle");
return QDF_STATUS_E_INVAL;
}
return wmi_unified_register_event(wmi_handle,
wmi_tdls_peer_event_id,
target_if_tdls_event_handler);
}
QDF_STATUS
target_if_tdls_unregister_event_handler(struct wlan_objmgr_psoc *psoc,
void *arg)
{
struct wmi_unified *wmi_handle;
wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
if (!wmi_handle) {
target_if_err("null wmi_handle");
return QDF_STATUS_E_INVAL;
}
return wmi_unified_unregister_event(wmi_handle,
wmi_tdls_peer_event_id);
}
QDF_STATUS
target_if_tdls_register_tx_ops(struct wlan_lmac_if_tx_ops *tx_ops)
{
struct wlan_lmac_if_tdls_tx_ops *tdls_txops;
tdls_txops = &tx_ops->tdls_tx_ops;
tdls_txops->update_fw_state = target_if_tdls_update_fw_state;
tdls_txops->update_peer_state = target_if_tdls_update_peer_state;
tdls_txops->set_offchan_mode = target_if_tdls_set_offchan_mode;
tdls_txops->tdls_reg_ev_handler = target_if_tdls_register_event_handler;
tdls_txops->tdls_unreg_ev_handler =
target_if_tdls_unregister_event_handler;
tdls_txops->tdls_set_uapsd = target_if_tdls_set_uapsd;
return QDF_STATUS_SUCCESS;
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,420 @@
/*
* Copyright (c) 2017-2018 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_tdls_cmds_process.h
*
* TDLS north bound commands include file
*/
#ifndef _WLAN_TDLS_CMDS_PROCESS_H_
#define _WLAN_TDLS_CMDS_PROCESS_H_
#define TDLS_IS_SETUP_ACTION(action) \
((TDLS_SETUP_REQUEST <= action) && \
(TDLS_SETUP_CONFIRM >= action))
/**
* enum legacy_result_code - defined to comply with tSirResultCodes, need refine
* when mlme converged.
* @legacy_result_success: success
* @legacy_result_max: max result value
*/
enum legacy_result_code {
legacy_result_success,
legacy_result_max = 0x7FFFFFFF
};
/**
* struct tdls_send_mgmt_rsp - TDLS Response struct PE --> TDLS module
* same as struct tSirSmeRsp
* @message_type: message type eWNI_SME_TDLS_SEND_MGMT_RSP
* @length: message length
* @session_id: session id
* @transaction_id: transaction id
* @status_code: status code as tSirResultCodes
* @psoc: soc object
*/
struct tdls_send_mgmt_rsp {
uint16_t message_type;
uint16_t length;
uint8_t session_id;
uint16_t transaction_id;
enum legacy_result_code status_code;
struct wlan_objmgr_psoc *psoc;
};
/**
* struct tdls_mgmt_tx_completion_ind - TDLS TX completion PE --> TDLS module
* same as struct sSirMgmtTxCompletionInd
* @message_type: message type eWNI_SME_MGMT_FRM_TX_COMPLETION_IND
* @length: message length
* @session_id: session id
* @tx_complete_status: tx complete status
* @psoc: soc object
*/
struct tdls_mgmt_tx_completion_ind {
uint16_t message_type;
uint16_t length;
uint8_t session_id; /* Session ID */
uint32_t tx_complete_status;
struct wlan_objmgr_psoc *psoc;
};
/**
* struct tdls_add_sta_req - TDLS request struct TDLS module --> PE
* same as struct tSirTdlsAddStaReq;
* @message_type: eWNI_SME_TDLS_ADD_STA_REQ
* @length: message length
* @session_id: session id
* @transaction_id: transaction id for cmd
* @bssid: bssid
* @tdls_oper: add peer type
* @peermac: MAC address for TDLS peer
* @capability: mac capability as sSirMacCapabilityInfo
* @extn_capability: extent capability
* @supported_rates_length: rates length
* @supported_rates: supported rates
* @htcap_present: ht capability present
* @ht_cap: ht capability
* @vhtcap_present: vht capability present
* @vht_cap: vht capability
* @uapsd_queues: uapsd queue as sSirMacQosInfoStation
* @max_sp: maximum service period
*/
struct tdls_add_sta_req {
uint16_t message_type;
uint16_t length;
uint8_t session_id;
uint16_t transaction_id;
struct qdf_mac_addr bssid;
enum tdls_add_oper tdls_oper;
struct qdf_mac_addr peermac;
uint16_t capability;
uint8_t extn_capability[WLAN_MAC_MAX_EXTN_CAP];
uint8_t supported_rates_length;
uint8_t supported_rates[WLAN_MAC_MAX_SUPP_RATES];
uint8_t htcap_present;
struct htcap_cmn_ie ht_cap;
uint8_t vhtcap_present;
struct vhtcap vht_cap;
uint8_t uapsd_queues;
uint8_t max_sp;
};
/**
* struct tdls_add_sta_rsp - TDLS Response struct PE --> TDLS module
* same as struct sSirTdlsAddStaRsp
* @message_type: message type eWNI_SME_TDLS_ADD_STA_RSP
* @length: message length
* @status_code: status code as tSirResultCodes
* @peermac: MAC address of the TDLS peer
* @session_id: session id
* @sta_id: sta id
* @sta_type: sta type
* @tdls_oper: add peer type
* @psoc: soc object
*/
struct tdls_add_sta_rsp {
uint16_t message_type;
uint16_t length;
QDF_STATUS status_code;
struct qdf_mac_addr peermac;
uint8_t session_id;
uint16_t sta_id;
uint16_t sta_type;
enum tdls_add_oper tdls_oper;
struct wlan_objmgr_psoc *psoc;
};
/**
* struct tdls_del_sta_req - TDLS Request struct TDLS module --> PE
* same as sSirTdlsDelStaReq
* @message_type: message type eWNI_SME_TDLS_DEL_STA_REQ
* @length: message length
* @session_id: session id
* @transaction_id: transaction id for cmd
* @bssid: bssid
* @peermac: MAC address of the TDLS peer
*/
struct tdls_del_sta_req {
uint16_t message_type;
uint16_t length;
uint8_t session_id;
uint16_t transaction_id;
struct qdf_mac_addr bssid;
struct qdf_mac_addr peermac;
};
/**
* struct tdls_del_sta_rsp - TDLS Response struct PE --> TDLS module
* same as sSirTdlsDelStaRsp
* @message_type: message type eWNI_SME_TDLS_DEL_STA_RSP
* @length: message length
* @session_id: session id
* @status_code: status code as tSirResultCodes
* @peermac: MAC address of the TDLS peer
* @sta_id: sta id
* @psoc: soc object
*/
struct tdls_del_sta_rsp {
uint16_t message_type;
uint16_t length;
uint8_t session_id;
QDF_STATUS status_code;
struct qdf_mac_addr peermac;
uint16_t sta_id;
struct wlan_objmgr_psoc *psoc;
};
/**
* tdls_process_add_peer() - add TDLS peer
* @req: TDLS add peer request
*
* Return: QDF_STATUS_SUCCESS if success; other value if failed
*/
QDF_STATUS tdls_process_add_peer(struct tdls_add_peer_request *req);
/**
* tdls_process_del_peer() - del TDLS peer
* @req: TDLS del peer request
*
* Return: QDF_STATUS_SUCCESS if success; other value if failed
*/
QDF_STATUS tdls_process_del_peer(struct tdls_oper_request *req);
/**
* tdls_process_enable_link() - enable TDLS link
* @req: TDLS enable link request
*
* Return: QDF_STATUS_SUCCESS if success; other value if failed
*/
QDF_STATUS tdls_process_enable_link(struct tdls_oper_request *req);
/**
* tdls_process_setup_peer() - process configure an externally
* controllable TDLS peer
* @req: TDLS configure force peer request
*
* Return: QDF_STATUS_SUCCESS if success; other values if failed
*/
QDF_STATUS tdls_process_setup_peer(struct tdls_oper_request *req);
/**
* tdls_process_remove_force_peer() - process remove an externally controllable
* TDLS peer
* @req: TDLS operation request
*
* Return: QDF_STATUS_SUCCESS if success; other values if failed
*/
QDF_STATUS tdls_process_remove_force_peer(struct tdls_oper_request *req);
/**
* tdls_process_update_peer() - update TDLS peer
* @req: TDLS update peer request
*
* Return: QDF_STATUS_SUCCESS if success; other value if failed
*/
QDF_STATUS tdls_process_update_peer(struct tdls_update_peer_request *req);
/**
* tdls_process_antenna_switch() - handle TDLS antenna switch
* @req: TDLS antenna switch request
*
* Rely on callback to indicate the antenna switch state to caller.
*
* Return: QDF_STATUS_SUCCESS if success; other value if failed.
*/
QDF_STATUS tdls_process_antenna_switch(struct tdls_antenna_switch_request *req);
/**
* tdls_antenna_switch_flush_callback() - flush TDLS antenna switch request
* @msg: scheduler message contains tdls antenna switch event
*
* This function call is invoked when scheduler thread is going down
*
* Return: QDF_STATUS
*/
QDF_STATUS tdls_antenna_switch_flush_callback(struct scheduler_msg *msg);
/**
* tdls_pe_del_peer() - send TDLS delete peer request to PE
* @req: TDLS delete peer request
*
* Return: QDF status
*/
QDF_STATUS tdls_pe_del_peer(struct tdls_del_peer_request *req);
/**
* tdls_process_add_peer_rsp() - handle response for add or update TDLS peer
* @rsp: TDLS add peer response
*
* Return: QDF status
*/
QDF_STATUS tdls_process_add_peer_rsp(struct tdls_add_sta_rsp *rsp);
/**
* tdls_reset_nss() - reset tdls nss parameters
* @tdls_soc: TDLS soc object
* @action_code: action code
*
* Return: None
*/
void tdls_reset_nss(struct tdls_soc_priv_obj *tdls_soc,
uint8_t action_code);
/**
* tdls_release_serialization_command() - TDLS wrapper to
* relases serialization command.
* @vdev: Object manager vdev
* @type: command to release.
*
* Return: None
*/
void
tdls_release_serialization_command(struct wlan_objmgr_vdev *vdev,
enum wlan_serialization_cmd_type type);
/**
* tdls_set_cap() - set TDLS capability type
* @tdls_vdev: tdls vdev object
* @mac: peer mac address
* @cap: TDLS capability type
*
* Return: 0 if successful or negative errno otherwise
*/
int tdls_set_cap(struct tdls_vdev_priv_obj *tdls_vdev, const uint8_t *mac,
enum tdls_peer_capab cap);
/**
* tdls_process_send_mgmt_rsp() - handle response for send mgmt
* @rsp: TDLS send mgmt response
*
* Return: QDF_STATUS_SUCCESS for success; other values if failed
*/
QDF_STATUS tdls_process_send_mgmt_rsp(struct tdls_send_mgmt_rsp *rsp);
/**
* tdls_send_mgmt_tx_completion() - process tx completion
* @tx_complete: TDLS mgmt completion info
*
* Return: QDF_STATUS_SUCCESS for success; other values if failed
*/
QDF_STATUS tdls_send_mgmt_tx_completion(
struct tdls_mgmt_tx_completion_ind *tx_complete);
/**
* tdls_process_add_peer_rsp() - handle response for delete TDLS peer
* @rsp: TDLS delete peer response
*
* Return: QDF status
*/
QDF_STATUS tdls_process_del_peer_rsp(struct tdls_del_sta_rsp *rsp);
/**
* tdls_process_should_discover() - handle tdls should_discover event
* @vdev: vdev object
* @evt: event info
*
* Return: QDF_STATUS
*/
QDF_STATUS tdls_process_should_discover(struct wlan_objmgr_vdev *vdev,
struct tdls_event_info *evt);
/**
* tdls_process_should_teardown() - handle tdls should_teardown event
* @vdev: vdev object
* @evt: event info
*
* Return: QDF_STATUS
*/
QDF_STATUS tdls_process_should_teardown(struct wlan_objmgr_vdev *vdev,
struct tdls_event_info *evt);
/**
* tdls_process_connection_tracker_notify() -handle tdls connect tracker notify
* @vdev: vdev object
* @evt: event info
*
* Return: QDF_STATUS
*/
QDF_STATUS tdls_process_connection_tracker_notify(struct wlan_objmgr_vdev *vdev,
struct tdls_event_info *evt);
/**
* tdls_validate_mgmt_request() -validate mgmt request
* @tdls_validate: action frame request
*
* Return: 0 for success or -EINVAL otherwise
*/
int tdls_validate_mgmt_request(struct tdls_action_frame_request *tdls_mgmt_req);
/**
* tdls_set_responder() - Set/clear TDLS peer's responder role
* @set_req: set responder request
*
* Return: 0 for success or -EINVAL otherwise
*/
int tdls_set_responder(struct tdls_set_responder_req *set_req);
/**
* tdls_decrement_peer_count() - decrement connected TDLS peer counter
* @soc_obj: TDLS soc object
*
* Used in scheduler thread context, no lock needed.
*
* Return: None.
*/
void tdls_decrement_peer_count(struct tdls_soc_priv_obj *soc_obj);
/**
* wlan_tdls_offchan_parms_callback() - Callback to release ref count
* @vdev: vdev object
*
* Return: none
*/
void wlan_tdls_offchan_parms_callback(struct wlan_objmgr_vdev *vdev);
/**
* tdls_process_set_offchannel() - Handle set offchannel request for TDLS
* @req: TDLS set offchannel request
*
* Return: int status
*/
int tdls_process_set_offchannel(struct tdls_set_offchannel *req);
/**
* tdls_process_set_offchan_mode() - Handle set offchan mode request for TDLS
* @req: TDLS set offchannel mode request
*
* Return: int status
*/
int tdls_process_set_offchan_mode(struct tdls_set_offchanmode *req);
/**
* tdls_process_set_secoffchanneloffset() - Handle set sec offchannel
* offset request for TDLS
* @req: TDLS set secoffchannel offchannel request
*
* Return: int status
*/
int tdls_process_set_secoffchanneloffset(
struct tdls_set_secoffchanneloffset *req);
#endif

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,247 @@
/*
* Copyright (c) 2017-2018 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_tdls_ct.h
*
* TDLS connection tracker declarations
*/
#ifndef _WLAN_TDLS_CT_H_
#define _WLAN_TDLS_CT_H_
/*
* Before UpdateTimer expires, we want to timeout discovery response
* should not be more than 2000.
*/
#define TDLS_DISCOVERY_TIMEOUT_ERE_UPDATE 1000
#define TDLS_PREFERRED_OFF_CHANNEL_NUM_MIN 1
#define TDLS_PREFERRED_OFF_CHANNEL_NUM_MAX 165
#define TDLS_PREFERRED_OFF_CHANNEL_NUM_DEFAULT 36
/**
* tdls_is_vdev_connected() - check the vdev is connected to ap
* @vdev: vdev object manager
*
* This function will check the vdev connection status and return
* true or false
*
* Return: true - Connected, false - Not connected
*/
bool tdls_is_vdev_connected(struct wlan_objmgr_vdev *vdev);
/**
* tdls_implicit_enable() - enable implicit tdls triggering
* @tdls_vdev: TDLS vdev
*
* Return: Void
*/
void tdls_implicit_enable(struct tdls_vdev_priv_obj *tdls_vdev);
/**
* tdls_update_rx_pkt_cnt() - Update rx packet count
* @vdev: vdev object manager
* @mac_addr: mac address of the data
*
* Increase the rx packet count, if the sender is not bssid and the packet is
* not broadcast and multicast packet
*
* This sampling information will be used in TDLS connection tracker
*
* This function expected to be called in an atomic context so blocking APIs
* not allowed
*
* Return: None
*/
void tdls_update_rx_pkt_cnt(struct wlan_objmgr_vdev *vdev,
struct qdf_mac_addr *mac_addr);
/**
* tdls_update_tx_pkt_cnt() - update tx packet
* @vdev: vdev object
* @mac_addr: mac address of the data
*
* Increase the tx packet count, if the sender is not bssid and the packet is
* not broadcast and multicast packet
*
* This sampling information will be used in TDLS connection tracker
*
* This function expected to be called in an atomic context so blocking APIs
* not allowed
*
* Return: None
*/
void tdls_update_tx_pkt_cnt(struct wlan_objmgr_vdev *vdev,
struct qdf_mac_addr *mac_addr);
/**
* wlan_hdd_tdls_implicit_send_discovery_request() - send discovery request
* @tdls_vdev_obj: tdls vdev object
*
* Return: None
*/
void tdls_implicit_send_discovery_request(
struct tdls_vdev_priv_obj *tdls_vdev_obj);
/**
* tdls_recv_discovery_resp() - handling of tdls discovery response
* @soc: object manager
* @mac: mac address of peer from which the response was received
*
* Return: 0 for success or negative errno otherwise
*/
int tdls_recv_discovery_resp(struct tdls_vdev_priv_obj *tdls_vdev,
const uint8_t *mac);
/**
* tdls_indicate_teardown() - indicate teardown to upper layer
* @tdls_vdev: tdls vdev object
* @curr_peer: teardown peer
* @reason: teardown reason
*
* Return: Void
*/
void tdls_indicate_teardown(struct tdls_vdev_priv_obj *tdls_vdev,
struct tdls_peer *curr_peer,
uint16_t reason);
/**
* tdls_ct_handler() - TDLS connection tracker handler
* @user_data: user data from timer
*
* tdls connection tracker timer starts, when the STA connected to AP
* and it's scan the traffic between two STA peers and make TDLS
* connection and teardown, based on the traffic threshold
*
* Return: None
*/
void tdls_ct_handler(void *user_data);
/**
* tdls_ct_idle_handler() - Check tdls idle traffic
* @user_data: data from tdls idle timer
*
* Function to check the tdls idle traffic and make a decision about
* tdls teardown
*
* Return: None
*/
void tdls_ct_idle_handler(void *user_data);
/**
* tdls_discovery_timeout_peer_cb() - tdls discovery timeout callback
* @userData: tdls vdev
*
* Return: None
*/
void tdls_discovery_timeout_peer_cb(void *user_data);
/**
* tdls_implicit_disable() - disable implicit tdls triggering
* @pHddTdlsCtx: TDLS context
*
* Return: Void
*/
void tdls_implicit_disable(struct tdls_vdev_priv_obj *tdls_vdev);
/**
* tdls_is_vdev_connected() -check the vdev connection
* @vdev: vdev oobject
*
* Return: true or false
*/
bool tdls_is_vdev_connected(struct wlan_objmgr_vdev *vdev);
/**
* tdls_is_vdev_authenticated() -check the vdev authentication state
* @vdev: vdev oobject
*
* Return: true or false
*/
bool tdls_is_vdev_authenticated(struct wlan_objmgr_vdev *vdev);
/**
* tdls_teardown_connections() -teardown and delete all the tdls peers
* @vdev: vdev oobject
*
* Return: true or false
*/
void tdls_teardown_connections(struct wlan_objmgr_vdev *vdev);
/**
* tdls_disable_offchan_and_teardown_links - Disable offchannel
* and teardown TDLS links
* @tdls_soc : tdls soc object
*
* Return: None
*/
void tdls_disable_offchan_and_teardown_links(
struct wlan_objmgr_vdev *vdev);
/**
* tdls_delete_all_tdls_peers(): send request to delete tdls peers
* @vdev: vdev object
* @tdls_soc: tdls soc object
*
* This function sends request to lim to delete tdls peers
*
* Return: QDF_STATUS
*/
QDF_STATUS tdls_delete_all_tdls_peers(struct wlan_objmgr_vdev *vdev,
struct tdls_soc_priv_obj *tdls_soc);
/**
* tdls_set_tdls_offchannel() - set tdls off-channel number
* @tdls_soc: tdls soc object
* @offchannel: tdls off-channel number
*
* This function sets tdls off-channel number
*
* Return: 0 on success; negative errno otherwise
*/
int tdls_set_tdls_offchannel(struct tdls_soc_priv_obj *tdls_soc,
int offchannel);
/**
* tdls_set_tdls_offchannelmode() - set tdls off-channel mode
* @adapter: Pointer to the HDD adapter
* @offchanmode: tdls off-channel mode
*
* This function sets tdls off-channel mode
*
* Return: 0 on success; negative errno otherwise
*/
int tdls_set_tdls_offchannelmode(struct wlan_objmgr_vdev *vdev,
int offchanmode);
/**
* tdls_set_tdls_secoffchanneloffset() - set secondary tdls off-channel offset
* @tdls_soc: tdls soc object
* @offchanoffset: tdls off-channel offset
*
* This function sets secondary tdls off-channel offset
*
* Return: 0 on success; negative errno otherwise
*/
int tdls_set_tdls_secoffchanneloffset(struct tdls_soc_priv_obj *tdls_soc,
int offchanoffset);
#endif

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,741 @@
/*
* Copyright (c) 2017-2018 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_tdls_main.h
*
* TDLS core function declaration
*/
#if !defined(_WLAN_TDLS_MAIN_H_)
#define _WLAN_TDLS_MAIN_H_
#include <qdf_trace.h>
#include <qdf_list.h>
#include <wlan_objmgr_psoc_obj.h>
#include <wlan_objmgr_pdev_obj.h>
#include <wlan_objmgr_vdev_obj.h>
#include <wlan_objmgr_peer_obj.h>
#include <wlan_tdls_public_structs.h>
#include <scheduler_api.h>
#include "wlan_serialization_api.h"
/* Bit mask flag for tdls_option to FW */
#define ENA_TDLS_OFFCHAN (1 << 0) /* TDLS Off Channel support */
#define ENA_TDLS_BUFFER_STA (1 << 1) /* TDLS Buffer STA support */
#define ENA_TDLS_SLEEP_STA (1 << 2) /* TDLS Sleep STA support */
#define BW_20_OFFSET_BIT 0
#define BW_40_OFFSET_BIT 1
#define BW_80_OFFSET_BIT 2
#define BW_160_OFFSET_BIT 3
#define TDLS_SEC_OFFCHAN_OFFSET_0 0
#define TDLS_SEC_OFFCHAN_OFFSET_40PLUS 40
#define TDLS_SEC_OFFCHAN_OFFSET_40MINUS (-40)
#define TDLS_SEC_OFFCHAN_OFFSET_80 80
#define TDLS_SEC_OFFCHAN_OFFSET_160 160
/*
* Before UpdateTimer expires, we want to timeout discovery response
* should not be more than 2000.
*/
#define TDLS_DISCOVERY_TIMEOUT_BEFORE_UPDATE 1000
#define TDLS_SCAN_REJECT_MAX 5
#define tdls_debug(params...) \
QDF_TRACE_DEBUG(QDF_MODULE_ID_TDLS, params)
#define tdls_notice(params...) \
QDF_TRACE_INFO(QDF_MODULE_ID_TDLS, params)
#define tdls_warn(params...) \
QDF_TRACE_WARN(QDF_MODULE_ID_TDLS, params)
#define tdls_err(params...) \
QDF_TRACE_ERROR(QDF_MODULE_ID_TDLS, params)
#define tdls_alert(params...) \
QDF_TRACE_FATAL(QDF_MODULE_ID_TDLS, params)
#define tdls_nofl_debug(params...) \
QDF_TRACE_DEBUG_NO_FL(QDF_MODULE_ID_TDLS, params)
#define tdls_nofl_notice(params...) \
QDF_TRACE_INFO_NO_FL(QDF_MODULE_ID_TDLS, params)
#define tdls_nofl_warn(params...) \
QDF_TRACE_WARN_NO_FL(QDF_MODULE_ID_TDLS, params)
#define tdls_nofl_err(params...) \
QDF_TRACE_ERROR_NO_FL(QDF_MODULE_ID_TDLS, params)
#define tdls_nofl_alert(params...) \
QDF_TRACE_FATAL_NO_FL(QDF_MODULE_ID_TDLS, params)
#define TDLS_IS_LINK_CONNECTED(peer) \
((TDLS_LINK_CONNECTED == (peer)->link_status) || \
(TDLS_LINK_TEARING == (peer)->link_status))
#define SET_BIT(value, mask) ((value) |= (1 << (mask)))
#define CLEAR_BIT(value, mask) ((value) &= ~(1 << (mask)))
#define CHECK_BIT(value, mask) ((value) & (1 << (mask)))
/**
* struct tdls_conn_info - TDLS connection record
* @session_id: session id
* @sta_id: sta id
* @peer_mac: peer address
*/
struct tdls_conn_info {
uint8_t session_id;
uint8_t sta_id;
struct qdf_mac_addr peer_mac;
};
/**
* enum tdls_nss_transition_state - TDLS NSS transition states
* @TDLS_NSS_TRANSITION_UNKNOWN: default state
* @TDLS_NSS_TRANSITION_2x2_to_1x1: transition from 2x2 to 1x1 stream
* @TDLS_NSS_TRANSITION_1x1_to_2x2: transition from 1x1 to 2x2 stream
*/
enum tdls_nss_transition_state {
TDLS_NSS_TRANSITION_S_UNKNOWN = 0,
TDLS_NSS_TRANSITION_S_2x2_to_1x1,
TDLS_NSS_TRANSITION_S_1x1_to_2x2,
};
/**
* struct tdls_conn_tracker_mac_table - connection tracker peer table
* @mac_address: peer mac address
* @tx_packet_cnt: number of tx pkts
* @rx_packet_cnt: number of rx pkts
* @peer_timestamp_ms: time stamp of latest peer traffic
*/
struct tdls_conn_tracker_mac_table {
struct qdf_mac_addr mac_address;
uint32_t tx_packet_cnt;
uint32_t rx_packet_cnt;
uint32_t peer_timestamp_ms;
};
/**
* struct tdls_ct_idle_peer_data - connection tracker idle peer info
* @vdev: vdev object
* @tdls_info: tdls connection info
*/
struct tdls_ct_idle_peer_data {
struct wlan_objmgr_vdev *vdev;
struct tdls_conn_info *tdls_info;
};
/**
* struct tdls_set_state_db - to record set tdls state command, we need to
* set correct tdls state to firmware:
* 1. enable tdls in firmware before tdls connection;
* 2. disable tdls if concurrency happen, before disable tdls, all active peer
* should be deleted in firmware.
*
* @set_state_cnt: tdls set state count
* @vdev_id: vdev id of last set state command
*/
struct tdls_set_state_info {
uint8_t set_state_cnt;
uint8_t vdev_id;
};
/**
* struct tdls_psoc_priv_ctx - tdls context
* @soc: objmgr psoc
* @tdls_current_mode: current tdls mode
* @tdls_last_mode: last tdls mode
* @scan_reject_count: number of times scan rejected due to TDLS
* @tdls_source_bitmap: bit map to set/reset TDLS by different sources
* @tdls_conn_info: this tdls_conn_info can be removed and we can use peer type
* of peer object to get the active tdls peers
* @tdls_configs: tdls user configure
* @max_num_tdls_sta: maximum TDLS station number allowed upon runtime condition
* @connected_peer_count: tdls peer connected count
* @tdls_off_channel: tdls off channel number
* @tdls_channel_offset: tdls channel offset
* @tdls_fw_off_chan_mode: tdls fw off channel mode
* @enable_tdls_connection_tracker: enable tdls connection tracker
* @tdls_external_peer_count: external tdls peer count
* @tdls_nss_switch_in_progress: tdls antenna switch in progress
* @tdls_nss_teardown_complete: tdls tear down complete
* @tdls_nss_transition_mode: tdls nss transition mode
* @tdls_teardown_peers_cnt: tdls tear down peer count
* @set_state_info: set tdls state info
* @tdls_event_cb: tdls event callback
* @tdls_evt_cb_data: tdls event user data
* @tdls_peer_context: userdata for register/deregister TDLS peer
* @tdls_reg_peer: register tdls peer with datapath
* @tdls_dereg_peer: deregister tdls peer from datapath
* @tx_q_ack: queue for tx frames waiting for ack
* @tdls_con_cap: tdls concurrency support
* @tdls_send_mgmt_req: store eWNI_SME_TDLS_SEND_MGMT_REQ value
* @tdls_add_sta_req: store eWNI_SME_TDLS_ADD_STA_REQ value
* @tdls_del_sta_req: store eWNI_SME_TDLS_DEL_STA_REQ value
* @tdls_update_peer_state: store WMA_UPDATE_TDLS_PEER_STATE value
* @tdls_del_all_peers:store eWNI_SME_DEL_ALL_TDLS_PEERS
* @tdls_update_dp_vdev_flags store CDP_UPDATE_TDLS_FLAGS
* @tdls_idle_peer_data: provide information about idle peer
* @tdls_ct_spinlock: connection tracker spin lock
*/
struct tdls_soc_priv_obj {
struct wlan_objmgr_psoc *soc;
enum tdls_feature_mode tdls_current_mode;
enum tdls_feature_mode tdls_last_mode;
int scan_reject_count;
unsigned long tdls_source_bitmap;
struct tdls_conn_info tdls_conn_info[WLAN_TDLS_STA_MAX_NUM];
struct tdls_user_config tdls_configs;
uint16_t max_num_tdls_sta;
uint16_t connected_peer_count;
uint8_t tdls_off_channel;
uint16_t tdls_channel_offset;
int32_t tdls_fw_off_chan_mode;
bool enable_tdls_connection_tracker;
uint8_t tdls_external_peer_count;
bool tdls_nss_switch_in_progress;
bool tdls_nss_teardown_complete;
bool tdls_disable_in_progress;
enum tdls_nss_transition_state tdls_nss_transition_mode;
int32_t tdls_teardown_peers_cnt;
struct tdls_set_state_info set_state_info;
tdls_rx_callback tdls_rx_cb;
void *tdls_rx_cb_data;
tdls_wmm_check tdls_wmm_cb;
void *tdls_wmm_cb_data;
tdls_evt_callback tdls_event_cb;
void *tdls_evt_cb_data;
void *tdls_peer_context;
tdls_register_peer_callback tdls_reg_peer;
tdls_deregister_peer_callback tdls_dereg_peer;
tdls_dp_vdev_update_flags_callback tdls_dp_vdev_update;
qdf_list_t tx_q_ack;
enum tdls_conc_cap tdls_con_cap;
uint16_t tdls_send_mgmt_req;
uint16_t tdls_add_sta_req;
uint16_t tdls_del_sta_req;
uint16_t tdls_update_peer_state;
uint16_t tdls_del_all_peers;
uint32_t tdls_update_dp_vdev_flags;
struct tdls_ct_idle_peer_data tdls_idle_peer_data;
qdf_spinlock_t tdls_ct_spinlock;
};
/**
* struct tdls_vdev_priv_obj - tdls private vdev object
* @vdev: vdev objmgr object
* @peer_list: tdls peer list on this vdev
* @peer_update_timer: connection tracker timer
* @peer_dicovery_timer: peer discovery timer
* @threshold_config: threshold config
* @discovery_peer_cnt: discovery peer count
* @discovery_sent_cnt: discovery sent count
* @ap_rssi: ap rssi
* @curr_candidate: current candidate
* @ct_peer_table: linear mac address table for counting the packets
* @valid_mac_entries: number of valid mac entry in @ct_peer_mac_table
* @magic: magic
* @tx_queue: tx frame queue
*/
struct tdls_vdev_priv_obj {
struct wlan_objmgr_vdev *vdev;
qdf_list_t peer_list[WLAN_TDLS_PEER_LIST_SIZE];
qdf_mc_timer_t peer_update_timer;
qdf_mc_timer_t peer_discovery_timer;
struct tdls_config_params threshold_config;
int32_t discovery_peer_cnt;
uint32_t discovery_sent_cnt;
int8_t ap_rssi;
struct tdls_peer *curr_candidate;
struct tdls_conn_tracker_mac_table
ct_peer_table[WLAN_TDLS_CT_TABLE_SIZE];
uint8_t valid_mac_entries;
uint32_t magic;
uint8_t session_id;
qdf_list_t tx_queue;
};
/**
* struct tdls_peer_mlme_info - tdls peer mlme info
**/
struct tdls_peer_mlme_info {
};
/**
* struct tdls_peer - tdls peer data
* @node: node
* @vdev_priv: tdls vdev priv obj
* @peer_mac: peer mac address
* @sta_id: station identifier
* @rssi: rssi
* @tdls_support: tdls support
* @link_status: tdls link status
* @is_responder: is responder
* @discovery_processed: dicovery processed
* @discovery_attempt: discovery attempt
* @tx_pkt: tx packet
* @rx_pkt: rx packet
* @uapsd_queues: uapsd queues
* @max_sp: max sp
* @buf_sta_capable: is buffer sta
* @off_channel_capable: is offchannel supported flag
* @supported_channels_len: supported channels length
* @supported_channels: supported channels
* @supported_oper_classes_len: supported operation classes length
* @supported_oper_classes: supported operation classes
* @is_forced_peer: is forced peer
* @op_class_for_pref_off_chan: op class for preferred off channel
* @pref_off_chan_num: preferred off channel number
* @op_class_for_pref_off_chan_is_set: op class for preferred off channel set
* @peer_idle_timer: time to check idle traffic in tdls peers
* @is_peer_idle_timer_initialised: Flag to check idle timer init
* @spatial_streams: Number of TX/RX spatial streams for TDLS
* @reason: reason
* @state_change_notification: state change notification
* @qos: QOS capability of TDLS link
*/
struct tdls_peer {
qdf_list_node_t node;
struct tdls_vdev_priv_obj *vdev_priv;
struct qdf_mac_addr peer_mac;
uint16_t sta_id;
int8_t rssi;
enum tdls_peer_capab tdls_support;
enum tdls_link_state link_status;
uint8_t is_responder;
uint8_t discovery_processed;
uint16_t discovery_attempt;
uint16_t tx_pkt;
uint16_t rx_pkt;
uint8_t uapsd_queues;
uint8_t max_sp;
uint8_t buf_sta_capable;
uint8_t off_channel_capable;
uint8_t supported_channels_len;
uint8_t supported_channels[WLAN_MAC_MAX_SUPP_CHANNELS];
uint8_t supported_oper_classes_len;
uint8_t supported_oper_classes[WLAN_MAX_SUPP_OPER_CLASSES];
bool is_forced_peer;
uint8_t op_class_for_pref_off_chan;
uint8_t pref_off_chan_num;
uint8_t op_class_for_pref_off_chan_is_set;
qdf_mc_timer_t peer_idle_timer;
bool is_peer_idle_timer_initialised;
uint8_t spatial_streams;
enum tdls_link_state_reason reason;
tdls_state_change_callback state_change_notification;
uint8_t qos;
struct tdls_peer_mlme_info *tdls_info;
};
/**
* struct tdls_os_if_event - TDLS os event info
* @type: type of event
* @info: pointer to event information
*/
struct tdls_os_if_event {
uint32_t type;
void *info;
};
/**
* enum tdls_os_if_notification - TDLS notification from OS IF
* @TDLS_NOTIFY_STA_SESSION_INCREMENT: sta session count incremented
* @TDLS_NOTIFY_STA_SESSION_DECREMENT: sta session count decremented
*/
enum tdls_os_if_notification {
TDLS_NOTIFY_STA_SESSION_INCREMENT,
TDLS_NOTIFY_STA_SESSION_DECREMENT
};
/**
* wlan_vdev_get_tdls_soc_obj - private API to get tdls soc object from vdev
* @vdev: vdev object
*
* Return: tdls soc object
*/
static inline struct tdls_soc_priv_obj *
wlan_vdev_get_tdls_soc_obj(struct wlan_objmgr_vdev *vdev)
{
struct wlan_objmgr_psoc *psoc;
struct tdls_soc_priv_obj *soc_obj;
if (!vdev) {
tdls_err("NULL vdev");
return NULL;
}
psoc = wlan_vdev_get_psoc(vdev);
if (!psoc) {
tdls_err("can't get psoc");
return NULL;
}
soc_obj = (struct tdls_soc_priv_obj *)
wlan_objmgr_psoc_get_comp_private_obj(psoc,
WLAN_UMAC_COMP_TDLS);
return soc_obj;
}
/**
* wlan_psoc_get_tdls_soc_obj - private API to get tdls soc object from psoc
* @psoc: psoc object
*
* Return: tdls soc object
*/
static inline struct tdls_soc_priv_obj *
wlan_psoc_get_tdls_soc_obj(struct wlan_objmgr_psoc *psoc)
{
struct tdls_soc_priv_obj *soc_obj;
if (!psoc) {
tdls_err("NULL psoc");
return NULL;
}
soc_obj = (struct tdls_soc_priv_obj *)
wlan_objmgr_psoc_get_comp_private_obj(psoc,
WLAN_UMAC_COMP_TDLS);
return soc_obj;
}
/**
* wlan_vdev_get_tdls_vdev_obj - private API to get tdls vdev object from vdev
* @vdev: vdev object
*
* Return: tdls vdev object
*/
static inline struct tdls_vdev_priv_obj *
wlan_vdev_get_tdls_vdev_obj(struct wlan_objmgr_vdev *vdev)
{
struct tdls_vdev_priv_obj *vdev_obj;
if (!vdev) {
tdls_err("NULL vdev");
return NULL;
}
vdev_obj = (struct tdls_vdev_priv_obj *)
wlan_objmgr_vdev_get_comp_private_obj(vdev,
WLAN_UMAC_COMP_TDLS);
return vdev_obj;
}
/**
* tdls_set_link_status - tdls set link status
* @vdev: vdev object
* @mac: mac address of tdls peer
* @link_state: tdls link state
* @link_reason: reason
*/
void tdls_set_link_status(struct tdls_vdev_priv_obj *vdev,
const uint8_t *mac,
enum tdls_link_state link_state,
enum tdls_link_state_reason link_reason);
/**
* tdls_psoc_obj_create_notification() - tdls psoc create notification handler
* @psoc: psoc object
* @arg_list: Argument list
*
* Return: QDF_STATUS
*/
QDF_STATUS tdls_psoc_obj_create_notification(struct wlan_objmgr_psoc *psoc,
void *arg_list);
/**
* tdls_psoc_obj_destroy_notification() - tdls psoc destroy notification handler
* @psoc: psoc object
* @arg_list: Argument list
*
* Return: QDF_STATUS
*/
QDF_STATUS tdls_psoc_obj_destroy_notification(struct wlan_objmgr_psoc *psoc,
void *arg_list);
/**
* tdls_vdev_obj_create_notification() - tdls vdev create notification handler
* @vdev: vdev object
* @arg_list: Argument list
*
* Return: QDF_STATUS
*/
QDF_STATUS tdls_vdev_obj_create_notification(struct wlan_objmgr_vdev *vdev,
void *arg_list);
/**
* tdls_vdev_obj_destroy_notification() - tdls vdev destroy notification handler
* @vdev: vdev object
* @arg_list: Argument list
*
* Return: QDF_STATUS
*/
QDF_STATUS tdls_vdev_obj_destroy_notification(struct wlan_objmgr_vdev *vdev,
void *arg_list);
/**
* tdls_process_cmd() - tdls main command process function
* @msg: scheduler msg
*
* Return: QDF_STATUS
*/
QDF_STATUS tdls_process_cmd(struct scheduler_msg *msg);
/**
* tdls_process_evt() - tdls main event process function
* @msg: scheduler msg
*
* Return: QDF_STATUS
*/
QDF_STATUS tdls_process_evt(struct scheduler_msg *msg);
/**
* tdls_timer_restart() - restart TDLS timer
* @vdev: VDEV object manager
* @timer: timer to restart
* @expiration_time: new expiration time to set for the timer
*
* Return: Void
*/
void tdls_timer_restart(struct wlan_objmgr_vdev *vdev,
qdf_mc_timer_t *timer,
uint32_t expiration_time);
/**
* wlan_hdd_tdls_timers_stop() - stop all the tdls timers running
* @tdls_vdev: TDLS vdev
*
* Return: none
*/
void tdls_timers_stop(struct tdls_vdev_priv_obj *tdls_vdev);
/**
* tdls_get_vdev_objects() - Get TDLS private objects
* @vdev: VDEV object manager
* @tdls_vdev_obj: tdls vdev object
* @tdls_soc_obj: tdls soc object
*
* Return: QDF_STATUS
*/
QDF_STATUS tdls_get_vdev_objects(struct wlan_objmgr_vdev *vdev,
struct tdls_vdev_priv_obj **tdls_vdev_obj,
struct tdls_soc_priv_obj **tdls_soc_obj);
/**
* cds_set_tdls_ct_mode() - Set the tdls connection tracker mode
* @hdd_ctx: hdd context
*
* This routine is called to set the tdls connection tracker operation status
*
* Return: NONE
*/
void tdls_set_ct_mode(struct wlan_objmgr_psoc *psoc);
/**
* tdls_set_operation_mode() - set tdls operating mode
* @tdls_set_mode: tdls mode set params
*
* Return: QDF_STATUS
*/
QDF_STATUS tdls_set_operation_mode(struct tdls_set_mode_params *tdls_set_mode);
/**
* tdls_notify_sta_connect() - Update tdls state for every
* connect event.
* @notify: sta connect params
*
* After every connect event in the system, check whether TDLS
* can be enabled in the system. If TDLS can be enabled, update the
* TDLS state as needed.
*
* Return: QDF_STATUS
*/
QDF_STATUS tdls_notify_sta_connect(struct tdls_sta_notify_params *notify);
/**
* tdls_notify_sta_disconnect() - Update tdls state for every
* disconnect event.
* @notify: sta disconnect params
*
* After every disconnect event in the system, check whether TDLS
* can be disabled/enabled in the system and update the
* TDLS state as needed.
*
* Return: QDF_STATUS
*/
QDF_STATUS tdls_notify_sta_disconnect(struct tdls_sta_notify_params *notify);
/**
* tdls_notify_reset_adapter() - notify reset adapter
* @vdev: vdev object
*
* Notify TDLS about the adapter reset
*
* Return: None
*/
void tdls_notify_reset_adapter(struct wlan_objmgr_vdev *vdev);
/**
* tdls_peers_deleted_notification() - peer delete notification
* @psoc: soc object
* @vdev_id: vdev id
*
* Legacy lim layer will delete tdls peers for roaming and heart beat failures
* and notify the component about the delete event to update the tdls.
* state.
*
* Return: QDF_STATUS
*/
QDF_STATUS tdls_peers_deleted_notification(struct wlan_objmgr_psoc *psoc,
uint8_t vdev_id);
/**
* tdls_notify_decrement_session() - Notify the session decrement
* @psoc: psoc object manager
*
* Policy manager notify TDLS about session decrement
*
* Return: None
*/
void tdls_notify_decrement_session(struct wlan_objmgr_psoc *psoc);
/**
* tdls_send_update_to_fw - update tdls status info
* @tdls_vdev_obj: tdls vdev private object.
* @tdls_prohibited: indicates whether tdls is prohibited.
* @tdls_chan_swit_prohibited: indicates whether tdls channel switch
* is prohibited.
* @sta_connect_event: indicate sta connect or disconnect event
* @session_id: session id
*
* Normally an AP does not influence TDLS connection between STAs
* associated to it. But AP may set bits for TDLS Prohibited or
* TDLS Channel Switch Prohibited in Extended Capability IE in
* Assoc/Re-assoc response to STA. So after STA is connected to
* an AP, call this function to update TDLS status as per those
* bits set in Ext Cap IE in received Assoc/Re-assoc response
* from AP.
*
* Return: None.
*/
void tdls_send_update_to_fw(struct tdls_vdev_priv_obj *tdls_vdev_obj,
struct tdls_soc_priv_obj *tdls_soc_obj,
bool tdls_prohibited,
bool tdls_chan_swit_prohibited,
bool sta_connect_event,
uint8_t session_id);
/**
* tdls_notify_increment_session() - Notify the session increment
* @psoc: psoc object manager
*
* Policy manager notify TDLS about session increment
*
* Return: None
*/
void tdls_notify_increment_session(struct wlan_objmgr_psoc *psoc);
/**
* tdls_check_is_tdls_allowed() - check is tdls allowed or not
* @vdev: vdev object
*
* Function determines the whether TDLS allowed in the system
*
* Return: true or false
*/
bool tdls_check_is_tdls_allowed(struct wlan_objmgr_vdev *vdev);
/**
* tdls_get_vdev() - Get tdls specific vdev object manager
* @psoc: wlan psoc object manager
* @dbg_id: debug id
*
* If TDLS possible, return the corresponding vdev
* to enable TDLS in the system.
*
* Return: vdev manager pointer or NULL.
*/
struct wlan_objmgr_vdev *tdls_get_vdev(struct wlan_objmgr_psoc *psoc,
wlan_objmgr_ref_dbgid dbg_id);
/**
* tdls_process_policy_mgr_notification() - process policy manager notification
* @psoc: soc object manager
*
* Return: QDF_STATUS
*/
QDF_STATUS
tdls_process_policy_mgr_notification(struct wlan_objmgr_psoc *psoc);
/**
* tdls_scan_complete_event_handler() - scan complete event handler for tdls
* @vdev: vdev object
* @event: scan event
* @arg: tdls soc object
*
* Return: None
*/
void tdls_scan_complete_event_handler(struct wlan_objmgr_vdev *vdev,
struct scan_event *event,
void *arg);
/**
* tdls_scan_callback() - callback for TDLS scan operation
* @soc: tdls soc pvt object
*
* Return: QDF_STATUS
*/
QDF_STATUS tdls_scan_callback(struct tdls_soc_priv_obj *tdls_soc);
/**
* wlan_hdd_tdls_scan_done_callback() - callback for tdls scan done event
* @tdls_soc: tdls soc object
*
* Return: Void
*/
void tdls_scan_done_callback(struct tdls_soc_priv_obj *tdls_soc);
/**
* tdls_scan_serialization_comp_info_cb() - callback for scan start
* @vdev: VDEV on which the scan command is being processed
* @comp_info: serialize rules info
*
* Return: negative = caller should stop and return error code immediately
* 1 = caller can continue to scan
*/
void tdls_scan_serialization_comp_info_cb(struct wlan_objmgr_vdev *vdev,
union wlan_serialization_rules_info *comp_info);
/**
* tdls_set_offchan_mode() - update tdls status info
* @psoc: soc object
* @param: channel switch params
*
* send message to WMI to set TDLS off channel in f/w
*
* Return: QDF_STATUS.
*/
QDF_STATUS tdls_set_offchan_mode(struct wlan_objmgr_psoc *psoc,
struct tdls_channel_switch_params *param);
/**
* tdls_delete_all_peers_indication() - update tdls status info
* @psoc: soc object
* @vdev_id: vdev id
*
* Notify tdls component to cleanup all peers
*
* Return: QDF_STATUS.
*/
QDF_STATUS tdls_delete_all_peers_indication(struct wlan_objmgr_psoc *psoc,
uint8_t vdev_id);
#endif

View file

@ -0,0 +1,449 @@
/*
* Copyright (c) 2017-2018 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_tdls_mgmt.c
*
* TDLS management frames implementation
*/
#include "wlan_tdls_main.h"
#include "wlan_tdls_tgt_api.h"
#include <wlan_serialization_api.h>
#include "wlan_mgmt_txrx_utils_api.h"
#include "wlan_tdls_peer.h"
#include "wlan_tdls_ct.h"
#include "wlan_tdls_cmds_process.h"
#include "wlan_tdls_mgmt.h"
static
const char *const tdls_action_frames_type[] = { "TDLS Setup Request",
"TDLS Setup Response",
"TDLS Setup Confirm",
"TDLS Teardown",
"TDLS Peer Traffic Indication",
"TDLS Channel Switch Request",
"TDLS Channel Switch Response",
"TDLS Peer PSM Request",
"TDLS Peer PSM Response",
"TDLS Peer Traffic Response",
"TDLS Discovery Request"};
/**
* tdls_set_rssi() - Set TDLS RSSI on peer given by mac
* @tdls_vdev: tdls vdev object
* @mac: MAC address of Peer
* @rx_rssi: rssi value
*
* Set RSSI on TDSL peer
*
* Return: 0 for success or -EINVAL otherwise
*/
static int tdls_set_rssi(struct tdls_vdev_priv_obj *tdls_vdev,
const uint8_t *mac,
int8_t rx_rssi)
{
struct tdls_peer *curr_peer;
curr_peer = tdls_find_peer(tdls_vdev, mac);
if (curr_peer == NULL) {
tdls_err("curr_peer is NULL");
return -EINVAL;
}
curr_peer->rssi = rx_rssi;
return 0;
}
/**
* tdls_process_rx_mgmt() - process tdls rx mgmt frames
* @rx_mgmt_event: tdls rx mgmt event
* @tdls_vdev: tdls vdev object
*
* Return: QDF_STATUS
*/
static QDF_STATUS tdls_process_rx_mgmt(
struct tdls_rx_mgmt_event *rx_mgmt_event,
struct tdls_vdev_priv_obj *tdls_vdev)
{
struct tdls_rx_mgmt_frame *rx_mgmt;
struct tdls_soc_priv_obj *tdls_soc_obj;
uint8_t *mac;
enum tdls_actioncode action_frame_type;
if (!rx_mgmt_event)
return QDF_STATUS_E_INVAL;
tdls_soc_obj = rx_mgmt_event->tdls_soc_obj;
rx_mgmt = rx_mgmt_event->rx_mgmt;
if (!tdls_soc_obj || !rx_mgmt) {
tdls_err("invalid psoc object or rx mgmt");
return QDF_STATUS_E_INVAL;
}
tdls_debug("soc:%pK, frame_len:%d, rx_chan:%d, vdev_id:%d, frm_type:%d, rx_rssi:%d, buf:%pK",
tdls_soc_obj->soc, rx_mgmt->frame_len,
rx_mgmt->rx_chan, rx_mgmt->vdev_id, rx_mgmt->frm_type,
rx_mgmt->rx_rssi, rx_mgmt->buf);
if (rx_mgmt->buf[TDLS_PUBLIC_ACTION_FRAME_OFFSET + 1] ==
TDLS_PUBLIC_ACTION_DISC_RESP) {
mac = &rx_mgmt->buf[TDLS_80211_PEER_ADDR_OFFSET];
tdls_notice("[TDLS] TDLS Discovery Response,"
QDF_MAC_ADDR_STR " RSSI[%d] <--- OTA",
QDF_MAC_ADDR_ARRAY(mac), rx_mgmt->rx_rssi);
tdls_recv_discovery_resp(tdls_vdev, mac);
tdls_set_rssi(tdls_vdev, mac, rx_mgmt->rx_rssi);
}
if (rx_mgmt->buf[TDLS_PUBLIC_ACTION_FRAME_OFFSET] ==
TDLS_ACTION_FRAME) {
action_frame_type =
rx_mgmt->buf[TDLS_PUBLIC_ACTION_FRAME_OFFSET + 1];
if (action_frame_type >= TDLS_ACTION_FRAME_TYPE_MAX) {
tdls_debug("[TDLS] unknown[%d] <--- OTA",
action_frame_type);
} else {
tdls_notice("[TDLS] %s <--- OTA",
tdls_action_frames_type[action_frame_type]);
}
}
/* tdls_soc_obj->tdls_rx_cb ==> wlan_cfg80211_tdls_rx_callback() */
if (tdls_soc_obj && tdls_soc_obj->tdls_rx_cb)
tdls_soc_obj->tdls_rx_cb(tdls_soc_obj->tdls_rx_cb_data,
rx_mgmt);
else
tdls_debug("rx mgmt, but no valid up layer callback");
qdf_mem_free(rx_mgmt);
return QDF_STATUS_SUCCESS;
}
QDF_STATUS tdls_process_rx_frame(struct scheduler_msg *msg)
{
struct wlan_objmgr_vdev *vdev;
struct tdls_rx_mgmt_event *tdls_rx;
struct tdls_vdev_priv_obj *tdls_vdev;
QDF_STATUS status = QDF_STATUS_E_FAILURE;
if (!(msg->bodyptr)) {
tdls_err("invalid message body");
return QDF_STATUS_E_INVAL;
}
tdls_rx = (struct tdls_rx_mgmt_event *) msg->bodyptr;
vdev = wlan_objmgr_get_vdev_by_id_from_psoc(tdls_rx->tdls_soc_obj->soc,
tdls_rx->rx_mgmt->vdev_id, WLAN_TDLS_NB_ID);
if (vdev) {
tdls_debug("tdls rx mgmt frame received");
tdls_vdev = wlan_objmgr_vdev_get_comp_private_obj(vdev,
WLAN_UMAC_COMP_TDLS);
if (tdls_vdev)
status = tdls_process_rx_mgmt(tdls_rx, tdls_vdev);
wlan_objmgr_vdev_release_ref(vdev, WLAN_TDLS_NB_ID);
}
qdf_mem_free(msg->bodyptr);
msg->bodyptr = NULL;
return status;
}
QDF_STATUS tdls_mgmt_rx_ops(struct wlan_objmgr_psoc *psoc,
bool isregister)
{
struct mgmt_txrx_mgmt_frame_cb_info frm_cb_info;
QDF_STATUS status;
int num_of_entries;
tdls_debug("psoc:%pK, is register rx:%d", psoc, isregister);
frm_cb_info.frm_type = MGMT_ACTION_TDLS_DISCRESP;
frm_cb_info.mgmt_rx_cb = tgt_tdls_mgmt_frame_rx_cb;
num_of_entries = 1;
if (isregister)
status = wlan_mgmt_txrx_register_rx_cb(psoc,
WLAN_UMAC_COMP_TDLS, &frm_cb_info,
num_of_entries);
else
status = wlan_mgmt_txrx_deregister_rx_cb(psoc,
WLAN_UMAC_COMP_TDLS, &frm_cb_info,
num_of_entries);
return status;
}
static QDF_STATUS
tdls_internal_send_mgmt_tx_done(struct tdls_action_frame_request *req,
QDF_STATUS status)
{
struct tdls_soc_priv_obj *tdls_soc_obj;
struct tdls_osif_indication indication;
if (!req || !req->vdev)
return QDF_STATUS_E_NULL_VALUE;
indication.status = status;
indication.vdev = req->vdev;
tdls_soc_obj = wlan_vdev_get_tdls_soc_obj(req->vdev);
if (tdls_soc_obj && tdls_soc_obj->tdls_event_cb)
tdls_soc_obj->tdls_event_cb(tdls_soc_obj->tdls_evt_cb_data,
TDLS_EVENT_MGMT_TX_ACK_CNF, &indication);
return QDF_STATUS_SUCCESS;
}
static QDF_STATUS tdls_activate_send_mgmt_request_flush_cb(
struct scheduler_msg *msg)
{
struct tdls_send_mgmt_request *tdls_mgmt_req;
tdls_mgmt_req = msg->bodyptr;
qdf_mem_free(tdls_mgmt_req);
msg->bodyptr = NULL;
return QDF_STATUS_SUCCESS;
}
static QDF_STATUS tdls_activate_send_mgmt_request(
struct tdls_action_frame_request *action_req)
{
struct wlan_objmgr_peer *peer;
struct tdls_soc_priv_obj *tdls_soc_obj;
QDF_STATUS status = QDF_STATUS_SUCCESS;
struct scheduler_msg msg = {0};
struct tdls_send_mgmt_request *tdls_mgmt_req;
if (!action_req || !action_req->vdev)
return QDF_STATUS_E_NULL_VALUE;
tdls_soc_obj = wlan_vdev_get_tdls_soc_obj(action_req->vdev);
if (!tdls_soc_obj) {
status = QDF_STATUS_E_NULL_VALUE;
goto release_cmd;
}
tdls_mgmt_req = qdf_mem_malloc(sizeof(struct tdls_send_mgmt_request) +
action_req->tdls_mgmt.len);
if (NULL == tdls_mgmt_req) {
status = QDF_STATUS_E_NOMEM;
tdls_err("mem alloc failed ");
QDF_ASSERT(0);
goto release_cmd;
}
tdls_debug("session_id %d "
"tdls_mgmt.dialog %d "
"tdls_mgmt.frame_type %d "
"tdls_mgmt.status_code %d "
"tdls_mgmt.responder %d "
"tdls_mgmt.peer_capability %d",
action_req->session_id,
action_req->tdls_mgmt.dialog,
action_req->tdls_mgmt.frame_type,
action_req->tdls_mgmt.status_code,
action_req->tdls_mgmt.responder,
action_req->tdls_mgmt.peer_capability);
tdls_mgmt_req->session_id = action_req->session_id;
/* Using dialog as transactionId. This can be used to
* match response with request
*/
tdls_mgmt_req->transaction_id = action_req->tdls_mgmt.dialog;
tdls_mgmt_req->req_type = action_req->tdls_mgmt.frame_type;
tdls_mgmt_req->dialog = action_req->tdls_mgmt.dialog;
tdls_mgmt_req->status_code = action_req->tdls_mgmt.status_code;
tdls_mgmt_req->responder = action_req->tdls_mgmt.responder;
tdls_mgmt_req->peer_capability = action_req->tdls_mgmt.peer_capability;
peer = wlan_vdev_get_bsspeer(action_req->vdev);
status = wlan_objmgr_peer_try_get_ref(peer, WLAN_TDLS_SB_ID);
if (QDF_IS_STATUS_ERROR(status)) {
qdf_mem_free(tdls_mgmt_req);
goto release_cmd;
}
qdf_mem_copy(tdls_mgmt_req->bssid.bytes,
wlan_peer_get_macaddr(peer), QDF_MAC_ADDR_SIZE);
qdf_mem_copy(tdls_mgmt_req->peer_mac.bytes,
action_req->tdls_mgmt.peer_mac.bytes, QDF_MAC_ADDR_SIZE);
if (action_req->tdls_mgmt.len) {
qdf_mem_copy(tdls_mgmt_req->add_ie, action_req->tdls_mgmt.buf,
action_req->tdls_mgmt.len);
}
tdls_mgmt_req->length = sizeof(struct tdls_send_mgmt_request) +
action_req->tdls_mgmt.len;
if (action_req->use_default_ac)
tdls_mgmt_req->ac = WIFI_AC_VI;
else
tdls_mgmt_req->ac = WIFI_AC_BK;
/* Send the request to PE. */
qdf_mem_zero(&msg, sizeof(msg));
tdls_debug("sending TDLS Mgmt Frame req to PE ");
tdls_mgmt_req->message_type = tdls_soc_obj->tdls_send_mgmt_req;
msg.type = tdls_soc_obj->tdls_send_mgmt_req;
msg.bodyptr = tdls_mgmt_req;
msg.flush_callback = tdls_activate_send_mgmt_request_flush_cb;
status = scheduler_post_message(QDF_MODULE_ID_TDLS,
QDF_MODULE_ID_TDLS,
QDF_MODULE_ID_PE, &msg);
if (QDF_IS_STATUS_ERROR(status)) {
tdls_err("failed to post msg, status %d", status);
qdf_mem_free(tdls_mgmt_req);
}
wlan_objmgr_peer_release_ref(peer, WLAN_TDLS_SB_ID);
release_cmd:
/*update tdls nss infornation based on action code */
tdls_reset_nss(tdls_soc_obj, action_req->chk_frame->action_code);
if (QDF_IS_STATUS_ERROR(status)) {
tdls_internal_send_mgmt_tx_done(action_req, status);
tdls_release_serialization_command(action_req->vdev,
WLAN_SER_CMD_TDLS_SEND_MGMT);
}
return status;
}
static QDF_STATUS
tdls_send_mgmt_serialize_callback(struct wlan_serialization_command *cmd,
enum wlan_serialization_cb_reason reason)
{
struct tdls_action_frame_request *req;
QDF_STATUS status = QDF_STATUS_SUCCESS;
if (!cmd || !cmd->umac_cmd) {
tdls_err("invalid params cmd: %pK, ", cmd);
return QDF_STATUS_E_NULL_VALUE;
}
req = cmd->umac_cmd;
tdls_debug("reason: %d, vdev_id: %d",
reason, req->vdev_id);
switch (reason) {
case WLAN_SER_CB_ACTIVATE_CMD:
/* command moved to active list */
status = tdls_activate_send_mgmt_request(req);
break;
case WLAN_SER_CB_CANCEL_CMD:
case WLAN_SER_CB_ACTIVE_CMD_TIMEOUT:
/* command removed from pending list.
* notify status complete with failure
*/
status = tdls_internal_send_mgmt_tx_done(req,
QDF_STATUS_E_FAILURE);
break;
case WLAN_SER_CB_RELEASE_MEM_CMD:
/* command successfully completed.
* release tdls_action_frame_request memory
*/
wlan_objmgr_vdev_release_ref(req->vdev, WLAN_TDLS_NB_ID);
qdf_mem_free(req);
break;
default:
/* Do nothing but logging */
QDF_ASSERT(0);
status = QDF_STATUS_E_INVAL;
break;
}
return status;
}
QDF_STATUS tdls_process_mgmt_req(
struct tdls_action_frame_request *tdls_mgmt_req)
{
QDF_STATUS status = QDF_STATUS_SUCCESS;
struct wlan_serialization_command cmd = {0, };
enum wlan_serialization_status ser_cmd_status;
/* If connected and in Infra. Only then allow this */
status = tdls_validate_mgmt_request(tdls_mgmt_req);
if (status != QDF_STATUS_SUCCESS) {
status = tdls_internal_send_mgmt_tx_done(tdls_mgmt_req,
status);
goto error_mgmt;
}
/* update the responder, status code information
* after the cmd validation
*/
tdls_mgmt_req->tdls_mgmt.responder =
!tdls_mgmt_req->chk_frame->responder;
tdls_mgmt_req->tdls_mgmt.status_code =
tdls_mgmt_req->chk_frame->status_code;
cmd.cmd_type = WLAN_SER_CMD_TDLS_SEND_MGMT;
/* Cmd Id not applicable for non scan cmds */
cmd.cmd_id = 0;
cmd.cmd_cb = (wlan_serialization_cmd_callback)
tdls_send_mgmt_serialize_callback;
cmd.umac_cmd = tdls_mgmt_req;
cmd.source = WLAN_UMAC_COMP_TDLS;
cmd.is_high_priority = false;
cmd.cmd_timeout_duration = TDLS_DEFAULT_SERIALIZE_CMD_TIMEOUT;
cmd.vdev = tdls_mgmt_req->vdev;
cmd.is_blocking = true;
ser_cmd_status = wlan_serialization_request(&cmd);
tdls_debug("wlan_serialization_request status:%d", ser_cmd_status);
switch (ser_cmd_status) {
case WLAN_SER_CMD_PENDING:
/* command moved to pending list.Do nothing */
break;
case WLAN_SER_CMD_ACTIVE:
/* command moved to active list. Do nothing */
break;
case WLAN_SER_CMD_DENIED_LIST_FULL:
case WLAN_SER_CMD_DENIED_RULES_FAILED:
case WLAN_SER_CMD_DENIED_UNSPECIFIED:
status = QDF_STATUS_E_FAILURE;
goto error_mgmt;
default:
QDF_ASSERT(0);
status = QDF_STATUS_E_INVAL;
goto error_mgmt;
}
return status;
error_mgmt:
wlan_objmgr_vdev_release_ref(tdls_mgmt_req->vdev, WLAN_TDLS_NB_ID);
qdf_mem_free(tdls_mgmt_req);
return status;
}

View file

@ -0,0 +1,111 @@
/*
* Copyright (c) 2017-2018 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_tdls_mgmt.h
*
* TDLS management frames include file
*/
#ifndef _WLAN_TDLS_MGMT_H_
#define _WLAN_TDLS_MGMT_H_
#define TDLS_PUBLIC_ACTION_FRAME_OFFSET 24
#define TDLS_PUBLIC_ACTION_FRAME 4
#define TDLS_PUBLIC_ACTION_DISC_RESP 14
#define TDLS_ACTION_FRAME 12
#define TDLS_80211_PEER_ADDR_OFFSET (TDLS_PUBLIC_ACTION_FRAME + \
QDF_MAC_ADDR_SIZE)
#define TDLS_ACTION_FRAME_TYPE_MAX 11
/**
* struct tdls_rx_mgmt_event - tdls rx mgmt frame event
* @tdls_soc_obj: tdls soc private object
* @rx_mgmt: tdls rx mgmt frame structure
*/
struct tdls_rx_mgmt_event {
struct tdls_soc_priv_obj *tdls_soc_obj;
struct tdls_rx_mgmt_frame *rx_mgmt;
};
/*
* struct tdls_send_mgmt_request - tdls management request
* @message_type: type of pe message
* @length: length of the frame.
* @session_id: session id
* @transaction_id: transaction ID for cmd
* @req_type: type of action frame
* @dialog: dialog token used in the frame.
* @status_code: status to be incuded in the frame.
* @responder: tdls request type
* @peer_capability: peer capability information
* @bssid: bssid
* @peer_mac: mac address of the peer
* @add_ie: additional ie's to be included
*/
struct tdls_send_mgmt_request {
uint16_t message_type;
uint16_t length;
uint8_t session_id;
uint16_t transaction_id;
uint8_t req_type;
uint8_t dialog;
uint16_t status_code;
uint8_t responder;
uint32_t peer_capability;
struct qdf_mac_addr bssid;
struct qdf_mac_addr peer_mac;
enum wifi_traffic_ac ac;
/* Variable length. Dont add any field after this. */
uint8_t add_ie[1];
};
/**
* tdls_process_mgmt_req() - send a TDLS mgmt request to serialize module
* @tdls_mgmt_req: tdls management request
*
* TDLS request API, called from cfg80211 to send a TDLS frame in
* serialized manner to PE
*
*Return: QDF_STATUS
*/
QDF_STATUS tdls_process_mgmt_req(
struct tdls_action_frame_request *tdls_mgmt_req);
/**
* tdls_mgmt_rx_ops() - register or unregister rx callback
* @psoc: psoc object
* @isregister: register if true, unregister if false
*
* This function registers or unregisters rx callback to mgmt txrx
* component.
*
* Return: QDF_STATUS
*/
QDF_STATUS tdls_mgmt_rx_ops(struct wlan_objmgr_psoc *psoc,
bool isregister);
/**
* tdls_process_rx_frame() - process tdls rx frames
* @msg: scheduler msg
*
* Return: QDF_STATUS
*/
QDF_STATUS tdls_process_rx_frame(struct scheduler_msg *msg);
#endif

View file

@ -0,0 +1,819 @@
/*
* Copyright (c) 2017-2018 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_tdls_peer.c
*
* TDLS peer basic operations
*/
#include "wlan_tdls_main.h"
#include "wlan_tdls_peer.h"
#include <wlan_reg_services_api.h>
#include <wlan_utility.h>
#include <wlan_policy_mgr_api.h>
static uint8_t calculate_hash_key(const uint8_t *macaddr)
{
uint8_t i, key;
for (i = 0, key = 0; i < 6; i++)
key ^= macaddr[i];
return key % WLAN_TDLS_PEER_LIST_SIZE;
}
struct tdls_peer *tdls_find_peer(struct tdls_vdev_priv_obj *vdev_obj,
const uint8_t *macaddr)
{
uint8_t key;
QDF_STATUS status;
struct tdls_peer *peer;
qdf_list_t *head;
qdf_list_node_t *p_node;
key = calculate_hash_key(macaddr);
head = &vdev_obj->peer_list[key];
status = qdf_list_peek_front(head, &p_node);
while (QDF_IS_STATUS_SUCCESS(status)) {
peer = qdf_container_of(p_node, struct tdls_peer, node);
if (WLAN_ADDR_EQ(&peer->peer_mac, macaddr)
== QDF_STATUS_SUCCESS) {
return peer;
}
status = qdf_list_peek_next(head, p_node, &p_node);
}
tdls_debug("no tdls peer " QDF_MAC_ADDR_STR,
QDF_MAC_ADDR_ARRAY(macaddr));
return NULL;
}
/**
* tdls_find_peer_handler() - helper function for tdls_find_all_peer
* @psoc: soc object
* @obj: vdev object
* @arg: used to keep search peer parameters
*
* Return: None.
*/
static void
tdls_find_peer_handler(struct wlan_objmgr_psoc *psoc, void *obj, void *arg)
{
struct wlan_objmgr_vdev *vdev = obj;
struct tdls_search_peer_param *tdls_param = arg;
struct tdls_vdev_priv_obj *vdev_obj;
if (tdls_param->peer)
return;
if (!vdev) {
tdls_err("invalid vdev");
return;
}
if (wlan_vdev_mlme_get_opmode(vdev) != QDF_STA_MODE &&
wlan_vdev_mlme_get_opmode(vdev) != QDF_P2P_CLIENT_MODE)
return;
vdev_obj = wlan_objmgr_vdev_get_comp_private_obj(vdev,
WLAN_UMAC_COMP_TDLS);
if (!vdev_obj)
return;
tdls_param->peer = tdls_find_peer(vdev_obj, tdls_param->macaddr);
}
struct tdls_peer *
tdls_find_all_peer(struct tdls_soc_priv_obj *soc_obj, const uint8_t *macaddr)
{
struct tdls_search_peer_param tdls_search_param;
struct wlan_objmgr_psoc *psoc;
if (!soc_obj) {
tdls_err("tdls soc object is NULL");
return NULL;
}
psoc = soc_obj->soc;
if (!psoc) {
tdls_err("psoc is NULL");
return NULL;
}
tdls_search_param.macaddr = macaddr;
tdls_search_param.peer = NULL;
wlan_objmgr_iterate_obj_list(psoc, WLAN_VDEV_OP,
tdls_find_peer_handler,
&tdls_search_param, 0, WLAN_TDLS_NB_ID);
return tdls_search_param.peer;
}
uint8_t tdls_find_opclass(struct wlan_objmgr_psoc *psoc, uint8_t channel,
uint8_t bw_offset)
{
char country[REG_ALPHA2_LEN + 1];
QDF_STATUS status;
if (!psoc) {
tdls_err("psoc is NULL");
return 0;
}
status = wlan_reg_read_default_country(psoc, country);
if (QDF_IS_STATUS_ERROR(status))
return 0;
return wlan_reg_dmn_get_opclass_from_channel(country, channel,
bw_offset);
}
/**
* tdls_add_peer() - add TDLS peer in TDLS vdev object
* @vdev_obj: TDLS vdev object
* @macaddr: MAC address of peer
*
* Allocate memory for the new peer, and add it to hash table.
*
* Return: new added TDLS peer, NULL if failed.
*/
static struct tdls_peer *tdls_add_peer(struct tdls_vdev_priv_obj *vdev_obj,
const uint8_t *macaddr)
{
struct tdls_peer *peer;
struct tdls_soc_priv_obj *soc_obj;
uint8_t key = 0;
qdf_list_t *head;
peer = qdf_mem_malloc(sizeof(*peer));
if (!peer) {
tdls_err("add tdls peer malloc memory failed!");
return NULL;
}
soc_obj = wlan_vdev_get_tdls_soc_obj(vdev_obj->vdev);
if (!soc_obj) {
tdls_err("NULL tdls soc object");
return NULL;
}
key = calculate_hash_key(macaddr);
head = &vdev_obj->peer_list[key];
qdf_mem_copy(&peer->peer_mac, macaddr, sizeof(peer->peer_mac));
peer->vdev_priv = vdev_obj;
peer->pref_off_chan_num =
soc_obj->tdls_configs.tdls_pre_off_chan_num;
peer->op_class_for_pref_off_chan =
tdls_find_opclass(soc_obj->soc,
peer->pref_off_chan_num,
soc_obj->tdls_configs.tdls_pre_off_chan_bw);
peer->sta_id = INVALID_TDLS_PEER_ID;
qdf_list_insert_back(head, &peer->node);
tdls_debug("add tdls peer: " QDF_MAC_ADDR_STR,
QDF_MAC_ADDR_ARRAY(macaddr));
return peer;
}
struct tdls_peer *tdls_get_peer(struct tdls_vdev_priv_obj *vdev_obj,
const uint8_t *macaddr)
{
struct tdls_peer *peer;
peer = tdls_find_peer(vdev_obj, macaddr);
if (!peer)
peer = tdls_add_peer(vdev_obj, macaddr);
return peer;
}
static struct tdls_peer *
tdls_find_progress_peer_in_list(qdf_list_t *head,
const uint8_t *macaddr, uint8_t skip_self)
{
QDF_STATUS status;
struct tdls_peer *peer;
qdf_list_node_t *p_node;
status = qdf_list_peek_front(head, &p_node);
while (QDF_IS_STATUS_SUCCESS(status)) {
peer = qdf_container_of(p_node, struct tdls_peer, node);
if (skip_self && macaddr &&
WLAN_ADDR_EQ(&peer->peer_mac, macaddr)
== QDF_STATUS_SUCCESS) {
status = qdf_list_peek_next(head, p_node, &p_node);
continue;
} else if (TDLS_LINK_CONNECTING == peer->link_status) {
tdls_debug(QDF_MAC_ADDR_STR " TDLS_LINK_CONNECTING",
QDF_MAC_ADDR_ARRAY(peer->peer_mac.bytes));
return peer;
}
status = qdf_list_peek_next(head, p_node, &p_node);
}
return NULL;
}
/**
* tdls_find_progress_peer() - find the peer with ongoing TDLS progress
* on present vdev
* @vdev_obj: TDLS vdev object
* @macaddr: MAC address of peer, if NULL check for all the peer list
* @skip_self: If true, skip this macaddr. Otherwise, check all the peer list.
* if macaddr is NULL, this argument is ignored, and check for all
* the peer list.
*
* Return: Pointer to tdls_peer if TDLS is ongoing. Otherwise return NULL.
*/
static struct tdls_peer *
tdls_find_progress_peer(struct tdls_vdev_priv_obj *vdev_obj,
const uint8_t *macaddr, uint8_t skip_self)
{
uint8_t i;
struct tdls_peer *peer;
qdf_list_t *head;
if (!vdev_obj) {
tdls_err("invalid tdls vdev object");
return NULL;
}
for (i = 0; i < WLAN_TDLS_PEER_LIST_SIZE; i++) {
head = &vdev_obj->peer_list[i];
peer = tdls_find_progress_peer_in_list(head, macaddr,
skip_self);
if (peer)
return peer;
}
return NULL;
}
/**
* tdls_find_progress_peer_handler() - helper function for tdls_is_progress
* @psoc: soc object
* @obj: vdev object
* @arg: used to keep search peer parameters
*
* Return: None.
*/
static void
tdls_find_progress_peer_handler(struct wlan_objmgr_psoc *psoc,
void *obj, void *arg)
{
struct wlan_objmgr_vdev *vdev = obj;
struct tdls_search_progress_param *tdls_progress = arg;
struct tdls_vdev_priv_obj *vdev_obj;
if (tdls_progress->peer)
return;
if (!vdev) {
tdls_err("invalid vdev");
return;
}
if (wlan_vdev_mlme_get_opmode(vdev) != QDF_STA_MODE &&
wlan_vdev_mlme_get_opmode(vdev) != QDF_P2P_CLIENT_MODE)
return;
vdev_obj = wlan_objmgr_vdev_get_comp_private_obj(vdev,
WLAN_UMAC_COMP_TDLS);
tdls_progress->peer = tdls_find_progress_peer(vdev_obj,
tdls_progress->macaddr,
tdls_progress->skip_self);
}
struct tdls_peer *tdls_is_progress(struct tdls_vdev_priv_obj *vdev_obj,
const uint8_t *macaddr, uint8_t skip_self)
{
struct tdls_search_progress_param tdls_progress;
struct wlan_objmgr_psoc *psoc;
if (!vdev_obj) {
tdls_err("invalid tdls vdev object");
return NULL;
}
psoc = wlan_vdev_get_psoc(vdev_obj->vdev);
if (!psoc) {
tdls_err("invalid psoc");
return NULL;
}
tdls_progress.macaddr = macaddr;
tdls_progress.skip_self = skip_self;
tdls_progress.peer = NULL;
wlan_objmgr_iterate_obj_list(psoc, WLAN_VDEV_OP,
tdls_find_progress_peer_handler,
&tdls_progress, 0, WLAN_TDLS_NB_ID);
return tdls_progress.peer;
}
struct tdls_peer *
tdls_find_first_connected_peer(struct tdls_vdev_priv_obj *vdev_obj)
{
uint16_t i;
struct tdls_peer *peer;
qdf_list_t *head;
qdf_list_node_t *p_node;
QDF_STATUS status;
if (!vdev_obj) {
tdls_err("invalid tdls vdev object");
return NULL;
}
for (i = 0; i < WLAN_TDLS_PEER_LIST_SIZE; i++) {
head = &vdev_obj->peer_list[i];
status = qdf_list_peek_front(head, &p_node);
while (QDF_IS_STATUS_SUCCESS(status)) {
peer = qdf_container_of(p_node, struct tdls_peer, node);
if (peer && TDLS_LINK_CONNECTED == peer->link_status) {
tdls_debug(QDF_MAC_ADDR_STR
" TDLS_LINK_CONNECTED",
QDF_MAC_ADDR_ARRAY(
peer->peer_mac.bytes));
return peer;
}
status = qdf_list_peek_next(head, p_node, &p_node);
}
}
return NULL;
}
/**
* tdls_determine_channel_opclass() - determine channel and opclass
* @soc_obj: TDLS soc object
* @vdev_obj: TDLS vdev object
* @peer: TDLS peer
* @channel: pointer to channel
* @opclass: pinter to opclass
*
* Function determines the channel and operating class
*
* Return: None.
*/
static void tdls_determine_channel_opclass(struct tdls_soc_priv_obj *soc_obj,
struct tdls_vdev_priv_obj *vdev_obj,
struct tdls_peer *peer,
uint32_t *channel, uint32_t *opclass)
{
uint32_t vdev_id;
enum QDF_OPMODE opmode;
/*
* If tdls offchannel is not enabled then we provide base channel
* and in that case pass opclass as 0 since opclass is mainly needed
* for offchannel cases.
*/
if (!(TDLS_IS_OFF_CHANNEL_ENABLED(
soc_obj->tdls_configs.tdls_feature_flags)) ||
soc_obj->tdls_fw_off_chan_mode != ENABLE_CHANSWITCH) {
vdev_id = wlan_vdev_get_id(vdev_obj->vdev);
opmode = wlan_vdev_mlme_get_opmode(vdev_obj->vdev);
*channel = policy_mgr_get_channel(soc_obj->soc,
policy_mgr_convert_device_mode_to_qdf_type(opmode),
&vdev_id);
*opclass = 0;
} else {
*channel = peer->pref_off_chan_num;
*opclass = peer->op_class_for_pref_off_chan;
}
tdls_debug("channel:%d opclass:%d", *channel, *opclass);
}
/**
* tdls_get_wifi_hal_state() - get TDLS wifi hal state on current peer
* @peer: TDLS peer
* @state: output parameter to store the TDLS wifi hal state
* @reason: output parameter to store the reason of the current peer
*
* Return: None.
*/
static void tdls_get_wifi_hal_state(struct tdls_peer *peer, uint32_t *state,
int32_t *reason)
{
struct wlan_objmgr_vdev *vdev;
struct tdls_soc_priv_obj *soc_obj;
vdev = peer->vdev_priv->vdev;
soc_obj = wlan_vdev_get_tdls_soc_obj(vdev);
if (!soc_obj) {
tdls_err("can't get tdls object");
return;
}
*reason = peer->reason;
switch (peer->link_status) {
case TDLS_LINK_IDLE:
case TDLS_LINK_DISCOVERED:
case TDLS_LINK_DISCOVERING:
case TDLS_LINK_CONNECTING:
*state = QCA_WIFI_HAL_TDLS_S_ENABLED;
break;
case TDLS_LINK_CONNECTED:
if ((TDLS_IS_OFF_CHANNEL_ENABLED(
soc_obj->tdls_configs.tdls_feature_flags)) &&
(soc_obj->tdls_fw_off_chan_mode == ENABLE_CHANSWITCH))
*state = QCA_WIFI_HAL_TDLS_S_ESTABLISHED_OFF_CHANNEL;
else
*state = QCA_WIFI_HAL_TDLS_S_ENABLED;
break;
case TDLS_LINK_TEARING:
*state = QCA_WIFI_HAL_TDLS_S_DROPPED;
break;
}
}
/**
* tdls_extract_peer_state_param() - extract peer update params from TDLS peer
* @peer_param: output peer update params
* @peer: TDLS peer
*
* This is used when enable TDLS link
*
* Return: None.
*/
void tdls_extract_peer_state_param(struct tdls_peer_update_state *peer_param,
struct tdls_peer *peer)
{
uint16_t i, num;
struct tdls_vdev_priv_obj *vdev_obj;
struct tdls_soc_priv_obj *soc_obj;
enum channel_state ch_state;
struct wlan_objmgr_pdev *pdev;
uint8_t chan_id;
vdev_obj = peer->vdev_priv;
soc_obj = wlan_vdev_get_tdls_soc_obj(vdev_obj->vdev);
pdev = wlan_vdev_get_pdev(vdev_obj->vdev);
if (!soc_obj || !pdev) {
tdls_err("soc_obj: %pK, pdev: %pK", soc_obj, pdev);
return;
}
qdf_mem_zero(peer_param, sizeof(*peer_param));
peer_param->vdev_id = wlan_vdev_get_id(vdev_obj->vdev);
qdf_mem_copy(peer_param->peer_macaddr,
peer->peer_mac.bytes, QDF_MAC_ADDR_SIZE);
peer_param->peer_state = TDLS_PEER_STATE_CONNCTED;
peer_param->peer_cap.is_peer_responder = peer->is_responder;
peer_param->peer_cap.peer_uapsd_queue = peer->uapsd_queues;
peer_param->peer_cap.peer_max_sp = peer->max_sp;
peer_param->peer_cap.peer_buff_sta_support = peer->buf_sta_capable;
peer_param->peer_cap.peer_off_chan_support =
peer->off_channel_capable;
peer_param->peer_cap.peer_curr_operclass = 0;
peer_param->peer_cap.self_curr_operclass = 0;
peer_param->peer_cap.pref_off_channum = peer->pref_off_chan_num;
peer_param->peer_cap.pref_off_chan_bandwidth =
soc_obj->tdls_configs.tdls_pre_off_chan_bw;
peer_param->peer_cap.opclass_for_prefoffchan =
peer->op_class_for_pref_off_chan;
if (wlan_reg_is_dfs_ch(pdev, peer_param->peer_cap.pref_off_channum)) {
tdls_err("Resetting TDLS off-channel from %d to %d",
peer_param->peer_cap.pref_off_channum,
WLAN_TDLS_PREFERRED_OFF_CHANNEL_NUM_DEF);
peer_param->peer_cap.pref_off_channum =
WLAN_TDLS_PREFERRED_OFF_CHANNEL_NUM_DEF;
}
num = 0;
for (i = 0; i < peer->supported_channels_len; i++) {
chan_id = peer->supported_channels[i];
ch_state = wlan_reg_get_channel_state(pdev, chan_id);
if (CHANNEL_STATE_INVALID != ch_state &&
CHANNEL_STATE_DFS != ch_state &&
!wlan_reg_is_dsrc_chan(pdev, chan_id)) {
peer_param->peer_cap.peer_chan[num].chan_id = chan_id;
peer_param->peer_cap.peer_chan[num].pwr =
wlan_reg_get_channel_reg_power(pdev, chan_id);
peer_param->peer_cap.peer_chan[num].dfs_set = false;
peer_param->peer_cap.peer_chanlen++;
num++;
}
}
peer_param->peer_cap.peer_oper_classlen =
peer->supported_oper_classes_len;
for (i = 0; i < peer->supported_oper_classes_len; i++)
peer_param->peer_cap.peer_oper_class[i] =
peer->supported_oper_classes[i];
}
/**
* tdls_set_link_status() - set link statue for TDLS peer
* @vdev_obj: TDLS vdev object
* @mac: MAC address of current TDLS peer
* @link_status: link status
* @link_reason: reason with link status
*
* Return: None.
*/
void tdls_set_link_status(struct tdls_vdev_priv_obj *vdev_obj,
const uint8_t *mac,
enum tdls_link_state link_status,
enum tdls_link_state_reason link_reason)
{
uint32_t state = 0;
int32_t res = 0;
uint32_t op_class = 0;
uint32_t channel = 0;
struct tdls_peer *peer;
struct tdls_soc_priv_obj *soc_obj;
peer = tdls_find_peer(vdev_obj, mac);
if (!peer) {
tdls_err("peer is NULL, can't set link status %d, reason %d",
link_status, link_reason);
return;
}
peer->link_status = link_status;
if (link_status >= TDLS_LINK_DISCOVERED)
peer->discovery_attempt = 0;
if (peer->is_forced_peer && peer->state_change_notification) {
peer->reason = link_reason;
soc_obj = wlan_vdev_get_tdls_soc_obj(vdev_obj->vdev);
if (!soc_obj) {
tdls_err("NULL psoc object");
return;
}
tdls_determine_channel_opclass(soc_obj, vdev_obj,
peer, &channel, &op_class);
tdls_get_wifi_hal_state(peer, &state, &res);
peer->state_change_notification(mac, op_class, channel,
state, res, soc_obj->soc);
}
}
void tdls_set_peer_link_status(struct tdls_peer *peer,
enum tdls_link_state link_status,
enum tdls_link_state_reason link_reason)
{
uint32_t state = 0;
int32_t res = 0;
uint32_t op_class = 0;
uint32_t channel = 0;
struct tdls_soc_priv_obj *soc_obj;
struct tdls_vdev_priv_obj *vdev_obj;
peer->link_status = link_status;
if (link_status >= TDLS_LINK_DISCOVERED)
peer->discovery_attempt = 0;
if (peer->is_forced_peer && peer->state_change_notification) {
peer->reason = link_reason;
vdev_obj = peer->vdev_priv;
soc_obj = wlan_vdev_get_tdls_soc_obj(vdev_obj->vdev);
if (!soc_obj) {
tdls_err("NULL psoc object");
return;
}
tdls_determine_channel_opclass(soc_obj, vdev_obj,
peer, &channel, &op_class);
tdls_get_wifi_hal_state(peer, &state, &res);
peer->state_change_notification(peer->peer_mac.bytes,
op_class, channel, state,
res, soc_obj->soc);
}
}
void tdls_set_peer_caps(struct tdls_vdev_priv_obj *vdev_obj,
const uint8_t *macaddr,
struct tdls_update_peer_params *req_info)
{
uint8_t is_buffer_sta = 0;
uint8_t is_off_channel_supported = 0;
uint8_t is_qos_wmm_sta = 0;
struct tdls_soc_priv_obj *soc_obj;
struct tdls_peer *curr_peer;
uint32_t feature;
soc_obj = wlan_vdev_get_tdls_soc_obj(vdev_obj->vdev);
if (!soc_obj) {
tdls_err("NULL psoc object");
return;
}
curr_peer = tdls_find_peer(vdev_obj, macaddr);
if (!curr_peer) {
tdls_err("NULL tdls peer");
return;
}
feature = soc_obj->tdls_configs.tdls_feature_flags;
if ((1 << 4) & req_info->extn_capability[3])
is_buffer_sta = 1;
if ((1 << 6) & req_info->extn_capability[3])
is_off_channel_supported = 1;
if (TDLS_IS_WMM_ENABLED(feature) && req_info->is_qos_wmm_sta)
is_qos_wmm_sta = 1;
curr_peer->uapsd_queues = req_info->uapsd_queues;
curr_peer->max_sp = req_info->max_sp;
curr_peer->buf_sta_capable = is_buffer_sta;
curr_peer->off_channel_capable = is_off_channel_supported;
qdf_mem_copy(curr_peer->supported_channels,
req_info->supported_channels,
req_info->supported_channels_len);
curr_peer->supported_channels_len = req_info->supported_channels_len;
qdf_mem_copy(curr_peer->supported_oper_classes,
req_info->supported_oper_classes,
req_info->supported_oper_classes_len);
curr_peer->supported_oper_classes_len =
req_info->supported_oper_classes_len;
curr_peer->qos = is_qos_wmm_sta;
}
QDF_STATUS tdls_set_sta_id(struct tdls_vdev_priv_obj *vdev_obj,
const uint8_t *macaddr, uint8_t sta_id)
{
struct tdls_peer *peer;
peer = tdls_find_peer(vdev_obj, macaddr);
if (!peer) {
tdls_err("peer is NULL");
return QDF_STATUS_E_FAILURE;
}
peer->sta_id = sta_id;
return QDF_STATUS_SUCCESS;
}
QDF_STATUS tdls_set_force_peer(struct tdls_vdev_priv_obj *vdev_obj,
const uint8_t *macaddr, bool forcepeer)
{
struct tdls_peer *peer;
peer = tdls_find_peer(vdev_obj, macaddr);
if (!peer) {
tdls_err("peer is NULL");
return QDF_STATUS_E_FAILURE;
}
peer->is_forced_peer = forcepeer;
return QDF_STATUS_SUCCESS;
}
QDF_STATUS tdls_set_callback(struct tdls_peer *peer,
tdls_state_change_callback callback)
{
if (!peer) {
tdls_err("peer is NULL");
return QDF_STATUS_E_FAILURE;
}
peer->state_change_notification = callback;
return QDF_STATUS_SUCCESS;
}
QDF_STATUS tdls_set_extctrl_param(struct tdls_peer *peer, uint32_t chan,
uint32_t max_latency, uint32_t op_class,
uint32_t min_bandwidth)
{
if (!peer) {
tdls_err("peer is NULL");
return QDF_STATUS_E_FAILURE;
}
peer->op_class_for_pref_off_chan = (uint8_t)op_class;
peer->pref_off_chan_num = (uint8_t)chan;
return QDF_STATUS_SUCCESS;
}
QDF_STATUS tdls_reset_peer(struct tdls_vdev_priv_obj *vdev_obj,
const uint8_t *macaddr)
{
struct tdls_soc_priv_obj *soc_obj;
struct tdls_peer *curr_peer;
struct tdls_user_config *config;
soc_obj = wlan_vdev_get_tdls_soc_obj(vdev_obj->vdev);
if (!soc_obj) {
tdls_err("NULL psoc object");
return QDF_STATUS_E_FAILURE;
}
curr_peer = tdls_find_peer(vdev_obj, macaddr);
if (!curr_peer) {
tdls_err("NULL tdls peer");
return QDF_STATUS_E_FAILURE;
}
if (!curr_peer->is_forced_peer) {
config = &soc_obj->tdls_configs;
curr_peer->pref_off_chan_num = config->tdls_pre_off_chan_num;
curr_peer->op_class_for_pref_off_chan =
tdls_find_opclass(soc_obj->soc,
curr_peer->pref_off_chan_num,
config->tdls_pre_off_chan_bw);
}
tdls_set_peer_link_status(curr_peer, TDLS_LINK_IDLE,
TDLS_LINK_UNSPECIFIED);
curr_peer->sta_id = INVALID_TDLS_PEER_ID;
return QDF_STATUS_SUCCESS;
}
void tdls_peer_idle_timers_destroy(struct tdls_vdev_priv_obj *vdev_obj)
{
uint16_t i;
struct tdls_peer *peer;
qdf_list_t *head;
qdf_list_node_t *p_node;
QDF_STATUS status;
if (!vdev_obj) {
tdls_err("NULL tdls vdev object");
return;
}
for (i = 0; i < WLAN_TDLS_PEER_LIST_SIZE; i++) {
head = &vdev_obj->peer_list[i];
status = qdf_list_peek_front(head, &p_node);
while (QDF_IS_STATUS_SUCCESS(status)) {
peer = qdf_container_of(p_node, struct tdls_peer, node);
if (peer && peer->is_peer_idle_timer_initialised) {
tdls_debug(QDF_MAC_ADDR_STR
": destroy idle timer ",
QDF_MAC_ADDR_ARRAY(
peer->peer_mac.bytes));
qdf_mc_timer_stop(&peer->peer_idle_timer);
qdf_mc_timer_destroy(&peer->peer_idle_timer);
}
status = qdf_list_peek_next(head, p_node, &p_node);
}
}
}
void tdls_free_peer_list(struct tdls_vdev_priv_obj *vdev_obj)
{
uint16_t i;
struct tdls_peer *peer;
qdf_list_t *head;
qdf_list_node_t *p_node;
if (!vdev_obj) {
tdls_err("NULL tdls vdev object");
return;
}
for (i = 0; i < WLAN_TDLS_PEER_LIST_SIZE; i++) {
head = &vdev_obj->peer_list[i];
while (QDF_IS_STATUS_SUCCESS(
qdf_list_remove_front(head, &p_node))) {
peer = qdf_container_of(p_node, struct tdls_peer, node);
qdf_mem_free(peer);
}
qdf_list_destroy(head);
}
}

View file

@ -0,0 +1,246 @@
/*
* Copyright (c) 2017-2018 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_tdls_peer.h
*
* TDLS peer function declaration
*/
#if !defined(_WLAN_TDLS_PEER_H_)
#define _WLAN_TDLS_PEER_H_
/**
* struct tdls_search_peer_param - used to search TDLS peer
* @macaddr: MAC address of peer
* @peer: pointer to the found peer
*/
struct tdls_search_peer_param {
const uint8_t *macaddr;
struct tdls_peer *peer;
};
/**
* struct tdls_progress_param - used to search progress TDLS peer
* @skip_self: skip self peer
* @macaddr: MAC address of peer
* @peer: pointer to the found peer
*/
struct tdls_search_progress_param {
uint8_t skip_self;
const uint8_t *macaddr;
struct tdls_peer *peer;
};
/**
* tdls_get_peer() - find or add an TDLS peer in TDLS vdev object
* @vdev_obj: TDLS vdev object
* @macaddr: MAC address of peer
*
* Search the TDLS peer in the hash table and create a new one if not found.
*
* Return: Pointer to tdls_peer, NULL if failed.
*/
struct tdls_peer *tdls_get_peer(struct tdls_vdev_priv_obj *vdev_obj,
const uint8_t *macaddr);
/**
* tdls_find_peer() - find TDLS peer in TDLS vdev object
* @vdev_obj: TDLS vdev object
* @macaddr: MAC address of peer
*
* This is in scheduler thread context, no lock required.
*
* Return: If peer is found, then it returns pointer to tdls_peer;
* otherwise, it returns NULL.
*/
struct tdls_peer *tdls_find_peer(struct tdls_vdev_priv_obj *vdev_obj,
const uint8_t *macaddr);
/**
* tdls_find_all_peer() - find peer matching the input MACaddr in soc range
* @soc_obj: TDLS soc object
* @macaddr: MAC address of TDLS peer
*
* This is in scheduler thread context, no lock required.
*
* Return: TDLS peer if a matching is detected; NULL otherwise
*/
struct tdls_peer *
tdls_find_all_peer(struct tdls_soc_priv_obj *soc_obj, const uint8_t *macaddr);
/**
* tdls_find_all_peer() - find peer matching the input MACaddr in soc range
* @soc_obj: TDLS soc object
* @channel:channel number
* @bw_offset: offset to bandwidth
*
* This is in scheduler thread context, no lock required.
*
* Return: Operating class
*/
uint8_t tdls_find_opclass(struct wlan_objmgr_psoc *psoc,
uint8_t channel,
uint8_t bw_offset);
/**
* tdls_find_first_connected_peer() - find the 1st connected tdls peer from vdev
* @vdev_obj: tdls vdev object
*
* This function searches for the 1st connected TDLS peer
*
* Return: The 1st connected TDLS peer if found; NULL otherwise
*/
struct tdls_peer *
tdls_find_first_connected_peer(struct tdls_vdev_priv_obj *vdev_obj);
/**
* tdls_is_progress() - find the peer with ongoing TDLS progress on present psoc
* @vdev_obj: TDLS vdev object
* @macaddr: MAC address of the peer
* @skip_self: if 1, skip checking self. If 0, search include self
*
* This is used in scheduler thread context, no lock required.
*
* Return: TDLS peer if found; NULL otherwise
*/
struct tdls_peer *tdls_is_progress(struct tdls_vdev_priv_obj *vdev_obj,
const uint8_t *macaddr, uint8_t skip_self);
/**
* tdls_extract_peer_state_param() - extract peer update params from TDL peer
* @peer_param: output peer update params
* @peer: TDLS peer
*
* This is used when enable TDLS link
*
* Return: None.
*/
void tdls_extract_peer_state_param(struct tdls_peer_update_state *peer_param,
struct tdls_peer *peer);
/**
* tdls_set_link_status() - set link statue for TDLS peer
* @peer: TDLS peer
* @link_state: link state
* @link_reason: reason with link status
*
* This is in scheduler thread context, no lock required.
*
* Return: None.
*/
void tdls_set_peer_link_status(struct tdls_peer *peer,
enum tdls_link_state link_state,
enum tdls_link_state_reason link_reason);
/**
* tdls_set_peer_caps() - set capability for TDLS peer
* @vdev_obj: TDLS vdev object
* @macaddr: MAC address for the TDLS peer
* @req_info: parameters to update peer capability
*
* This is in scheduler thread context, no lock required.
*
* Return: None.
*/
void tdls_set_peer_caps(struct tdls_vdev_priv_obj *vdev_obj,
const uint8_t *macaddr,
struct tdls_update_peer_params *req_info);
/**
* tdls_set_sta_id() - set station ID on a TDLS peer
* @vdev_obj: TDLS vdev object
* @macaddr: MAC address of the TDLS peer
* @sta_id: station ID
*
* Return: QDF_STATUS_SUCCESS if success; other values if failed
*/
QDF_STATUS tdls_set_sta_id(struct tdls_vdev_priv_obj *vdev_obj,
const uint8_t *macaddr, uint8_t sta_id);
/**
* tdls_set_force_peer() - set/clear is_forced_peer flag on peer
* @vdev_obj: TDLS vdev object
* @macaddr: MAC address of TDLS peer
* @forcepeer: value used to set is_forced_peer flag
*
* This is used in scheduler thread context, no lock required.
*
* Return: QDF_STATUS_SUCCESS if success; other values if failed
*/
QDF_STATUS tdls_set_force_peer(struct tdls_vdev_priv_obj *vdev_obj,
const uint8_t *macaddr, bool forcepeer);
/**
* tdls_set_callback() - set state change callback on current TDLS peer
* @peer: TDLS peer
* @callback: state change callback
*
* This is used in scheduler thread context, no lock required.
*
* Return: QDF_STATUS_SUCCESS if success; other values if failed
*/
QDF_STATUS tdls_set_callback(struct tdls_peer *peer,
tdls_state_change_callback callback);
/**
* tdls_set_extctrl_param() - set external control parameter on TDLS peer
* @peer: TDLS peer
* @chan: channel
* @max_latency: maximum latency
* @op_class: operation class
* @min_bandwidth: minimal bandwidth
*
* This is used in scheduler thread context, no lock required.
*
* Return: QDF_STATUS_SUCCESS if success; other values if failed
*/
QDF_STATUS tdls_set_extctrl_param(struct tdls_peer *peer, uint32_t chan,
uint32_t max_latency, uint32_t op_class,
uint32_t min_bandwidth);
/**
* tdls_reset_peer() - reset TDLS peer identified by MAC address
* @vdev_obj: TDLS vdev object
* @mac: MAC address of the peer
*
* Return: QDF_STATUS_SUCCESS if success; other values if failed
*/
QDF_STATUS tdls_reset_peer(struct tdls_vdev_priv_obj *vdev_obj,
const uint8_t *mac);
/**
* tdls_peer_idle_timers_destroy() - destroy peer idle timers
* @vdev_obj: TDLS vdev object
*
* Loop through the idle peer list and destroy their timers
*
* Return: None
*/
void tdls_peer_idle_timers_destroy(struct tdls_vdev_priv_obj *vdev_obj);
/**
* tdls_free_peer_list() - free TDLS peer list
* @vdev_obj: TDLS vdev object
*
* Free all the tdls peers
*
* Return: None
*/
void tdls_free_peer_list(struct tdls_vdev_priv_obj *vdev_obj);
#endif

View file

@ -0,0 +1,23 @@
/*
* Copyright (c) 2017 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_tdls_txrx.c
*
* TDLS txrx function definitions
*/

View file

@ -0,0 +1,23 @@
/*
* Copyright (c) 2017 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_tdls_txrx.h
*
* TDLS txrx api declaration
*/

View file

@ -0,0 +1,759 @@
/*
* Copyright (c) 2018 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.
*/
#if !defined(CONFIG_TDLS_H__)
#define CONFIG_TDLS_H__
#include "cfg_define.h"
#include "cfg_converged.h"
#include "qdf_types.h"
/*
* <ini>
* gTDLSUapsdMask - ACs to setup U-APSD for TDLS Sta.
* @Min: 0
* @Max: 0x0F
* @Default: 0x0F
*
* This ini is used to configure the ACs for which mask needs to be enabled.
* 0x1: Background 0x2: Best effort
* 0x4: Video 0x8: Voice
*
* Related: gEnableTDLSSupport.
*
* Supported Feature: TDLS
*
* Usage: Internal/External
*
* </ini>
*/
#define CFG_TDLS_QOS_WMM_UAPSD_MASK CFG_INI_UINT( \
"gTDLSUapsdMask", \
0, \
0x0F, \
0x0F, \
CFG_VALUE_OR_DEFAULT, \
"ACs to setup U-APSD for TDLS Sta")
/*
* <ini>
* gEnableTDLSBufferSta - Controls the TDLS buffer.
* @Min: 0
* @Max: 1
* @Default: 1
*
* This ini is used to control the TDLS buffer.
* Buffer STA is not enabled in CLD 2.0 yet.
*
* Related: gEnableTDLSSupport.
*
* Supported Feature: TDLS
*
* Usage: Internal/External
*
* </ini>
*/
#define CFG_TDLS_BUF_STA_ENABLED CFG_INI_BOOL( \
"gEnableTDLSBufferSta", \
1, \
"Controls the TDLS buffer")
/*
* <ini>
* gTDLSPuapsdInactivityTime - Peer UAPSD Inactivity time.
* @Min: 0
* @Max: 10
* @Default: 0
*
* This ini is used to configure peer uapsd inactivity time.
*
* Related: gEnableTDLSSupport.
*
* Supported Feature: TDLS
*
* Usage: Internal/External
*
* </ini>
*/
#define CFG_TDLS_PUAPSD_INACT_TIME CFG_INI_UINT( \
"gTDLSPuapsdInactivityTime", \
0, \
10, \
0, \
CFG_VALUE_OR_DEFAULT, \
"Peer UAPSD Inactivity time")
/*
* <ini>
* gTDLSPuapsdRxFrameThreshold - Peer UAPSD Rx frame threshold.
* @Min: 10
* @Max: 20
* @Default: 10
*
* This ini is used to configure maximum Rx frame during SP.
*
* Related: gEnableTDLSSupport.
*
* Supported Feature: TDLS
*
* Usage: Internal/External
*
* </ini>
*/
#define CFG_TDLS_RX_FRAME_THRESHOLD CFG_INI_UINT( \
"gTDLSPuapsdRxFrameThreshold", \
10, \
20, \
10, \
CFG_VALUE_OR_DEFAULT, \
"Peer UAPSD Rx frame threshold")
/*
* <ini>
* gEnableTDLSOffChannel - Enables off-channel support for TDLS link.
* @Min: 0
* @Max: 1
* @Default: 0
*
* This ini is used to enable/disable off-channel support for TDLS link.
*
* Related: gEnableTDLSSupport.
*
* Supported Feature: TDLS
*
* Usage: Internal/External
*
* </ini>
*/
#define CFG_TDLS_OFF_CHANNEL_ENABLED CFG_INI_BOOL( \
"gEnableTDLSOffChannel", \
0, \
"Enables off-channel support for TDLS")
/*
* <ini>
* gEnableTDLSSupport - Enable support for TDLS.
* @Min: 0
* @Max: 1
* @Default: 0
*
* This ini is used to enable/disable TDLS support.
*
* Related: None.
*
* Supported Feature: TDLS
*
* Usage: Internal/External
*
* </ini>
*/
#define CFG_TDLS_SUPPORT_ENABLE CFG_INI_BOOL( \
"gEnableTDLSSupport", \
0, \
"enable/disable TDLS support")
/*
* <ini>
* gEnableTDLSImplicitTrigger - Enable Implicit TDLS.
* @Min: 0
* @Max: 1
* @Default: 0
*
* This ini is used to enable/disable implicit TDLS.
* CLD driver initiates TDLS Discovery towards a peer whenever TDLS Setup
* criteria (throughput and RSSI thresholds) is met and then it tears down
* TDLS when teardown criteria (idle packet count and RSSI) is met.
*
* Related: gEnableTDLSSupport.
*
* Supported Feature: TDLS
*
* Usage: Internal/External
*
* </ini>
*/
#define CFG_TDLS_IMPLICIT_TRIGGER CFG_INI_BOOL( \
"gEnableTDLSImplicitTrigger", \
0, \
"enable/disable implicit TDLS")
/*
* <ini>
* gTDLSTxStatsPeriod - TDLS TX statistics time period.
* @Min: 1000
* @Max: 4294967295
* @Default: 2000
*
* This ini is used to configure the time period (in ms) to evaluate whether
* the number of Tx/Rx packets exceeds TDLSTxPacketThreshold and triggers a
* TDLS Discovery request.
*
* Related: gEnableTDLSSupport.
*
* Supported Feature: TDLS
*
* Usage: Internal/External
*
* </ini>
*/
#define CFG_TDLS_TX_STATS_PERIOD CFG_INI_UINT( \
"gTDLSTxStatsPeriod", \
1000, \
4294967295UL, \
2000, \
CFG_VALUE_OR_DEFAULT, \
"TDLS TX statistics time period")
/*
* <ini>
* gTDLSTxPacketThreshold - Tx/Rx Packet threshold for initiating TDLS.
* @Min: 0
* @Max: 4294967295
* @Default: 40
*
* This ini is used to configure the number of Tx/Rx packets during the
* period of gTDLSTxStatsPeriod when exceeded, a TDLS Discovery request
* is triggered.
* Related: gEnableTDLSSupport.
*
* Supported Feature: TDLS
*
* Usage: Internal/External
*
* </ini>
*/
#define CFG_TDLS_TX_PACKET_THRESHOLD CFG_INI_UINT( \
"gTDLSTxPacketThreshold", \
0, \
4294967295UL, \
40, \
CFG_VALUE_OR_DEFAULT, \
"Tx/Rx Packet threshold for initiating TDLS")
/*
* <ini>
* gTDLSMaxDiscoveryAttempt - Attempts for sending TDLS discovery requests.
* @Min: 1
* @Max: 100
* @Default: 5
*
* This ini is used to configure the number of failures of discover request,
* when exceeded, the peer is assumed to be not TDLS capable and no further
* TDLS Discovery request is made.
*
* Related: gEnableTDLSSupport.
*
* Supported Feature: TDLS
*
* Usage: Internal/External
*
* </ini>
*/
#define CFG_TDLS_MAX_DISCOVERY_ATTEMPT CFG_INI_UINT( \
"gTDLSMaxDiscoveryAttempt", \
1, \
100, \
5, \
CFG_VALUE_OR_DEFAULT, \
"Attempts for sending TDLS discovery requests")
/*
* <ini>
* gTDLSIdleTimeout - Duration within which number of TX / RX frames meet the
* criteria for TDLS teardown.
* @Min: 500
* @Max: 40000
* @Default: 5000
*
* This ini is used to configure the time period (in ms) to evaluate whether
* the number of Tx/Rx packets exceeds gTDLSIdlePacketThreshold and thus meets
* criteria for TDLS teardown.
* Teardown notification interval (gTDLSIdleTimeout) should be multiple of
* setup notification (gTDLSTxStatsPeriod) interval.
* e.g.
* if setup notification (gTDLSTxStatsPeriod) interval = 500, then
* teardown notification (gTDLSIdleTimeout) interval should be 1000,
* 1500, 2000, 2500...
*
* Related: gEnableTDLSSupport.
*
* Supported Feature: TDLS
*
* Usage: Internal/External
*
*/
#define CFG_TDLS_IDLE_TIMEOUT CFG_INI_UINT( \
"gTDLSIdleTimeout", \
500, \
40000, \
5000, \
CFG_VALUE_OR_DEFAULT, \
"this is idle time period")
/*
* <ini>
* gTDLSIdlePacketThreshold - Number of idle packet.
* @Min: 0
* @Max: 40000
* @Default: 3
*
* This ini is used to configure the number of Tx/Rx packet, below which
* within last gTDLSTxStatsPeriod period is considered as idle condition.
*
* Related: gEnableTDLSSupport.
*
* Supported Feature: TDLS
*
* Usage: Internal/External
*
* </ini>
*/
#define CFG_TDLS_IDLE_PACKET_THRESHOLD CFG_INI_UINT( \
"gTDLSIdlePacketThreshold", \
0, \
40000, \
3, \
CFG_VALUE_OR_DEFAULT, \
"Number of idle packet")
/*
* <ini>
* gTDLSRSSITriggerThreshold - RSSI threshold for TDLS connection.
* @Min: -120
* @Max: 0
* @Default: -75
*
* This ini is used to configure the absolute value (in dB) of the peer RSSI,
* below which a TDLS setup request is triggered.
*
* Related: gEnableTDLSSupport.
*
* Supported Feature: TDLS
*
* Usage: Internal/External
*
* </ini>
*/
#define CFG_TDLS_RSSI_TRIGGER_THRESHOLD CFG_INI_INT( \
"gTDLSRSSITriggerThreshold", \
-120, \
0, \
-75, \
CFG_VALUE_OR_DEFAULT, \
"RSSI threshold for TDLS connection")
/*
* <ini>
* gTDLSRSSITeardownThreshold - RSSI threshold for TDLS teardown.
* @Min: -120
* @Max: 0
* @Default: -75
*
* This ini is used to configure the absolute value (in dB) of the peer RSSI,
* when exceed, a TDLS teardown is triggered.
*
* Related: gEnableTDLSSupport.
*
* Supported Feature: TDLS
*
* Usage: Internal/External
*
* </ini>
*/
#define CFG_TDLS_RSSI_TEARDOWN_THRESHOLD CFG_INI_INT( \
"gTDLSRSSITeardownThreshold", \
-120, \
0, \
-75, \
CFG_VALUE_OR_DEFAULT, \
"RSSI threshold for TDLS teardown")
/*
* <ini>
* gTDLSRSSITeardownThreshold - RSSI threshold for TDLS teardown.
* @Min: -120
* @Max: 0
* @Default: -75
*
* This ini is used to configure the absolute value (in dB) of the peer RSSI,
* when exceed, a TDLS teardown is triggered.
*
* Related: gEnableTDLSSupport.
*
* Supported Feature: TDLS
*
* Usage: Internal/External
*
* </ini>
*/
#define CFG_TDLS_RSSI_DELTA CFG_INI_INT( \
"gTDLSRSSIDelta", \
-30, \
0, \
-20, \
CFG_VALUE_OR_DEFAULT, \
"Delta value for the peer RSSI that can trigger teardown")
/*
* <ini>
* gTDLSPrefOffChanNum - Preferred TDLS channel number when off-channel support
* is enabled.
* @Min: 1
* @Max: 165
* @Default: 36
*
* This ini is used to configure preferred TDLS channel number when off-channel
* support is enabled.
*
* Related: gEnableTDLSSupport, gEnableTDLSOffChannel.
*
* Supported Feature: TDLS
*
* Usage: Internal/External
*
* </ini>
*/
#define CFG_TDLS_PREFERRED_OFF_CHANNEL_NUM CFG_INI_UINT( \
"gTDLSPrefOffChanNum", \
1, \
165, \
36, \
CFG_VALUE_OR_DEFAULT, \
"Preferred TDLS channel number")
/*
* <ini>
* gTDLSPrefOffChanBandwidth - Preferred TDLS channel bandwidth when
* off-channel support is enabled.
* @Min: 0x01
* @Max: 0x0F
* @Default: 0x07
*
* This ini is used to configure preferred TDLS channel bandwidth when
* off-channel support is enabled.
* 0x1: 20 MHz 0x2: 40 MHz 0x4: 80 MHz 0x8: 160 MHz
* When more than one bits are set then firmware starts from the highest and
* selects one based on capability of peer.
*
* Related: gEnableTDLSSupport, gEnableTDLSOffChannel.
*
* Supported Feature: TDLS
*
* Usage: Internal/External
*
* </ini>
*/
#define CFG_TDLS_PREFERRED_OFF_CHANNEL_BW CFG_INI_UINT( \
"gTDLSPrefOffChanBandwidth", \
1, \
15, \
7, \
CFG_VALUE_OR_DEFAULT, \
"Preferred TDLS channel bandwidth")
/*
* <ini>
* gTDLSPuapsdInactivityTime - Peer UAPSD Inactivity time.
* @Min: 0
* @Max: 10
* @Default: 0
*
* This ini is used to configure peer uapsd inactivity time.
*
* Related: gEnableTDLSSupport.
*
* Supported Feature: TDLS
*
* Usage: Internal/External
*
* </ini>
*/
#define CFG_TDLS_PUAPSD_INACTIVITY_TIME CFG_INI_UINT( \
"gTDLSPuapsdInactivityTime", \
0, \
10, \
0, \
CFG_VALUE_OR_DEFAULT, \
"Peer UAPSD Inactivity time")
/*
* <ini>
* gTDLSPuapsdInactivityTime - Peer UAPSD Inactivity time.
* @Min: 0
* @Max: 10
* @Default: 0
*
* This ini is used to configure peer uapsd inactivity time.
*
* Related: gEnableTDLSSupport.
*
* Supported Feature: TDLS
*
* Usage: Internal/External
*
* </ini>
*/
#define CFG_TDLS_PUAPSD_RX_FRAME_THRESHOLD CFG_INI_UINT( \
"gTDLSPuapsdRxFrameThreshold", \
10, \
20, \
10, \
CFG_VALUE_OR_DEFAULT, \
"Peer UAPSD Rx frame threshold")
/*
* <ini>
* gTDLSPuapsdPTIWindow - This ini is used to configure peer traffic indication
* window.
* @Min: 1
* @Max: 5
* @Default: 2
*
* This ini is used to configure buffering time in number of beacon intervals.
*
* Related: gEnableTDLSSupport.
*
* Supported Feature: TDLS
*
* Usage: Internal/External
*
* </ini>
*/
#define CFG_TDLS_PUAPSD_PEER_TRAFFIC_IND_WINDOW CFG_INI_UINT( \
"gTDLSPuapsdPTIWindow", \
1, \
5, \
2, \
CFG_VALUE_OR_DEFAULT, \
"This ini is used to configure peer traffic indication")
/*
* <ini>
* gTDLSPuapsdPTIWindow - This ini is used to configure peer traffic indication
* window.
* @Min: 1
* @Max: 5
* @Default: 2
*
* This ini is used to configure buffering time in number of beacon intervals.
*
* Related: gEnableTDLSSupport.
*
* Supported Feature: TDLS
*
* Usage: Internal/External
*
* </ini>
*/
#define CFG_TDLS_PUAPSD_PEER_TRAFFIC_RSP_TIMEOUT CFG_INI_UINT( \
"gTDLSPuapsdPTRTimeout", \
0, \
10000, \
5000, \
CFG_VALUE_OR_DEFAULT, \
"Peer Traffic Response timer duration in ms")
/*
* <ini>
* gTDLSPuapsdPTIWindow - This ini is used to configure peer traffic indication
* window.
* @Min: 1
* @Max: 5
* @Default: 2
*
* This ini is used to configure buffering time in number of beacon intervals.
*
* Related: gEnableTDLSSupport.
*
* Supported Feature: TDLS
*
* Usage: Internal/External
*
* </ini>
*/
#define CFG_TDLS_EXTERNAL_CONTROL CFG_INI_BOOL( \
"gTDLSExternalControl", \
1, \
"Enable external TDLS control")
/*
* <ini>
* gEnableTDLSWmmMode - Enables WMM support over TDLS link.
* @Min: 0
* @Max: 1
* @Default: 1
*
* This ini is used to enable/disable WMM support over TDLS link.
* This is required to be set to 1 for any TDLS and uAPSD functionality.
*
* Related: gEnableTDLSSupport.
*
* Supported Feature: TDLS
*
* Usage: Internal/External
*
* </ini>
*/
#define CFG_TDLS_WMM_MODE_ENABLE CFG_INI_BOOL( \
"gEnableTDLSWmmMode", \
1, \
"Enables WMM support over TDLS link")
/*
* <ini>
* gEnableTDLSScan - Allow scan and maintain TDLS link.
* @Min: 0
* @Max: 1
* @Default: 0
*
* This ini is used to enable/disable TDLS scan.
* 0: If peer is not buffer STA capable and device is not sleep STA
* capable, then teardown TDLS link when scan is initiated. If peer
* is buffer STA and we can be sleep STA then TDLS link is maintained
* during scan.
* 1: Maintain TDLS link and allow scan even if peer is not buffer STA
* capable and device is not sleep STA capable. There will be loss of
* Rx pkts since peer would not know when device moves away from tdls
* channel. Tx on TDLS link would stop when device moves away from tdls
* channel.
*
* Related: gEnableTDLSSupport.
*
* Supported Feature: TDLS
*
* Usage: Internal/External
*
* </ini>
*/
#define CFG_TDLS_SCAN_ENABLE CFG_INI_BOOL( \
"gEnableTDLSScan", \
0, \
"Allow scan and maintain TDLS link")
/*
* <ini>
* gTDLSPeerKickoutThreshold - TDLS peer kick out threshold to firmware.
* @Min: 10
* @Max: 5000
* @Default: 96
*
* This ini is used to configure TDLS peer kick out threshold to firmware.
* Firmware will use this value to determine, when to send TDLS
* peer kick out event to host.
* E.g.
* if peer kick out threshold is 10, then firmware will wait for 10
* consecutive packet failures and then send TDLS kick out
* notification to host driver
*
* Related: gEnableTDLSSupport.
*
* Supported Feature: TDLS
*
* Usage: Internal/External
*
* </ini>
*/
#define CFG_TDLS_PEER_KICKOUT_THRESHOLD CFG_INI_UINT( \
"gTDLSPeerKickoutThreshold", \
10, \
5000, \
96, \
CFG_VALUE_OR_DEFAULT, \
"TDLS peer kick out threshold to firmware")
/*
* <ini>
* gTDLSEnableDeferTime - Timer to defer for enabling TDLS on P2P listen.
* @Min: 500
* @Max: 6000
* @Default: 2000
*
* This ini is used to set the timer to defer for enabling TDLS on P2P
* listen (value in milliseconds).
*
* Related: gEnableTDLSSupport.
*
* Supported Feature: TDLS
*
* Usage: Internal/External
*
* </ini>
*/
#define CFG_TDLS_ENABLE_DEFER_TIMER CFG_INI_UINT( \
"gTDLSEnableDeferTime", \
500, \
6000, \
2000, \
CFG_VALUE_OR_DEFAULT, \
"Timer to defer for enabling TDLS on P2P listen")
/*
* <ini>
* DelayedTriggerFrmInt - delayed trigger frame interval.
* @Min: 500
* @Max: 6000
* @Default: 2000
*
* This ini is used to set the delayed trigger frame interval.
*
* Related: gEnableTDLSSupport.
*
* Supported Feature: TDLS
*
* Usage: Internal/External
*
* </ini>
*/
#define CFG_TDLS_DELAYED_TRGR_FRM_INT CFG_INI_UINT( \
"DelayedTriggerFrmInt", \
1, \
4294967295UL, \
3000, \
CFG_VALUE_OR_DEFAULT, \
"delayed trigger frame interval")
#define CFG_TDLS_ALL \
CFG(CFG_TDLS_QOS_WMM_UAPSD_MASK) \
CFG(CFG_TDLS_BUF_STA_ENABLED) \
CFG(CFG_TDLS_PUAPSD_INACT_TIME) \
CFG(CFG_TDLS_RX_FRAME_THRESHOLD) \
CFG(CFG_TDLS_OFF_CHANNEL_ENABLED) \
CFG(CFG_TDLS_SUPPORT_ENABLE) \
CFG(CFG_TDLS_IMPLICIT_TRIGGER) \
CFG(CFG_TDLS_TX_STATS_PERIOD) \
CFG(CFG_TDLS_TX_PACKET_THRESHOLD) \
CFG(CFG_TDLS_MAX_DISCOVERY_ATTEMPT) \
CFG(CFG_TDLS_IDLE_TIMEOUT) \
CFG(CFG_TDLS_IDLE_PACKET_THRESHOLD) \
CFG(CFG_TDLS_RSSI_TRIGGER_THRESHOLD) \
CFG(CFG_TDLS_RSSI_TEARDOWN_THRESHOLD) \
CFG(CFG_TDLS_RSSI_DELTA) \
CFG(CFG_TDLS_PREFERRED_OFF_CHANNEL_NUM) \
CFG(CFG_TDLS_PREFERRED_OFF_CHANNEL_BW) \
CFG(CFG_TDLS_PUAPSD_INACTIVITY_TIME) \
CFG(CFG_TDLS_PUAPSD_RX_FRAME_THRESHOLD) \
CFG(CFG_TDLS_PUAPSD_PEER_TRAFFIC_IND_WINDOW) \
CFG(CFG_TDLS_PUAPSD_PEER_TRAFFIC_RSP_TIMEOUT) \
CFG(CFG_TDLS_EXTERNAL_CONTROL) \
CFG(CFG_TDLS_WMM_MODE_ENABLE) \
CFG(CFG_TDLS_SCAN_ENABLE) \
CFG(CFG_TDLS_PEER_KICKOUT_THRESHOLD) \
CFG(CFG_TDLS_ENABLE_DEFER_TIMER) \
CFG(CFG_TDLS_DELAYED_TRGR_FRM_INT)
#endif

View file

@ -0,0 +1,217 @@
/*
* Copyright (c) 2018 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: Contains p2p configures interface definitions
*/
#ifndef _WLAN_TDLS_CFG_API_H_
#define _WLAN_TDLS_CFG_API_H_
#include <qdf_types.h>
struct wlan_objmgr_psoc;
/**
* cfg_tdls_get_support_enable() - get tdls support enable
* @psoc: pointer to psoc object
* @val: pointer to tdls support enable/disable
*
* This function gets tdls support enable
*/
QDF_STATUS
cfg_tdls_get_support_enable(struct wlan_objmgr_psoc *psoc,
bool *val);
/**
* cfg_tdls_set_support_enable() - set tdls support enable
* @psoc: pointer to psoc object
* @val: set tdls support enable/disable
*
* This function sets tdls support enable
*/
QDF_STATUS
cfg_tdls_set_support_enable(struct wlan_objmgr_psoc *psoc,
bool val);
/**
* cfg_tdls_get_external_control() - get tdls external control
* @psoc: pointer to psoc object
* @val: pointer to tdls external control enable/disable
*
* This function gets tdls external control
*/
QDF_STATUS
cfg_tdls_get_external_control(struct wlan_objmgr_psoc *psoc,
bool *val);
/**
* cfg_tdls_get_uapsd_mask() - get tdls uapsd mask
* @psoc: pointer to psoc object
* @val: pointer to tdls uapsd mask
*
* This function gets tdls uapsd mask
*/
QDF_STATUS
cfg_tdls_get_uapsd_mask(struct wlan_objmgr_psoc *psoc,
uint32_t *val);
/**
* cfg_tdls_get_buffer_sta_enable() - get tdls buffer sta enable
* @psoc: pointer to psoc object
* @val: pointer to tdls buffer sta enable
*
* This function gets tdls buffer sta enable
*/
QDF_STATUS
cfg_tdls_get_buffer_sta_enable(struct wlan_objmgr_psoc *psoc,
bool *val);
/**
* cfg_tdls_set_buffer_sta_enable() - set tdls buffer sta enable
* @psoc: pointer to psoc object
* @val: tdls buffer sta enable
*
* This function sets tdls buffer sta enable
*/
QDF_STATUS
cfg_tdls_set_buffer_sta_enable(struct wlan_objmgr_psoc *psoc,
bool val);
/**
* cfg_tdls_get_uapsd_inactivity_time() - get tdls uapsd inactivity time
* @psoc: pointer to psoc object
* @val: pointer to tdls uapsd inactivity time
*
* This function gets tdls uapsd inactivity time
*/
QDF_STATUS
cfg_tdls_get_uapsd_inactivity_time(struct wlan_objmgr_psoc *psoc,
uint32_t *val);
/**
* cfg_tdls_get_rx_pkt_threshold() - get tdls rx pkt threshold
* @psoc: pointer to psoc object
* @val: pointer to tdls tdls rx pkt threshold
*
* This function gets tdls rx pkt threshold
*/
QDF_STATUS
cfg_tdls_get_rx_pkt_threshold(struct wlan_objmgr_psoc *psoc,
uint32_t *val);
/**
* cfg_tdls_get_off_channel_enable() - get tdls off channel enable
* @psoc: pointer to psoc object
* @val: pointer to tdls off channel enable
*
* This function gets tdls off channel enable
*/
QDF_STATUS
cfg_tdls_get_off_channel_enable(struct wlan_objmgr_psoc *psoc,
bool *val);
/**
* cfg_tdls_set_off_channel_enable() - set tdls off channel enable
* @psoc: pointer to psoc object
* @val: tdls off channel enable
*
* This function sets tdls off channel enable
*/
QDF_STATUS
cfg_tdls_set_off_channel_enable(struct wlan_objmgr_psoc *psoc,
bool val);
/**
* cfg_tdls_get_wmm_mode_enable() - get tdls wmm mode enable
* @psoc: pointer to psoc object
* @val: pointer to tdls wmm mode enable
*
* This function gets tdls wmm mode enable
*/
QDF_STATUS
cfg_tdls_get_wmm_mode_enable(struct wlan_objmgr_psoc *psoc,
bool *val);
/**
* cfg_tdls_set_vdev_nss_2g() - set tdls vdev nss 2g
* @psoc: pointer to psoc object
* @val: tdls vdev nss 2g
*
* This function sets tdls vdev nss 2g
*/
QDF_STATUS
cfg_tdls_set_vdev_nss_2g(struct wlan_objmgr_psoc *psoc,
uint8_t val);
/**
* cfg_tdls_set_vdev_nss_5g() - set tdls vdev nss 5g
* @psoc: pointer to psoc object
* @val: tdls vdev nss 5g
*
* This function sets tdls vdev nss 5g
*/
QDF_STATUS
cfg_tdls_set_vdev_nss_5g(struct wlan_objmgr_psoc *psoc,
uint8_t val);
/**
* cfg_tdls_get_sleep_sta_enable() - get tdls sleep sta enable
* @psoc: pointer to psoc object
* @val: pointer to tdls sleep sta enable
*
* This function gets tdls sleep sta enable
*/
QDF_STATUS
cfg_tdls_get_sleep_sta_enable(struct wlan_objmgr_psoc *psoc,
bool *val);
/**
* cfg_tdls_set_sleep_sta_enable() - set tdls sleep sta enable
* @psoc: pointer to psoc object
* @val: tdls sleep sta enable
*
* This function sets tdls sleep sta enable
*/
QDF_STATUS
cfg_tdls_set_sleep_sta_enable(struct wlan_objmgr_psoc *psoc,
bool val);
/**
* cfg_tdls_get_scan_enable() - get tdls scan enable
* @psoc: pointer to psoc object
* @val: pointer to tdls scan enable
*
* This function gets tdls scan enable
*/
QDF_STATUS
cfg_tdls_get_scan_enable(struct wlan_objmgr_psoc *psoc,
bool *val);
/**
* cfg_tdls_set_scan_enable() - set tdls scan enable
* @psoc: pointer to psoc object
* @val: tdls scan enable
*
* This function sets tdls scan enable
*/
QDF_STATUS
cfg_tdls_set_scan_enable(struct wlan_objmgr_psoc *psoc,
bool val);
#endif /* _WLAN_TDLS_CFG_API_H_ */

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,173 @@
/*
* Copyright (c) 2018 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_tdls_tgt_api.h
*
* TDLS south bound interface declaration
*/
#ifndef _WLAN_TDLS_TGT_API_H_
#define _WLAN_TDLS_TGT_API_H_
#include <wlan_tdls_public_structs.h>
#include "../../core/src/wlan_tdls_main.h"
/**
* tgt_tdls_set_fw_state() - invoke lmac tdls update fw
* @psoc: soc object
* @tdls_param: update tdls state parameters
*
* Return: QDF_STATUS
*/
QDF_STATUS tgt_tdls_set_fw_state(struct wlan_objmgr_psoc *psoc,
struct tdls_info *tdls_param);
/**
* tgt_tdls_set_peer_state() - invoke lmac tdls update peer state
* @psoc: soc object
* @peer_param: update tdls peer parameters
*
* Return: QDF_STATUS
*/
QDF_STATUS tgt_tdls_set_peer_state(struct wlan_objmgr_psoc *psoc,
struct tdls_peer_update_state *peer_param);
/**
* tgt_tdls_set_offchan_mode() - invoke lmac tdls set off-channel mode
* @psoc: soc object
* @param: set tdls off channel parameters
*
* Return: QDF_STATUS
*/
QDF_STATUS tgt_tdls_set_offchan_mode(struct wlan_objmgr_psoc *psoc,
struct tdls_channel_switch_params *param);
/**
* tgt_tdls_set_uapsd()- invoke lamc tdls set uapsd function
* @psoc: soc object
* @params: uapsd parameters
*
* Return: QDF_STATUS
*/
QDF_STATUS tgt_tdls_set_uapsd(struct wlan_objmgr_psoc *psoc,
struct sta_uapsd_trig_params *params);
/**
* tgt_tdls_send_mgmt_rsp() - process tdls mgmt response
* @pmsg: sheduler msg
*
* Return: QDF_STATUS
*/
QDF_STATUS tgt_tdls_send_mgmt_rsp(struct scheduler_msg *pmsg);
/**
* tgt_tdls_send_mgmt_tx_completion() -process tx completion message
* @pmsg: sheduler msg
*
* Return: QDF_STATUS
*/
QDF_STATUS tgt_tdls_send_mgmt_tx_completion(struct scheduler_msg *pmsg);
/**
* tgt_tdls_del_peer_rsp() - handle TDLS del peer response
* @pmsg: sheduler msg
*
* Return: QDF_STATUS
*/
QDF_STATUS tgt_tdls_del_peer_rsp(struct scheduler_msg *pmsg);
/**
* tgt_tdls_add_peer_rsp() - handle TDLS add peer response
* @pmsg: sheduler msg
*
* Return: QDF_STATUS
*/
QDF_STATUS tgt_tdls_add_peer_rsp(struct scheduler_msg *pmsg);
/**
* tgt_tdls_register_ev_handler() - invoke lmac register tdls event handler
* @psoc: soc object
*
* Return: QDF_STATUS_SUCCESS for success or error code.
*/
QDF_STATUS tgt_tdls_register_ev_handler(struct wlan_objmgr_psoc *psoc);
/**
* tgt_tdls_unregister_ev_handler() - invoke lmac unregister tdls event handler
* @psoc: soc object
*
* Return: QDF_STATUS_SUCCESS for success or error code.
*/
QDF_STATUS tgt_tdls_unregister_ev_handler(struct wlan_objmgr_psoc *psoc);
/**
* tgt_tdls_event_handler() - The callback registered to WMI for tdls events
* @psoc: psoc object
* @info: tdls event info
*
* The callback is registered by tgt as tdls rx ops handler.
*
* Return: 0 for success or err code.
*/
QDF_STATUS
tgt_tdls_event_handler(struct wlan_objmgr_psoc *psoc,
struct tdls_event_info *info);
/**
* tgt_tdls_mgmt_frame_rx_cb() - callback for rx mgmt frame
* @psoc: soc context
* @peer: peer context
* @buf: rx buffer
* @mgmt_rx_params: mgmt rx parameters
* @frm_type: frame type
*
* This function gets called from mgmt tx/rx component when rx mgmt
* received.
*
* Return: QDF_STATUS_SUCCESS
*/
QDF_STATUS tgt_tdls_mgmt_frame_rx_cb(struct wlan_objmgr_psoc *psoc,
struct wlan_objmgr_peer *peer, qdf_nbuf_t buf,
struct mgmt_rx_event_params *mgmt_rx_params,
enum mgmt_frame_type frm_type);
/**
* tgt_tdls_peers_deleted_notification()- notification from legacy lim
* @psoc: soc object
* @session_id: session id
*
* This function called from legacy lim to notify tdls peer deletion
*
* Return: None
*/
void tgt_tdls_peers_deleted_notification(struct wlan_objmgr_psoc *psoc,
uint32_t session_id);
/**
* tgt_tdls_delete_all_peers_indication()- Indication to tdls component
* @psoc: soc object
* @session_id: session id
*
* This function called from legacy lim to tdls component to delete tdls peers.
*
* Return: None
*/
void tgt_tdls_delete_all_peers_indication(struct wlan_objmgr_psoc *psoc,
uint32_t session_id);
#endif

View file

@ -0,0 +1,254 @@
/*
* Copyright (c) 2017-2018 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_tdls_ucfg_api.h
*
* TDLS north bound interface declaration
*/
#if !defined(_WLAN_TDLS_UCFG_API_H_)
#define _WLAN_TDLS_UCFG_API_H_
#include <scheduler_api.h>
#include <wlan_tdls_public_structs.h>
#include <wlan_objmgr_cmn.h>
#include <wlan_objmgr_psoc_obj.h>
#include <wlan_objmgr_pdev_obj.h>
#include <wlan_objmgr_vdev_obj.h>
/**
* ucfg_tdls_init() - TDLS module initialization API
*
* Return: QDF_STATUS
*/
QDF_STATUS ucfg_tdls_init(void);
/**
* ucfg_tdls_deinit() - TDLS module deinitialization API
*
* Return: QDF_STATUS
*/
QDF_STATUS ucfg_tdls_deinit(void);
/**
* ucfg_tdls_psoc_open() - TDLS module psoc open API
* @psoc: psoc object
*
* Return: QDF_STATUS
*/
QDF_STATUS ucfg_tdls_psoc_open(struct wlan_objmgr_psoc *psoc);
/**
* ucfg_tdls_psoc_close() - TDLS module psoc close API
* @psoc: psoc object
*
* Return: QDF_STATUS
*/
QDF_STATUS ucfg_tdls_psoc_close(struct wlan_objmgr_psoc *psoc);
/**
* ucfg_tdls_psoc_start() - TDLS module start
* @psoc: psoc object
* @req: tdls start paramets
*
* Return: QDF_STATUS
*/
QDF_STATUS ucfg_tdls_update_config(struct wlan_objmgr_psoc *psoc,
struct tdls_start_params *req);
/**
* ucfg_tdls_psoc_enable() - TDLS module enable API
* @psoc: psoc object
*
* Return: QDF_STATUS
*/
QDF_STATUS ucfg_tdls_psoc_enable(struct wlan_objmgr_psoc *psoc);
/**
* ucfg_tdls_psoc_disable() - TDLS moudle disable API
* @psoc: psoc object
*
* Return: QDF_STATUS
*/
QDF_STATUS ucfg_tdls_psoc_disable(struct wlan_objmgr_psoc *psoc);
/**
* ucfg_tdls_add_peer() - handle TDLS add peer
* @vdev: vdev object
* @add_peer_req: add peer request parameters
*
* Return: QDF_STATUS
*/
QDF_STATUS ucfg_tdls_add_peer(struct wlan_objmgr_vdev *vdev,
struct tdls_add_peer_params *add_peer_req);
/**
* ucfg_tdls_update_peer() - handle TDLS update peer
* @vdev: vdev object
* @update_peer: update TDLS request parameters
*
* Return: QDF_STATUS
*/
QDF_STATUS ucfg_tdls_update_peer(struct wlan_objmgr_vdev *vdev,
struct tdls_update_peer_params *update_peer);
/**
* ucfg_tdls_oper() - handle TDLS oper functions
* @vdev: vdev object
* @macaddr: MAC address of TDLS peer
* @cmd: oper cmd
*
* Return: QDF_STATUS
*/
QDF_STATUS ucfg_tdls_oper(struct wlan_objmgr_vdev *vdev,
const uint8_t *macaddr, enum tdls_command_type cmd);
/**
* ucfg_tdls_get_all_peers() - get all tdls peers from the list
* @vdev: vdev object
* @buf: output buffer
* @buflen: length of written data
*
* Return: QDF_STATUS
*/
QDF_STATUS ucfg_tdls_get_all_peers(struct wlan_objmgr_vdev *vdev,
char *buf, int buflen);
/**
* ucfg_tdls_send_mgmt_frame() - send TDLS mgmt frame
* @mgmt_req: pointer to TDLS action frame request struct
*
* This will TDLS action frames to peer
*
* Return: QDF_STATUS
*/
QDF_STATUS ucfg_tdls_send_mgmt_frame(
struct tdls_action_frame_request *mgmt_req);
/**
* ucfg_tdls_responder() - set responder in TDLS peer
* @msg_req: responder msg
*
* Return: QDF_STATUS
*/
QDF_STATUS ucfg_tdls_responder(struct tdls_set_responder_req *msg_req);
/**
* ucfg_tdls_teardown_links() - teardown all TDLS links
* @vdev: vdev object manager
*
* Return: None
*/
QDF_STATUS ucfg_tdls_teardown_links(struct wlan_objmgr_vdev *vdev);
/**
* ucfg_tdls_notify_reset_adapter() - notify reset adapter
* @vdev: vdev object manager
*
* Return: QDF_STATUS
*/
QDF_STATUS ucfg_tdls_notify_reset_adapter(struct wlan_objmgr_vdev *vdev);
/**
* ucfg_tdls_notify_sta_connect() - notify sta connect
* @notify_info: sta notification info
*
* Return: QDF_STATUS
*/
QDF_STATUS ucfg_tdls_notify_sta_connect(
struct tdls_sta_notify_params *notify_info);
/**
* ucfg_tdls_notify_sta_disconnect() - notify sta disconnect
* @notify_info: sta notification info
*
* Return: QDF_STATUS
*/
QDF_STATUS ucfg_tdls_notify_sta_disconnect(
struct tdls_sta_notify_params *notify_info);
/**
* ucfg_tdls_set_operating_mode() - set operating mode
* @set_mode_params: set mode params
*
* Return: QDF_STATUS
*/
QDF_STATUS ucfg_tdls_set_operating_mode(
struct tdls_set_mode_params *set_mode_params);
/**
* ucfg_tdls_update_rx_pkt_cnt() - update rx pkt count
* @vdev: tdls vdev object
* @mac_addr: peer mac address
*
* Return: None
*/
void ucfg_tdls_update_rx_pkt_cnt(struct wlan_objmgr_vdev *vdev,
struct qdf_mac_addr *mac_addr);
/**
* ucfg_tdls_update_tx_pkt_cnt() - update tx pkt count
* @vdev: tdls vdev object
* @mac_addr: peer mac address
*
* Return: None
*/
void ucfg_tdls_update_tx_pkt_cnt(struct wlan_objmgr_vdev *vdev,
struct qdf_mac_addr *mac_addr);
/**
* ucfg_tdls_antenna_switch() - tdls antenna switch
* @vdev: tdls vdev object
* @mode: antenna mode
*
* Return: QDF_STATUS
*/
QDF_STATUS ucfg_tdls_antenna_switch(struct wlan_objmgr_vdev *vdev,
uint32_t mode);
/**
* ucfg_set_tdls_offchannel() - Handle TDLS set offchannel
* @vdev: vdev object
* @offchannel: updated offchannel
*
* Return: QDF_STATUS
*/
QDF_STATUS ucfg_set_tdls_offchannel(struct wlan_objmgr_vdev *vdev,
int offchannel);
/**
* ucfg_set_tdls_offchan_mode() - Handle TDLS set offchannel mode
* @vdev: vdev object
* @offchanmode: updated off-channel mode
*
* Return: QDF_STATUS
*/
QDF_STATUS ucfg_set_tdls_offchan_mode(struct wlan_objmgr_vdev *vdev,
int offchanmode);
/**
* ucfg_set_tdls_secoffchanneloffset() - Handle TDLS set offchannel offset
* @vdev: vdev object
* @offchanoffset: tdls off-channel offset
*
* Return: QDF_STATUS
*/
QDF_STATUS ucfg_set_tdls_secoffchanneloffset(struct wlan_objmgr_vdev *vdev,
int offchanoffset);
#endif

View file

@ -0,0 +1,324 @@
/*
* Copyright (c) 2018 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: This file contains TDLS configures interface definitions
*/
#include <wlan_objmgr_psoc_obj.h>
#include "wlan_tdls_cfg_api.h"
#include "../../core/src/wlan_tdls_main.h"
QDF_STATUS
cfg_tdls_get_support_enable(struct wlan_objmgr_psoc *psoc,
bool *val)
{
struct tdls_soc_priv_obj *soc_obj;
soc_obj = wlan_psoc_get_tdls_soc_obj(psoc);
if (!soc_obj) {
*val = false;
tdls_err("tdls soc null");
return QDF_STATUS_E_INVAL;
}
*val = soc_obj->tdls_configs.tdls_support_enable;
return QDF_STATUS_SUCCESS;
}
QDF_STATUS
cfg_tdls_set_support_enable(struct wlan_objmgr_psoc *psoc,
bool val)
{
struct tdls_soc_priv_obj *soc_obj;
soc_obj = wlan_psoc_get_tdls_soc_obj(psoc);
if (!soc_obj) {
tdls_err("tdls soc null");
return QDF_STATUS_E_INVAL;
}
soc_obj->tdls_configs.tdls_support_enable = val;
return QDF_STATUS_SUCCESS;
}
QDF_STATUS
cfg_tdls_get_external_control(struct wlan_objmgr_psoc *psoc,
bool *val)
{
struct tdls_soc_priv_obj *soc_obj;
soc_obj = wlan_psoc_get_tdls_soc_obj(psoc);
if (!soc_obj) {
*val = false;
tdls_err("tdls soc null");
return QDF_STATUS_E_INVAL;
}
*val = soc_obj->tdls_configs.tdls_external_control;
return QDF_STATUS_SUCCESS;
}
QDF_STATUS
cfg_tdls_get_uapsd_mask(struct wlan_objmgr_psoc *psoc,
uint32_t *val)
{
struct tdls_soc_priv_obj *soc_obj;
soc_obj = wlan_psoc_get_tdls_soc_obj(psoc);
if (!soc_obj) {
*val = 0;
tdls_err("tdls soc null");
return QDF_STATUS_E_INVAL;
}
*val = soc_obj->tdls_configs.tdls_uapsd_mask;
return QDF_STATUS_SUCCESS;
}
QDF_STATUS
cfg_tdls_get_buffer_sta_enable(struct wlan_objmgr_psoc *psoc,
bool *val)
{
struct tdls_soc_priv_obj *soc_obj;
soc_obj = wlan_psoc_get_tdls_soc_obj(psoc);
if (!soc_obj) {
*val = false;
tdls_err("tdls soc null");
return QDF_STATUS_E_INVAL;
}
*val = soc_obj->tdls_configs.tdls_buffer_sta_enable;
return QDF_STATUS_SUCCESS;
}
QDF_STATUS
cfg_tdls_set_buffer_sta_enable(struct wlan_objmgr_psoc *psoc,
bool val)
{
struct tdls_soc_priv_obj *soc_obj;
soc_obj = wlan_psoc_get_tdls_soc_obj(psoc);
if (!soc_obj) {
tdls_err("tdls soc null");
return QDF_STATUS_E_INVAL;
}
soc_obj->tdls_configs.tdls_buffer_sta_enable = val;
return QDF_STATUS_SUCCESS;
}
QDF_STATUS
cfg_tdls_get_uapsd_inactivity_time(struct wlan_objmgr_psoc *psoc,
uint32_t *val)
{
struct tdls_soc_priv_obj *soc_obj;
soc_obj = wlan_psoc_get_tdls_soc_obj(psoc);
if (!soc_obj) {
*val = 0;
tdls_err("tdls soc null");
return QDF_STATUS_E_INVAL;
}
*val = soc_obj->tdls_configs.tdls_uapsd_inactivity_time;
return QDF_STATUS_SUCCESS;
}
QDF_STATUS
cfg_tdls_get_rx_pkt_threshold(struct wlan_objmgr_psoc *psoc,
uint32_t *val)
{
struct tdls_soc_priv_obj *soc_obj;
soc_obj = wlan_psoc_get_tdls_soc_obj(psoc);
if (!soc_obj) {
*val = 0;
tdls_err("tdls soc null");
return QDF_STATUS_E_INVAL;
}
*val = soc_obj->tdls_configs.tdls_rx_pkt_threshold;
return QDF_STATUS_SUCCESS;
}
QDF_STATUS
cfg_tdls_get_off_channel_enable(struct wlan_objmgr_psoc *psoc,
bool *val)
{
struct tdls_soc_priv_obj *soc_obj;
soc_obj = wlan_psoc_get_tdls_soc_obj(psoc);
if (!soc_obj) {
*val = false;
tdls_err("tdls soc null");
return QDF_STATUS_E_INVAL;
}
*val = soc_obj->tdls_configs.tdls_off_chan_enable;
return QDF_STATUS_SUCCESS;
}
QDF_STATUS
cfg_tdls_set_off_channel_enable(struct wlan_objmgr_psoc *psoc,
bool val)
{
struct tdls_soc_priv_obj *soc_obj;
soc_obj = wlan_psoc_get_tdls_soc_obj(psoc);
if (!soc_obj) {
tdls_err("tdls soc null");
return QDF_STATUS_E_INVAL;
}
soc_obj->tdls_configs.tdls_off_chan_enable = val;
return QDF_STATUS_SUCCESS;
}
QDF_STATUS
cfg_tdls_get_wmm_mode_enable(struct wlan_objmgr_psoc *psoc,
bool *val)
{
struct tdls_soc_priv_obj *soc_obj;
soc_obj = wlan_psoc_get_tdls_soc_obj(psoc);
if (!soc_obj) {
*val = false;
tdls_err("tdls soc null");
return QDF_STATUS_E_INVAL;
}
*val = soc_obj->tdls_configs.tdls_wmm_mode_enable;
return QDF_STATUS_SUCCESS;
}
QDF_STATUS
cfg_tdls_set_vdev_nss_2g(struct wlan_objmgr_psoc *psoc,
uint8_t val)
{
struct tdls_soc_priv_obj *soc_obj;
soc_obj = wlan_psoc_get_tdls_soc_obj(psoc);
if (!soc_obj) {
tdls_err("tdls soc null");
return QDF_STATUS_E_INVAL;
}
soc_obj->tdls_configs.tdls_vdev_nss_2g = val;
return QDF_STATUS_SUCCESS;
}
QDF_STATUS
cfg_tdls_set_vdev_nss_5g(struct wlan_objmgr_psoc *psoc,
uint8_t val)
{
struct tdls_soc_priv_obj *soc_obj;
soc_obj = wlan_psoc_get_tdls_soc_obj(psoc);
if (!soc_obj) {
tdls_err("tdls soc null");
return QDF_STATUS_E_INVAL;
}
soc_obj->tdls_configs.tdls_vdev_nss_5g = val;
return QDF_STATUS_SUCCESS;
}
QDF_STATUS
cfg_tdls_get_sleep_sta_enable(struct wlan_objmgr_psoc *psoc,
bool *val)
{
struct tdls_soc_priv_obj *soc_obj;
soc_obj = wlan_psoc_get_tdls_soc_obj(psoc);
if (!soc_obj) {
*val = false;
tdls_err("tdls soc null");
return QDF_STATUS_E_INVAL;
}
*val = soc_obj->tdls_configs.tdls_sleep_sta_enable;
return QDF_STATUS_SUCCESS;
}
QDF_STATUS
cfg_tdls_set_sleep_sta_enable(struct wlan_objmgr_psoc *psoc,
bool val)
{
struct tdls_soc_priv_obj *soc_obj;
soc_obj = wlan_psoc_get_tdls_soc_obj(psoc);
if (!soc_obj) {
tdls_err("tdls soc null");
return QDF_STATUS_E_INVAL;
}
soc_obj->tdls_configs.tdls_sleep_sta_enable = val;
return QDF_STATUS_SUCCESS;
}
QDF_STATUS
cfg_tdls_get_scan_enable(struct wlan_objmgr_psoc *psoc,
bool *val)
{
struct tdls_soc_priv_obj *soc_obj;
soc_obj = wlan_psoc_get_tdls_soc_obj(psoc);
if (!soc_obj) {
*val = false;
tdls_err("tdls soc null");
return QDF_STATUS_E_INVAL;
}
*val = soc_obj->tdls_configs.tdls_scan_enable;
return QDF_STATUS_SUCCESS;
}
QDF_STATUS
cfg_tdls_set_scan_enable(struct wlan_objmgr_psoc *psoc,
bool val)
{
struct tdls_soc_priv_obj *soc_obj;
soc_obj = wlan_psoc_get_tdls_soc_obj(psoc);
if (!soc_obj) {
tdls_err("tdls soc null");
return QDF_STATUS_E_INVAL;
}
soc_obj->tdls_configs.tdls_scan_enable = val;
return QDF_STATUS_SUCCESS;
}

View file

@ -0,0 +1,383 @@
/*
* Copyright (c) 2017-2018 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_tdls_tgt_api.c
*
* TDLS south bound interface definitions
*/
#include "qdf_status.h"
#include <wlan_tdls_tgt_api.h>
#include "../../core/src/wlan_tdls_main.h"
#include "../../core/src/wlan_tdls_cmds_process.h"
#include "../../core/src/wlan_tdls_mgmt.h"
static inline struct wlan_lmac_if_tdls_tx_ops *
wlan_psoc_get_tdls_txops(struct wlan_objmgr_psoc *psoc)
{
return &psoc->soc_cb.tx_ops.tdls_tx_ops;
}
static inline struct wlan_lmac_if_tdls_rx_ops *
wlan_psoc_get_tdls_rxops(struct wlan_objmgr_psoc *psoc)
{
return &psoc->soc_cb.rx_ops.tdls_rx_ops;
}
QDF_STATUS tgt_tdls_set_fw_state(struct wlan_objmgr_psoc *psoc,
struct tdls_info *tdls_param)
{
struct wlan_lmac_if_tdls_tx_ops *tdls_ops = NULL;
tdls_ops = wlan_psoc_get_tdls_txops(psoc);
if (tdls_ops && tdls_ops->update_fw_state)
return tdls_ops->update_fw_state(psoc, tdls_param);
else
return QDF_STATUS_SUCCESS;
}
QDF_STATUS tgt_tdls_set_peer_state(struct wlan_objmgr_psoc *psoc,
struct tdls_peer_update_state *peer_param)
{
struct wlan_lmac_if_tdls_tx_ops *tdls_ops = NULL;
tdls_ops = wlan_psoc_get_tdls_txops(psoc);
if (tdls_ops && tdls_ops->update_peer_state)
return tdls_ops->update_peer_state(psoc, peer_param);
else
return QDF_STATUS_SUCCESS;
}
QDF_STATUS tgt_tdls_set_offchan_mode(struct wlan_objmgr_psoc *psoc,
struct tdls_channel_switch_params *param)
{
struct wlan_lmac_if_tdls_tx_ops *tdls_ops = NULL;
tdls_ops = wlan_psoc_get_tdls_txops(psoc);
if (tdls_ops && tdls_ops->set_offchan_mode)
return tdls_ops->set_offchan_mode(psoc, param);
else
return QDF_STATUS_SUCCESS;
}
QDF_STATUS tgt_tdls_set_uapsd(struct wlan_objmgr_psoc *psoc,
struct sta_uapsd_trig_params *params)
{
struct wlan_lmac_if_tdls_tx_ops *tdls_ops = NULL;
tdls_ops = wlan_psoc_get_tdls_txops(psoc);
if (tdls_ops && tdls_ops->tdls_set_uapsd)
return tdls_ops->tdls_set_uapsd(psoc, params);
else
return QDF_STATUS_SUCCESS;
}
QDF_STATUS tgt_tdls_send_mgmt_tx_completion(struct scheduler_msg *pmsg)
{
QDF_STATUS status = QDF_STATUS_SUCCESS;
if (!pmsg || !pmsg->bodyptr) {
tdls_err("msg: 0x%pK", pmsg);
QDF_ASSERT(0);
return QDF_STATUS_E_NULL_VALUE;
}
status = tdls_send_mgmt_tx_completion(pmsg->bodyptr);
return status;
}
QDF_STATUS tgt_tdls_send_mgmt_rsp(struct scheduler_msg *pmsg)
{
QDF_STATUS status = QDF_STATUS_SUCCESS;
if (!pmsg || !pmsg->bodyptr) {
tdls_err("msg: 0x%pK", pmsg);
QDF_ASSERT(0);
return QDF_STATUS_E_NULL_VALUE;
}
status = tdls_process_send_mgmt_rsp(pmsg->bodyptr);
return status;
}
QDF_STATUS tgt_tdls_add_peer_rsp(struct scheduler_msg *pmsg)
{
QDF_STATUS status = QDF_STATUS_SUCCESS;
if (!pmsg || !pmsg->bodyptr) {
tdls_err("msg: 0x%pK", pmsg);
QDF_ASSERT(0);
return QDF_STATUS_E_NULL_VALUE;
}
status = tdls_process_add_peer_rsp(pmsg->bodyptr);
return status;
}
QDF_STATUS tgt_tdls_del_peer_rsp(struct scheduler_msg *pmsg)
{
QDF_STATUS status = QDF_STATUS_SUCCESS;
if (!pmsg || !pmsg->bodyptr) {
tdls_err("msg: 0x%pK", pmsg);
QDF_ASSERT(0);
return QDF_STATUS_E_NULL_VALUE;
}
status = tdls_process_del_peer_rsp(pmsg->bodyptr);
return status;
}
QDF_STATUS tgt_tdls_register_ev_handler(struct wlan_objmgr_psoc *psoc)
{
struct wlan_lmac_if_tdls_tx_ops *tdls_ops = NULL;
tdls_ops = wlan_psoc_get_tdls_txops(psoc);
if (tdls_ops && tdls_ops->tdls_reg_ev_handler)
return tdls_ops->tdls_reg_ev_handler(psoc, NULL);
else
return QDF_STATUS_SUCCESS;
}
QDF_STATUS tgt_tdls_unregister_ev_handler(struct wlan_objmgr_psoc *psoc)
{
struct wlan_lmac_if_tdls_tx_ops *tdls_ops = NULL;
tdls_ops = wlan_psoc_get_tdls_txops(psoc);
if (tdls_ops->tdls_unreg_ev_handler)
return tdls_ops->tdls_unreg_ev_handler(psoc, NULL);
else
return QDF_STATUS_SUCCESS;
}
static QDF_STATUS tgt_tdls_event_flush_cb(struct scheduler_msg *msg)
{
struct tdls_event_notify *notify;
notify = msg->bodyptr;
if (notify && notify->vdev) {
wlan_objmgr_vdev_release_ref(notify->vdev, WLAN_TDLS_SB_ID);
qdf_mem_free(notify);
}
return QDF_STATUS_SUCCESS;
}
QDF_STATUS
tgt_tdls_event_handler(struct wlan_objmgr_psoc *psoc,
struct tdls_event_info *info)
{
struct scheduler_msg msg = {0,};
struct tdls_event_notify *notify;
uint8_t vdev_id;
QDF_STATUS status;
if (!psoc || !info) {
tdls_err("psoc: 0x%pK, info: 0x%pK", psoc, info);
return QDF_STATUS_E_NULL_VALUE;
}
tdls_debug("vdev: %d, type: %d, reason: %d" QDF_MAC_ADDR_STR,
info->vdev_id, info->message_type, info->peer_reason,
QDF_MAC_ADDR_ARRAY(info->peermac.bytes));
notify = qdf_mem_malloc(sizeof(*notify));
if (!notify) {
tdls_err("mem allocate fail");
return QDF_STATUS_E_NOMEM;
}
vdev_id = info->vdev_id;
notify->vdev =
wlan_objmgr_get_vdev_by_id_from_psoc(psoc,
vdev_id, WLAN_TDLS_SB_ID);
if (!notify->vdev) {
tdls_err("null vdev, vdev_id: %d, psoc: 0x%pK", vdev_id, psoc);
return QDF_STATUS_E_INVAL;
}
qdf_mem_copy(&notify->event, info, sizeof(*info));
msg.bodyptr = notify;
msg.callback = tdls_process_evt;
msg.flush_callback = tgt_tdls_event_flush_cb;
status = scheduler_post_message(QDF_MODULE_ID_TDLS,
QDF_MODULE_ID_TDLS,
QDF_MODULE_ID_TARGET_IF, &msg);
if (QDF_IS_STATUS_ERROR(status)) {
tdls_err("can't post msg to handle tdls event");
wlan_objmgr_vdev_release_ref(notify->vdev, WLAN_TDLS_SB_ID);
qdf_mem_free(notify);
}
return status;
}
static QDF_STATUS tgt_tdls_mgmt_frame_rx_flush_cb(struct scheduler_msg *msg)
{
struct tdls_rx_mgmt_event *rx_mgmt_event;
rx_mgmt_event = msg->bodyptr;
if (rx_mgmt_event) {
if (rx_mgmt_event->rx_mgmt)
qdf_mem_free(rx_mgmt_event->rx_mgmt);
qdf_mem_free(rx_mgmt_event);
}
msg->bodyptr = NULL;
return QDF_STATUS_SUCCESS;
}
static
QDF_STATUS tgt_tdls_mgmt_frame_process_rx_cb(
struct wlan_objmgr_psoc *psoc,
struct wlan_objmgr_peer *peer,
qdf_nbuf_t buf,
struct mgmt_rx_event_params *mgmt_rx_params,
enum mgmt_frame_type frm_type)
{
struct tdls_rx_mgmt_frame *rx_mgmt;
struct tdls_rx_mgmt_event *rx_mgmt_event;
struct tdls_soc_priv_obj *tdls_soc_obj;
struct scheduler_msg msg = {0};
struct wlan_objmgr_vdev *vdev;
uint32_t vdev_id;
uint8_t *pdata;
QDF_STATUS status;
tdls_soc_obj = wlan_objmgr_psoc_get_comp_private_obj(psoc,
WLAN_UMAC_COMP_TDLS);
if (!tdls_soc_obj) {
tdls_err("tdls ctx is NULL, drop this frame");
return QDF_STATUS_E_FAILURE;
}
if (!peer) {
vdev = tdls_get_vdev(psoc, WLAN_TDLS_SB_ID);
if (!vdev) {
tdls_err("current tdls vdev is null, can't get vdev id");
return QDF_STATUS_E_FAILURE;
}
vdev_id = wlan_vdev_get_id(vdev);
wlan_objmgr_vdev_release_ref(vdev, WLAN_TDLS_SB_ID);
} else {
vdev = wlan_peer_get_vdev(peer);
if (!vdev) {
tdls_err("vdev is NULL in peer, drop this frame");
return QDF_STATUS_E_FAILURE;
}
vdev_id = wlan_vdev_get_id(vdev);
}
rx_mgmt_event = qdf_mem_malloc(sizeof(*rx_mgmt_event));
if (!rx_mgmt_event) {
tdls_err("Failed to allocate rx mgmt event");
return QDF_STATUS_E_NOMEM;
}
rx_mgmt = qdf_mem_malloc(sizeof(*rx_mgmt) +
mgmt_rx_params->buf_len);
if (!rx_mgmt) {
tdls_err("Failed to allocate rx mgmt frame");
qdf_mem_free(rx_mgmt_event);
return QDF_STATUS_E_NOMEM;
}
pdata = (uint8_t *)qdf_nbuf_data(buf);
rx_mgmt->frame_len = mgmt_rx_params->buf_len;
rx_mgmt->rx_chan = mgmt_rx_params->channel;
rx_mgmt->vdev_id = vdev_id;
rx_mgmt->frm_type = frm_type;
rx_mgmt->rx_rssi = mgmt_rx_params->rssi;
rx_mgmt_event->rx_mgmt = rx_mgmt;
rx_mgmt_event->tdls_soc_obj = tdls_soc_obj;
qdf_mem_copy(rx_mgmt->buf, pdata, mgmt_rx_params->buf_len);
msg.type = TDLS_EVENT_RX_MGMT;
msg.bodyptr = rx_mgmt_event;
msg.callback = tdls_process_rx_frame;
msg.flush_callback = tgt_tdls_mgmt_frame_rx_flush_cb;
status = scheduler_post_message(QDF_MODULE_ID_TDLS,
QDF_MODULE_ID_TDLS,
QDF_MODULE_ID_TARGET_IF, &msg);
if (QDF_IS_STATUS_ERROR(status)) {
qdf_mem_free(rx_mgmt);
qdf_mem_free(rx_mgmt_event);
}
qdf_nbuf_free(buf);
return status;
}
QDF_STATUS tgt_tdls_mgmt_frame_rx_cb(
struct wlan_objmgr_psoc *psoc,
struct wlan_objmgr_peer *peer,
qdf_nbuf_t buf,
struct mgmt_rx_event_params *mgmt_rx_params,
enum mgmt_frame_type frm_type)
{
QDF_STATUS status;
tdls_debug("psoc:%pK, peer:%pK, type:%d", psoc, peer, frm_type);
if (!buf) {
tdls_err("rx frame buff is null buf:%pK", buf);
return QDF_STATUS_E_INVAL;
}
if (!mgmt_rx_params || !psoc) {
tdls_err("input is NULL mgmt_rx_params:%pK psoc:%pK, peer:%pK",
mgmt_rx_params, psoc, peer);
status = QDF_STATUS_E_INVAL;
goto release_nbuf;
}
status = wlan_objmgr_peer_try_get_ref(peer, WLAN_TDLS_SB_ID);
if (QDF_STATUS_SUCCESS != status)
goto release_nbuf;
status = tgt_tdls_mgmt_frame_process_rx_cb(psoc, peer, buf,
mgmt_rx_params, frm_type);
wlan_objmgr_peer_release_ref(peer, WLAN_TDLS_SB_ID);
if (QDF_STATUS_SUCCESS != status)
release_nbuf:
qdf_nbuf_free(buf);
return status;
}
void tgt_tdls_peers_deleted_notification(struct wlan_objmgr_psoc *psoc,
uint32_t session_id)
{
tdls_peers_deleted_notification(psoc, session_id);
}
void tgt_tdls_delete_all_peers_indication(struct wlan_objmgr_psoc *psoc,
uint32_t session_id)
{
tdls_delete_all_peers_indication(psoc, session_id);
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,23 @@
/*
* Copyright (c) 2017 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_tdls_utils_api.c
*
* TDLS utility functions definitions
*/

View file

@ -63,7 +63,6 @@ enum active_apf_mode {
* @sta_maxlimod_dtim: station max listen interval
* @driver_type: Enumeration of Driver Type whether FTM or Mission mode
* currently rest of bits are not used
* @dfs_phyerr_filter_offload: DFS Phyerror Filtering offload status from ini
* Indicates whether support is enabled or not
* @ap_disable_intrabss_fwd: pass intra-bss-fwd info to txrx module
* @ap_maxoffload_peers: max offload peer
@ -110,7 +109,6 @@ struct cds_config_info {
uint16_t max_bssid;
uint8_t sta_maxlimod_dtim;
enum qdf_driver_type driver_type;
uint8_t dfs_phyerr_filter_offload;
uint8_t ap_maxoffload_peers;
uint8_t ap_maxoffload_reorderbuffs;
#ifdef FEATURE_WLAN_RA_FILTERING
@ -118,7 +116,6 @@ struct cds_config_info {
bool is_ra_ratelimit_enabled;
#endif
uint8_t reorder_offload;
int32_t dfs_pri_multiplier;
uint8_t uc_offload_enabled;
uint32_t uc_txbuf_count;
uint32_t uc_txbuf_size;

View file

@ -2201,70 +2201,6 @@ enum hdd_link_speed_rpt_type {
eHDD_LINK_SPEED_REPORT_MAX_SCALED = 2,
};
/*
* <ini>
* gDisableDFSChSwitch - Disable channel switch if radar is found
* @Min: 0
* @Max: 1
* @Default: 0
*
* This ini is used to disable channel switch if radar is found
* on that channel.
* Related: NA.
*
* Supported Feature: DFS
*
* Usage: Internal
*
* </ini>
*/
#define CFG_DISABLE_DFS_CH_SWITCH "gDisableDFSChSwitch"
#define CFG_DISABLE_DFS_CH_SWITCH_MIN (0)
#define CFG_DISABLE_DFS_CH_SWITCH_MAX (1)
#define CFG_DISABLE_DFS_CH_SWITCH_DEFAULT (0)
/*
* <ini>
* gDisableDfsJapanW53 - Block W53 channels in random channel selection
* @Min: 0
* @Max: 1
* @Default: 0
*
* This ini is used to block W53 Japan channel in random channel selection
* Related: NA.
*
* Supported Feature: DFS
*
* Usage: Internal/External
*
* </ini>
*/
#define CFG_DISABLE_DFS_JAPAN_W53 "gDisableDfsJapanW53"
#define CFG_DISABLE_DFS_JAPAN_W53_MIN (0)
#define CFG_DISABLE_DFS_JAPAN_W53_MAX (1)
#define CFG_DISABLE_DFS_JAPAN_W53_DEFAULT (0)
/*
* <ini>
* dfsPhyerrFilterOffload - DFS PHY error filter offload
* @Min: 0
* @Max: 1
* @Default: 0
*
* This ini is used to enable firmware to do DFS PHY error filtering.
* Related: NA.
*
* Supported Feature: DFS
*
* Usage: Internal/External
*
* </ini>
*/
#define CFG_ENABLE_DFS_PHYERR_FILTEROFFLOAD_NAME "dfsPhyerrFilterOffload"
#define CFG_ENABLE_DFS_PHYERR_FILTEROFFLOAD_MIN (0)
#define CFG_ENABLE_DFS_PHYERR_FILTEROFFLOAD_MAX (1)
#define CFG_ENABLE_DFS_PHYERR_FILTEROFFLOAD_DEFAULT (0)
/*
* <ini>
* gReportMaxLinkSpeed - Reporting of max link speed
@ -2936,34 +2872,6 @@ enum hdd_link_speed_rpt_type {
#endif /* MSM_PLATFORM */
/*
* <ini>
* gIgnoreCAC - Used to ignore CAC
* @Min: 0
* @Max: 1
* @Default: 0
*
* This ini is used to set default CAC
*
* Related: None
*
* Supported Feature: STA
*
* Usage: Internal/External
*
* </ini>
*/
#define CFG_IGNORE_CAC_NAME "gIgnoreCAC"
#define CFG_IGNORE_CAC_MIN (0)
#define CFG_IGNORE_CAC_MAX (1)
#define CFG_IGNORE_CAC_DEFAULT (0)
#define CFG_DFS_RADAR_PRI_MULTIPLIER_NAME "gDFSradarMappingPriMultiplier"
#define CFG_DFS_RADAR_PRI_MULTIPLIER_DEFAULT (4)
#define CFG_DFS_RADAR_PRI_MULTIPLIER_MIN (0)
#define CFG_DFS_RADAR_PRI_MULTIPLIER_MAX (10)
#define CFG_ENABLE_SAP_SUSPEND "gEnableSapSuspend"
#define CFG_ENABLE_SAP_SUSPEND_MIN (0)
#define CFG_ENABLE_SAP_SUSPEND_MAX (1)
@ -3101,11 +3009,6 @@ enum hdd_link_speed_rpt_type {
#define CFG_GO_11AC_OVERRIDE_MAX (1)
#define CFG_GO_11AC_OVERRIDE_DEFAULT (1)
#define CFG_ENABLE_NON_DFS_CHAN_ON_RADAR "gPreferNonDfsChanOnRadar"
#define CFG_ENABLE_NON_DFS_CHAN_ON_RADAR_MIN (0)
#define CFG_ENABLE_NON_DFS_CHAN_ON_RADAR_MAX (1)
#define CFG_ENABLE_NON_DFS_CHAN_ON_RADAR_DEFAULT (0)
/*
* set the self gen power value from
* 0 to 0xffff
@ -3115,34 +3018,6 @@ enum hdd_link_speed_rpt_type {
#define CFG_SELF_GEN_FRM_PWR_MAX (0xffff)
#define CFG_SELF_GEN_FRM_PWR_DEFAULT (0)
/*
* fine timing measurement capability information
*
* <----- fine_time_meas_cap (in bits) ----->
*+----------+-----+-----+------+------+-------+-------+-----+-----+
*| 8-31 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
*+----------+-----+-----+------+------+-------+-------+-----+-----+
*| reserved | SAP | SAP |P2P-GO|P2P-GO|P2P-CLI|P2P-CLI| STA | STA |
*| |resp |init |resp |init |resp |init |resp |init |
*+----------+-----+-----+------+------+-------+-------+-----+-----+
*
* resp - responder role; init- initiator role
*
* CFG_FINE_TIME_MEAS_CAPABILITY_MAX computed based on the table
* +-----------------+-----------------+-----------+
* | Device Role | Initiator | Responder |
* +-----------------+-----------------+-----------+
* | Station | Y | N |
* | P2P-CLI | Y | Y |
* | P2P-GO | Y | Y |
* | SAP | N | Y |
* +-----------------+-----------------+-----------+
*/
#define CFG_FINE_TIME_MEAS_CAPABILITY "gfine_time_meas_cap"
#define CFG_FINE_TIME_MEAS_CAPABILITY_MIN (0x0000)
#define CFG_FINE_TIME_MEAS_CAPABILITY_MAX (0x00BD)
#define CFG_FINE_TIME_MEAS_CAPABILITY_DEFAULT (0x000D)
/*
* <ini>
* etsi13_srd_chan_in_master_mode - Enable/disable ETSI SRD channels in
@ -3461,16 +3336,6 @@ enum hdd_link_speed_rpt_type {
#define CFG_MARK_INDOOR_AS_DISABLE_MAX (1)
#define CFG_MARK_INDOOR_AS_DISABLE_DEFAULT (0)
/*
* sap tx leakage threshold
* customer can set this value from 100 to 1000 which means
* sap tx leakage threshold is -10db to -100db
*/
#define CFG_SAP_TX_LEAKAGE_THRESHOLD_NAME "gsap_tx_leakage_threshold"
#define CFG_SAP_TX_LEAKAGE_THRESHOLD_MIN (100)
#define CFG_SAP_TX_LEAKAGE_THRESHOLD_MAX (1000)
#define CFG_SAP_TX_LEAKAGE_THRESHOLD_DEFAULT (310)
/*
* <ini>
* enable_5g_band_pref - Enable preference for 5G from INI.
@ -4231,26 +4096,6 @@ enum hdd_link_speed_rpt_type {
#define CFG_ENABLE_PACKET_FILTERS_MAX (63)
#endif /* WLAN_FEATURE_PACKET_FILTERING */
/*
* <ini>
* gDfsBeaconTxEnhanced - beacon tx enhanced
* @Min: 0
* @Max: 1
* @Default: 0
*
* This ini is used to enhance dfs beacon tx
*
* Related: none
*
* Usage: External
*
* </ini>
*/
#define CFG_DFS_BEACON_TX_ENHANCED "gDfsBeaconTxEnhanced"
#define CFG_DFS_BEACON_TX_ENHANCED_MIN (0)
#define CFG_DFS_BEACON_TX_ENHANCED_MAX (1)
#define CFG_DFS_BEACON_TX_ENHANCED_DEFAULT (0)
/*
* <ini>
* btm_offload_config - Configure BTM
@ -4561,29 +4406,6 @@ enum hdd_link_speed_rpt_type {
#define CFG_OFFLOAD_NEIGHBOR_REPORT_MAX_REQ_CAP_MAX (300)
#define CFG_OFFLOAD_NEIGHBOR_REPORT_MAX_REQ_CAP_DEFAULT (3)
/*
* <ini>
* wmi_wq_watchdog - Sets timeout period for wmi watchdog bite
* @Min: 0
* @Max: 30
* @Default: 20
*
* This ini is used to set timeout period for wmi watchdog bite. If it is
* 0 then wmi watchdog bite is disabled.
*
* Related: None
*
* Supported Feature: STA
*
* Usage: External
*
* </ini>
*/
#define CFG_WMI_WQ_WATCHDOG "wmi_wq_watchdog"
#define CFG_WMI_WQ_WATCHDOG_MIN (0)
#define CFG_WMI_WQ_WATCHDOG_MAX (30) /* 30s */
#define CFG_WMI_WQ_WATCHDOG_DEFAULT (20) /* 20s */
/*
* <ini>
* gEnableDTIMSelectionDiversity - Enable/Disable chain
@ -5241,8 +5063,6 @@ struct hdd_config {
uint32_t ibssPs1RxChainInAtimEnable;
uint32_t IpaConfig;
bool IpaClkScalingEnable;
uint8_t disableDFSChSwitch;
bool fDfsPhyerrFilterOffload;
uint8_t gDisableDfsJapanW53;
bool gEnableOverLapCh;
bool fRegChangeDefCountry;
@ -5250,12 +5070,8 @@ struct hdd_config {
uint8_t enableFwModuleLogLevel[FW_MODULE_LOG_LEVEL_STRING_LENGTH];
uint8_t ignoreCAC;
bool enable_sap_mandatory_chan_list;
int32_t dfsRadarPriMultiplier;
#ifdef FEATURE_WLAN_FORCE_SAP_SCC
uint8_t SapSccChanAvoidance;
#endif /* FEATURE_WLAN_FORCE_SAP_SCC */
@ -5273,9 +5089,6 @@ struct hdd_config {
#endif /* FEATURE_AP_MCC_CH_AVOIDANCE */
uint8_t sap_11ac_override;
uint8_t go_11ac_override;
uint8_t prefer_non_dfs_on_radar;
/* parameter for defer timer for enabling TDLS on p2p listen */
uint32_t fine_time_meas_cap;
uint8_t max_scan_count;
bool etsi13_srd_chan_in_master_mode;
uint32_t dual_mac_feature_disable;
@ -5367,7 +5180,6 @@ struct hdd_config {
#ifdef WLAN_FEATURE_PACKET_FILTERING
uint8_t packet_filters_bitmap;
#endif
uint8_t dfs_beacon_tx_enhanced;
uint32_t btm_offload_config;
#ifdef WLAN_FEATURE_SAE
bool is_sae_enabled;
@ -5388,7 +5200,6 @@ struct hdd_config {
uint32_t neighbor_report_offload_max_req_cap;
bool action_oui_enable;
uint8_t action_oui_str[ACTION_OUI_MAXIMUM_ID][ACTION_OUI_MAX_STR_LEN];
uint16_t wmi_wq_watchdog_timeout;
uint8_t enable_tx_sch_delay;
uint32_t enable_secondary_rate;
bool is_unit_test_framework_enabled;

View file

@ -48,14 +48,6 @@
#include "cfg_ucfg_api.h"
#include "hdd_dp_cfg.h"
static void ch_notify_set_g_disable_dfs_japan_w53(struct hdd_context *hdd_ctx,
unsigned long notify_id)
{
bool disabled = hdd_ctx->config->gDisableDfsJapanW53;
wlansap_set_dfs_restrict_japan_w53(hdd_ctx->mac_handle, disabled);
}
struct reg_table_entry g_registry_table[] = {
REG_VARIABLE(CFG_ENABLE_CONNECTED_SCAN_NAME, WLAN_PARAM_Integer,
struct hdd_config, enable_connected_scan,
@ -495,22 +487,6 @@ struct reg_table_entry g_registry_table[] = {
CFG_THROTTLE_DUTY_CYCLE_LEVEL3_MIN,
CFG_THROTTLE_DUTY_CYCLE_LEVEL3_MAX),
REG_VARIABLE(CFG_DISABLE_DFS_CH_SWITCH, WLAN_PARAM_Integer,
struct hdd_config, disableDFSChSwitch,
VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
CFG_DISABLE_DFS_CH_SWITCH_DEFAULT,
CFG_DISABLE_DFS_CH_SWITCH_MIN,
CFG_DISABLE_DFS_CH_SWITCH_MAX),
REG_DYNAMIC_VARIABLE(CFG_DISABLE_DFS_JAPAN_W53, WLAN_PARAM_Integer,
struct hdd_config, gDisableDfsJapanW53,
VAR_FLAGS_OPTIONAL |
VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
CFG_DISABLE_DFS_JAPAN_W53_DEFAULT,
CFG_DISABLE_DFS_JAPAN_W53_MIN,
CFG_DISABLE_DFS_JAPAN_W53_MAX,
ch_notify_set_g_disable_dfs_japan_w53, 0),
REG_VARIABLE(CFG_ENABLE_FIRST_SCAN_2G_ONLY_NAME, WLAN_PARAM_Integer,
struct hdd_config, enableFirstScan2GOnly,
VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
@ -640,14 +616,6 @@ struct reg_table_entry g_registry_table[] = {
CFG_IBSS_PS_1RX_CHAIN_IN_ATIM_WINDOW_MIN,
CFG_IBSS_PS_1RX_CHAIN_IN_ATIM_WINDOW_MAX),
REG_VARIABLE(CFG_ENABLE_DFS_PHYERR_FILTEROFFLOAD_NAME,
WLAN_PARAM_Integer,
struct hdd_config, fDfsPhyerrFilterOffload,
VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
CFG_ENABLE_DFS_PHYERR_FILTEROFFLOAD_DEFAULT,
CFG_ENABLE_DFS_PHYERR_FILTEROFFLOAD_MIN,
CFG_ENABLE_DFS_PHYERR_FILTEROFFLOAD_MAX),
REG_VARIABLE(CFG_ENABLE_OVERLAP_CH, WLAN_PARAM_Integer,
struct hdd_config, gEnableOverLapCh,
VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK,
@ -698,20 +666,6 @@ struct reg_table_entry g_registry_table[] = {
VAR_FLAGS_OPTIONAL,
(void *)CFG_ENABLE_FW_MODULE_LOG_DEFAULT),
REG_VARIABLE(CFG_IGNORE_CAC_NAME, WLAN_PARAM_Integer,
struct hdd_config, ignoreCAC,
VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
CFG_IGNORE_CAC_DEFAULT,
CFG_IGNORE_CAC_MIN,
CFG_IGNORE_CAC_MAX),
REG_VARIABLE(CFG_DFS_RADAR_PRI_MULTIPLIER_NAME, WLAN_PARAM_Integer,
struct hdd_config, dfsRadarPriMultiplier,
VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
CFG_DFS_RADAR_PRI_MULTIPLIER_DEFAULT,
CFG_DFS_RADAR_PRI_MULTIPLIER_MIN,
CFG_DFS_RADAR_PRI_MULTIPLIER_MAX),
REG_VARIABLE(CFG_ENABLE_SAP_SUSPEND, WLAN_PARAM_Integer,
struct hdd_config, enable_sap_suspend,
VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
@ -773,20 +727,6 @@ struct reg_table_entry g_registry_table[] = {
CFG_GO_11AC_OVERRIDE_MIN,
CFG_GO_11AC_OVERRIDE_MAX),
REG_VARIABLE(CFG_ENABLE_NON_DFS_CHAN_ON_RADAR, WLAN_PARAM_Integer,
struct hdd_config, prefer_non_dfs_on_radar,
VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
CFG_ENABLE_NON_DFS_CHAN_ON_RADAR_DEFAULT,
CFG_ENABLE_NON_DFS_CHAN_ON_RADAR_MIN,
CFG_ENABLE_NON_DFS_CHAN_ON_RADAR_MAX),
REG_VARIABLE(CFG_FINE_TIME_MEAS_CAPABILITY, WLAN_PARAM_HexInteger,
struct hdd_config, fine_time_meas_cap,
VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
CFG_FINE_TIME_MEAS_CAPABILITY_DEFAULT,
CFG_FINE_TIME_MEAS_CAPABILITY_MIN,
CFG_FINE_TIME_MEAS_CAPABILITY_MAX),
REG_VARIABLE(CFG_MAX_SCAN_COUNT_NAME, WLAN_PARAM_Integer,
struct hdd_config, max_scan_count,
VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
@ -996,14 +936,6 @@ struct reg_table_entry g_registry_table[] = {
CFG_MARK_INDOOR_AS_DISABLE_MIN,
CFG_MARK_INDOOR_AS_DISABLE_MAX),
REG_VARIABLE(CFG_SAP_TX_LEAKAGE_THRESHOLD_NAME,
WLAN_PARAM_Integer,
struct hdd_config, sap_tx_leakage_threshold,
VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
CFG_SAP_TX_LEAKAGE_THRESHOLD_DEFAULT,
CFG_SAP_TX_LEAKAGE_THRESHOLD_MIN,
CFG_SAP_TX_LEAKAGE_THRESHOLD_MAX),
REG_VARIABLE(CFG_RESTART_BEACONING_ON_CH_AVOID_NAME, WLAN_PARAM_Integer,
struct hdd_config, restart_beaconing_on_chan_avoid_event,
VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
@ -1223,14 +1155,6 @@ struct reg_table_entry g_registry_table[] = {
CFG_LATENCY_FLAGS_ULTRALOW_MIN,
CFG_LATENCY_FLAGS_ULTRALOW_MAX),
REG_VARIABLE(CFG_DFS_BEACON_TX_ENHANCED, WLAN_PARAM_Integer,
struct hdd_config, dfs_beacon_tx_enhanced,
VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
CFG_DFS_BEACON_TX_ENHANCED_DEFAULT,
CFG_DFS_BEACON_TX_ENHANCED_MIN,
CFG_DFS_BEACON_TX_ENHANCED_MAX),
REG_VARIABLE(CFG_BTM_ENABLE_NAME, WLAN_PARAM_HexInteger,
struct hdd_config, btm_offload_config,
VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
@ -1341,13 +1265,6 @@ struct reg_table_entry g_registry_table[] = {
CFG_OFFLOAD_NEIGHBOR_REPORT_MAX_REQ_CAP_MIN,
CFG_OFFLOAD_NEIGHBOR_REPORT_MAX_REQ_CAP_MAX),
REG_VARIABLE(CFG_WMI_WQ_WATCHDOG, WLAN_PARAM_Integer,
struct hdd_config, wmi_wq_watchdog_timeout,
VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
CFG_WMI_WQ_WATCHDOG_DEFAULT,
CFG_WMI_WQ_WATCHDOG_MIN,
CFG_WMI_WQ_WATCHDOG_MAX),
REG_VARIABLE(CFG_DTIM_SELECTION_DIVERSITY_NAME,
WLAN_PARAM_Integer,
struct hdd_config, enable_dtim_selection_diversity,
@ -2540,16 +2457,11 @@ QDF_STATUS hdd_set_idle_ps_config(struct hdd_context *hdd_ctx, bool val)
*/
static void hdd_set_fine_time_meas_cap(struct hdd_context *hdd_ctx)
{
struct hdd_config *config = hdd_ctx->config;
uint32_t capability = config->fine_time_meas_cap;
uint32_t capability = 0;
/* Make sure only supported capabilities are enabled in INI */
capability &= CFG_FINE_TIME_MEAS_CAPABILITY_MAX;
ucfg_mlme_get_fine_time_meas_cap(hdd_ctx->psoc, &capability);
ucfg_wifi_pos_set_ftm_cap(hdd_ctx->psoc, capability);
hdd_debug("fine time meas capability - INI: %04x Enabled: %04x",
config->fine_time_meas_cap,
capability);
hdd_debug("fine time meas capability - Enabled: %04x", capability);
}
/**
@ -3029,9 +2941,6 @@ QDF_STATUS hdd_set_sme_config(struct hdd_context *hdd_ctx)
hdd_ctx->config->sap_channel_avoidance;
#endif /* FEATURE_AP_MCC_CH_AVOIDANCE */
smeConfig->csrConfig.f_prefer_non_dfs_on_radar =
hdd_ctx->config->prefer_non_dfs_on_radar;
smeConfig->csrConfig.is_ps_enabled = hdd_ctx->config->is_ps_enabled;
smeConfig->csrConfig.auto_bmps_timer_val =
hdd_ctx->config->auto_bmps_timer_val;

View file

@ -5589,6 +5589,7 @@ __wlan_hdd_cfg80211_wifi_configuration_set(struct wiphy *wiphy,
uint16_t latency_level;
mac_handle_t mac_handle;
bool b_value;
uint32_t fine_time_meas_cap = 0;
struct wlan_objmgr_vdev *vdev;
uint8_t bmiss_first_bcnt;
uint8_t bmiss_final_bcnt;
@ -5616,16 +5617,26 @@ __wlan_hdd_cfg80211_wifi_configuration_set(struct wiphy *wiphy,
if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_FINE_TIME_MEASUREMENT]) {
ftm_capab = nla_get_u32(tb[
QCA_WLAN_VENDOR_ATTR_CONFIG_FINE_TIME_MEASUREMENT]);
hdd_ctx->config->fine_time_meas_cap =
fine_time_meas_cap =
hdd_ctx->fine_time_meas_cap_target & ftm_capab;
qdf_status =
ucfg_mlme_set_fine_time_meas_cap(hdd_ctx->psoc,
fine_time_meas_cap);
if (QDF_IS_STATUS_ERROR(qdf_status)) {
hdd_err("FTM capability: values 0x%x, 0x%x, 0x%x",
ftm_capab, hdd_ctx->fine_time_meas_cap_target,
fine_time_meas_cap);
return -EINVAL;
}
sme_update_fine_time_measurement_capab(mac_handle,
adapter->session_id,
hdd_ctx->config->fine_time_meas_cap);
ucfg_wifi_pos_set_ftm_cap(hdd_ctx->psoc,
hdd_ctx->config->fine_time_meas_cap);
adapter->session_id,
fine_time_meas_cap);
ucfg_wifi_pos_set_ftm_cap(hdd_ctx->psoc, fine_time_meas_cap);
hdd_debug("FTM capability: user value: 0x%x, target value: 0x%x, final value: 0x%x",
ftm_capab, hdd_ctx->fine_time_meas_cap_target,
hdd_ctx->config->fine_time_meas_cap);
ftm_capab, hdd_ctx->fine_time_meas_cap_target,
fine_time_meas_cap);
}
if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MODULATED_DTIM]) {

View file

@ -4628,10 +4628,11 @@ int wlan_hdd_cfg80211_start_bss(struct hdd_adapter *adapter,
uint16_t prev_rsn_length = 0;
enum dfs_mode mode;
struct hdd_adapter *sta_adapter;
uint8_t ignore_cac = 0;
bool ignore_cac = 0;
uint8_t beacon_fixed_len;
int value;
bool val;
uint32_t tx_leakage_threshold = 0;
uint32_t auto_channel_select_weight =
cfg_default(CFG_AUTO_CHANNEL_SELECT_WEIGHT);
uint8_t pref_chan_location = 0;
@ -4768,7 +4769,6 @@ int wlan_hdd_cfg80211_start_bss(struct hdd_adapter *adapter,
hdd_err("ucfg_mlme_get_auto_channel_weight failed, set def");
pConfig->auto_channel_select_weight = auto_channel_select_weight;
pConfig->disableDFSChSwitch = iniConfig->disableDFSChSwitch;
ucfg_mlme_get_sap_chn_switch_bcn_count(hdd_ctx->psoc, &value);
pConfig->sap_chanswitch_beacon_cnt = value;
ucfg_mlme_get_sap_channel_switch_mode(hdd_ctx->psoc, &val);
@ -4793,7 +4793,6 @@ int wlan_hdd_cfg80211_start_bss(struct hdd_adapter *adapter,
ucfg_mlme_get_sap_reduces_beacon_interval(hdd_ctx->psoc, &value);
pConfig->dtim_period = pBeacon->dtim_period;
pConfig->dfs_beacon_tx_enhanced = iniConfig->dfs_beacon_tx_enhanced;
pConfig->reduced_beacon_interval = value;
hdd_debug("acs_mode %d", pConfig->acs_cfg.acs_mode);
@ -4866,14 +4865,13 @@ int wlan_hdd_cfg80211_start_bss(struct hdd_adapter *adapter,
goto error;
}
if (iniConfig->ignoreCAC ||
ucfg_mlme_get_dfs_ignore_cac(hdd_ctx->psoc, &ignore_cac);
if (ignore_cac ||
((mcc_to_scc_switch != QDF_MCC_TO_SCC_SWITCH_DISABLE) &&
iniConfig->sta_sap_scc_on_dfs_chan))
ignore_cac = 1;
wlansap_set_dfs_ignore_cac(mac_handle, ignore_cac);
wlansap_set_dfs_restrict_japan_w53(mac_handle,
iniConfig->gDisableDfsJapanW53);
ucfg_mlme_get_pref_chan_location(hdd_ctx->psoc,
&pref_chan_location);
wlansap_set_dfs_preferred_channel_location(mac_handle,
@ -4890,8 +4888,9 @@ int wlan_hdd_cfg80211_start_bss(struct hdd_adapter *adapter,
pConfig->ieee80211d = 0;
}
wlansap_set_tx_leakage_threshold(mac_handle,
iniConfig->sap_tx_leakage_threshold);
ucfg_mlme_get_sap_tx_leakage_threshold(hdd_ctx->psoc,
&tx_leakage_threshold);
tgt_dfs_set_tx_leakage_threshold(hdd_ctx->pdev, tx_leakage_threshold);
capab_info = pMgmt_frame->u.beacon.capab_info;

View file

@ -1885,6 +1885,7 @@ void hdd_update_tgt_cfg(hdd_handle_t hdd_handle, struct wma_tgt_cfg *cfg)
mac_handle_t mac_handle;
bool bval = false;
uint8_t value = 0;
uint32_t fine_time_meas_cap = 0;
if (!hdd_ctx) {
hdd_err("HDD context is NULL");
@ -2051,10 +2052,19 @@ void hdd_update_tgt_cfg(hdd_handle_t hdd_handle, struct wma_tgt_cfg *cfg)
hdd_update_hw_dbs_capable(hdd_ctx);
hdd_ctx->dynamic_nss_chains_support =
cfg->dynamic_nss_chains_support;
hdd_ctx->config->fine_time_meas_cap &= cfg->fine_time_measurement_cap;
ucfg_mlme_get_fine_time_meas_cap(hdd_ctx->psoc, &fine_time_meas_cap);
fine_time_meas_cap &= cfg->fine_time_measurement_cap;
status = ucfg_mlme_set_fine_time_meas_cap(hdd_ctx->psoc,
fine_time_meas_cap);
if (QDF_IS_STATUS_ERROR(status)) {
hdd_err("failed to set fine_time_meas_cap, 0x%x, ox%x",
fine_time_meas_cap, cfg->fine_time_measurement_cap);
ucfg_mlme_get_fine_time_meas_cap(hdd_ctx->psoc,
&fine_time_meas_cap);
}
hdd_ctx->fine_time_meas_cap_target = cfg->fine_time_measurement_cap;
hdd_debug("fine_time_meas_cap: 0x%x",
hdd_ctx->config->fine_time_meas_cap);
hdd_debug("fine_time_meas_cap: 0x%x", fine_time_meas_cap);
status = ucfg_mlme_get_vht_enable2x2(hdd_ctx->psoc, &bval);
if (!QDF_IS_STATUS_SUCCESS(status))
@ -2126,15 +2136,18 @@ bool hdd_dfs_indicate_radar(struct hdd_context *hdd_ctx)
{
struct hdd_adapter *adapter;
struct hdd_ap_ctx *ap_ctx;
bool dfs_disable_channel_switch = false;
if (!hdd_ctx) {
hdd_info("Couldn't get hdd_ctx");
return true;
}
if (hdd_ctx->config->disableDFSChSwitch) {
ucfg_mlme_get_dfs_disable_channel_switch(hdd_ctx->psoc,
&dfs_disable_channel_switch);
if (dfs_disable_channel_switch) {
hdd_info("skip tx block hdd_ctx=%pK, disableDFSChSwitch=%d",
hdd_ctx, hdd_ctx->config->disableDFSChSwitch);
hdd_ctx, dfs_disable_channel_switch);
return true;
}
@ -9577,6 +9590,7 @@ int hdd_start_ap_adapter(struct hdd_adapter *adapter)
bool is_ssr = false;
int ret;
struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
uint32_t fine_time_meas_cap = 0;
hdd_enter();
@ -9606,12 +9620,14 @@ int hdd_start_ap_adapter(struct hdd_adapter *adapter)
return ret;
}
if (adapter->device_mode == QDF_SAP_MODE)
if (adapter->device_mode == QDF_SAP_MODE) {
ucfg_mlme_get_fine_time_meas_cap(hdd_ctx->psoc,
&fine_time_meas_cap);
sme_cli_set_command(adapter->session_id,
WMI_VDEV_PARAM_ENABLE_DISABLE_RTT_RESPONDER_ROLE,
(bool)(hdd_ctx->config->fine_time_meas_cap &
WMI_FW_AP_RTT_RESPR),
(bool)(fine_time_meas_cap & WMI_FW_AP_RTT_RESPR),
VDEV_CMD);
}
status = hdd_init_ap_mode(adapter, is_ssr);
@ -9712,14 +9728,6 @@ static int hdd_update_cds_config(struct hdd_context *hdd_ctx)
ucfg_mlme_get_sap_max_modulated_dtim(hdd_ctx->psoc,
&cds_cfg->sta_maxlimod_dtim);
/*
* Copy the DFS Phyerr Filtering Offload status.
* This parameter reflects the value of the
* dfs_phyerr_filter_offload flag as set in the ini.
*/
cds_cfg->dfs_phyerr_filter_offload =
hdd_ctx->config->fDfsPhyerrFilterOffload;
status = ucfg_mlme_get_crash_inject(hdd_ctx->psoc, &crash_inject);
if (QDF_IS_STATUS_ERROR(status)) {
hdd_err("Failed to get crash inject ini config");
@ -9754,8 +9762,6 @@ static int hdd_update_cds_config(struct hdd_context *hdd_ctx)
&value);
cds_cfg->ap_maxoffload_reorderbuffs = value;
cds_cfg->dfs_pri_multiplier =
hdd_ctx->config->dfsRadarPriMultiplier;
cds_cfg->reorder_offload =
cfg_get(hdd_ctx->psoc, CFG_DP_REORDER_OFFLOAD_SUPPORT);
@ -14229,11 +14235,11 @@ QDF_STATUS hdd_update_score_config(
static int hdd_update_dfs_config(struct hdd_context *hdd_ctx)
{
struct wlan_objmgr_psoc *psoc = hdd_ctx->psoc;
struct hdd_config *cfg = hdd_ctx->config;
struct dfs_user_config dfs_cfg;
QDF_STATUS status;
dfs_cfg.dfs_is_phyerr_filter_offload = !!cfg->fDfsPhyerrFilterOffload;
ucfg_mlme_get_dfs_filter_offload(hdd_ctx->psoc,
&dfs_cfg.dfs_is_phyerr_filter_offload);
status = ucfg_dfs_update_config(psoc, &dfs_cfg);
if (QDF_IS_STATUS_ERROR(status)) {
hdd_err("failed dfs psoc configuration");

View file

@ -834,7 +834,6 @@ struct mac_context {
uint8_t beacon_offload;
bool pmf_offload;
bool is_fils_roaming_supported;
uint8_t f_prefer_non_dfs_on_radar;
uint32_t f_sta_miracast_mcc_rest_time_val;
#ifdef WLAN_FEATURE_EXTWOW_SUPPORT
csr_readyToExtWoWCallback readyToExtWoWCallback;

View file

@ -32,9 +32,9 @@
#define QWLAN_VERSION_MAJOR 5
#define QWLAN_VERSION_MINOR 2
#define QWLAN_VERSION_PATCH 0
#define QWLAN_VERSION_EXTRA "T"
#define QWLAN_VERSION_EXTRA "U"
#define QWLAN_VERSION_BUILD 109
#define QWLAN_VERSIONSTR "5.2.0.109T"
#define QWLAN_VERSIONSTR "5.2.0.109U"
#endif /* QWLAN_VERSION_H */

View file

@ -7936,7 +7936,7 @@ void lim_process_ap_ecsa_timeout(void *data)
ch = session->gLimChannelSwitch.primaryChannel;
ch_width = session->gLimChannelSwitch.ch_width;
if (mac_ctx->sap.SapDfsInfo.dfs_beacon_tx_enhanced)
if (mac_ctx->mlme_cfg->dfs_cfg.dfs_beacon_tx_enhanced)
/* Send Action frame after updating beacon */
lim_send_chan_switch_action_frame(mac_ctx, ch, ch_width,
session);

View file

@ -587,7 +587,6 @@ typedef struct sap_config {
uint32_t ap_table_expiration_time;
uint32_t ht_op_mode_fixed;
enum QDF_OPMODE persona; /* Tells us which persona, GO or AP */
uint8_t disableDFSChSwitch;
bool enOverLapCh;
#ifdef WLAN_FEATURE_11W
bool mfpRequired;
@ -625,7 +624,6 @@ typedef struct sap_config {
uint8_t sap_chanswitch_beacon_cnt;
uint8_t sap_chanswitch_mode;
bool chan_switch_hostapd_rate_enabled;
bool dfs_beacon_tx_enhanced;
uint16_t reduced_beacon_interval;
} tsap_config_t;
@ -720,7 +718,6 @@ typedef struct sSapDfsInfo {
/* beacon count before channel switch */
uint8_t sap_ch_switch_beacon_cnt;
uint8_t sap_ch_switch_mode;
bool dfs_beacon_tx_enhanced;
uint16_t reduced_beacon_interval;
} tSapDfsInfo;
@ -1268,19 +1265,6 @@ QDF_STATUS wlansap_get_dfs_ignore_cac(mac_handle_t mac_handle,
QDF_STATUS wlansap_set_dfs_ignore_cac(mac_handle_t mac_handle,
uint8_t ignore_cac);
/**
* wlansap_set_dfs_restrict_japan_w53() - enable/disable dfS for japan
* @mac_handle: Opaque handle to the global MAC context
* @disable_dfs_w53: Indicates if Japan W53 is disabled when set to 1
* Indicates if Japan W53 is enabled when set to 0
*
* This API is used to enable or disable Japan W53 Band
* Return: The QDF_STATUS code associated with performing the operation
* QDF_STATUS_SUCCESS: Success
*/
QDF_STATUS wlansap_set_dfs_restrict_japan_w53(mac_handle_t mac_handle,
uint8_t disable_dfs_w53);
#ifdef FEATURE_AP_MCC_CH_AVOIDANCE
QDF_STATUS
wlan_sap_set_channel_avoidance(mac_handle_t mac_handle,
@ -1438,18 +1422,6 @@ QDF_STATUS wlansap_acs_chselect(struct sap_context *sap_context,
*/
uint32_t wlansap_get_chan_width(struct sap_context *sap_ctx);
/**
* wlansap_set_tx_leakage_threshold() - set sap tx leakage threshold.
* @mac_handle: Opaque handle to the global MAC context
* @tx_leakage_threshold: sap tx leakage threshold
*
* This function set sap tx leakage threshold.
*
* Return: QDF_STATUS.
*/
QDF_STATUS wlansap_set_tx_leakage_threshold(mac_handle_t mac_handle,
uint16_t tx_leakage_threshold);
/*
* wlansap_set_invalid_session() - set session ID to invalid
* @sap_ctx: pointer to the SAP context

View file

@ -419,7 +419,7 @@ wlansap_roam_process_dfs_chansw_update(mac_handle_t mac_handle,
uint8_t dfs_beacon_start_req = 0;
bool sap_scc_dfs;
if (sap_ctx->csr_roamProfile.disableDFSChSwitch) {
if (mac_ctx->mlme_cfg->dfs_cfg.dfs_disable_channel_switch) {
QDF_TRACE(QDF_MODULE_ID_SAP,
QDF_TRACE_LEVEL_ERROR,
FL("sapdfs: DFS channel switch disabled"));
@ -582,7 +582,7 @@ wlansap_roam_process_dfs_radar_found(tpAniSirGlobal mac_ctx,
tWLAN_SAPEvent sap_event;
if (sap_is_dfs_cac_wait_state(sap_ctx)) {
if (sap_ctx->csr_roamProfile.disableDFSChSwitch) {
if (mac_ctx->mlme_cfg->dfs_cfg.dfs_disable_channel_switch) {
QDF_TRACE(QDF_MODULE_ID_SAP,
QDF_TRACE_LEVEL_ERROR,
"sapdfs: DFS channel switch disabled");

View file

@ -193,7 +193,7 @@ static uint8_t sap_random_channel_sel(struct sap_context *sap_ctx)
uint8_t ch_wd;
struct wlan_objmgr_pdev *pdev = NULL;
struct ch_params *ch_params;
uint32_t hw_mode;
uint32_t hw_mode, flag = 0;
struct mac_context *mac_ctx;
struct dfs_acs_info acs_info = {0};
@ -226,8 +226,12 @@ static uint8_t sap_random_channel_sel(struct sap_context *sap_ctx)
} else {
acs_info.acs_mode = false;
}
if (mac_ctx->mlme_cfg->dfs_cfg.dfs_prefer_non_dfs)
flag |= DFS_RANDOM_CH_FLAG_NO_DFS_CH;
if (QDF_IS_STATUS_ERROR(utils_dfs_get_random_channel(
pdev, 0, ch_params, &hw_mode, &ch, &acs_info))) {
pdev, flag, ch_params, &hw_mode, &ch, &acs_info))) {
/* No available channel found */
QDF_TRACE(QDF_MODULE_ID_SAP, QDF_TRACE_LEVEL_ERROR,
FL("No available channel found!!!"));
@ -544,34 +548,12 @@ void sap_dfs_set_current_channel(void *ctx)
tgt_dfs_get_radars(pdev);
}
tgt_dfs_set_phyerr_filter_offload(pdev);
if (sap_ctx->csr_roamProfile.disableDFSChSwitch)
if (mac_ctx->mlme_cfg->dfs_cfg.dfs_disable_channel_switch)
tgt_dfs_control(pdev, DFS_SET_USENOL, &use_nol,
sizeof(uint32_t), NULL, NULL, &error);
}
}
bool sap_dfs_is_w53_invalid(mac_handle_t mac_handle, uint8_t channel_id)
{
tpAniSirGlobal mac;
mac = MAC_CONTEXT(mac_handle);
if (NULL == mac) {
QDF_TRACE(QDF_MODULE_ID_SAP, QDF_TRACE_LEVEL_ERROR,
FL("invalid mac"));
return false;
}
/*
* Check for JAPAN W53 Channel operation capability
*/
if (true == mac->sap.SapDfsInfo.is_dfs_w53_disabled &&
true == IS_CHAN_JAPAN_W53(channel_id)) {
return true;
}
return false;
}
bool sap_dfs_is_channel_in_preferred_location(mac_handle_t mac_handle,
uint8_t channel_id)
{
@ -2826,7 +2808,6 @@ sapconvert_to_csr_profile(tsap_config_t *pconfig_params, eCsrRoamBssType bssType
profile->BSSType = eCSR_BSS_TYPE_INFRA_AP;
profile->SSIDs.numOfSSIDs = 1;
profile->csrPersona = pconfig_params->persona;
profile->disableDFSChSwitch = pconfig_params->disableDFSChSwitch;
qdf_mem_zero(profile->SSIDs.SSIDList[0].SSID.ssId,
sizeof(profile->SSIDs.SSIDList[0].SSID.ssId));
@ -3462,7 +3443,7 @@ uint8_t sap_indicate_radar(struct sap_context *sap_ctx)
if (sap_ctx->fsm_state == SAP_STARTED)
mac->sap.SapDfsInfo.csaIERequired = true;
if (sap_ctx->csr_roamProfile.disableDFSChSwitch)
if (mac->mlme_cfg->dfs_cfg.dfs_disable_channel_switch)
return sap_ctx->channel;
/* set the Radar Found flag in SapDfsInfo */

View file

@ -387,21 +387,6 @@ bool sap_is_conc_sap_doing_scc_dfs(mac_handle_t mac_handle,
uint8_t sap_get_total_number_sap_intf(mac_handle_t mac_handle);
/**
* sap_dfs_is_w53_invalid() - Check to see if invalid W53 operation requested
* @mac_handle: Opaque handle to the global MAC context
* @channel_id: Channel number to be verified
*
* This function checks if the passed channel is W53 and, if so, if
* SAP W53 operation is allowed.
*
* Return:
* * true - operation is invalid because the channel is W53 and W53
* operation has been disabled
* * false - operation is valid
*/
bool sap_dfs_is_w53_invalid(mac_handle_t mac_handle, uint8_t channel_id);
/**
* sap_dfs_is_channel_in_preferred_location() - Verify a channel is valid
* with respect to indoor/outdoor location setting

View file

@ -721,8 +721,6 @@ QDF_STATUS wlansap_start_bss(struct sap_context *sap_ctx,
* Copy the DFS Test Mode setting to pmac for
* access in lower layers
*/
pmac->sap.SapDfsInfo.disable_dfs_ch_switch =
pConfig->disableDFSChSwitch;
pmac->sap.SapDfsInfo.sap_ch_switch_beacon_cnt =
pConfig->sap_chanswitch_beacon_cnt;
pmac->sap.SapDfsInfo.sap_ch_switch_mode =
@ -733,8 +731,6 @@ QDF_STATUS wlansap_start_bss(struct sap_context *sap_ctx,
sap_ctx->csr_roamProfile.csrPersona;
pmac->sap.sapCtxList[sap_ctx->sessionId].sessionID =
sap_ctx->sessionId;
pmac->sap.SapDfsInfo.dfs_beacon_tx_enhanced =
pConfig->dfs_beacon_tx_enhanced;
pmac->sap.SapDfsInfo.reduced_beacon_interval =
pConfig->reduced_beacon_interval;
@ -1857,47 +1853,6 @@ QDF_STATUS wlansap_set_dfs_ignore_cac(mac_handle_t mac_handle,
return QDF_STATUS_SUCCESS;
}
QDF_STATUS
wlansap_set_dfs_restrict_japan_w53(mac_handle_t mac_handle,
uint8_t disable_dfs_w53)
{
tpAniSirGlobal mac = NULL;
QDF_STATUS status;
enum dfs_reg dfs_region;
if (NULL != mac_handle) {
mac = MAC_CONTEXT(mac_handle);
} else {
QDF_TRACE(QDF_MODULE_ID_SAP, QDF_TRACE_LEVEL_ERROR,
"%s: Invalid mac_handle pointer", __func__);
return QDF_STATUS_E_FAULT;
}
wlan_reg_get_dfs_region(mac->pdev, &dfs_region);
/*
* Set the JAPAN W53 restriction only if the current
* regulatory domain is JAPAN.
*/
if (DFS_MKK_REGION == dfs_region) {
mac->sap.SapDfsInfo.is_dfs_w53_disabled = disable_dfs_w53;
QDF_TRACE(QDF_MODULE_ID_SAP,
QDF_TRACE_LEVEL_INFO_LOW,
FL("sapdfs: SET DFS JAPAN W53 DISABLED = %d"),
mac->sap.SapDfsInfo.is_dfs_w53_disabled);
status = QDF_STATUS_SUCCESS;
} else {
QDF_TRACE(QDF_MODULE_ID_SAP, QDF_TRACE_LEVEL_ERROR,
FL
("Regdomain not japan, set disable JP W53 not valid"));
status = QDF_STATUS_E_FAULT;
}
return status;
}
bool sap_is_auto_channel_select(struct sap_context *sapcontext)
{
if (NULL == sapcontext) {
@ -2448,25 +2403,6 @@ uint32_t wlansap_get_chan_width(struct sap_context *sap_ctx)
return wlan_sap_get_vht_ch_width(sap_ctx);
}
QDF_STATUS wlansap_set_tx_leakage_threshold(mac_handle_t mac_handle,
uint16_t tx_leakage_threshold)
{
tpAniSirGlobal mac;
if (NULL == mac_handle) {
QDF_TRACE(QDF_MODULE_ID_SAP, QDF_TRACE_LEVEL_ERROR,
"%s: Invalid mac_handle pointer", __func__);
return QDF_STATUS_E_FAULT;
}
mac = MAC_CONTEXT(mac_handle);
tgt_dfs_set_tx_leakage_threshold(mac->pdev, tx_leakage_threshold);
QDF_TRACE(QDF_MODULE_ID_SAP, QDF_TRACE_LEVEL_DEBUG,
"%s: leakage_threshold %d", __func__,
tx_leakage_threshold);
return QDF_STATUS_SUCCESS;
}
QDF_STATUS wlansap_set_invalid_session(struct sap_context *sap_ctx)
{
if (NULL == sap_ctx) {

View file

@ -880,7 +880,6 @@ struct csr_roam_profile {
uint8_t wps_state;
tCsrMobilityDomainInfo MDID;
enum QDF_OPMODE csrPersona;
uint8_t disableDFSChSwitch;
/* addIe params */
tSirAddIeParams addIeParams;
uint16_t beacon_tx_rate;
@ -1119,7 +1118,6 @@ typedef struct tagCsrConfigParam {
#ifdef FEATURE_AP_MCC_CH_AVOIDANCE
bool sap_channel_avoidance;
#endif /* FEATURE_AP_MCC_CH_AVOIDANCE */
uint8_t f_prefer_non_dfs_on_radar;
bool is_ps_enabled;
uint32_t auto_bmps_timer_val;
uint32_t dual_mac_feature_disable;

View file

@ -2721,9 +2721,6 @@ QDF_STATUS csr_change_default_config_param(tpAniSirGlobal mac,
pParam->sap_channel_avoidance;
#endif /* FEATURE_AP_MCC_CH_AVOIDANCE */
mac->f_prefer_non_dfs_on_radar =
pParam->f_prefer_non_dfs_on_radar;
mac->sme.ps_global_info.ps_enabled =
pParam->is_ps_enabled;
mac->sme.ps_global_info.auto_bmps_timer_val =
@ -2888,8 +2885,6 @@ QDF_STATUS csr_get_config_param(tpAniSirGlobal mac, tCsrConfigParam *pParam)
pParam->sap_channel_avoidance = mac->sap.sap_channel_avoidance;
#endif /* FEATURE_AP_MCC_CH_AVOIDANCE */
pParam->max_intf_count = mac->sme.max_intf_count;
pParam->f_prefer_non_dfs_on_radar =
mac->f_prefer_non_dfs_on_radar;
pParam->dual_mac_feature_disable =
mac->dual_mac_feature_disable;
pParam->sta_sap_scc_on_dfs_chan =

View file

@ -0,0 +1,115 @@
/*
* Copyright (c) 2017 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: declares P2P functions interfacing with linux kernel
*/
#ifndef _WLAN_CFG80211_P2P_H_
#define _WLAN_CFG80211_P2P_H_
#include <qdf_types.h>
struct wlan_objmgr_psoc;
struct wlan_objmgr_vdev;
struct ieee80211_channel;
/**
* wlan_p2p_start() - start p2p component
* @psoc: soc object
*
* This function used to start P2P component and register events.
*
* Return: QDF_STATUS_SUCCESS - in case of success
*/
QDF_STATUS wlan_p2p_start(struct wlan_objmgr_psoc *psoc);
/**
* wlan_p2p_stop() - stop p2p component
* @psoc: soc object
*
* This function used to stop P2P component and unregister events.
*
* Return: QDF_STATUS_SUCCESS - in case of success
*/
QDF_STATUS wlan_p2p_stop(struct wlan_objmgr_psoc *psoc);
/**
* wlan_cfg80211_roc() - API to process cfg80211 roc request
* @vdev: Pointer to vdev object
* @chan: Pointer to channel
* @duration: Duration for this roc request
* @cookie: Pointer to return cookie to up layer
*
* API to trigger remain on channel request. It returns cookie
* as the identifier of roc.
*
* Return: 0 for success, non zero for failure
*/
int wlan_cfg80211_roc(struct wlan_objmgr_vdev *vdev,
struct ieee80211_channel *chan, uint32_t duration,
uint64_t *cookie);
/**
* wlan_cfg80211_cancel_roc() - API to process cfg80211 cancel remain
* on channel request
* @vdev: Pointer to vdev object
* @cookie: Find out the roc request by cookie
*
* API to trigger cancel remain on channel request.
*
* Return: 0 for success, non zero for failure
*/
int wlan_cfg80211_cancel_roc(struct wlan_objmgr_vdev *vdev,
uint64_t cookie);
/**
* wlan_cfg80211_mgmt_tx() - API to process cfg80211 mgmt tx request
* @vdev: Pointer to vdev object
* @chan: Pointer to channel
* @wait: wait time for this mgmt tx request
* @buf: TX buffer
* @len: Length of tx buffer
* @no_cck: Required cck or not
* @dont_wait_for_ack: Wait for ack or not
* @cookie: Return the cookie to caller
*
* API to trigger mgmt frame tx request. It returns cookie as the
* identifier of this tx.
*
* Return: 0 for success, non zero for failure
*/
int wlan_cfg80211_mgmt_tx(struct wlan_objmgr_vdev *vdev,
struct ieee80211_channel *chan, bool offchan, uint32_t wait,
const uint8_t *buf, uint32_t len, bool no_cck,
bool dont_wait_for_ack, uint64_t *cookie);
/**
* wlan_cfg80211_mgmt_tx_cancel() - API to process cfg80211 cancel to
* wait mgmt tx
* @vdev: Pointer to vdev object
* @cookie: Find out the mgmt tx request by cookie
*
* API to trigger cancel mgmt frame tx request.
*
* Return: 0 for success, non zero for failure
*/
int wlan_cfg80211_mgmt_tx_cancel(struct wlan_objmgr_vdev *vdev,
uint64_t cookie);
#endif /* _WLAN_CFG80211_P2P_H_ */

View file

@ -0,0 +1,499 @@
/*
* Copyright (c) 2017-2018 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: defines driver functions interfacing with linux kernel
*/
#include <qdf_util.h>
#include <wlan_objmgr_psoc_obj.h>
#include <wlan_objmgr_global_obj.h>
#include <wlan_objmgr_pdev_obj.h>
#include <wlan_objmgr_vdev_obj.h>
#include <wlan_objmgr_peer_obj.h>
#include <wlan_p2p_public_struct.h>
#include <wlan_p2p_ucfg_api.h>
#include <wlan_policy_mgr_api.h>
#include <wlan_utility.h>
#include <wlan_osif_priv.h>
#include "wlan_cfg80211.h"
#include "wlan_cfg80211_p2p.h"
#define MAX_NO_OF_2_4_CHANNELS 14
#define MAX_OFFCHAN_TIME_FOR_DNBS 150
/**
* wlan_p2p_rx_callback() - Callback for rx mgmt frame
* @user_data: pointer to soc object
* @rx_frame: RX mgmt frame information
*
* This callback will be used to rx frames in os interface.
*
* Return: None
*/
static void wlan_p2p_rx_callback(void *user_data,
struct p2p_rx_mgmt_frame *rx_frame)
{
struct wlan_objmgr_psoc *psoc;
struct wlan_objmgr_vdev *vdev;
struct vdev_osif_priv *osif_priv;
struct wireless_dev *wdev;
uint16_t freq;
cfg80211_debug("user data:%pK, vdev id:%d, rssi:%d, buf:%pK, len:%d",
user_data, rx_frame->vdev_id, rx_frame->rx_rssi,
rx_frame->buf, rx_frame->frame_len);
psoc = user_data;
if (!psoc) {
cfg80211_err("psoc is null");
return;
}
vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc,
rx_frame->vdev_id, WLAN_P2P_ID);
if (!vdev) {
cfg80211_err("vdev is null");
return;
}
osif_priv = wlan_vdev_get_ospriv(vdev);
if (!osif_priv) {
cfg80211_err("osif_priv is null");
goto fail;
}
wdev = osif_priv->wdev;
if (!wdev) {
cfg80211_err("wdev is null");
goto fail;
}
if (rx_frame->rx_chan <= MAX_NO_OF_2_4_CHANNELS)
freq = ieee80211_channel_to_frequency(
rx_frame->rx_chan, NL80211_BAND_2GHZ);
else
freq = ieee80211_channel_to_frequency(
rx_frame->rx_chan, NL80211_BAND_5GHZ);
cfg80211_debug("Indicate frame over nl80211, vdev id:%d, idx:%d",
rx_frame->vdev_id, wdev->netdev->ifindex);
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 0))
cfg80211_rx_mgmt(wdev, freq, rx_frame->rx_rssi * 100,
rx_frame->buf, rx_frame->frame_len,
NL80211_RXMGMT_FLAG_ANSWERED);
#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 0))
cfg80211_rx_mgmt(wdev, freq, rx_frame->rx_rssi * 100,
rx_frame->buf, rx_frame->frame_len,
NL80211_RXMGMT_FLAG_ANSWERED, GFP_ATOMIC);
#else
cfg80211_rx_mgmt(wdev, freq, rx_frame->rx_rssi * 100,
rx_frame->buf, rx_frame->frame_len, GFP_ATOMIC);
#endif /* LINUX_VERSION_CODE */
fail:
wlan_objmgr_vdev_release_ref(vdev, WLAN_P2P_ID);
}
/**
* wlan_p2p_action_tx_cnf_callback() - Callback for tx confirmation
* @user_data: pointer to soc object
* @tx_cnf: tx confirmation information
*
* This callback will be used to give tx mgmt frame confirmation to
* os interface.
*
* Return: None
*/
static void wlan_p2p_action_tx_cnf_callback(void *user_data,
struct p2p_tx_cnf *tx_cnf)
{
struct wlan_objmgr_psoc *psoc;
struct wlan_objmgr_vdev *vdev;
struct vdev_osif_priv *osif_priv;
struct wireless_dev *wdev;
bool is_success;
cfg80211_debug("user data:%pK, action cookie:%llx, buf:%pK, len:%d, tx status:%d",
user_data, tx_cnf->action_cookie, tx_cnf->buf,
tx_cnf->buf_len, tx_cnf->status);
psoc = user_data;
if (!psoc) {
cfg80211_err("psoc is null");
return;
}
vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc,
tx_cnf->vdev_id, WLAN_P2P_ID);
if (!vdev) {
cfg80211_err("vdev is null");
return;
}
osif_priv = wlan_vdev_get_ospriv(vdev);
if (!osif_priv) {
cfg80211_err("osif_priv is null");
goto fail;
}
wdev = osif_priv->wdev;
if (!wdev) {
cfg80211_err("wireless dev is null");
goto fail;
}
is_success = tx_cnf->status ? false : true;
cfg80211_mgmt_tx_status(
wdev,
tx_cnf->action_cookie,
tx_cnf->buf, tx_cnf->buf_len,
is_success, GFP_KERNEL);
fail:
wlan_objmgr_vdev_release_ref(vdev, WLAN_P2P_ID);
}
#ifdef FEATURE_P2P_LISTEN_OFFLOAD
/**
* wlan_p2p_lo_event_callback() - Callback for listen offload event
* @user_data: pointer to soc object
* @p2p_lo_event: listen offload event information
*
* This callback will be used to give listen offload event to os interface.
*
* Return: None
*/
static void wlan_p2p_lo_event_callback(void *user_data,
struct p2p_lo_event *p2p_lo_event)
{
struct wlan_objmgr_psoc *psoc;
struct wlan_objmgr_vdev *vdev;
struct vdev_osif_priv *osif_priv;
struct wireless_dev *wdev;
struct sk_buff *vendor_event;
cfg80211_debug("user data:%pK, vdev id:%d, reason code:%d",
user_data, p2p_lo_event->vdev_id,
p2p_lo_event->reason_code);
psoc = user_data;
if (!psoc) {
cfg80211_err("psoc is null");
return;
}
vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc,
p2p_lo_event->vdev_id, WLAN_P2P_ID);
if (!vdev) {
cfg80211_err("vdev is null");
return;
}
osif_priv = wlan_vdev_get_ospriv(vdev);
if (!osif_priv) {
cfg80211_err("osif_priv is null");
goto fail;
}
wdev = osif_priv->wdev;
if (!wdev) {
cfg80211_err("wireless dev is null");
goto fail;
}
vendor_event = cfg80211_vendor_event_alloc(wdev->wiphy, NULL,
sizeof(uint32_t) + NLMSG_HDRLEN,
QCA_NL80211_VENDOR_SUBCMD_P2P_LO_EVENT_INDEX,
GFP_KERNEL);
if (!vendor_event) {
cfg80211_err("cfg80211_vendor_event_alloc failed");
goto fail;
}
if (nla_put_u32(vendor_event,
QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_STOP_REASON,
p2p_lo_event->reason_code)) {
cfg80211_err("nla put failed");
kfree_skb(vendor_event);
goto fail;
}
cfg80211_vendor_event(vendor_event, GFP_KERNEL);
fail:
wlan_objmgr_vdev_release_ref(vdev, WLAN_P2P_ID);
}
static inline void wlan_p2p_init_lo_event(struct p2p_start_param *start_param,
struct wlan_objmgr_psoc *psoc)
{
start_param->lo_event_cb = wlan_p2p_lo_event_callback;
start_param->lo_event_cb_data = psoc;
}
#else
static inline void wlan_p2p_init_lo_event(struct p2p_start_param *start_param,
struct wlan_objmgr_psoc *psoc)
{
}
#endif /* FEATURE_P2P_LISTEN_OFFLOAD */
/**
* wlan_p2p_event_callback() - Callback for P2P event
* @user_data: pointer to soc object
* @p2p_event: p2p event information
*
* This callback will be used to give p2p event to os interface.
*
* Return: None
*/
static void wlan_p2p_event_callback(void *user_data,
struct p2p_event *p2p_event)
{
struct wlan_objmgr_psoc *psoc;
struct wlan_objmgr_vdev *vdev;
struct ieee80211_channel *chan;
struct vdev_osif_priv *osif_priv;
struct wireless_dev *wdev;
cfg80211_debug("user data:%pK, vdev id:%d, event type:%d",
user_data, p2p_event->vdev_id, p2p_event->roc_event);
psoc = user_data;
if (!psoc) {
cfg80211_err("psoc is null");
return;
}
vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc,
p2p_event->vdev_id, WLAN_P2P_ID);
if (!vdev) {
cfg80211_err("vdev is null");
return;
}
osif_priv = wlan_vdev_get_ospriv(vdev);
if (!osif_priv) {
cfg80211_err("osif_priv is null");
goto fail;
}
wdev = osif_priv->wdev;
if (!wdev) {
cfg80211_err("wireless dev is null");
goto fail;
}
chan = ieee80211_get_channel(wdev->wiphy,
wlan_chan_to_freq(p2p_event->chan));
if (!chan) {
cfg80211_err("channel conversion failed");
goto fail;
}
if (p2p_event->roc_event == ROC_EVENT_READY_ON_CHAN) {
cfg80211_ready_on_channel(wdev,
p2p_event->cookie, chan,
p2p_event->duration, GFP_KERNEL);
} else if (p2p_event->roc_event == ROC_EVENT_COMPLETED) {
cfg80211_remain_on_channel_expired(wdev,
p2p_event->cookie, chan, GFP_KERNEL);
} else {
cfg80211_err("Invalid p2p event");
}
fail:
wlan_objmgr_vdev_release_ref(vdev, WLAN_P2P_ID);
}
QDF_STATUS wlan_p2p_start(struct wlan_objmgr_psoc *psoc)
{
struct p2p_start_param start_param;
if (!psoc) {
cfg80211_err("psoc null");
return QDF_STATUS_E_INVAL;
}
start_param.rx_cb = wlan_p2p_rx_callback;
start_param.rx_cb_data = psoc;
start_param.event_cb = wlan_p2p_event_callback;
start_param.event_cb_data = psoc;
start_param.tx_cnf_cb = wlan_p2p_action_tx_cnf_callback;
start_param.tx_cnf_cb_data = psoc;
wlan_p2p_init_lo_event(&start_param, psoc);
return ucfg_p2p_psoc_start(psoc, &start_param);
}
QDF_STATUS wlan_p2p_stop(struct wlan_objmgr_psoc *psoc)
{
if (!psoc) {
cfg80211_err("psoc null");
return QDF_STATUS_E_INVAL;
}
return ucfg_p2p_psoc_stop(psoc);
}
int wlan_cfg80211_roc(struct wlan_objmgr_vdev *vdev,
struct ieee80211_channel *chan, uint32_t duration,
uint64_t *cookie)
{
struct p2p_roc_req roc_req = {0};
struct wlan_objmgr_psoc *psoc;
uint8_t vdev_id;
bool ok;
int ret;
if (!vdev) {
cfg80211_err("invalid vdev object");
return -EINVAL;
}
if (!chan) {
cfg80211_err("invalid channel");
return -EINVAL;
}
psoc = wlan_vdev_get_psoc(vdev);
vdev_id = wlan_vdev_get_id(vdev);
if (!psoc) {
cfg80211_err("psoc handle is NULL");
return -EINVAL;
}
roc_req.chan = (uint32_t)wlan_freq_to_chan(chan->center_freq);
roc_req.duration = duration;
roc_req.vdev_id = (uint32_t)vdev_id;
ret = policy_mgr_is_chan_ok_for_dnbs(psoc, roc_req.chan, &ok);
if (QDF_IS_STATUS_ERROR(ret)) {
cfg80211_err("policy_mgr_is_chan_ok_for_dnbs():ret:%d",
ret);
return -EINVAL;
}
if (!ok) {
cfg80211_err("channel%d not OK for DNBS", roc_req.chan);
return -EINVAL;
}
return qdf_status_to_os_return(
ucfg_p2p_roc_req(psoc, &roc_req, cookie));
}
int wlan_cfg80211_cancel_roc(struct wlan_objmgr_vdev *vdev,
uint64_t cookie)
{
struct wlan_objmgr_psoc *psoc;
if (!vdev) {
cfg80211_err("invalid vdev object");
return -EINVAL;
}
psoc = wlan_vdev_get_psoc(vdev);
if (!psoc) {
cfg80211_err("psoc handle is NULL");
return -EINVAL;
}
return qdf_status_to_os_return(
ucfg_p2p_roc_cancel_req(psoc, cookie));
}
int wlan_cfg80211_mgmt_tx(struct wlan_objmgr_vdev *vdev,
struct ieee80211_channel *chan, bool offchan,
unsigned int wait,
const uint8_t *buf, uint32_t len, bool no_cck,
bool dont_wait_for_ack, uint64_t *cookie)
{
struct p2p_mgmt_tx mgmt_tx = {0};
struct wlan_objmgr_psoc *psoc;
uint8_t vdev_id;
if (!vdev) {
cfg80211_err("invalid vdev object");
return -EINVAL;
}
if (!chan) {
cfg80211_err("invalid channel");
return -EINVAL;
}
psoc = wlan_vdev_get_psoc(vdev);
vdev_id = wlan_vdev_get_id(vdev);
if (!psoc) {
cfg80211_err("psoc handle is NULL");
return -EINVAL;
}
/**
* When offchannel time is more than MAX_OFFCHAN_TIME_FOR_DNBS,
* allow offchannel only if Do_Not_Switch_Channel is not set.
*/
if (wait > MAX_OFFCHAN_TIME_FOR_DNBS) {
int ret;
bool ok;
uint32_t channel = wlan_freq_to_chan(chan->center_freq);
ret = policy_mgr_is_chan_ok_for_dnbs(psoc, channel, &ok);
if (QDF_IS_STATUS_ERROR(ret)) {
cfg80211_err("policy_mgr_is_chan_ok_for_dnbs():ret:%d",
ret);
return -EINVAL;
}
if (!ok) {
cfg80211_err("Rejecting mgmt_tx for channel:%d as DNSC is set",
channel);
return -EINVAL;
}
}
mgmt_tx.vdev_id = (uint32_t)vdev_id;
mgmt_tx.chan = (uint32_t)wlan_freq_to_chan(chan->center_freq);
mgmt_tx.wait = wait;
mgmt_tx.len = len;
mgmt_tx.no_cck = (uint32_t)no_cck;
mgmt_tx.dont_wait_for_ack = (uint32_t)dont_wait_for_ack;
mgmt_tx.off_chan = (uint32_t)offchan;
mgmt_tx.buf = buf;
return qdf_status_to_os_return(
ucfg_p2p_mgmt_tx(psoc, &mgmt_tx, cookie));
}
int wlan_cfg80211_mgmt_tx_cancel(struct wlan_objmgr_vdev *vdev,
uint64_t cookie)
{
struct wlan_objmgr_psoc *psoc;
if (!vdev) {
cfg80211_err("invalid vdev object");
return -EINVAL;
}
psoc = wlan_vdev_get_psoc(vdev);
if (!psoc) {
cfg80211_err("psoc handle is NULL");
return -EINVAL;
}
return qdf_status_to_os_return(
ucfg_p2p_mgmt_tx_cancel(psoc, vdev, cookie));
}

View file

@ -0,0 +1,309 @@
/*
* Copyright (c) 2017-2018 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: declares driver functions interfacing with linux kernel
*/
#ifndef _WLAN_CFG80211_TDLS_H_
#define _WLAN_CFG80211_TDLS_H_
#include <linux/version.h>
#include <linux/netdevice.h>
#include <linux/completion.h>
#include <net/cfg80211.h>
#include <qca_vendor.h>
#include <wlan_tdls_public_structs.h>
#include <qdf_list.h>
#include <qdf_types.h>
#include <wlan_tdls_ucfg_api.h>
#ifdef CONVERGED_TDLS_ENABLE
#define TDLS_VDEV_MAGIC 0x54444c53 /* "TDLS" */
/**
* struct osif_tdls_vdev - OS tdls vdev private structure
* @tdls_add_peer_comp: Completion to add tdls peer
* @tdls_del_peer_comp: Completion to delete tdls peer
* @tdls_mgmt_comp: Completion to send tdls mgmt packets
* @tdls_link_establish_req_comp: Completion to establish link, sync to
* send establish params to firmware, not used today.
* @tdls_teardown_comp: Completion to teardown tdls peer
* @tdls_user_cmd_comp: tdls user command completion event
* @tdls_antenna_switch_comp: Completion to switch antenna
* @tdls_add_peer_status: Peer status after add peer
* @mgmt_tx_completion_status: Tdls mgmt frames TX completion status code
* @tdls_user_cmd_len: tdls user command written buffer length
* @tdls_antenna_switch_status: return status after antenna switch
*/
struct osif_tdls_vdev {
struct completion tdls_add_peer_comp;
struct completion tdls_del_peer_comp;
struct completion tdls_mgmt_comp;
struct completion tdls_link_establish_req_comp;
struct completion tdls_teardown_comp;
struct completion tdls_user_cmd_comp;
struct completion tdls_antenna_switch_comp;
QDF_STATUS tdls_add_peer_status;
uint32_t mgmt_tx_completion_status;
uint32_t tdls_user_cmd_len;
int tdls_antenna_switch_status;
};
/**
* enum qca_wlan_vendor_tdls_trigger_mode_vdev_map: Maps the user space TDLS
* trigger mode in the host driver.
* @WLAN_VENDOR_TDLS_TRIGGER_MODE_EXPLICIT: TDLS Connection and
* disconnection handled by user space.
* @WLAN_VENDOR_TDLS_TRIGGER_MODE_IMPLICIT: TDLS connection and
* disconnection controlled by host driver based on data traffic.
* @WLAN_VENDOR_TDLS_TRIGGER_MODE_EXTERNAL: TDLS connection and
* disconnection jointly controlled by user space and host driver.
*/
enum qca_wlan_vendor_tdls_trigger_mode_vdev_map {
WLAN_VENDOR_TDLS_TRIGGER_MODE_EXPLICIT =
QCA_WLAN_VENDOR_TDLS_TRIGGER_MODE_EXPLICIT,
WLAN_VENDOR_TDLS_TRIGGER_MODE_IMPLICIT =
QCA_WLAN_VENDOR_TDLS_TRIGGER_MODE_IMPLICIT,
WLAN_VENDOR_TDLS_TRIGGER_MODE_EXTERNAL =
((QCA_WLAN_VENDOR_TDLS_TRIGGER_MODE_EXPLICIT |
QCA_WLAN_VENDOR_TDLS_TRIGGER_MODE_IMPLICIT) << 1),
};
/**
* wlan_cfg80211_tdls_priv_init() - API to initialize tdls os private
* @osif_priv: vdev os private
*
* API to initialize tdls os private
*
* Return: QDF_STATUS
*/
QDF_STATUS wlan_cfg80211_tdls_priv_init(struct vdev_osif_priv *osif_priv);
/**
* wlan_cfg80211_tdls_priv_deinit() - API to deinitialize tdls os private
* @osif_priv: vdev os private
*
* API to deinitialize tdls os private
*
* Return: None
*/
void wlan_cfg80211_tdls_priv_deinit(struct vdev_osif_priv *osif_priv);
/**
* wlan_cfg80211_tdls_add_peer() - process cfg80211 add TDLS peer request
* @vdev: vdev object
* @mac: MAC address for TDLS peer
*
* Return: 0 for success; negative errno otherwise
*/
int wlan_cfg80211_tdls_add_peer(struct wlan_objmgr_vdev *vdev,
const uint8_t *mac);
/**
* wlan_cfg80211_tdls_update_peer() - process cfg80211 update TDLS peer request
* @vdev: vdev object
* @mac: MAC address for TDLS peer
* @params: Pointer to station parameters
*
* Return: 0 for success; negative errno otherwise
*/
int wlan_cfg80211_tdls_update_peer(struct wlan_objmgr_vdev *vdev,
const uint8_t *mac,
struct station_parameters *params);
/**
* wlan_cfg80211_tdls_configure_mode() - configure tdls mode
* @vdev: vdev obj manager
* @trigger_mode: tdls trgger mode
*
* Return: 0 for success; negative errno otherwise
*/
int wlan_cfg80211_tdls_configure_mode(struct wlan_objmgr_vdev *vdev,
uint32_t trigger_mode);
/**
* wlan_cfg80211_tdls_oper() - process cfg80211 operation on an TDLS peer
* @vdev: vdev object
* @peer: MAC address of the TDLS peer
* @oper: cfg80211 TDLS operation
*
* Return: 0 on success; negative errno otherwise
*/
int wlan_cfg80211_tdls_oper(struct wlan_objmgr_vdev *vdev,
const uint8_t *peer,
enum nl80211_tdls_operation oper);
/**
* wlan_cfg80211_tdls_get_all_peers() - get all the TDLS peers from the list
* @vdev: vdev object
* @buf: output buffer
* @buflen: valid length of the output error
*
* Return: length of the output buffer
*/
int wlan_cfg80211_tdls_get_all_peers(struct wlan_objmgr_vdev *vdev,
char *buf, int buflen);
/**
* wlan_cfg80211_tdls_mgmt() - process tdls management frames from the supplicant
* @vdev: vdev object
* @peer: MAC address of the TDLS peer
* @action_code: type of TDLS mgmt frame to be sent
* @dialog_token: dialog token used in the frame
* @status_code: status to be incuded in the frame
* @peer_capability: peer capability information
* @buf: additional IEs to be included
* @len: length of additional Ies
* @oper: cfg80211 TDLS operation
*
* Return: 0 on success; negative errno otherwise
*/
int wlan_cfg80211_tdls_mgmt(struct wlan_objmgr_vdev *vdev,
const uint8_t *peer,
uint8_t action_code, uint8_t dialog_token,
uint16_t status_code, uint32_t peer_capability,
const uint8_t *buf, size_t len);
/**
* wlan_tdls_antenna_switch() - process tdls antenna switch
* @vdev: vdev object
* @mode: antenna mode
*
* Return: 0 on success; -EAGAIN to retry
*/
int wlan_tdls_antenna_switch(struct wlan_objmgr_vdev *vdev, uint32_t mode);
/**
* wlan_cfg80211_tdls_event_callback() - callback for tdls module
* @userdata: user data
* @type: request callback type
* @param: passed parameter
*
* This is used by TDLS to sync with os interface
*
* Return: None
*/
void wlan_cfg80211_tdls_event_callback(void *userdata,
enum tdls_event_type type,
struct tdls_osif_indication *param);
/**
* wlan_cfg80211_tdls_rx_callback() - Callback for rx mgmt frame
* @user_data: pointer to soc object
* @rx_frame: RX mgmt frame information
*
* This callback will be used to rx frames in os interface.
*
* Return: None
*/
void wlan_cfg80211_tdls_rx_callback(void *user_data,
struct tdls_rx_mgmt_frame *rx_frame);
/**
* hdd_notify_tdls_reset_adapter() - notify reset adapter to TDLS
* @vdev: vdev object manager
*
* Notify hdd reset adapter to TDLS component
*
* Return: None
*/
void hdd_notify_tdls_reset_adapter(struct wlan_objmgr_vdev *vdev);
/**
* hdd_notify_sta_connect() - notify sta connect to TDLS
* @session_id: pointer to soc object
* @tdls_chan_swit_prohibited: indicates channel switch capability
* @tdls_prohibited: indicates tdls allowed or not
* @vdev: vdev object manager
*
* Notify sta connect event to TDLS component
*
* Return: None
*/
void
hdd_notify_sta_connect(uint8_t session_id,
bool tdls_chan_swit_prohibited,
bool tdls_prohibited,
struct wlan_objmgr_vdev *vdev);
/**
* hdd_notify_sta_disconnect() - notify sta disconnect to TDLS
* @session_id: pointer to soc object
* @lfr_roam: indicate, whether disconnect due to lfr roam
* @bool user_disconnect: disconnect from user space
* @vdev: vdev object manager
*
* Notify sta disconnect event to TDLS component
*
* Return: None
*/
void hdd_notify_sta_disconnect(uint8_t session_id,
bool lfr_roam,
bool user_disconnect,
struct wlan_objmgr_vdev *vdev);
/**
* hdd_notify_teardown_tdls_links() - notify TDLS to teardown links
* @vdev: vdev object manager
*
* Notify tdls to teardown all the links, due to certain events
* in the system
*
* Return: None
*/
void hdd_notify_teardown_tdls_links(struct wlan_objmgr_vdev *vdev);
#else
static inline void
hdd_notify_tdls_reset_adapter(struct wlan_objmgr_vdev *vdev)
{
}
static inline void
hdd_notify_sta_connect(uint8_t session_id,
bool tdls_chan_swit_prohibited,
bool tdls_prohibited,
struct wlan_objmgr_vdev *vdev)
{
}
static inline
void hdd_notify_sta_disconnect(uint8_t session_id,
bool lfr_roam,
bool user_disconnect,
struct wlan_objmgr_vdev *vdev)
{
}
static inline
int wlan_cfg80211_tdls_configure_mode(struct wlan_objmgr_vdev *vdev,
uint32_t trigger_mode)
{
return 0;
}
static inline
void hdd_notify_teardown_tdls_links(struct wlan_objmgr_vdev *vdev)
{
}
#endif
#endif

View file

@ -0,0 +1,922 @@
/*
* Copyright (c) 2017-2018 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: defines driver functions interfacing with linux kernel
*/
#include <qdf_list.h>
#include <qdf_status.h>
#include <linux/wireless.h>
#include <linux/netdevice.h>
#include <net/cfg80211.h>
#include <wlan_cfg80211.h>
#include <wlan_cfg80211_tdls.h>
#include <wlan_osif_priv.h>
#include <wlan_tdls_public_structs.h>
#include <wlan_tdls_ucfg_api.h>
#include <qdf_mem.h>
#include <wlan_utility.h>
#include <wlan_reg_services_api.h>
#define MAX_CHANNEL (NUM_24GHZ_CHANNELS + NUM_5GHZ_CHANNELS)
#define TDLS_MAX_NO_OF_2_4_CHANNELS 14
static int wlan_cfg80211_tdls_validate_mac_addr(const uint8_t *mac)
{
static const uint8_t temp_mac[QDF_MAC_ADDR_SIZE] = {0};
if (!qdf_mem_cmp(mac, temp_mac, QDF_MAC_ADDR_SIZE)) {
cfg80211_debug("Invalid Mac address " QDF_MAC_ADDR_STR " cmd declined.",
QDF_MAC_ADDR_ARRAY(mac));
return -EINVAL;
}
return 0;
}
QDF_STATUS wlan_cfg80211_tdls_priv_init(struct vdev_osif_priv *osif_priv)
{
struct osif_tdls_vdev *tdls_priv;
cfg80211_debug("initialize tdls os if layer private structure");
tdls_priv = qdf_mem_malloc(sizeof(*tdls_priv));
if (!tdls_priv) {
cfg80211_err("failed to allocate memory for tdls_priv");
return QDF_STATUS_E_NOMEM;
}
init_completion(&tdls_priv->tdls_add_peer_comp);
init_completion(&tdls_priv->tdls_del_peer_comp);
init_completion(&tdls_priv->tdls_mgmt_comp);
init_completion(&tdls_priv->tdls_link_establish_req_comp);
init_completion(&tdls_priv->tdls_teardown_comp);
init_completion(&tdls_priv->tdls_user_cmd_comp);
init_completion(&tdls_priv->tdls_antenna_switch_comp);
osif_priv->osif_tdls = tdls_priv;
return QDF_STATUS_SUCCESS;
}
void wlan_cfg80211_tdls_priv_deinit(struct vdev_osif_priv *osif_priv)
{
cfg80211_debug("deinitialize tdls os if layer private structure");
if (!osif_priv) {
cfg80211_err("OS private structure of vdev is null ");
return;
}
if (osif_priv->osif_tdls)
qdf_mem_free(osif_priv->osif_tdls);
osif_priv->osif_tdls = NULL;
}
void hdd_notify_teardown_tdls_links(struct wlan_objmgr_vdev *vdev)
{
struct vdev_osif_priv *osif_priv;
struct osif_tdls_vdev *tdls_priv;
QDF_STATUS status;
unsigned long rc;
if (!vdev)
return;
osif_priv = wlan_vdev_get_ospriv(vdev);
tdls_priv = osif_priv->osif_tdls;
reinit_completion(&tdls_priv->tdls_teardown_comp);
status = ucfg_tdls_teardown_links(vdev);
if (QDF_IS_STATUS_ERROR(status)) {
cfg80211_err("ucfg_tdls_teardown_links failed err %d", status);
return;
}
cfg80211_debug("Wait for tdls teardown completion. Timeout %u ms",
WAIT_TIME_FOR_TDLS_TEARDOWN_LINKS);
rc = wait_for_completion_timeout(
&tdls_priv->tdls_teardown_comp,
msecs_to_jiffies(WAIT_TIME_FOR_TDLS_TEARDOWN_LINKS));
if (0 == rc) {
cfg80211_err(" Teardown Completion timed out rc: %ld", rc);
return;
}
cfg80211_debug("TDLS teardown completion status %ld ", rc);
}
void hdd_notify_tdls_reset_adapter(struct wlan_objmgr_vdev *vdev)
{
ucfg_tdls_notify_reset_adapter(vdev);
}
void
hdd_notify_sta_connect(uint8_t session_id,
bool tdls_chan_swit_prohibited,
bool tdls_prohibited,
struct wlan_objmgr_vdev *vdev)
{
struct tdls_sta_notify_params notify_info = {0};
QDF_STATUS status;
if (!vdev) {
cfg80211_err("vdev is NULL");
return;
}
status = wlan_objmgr_vdev_try_get_ref(vdev, WLAN_TDLS_NB_ID);
if (QDF_IS_STATUS_ERROR(status)) {
cfg80211_err("can't get vdev");
return;
}
notify_info.session_id = session_id;
notify_info.vdev = vdev;
notify_info.tdls_chan_swit_prohibited = tdls_chan_swit_prohibited;
notify_info.tdls_prohibited = tdls_prohibited;
ucfg_tdls_notify_sta_connect(&notify_info);
}
void hdd_notify_sta_disconnect(uint8_t session_id,
bool lfr_roam,
bool user_disconnect,
struct wlan_objmgr_vdev *vdev)
{
struct tdls_sta_notify_params notify_info = {0};
QDF_STATUS status;
if (!vdev) {
cfg80211_err("vdev is NULL");
return;
}
status = wlan_objmgr_vdev_try_get_ref(vdev, WLAN_TDLS_NB_ID);
if (QDF_IS_STATUS_ERROR(status)) {
cfg80211_err("can't get vdev");
return;
}
notify_info.session_id = session_id;
notify_info.lfr_roam = lfr_roam;
notify_info.tdls_chan_swit_prohibited = false;
notify_info.tdls_prohibited = false;
notify_info.vdev = vdev;
notify_info.user_disconnect = user_disconnect;
ucfg_tdls_notify_sta_disconnect(&notify_info);
}
int wlan_cfg80211_tdls_add_peer(struct wlan_objmgr_vdev *vdev,
const uint8_t *mac)
{
struct tdls_add_peer_params *add_peer_req;
int status;
struct vdev_osif_priv *osif_priv;
struct osif_tdls_vdev *tdls_priv;
unsigned long rc;
status = wlan_cfg80211_tdls_validate_mac_addr(mac);
if (status)
return status;
cfg80211_debug("Add TDLS peer " QDF_MAC_ADDR_STR,
QDF_MAC_ADDR_ARRAY(mac));
add_peer_req = qdf_mem_malloc(sizeof(*add_peer_req));
if (!add_peer_req) {
cfg80211_err("Failed to allocate tdls add peer request mem");
return -EINVAL;
}
osif_priv = wlan_vdev_get_ospriv(vdev);
tdls_priv = osif_priv->osif_tdls;
add_peer_req->vdev_id = wlan_vdev_get_id(vdev);
qdf_mem_copy(add_peer_req->peer_addr, mac, QDF_MAC_ADDR_SIZE);
reinit_completion(&tdls_priv->tdls_add_peer_comp);
status = ucfg_tdls_add_peer(vdev, add_peer_req);
if (QDF_IS_STATUS_ERROR(status)) {
cfg80211_err("ucfg_tdls_add_peer returned err %d", status);
status = -EIO;
goto error;
}
rc = wait_for_completion_timeout(
&tdls_priv->tdls_add_peer_comp,
msecs_to_jiffies(WAIT_TIME_TDLS_ADD_STA));
if (!rc) {
cfg80211_err("timeout for tdls add peer indication %ld", rc);
status = -EPERM;
goto error;
}
if (QDF_IS_STATUS_ERROR(tdls_priv->tdls_add_peer_status)) {
cfg80211_err("tdls add peer failed, status:%d",
tdls_priv->tdls_add_peer_status);
status = -EPERM;
}
error:
qdf_mem_free(add_peer_req);
return status;
}
static bool
is_duplicate_channel(uint8_t *arr, int index, uint8_t match)
{
int i;
for (i = 0; i < index; i++) {
if (arr[i] == match)
return true;
}
return false;
}
static void
tdls_calc_channels_from_staparams(struct tdls_update_peer_params *req_info,
struct station_parameters *params)
{
int i = 0, j = 0, k = 0, no_of_channels = 0;
int num_unique_channels;
int next;
uint8_t *dest_chans;
const uint8_t *src_chans;
dest_chans = req_info->supported_channels;
src_chans = params->supported_channels;
/* Convert (first channel , number of channels) tuple to
* the total list of channels. This goes with the assumption
* that if the first channel is < 14, then the next channels
* are an incremental of 1 else an incremental of 4 till the number
* of channels.
*/
for (i = 0; i < params->supported_channels_len &&
j < WLAN_MAC_MAX_SUPP_CHANNELS; i += 2) {
int wifi_chan_index;
if (!is_duplicate_channel(dest_chans, j, src_chans[i]))
dest_chans[j] = src_chans[i];
else
continue;
wifi_chan_index = ((dest_chans[j] <= WLAN_CHANNEL_14) ? 1 : 4);
no_of_channels = src_chans[i + 1];
cfg80211_debug("i:%d,j:%d,k:%d,[%d]:%d,index:%d,chans_num: %d",
i, j, k, j,
dest_chans[j],
wifi_chan_index,
no_of_channels);
for (k = 1; k <= no_of_channels &&
j < WLAN_MAC_MAX_SUPP_CHANNELS - 1; k++) {
next = dest_chans[j] + wifi_chan_index;
if (!is_duplicate_channel(dest_chans, j + 1, next))
dest_chans[j + 1] = next;
else
continue;
cfg80211_debug("i: %d, j: %d, k: %d, [%d]: %d",
i, j, k, j + 1, dest_chans[j + 1]);
j += 1;
}
}
num_unique_channels = j + 1;
cfg80211_debug("Unique Channel List: supported_channels ");
for (i = 0; i < num_unique_channels; i++)
cfg80211_debug("[%d]: %d,", i, dest_chans[i]);
if (MAX_CHANNEL < num_unique_channels)
num_unique_channels = MAX_CHANNEL;
req_info->supported_channels_len = num_unique_channels;
cfg80211_debug("After removing duplcates supported_channels_len: %d",
req_info->supported_channels_len);
}
static void
wlan_cfg80211_tdls_extract_params(struct tdls_update_peer_params *req_info,
struct station_parameters *params)
{
int i;
cfg80211_debug("sta cap %d, uapsd_queue %d, max_sp %d",
params->capability,
params->uapsd_queues, params->max_sp);
if (!req_info) {
cfg80211_err("reg_info is NULL");
return;
}
req_info->capability = params->capability;
req_info->uapsd_queues = params->uapsd_queues;
req_info->max_sp = params->max_sp;
if (params->supported_channels_len)
tdls_calc_channels_from_staparams(req_info, params);
qdf_mem_copy(req_info->supported_oper_classes,
params->supported_oper_classes,
params->supported_oper_classes_len);
req_info->supported_oper_classes_len =
params->supported_oper_classes_len;
if (params->ext_capab_len)
qdf_mem_copy(req_info->extn_capability, params->ext_capab,
sizeof(req_info->extn_capability));
if (params->ht_capa) {
req_info->htcap_present = 1;
qdf_mem_copy(&req_info->ht_cap, params->ht_capa,
sizeof(struct htcap_cmn_ie));
}
req_info->supported_rates_len = params->supported_rates_len;
/* Note : The Maximum sizeof supported_rates sent by the Supplicant is
* 32. The supported_rates array , for all the structures propogating
* till Add Sta to the firmware has to be modified , if the supplicant
* (ieee80211) is modified to send more rates.
*/
/* To avoid Data Currption , set to max length to SIR_MAC_MAX_SUPP_RATES
*/
if (req_info->supported_rates_len > WLAN_MAC_MAX_SUPP_RATES)
req_info->supported_rates_len = WLAN_MAC_MAX_SUPP_RATES;
if (req_info->supported_rates_len) {
qdf_mem_copy(req_info->supported_rates,
params->supported_rates,
req_info->supported_rates_len);
cfg80211_debug("Supported Rates with Length %d",
req_info->supported_rates_len);
for (i = 0; i < req_info->supported_rates_len; i++)
cfg80211_debug("[%d]: %0x", i,
req_info->supported_rates[i]);
}
if (params->vht_capa) {
req_info->vhtcap_present = 1;
qdf_mem_copy(&req_info->vht_cap, params->vht_capa,
sizeof(struct vhtcap));
}
if (params->ht_capa || params->vht_capa ||
(params->sta_flags_set & BIT(NL80211_STA_FLAG_WME)))
req_info->is_qos_wmm_sta = true;
}
int wlan_cfg80211_tdls_update_peer(struct wlan_objmgr_vdev *vdev,
const uint8_t *mac,
struct station_parameters *params)
{
struct tdls_update_peer_params *req_info;
int status;
struct vdev_osif_priv *osif_priv;
struct osif_tdls_vdev *tdls_priv;
unsigned long rc;
status = wlan_cfg80211_tdls_validate_mac_addr(mac);
if (status)
return status;
cfg80211_debug("Update TDLS peer " QDF_MAC_ADDR_STR,
QDF_MAC_ADDR_ARRAY(mac));
req_info = qdf_mem_malloc(sizeof(*req_info));
if (!req_info) {
cfg80211_err("Failed to allocate tdls add peer request mem");
return -EINVAL;
}
wlan_cfg80211_tdls_extract_params(req_info, params);
osif_priv = wlan_vdev_get_ospriv(vdev);
tdls_priv = osif_priv->osif_tdls;
req_info->vdev_id = wlan_vdev_get_id(vdev);
qdf_mem_copy(req_info->peer_addr, mac, QDF_MAC_ADDR_SIZE);
reinit_completion(&tdls_priv->tdls_add_peer_comp);
status = ucfg_tdls_update_peer(vdev, req_info);
if (QDF_IS_STATUS_ERROR(status)) {
cfg80211_err("ucfg_tdls_update_peer returned err %d", status);
status = -EIO;
goto error;
}
rc = wait_for_completion_timeout(
&tdls_priv->tdls_add_peer_comp,
msecs_to_jiffies(WAIT_TIME_TDLS_ADD_STA));
if (!rc) {
cfg80211_err("timeout for tdls update peer indication %ld", rc);
status = -EPERM;
goto error;
}
if (QDF_IS_STATUS_ERROR(tdls_priv->tdls_add_peer_status)) {
cfg80211_err("tdls update peer failed, status:%d",
tdls_priv->tdls_add_peer_status);
status = -EPERM;
}
error:
qdf_mem_free(req_info);
return status;
}
static char *tdls_oper_to_str(enum nl80211_tdls_operation oper)
{
switch (oper) {
case NL80211_TDLS_ENABLE_LINK:
return "TDLS_ENABLE_LINK";
case NL80211_TDLS_DISABLE_LINK:
return "TDLS_DISABLE_LINK";
case NL80211_TDLS_TEARDOWN:
return "TDLS_TEARDOWN";
case NL80211_TDLS_SETUP:
return "TDLS_SETUP";
default:
return "UNKNOWN:ERR";
}
}
static enum tdls_command_type tdls_oper_to_cmd(enum nl80211_tdls_operation oper)
{
if (oper == NL80211_TDLS_ENABLE_LINK)
return TDLS_CMD_ENABLE_LINK;
else if (oper == NL80211_TDLS_DISABLE_LINK)
return TDLS_CMD_DISABLE_LINK;
else if (oper == NL80211_TDLS_TEARDOWN)
return TDLS_CMD_REMOVE_FORCE_PEER;
else if (oper == NL80211_TDLS_SETUP)
return TDLS_CMD_CONFIG_FORCE_PEER;
else
return 0;
}
int wlan_cfg80211_tdls_configure_mode(struct wlan_objmgr_vdev *vdev,
uint32_t trigger_mode)
{
enum tdls_feature_mode tdls_mode;
struct tdls_set_mode_params set_mode_params;
int status;
if (!vdev)
return -EINVAL;
switch (trigger_mode) {
case WLAN_VENDOR_TDLS_TRIGGER_MODE_EXPLICIT:
tdls_mode = TDLS_SUPPORT_EXP_TRIG_ONLY;
return 0;
case WLAN_VENDOR_TDLS_TRIGGER_MODE_EXTERNAL:
tdls_mode = TDLS_SUPPORT_EXT_CONTROL;
break;
case WLAN_VENDOR_TDLS_TRIGGER_MODE_IMPLICIT:
tdls_mode = TDLS_SUPPORT_IMP_MODE;
return 0;
default:
cfg80211_err("Invalid TDLS trigger mode");
return -EINVAL;
}
cfg80211_notice("cfg80211 tdls trigger mode %d", trigger_mode);
set_mode_params.source = TDLS_SET_MODE_SOURCE_USER;
set_mode_params.tdls_mode = tdls_mode;
set_mode_params.update_last = false;
set_mode_params.vdev = vdev;
status = ucfg_tdls_set_operating_mode(&set_mode_params);
return status;
}
int wlan_cfg80211_tdls_oper(struct wlan_objmgr_vdev *vdev,
const uint8_t *peer,
enum nl80211_tdls_operation oper)
{
struct vdev_osif_priv *osif_priv;
struct osif_tdls_vdev *tdls_priv;
int status;
unsigned long rc;
enum tdls_command_type cmd;
status = wlan_cfg80211_tdls_validate_mac_addr(peer);
if (status)
return status;
if (NL80211_TDLS_DISCOVERY_REQ == oper) {
cfg80211_warn(
"We don't support in-driver setup/teardown/discovery");
return -ENOTSUPP;
}
cfg80211_debug("%s start", tdls_oper_to_str(oper));
cmd = tdls_oper_to_cmd(oper);
switch (oper) {
case NL80211_TDLS_ENABLE_LINK:
case NL80211_TDLS_TEARDOWN:
case NL80211_TDLS_SETUP:
status = ucfg_tdls_oper(vdev, peer, cmd);
if (QDF_IS_STATUS_ERROR(status)) {
cfg80211_err("%s fail %d",
tdls_oper_to_str(oper), status);
status = -EIO;
goto error;
}
break;
case NL80211_TDLS_DISABLE_LINK:
osif_priv = wlan_vdev_get_ospriv(vdev);
tdls_priv = osif_priv->osif_tdls;
reinit_completion(&tdls_priv->tdls_del_peer_comp);
status = ucfg_tdls_oper(vdev, peer, cmd);
if (QDF_IS_STATUS_ERROR(status)) {
cfg80211_err("ucfg_tdls_disable_link fail %d", status);
status = -EIO;
goto error;
}
rc = wait_for_completion_timeout(
&tdls_priv->tdls_del_peer_comp,
msecs_to_jiffies(WAIT_TIME_TDLS_DEL_STA));
if (!rc) {
cfg80211_err("timeout for tdls disable link %ld", rc);
status = -EPERM;
}
break;
default:
cfg80211_err("unsupported event %d", oper);
status = -ENOTSUPP;
}
error:
return status;
}
void wlan_cfg80211_tdls_rx_callback(void *user_data,
struct tdls_rx_mgmt_frame *rx_frame)
{
struct wlan_objmgr_psoc *psoc;
struct wlan_objmgr_vdev *vdev;
struct vdev_osif_priv *osif_priv;
struct wireless_dev *wdev;
uint16_t freq;
cfg80211_debug("user data:%pK, vdev id:%d, rssi:%d, buf:%pK, len:%d",
user_data, rx_frame->vdev_id, rx_frame->rx_rssi,
rx_frame->buf, rx_frame->frame_len);
psoc = user_data;
if (!psoc) {
cfg80211_err("psoc is null");
return;
}
vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc,
rx_frame->vdev_id, WLAN_TDLS_NB_ID);
if (!vdev) {
cfg80211_err("vdev is null");
return;
}
osif_priv = wlan_vdev_get_ospriv(vdev);
if (!osif_priv) {
cfg80211_err("osif_priv is null");
goto fail;
}
wdev = osif_priv->wdev;
if (!wdev) {
cfg80211_err("wdev is null");
goto fail;
}
if (rx_frame->rx_chan <= TDLS_MAX_NO_OF_2_4_CHANNELS)
freq = ieee80211_channel_to_frequency(
rx_frame->rx_chan, NL80211_BAND_2GHZ);
else
freq = ieee80211_channel_to_frequency(
rx_frame->rx_chan, NL80211_BAND_5GHZ);
cfg80211_notice("Indicate frame over nl80211, vdev id:%d, idx:%d",
rx_frame->vdev_id, wdev->netdev->ifindex);
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 0))
cfg80211_rx_mgmt(wdev, freq, rx_frame->rx_rssi * 100,
rx_frame->buf, rx_frame->frame_len,
NL80211_RXMGMT_FLAG_ANSWERED);
#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 0))
cfg80211_rx_mgmt(wdev, freq, rx_frame->rx_rssi * 100,
rx_frame->buf, rx_frame->frame_len,
NL80211_RXMGMT_FLAG_ANSWERED, GFP_ATOMIC);
#else
cfg80211_rx_mgmt(wdev, freq, rx_frame->rx_rssi * 100,
rx_frame->buf, rx_frame->frame_len, GFP_ATOMIC);
#endif /* LINUX_VERSION_CODE */
fail:
wlan_objmgr_vdev_release_ref(vdev, WLAN_TDLS_NB_ID);
}
int wlan_cfg80211_tdls_get_all_peers(struct wlan_objmgr_vdev *vdev,
char *buf, int buflen)
{
struct vdev_osif_priv *osif_priv;
struct osif_tdls_vdev *tdls_priv;
int32_t len;
QDF_STATUS status;
unsigned long rc;
osif_priv = wlan_vdev_get_ospriv(vdev);
tdls_priv = osif_priv->osif_tdls;
reinit_completion(&tdls_priv->tdls_user_cmd_comp);
status = ucfg_tdls_get_all_peers(vdev, buf, buflen);
if (QDF_IS_STATUS_ERROR(status)) {
cfg80211_err("ucfg_tdls_get_all_peers failed err %d", status);
len = scnprintf(buf, buflen,
"\nucfg_tdls_send_mgmt failed\n");
goto error_get_tdls_peers;
}
cfg80211_debug("Wait for tdls_user_cmd_comp. Timeout %u ms",
WAIT_TIME_FOR_TDLS_USER_CMD);
rc = wait_for_completion_timeout(
&tdls_priv->tdls_user_cmd_comp,
msecs_to_jiffies(WAIT_TIME_FOR_TDLS_USER_CMD));
if (0 == rc) {
cfg80211_err("TDLS user cmd get all peers timed out rc %ld",
rc);
len = scnprintf(buf, buflen,
"\nTDLS user cmd get all peers timed out\n");
goto error_get_tdls_peers;
}
len = tdls_priv->tdls_user_cmd_len;
error_get_tdls_peers:
return len;
}
int wlan_cfg80211_tdls_mgmt(struct wlan_objmgr_vdev *vdev,
const uint8_t *peer_mac,
uint8_t action_code, uint8_t dialog_token,
uint16_t status_code, uint32_t peer_capability,
const uint8_t *buf, size_t len)
{
struct tdls_action_frame_request mgmt_req;
struct vdev_osif_priv *osif_priv;
struct osif_tdls_vdev *tdls_priv;
int status;
unsigned long rc;
int max_sta_failed = 0;
struct tdls_validate_action_req chk_frame;
struct tdls_set_responder_req set_responder;
status = wlan_cfg80211_tdls_validate_mac_addr(peer_mac);
if (status)
return status;
osif_priv = wlan_vdev_get_ospriv(vdev);
tdls_priv = osif_priv->osif_tdls;
/* make sure doesn't call send_mgmt() while it is pending */
if (TDLS_VDEV_MAGIC == tdls_priv->mgmt_tx_completion_status) {
cfg80211_err(QDF_MAC_ADDR_STR " action %d couldn't sent, as one is pending. return EBUSY",
QDF_MAC_ADDR_ARRAY(peer_mac), action_code);
return -EBUSY;
}
/* Reset TDLS VDEV magic */
tdls_priv->mgmt_tx_completion_status = TDLS_VDEV_MAGIC;
/*prepare the request */
/* Validate the management Request */
chk_frame.vdev = vdev;
chk_frame.action_code = action_code;
qdf_mem_copy(chk_frame.peer_mac, peer_mac, QDF_MAC_ADDR_SIZE);
chk_frame.dialog_token = dialog_token;
chk_frame.action_code = action_code;
chk_frame.status_code = status_code;
chk_frame.len = len;
chk_frame.max_sta_failed = max_sta_failed;
mgmt_req.chk_frame = &chk_frame;
mgmt_req.vdev = vdev;
mgmt_req.vdev_id = wlan_vdev_get_id(vdev);
mgmt_req.session_id = mgmt_req.vdev_id;
/* populate management req params */
qdf_mem_copy(mgmt_req.tdls_mgmt.peer_mac.bytes,
peer_mac, QDF_MAC_ADDR_SIZE);
mgmt_req.tdls_mgmt.dialog = dialog_token;
mgmt_req.tdls_mgmt.frame_type = action_code;
mgmt_req.tdls_mgmt.len = len;
mgmt_req.tdls_mgmt.peer_capability = peer_capability;
mgmt_req.tdls_mgmt.status_code = chk_frame.status_code;
/*populate the additional IE's */
mgmt_req.cmd_buf = buf;
mgmt_req.len = len;
reinit_completion(&tdls_priv->tdls_mgmt_comp);
status = ucfg_tdls_send_mgmt_frame(&mgmt_req);
if (QDF_IS_STATUS_ERROR(status)) {
cfg80211_err("ucfg_tdls_send_mgmt failed err %d", status);
status = -EIO;
tdls_priv->mgmt_tx_completion_status = false;
goto error_mgmt_req;
}
cfg80211_debug("Wait for tdls_mgmt_comp. Timeout %u ms",
WAIT_TIME_FOR_TDLS_MGMT);
rc = wait_for_completion_timeout(
&tdls_priv->tdls_mgmt_comp,
msecs_to_jiffies(WAIT_TIME_FOR_TDLS_MGMT));
if ((0 == rc) || (true != tdls_priv->mgmt_tx_completion_status)) {
cfg80211_err("%s rc %ld mgmtTxCompletionStatus %u",
!rc ? "Mgmt Tx Completion timed out" :
"Mgmt Tx Completion failed",
rc, tdls_priv->mgmt_tx_completion_status);
tdls_priv->mgmt_tx_completion_status = false;
status = -EINVAL;
goto error_mgmt_req;
}
cfg80211_debug("Mgmt Tx Completion status %ld TxCompletion %u",
rc, tdls_priv->mgmt_tx_completion_status);
if (chk_frame.max_sta_failed) {
status = max_sta_failed;
goto error_mgmt_req;
}
if (TDLS_SETUP_RESPONSE == action_code ||
TDLS_SETUP_CONFIRM == action_code) {
qdf_mem_copy(set_responder.peer_mac, peer_mac,
QDF_MAC_ADDR_SIZE);
set_responder.vdev = vdev;
if (TDLS_SETUP_RESPONSE == action_code)
set_responder.responder = false;
if (TDLS_SETUP_CONFIRM == action_code)
set_responder.responder = true;
ucfg_tdls_responder(&set_responder);
}
error_mgmt_req:
return status;
}
int wlan_tdls_antenna_switch(struct wlan_objmgr_vdev *vdev, uint32_t mode)
{
struct vdev_osif_priv *osif_priv;
struct osif_tdls_vdev *tdls_priv;
int ret;
unsigned long rc;
if (!vdev) {
cfg80211_err("vdev is NULL");
return -EAGAIN;
}
osif_priv = wlan_vdev_get_ospriv(vdev);
tdls_priv = osif_priv->osif_tdls;
reinit_completion(&tdls_priv->tdls_antenna_switch_comp);
ret = ucfg_tdls_antenna_switch(vdev, mode);
if (QDF_IS_STATUS_ERROR(ret)) {
cfg80211_err("ucfg_tdls_antenna_switch failed err %d", ret);
ret = -EAGAIN;
goto error;
}
rc = wait_for_completion_timeout(
&tdls_priv->tdls_antenna_switch_comp,
msecs_to_jiffies(WAIT_TIME_FOR_TDLS_ANTENNA_SWITCH));
if (!rc) {
cfg80211_err("timeout for tdls antenna switch %ld", rc);
ret = -EAGAIN;
goto error;
}
ret = tdls_priv->tdls_antenna_switch_status;
cfg80211_debug("tdls antenna switch status:%d", ret);
error:
return ret;
}
static void
wlan_cfg80211_tdls_indicate_discovery(struct tdls_osif_indication *ind)
{
struct vdev_osif_priv *osif_vdev;
osif_vdev = wlan_vdev_get_ospriv(ind->vdev);
cfg80211_debug("Implicit TDLS, request Send Discovery request");
cfg80211_tdls_oper_request(osif_vdev->wdev->netdev,
ind->peer_mac, NL80211_TDLS_DISCOVERY_REQ,
false, GFP_KERNEL);
}
static void
wlan_cfg80211_tdls_indicate_setup(struct tdls_osif_indication *ind)
{
struct vdev_osif_priv *osif_vdev;
osif_vdev = wlan_vdev_get_ospriv(ind->vdev);
cfg80211_debug("Indication to request TDLS setup");
cfg80211_tdls_oper_request(osif_vdev->wdev->netdev,
ind->peer_mac, NL80211_TDLS_SETUP, false,
GFP_KERNEL);
}
static void
wlan_cfg80211_tdls_indicate_teardown(struct tdls_osif_indication *ind)
{
struct vdev_osif_priv *osif_vdev;
osif_vdev = wlan_vdev_get_ospriv(ind->vdev);
cfg80211_debug("Teardown reason %d", ind->reason);
cfg80211_tdls_oper_request(osif_vdev->wdev->netdev,
ind->peer_mac, NL80211_TDLS_TEARDOWN,
ind->reason, GFP_KERNEL);
}
void wlan_cfg80211_tdls_event_callback(void *user_data,
enum tdls_event_type type,
struct tdls_osif_indication *ind)
{
struct vdev_osif_priv *osif_vdev;
struct osif_tdls_vdev *tdls_priv;
if (!ind || !ind->vdev) {
cfg80211_err("ind: %pK", ind);
return;
}
osif_vdev = wlan_vdev_get_ospriv(ind->vdev);
tdls_priv = osif_vdev->osif_tdls;
switch (type) {
case TDLS_EVENT_MGMT_TX_ACK_CNF:
tdls_priv->mgmt_tx_completion_status = ind->status;
complete(&tdls_priv->tdls_mgmt_comp);
break;
case TDLS_EVENT_ADD_PEER:
tdls_priv->tdls_add_peer_status = ind->status;
complete(&tdls_priv->tdls_add_peer_comp);
break;
case TDLS_EVENT_DEL_PEER:
complete(&tdls_priv->tdls_del_peer_comp);
break;
case TDLS_EVENT_DISCOVERY_REQ:
wlan_cfg80211_tdls_indicate_discovery(ind);
break;
case TDLS_EVENT_TEARDOWN_REQ:
wlan_cfg80211_tdls_indicate_teardown(ind);
break;
case TDLS_EVENT_SETUP_REQ:
wlan_cfg80211_tdls_indicate_setup(ind);
break;
case TDLS_EVENT_TEARDOWN_LINKS_DONE:
complete(&tdls_priv->tdls_teardown_comp);
break;
case TDLS_EVENT_USER_CMD:
tdls_priv->tdls_user_cmd_len = ind->status;
complete(&tdls_priv->tdls_user_cmd_comp);
break;
case TDLS_EVENT_ANTENNA_SWITCH:
tdls_priv->tdls_antenna_switch_status = ind->status;
complete(&tdls_priv->tdls_antenna_switch_comp);
default:
break;
}
}