qcacld-3.0: Correct channel parameters during channel switch notification

Correct the channel parameters that are calculated and used to indicate
the channel switch notification sent to user space. The channel bonding
values should not be used to get the channel width information since
they can be used only in STA mode to enable or disable the channel
bonding. Fix the same by getting the updated channel switch information
from the session entries.

Change-Id: Ia51779cddb2b9c3108b211822f104c45f88e53fd
CRs-Fixed: 1021380
This commit is contained in:
Manishekar Chandrasekaran 2016-05-26 19:10:04 +05:30 • committed by Akash Patel
commit ec26759fc8
9 changed files with 135 additions and 159 deletions

View file

@ -821,6 +821,15 @@ struct hdd_netif_queue_history {
uint32_t pause_map;
};
/**
* struct hdd_chan_change_params - channel related information
* @chan: operating channel
* @chan_params: channel parameters
*/
struct hdd_chan_change_params {
uint8_t chan;
struct ch_params_s chan_params;
};
#define WLAN_HDD_ADAPTER_MAGIC 0x574c414e /* ASCII "WLAN" */
@ -1635,8 +1644,8 @@ uint8_t wlan_hdd_find_opclass(tHalHandle hal, uint8_t channel,
void hdd_update_config(hdd_context_t *hdd_ctx);
QDF_STATUS hdd_chan_change_notify(hdd_adapter_t *adapter,
struct net_device *dev, uint8_t oper_chan);
struct net_device *dev,
struct hdd_chan_change_params chan_change);
#ifdef FEATURE_WLAN_MCC_TO_SCC_SWITCH
QDF_STATUS hdd_register_for_sap_restart_with_channel_switch(void);
#else

View file

