Merge "[qca-nss-drv] Correct NETIF flags check"
diff --git a/Makefile b/Makefile
index b8c176c..0cdc956 100644
--- a/Makefile
+++ b/Makefile
@@ -65,7 +65,7 @@
ccflags-y += -DNSS_PM_DEBUG_LEVEL=0 -DNSS_PPP_SUPPORT=1
ifneq ($(findstring 3.4, $(KERNELVERSION)),)
-NSS_CCFLAGS = -DNSS_DT_SUPPORT=0 -DNSS_FW_DBG_SUPPORT=1 -DNSS_PM_SUPPORT=1 -DNSS_EMPTY_BUFFER_SIZE=2048
+NSS_CCFLAGS = -DNSS_DT_SUPPORT=0 -DNSS_FW_DBG_SUPPORT=1 -DNSS_PM_SUPPORT=1 -DNSS_EMPTY_BUFFER_SIZE=1984
else
NSS_CCFLAGS = -DNSS_DT_SUPPORT=1 -DNSS_FW_DBG_SUPPORT=0 -DNSS_PM_SUPPORT=0 -DNSS_EMPTY_BUFFER_SIZE=1792
ccflags-y += -I$(obj)
diff --git a/exports/nss_ipv4.h b/exports/nss_ipv4.h
index 3e8d786..eb103be 100644
--- a/exports/nss_ipv4.h
+++ b/exports/nss_ipv4.h
@@ -38,6 +38,7 @@
NSS_IPV4_RX_NODE_STATS_SYNC_MSG, /**< IPv4 generic statistics sync message */
NSS_IPV4_TX_CONN_CFG_RULE_MSG, /**< IPv4 number of connections supported rule message */
NSS_IPV4_TX_CREATE_MC_RULE_MSG, /**< IPv4 multicast create rule message */
+ NSS_IPV4_TX_CONN_STATS_SYNC_MANY_MSG, /**< IPv4 request FW to send many conn sync message */
NSS_IPV4_MAX_MSG_TYPES, /**< IPv4 message max type number */
};
@@ -350,6 +351,20 @@
};
/**
+ * The NSS IPv4 conn sync many structure.
+ */
+struct nss_ipv4_conn_sync_many_msg {
+ /* Request */
+ uint16_t index; /**< Request conn stats from index */
+ uint16_t size; /**< The buf size of this msg */
+
+ /* Response */
+ uint16_t next; /**< FW response the next conn to be requested */
+ uint16_t count; /**< How many conn_sync included in this msg */
+ struct nss_ipv4_conn_sync conn_sync[]; /**< Array for the stats */
+};
+
+/**
* Exception events from bridge/route handler
*/
enum exception_events_ipv4 {
@@ -480,7 +495,8 @@
struct nss_ipv4_conn_sync conn_stats; /**< Message: connection stats sync */
struct nss_ipv4_node_sync node_stats; /**< Message: node stats sync */
struct nss_ipv4_rule_conn_cfg_msg rule_conn_cfg; /**< Message: rule connections supported */
- struct nss_ipv4_mc_rule_create_msg mc_rule_create; /**<Message: Multicast rule create */
+ struct nss_ipv4_mc_rule_create_msg mc_rule_create; /**< Message: Multicast rule create */
+ struct nss_ipv4_conn_sync_many_msg conn_stats_many; /**< Message: connection stats sync */
} msg;
};
@@ -511,6 +527,17 @@
extern nss_tx_status_t nss_ipv4_tx(struct nss_ctx_instance *nss_ctx, struct nss_ipv4_msg *msg);
/**
+ * @brief Transmit an IPv4 message to the NSS with specified size
+ *
+ * @param nss_ctx NSS context
+ * @param msg The IPv4 message
+ * @param size Actual size of this msg
+ *
+ * @return nss_tx_status_t The status of the Tx operation
+ */
+extern nss_tx_status_t nss_ipv4_tx_with_size(struct nss_ctx_instance *nss_ctx, struct nss_ipv4_msg *msg, uint32_t size);
+
+/**
* @brief Register a notifier callback for IPv4 messages from NSS
*
* @param cb The callback pointer
diff --git a/exports/nss_ipv6.h b/exports/nss_ipv6.h
index 8f6bbf7..b1b0d56 100644
--- a/exports/nss_ipv6.h
+++ b/exports/nss_ipv6.h
@@ -38,6 +38,7 @@
NSS_IPV6_RX_NODE_STATS_SYNC_MSG, /**< IPv6 generic statistics sync message */
NSS_IPV6_TX_CONN_CFG_RULE_MSG, /**< IPv6 connection cfg rule message */
NSS_IPV6_TX_CREATE_MC_RULE_MSG, /**< IPv6 create multicast rule message */
+ NSS_IPV6_TX_CONN_STATS_SYNC_MANY_MSG, /**< IPv6 connection stats sync many message */
NSS_IPV6_MAX_MSG_TYPES,
};
@@ -394,6 +395,20 @@
};
/**
+ * NSS IPv6 connection stats sync many structure
+ */
+struct nss_ipv6_conn_sync_many_msg {
+ /* Request */
+ uint16_t index; /**< Request conn stats from index */
+ uint16_t size; /**< The buf size of this msg */
+
+ /* Response */
+ uint16_t next; /**< FW response the next conn to be requested */
+ uint16_t count; /**< How many conn_sync included in this msg */
+ struct nss_ipv6_conn_sync conn_sync[]; /**< Array for the stats */
+};
+
+/**
* NSS IPv6 node stats sync structure
*/
struct nss_ipv6_node_sync {
@@ -448,7 +463,8 @@
struct nss_ipv6_conn_sync conn_stats; /**< Message: stats sync */
struct nss_ipv6_node_sync node_stats; /**< Message: node stats sync */
struct nss_ipv6_rule_conn_cfg_msg rule_conn_cfg;/**< Message: rule conn cfg */
- struct nss_ipv6_mc_rule_create_msg mc_rule_create; /**<Message: Multicast rule create */
+ struct nss_ipv6_mc_rule_create_msg mc_rule_create; /**< Message: Multicast rule create */
+ struct nss_ipv6_conn_sync_many_msg conn_stats_many; /**< Message: stats sync many */
} msg;
};
@@ -477,6 +493,17 @@
extern nss_tx_status_t nss_ipv6_tx(struct nss_ctx_instance *nss_ctx, struct nss_ipv6_msg *msg);
/**
+ * @brief Transmit an IPv6 message to the NSS with specified size
+ *
+ * @param nss_ctx NSS context
+ * @param msg The IPv6 message
+ * @param size Actual size of this message
+ *
+ * @return nss_tx_status_t The status of the Tx operation
+ */
+extern nss_tx_status_t nss_ipv6_tx_with_size(struct nss_ctx_instance *nss_ctx, struct nss_ipv6_msg *msg, uint32_t size);
+
+/**
* @brief Register a notifier callback for IPv6 messages from NSS
*
* @param cb The callback pointer
diff --git a/exports/nss_n2h.h b/exports/nss_n2h.h
index cb20caa..7290c97 100644
--- a/exports/nss_n2h.h
+++ b/exports/nss_n2h.h
@@ -27,13 +27,17 @@
#ifndef __NSS_N2H_H
#define __NSS_N2H_H
+#define MAX_PAGES_PER_MSG 32
+
/*
* Private data structure for configure general configs
*/
struct nss_n2h_cfg_pvt {
struct semaphore sem; /* Semaphore structure */
struct completion complete; /* completion structure */
- int current_value; /* valid entry */
+ int empty_buf_pool; /* valid entry */
+ int low_water; /* valid entry */
+ int high_water; /* valid entry */
int response; /* Response from FW */
};
@@ -45,6 +49,10 @@
NSS_TX_METADATA_TYPE_N2H_RPS_CFG,
NSS_TX_METADATA_TYPE_N2H_EMPTY_POOL_BUF_CFG,
NSS_TX_METADATA_TYPE_N2H_FLUSH_PAYLOADS,
+ NSS_TX_METADATA_TYPE_N2H_MITIGATION_CFG,
+ NSS_METADATA_TYPE_N2H_ADD_BUF_POOL,
+ NSS_TX_METADATA_TYPE_SET_WATER_MARK,
+ NSS_TX_METADATA_TYPE_GET_PAYLOAD_INFO,
NSS_METADATA_TYPE_N2H_MAX,
};
@@ -52,8 +60,51 @@
uint32_t enable; /* Enable NSS RPS */
};
+struct nss_n2h_mitigation {
+ uint32_t enable; /* Enable NSS MITIGATION */
+};
+
+struct nss_n2h_buf_pool {
+ uint32_t nss_buf_page_size;
+ uint32_t nss_buf_num_pages;
+ void *nss_buf_pool_vaddr[MAX_PAGES_PER_MSG];
+ uint32_t nss_buf_pool_addr[MAX_PAGES_PER_MSG];
+};
+
+/*
+ * Old way of setting number of empty pool buffers (payloads).
+ * NSS FW then sets low water mark to 'n - ring_size' and
+ * high water mark to 'n + ring_size'.
+ */
struct nss_n2h_empty_pool_buf {
- uint32_t pool_size; /* Empty pool buf size */
+ uint32_t pool_size; /* Empty buffer pool size */
+};
+
+/*
+ * New way of setting low and high water marks in the NSS FW.
+ */
+struct nss_n2h_water_mark {
+ /*
+ * Low water mark. Set it to 0 for system to determine automatically.
+ */
+ uint32_t low_water;
+
+ /*
+ * High water mark. Set it to 0 for system to determine automatically.
+ */
+ uint32_t high_water;
+};
+
+struct nss_n2h_payload_info {
+ uint32_t pool_size; /* Empty buffer pool size */
+ /*
+ * Low water mark. Set it to 0 for system to determine automatically.
+ */
+ uint32_t low_water;
+ /*
+ * High water mark. Set it to 0 for system to determine automatically.
+ */
+ uint32_t high_water;
};
struct nss_n2h_flush_payloads {
@@ -64,9 +115,9 @@
* NSS Pbuf mgr stats
*/
struct nss_n2h_pbuf_mgr_stats {
- uint32_t pbuf_alloc_fails; /* Pbuf ocm alloc fail */
- uint32_t pbuf_free_count; /* Pbuf ocm free count */
- uint32_t pbuf_total_count; /* Pbuf ocm total count */
+ uint32_t pbuf_alloc_fails; /* Pbuf alloc fail */
+ uint32_t pbuf_free_count; /* Pbuf free count */
+ uint32_t pbuf_total_count; /* Pbuf total count */
};
/*
@@ -97,6 +148,7 @@
uint32_t h2n_data_bytes; /* Data bytes received from HLOS */
uint32_t n2h_data_pkts; /* Data packets sent to HLOS */
uint32_t n2h_data_bytes; /* Data bytes sent to HLOS */
+ uint32_t tot_payloads; /* Total number of payloads in NSS FW */
};
/*
@@ -111,6 +163,13 @@
/* Message: empty pool buf configuration */
struct nss_n2h_flush_payloads flush_payloads;
/* Message: flush payloads present in NSS */
+ struct nss_n2h_mitigation mitigation_cfg;
+ /* Message: Mitigation configuration */
+ struct nss_n2h_buf_pool buf_pool; /* Message: pbuf coniguration */
+ struct nss_n2h_water_mark wm;
+ /* Message: Sets low and high water marks */
+ struct nss_n2h_payload_info payload_info;
+ /* Message: Gets payload info */
} msg;
};
@@ -132,6 +191,18 @@
extern nss_tx_status_t nss_n2h_rps_cfg(struct nss_ctx_instance *nss_ctx, int enable_rps);
/*
+ * nss_n2h_mitigation_cfg()
+ * API to enable/disable Host MITIGATION support in NSS
+ */
+extern nss_tx_status_t nss_n2h_mitigation_cfg(struct nss_ctx_instance *nss_ctx, int enable_mitigation, nss_core_id_t nss_core);
+
+/*
+ * nss_n2h_buf_pool_cfg()
+ * API to increase the pbufs on NSS using Host memory
+ */
+extern nss_tx_status_t nss_n2h_buf_pool_cfg(struct nss_ctx_instance *nss_ctx, int nss_pbuf_pool_size, nss_core_id_t nss_core);
+
+/*
* nss_n2h_empty_pool_buf_register_sysctl()
* API to register sysctl for empty pool buffer in n2h.
*/
diff --git a/exports/nss_wifi_vdev.h b/exports/nss_wifi_vdev.h
index 62175ef..b0a3726 100644
--- a/exports/nss_wifi_vdev.h
+++ b/exports/nss_wifi_vdev.h
@@ -41,6 +41,7 @@
NSS_WIFI_VDEV_SNOOPLIST_DENY_LIST_DELETE_MSG,
NSS_WIFI_VDEV_SNOOPLIST_DENY_LIST_DUMP_MSG,
NSS_WIFI_VDEV_SNOOPLIST_DUMP_MSG,
+ NSS_WIFI_VDEV_SNOOPLIST_RESET_MSG,
NSS_WIFI_VDEV_MAX_MSG
};
diff --git a/nss_core.h b/nss_core.h
index 89638ed..38c586b 100755
--- a/nss_core.h
+++ b/nss_core.h
@@ -49,6 +49,8 @@
/*
* NSS debug macros
*/
+#define nss_info_always(s, ...) pr_alert(s, ##__VA_ARGS__)
+
#if (NSS_DEBUG_LEVEL < 1)
#define nss_assert(fmt, args...)
#else
@@ -482,6 +484,7 @@
NSS_STATS_N2H_H2N_DATA_BYTES, /* Data bytes received from HLOS */
NSS_STATS_N2H_N2H_DATA_PACKETS, /* Data packets sent to HLOS */
NSS_STATS_N2H_N2H_DATA_BYTES, /* Data bytes sent to HLOS */
+ NSS_STATS_N2H_N2H_TOT_PAYLOADS, /* No. of payloads in NSS */
NSS_STATS_N2H_MAX,
};
@@ -619,8 +622,10 @@
/* Host to NSS descriptor rings */
struct hlos_n2h_desc_ring n2h_desc_ring[15];
/* NSS to Host descriptor rings */
- uint8_t n2h_rps_en; /* N2H Enable Multiple queues for Data Packets */
+ uint16_t n2h_rps_en; /* N2H Enable Multiple queues for Data Packets */
+ uint16_t n2h_mitigate_en; /* N2H mitigation */
uint32_t max_buf_size; /* Maximum buffer size */
+ uint32_t buf_sz_allocated; /* size of bufs allocated from host */
nss_cmn_queue_decongestion_callback_t queue_decongestion_callback[NSS_MAX_CLIENTS];
/* Queue decongestion callbacks */
void *queue_decongestion_ctx[NSS_MAX_CLIENTS];
diff --git a/nss_data_plane.c b/nss_data_plane.c
index 1549b2e..d9c3d0d 100644
--- a/nss_data_plane.c
+++ b/nss_data_plane.c
@@ -20,7 +20,7 @@
#include "nss_tx_rx_common.h"
#include <nss_gmac_api_if.h>
-#define NSS_DP_SUPPORTED_FEATURES NETIF_F_HW_CSUM | NETIF_F_RXCSUM | NETIF_F_SG | NETIF_F_FRAGLIST | (NETIF_F_TSO | NETIF_F_TSO6 | NETIF_F_UFO)
+#define NSS_DP_SUPPORTED_FEATURES NETIF_F_HIGHDMA | NETIF_F_HW_CSUM | NETIF_F_RXCSUM | NETIF_F_SG | NETIF_F_FRAGLIST | (NETIF_F_TSO | NETIF_F_TSO6 | NETIF_F_UFO)
struct nss_data_plane_param nss_data_plane_params[NSS_MAX_PHYSICAL_INTERFACES];
diff --git a/nss_hal/fsm9010/nss_hal_pvt.c b/nss_hal/fsm9010/nss_hal_pvt.c
index 6c99955..8410373 100644
--- a/nss_hal/fsm9010/nss_hal_pvt.c
+++ b/nss_hal/fsm9010/nss_hal_pvt.c
@@ -436,7 +436,6 @@
#endif
nss_eth_rx_register_handler();
nss_n2h_register_handler();
- nss_virt_if_register_handler();
nss_lag_register_handler();
nss_dynamic_interface_register_handler();
diff --git a/nss_init.c b/nss_init.c
index dbc52dd..a41f463 100755
--- a/nss_init.c
+++ b/nss_init.c
@@ -47,12 +47,18 @@
#include <linux/regulator/consumer.h>
#include <linux/clk.h>
+#define NSS_N2H_MAX_BUF_POOL_SIZE (1024 * 1024 * 4) /* 4MB */
+
/*
* Global declarations
*/
int nss_ctl_redirect __read_mostly = 0;
int nss_ctl_debug __read_mostly = 0;
int nss_rps_cfg __read_mostly = 0;
+int nss_core0_mitigation_cfg __read_mostly = 1;
+int nss_core1_mitigation_cfg __read_mostly = 1;
+int nss_core0_add_buf_pool_size __read_mostly = 0;
+int nss_core1_add_buf_pool_size __read_mostly = 0;
int nss_ctl_logbuf __read_mostly = 0;
int nss_jumbo_mru __read_mostly = 0;
int nss_paged_mode __read_mostly = 0;
@@ -433,6 +439,146 @@
}
/*
+ * nss_mitigation_handler()
+ * Enable NSS MITIGATION
+ */
+static int nss_mitigationcfg_core0_handler(ctl_table *ctl, int write, void __user *buffer, size_t *lenp, loff_t *ppos)
+{
+ struct nss_top_instance *nss_top = &nss_top_main;
+ struct nss_ctx_instance *nss_ctx = &nss_top->nss[NSS_CORE_0];
+ int ret;
+
+ ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
+ if (ret) {
+ return ret;
+ }
+
+ /*
+ * It's a read operation
+ */
+ if (!write) {
+ return ret;
+ }
+
+ if (!nss_core0_mitigation_cfg ) {
+ printk("Disabling NSS MITIGATION\n");
+ nss_n2h_mitigation_cfg(nss_ctx, 0, NSS_CORE_0);
+ return 0;
+ }
+ printk("Invalid input value.Valid value is 0, Runtime re-enabling not supported\n");
+ return -EINVAL;
+}
+
+/*
+ * nss_mitigation_handler()
+ * Enable NSS MITIGATION
+ */
+static int nss_mitigationcfg_core1_handler(ctl_table *ctl, int write, void __user *buffer, size_t *lenp, loff_t *ppos)
+{
+ struct nss_top_instance *nss_top = &nss_top_main;
+ struct nss_ctx_instance *nss_ctx = &nss_top->nss[NSS_CORE_1];
+ int ret;
+
+ ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
+ if (ret) {
+ return ret;;
+ }
+
+ /*
+ * It's a read operation
+ */
+ if (!write) {
+ return ret;
+ }
+
+ if (!nss_core1_mitigation_cfg ) {
+ printk("Disabling NSS MITIGATION\n");
+ nss_n2h_mitigation_cfg(nss_ctx, 0, NSS_CORE_1);
+ return 0;
+ }
+ printk("Invalid input value.Valid value is 0, Runtime re-enabling not supported\n");
+ return -EINVAL;
+}
+
+/*
+ * nss_buf_handler()
+ * Add extra NSS bufs from host memory
+ */
+static int nss_buf_cfg_core0_handler(ctl_table *ctl, int write, void __user *buffer, size_t *lenp, loff_t *ppos)
+{
+ struct nss_top_instance *nss_top = &nss_top_main;
+ struct nss_ctx_instance *nss_ctx = &nss_top->nss[NSS_CORE_0];
+ int ret;
+
+ ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
+ if (ret) {
+ return ret;
+ }
+
+ /*
+ * It's a read operation
+ */
+ if (!write) {
+ return ret;
+ }
+
+ if (nss_ctx->buf_sz_allocated) {
+ nss_core0_add_buf_pool_size = nss_ctx->buf_sz_allocated;
+ return -EPERM;
+ }
+
+ if ((nss_core0_add_buf_pool_size >= 1) && (nss_core0_add_buf_pool_size <= NSS_N2H_MAX_BUF_POOL_SIZE)) {
+ printk("configuring additional NSS pbufs\n");
+ ret = nss_n2h_buf_pool_cfg(nss_ctx, nss_core0_add_buf_pool_size, NSS_CORE_0);
+ nss_core0_add_buf_pool_size = nss_ctx->buf_sz_allocated;
+ printk("additional pbufs of size %d got added to NSS\n", nss_ctx->buf_sz_allocated);
+ return ret;;
+ }
+
+ printk("Invalid input value. should be greater than 1 and less than %d\n", NSS_N2H_MAX_BUF_POOL_SIZE);
+ return -EINVAL;
+}
+
+/*
+ * nss_buf_handler()
+ * Add extra NSS bufs from host memory
+ */
+static int nss_buf_cfg_core1_handler(ctl_table *ctl, int write, void __user *buffer, size_t *lenp, loff_t *ppos)
+{
+ struct nss_top_instance *nss_top = &nss_top_main;
+ struct nss_ctx_instance *nss_ctx = &nss_top->nss[NSS_CORE_1];
+ int ret;
+
+ ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
+ if (ret) {
+ return ret;
+ }
+
+ /*
+ * It's a read operation
+ */
+ if (!write) {
+ return ret;
+ }
+
+ if (nss_ctx->buf_sz_allocated) {
+ nss_core1_add_buf_pool_size = nss_ctx->buf_sz_allocated;
+ return -EPERM;
+ }
+
+ if ((nss_core1_add_buf_pool_size >= 1) && (nss_core1_add_buf_pool_size <= NSS_N2H_MAX_BUF_POOL_SIZE)) {
+ printk("configuring additional NSS pbufs\n");
+ ret = nss_n2h_buf_pool_cfg(nss_ctx, nss_core1_add_buf_pool_size, NSS_CORE_1);
+ nss_core1_add_buf_pool_size = nss_ctx->buf_sz_allocated;
+ printk("additional pbufs of size %d got added to NSS\n", nss_ctx->buf_sz_allocated);
+ return ret;
+ }
+
+ printk("Invalid input value. should be greater than 1 and less than %d\n", NSS_N2H_MAX_BUF_POOL_SIZE);
+ return -EINVAL;
+}
+
+/*
* nss_coredump_handler()
* Send Signal To Coredump NSS Cores
*/
@@ -563,6 +709,34 @@
.proc_handler = &nss_rpscfg_handler,
},
{
+ .procname = "mitigation_core0",
+ .data = &nss_core0_mitigation_cfg,
+ .maxlen = sizeof(int),
+ .mode = 0644,
+ .proc_handler = &nss_mitigationcfg_core0_handler,
+ },
+ {
+ .procname = "mitigation_core1",
+ .data = &nss_core1_mitigation_cfg,
+ .maxlen = sizeof(int),
+ .mode = 0644,
+ .proc_handler = &nss_mitigationcfg_core1_handler,
+ },
+ {
+ .procname = "extra_pbuf_core0",
+ .data = &nss_core0_add_buf_pool_size,
+ .maxlen = sizeof(int),
+ .mode = 0644,
+ .proc_handler = &nss_buf_cfg_core0_handler,
+ },
+ {
+ .procname = "extra_pbuf_core1",
+ .data = &nss_core1_add_buf_pool_size,
+ .maxlen = sizeof(int),
+ .mode = 0644,
+ .proc_handler = &nss_buf_cfg_core1_handler,
+ },
+ {
.procname = "logbuf",
.data = &nss_ctl_logbuf,
.maxlen = sizeof(int),
@@ -641,8 +815,8 @@
*/
cmn = of_find_node_by_name(NULL, "nss-common");
if (!cmn) {
- nss_info("cannot find nss-common node\n");
- return -EFAULT;
+ nss_info_always("qca-nss-drv.ko is loaded for symbol link\n");
+ return 0;
}
if (of_address_to_resource(cmn, 0, &res_nss_fpb_base) != 0) {
@@ -759,6 +933,19 @@
*/
static void __exit nss_cleanup(void)
{
+#if (NSS_DT_SUPPORT == 1)
+ struct device_node *cmn = NULL;
+
+ /*
+ * Get reference to NSS common device node
+ */
+ cmn = of_find_node_by_name(NULL, "nss-common");
+ if (!cmn) {
+ nss_info_always("cannot find nss-common node, maybe just for symbol link\n");
+ return;
+ }
+#endif
+
nss_info("Exit NSS driver");
if (nss_dev_header)
diff --git a/nss_ipv4.c b/nss_ipv4.c
index de99ece..6c73c7c 100644
--- a/nss_ipv4.c
+++ b/nss_ipv4.c
@@ -54,6 +54,27 @@
}
/*
+ * nss_ipv4_driver_conn_sync_many_update()
+ * Update driver specific information from the conn_sync_many messsage.
+ */
+static void nss_ipv4_driver_conn_sync_many_update(struct nss_ctx_instance *nss_ctx, struct nss_ipv4_conn_sync_many_msg *nicsm)
+{
+ int i;
+
+ /*
+ * Sanity check for the stats count
+ */
+ if (nicsm->count * sizeof(struct nss_ipv4_conn_sync) >= nicsm->size) {
+ nss_warning("%p: stats sync count %u exceeds the size of this msg %u", nss_ctx, nicsm->count, nicsm->size);
+ return;
+ }
+
+ for (i = 0; i < nicsm->count; i++) {
+ nss_ipv4_driver_conn_sync_update(nss_ctx, &nicsm->conn_sync[i]);
+ }
+}
+
+/*
* nss_ipv4_driver_node_sync_update)
* Update driver specific information from the messsage.
*/
@@ -138,6 +159,13 @@
*/
nss_ipv4_driver_conn_sync_update(nss_ctx, &nim->msg.conn_stats);
break;
+
+ case NSS_IPV4_TX_CONN_STATS_SYNC_MANY_MSG:
+ /*
+ * Update driver statistics on connection sync many.
+ */
+ nss_ipv4_driver_conn_sync_many_update(nss_ctx, &nim->msg.conn_stats_many);
+ break;
}
/*
@@ -164,10 +192,10 @@
}
/*
- * nss_ipv4_tx()
- * Transmit an ipv4 message to the FW.
+ * nss_ipv4_tx_with_size()
+ * Transmit an ipv4 message to the FW with a specified size.
*/
-nss_tx_status_t nss_ipv4_tx(struct nss_ctx_instance *nss_ctx, struct nss_ipv4_msg *nim)
+nss_tx_status_t nss_ipv4_tx_with_size(struct nss_ctx_instance *nss_ctx, struct nss_ipv4_msg *nim, uint32_t size)
{
struct nss_ipv4_msg *nim2;
struct nss_cmn_msg *ncm = &nim->cm;
@@ -198,7 +226,12 @@
return NSS_TX_FAILURE;
}
- nbuf = dev_alloc_skb(NSS_NBUF_PAYLOAD_SIZE);
+ if(size > PAGE_SIZE) {
+ nss_warning("%p: tx request size too large: %u", nss_ctx, size);
+ return NSS_TX_FAILURE;
+ }
+
+ nbuf = dev_alloc_skb(size);
if (unlikely(!nbuf)) {
NSS_PKT_STATS_INCREMENT(nss_ctx, &nss_ctx->nss_top->stats_drv[NSS_STATS_DRV_NBUF_ALLOC_FAILS]);
nss_warning("%p: msg dropped as command allocation failed", nss_ctx);
@@ -226,6 +259,15 @@
}
/*
+ * nss_ipv4_tx()
+ * Transmit an ipv4 message to the FW.
+ */
+nss_tx_status_t nss_ipv4_tx(struct nss_ctx_instance *nss_ctx, struct nss_ipv4_msg *nim)
+{
+ return nss_ipv4_tx_with_size(nss_ctx, nim, NSS_NBUF_PAYLOAD_SIZE);
+}
+
+/*
**********************************
Register/Unregister/Miscellaneous APIs
**********************************
@@ -487,6 +529,7 @@
}
EXPORT_SYMBOL(nss_ipv4_tx);
+EXPORT_SYMBOL(nss_ipv4_tx_with_size);
EXPORT_SYMBOL(nss_ipv4_notify_register);
EXPORT_SYMBOL(nss_ipv4_notify_unregister);
EXPORT_SYMBOL(nss_ipv4_get_mgr);
diff --git a/nss_ipv6.c b/nss_ipv6.c
index 16067a4..ffd2032 100644
--- a/nss_ipv6.c
+++ b/nss_ipv6.c
@@ -53,6 +53,27 @@
}
/*
+ * nss_ipv6_driver_conn_sync_many_update()
+ * Update driver specific information from the conn_sync_many messsage.
+ */
+static void nss_ipv6_driver_conn_sync_many_update(struct nss_ctx_instance *nss_ctx, struct nss_ipv6_conn_sync_many_msg *nicsm)
+{
+ uint32_t i;
+
+ /*
+ * Sanity check for the stats count
+ */
+ if (nicsm->count * sizeof(struct nss_ipv6_conn_sync) >= nicsm->size) {
+ nss_warning("%p: stats sync count %u exceeds the size of this msg %u", nss_ctx, nicsm->count, nicsm->size);
+ return;
+ }
+
+ for (i = 0; i < nicsm->count; i++) {
+ nss_ipv6_driver_conn_sync_update(nss_ctx, &nicsm->conn_sync[i]);
+ }
+}
+
+/*
* nss_ipv6_driver_node_sync_update)
* Update driver specific information from the messsage.
*/
@@ -141,6 +162,13 @@
*/
nss_ipv6_driver_conn_sync_update(nss_ctx, &nim->msg.conn_stats);
break;
+
+ case NSS_IPV6_TX_CONN_STATS_SYNC_MANY_MSG:
+ /*
+ * Update driver statistics on connection sync many.
+ */
+ nss_ipv6_driver_conn_sync_many_update(nss_ctx, &nim->msg.conn_stats_many);
+ break;
}
/*
@@ -167,10 +195,10 @@
}
/*
- * nss_ipv6_tx()
- * Transmit an ipv6 message to the FW.
+ * nss_ipv6_tx_with_size()
+ * Transmit an ipv6 message to the FW with a specified size.
*/
-nss_tx_status_t nss_ipv6_tx(struct nss_ctx_instance *nss_ctx, struct nss_ipv6_msg *nim)
+nss_tx_status_t nss_ipv6_tx_with_size(struct nss_ctx_instance *nss_ctx, struct nss_ipv6_msg *nim, uint32_t size)
{
struct nss_ipv6_msg *nim2;
struct nss_cmn_msg *ncm = &nim->cm;
@@ -201,7 +229,12 @@
return NSS_TX_FAILURE;
}
- nbuf = dev_alloc_skb(NSS_NBUF_PAYLOAD_SIZE);
+ if(size > PAGE_SIZE) {
+ nss_warning("%p: tx request size too large: %u", nss_ctx, size);
+ return NSS_TX_FAILURE;
+ }
+
+ nbuf = dev_alloc_skb(size);
if (unlikely(!nbuf)) {
NSS_PKT_STATS_INCREMENT(nss_ctx, &nss_ctx->nss_top->stats_drv[NSS_STATS_DRV_NBUF_ALLOC_FAILS]);
nss_warning("%p: msg dropped as command allocation failed", nss_ctx);
@@ -229,6 +262,15 @@
}
/*
+ * nss_ipv6_tx()
+ * Transmit an ipv4 message to the FW.
+ */
+nss_tx_status_t nss_ipv6_tx(struct nss_ctx_instance *nss_ctx, struct nss_ipv6_msg *nim)
+{
+ return nss_ipv6_tx_with_size(nss_ctx, nim, NSS_NBUF_PAYLOAD_SIZE);
+}
+
+/*
**********************************
Register/Unregister/Miscellaneous APIs
**********************************
@@ -487,6 +529,7 @@
}
EXPORT_SYMBOL(nss_ipv6_tx);
+EXPORT_SYMBOL(nss_ipv6_tx_with_size);
EXPORT_SYMBOL(nss_ipv6_notify_register);
EXPORT_SYMBOL(nss_ipv6_notify_unregister);
EXPORT_SYMBOL(nss_ipv6_get_mgr);
diff --git a/nss_n2h.c b/nss_n2h.c
index ca87dbd..486a41b 100755
--- a/nss_n2h.c
+++ b/nss_n2h.c
@@ -20,19 +20,14 @@
*/
#include "nss_tx_rx_common.h"
+#include <asm/cacheflush.h>
-#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;
@@ -42,6 +37,8 @@
static struct nss_n2h_cfg_pvt nss_n2h_nepbcfgp[NSS_MAX_CORES];
static struct nss_n2h_registered_data nss_n2h_rd[NSS_MAX_CORES];
static struct nss_n2h_cfg_pvt nss_n2h_rcp;
+static struct nss_n2h_cfg_pvt nss_n2h_mitigationcp[NSS_CORE_MAX];
+static struct nss_n2h_cfg_pvt nss_n2h_bufcp[NSS_CORE_MAX];
/*
* nss_n2h_stats_sync()
@@ -103,6 +100,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);
}
@@ -132,6 +134,10 @@
nss_info("NSS N2H rps_en %d \n",nnm->msg.rps_cfg.enable);
break;
+ case NSS_TX_METADATA_TYPE_N2H_MITIGATION_CFG:
+ nss_info("NSS N2H mitigation_dis %d \n",nnm->msg.mitigation_cfg.enable);
+ break;
+
case NSS_TX_METADATA_TYPE_N2H_EMPTY_POOL_BUF_CFG:
nss_info("%p: empty pool buf cfg response from FW", nss_ctx);
break;
@@ -209,43 +215,157 @@
}
/*
- * nss_n2h_empty_pool_buf_cfg_core1_callback()
- * call back function for the n2h connection configuration handler
+ * nss_n2h_mitigation_cfg_callback()
+ * call back function for mitigation configuration
*/
-static void nss_n2h_empty_pool_buf_cfg_callback(void *app_data,
- struct nss_n2h_msg *nnm)
+static void nss_n2h_mitigation_cfg_callback(void *app_data, struct nss_n2h_msg *nnm)
{
int core_num = (int)app_data;
+ struct nss_top_instance *nss_top = &nss_top_main;
+ struct nss_ctx_instance *nss_ctx = &nss_top->nss[core_num];
+
+ if (nnm->cm.response != NSS_CMN_RESPONSE_ACK) {
+
+ /*
+ * Error, hence we are not updating the nss_n2h_mitigate_en
+ */
+ nss_n2h_mitigationcp[core_num].response = NSS_FAILURE;
+ complete(&nss_n2h_mitigationcp[core_num].complete);
+ nss_warning("core%d: MITIGATION configuration failed : %d\n", core_num, nnm->cm.error);
+ return;
+ }
+
+ nss_info("core%d: MITIGATION configuration succeeded: %d\n", core_num, nnm->cm.error);
+
+ nss_ctx->n2h_mitigate_en = nnm->msg.mitigation_cfg.enable;
+ nss_n2h_mitigationcp[core_num].response = NSS_SUCCESS;
+ complete(&nss_n2h_mitigationcp[core_num].complete);
+}
+
+/*
+ * nss_n2h_buf_cfg_callback()
+ * call back function for pbuf configuration
+ */
+static void nss_n2h_bufs_cfg_callback(void *app_data, struct nss_n2h_msg *nnm)
+{
+ int core_num = (int)app_data;
+ unsigned int allocated_sz;
+
+ struct nss_top_instance *nss_top = &nss_top_main;
+ struct nss_ctx_instance *nss_ctx = &nss_top->nss[core_num];
+
+ if (nnm->cm.response != NSS_CMN_RESPONSE_ACK) {
+ nss_n2h_bufcp[core_num].response = NSS_FAILURE;
+ nss_warning("core%d: buf configuration failed : %d\n", core_num, nnm->cm.error);
+ goto done;
+ }
+
+ nss_info("core%d: buf configuration succeeded: %d\n", core_num, nnm->cm.error);
+
+ allocated_sz = nnm->msg.buf_pool.nss_buf_page_size * nnm->msg.buf_pool.nss_buf_num_pages;
+ nss_ctx->buf_sz_allocated += allocated_sz;
+
+ nss_n2h_bufcp[core_num].response = NSS_SUCCESS;
+
+done:
+ complete(&nss_n2h_bufcp[core_num].complete);
+}
+
+/*
+ * nss_n2h_payload_stats_callback()
+ * It gets called response to payload accounting.
+ */
+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 +382,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 +417,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 +425,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 +433,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 +457,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 +627,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 +639,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]);
}
/*
@@ -443,20 +725,188 @@
return NSS_SUCCESS;
}
+/*
+ * nss_n2h_mitigation_cfg()
+ * Send Message to NSS to disable MITIGATION.
+ */
+nss_tx_status_t nss_n2h_mitigation_cfg(struct nss_ctx_instance *nss_ctx, int enable_mitigation, nss_core_id_t core_num)
+{
+ struct nss_n2h_msg nnm;
+ struct nss_n2h_mitigation *mitigation_cfg;
+ nss_tx_status_t nss_tx_status;
+ int ret;
+
+ nss_assert(core_num < NSS_CORE_MAX);
+
+ down(&nss_n2h_mitigationcp[core_num].sem);
+ nss_n2h_msg_init(&nnm, NSS_N2H_INTERFACE, NSS_TX_METADATA_TYPE_N2H_MITIGATION_CFG,
+ sizeof(struct nss_n2h_mitigation),
+ nss_n2h_mitigation_cfg_callback,
+ (void *)core_num);
+
+ mitigation_cfg = &nnm.msg.mitigation_cfg;
+ mitigation_cfg->enable = enable_mitigation;
+
+ nss_tx_status = nss_n2h_tx_msg(nss_ctx, &nnm);
+
+ if (nss_tx_status != NSS_TX_SUCCESS) {
+ nss_warning("%p: nss_tx error setting mitigation\n", nss_ctx);
+ goto failure;
+ }
+
+ /*
+ * Blocking call, wait till we get ACK for this msg.
+ */
+ ret = wait_for_completion_timeout(&nss_n2h_mitigationcp[core_num].complete, msecs_to_jiffies(NSS_CONN_CFG_TIMEOUT));
+ if (ret == 0) {
+ nss_warning("%p: Waiting for ack timed out\n", nss_ctx);
+ goto failure;
+ }
+
+ /*
+ * ACK/NACK received from NSS FW
+ */
+ if (NSS_FAILURE == nss_n2h_mitigationcp[core_num].response) {
+ goto failure;
+ }
+
+ up(&nss_n2h_mitigationcp[core_num].sem);
+ return NSS_SUCCESS;
+
+failure:
+ up(&nss_n2h_mitigationcp[core_num].sem);
+ return NSS_FAILURE;
+}
+
+static inline void nss_n2h_buf_pool_free(struct nss_n2h_buf_pool *buf_pool)
+{
+ int page_count;
+ for (page_count = 0; page_count < buf_pool->nss_buf_num_pages; page_count++) {
+ kfree(buf_pool->nss_buf_pool_vaddr[page_count]);
+ }
+}
+
+/*
+ * nss_n2h_buf_cfg()
+ * Send Message to NSS to enable pbufs.
+ */
+nss_tx_status_t nss_n2h_buf_pool_cfg(struct nss_ctx_instance *nss_ctx,
+ int buf_pool_size, nss_core_id_t core_num)
+{
+ static struct nss_n2h_msg nnm;
+ struct nss_n2h_buf_pool *buf_pool;
+ nss_tx_status_t nss_tx_status;
+ int ret;
+ int page_count;
+ int num_pages = ALIGN(buf_pool_size, PAGE_SIZE)/PAGE_SIZE;
+
+ nss_assert(core_num < NSS_CORE_MAX);
+
+ nss_n2h_msg_init(&nnm, NSS_N2H_INTERFACE, NSS_METADATA_TYPE_N2H_ADD_BUF_POOL,
+ sizeof(struct nss_n2h_buf_pool),
+ nss_n2h_bufs_cfg_callback,
+ (void *)core_num);
+
+ do {
+
+ down(&nss_n2h_bufcp[core_num].sem);
+
+ buf_pool = &nnm.msg.buf_pool;
+ buf_pool->nss_buf_page_size = PAGE_SIZE;
+
+ for (page_count = 0; page_count < MAX_PAGES_PER_MSG && num_pages; page_count++, num_pages--) {
+
+ void *kern_addr = kzalloc(PAGE_SIZE, GFP_ATOMIC);
+ if (!kern_addr) {
+ BUG_ON(!page_count);
+ break;
+ }
+ BUG_ON((long unsigned int)kern_addr % PAGE_SIZE);
+
+ buf_pool->nss_buf_pool_vaddr[page_count] = kern_addr;
+ buf_pool->nss_buf_pool_addr[page_count] = dma_map_single(NULL, kern_addr, PAGE_SIZE, DMA_TO_DEVICE);
+ }
+
+ buf_pool->nss_buf_num_pages = page_count;
+ nss_tx_status = nss_n2h_tx_msg(nss_ctx, &nnm);
+ if (nss_tx_status != NSS_TX_SUCCESS) {
+
+ nss_n2h_buf_pool_free(buf_pool);
+ nss_warning("%p: nss_tx error setting pbuf\n", nss_ctx);
+ goto failure;
+ }
+
+ /*
+ * Blocking call, wait till we get ACK for this msg.
+ */
+ ret = wait_for_completion_timeout(&nss_n2h_bufcp[core_num].complete, msecs_to_jiffies(NSS_CONN_CFG_TIMEOUT));
+ if (ret == 0) {
+ nss_warning("%p: Waiting for ack timed out\n", nss_ctx);
+ goto failure;
+ }
+
+ /*
+ * ACK/NACK received from NSS FW
+ */
+ if (NSS_FAILURE == nss_n2h_bufcp[core_num].response) {
+
+ nss_n2h_buf_pool_free(buf_pool);
+ goto failure;
+ }
+
+ up(&nss_n2h_bufcp[core_num].sem);
+ } while(num_pages);
+
+ return NSS_SUCCESS;
+failure:
+ up(&nss_n2h_bufcp[core_num].sem);
+ return NSS_FAILURE;
+}
+
+
+
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 +968,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];
}
/*
@@ -636,6 +1096,29 @@
sema_init(&nss_n2h_rcp.sem, 1);
init_completion(&nss_n2h_rcp.complete);
+ /*
+ * MITIGATION sema init for core0
+ */
+ sema_init(&nss_n2h_mitigationcp[NSS_CORE_0].sem, 1);
+ init_completion(&nss_n2h_mitigationcp[NSS_CORE_0].complete);
+
+ /*
+ * MITIGATION sema init for core1
+ */
+ sema_init(&nss_n2h_mitigationcp[NSS_CORE_1].sem, 1);
+ init_completion(&nss_n2h_mitigationcp[NSS_CORE_1].complete);
+
+ /*
+ * PBUF addition sema init for core0
+ */
+ sema_init(&nss_n2h_bufcp[NSS_CORE_0].sem, 1);
+ init_completion(&nss_n2h_bufcp[NSS_CORE_0].complete);
+
+ /*
+ * PBUF addition sema init for core1
+ */
+ sema_init(&nss_n2h_bufcp[NSS_CORE_1].sem, 1);
+ init_completion(&nss_n2h_bufcp[NSS_CORE_1].complete);
nss_n2h_notify_register(NSS_CORE_0, NULL, NULL);
nss_n2h_notify_register(NSS_CORE_1, NULL, NULL);
diff --git a/nss_phys_if.c b/nss_phys_if.c
index 6da204d..b8af1c2 100644
--- a/nss_phys_if.c
+++ b/nss_phys_if.c
@@ -600,6 +600,13 @@
nss_ctx->max_buf_size = ((mtu_sz + ETH_HLEN + SMP_CACHE_BYTES - 1) & ~(SMP_CACHE_BYTES - 1)) + NSS_NBUF_PAD_EXTRA;
+ /*
+ * max_buf_size should not be lesser than NSS_NBUF_PAYLOAD_SIZE
+ */
+ if (nss_ctx->max_buf_size < NSS_NBUF_PAYLOAD_SIZE) {
+ nss_ctx->max_buf_size = NSS_NBUF_PAYLOAD_SIZE;
+ }
+
nss_info("Current mtu:%u mtu_sz:%u max_buf_size:%d\n", mtu, mtu_sz, nss_ctx->max_buf_size);
if (mtu_sz > nss_ctx->nss_top->prev_mtu_sz) {
diff --git a/nss_pm.h b/nss_pm.h
index 2a2cb8d..1b2d27e 100644
--- a/nss_pm.h
+++ b/nss_pm.h
@@ -115,8 +115,8 @@
{\
.src = MSM_BUS_MASTER_NSS_CRYPTO5_0, \
.dst = MSM_BUS_SLAVE_EBI_CH0, \
- .ab = (_data_bw) * 16 * 1000000ULL, \
- .ib = (_data_bw) * 16 * 1000000ULL, \
+ .ab = 0, \
+ .ib = 0, \
}, \
{ \
.src = MSM_BUS_MASTER_NSS_CRYPTO5_0, \
diff --git a/nss_stats.c b/nss_stats.c
index d5ed3e5..b5f1373 100644
--- a/nss_stats.c
+++ b/nss_stats.c
@@ -150,6 +150,7 @@
"h2n_data_bytes",
"n2h_data_packets",
"n2h_data_bytes",
+ "n2h_tot_payloads",
};
/*
diff --git a/nss_tx_rx_virt_if.c b/nss_tx_rx_virt_if.c
index bd59d4e..87e7e6d 100644
--- a/nss_tx_rx_virt_if.c
+++ b/nss_tx_rx_virt_if.c
@@ -119,7 +119,7 @@
* to the same callback/app_data.
*/
if (ncm->response == NSS_CMM_RESPONSE_NOTIFY) {
- ncm->cb = (uint32_t)nss_ctx->nss_top->virt_if_msg_callback[ncm->interface];
+ ncm->cb = (uint32_t)nss_ctx->nss_top->if_rx_msg_callback[ncm->interface];
ncm->app_data = (uint32_t)nss_ctx->nss_top->subsys_dp_register[ncm->interface].ndev;
}
@@ -180,6 +180,8 @@
nss_top_main.subsys_dp_register[if_num].app_data = NULL;
nss_top_main.subsys_dp_register[if_num].features = (uint32_t)netdev->features;
+ nss_top_main.if_rx_msg_callback[if_num] = NULL;
+
return ctx;
}
diff --git a/nss_virt_if.c b/nss_virt_if.c
index 92b80e8..8a14d63 100644
--- a/nss_virt_if.c
+++ b/nss_virt_if.c
@@ -117,7 +117,7 @@
* to the same callback/app_data.
*/
if (ncm->response == NSS_CMM_RESPONSE_NOTIFY) {
- ncm->cb = (uint32_t)nss_ctx->nss_top->virt_if_msg_callback[ncm->interface];
+ ncm->cb = (uint32_t)nss_ctx->nss_top->if_rx_msg_callback[ncm->interface];
ncm->app_data = (uint32_t)nss_ctx->nss_top->subsys_dp_register[ncm->interface].ndev;
}
@@ -887,6 +887,8 @@
nss_top_main.subsys_dp_register[if_num].cb = data_callback;
nss_top_main.subsys_dp_register[if_num].app_data = NULL;
nss_top_main.subsys_dp_register[if_num].features = (uint32_t)netdev->features;
+
+ nss_top_main.if_rx_msg_callback[if_num] = NULL;
}
EXPORT_SYMBOL(nss_virt_if_register);