Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit aa17c3a0 authored by Abhishek's avatar Abhishek
Browse files

wlan: Notify upper layer about channel change after CSA is done

Currently channel change info is not being reflected in
iw wlan0 link or in wpa_cli. This change updates the flow
in eCSR_ROAM_STA_CHANNEL_SWITCH where it updates about the
channel change info after Channel Switch Announcement is
processed in case of sta using cfg80211_ch_switch_notify.

Change-Id: I3cab261506ca5f6c1922fe9c6b06f4964cdee4cc
CRs-Fixed: 2769278
parent b01bf123
Loading
Loading
Loading
Loading
+18 −0
Original line number Diff line number Diff line
@@ -2314,6 +2314,24 @@ void hdd_disable_roaming(hdd_context_t *hdd_ctx);
 */
void hdd_restore_roaming(hdd_context_t *hdd_ctx);

/**
 * hdd_chan_change_notify() - Function to notify about channel change
 * @adapter: pointer to adapter
 * @dev: Net device structure
 * @oper_chan: New operating channel
 * @phy_mode: phy mode
 *
 * This function is used to notify hostapd/supplicant about the channel change
 *
 * Return: Success on intimating userspace
 *
 */
VOS_STATUS hdd_chan_change_notify(hdd_adapter_t *adapter,
        struct net_device *dev,
        uint8_t oper_chan,
        eCsrPhyMode phy_mode);


int wlan_hdd_check_and_stop_mon(hdd_adapter_t *sta_adapter, bool wait);

/**
+19 −0
Original line number Diff line number Diff line
@@ -4414,6 +4414,7 @@ eHalStatus hdd_smeRoamCallback( void *pContext, tCsrRoamInfo *pRoamInfo, tANI_U3
       case eCSR_ROAM_STA_CHANNEL_SWITCH:
         {
             hdd_adapter_t *pHostapdAdapter = NULL;
             eCsrPhyMode phy_mode = 0;
             pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
             pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);

@@ -4428,6 +4429,24 @@ eHalStatus hdd_smeRoamCallback( void *pContext, tCsrRoamInfo *pRoamInfo, tANI_U3
             pHddStaCtx->conn_info.operationChannel =
                 pRoamInfo->chan_info.chan_id;

             if(pRoamInfo->pProfile) {
                 phy_mode = pRoamInfo->pProfile->phyMode;
             }

             status = hdd_chan_change_notify(pAdapter,
                                             pAdapter->dev,
                                             pRoamInfo->chan_info.chan_id,
                                             phy_mode);

             if(status != VOS_STATUS_SUCCESS) {
                 hddLog(VOS_TRACE_LEVEL_ERROR,
                        "%s: hdd_chan_change_notify failed", __func__);
             }

             hddLog(VOS_TRACE_LEVEL_ERROR,
                    "%s: Channel switch event updated to upper layer to %d",
                    __func__, pRoamInfo->chan_info.chan_id);

             pHostapdAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_SOFTAP);
             if (pHostapdAdapter &&
                    (test_bit(SOFTAP_BSS_STARTED,
+8 −146
Original line number Diff line number Diff line
@@ -1023,149 +1023,6 @@ wlansap_get_phymode(v_PVOID_t pctx)
   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);

#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4,14,0))
   chan = ieee80211_get_channel(hostapd_adapter->wdev.wiphy, freq);
#else
   chan = __ieee80211_get_channel(hostapd_adapter->wdev.wiphy, freq);
#endif

   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.channelBondingAPMode24GHz);
   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;
}

/**
 * hdd_convert_dot11mode_from_phymode() - get dot11mode to phymode
 * @phymode: phy mode
@@ -1735,10 +1592,15 @@ VOS_STATUS hdd_hostapd_SAPEventCB( tpSap_Event pSapEvent, v_PVOID_t usrDataForCa
            }
            return VOS_STATUS_SUCCESS;
        case eSAP_CHANNEL_CHANGED_EVENT:
        {
            eCsrPhyMode phy_mode = wlansap_get_phymode(
                          (WLAN_HDD_GET_CTX(pHostapdAdapter))->pvosContext);

            hddLog(LOG1, FL("Received eSAP_CHANNEL_CHANGED_EVENT event"));

            return hdd_chan_change_notify(pHostapdAdapter, dev,
                           pSapEvent->sapevt.sap_chan_selected.new_chan);
                           pSapEvent->sapevt.sap_chan_selected.new_chan, phy_mode);
        }
        case eSAP_STA_LOSTLINK_DETECTED:
        {
            tSap_StationDisassocCompleteEvent *disassoc_comp =
+130 −0
Original line number Diff line number Diff line
@@ -10536,6 +10536,136 @@ void hdd_restore_roaming(hdd_context_t *hdd_ctx)
					CFG_LFR_FEATURE_ENABLED_MAX);
}
/**
 * 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);
}
VOS_STATUS hdd_chan_change_notify(hdd_adapter_t *adapter,
   struct net_device *dev, uint8_t oper_chan, eCsrPhyMode phy_mode)
{
   struct ieee80211_channel *chan;
   struct cfg80211_chan_def chandef;
   enum nl80211_channel_type channel_type;
   ePhyChanBondState cb_mode;
   uint32_t freq;
   tHalHandle  hal = WLAN_HDD_GET_HAL_CTX(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);
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4,14,0))
   chan = ieee80211_get_channel(adapter->wdev.wiphy, freq);
#else
   chan = __ieee80211_get_channel(adapter->wdev.wiphy, freq);
#endif
   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;
   }
   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_stop_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter,
                             const v_BOOL_t bCloseSession )
{