diff --git a/core/hdd/inc/wlan_hdd_main.h b/core/hdd/inc/wlan_hdd_main.h index c01dd8f3821e..1cca60c81d8f 100644 --- a/core/hdd/inc/wlan_hdd_main.h +++ b/core/hdd/inc/wlan_hdd_main.h @@ -1665,8 +1665,8 @@ struct hdd_context_s { bool dfs_cac_offload; bool reg_offload; #ifdef FEATURE_WLAN_CH_AVOID - tHddAvoidFreqList coex_avoid_freq_list; - tHddAvoidFreqList dnbs_avoid_freq_list; + struct ch_avoid_ind_type coex_avoid_freq_list; + struct ch_avoid_ind_type dnbs_avoid_freq_list; /* Lock to control access to dnbs and coex avoid freq list */ struct mutex avoid_freq_lock; #endif @@ -2334,8 +2334,10 @@ static inline void hdd_enable_fastpath(struct hdd_config *hdd_cfg, } #endif void hdd_wlan_update_target_info(hdd_context_t *hdd_ctx, void *context); +void hdd_ch_avoid_ind(hdd_context_t *hdd_ctxt, + struct unsafe_ch_list *unsafe_chan_list, + struct ch_avoid_ind_type *avoid_freq_list); enum sap_acs_dfs_mode wlan_hdd_get_dfs_mode(enum dfs_mode mode); -void hdd_ch_avoid_cb(void *hdd_context, void *indi_param); void hdd_unsafe_channel_restart_sap(hdd_context_t *hdd_ctx); int hdd_enable_disable_ca_event(hdd_context_t *hddctx, uint8_t set_value); diff --git a/core/hdd/src/wlan_hdd_cfg80211.c b/core/hdd/src/wlan_hdd_cfg80211.c index 27ffff6e09e6..e7b4d99b270c 100644 --- a/core/hdd/src/wlan_hdd_cfg80211.c +++ b/core/hdd/src/wlan_hdd_cfg80211.c @@ -803,24 +803,25 @@ wlan_hdd_cfg80211_get_tdls_capabilities(struct wiphy *wiphy, static void wlan_hdd_cfg80211_start_pending_acs(struct work_struct *work); #endif -int wlan_hdd_merge_avoid_freqs(tHddAvoidFreqList *destFreqList, - tHddAvoidFreqList *srcFreqList) +int wlan_hdd_merge_avoid_freqs(struct ch_avoid_ind_type *destFreqList, + struct ch_avoid_ind_type *srcFreqList) { int i; - tHddAvoidFreqRange *avoidRange = - &destFreqList->avoidFreqRange[destFreqList->avoidFreqRangeCount]; + struct ch_avoid_freq_type *avoid_range = + &destFreqList->avoid_freq_range[destFreqList->ch_avoid_range_cnt]; - destFreqList->avoidFreqRangeCount += srcFreqList->avoidFreqRangeCount; - if (destFreqList->avoidFreqRangeCount > HDD_MAX_AVOID_FREQ_RANGES) { + destFreqList->ch_avoid_range_cnt += srcFreqList->ch_avoid_range_cnt; + if (destFreqList->ch_avoid_range_cnt > HDD_MAX_AVOID_FREQ_RANGES) { hdd_err("avoid freq overflow"); return -EINVAL; } - for (i = 0; i < srcFreqList->avoidFreqRangeCount; i++) { - avoidRange->startFreq = - srcFreqList->avoidFreqRange[i].startFreq; - avoidRange->endFreq = srcFreqList->avoidFreqRange[i].endFreq; - avoidRange++; + for (i = 0; i < srcFreqList->ch_avoid_range_cnt; i++) { + avoid_range->start_freq = + srcFreqList->avoid_freq_range[i].start_freq; + avoid_range->end_freq = + srcFreqList->avoid_freq_range[i].end_freq; + avoid_range++; } return 0; } @@ -830,7 +831,7 @@ int wlan_hdd_merge_avoid_freqs(tHddAvoidFreqList *destFreqList, * avoid frequency range event to userspace */ int wlan_hdd_send_avoid_freq_event(hdd_context_t *pHddCtx, - tHddAvoidFreqList *pAvoidFreqList) + struct ch_avoid_ind_type *avoid_freq_list) { struct sk_buff *vendor_event; @@ -841,23 +842,23 @@ int wlan_hdd_send_avoid_freq_event(hdd_context_t *pHddCtx, return -EINVAL; } - if (!pAvoidFreqList) { - hdd_err("pAvoidFreqList is null"); + if (!avoid_freq_list) { + hdd_err("avoid_freq_list is null"); return -EINVAL; } vendor_event = cfg80211_vendor_event_alloc(pHddCtx->wiphy, - NULL, - sizeof(tHddAvoidFreqList), - QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY_INDEX, - GFP_KERNEL); + NULL, sizeof(struct ch_avoid_ind_type), + QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY_INDEX, + GFP_KERNEL); + if (!vendor_event) { hdd_err("cfg80211_vendor_event_alloc failed"); return -EINVAL; } - memcpy(skb_put(vendor_event, sizeof(tHddAvoidFreqList)), - (void *)pAvoidFreqList, sizeof(tHddAvoidFreqList)); + memcpy(skb_put(vendor_event, sizeof(struct ch_avoid_ind_type)), + (void *)avoid_freq_list, sizeof(struct ch_avoid_ind_type)); cfg80211_vendor_event(vendor_event, GFP_KERNEL); @@ -908,7 +909,7 @@ int wlan_hdd_get_adjacent_chan(uint8_t chan, bool upper) */ int wlan_hdd_send_avoid_freq_for_dnbs(hdd_context_t *pHddCtx, uint8_t op_chan) { - tHddAvoidFreqList p2p_avoid_freq_list; + struct ch_avoid_ind_type p2p_avoid_freq_list; uint8_t min_chan, max_chan; int ret; int chan; @@ -920,7 +921,7 @@ int wlan_hdd_send_avoid_freq_for_dnbs(hdd_context_t *pHddCtx, uint8_t op_chan) return -EINVAL; } - qdf_mem_zero(&p2p_avoid_freq_list, sizeof(tHddAvoidFreqList)); + qdf_mem_zero(&p2p_avoid_freq_list, sizeof(struct ch_avoid_ind_type)); /* * If channel passed is zero, clear the avoid_freq list in application. */ @@ -928,11 +929,11 @@ int wlan_hdd_send_avoid_freq_for_dnbs(hdd_context_t *pHddCtx, uint8_t op_chan) #ifdef FEATURE_WLAN_CH_AVOID mutex_lock(&pHddCtx->avoid_freq_lock); qdf_mem_zero(&pHddCtx->dnbs_avoid_freq_list, - sizeof(tHddAvoidFreqList)); - if (pHddCtx->coex_avoid_freq_list.avoidFreqRangeCount) + sizeof(struct ch_avoid_ind_type)); + if (pHddCtx->coex_avoid_freq_list.ch_avoid_range_cnt) memcpy(&p2p_avoid_freq_list, &pHddCtx->coex_avoid_freq_list, - sizeof(tHddAvoidFreqList)); + sizeof(struct ch_avoid_ind_type)); mutex_unlock(&pHddCtx->avoid_freq_lock); #endif ret = wlan_hdd_send_avoid_freq_event(pHddCtx, @@ -956,52 +957,52 @@ int wlan_hdd_send_avoid_freq_for_dnbs(hdd_context_t *pHddCtx, uint8_t op_chan) } if ((op_chan > min_chan) && (op_chan < max_chan)) { - p2p_avoid_freq_list.avoidFreqRangeCount = 2; - p2p_avoid_freq_list.avoidFreqRange[0].startFreq = + p2p_avoid_freq_list.ch_avoid_range_cnt = 2; + p2p_avoid_freq_list.avoid_freq_range[0].start_freq = wlan_chan_to_freq(min_chan); /* Get channel before the op_chan */ chan = wlan_hdd_get_adjacent_chan(op_chan, false); if (chan < 0) return -EINVAL; - p2p_avoid_freq_list.avoidFreqRange[0].endFreq = + p2p_avoid_freq_list.avoid_freq_range[0].end_freq = wlan_chan_to_freq(chan); /* Get channel next to the op_chan */ chan = wlan_hdd_get_adjacent_chan(op_chan, true); if (chan < 0) return -EINVAL; - p2p_avoid_freq_list.avoidFreqRange[1].startFreq = + p2p_avoid_freq_list.avoid_freq_range[1].start_freq = wlan_chan_to_freq(chan); - p2p_avoid_freq_list.avoidFreqRange[1].endFreq = + p2p_avoid_freq_list.avoid_freq_range[1].end_freq = wlan_chan_to_freq(max_chan); } else if (op_chan == min_chan) { - p2p_avoid_freq_list.avoidFreqRangeCount = 1; + p2p_avoid_freq_list.ch_avoid_range_cnt = 1; chan = wlan_hdd_get_adjacent_chan(op_chan, true); if (chan < 0) return -EINVAL; - p2p_avoid_freq_list.avoidFreqRange[0].startFreq = + p2p_avoid_freq_list.avoid_freq_range[0].start_freq = wlan_chan_to_freq(chan); - p2p_avoid_freq_list.avoidFreqRange[0].endFreq = + p2p_avoid_freq_list.avoid_freq_range[0].end_freq = wlan_chan_to_freq(max_chan); } else { - p2p_avoid_freq_list.avoidFreqRangeCount = 1; - p2p_avoid_freq_list.avoidFreqRange[0].startFreq = + p2p_avoid_freq_list.ch_avoid_range_cnt = 1; + p2p_avoid_freq_list.avoid_freq_range[0].start_freq = wlan_chan_to_freq(min_chan); chan = wlan_hdd_get_adjacent_chan(op_chan, false); if (chan < 0) return -EINVAL; - p2p_avoid_freq_list.avoidFreqRange[0].endFreq = + p2p_avoid_freq_list.avoid_freq_range[0].end_freq = wlan_chan_to_freq(chan); } #ifdef FEATURE_WLAN_CH_AVOID mutex_lock(&pHddCtx->avoid_freq_lock); pHddCtx->dnbs_avoid_freq_list = p2p_avoid_freq_list; - if (pHddCtx->coex_avoid_freq_list.avoidFreqRangeCount) { + if (pHddCtx->coex_avoid_freq_list.ch_avoid_range_cnt) { ret = wlan_hdd_merge_avoid_freqs(&p2p_avoid_freq_list, &pHddCtx->coex_avoid_freq_list); if (ret) { diff --git a/core/hdd/src/wlan_hdd_cfg80211.h b/core/hdd/src/wlan_hdd_cfg80211.h index f6bbde19adc2..02281cf6e563 100644 --- a/core/hdd/src/wlan_hdd_cfg80211.h +++ b/core/hdd/src/wlan_hdd_cfg80211.h @@ -327,7 +327,7 @@ void wlan_hdd_testmode_rx_event(void *buf, size_t buf_len); #endif int wlan_hdd_send_avoid_freq_event(hdd_context_t *pHddCtx, - tHddAvoidFreqList * pAvoidFreqList); + struct ch_avoid_ind_type *avoid_freq_list); int wlan_hdd_send_avoid_freq_for_dnbs(hdd_context_t *pHddCtx, uint8_t op_chan); @@ -573,8 +573,9 @@ int wlan_hdd_get_adjacent_chan(uint8_t chan, bool upper); * * Merges two avoid_frequency lists */ -int wlan_hdd_merge_avoid_freqs(tHddAvoidFreqList *destFreqList, - tHddAvoidFreqList *srcFreqList); +int wlan_hdd_merge_avoid_freqs(struct ch_avoid_ind_type *destFreqList, + struct ch_avoid_ind_type *srcFreqList); + /** * hdd_bt_activity_cb() - callback function to receive bt activity diff --git a/core/hdd/src/wlan_hdd_main.c b/core/hdd/src/wlan_hdd_main.c index 008837fbb835..99ebb2834ecf 100644 --- a/core/hdd/src/wlan_hdd_main.c +++ b/core/hdd/src/wlan_hdd_main.c @@ -7090,176 +7090,6 @@ next_adapater: } } -/** - * hdd_ch_avoid_cb() - Avoid notified channels from FW handler - * @adapter: HDD adapter pointer - * @indParam: Channel avoid notification parameter - * - * Avoid channel notification from FW handler. - * FW will send un-safe channel list to avoid over wrapping. - * hostapd should not use notified channel - * - * Return: None - */ -void hdd_ch_avoid_cb(void *hdd_context, void *indi_param) -{ - hdd_context_t *hdd_ctxt; - tSirChAvoidIndType *ch_avoid_indi; - uint8_t range_loop; - enum channel_enum channel_loop, start_channel_idx = INVALID_CHANNEL, - end_channel_idx = INVALID_CHANNEL; - uint16_t start_channel; - uint16_t end_channel; - v_CONTEXT_t cds_context; - tHddAvoidFreqList hdd_avoid_freq_list; - uint32_t i; - - /* Basic sanity */ - if (!hdd_context || !indi_param) { - hdd_err("Invalid arguments"); - return; - } - - hdd_ctxt = (hdd_context_t *) hdd_context; - ch_avoid_indi = (tSirChAvoidIndType *) indi_param; - cds_context = hdd_ctxt->pcds_context; - - /* Make unsafe channel list */ - hdd_debug("band count %d", - ch_avoid_indi->avoid_range_count); - - /* generate vendor specific event */ - qdf_mem_zero((void *)&hdd_avoid_freq_list, sizeof(tHddAvoidFreqList)); - for (i = 0; i < ch_avoid_indi->avoid_range_count; i++) { - hdd_avoid_freq_list.avoidFreqRange[i].startFreq = - ch_avoid_indi->avoid_freq_range[i].start_freq; - hdd_avoid_freq_list.avoidFreqRange[i].endFreq = - ch_avoid_indi->avoid_freq_range[i].end_freq; - } - hdd_avoid_freq_list.avoidFreqRangeCount = - ch_avoid_indi->avoid_range_count; - - mutex_lock(&hdd_ctxt->avoid_freq_lock); - hdd_ctxt->coex_avoid_freq_list = hdd_avoid_freq_list; - mutex_unlock(&hdd_ctxt->avoid_freq_lock); - - /* clear existing unsafe channel cache */ - hdd_ctxt->unsafe_channel_count = 0; - qdf_mem_zero(hdd_ctxt->unsafe_channel_list, - sizeof(hdd_ctxt->unsafe_channel_list)); - - for (range_loop = 0; range_loop < ch_avoid_indi->avoid_range_count; - range_loop++) { - if (hdd_ctxt->unsafe_channel_count >= NUM_CHANNELS) { - hdd_warn("LTE Coex unsafe channel list full"); - break; - } - - start_channel = ieee80211_frequency_to_channel( - ch_avoid_indi->avoid_freq_range[range_loop].start_freq); - end_channel = ieee80211_frequency_to_channel( - ch_avoid_indi->avoid_freq_range[range_loop].end_freq); - hdd_debug("start %d : %d, end %d : %d", - ch_avoid_indi->avoid_freq_range[range_loop].start_freq, - start_channel, - ch_avoid_indi->avoid_freq_range[range_loop].end_freq, - end_channel); - - /* do not process frequency bands that are not mapped to - * predefined channels - */ - if (start_channel == 0 || end_channel == 0) - continue; - - for (channel_loop = CHAN_ENUM_1; channel_loop <= - CHAN_ENUM_184; channel_loop++) { - if (WLAN_REG_CH_TO_FREQ(channel_loop) >= - ch_avoid_indi->avoid_freq_range[ - range_loop].start_freq) { - start_channel_idx = channel_loop; - break; - } - } - for (channel_loop = CHAN_ENUM_1; channel_loop <= - CHAN_ENUM_184; channel_loop++) { - if (WLAN_REG_CH_TO_FREQ(channel_loop) >= - ch_avoid_indi->avoid_freq_range[ - range_loop].end_freq) { - end_channel_idx = channel_loop; - if (WLAN_REG_CH_TO_FREQ(channel_loop) > - ch_avoid_indi->avoid_freq_range[ - range_loop].end_freq) - end_channel_idx--; - break; - } - } - - if (start_channel_idx == INVALID_CHANNEL || - end_channel_idx == INVALID_CHANNEL) - continue; - - for (channel_loop = start_channel_idx; channel_loop <= - end_channel_idx; channel_loop++) { - hdd_ctxt->unsafe_channel_list[ - hdd_ctxt->unsafe_channel_count++] = - WLAN_REG_CH_NUM(channel_loop); - if (hdd_ctxt->unsafe_channel_count >= - NUM_CHANNELS) { - hdd_warn("LTECoex unsafe ch list full"); - break; - } - } - } - - hdd_debug("number of unsafe channels is %d ", - hdd_ctxt->unsafe_channel_count); - - if (pld_set_wlan_unsafe_channel(hdd_ctxt->parent_dev, - hdd_ctxt->unsafe_channel_list, - hdd_ctxt->unsafe_channel_count)) { - hdd_err("Failed to set unsafe channel"); - - /* clear existing unsafe channel cache */ - hdd_ctxt->unsafe_channel_count = 0; - qdf_mem_zero(hdd_ctxt->unsafe_channel_list, - sizeof(hdd_ctxt->unsafe_channel_list)); - - return; - } - - for (channel_loop = 0; - channel_loop < hdd_ctxt->unsafe_channel_count; channel_loop++) { - hdd_debug("channel %d is not safe ", - hdd_ctxt->unsafe_channel_list[channel_loop]); - } - - mutex_lock(&hdd_ctxt->avoid_freq_lock); - if (hdd_ctxt->dnbs_avoid_freq_list.avoidFreqRangeCount) - if (wlan_hdd_merge_avoid_freqs(&hdd_avoid_freq_list, - &hdd_ctxt->dnbs_avoid_freq_list)) { - mutex_unlock(&hdd_ctxt->avoid_freq_lock); - hdd_debug("unable to merge avoid freqs"); - return; - } - mutex_unlock(&hdd_ctxt->avoid_freq_lock); - /* - * first update the unsafe channel list to the platform driver and - * send the avoid freq event to the application - */ - if (hdd_ctxt->config->restart_beaconing_on_chan_avoid_event) { - wlan_hdd_send_avoid_freq_event(hdd_ctxt, &hdd_avoid_freq_list); - - if (!hdd_ctxt->unsafe_channel_count) { - hdd_info("no unsafe channels - not restarting SAP"); - return; - } - - hdd_unsafe_channel_restart_sap(hdd_ctxt); - } - - return; -} - /** * hdd_init_channel_avoidance() - Initialize channel avoidance * @hdd_ctx: HDD global context @@ -7293,8 +7123,6 @@ static void hdd_init_channel_avoidance(hdd_context_t *hdd_ctx) } - /* Plug in avoid channel notification callback */ - sme_add_ch_avoid_callback(hdd_ctx->hHal, hdd_ch_avoid_cb); } #else static void hdd_init_channel_avoidance(hdd_context_t *hdd_ctx) diff --git a/core/hdd/src/wlan_hdd_regulatory.c b/core/hdd/src/wlan_hdd_regulatory.c index cc1d83ae82de..6656677c9fe4 100644 --- a/core/hdd/src/wlan_hdd_regulatory.c +++ b/core/hdd/src/wlan_hdd_regulatory.c @@ -38,6 +38,7 @@ #include "wlan_hdd_regulatory.h" #include #include "cds_regdomain.h" +#include "pld_common.h" #define REG_RULE_2412_2462 REG_RULE(2412-10, 2462+10, 40, 0, 20, 0) @@ -845,10 +846,85 @@ static void fill_wiphy_band_channels(struct wiphy *wiphy, } } +/** + * hdd_ch_avoid_ind() - Avoid notified channels from FW handler + * @adapter: HDD adapter pointer + * @indParam: Channel avoid notification parameter + * + * Avoid channel notification from FW handler. + * FW will send un-safe channel list to avoid over wrapping. + * hostapd should not use notified channel + * + * Return: None + */ +void hdd_ch_avoid_ind(hdd_context_t *hdd_ctxt, + struct unsafe_ch_list *unsafe_chan_list, + struct ch_avoid_ind_type *avoid_freq_list) +{ + + /* Basic sanity */ + if (!hdd_ctxt) { + hdd_err("Invalid arguments"); + return; + } + + mutex_lock(&hdd_ctxt->avoid_freq_lock); + qdf_mem_copy(&hdd_ctxt->coex_avoid_freq_list, avoid_freq_list, + sizeof(struct ch_avoid_ind_type)); + mutex_unlock(&hdd_ctxt->avoid_freq_lock); + + /* clear existing unsafe channel cache */ + hdd_ctxt->unsafe_channel_count = 0; + qdf_mem_zero(hdd_ctxt->unsafe_channel_list, + sizeof(hdd_ctxt->unsafe_channel_list)); + + hdd_ctxt->unsafe_channel_count = unsafe_chan_list->ch_cnt; + + qdf_mem_copy(hdd_ctxt->unsafe_channel_list, unsafe_chan_list->ch_list, + sizeof(hdd_ctxt->unsafe_channel_list)); + hdd_debug("number of unsafe channels is %d ", + hdd_ctxt->unsafe_channel_count); + + if (pld_set_wlan_unsafe_channel(hdd_ctxt->parent_dev, + hdd_ctxt->unsafe_channel_list, + hdd_ctxt->unsafe_channel_count)) { + hdd_err("Failed to set unsafe channel"); + + /* clear existing unsafe channel cache */ + hdd_ctxt->unsafe_channel_count = 0; + qdf_mem_zero(hdd_ctxt->unsafe_channel_list, + sizeof(hdd_ctxt->unsafe_channel_list)); + + return; + } + + mutex_lock(&hdd_ctxt->avoid_freq_lock); + if (hdd_ctxt->dnbs_avoid_freq_list.ch_avoid_range_cnt) + if (wlan_hdd_merge_avoid_freqs(avoid_freq_list, + &hdd_ctxt->dnbs_avoid_freq_list)) { + mutex_unlock(&hdd_ctxt->avoid_freq_lock); + hdd_debug("unable to merge avoid freqs"); + return; + } + mutex_unlock(&hdd_ctxt->avoid_freq_lock); + /* + * first update the unsafe channel list to the platform driver and + * send the avoid freq event to the application + */ + wlan_hdd_send_avoid_freq_event(hdd_ctxt, avoid_freq_list); + + if (!hdd_ctxt->unsafe_channel_count) { + hdd_debug("no unsafe channels - not restarting SAP"); + return; + } + hdd_unsafe_channel_restart_sap(hdd_ctxt); +} + static void hdd_regulatory_dyn_cbk(struct wlan_objmgr_psoc *psoc, struct wlan_objmgr_pdev *pdev, struct regulatory_channel *chan_list, + struct avoid_freq_ind_data *avoid_freq_ind, void *arg) { struct wiphy *wiphy; @@ -872,6 +948,10 @@ static void hdd_regulatory_dyn_cbk(struct wlan_objmgr_psoc *psoc, sme_generic_change_country_code(hdd_ctx->hHal, hdd_ctx->reg.alpha2); + + if (avoid_freq_ind) + hdd_ch_avoid_ind(hdd_ctx, &avoid_freq_ind->chan_list, + &avoid_freq_ind->freq_list); } /**