@ -3973,6 +3973,7 @@ hdd_sme_roam_callback(void *pContext, tCsrRoamInfo *pRoamInfo, uint32_t roamId,
hdd_station_ctx_t *pHddStaCtx = NULL;
QDF_STATUS status = QDF_STATUS_SUCCESS;
hdd_context_t *pHddCtx = NULL;
struct hdd_chan_change_params chan_change;
hddLog(LOG2,
"CSR Callback: status= %d result= %d roamID=%d",
@ -4313,8 +4314,18 @@ hdd_sme_roam_callback(void *pContext, tCsrRoamInfo *pRoamInfo, uint32_t roamId,
hdd_info("channel switch for session:%d to channel:%d",
pAdapter->sessionId, pRoamInfo->chan_info.chan_id);
chan_change.chan = pRoamInfo->chan_info.chan_id;
chan_change.chan_params.ch_width =
pRoamInfo->chan_info.ch_width;
chan_change.chan_params.sec_ch_offset =
pRoamInfo->chan_info.sec_ch_offset;
chan_change.chan_params.center_freq_seg0 =
pRoamInfo->chan_info.band_center_freq1;
chan_change.chan_params.center_freq_seg1 =
pRoamInfo->chan_info.band_center_freq2;
status = hdd_chan_change_notify(pAdapter, pAdapter->dev,
pRoamInfo->chan_info.chan_id);
chan_change);
if (QDF_IS_STATUS_ERROR(status))
hdd_err("channel change notification failed");

View file

@ -625,97 +625,11 @@ static void hdd_issue_stored_joinreq(hdd_adapter_t *sta_adapter,
}
}
#ifdef WLAN_FEATURE_MBSSID
static eCsrPhyMode
hdd_sap_get_phymode(hdd_adapter_t *hostapd_adapter)
{
return wlansap_get_phymode(WLAN_HDD_GET_SAP_CTX_PTR(hostapd_adapter));
}
#else
static eCsrPhyMode
hdd_sap_get_phymode(hdd_adapter_t *hostapd_adapter)
{
return wlansap_get_phymode(
(WLAN_HDD_GET_CTX(hostapd_adapter))->pcds_context);
}
#endif
/**
* hdd_update_chandef() - Function to update channel width and center freq
* @hostapd_adapter: hostapd adapter
* @chandef: cfg80211 chan def
* @cb_mode: chan offset
*
* This function will be called to update channel width and center freq
*
* Return: None
*/
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0)) || defined(WITH_BACKPORTS)
static inline void
hdd_update_chandef(hdd_adapter_t *hostapd_adapter,
struct cfg80211_chan_def *chandef,
ePhyChanBondState cb_mode)
{
uint16_t ch_width;
hdd_ap_ctx_t *phdd_ap_ctx;
uint8_t center_chan, chan;
phdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(hostapd_adapter);
ch_width = phdd_ap_ctx->sapConfig.acs_cfg.ch_width;
switch (ch_width) {
case eHT_CHANNEL_WIDTH_20MHZ:
case eHT_CHANNEL_WIDTH_40MHZ:
hdd_info("ch_width %d, won't update", ch_width);
break;
case eHT_CHANNEL_WIDTH_80MHZ:
chan = cds_freq_to_chan(chandef->chan->center_freq);
chandef->width = NL80211_CHAN_WIDTH_80;
switch (cb_mode) {
case PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_CENTERED:
case PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_LOW:
center_chan = chan + 2;
break;
case PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_LOW:
center_chan = chan + 6;
break;
case PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_HIGH:
case PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_CENTERED:
center_chan = chan - 2;
break;
case PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_HIGH:
center_chan = chan - 6;
break;
default:
center_chan = chan;
break;
}
chandef->center_freq1 = cds_chan_to_freq(center_chan);
break;
case eHT_CHANNEL_WIDTH_160MHZ:
default:
/* Todo, please add related codes if support 160MHZ or others */
hdd_err("unsupport ch_width %d", ch_width);
break;
}
}
#else
static inline void
hdd_update_chandef(hdd_adapter_t *hostapd_adapter,
struct cfg80211_chan_def *chandef,
ePhyChanBondState cb_mode)
{
}
#endif
/**
* hdd_chan_change_notify() - Function to notify hostapd about channel change
* @hostapd_adapter hostapd adapter
* @dev: Net device structure
* @oper_chan: New operating channel
* @chan_change: New channel change parameters
*
* This function is used to notify hostapd about the channel change
*
@ -724,13 +638,11 @@ hdd_update_chandef(hdd_adapter_t *hostapd_adapter,
*/
QDF_STATUS hdd_chan_change_notify(hdd_adapter_t *adapter,
struct net_device *dev,
uint8_t oper_chan)
struct hdd_chan_change_params chan_change)
{
struct ieee80211_channel *chan;
struct cfg80211_chan_def chandef;
enum nl80211_channel_type channel_type;
eCsrPhyMode phy_mode;
ePhyChanBondState cb_mode;
uint32_t freq;
tHalHandle hal = WLAN_HDD_GET_HAL_CTX(adapter);
@ -739,7 +651,13 @@ QDF_STATUS hdd_chan_change_notify(hdd_adapter_t *adapter,
return QDF_STATUS_E_FAILURE;
}
freq = cds_chan_to_freq(oper_chan);
hdd_info("chan:%d width:%d sec_ch_offset:%d seg0:%d seg1:%d",
chan_change.chan, chan_change.chan_params.ch_width,
chan_change.chan_params.sec_ch_offset,
chan_change.chan_params.center_freq_seg0,
chan_change.chan_params.center_freq_seg1);
freq = cds_chan_to_freq(chan_change.chan);
chan = __ieee80211_get_channel(adapter->wdev.wiphy, freq);
@ -748,46 +666,49 @@ QDF_STATUS hdd_chan_change_notify(hdd_adapter_t *adapter,
return QDF_STATUS_E_FAILURE;
}
if (adapter->device_mode == QDF_SAP_MODE ||
adapter->device_mode == QDF_P2P_GO_MODE)
phy_mode = hdd_sap_get_phymode(adapter);
else
phy_mode = sme_get_phy_mode(hal);
if (oper_chan <= 14)
cb_mode = sme_get_cb_phy_state_from_cb_ini_value(
sme_get_channel_bonding_mode24_g(hal));
else
cb_mode = sme_get_cb_phy_state_from_cb_ini_value(
sme_get_channel_bonding_mode5_g(hal));
switch (phy_mode) {
case eCSR_DOT11_MODE_11n:
case eCSR_DOT11_MODE_11n_ONLY:
case eCSR_DOT11_MODE_11ac:
case eCSR_DOT11_MODE_11ac_ONLY:
if (cb_mode == PHY_SINGLE_CHANNEL_CENTERED)
channel_type = NL80211_CHAN_HT20;
else if (cb_mode == PHY_DOUBLE_CHANNEL_HIGH_PRIMARY)
channel_type = NL80211_CHAN_HT40MINUS;
else if (cb_mode == PHY_DOUBLE_CHANNEL_LOW_PRIMARY)
channel_type = NL80211_CHAN_HT40PLUS;
else
channel_type = NL80211_CHAN_HT40PLUS;
switch (chan_change.chan_params.sec_ch_offset) {
case PHY_SINGLE_CHANNEL_CENTERED:
channel_type = NL80211_CHAN_HT20;
break;
case PHY_DOUBLE_CHANNEL_HIGH_PRIMARY:
channel_type = NL80211_CHAN_HT40MINUS;
break;
case PHY_DOUBLE_CHANNEL_LOW_PRIMARY:
channel_type = NL80211_CHAN_HT40PLUS;
break;
default:
channel_type = NL80211_CHAN_NO_HT;
break;
}
hdd_info("%s: phy_mode %d cb_mode %d chann_type %d oper_chan %d",
__func__, phy_mode, cb_mode, channel_type, oper_chan);
cfg80211_chandef_create(&chandef, chan, channel_type);
if ((phy_mode == eCSR_DOT11_MODE_11ac) ||
(phy_mode == eCSR_DOT11_MODE_11ac_ONLY))
hdd_update_chandef(adapter, &chandef, cb_mode);
/* cfg80211_chandef_create() does update of width and center_freq1
* only for NL80211_CHAN_NO_HT, NL80211_CHAN_HT20, NL80211_CHAN_HT40PLUS
* and NL80211_CHAN_HT40MINUS.
*/
if (chan_change.chan_params.ch_width == CH_WIDTH_80MHZ)
chandef.width = NL80211_CHAN_WIDTH_80;
else if (chan_change.chan_params.ch_width == CH_WIDTH_80P80MHZ)
chandef.width = NL80211_CHAN_WIDTH_80P80;
else if (chan_change.chan_params.ch_width == CH_WIDTH_160MHZ)
chandef.width = NL80211_CHAN_WIDTH_160;
if ((chan_change.chan_params.ch_width == CH_WIDTH_80MHZ) ||
(chan_change.chan_params.ch_width == CH_WIDTH_80P80MHZ) ||
(chan_change.chan_params.ch_width == CH_WIDTH_160MHZ)) {
if (chan_change.chan_params.center_freq_seg0)
chandef.center_freq1 = cds_chan_to_freq(
chan_change.chan_params.center_freq_seg0);
if (chan_change.chan_params.center_freq_seg1)
chandef.center_freq2 = cds_chan_to_freq(
chan_change.chan_params.center_freq_seg1);
}
hdd_info("notify: chan:%d width:%d freq1:%d freq2:%d",
chandef.chan->center_freq, chandef.width, chandef.center_freq1,
chandef.center_freq2);
cfg80211_ch_switch_notify(dev, &chandef);
@ -898,6 +819,7 @@ QDF_STATUS hdd_hostapd_sap_event_cb(tpSap_Event pSapEvent,
uint8_t cc_len = WLAN_SVC_COUNTRY_CODE_LEN;
hdd_adapter_t *con_sap_adapter;
QDF_STATUS status = QDF_STATUS_SUCCESS;
struct hdd_chan_change_params chan_change;
int ret = 0;
dev = (struct net_device *)usrDataForCallback;
@ -1750,11 +1672,23 @@ QDF_STATUS hdd_hostapd_sap_event_cb(tpSap_Event pSapEvent,
* only for non driver override acs
*/
if (pHostapdAdapter->device_mode == QDF_SAP_MODE &&
pHddCtx->config->force_sap_acs)
pHddCtx->config->force_sap_acs) {
return QDF_STATUS_SUCCESS;
else
} else {
chan_change.chan =
pSapEvent->sapevt.sap_ch_selected.pri_ch;
chan_change.chan_params.ch_width =
pSapEvent->sapevt.sap_ch_selected.ch_width;
chan_change.chan_params.sec_ch_offset =
pSapEvent->sapevt.sap_ch_selected.ht_sec_ch;
chan_change.chan_params.center_freq_seg0 =
pSapEvent->sapevt.sap_ch_selected.vht_seg0_center_ch;
chan_change.chan_params.center_freq_seg1 =
pSapEvent->sapevt.sap_ch_selected.vht_seg1_center_ch;
return hdd_chan_change_notify(pHostapdAdapter, dev,
pSapEvent->sapevt.sap_ch_selected.pri_ch);
chan_change);
}
#ifdef FEATURE_WLAN_AP_AP_ACS_OPTIMIZE
case eSAP_ACS_SCAN_SUCCESS_EVENT:

View file

@ -1170,6 +1170,8 @@ typedef struct sSirSmeChanInfo {
uint32_t reg_info_2;
uint8_t nss;
uint32_t rate_flags;
uint8_t sec_ch_offset;
enum phy_ch_width ch_width;
} tSirSmeChanInfo, *tpSirSmeChanInfo;
/* / Definition for Association indication from peer */
@ -1536,6 +1538,7 @@ typedef struct sSirSmeSwitchChannelInd {
uint16_t length;
uint8_t sessionId;
uint16_t newChannelId;
struct ch_params_s chan_params;
struct qdf_mac_addr bssid; /* BSSID */
} tSirSmeSwitchChannelInd, *tpSirSmeSwitchChannelInd;

View file

@ -2650,6 +2650,24 @@ void lim_switch_channel_cback(tpAniSirGlobal pMac, QDF_STATUS status,
pSirSmeSwitchChInd->newChannelId =
psessionEntry->gLimChannelSwitch.primaryChannel;
pSirSmeSwitchChInd->sessionId = psessionEntry->smeSessionId;
pSirSmeSwitchChInd->chan_params.ch_width =
psessionEntry->gLimChannelSwitch.ch_width;
pSirSmeSwitchChInd->chan_params.sec_ch_offset =
psessionEntry->gLimChannelSwitch.sec_ch_offset;
pSirSmeSwitchChInd->chan_params.center_freq_seg0 =
psessionEntry->gLimChannelSwitch.ch_center_freq_seg0;
pSirSmeSwitchChInd->chan_params.center_freq_seg1 =
psessionEntry->gLimChannelSwitch.ch_center_freq_seg1;
lim_log(pMac, LOG1,
FL("session:%d chan:%d width:%d sec offset:%d seg0:%d seg1:%d"),
pSirSmeSwitchChInd->sessionId,
pSirSmeSwitchChInd->newChannelId,
pSirSmeSwitchChInd->chan_params.ch_width,
pSirSmeSwitchChInd->chan_params.sec_ch_offset,
pSirSmeSwitchChInd->chan_params.center_freq_seg0,
pSirSmeSwitchChInd->chan_params.center_freq_seg1);
qdf_mem_copy(pSirSmeSwitchChInd->bssid.bytes, psessionEntry->bssId,
QDF_MAC_ADDR_SIZE);
mmhMsg.bodyptr = pSirSmeSwitchChInd;

View file

@ -907,7 +907,6 @@ QDF_STATUS wlansap_acs_chselect(void *pvos_gctx,
tpWLAN_SAPEventCB pacs_event_callback,
tsap_Config_t *pconfig,
void *pusr_context);
eCsrPhyMode wlansap_get_phymode(void *pctx);
#ifdef __cplusplus
}
#endif

View file

@ -2871,19 +2871,23 @@ QDF_STATUS sap_signal_hdd_event(ptSapContext sap_ctx,
* follows pri AP
*/
sap_ctx->acs_cfg->pri_ch = sap_ctx->channel;
sap_ctx->acs_cfg->ch_width = sap_ctx->ch_params.ch_width;
sap_config_acs_result(hal, sap_ctx, sap_ctx->secondary_ch);
sap_ctx->acs_cfg->ch_width =
sap_ctx->csr_roamProfile.ch_params.ch_width;
sap_config_acs_result(hal, sap_ctx,
sap_ctx->csr_roamProfile.ch_params.sec_ch_offset);
sap_ap_event.sapHddEventCode = eSAP_CHANNEL_CHANGE_EVENT;
acs_selected = &sap_ap_event.sapevt.sap_ch_selected;
acs_selected->pri_ch = sap_ctx->acs_cfg->pri_ch;
acs_selected->ht_sec_ch = sap_ctx->acs_cfg->ht_sec_ch;
acs_selected->ch_width = sap_ctx->acs_cfg->ch_width;
acs_selected->ht_sec_ch =
sap_ctx->csr_roamProfile.ch_params.sec_ch_offset;
acs_selected->ch_width =
sap_ctx->csr_roamProfile.ch_params.ch_width;
acs_selected->vht_seg0_center_ch =
sap_ctx->acs_cfg->vht_seg0_center_ch;
sap_ctx->csr_roamProfile.ch_params.center_freq_seg0;
acs_selected->vht_seg1_center_ch =
sap_ctx->acs_cfg->vht_seg1_center_ch;
sap_ctx->csr_roamProfile.ch_params.center_freq_seg1;
break;
case eSAP_DFS_NOL_GET:

View file

@ -2310,9 +2310,22 @@ wlansap_channel_change_request(void *pSapCtx, uint8_t target_channel)
*/
sapContext->channel = target_channel;
sapContext->csr_roamProfile.ch_params.ch_width = ch_params->ch_width;
sapContext->csr_roamProfile.ch_params.sec_ch_offset =
ch_params->sec_ch_offset;
sapContext->csr_roamProfile.ch_params.center_freq_seg0 =
ch_params->center_freq_seg0;
sapContext->csr_roamProfile.ch_params.center_freq_seg1 =
ch_params->center_freq_seg1;
qdf_ret_status = sme_roam_channel_change_req(hHal, sapContext->bssid,
ch_params, &sapContext->csr_roamProfile);
QDF_TRACE(QDF_MODULE_ID_SAP, QDF_TRACE_LEVEL_INFO,
"%s: chan:%d width:%d offset:%d seg0:%d seg1:%d",
__func__, sapContext->channel, ch_params->ch_width,
ch_params->sec_ch_offset, ch_params->center_freq_seg0,
ch_params->center_freq_seg1);
if (qdf_ret_status == QDF_STATUS_SUCCESS) {
sap_signal_hdd_event(sapContext, NULL,
eSAP_CHANNEL_CHANGE_EVENT,
@ -3295,26 +3308,3 @@ void wlan_sap_enable_phy_error_logs(tHalHandle hal, bool enable_log)
tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal);
mac_ctx->sap.enable_dfs_phy_error_logs = enable_log;
}
/**
* wlansap_get_phymode() - get SAP phymode.
* @pctx: Pointer to the global vos context; a handle to SAP's control block
* can be extracted from its context. When MBSSID feature is enabled,
* SAP context is directly passed to SAP APIs.
*
* This function provides current phymode of SAP interface.
*
* Return: phymode with eCsrPhyMode type.
*/
eCsrPhyMode
wlansap_get_phymode(void *pctx)
{
ptSapContext sap_context = NULL;
sap_context = CDS_GET_SAP_CB(pctx);
if (NULL == sap_context) {
QDF_TRACE(QDF_MODULE_ID_SAP, QDF_TRACE_LEVEL_ERROR,
"%s: Invalid SAP pointer from pctx", __func__);
return eCSR_DOT11_MODE_AUTO;
}
return sap_context->csr_roamProfile.phyMode;
}

View file

@ -10341,6 +10341,14 @@ csr_roam_chk_lnk_swt_ch_ind(tpAniSirGlobal mac_ctx, tSirSmeRsp *msg_ptr)
qdf_mem_set(&roamInfo, sizeof(tCsrRoamInfo), 0);
roamInfo.chan_info.chan_id = pSwitchChnInd->newChannelId;
roamInfo.chan_info.ch_width =
pSwitchChnInd->chan_params.ch_width;
roamInfo.chan_info.sec_ch_offset =
pSwitchChnInd->chan_params.sec_ch_offset;
roamInfo.chan_info.band_center_freq1 =
pSwitchChnInd->chan_params.center_freq_seg0;
roamInfo.chan_info.band_center_freq2 =
pSwitchChnInd->chan_params.center_freq_seg1;
status = csr_roam_call_callback(mac_ctx, sessionId,
&roamInfo, 0, eCSR_ROAM_STA_CHANNEL_SWITCH,
eCSR_ROAM_RESULT_NONE);