[][openwrt][mt7988][tops][TOPS Alpha release]

[Description]
Add alpha version of TOPS(tunnel offload processor system) and tops-tool
package.

TOPS package supports tunnel protocol HW offload. The support offload
tunnel protocols for Alpha version are L2oGRE and L2TPv2.
Notice that, TOPS only guarantees that inner packets are TCP. It is still
unstable for UDP inner packet flow.

tops-tool package provides several debug features such as logger, coredump
for TOPS.

[Release-log]
N/A

Change-Id: Iab6e4a89bebbe42c967f28e0c9e9c0611673f354
Reviewed-on: https://gerrit.mediatek.inc/c/openwrt/feeds/mtk_openwrt_feeds/+/7852683
diff --git a/package-21.02/kernel/tops/src/net-event.c b/package-21.02/kernel/tops/src/net-event.c
new file mode 100644
index 0000000..7cc4553
--- /dev/null
+++ b/package-21.02/kernel/tops/src/net-event.c
@@ -0,0 +1,151 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) 2023 MediaTek Inc. All Rights Reserved.
+ *
+ * Author: Ren-Ting Wang <ren-ting.wang@mediatek.com>
+ */
+
+#include <linux/device.h>
+#include <linux/hashtable.h>
+#include <linux/netdevice.h>
+#include <linux/netfilter.h>
+#include <linux/netfilter_ipv4.h>
+#include <linux/notifier.h>
+#include <net/arp.h>
+#include <net/flow.h>
+#include <net/ip.h>
+#include <net/ip_tunnels.h>
+#include <net/netevent.h>
+#include <net/net_namespace.h>
+#include <net/neighbour.h>
+#include <net/route.h>
+
+#include "internal.h"
+#include "netsys.h"
+#include "net-event.h"
+#include "mcu.h"
+#include "ser.h"
+#include "trm.h"
+#include "tunnel.h"
+
+static struct completion wait_fe_reset_done;
+
+static void mtk_tops_netdev_ser_callback(struct tops_ser_params *ser_param)
+{
+	struct net_device *netdev = ser_param->data.net.ndev;
+
+	WARN_ON(ser_param->type != TOPS_SER_NETSYS_FE_RST);
+
+	mtk_trm_dump(TRM_RSN_FE_RESET);
+
+	/* send tops dump done notification to mtk eth */
+	rtnl_lock();
+	call_netdevice_notifiers(MTK_TOPS_DUMP_DONE, netdev);
+	rtnl_unlock();
+
+	/* wait for FE reset done notification */
+	/* TODO : if not received FE reset done notification */
+	wait_for_completion(&wait_fe_reset_done);
+}
+
+static inline void mtk_tops_netdev_ser(struct net_device *dev)
+{
+	struct tops_ser_params ser_params = {
+		.type = TOPS_SER_NETSYS_FE_RST,
+		.data.net.ndev = dev,
+		.ser_callback = mtk_tops_netdev_ser_callback,
+	};
+
+	mtk_tops_ser(&ser_params);
+}
+
+/* TODO: update tunnel status when user delete or change tunnel parameters */
+/*
+ * eth will send out MTK_FE_START_RESET event if detected wdma abnormal, or
+ * send out MTK_FE_STOP_TRAFFIC event if detected qdma or adma or tdma abnormal,
+ * then do FE reset, so we use the same mcu event to represent it.
+ *
+ * after FE reset done, eth will send out MTK_FE_START_TRAFFIC event if this is
+ * wdma abnormal induced FE reset, or send out MTK_FE_RESET_DONE event for qdma
+ * or adma or tdma abnormal induced FE reset.
+ */
+static int mtk_tops_netdev_callback(struct notifier_block *nb,
+				   unsigned long event,
+				   void *data)
+{
+	struct net_device *dev = netdev_notifier_info_to_dev(data);
+	int ret = 0;
+
+	switch (event) {
+	case NETDEV_UP:
+		break;
+	case NETDEV_DOWN:
+		mtk_tops_tnl_offload_netdev_down(dev);
+		break;
+	case MTK_FE_START_RESET:
+	case MTK_FE_STOP_TRAFFIC:
+		mtk_tops_netdev_ser(dev);
+		break;
+	case MTK_FE_RESET_DONE:
+	case MTK_FE_START_TRAFFIC:
+		complete(&wait_fe_reset_done);
+		break;
+	default:
+		break;
+	}
+
+	return ret;
+}
+
+static struct notifier_block mtk_tops_netdev_notifier = {
+	.notifier_call = mtk_tops_netdev_callback,
+};
+
+static int mtk_tops_netevent_callback(struct notifier_block *nb,
+				      unsigned long event,
+				      void *data)
+{
+	int ret = 0;
+
+	switch (event) {
+	case NETEVENT_NEIGH_UPDATE:
+		break;
+	default:
+		break;
+	}
+
+	return ret;
+}
+
+static struct notifier_block mtk_tops_netevent_notifier = {
+	.notifier_call = mtk_tops_netevent_callback,
+};
+
+int mtk_tops_netevent_register(struct platform_device *pdev)
+{
+	int ret = 0;
+
+	ret = register_netdevice_notifier(&mtk_tops_netdev_notifier);
+	if (ret) {
+		TOPS_ERR("TOPS register netdev notifier failed: %d\n", ret);
+		return ret;
+	}
+
+	ret = register_netevent_notifier(&mtk_tops_netevent_notifier);
+	if (ret) {
+		unregister_netdevice_notifier(&mtk_tops_netdev_notifier);
+		TOPS_ERR("TOPS register net event notifier failed: %d\n", ret);
+		return ret;
+	}
+
+	init_completion(&wait_fe_reset_done);
+
+	return ret;
+}
+
+void mtk_tops_netevent_unregister(struct platform_device *pdev)
+{
+	unregister_netevent_notifier(&mtk_tops_netevent_notifier);
+
+	unregister_netdevice_notifier(&mtk_tops_netdev_notifier);
+}