Browse Source

msm: ipa: includes raw notifier for rmnet_data

Supports APIs for rmnet to register for buffer high/low
notification on WAN and WAN_COAL pipes.

Change-Id: I0b8fd7287f5a25a695243d2aaad93bbc8fb505c1
Signed-off-by: Michael Adisumarta <[email protected]>
Michael Adisumarta 3 years ago
parent
commit
ca5cf8cba8

+ 12 - 0
drivers/platform/msm/ipa/ipa_v3/ipa.c

@@ -69,6 +69,8 @@
 #define DEFAULT_MPM_TETH_AGGR_SIZE 24
 #define DEFAULT_MPM_UC_THRESH_SIZE 4
 
+RAW_NOTIFIER_HEAD(ipa_rmnet_notifier_list);
+
 /*
  * The following for adding code (ie. for EMULATION) not found on x86.
  */
@@ -7266,6 +7268,10 @@ static inline void ipa3_register_to_fmwk(void)
 	data.ipa_rmnet_ll_xmit = ipa3_rmnet_ll_xmit;
 	data.ipa_register_rmnet_ll_cb = ipa3_register_rmnet_ll_cb;
 	data.ipa_unregister_rmnet_ll_cb = ipa3_unregister_rmnet_ll_cb;
+	data.ipa_register_notifier =
+		ipa3_register_notifier;
+	data.ipa_unregister_notifier =
+		ipa3_unregister_notifier;
 
 	if (ipa_fmwk_register_ipa(&data)) {
 		IPAERR("couldn't register to IPA framework\n");
@@ -9123,6 +9129,12 @@ static int ipa3_pre_init(const struct ipa3_plat_drv_res *resource_p,
 			goto fail_rmnet_ll_init;
 		}
 	}
+	ipa3_ctx->ipa_rmnet_notifier_list_internal = &ipa_rmnet_notifier_list;
+	spin_lock_init(&ipa3_ctx->notifier_lock);
+	ipa3_ctx->buff_above_thresh_for_def_pipe_notified = false;
+	ipa3_ctx->buff_above_thresh_for_coal_pipe_notified = false;
+	ipa3_ctx->buff_below_thresh_for_def_pipe_notified = false;
+	ipa3_ctx->buff_below_thresh_for_coal_pipe_notified = false;
 
 	mutex_init(&ipa3_ctx->app_clock_vote.mutex);
 	ipa3_ctx->is_modem_up = false;

+ 12 - 3
drivers/platform/msm/ipa/ipa_v3/ipa_debugfs.c

@@ -1554,7 +1554,12 @@ static ssize_t ipa3_read_stats(struct file *file, char __user *ubuf,
 		"flow_enable=%u\n"
 		"flow_disable=%u\n"
 		"rx_page_drop_cnt=%u\n"
-		"lower_order=%u\n",
+		"lower_order=%u\n"
+		"rmnet_notifier_enabled=%u\n"
+		"num_buff_above_thresh_for_def_pipe_notified=%u\n"
+		"num_buff_below_thresh_for_def_pipe_notified=%u\n"
+		"num_buff_above_thresh_for_coal_pipe_notified=%u\n"
+		"num_buff_below_thresh_for_coal_pipe_notified=%u\n",
 		ipa3_ctx->stats.tx_sw_pkts,
 		ipa3_ctx->stats.tx_hw_pkts,
 		ipa3_ctx->stats.tx_non_linear,
@@ -1575,8 +1580,12 @@ static ssize_t ipa3_read_stats(struct file *file, char __user *ubuf,
 		ipa3_ctx->stats.flow_enable,
 		ipa3_ctx->stats.flow_disable,
 		ipa3_ctx->stats.rx_page_drop_cnt,
-		ipa3_ctx->stats.lower_order
-		);
+		ipa3_ctx->stats.lower_order,
+		ipa3_ctx->ipa_rmnet_notifier_enabled,
+		atomic_read(&ipa3_ctx->stats.num_buff_above_thresh_for_def_pipe_notified),
+		atomic_read(&ipa3_ctx->stats.num_buff_below_thresh_for_def_pipe_notified),
+		atomic_read(&ipa3_ctx->stats.num_buff_above_thresh_for_coal_pipe_notified),
+		atomic_read(&ipa3_ctx->stats.num_buff_below_thresh_for_coal_pipe_notified));
 	cnt += nbytes;
 
 	for (i = 0; i < IPAHAL_PKT_STATUS_EXCEPTION_MAX; i++) {

+ 90 - 2
drivers/platform/msm/ipa/ipa_v3/ipa_dp.c

@@ -14,6 +14,7 @@
 #include <net/sock.h>
 #include <net/ipv6.h>
 #include <asm/page.h>
+#include <linux/mutex.h>
 #include "gsi.h"
 #include "ipa_i.h"
 #include "ipa_trace.h"
@@ -79,6 +80,8 @@
 #define IPA_GSI_CH_20_WA_VIRT_CHAN 29
 
 #define IPA_DEFAULT_SYS_YELLOW_WM 32
+/* High threshold is set for 50% of the buffer */
+#define IPA_BUFF_THRESHOLD_HIGH 112
 #define IPA_REPL_XFER_THRESH 20
 #define IPA_REPL_XFER_MAX 36
 
@@ -2466,6 +2469,43 @@ static struct ipa3_rx_pkt_wrapper * ipa3_get_free_page
 	return NULL;
 }
 
