wlan: Notify new channel of the SAP to CFG layer
Adds changes to notify the new channel of the SAP to CFG layer.
Change-Id: Ie917003748a6c88d8fd9014e71aceaf7a88328b7
CRs-Fixed: 2143138
diff --git a/CORE/HDD/src/wlan_hdd_hostapd.c b/CORE/HDD/src/wlan_hdd_hostapd.c
index 235e0a6..2a5e376 100644
--- a/CORE/HDD/src/wlan_hdd_hostapd.c
+++ b/CORE/HDD/src/wlan_hdd_hostapd.c
@@ -844,6 +844,170 @@
}
#endif
+/**
+* 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.
+*/
+static eCsrPhyMode
+wlansap_get_phymode(v_PVOID_t pctx)
+{
+ ptSapContext psapctx = VOS_GET_SAP_CB(pctx);
+
+ if (!psapctx) {
+ VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR,
+ "%s: Invalid SAP pointer from pCtx", __func__);
+ return eCSR_DOT11_MODE_AUTO;
+ }
+ return psapctx->csrRoamProfile.phyMode;
+}
+
+/**
+ * hdd_update_chandef() - Function to update channel width and center freq
+ * @chandef: cfg80211 chan def
+ * @cb_mode: chan offset
+ *
+ * This function will be called to update channel width and center freq
+ *
+ * Return: None
+ */
+static void
+hdd_update_chandef(struct cfg80211_chan_def *chandef,
+ ePhyChanBondState cb_mode)
+{
+ uint8_t center_chan, chan;
+
+ if (cb_mode <= PHY_DOUBLE_CHANNEL_HIGH_PRIMARY)
+ return;
+
+ chan = vos_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 = vos_chan_to_freq(center_chan);
+}
+
+/**
+ * hdd_chan_change_notify() - Function to notify hostapd about channel change
+ * @hostapd_adapter: hostapd adapter
+ * @dev: Net device structure
+ * @oper_chan: New operating channel
+ *
+ * This function is used to notify hostapd about the channel change
+ *
+ * Return: Success on intimating userspace
+ *
+ */
+static VOS_STATUS hdd_chan_change_notify(hdd_adapter_t *hostapd_adapter,
+ struct net_device *dev, uint8_t oper_chan)
+{
+ 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(hostapd_adapter);
+ tSmeConfigParams sme_config;
+
+ if (!hal) {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+ "%s: hal is NULL", __func__);
+ return VOS_STATUS_E_FAILURE;
+ }
+
+ freq = vos_chan_to_freq(oper_chan);
+
+ chan = __ieee80211_get_channel(hostapd_adapter->wdev.wiphy, freq);
+
+ if (!chan) {
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+ "%s: Invalid input frequency for channel conversion", __func__);
+ return VOS_STATUS_E_FAILURE;
+ }
+
+ phy_mode = wlansap_get_phymode(
+ (WLAN_HDD_GET_CTX(hostapd_adapter))->pvosContext);
+ sme_GetConfigParam(hal, &sme_config);
+ if (oper_chan <= 14)
+ cb_mode = sme_get_cb_phy_mode_from_cb_ini_mode(
+ sme_config.csrConfig.channelBondingMode24GHz);
+ else
+ cb_mode = sme_get_cb_phy_mode_from_cb_ini_mode(
+ sme_config.csrConfig.channelBondingMode5GHz);
+
+ 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:
+ switch (cb_mode) {
+ case PHY_SINGLE_CHANNEL_CENTERED:
+ channel_type = NL80211_CHAN_HT20;
+ break;
+ case PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_LOW:
+ case PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_CENTERED:
+ case PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_HIGH:
+ case PHY_DOUBLE_CHANNEL_HIGH_PRIMARY:
+ channel_type = NL80211_CHAN_HT40MINUS;
+ break;
+ case PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_LOW:
+ case PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_CENTERED:
+ case PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_HIGH:
+ case PHY_DOUBLE_CHANNEL_LOW_PRIMARY:
+ channel_type = NL80211_CHAN_HT40PLUS;
+ break;
+ default:
+ channel_type = NL80211_CHAN_HT20;
+ break;
+ }
+ break;
+ default:
+ channel_type = NL80211_CHAN_NO_HT;
+ break;
+ }
+
+ cfg80211_chandef_create(&chandef, chan, channel_type);
+ if ((phy_mode == eCSR_DOT11_MODE_11ac) ||
+ (phy_mode == eCSR_DOT11_MODE_11ac_ONLY))
+ hdd_update_chandef(&chandef, cb_mode);
+
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
+ "%s: phy_mode %d cb_mode %d chann_type %d oper_chan %d width %d freq_1 %d",
+ __func__, phy_mode, cb_mode, channel_type, oper_chan,
+ chandef.width, chandef.center_freq1);
+
+
+ cfg80211_ch_switch_notify(dev, &chandef);
+
+ return VOS_STATUS_SUCCESS;
+}
+
+
+
VOS_STATUS hdd_hostapd_SAPEventCB( tpSap_Event pSapEvent, v_PVOID_t usrDataForCallback)
{
hdd_adapter_t *pHostapdAdapter;
@@ -1315,7 +1479,11 @@
hddLog(LOGW, FL("hdd_stop_bss_link failed %d"), vos_status);
}
return VOS_STATUS_SUCCESS;
+ case eSAP_CHANNEL_CHANGED_EVENT:
+ hddLog(LOG1, FL("Received eSAP_CHANNEL_CHANGED_EVENT event"));
+ return hdd_chan_change_notify(pHostapdAdapter, dev,
+ pSapEvent->sapevt.sap_chan_selected.new_chan);
default:
hddLog(LOG1,"SAP message is not handled");
goto stopbss;