qcacld-3.0: Add initial checks for TDLS concurrencies
Check if TDLS is allowed for the current existing concurrency combination. In below combinations, TDLS is not allowed: 1. MCC on STA vdev 2. STA + STA 3. Total connection count > 3 4. No STA vdev exists If existing TDLS connection exists when 4th port is coming up, then teardown the TDLS connection and disable off channel. Change-Id: Iabe174bedecfa6147bd9de3cb2a3716b63145456 CRs-Fixed: 3435864
This commit is contained in:

committed by
Madan Koyyalamudi

parent
c92b309cfa
commit
37a1c90ea3
@@ -1966,10 +1966,7 @@ static QDF_STATUS tdls_config_force_peer(
|
|||||||
req->op_class, req->min_bandwidth);
|
req->op_class, req->min_bandwidth);
|
||||||
|
|
||||||
tdls_set_callback(peer, req->callback);
|
tdls_set_callback(peer, req->callback);
|
||||||
|
tdls_set_ct_mode(soc_obj->soc, vdev);
|
||||||
tdls_set_ct_mode(soc_obj->soc);
|
|
||||||
if (soc_obj->enable_tdls_connection_tracker)
|
|
||||||
tdls_implicit_enable(vdev_obj);
|
|
||||||
|
|
||||||
return status;
|
return status;
|
||||||
error:
|
error:
|
||||||
@@ -2146,9 +2143,7 @@ QDF_STATUS tdls_process_remove_force_peer(struct tdls_oper_request *req)
|
|||||||
qdf_mem_free(peer_update_param);
|
qdf_mem_free(peer_update_param);
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
tdls_set_ct_mode(soc_obj->soc);
|
tdls_set_ct_mode(soc_obj->soc, vdev);
|
||||||
if (!soc_obj->enable_tdls_connection_tracker)
|
|
||||||
tdls_implicit_disable(vdev_obj);
|
|
||||||
|
|
||||||
error:
|
error:
|
||||||
wlan_objmgr_vdev_release_ref(vdev, WLAN_TDLS_NB_ID);
|
wlan_objmgr_vdev_release_ref(vdev, WLAN_TDLS_NB_ID);
|
||||||
|
@@ -958,6 +958,7 @@ bool tdls_check_is_tdls_allowed(struct wlan_objmgr_vdev *vdev)
|
|||||||
bool state = false;
|
bool state = false;
|
||||||
qdf_freq_t ch_freq;
|
qdf_freq_t ch_freq;
|
||||||
QDF_STATUS status;
|
QDF_STATUS status;
|
||||||
|
uint32_t connection_count;
|
||||||
|
|
||||||
status = wlan_objmgr_vdev_try_get_ref(vdev, WLAN_TDLS_NB_ID);
|
status = wlan_objmgr_vdev_try_get_ref(vdev, WLAN_TDLS_NB_ID);
|
||||||
if (QDF_IS_STATUS_ERROR(status))
|
if (QDF_IS_STATUS_ERROR(status))
|
||||||
@@ -979,14 +980,22 @@ bool tdls_check_is_tdls_allowed(struct wlan_objmgr_vdev *vdev)
|
|||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (policy_mgr_get_connection_count(tdls_soc_obj->soc) == 1)
|
connection_count = policy_mgr_get_connection_count(tdls_soc_obj->soc);
|
||||||
|
if (connection_count == 1 ||
|
||||||
|
(connection_count > 1 &&
|
||||||
|
tdls_is_concurrency_allowed(tdls_soc_obj->soc))) {
|
||||||
state = true;
|
state = true;
|
||||||
else
|
} else {
|
||||||
tdls_warn("Concurrent sessions exist disable TDLS");
|
tdls_warn("Concurrent sessions exist disable TDLS");
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
ch_freq = wlan_get_operation_chan_freq(vdev);
|
ch_freq = wlan_get_operation_chan_freq(vdev);
|
||||||
if (wlan_reg_is_6ghz_chan_freq(ch_freq))
|
if (wlan_reg_is_6ghz_chan_freq(ch_freq) &&
|
||||||
state &= tdls_is_6g_freq_allowed(vdev, ch_freq);
|
!tdls_is_6g_freq_allowed(vdev, ch_freq)) {
|
||||||
|
tdls_debug("6GHz freq:%d not allowed for TDLS", ch_freq);
|
||||||
|
state = false;
|
||||||
|
}
|
||||||
|
|
||||||
exit:
|
exit:
|
||||||
wlan_objmgr_vdev_release_ref(vdev, WLAN_TDLS_NB_ID);
|
wlan_objmgr_vdev_release_ref(vdev, WLAN_TDLS_NB_ID);
|
||||||
@@ -994,72 +1003,105 @@ exit:
|
|||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
#ifdef WLAN_FEATURE_TDLS_CONCURRENCIES
|
||||||
* tdls_set_ct_mode() - Set the tdls connection tracker mode
|
bool tdls_is_concurrency_allowed(struct wlan_objmgr_psoc *psoc)
|
||||||
* @psoc: psoc 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)
|
|
||||||
{
|
{
|
||||||
bool state = false;
|
if (!wlan_psoc_nif_fw_ext2_cap_get(psoc,
|
||||||
struct tdls_soc_priv_obj *tdls_soc_obj;
|
WLAN_TDLS_CONCURRENCIES_SUPPORT))
|
||||||
|
return false;
|
||||||
|
|
||||||
tdls_soc_obj = wlan_psoc_get_tdls_soc_obj(psoc);
|
if (policy_mgr_get_connection_count(psoc) >
|
||||||
if (!tdls_soc_obj)
|
WLAN_TDLS_MAX_CONCURRENT_VDEV_SUPPORTED)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (policy_mgr_mode_specific_connection_count(psoc, PM_STA_MODE,
|
||||||
|
NULL) > 1) {
|
||||||
|
tdls_debug("More than one STA exist. Don't allow TDLS");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (policy_mgr_current_concurrency_is_mcc(psoc)) {
|
||||||
|
tdls_debug("Base channel MCC. Don't allow TDLS");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Don't enable TDLS for P2P_CLI in concurrency cases
|
||||||
|
*/
|
||||||
|
if (policy_mgr_get_connection_count(psoc) > 1 &&
|
||||||
|
!policy_mgr_mode_specific_connection_count(psoc, PM_STA_MODE,
|
||||||
|
NULL))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void tdls_set_ct_mode(struct wlan_objmgr_psoc *psoc,
|
||||||
|
struct wlan_objmgr_vdev *vdev)
|
||||||
|
{
|
||||||
|
struct tdls_soc_priv_obj *tdls_soc_obj;
|
||||||
|
struct tdls_vdev_priv_obj *tdls_vdev_obj;
|
||||||
|
uint32_t tdls_feature_flags = 0, sta_count, p2p_count;
|
||||||
|
bool state = false;
|
||||||
|
QDF_STATUS status;
|
||||||
|
|
||||||
|
if (!tdls_check_is_tdls_allowed(vdev))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* If any concurrency is detected, skip tdls pkt tracker */
|
status = tdls_get_vdev_objects(vdev, &tdls_vdev_obj, &tdls_soc_obj);
|
||||||
if (policy_mgr_get_connection_count(psoc) > 1) {
|
if (QDF_IS_STATUS_ERROR(status)) {
|
||||||
|
tdls_err("Failed to get TDLS objects");
|
||||||
state = false;
|
state = false;
|
||||||
goto set_state;
|
goto set_state;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tdls_feature_flags = tdls_soc_obj->tdls_configs.tdls_feature_flags;
|
||||||
if (TDLS_SUPPORT_DISABLED == tdls_soc_obj->tdls_current_mode ||
|
if (TDLS_SUPPORT_DISABLED == tdls_soc_obj->tdls_current_mode ||
|
||||||
TDLS_SUPPORT_SUSPENDED == tdls_soc_obj->tdls_current_mode ||
|
TDLS_SUPPORT_SUSPENDED == tdls_soc_obj->tdls_current_mode ||
|
||||||
!TDLS_IS_IMPLICIT_TRIG_ENABLED(
|
!TDLS_IS_IMPLICIT_TRIG_ENABLED(tdls_feature_flags)) {
|
||||||
tdls_soc_obj->tdls_configs.tdls_feature_flags)) {
|
|
||||||
state = false;
|
|
||||||
goto set_state;
|
|
||||||
} else if (policy_mgr_mode_specific_connection_count(psoc,
|
|
||||||
PM_STA_MODE,
|
|
||||||
NULL) == 1) {
|
|
||||||
state = true;
|
|
||||||
} else if (policy_mgr_mode_specific_connection_count(psoc,
|
|
||||||
PM_P2P_CLIENT_MODE,
|
|
||||||
NULL) == 1){
|
|
||||||
state = true;
|
|
||||||
} else {
|
|
||||||
state = false;
|
state = false;
|
||||||
goto set_state;
|
goto set_state;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* In case of TDLS external control, peer should be added
|
sta_count = policy_mgr_mode_specific_connection_count(psoc, PM_STA_MODE,
|
||||||
|
NULL);
|
||||||
|
p2p_count =
|
||||||
|
policy_mgr_mode_specific_connection_count(psoc,
|
||||||
|
PM_P2P_CLIENT_MODE,
|
||||||
|
NULL);
|
||||||
|
if (sta_count == 1 ||
|
||||||
|
(policy_mgr_get_connection_count(psoc) == 1 && p2p_count == 1)) {
|
||||||
|
state = true;
|
||||||
|
/*
|
||||||
|
* In case of TDLS external control, peer should be added
|
||||||
* by the user space to start connection tracker.
|
* by the user space to start connection tracker.
|
||||||
*/
|
*/
|
||||||
if (TDLS_IS_EXTERNAL_CONTROL_ENABLED(
|
if (TDLS_IS_EXTERNAL_CONTROL_ENABLED(tdls_feature_flags) &&
|
||||||
tdls_soc_obj->tdls_configs.tdls_feature_flags)) {
|
!tdls_soc_obj->tdls_external_peer_count)
|
||||||
if (tdls_soc_obj->tdls_external_peer_count)
|
|
||||||
state = true;
|
|
||||||
else
|
|
||||||
state = false;
|
state = false;
|
||||||
|
|
||||||
|
goto set_state;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
state = false;
|
||||||
|
|
||||||
set_state:
|
set_state:
|
||||||
tdls_soc_obj->enable_tdls_connection_tracker = state;
|
tdls_soc_obj->enable_tdls_connection_tracker = state;
|
||||||
|
if (tdls_soc_obj->enable_tdls_connection_tracker)
|
||||||
|
tdls_implicit_enable(tdls_vdev_obj);
|
||||||
|
else
|
||||||
|
tdls_implicit_disable(tdls_vdev_obj);
|
||||||
|
|
||||||
tdls_debug("enable_tdls_connection_tracker %d",
|
tdls_debug("enable_tdls_connection_tracker %d current_mode:%d feature_flags:0x%x",
|
||||||
tdls_soc_obj->enable_tdls_connection_tracker);
|
tdls_soc_obj->enable_tdls_connection_tracker,
|
||||||
|
tdls_soc_obj->tdls_current_mode, tdls_feature_flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
QDF_STATUS
|
QDF_STATUS
|
||||||
tdls_process_policy_mgr_notification(struct wlan_objmgr_psoc *psoc)
|
tdls_process_policy_mgr_notification(struct wlan_objmgr_psoc *psoc)
|
||||||
{
|
{
|
||||||
struct tdls_vdev_priv_obj *tdls_priv_vdev;
|
|
||||||
struct wlan_objmgr_vdev *tdls_obj_vdev;
|
struct wlan_objmgr_vdev *tdls_obj_vdev;
|
||||||
struct tdls_soc_priv_obj *tdls_priv_soc;
|
|
||||||
|
|
||||||
if (!psoc) {
|
if (!psoc) {
|
||||||
tdls_err("psoc: %pK", psoc);
|
tdls_err("psoc: %pK", psoc);
|
||||||
@@ -1078,11 +1120,7 @@ tdls_process_policy_mgr_notification(struct wlan_objmgr_psoc *psoc)
|
|||||||
}
|
}
|
||||||
|
|
||||||
tdls_debug("enter ");
|
tdls_debug("enter ");
|
||||||
tdls_set_ct_mode(psoc);
|
tdls_set_ct_mode(psoc, tdls_obj_vdev);
|
||||||
if (tdls_get_vdev_objects(tdls_obj_vdev, &tdls_priv_vdev,
|
|
||||||
&tdls_priv_soc) == QDF_STATUS_SUCCESS &&
|
|
||||||
tdls_priv_soc->enable_tdls_connection_tracker)
|
|
||||||
tdls_implicit_enable(tdls_priv_vdev);
|
|
||||||
|
|
||||||
wlan_objmgr_vdev_release_ref(tdls_obj_vdev, WLAN_TDLS_NB_ID);
|
wlan_objmgr_vdev_release_ref(tdls_obj_vdev, WLAN_TDLS_NB_ID);
|
||||||
|
|
||||||
@@ -1137,21 +1175,23 @@ struct wlan_objmgr_vdev *tdls_get_vdev(struct wlan_objmgr_psoc *psoc,
|
|||||||
{
|
{
|
||||||
uint32_t vdev_id;
|
uint32_t vdev_id;
|
||||||
|
|
||||||
if (policy_mgr_get_connection_count(psoc) > 1)
|
if (policy_mgr_get_connection_count(psoc) > 1 &&
|
||||||
|
!tdls_is_concurrency_allowed(psoc))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
vdev_id = policy_mgr_mode_specific_vdev_id(psoc, PM_STA_MODE);
|
vdev_id = policy_mgr_mode_specific_vdev_id(psoc, PM_STA_MODE);
|
||||||
|
|
||||||
if (WLAN_INVALID_VDEV_ID != vdev_id)
|
if (WLAN_INVALID_VDEV_ID != vdev_id)
|
||||||
return wlan_objmgr_get_vdev_by_id_from_psoc(psoc,
|
return wlan_objmgr_get_vdev_by_id_from_psoc(psoc, vdev_id,
|
||||||
vdev_id,
|
|
||||||
dbg_id);
|
dbg_id);
|
||||||
|
/*
|
||||||
|
* For P2P_Client mode, TDLS is not supported on concurrency
|
||||||
|
* so return P2P_client vdev only if P2P client mode exists without
|
||||||
|
* any concurreny
|
||||||
|
*/
|
||||||
vdev_id = policy_mgr_mode_specific_vdev_id(psoc, PM_P2P_CLIENT_MODE);
|
vdev_id = policy_mgr_mode_specific_vdev_id(psoc, PM_P2P_CLIENT_MODE);
|
||||||
|
if (WLAN_INVALID_VDEV_ID != vdev_id &&
|
||||||
if (WLAN_INVALID_VDEV_ID != vdev_id)
|
policy_mgr_get_connection_count(psoc) == 1)
|
||||||
return wlan_objmgr_get_vdev_by_id_from_psoc(psoc,
|
return wlan_objmgr_get_vdev_by_id_from_psoc(psoc, vdev_id,
|
||||||
vdev_id,
|
|
||||||
dbg_id);
|
dbg_id);
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
@@ -1369,9 +1409,7 @@ tdls_process_sta_connect(struct tdls_sta_notify_params *notify)
|
|||||||
notify->session_id);
|
notify->session_id);
|
||||||
|
|
||||||
/* check and set the connection tracker */
|
/* check and set the connection tracker */
|
||||||
tdls_set_ct_mode(tdls_soc_obj->soc);
|
tdls_set_ct_mode(tdls_soc_obj->soc, notify->vdev);
|
||||||
if (tdls_soc_obj->enable_tdls_connection_tracker)
|
|
||||||
tdls_implicit_enable(tdls_vdev_obj);
|
|
||||||
|
|
||||||
return QDF_STATUS_SUCCESS;
|
return QDF_STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
@@ -1458,16 +1496,11 @@ tdls_process_sta_disconnect(struct tdls_sta_notify_params *notify)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Check and set the connection tracker and implicit timers */
|
/* Check and set the connection tracker and implicit timers */
|
||||||
tdls_set_ct_mode(curr_tdls_soc->soc);
|
if (temp_vdev) {
|
||||||
if (curr_tdls_soc->enable_tdls_connection_tracker)
|
tdls_set_ct_mode(curr_tdls_soc->soc, temp_vdev);
|
||||||
tdls_implicit_enable(curr_tdls_vdev);
|
|
||||||
else
|
|
||||||
tdls_implicit_disable(curr_tdls_vdev);
|
|
||||||
|
|
||||||
/* release the vdev ref , if temp vdev was acquired */
|
|
||||||
if (temp_vdev)
|
|
||||||
wlan_objmgr_vdev_release_ref(temp_vdev,
|
wlan_objmgr_vdev_release_ref(temp_vdev,
|
||||||
WLAN_TDLS_NB_ID);
|
WLAN_TDLS_NB_ID);
|
||||||
|
}
|
||||||
|
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
@@ -1657,18 +1690,15 @@ static void tdls_set_mode_in_vdev(struct tdls_vdev_priv_obj *tdls_vdev,
|
|||||||
/* If tdls implicit mode is disabled, then
|
/* If tdls implicit mode is disabled, then
|
||||||
* stop the connection tracker.
|
* stop the connection tracker.
|
||||||
*/
|
*/
|
||||||
tdls_soc->enable_tdls_connection_tracker =
|
tdls_soc->enable_tdls_connection_tracker = false;
|
||||||
false;
|
} else if (TDLS_SUPPORT_EXP_TRIG_ONLY == tdls_mode) {
|
||||||
} else if (TDLS_SUPPORT_EXP_TRIG_ONLY ==
|
|
||||||
tdls_mode) {
|
|
||||||
clear_bit((unsigned long)source,
|
clear_bit((unsigned long)source,
|
||||||
&tdls_soc->tdls_source_bitmap);
|
&tdls_soc->tdls_source_bitmap);
|
||||||
tdls_implicit_disable(tdls_vdev);
|
tdls_implicit_disable(tdls_vdev);
|
||||||
/* If tdls implicit mode is disabled, then
|
/* If tdls implicit mode is disabled, then
|
||||||
* stop the connection tracker.
|
* stop the connection tracker.
|
||||||
*/
|
*/
|
||||||
tdls_soc->enable_tdls_connection_tracker =
|
tdls_soc->enable_tdls_connection_tracker = false;
|
||||||
false;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Check if any TDLS source bit is set and if
|
* Check if any TDLS source bit is set and if
|
||||||
@@ -1679,7 +1709,6 @@ static void tdls_set_mode_in_vdev(struct tdls_vdev_priv_obj *tdls_vdev,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
tdls_debug("exit ");
|
tdls_debug("exit ");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2017-2021 The Linux Foundation. All rights reserved.
|
* Copyright (c) 2017-2021 The Linux Foundation. All rights reserved.
|
||||||
* Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
|
* Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||||
*
|
*
|
||||||
* Permission to use, copy, modify, and/or distribute this software for
|
* Permission to use, copy, modify, and/or distribute this software for
|
||||||
* any purpose with or without fee is hereby granted, provided that the
|
* any purpose with or without fee is hereby granted, provided that the
|
||||||
@@ -566,12 +566,14 @@ QDF_STATUS tdls_get_vdev_objects(struct wlan_objmgr_vdev *vdev,
|
|||||||
/**
|
/**
|
||||||
* tdls_set_ct_mode() - Set the tdls connection tracker mode
|
* tdls_set_ct_mode() - Set the tdls connection tracker mode
|
||||||
* @psoc: objmgr psoc object
|
* @psoc: objmgr psoc object
|
||||||
|
* @vdev: Pointer to vdev object
|
||||||
*
|
*
|
||||||
* This routine is called to set the tdls connection tracker operation status
|
* This routine is called to set the tdls connection tracker operation status
|
||||||
*
|
*
|
||||||
* Return: NONE
|
* Return: NONE
|
||||||
*/
|
*/
|
||||||
void tdls_set_ct_mode(struct wlan_objmgr_psoc *psoc);
|
void tdls_set_ct_mode(struct wlan_objmgr_psoc *psoc,
|
||||||
|
struct wlan_objmgr_vdev *vdev);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* tdls_set_operation_mode() - set tdls operating mode
|
* tdls_set_operation_mode() - set tdls operating mode
|
||||||
@@ -825,4 +827,20 @@ QDF_STATUS tdls_delete_all_peers_indication(struct wlan_objmgr_psoc *psoc,
|
|||||||
uint8_t tdls_get_opclass_from_bandwidth(struct wlan_objmgr_vdev *vdev,
|
uint8_t tdls_get_opclass_from_bandwidth(struct wlan_objmgr_vdev *vdev,
|
||||||
qdf_freq_t freq, uint8_t bw_offset,
|
qdf_freq_t freq, uint8_t bw_offset,
|
||||||
uint8_t *reg_bw_offset);
|
uint8_t *reg_bw_offset);
|
||||||
|
|
||||||
|
#ifdef WLAN_FEATURE_TDLS_CONCURRENCIES
|
||||||
|
/**
|
||||||
|
* tdls_is_concurrency_allowed() - Is TDLS allowed with the current concurrency
|
||||||
|
* @psoc: Pointer to PSOC
|
||||||
|
*
|
||||||
|
* Return: True or False
|
||||||
|
*/
|
||||||
|
bool tdls_is_concurrency_allowed(struct wlan_objmgr_psoc *psoc);
|
||||||
|
#else
|
||||||
|
static inline bool
|
||||||
|
tdls_is_concurrency_allowed(struct wlan_objmgr_psoc *psoc)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
#endif /* WLAN_FEATURE_TDLS_CONCURRENCIES */
|
||||||
#endif
|
#endif
|
||||||
|
@@ -54,7 +54,7 @@
|
|||||||
#define WLAN_TDLS_PREFERRED_OFF_CHANNEL_NUM_MAX 165
|
#define WLAN_TDLS_PREFERRED_OFF_CHANNEL_NUM_MAX 165
|
||||||
#define WLAN_TDLS_PREFERRED_OFF_CHANNEL_NUM_DEF 36
|
#define WLAN_TDLS_PREFERRED_OFF_CHANNEL_NUM_DEF 36
|
||||||
#define WLAN_TDLS_PREFERRED_OFF_CHANNEL_FRQ_DEF 5180
|
#define WLAN_TDLS_PREFERRED_OFF_CHANNEL_FRQ_DEF 5180
|
||||||
|
#define WLAN_TDLS_MAX_CONCURRENT_VDEV_SUPPORTED 3
|
||||||
|
|
||||||
#define AC_PRIORITY_NUM 4
|
#define AC_PRIORITY_NUM 4
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user