Просмотр исходного кода

qcacmn: Register IRQ for near full irq

WCN7850 has support for near full indication for
the consumer srngs. This interrupt is used to take
preventive actions to avoid ring full watchdog irq
trigger.

Register for the near full irq and add the necessary
ext groups for these near-full irqs.

Change-Id: Ic16381fceabc54e6c52b34dd13abea74cad4d38c
CRs-Fixed: 2965081
Rakesh Pillai 4 лет назад
Родитель
Сommit
37e2c6d9ed

+ 395 - 38
dp/wifi3.0/dp_main.c

@@ -1221,20 +1221,271 @@ static int dp_srng_find_ring_in_mask(int ring_num, uint8_t *grp_mask)
 	return -QDF_STATUS_E_NOENT;
 }
 
+/**
+ * dp_is_msi_group_number_invalid() - check msi_group_number valid or not
+ * @msi_group_number: MSI group number.
+ * @msi_data_count: MSI data count.
+ *
+ * Return: true if msi_group_number is invalid.
+ */
+#ifdef WLAN_ONE_MSI_VECTOR
+static bool dp_is_msi_group_number_invalid(int msi_group_number,
+					   int msi_data_count)
+{
+	return false;
+}
+#else
+static bool dp_is_msi_group_number_invalid(int msi_group_number,
+					   int msi_data_count)
+{
+	return msi_group_number > msi_data_count;
+}
+#endif
+
+#ifdef WLAN_FEATURE_NEAR_FULL_IRQ
+/**
+ * dp_is_reo_ring_num_in_nf_grp1() - Check if the current reo ring is part of
+ *				rx_near_full_grp1 mask
+ * @soc: Datapath SoC Handle
+ * @ring_num: REO ring number
+ *
+ * Return: 1 if the ring_num belongs to reo_nf_grp1,
+ *	   0, otherwise.
+ */
+static inline int
+dp_is_reo_ring_num_in_nf_grp1(struct dp_soc *soc, int ring_num)
+{
+	return (WLAN_CFG_RX_NEAR_FULL_IRQ_MASK_1 & (1 << ring_num));
+}
+
+/**
+ * dp_is_reo_ring_num_in_nf_grp2() - Check if the current reo ring is part of
+ *				rx_near_full_grp2 mask
+ * @soc: Datapath SoC Handle
+ * @ring_num: REO ring number
+ *
+ * Return: 1 if the ring_num belongs to reo_nf_grp2,
+ *	   0, otherwise.
+ */
+static inline int
+dp_is_reo_ring_num_in_nf_grp2(struct dp_soc *soc, int ring_num)
+{
+	return (WLAN_CFG_RX_NEAR_FULL_IRQ_MASK_2 & (1 << ring_num));
+}
+
+/**
+ * dp_srng_get_near_full_irq_mask() - Get near-full irq mask for a particular
+ *				ring type and number
+ * @soc: Datapath SoC handle
+ * @ring_type: SRNG type
+ * @ring_num: ring num
+ *
+ * Return: near ful irq mask pointer
+ */
+static inline
+uint8_t *dp_srng_get_near_full_irq_mask(struct dp_soc *soc,
+					enum hal_ring_type ring_type,
+					int ring_num)
+{
+	uint8_t *nf_irq_mask = NULL;
+
+	switch (ring_type) {
+	case WBM2SW_RELEASE:
+		if (ring_num < 3) {
+			nf_irq_mask = &soc->wlan_cfg_ctx->
+					int_tx_ring_near_full_irq_mask[0];
+		}
+		break;
+	case REO_DST:
+		if (dp_is_reo_ring_num_in_nf_grp1(soc, ring_num))
+			nf_irq_mask =
+			&soc->wlan_cfg_ctx->int_rx_ring_near_full_irq_1_mask[0];
+		else if (dp_is_reo_ring_num_in_nf_grp2(soc, ring_num))
+			nf_irq_mask =
+			&soc->wlan_cfg_ctx->int_rx_ring_near_full_irq_2_mask[0];
+		else
+			qdf_assert(0);
+		break;
+	default:
+		break;
+	}
+
+	return nf_irq_mask;
+}
+
+/**
+ * dp_srng_set_msi2_ring_params() - Set the msi2 addr/data in the ring params
+ * @soc: Datapath SoC handle
+ * @ring_params: srng params handle
+ * @msi2_addr: MSI2 addr to be set for the SRNG
+ * @msi2_data: MSI2 data to be set for the SRNG
+ *
+ * Return: None
+ */
+static inline
+void dp_srng_set_msi2_ring_params(struct dp_soc *soc,
+				  struct hal_srng_params *ring_params,
+				  qdf_dma_addr_t msi2_addr,
+				  uint32_t msi2_data)
+{
+	ring_params->msi2_addr = msi2_addr;
+	ring_params->msi2_data = msi2_data;
+}
+
+/**
+ * dp_srng_msi2_setup() - Setup MSI2 details for near full IRQ of an SRNG
+ * @soc: Datapath SoC handle
+ * @ring_params: ring_params for SRNG
+ * @ring_type: SENG type
+ * @ring_num: ring number for the SRNG
+ * @nf_msi_grp_num: near full msi group number
+ *
+ * Return: None
+ */
+static inline void
+dp_srng_msi2_setup(struct dp_soc *soc,
+		   struct hal_srng_params *ring_params,
+		   int ring_type, int ring_num, int nf_msi_grp_num)
+{
+	uint32_t msi_data_start, msi_irq_start, addr_low, addr_high;
+	int msi_data_count, ret;
+
+	ret = pld_get_user_msi_assignment(soc->osdev->dev, "DP",
+					  &msi_data_count, &msi_data_start,
+					  &msi_irq_start);
+	if (ret)
+		return;
+
+	if (nf_msi_grp_num < 0) {
+		dp_init_info("%pK: ring near full IRQ not part of an ext_group; ring_type: %d,ring_num %d",
+			     soc, ring_type, ring_num);
+		ring_params->msi2_addr = 0;
+		ring_params->msi2_data = 0;
+		return;
+	}
+
+	if (dp_is_msi_group_number_invalid(nf_msi_grp_num, msi_data_count)) {
+		dp_init_warn("%pK: 2 msi_groups will share an msi for near full IRQ; msi_group_num %d",
+			     soc, nf_msi_grp_num);
+		QDF_ASSERT(0);
+	}
+
+	pld_get_msi_address(soc->osdev->dev, &addr_low, &addr_high);
+
+	ring_params->nf_irq_support = 1;
+	ring_params->msi2_addr = addr_low;
+	ring_params->msi2_addr |= (qdf_dma_addr_t)(((uint64_t)addr_high) << 32);
+	ring_params->msi2_data = (nf_msi_grp_num % msi_data_count)
+		+ msi_data_start;
+	ring_params->flags |= HAL_SRNG_MSI_INTR;
+}
+
+/* Percentage of ring entries considered as nearly full */
+#define DP_NF_HIGH_THRESH_PERCENTAGE	75
+/* Percentage of ring entries considered as critically full */
+#define DP_NF_CRIT_THRESH_PERCENTAGE	90
+/* Percentage of ring entries considered as safe threshold */
+#define DP_NF_SAFE_THRESH_PERCENTAGE	50
+
+/**
+ * dp_srng_configure_nf_interrupt_thresholds() - Configure the thresholds for
+ *			near full irq
+ * @soc: Datapath SoC handle
+ * @ring_params: ring params for SRNG
+ * @ring_type: ring type
+ */
+static inline void
+dp_srng_configure_nf_interrupt_thresholds(struct dp_soc *soc,
+					  struct hal_srng_params *ring_params,
+					  int ring_type)
+{
+	if (ring_params->nf_irq_support) {
+		ring_params->high_thresh = (ring_params->num_entries *
+					    DP_NF_HIGH_THRESH_PERCENTAGE) / 100;
+		ring_params->crit_thresh = (ring_params->num_entries *
+					    DP_NF_CRIT_THRESH_PERCENTAGE) / 100;
+		ring_params->safe_thresh = (ring_params->num_entries *
+					    DP_NF_SAFE_THRESH_PERCENTAGE) /100;
+	}
+}
+
+/**
+ * dp_srng_set_nf_thresholds() - Set the near full thresholds to srng data
+ *			structure from the ring params
+ * @soc: Datapath SoC handle
+ * @srng: SRNG handle
+ * @ring_params: ring params for a SRNG
+ *
+ * Return: None
+ */
+static inline void
+dp_srng_set_nf_thresholds(struct dp_soc *soc, struct dp_srng *srng,
+			  struct hal_srng_params *ring_params)
+{
+	srng->crit_thresh = ring_params->crit_thresh;
+	srng->safe_thresh = ring_params->safe_thresh;
+}
+
+#else
+static inline
+uint8_t *dp_srng_get_near_full_irq_mask(struct dp_soc *soc,
+					enum hal_ring_type ring_type,
+					int ring_num)
+{
+	return NULL;
+}
+
+static inline
+void dp_srng_set_msi2_ring_params(struct dp_soc *soc,
+				  struct hal_srng_params *ring_params,
+				  qdf_dma_addr_t msi2_addr,
+				  uint32_t msi2_data)
+{
+}
+
+static inline void
+dp_srng_msi2_setup(struct dp_soc *soc,
+		   struct hal_srng_params *ring_params,
+		   int ring_type, int ring_num, int nf_msi_grp_num)
+{
+}
+
+static inline void
+dp_srng_configure_nf_interrupt_thresholds(struct dp_soc *soc,
+					  struct hal_srng_params *ring_params,
+					  int ring_type)
+{
+}
+
+static inline void
+dp_srng_set_nf_thresholds(struct dp_soc *soc, struct dp_srng *srng,
+			  struct hal_srng_params *ring_params)
+{
+}
+#endif
+
 static int dp_srng_calculate_msi_group(struct dp_soc *soc,
 				       enum hal_ring_type ring_type,
-				       int ring_num)
+				       int ring_num,
+				       int *reg_msi_grp_num,
+				       bool nf_irq_support,
+				       int *nf_msi_grp_num)
 {
-	uint8_t *grp_mask;
+	uint8_t *grp_mask, *nf_irq_mask = NULL;
+	bool nf_irq_enabled = false;
 
 	switch (ring_type) {
 	case WBM2SW_RELEASE:
 		/* dp_tx_comp_handler - soc->tx_comp_ring */
-		if (ring_num < 3)
+		if (ring_num < 3) {
 			grp_mask = &soc->wlan_cfg_ctx->int_tx_ring_mask[0];
-
+			nf_irq_mask = dp_srng_get_near_full_irq_mask(soc,
+								     ring_type,
+								     ring_num);
+			if (nf_irq_mask)
+				nf_irq_enabled = true;
 		/* dp_rx_wbm_err_process - soc->rx_rel_ring */
-		else if (ring_num == 3) {
+		} else if (ring_num == 3) {
 			/* sw treats this as a separate ring type */
 			grp_mask = &soc->wlan_cfg_ctx->
 				int_rx_wbm_rel_ring_mask[0];
@@ -1253,6 +1504,10 @@ static int dp_srng_calculate_msi_group(struct dp_soc *soc,
 	case REO_DST:
 		/* dp_rx_process - soc->reo_dest_ring */
 		grp_mask = &soc->wlan_cfg_ctx->int_rx_ring_mask[0];
+		nf_irq_mask = dp_srng_get_near_full_irq_mask(soc, ring_type,
+							     ring_num);
+		if (nf_irq_mask)
+			nf_irq_enabled = true;
 	break;
 
 	case REO_STATUS:
@@ -1305,7 +1560,14 @@ static int dp_srng_calculate_msi_group(struct dp_soc *soc,
 	break;
 	}
 
-	return dp_srng_find_ring_in_mask(ring_num, grp_mask);
+	*reg_msi_grp_num = dp_srng_find_ring_in_mask(ring_num, grp_mask);
+
+	if (nf_irq_support && nf_irq_enabled) {
+		*nf_msi_grp_num = dp_srng_find_ring_in_mask(ring_num,
+							    nf_irq_mask);
+	}
+
+	return QDF_STATUS_SUCCESS;
 }
 
 /*
@@ -1355,34 +1617,19 @@ static int dp_get_num_msi_available(struct dp_soc *soc, int interrupt_mode)
 }
 #endif
 
-/**
- * dp_is_msi_group_number_invalid() - check msi_group_number valid or not
- * @msi_group_number: MSI group number.
- * @msi_data_count: MSI data count.
- *
- * Return: true if msi_group_number is valid.
- */
-#ifdef WLAN_ONE_MSI_VECTOR
-static bool dp_is_msi_group_number_invalid(int msi_group_number,
-					   int msi_data_count)
-{
-	return false;
-}
-#else
-static bool dp_is_msi_group_number_invalid(int msi_group_number,
-					   int msi_data_count)
-{
-	return msi_group_number > msi_data_count;
-}
-#endif
-
 static void dp_srng_msi_setup(struct dp_soc *soc, struct hal_srng_params
 			      *ring_params, int ring_type, int ring_num)
 {
-	int msi_group_number;
+	int reg_msi_grp_num;
+	/*
+	 * nf_msi_grp_num needs to be initialized with negative value,
+	 * to avoid configuring near-full msi for WBM2SW3 ring
+	 */
+	int nf_msi_grp_num = -1;
 	int msi_data_count;
 	int ret;
 	uint32_t msi_data_start, msi_irq_start, addr_low, addr_high;
+	bool nf_irq_support;
 
 	ret = pld_get_user_msi_assignment(soc->osdev->dev, "DP",
 					    &msi_data_count, &msi_data_start,
@@ -1391,20 +1638,33 @@ static void dp_srng_msi_setup(struct dp_soc *soc, struct hal_srng_params
 	if (ret)
 		return;
 
-	msi_group_number = dp_srng_calculate_msi_group(soc, ring_type,
-						       ring_num);
-	if (msi_group_number < 0) {
+	nf_irq_support = hal_srng_is_near_full_irq_supported(soc->hal_soc,
+							     ring_type,
+							     ring_num);
+	ret = dp_srng_calculate_msi_group(soc, ring_type, ring_num,
+					  &reg_msi_grp_num,
+					  nf_irq_support,
+					  &nf_msi_grp_num);
+	if (ret < 0) {
 		dp_init_info("%pK: ring not part of an ext_group; ring_type: %d,ring_num %d",
 			     soc, ring_type, ring_num);
 		ring_params->msi_addr = 0;
 		ring_params->msi_data = 0;
+		dp_srng_set_msi2_ring_params(soc, ring_params, 0, 0);
 		return;
 	}
 
-	if (dp_is_msi_group_number_invalid(msi_group_number, msi_data_count)) {
-		dp_init_warn("%pK: 2 msi_groups will share an msi; msi_group_num %d",
-			     soc, msi_group_number);
+	if (reg_msi_grp_num < 0) {
+		dp_init_info("%pK: ring not part of an ext_group; ring_type: %d,ring_num %d",
+			     soc, ring_type, ring_num);
+		ring_params->msi_addr = 0;
+		ring_params->msi_data = 0;
+		goto configure_msi2;
+	}
 
+	if (dp_is_msi_group_number_invalid(reg_msi_grp_num, msi_data_count)) {
+		dp_init_warn("%pK: 2 msi_groups will share an msi; msi_group_num %d",
+			     soc, reg_msi_grp_num);
 		QDF_ASSERT(0);
 	}
 
@@ -1412,9 +1672,18 @@ static void dp_srng_msi_setup(struct dp_soc *soc, struct hal_srng_params
 
 	ring_params->msi_addr = addr_low;
 	ring_params->msi_addr |= (qdf_dma_addr_t)(((uint64_t)addr_high) << 32);
-	ring_params->msi_data = (msi_group_number % msi_data_count)
+	ring_params->msi_data = (reg_msi_grp_num % msi_data_count)
 		+ msi_data_start;
 	ring_params->flags |= HAL_SRNG_MSI_INTR;
+
+configure_msi2:
+	if (!nf_irq_support) {
+		dp_srng_set_msi2_ring_params(soc, ring_params, 0, 0);
+		return;
+	}
+
+	dp_srng_msi2_setup(soc, ring_params, ring_type, ring_num,
+			   nf_msi_grp_num);
 }
 
 #ifdef FEATURE_AST
@@ -1576,6 +1845,8 @@ dp_srng_configure_interrupt_thresholds(struct dp_soc *soc,
 			soc->wlan_srng_cfg[ring_type].low_threshold;
 	if (ring_params->low_threshold)
 		ring_params->flags |= HAL_SRNG_LOW_THRES_INTR_ENABLE;
+
+	dp_srng_configure_nf_interrupt_thresholds(soc, ring_params, ring_type);
 }
 #else
 static void
@@ -1886,6 +2157,7 @@ static QDF_STATUS dp_srng_init(struct dp_soc *soc, struct dp_srng *srng,
 	} else {
 		ring_params.msi_data = 0;
 		ring_params.msi_addr = 0;
+		dp_srng_set_msi2_ring_params(soc, &ring_params, 0, 0);
 		dp_verbose_debug("Skipping MSI for ring_type: %d, ring_num %d",
 				 ring_type, ring_num);
 	}
@@ -1894,6 +2166,8 @@ static QDF_STATUS dp_srng_init(struct dp_soc *soc, struct dp_srng *srng,
 					       ring_type, ring_num,
 					       srng->num_entries);
 
+	dp_srng_set_nf_thresholds(soc, srng, &ring_params);
+
 	if (srng->cached)
 		ring_params.flags |= HAL_SRNG_CACHED_DESC;
 
@@ -2147,6 +2421,22 @@ budget_done:
 	return total_budget - budget;
 }
 
+#ifdef WLAN_FEATURE_NEAR_FULL_IRQ
+/**
+ * dp_service_near_full_srngs() - Bottom half handler to process the near
+ *				full IRQ on a SRNG
+ * @dp_ctx: Datapath SoC handle
+ * @dp_budget: Number of SRNGs which can be processed in a single attempt
+ *		without rescheduling
+ *
+ * Return: remaining budget/quota for the soc device
+ */
+static uint32_t dp_service_near_full_srngs(void *dp_ctx, uint32_t dp_budget)
+{
+	return 0;
+}
+#endif
+
 #ifndef QCA_HOST_MODE_WIFI_DISABLED
 
 /*
@@ -2722,6 +3012,15 @@ static void dp_soc_interrupt_map_calculate_msi(struct dp_soc *soc,
 					soc->wlan_cfg_ctx, intr_ctx_num);
 	int host2rxdma_mon_ring_mask = wlan_cfg_get_host2rxdma_mon_ring_mask(
 					soc->wlan_cfg_ctx, intr_ctx_num);
+	int rx_near_full_grp_1_mask =
+		wlan_cfg_get_rx_near_full_grp_1_mask(soc->wlan_cfg_ctx,
+						     intr_ctx_num);
+	int rx_near_full_grp_2_mask =
+		wlan_cfg_get_rx_near_full_grp_2_mask(soc->wlan_cfg_ctx,
+						     intr_ctx_num);
+	int tx_ring_near_full_mask =
+		wlan_cfg_get_tx_ring_near_full_mask(soc->wlan_cfg_ctx,
+						    intr_ctx_num);
 
 	unsigned int vector =
 		(intr_ctx_num % msi_vector_count) + msi_vector_start;
@@ -2731,7 +3030,9 @@ static void dp_soc_interrupt_map_calculate_msi(struct dp_soc *soc,
 
 	if (tx_mask | rx_mask | rx_mon_mask | rx_err_ring_mask |
 	    rx_wbm_rel_ring_mask | reo_status_ring_mask | rxdma2host_ring_mask |
-	    host2rxdma_ring_mask | host2rxdma_mon_ring_mask)
+	    host2rxdma_ring_mask | host2rxdma_mon_ring_mask |
+	    rx_near_full_grp_1_mask | rx_near_full_grp_2_mask |
+	    tx_ring_near_full_mask)
 		irq_id_map[num_irq++] =
 			pld_get_msi_irq(soc->osdev->dev, vector);
 
@@ -2758,6 +3059,36 @@ static void dp_soc_interrupt_map_calculate(struct dp_soc *soc, int intr_ctx_num,
 				msi_vector_count, msi_vector_start);
 }
 
+#ifdef WLAN_FEATURE_NEAR_FULL_IRQ
+/**
+ * dp_soc_near_full_interrupt_attach() - Register handler for DP near fill irq
+ * @soc: DP soc handle
+ * @num_irq: IRQ number
+ * @irq_id_map: IRQ map
+ * intr_id: interrupt context ID
+ *
+ * Return: 0 for success. nonzero for failure.
+ */
+static inline int
+dp_soc_near_full_interrupt_attach(struct dp_soc *soc, int num_irq,
+				  int irq_id_map[], int intr_id)
+{
+	return hif_register_ext_group(soc->hif_handle,
+				      num_irq, irq_id_map,
+				      dp_service_near_full_srngs,
+				      &soc->intr_ctx[intr_id], "dp_nf_intr",
+				      HIF_EXEC_NAPI_TYPE,
+				      QCA_NAPI_DEF_SCALE_BIN_SHIFT);
+}
+#else
+static inline int
+dp_soc_near_full_interrupt_attach(struct dp_soc *soc, int num_irq,
+				  int *irq_id_map, int intr_id)
+{
+	return 0;
+}
+#endif
+
 /*
  * dp_soc_interrupt_attach() - Register handlers for DP interrupts
  * @txrx_soc: DP SOC handle
@@ -2803,6 +3134,15 @@ static QDF_STATUS dp_soc_interrupt_attach(struct cdp_soc_t *txrx_soc)
 		int host2rxdma_mon_ring_mask =
 			wlan_cfg_get_host2rxdma_mon_ring_mask(
 				soc->wlan_cfg_ctx, i);
+		int rx_near_full_grp_1_mask =
+			wlan_cfg_get_rx_near_full_grp_1_mask(soc->wlan_cfg_ctx,
+							     i);
+		int rx_near_full_grp_2_mask =
+			wlan_cfg_get_rx_near_full_grp_2_mask(soc->wlan_cfg_ctx,
+							     i);
+		int tx_ring_near_full_mask =
+			wlan_cfg_get_tx_ring_near_full_mask(soc->wlan_cfg_ctx,
+							    i);
 
 		soc->intr_ctx[i].dp_intr_id = i;
 		soc->intr_ctx[i].tx_ring_mask = tx_mask;
@@ -2815,6 +3155,12 @@ static QDF_STATUS dp_soc_interrupt_attach(struct cdp_soc_t *txrx_soc)
 		soc->intr_ctx[i].reo_status_ring_mask = reo_status_ring_mask;
 		soc->intr_ctx[i].host2rxdma_mon_ring_mask =
 			 host2rxdma_mon_ring_mask;
+		soc->intr_ctx[i].rx_near_full_grp_1_mask =
+						rx_near_full_grp_1_mask;
+		soc->intr_ctx[i].rx_near_full_grp_2_mask =
+						rx_near_full_grp_2_mask;
+		soc->intr_ctx[i].tx_ring_near_full_mask =
+						tx_ring_near_full_mask;
 
 		soc->intr_ctx[i].soc = soc;
 
@@ -2823,10 +3169,17 @@ static QDF_STATUS dp_soc_interrupt_attach(struct cdp_soc_t *txrx_soc)
 		dp_soc_interrupt_map_calculate(soc, i, &irq_id_map[0],
 					       &num_irq);
 
-		ret = hif_register_ext_group(soc->hif_handle,
+		if (rx_near_full_grp_1_mask | rx_near_full_grp_2_mask |
+		    tx_ring_near_full_mask) {
+			dp_soc_near_full_interrupt_attach(soc, num_irq,
+							  irq_id_map, i);
+		} else {
+			ret = hif_register_ext_group(soc->hif_handle,
 				num_irq, irq_id_map, dp_service_srngs,
 				&soc->intr_ctx[i], "dp_intr",
-				HIF_EXEC_NAPI_TYPE, QCA_NAPI_DEF_SCALE_BIN_SHIFT);
+				HIF_EXEC_NAPI_TYPE,
+				QCA_NAPI_DEF_SCALE_BIN_SHIFT);
+		}
 
 		if (ret) {
 			dp_init_err("%pK: failed, ret = %d", soc, ret);
@@ -2859,6 +3212,7 @@ static void dp_soc_interrupt_detach(struct cdp_soc_t *txrx_soc)
 	} else {
 		hif_deconfigure_ext_group_interrupts(soc->hif_handle);
 		hif_deregister_exec_group(soc->hif_handle, "dp_intr");
+		hif_deregister_exec_group(soc->hif_handle, "dp_nf_intr");
 	}
 
 	for (i = 0; i < wlan_cfg_get_num_contexts(soc->wlan_cfg_ctx); i++) {
@@ -2871,6 +3225,9 @@ static void dp_soc_interrupt_detach(struct cdp_soc_t *txrx_soc)
 		soc->intr_ctx[i].rxdma2host_ring_mask = 0;
 		soc->intr_ctx[i].host2rxdma_ring_mask = 0;
 		soc->intr_ctx[i].host2rxdma_mon_ring_mask = 0;
+		soc->intr_ctx[i].rx_near_full_grp_1_mask = 0;
+		soc->intr_ctx[i].rx_near_full_grp_2_mask = 0;
+		soc->intr_ctx[i].tx_ring_near_full_mask = 0;
 
 		hif_event_history_deinit(soc->hif_handle, i);
 		qdf_lro_deinit(soc->intr_ctx[i].lro_ctx);

+ 13 - 0
dp/wifi3.0/dp_types.h

@@ -668,6 +668,9 @@ struct dp_txrx_pool_stats {
  * @cached: is the srng ring memory cached or un-cached memory
  * @irq: irq number of the srng ring
  * @num_entries: number of entries in the srng ring
+ * @is_mem_prealloc: Is this srng memeory pre-allocated
+ * @crit_thresh: Critical threshold for near-full processing of this srng
+ * @safe_thresh: Safe threshold for near-full processing of this srng
  */
 struct dp_srng {
 	hal_ring_handle_t hal_srng;
@@ -682,6 +685,10 @@ struct dp_srng {
 #ifdef DP_MEM_PRE_ALLOC
 	uint8_t is_mem_prealloc;
 #endif
+#ifdef WLAN_FEATURE_NEAR_FULL_IRQ
+	uint16_t crit_thresh;
+	uint16_t safe_thresh;
+#endif
 };
 
 struct dp_rx_reorder_array_elem {
@@ -831,6 +838,12 @@ struct dp_intr {
 	uint8_t host2rxdma_ring_mask; /* Host to RXDMA buffer ring */
 	/* Host to RXDMA monitor  buffer ring */
 	uint8_t host2rxdma_mon_ring_mask;
+	/* RX REO rings near full interrupt mask */
+	uint8_t rx_near_full_grp_1_mask;
+	/* RX REO rings near full interrupt mask */
+	uint8_t rx_near_full_grp_2_mask;
+	/* WBM TX completion rings near full interrupt mask */
+	uint8_t tx_ring_near_full_mask;
 	struct dp_soc *soc;    /* Reference to SoC structure ,
 				to get DMA ring handles */
 	qdf_lro_ctx_t lro_ctx;

+ 36 - 0
hal/wifi3.0/hal_api.h

@@ -989,6 +989,20 @@ struct hal_srng_params {
 	void *hwreg_base[MAX_SRNG_REG_GROUPS];
 	/* prefetch timer config - in micro seconds */
 	uint32_t prefetch_timer;
+#ifdef WLAN_FEATURE_NEAR_FULL_IRQ
+	/* Near full IRQ support flag */
+	uint32_t nf_irq_support;
+	/* MSI2 Address */
+	qdf_dma_addr_t msi2_addr;
+	/* MSI2 data */
+	uint32_t msi2_data;
+	/* Critical threshold */
+	uint16_t crit_thresh;
+	/* High threshold */
+	uint16_t high_thresh;
+	/* Safe threshold */
+	uint16_t safe_thresh;
+#endif
 };
 
 /* hal_construct_srng_shadow_regs() - initialize the shadow
@@ -1025,6 +1039,28 @@ QDF_STATUS hal_set_one_shadow_config(void *hal_soc, int ring_type,
 extern void hal_get_shadow_config(void *hal_soc,
 				  struct pld_shadow_reg_v2_cfg **shadow_config,
 				  int *num_shadow_registers_configured);
+
+#ifdef WLAN_FEATURE_NEAR_FULL_IRQ
+/**
+ * hal_srng_is_near_full_irq_supported() - Check if srng supports near full irq
+ * @hal_soc: HAL SoC handle [To be validated by caller]
+ * @ring_type: srng type
+ * @ring_num: The index of the srng (of the same type)
+ *
+ * Return: true, if srng support near full irq trigger
+ *	false, if the srng does not support near full irq support.
+ */
+bool hal_srng_is_near_full_irq_supported(hal_soc_handle_t hal_soc,
+					 int ring_type, int ring_num);
+#else
+static inline
+bool hal_srng_is_near_full_irq_supported(hal_soc_handle_t hal_soc,
+					 int ring_type, int ring_num)
+{
+	return false;
+}
+#endif
+
 /**
  * hal_srng_setup - Initialize HW SRNG ring.
  *

+ 69 - 0
hal/wifi3.0/hal_generic_api.h

@@ -292,6 +292,65 @@ void hal_srng_src_hw_init_generic(struct hal_soc *hal,
 	SRNG_SRC_REG_WRITE(srng, MISC, reg_val);
 }
 
+#ifdef WLAN_FEATURE_NEAR_FULL_IRQ
+/**
+ * hal_srng_dst_msi2_setup() - Configure MSI2 register for a SRNG
+ * @srng: SRNG handle
+ *
+ * Return: None
+ */
+static inline void hal_srng_dst_msi2_setup(struct hal_srng *srng)
+{
+	uint32_t reg_val = 0;
+
+	if (srng->u.dst_ring.nf_irq_support) {
+		SRNG_DST_REG_WRITE(srng, MSI2_BASE_LSB,
+				   srng->msi2_addr & 0xffffffff);
+		reg_val = SRNG_SM(SRNG_DST_FLD(MSI2_BASE_MSB, ADDR),
+				  (uint64_t)(srng->msi2_addr) >> 32) |
+				  SRNG_SM(SRNG_DST_FLD(MSI2_BASE_MSB,
+					  MSI2_ENABLE), 1);
+		SRNG_DST_REG_WRITE(srng, MSI2_BASE_MSB, reg_val);
+		SRNG_DST_REG_WRITE(srng, MSI2_DATA,
+				   qdf_cpu_to_le32(srng->msi2_data));
+	}
+}
+
+/**
+ * hal_srng_dst_near_full_int_setup() - Configure near-full params for SRNG
+ * @srng: SRNG handle
+ *
+ * Return: None
+ */
+static inline void hal_srng_dst_near_full_int_setup(struct hal_srng *srng)
+{
+	uint32_t reg_val = 0;
+
+	if (srng->u.dst_ring.nf_irq_support) {
+		if (srng->intr_timer_thres_us) {
+			reg_val |= SRNG_SM(SRNG_DST_FLD(PRODUCER_INT2_SETUP,
+					   INTERRUPT2_TIMER_THRESHOLD),
+					   srng->intr_timer_thres_us >> 3);
+		}
+
+		reg_val |= SRNG_SM(SRNG_DST_FLD(PRODUCER_INT2_SETUP,
+				   HIGH_THRESHOLD),
+				   srng->u.dst_ring.high_thresh *
+				   srng->entry_size);
+	}
+
+	SRNG_DST_REG_WRITE(srng, PRODUCER_INT2_SETUP, reg_val);
+}
+#else
+static inline void hal_srng_dst_msi2_setup(struct hal_srng *srng)
+{
+}
+
+static inline void hal_srng_dst_near_full_int_setup(struct hal_srng *srng)
+{
+}
+#endif
+
 /**
  * hal_srng_dst_hw_init - Private function to initialize SRNG
  * destination ring HW
@@ -317,6 +376,8 @@ void hal_srng_dst_hw_init_generic(struct hal_soc *hal,
 		SRNG_DST_REG_WRITE(srng, MSI1_BASE_MSB, reg_val);
 		SRNG_DST_REG_WRITE(srng, MSI1_DATA,
 				   qdf_cpu_to_le32(srng->msi_data));
+
+		hal_srng_dst_msi2_setup(srng);
 	}
 
 	SRNG_DST_REG_WRITE(srng, BASE_LSB, srng->ring_base_paddr & 0xffffffff);
@@ -351,6 +412,14 @@ void hal_srng_dst_hw_init_generic(struct hal_soc *hal,
 	}
 
 	SRNG_DST_REG_WRITE(srng, PRODUCER_INT_SETUP, reg_val);
+
+	/**
+	 * Near-Full Interrupt setup:
+	 * Default interrupt mode is 'pulse'. Need to setup SW_INTERRUPT_MODE
+	 * if level mode is required
+	 */
+	hal_srng_dst_near_full_int_setup(srng);
+
 	hp_addr = (uint64_t)(hal->shadow_rdptr_mem_paddr +
 		((unsigned long)(srng->u.dst_ring.hp_addr) -
 		(unsigned long)(hal->shadow_rdptr_mem_vaddr)));

+ 16 - 29
hal/wifi3.0/hal_hw_headers.h

@@ -86,6 +86,12 @@
 #define HAL_REO_R0_REO2SW1_RING_MSI1_BASE_MSB_MSI1_ENABLE_SHFT	0x8
 #define HAL_REO_R0_REO2SW1_RING_MSI1_BASE_MSB_MSI1_ENABLE_BMSK	0x100
 
+#define HAL_REO_R0_REO2SW1_RING_MSI2_BASE_MSB_ADDR_SHFT		0x0
+#define HAL_REO_R0_REO2SW1_RING_MSI2_BASE_MSB_ADDR_BMSK		0xff
+
+#define HAL_REO_R0_REO2SW1_RING_MSI2_BASE_MSB_MSI2_ENABLE_SHFT	0x8
+#define HAL_REO_R0_REO2SW1_RING_MSI2_BASE_MSB_MSI2_ENABLE_BMSK	0x100
+
 #define HAL_REO_R0_REO2SW1_RING_BASE_MSB_RING_BASE_ADDR_MSB_SHFT	0x0
 #define HAL_REO_R0_REO2SW1_RING_BASE_MSB_RING_BASE_ADDR_MSB_BMSK	0xff
 
@@ -104,6 +110,12 @@
 #define HAL_REO_R0_REO2SW1_RING_PRODUCER_INT_SETUP_BATCH_COUNTER_THRESHOLD_SHFT		0x0
 #define HAL_REO_R0_REO2SW1_RING_PRODUCER_INT_SETUP_BATCH_COUNTER_THRESHOLD_BMSK		0x00007fff
 
+#define HAL_REO_R0_REO2SW1_RING_PRODUCER_INT2_SETUP_INTERRUPT2_TIMER_THRESHOLD_SHFT	24
+#define HAL_REO_R0_REO2SW1_RING_PRODUCER_INT2_SETUP_INTERRUPT2_TIMER_THRESHOLD_BMSK	0xff000000
+
+#define HAL_REO_R0_REO2SW1_RING_PRODUCER_INT2_SETUP_HIGH_THRESHOLD_SHFT		0
+#define HAL_REO_R0_REO2SW1_RING_PRODUCER_INT2_SETUP_HIGH_THRESHOLD_BMSK		0xfffff
+
 #define HAL_REO_R0_REO2SW1_RING_MISC_DATA_TLV_SWAP_BIT_SHFT	0x5
 #define HAL_REO_R0_REO2SW1_RING_MISC_DATA_TLV_SWAP_BIT_BMSK	0x20
 
@@ -183,11 +195,15 @@
 #define HP_ADDR_LSB_GROUP R0
 #define HP_ADDR_MSB_GROUP R0
 #define PRODUCER_INT_SETUP_GROUP R0
+#define PRODUCER_INT2_SETUP_GROUP R0
 #define PRODUCER_INT_STATUS_GROUP R0
 #define PRODUCER_FULL_COUNTER_GROUP R0
 #define MSI1_BASE_LSB_GROUP R0
 #define MSI1_BASE_MSB_GROUP R0
 #define MSI1_DATA_GROUP R0
+#define MSI2_BASE_LSB_GROUP R0
+#define MSI2_BASE_MSB_GROUP R0
+#define MSI2_DATA_GROUP R0
 #define HP_TP_SW_OFFSET_GROUP R0
 #define TP_ADDR_LSB_GROUP R0
 #define TP_ADDR_MSB_GROUP R0
@@ -314,35 +330,6 @@
 #define HAL_SRNG_CONFIG(_hal_soc, _ring_type) \
 			(&_hal_soc->hw_srng_table[_ring_type])
 
-enum SRNG_REGISTERS {
-DST_HP = 0,
-DST_TP,
-DST_ID,
-DST_MISC,
-DST_HP_ADDR_LSB,
-DST_HP_ADDR_MSB,
-DST_MSI1_BASE_LSB,
-DST_MSI1_BASE_MSB,
-DST_MSI1_DATA,
-DST_BASE_LSB,
-DST_BASE_MSB,
-DST_PRODUCER_INT_SETUP,
-
-SRC_HP,
-SRC_TP,
-SRC_ID,
-SRC_MISC,
-SRC_TP_ADDR_LSB,
-SRC_TP_ADDR_MSB,
-SRC_MSI1_BASE_LSB,
-SRC_MSI1_BASE_MSB,
-SRC_MSI1_DATA,
-SRC_BASE_LSB,
-SRC_BASE_MSB,
-SRC_CONSUMER_INT_SETUP_IX0,
-SRC_CONSUMER_INT_SETUP_IX1,
-};
-
 /**
  * hal_set_link_desc_addr - Setup link descriptor in a buffer_addr_info
  * HW structure

+ 55 - 0
hal/wifi3.0/hal_internal.h

@@ -272,6 +272,44 @@ enum hal_ring_type {
 	MAX_RING_TYPES
 };
 
+enum SRNG_REGISTERS {
+	DST_HP = 0,
+	DST_TP,
+	DST_ID,
+	DST_MISC,
+	DST_HP_ADDR_LSB,
+	DST_HP_ADDR_MSB,
+	DST_MSI1_BASE_LSB,
+	DST_MSI1_BASE_MSB,
+	DST_MSI1_DATA,
+#ifdef CONFIG_BERYLLIUM
+	DST_MSI2_BASE_LSB,
+	DST_MSI2_BASE_MSB,
+	DST_MSI2_DATA,
+#endif
+	DST_BASE_LSB,
+	DST_BASE_MSB,
+	DST_PRODUCER_INT_SETUP,
+#ifdef CONFIG_BERYLLIUM
+	DST_PRODUCER_INT2_SETUP,
+#endif
+
+	SRC_HP,
+	SRC_TP,
+	SRC_ID,
+	SRC_MISC,
+	SRC_TP_ADDR_LSB,
+	SRC_TP_ADDR_MSB,
+	SRC_MSI1_BASE_LSB,
+	SRC_MSI1_BASE_MSB,
+	SRC_MSI1_DATA,
+	SRC_BASE_LSB,
+	SRC_BASE_MSB,
+	SRC_CONSUMER_INT_SETUP_IX0,
+	SRC_CONSUMER_INT_SETUP_IX1,
+	SRNG_REGISTER_MAX,
+};
+
 #define HAL_RXDMA_MAX_RING_SIZE 0xFFFF
 #define HAL_MAX_LMACS 3
 #define HAL_MAX_RINGS_PER_LMAC (HAL_SRNG_LMAC1_ID_END - HAL_SRNG_LMAC1_ID_START)
@@ -475,6 +513,14 @@ struct hal_srng {
 	/* MSI data */
 	uint32_t msi_data;
 
+#ifdef WLAN_FEATURE_NEAR_FULL_IRQ
+	/* MSI2 Address */
+	qdf_dma_addr_t msi2_addr;
+
+	/* MSI2 data */
+	uint32_t msi2_data;
+#endif
+
 	/* Misc flags */
 	uint32_t flags;
 
@@ -514,6 +560,14 @@ struct hal_srng {
 
 			/* max transfer size */
 			uint16_t max_buffer_length;
+
+#ifdef WLAN_FEATURE_NEAR_FULL_IRQ
+			/* near full IRQ supported */
+			uint16_t nf_irq_support;
+
+			/* High threshold for Near full IRQ */
+			uint16_t high_thresh;
+#endif
 		} dst_ring;
 
 		struct {
@@ -571,6 +625,7 @@ struct hal_hw_srng_config {
 	uint8_t lmac_ring;
 	enum hal_srng_dir ring_dir;
 	uint32_t max_size;
+	bool nf_irq_support;
 };
 
 #define MAX_SHADOW_REGISTERS 40

+ 90 - 0
hal/wifi3.0/hal_srng.c

@@ -1767,6 +1767,92 @@ static inline void hal_srng_hw_init(struct hal_soc *hal,
 #define CHECK_SHADOW_REGISTERS false
 #endif
 
+#ifdef WLAN_FEATURE_NEAR_FULL_IRQ
+/**
+ * hal_srng_is_near_full_irq_supported() - Check if near full irq is
+ *				supported on this SRNG
+ * @hal_soc: HAL SoC handle
+ * @ring_type: SRNG type
+ * @ring_num: ring number
+ *
+ * Return: true, if near full irq is supported for this SRNG
+ *	   false, if near full irq is not supported for this SRNG
+ */
+bool hal_srng_is_near_full_irq_supported(hal_soc_handle_t hal_soc,
+					 int ring_type, int ring_num)
+{
+	struct hal_soc *hal = (struct hal_soc *)hal_soc;
+	struct hal_hw_srng_config *ring_config =
+		HAL_SRNG_CONFIG(hal, ring_type);
+
+	return ring_config->nf_irq_support;
+}
+
+/**
+ * hal_srng_set_msi2_params() - Set MSI2 params to SRNG data structure from
+ *				ring params
+ * @srng: SRNG handle
+ * @ring_params: ring params for this SRNG
+ *
+ * Return: None
+ */
+static inline void
+hal_srng_set_msi2_params(struct hal_srng *srng,
+			 struct hal_srng_params *ring_params)
+{
+	srng->msi2_addr = ring_params->msi2_addr;
+	srng->msi2_data = ring_params->msi2_data;
+}
+
+/**
+ * hal_srng_get_nf_params() - Get the near full MSI2 params from srng
+ * @srng: SRNG handle
+ * @ring_params: ring params for this SRNG
+ *
+ * Return: None
+ */
+static inline void
+hal_srng_get_nf_params(struct hal_srng *srng,
+		       struct hal_srng_params *ring_params)
+{
+	ring_params->msi2_addr = srng->msi2_addr;
+	ring_params->msi2_data = srng->msi2_data;
+}
+
+/**
+ * hal_srng_set_nf_thresholds() - Set the near full thresholds in SRNG
+ * @srng: SRNG handle where the params are to be set
+ * @ring_params: ring params, from where threshold is to be fetched
+ *
+ * Return: None
+ */
+static inline void
+hal_srng_set_nf_thresholds(struct hal_srng *srng,
+			   struct hal_srng_params *ring_params)
+{
+	srng->u.dst_ring.nf_irq_support = ring_params->nf_irq_support;
+	srng->u.dst_ring.high_thresh = ring_params->high_thresh;
+}
+#else
+static inline void
+hal_srng_set_msi2_params(struct hal_srng *srng,
+			 struct hal_srng_params *ring_params)
+{
+}
+
+static inline void
+hal_srng_get_nf_params(struct hal_srng *srng,
+		       struct hal_srng_params *ring_params)
+{
+}
+
+static inline void
+hal_srng_set_nf_thresholds(struct hal_srng *srng,
+			   struct hal_srng_params *ring_params)
+{
+}
+#endif
+
 /**
  * hal_srng_setup - Initialize HW SRNG ring.
  * @hal_soc: Opaque HAL SOC handle
@@ -1827,6 +1913,7 @@ void *hal_srng_setup(void *hal_soc, int ring_type, int ring_num,
 		ring_params->intr_batch_cntr_thres_entries;
 	srng->prefetch_timer = ring_params->prefetch_timer;
 	srng->hal_soc = hal_soc;
+	hal_srng_set_msi2_params(srng, ring_params);
 
 	for (i = 0 ; i < MAX_SRNG_REG_GROUPS; i++) {
 		srng->hwreg_base[i] = dev_base_addr + ring_config->reg_start[i]
@@ -1886,6 +1973,7 @@ void *hal_srng_setup(void *hal_soc, int ring_type, int ring_num,
 		 * loop count in descriptors updated by HW (to be processed
 		 * by SW).
 		 */
+		hal_srng_set_nf_thresholds(srng, ring_params);
 		srng->u.dst_ring.loop_cnt = 1;
 		srng->u.dst_ring.tp = 0;
 		srng->u.dst_ring.hp_addr =
@@ -2042,6 +2130,8 @@ extern void hal_get_srng_params(hal_soc_handle_t hal_soc_hdl,
 	ring_params->ring_id = srng->ring_id;
 	for (i = 0 ; i < MAX_SRNG_REG_GROUPS; i++)
 		ring_params->hwreg_base[i] = srng->hwreg_base[i];
+
+	hal_srng_get_nf_params(srng, ring_params);
 }
 qdf_export_symbol(hal_get_srng_params);
 

+ 6 - 0
hal/wifi3.0/wcn7850/hal_7850.c

@@ -1449,6 +1449,7 @@ struct hal_hw_srng_config hw_srng_table_7850[] = {
 		.entry_size = sizeof(struct reo_destination_ring) >> 2,
 		.lmac_ring = FALSE,
 		.ring_dir = HAL_SRNG_DST_RING,
+		.nf_irq_support = true,
 		.reg_start = {
 			HWIO_REO_R0_REO2SW1_RING_BASE_LSB_ADDR(
 				REO_REG_REG_BASE),
@@ -1716,6 +1717,7 @@ struct hal_hw_srng_config hw_srng_table_7850[] = {
 		.entry_size = sizeof(struct wbm_release_ring) >> 2,
 		.lmac_ring = FALSE,
 		.ring_dir = HAL_SRNG_DST_RING,
+		.nf_irq_support = true,
 		.reg_start = {
 		HWIO_WBM_R0_WBM2SW0_RELEASE_RING_BASE_LSB_ADDR(WBM_REG_REG_BASE),
 		HWIO_WBM_R2_WBM2SW0_RELEASE_RING_HP_ADDR(WBM_REG_REG_BASE),
@@ -1857,9 +1859,13 @@ int32_t hal_hw_reg_offset_wcn7850[] = {
 	REG_OFFSET(DST, MSI1_BASE_LSB),
 	REG_OFFSET(DST, MSI1_BASE_MSB),
 	REG_OFFSET(DST, MSI1_DATA),
+	REG_OFFSET(DST, MSI2_BASE_LSB),
+	REG_OFFSET(DST, MSI2_BASE_MSB),
+	REG_OFFSET(DST, MSI2_DATA),
 	REG_OFFSET(DST, BASE_LSB),
 	REG_OFFSET(DST, BASE_MSB),
 	REG_OFFSET(DST, PRODUCER_INT_SETUP),
+	REG_OFFSET(DST, PRODUCER_INT2_SETUP),
 	/* src */
 	REG_OFFSET(SRC, HP),
 	REG_OFFSET(SRC, TP),

+ 2 - 2
hif/inc/hif.h

@@ -134,8 +134,8 @@ struct CE_state;
 
 #ifndef HIF_MAX_GROUP
 #ifdef CONFIG_BERYLLIUM
-#define HIF_MAX_GROUP 11
-#define HIF_MAX_GRP_IRQ 20
+#define HIF_MAX_GROUP 14
+#define HIF_MAX_GRP_IRQ 23
 #else
 #define HIF_MAX_GROUP 7
 #define HIF_MAX_GRP_IRQ 16

+ 74 - 34
wlan_cfg/wlan_cfg.c

@@ -48,15 +48,6 @@
 #define WLAN_CFG_TX_RING_MASK_2 0x4
 #define WLAN_CFG_TX_RING_MASK_3 0x0
 
-#define WLAN_CFG_RX_RING_MASK_0 0x1
-#define WLAN_CFG_RX_RING_MASK_1 0x2
-#define WLAN_CFG_RX_RING_MASK_2 0x4
-#define WLAN_CFG_RX_RING_MASK_3 0x8
-#define WLAN_CFG_RX_RING_MASK_4 0x10
-#define WLAN_CFG_RX_RING_MASK_5 0x20
-#define WLAN_CFG_RX_RING_MASK_6 0x40
-#define WLAN_CFG_RX_RING_MASK_7 0x80
-
 
 #define WLAN_CFG_RX_MON_RING_MASK_0 0x1
 #define WLAN_CFG_RX_MON_RING_MASK_1 0x2
@@ -107,6 +98,9 @@ struct dp_int_mask_assignment {
 	uint8_t rx_err_ring_mask[WLAN_CFG_INT_NUM_CONTEXTS];
 	uint8_t rx_wbm_rel_ring_mask[WLAN_CFG_INT_NUM_CONTEXTS];
 	uint8_t reo_status_ring_mask[WLAN_CFG_INT_NUM_CONTEXTS];
+	uint8_t rx_ring_near_full_irq_1_mask[WLAN_CFG_INT_NUM_CONTEXTS];
+	uint8_t rx_ring_near_full_irq_2_mask[WLAN_CFG_INT_NUM_CONTEXTS];
+	uint8_t tx_ring_near_full_irq_mask[WLAN_CFG_INT_NUM_CONTEXTS];
 };
 
 #if defined(WLAN_MAX_PDEVS) && (WLAN_MAX_PDEVS == 1)
@@ -185,6 +179,28 @@ static struct dp_int_mask_assignment dp_mask_assignment[NUM_INTERRUPT_COMBINATIO
 		/* reo status ring masks */
 		{ 0, 0, 0, 0, 0, 0,
 		  WLAN_CFG_REO_STATUS_RING_MASK_0},
+#ifdef CONFIG_BERYLLIUM
+		/* rx near full irq1 mask */
+		{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+		  WLAN_CFG_RX_NEAR_FULL_IRQ_MASK_1,
+		  0, 0},
+		/* rx near full irq2 mask */
+		{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+		  0,
+		  WLAN_CFG_RX_NEAR_FULL_IRQ_MASK_2,
+		  0},
+		/* tx near full irq mask */
+		{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+		  0, 0,
+		  WLAN_CFG_TX_RING_NEAR_FULL_IRQ_MASK},
+#else /* CONFIG_BERYLLIUM */
+		/* rx near full irq1 mask */
+		{ 0, 0, 0, 0, 0, 0, 0},
+		/* rx near full irq2 mask */
+		{ 0, 0, 0, 0, 0, 0, 0},
+		/* tx near full irq mask */
+		{ 0, 0, 0, 0, 0, 0, 0},
+#endif /* CONFIG_BERYLLIUM */
 	},
 };
 
@@ -889,32 +905,38 @@ void wlan_cfg_fill_interrupt_mask(struct wlan_cfg_dp_soc_ctxt *wlan_cfg_ctx,
 
 
 	for (i = 0; i < WLAN_CFG_INT_NUM_CONTEXTS; i++) {
-			wlan_cfg_ctx->int_tx_ring_mask[i] =
-				dp_mask_assignment[interrupt_index].tx_ring_mask[i];
-			wlan_cfg_ctx->int_rx_mon_ring_mask[i] =
-				dp_mask_assignment[interrupt_index].rx_mon_ring_mask[i];
-			wlan_cfg_ctx->int_rx_err_ring_mask[i] =
-				dp_mask_assignment[interrupt_index].rx_err_ring_mask[i];
-			wlan_cfg_ctx->int_rx_wbm_rel_ring_mask[i] =
-				dp_mask_assignment[interrupt_index].rx_wbm_rel_ring_mask[i];
-			wlan_cfg_ctx->int_reo_status_ring_mask[i] =
-				dp_mask_assignment[interrupt_index].reo_status_ring_mask[i];
-			if (is_monitor_mode) {
-				wlan_cfg_ctx->int_rx_ring_mask[i] = 0;
-				wlan_cfg_ctx->int_rxdma2host_ring_mask[i] = 0;
-			} else {
-				wlan_cfg_ctx->int_rx_ring_mask[i] =
-					dp_mask_assignment[interrupt_index].rx_ring_mask[i];
-				wlan_cfg_ctx->int_rxdma2host_ring_mask[i] =
-					dp_mask_assignment[interrupt_index].rxdma2host_ring_mask[i];
-			}
-			wlan_cfg_ctx->int_host2rxdma_ring_mask[i] =
-				dp_mask_assignment[interrupt_index].host2rxdma_ring_mask[i];
-			wlan_cfg_ctx->int_host2rxdma_mon_ring_mask[i] =
-				dp_mask_assignment[interrupt_index].host2rxdma_mon_ring_mask[i];
-			wlan_cfg_ctx->int_rxdma2host_mon_ring_mask[i] =
-				dp_mask_assignment[interrupt_index].rxdma2host_mon_ring_mask[i];
+		wlan_cfg_ctx->int_tx_ring_mask[i] =
+			dp_mask_assignment[interrupt_index].tx_ring_mask[i];
+		wlan_cfg_ctx->int_rx_mon_ring_mask[i] =
+			dp_mask_assignment[interrupt_index].rx_mon_ring_mask[i];
+		wlan_cfg_ctx->int_rx_err_ring_mask[i] =
+			dp_mask_assignment[interrupt_index].rx_err_ring_mask[i];
+		wlan_cfg_ctx->int_rx_wbm_rel_ring_mask[i] =
+			dp_mask_assignment[interrupt_index].rx_wbm_rel_ring_mask[i];
+		wlan_cfg_ctx->int_reo_status_ring_mask[i] =
+			dp_mask_assignment[interrupt_index].reo_status_ring_mask[i];
+		if (is_monitor_mode) {
+			wlan_cfg_ctx->int_rx_ring_mask[i] = 0;
+			wlan_cfg_ctx->int_rxdma2host_ring_mask[i] = 0;
+		} else {
+			wlan_cfg_ctx->int_rx_ring_mask[i] =
+				dp_mask_assignment[interrupt_index].rx_ring_mask[i];
+			wlan_cfg_ctx->int_rxdma2host_ring_mask[i] =
+				dp_mask_assignment[interrupt_index].rxdma2host_ring_mask[i];
 		}
+		wlan_cfg_ctx->int_host2rxdma_ring_mask[i] =
+			dp_mask_assignment[interrupt_index].host2rxdma_ring_mask[i];
+		wlan_cfg_ctx->int_host2rxdma_mon_ring_mask[i] =
+			dp_mask_assignment[interrupt_index].host2rxdma_mon_ring_mask[i];
+		wlan_cfg_ctx->int_rxdma2host_mon_ring_mask[i] =
+			dp_mask_assignment[interrupt_index].rxdma2host_mon_ring_mask[i];
+		wlan_cfg_ctx->int_rx_ring_near_full_irq_1_mask[i] =
+			dp_mask_assignment[interrupt_index].rx_ring_near_full_irq_1_mask[i];
+		wlan_cfg_ctx->int_rx_ring_near_full_irq_2_mask[i] =
+			dp_mask_assignment[interrupt_index].rx_ring_near_full_irq_2_mask[i];
+		wlan_cfg_ctx->int_tx_ring_near_full_irq_mask[i] =
+			dp_mask_assignment[interrupt_index].tx_ring_near_full_irq_mask[i];
+	}
 }
 
 #ifdef IPA_OFFLOAD
@@ -1280,6 +1302,24 @@ int wlan_cfg_get_host2rxdma_ring_mask(struct wlan_cfg_dp_soc_ctxt *cfg,
 	return cfg->int_host2rxdma_ring_mask[context];
 }
 
+int wlan_cfg_get_rx_near_full_grp_1_mask(struct wlan_cfg_dp_soc_ctxt *cfg,
+					 int context)
+{
+	return cfg->int_rx_ring_near_full_irq_1_mask[context];
+}
+
+int wlan_cfg_get_rx_near_full_grp_2_mask(struct wlan_cfg_dp_soc_ctxt *cfg,
+					 int context)
+{
+	return cfg->int_rx_ring_near_full_irq_2_mask[context];
+}
+
+int wlan_cfg_get_tx_ring_near_full_mask(struct wlan_cfg_dp_soc_ctxt *cfg,
+					int context)
+{
+	return cfg->int_tx_ring_near_full_irq_mask[context];
+}
+
 void wlan_cfg_set_hw_mac_idx(struct wlan_cfg_dp_soc_ctxt *cfg, int pdev_idx,
 			     int hw_macid)
 {

+ 80 - 2
wlan_cfg/wlan_cfg.h

@@ -27,7 +27,7 @@
 #define WLAN_CFG_DST_RING_CACHED_DESC 0
 #define MAX_PDEV_CNT 1
 #ifdef CONFIG_BERYLLIUM
-#define WLAN_CFG_INT_NUM_CONTEXTS 11
+#define WLAN_CFG_INT_NUM_CONTEXTS 14
 #else
 #define WLAN_CFG_INT_NUM_CONTEXTS 7
 #endif
@@ -54,7 +54,7 @@
 
 #endif
 
-#define WLAN_CFG_INT_NUM_CONTEXTS_MAX 11
+#define WLAN_CFG_INT_NUM_CONTEXTS_MAX 14
 
 /* Tx configuration */
 #define MAX_LINK_DESC_BANKS 8
@@ -92,6 +92,41 @@
 
 #define INVALID_PDEV_ID 0xFF
 
+#define WLAN_CFG_RX_RING_MASK_0 0x1
+#define WLAN_CFG_RX_RING_MASK_1 0x2
+#define WLAN_CFG_RX_RING_MASK_2 0x4
+#define WLAN_CFG_RX_RING_MASK_3 0x8
+#define WLAN_CFG_RX_RING_MASK_4 0x10
+#define WLAN_CFG_RX_RING_MASK_5 0x20
+#define WLAN_CFG_RX_RING_MASK_6 0x40
+#define WLAN_CFG_RX_RING_MASK_7 0x80
+
+#ifdef WLAN_FEATURE_NEAR_FULL_IRQ
+#ifdef IPA_OFFLOAD
+#define WLAN_CFG_RX_NEAR_FULL_IRQ_MASK_1 (WLAN_CFG_RX_RING_MASK_0 |	\
+					  WLAN_CFG_RX_RING_MASK_1 |	\
+					  WLAN_CFG_RX_RING_MASK_2)
+
+#define WLAN_CFG_RX_NEAR_FULL_IRQ_MASK_2 (WLAN_CFG_RX_RING_MASK_4 |	\
+					  WLAN_CFG_RX_RING_MASK_5 |	\
+					  WLAN_CFG_RX_RING_MASK_6)
+
+#define WLAN_CFG_TX_RING_NEAR_FULL_IRQ_MASK (WLAN_CFG_TX_RING_MASK_0)
+#else
+#define WLAN_CFG_RX_NEAR_FULL_IRQ_MASK_1 (WLAN_CFG_RX_RING_MASK_0 |	\
+					  WLAN_CFG_RX_RING_MASK_1 |	\
+					  WLAN_CFG_RX_RING_MASK_2 |	\
+					  WLAN_CFG_RX_RING_MASK_3)
+
+#define WLAN_CFG_RX_NEAR_FULL_IRQ_MASK_2 (WLAN_CFG_RX_RING_MASK_4 |	\
+					  WLAN_CFG_RX_RING_MASK_5 |	\
+					  WLAN_CFG_RX_RING_MASK_6 |	\
+					  WLAN_CFG_RX_RING_MASK_7)
+
+#define WLAN_CFG_TX_RING_NEAR_FULL_IRQ_MASK (WLAN_CFG_TX_RING_MASK_0)
+#endif
+#endif
+
 struct wlan_cfg_dp_pdev_ctxt;
 
 /**
@@ -135,6 +170,14 @@ struct wlan_srng_cfg {
  *			  NAPI/Intr context
  * @int_reo_status_ring_mask: Bitmap of reo status ring interrupts mapped to
  *                            each NAPI/Intr context
+ * @int_rxdma2host_ring_mask:
+ * @int_host2rxdma_ring_mask:
+ * @int_rx_ring_near_full_irq_1_mask: Bitmap of REO DST ring near full interrupt
+ *				mapped to each NAPI/INTR context
+ * @int_rx_ring_near_full_irq_2_mask: Bitmap of REO DST ring near full interrupt
+ *				mapped to each NAPI/INTR context
+ * @int_tx_ring_near_full_irq_mask: Bitmap of Tx completion ring near full
+ *				interrupt mapped to each NAPI/INTR context
  * @int_ce_ring_mask: Bitmap of CE interrupts mapped to each NAPI/Intr context
  * @lro_enabled: enable/disable lro feature
  * @rx_hash: Enable hash based steering of rx packets
@@ -246,6 +289,9 @@ struct wlan_cfg_dp_soc_ctxt {
 	uint8_t int_reo_status_ring_mask[WLAN_CFG_INT_NUM_CONTEXTS];
 	uint8_t int_rxdma2host_ring_mask[WLAN_CFG_INT_NUM_CONTEXTS];
 	uint8_t int_host2rxdma_ring_mask[WLAN_CFG_INT_NUM_CONTEXTS];
+	uint8_t int_rx_ring_near_full_irq_1_mask[WLAN_CFG_INT_NUM_CONTEXTS];
+	uint8_t int_rx_ring_near_full_irq_2_mask[WLAN_CFG_INT_NUM_CONTEXTS];
+	uint8_t int_tx_ring_near_full_irq_mask[WLAN_CFG_INT_NUM_CONTEXTS];
 	int hw_macid[MAX_PDEV_CNT];
 	int hw_macid_pdev_id_map[MAX_NUM_LMAC_HW];
 	int base_hw_macid;
@@ -527,6 +573,38 @@ void wlan_cfg_set_host2rxdma_ring_mask(struct wlan_cfg_dp_soc_ctxt *cfg,
 int wlan_cfg_get_host2rxdma_ring_mask(struct wlan_cfg_dp_soc_ctxt *cfg,
 	int context);
 
+/**
+ * wlan_cfg_get_rx_near_full_grp_1_mask() - Return REO near full interrupt mask
+ *					mapped to an interrupt context
+ * @cfg: Configuration Handle
+ * @context - Numerical ID identifying the Interrupt/NAPI context
+ *
+ * Return: REO near full interrupt mask[context]
+ */
+int wlan_cfg_get_rx_near_full_grp_1_mask(struct wlan_cfg_dp_soc_ctxt *cfg,
+					 int context);
+
+/**
+ * wlan_cfg_get_rx_near_full_grp_2_mask() - Return REO near full interrupt mask
+ *					mapped to an interrupt context
+ * @cfg: Configuration Handle
+ * @context - Numerical ID identifying the Interrupt/NAPI context
+ *
+ * Return: REO near full interrupt mask[context]
+ */
+int wlan_cfg_get_rx_near_full_grp_2_mask(struct wlan_cfg_dp_soc_ctxt *cfg,
+					 int context);
+
+/**
+ * wlan_cfg_get_tx_ring_near_full_mask() - Return tx completion ring near full
+ *				interrupt mask mapped to an interrupt context
+ * @cfg: Configuration Handle
+ * @context - Numerical ID identifying the Interrupt/NAPI context
+ *
+ * Return: tx completion near full interrupt mask[context]
+ */
+int wlan_cfg_get_tx_ring_near_full_mask(struct wlan_cfg_dp_soc_ctxt *cfg,
+					int context);
 /**
  * wlan_cfg_set_host2rxdma_mon_ring_mask() - Set host2rxdma monitor ring
  *                                interrupt mask for the given interrupt context