+int ipa3_register_notifier(void *fn_ptr)
+{
+	if (fn_ptr == NULL)
+		return -EFAULT;
+	spin_lock(&ipa3_ctx->notifier_lock);
+	atomic_set(&ipa3_ctx->stats.num_buff_above_thresh_for_def_pipe_notified, 0);
+	atomic_set(&ipa3_ctx->stats.num_buff_above_thresh_for_coal_pipe_notified, 0);
+	atomic_set(&ipa3_ctx->stats.num_buff_below_thresh_for_def_pipe_notified, 0);
+	atomic_set(&ipa3_ctx->stats.num_buff_below_thresh_for_coal_pipe_notified, 0);
+	ipa3_ctx->ipa_rmnet_notifier.notifier_call = fn_ptr;
+	if (!ipa3_ctx->ipa_rmnet_notifier_enabled)
+		raw_notifier_chain_register(ipa3_ctx->ipa_rmnet_notifier_list_internal,
+			&ipa3_ctx->ipa_rmnet_notifier);
+	else {
+		IPAWANERR("rcvd notifier reg again, changing the cb function\n");
+		ipa3_ctx->ipa_rmnet_notifier.notifier_call = fn_ptr;
+	}
+	ipa3_ctx->ipa_rmnet_notifier_enabled = true;
+	spin_unlock(&ipa3_ctx->notifier_lock);
+	return 0;
+}
+
+int ipa3_unregister_notifier(void *fn_ptr)
+{
+	if (fn_ptr == NULL)
+		return -EFAULT;
+	spin_lock(&ipa3_ctx->notifier_lock);
+	ipa3_ctx->ipa_rmnet_notifier.notifier_call = fn_ptr;
+	if (ipa3_ctx->ipa_rmnet_notifier_enabled)
+		raw_notifier_chain_unregister(ipa3_ctx->ipa_rmnet_notifier_list_internal,
+			&ipa3_ctx->ipa_rmnet_notifier);
+	else IPAWANERR("rcvd notifier unreg again\n");
+	ipa3_ctx->ipa_rmnet_notifier_enabled = false;
+	spin_unlock(&ipa3_ctx->notifier_lock);
+	return 0;
+}
+
 static void ipa3_replenish_rx_page_recycle(struct ipa3_sys_context *sys)
 {
 	struct ipa3_rx_pkt_wrapper *rx_pkt;
@@ -2564,10 +2604,32 @@ static void ipa3_replenish_rx_page_recycle(struct ipa3_sys_context *sys)
 		__trigger_repl_work(sys);
 
 	if (rx_len_cached <= IPA_DEFAULT_SYS_YELLOW_WM) {
-		if (sys->ep->client == IPA_CLIENT_APPS_WAN_CONS)
+		if (sys->ep->client == IPA_CLIENT_APPS_WAN_CONS) {
 			IPA_STATS_INC_CNT(ipa3_ctx->stats.wan_rx_empty);
-		else if (sys->ep->client == IPA_CLIENT_APPS_WAN_COAL_CONS)
+			spin_lock(&ipa3_ctx->notifier_lock);
+			if (ipa3_ctx->ipa_rmnet_notifier_enabled
+				&& !ipa3_ctx->buff_below_thresh_for_def_pipe_notified) {
+				atomic_inc(&ipa3_ctx->stats.num_buff_below_thresh_for_def_pipe_notified);
+				raw_notifier_call_chain(ipa3_ctx->ipa_rmnet_notifier_list_internal,
+					BUFF_BELOW_LOW_THRESHOLD_FOR_DEFAULT_PIPE, &rx_len_cached);
+				ipa3_ctx->buff_above_thresh_for_def_pipe_notified = false;
+				ipa3_ctx->buff_below_thresh_for_def_pipe_notified = true;
+			}
+			spin_unlock(&ipa3_ctx->notifier_lock);
+		}
+		else if (sys->ep->client == IPA_CLIENT_APPS_WAN_COAL_CONS) {
 			IPA_STATS_INC_CNT(ipa3_ctx->stats.wan_rx_empty_coal);
+			spin_lock(&ipa3_ctx->notifier_lock);
+			if (ipa3_ctx->ipa_rmnet_notifier_enabled
+				&& !ipa3_ctx->buff_below_thresh_for_coal_pipe_notified) {
+				atomic_inc(&ipa3_ctx->stats.num_buff_below_thresh_for_coal_pipe_notified);
+				raw_notifier_call_chain(ipa3_ctx->ipa_rmnet_notifier_list_internal,
+					BUFF_BELOW_LOW_THRESHOLD_FOR_COAL_PIPE, &rx_len_cached);
+				ipa3_ctx->buff_above_thresh_for_coal_pipe_notified = false;
+				ipa3_ctx->buff_below_thresh_for_coal_pipe_notified = true;
+			}
+			spin_unlock(&ipa3_ctx->notifier_lock);
+		}
 		else if (sys->ep->client == IPA_CLIENT_APPS_LAN_CONS)
 			IPA_STATS_INC_CNT(ipa3_ctx->stats.lan_rx_empty);
 		else if (sys->ep->client == IPA_CLIENT_APPS_WAN_LOW_LAT_DATA_CONS)
@@ -2576,6 +2638,32 @@ static void ipa3_replenish_rx_page_recycle(struct ipa3_sys_context *sys)
 			WARN_ON(1);
 	}
 
+	if (rx_len_cached >= IPA_BUFF_THRESHOLD_HIGH) {
+		if (sys->ep->client == IPA_CLIENT_APPS_WAN_CONS) {
+			spin_lock(&ipa3_ctx->notifier_lock);
+			if(ipa3_ctx->ipa_rmnet_notifier_enabled &&
+				!ipa3_ctx->buff_above_thresh_for_def_pipe_notified) {
+				atomic_inc(&ipa3_ctx->stats.num_buff_above_thresh_for_def_pipe_notified);
+				raw_notifier_call_chain(ipa3_ctx->ipa_rmnet_notifier_list_internal,
+					BUFF_ABOVE_HIGH_THRESHOLD_FOR_DEFAULT_PIPE, &rx_len_cached);
+				ipa3_ctx->buff_above_thresh_for_def_pipe_notified = true;
+				ipa3_ctx->buff_below_thresh_for_def_pipe_notified = false;
+			}
+			spin_unlock(&ipa3_ctx->notifier_lock);
+		} else if (sys->ep->client == IPA_CLIENT_APPS_WAN_COAL_CONS) {
+			spin_lock(&ipa3_ctx->notifier_lock);
+			if(ipa3_ctx->ipa_rmnet_notifier_enabled &&
+				!ipa3_ctx->buff_above_thresh_for_coal_pipe_notified) {
+				atomic_inc(&ipa3_ctx->stats.num_buff_above_thresh_for_coal_pipe_notified);
+				raw_notifier_call_chain(ipa3_ctx->ipa_rmnet_notifier_list_internal,
+					BUFF_ABOVE_HIGH_THRESHOLD_FOR_COAL_PIPE, &rx_len_cached);
+				ipa3_ctx->buff_above_thresh_for_coal_pipe_notified = true;
+				ipa3_ctx->buff_below_thresh_for_coal_pipe_notified = false;
+			}
+			spin_unlock(&ipa3_ctx->notifier_lock);
+		}
+	}
+
 	return;
 }
 

