Browse Source

qcacld-3.0: Handle the wmi event from WMI_ROAM_BLACKLIST_EVENTID

When firmware receives BTM request with disassoc imminent set,
the firmware should blacklist the AP and should not roam to it
for disassoc timer duration sent in the btm frame. The new wmi
event WMI_ROAM_BLACKLIST_EVENTID received from the firmware
carries the bssid to be blacklisted.

Handle this wmi event WMI_ROAM_BLACKLIST_EVENTID and update the
mac_ctx->roam.rssi_disallow_bssid with the bssid entries
received from firmware.

Change-Id: Ib41bcb91f123ce24b7d28407468e4597af7b5e1a
CRs-Fixed: 2369078
Pragaspathi Thilagaraj 6 years ago
parent
commit
30251ecf5a

+ 1 - 0
core/mac/src/include/sir_params.h

@@ -696,6 +696,7 @@ struct sir_cfg_action_frm_tb_ppdu {
 #define SIR_HAL_SEND_BCN_RSP                (SIR_HAL_ITC_MSG_TYPES_BEGIN + 401)
 #define SIR_HAL_CFG_VENDOR_ACTION_TB_PPDU   (SIR_HAL_ITC_MSG_TYPES_BEGIN + 402)
 #define SIR_HAL_BEACON_DEBUG_STATS_REQ       (SIR_HAL_ITC_MSG_TYPES_BEGIN + 403)
+#define SIR_HAL_ROAM_BLACKLIST_MSG          (SIR_HAL_ITC_MSG_TYPES_BEGIN + 404)
 #define SIR_HAL_MSG_TYPES_END               (SIR_HAL_MSG_TYPES_BEGIN + 0x1FF)
 
 /* CFG message types */

+ 7 - 0
core/mac/src/pe/lim/lim_process_message_queue.c

@@ -2040,6 +2040,13 @@ static void lim_process_messages(struct mac_context *mac_ctx,
 		qdf_mem_free((void *)msg->bodyptr);
 		msg->bodyptr = NULL;
 		break;
+	case WMA_ROAM_BLACKLIST_MSG:
+		lim_add_roam_blacklist_ap(mac_ctx,
+					  (struct roam_blacklist_event *)
+					  msg->bodyptr);
+		qdf_mem_free((void *)msg->bodyptr);
+		msg->bodyptr = NULL;
+		break;
 	default:
 		qdf_mem_free((void *)msg->bodyptr);
 		msg->bodyptr = NULL;

+ 93 - 0
core/mac/src/pe/lim/lim_process_sme_req_messages.c

@@ -6550,3 +6550,96 @@ void lim_send_csa_restart_req(struct mac_context *mac_ctx, uint8_t vdev_id)
 				      sizeof(*session), session);
 }
 #endif
+
+void lim_remove_duplicate_bssid_node(struct sir_rssi_disallow_lst *entry,
+				     qdf_list_t *list)
+{
+	qdf_list_node_t *cur_list = NULL;
+	qdf_list_node_t *next_list = NULL;
+	struct sir_rssi_disallow_lst *cur_entry;
+	QDF_STATUS status;
+
+	qdf_list_peek_front(list, &cur_list);
+	while (cur_list) {
+		qdf_list_peek_next(list, cur_list, &next_list);
+		cur_entry = qdf_container_of(cur_list,
+					     struct sir_rssi_disallow_lst,
+					     node);
+
+		/*
+		 * Remove the node from blacklisting if the timeout is 0 and
+		 * rssi is 0 dbm i.e btm blacklisted entry
+		 */
+		if ((lim_assoc_rej_get_remaining_delta(cur_entry) == 0) &&
+		    cur_entry->expected_rssi == LIM_MIN_RSSI) {
+			status = qdf_list_remove_node(list, cur_list);
+			if (QDF_IS_STATUS_SUCCESS(status))
+				qdf_mem_free(cur_entry);
+		} else if (qdf_is_macaddr_equal(&entry->bssid,
+						&cur_entry->bssid)) {
+			/*
+			 * Remove the node if we try to add the same bssid again
+			 * Copy the old rssi value alone
+			 */
+			entry->expected_rssi = cur_entry->expected_rssi;
+			status = qdf_list_remove_node(list, cur_list);
+			if (QDF_IS_STATUS_SUCCESS(status)) {
+				qdf_mem_free(cur_entry);
+				break;
+			}
+		}
+		cur_list = next_list;
+		next_list = NULL;
+	}
+}
+
+void lim_add_roam_blacklist_ap(struct mac_context *mac_ctx,
+			       struct roam_blacklist_event *src_lst)
+{
+	uint32_t i;
+	struct sir_rssi_disallow_lst *entry;
+	struct roam_blacklist_timeout *blacklist;
+	QDF_STATUS status = QDF_STATUS_SUCCESS;
+
+	blacklist = &src_lst->roam_blacklist[0];
+	for (i = 0; i < src_lst->num_entries; i++) {
+		entry = qdf_mem_malloc(sizeof(struct sir_rssi_disallow_lst));
+		if (!entry)
+			return;
+
+		qdf_copy_macaddr(&entry->bssid, &blacklist->bssid);
+		entry->retry_delay = blacklist->timeout;
+		entry->time_during_rejection = blacklist->received_time;
+		/* set 0dbm as expected rssi for btm blaclisted entries */
+		entry->expected_rssi = LIM_MIN_RSSI;
+		lim_remove_duplicate_bssid_node(
+					entry,
+					&mac_ctx->roam.rssi_disallow_bssid);
+
+		if (qdf_list_size(&mac_ctx->roam.rssi_disallow_bssid) >=
+		    MAX_RSSI_AVOID_BSSID_LIST) {
+			status = lim_rem_blacklist_entry_with_lowest_delta(
+					&mac_ctx->roam.rssi_disallow_bssid);
+			if (QDF_IS_STATUS_ERROR(status)) {
+				pe_err("Failed to remove entry with lowest delta");
+				qdf_mem_free(entry);
+				return;
+			}
+		}
+
+		if (QDF_IS_STATUS_SUCCESS(status)) {
+			status = qdf_list_insert_back(
+					&mac_ctx->roam.rssi_disallow_bssid,
+					&entry->node);
+			if (QDF_IS_STATUS_ERROR(status)) {
+				pe_err("Failed to enqueue bssid: %pM",
+				       entry->bssid.bytes);
+				qdf_mem_free(entry);
+				return;
+			}
+			pe_debug("Added BTM blacklisted bssid: %pM",
+				 entry->bssid.bytes);
+		}
+		blacklist++;
+	}
+}

