qcacld-3.0: Add bss color collision detection support
Add support for bss color collision detection.
Change-Id: Idd616ca902469f5dc446d35e63fce7fe7eb0d327
CRs-Fixed: 2130127
diff --git a/core/mac/src/pe/include/lim_session.h b/core/mac/src/pe/include/lim_session.h
index c637d5c..6f79b35 100644
--- a/core/mac/src/pe/include/lim_session.h
+++ b/core/mac/src/pe/include/lim_session.h
@@ -100,6 +100,10 @@
#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 @@
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 4ea1362..6387ea7 100644
--- a/core/mac/src/pe/lim/lim_api.c
+++ b/core/mac/src/pe/lim/lim_api.c
@@ -476,6 +476,14 @@
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 c22a695..898547a 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 @@
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 7977e1b..29ae301 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 @@
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 @@
* 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 f9aea2f..2a39975 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 @@
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 @@
}
#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 @@
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 @@
}
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 93757ca..ce4d45f 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 @@
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 e30a5ee..2656571 100644
--- a/core/mac/src/pe/lim/lim_session.c
+++ b/core/mac/src/pe/lim/lim_session.c
@@ -473,6 +473,8 @@
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 d6e47ab..ed0cb5f 100644
--- a/core/mac/src/pe/lim/lim_types.h
+++ b/core/mac/src/pe/lim/lim_types.h
@@ -567,10 +567,41 @@
* 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 7c4b489..9339266 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 @@
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 @@
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) &&