[qca-nss-drv]: Improve N2H payloads stats
Improve N2H payload accounting in NSS FW
Change-Id: Ifeb83f570a7220e8e82aa868bb0e67614804c3c1
Signed-off-by: Saurabh Misra <smisra@codeaurora.org>
diff --git a/nss_n2h.c b/nss_n2h.c
index ca87dbd..b12509f 100755
--- a/nss_n2h.c
+++ b/nss_n2h.c
@@ -24,15 +24,11 @@
#define NSS_CORE_0 0
#define NSS_CORE_1 1
-/*
- * This number is chosen becuase currently default IPV4 + IPV6
- * connection size is 1024 + 1024 = 2048.
- * FYI: However this doesnt have any impact on n2h/ipv6 connections
- */
-#define NSS_N2H_MIN_EMPTY_POOL_BUF_SZ 2048
+#define NSS_N2H_MIN_EMPTY_POOL_BUF_SZ 32
#define NSS_N2H_DEFAULT_EMPTY_POOL_BUF_SZ 8192
-int nss_n2h_empty_pool_buf_cfg[NSS_MAX_CORES] __read_mostly = {NSS_N2H_DEFAULT_EMPTY_POOL_BUF_SZ, NSS_N2H_DEFAULT_EMPTY_POOL_BUF_SZ};
+int nss_n2h_empty_pool_buf_cfg[NSS_MAX_CORES] __read_mostly = {-1, -1};
+int nss_n2h_water_mark[NSS_MAX_CORES][2] __read_mostly = {{-1, -1}, {-1, -1} };
struct nss_n2h_registered_data {
nss_n2h_msg_callback_t n2h_callback;
@@ -103,6 +99,11 @@
nss_ctx->stats_n2h[NSS_STATS_N2H_N2H_DATA_PACKETS] += nnss->n2h_data_pkts;
nss_ctx->stats_n2h[NSS_STATS_N2H_N2H_DATA_BYTES] += nnss->n2h_data_bytes;
+ /*
+ * Payloads related stats
+ */
+ nss_ctx->stats_n2h[NSS_STATS_N2H_N2H_TOT_PAYLOADS] = nnss->tot_payloads;
+
spin_unlock_bh(&nss_top->stats_lock);
}
@@ -209,43 +210,100 @@
}
/*
- * nss_n2h_empty_pool_buf_cfg_core1_callback()
- * call back function for the n2h connection configuration handler
+ * nss_n2h_payload_stats_callback()
+ * It gets called response to payload accounting.
*/
-static void nss_n2h_empty_pool_buf_cfg_callback(void *app_data,
- struct nss_n2h_msg *nnm)
+static void nss_n2h_payload_stats_callback(void *app_data,
+ struct nss_n2h_msg *nnm)
{
int core_num = (int)app_data;
+
if (nnm->cm.response != NSS_CMN_RESPONSE_ACK) {
struct nss_n2h_empty_pool_buf *nnepbcm;
nnepbcm = &nnm->msg.empty_pool_buf_cfg;
- /*
- * Error, hence we are not updating the nss_n2h_empty_pool_buf
- * Restore the current_value to its previous state
- */
- nss_warning("Core %d empty pool buf set failure: %d\n", core_num, nnm->cm.error);
+ nss_warning("%d: core empty pool buf set failure: %d\n",
+ core_num, nnm->cm.error);
nss_n2h_nepbcfgp[core_num].response = NSS_FAILURE;
complete(&nss_n2h_nepbcfgp[core_num].complete);
return;
}
- /*
- * Sucess at NSS FW, hence updating nss_n2h_empty_pool_buf, with the valid value
- * saved at the sysctl handler.
- */
- nss_info("Core %d empty pool buf set success: %d\n", core_num, nnm->cm.error);
+ if (nnm->cm.type == NSS_TX_METADATA_TYPE_GET_PAYLOAD_INFO) {
+ nss_n2h_nepbcfgp[core_num].empty_buf_pool =
+ ntohl(nnm->msg.payload_info.pool_size);
+ nss_n2h_nepbcfgp[core_num].low_water =
+ ntohl(nnm->msg.payload_info.low_water);
+ nss_n2h_nepbcfgp[core_num].high_water =
+ ntohl(nnm->msg.payload_info.high_water);
+ }
+
nss_n2h_nepbcfgp[core_num].response = NSS_SUCCESS;
complete(&nss_n2h_nepbcfgp[core_num].complete);
}
/*
- * nss_n2h_empty_pool_buf_core1_handler()
- * Sets the number of connections for IPv4
+ * nss_n2h_get_payload_info()
+ * Gets Payload information
*/
-static int nss_n2h_set_empty_pool_buf(ctl_table *ctl, int write, void __user *buffer,
- size_t *lenp, loff_t *ppos,
- int core_num, int *new_val)
+static int nss_n2h_get_payload_info(ctl_table *ctl, int write,
+ void __user *buffer, size_t *lenp, loff_t *ppos,
+ int core_num)
+{
+ struct nss_top_instance *nss_top = &nss_top_main;
+ struct nss_ctx_instance *nss_ctx = &nss_top->nss[core_num];
+ struct nss_n2h_msg nnm;
+ struct nss_n2h_payload_info *nnepbcm;
+ nss_tx_status_t nss_tx_status;
+ int ret = NSS_FAILURE;
+
+ /*
+ * Note that semaphore should be already held.
+ */
+
+ nss_n2h_msg_init(&nnm, NSS_N2H_INTERFACE,
+ NSS_TX_METADATA_TYPE_GET_PAYLOAD_INFO,
+ sizeof(struct nss_n2h_payload_info),
+ nss_n2h_payload_stats_callback,
+ (void *)core_num);
+
+ nnepbcm = &nnm.msg.payload_info;
+ nss_tx_status = nss_n2h_tx_msg(nss_ctx, &nnm);
+
+ if (nss_tx_status != NSS_TX_SUCCESS) {
+ nss_warning("%p: core %d nss_tx error errorn",
+ nss_ctx, core_num);
+ return NSS_FAILURE;
+ }
+
+ /*
+ * Blocking call, wait till we get ACK for this msg.
+ */
+ ret = wait_for_completion_timeout(&nss_n2h_nepbcfgp[core_num].complete,
+ msecs_to_jiffies(NSS_CONN_CFG_TIMEOUT));
+ if (ret == 0) {
+ nss_warning("%p: core %d waiting for ack timed out\n", nss_ctx,
+ core_num);
+ return NSS_FAILURE;
+ }
+
+ if (NSS_FAILURE == nss_n2h_nepbcfgp[core_num].response) {
+ nss_warning("%p: core %d response returned failure\n", nss_ctx,
+ core_num);
+ return NSS_FAILURE;
+ }
+
+ return NSS_SUCCESS;
+}
+
+/*
+ * nss_n2h_set_empty_pool_buf()
+ * Sets empty pool buffer
+ */
+static int nss_n2h_set_empty_pool_buf(ctl_table *ctl, int write,
+ void __user *buffer,
+ size_t *lenp, loff_t *ppos,
+ int core_num, int *new_val)
{
struct nss_top_instance *nss_top = &nss_top_main;
struct nss_ctx_instance *nss_ctx = &nss_top->nss[core_num];
@@ -262,23 +320,31 @@
/*
* Take snap shot of current value
*/
- nss_n2h_nepbcfgp[core_num].current_value = *new_val;
+ nss_n2h_nepbcfgp[core_num].empty_buf_pool = *new_val;
- /*
- * Write the variable with user input
- */
+ if (!write) {
+ ret = nss_n2h_get_payload_info(ctl, write, buffer, lenp, ppos,
+ core_num);
+ *new_val = nss_n2h_nepbcfgp[core_num].empty_buf_pool;
+ if (ret == NSS_FAILURE) {
+ up(&nss_n2h_nepbcfgp[core_num].sem);
+ return -EBUSY;
+ }
+
+ up(&nss_n2h_nepbcfgp[core_num].sem);
+
+ ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
+ return ret;
+ }
+
ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
- if (ret || (!write)) {
+ if (ret) {
up(&nss_n2h_nepbcfgp[core_num].sem);
return ret;
}
- /*
- * Input for n2h should be atleast 2048 to support defalt connections
- * of 1024 (IPV4) + 1024 (IPV6) connections.
- */
if ((*new_val < NSS_N2H_MIN_EMPTY_POOL_BUF_SZ)) {
- nss_warning("%p: core %d setting %d is less than minimum number of buffer",
+ nss_warning("%p: core %d setting %d < min number of buffer",
nss_ctx, core_num, *new_val);
goto failure;
}
@@ -289,7 +355,7 @@
nss_n2h_msg_init(&nnm, NSS_N2H_INTERFACE,
NSS_TX_METADATA_TYPE_N2H_EMPTY_POOL_BUF_CFG,
sizeof(struct nss_n2h_empty_pool_buf),
- nss_n2h_empty_pool_buf_cfg_callback,
+ nss_n2h_payload_stats_callback,
(void *)core_num);
nnepbcm = &nnm.msg.empty_pool_buf_cfg;
@@ -297,7 +363,7 @@
nss_tx_status = nss_n2h_tx_msg(nss_ctx, &nnm);
if (nss_tx_status != NSS_TX_SUCCESS) {
- nss_warning("%p: core %d nss_tx error setting empty pool buffer: %d\n",
+ nss_warning("%p: core %d nss_tx error empty pool buffer: %d\n",
nss_ctx, core_num, *new_val);
goto failure;
}
@@ -305,9 +371,11 @@
/*
* Blocking call, wait till we get ACK for this msg.
*/
- ret = wait_for_completion_timeout(&nss_n2h_nepbcfgp[core_num].complete, msecs_to_jiffies(NSS_CONN_CFG_TIMEOUT));
+ ret = wait_for_completion_timeout(&nss_n2h_nepbcfgp[core_num].complete,
+ msecs_to_jiffies(NSS_CONN_CFG_TIMEOUT));
if (ret == 0) {
- nss_warning("%p: core %d Waiting for ack timed out\n", nss_ctx, core_num);
+ nss_warning("%p: core %d Waiting for ack timed out\n", nss_ctx,
+ core_num);
goto failure;
}
@@ -327,7 +395,133 @@
/*
* Restore the current_value to its previous state
*/
- *new_val = nss_n2h_nepbcfgp[core_num].current_value;
+ *new_val = nss_n2h_nepbcfgp[core_num].empty_buf_pool;
+ up(&nss_n2h_nepbcfgp[core_num].sem);
+ return NSS_FAILURE;
+}
+
+/*
+ * nss_n2h_set_water_mark()
+ * Sets water mark for N2H SOS
+ */
+static int nss_n2h_set_water_mark(ctl_table *ctl, int write,
+ void __user *buffer,
+ size_t *lenp, loff_t *ppos,
+ int core_num, int *low, int *high)
+{
+ struct nss_top_instance *nss_top = &nss_top_main;
+ struct nss_ctx_instance *nss_ctx = &nss_top->nss[core_num];
+ struct nss_n2h_msg nnm;
+ struct nss_n2h_water_mark *wm;
+ nss_tx_status_t nss_tx_status;
+ int ret = NSS_FAILURE;
+
+ /*
+ * Acquiring semaphore
+ */
+ down(&nss_n2h_nepbcfgp[core_num].sem);
+
+ /*
+ * Take snap shot of current value
+ */
+ nss_n2h_nepbcfgp[core_num].low_water = *low;
+ nss_n2h_nepbcfgp[core_num].high_water = *high;
+
+ if (!write) {
+ ret = nss_n2h_get_payload_info(ctl, write, buffer, lenp, ppos,
+ core_num);
+ *low = nss_n2h_nepbcfgp[core_num].low_water;
+ *high = nss_n2h_nepbcfgp[core_num].high_water;
+
+ if (ret == NSS_FAILURE) {
+ up(&nss_n2h_nepbcfgp[core_num].sem);
+ return -EBUSY;
+ }
+
+ up(&nss_n2h_nepbcfgp[core_num].sem);
+ ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
+ return ret;
+ }
+
+ ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
+ if (ret) {
+ up(&nss_n2h_nepbcfgp[core_num].sem);
+ return ret;
+ }
+
+ /*
+ * If either low or high water mark is not set then we do
+ * nothing.
+ */
+ if (*low == -1 || *high == -1)
+ goto failure;
+
+ if ((*low < NSS_N2H_MIN_EMPTY_POOL_BUF_SZ) ||
+ (*high < NSS_N2H_MIN_EMPTY_POOL_BUF_SZ)) {
+ nss_warning("%p: core %d setting %d, %d < min number of buffer",
+ nss_ctx, core_num, *low, *high);
+ goto failure;
+ }
+
+ if ((*low > (NSS_N2H_DEFAULT_EMPTY_POOL_BUF_SZ * 2)) ||
+ (*high > (NSS_N2H_DEFAULT_EMPTY_POOL_BUF_SZ * 2))) {
+ nss_warning("%p: core %d setting %d, %d is > upper limit",
+ nss_ctx, core_num, *low, *high);
+ goto failure;
+ }
+
+ if (*low > *high) {
+ nss_warning("%p: core %d setting low %d is more than high %d",
+ nss_ctx, core_num, *low, *high);
+ goto failure;
+ }
+
+ nss_info("%p: core %d number of low : %d and high : %d\n",
+ nss_ctx, core_num, *low, *high);
+
+ nss_n2h_msg_init(&nnm, NSS_N2H_INTERFACE,
+ NSS_TX_METADATA_TYPE_SET_WATER_MARK,
+ sizeof(struct nss_n2h_water_mark),
+ nss_n2h_payload_stats_callback,
+ (void *)core_num);
+
+ wm = &nnm.msg.wm;
+ wm->low_water = htonl(*low);
+ wm->high_water = htonl(*high);
+ nss_tx_status = nss_n2h_tx_msg(nss_ctx, &nnm);
+
+ if (nss_tx_status != NSS_TX_SUCCESS) {
+ nss_warning("%p: core %d nss_tx error setting : %d, %d\n",
+ nss_ctx, core_num, *low, *high);
+ goto failure;
+ }
+
+ /*
+ * Blocking call, wait till we get ACK for this msg.
+ */
+ ret = wait_for_completion_timeout(&nss_n2h_nepbcfgp[core_num].complete,
+ msecs_to_jiffies(NSS_CONN_CFG_TIMEOUT));
+ if (ret == 0) {
+ nss_warning("%p: core %d Waiting for ack timed out\n", nss_ctx,
+ core_num);
+ goto failure;
+ }
+
+ /*
+ * ACK/NACK received from NSS FW
+ */
+ if (NSS_FAILURE == nss_n2h_nepbcfgp[core_num].response)
+ goto failure;
+
+ up(&nss_n2h_nepbcfgp[core_num].sem);
+ return NSS_SUCCESS;
+
+failure:
+ /*
+ * Restore the current_value to its previous state
+ */
+ *low = nss_n2h_nepbcfgp[core_num].low_water;
+ *high = nss_n2h_nepbcfgp[core_num].high_water;
up(&nss_n2h_nepbcfgp[core_num].sem);
return -EINVAL;
}
@@ -371,11 +565,11 @@
* Sets the number of empty buffer for core 1
*/
static int nss_n2h_empty_pool_buf_cfg_core1_handler(ctl_table *ctl,
- int write, void __user *buffer,
- size_t *lenp, loff_t *ppos)
+ int write, void __user *buffer,
+ size_t *lenp, loff_t *ppos)
{
return nss_n2h_set_empty_pool_buf(ctl, write, buffer, lenp, ppos,
- NSS_CORE_1, &nss_n2h_empty_pool_buf_cfg[NSS_CORE_1]);
+ NSS_CORE_1, &nss_n2h_empty_pool_buf_cfg[NSS_CORE_1]);
}
/*
@@ -383,11 +577,37 @@
* Sets the number of empty buffer for core 0
*/
static int nss_n2h_empty_pool_buf_cfg_core0_handler(ctl_table *ctl,
- int write, void __user *buffer,
- size_t *lenp, loff_t *ppos)
+ int write, void __user *buffer,
+ size_t *lenp, loff_t *ppos)
{
return nss_n2h_set_empty_pool_buf(ctl, write, buffer, lenp, ppos,
- NSS_CORE_0, &nss_n2h_empty_pool_buf_cfg[NSS_CORE_0]);
+ NSS_CORE_0, &nss_n2h_empty_pool_buf_cfg[NSS_CORE_0]);
+}
+
+/*
+ * nss_n2h_water_mark_core1_handler()
+ * Sets water mark for core 1
+ */
+static int nss_n2h_water_mark_core1_handler(ctl_table *ctl,
+ int write, void __user *buffer,
+ size_t *lenp, loff_t *ppos)
+{
+ return nss_n2h_set_water_mark(ctl, write, buffer, lenp, ppos,
+ NSS_CORE_1, &nss_n2h_water_mark[NSS_CORE_1][0],
+ &nss_n2h_water_mark[NSS_CORE_1][1]);
+}
+
+/*
+ * nss_n2h_water_mark_core0_handler()
+ * Sets water mark for core 0
+ */
+static int nss_n2h_water_mark_core0_handler(ctl_table *ctl,
+ int write, void __user *buffer,
+ size_t *lenp, loff_t *ppos)
+{
+ return nss_n2h_set_water_mark(ctl, write, buffer, lenp, ppos,
+ NSS_CORE_0, &nss_n2h_water_mark[NSS_CORE_0][0],
+ &nss_n2h_water_mark[NSS_CORE_0][1]);
}
/*
@@ -445,18 +665,46 @@
static ctl_table nss_n2h_table[] = {
{
- .procname = "n2h_empty_pool_buf_core0",
- .data = &nss_n2h_empty_pool_buf_cfg[NSS_CORE_0],
- .maxlen = sizeof(int),
- .mode = 0644,
- .proc_handler = &nss_n2h_empty_pool_buf_cfg_core0_handler,
+ .procname = "n2h_empty_pool_buf_core0",
+ .data = &nss_n2h_empty_pool_buf_cfg[NSS_CORE_0],
+ .maxlen = sizeof(int),
+ .mode = 0644,
+ .proc_handler = &nss_n2h_empty_pool_buf_cfg_core0_handler,
},
{
- .procname = "n2h_empty_pool_buf_core1",
- .data = &nss_n2h_empty_pool_buf_cfg[NSS_CORE_1],
- .maxlen = sizeof(int),
- .mode = 0644,
- .proc_handler = &nss_n2h_empty_pool_buf_cfg_core1_handler,
+ .procname = "n2h_empty_pool_buf_core1",
+ .data = &nss_n2h_empty_pool_buf_cfg[NSS_CORE_1],
+ .maxlen = sizeof(int),
+ .mode = 0644,
+ .proc_handler = &nss_n2h_empty_pool_buf_cfg_core1_handler,
+ },
+ {
+ .procname = "n2h_low_water_core0",
+ .data = &nss_n2h_water_mark[NSS_CORE_0][0],
+ .maxlen = sizeof(int),
+ .mode = 0644,
+ .proc_handler = &nss_n2h_water_mark_core0_handler,
+ },
+ {
+ .procname = "n2h_low_water_core1",
+ .data = &nss_n2h_water_mark[NSS_CORE_1][0],
+ .maxlen = sizeof(int),
+ .mode = 0644,
+ .proc_handler = &nss_n2h_water_mark_core1_handler,
+ },
+ {
+ .procname = "n2h_high_water_core0",
+ .data = &nss_n2h_water_mark[NSS_CORE_0][1],
+ .maxlen = sizeof(int),
+ .mode = 0644,
+ .proc_handler = &nss_n2h_water_mark_core0_handler,
+ },
+ {
+ .procname = "n2h_high_water_core1",
+ .data = &nss_n2h_water_mark[NSS_CORE_1][1],
+ .maxlen = sizeof(int),
+ .mode = 0644,
+ .proc_handler = &nss_n2h_water_mark_core1_handler,
},
{ }
@@ -518,14 +766,24 @@
*/
sema_init(&nss_n2h_nepbcfgp[NSS_CORE_0].sem, 1);
init_completion(&nss_n2h_nepbcfgp[NSS_CORE_0].complete);
- nss_n2h_nepbcfgp[NSS_CORE_0].current_value = nss_n2h_empty_pool_buf_cfg[NSS_CORE_0];
+ nss_n2h_nepbcfgp[NSS_CORE_0].empty_buf_pool =
+ nss_n2h_empty_pool_buf_cfg[NSS_CORE_0];
+ nss_n2h_nepbcfgp[NSS_CORE_0].low_water =
+ nss_n2h_water_mark[NSS_CORE_0][0];
+ nss_n2h_nepbcfgp[NSS_CORE_0].high_water =
+ nss_n2h_water_mark[NSS_CORE_0][1];
/*
* Core1
*/
sema_init(&nss_n2h_nepbcfgp[NSS_CORE_1].sem, 1);
init_completion(&nss_n2h_nepbcfgp[NSS_CORE_1].complete);
- nss_n2h_nepbcfgp[NSS_CORE_1].current_value = nss_n2h_empty_pool_buf_cfg[NSS_CORE_1];
+ nss_n2h_nepbcfgp[NSS_CORE_1].empty_buf_pool =
+ nss_n2h_empty_pool_buf_cfg[NSS_CORE_1];
+ nss_n2h_nepbcfgp[NSS_CORE_1].low_water =
+ nss_n2h_water_mark[NSS_CORE_1][0];
+ nss_n2h_nepbcfgp[NSS_CORE_1].high_water =
+ nss_n2h_water_mark[NSS_CORE_1][1];
}
/*