+ 22 - 1
core/mac/src/pe/lim/lim_types.h

@@ -136,7 +136,7 @@
 #endif
 
 #define LIM_DOS_PROTECTION_TIME 1000 //1000ms
-
+#define LIM_MIN_RSSI 0 /* 0dbm */
 /* enums used by LIM are as follows */
 
 enum eLimDisassocTrigger {
@@ -989,6 +989,27 @@ QDF_STATUS lim_process_sme_del_all_tdls_peers(struct mac_context *p_mac,
  */
 void lim_send_bcn_rsp(struct mac_context *mac_ctx, tpSendbeaconParams rsp);
 
+/**
+ * lim_remove_duplicate_bssid_node() - remove duplicate bssid from the
+ * @entry: entry to check for which the duplicate entry is present
+ * @list:  mac_ctx->roam.rssi_disallow_bssid list
+ *
+ * Return: None
+ */
+void lim_remove_duplicate_bssid_node(struct sir_rssi_disallow_lst *entry,
+				     qdf_list_t *list);
+
+/**
+ * lim_add_roam_blacklist_ap() - handle the blacklist bssid list received from
+ * firmware
+ * @mac_ctx: Pointer to Global MAC structure
+ * @list: roam blacklist ap list
+ *
+ * Return: None
+ */
+void lim_add_roam_blacklist_ap(struct mac_context *mac_ctx,
+			       struct roam_blacklist_event *src_lst);
+
 /**
  * lim_process_rx_channel_status_event() - processes
  * event WDA_RX_CHN_STATUS_EVENT

+ 4 - 18
core/mac/src/pe/lim/lim_utils.c

@@ -7518,14 +7518,7 @@ QDF_STATUS lim_populate_he_mcs_set(struct mac_context *mac_ctx,
 }
 #endif
 
-/**
- * lim_assoc_rej_get_remaining_delta() - Get remaining time delta for
- * the rssi based disallowed list entry
- * @node: rssi based disallowed list entry
- *
- * Return: remaining delta, can be -ve if time has already expired.
- */
-static inline int
+int
 lim_assoc_rej_get_remaining_delta(struct sir_rssi_disallow_lst *node)
 {
 	qdf_time_t cur_time;
@@ -7538,15 +7531,8 @@ lim_assoc_rej_get_remaining_delta(struct sir_rssi_disallow_lst *node)
 	return node->retry_delay - time_diff;
 }
 
-/**
- * lim_assoc_rej_rem_entry_with_lowest_delta() - Remove the entry
- * with lowest time delta
- * @list: rssi based rejected BSSID list
- *
- * Return: QDF_STATUS
- */
-static QDF_STATUS
-lim_assoc_rej_rem_entry_with_lowest_delta(qdf_list_t *list)
+QDF_STATUS
+lim_rem_blacklist_entry_with_lowest_delta(qdf_list_t *list)
 {
 	struct sir_rssi_disallow_lst *oldest_node = NULL;
 	struct sir_rssi_disallow_lst *cur_node;
@@ -7606,7 +7592,7 @@ void lim_assoc_rej_add_to_rssi_based_reject_list(struct mac_context *mac_ctx,
 
 	if (qdf_list_size(&mac_ctx->roam.rssi_disallow_bssid) >=
 		MAX_RSSI_AVOID_BSSID_LIST) {
-		status = lim_assoc_rej_rem_entry_with_lowest_delta(
+		status = lim_rem_blacklist_entry_with_lowest_delta(
 					&mac_ctx->roam.rssi_disallow_bssid);
 		if (QDF_IS_STATUS_ERROR(status))
 			pe_err("Failed to remove entry with lowest delta");

+ 20 - 0
core/mac/src/pe/lim/lim_utils.h

@@ -333,6 +333,26 @@ void lim_prepare_for11h_channel_switch(struct mac_context *mac,
 void lim_switch_channel_cback(struct mac_context *mac, QDF_STATUS status,
 		uint32_t *data, struct pe_session *pe_session);
 
+/**
+ * lim_assoc_rej_get_remaining_delta() - Get remaining time delta for
+ * the rssi based disallowed list entry
+ * @node: rssi based disallowed list entry
+ *
+ * Return: remaining delta, can be -ve if time has already expired.
+ */
+int
+lim_assoc_rej_get_remaining_delta(struct sir_rssi_disallow_lst *node);
+
+/**
+ * lim_rem_blacklist_entry_with_lowest_delta() - Remove the entry with lowest
+ * time delta
+ * @list: rssi based rejected BSSID list
+ *
+ * Return: QDF_STATUS
+ */
+QDF_STATUS
+lim_rem_blacklist_entry_with_lowest_delta(qdf_list_t *list);
+
 /**
  * lim_get_session_by_macaddr() - api to find session based on MAC
  * @mac_ctx: Pointer to global mac structure.

+ 3 - 3
core/sme/src/csr/csr_api_roam.c

@@ -18800,13 +18800,13 @@ csr_roam_offload_scan(struct mac_context *mac_ctx, uint8_t session_id,
 		check_allowed_ssid_list(req_buf, roam_params_src);
 
 	/*
-	 * For CTX INT cmd if rssi disallow bssid list have any member
+	 * If rssi disallow bssid list have any member
 	 * fill it and send it to firmware so that firmware does not
 	 * try to roam to these BSS until RSSI OR time condition are
 	 * matched.
 	 */
-	if (reason == REASON_CTX_INIT)
-		csr_add_rssi_reject_ap_list(mac_ctx, roam_params_src);
+	csr_add_rssi_reject_ap_list(mac_ctx, roam_params_src);
+
 	/*
 	 * Configure the lookup threshold either from INI or from framework.
 	 * If both are present, give higher priority to the one from framework.

+ 22 - 0
core/wma/inc/wma_if.h

@@ -1321,4 +1321,26 @@ typedef struct sNanRequest {
 } tNanRequest, *tpNanRequest;
 #endif /* WLAN_FEATURE_NAN */
 
+/*
+ * struct roam_blacklist_timeout - BTM blacklist entry
+ * @bssid - bssid that is to be blacklisted
+ * @timeout - time duration for which the bssid is blacklisted
+ * @received_time - boot timestamp at which the firmware event was received
+ */
+struct roam_blacklist_timeout {
+	struct qdf_mac_addr bssid;
+	uint32_t timeout;
+	qdf_time_t received_time;
+};
+
+/*
+ * struct roam_blacklist_event - Blacklist event entries destination structure
+ * @num_entries: total entries sent over the event
+ * @roam_blacklist: blacklist details
+ */
+struct roam_blacklist_event {
+	uint32_t num_entries;
+	struct roam_blacklist_timeout roam_blacklist[];
+};
+
 #endif /* _HALMSGAPI_H_ */

+ 3 - 0
core/wma/inc/wma_internal.h

@@ -350,6 +350,9 @@ int wma_passpoint_match_event_handler(void *handle,
 
 #endif
 
+int wma_handle_btm_blacklist_event(void *handle, uint8_t *cmd_param_info,
+				   uint32_t len);
+
 #ifdef FEATURE_WLAN_EXTSCAN
 int wma_extscan_wow_event_callback(void *handle, void *event, uint32_t len);
 

+ 2 - 0
core/wma/inc/wma_types.h

@@ -144,6 +144,7 @@
 #define WMA_SEND_BEACON_REQ            SIR_HAL_SEND_BEACON_REQ
 #define WMA_SEND_BCN_RSP               SIR_HAL_SEND_BCN_RSP
 #define WMA_SEND_PROBE_RSP_TMPL        SIR_HAL_SEND_PROBE_RSP_TMPL
+#define WMA_ROAM_BLACLIST_MSG          SIR_HAL_ROAM_BLACKLIST_MSG
 
 #define WMA_SET_BSSKEY_REQ             SIR_HAL_SET_BSSKEY_REQ
 #define WMA_SET_BSSKEY_RSP             SIR_HAL_SET_BSSKEY_RSP
@@ -436,6 +437,7 @@
 #define WMA_POWER_DEBUG_STATS_REQ            SIR_HAL_POWER_DEBUG_STATS_REQ
 #define WMA_BEACON_DEBUG_STATS_REQ           SIR_HAL_BEACON_DEBUG_STATS_REQ
 #define WMA_GET_RCPI_REQ                     SIR_HAL_GET_RCPI_REQ
+#define WMA_ROAM_BLACKLIST_MSG               SIR_HAL_ROAM_BLACKLIST_MSG
 
 #define WMA_SET_DBS_SCAN_SEL_CONF_PARAMS     SIR_HAL_SET_DBS_SCAN_SEL_PARAMS
 

+ 77 - 0
core/wma/src/wma_scan_roam.c

@@ -3454,6 +3454,12 @@ void wma_register_extscan_event_handler(tp_wma_handle wma_handle)
 			wmi_passpoint_match_event_id,
 			wma_passpoint_match_event_handler,
 			WMA_RX_SERIALIZER_CTX);
+
+	/* Register BTM reject list event handler */
+	wmi_unified_register_event_handler(wma_handle->wmi_handle,
+					   wmi_roam_blacklist_event_id,
+					   wma_handle_btm_blacklist_event,
+					   WMA_RX_SERIALIZER_CTX);
 }
 
 /**
@@ -5156,3 +5162,74 @@ QDF_STATUS wma_send_ht40_obss_scanind(tp_wma_handle wma,
 	}
 	return QDF_STATUS_SUCCESS;
 }
+
+int wma_handle_btm_blacklist_event(void *handle, uint8_t *cmd_param_info,
+				   uint32_t len)
+{
+	tp_wma_handle wma = (tp_wma_handle) handle;
+	WMI_ROAM_BLACKLIST_EVENTID_param_tlvs *param_buf;
+	wmi_roam_blacklist_event_fixed_param *resp_event;
+	wmi_roam_blacklist_with_timeout_tlv_param *src_list;
+	struct roam_blacklist_event *dst_list;
+	struct roam_blacklist_timeout *roam_blacklist;
+	uint32_t num_entries, i;
+
+	param_buf = (WMI_ROAM_BLACKLIST_EVENTID_param_tlvs *)cmd_param_info;
+	if (!param_buf) {
+		WMA_LOGE("Invalid event buffer");
+		return -EINVAL;
+	}
+
+	resp_event = param_buf->fixed_param;
+	if (!resp_event) {
+		WMA_LOGE("%s: received null event data from target", __func__);
+		return -EINVAL;
+	}
+
+	if (resp_event->vdev_id >= wma->max_bssid) {
+		WMA_LOGE("%s: received invalid vdev_id %d",
+			 __func__, resp_event->vdev_id);
+		return -EINVAL;
+	}
+
+	num_entries = param_buf->num_blacklist_with_timeout;
+	if (num_entries == 0) {
+		/* no aps to blacklist just return*/
+		WMA_LOGE("%s: No APs in blacklist received", __func__);
+		return 0;
+	}
+
+	if (num_entries > MAX_RSSI_AVOID_BSSID_LIST) {
+		WMA_LOGE("%s: num blacklist entries:%d exceeds maximum value",
+			 __func__, num_entries);
+		return -EINVAL;
+	}
+
+	src_list = param_buf->blacklist_with_timeout;
+	if (len < (sizeof(*resp_event) + (num_entries * sizeof(*src_list)))) {
+		WMA_LOGE("%s: Invalid length:%d", __func__, len);
+		return -EINVAL;
+	}
+
+	dst_list = qdf_mem_malloc(sizeof(struct roam_blacklist_event) +
+				 (sizeof(struct roam_blacklist_timeout) *
+				 num_entries));
+	if (!dst_list)
+		return -ENOMEM;
+
+	roam_blacklist = &dst_list->roam_blacklist[0];
+	for (i = 0; i < num_entries; i++) {
+		WMI_MAC_ADDR_TO_CHAR_ARRAY(&src_list->bssid,
+					   roam_blacklist->bssid.bytes);
+		roam_blacklist->timeout = src_list->timeout;
+		roam_blacklist->received_time =
+			qdf_do_div(qdf_get_monotonic_boottime(),
+				   QDF_MC_TIMER_TO_MS_UNIT);
+		roam_blacklist++;
+		src_list++;
+	}
+
+	dst_list->num_entries = num_entries;
+	wma_send_msg(wma, WMA_ROAM_BLACKLIST_MSG, (void *)dst_list, 0);
+	return 0;
+}