qcacld-3.0: Add support for TDLS offchannel

Add support for TDLS offchannel changes required
for supporting TDLS offchannel on 6 GHz band.

Change-Id: Ie150ff7e5a8237dab445ccb0ab6a4959a7c7fbf0
CRs-Fixed: 3223640
This commit is contained in:
Utkarsh Bhatnagar
2022-06-28 07:55:20 +05:30
committed by Madan Koyyalamudi
parent 186163bc5a
commit 50885ab717
8 changed files with 160 additions and 51 deletions

View File

@@ -46,39 +46,6 @@ static uint16_t tdls_get_connected_peer(struct tdls_soc_priv_obj *soc_obj)
} }
#ifdef WLAN_FEATURE_11AX #ifdef WLAN_FEATURE_11AX
static uint32_t tdls_get_6g_pwr(struct wlan_objmgr_vdev *vdev,
qdf_freq_t freq,
enum supported_6g_pwr_types pwr_typ)
{
struct wlan_objmgr_pdev *pdev = wlan_vdev_get_pdev(vdev);
struct regulatory_channel chan[NUM_CHANNELS] = {0};
uint8_t chn_idx, num_chan;
uint8_t band_mask = BIT(REG_BAND_6G);
if (!pdev)
return 0;
/* No power check is required for non 6 Ghz channel */
if (!wlan_reg_is_6ghz_chan_freq(freq))
return 0;
num_chan = wlan_reg_get_band_channel_list_for_pwrmode(pdev,
band_mask,
chan,
REG_CLI_DEF_VLP);
for (chn_idx = 0; chn_idx < num_chan; chn_idx++) {
if (chan[chn_idx].center_freq == freq) {
tdls_debug("VLP power for channel %d is %d",
chan[chn_idx].center_freq,
chan[chn_idx].tx_power);
return chan[chn_idx].tx_power;
}
}
return 0;
}
static static
uint8_t tdls_get_mlme_ch_power(struct vdev_mlme_obj *mlme_obj, qdf_freq_t freq) uint8_t tdls_get_mlme_ch_power(struct vdev_mlme_obj *mlme_obj, qdf_freq_t freq)
{ {
@@ -107,7 +74,7 @@ void tdls_set_mlme_ch_power(struct wlan_objmgr_vdev *vdev,
struct reg_tpc_power_info *reg_power_info = &mlme_obj->reg_tpc_obj; struct reg_tpc_power_info *reg_power_info = &mlme_obj->reg_tpc_obj;
if (REG_VERY_LOW_POWER_AP == reg_power_info->power_type_6g) if (REG_VERY_LOW_POWER_AP == reg_power_info->power_type_6g)
tx_power = tdls_get_6g_pwr(vdev, freq, tx_power = tdls_get_6g_pwr_for_power_type(vdev, freq,
REG_CLI_DEF_VLP); REG_CLI_DEF_VLP);
else else
tx_power = tdls_soc_obj->bss_sta_power; tx_power = tdls_soc_obj->bss_sta_power;
@@ -1987,6 +1954,7 @@ QDF_STATUS tdls_process_setup_peer(struct tdls_oper_request *req)
struct tdls_soc_priv_obj *soc_obj; struct tdls_soc_priv_obj *soc_obj;
struct wlan_objmgr_vdev *vdev; struct wlan_objmgr_vdev *vdev;
QDF_STATUS status; QDF_STATUS status;
uint8_t reg_bw_offset;
tdls_debug("Configure external TDLS peer " QDF_MAC_ADDR_FMT, tdls_debug("Configure external TDLS peer " QDF_MAC_ADDR_FMT,
QDF_MAC_ADDR_REF(req->peer_addr)); QDF_MAC_ADDR_REF(req->peer_addr));
@@ -2011,7 +1979,14 @@ QDF_STATUS tdls_process_setup_peer(struct tdls_oper_request *req)
} }
peer_req.chan = soc_obj->tdls_configs.tdls_pre_off_chan_num; peer_req.chan = soc_obj->tdls_configs.tdls_pre_off_chan_num;
if (!peer_req.op_class)
peer_req.op_class = tdls_get_opclass_from_bandwidth(
soc_obj, peer_req.chan,
soc_obj->tdls_configs.tdls_pre_off_chan_bw,
&reg_bw_offset);
tdls_debug("peer chan %d peer opclass %d", peer_req.chan,
peer_req.op_class);
status = tdls_config_force_peer(&peer_req); status = tdls_config_force_peer(&peer_req);
error: error:
wlan_objmgr_vdev_release_ref(vdev, WLAN_TDLS_NB_ID); wlan_objmgr_vdev_release_ref(vdev, WLAN_TDLS_NB_ID);

View File

@@ -846,6 +846,39 @@ QDF_STATUS tdls_update_fw_tdls_state(struct tdls_soc_priv_obj *tdls_soc_obj,
} }
#ifdef WLAN_FEATURE_11AX #ifdef WLAN_FEATURE_11AX
uint32_t tdls_get_6g_pwr_for_power_type(struct wlan_objmgr_vdev *vdev,
qdf_freq_t freq,
enum supported_6g_pwr_types pwr_typ)
{
struct wlan_objmgr_pdev *pdev = wlan_vdev_get_pdev(vdev);
struct regulatory_channel chan[NUM_CHANNELS] = {0};
uint8_t chn_idx, num_chan;
uint8_t band_mask = BIT(REG_BAND_6G);
if (!pdev)
return 0;
/* No power check is required for non 6 Ghz channel */
if (!wlan_reg_is_6ghz_chan_freq(freq))
return 0;
num_chan = wlan_reg_get_band_channel_list_for_pwrmode(pdev,
band_mask,
chan,
REG_CLI_DEF_VLP);
for (chn_idx = 0; chn_idx < num_chan; chn_idx++) {
if (chan[chn_idx].center_freq == freq) {
tdls_debug("VLP power for channel %d is %d",
chan[chn_idx].center_freq,
chan[chn_idx].tx_power);
return chan[chn_idx].tx_power;
}
}
return 0;
}
bool tdls_is_6g_freq_allowed(struct wlan_objmgr_vdev *vdev, bool tdls_is_6g_freq_allowed(struct wlan_objmgr_vdev *vdev,
qdf_freq_t freq) qdf_freq_t freq)
{ {
@@ -897,6 +930,13 @@ bool tdls_is_6g_freq_allowed(struct wlan_objmgr_vdev *vdev,
{ {
return false; return false;
} }
uint32_t tdls_get_6g_pwr_for_power_type(struct wlan_objmgr_vdev *vdev,
qdf_freq_t freq,
enum supported_6g_pwr_types pwr_typ)
{
return 0;
}
#endif #endif
bool tdls_check_is_tdls_allowed(struct wlan_objmgr_vdev *vdev) bool tdls_check_is_tdls_allowed(struct wlan_objmgr_vdev *vdev)
@@ -1923,7 +1963,11 @@ uint8_t tdls_get_opclass_from_bandwidth(struct tdls_soc_priv_obj *soc_obj,
{ {
uint8_t opclass; uint8_t opclass;
if (bw_offset & (1 << BW_80_OFFSET_BIT)) { if (bw_offset & (1 << BW_160_OFFSET_BIT)) {
opclass = tdls_find_opclass(soc_obj->soc,
channel, BWALL);
*reg_bw_offset = BWALL;
} else if (bw_offset & (1 << BW_80_OFFSET_BIT)) {
opclass = tdls_find_opclass(soc_obj->soc, opclass = tdls_find_opclass(soc_obj->soc,
channel, BW80); channel, BW80);
*reg_bw_offset = BW80; *reg_bw_offset = BW80;

View File

@@ -318,6 +318,7 @@ struct tdls_peer_mlme_info {
* @is_forced_peer: is forced peer * @is_forced_peer: is forced peer
* @op_class_for_pref_off_chan: op class for preferred off channel * @op_class_for_pref_off_chan: op class for preferred off channel
* @pref_off_chan_num: preferred off channel number * @pref_off_chan_num: preferred off channel number
* @pref_off_chan_width: preferred off channel width
* @peer_idle_timer: time to check idle traffic in tdls peers * @peer_idle_timer: time to check idle traffic in tdls peers
* @is_peer_idle_timer_initialised: Flag to check idle timer init * @is_peer_idle_timer_initialised: Flag to check idle timer init
* @spatial_streams: Number of TX/RX spatial streams for TDLS * @spatial_streams: Number of TX/RX spatial streams for TDLS
@@ -349,6 +350,7 @@ struct tdls_peer {
bool is_forced_peer; bool is_forced_peer;
uint8_t op_class_for_pref_off_chan; uint8_t op_class_for_pref_off_chan;
uint8_t pref_off_chan_num; uint8_t pref_off_chan_num;
uint8_t pref_off_chan_width;
qdf_mc_timer_t peer_idle_timer; qdf_mc_timer_t peer_idle_timer;
bool is_peer_idle_timer_initialised; bool is_peer_idle_timer_initialised;
uint8_t spatial_streams; uint8_t spatial_streams;
@@ -664,6 +666,21 @@ void tdls_send_update_to_fw(struct tdls_vdev_priv_obj *tdls_vdev_obj,
*/ */
void tdls_notify_increment_session(struct wlan_objmgr_psoc *psoc); void tdls_notify_increment_session(struct wlan_objmgr_psoc *psoc);
/**
* tdls_get_6g_pwr_for_power_type() - get power for a 6g freq for paticular
* power type
* @vdev: vdev object
* @freq: 6g freq
* @pwr_typ: power type
*
* Function that gets power for a 6g freq for paticular power type
*
* Return: true or false
*/
uint32_t tdls_get_6g_pwr_for_power_type(struct wlan_objmgr_vdev *vdev,
qdf_freq_t freq,
enum supported_6g_pwr_types pwr_typ);
/** /**
* tdls_is_6g_freq_allowed() - check is tdls 6ghz allowed or not * tdls_is_6g_freq_allowed() - check is tdls 6ghz allowed or not
* @vdev: vdev object * @vdev: vdev object

View File

@@ -1,5 +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.
* *
* 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
@@ -146,6 +147,33 @@ uint8_t tdls_find_opclass(struct wlan_objmgr_psoc *psoc, uint8_t channel,
bw_offset); bw_offset);
} }
static void tdls_fill_pref_off_chan_num(struct tdls_vdev_priv_obj *vdev_obj,
struct tdls_soc_priv_obj *soc_obj,
struct tdls_peer *peer)
{
struct wlan_objmgr_pdev *pdev = wlan_vdev_get_pdev(vdev_obj->vdev);
/*
* Fill preffered offchannel number here and prefferd bw here.
* Bw and channel number can be used to later calculate Op_class
* which will be used to identify the channels
*/
peer->pref_off_chan_width = soc_obj->tdls_configs.tdls_pre_off_chan_bw;
if (soc_obj->tdls_configs.tdls_pre_off_chan_freq_6g &&
tdls_is_6g_freq_allowed(vdev_obj->vdev,
soc_obj->tdls_configs.tdls_pre_off_chan_freq_6g)) {
peer->pref_off_chan_num =
wlan_reg_freq_to_chan(pdev,
soc_obj->tdls_configs.tdls_pre_off_chan_freq_6g);
} else {
peer->pref_off_chan_num =
soc_obj->tdls_configs.tdls_pre_off_chan_num;
if (CHECK_BIT(peer->pref_off_chan_width, BW_160_OFFSET_BIT))
peer->pref_off_chan_width &= ~(1 << BW_160_OFFSET_BIT);
}
}
/** /**
* tdls_add_peer() - add TDLS peer in TDLS vdev object * tdls_add_peer() - add TDLS peer in TDLS vdev object
* @vdev_obj: TDLS vdev object * @vdev_obj: TDLS vdev object
@@ -180,8 +208,7 @@ static struct tdls_peer *tdls_add_peer(struct tdls_vdev_priv_obj *vdev_obj,
qdf_mem_copy(&peer->peer_mac, macaddr, sizeof(peer->peer_mac)); qdf_mem_copy(&peer->peer_mac, macaddr, sizeof(peer->peer_mac));
peer->vdev_priv = vdev_obj; peer->vdev_priv = vdev_obj;
peer->pref_off_chan_num = tdls_fill_pref_off_chan_num(vdev_obj, soc_obj, peer);
soc_obj->tdls_configs.tdls_pre_off_chan_num;
peer->op_class_for_pref_off_chan = peer->op_class_for_pref_off_chan =
tdls_get_opclass_from_bandwidth( tdls_get_opclass_from_bandwidth(
soc_obj, peer->pref_off_chan_num, soc_obj, peer->pref_off_chan_num,
@@ -479,6 +506,7 @@ void tdls_extract_peer_state_param(struct tdls_peer_update_state *peer_param,
uint8_t chan_id; uint8_t chan_id;
uint32_t cur_band; uint32_t cur_band;
qdf_freq_t ch_freq; qdf_freq_t ch_freq;
uint32_t tx_power = 0;
vdev_obj = peer->vdev_priv; vdev_obj = peer->vdev_priv;
soc_obj = wlan_vdev_get_tdls_soc_obj(vdev_obj->vdev); soc_obj = wlan_vdev_get_tdls_soc_obj(vdev_obj->vdev);
@@ -501,10 +529,11 @@ void tdls_extract_peer_state_param(struct tdls_peer_update_state *peer_param,
peer_param->peer_cap.peer_off_chan_support = peer_param->peer_cap.peer_off_chan_support =
peer->off_channel_capable; peer->off_channel_capable;
peer_param->peer_cap.peer_curr_operclass = 0; peer_param->peer_cap.peer_curr_operclass = 0;
peer_param->peer_cap.self_curr_operclass = 0; peer_param->peer_cap.self_curr_operclass =
peer->op_class_for_pref_off_chan;
peer_param->peer_cap.pref_off_channum = peer->pref_off_chan_num; peer_param->peer_cap.pref_off_channum = peer->pref_off_chan_num;
peer_param->peer_cap.pref_off_chan_bandwidth = peer_param->peer_cap.pref_off_chan_bandwidth =
soc_obj->tdls_configs.tdls_pre_off_chan_bw; peer->pref_off_chan_width;
peer_param->peer_cap.opclass_for_prefoffchan = peer_param->peer_cap.opclass_for_prefoffchan =
peer->op_class_for_pref_off_chan; peer->op_class_for_pref_off_chan;
@@ -539,8 +568,17 @@ void tdls_extract_peer_state_param(struct tdls_peer_update_state *peer_param,
CHANNEL_STATE_DFS != ch_state && CHANNEL_STATE_DFS != ch_state &&
!wlan_reg_is_dsrc_freq(ch_freq)) { !wlan_reg_is_dsrc_freq(ch_freq)) {
peer_param->peer_cap.peer_chan[num].chan_id = chan_id; peer_param->peer_cap.peer_chan[num].chan_id = chan_id;
peer_param->peer_cap.peer_chan[num].pwr = if (!wlan_reg_is_6ghz_chan_freq(ch_freq)) {
wlan_reg_get_channel_reg_power_for_freq(pdev, ch_freq); tx_power =
wlan_reg_get_channel_reg_power_for_freq(pdev,
ch_freq);
} else {
tx_power =
tdls_get_6g_pwr_for_power_type(vdev_obj->vdev,
ch_freq,
REG_CLI_DEF_VLP);
}
peer_param->peer_cap.peer_chan[num].pwr = tx_power;
peer_param->peer_cap.peer_chan[num].dfs_set = false; peer_param->peer_cap.peer_chan[num].dfs_set = false;
peer_param->peer_cap.peer_chanlen++; peer_param->peer_cap.peer_chanlen++;
num++; num++;
@@ -860,7 +898,7 @@ QDF_STATUS tdls_reset_peer(struct tdls_vdev_priv_obj *vdev_obj,
if (!curr_peer->is_forced_peer) { if (!curr_peer->is_forced_peer) {
config = &soc_obj->tdls_configs; config = &soc_obj->tdls_configs;
curr_peer->pref_off_chan_num = config->tdls_pre_off_chan_num; tdls_fill_pref_off_chan_num(vdev_obj, soc_obj, curr_peer);
curr_peer->op_class_for_pref_off_chan = curr_peer->op_class_for_pref_off_chan =
tdls_get_opclass_from_bandwidth( tdls_get_opclass_from_bandwidth(
soc_obj, curr_peer->pref_off_chan_num, soc_obj, curr_peer->pref_off_chan_num,

View File

@@ -461,19 +461,48 @@
CFG_VALUE_OR_DEFAULT, \ CFG_VALUE_OR_DEFAULT, \
"Preferred TDLS channel number") "Preferred TDLS channel number")
/*
* <ini>
* tdls_pref_off_chan_num_6g - Preferred TDLS 6g channel freq when off-channel
* support is enabled.
* @Min: 0
* @Max: 7115
* @Default: 5975
*
* This ini is used to configure preferred TDLS 6G channel number when
* off-channel support is enabled. If this is set to 0, 6Ghz offchannel is
* disabled.
*
* Related: gEnableTDLSSupport, gEnableTDLSOffChannel.
*
* Supported Feature: TDLS
*
* Usage: Internal/External
*
* </ini>
*/
#define CFG_TDLS_PREFERRED_OFF_CHANNEL_FREQ_6G CFG_INI_UINT( \
"tdls_pref_off_chan_freq_6g", \
0, \
7115, \
5975, \
CFG_VALUE_OR_DEFAULT, \
"Preferred TDLS channel frequency for 6ghz channels")
/* /*
* <ini> * <ini>
* gTDLSPrefOffChanBandwidth - Preferred TDLS channel bandwidth when * gTDLSPrefOffChanBandwidth - Preferred TDLS channel bandwidth when
* off-channel support is enabled. * off-channel support is enabled.
* @Min: 0x01 * @Min: 1
* @Max: 0x0F * @Max: 15
* @Default: 0x07 * @Default: 15
* *
* This ini is used to configure preferred TDLS channel bandwidth when * This ini is used to configure preferred TDLS channel bandwidth when
* off-channel support is enabled. * off-channel support is enabled.
* 0x1: 20 MHz 0x2: 40 MHz 0x4: 80 MHz 0x8: 160 MHz * 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 * When more than one bits are set then firmware starts from the highest and
* selects one based on capability of peer. * selects one based on capability of peer. So, that means if 0xF is set that
* means fw will try intersect with 160 MHz BW and the peer supported BW.
* *
* Related: gEnableTDLSSupport, gEnableTDLSOffChannel. * Related: gEnableTDLSSupport, gEnableTDLSOffChannel.
* *
@@ -487,7 +516,7 @@
"gTDLSPrefOffChanBandwidth", \ "gTDLSPrefOffChanBandwidth", \
1, \ 1, \
15, \ 15, \
7, \ 15, \
CFG_VALUE_OR_DEFAULT, \ CFG_VALUE_OR_DEFAULT, \
"Preferred TDLS channel bandwidth") "Preferred TDLS channel bandwidth")
@@ -734,6 +763,7 @@
CFG(CFG_TDLS_RSSI_TEARDOWN_THRESHOLD) \ CFG(CFG_TDLS_RSSI_TEARDOWN_THRESHOLD) \
CFG(CFG_TDLS_RSSI_DELTA) \ CFG(CFG_TDLS_RSSI_DELTA) \
CFG(CFG_TDLS_PREFERRED_OFF_CHANNEL_NUM) \ CFG(CFG_TDLS_PREFERRED_OFF_CHANNEL_NUM) \
CFG(CFG_TDLS_PREFERRED_OFF_CHANNEL_FREQ_6G) \
CFG(CFG_TDLS_PREFERRED_OFF_CHANNEL_BW) \ CFG(CFG_TDLS_PREFERRED_OFF_CHANNEL_BW) \
CFG(CFG_TDLS_PUAPSD_PEER_TRAFFIC_IND_WINDOW) \ CFG(CFG_TDLS_PUAPSD_PEER_TRAFFIC_IND_WINDOW) \
CFG(CFG_TDLS_PUAPSD_PEER_TRAFFIC_RSP_TIMEOUT) \ CFG(CFG_TDLS_PUAPSD_PEER_TRAFFIC_RSP_TIMEOUT) \

View File

@@ -1,5 +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.
* *
* 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
@@ -467,6 +468,7 @@ enum tdls_feature_bit {
* @tdls_uapsd_ptr_timeout: tdls peer response timeout * @tdls_uapsd_ptr_timeout: tdls peer response timeout
* @tdls_feature_flags: tdls feature flags * @tdls_feature_flags: tdls feature flags
* @tdls_pre_off_chan_num: tdls off channel number * @tdls_pre_off_chan_num: tdls off channel number
* @tdls_pre_off_chan_freq_6g: tdls pref off channel freq for 6g band
* @tdls_pre_off_chan_bw: tdls off channel bandwidth * @tdls_pre_off_chan_bw: tdls off channel bandwidth
* @tdls_peer_kickout_threshold: sta kickout threshold for tdls peer * @tdls_peer_kickout_threshold: sta kickout threshold for tdls peer
* @tdls_discovery_wake_timeout: tdls discovery wake timeout * @tdls_discovery_wake_timeout: tdls discovery wake timeout
@@ -499,6 +501,7 @@ struct tdls_user_config {
uint32_t tdls_uapsd_ptr_timeout; uint32_t tdls_uapsd_ptr_timeout;
uint32_t tdls_feature_flags; uint32_t tdls_feature_flags;
uint32_t tdls_pre_off_chan_num; uint32_t tdls_pre_off_chan_num;
uint32_t tdls_pre_off_chan_freq_6g;
uint32_t tdls_pre_off_chan_bw; uint32_t tdls_pre_off_chan_bw;
uint32_t tdls_peer_kickout_threshold; uint32_t tdls_peer_kickout_threshold;
uint32_t tdls_discovery_wake_timeout; uint32_t tdls_discovery_wake_timeout;

View File

@@ -202,6 +202,8 @@ static QDF_STATUS tdls_object_init_params(
cfg_get(psoc, CFG_TDLS_PUAPSD_PEER_TRAFFIC_RSP_TIMEOUT); cfg_get(psoc, CFG_TDLS_PUAPSD_PEER_TRAFFIC_RSP_TIMEOUT);
tdls_soc_obj->tdls_configs.tdls_pre_off_chan_num = tdls_soc_obj->tdls_configs.tdls_pre_off_chan_num =
cfg_get(psoc, CFG_TDLS_PREFERRED_OFF_CHANNEL_NUM); cfg_get(psoc, CFG_TDLS_PREFERRED_OFF_CHANNEL_NUM);
tdls_soc_obj->tdls_configs.tdls_pre_off_chan_freq_6g =
cfg_get(psoc, CFG_TDLS_PREFERRED_OFF_CHANNEL_FREQ_6G);
tdls_soc_obj->tdls_configs.tdls_pre_off_chan_bw = tdls_soc_obj->tdls_configs.tdls_pre_off_chan_bw =
cfg_get(psoc, CFG_TDLS_PREFERRED_OFF_CHANNEL_BW); cfg_get(psoc, CFG_TDLS_PREFERRED_OFF_CHANNEL_BW);
tdls_soc_obj->tdls_configs.tdls_peer_kickout_threshold = tdls_soc_obj->tdls_configs.tdls_peer_kickout_threshold =

View File

@@ -213,10 +213,10 @@ static void populate_dot11f_tdls_offchannel_params(
mac->mlme_cfg->reg.valid_channel_freq_list[i]); mac->mlme_cfg->reg.valid_channel_freq_list[i]);
} }
if (wlan_reg_is_5ghz_ch_freq(pe_session->curr_op_freq)) if (wlan_reg_is_24ghz_ch_freq(pe_session->curr_op_freq))
band = BAND_5G;
else
band = BAND_2G; band = BAND_2G;
else
band = BAND_5G;
nss_5g = QDF_MIN(mac->vdev_type_nss_5g.tdls, nss_5g = QDF_MIN(mac->vdev_type_nss_5g.tdls,
mac->user_configured_nss); mac->user_configured_nss);