Bläddra i källkod

qcacmn: Add logic to handle reg/dereg of multiple rx callbacks

Add logic to handle registration and deregistration of rx callbacks
for multiple frames in a single call of corresponding func.

Change-Id: I09479988f0c55f6d358ef503417dcfb46f2a0565
CRs-Fixed: 1103247
Himanshu Agarwal 8 år sedan
förälder
incheckning
ca307114d1

+ 26 - 10
umac/cmn_services/mgmt_txrx/dispatcher/inc/wlan_mgmt_txrx_utils_api.h

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2016-2017 The Linux Foundation. All rights reserved.
  *
  * Permission to use, copy, modify, and/or distribute this software for
  * any purpose with or without fee is hereby granted, provided that the
@@ -495,10 +495,11 @@ struct action_frm_hdr {
  * @MGMT_ACTION_VHT_COMPRESSED_BF: vht compressed bf action frame
  * @MGMT_ACTION_VHT_GID_NOTIF:   vht gid notification action frame
  * @MGMT_ACTION_VHT_OPMODE_NOTIF: vht opmode notification action frame
+ * @MGMT_FRAME_TYPE_ALL:         mgmt frame type for all type of frames
  * @MGMT_MAX_FRAME_TYPE:         max. mgmt frame types
  */
 enum mgmt_frame_type {
-	MGMT_FRM_UNSPECIFIED,
+	MGMT_FRM_UNSPECIFIED = -1,
 	MGMT_ASSOC_REQ,
 	MGMT_ASSOC_RESP,
 	MGMT_REASSOC_REQ,
@@ -589,6 +590,7 @@ enum mgmt_frame_type {
 	MGMT_ACTION_VHT_COMPRESSED_BF,
 	MGMT_ACTION_VHT_GID_NOTIF,
 	MGMT_ACTION_VHT_OPMODE_NOTIF,
+	MGMT_FRAME_TYPE_ALL,
 	MGMT_MAX_FRAME_TYPE,
 };
 
@@ -639,6 +641,17 @@ typedef QDF_STATUS (*mgmt_frame_rx_callback)(struct wlan_objmgr_psoc *psoc,
 					     enum mgmt_frame_type frm_type);
 
 
+/**
+ * struct mgmt_txrx_mgmt_frame_cb_info - frm and corresponding rx cb info
+ * @frm_type:    mgmt frm type
+ * @mgmt_rx_cb:  corresponding rx callback
+ */
+struct mgmt_txrx_mgmt_frame_cb_info {
+	enum mgmt_frame_type frm_type;
+	mgmt_frame_rx_callback mgmt_rx_cb;
+};
+
+
 /**
  * wlan_mgmt_txrx_init() - initialize mgmt txrx context.
  *
@@ -698,25 +711,27 @@ QDF_STATUS wlan_mgmt_txrx_beacon_frame_tx(struct wlan_objmgr_peer *peer,
 /**
  * wlan_mgmt_txrx_register_rx_cb() - registers the rx cb for mgmt. frames
  * @psoc: psoc context
- * @mgmt_rx_cb: mgmt rx callback to be registered
  * @comp_id: umac component id
- * @frm_type: mgmt. frame for which cb to be registered.
+ * @frm_cb_info: pointer to array of structure containing frm type and callback
+ * @num_entries: num of frames for which cb to be registered
  *
  * This function registers rx callback for mgmt. frames for
  * the corresponding umac component passed in the func.
  *
  * Return: QDF_STATUS_SUCCESS - in case of success
  */
-QDF_STATUS wlan_mgmt_txrx_register_rx_cb(struct wlan_objmgr_psoc *psoc,
-					 mgmt_frame_rx_callback mgmt_rx_cb,
-					 enum wlan_umac_comp_id comp_id,
-					 enum mgmt_frame_type frm_type);
+QDF_STATUS wlan_mgmt_txrx_register_rx_cb(
+			struct wlan_objmgr_psoc *psoc,
+			enum wlan_umac_comp_id comp_id,
+			struct mgmt_txrx_mgmt_frame_cb_info *frm_cb_info,
+			uint8_t num_entries);
 
 /**
  * wlan_mgmt_txrx_deregister_rx_cb() - deregisters the rx cb for mgmt. frames
  * @psoc: psoc context
  * @comp_id: umac component id
- * @frm_type: mgmt. frame for which cb to be registered.
+ * @frm_cb_info: pointer to array of structure containing frm type and callback
+ * @num_entries: num of frames for which cb to be deregistered
  *
  * This function deregisters rx callback for mgmt. frames for
  * the corresponding umac component passed in the func.
@@ -726,6 +741,7 @@ QDF_STATUS wlan_mgmt_txrx_register_rx_cb(struct wlan_objmgr_psoc *psoc,
 QDF_STATUS wlan_mgmt_txrx_deregister_rx_cb(
 			struct wlan_objmgr_psoc *psoc,
 			enum wlan_umac_comp_id comp_id,
-			enum mgmt_frame_type frm_type);
+			struct mgmt_txrx_mgmt_frame_cb_info *frm_cb_info,
+			uint8_t num_entries);
 
 #endif

+ 66 - 26
umac/cmn_services/mgmt_txrx/dispatcher/src/wlan_mgmt_txrx_tgt_api.c

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2016-2017 The Linux Foundation. All rights reserved.
  *
  * Permission to use, copy, modify, and/or distribute this software for
  * any purpose with or without fee is hereby granted, provided that the
@@ -750,6 +750,48 @@ mgmt_txrx_get_frm_type(uint8_t mgmt_subtype, uint8_t *mpdu_data_ptr)
 	return frm_type;
 }
 
+/**
+ * wlan_mgmt_txrx_rx_handler_list_copy() - copies rx handler list
+ * @rx_handler: pointer to rx handler list
+ * @rx_handler_head: pointer to head of the copies list
+ * @rx_handler_tail: pointer to tail of the copies list
+ *
+ * This function copies the rx handler linked list into a local
+ * linked list.
+ *
+ * Return: QDF_STATUS_SUCCESS in case of success
+ */
+static QDF_STATUS wlan_mgmt_txrx_rx_handler_list_copy(
+			struct mgmt_rx_handler *rx_handler,
+			struct mgmt_rx_handler **rx_handler_head,
+			struct mgmt_rx_handler **rx_handler_tail)
+{
+	struct mgmt_rx_handler *rx_handler_node;
+
+	while (rx_handler) {
+		rx_handler_node = qdf_mem_malloc(sizeof(*rx_handler_node));
+		if (!rx_handler_node) {
+			mgmt_txrx_err("Couldn't allocate memory for rx handler node");
+			return QDF_STATUS_E_NOMEM;
+		}
+
+		rx_handler_node->comp_id = rx_handler->comp_id;
+		rx_handler_node->rx_cb = rx_handler->rx_cb;
+		rx_handler_node->next = NULL;
+
+		if (!(*rx_handler_head)) {
+			*rx_handler_head = rx_handler_node;
+			*rx_handler_tail = *rx_handler_head;
+		} else {
+			(*rx_handler_tail)->next = rx_handler_node;
+			*rx_handler_tail = (*rx_handler_tail)->next;
+		}
+		rx_handler = rx_handler->next;
+	}
+
+	return QDF_STATUS_SUCCESS;
+}
+
 QDF_STATUS tgt_mgmt_txrx_rx_frame_handler(
 			struct wlan_objmgr_psoc *psoc,
 			qdf_nbuf_t buf, void *params)
@@ -761,7 +803,7 @@ QDF_STATUS tgt_mgmt_txrx_rx_frame_handler(
 	uint8_t mgmt_type, mgmt_subtype;
 	uint8_t *mac_addr, *mpdu_data_ptr;
 	enum mgmt_frame_type frm_type;
-	struct mgmt_rx_handler *rx_handler, *rx_handler_node;
+	struct mgmt_rx_handler *rx_handler;
 	struct mgmt_rx_handler *rx_handler_head = NULL, *rx_handler_tail = NULL;
 	QDF_STATUS status = QDF_STATUS_SUCCESS;
 
@@ -828,39 +870,37 @@ QDF_STATUS tgt_mgmt_txrx_rx_frame_handler(
 	mgmt_txrx_ctx = (struct mgmt_txrx_priv_context *)
 			wlan_objmgr_psoc_get_comp_private_obj(psoc,
 				WLAN_UMAC_COMP_MGMT_TXRX);
+
 	qdf_spin_lock_bh(&mgmt_txrx_ctx->mgmt_txrx_ctx_lock);
 	rx_handler = mgmt_txrx_ctx->mgmt_rx_comp_cb[frm_type];
-	if (!rx_handler) {
-		qdf_spin_unlock_bh(&mgmt_txrx_ctx->mgmt_txrx_ctx_lock);
-		mgmt_txrx_info("No rx callback registered for frm_type: %d",
-			frm_type);
-		qdf_nbuf_free(buf);
-		status = QDF_STATUS_E_FAILURE;
-		goto dec_peer_ref_cnt;
+	if (rx_handler) {
+		status = wlan_mgmt_txrx_rx_handler_list_copy(rx_handler,
+				&rx_handler_head, &rx_handler_tail);
+		if (status != QDF_STATUS_SUCCESS) {
+			qdf_spin_unlock_bh(&mgmt_txrx_ctx->mgmt_txrx_ctx_lock);
+			qdf_nbuf_free(buf);
+			goto rx_handler_mem_free;
+		}
 	}
 
-	while (rx_handler) {
-		rx_handler_node = qdf_mem_malloc(sizeof(*rx_handler_node));
-		if (!rx_handler_node) {
+	rx_handler = mgmt_txrx_ctx->mgmt_rx_comp_cb[MGMT_FRAME_TYPE_ALL];
+	if (rx_handler) {
+		status = wlan_mgmt_txrx_rx_handler_list_copy(rx_handler,
+				&rx_handler_head, &rx_handler_tail);
+		if (status != QDF_STATUS_SUCCESS) {
 			qdf_spin_unlock_bh(&mgmt_txrx_ctx->mgmt_txrx_ctx_lock);
-			mgmt_txrx_err("Couldn't allocate memory for rx handler node");
 			qdf_nbuf_free(buf);
-			status = QDF_STATUS_E_NOMEM;
 			goto rx_handler_mem_free;
 		}
+	}
 
-		rx_handler_node->comp_id = rx_handler->comp_id;
-		rx_handler_node->rx_cb = rx_handler->rx_cb;
-		rx_handler_node->next = NULL;
-
-		if (!rx_handler_head) {
-			rx_handler_head = rx_handler_node;
-			rx_handler_tail = rx_handler_head;
-		} else {
-			rx_handler_tail->next = rx_handler_node;
-			rx_handler_tail = rx_handler_tail->next;
-		}
-		rx_handler = rx_handler->next;
+	if (!rx_handler_head) {
+		qdf_spin_unlock_bh(&mgmt_txrx_ctx->mgmt_txrx_ctx_lock);
+		mgmt_txrx_info("No rx callback registered for frm_type: %d",
+			frm_type);
+		qdf_nbuf_free(buf);
+		status = QDF_STATUS_E_FAILURE;
+		goto dec_peer_ref_cnt;
 	}
 	qdf_spin_unlock_bh(&mgmt_txrx_ctx->mgmt_txrx_ctx_lock);
 

+ 41 - 39
umac/cmn_services/mgmt_txrx/dispatcher/src/wlan_mgmt_txrx_utils_api.c

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2016-2017 The Linux Foundation. All rights reserved.
  *
  * Permission to use, copy, modify, and/or distribute this software for
  * any purpose with or without fee is hereby granted, provided that the
@@ -343,6 +343,7 @@ static QDF_STATUS wlan_mgmt_txrx_create_rx_handler(
 /**
  * wlan_mgmt_txrx_delete_rx_handler() - deletes rx handler node for umac comp.
  * @mgmt_txrx_ctx: mgmt txrx context
+ * @mgmt_rx_cb: mgmt rx callback to be deregistered
  * @comp_id: umac component id
  * @frm_type: mgmt. frame for which cb to be registered.
  *
@@ -353,6 +354,7 @@ static QDF_STATUS wlan_mgmt_txrx_create_rx_handler(
  */
 static QDF_STATUS wlan_mgmt_txrx_delete_rx_handler(
 				struct mgmt_txrx_priv_context *mgmt_txrx_ctx,
+				mgmt_frame_rx_callback mgmt_rx_cb,
 				enum wlan_umac_comp_id comp_id,
 				enum mgmt_frame_type frm_type)
 {
@@ -362,7 +364,8 @@ static QDF_STATUS wlan_mgmt_txrx_delete_rx_handler(
 	qdf_spin_lock_bh(&mgmt_txrx_ctx->mgmt_txrx_ctx_lock);
 	rx_handler = mgmt_txrx_ctx->mgmt_rx_comp_cb[frm_type];
 	while (rx_handler) {
-		if (rx_handler->comp_id == comp_id) {
+		if (rx_handler->comp_id == comp_id &&
+				rx_handler->rx_cb == mgmt_rx_cb) {
 			if (rx_handler_prev)
 				rx_handler_prev->next =
 					rx_handler->next;
@@ -391,10 +394,11 @@ static QDF_STATUS wlan_mgmt_txrx_delete_rx_handler(
 	return QDF_STATUS_SUCCESS;
 }
 
-QDF_STATUS wlan_mgmt_txrx_register_rx_cb(struct wlan_objmgr_psoc *psoc,
-					 mgmt_frame_rx_callback mgmt_rx_cb,
-					 enum wlan_umac_comp_id comp_id,
-					 enum mgmt_frame_type frm_type)
+QDF_STATUS wlan_mgmt_txrx_register_rx_cb(
+			struct wlan_objmgr_psoc *psoc,
+			enum wlan_umac_comp_id comp_id,
+			struct mgmt_txrx_mgmt_frame_cb_info *frm_cb_info,
+			uint8_t num_entries)
 {
 	struct mgmt_txrx_priv_context *mgmt_txrx_ctx;
 	QDF_STATUS status;
@@ -410,13 +414,14 @@ QDF_STATUS wlan_mgmt_txrx_register_rx_cb(struct wlan_objmgr_psoc *psoc,
 		return QDF_STATUS_E_INVAL;
 	}
 
-	if (frm_type >= MGMT_MAX_FRAME_TYPE) {
-		mgmt_txrx_err("Invalid frame type %d passed", frm_type);
+	if (!num_entries || num_entries >= MGMT_MAX_FRAME_TYPE) {
+		mgmt_txrx_err("Invalid value for num_entries: %d passed",
+				num_entries);
 		return QDF_STATUS_E_INVAL;
 	}
 
-	if (!mgmt_rx_cb) {
-		mgmt_txrx_err("NULL rx cb passed for registration");
+	if (!frm_cb_info) {
+		mgmt_txrx_err("frame cb info pointer is NULL");
 		return QDF_STATUS_E_INVAL;
 	}
 
@@ -428,23 +433,19 @@ QDF_STATUS wlan_mgmt_txrx_register_rx_cb(struct wlan_objmgr_psoc *psoc,
 		return QDF_STATUS_E_FAILURE;
 	}
 
-	if (comp_id == WLAN_UMAC_COMP_MLME) {
-		for (i = 0; i < MGMT_MAX_FRAME_TYPE; i++) {
-			status = wlan_mgmt_txrx_create_rx_handler(mgmt_txrx_ctx,
-						mgmt_rx_cb, comp_id, i);
-			if (status != QDF_STATUS_SUCCESS) {
-				for (j = 0; j < i; j++) {
-					wlan_mgmt_txrx_delete_rx_handler(
-						mgmt_txrx_ctx, comp_id, j);
-				}
-				return status;
-			}
-		}
-	} else {
+	for (i = 0; i < num_entries; i++) {
 		status = wlan_mgmt_txrx_create_rx_handler(mgmt_txrx_ctx,
-					mgmt_rx_cb, comp_id, frm_type);
-		if (status != QDF_STATUS_SUCCESS)
+				frm_cb_info[i].mgmt_rx_cb, comp_id,
+				frm_cb_info[i].frm_type);
+		if (status != QDF_STATUS_SUCCESS) {
+			for (j = 0; j < i; j++) {
+				wlan_mgmt_txrx_delete_rx_handler(
+					mgmt_txrx_ctx,
+					frm_cb_info[j].mgmt_rx_cb,
+					comp_id, frm_cb_info[j].frm_type);
+			}
 			return status;
+		}
 	}
 
 	return QDF_STATUS_SUCCESS;
@@ -453,10 +454,10 @@ QDF_STATUS wlan_mgmt_txrx_register_rx_cb(struct wlan_objmgr_psoc *psoc,
 QDF_STATUS wlan_mgmt_txrx_deregister_rx_cb(
 			struct wlan_objmgr_psoc *psoc,
 			enum wlan_umac_comp_id comp_id,
-			enum mgmt_frame_type frm_type)
+			struct mgmt_txrx_mgmt_frame_cb_info *frm_cb_info,
+			uint8_t num_entries)
 {
 	struct mgmt_txrx_priv_context *mgmt_txrx_ctx;
-	QDF_STATUS status;
 	uint8_t i;
 
 	if (!psoc) {
@@ -469,10 +470,17 @@ QDF_STATUS wlan_mgmt_txrx_deregister_rx_cb(
 		return QDF_STATUS_E_INVAL;
 	}
 
-	if (frm_type >= MGMT_MAX_FRAME_TYPE) {
-		mgmt_txrx_err("Invalid frame type %d passed", frm_type);
+	if (!num_entries || num_entries >= MGMT_MAX_FRAME_TYPE) {
+		mgmt_txrx_err("Invalid value for num_entries: %d passed",
+				num_entries);
 		return QDF_STATUS_E_INVAL;
 	}
+
+	if (!frm_cb_info) {
+		mgmt_txrx_err("frame cb info pointer is NULL");
+		return QDF_STATUS_E_INVAL;
+	}
+
 	mgmt_txrx_ctx = (struct mgmt_txrx_priv_context *)
 			wlan_objmgr_psoc_get_comp_private_obj(psoc,
 				WLAN_UMAC_COMP_MGMT_TXRX);
@@ -481,16 +489,10 @@ QDF_STATUS wlan_mgmt_txrx_deregister_rx_cb(
 		return QDF_STATUS_E_FAILURE;
 	}
 
-	if (comp_id == WLAN_UMAC_COMP_MLME) {
-		for (i = 0; i < MGMT_MAX_FRAME_TYPE; i++) {
-			wlan_mgmt_txrx_delete_rx_handler(mgmt_txrx_ctx,
-					comp_id, i);
-		}
-	} else {
-		status = wlan_mgmt_txrx_delete_rx_handler(mgmt_txrx_ctx,
-				comp_id, frm_type);
-		if (status != QDF_STATUS_SUCCESS)
-			return status;
+	for (i = 0; i < num_entries; i++) {
+		wlan_mgmt_txrx_delete_rx_handler(mgmt_txrx_ctx,
+				frm_cb_info[i].mgmt_rx_cb, comp_id,
+				frm_cb_info[i].frm_type);
 	}
 
 	return QDF_STATUS_SUCCESS;