[qca-nss-drv] add support for vlan configuration
Enables sending of configuration messages to vlan dynamic interface
in NSS. This includes messages such as assign vsi/unassign vsi/add tag
/set mtu/set mac_addr.
Change-Id: Ie5b15b1512bc34f8a190d8aaa8c72459686c39fd
Signed-off-by: Stephen Wang <wstephen@codeaurora.org>
diff --git a/Makefile b/Makefile
index f35dbaf..14ce906 100644
--- a/Makefile
+++ b/Makefile
@@ -50,6 +50,7 @@
nss_trustsec_tx.o \
nss_tunipip6.o \
nss_virt_if.o \
+ nss_vlan.o \
nss_wifi.o \
nss_wifi_if.o \
nss_wifi_vdev.o
diff --git a/exports/nss_api_if.h b/exports/nss_api_if.h
index 433883a..7f0ed1a 100644
--- a/exports/nss_api_if.h
+++ b/exports/nss_api_if.h
@@ -1,6 +1,6 @@
/*
**************************************************************************
- * Copyright (c) 2013-2016, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-2017, The Linux Foundation. All rights reserved.
* Permission to use, copy, modify, and/or distribute this software for
* any purpose with or without fee is hereby granted, provided that the
* above copyright notice and this permission notice appear in all copies.
@@ -68,6 +68,7 @@
#include "nss_bridge.h"
#include "nss_ppe.h"
#include "nss_trustsec_tx.h"
+#include "nss_vlan.h"
/*
* Interface numbers are reserved in the
@@ -95,7 +96,7 @@
#define NSS_MAX_PHYSICAL_INTERFACES 8
#define NSS_MAX_VIRTUAL_INTERFACES 16
#define NSS_MAX_TUNNEL_INTERFACES 4
-#define NSS_MAX_SPECIAL_INTERFACES 44
+#define NSS_MAX_SPECIAL_INTERFACES 45
#define NSS_MAX_WIFI_RADIO_INTERFACES 3
/**
@@ -154,6 +155,7 @@
#define NSS_EDMA_INTERFACE (NSS_SPECIAL_IF_START + 41) /* Special EDMA interface */
#define NSS_GRE_TUNNEL_INTERFACE (NSS_SPECIAL_IF_START + 42) /* Special NSS GRE TUNNEL interface */
#define NSS_TRUSTSEC_TX_INTERFACE (NSS_SPECIAL_IF_START + 43) /* Special TrustSec TX interface */
+#define NSS_VLAN_INTERFACE (NSS_SPECIAL_IF_START + 44) /* Special VLAN interface */
/**
* This macro converts format for IPv6 address (from Linux to NSS)
diff --git a/exports/nss_dynamic_interface.h b/exports/nss_dynamic_interface.h
index 164b56a..9fce590 100644
--- a/exports/nss_dynamic_interface.h
+++ b/exports/nss_dynamic_interface.h
@@ -1,6 +1,6 @@
/*
**************************************************************************
- * Copyright (c) 2014-2016 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2014-2017 The Linux Foundation. All rights reserved.
* Permission to use, copy, modify, and/or distribute this software for
* any purpose with or without fee is hereby granted, provided that the
* above copyright notice and this permission notice appear in all copies.
@@ -45,6 +45,7 @@
NSS_DYNAMIC_INTERFACE_TYPE_MAP_T, /* MAP-T Interface Type */
NSS_DYNAMIC_INTERFACE_TYPE_GRE_TUNNEL, /* GRE Tunnel Interface Type */
NSS_DYNAMIC_INTERFACE_TYPE_BRIDGE, /* Bridge Interface Type */
+ NSS_DYNAMIC_INTERFACE_TYPE_VLAN, /* VLAN Interface Type */
NSS_DYNAMIC_INTERFACE_TYPE_MAX
};
diff --git a/exports/nss_vlan.h b/exports/nss_vlan.h
new file mode 100644
index 0000000..63f8c02
--- /dev/null
+++ b/exports/nss_vlan.h
@@ -0,0 +1,207 @@
+/*
+ **************************************************************************
+ * Copyright (c) 2017, The Linux Foundation. All rights reserved.
+ * Permission to use, copy, modify, and/or distribute this software for
+ * any purpose with or without fee is hereby granted, provided that the
+ * above copyright notice and this permission notice appear in all copies.
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+ * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ **************************************************************************
+ */
+
+/*
+ * nss_vlan.h
+ * NSS TO HLOS interface definitions.
+ */
+
+#ifndef __NSS_VLAN_H
+#define __NSS_VLAN_H
+
+/**
+ * Vlan message types
+ */
+enum nss_vlan_msg_types {
+ NSS_VLAN_MSG_ADD_TAG = NSS_IF_MAX_MSG_TYPES + 1,
+ /**< Msg to add vlan tag on physical interface */
+ NSS_VLAN_MSG_TYPE_MAX, /**< Max message types */
+};
+
+/**
+ * Vlan error types
+ */
+enum nss_vlan_error_types {
+ NSS_VLAN_ERROR_UNKNOWN_MSG = NSS_IF_ERROR_TYPE_MAX + 1,
+ /**< Message type is unknown */
+ NSS_VLAN_ERROR_TYPE_MAX, /**< Max message types */
+};
+
+#define NSS_VLAN_TYPE_SINGLE 0
+#define NSS_VLAN_TYPE_DOUBLE 1
+
+/**
+ * VLAN message - add vlan tag
+ */
+struct nss_vlan_msg_add_tag {
+ uint32_t vlan_tag; /* VLAN tag information */
+ uint32_t next_hop; /* Parent interface */
+ uint32_t if_num; /* Real Physical Interface */
+};
+
+/**
+ * Message structure to send/receive vlan messages
+ */
+struct nss_vlan_msg {
+ struct nss_cmn_msg cm; /**< Message Header */
+ union {
+ union nss_if_msgs if_msg; /**< nss_if base messages */
+ struct nss_vlan_msg_add_tag add_tag; /**< Vlan add tag message */
+ } msg;
+};
+
+/**
+ * @brief Send vlan messages
+ *
+ * @param nss_ctx NSS context
+ * @param msg NSS vlan message
+ *
+ * @return nss_tx_status_t Tx status
+ */
+nss_tx_status_t nss_vlan_tx_msg(struct nss_ctx_instance *nss_ctx, struct nss_vlan_msg *msg);
+
+/**
+ * @brief Send vlan messages synchronously
+ *
+ * @param nss_ctx NSS context
+ * @param msg NSS vlan message
+ *
+ * @return nss_tx_status_t Tx status
+ */
+nss_tx_status_t nss_vlan_tx_msg_sync(struct nss_ctx_instance *nss_ctx, struct nss_vlan_msg *msg);
+
+/**
+ * @brief Initialize vlan msg
+ *
+ * @param nss_vlan_msg
+ * @param if_num Interface number
+ * @param type Message type
+ * @param len Message length
+ * @param cb message callback
+ * @param app_data
+ *
+ * @return None
+ */
+void nss_vlan_msg_init(struct nss_vlan_msg *ncm, uint16_t if_num, uint32_t type, uint32_t len, void *cb, void *app_data);
+
+/**
+ * @brief Get the vlan context used in the nss_vlan_tx
+ *
+ * @return struct nss_ctx_instance *NSS context
+ */
+struct nss_ctx_instance *nss_vlan_get_context(void);
+
+/**
+ * @brief Callback when vlan data is received
+ *
+ * @param netdevice of vlan interface
+ * @param skb Pointer to data buffer
+ * @param napi pointer
+ *
+ * @return void
+ */
+typedef void (*nss_vlan_callback_t)(struct net_device *netdev, struct sk_buff *skb, struct napi_struct *napi);
+
+/**
+ * @brief Callback to receive vlan messages
+ *
+ * @param app_data Application context of the message
+ * @param msg Message data
+ *
+ * @return void
+ */
+typedef void (*nss_vlan_msg_callback_t)(void *app_data, struct nss_vlan_msg *msg);
+
+/**
+ * @brief Register to send/receive vlan messages to NSS
+ *
+ * @param if_num NSS interface number
+ * @param vlan_data_callback Callback for vlan data
+ * @param netdev netdevice associated with the vlan interface
+ * @param features denotes the skb types supported by this interface
+ *
+ * @return nss_ctx_instance* NSS context
+ */
+struct nss_ctx_instance *nss_register_vlan_if(uint32_t if_num, nss_vlan_callback_t vlan_data_callback,
+ struct net_device *netdev, uint32_t features, void *app_ctx);
+
+/**
+ * @brief Unregister vlan interface with NSS
+ *
+ * @return void
+ */
+void nss_unregister_vlan_if(uint32_t if_num);
+
+/*
+ * @brief Send vlan set mtu message
+ *
+ * @param vlan_if_num NSS dynamic interface
+ * @param mtu MTU value to be set
+ *
+ * @return nss_tx_status_t Tx status
+ */
+nss_tx_status_t nss_vlan_tx_set_mtu_msg(uint32_t vlan_if_num, uint32_t mtu);
+
+/**
+ * @brief Send vlan set mac address message
+ *
+ * @param vlan_if_num NSS dynamic interface
+ * @param addr MAC addr to be set
+ *
+ * @return nss_tx_status_t Tx status
+ */
+nss_tx_status_t nss_vlan_tx_set_mac_addr_msg(uint32_t vlan_if_num, uint8_t *addr);
+
+/**
+ * @brief Send vlan attach VSI message
+ *
+ * @param vlan_if_num NSS dynamic interface
+ * @param vsi PPE VSI to attach
+ *
+ * @return nss_tx_status_t Tx status
+ */
+nss_tx_status_t nss_vlan_tx_vsi_attach_msg(uint32_t vlan_if_num, uint32_t vsi);
+
+/**
+ * @brief Send vlan detach VSI message
+ *
+ * @param vlan_if_num NSS dynamic interface
+ * @param vsi PPE VSI to detach
+ *
+ * @return nss_tx_status_t Tx status
+ */
+nss_tx_status_t nss_vlan_tx_vsi_detach_msg(uint32_t vlan_if_num, uint32_t vsi);
+
+/**
+ * @brief Send vlan add tag message
+ *
+ * @param vlan_if_num NSS dynamic interface
+ * @param vlan_tag vlan tag info
+ * @param next_hop parent interface
+ * @param physical_dev physical port which to add vlan tag
+ *
+ * @return nss_tx_status_t Tx status
+ */
+nss_tx_status_t nss_vlan_tx_add_tag_msg(uint32_t vlan_if_num, uint32_t vlan_tag, uint32_t next_hop, uint32_t physical_dev);
+
+/**
+ * @brief Initialize vlan
+ *
+ * @return None
+ */
+void nss_vlan_register_handler(void);
+
+#endif /* __NSS_VLAN_H */
diff --git a/nss_core.h b/nss_core.h
index e396f1f..64104f1 100644
--- a/nss_core.h
+++ b/nss_core.h
@@ -998,6 +998,7 @@
uint8_t edma_handler_id;
uint8_t bridge_handler_id;
uint8_t trustsec_tx_handler_id;
+ uint8_t vlan_handler_id;
/* subsystem registration data */
struct nss_subsystem_dataplane_register subsys_dp_register[NSS_MAX_NET_INTERFACES];
@@ -1052,6 +1053,8 @@
/* EDMA callback */
nss_bridge_msg_callback_t bridge_callback;
/* Bridge callback */
+ nss_vlan_msg_callback_t vlan_callback;
+ /* Vlan callback */
uint32_t dynamic_interface_table[NSS_DYNAMIC_INTERFACE_TYPE_MAX];
/*
@@ -1069,6 +1072,7 @@
void *oam_ctx; /* oam context */
void *edma_ctx; /* edma context */
void *bridge_ctx; /* Bridge context */
+ void *vlan_ctx; /* Vlan context */
/*
* Statistics for various interfaces
@@ -1292,6 +1296,8 @@
/* Does this core handle WIFI OFFLOAD? */
enum nss_feature_enabled bridge_enabled;
/* Does this core handle bridge configuration */
+ enum nss_feature_enabled vlan_enabled;
+ /* Does this core handle vlan configuration */
};
#endif
diff --git a/nss_hal/nss_hal.c b/nss_hal/nss_hal.c
index 8adade5..2a7271b 100644
--- a/nss_hal/nss_hal.c
+++ b/nss_hal/nss_hal.c
@@ -123,6 +123,7 @@
npd->wlanredirect_enabled = of_property_read_bool(np, "qcom,wlanredirect-enabled");
npd->wifioffload_enabled = of_property_read_bool(np, "qcom,wlan-dataplane-offload-enabled");
npd->bridge_enabled = of_property_read_bool(np, "qcom,bridge-enabled");
+ npd->vlan_enabled = of_property_read_bool(np, "qcom,vlan-enabled");
}
/*
@@ -489,6 +490,12 @@
nss_bridge_init();
}
+ if (npd->vlan_enabled == NSS_FEATURE_ENABLED) {
+ nss_top->vlan_handler_id = nss_dev->id;
+ nss_top->dynamic_interface_table[NSS_DYNAMIC_INTERFACE_TYPE_VLAN] = nss_dev->id;
+ nss_vlan_register_handler();
+ }
+
if (nss_ctx->id == 0) {
#if (NSS_FREQ_SCALE_SUPPORT == 1)
nss_freq_register_handler();
diff --git a/nss_vlan.c b/nss_vlan.c
new file mode 100644
index 0000000..7001f24
--- /dev/null
+++ b/nss_vlan.c
@@ -0,0 +1,437 @@
+/*
+ **************************************************************************
+ * Copyright (c) 2017, The Linux Foundation. All rights reserved.
+ * Permission to use, copy, modify, and/or distribute this software for
+ * any purpose with or without fee is hereby granted, provided that the
+ * above copyright notice and this permission notice appear in all copies.
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+ * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ **************************************************************************
+ */
+
+#include "nss_tx_rx_common.h"
+
+#define NSS_VLAN_TX_TIMEOUT 1000 /* 1 Second */
+
+/*
+ * Private data structure
+ */
+static struct nss_vlan_pvt {
+ struct semaphore sem;
+ struct completion complete;
+ int response;
+ void *cb;
+ void *app_data;
+} vlan_pvt;
+
+/*
+ * nss_vlan_verify_if_num()
+ * Verify if_num passed to us.
+ */
+static bool nss_vlan_verify_if_num(uint32_t if_num)
+{
+ if (!nss_is_dynamic_interface(if_num)) {
+ return false;
+ }
+
+ if (nss_dynamic_interface_get_type(if_num) != NSS_DYNAMIC_INTERFACE_TYPE_VLAN) {
+ return false;
+ }
+
+ return true;
+}
+
+/*
+ * nss_vlan_handler()
+ * Handle NSS -> HLOS messages for vlan
+ */
+static void nss_vlan_handler(struct nss_ctx_instance *nss_ctx, struct nss_cmn_msg *ncm, void *app_data)
+{
+ struct nss_vlan_msg *nvm = (struct nss_vlan_msg *)ncm;
+ nss_vlan_msg_callback_t cb;
+
+ nss_assert(nss_vlan_verify_if_num(ncm->interface));
+
+ /*
+ * Is this a valid request/response packet?
+ */
+ if (ncm->type >= NSS_VLAN_MSG_TYPE_MAX) {
+ nss_warning("%p: received invalid message %d for vlan interface", nss_ctx, ncm->type);
+ return;
+ }
+
+ if (nss_cmn_get_msg_len(ncm) > sizeof(struct nss_vlan_msg)) {
+ nss_warning("%p: length of message is greater than required: %d", nss_ctx, nss_cmn_get_msg_len(ncm));
+ return;
+ }
+
+ /*
+ * Update the callback and app_data for NOTIFY messages, vlan sends all notify messages
+ * to the same callback/app_data.
+ */
+ if (ncm->response == NSS_CMM_RESPONSE_NOTIFY) {
+ ncm->cb = (nss_ptr_t)nss_ctx->nss_top->vlan_callback;
+ ncm->app_data = (nss_ptr_t)app_data;
+ }
+
+ /*
+ * Log failures
+ */
+ nss_core_log_msg_failures(nss_ctx, ncm);
+
+ /*
+ * Do we have a call back
+ */
+ if (!ncm->cb) {
+ return;
+ }
+
+ /*
+ * callback
+ */
+ cb = (nss_vlan_msg_callback_t)ncm->cb;
+ cb((void *)ncm->app_data, nvm);
+}
+
+/*
+ * nss_vlan_callback()
+ * Callback to handle the completion of NSS->HLOS messages.
+ */
+static void nss_vlan_callback(void *app_data, struct nss_vlan_msg *nvm)
+{
+ nss_vlan_msg_callback_t callback = (nss_vlan_msg_callback_t)vlan_pvt.cb;
+ void *data = vlan_pvt.app_data;
+
+ vlan_pvt.response = NSS_TX_SUCCESS;
+ vlan_pvt.cb = NULL;
+ vlan_pvt.app_data = NULL;
+
+ if (nvm->cm.response != NSS_CMN_RESPONSE_ACK) {
+ nss_warning("vlan error response %d\n", nvm->cm.response);
+ vlan_pvt.response = nvm->cm.response;
+ }
+
+ if (callback) {
+ callback(data, nvm);
+ }
+ complete(&vlan_pvt.complete);
+}
+
+/*
+ * nss_vlan_tx_msg()
+ * Transmit a vlan message to NSSFW
+ */
+nss_tx_status_t nss_vlan_tx_msg(struct nss_ctx_instance *nss_ctx, struct nss_vlan_msg *msg)
+{
+ struct nss_vlan_msg *nm;
+ struct nss_cmn_msg *ncm = &msg->cm;
+ struct sk_buff *nbuf;
+ int32_t status;
+
+ NSS_VERIFY_CTX_MAGIC(nss_ctx);
+ if (unlikely(nss_ctx->state != NSS_CORE_STATE_INITIALIZED)) {
+ nss_warning("%p: vlan msg dropped as core not ready", nss_ctx);
+ return NSS_TX_FAILURE_NOT_READY;
+ }
+
+ /*
+ * Sanity check the message
+ */
+ if (!nss_vlan_verify_if_num(ncm->interface)) {
+ nss_warning("%p: tx request for interface that is not a vlan: %d", nss_ctx, ncm->interface);
+ return NSS_TX_FAILURE;
+ }
+
+ if (ncm->type >= NSS_VLAN_MSG_TYPE_MAX) {
+ nss_warning("%p: message type out of range: %d", nss_ctx, ncm->type);
+ return NSS_TX_FAILURE;
+ }
+
+ if (nss_cmn_get_msg_len(ncm) > sizeof(struct nss_vlan_msg)) {
+ nss_warning("%p: message length is invalid: %d", nss_ctx, nss_cmn_get_msg_len(ncm));
+ return NSS_TX_FAILURE;
+ }
+
+ nbuf = dev_alloc_skb(NSS_NBUF_PAYLOAD_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);
+ return NSS_TX_FAILURE;
+ }
+
+ /*
+ * Copy the message to our skb
+ */
+ nm = (struct nss_vlan_msg *)skb_put(nbuf, sizeof(struct nss_vlan_msg));
+ memcpy(nm, msg, sizeof(struct nss_vlan_msg));
+
+ status = nss_core_send_buffer(nss_ctx, 0, nbuf, NSS_IF_CMD_QUEUE, H2N_BUFFER_CTRL, 0);
+ if (status != NSS_CORE_STATUS_SUCCESS) {
+ dev_kfree_skb_any(nbuf);
+ nss_warning("%p: Unable to enqueue 'vlan message'", nss_ctx);
+ return NSS_TX_FAILURE;
+ }
+
+ nss_hal_send_interrupt(nss_ctx, NSS_H2N_INTR_DATA_COMMAND_QUEUE);
+
+ NSS_PKT_STATS_INCREMENT(nss_ctx, &nss_ctx->nss_top->stats_drv[NSS_STATS_DRV_TX_CMD_REQ]);
+ return NSS_TX_SUCCESS;
+}
+EXPORT_SYMBOL(nss_vlan_tx_msg);
+
+/*
+ * nss_vlan_tx_msg_sync()
+ * Transmit a vlan message to NSS firmware synchronously.
+ */
+nss_tx_status_t nss_vlan_tx_msg_sync(struct nss_ctx_instance *nss_ctx, struct nss_vlan_msg *nvm)
+{
+ nss_tx_status_t status;
+ int ret = 0;
+
+ down(&vlan_pvt.sem);
+ vlan_pvt.cb = (void *)nvm->cm.cb;
+ vlan_pvt.app_data = (void *)nvm->cm.app_data;
+
+ nvm->cm.cb = (nss_ptr_t)nss_vlan_callback;
+ nvm->cm.app_data = (nss_ptr_t)NULL;
+
+ status = nss_vlan_tx_msg(nss_ctx, nvm);
+ if (status != NSS_TX_SUCCESS) {
+ nss_warning("%p: vlan_tx_msg failed\n", nss_ctx);
+ up(&vlan_pvt.sem);
+ return status;
+ }
+
+ ret = wait_for_completion_timeout(&vlan_pvt.complete, msecs_to_jiffies(NSS_VLAN_TX_TIMEOUT));
+ if (!ret) {
+ nss_warning("%p: vlan msg tx failed due to timeout\n", nss_ctx);
+ vlan_pvt.response = NSS_TX_FAILURE;
+ }
+
+ status = vlan_pvt.response;
+ up(&vlan_pvt.sem);
+ return status;
+}
+EXPORT_SYMBOL(nss_vlan_tx_msg_sync);
+
+/*
+ * nss_vlan_get_context()
+ */
+struct nss_ctx_instance *nss_vlan_get_context(void)
+{
+ return (struct nss_ctx_instance *)&nss_top_main.nss[nss_top_main.vlan_handler_id];
+}
+EXPORT_SYMBOL(nss_vlan_get_context);
+
+/*
+ * nss_vlan_msg_init()
+ * Initialize nss_vlan_msg.
+ */
+void nss_vlan_msg_init(struct nss_vlan_msg *ncm, uint16_t if_num, uint32_t type, uint32_t len, void *cb, void *app_data)
+{
+ nss_cmn_msg_init(&ncm->cm, if_num, type, len, cb, app_data);
+}
+EXPORT_SYMBOL(nss_vlan_msg_init);
+
+/*
+ * nss_vlan_tx_change_mtu_msg
+ * API to send change mtu message to NSS FW
+ */
+nss_tx_status_t nss_vlan_tx_set_mtu_msg(uint32_t vlan_if_num, uint32_t mtu)
+{
+ struct nss_ctx_instance *nss_ctx = nss_vlan_get_context();
+ struct nss_vlan_msg nvm;
+ struct nss_if_mtu_change *nimc;
+
+ if (!nss_ctx) {
+ nss_warning("Can't get nss context\n");
+ return NSS_TX_FAILURE;
+ }
+
+ if (nss_vlan_verify_if_num(vlan_if_num) == false) {
+ nss_warning("%p: received invalid interface %d", nss_ctx, vlan_if_num);
+ return NSS_TX_FAILURE;
+ }
+
+ nss_vlan_msg_init(&nvm, vlan_if_num, NSS_IF_MTU_CHANGE,
+ sizeof(struct nss_if_mtu_change), NULL, NULL);
+
+ nimc = &nvm.msg.if_msg.mtu_change;
+ nimc->min_buf_size = (uint16_t)mtu;
+
+ return nss_vlan_tx_msg_sync(nss_ctx, &nvm);
+}
+EXPORT_SYMBOL(nss_vlan_tx_set_mtu_msg);
+
+/*
+ * nss_vlan_tx_set_mac_addr_msg
+ * API to send change mac addr message to NSS FW
+ */
+nss_tx_status_t nss_vlan_tx_set_mac_addr_msg(uint32_t vlan_if_num, uint8_t *addr)
+{
+ struct nss_ctx_instance *nss_ctx = nss_vlan_get_context();
+ struct nss_vlan_msg nvm;
+ struct nss_if_mac_address_set *nmas;
+
+ if (!nss_ctx) {
+ nss_warning("Can't get nss context\n");
+ return NSS_TX_FAILURE;
+ }
+
+ if (nss_vlan_verify_if_num(vlan_if_num) == false) {
+ nss_warning("%p: received invalid interface %d", nss_ctx, vlan_if_num);
+ return NSS_TX_FAILURE;
+ }
+
+ nss_vlan_msg_init(&nvm, vlan_if_num, NSS_IF_MAC_ADDR_SET,
+ sizeof(struct nss_if_mac_address_set), NULL, NULL);
+
+ nmas = &nvm.msg.if_msg.mac_address_set;
+ memcpy(nmas->mac_addr, addr, ETH_ALEN);
+ return nss_vlan_tx_msg_sync(nss_ctx, &nvm);
+}
+EXPORT_SYMBOL(nss_vlan_tx_set_mac_addr_msg);
+
+/*
+ * nss_vlan_tx_vsi_attach_msg
+ * API to send VSI attach message to NSS FW
+ */
+nss_tx_status_t nss_vlan_tx_vsi_attach_msg(uint32_t vlan_if_num, uint32_t vsi)
+{
+ struct nss_ctx_instance *nss_ctx = nss_vlan_get_context();
+ struct nss_vlan_msg nvm;
+
+ if (!nss_ctx) {
+ nss_warning("Can't get nss context\n");
+ return NSS_TX_FAILURE;
+ }
+
+ if (nss_vlan_verify_if_num(vlan_if_num) == false) {
+ nss_warning("%p: received invalid interface %d\n", nss_ctx, vlan_if_num);
+ return NSS_TX_FAILURE;
+ }
+
+ nvm.msg.if_msg.vsi_assign.vsi = vsi;
+ nss_vlan_msg_init(&nvm, vlan_if_num, NSS_IF_VSI_ASSIGN,
+ sizeof(struct nss_if_vsi_assign), NULL, NULL);
+
+ return nss_vlan_tx_msg_sync(nss_ctx, &nvm);
+}
+EXPORT_SYMBOL(nss_vlan_tx_vsi_attach_msg);
+
+/*
+ * nss_vlan_tx_vsi_detach_msg
+ * API to send VSI detach message to NSS FW
+ */
+nss_tx_status_t nss_vlan_tx_vsi_detach_msg(uint32_t vlan_if_num, uint32_t vsi)
+{
+ struct nss_ctx_instance *nss_ctx = nss_vlan_get_context();
+ struct nss_vlan_msg nvm;
+
+ if (!nss_ctx) {
+ nss_warning("Can't get nss context\n");
+ return NSS_TX_FAILURE;
+ }
+
+ if (nss_vlan_verify_if_num(vlan_if_num) == false) {
+ nss_warning("%p: received invalid interface %d\n", nss_ctx, vlan_if_num);
+ return NSS_TX_FAILURE;
+ }
+
+ nvm.msg.if_msg.vsi_unassign.vsi = vsi;
+ nss_vlan_msg_init(&nvm, vlan_if_num, NSS_IF_VSI_UNASSIGN,
+ sizeof(struct nss_if_vsi_unassign), NULL, NULL);
+
+ return nss_vlan_tx_msg_sync(nss_ctx, &nvm);
+}
+EXPORT_SYMBOL(nss_vlan_tx_vsi_detach_msg);
+
+/*
+ * nss_vlan_tx_add_tag_msg
+ * API to send vlan add tag message to NSS FW
+ */
+nss_tx_status_t nss_vlan_tx_add_tag_msg(uint32_t vlan_if_num, uint32_t vlan_tag, uint32_t next_hop, uint32_t physical_dev)
+{
+ struct nss_ctx_instance *nss_ctx = nss_vlan_get_context();
+ struct nss_vlan_msg nvm;
+
+ if (!nss_ctx) {
+ nss_warning("Can't get nss context\n");
+ return NSS_TX_FAILURE;
+ }
+
+ if (nss_vlan_verify_if_num(vlan_if_num) == false) {
+ nss_warning("%p: received invalid interface %d\n", nss_ctx, vlan_if_num);
+ return NSS_TX_FAILURE;
+ }
+
+ nvm.msg.add_tag.next_hop = next_hop;
+ nvm.msg.add_tag.if_num = physical_dev;
+ nvm.msg.add_tag.vlan_tag = vlan_tag;
+ nss_vlan_msg_init(&nvm, vlan_if_num, NSS_VLAN_MSG_ADD_TAG,
+ sizeof(struct nss_vlan_msg_add_tag), NULL, NULL);
+
+ return nss_vlan_tx_msg_sync(nss_ctx, &nvm);
+}
+EXPORT_SYMBOL(nss_vlan_tx_add_tag_msg);
+
+/**
+ * @brief Register to send/receive vlan messages to NSS
+ *
+ * @param if_num NSS interface number
+ * @param vlan_data_callback Callback for vlan data
+ * @param netdev netdevice associated with the vlan interface
+ * @param features denotes the skb types supported by this interface
+ *
+ * @return nss_ctx_instance* NSS context
+ */
+struct nss_ctx_instance *nss_register_vlan_if(uint32_t if_num, nss_vlan_callback_t vlan_data_callback,
+ struct net_device *netdev, uint32_t features, void *app_ctx)
+{
+ nss_assert(nss_vlan_verify_if_num(if_num));
+
+ nss_top_main.subsys_dp_register[if_num].ndev = netdev;
+ nss_top_main.subsys_dp_register[if_num].cb = vlan_data_callback;
+ nss_top_main.subsys_dp_register[if_num].app_data = app_ctx;
+ nss_top_main.subsys_dp_register[if_num].features = features;
+
+ nss_core_register_handler(if_num, nss_vlan_handler, app_ctx);
+
+ return nss_vlan_get_context();
+}
+EXPORT_SYMBOL(nss_register_vlan_if);
+
+/*
+ * nss_unregister_vlan_if()
+ */
+void nss_unregister_vlan_if(uint32_t if_num)
+{
+ nss_assert(nss_vlan_verify_if_num(if_num));
+
+ nss_top_main.subsys_dp_register[if_num].ndev = NULL;
+ nss_top_main.subsys_dp_register[if_num].cb = NULL;
+ nss_top_main.subsys_dp_register[if_num].app_data = NULL;
+ nss_top_main.subsys_dp_register[if_num].features = 0;
+
+ nss_core_unregister_handler(if_num);
+}
+EXPORT_SYMBOL(nss_unregister_vlan_if);
+
+/*
+ * nss_vlan_register_handler()
+ * debugfs stats msg handler received on static vlan interface
+ */
+void nss_vlan_register_handler(void)
+{
+ nss_info("nss_vlan_register_handler\n");
+ nss_core_register_handler(NSS_VLAN_INTERFACE, nss_vlan_handler, NULL);
+
+ sema_init(&vlan_pvt.sem, 1);
+ init_completion(&vlan_pvt.complete);
+}
+EXPORT_SYMBOL(nss_vlan_register_handler);