+ 14 - 0
drivers/platform/msm/ipa/ipa_v3/ipa_i.h

@@ -1551,6 +1551,10 @@ struct ipa3_stats {
 	u64 lower_order;
 	struct ipa3_page_recycle_stats page_recycle_stats[3];
 	u64 page_recycle_cnt[3][IPA_PAGE_POLL_THRESHOLD_MAX];
+	atomic_t num_buff_above_thresh_for_def_pipe_notified;
+	atomic_t num_buff_above_thresh_for_coal_pipe_notified;
+	atomic_t num_buff_below_thresh_for_def_pipe_notified;
+	atomic_t num_buff_below_thresh_for_coal_pipe_notified;
 };
 
 /* offset for each stats */
@@ -2335,6 +2339,14 @@ struct ipa3_context {
 	bool is_device_crashed;
 	bool ulso_wa;
 	u64 gsi_msi_addr;
+	spinlock_t notifier_lock;
+	struct raw_notifier_head *ipa_rmnet_notifier_list_internal;
+	struct notifier_block ipa_rmnet_notifier;
+	bool ipa_rmnet_notifier_enabled;
+	bool buff_above_thresh_for_def_pipe_notified;
+	bool buff_above_thresh_for_coal_pipe_notified;
+	bool buff_below_thresh_for_def_pipe_notified;
+	bool buff_below_thresh_for_coal_pipe_notified;
 };
 
 struct ipa3_plat_drv_res {
@@ -3359,6 +3371,8 @@ int ipa3_register_rmnet_ll_cb(
 	void *user_data3);
 int ipa3_unregister_rmnet_ll_cb(void);
 int ipa3_rmnet_ll_xmit(struct sk_buff *skb);
+int ipa3_register_notifier(void *fn_ptr);
+int ipa3_unregister_notifier(void *fn_ptr);
 int ipa3_setup_apps_low_lat_data_prod_pipe(
 	struct rmnet_egress_param *egress_param,
 	struct net_device *dev);