diff --git a/components/pmo/core/src/wlan_pmo_wow.c b/components/pmo/core/src/wlan_pmo_wow.c index 97a125cbdd..10e1081e46 100644 --- a/components/pmo/core/src/wlan_pmo_wow.c +++ b/components/pmo/core/src/wlan_pmo_wow.c @@ -427,4 +427,7 @@ void pmo_set_sap_wow_bitmask(uint32_t *bitmask, uint32_t wow_bitmap_size) pmo_set_wow_event_bitmap(WOW_SAP_OBSS_DETECTION_EVENT, wow_bitmap_size, bitmask); + pmo_set_wow_event_bitmap(WOW_BSS_COLOR_COLLISION_DETECT_EVENT, + wow_bitmap_size, + bitmask); } diff --git a/core/hdd/src/wlan_hdd_main.c b/core/hdd/src/wlan_hdd_main.c index fa6b5f414f..88374529df 100644 --- a/core/hdd/src/wlan_hdd_main.c +++ b/core/hdd/src/wlan_hdd_main.c @@ -2015,6 +2015,12 @@ void hdd_update_tgt_cfg(void *context, void *param) cfg->obss_detection_offloaded); if (QDF_IS_STATUS_ERROR(status)) hdd_err("Couldn't pass WNI_CFG_OBSS_DETECTION_OFFLOAD to CFG"); + + status = sme_cfg_set_int(hdd_ctx->hHal, + WNI_CFG_OBSS_COLOR_COLLISION_OFFLOAD, + cfg->obss_color_collision_offloaded); + if (QDF_IS_STATUS_ERROR(status)) + hdd_err("Failed to set WNI_CFG_OBSS_COLOR_COLLISION_OFFLOAD"); } bool hdd_dfs_indicate_radar(struct hdd_context *hdd_ctx) diff --git a/core/mac/inc/ani_global.h b/core/mac/inc/ani_global.h index 476319a0cf..c251278c49 100644 --- a/core/mac/inc/ani_global.h +++ b/core/mac/inc/ani_global.h @@ -832,6 +832,7 @@ typedef struct sAniSirLim { uint8_t beacon_probe_rsp_cnt_per_scan; wlan_scan_requester req_id; bool global_obss_offload_enabled; + bool global_obss_color_collision_det_offload; } tAniSirLim, *tpAniSirLim; struct mgmt_frm_reg_info { diff --git a/core/mac/inc/wni_cfg.h b/core/mac/inc/wni_cfg.h index 4c6bf4fb26..a99897f8f7 100644 --- a/core/mac/inc/wni_cfg.h +++ b/core/mac/inc/wni_cfg.h @@ -354,6 +354,7 @@ enum { WNI_CFG_EDCA_ETSI_ACVI, WNI_CFG_EDCA_ETSI_ACVO, WNI_CFG_OBSS_DETECTION_OFFLOAD, + WNI_CFG_OBSS_COLOR_COLLISION_OFFLOAD, /* Any new items to be added should be above this strictly */ CFG_PARAM_MAX_NUM }; diff --git a/core/mac/src/cfg/cfg_param_name.c b/core/mac/src/cfg/cfg_param_name.c index 857ea17f13..a646122b60 100644 --- a/core/mac/src/cfg/cfg_param_name.c +++ b/core/mac/src/cfg/cfg_param_name.c @@ -356,6 +356,7 @@ const char *cfg_get_string(uint16_t cfg_id) CASE_RETURN_STRING(WNI_CFG_EDCA_ETSI_ACVI); CASE_RETURN_STRING(WNI_CFG_EDCA_ETSI_ACVO); CASE_RETURN_STRING(WNI_CFG_OBSS_DETECTION_OFFLOAD); + CASE_RETURN_STRING(WNI_CFG_OBSS_COLOR_COLLISION_OFFLOAD); } return "invalid"; diff --git a/core/mac/src/cfg/cfg_proc_msg.c b/core/mac/src/cfg/cfg_proc_msg.c index 0644b84862..c1aae42601 100644 --- a/core/mac/src/cfg/cfg_proc_msg.c +++ b/core/mac/src/cfg/cfg_proc_msg.c @@ -1584,6 +1584,9 @@ cgstatic cfg_static[CFG_PARAM_MAX_NUM] = { {WNI_CFG_OBSS_DETECTION_OFFLOAD, CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT, 0, 1, 0}, + {WNI_CFG_OBSS_COLOR_COLLISION_OFFLOAD, + CFG_CTL_VALID | CFG_CTL_RE | CFG_CTL_WE | CFG_CTL_INT, + 0, 1, 0}, }; diff --git a/core/mac/src/include/sir_params.h b/core/mac/src/include/sir_params.h index 472992f4a5..ad84a0fc2f 100644 --- a/core/mac/src/include/sir_params.h +++ b/core/mac/src/include/sir_params.h @@ -694,6 +694,8 @@ struct sir_mgmt_msg { #define SIR_HAL_OBSS_DETECTION_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 393) #define SIR_HAL_OBSS_DETECTION_INFO (SIR_HAL_ITC_MSG_TYPES_BEGIN + 394) #define SIR_HAL_INVOKE_NEIGHBOR_REPORT (SIR_HAL_ITC_MSG_TYPES_BEGIN + 395) +#define SIR_HAL_OBSS_COLOR_COLLISION_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 396) +#define SIR_HAL_OBSS_COLOR_COLLISION_INFO (SIR_HAL_ITC_MSG_TYPES_BEGIN + 397) #define SIR_HAL_MSG_TYPES_END (SIR_HAL_MSG_TYPES_BEGIN + 0x1FF) /* CFG message types */ diff --git a/core/mac/src/pe/include/lim_session.h b/core/mac/src/pe/include/lim_session.h index c637d5cd17..6f79b35a57 100644 --- a/core/mac/src/pe/include/lim_session.h +++ b/core/mac/src/pe/include/lim_session.h @@ -100,6 +100,10 @@ typedef struct join_params { #define MAX_BSS_COLOR_VALUE 63 #define TIME_BEACON_NOT_UPDATED 30000 #define BSS_COLOR_SWITCH_COUNTDOWN 5 +#define OBSS_COLOR_COLLISION_DETECTION_STA_PERIOD_MS 10000 +#define OBSS_COLOR_COLLISION_DETECTION_AP_PERIOD_MS 5000 +#define OBSS_COLOR_COLLISION_SCAN_PERIOD_MS 200 +#define OBSS_COLOR_COLLISION_FREE_SLOT_EXPIRY_MS 50000 struct bss_color_info { qdf_time_t timestamp; uint64_t seen_count; @@ -555,6 +559,8 @@ typedef struct sPESession /* Added to Support BT-AMP */ bool recvd_deauth_while_roaming; bool recvd_disassoc_while_roaming; bool deauth_disassoc_rc; + enum wmi_obss_color_collision_evt_type obss_color_collision_dec_evt; + bool is_session_obss_color_collision_det_enabled; } tPESession, *tpPESession; /*------------------------------------------------------------------------- diff --git a/core/mac/src/pe/lim/lim_api.c b/core/mac/src/pe/lim/lim_api.c index 4ea1362384..6387ea7719 100644 --- a/core/mac/src/pe/lim/lim_api.c +++ b/core/mac/src/pe/lim/lim_api.c @@ -476,6 +476,14 @@ static tSirRetStatus __lim_init_config(tpAniSirGlobal pMac) return eSIR_FAILURE; } + if (eSIR_SUCCESS != + wlan_cfg_get_int(pMac, WNI_CFG_OBSS_COLOR_COLLISION_OFFLOAD, + (uint32_t *) &pMac->lim. + global_obss_color_collision_det_offload)) { + pe_err("cfg get obss_color_collision_offload failed"); + return eSIR_FAILURE; + } + return eSIR_SUCCESS; } diff --git a/core/mac/src/pe/lim/lim_process_message_queue.c b/core/mac/src/pe/lim/lim_process_message_queue.c index c22a69509e..898547a9a8 100644 --- a/core/mac/src/pe/lim/lim_process_message_queue.c +++ b/core/mac/src/pe/lim/lim_process_message_queue.c @@ -1921,6 +1921,11 @@ static void lim_process_messages(tpAniSirGlobal mac_ctx, qdf_mem_free((void *)msg->bodyptr); msg->bodyptr = NULL; break; + case WMA_OBSS_COLOR_COLLISION_INFO: + lim_process_obss_color_collision_info(mac_ctx, msg->bodyptr); + qdf_mem_free((void *)msg->bodyptr); + msg->bodyptr = NULL; + break; default: qdf_mem_free((void *)msg->bodyptr); msg->bodyptr = NULL; diff --git a/core/mac/src/pe/lim/lim_process_mlm_rsp_messages.c b/core/mac/src/pe/lim/lim_process_mlm_rsp_messages.c index 7977e1bc14..29ae3018b6 100644 --- a/core/mac/src/pe/lim/lim_process_mlm_rsp_messages.c +++ b/core/mac/src/pe/lim/lim_process_mlm_rsp_messages.c @@ -255,7 +255,9 @@ void lim_process_mlm_start_cnf(tpAniSirGlobal pMac, uint32_t *pMsgBuf) psessionEntry->ssId.ssId, psessionEntry->currentOperChannel); lim_send_beacon_ind(pMac, psessionEntry); - lim_enable_obss_detection_config (pMac, psessionEntry); + lim_enable_obss_detection_config(pMac, psessionEntry); + lim_send_obss_color_collision_cfg(pMac, psessionEntry, + OBSS_COLOR_COLLISION_DETECTION); } } } @@ -1564,6 +1566,8 @@ void lim_process_sta_mlm_add_sta_rsp(tpAniSirGlobal mac_ctx, * be passed in here */ mlm_assoc_cnf.resultCode = (tSirResultCodes) eSIR_SME_SUCCESS; + lim_send_obss_color_collision_cfg(mac_ctx, session_entry, + OBSS_COLOR_COLLISION_DETECTION); } else { pe_err("ADD_STA failed!"); if (session_entry->limSmeState == eLIM_SME_WT_REASSOC_STATE) diff --git a/core/mac/src/pe/lim/lim_process_sme_req_messages.c b/core/mac/src/pe/lim/lim_process_sme_req_messages.c index f9aea2f112..2a39975b99 100644 --- a/core/mac/src/pe/lim/lim_process_sme_req_messages.c +++ b/core/mac/src/pe/lim/lim_process_sme_req_messages.c @@ -5095,6 +5095,8 @@ static void lim_process_sme_start_beacon_req(tpAniSirGlobal pMac, uint32_t *pMsg psessionEntry->currentOperChannel); lim_send_beacon_ind(pMac, psessionEntry); lim_enable_obss_detection_config(pMac, psessionEntry); + lim_send_obss_color_collision_cfg(pMac, psessionEntry, + OBSS_COLOR_COLLISION_DETECTION); } else { pe_err("Invalid Beacon Start Indication"); return; @@ -5979,6 +5981,163 @@ static void lim_process_set_ie_req(tpAniSirGlobal mac_ctx, uint32_t *msg_buf) } #ifdef WLAN_FEATURE_11AX_BSS_COLOR + +/** + * obss_color_collision_process_color_disable() - Disable bss color + * @mac_ctx: Pointer to Global MAC structure + * @session: pointer to session + * + * This function will disbale bss color. + * + * Return: None + */ +static void obss_color_collision_process_color_disable(tpAniSirGlobal mac_ctx, + tpPESession session) +{ + tUpdateBeaconParams beacon_params; + + if (!session) { + pe_err("Invalid session"); + return; + } + + if (session->valid && !LIM_IS_AP_ROLE(session)) { + pe_err("Invalid SystemRole %d", + GET_LIM_SYSTEM_ROLE(session)); + return; + } + + if (session->bss_color_changing == 1) { + pe_warn("%d: color change in progress", session->smeSessionId); + /* Continue color collision detection */ + lim_send_obss_color_collision_cfg(mac_ctx, session, + OBSS_COLOR_COLLISION_DETECTION); + return; + } + + if (session->he_op.bss_col_disabled == 1) { + pe_warn("%d: bss color already disabled", + session->smeSessionId); + /* Continue free color detection */ + lim_send_obss_color_collision_cfg(mac_ctx, session, + OBSS_COLOR_FREE_SLOT_AVAILABLE); + return; + } + + qdf_mem_zero(&beacon_params, sizeof(beacon_params)); + beacon_params.paramChangeBitmap |= PARAM_BSS_COLOR_CHANGED; + session->he_op.bss_col_disabled = 1; + session->he_bss_color_change.new_color = 0; + session->he_op.bss_color = 0; + beacon_params.bss_color = 0; + beacon_params.bss_color_disabled = 1; + + if (sch_set_fixed_beacon_fields(mac_ctx, session) != + eSIR_SUCCESS) { + pe_err("Unable to set op mode IE in beacon"); + return; + } + + lim_send_beacon_params(mac_ctx, &beacon_params, session); + lim_send_obss_color_collision_cfg(mac_ctx, session, + OBSS_COLOR_FREE_SLOT_AVAILABLE); +} + +/** + * obss_color_collision_process_color_change() - Process bss color change + * @mac_ctx: Pointer to Global MAC structure + * @session: pointer to session + * @obss_color_info: obss color collision/free slot indication info + * + * This function selects new color ib case of bss color collision. + * + * Return: None + */ +static void obss_color_collision_process_color_change(tpAniSirGlobal mac_ctx, + tpPESession session, + struct wmi_obss_color_collision_info *obss_color_info) +{ + int i, num_bss_color = 0; + uint32_t bss_color_bitmap; + uint8_t bss_color_index_array[MAX_BSS_COLOR_VALUE]; + uint32_t rand_byte = 0; + struct sir_set_he_bss_color he_bss_color; + bool is_color_collision = false; + + + if (session->bss_color_changing == 1) { + pe_err("%d: color change in progress", session->smeSessionId); + return; + } + + if (!session->he_op.bss_col_disabled) { + if (session->he_op.bss_color < 32) + is_color_collision = (obss_color_info-> + obss_color_bitmap_bit0to31 >> + session->he_op.bss_color) & 0x01; + else + is_color_collision = (obss_color_info-> + obss_color_bitmap_bit32to63 >> + (session->he_op.bss_color - + 31)) & 0x01; + if (!is_color_collision) { + pe_err("%d: color collision not found, curr_color: %d", + session->smeSessionId, + session->he_op.bss_color); + return; + } + } + + bss_color_bitmap = obss_color_info->obss_color_bitmap_bit0to31; + + /* Skip color zero */ + bss_color_bitmap = bss_color_bitmap >> 1; + for (i = 0; (i < 31) && (num_bss_color < MAX_BSS_COLOR_VALUE); i++) { + if (!(bss_color_bitmap & 0x01)) { + bss_color_index_array[num_bss_color] = i + 1; + num_bss_color++; + } + bss_color_bitmap = bss_color_bitmap >> 1; + } + + bss_color_bitmap = obss_color_info->obss_color_bitmap_bit32to63; + for (i = 0; (i < 32) && (num_bss_color < MAX_BSS_COLOR_VALUE); i++) { + if (!(bss_color_bitmap & 0x01)) { + bss_color_index_array[num_bss_color] = i + 32; + num_bss_color++; + } + bss_color_bitmap = bss_color_bitmap >> 1; + } + + if (num_bss_color) { + qdf_get_random_bytes((void *) &rand_byte, 1); + i = (rand_byte + qdf_mc_timer_get_system_ticks()) % + num_bss_color; + pe_debug("New bss color = %d", bss_color_index_array[i]); + he_bss_color.session_id = obss_color_info->vdev_id; + he_bss_color.bss_color = bss_color_index_array[i]; + lim_process_set_he_bss_color(mac_ctx, + (uint32_t *)&he_bss_color); + } else { + pe_err("Unable to find bss color from bitmasp"); + if (obss_color_info->evt_type == + OBSS_COLOR_FREE_SLOT_TIMER_EXPIRY && + session->obss_color_collision_dec_evt == + OBSS_COLOR_FREE_SLOT_TIMER_EXPIRY) + /* In dot11BSSColorCollisionAPPeriod and + * timer expired, time to disable bss color. + */ + obss_color_collision_process_color_disable(mac_ctx, + session); + else + /* + * Enter dot11BSSColorCollisionAPPeriod period. + */ + lim_send_obss_color_collision_cfg(mac_ctx, session, + OBSS_COLOR_FREE_SLOT_TIMER_EXPIRY); + } +} + void lim_process_set_he_bss_color(tpAniSirGlobal mac_ctx, uint32_t *msg_buf) { struct sir_set_he_bss_color *bss_color; @@ -6016,9 +6175,6 @@ void lim_process_set_he_bss_color(tpAniSirGlobal mac_ctx, uint32_t *msg_buf) session_entry->he_bss_color_change.countdown = BSS_COLOR_SWITCH_COUNTDOWN; session_entry->he_bss_color_change.new_color = bss_color->bss_color; - session_entry->he_op.bss_color = - session_entry->he_bss_color_change.new_color; - beacon_params.bss_color = session_entry->he_op.bss_color; beacon_params.bss_color_disabled = session_entry->he_op.bss_col_disabled; session_entry->bss_color_changing = 1; @@ -6030,5 +6186,132 @@ void lim_process_set_he_bss_color(tpAniSirGlobal mac_ctx, uint32_t *msg_buf) } lim_send_beacon_params(mac_ctx, &beacon_params, session_entry); + lim_send_obss_color_collision_cfg(mac_ctx, session_entry, + OBSS_COLOR_COLLISION_DETECTION_DISABLE); +} + +void lim_send_obss_color_collision_cfg(tpAniSirGlobal mac_ctx, + tpPESession session, + enum wmi_obss_color_collision_evt_type + event_type) +{ + struct wmi_obss_color_collision_cfg_param *cfg_param; + struct scheduler_msg msg = {0}; + + if (!session) { + pe_err("Invalid session"); + return; + } + + if (!session->he_capable || + !session->is_session_obss_color_collision_det_enabled) { + pe_debug("%d: obss color det not enabled, he_cap:%d, sup:%d:%d", + session->smeSessionId, session->he_capable, + session->is_session_obss_color_collision_det_enabled, + mac_ctx->lim.global_obss_color_collision_det_offload); + return; + } + + cfg_param = qdf_mem_malloc(sizeof(*cfg_param)); + if (!cfg_param) { + pe_err("Failed to allocate memory"); + return; + } + + pe_debug("%d: sending event:%d", session->smeSessionId, event_type); + qdf_mem_zero(cfg_param, sizeof(*cfg_param)); + cfg_param->vdev_id = session->smeSessionId; + cfg_param->evt_type = event_type; + if (LIM_IS_AP_ROLE(session)) + cfg_param->detection_period_ms = + OBSS_COLOR_COLLISION_DETECTION_AP_PERIOD_MS; + else + cfg_param->detection_period_ms = + OBSS_COLOR_COLLISION_DETECTION_STA_PERIOD_MS; + + cfg_param->scan_period_ms = OBSS_COLOR_COLLISION_SCAN_PERIOD_MS; + if (event_type == OBSS_COLOR_FREE_SLOT_TIMER_EXPIRY) + cfg_param->free_slot_expiry_time_ms = + OBSS_COLOR_COLLISION_FREE_SLOT_EXPIRY_MS; + + msg.type = WMA_OBSS_COLOR_COLLISION_REQ; + msg.bodyptr = cfg_param; + msg.reserved = 0; + + if (QDF_IS_STATUS_ERROR(scheduler_post_msg(QDF_MODULE_ID_WMA, &msg))) { + pe_err("Failed to post WMA_OBSS_COLOR_COLLISION_REQ to WMA"); + qdf_mem_free(cfg_param); + } else { + session->obss_color_collision_dec_evt = event_type; + } +} + +void lim_process_obss_color_collision_info(tpAniSirGlobal mac_ctx, + uint32_t *msg_buf) +{ + struct wmi_obss_color_collision_info *obss_color_info; + tpPESession session; + + if (!msg_buf) { + pe_err("Buffer is Pointing to NULL"); + return; + } + + obss_color_info = (struct wmi_obss_color_collision_info *)msg_buf; + session = pe_find_session_by_sme_session_id(mac_ctx, + obss_color_info->vdev_id); + if (!session) { + pe_err("Session not found for given session_id %d", + obss_color_info->vdev_id); + return; + } + + pe_debug("vdev_id:%d, evt:%d:%d, 0to31:0x%x, 32to63:0x%x, cap:%d:%d:%d", + obss_color_info->vdev_id, + obss_color_info->evt_type, + session->obss_color_collision_dec_evt, + obss_color_info->obss_color_bitmap_bit0to31, + obss_color_info->obss_color_bitmap_bit32to63, + session->he_capable, + session->is_session_obss_color_collision_det_enabled, + mac_ctx->lim.global_obss_color_collision_det_offload); + + if (!session->he_capable || + !session->is_session_obss_color_collision_det_enabled) { + return; + } + + switch (obss_color_info->evt_type) { + case OBSS_COLOR_COLLISION_DETECTION_DISABLE: + pe_err("%d: FW disabled obss color det. he_cap:%d, sup:%d:%d", + session->smeSessionId, session->he_capable, + session->is_session_obss_color_collision_det_enabled, + mac_ctx->lim.global_obss_color_collision_det_offload); + session->is_session_obss_color_collision_det_enabled = false; + return; + case OBSS_COLOR_FREE_SLOT_AVAILABLE: + case OBSS_COLOR_COLLISION_DETECTION: + case OBSS_COLOR_FREE_SLOT_TIMER_EXPIRY: + if (session->valid && !LIM_IS_AP_ROLE(session)) { + pe_debug("Invalid System Role %d", + GET_LIM_SYSTEM_ROLE(session)); + return; + } + + if (session->obss_color_collision_dec_evt != + obss_color_info->evt_type) { + pe_debug("%d: Wrong event: %d, skiping", + obss_color_info->vdev_id, + obss_color_info->evt_type); + return; + } + obss_color_collision_process_color_change(mac_ctx, session, + obss_color_info); + break; + default: + pe_err("%d: Invalid event type %d", + obss_color_info->vdev_id, obss_color_info->evt_type); + return; + } } #endif diff --git a/core/mac/src/pe/lim/lim_send_sme_rsp_messages.c b/core/mac/src/pe/lim/lim_send_sme_rsp_messages.c index 93757ca191..ce4d45fdd2 100644 --- a/core/mac/src/pe/lim/lim_send_sme_rsp_messages.c +++ b/core/mac/src/pe/lim/lim_send_sme_rsp_messages.c @@ -2535,8 +2535,14 @@ lim_handle_bss_color_change_ie(tpAniSirGlobal mac_ctx, session->he_bss_color_change.countdown--; } else { session->bss_color_changing = 0; - if (session->he_bss_color_change.new_color != 0) + if (session->he_bss_color_change.new_color != 0) { session->he_op.bss_col_disabled = 0; + session->he_op.bss_color = + session->he_bss_color_change.new_color; + lim_send_obss_color_collision_cfg(mac_ctx, + session, + OBSS_COLOR_COLLISION_DETECTION); + } } lim_send_bss_color_change_ie_update(mac_ctx, session); diff --git a/core/mac/src/pe/lim/lim_session.c b/core/mac/src/pe/lim/lim_session.c index e30a5ee478..265657113c 100644 --- a/core/mac/src/pe/lim/lim_session.c +++ b/core/mac/src/pe/lim/lim_session.c @@ -473,6 +473,8 @@ pe_create_session(tpAniSirGlobal pMac, uint8_t *bssid, uint8_t *sessionId, session_ptr->fWaitForProbeRsp = 0; session_ptr->fIgnoreCapsChange = 0; session_ptr->ignore_assoc_disallowed = pMac->ignore_assoc_disallowed; + session_ptr->is_session_obss_color_collision_det_enabled = + pMac->lim.global_obss_color_collision_det_offload; pe_debug("Create a new PE session: %d BSSID: "MAC_ADDRESS_STR" Max No of STA: %d", *sessionId, MAC_ADDR_ARRAY(bssid), numSta); diff --git a/core/mac/src/pe/lim/lim_types.h b/core/mac/src/pe/lim/lim_types.h index d6e47ab6a3..ed0cb5f17e 100644 --- a/core/mac/src/pe/lim/lim_types.h +++ b/core/mac/src/pe/lim/lim_types.h @@ -567,10 +567,41 @@ static inline void lim_process_rx_scan_handler(struct wlan_objmgr_vdev *vdev, * Return: void */ void lim_process_set_he_bss_color(tpAniSirGlobal mac_ctx, uint32_t *msg_buf); + +/** + * lim_process_obss_color_collision_info() - Process the obss color collision + * request. + * @mac_ctx: global mac context pointer + * @msg_buf: message buffer pointer + * + * Return: void + */ +void lim_process_obss_color_collision_info(tpAniSirGlobal mac_ctx, + uint32_t *msg_buf); + +/** + * lim_send_obss_color_collision_cfg() - Send obss color collision cfg. + * @mac_ctx: global mac context pointer + * @session: Pointer to session + * @event_type: obss color collision detection type + * + * Return: void + */ +void lim_send_obss_color_collision_cfg(tpAniSirGlobal mac_ctx, + tpPESession session, + enum wmi_obss_color_collision_evt_type + event_type); #else static inline void lim_process_set_he_bss_color(tpAniSirGlobal mac_ctx, uint32_t *msg_buf) {} +static inline void lim_process_obss_color_collision_info(tpAniSirGlobal mac_ctx, + uint32_t *msg_buf) +{} +static inline void lim_send_obss_color_collision_cfg(tpAniSirGlobal mac_ctx, + tpPESession session, + enum wmi_obss_color_collision_evt_type event_type) +{} #endif void lim_send_delts_req_action_frame(tpAniSirGlobal pMac, tSirMacAddr peer, uint8_t wmmTspecPresent, diff --git a/core/mac/src/pe/sch/sch_beacon_process.c b/core/mac/src/pe/sch/sch_beacon_process.c index 7c4b4899ab..933926620b 100644 --- a/core/mac/src/pe/sch/sch_beacon_process.c +++ b/core/mac/src/pe/sch/sch_beacon_process.c @@ -492,6 +492,9 @@ sch_bcn_update_he_ies(tpAniSirGlobal mac_ctx, tpDphHashNode sta_ds, uint8_t session_bss_col_disabled_flag; bool anything_changed = false; + if (session->is_session_obss_color_collision_det_enabled) + return; + if (session->he_op.present && bcn->he_op.present) { if (bcn->vendor_he_bss_color_change.present && (session->he_op.bss_color != @@ -1055,7 +1058,9 @@ sch_beacon_process(tpAniSirGlobal mac_ctx, uint8_t *rx_pkt_info, bcn_prm.bssIdx = ap_session->bssIdx; - sch_check_bss_color_ie(mac_ctx, ap_session, &bcn, &bcn_prm); + if (!ap_session->is_session_obss_color_collision_det_enabled) + sch_check_bss_color_ie(mac_ctx, ap_session, + &bcn, &bcn_prm); if ((ap_session->gLimProtectionControl != WNI_CFG_FORCE_POLICY_PROTECTION_DISABLE) && diff --git a/core/wma/inc/wma_internal.h b/core/wma/inc/wma_internal.h index 1e322a81ef..9b5d088261 100644 --- a/core/wma/inc/wma_internal.h +++ b/core/wma/inc/wma_internal.h @@ -1360,4 +1360,21 @@ bool wma_is_vdev_valid(uint32_t vdev_id); */ int wma_vdev_obss_detection_info_handler(void *handle, uint8_t *event, uint32_t len); + +/** + * wma_vdev_bss_color_collision_info_handler - event handler to + * handle obss color collision detection. + * @handle: the wma handle + * @event: buffer with event + * @len: buffer length + * + * This function receives obss color collision detection info from firmware + * which is used to select new bss color. + * + * Return: 0 on success + */ +int wma_vdev_bss_color_collision_info_handler(void *handle, + uint8_t *event, + uint32_t len); + #endif diff --git a/core/wma/inc/wma_tgt_cfg.h b/core/wma/inc/wma_tgt_cfg.h index 90b0f0674f..8556b3c916 100644 --- a/core/wma/inc/wma_tgt_cfg.h +++ b/core/wma/inc/wma_tgt_cfg.h @@ -161,6 +161,7 @@ struct wma_dfs_radar_ind { * @tx_bfee_8ss_enabled: Tx Beamformee support for 8x8 * @rcpi_enabled: for checking rcpi support * @obss_detection_offloaded: obss detection offloaded to firmware + * @obss_color_collision_offloaded: obss color collision offloaded to firmware */ struct wma_tgt_cfg { uint32_t target_fw_version; @@ -196,5 +197,6 @@ struct wma_tgt_cfg { bool tx_bfee_8ss_enabled; bool rcpi_enabled; bool obss_detection_offloaded; + bool obss_color_collision_offloaded; }; #endif /* WMA_TGT_CFG_H */ diff --git a/core/wma/inc/wma_types.h b/core/wma/inc/wma_types.h index e0a8e02ba1..7ad9665104 100644 --- a/core/wma/inc/wma_types.h +++ b/core/wma/inc/wma_types.h @@ -474,6 +474,8 @@ #define WMA_OBSS_DETECTION_REQ SIR_HAL_OBSS_DETECTION_REQ #define WMA_OBSS_DETECTION_INFO SIR_HAL_OBSS_DETECTION_INFO #define WMA_INVOKE_NEIGHBOR_REPORT SIR_HAL_INVOKE_NEIGHBOR_REPORT +#define WMA_OBSS_COLOR_COLLISION_REQ SIR_HAL_OBSS_COLOR_COLLISION_REQ +#define WMA_OBSS_COLOR_COLLISION_INFO SIR_HAL_OBSS_COLOR_COLLISION_INFO /* Bit 6 will be used to control BD rate for Management frames */ #define HAL_USE_BD_RATE2_FOR_MANAGEMENT_FRAME 0x40 diff --git a/core/wma/src/wma_dev_if.c b/core/wma/src/wma_dev_if.c index 876cb84501..296032d1d8 100644 --- a/core/wma/src/wma_dev_if.c +++ b/core/wma/src/wma_dev_if.c @@ -4584,10 +4584,50 @@ send_rsp: } #endif +/** + * wma_send_bss_color_change_enable() - send bss color chnage enable cmd. + * @wma: wma handle + * @params: add sta params + * + * Send bss color change command to firmware, to enable firmware to update + * internally if any change in bss color in advertised by associated AP. + * + * Return: none + */ +#ifdef WLAN_FEATURE_11AX +static void wma_send_bss_color_change_enable(tp_wma_handle wma, + tpAddStaParams params) +{ + QDF_STATUS status; + uint32_t vdev_id = params->smesessionId; + + if (!params->he_capable) { + WMA_LOGD("%s: he_capable is not set for vdev_id:%d", + __func__, vdev_id); + return; + } + + status = wmi_unified_send_bss_color_change_enable_cmd(wma->wmi_handle, + vdev_id, + true); + if (QDF_IS_STATUS_ERROR(status)) { + WMA_LOGE("Failed to enable bss color change offload, vdev:%d", + vdev_id); + } + + return; +} +#else +static void wma_send_bss_color_change_enable(tp_wma_handle wma, + tpAddStaParams params) +{ +} +#endif + /** * wma_add_sta_req_sta_mode() - process add sta request in sta mode * @wma: wma handle - * @add_sta: add sta params + * @params: add sta params * * Return: none */ @@ -4796,6 +4836,8 @@ static void wma_add_sta_req_sta_mode(tp_wma_handle wma, tpAddStaParams params) } } + wma_send_bss_color_change_enable(wma, params); + /* Partial AID match power save, enable when SU bformee */ if (params->enableVhtpAid && params->vhtTxBFCapable) wma_set_ppsconfig(params->smesessionId, diff --git a/core/wma/src/wma_features.c b/core/wma/src/wma_features.c index 4705b2ee09..db0d7d0c1c 100644 --- a/core/wma/src/wma_features.c +++ b/core/wma/src/wma_features.c @@ -1612,6 +1612,10 @@ static const u8 *wma_wow_wake_reason_str(A_INT32 wake_reason) return "CHIP_POWER_FAILURE_DETECT"; case WOW_REASON_11D_SCAN: return "11D_SCAN"; + case WOW_REASON_SAP_OBSS_DETECTION: + return "SAP_OBSS_DETECTION"; + case WOW_REASON_BSS_COLOR_COLLISION_DETECT: + return "BSS_COLOR_COLLISION_DETECT"; default: return "unknown"; } @@ -5332,3 +5336,44 @@ int wma_vdev_obss_detection_info_handler(void *handle, uint8_t *event, return 0; } + +int wma_vdev_bss_color_collision_info_handler(void *handle, + uint8_t *event, + uint32_t len) +{ + tp_wma_handle wma = (tp_wma_handle) handle; + struct wmi_obss_color_collision_info *obss_color_info; + QDF_STATUS status; + + if (!event) { + WMA_LOGE("Invalid obss_color_collision event buffer"); + return -EINVAL; + } + + obss_color_info = qdf_mem_malloc(sizeof(*obss_color_info)); + if (!obss_color_info) { + WMA_LOGE("%s: Failed to malloc", __func__); + return -ENOMEM; + } + + status = wmi_unified_extract_obss_color_collision_info(wma->wmi_handle, + event, + obss_color_info); + + if (QDF_IS_STATUS_ERROR(status)) { + WMA_LOGE("%s: Failed to extract obss color info", __func__); + qdf_mem_free(obss_color_info); + return -EINVAL; + } + + if (!wma_is_vdev_valid(obss_color_info->vdev_id)) { + WMA_LOGE("%s: Invalid vdev id %d", __func__, + obss_color_info->vdev_id); + qdf_mem_free(obss_color_info); + return -EINVAL; + } + + wma_send_msg(wma, WMA_OBSS_COLOR_COLLISION_INFO, obss_color_info, 0); + + return 0; +} diff --git a/core/wma/src/wma_main.c b/core/wma/src/wma_main.c index 36d858e6ed..0d19c69a05 100644 --- a/core/wma/src/wma_main.c +++ b/core/wma/src/wma_main.c @@ -3304,6 +3304,12 @@ QDF_STATUS wma_open(struct wlan_objmgr_psoc *psoc, wma_vdev_obss_detection_info_handler, WMA_RX_SERIALIZER_CTX); + wmi_unified_register_event_handler(wma_handle->wmi_handle, + wmi_obss_color_collision_report_event_id, + wma_vdev_bss_color_collision_info_handler, + WMA_RX_WORK_CTX); + + return QDF_STATUS_SUCCESS; err_dbglog_init: @@ -5068,14 +5074,32 @@ static void wma_update_hdd_band_cap(WMI_PHY_CAPABILITY supported_band, static void wma_update_obss_detection_support(tp_wma_handle wh, struct wma_tgt_cfg *tgt_cfg) { - if (WMI_SERVICE_EXT_IS_ENABLED(wh->wmi_service_bitmap, - wh->wmi_service_ext_bitmap, - WMI_SERVICE_AP_OBSS_DETECTION_OFFLOAD)) + if (wmi_service_enabled(wh->wmi_handle, + wmi_service_ap_obss_detection_offload)) tgt_cfg->obss_detection_offloaded = true; else tgt_cfg->obss_detection_offloaded = false; } +/** + * wma_update_obss_color_collision_support() - update obss color collision + * offload support + * @wh: wma handle + * @tgt_cfg: target configuration to be updated + * + * Update obss color collision offload support based on service bit. + * + * Return: None + */ +static void wma_update_obss_color_collision_support(tp_wma_handle wh, + struct wma_tgt_cfg *tgt_cfg) +{ + if (wmi_service_enabled(wh->wmi_handle, wmi_service_bss_color_offload)) + tgt_cfg->obss_color_collision_offloaded = true; + else + tgt_cfg->obss_color_collision_offloaded = false; +} + /** * wma_update_hdd_cfg() - update HDD config * @wma_handle: wma handle @@ -5152,6 +5176,7 @@ static void wma_update_hdd_cfg(tp_wma_handle wma_handle) - WMI_TLV_HEADROOM; tgt_cfg.tx_bfee_8ss_enabled = wma_handle->tx_bfee_8ss_enabled; wma_update_obss_detection_support(wma_handle, &tgt_cfg); + wma_update_obss_color_collision_support(wma_handle, &tgt_cfg); wma_update_hdd_cfg_ndp(wma_handle, &tgt_cfg); wma_handle->tgt_cfg_update_cb(hdd_ctx, &tgt_cfg); target_if_store_pdev_target_if_ctx(wma_get_pdev_from_scn_handle); @@ -7300,6 +7325,29 @@ static QDF_STATUS wma_process_limit_off_chan(tp_wma_handle wma_handle, return QDF_STATUS_SUCCESS; } +static QDF_STATUS wma_process_obss_color_collision_req(tp_wma_handle wma_handle, + struct wmi_obss_color_collision_cfg_param *cfg) +{ + QDF_STATUS status; + + if (cfg->vdev_id >= wma_handle->max_bssid) { + WMA_LOGE(FL("Invalid vdev_id: %d"), cfg->vdev_id); + return QDF_STATUS_E_INVAL; + } + if (!wma_is_vdev_up(cfg->vdev_id)) { + WMA_LOGE("vdev %d is not up skipping obss color collision req", + cfg->vdev_id); + return QDF_STATUS_E_INVAL; + } + + status = wmi_unified_send_obss_color_collision_cfg_cmd(wma_handle-> + wmi_handle, cfg); + if (QDF_IS_STATUS_ERROR(status)) + WMA_LOGE("Failed to send obss color collision cfg"); + + return status; +} + /** * wma_send_obss_detection_cfg() - send obss detection cfg to firmware * @wma_handle: pointer to wma handle @@ -8090,6 +8138,10 @@ static QDF_STATUS wma_mc_process_msg(struct scheduler_msg *msg) wma_send_invoke_neighbor_report(wma_handle, msg->bodyptr); qdf_mem_free(msg->bodyptr); break; + case WMA_OBSS_COLOR_COLLISION_REQ: + wma_process_obss_color_collision_req(wma_handle, msg->bodyptr); + qdf_mem_free(msg->bodyptr); + break; default: WMA_LOGE("Unhandled WMA message of type %d", msg->type); if (msg->bodyptr)