瀏覽代碼

qcacmn: Add crash info in global shmem arena

Changes to add chip crash info in global shared mem arena
and expose the respective APIs to qca_ol.
Also add APIs to process global link info tlvs in order
to offset to crash info.

CRs-Fixed: 3121465
Change-Id: Idabf9fb8d4755bdd755897b3c09d2e28259a6f46
Shwetha G K 3 年之前
父節點
當前提交
8b4151516b

+ 47 - 0
target_if/init_deinit/inc/mlo_global_h_shmem_arena.h

@@ -67,6 +67,32 @@ struct wlan_host_mlo_glb_rx_reo_snapshot_info {
 	struct wlan_host_mlo_glb_rx_reo_per_link_info *link_info;
 };
 
+/**
+ * wlan_host_mlo_glb_per_chip_crash_info - per chip crash information in MLO
+ * global shared memory
+ * @chip_id: MLO Chip ID
+ * @crash_reason: Address of the crash_reason corresponding to chip_id
+ */
+struct wlan_host_mlo_glb_per_chip_crash_info {
+	uint8_t chip_id;
+	void *crash_reason;
+};
+
+/**
+ * wlan_host_mlo_glb_chip_crash_info - chip crash information in MLO
+ * global shared memory
+ * @no_of_chips: No of partner chip to which crash information is shared
+ * @valid_chip_bmap: Bitmap to indicate the chip to which the crash information
+ * is shared
+ * @per_chip_crash_info: pointer to an array of crash information associated
+ * with each chip
+ */
+struct wlan_host_mlo_glb_chip_crash_info {
+	uint8_t no_of_chips;
+	qdf_bitmap(valid_chip_bmap, QDF_CHAR_BIT);
+	struct wlan_host_mlo_glb_per_chip_crash_info *per_chip_crash_info;
+};
+
 /**
  * wlan_host_mlo_glb_h_shmem_arena_ctx - MLO Global shared memory arena context
  * @shmem_params: shared memory parameters
@@ -76,6 +102,7 @@ struct wlan_host_mlo_glb_rx_reo_snapshot_info {
 struct wlan_host_mlo_glb_h_shmem_arena_ctx {
 	struct wlan_host_mlo_glb_h_shmem_params shmem_params;
 	struct wlan_host_mlo_glb_rx_reo_snapshot_info rx_reo_snapshot_info;
+	struct wlan_host_mlo_glb_chip_crash_info chip_crash_info;
 	qdf_atomic_t init_count;
 };
 
@@ -100,6 +127,26 @@ QDF_STATUS mlo_glb_h_shmem_arena_ctx_init(void *arena_vaddr,
 QDF_STATUS mlo_glb_h_shmem_arena_ctx_deinit(void);
 #endif
 
+#ifdef WLAN_MLO_GLOBAL_SHMEM_SUPPORT
+/**
+ * mlo_glb_h_shmem_arena_get_crash_reason_address(): get the address of crash
+ * reason associated with chip_id
+ *
+ * Return: Address of crash_reason field fron global shmem arena in case of
+ * success, else returns NULL
+ */
+void *mlo_glb_h_shmem_arena_get_crash_reason_address(uint8_t chip_id);
+
+/**
+ * mlo_glb_h_shmem_arena_get_no_of_chips_from_crash_info() - Get number of chips
+ * from crash info
+ *
+ * Return: number of chips participating in MLO from crash info shared by target
+ * in case of sccess, else returns 0
+ */
+uint8_t mlo_glb_h_shmem_arena_get_no_of_chips_from_crash_info(void);
+#endif
+
 #ifdef WLAN_MGMT_RX_REO_SUPPORT
 /**
  * mgmt_rx_reo_get_num_links() - Get number of links to be used by MGMT Rx REO

+ 310 - 1
target_if/init_deinit/src/mlo_global_h_shmem_arena.c

@@ -273,6 +273,95 @@ extract_mlo_glb_rx_reo_snapshot_info_tlv(
 	return tlv_len;
 }
 
+/**
+ * extract_mlo_glb_link_info_tlv() - extract lobal link info from shmem
+ * @data: Pointer to the first TLV in the arena
+ * @remaining_len: Length (in bytes) remaining in the arena from @data pointer
+ * @link_info: Pointer to which link info needs to be copied
+ *
+ * Return: On success, the number of bytes parsed. On failure, -1.
+ */
+static int
+extract_mlo_glb_link_info_tlv(uint8_t *data,
+			      size_t remaining_len,
+			      uint32_t *link_info)
+{
+	mlo_glb_link_info *ptlv;
+	uint32_t tlv_len, tlv_tag;
+
+	qdf_assert_always(data);
+	qdf_assert_always(link_info);
+
+	if (process_tlv_header(data, remaining_len,
+			       MLO_SHMEM_TLV_STRUCT_MLO_GLB_LINK_INFO,
+			       &tlv_len, &tlv_tag) != 0) {
+		return -EPERM;
+	}
+
+	ptlv = (mlo_glb_link_info *)data;
+
+	*link_info = get_field_value_in_tlv(ptlv, link_info, tlv_len);
+
+	return tlv_len;
+}
+
+/**
+ * process_mlo_glb_per_link_status_tlv() - process per link info
+ * @data: Pointer to the first TLV in the arena
+ * @remaining_len: Length (in bytes) remaining in the arena from @data pointer
+ *
+ * Return: On success, the number of bytes parsed. On failure, -1.
+ */
+static int
+process_mlo_glb_per_link_status_tlv(uint8_t *data, size_t remaining_len)
+{
+	uint32_t tlv_len, tlv_tag;
+
+	qdf_assert_always(data);
+
+	if (process_tlv_header(data, remaining_len,
+			       MLO_SHMEM_TLV_STRUCT_MLO_GLB_LINK,
+			       &tlv_len, &tlv_tag) != 0) {
+		return -EPERM;
+	}
+
+	return tlv_len;
+}
+
+/**
+ * parse_global_link_info() - parse lobal link info
+ * @data: Pointer to the first TLV in the arena
+ * @remaining_len: Length (in bytes) remaining in the arena from @data pointer
+ *
+ * Return: On success, the number of bytes parsed. On failure, -1.
+ */
+static int
+parse_global_link_info(uint8_t *data, size_t remaining_len)
+{
+	int parsed_bytes, len;
+	uint8_t link;
+	uint32_t link_info;
+	uint8_t num_links;
+
+	qdf_assert_always(data);
+
+	/* Extract MLO_SHMEM_TLV_STRUCT_MLO_GLB_LINK_INFO_TLV */
+	len = extract_mlo_glb_link_info_tlv(data, remaining_len, &link_info);
+	validate_parsed_bytes_advance_data_pointer(len, data, remaining_len);
+	parsed_bytes = len;
+
+	num_links = MLO_SHMEM_GLB_LINK_INFO_PARAM_NO_OF_LINKS_GET(link_info);
+
+	for (link = 0; link < num_links; link++) {
+		len = process_mlo_glb_per_link_status_tlv(data, remaining_len);
+		validate_parsed_bytes_advance_data_pointer(len, data,
+							   remaining_len);
+		parsed_bytes += len;
+	}
+
+	return parsed_bytes;
+}
+
 /**
  * free_mlo_glb_rx_reo_per_link_info() - Free Rx REO per-link info
  * @snapshot_info: Pointer to MGMT Rx REO snapshot info
@@ -366,6 +455,213 @@ extract_mlo_glb_rx_reo_snapshot_info(
 	return parsed_bytes;
 }
 
+/**
+ * mlo_glb_h_shmem_arena_get_no_of_chips_from_crash_info() - get the number of
+ * chips from crash info
+ *
+ * Return: number of chips participating in MLO from crash info shared by target
+ * in case of success, else returns 0
+ */
+uint8_t mlo_glb_h_shmem_arena_get_no_of_chips_from_crash_info(void)
+{
+	struct wlan_host_mlo_glb_h_shmem_arena_ctx *shmem_arena_ctx;
+
+	shmem_arena_ctx = get_shmem_arena_ctx();
+
+	if (!shmem_arena_ctx) {
+		target_if_err("mlo_glb_h_shmem_arena context is NULL");
+		return 0;
+	}
+
+	return shmem_arena_ctx->chip_crash_info.no_of_chips;
+}
+
+/**
+ * mlo_glb_h_shmem_arena_get_crash_reason_address() - get the address of crash
+ * reason associated with chip_id
+ *
+ * Return: Address of crash_reason field fron global shmem arena in case of
+ * success, else returns NULL
+ */
+void *mlo_glb_h_shmem_arena_get_crash_reason_address(uint8_t chip_id)
+{
+	struct wlan_host_mlo_glb_h_shmem_arena_ctx *shmem_arena_ctx;
+	struct wlan_host_mlo_glb_chip_crash_info *crash_info;
+	struct wlan_host_mlo_glb_per_chip_crash_info *per_chip_crash_info;
+	uint8_t chip;
+
+	shmem_arena_ctx = get_shmem_arena_ctx();
+	if (!shmem_arena_ctx) {
+		target_if_err("mlo_glb_h_shmem_arena context is NULL");
+		return NULL;
+	}
+
+	crash_info = &shmem_arena_ctx->chip_crash_info;
+
+	for (chip = 0; chip < crash_info->no_of_chips; chip++) {
+		per_chip_crash_info = &crash_info->per_chip_crash_info[chip];
+
+		if (chip_id == per_chip_crash_info->chip_id)
+			break;
+	}
+
+	if (chip == crash_info->no_of_chips) {
+		target_if_err("No crash info corressponding to chip %u",
+			      chip_id);
+		return NULL;
+	}
+
+	return per_chip_crash_info->crash_reason;
+}
+
+/**
+ * free_mlo_glb_per_chip_crash_info() - free per chip crash info
+ * @crash_info: Pointer to crash info
+ *
+ * Return: None
+ */
+static void free_mlo_glb_per_chip_crash_info(
+		struct wlan_host_mlo_glb_chip_crash_info *crash_info)
+{
+	if (crash_info) {
+		qdf_mem_free(crash_info->per_chip_crash_info);
+		crash_info->per_chip_crash_info = NULL;
+	}
+}
+
+/**
+ * extract_mlo_glb_per_chip_crash_info_tlv() - extract PER_CHIP_CRASH_INFO TLV
+ * @data: Pointer to start of the TLV
+ * @remaining_len: Length (in bytes) remaining in the arena from @data pointer
+ * @chip_id: Chip id to which the crash info tlv being extracted.
+ * @chip_crash_info: Pointer to the per chip crash info. This API will populate
+ * the crash_reason address & chip_id into chip_crash_info
+ */
+static int extract_mlo_glb_per_chip_crash_info_tlv(
+		uint8_t *data, size_t remaining_len, uint8_t chip_id,
+		struct wlan_host_mlo_glb_per_chip_crash_info *chip_crash_info)
+{
+	mlo_glb_per_chip_crash_info *ptlv;
+	uint32_t tlv_len, tlv_tag;
+	uint8_t *crash_reason;
+
+	qdf_assert_always(data);
+	qdf_assert_always(chip_crash_info);
+
+	/* process MLO_SHMEM_TLV_STRUCT_MLO_GLB_PER_CHIP_CRASH_INFO TLV */
+	if (process_tlv_header(data, remaining_len,
+			       MLO_SHMEM_TLV_STRUCT_MLO_GLB_PER_CHIP_CRASH_INFO,
+			       &tlv_len, &tlv_tag) != 0) {
+		return -EPERM;
+	}
+
+	ptlv = (mlo_glb_per_chip_crash_info *)data;
+
+	chip_crash_info->chip_id = chip_id;
+	crash_reason = (uint8_t *)get_field_pointer_in_tlv(
+			ptlv, crash_reason, tlv_len);
+	chip_crash_info->crash_reason = (void *)crash_reason;
+	return tlv_len;
+}
+
+/**
+ * extract_mlo_glb_chip_crash_info_tlv() - extract CHIP_CRASH_INFO TLV
+ * @data: Pointer to start of the TLV
+ * @remaining_len: Length (in bytes) remaining in the arena from @data pointer
+ * @crash_info: Pointer to the crash_info structure to which crash info fields
+ * are populated.
+ *
+ * Return: On success, the number of bytes parsed. On failure, -1.
+ */
+static int extract_mlo_glb_chip_crash_info_tlv(
+		uint8_t *data, size_t remaining_len,
+		struct wlan_host_mlo_glb_chip_crash_info *crash_info)
+{
+	mlo_glb_chip_crash_info *ptlv;
+	uint32_t tlv_len, tlv_tag;
+	uint32_t chip_info;
+	uint8_t chip_map;
+
+	qdf_assert_always(data);
+	qdf_assert_always(crash_info);
+
+	if (process_tlv_header(data, remaining_len,
+			       MLO_SHMEM_TLV_STRUCT_MLO_GLB_CHIP_CRASH_INFO,
+			       &tlv_len, &tlv_tag) != 0) {
+		return -EPERM;
+	}
+
+	ptlv = (mlo_glb_chip_crash_info *)data;
+	chip_info = get_field_value_in_tlv(ptlv, chip_info, tlv_len);
+	crash_info->no_of_chips =
+		MLO_SHMEM_CHIP_CRASH_INFO_PARAM_NO_OF_CHIPS_GET(chip_info);
+	chip_map =
+		MLO_SHMEM_CHIP_CRASH_INFO_PARAM_VALID_CHIP_BMAP_GET(chip_info);
+	qdf_mem_copy(crash_info->valid_chip_bmap,
+		     &chip_map,
+		     qdf_min(sizeof(crash_info->valid_chip_bmap),
+			     sizeof(chip_map)));
+
+	crash_info->per_chip_crash_info =
+		qdf_mem_malloc(sizeof(*crash_info->per_chip_crash_info) *
+			       crash_info->no_of_chips);
+
+	if (!crash_info->per_chip_crash_info) {
+		target_if_err("Couldn't allocate memory for crash info");
+		return -EPERM;
+	}
+
+	return tlv_len;
+}
+
+/**
+ * extract_mlo_glb_chip_crash_info() - extract the crash information from global
+ * shmem arena
+ * @data: Pointer to start of the TLV
+ * @remaining_len: Length (in bytes) remaining in the arena from @data pointer
+ * @crash_info: Pointer to the crash_info structure to which crash info fields
+ * are populated.
+ *
+ * Return: On success, the number of bytes parsed. On failure, -1.
+ */
+static int extract_mlo_glb_chip_crash_info(
+		uint8_t *data, size_t remaining_len,
+		struct wlan_host_mlo_glb_chip_crash_info *crash_info)
+{
+	int parsed_bytes, len;
+	int cur_chip_id;
+	qdf_bitmap(valid_chip_bmap, QDF_CHAR_BIT);
+	uint8_t chip;
+
+	qdf_assert_always(data);
+	qdf_assert_always(crash_info);
+
+	/* Extract MLO_SHMEM_TLV_STRUCT_MLO_GLB_CHIP_CRASH_INFO_TLV */
+	len = extract_mlo_glb_chip_crash_info_tlv(
+			data, remaining_len, crash_info);
+	validate_parsed_bytes_advance_data_pointer(len, data, remaining_len);
+
+	parsed_bytes = len;
+	qdf_mem_copy(valid_chip_bmap,
+		     crash_info->valid_chip_bmap,
+		     qdf_min(sizeof(valid_chip_bmap),
+			     sizeof(crash_info->valid_chip_bmap)));
+	/* Foreach valid chip_id */
+	for (chip = 0; chip < crash_info->no_of_chips; chip++) {
+		cur_chip_id = qdf_find_first_bit(valid_chip_bmap, QDF_CHAR_BIT);
+		qdf_clear_bit(cur_chip_id, valid_chip_bmap);
+		qdf_assert_always(cur_chip_id >= 0);
+		/* Extract per_chip_crash_info */
+		len = extract_mlo_glb_per_chip_crash_info_tlv(
+				data, remaining_len, cur_chip_id,
+				&crash_info->per_chip_crash_info[chip]);
+		validate_parsed_bytes_advance_data_pointer(
+				len, data, remaining_len);
+		parsed_bytes += len;
+	}
+	return parsed_bytes;
+}
+
 /**
  * extract_mlo_glb_h_shmem_tlv() - extract MLO_SHMEM_TLV_STRUCT_MLO_GLB_H_SHMEM
  * TLV
@@ -427,13 +723,22 @@ static int parse_mlo_glb_h_shmem_arena(
 	len = extract_mlo_glb_h_shmem_tlv(data, remaining_len,
 					  &shmem_arena_ctx->shmem_params);
 	validate_parsed_bytes_advance_data_pointer(len, data, remaining_len);
-	parsed_bytes += len;
+	parsed_bytes = len;
 
 	len = extract_mlo_glb_rx_reo_snapshot_info(
 		data, remaining_len, &shmem_arena_ctx->rx_reo_snapshot_info);
 	validate_parsed_bytes_advance_data_pointer(len, data, remaining_len);
 	parsed_bytes += len;
 
+	len = parse_global_link_info(data, remaining_len);
+	validate_parsed_bytes_advance_data_pointer(len, data, remaining_len);
+	parsed_bytes += len;
+
+	len = extract_mlo_glb_chip_crash_info(
+			data, remaining_len, &shmem_arena_ctx->chip_crash_info);
+	validate_parsed_bytes_advance_data_pointer(len, data, remaining_len);
+	parsed_bytes += len;
+
 	return parsed_bytes;
 }
 
@@ -456,6 +761,8 @@ QDF_STATUS mlo_glb_h_shmem_arena_ctx_init(void *arena_vaddr,
 					shmem_arena_ctx) < 0) {
 		free_mlo_glb_rx_reo_per_link_info(
 			&shmem_arena_ctx->rx_reo_snapshot_info);
+		free_mlo_glb_per_chip_crash_info(
+			&shmem_arena_ctx->chip_crash_info);
 		return QDF_STATUS_E_FAILURE;
 	}
 
@@ -487,6 +794,8 @@ QDF_STATUS mlo_glb_h_shmem_arena_ctx_deinit(void)
 
 	free_mlo_glb_rx_reo_per_link_info(
 		&shmem_arena_ctx->rx_reo_snapshot_info);
+	free_mlo_glb_per_chip_crash_info(
+		&shmem_arena_ctx->chip_crash_info);
 
 success:
 	return QDF_STATUS_SUCCESS;

+ 32 - 0
target_if/init_deinit/src/mlo_global_h_shmem_arena_api.c

@@ -119,6 +119,36 @@ QDF_STATUS mgmt_rx_reo_register_wifi3_0_ops(
 }
 #endif
 
+#ifdef WLAN_MLO_GLOBAL_SHMEM_SUPPORT
+static inline
+void global_shmem_register_target_recovery_ops(
+	struct wlan_lmac_if_global_shmem_local_ops *shmem_local_ops)
+{
+	if (!shmem_local_ops) {
+		target_if_err("Low level ops of global shmem is NULL");
+		return;
+	}
+
+	shmem_local_ops->get_crash_reason_address =
+		mlo_glb_h_shmem_arena_get_crash_reason_address;
+	shmem_local_ops->get_no_of_chips_from_crash_info =
+		mlo_glb_h_shmem_arena_get_no_of_chips_from_crash_info;
+}
+#else
+static inline
+void global_shmem_register_target_recovery_ops(
+	struct wlan_lmac_if_global_shmem_local_ops *shmem_local_ops)
+{
+	if (!shmem_local_ops) {
+		target_if_err("Low level ops of global shmem is NULL");
+		return;
+	}
+
+	shmem_local_ops->get_crash_reason_address = NULL;
+	shmem_local_ops->get_no_of_chips_from_crash_info = NULL;
+}
+#endif
+
 QDF_STATUS global_shmem_register_wifi3_0_ops(
 	struct wlan_lmac_if_global_shmem_local_ops *shmem_local_ops)
 {
@@ -132,6 +162,8 @@ QDF_STATUS global_shmem_register_wifi3_0_ops(
 	shmem_local_ops->deinit_shmem_arena_ctx =
 		mlo_glb_h_shmem_arena_ctx_deinit;
 
+	global_shmem_register_target_recovery_ops(shmem_local_ops);
+
 	shmem_local_ops->implemented = true;
 
 	return QDF_STATUS_SUCCESS;