gl-infra-builder-FUjr/patches-21.02.2/0017-ipq40xx-add-modem-support-and-compatible-with-a1300_update_dts.patch
2023-05-30 04:57:21 -04:00

1225 lines
47 KiB
Diff

From 3f845f1214061d3ab3cc5eafeacf04e0c3a5de1a Mon Sep 17 00:00:00 2001
From: gl-yangweiping <weiping.yang@gl-inet.com>
Date: Tue, 7 Jun 2022 21:57:04 -0400
Subject: [PATCH] A1300 adapt 21.02.2
---
feeds.conf.default | 1 -
include/image-commands.mk | 17 +-
.../ipq-wifi/board-glinet_gl-a1300.qca4019 | Bin 48596 -> 24308 bytes
.../src/gpio-button-hotplug.c | 1 +
.../patches/300-remove-limit-hostname.patch | 11 +
package/network/services/ppp/files/ppp.sh | 1 +
.../arm/boot/dts/qcom-ipq4018-gl-a1300.dts | 32 +-
target/linux/ipq40xx/image/generic.mk | 4 +-
.../patches-5.4/320-add_spi_nor_write.patch | 11 +
.../patches-5.4/700-add-modem-support.patch | 280 ++++++++++++++++
...k-events-support-multiple-registrant.patch | 313 ++++++++++++++++++
...-linux-kernel-to-support-shortcut-fe.patch | 282 ++++++++++++++++
12 files changed, 936 insertions(+), 17 deletions(-)
create mode 100644 package/network/services/dnsmasq/patches/300-remove-limit-hostname.patch
create mode 100644 target/linux/ipq40xx/patches-5.4/320-add_spi_nor_write.patch
create mode 100644 target/linux/ipq40xx/patches-5.4/700-add-modem-support.patch
create mode 100644 target/linux/ipq40xx/patches-5.4/952-net-conntrack-events-support-multiple-registrant.patch
create mode 100644 target/linux/ipq40xx/patches-5.4/953-net-patch-linux-kernel-to-support-shortcut-fe.patch
diff --git a/feeds.conf.default b/feeds.conf.default
index c07b0bcc1e..3dfca3a7df 100644
--- a/feeds.conf.default
+++ b/feeds.conf.default
@@ -1,4 +1,3 @@
-src-git gl_feeds https://github.com/gl-inet/gl-feeds.git;21.02.2
src-git packages https://git.openwrt.org/feed/packages.git^b0ccc356900f6e1e1dc613d0ea980d5572f553dd
src-git luci https://git.openwrt.org/project/luci.git^cc582ebfb3cb2782db841ad2a4e908d1df4046f9
src-git routing https://git.openwrt.org/feed/routing.git^10d3ffd8b30186b49538167bac1fa1bf9c88f860
diff --git a/include/image-commands.mk b/include/image-commands.mk
index 7ed6c60e8f..1f5264c3ae 100644
--- a/include/image-commands.mk
+++ b/include/image-commands.mk
@@ -66,8 +66,13 @@ endef
metadata_gl_json = \
'{ $(if $(IMAGE_METADATA),$(IMAGE_METADATA)$(comma)) \
- "metadata_version": "1.0", \
- "supported_devices":[$(call metadata_devices,$(1))], \
+ "metadata_version": "1.1", \
+ "compat_version": "$(call json_quote,$(compat_version))", \
+ $(if $(DEVICE_COMPAT_MESSAGE),"compat_message": "$(call json_quote,$(DEVICE_COMPAT_MESSAGE))"$(comma)) \
+ $(if $(filter-out 1.0,$(compat_version)),"new_supported_devices": \
+ [$(call metadata_devices,$(SUPPORTED_DEVICES))]$(comma) \
+ "supported_devices": ["$(call json_quote,$(legacy_supported_message))"]$(comma)) \
+ $(if $(filter 1.0,$(compat_version)),"supported_devices":[$(call metadata_devices,$(SUPPORTED_DEVICES))]$(comma)) \
"version": { \
"release": "$(shell cat $(TOPDIR)/release)", \
"date": "$(shell TZ='Asia/Chongqing' date '+%Y%m%d%H%M%S')", \
@@ -78,15 +83,15 @@ metadata_gl_json = \
"target": "$(call json_quote,$(TARGETID))", \
"board": "$(call json_quote,$(if $(BOARD_NAME),$(BOARD_NAME),$(DEVICE_NAME)))" \
}, \
+ "upgrade_control":"$(shell python3 $(TOPDIR)/make_gl_metadata.py)", \
+ "release_note":"$(shell sed ':a;N;s/\n/\\\\n/g;s/\r/\\\\r/g;ta' $(TOPDIR)/gl_release_note | sed "s/'/\\\047/g")" \
}'
define Build/append-gl-metadata
$(if $(SUPPORTED_DEVICES),-echo -e $(call metadata_gl_json,$(SUPPORTED_DEVICES)) | fwtool -I - $@)
- [ ! -s "$(BUILD_KEY)" -o ! -s "$(BUILD_KEY).ucert" -o ! -s "$@" ] || { \
- cp "$(BUILD_KEY).ucert" "$@.ucert" ;\
+ [ ! -s "$(BUILD_KEY)" -o ! -s "$@" ] || { \
usign -S -m "$@" -s "$(BUILD_KEY)" -x "$@.sig" ;\
- ucert -A -c "$@.ucert" -x "$@.sig" ;\
- fwtool -S "$@.ucert" "$@" ;\
+ fwtool -S "$@.sig" "$@" ;\
}
endef
diff --git a/package/firmware/ipq-wifi/board-glinet_gl-a1300.qca4019 b/package/firmware/ipq-wifi/board-glinet_gl-a1300.qca4019
index 0b9a908bcdd0f86f1de1100b98556e353085fcef..d8695c983641b25f4e059f65a0ce8b4f2501338c 100644
GIT binary patch
delta 2274
zcmdT_Yfw{16yBQz0vHSlNeJ>txB-%&f;?=)7)hjvLFG{?3>PUc3qq#A0EUN23tGh#
zVnLQtLx`d>JT(nm#`*vPh}G#-+8=bL^@lQj*qPd@qjq#g#cl$K(>l}kSEuLRv%B}4
z@9gf~d%kmLpHLo-VJ%yrI7c8-6=4{l*0H0~0g{j|)Z_x-M)yDi05|}wjD#$T4=$DB
zn8Oqq8Ts)3eN4`A29JMeRxBx%11DXhv58hpz+3=2(5UG~@q8GMt>W9UOV;IHVULX8
z;^wei`jP>Jix)Bomtkl#?3bSu96Fuu<m5zsNdOpwtQB0Sr19Lj2>e3fM#>vBCK9yN
zRk)q%%NajyYN{>B+?F64Crz-nB=fC=Sg51&y)R#pioy69Q)6v@W<tVi<5p8kZE<Ew
zLJT}(_g)o;fbk*IVHBH~5Iz1W@~R!)8&p0GdBtQnTSb9iyH3B;-IP}yT_8^P-8Ka)
z>f%d6bGWf%1Lel}Ly`)9u5oauG5V0O(lf88F;5enADrr!Fxpb8+g!Y6CpYHv{@PEH
z4~16x?Yb~nZA@%hTkTsoa=54_ra+p`ioS?&aq7^Wo-w4F{v8G<w@1P%SD{m1ea1RI
zX>z4vXao8;GctB0;kW=D#G^;|@6ONLk3%L65-r%C-o1Y7Wt$!7$DmVav}Xv%1Q=M3
zfAHYWZG=Uqw+mih;a?{S4h{|s#Bqt_KN$)BW?__Z9CCp11;0)SSitj^v>t$P5RCFi
zfHFD|<u;Dg-nX#B0gn6n;(wAhWdExb$FpD{kjpUeund4UItx=q0U&W<0XdM<a-CU#
z!lk%nq29v-(Fy>#KJf!mD9FS}YlE|kNc0tkA*R)|I5L^rg%G(YOX>A!;K<e`vJwA?
zY$PHZ3{Mo>$rZLlE`OF|vc+bBC3I)16YT|0066>H&bcrc8Xk_>N1IYP91gJSlJIyu
zVAm!2m(T7<(7Z}24xG`)@PbJZ&TbQ2Auokj&$IH7Yn{ul3o?!T{w|%JGc%oC3<fzG
zkxSjk(gTp%f&mSm0(xgLhc=+TVGaW|ffO)sngRyzQNXoxRB%U51I#fRP;7JpEH2fF
zPO=26Dd^DIl!E01eiZ?p{PN@6&70q%S6m>4odC~&`}zCZw|_#mR}ui(<?^U?3j~^<
z|NY(qDU$z3q<Bhk*`85k=o%Tj28WnjcqKwqcVpPrX0Fnv6Ja;b+e~JiHk**y&YIh`
z<wU$J$Tn>0HfYs^%=a;p(Fw5xpa5vrXw!($8LQ=pp-jDlkXc5|U1~LvBwJ(q%-pIi
zA!21hd%)O~SPUF6wKiRwK6Am+Y0#)siPtR`4DIR)Rh$fdqhNZEPl=^qX4G=bP=#h&
zZ?jrX8FXrbki%yRzPD`(tvYkwVlwYDl&Ck`hAbz|jR=_pLzR5*iAxeGKwCd<X*O#N
zxo8Qq`Jka(OTZk5R~l^JK&yGLp-`JNa}ljkqfQ~hU<>k2PD#=GkT#>a(vYo<n>lCc
zFjQ)@)LY@Cl24nwES8{(j?v%*d)kpy@}tA0y^6NAdY`HjmbXoD&0?K*>7MrZ1Jd$U
z`Hc99?t;S`wW8f##EIcOy|FM%@1q&E7MiynS^d6G8N9cJBR5#nj?0b+bZoW0Kf5!c
z!C%A9Ki5~@uG}xJV5eOgD29r9(YyR?-C)|Wwfa?6EAs}d)u)snNpxOCP^sd`r_XB#
zl1<`$yb{Zh=H!M(yo#OEXiRR1s^Sw26*-vmv24Gfgqz)CDLx+8EYz@a`v)t{@`HG}
z2LW5q1pU_CUGc4fdpU(i2TG4A8iQ*%dA-JBeT*h#x97H=zOs%D2SgQ|?2i6C<EEy7
zN_KWzPjQF5K~(9PMb4>asqRj6*A?zemM7QC+s6<6e^Py{`dpdE)%Q{&{DXo5(JjIQ
zgra}|JRlvwA=eK{l|PpX=Rzfm+K2v7b>uAGMNuu)=3rEQx|yghGmyFiphPv>ty@}e
h*R4~_y`#=jXp40gU~#C%heQXKBjS%><Xk$(<q!QajGO=f
literal 48596
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
diff --git a/package/kernel/gpio-button-hotplug/src/gpio-button-hotplug.c b/package/kernel/gpio-button-hotplug/src/gpio-button-hotplug.c
index fcaf7f59de..125dbff2f5 100644
--- a/package/kernel/gpio-button-hotplug/src/gpio-button-hotplug.c
+++ b/package/kernel/gpio-button-hotplug/src/gpio-button-hotplug.c
@@ -100,6 +100,7 @@ static struct bh_map button_map[] = {
BH_MAP(KEY_WIMAX, "wwan"),
BH_MAP(KEY_WLAN, "wlan"),
BH_MAP(KEY_WPS_BUTTON, "wps"),
+ BH_MAP(KEY_SETUP, "switch"),
};
/* -------------------------------------------------------------------------*/
diff --git a/package/network/services/dnsmasq/patches/300-remove-limit-hostname.patch b/package/network/services/dnsmasq/patches/300-remove-limit-hostname.patch
new file mode 100644
index 0000000000..a921c5e5b0
--- /dev/null
+++ b/package/network/services/dnsmasq/patches/300-remove-limit-hostname.patch
@@ -0,0 +1,11 @@
+--- a/src/rfc2131.c
++++ b/src/rfc2131.c
+@@ -724,7 +724,7 @@ size_t dhcp_reply(struct dhcp_context *c
+ borken_opt = 1;
+ else
+ daemon->dhcp_buff[len] = 0;
+- if (legal_hostname(daemon->dhcp_buff))
++ //if (legal_hostname(daemon->dhcp_buff))
+ client_hostname = daemon->dhcp_buff;
+ }
+
diff --git a/package/network/services/ppp/files/ppp.sh b/package/network/services/ppp/files/ppp.sh
index b553effd88..78a712b41a 100755
--- a/package/network/services/ppp/files/ppp.sh
+++ b/package/network/services/ppp/files/ppp.sh
@@ -140,6 +140,7 @@ ppp_generic_setup() {
${localip:+$localip:} \
${lcp_failure:+lcp-echo-interval $lcp_interval lcp-echo-failure $lcp_failure $lcp_adaptive} \
${ipv6:++ipv6} \
+ ${ipv6:-noipv6} \
${autoipv6:+set AUTOIPV6=1} \
${ip6table:+set IP6TABLE=$ip6table} \
${peerdns:+set PEERDNS=$peerdns} \
diff --git a/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-gl-a1300.dts b/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-gl-a1300.dts
index a6d662e6da..35548085c9 100644
--- a/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-gl-a1300.dts
+++ b/target/linux/ipq40xx/files/arch/arm/boot/dts/qcom-ipq4018-gl-a1300.dts
@@ -10,10 +10,10 @@
compatible = "glinet,gl-a1300", "qcom,ipq4019";
aliases {
- led-boot = &led_run;
- led-failsafe = &led_run;
- led-running = &led_run;
- led-upgrade = &led_run;
+ //led-boot = &led_run;
+ //led-failsafe = &led_run;
+ //led-running = &led_run;
+ //led-upgrade = &led_run;
};
gl_hw {
@@ -22,14 +22,19 @@
#address-cells = <1>;
#size-cells = <1>;
model = "a1300";
- wan = "etho";
- lan = "eth1";
+ wan = "eth1";
+ lan = "eth0";
+ usb-port = "1-1,2-1";
+ flash_size = <128>;
reset-button = "gpio-63";
+ switch-button = "gpio-0";
+ radio = "radio0";
factory_data {
- device_mac = "ART", "0";
+ device_mac = "ART", "0x0";
device_ddns = "ART", "0x10";
device_sn_bak = "ART", "0x20";
device_sn = "ART", "0x30";
+ country_code = "ART", "0x88";
};
};
@@ -116,6 +121,12 @@
gpios = <&tlmm 63 GPIO_ACTIVE_LOW>;
linux,code = <KEY_RESTART>;
};
+
+ switch {
+ label = "switch-button";
+ gpios = <&tlmm 0 GPIO_ACTIVE_LOW>;
+ linux,code = <KEY_SETUP>;
+ };
};
leds {
@@ -124,6 +135,7 @@
led_run: blue {
label = "gl-a1300:blue";
gpios = <&tlmm 2 GPIO_ACTIVE_HIGH>;
+ default-state = "on";
};
white {
@@ -136,7 +148,7 @@
compatible = "gpio-export";
usb {
- gpio-export,name = "usb-power";
+ gpio-export,name = "usb_power";
gpio-export,output = <1>;
gpios = <&tlmm 4 GPIO_ACTIVE_HIGH>;
};
@@ -216,6 +228,10 @@
reg = <0x00170000 0x00010000>;
read-only;
};
+ partition@180000 {
+ label = "log";
+ reg = <0x00180000 0x00020000>;
+ };
};
};
diff --git a/target/linux/ipq40xx/image/generic.mk b/target/linux/ipq40xx/image/generic.mk
index da6a2ce2eb..d9ace7711c 100644
--- a/target/linux/ipq40xx/image/generic.mk
+++ b/target/linux/ipq40xx/image/generic.mk
@@ -23,8 +23,8 @@ endef
define Device/UbiFit
KERNEL_IN_UBI := 1
- IMAGES := nand-factory.ubi nand-sysupgrade.bin
- IMAGE/nand-factory.ubi := append-ubi
+ IMAGES := nand-factory.img nand-sysupgrade.bin
+ IMAGE/nand-factory.img := append-ubi
IMAGE/nand-sysupgrade.bin := sysupgrade-tar | append-metadata
endef
diff --git a/target/linux/ipq40xx/patches-5.4/320-add_spi_nor_write.patch b/target/linux/ipq40xx/patches-5.4/320-add_spi_nor_write.patch
new file mode 100644
index 0000000000..2f1d4ad139
--- /dev/null
+++ b/target/linux/ipq40xx/patches-5.4/320-add_spi_nor_write.patch
@@ -0,0 +1,11 @@
+--- a/drivers/mtd/spi-nor/spi-nor.c
++++ b/drivers/mtd/spi-nor/spi-nor.c
+@@ -5025,6 +5025,8 @@ int spi_nor_scan(struct spi_nor *nor, co
+ else
+ mtd->_write = spi_nor_write;
+
++ mtd->_panic_write = spi_nor_write;
++
+ if (info->flags & USE_FSR)
+ nor->flags |= SNOR_F_USE_FSR;
+ if (info->flags & SPI_NOR_HAS_TB)
diff --git a/target/linux/ipq40xx/patches-5.4/700-add-modem-support.patch b/target/linux/ipq40xx/patches-5.4/700-add-modem-support.patch
new file mode 100644
index 0000000000..4accdeae0c
--- /dev/null
+++ b/target/linux/ipq40xx/patches-5.4/700-add-modem-support.patch
@@ -0,0 +1,280 @@
+--- a/drivers/net/usb/qmi_wwan.c
++++ b/drivers/net/usb/qmi_wwan.c
+@@ -507,6 +507,25 @@ static const u8 default_modem_addr[ETH_A
+
+ static const u8 buggy_fw_addr[ETH_ALEN] = {0x00, 0xa0, 0xc6, 0x00, 0x00, 0x00};
+
++#if 1 //Added by Quectel
++#include <linux/etherdevice.h>
++struct sk_buff *qmi_wwan_tx_fixup(struct usbnet *dev, struct sk_buff *skb, gfp_t flags)
++{
++ if (dev->udev->descriptor.idVendor != cpu_to_le16(0x2C7C))
++ return skb;
++ // Skip Ethernet header from message
++ if (skb_pull(skb, ETH_HLEN)) {
++ return skb;
++ } else {
++ dev_err(&dev->intf->dev, "Packet Dropped ");
++ }
++ // Filter the packet out, release it
++ dev_kfree_skb_any(skb);
++ return NULL;
++}
++#endif
++
++
+ /* Make up an ethernet header if the packet doesn't have one.
+ *
+ * A firmware bug common among several devices cause them to send raw
+@@ -801,6 +820,20 @@ static int qmi_wwan_bind(struct usbnet *
+ }
+ dev->net->netdev_ops = &qmi_wwan_netdev_ops;
+ dev->net->sysfs_groups[0] = &qmi_wwan_sysfs_attr_group;
++#if 1 //Added by Quectel
++ if (dev->udev->descriptor.idVendor == cpu_to_le16(0x2C7C)) {
++ dev_info(&intf->dev, "QuectelEC25&EC21&EG91&EG95&EG06&EP06&EM06&BG96&AG35 work on RawIP mode\n");
++ dev->net->flags |= IFF_NOARP;
++ usb_control_msg(
++ interface_to_usbdev(intf),
++ usb_sndctrlpipe(interface_to_usbdev(intf), 0),
++ 0x22, //USB_CDC_REQ_SET_CONTROL_LINE_STATE
++ 0x21, //USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE
++ 1, //active CDC DTR
++ intf->cur_altsetting->desc.bInterfaceNumber,
++ NULL, 0, 100);
++ }
++#endif
+ err:
+ return status;
+ }
+@@ -891,7 +924,10 @@ static const struct driver_info qmi_wwan
+ .bind = qmi_wwan_bind,
+ .unbind = qmi_wwan_unbind,
+ .manage_power = qmi_wwan_manage_power,
+- .rx_fixup = qmi_wwan_rx_fixup,
++ #if 1 //Added by Quectel
++ .tx_fixup = qmi_wwan_tx_fixup,
++ .rx_fixup = qmi_wwan_rx_fixup,
++ #endif
+ };
+
+ static const struct driver_info qmi_wwan_info_quirk_dtr = {
+@@ -938,6 +974,17 @@ static const struct driver_info qmi_wwan
+ .driver_info = (unsigned long)&qmi_wwan_info_quirk_dtr
+
+ static const struct usb_device_id products[] = {
++#if 1 //Added by Quectel
++ { QMI_FIXED_INTF(0x05C6, 0x9003, 4) }, /* Quectel UC20 */
++ { QMI_FIXED_INTF(0x2C7C, 0x0125, 4) }, /* Quectel EC25 */
++ { QMI_FIXED_INTF(0x2C7C, 0x0121, 4) }, /* Quectel EC21 */
++ { QMI_FIXED_INTF(0x05C6, 0x9215, 4) }, /* Quectel EC20 */
++ { QMI_FIXED_INTF(0x2C7C, 0x0191, 4) }, /* Quectel EG91 */
++ { QMI_FIXED_INTF(0x2C7C, 0x0195, 4) }, /* Quectel EG95 */
++ { QMI_FIXED_INTF(0x2C7C, 0x0306, 4) }, /* Quectel EG06/EP06/EM06 */
++ { QMI_FIXED_INTF(0x2C7C, 0x0296, 4) }, /* Quectel BG96 */
++ { QMI_FIXED_INTF(0x2C7C, 0x0435, 4) }, /* Quectel AG35 */
++#endif
+ /* 1. CDC ECM like devices match on the control interface */
+ { /* Huawei E392, E398 and possibly others sharing both device id and more... */
+ USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, USB_CLASS_VENDOR_SPEC, 1, 9),
+@@ -1357,6 +1404,7 @@ static const struct usb_device_id produc
+ {QMI_FIXED_INTF(0x413c, 0x81e0, 0)}, /* Dell Wireless 5821e with eSIM support*/
+ {QMI_FIXED_INTF(0x03f0, 0x4e1d, 8)}, /* HP lt4111 LTE/EV-DO/HSPA+ Gobi 4G Module */
+ {QMI_FIXED_INTF(0x03f0, 0x9d1d, 1)}, /* HP lt4120 Snapdragon X5 LTE */
++ {QMI_FIXED_INTF(0x1e0e, 0x9001, 5)}, /* SIMCom 7230E */
+ {QMI_FIXED_INTF(0x22de, 0x9061, 3)}, /* WeTelecom WPD-600N */
+ {QMI_QUIRK_SET_DTR(0x1e0e, 0x9001, 5)}, /* SIMCom 7100E, 7230E, 7600E ++ */
+ {QMI_QUIRK_SET_DTR(0x2c7c, 0x0121, 4)}, /* Quectel EC21 Mini PCIe */
+@@ -1396,7 +1444,6 @@ static const struct usb_device_id produc
+ {QMI_GOBI_DEVICE(0x05c6, 0x9225)}, /* Sony Gobi 2000 Modem device (N0279, VU730) */
+ {QMI_GOBI_DEVICE(0x05c6, 0x9245)}, /* Samsung Gobi 2000 Modem device (VL176) */
+ {QMI_GOBI_DEVICE(0x03f0, 0x251d)}, /* HP Gobi 2000 Modem device (VP412) */
+- {QMI_GOBI_DEVICE(0x05c6, 0x9215)}, /* Acer Gobi 2000 Modem device (VP413) */
+ {QMI_FIXED_INTF(0x05c6, 0x9215, 4)}, /* Quectel EC20 Mini PCIe */
+ {QMI_GOBI_DEVICE(0x05c6, 0x9265)}, /* Asus Gobi 2000 Modem device (VR305) */
+ {QMI_GOBI_DEVICE(0x05c6, 0x9235)}, /* Top Global Gobi 2000 Modem device (VR306) */
+--- a/drivers/usb/serial/option.c
++++ b/drivers/usb/serial/option.c
+@@ -565,6 +565,22 @@ static void option_instat_callback(struc
+ #define WETELECOM_PRODUCT_6802 0x6802
+ #define WETELECOM_PRODUCT_WMD300 0x6803
+
++#define LONGSUNG_PRODUCT_U9300C 0x9b3c
++
++/* FORGE PRODUCT */
++#define FORGE_VENDOR_ID 0x05c6
++
++#define FORGE_PRODUCT_SLM750 0xf601
++
++/* NODECOM PRODUCT */
++#define NODECOM_VENDOR_ID 0x1508
++
++#define NODECOM_PRODUCT_NL660 0x1001
++
++/* NEOWAY PRODUCT */
++#define NEOWAY_VENDOR_ID 0x2949
++
++#define NEOWAY_PRODUCT_N720 0x8243
+
+ /* Device flags */
+
+@@ -585,6 +601,29 @@ static void option_instat_callback(struc
+
+
+ static const struct usb_device_id option_ids[] = {
++#if 1 //Added by Quectel
++ { USB_DEVICE(0x05C6, 0x9090) }, /* Quectel UC15 */
++ { USB_DEVICE(0x05C6, 0x9003) }, /* Quectel UC20 */
++ { USB_DEVICE(0x2C7C, 0x0125) }, /* Quectel EC25 */
++ { USB_DEVICE(0x2C7C, 0x0121) }, /* Quectel EC21 */
++ { USB_DEVICE(0x05C6, 0x9215) }, /* Quectel EC20 */
++ { USB_DEVICE(0x2C7C, 0x0191) }, /* Quectel EG91 */
++ { USB_DEVICE(0x2C7C, 0x0195) }, /* Quectel EG95 */
++ { USB_DEVICE(0x2C7C, 0x0306) }, /* Quectel EG06/EP06/EM06 */
++ { USB_DEVICE(0x2C7C, 0x0700) }, /* Quectel BG95 */
++ { USB_DEVICE(0x2C7C, 0x0296) }, /* Quectel BG96 */
++ { USB_DEVICE(0x2C7C, 0x0435) }, /* Quectel AG35 */
++ { USB_DEVICE(0x2C7C, 0x6026) }, /* Quectel EC200t */
++#endif
++ { USB_DEVICE(0x19d2, 0x0536) },/* MZ386 */
++ { USB_DEVICE(0x19d2, 0x0117) },
++ { USB_DEVICE(0x19d2, 0x0199) },
++ { USB_DEVICE(0x19d2, 0x1476) },
++ { USB_DEVICE(LONGCHEER_VENDOR_ID, LONGSUNG_PRODUCT_U9300C) },
++ { USB_DEVICE(FORGE_VENDOR_ID, FORGE_PRODUCT_SLM750) },
++ { USB_DEVICE(NODECOM_VENDOR_ID, NODECOM_PRODUCT_NL660) },
++ { USB_DEVICE(NEOWAY_VENDOR_ID, NEOWAY_PRODUCT_N720) },
++
+ { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COLT) },
+ { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_RICOLA) },
+ { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_RICOLA_LIGHT) },
+@@ -2146,6 +2185,9 @@ static struct usb_serial_driver option_1
+ #ifdef CONFIG_PM
+ .suspend = usb_wwan_suspend,
+ .resume = usb_wwan_resume,
++#if 1 //Added by Quectel
++ .reset_resume = usb_wwan_resume,
++#endif
+ #endif
+ };
+
+@@ -2189,9 +2231,84 @@ static int option_probe(struct usb_seria
+ if (device_flags & NUMEP2 && iface_desc->bNumEndpoints != 2)
+ return -ENODEV;
+
+- /* Store the device flags so we can use them during attach. */
+- usb_set_serial_data(serial, (void *)device_flags);
+-
++#if 1 //Added by Quectel
++ //Quectel UC20's interface 4 can be used as USB network device
++ if (serial->dev->descriptor.idVendor == cpu_to_le16(0x05C6) && \
++ serial->dev->descriptor.idProduct == cpu_to_le16(0x9003) \
++ && serial->interface->cur_altsetting->desc.bInterfaceNumber >= 4)
++ return -ENODEV;
++ //Quectel EC20's interface 4 can be used as USB network device
++ if (serial->dev->descriptor.idVendor == cpu_to_le16(0x05C6) && \
++ serial->dev->descriptor.idProduct == cpu_to_le16(0x9215) \
++ && serial->interface->cur_altsetting->desc.bInterfaceNumber >= 4)
++ return -ENODEV;
++ //Quectel EC25&EC21&EG91&EG95&EG06&EP06&EM06&BG96/AG35's interface 4 can be used as USB network device
++ if (serial->dev->descriptor.idVendor == cpu_to_le16(0x2C7C) && \
++ serial->dev->descriptor.idProduct != cpu_to_le16(0x6026) \
++ && serial->interface->cur_altsetting->desc.bInterfaceNumber >= 4)
++ return -ENODEV;
++ if (serial->dev->descriptor.idVendor == cpu_to_le16(0x2C7C) && \
++ serial->dev->descriptor.idProduct == cpu_to_le16(0x6026) \
++ && serial->interface->cur_altsetting->desc.bInterfaceNumber<= 1)
++ return -ENODEV;
++#endif
++#if 0 //Added by Quectel
++ //For USB Auto Suspend
++ if (serial->dev->descriptor.idVendor == cpu_to_le16(0x05C6) &&
++ serial->dev->descriptor.idProduct == cpu_to_le16(0x9090)) {
++ pm_runtime_set_autosuspend_delay(&serial->dev->dev, 3000);
++ usb_enable_autosuspend(serial->dev);
++ }
++ if (serial->dev->descriptor.idVendor == cpu_to_le16(0x05C6) &&
++ serial->dev->descriptor.idProduct == cpu_to_le16(0x9003)) {
++ pm_runtime_set_autosuspend_delay(&serial->dev->dev, 3000);
++ usb_enable_autosuspend(serial->dev);
++ }
++ if (serial->dev->descriptor.idVendor == cpu_to_le16(0x05C6) &&
++ serial->dev->descriptor.idProduct == cpu_to_le16(0x9215)) {
++ pm_runtime_set_autosuspend_delay(&serial->dev->dev, 3000);
++ usb_set_serial_data(serial, (void *)device_flags);
++ usb_enable_autosuspend(serial->dev);
++ }
++ if (serial->dev->descriptor.idVendor == cpu_to_le16(0x2C7C)) {
++ pm_runtime_set_autosuspend_delay(&serial->dev->dev, 3000);
++ usb_enable_autosuspend(serial->dev);
++ }
++#endif
++#if 0 //Added by Quectel
++ //For USB Remote Wakeup
++ if (serial->dev->descriptor.idVendor == cpu_to_le16(0x05C6) &&
++ serial->dev->descriptor.idProduct == cpu_to_le16(0x9090)) {
++ device_init_wakeup(&serial->dev->dev, 1); //usb remote wakeup
++ }
++ if (serial->dev->descriptor.idVendor == cpu_to_le16(0x05C6) &&
++ serial->dev->descriptor.idProduct == cpu_to_le16(0x9003)) {
++ device_init_wakeup(&serial->dev->dev, 1); //usb remote wakeup
++ }
++ if (serial->dev->descriptor.idVendor == cpu_to_le16(0x05C6) &&
++ serial->dev->descriptor.idProduct == cpu_to_le16(0x9215)) {
++ device_init_wakeup(&serial->dev->dev, 1); //usb remote wakeup
++ }
++ if (serial->dev->descriptor.idVendor == cpu_to_le16(0x2C7C)) {
++ device_init_wakeup(&serial->dev->dev, 1); //usb remote wakeup
++ }
++#endif
++ if (serial->dev->descriptor.idVendor == cpu_to_le16(0x19d2) &&
++ serial->dev->descriptor.idProduct == cpu_to_le16(0x1476) &&
++ serial->interface->cur_altsetting->desc. bInterfaceNumber == 3)
++ return -ENODEV;
++ if (serial->dev->descriptor.idVendor == cpu_to_le16(0x19d2) &&
++ serial->dev->descriptor.idProduct == cpu_to_le16(0x1476) &&
++ serial->interface->cur_altsetting->desc. bInterfaceNumber == 4)
++ return -ENODEV;
++ if (serial->dev->descriptor.idVendor == cpu_to_le16(0x19d2) &&
++ serial->dev->descriptor.idProduct == cpu_to_le16(0x1509) &&
++ serial->interface->cur_altsetting->desc. bInterfaceNumber == 4)
++ return -ENODEV;
++ if (serial->dev->descriptor.idVendor == cpu_to_le16(0x19d2) &&
++ serial->dev->descriptor.idProduct == cpu_to_le16(0x1509) &&
++ serial->interface->cur_altsetting->desc. bInterfaceNumber == 5)
++ return -ENODEV;
+ return 0;
+ }
+
+--- a/drivers/usb/serial/qcserial.c
++++ b/drivers/usb/serial/qcserial.c
+@@ -88,7 +88,6 @@ static const struct usb_device_id id_tab
+ {USB_DEVICE(0x03f0, 0x241d)}, /* HP Gobi 2000 QDL device (VP412) */
+ {USB_DEVICE(0x03f0, 0x251d)}, /* HP Gobi 2000 Modem device (VP412) */
+ {USB_DEVICE(0x05c6, 0x9214)}, /* Acer Gobi 2000 QDL device (VP413) */
+- {USB_DEVICE(0x05c6, 0x9215)}, /* Acer Gobi 2000 Modem device (VP413) */
+ {USB_DEVICE(0x05c6, 0x9264)}, /* Asus Gobi 2000 QDL device (VR305) */
+ {USB_DEVICE(0x05c6, 0x9265)}, /* Asus Gobi 2000 Modem device (VR305) */
+ {USB_DEVICE(0x05c6, 0x9234)}, /* Top Global Gobi 2000 QDL device (VR306) */
+--- a/drivers/usb/serial/usb_wwan.c
++++ b/drivers/usb/serial/usb_wwan.c
+@@ -476,6 +476,19 @@ static struct urb *usb_wwan_setup_urb(st
+ usb_fill_bulk_urb(urb, serial->dev,
+ usb_sndbulkpipe(serial->dev, endpoint) | dir,
+ buf, len, callback, ctx);
++#if 1 //Added by Quectel for zero packet
++ if (dir == USB_DIR_OUT) {
++ struct usb_device_descriptor *desc = &serial->dev->descriptor;
++ if (desc->idVendor == cpu_to_le16(0x05C6) && desc->idProduct == cpu_to_le16(0x9090))
++ urb->transfer_flags |= URB_ZERO_PACKET;
++ if (desc->idVendor == cpu_to_le16(0x05C6) && desc->idProduct == cpu_to_le16(0x9003))
++ urb->transfer_flags |= URB_ZERO_PACKET;
++ if (desc->idVendor == cpu_to_le16(0x05C6) && desc->idProduct == cpu_to_le16(0x9215))
++ urb->transfer_flags |= URB_ZERO_PACKET;
++ if (desc->idVendor == cpu_to_le16(0x2C7C))
++ urb->transfer_flags |= URB_ZERO_PACKET;
++ }
++#endif
+
+ if (intfdata->use_zlp && dir == USB_DIR_OUT)
+ urb->transfer_flags |= URB_ZERO_PACKET;
diff --git a/target/linux/ipq40xx/patches-5.4/952-net-conntrack-events-support-multiple-registrant.patch b/target/linux/ipq40xx/patches-5.4/952-net-conntrack-events-support-multiple-registrant.patch
new file mode 100644
index 0000000000..c763449594
--- /dev/null
+++ b/target/linux/ipq40xx/patches-5.4/952-net-conntrack-events-support-multiple-registrant.patch
@@ -0,0 +1,313 @@
+From 42824d4b753f84ccf885eca602c5037338b546c8 Mon Sep 17 00:00:00 2001
+From: Zhi Chen <zhichen@codeaurora.org>
+Date: Tue, 13 Jan 2015 14:28:18 -0800
+Subject: [PATCH 3/3] net: conntrack events, support multiple registrant
+
+Merging this patch from kernel 3.4:
+This was supported by old (.28) kernel versions but removed
+because of it's overhead.
+But we need this feature for NA connection manager. Both ipv4
+and ipv6 modules needs to register themselves to ct events.
+
+Change-Id: Iebfb254590fb594f5baf232f849d1b7ae45ef757
+Signed-off-by: Zhi Chen <zhichen@codeaurora.org>
+---
+ include/net/netfilter/nf_conntrack_ecache.h | 42 ++++++++++++++++++-
+ include/net/netns/conntrack.h | 4 ++
+ net/netfilter/Kconfig | 8 ++++
+ net/netfilter/nf_conntrack_core.c | 4 ++
+ net/netfilter/nf_conntrack_ecache.c | 63 +++++++++++++++++++++++++++++
+ net/netfilter/nf_conntrack_netlink.c | 17 ++++++++
+ 6 files changed, 137 insertions(+), 1 deletion(-)
+
+--- a/include/net/netfilter/nf_conntrack_ecache.h
++++ b/include/net/netfilter/nf_conntrack_ecache.h
+@@ -72,6 +72,10 @@ struct nf_ct_event {
+ int report;
+ };
+
++#ifdef CONFIG_NF_CONNTRACK_CHAIN_EVENTS
++extern int nf_conntrack_register_notifier(struct net *net, struct notifier_block *nb);
++extern int nf_conntrack_unregister_notifier(struct net *net, struct notifier_block *nb);
++#else
+ struct nf_ct_event_notifier {
+ int (*fcn)(unsigned int events, struct nf_ct_event *item);
+ };
+@@ -80,6 +84,7 @@ int nf_conntrack_register_notifier(struc
+ struct nf_ct_event_notifier *nb);
+ void nf_conntrack_unregister_notifier(struct net *net,
+ struct nf_ct_event_notifier *nb);
++#endif
+
+ void nf_ct_deliver_cached_events(struct nf_conn *ct);
+ int nf_conntrack_eventmask_report(unsigned int eventmask, struct nf_conn *ct,
+@@ -105,11 +110,13 @@ static inline void
+ nf_conntrack_event_cache(enum ip_conntrack_events event, struct nf_conn *ct)
+ {
+ #ifdef CONFIG_NF_CONNTRACK_EVENTS
+- struct net *net = nf_ct_net(ct);
+ struct nf_conntrack_ecache *e;
++#ifndef CONFIG_NF_CONNTRACK_CHAIN_EVENTS
++ struct net *net = nf_ct_net(ct);
+
+ if (!rcu_access_pointer(net->ct.nf_conntrack_event_cb))
+ return;
++#endif
+
+ e = nf_ct_ecache_find(ct);
+ if (e == NULL)
+@@ -124,10 +131,12 @@ nf_conntrack_event_report(enum ip_conntr
+ u32 portid, int report)
+ {
+ #ifdef CONFIG_NF_CONNTRACK_EVENTS
++#ifndef CONFIG_NF_CONNTRACK_CHAIN_EVENTS
+ const struct net *net = nf_ct_net(ct);
+
+ if (!rcu_access_pointer(net->ct.nf_conntrack_event_cb))
+ return 0;
++#endif
+
+ return nf_conntrack_eventmask_report(1 << event, ct, portid, report);
+ #else
+@@ -139,10 +148,12 @@ static inline int
+ nf_conntrack_event(enum ip_conntrack_events event, struct nf_conn *ct)
+ {
+ #ifdef CONFIG_NF_CONNTRACK_EVENTS
++#ifndef CONFIG_NF_CONNTRACK_CHAIN_EVENTS
+ const struct net *net = nf_ct_net(ct);
+
+ if (!rcu_access_pointer(net->ct.nf_conntrack_event_cb))
+ return 0;
++#endif
+
+ return nf_conntrack_eventmask_report(1 << event, ct, 0, 0);
+ #else
+--- a/include/net/netns/conntrack.h
++++ b/include/net/netns/conntrack.h
+@@ -112,7 +112,11 @@ struct netns_ct {
+
+ struct ct_pcpu __percpu *pcpu_lists;
+ struct ip_conntrack_stat __percpu *stat;
++#ifdef CONFIG_NF_CONNTRACK_CHAIN_EVENTS
++ struct atomic_notifier_head nf_conntrack_chain;
++#else
+ struct nf_ct_event_notifier __rcu *nf_conntrack_event_cb;
++#endif
+ struct nf_exp_event_notifier __rcu *nf_expect_event_cb;
+ struct nf_ip_net nf_ct_proto;
+ #if defined(CONFIG_NF_CONNTRACK_LABELS)
+--- a/net/netfilter/Kconfig
++++ b/net/netfilter/Kconfig
+@@ -136,6 +136,14 @@ config NF_CONNTRACK_EVENTS
+
+ If unsure, say `N'.
+
++config NF_CONNTRACK_CHAIN_EVENTS
++ bool "Register multiple callbacks to ct events"
++ depends on NF_CONNTRACK_EVENTS
++ help
++ Support multiple registrations.
++
++ If unsure, say `N'.
++
+ config NF_CONNTRACK_TIMEOUT
+ bool 'Connection tracking timeout'
+ depends on NETFILTER_ADVANCED
+--- a/net/netfilter/nf_conntrack_core.c
++++ b/net/netfilter/nf_conntrack_core.c
+@@ -2572,6 +2572,9 @@ int nf_conntrack_init_net(struct net *ne
+ nf_conntrack_helper_pernet_init(net);
+ nf_conntrack_proto_pernet_init(net);
+
++#ifdef CONFIG_NF_CONNTRACK_CHAIN_EVENTS
++ ATOMIC_INIT_NOTIFIER_HEAD(&net->ct.nf_conntrack_chain);
++#endif
+ return 0;
+
+ err_expect:
+--- a/net/netfilter/nf_conntrack_ecache.c
++++ b/net/netfilter/nf_conntrack_ecache.c
+@@ -17,6 +17,9 @@
+ #include <linux/stddef.h>
+ #include <linux/err.h>
+ #include <linux/percpu.h>
++#ifdef CONFIG_NF_CONNTRACK_CHAIN_EVENTS
++#include <linux/notifier.h>
++#endif
+ #include <linux/kernel.h>
+ #include <linux/netdevice.h>
+ #include <linux/slab.h>
+@@ -116,7 +119,35 @@ static void ecache_work(struct work_stru
+ if (delay >= 0)
+ schedule_delayed_work(&ctnet->ecache_dwork, delay);
+ }
++#ifdef CONFIG_NF_CONNTRACK_CHAIN_EVENTS
++int nf_conntrack_eventmask_report(unsigned int eventmask, struct nf_conn *ct,
++ u32 portid, int report)
++{
++ struct nf_conntrack_ecache *e;
++ struct net *net = nf_ct_net(ct);
++
++ e = nf_ct_ecache_find(ct);
++ if (e == NULL)
++ return 0;
++
++ if (nf_ct_is_confirmed(ct)) {
++ struct nf_ct_event item = {
++ .ct = ct,
++ .portid = e->portid ? e->portid : portid,
++ .report = report
++ };
++ /* This is a resent of a destroy event? If so, skip missed */
++ unsigned long missed = e->portid ? 0 : e->missed;
++
++ if (!((eventmask | missed) & e->ctmask))
++ return 0;
+
++ atomic_notifier_call_chain(&net->ct.nf_conntrack_chain, eventmask | missed, &item);
++ }
++
++ return 0;
++}
++#else
+ int nf_conntrack_eventmask_report(unsigned int eventmask, struct nf_conn *ct,
+ u32 portid, int report)
+ {
+@@ -171,10 +202,52 @@ out_unlock:
+ rcu_read_unlock();
+ return ret;
+ }
++#endif
+ EXPORT_SYMBOL_GPL(nf_conntrack_eventmask_report);
+
+ /* deliver cached events and clear cache entry - must be called with locally
+ * disabled softirqs */
++#ifdef CONFIG_NF_CONNTRACK_CHAIN_EVENTS
++void nf_ct_deliver_cached_events(struct nf_conn *ct)
++{
++ unsigned long events, missed;
++ struct nf_conntrack_ecache *e;
++ struct nf_ct_event item;
++ struct net *net = nf_ct_net(ct);
++
++ e = nf_ct_ecache_find(ct);
++ if (e == NULL)
++ return;
++
++ events = xchg(&e->cache, 0);
++
++ if (!nf_ct_is_confirmed(ct) || nf_ct_is_dying(ct) || !events)
++ return;
++
++ /* We make a copy of the missed event cache without taking
++ * the lock, thus we may send missed events twice. However,
++ * this does not harm and it happens very rarely. */
++ missed = e->missed;
++
++ if (!((events | missed) & e->ctmask))
++ return;
++
++ item.ct = ct;
++ item.portid = 0;
++ item.report = 0;
++
++ atomic_notifier_call_chain(&net->ct.nf_conntrack_chain,
++ events | missed,
++ &item);
++
++ if (likely(!missed))
++ return;
++
++ spin_lock_bh(&ct->lock);
++ e->missed &= ~missed;
++ spin_unlock_bh(&ct->lock);
++}
++#else
+ void nf_ct_deliver_cached_events(struct nf_conn *ct)
+ {
+ struct net *net = nf_ct_net(ct);
+@@ -225,6 +298,7 @@ void nf_ct_deliver_cached_events(struct
+ out_unlock:
+ rcu_read_unlock();
+ }
++#endif
+ EXPORT_SYMBOL_GPL(nf_ct_deliver_cached_events);
+
+ void nf_ct_expect_event_report(enum ip_conntrack_expect_events event,
+@@ -257,6 +331,13 @@ out_unlock:
+ rcu_read_unlock();
+ }
+
++#ifdef CONFIG_NF_CONNTRACK_CHAIN_EVENTS
++int nf_conntrack_register_notifier(struct net *net,
++ struct notifier_block *nb)
++{
++ return atomic_notifier_chain_register(&net->ct.nf_conntrack_chain, nb);
++}
++#else
+ int nf_conntrack_register_notifier(struct net *net,
+ struct nf_ct_event_notifier *new)
+ {
+@@ -277,8 +358,15 @@ out_unlock:
+ mutex_unlock(&nf_ct_ecache_mutex);
+ return ret;
+ }
++#endif
+ EXPORT_SYMBOL_GPL(nf_conntrack_register_notifier);
+
++#ifdef CONFIG_NF_CONNTRACK_CHAIN_EVENTS
++int nf_conntrack_unregister_notifier(struct net *net, struct notifier_block *nb)
++{
++ return atomic_notifier_chain_unregister(&net->ct.nf_conntrack_chain, nb);
++}
++#else
+ void nf_conntrack_unregister_notifier(struct net *net,
+ struct nf_ct_event_notifier *new)
+ {
+@@ -292,6 +380,7 @@ void nf_conntrack_unregister_notifier(st
+ mutex_unlock(&nf_ct_ecache_mutex);
+ /* synchronize_rcu() is called from ctnetlink_exit. */
+ }
++#endif
+ EXPORT_SYMBOL_GPL(nf_conntrack_unregister_notifier);
+
+ int nf_ct_expect_register_notifier(struct net *net,
+--- a/net/netfilter/nf_conntrack_netlink.c
++++ b/net/netfilter/nf_conntrack_netlink.c
+@@ -680,13 +680,20 @@ static size_t ctnetlink_nlmsg_size(const
+ }
+
+ static int
++#ifdef CONFIG_NF_CONNTRACK_CHAIN_EVENTS
++ctnetlink_conntrack_event(struct notifier_block *this, unsigned long events, void *ptr)
++#else
+ ctnetlink_conntrack_event(unsigned int events, struct nf_ct_event *item)
++#endif
+ {
+ const struct nf_conntrack_zone *zone;
+ struct net *net;
+ struct nlmsghdr *nlh;
+ struct nfgenmsg *nfmsg;
+ struct nlattr *nest_parms;
++#ifdef CONFIG_NF_CONNTRACK_CHAIN_EVENTS
++ struct nf_ct_event *item = (struct nf_ct_event *)ptr;
++#endif
+ struct nf_conn *ct = item->ct;
+ struct sk_buff *skb;
+ unsigned int type;
+@@ -3508,9 +3515,15 @@ static int ctnetlink_stat_exp_cpu(struct
+ }
+
+ #ifdef CONFIG_NF_CONNTRACK_EVENTS
++#ifdef CONFIG_NF_CONNTRACK_CHAIN_EVENTS
++static struct notifier_block ctnl_notifier = {
++ .notifier_call = ctnetlink_conntrack_event,
++};
++#else
+ static struct nf_ct_event_notifier ctnl_notifier = {
+ .fcn = ctnetlink_conntrack_event,
+ };
++#endif
+
+ static struct nf_exp_event_notifier ctnl_notifier_exp = {
+ .fcn = ctnetlink_expect_event,
diff --git a/target/linux/ipq40xx/patches-5.4/953-net-patch-linux-kernel-to-support-shortcut-fe.patch b/target/linux/ipq40xx/patches-5.4/953-net-patch-linux-kernel-to-support-shortcut-fe.patch
new file mode 100644
index 0000000000..6de31b973d
--- /dev/null
+++ b/target/linux/ipq40xx/patches-5.4/953-net-patch-linux-kernel-to-support-shortcut-fe.patch
@@ -0,0 +1,282 @@
+Index: linux-5.4.179/include/linux/if_bridge.h
+===================================================================
+--- linux-5.4.179.orig/include/linux/if_bridge.h
++++ linux-5.4.179/include/linux/if_bridge.h
+@@ -52,6 +52,9 @@ struct br_ip_list {
+
+ extern void brioctl_set(int (*ioctl_hook)(struct net *, unsigned int, void __user *));
+
++extern void br_dev_update_stats(struct net_device *dev,
++ struct rtnl_link_stats64 *nlstats);
++
+ #if IS_ENABLED(CONFIG_BRIDGE) && IS_ENABLED(CONFIG_BRIDGE_IGMP_SNOOPING)
+ int br_multicast_list_adjacent(struct net_device *dev,
+ struct list_head *br_ip_list);
+Index: linux-5.4.179/include/linux/skbuff.h
+===================================================================
+--- linux-5.4.179.orig/include/linux/skbuff.h
++++ linux-5.4.179/include/linux/skbuff.h
+@@ -826,6 +826,10 @@ struct sk_buff {
+ #endif
+ __u8 gro_skip:1;
+
++#ifdef CONFIG_SHORTCUT_FE
++ __u8 fast_forwarded:1;
++#endif
++
+ #ifdef CONFIG_NET_SCHED
+ __u16 tc_index; /* traffic control index */
+ #endif
+Index: linux-5.4.179/include/linux/timer.h
+===================================================================
+--- linux-5.4.179.orig/include/linux/timer.h
++++ linux-5.4.179/include/linux/timer.h
+@@ -18,6 +18,10 @@ struct timer_list {
+ void (*function)(struct timer_list *);
+ u32 flags;
+
++#ifdef CONFIG_SHORTCUT_FE
++ unsigned long cust_data;
++#endif
++
+ #ifdef CONFIG_LOCKDEP
+ struct lockdep_map lockdep_map;
+ #endif
+Index: linux-5.4.179/include/net/netfilter/nf_conntrack_ecache.h
+===================================================================
+--- linux-5.4.179.orig/include/net/netfilter/nf_conntrack_ecache.h
++++ linux-5.4.179/include/net/netfilter/nf_conntrack_ecache.h
+@@ -75,6 +75,8 @@ struct nf_ct_event {
+ #ifdef CONFIG_NF_CONNTRACK_CHAIN_EVENTS
+ extern int nf_conntrack_register_notifier(struct net *net, struct notifier_block *nb);
+ extern int nf_conntrack_unregister_notifier(struct net *net, struct notifier_block *nb);
++extern int nf_conntrack_register_chain_notifier(struct net *net, struct notifier_block *nb);
++extern int nf_conntrack_unregister_chain_notifier(struct net *net, struct notifier_block *nb);
+ #else
+ struct nf_ct_event_notifier {
+ int (*fcn)(unsigned int events, struct nf_ct_event *item);
+Index: linux-5.4.179/net/bridge/br_if.c
+===================================================================
+--- linux-5.4.179.orig/net/bridge/br_if.c
++++ linux-5.4.179/net/bridge/br_if.c
+@@ -763,6 +763,28 @@ void br_port_flags_change(struct net_bri
+ br_recalculate_neigh_suppress_enabled(br);
+ }
+
++void br_dev_update_stats(struct net_device *dev,
++ struct rtnl_link_stats64 *nlstats)
++{
++ struct net_bridge *br;
++ struct pcpu_sw_netstats *stats;
++
++ /* Is this a bridge? */
++ if (!(dev->priv_flags & IFF_EBRIDGE))
++ return;
++
++ br = netdev_priv(dev);
++ stats = this_cpu_ptr(br->stats);
++
++ u64_stats_update_begin(&stats->syncp);
++ stats->rx_packets += nlstats->rx_packets;
++ stats->rx_bytes += nlstats->rx_bytes;
++ stats->tx_packets += nlstats->tx_packets;
++ stats->tx_bytes += nlstats->tx_bytes;
++ u64_stats_update_end(&stats->syncp);
++}
++EXPORT_SYMBOL_GPL(br_dev_update_stats);
++
+ bool br_port_flag_is_set(const struct net_device *dev, unsigned long flag)
+ {
+ struct net_bridge_port *p;
+Index: linux-5.4.179/net/core/dev.c
+===================================================================
+--- linux-5.4.179.orig/net/core/dev.c
++++ linux-5.4.179/net/core/dev.c
+@@ -3218,9 +3218,17 @@ static int xmit_one(struct sk_buff *skb,
+ unsigned int len;
+ int rc;
+
++#ifdef CONFIG_SHORTCUT_FE
++ /* If this skb has been fast forwarded then we don't want it to
++ * go to any taps (by definition we're trying to bypass them).
++ */
++ if (!skb->fast_forwarded) {
++#endif
+ if (dev_nit_active(dev))
+ dev_queue_xmit_nit(skb, dev);
+-
++#ifdef CONFIG_SHORTCUT_FE
++ }
++#endif
+ #ifdef CONFIG_ETHERNET_PACKET_MANGLE
+ if (!dev->eth_mangle_tx ||
+ (skb = dev->eth_mangle_tx(dev, skb)) != NULL)
+@@ -4753,6 +4761,13 @@ void netdev_rx_handler_unregister(struct
+ }
+ EXPORT_SYMBOL_GPL(netdev_rx_handler_unregister);
+
++#ifdef CONFIG_SHORTCUT_FE
++int (*athrs_fast_nat_recv)(struct sk_buff *skb) __rcu __read_mostly;
++EXPORT_SYMBOL_GPL(athrs_fast_nat_recv);
++int (*gl_parental_control_handle)(struct sk_buff *skb) __rcu __read_mostly;
++EXPORT_SYMBOL_GPL(gl_parental_control_handle);
++#endif
++
+ /*
+ * Limit the use of PFMEMALLOC reserves to those protocols that implement
+ * the special handling of PFMEMALLOC skbs.
+@@ -4803,6 +4818,11 @@ static int __netif_receive_skb_core(stru
+ int ret = NET_RX_DROP;
+ __be16 type;
+
++#ifdef CONFIG_SHORTCUT_FE
++ int (*fast_recv)(struct sk_buff *skb);
++ int (*gl_pc_recv)(struct sk_buff *skb);
++#endif
++
+ net_timestamp_check(!netdev_tstamp_prequeue, skb);
+
+ trace_netif_receive_skb(skb);
+@@ -4842,6 +4862,24 @@ another_round:
+ goto out;
+ }
+
++#ifdef CONFIG_SHORTCUT_FE
++ gl_pc_recv = rcu_dereference(gl_parental_control_handle);
++ if(gl_pc_recv){
++ if (gl_pc_recv(skb) == NET_RX_DROP){
++ ret = NET_RX_DROP;
++ goto out;
++ }
++ }
++
++ fast_recv = rcu_dereference(athrs_fast_nat_recv);
++ if (fast_recv) {
++ if (fast_recv(skb)) {
++ ret = NET_RX_SUCCESS;
++ goto out;
++ }
++ }
++#endif
++
+ if (skb_skip_tc_classify(skb))
+ goto skip_classify;
+
+Index: linux-5.4.179/net/Kconfig
+===================================================================
+--- linux-5.4.179.orig/net/Kconfig
++++ linux-5.4.179/net/Kconfig
+@@ -473,3 +473,6 @@ config HAVE_CBPF_JIT
+ # Extended BPF JIT (eBPF)
+ config HAVE_EBPF_JIT
+ bool
++
++config SHORTCUT_FE
++ bool "Enables kernel network stack path for Shortcut Forwarding Engine
+Index: linux-5.4.179/net/netfilter/nf_conntrack_proto_tcp.c
+===================================================================
+--- linux-5.4.179.orig/net/netfilter/nf_conntrack_proto_tcp.c
++++ linux-5.4.179/net/netfilter/nf_conntrack_proto_tcp.c
+@@ -34,11 +34,19 @@
+ /* Do not check the TCP window for incoming packets */
+ static int nf_ct_tcp_no_window_check __read_mostly = 1;
+
++#ifdef CONFIG_SHORTCUT_FE
++EXPORT_SYMBOL_GPL(nf_ct_tcp_no_window_check);
++#endif
++
+ /* "Be conservative in what you do,
+ be liberal in what you accept from others."
+ If it's non-zero, we mark only out of window RST segments as INVALID. */
+ static int nf_ct_tcp_be_liberal __read_mostly = 0;
+
++#ifdef CONFIG_SHORTCUT_FE
++EXPORT_SYMBOL_GPL(nf_ct_tcp_be_liberal);
++#endif
++
+ /* If it is set to zero, we disable picking up already established
+ connections. */
+ static int nf_ct_tcp_loose __read_mostly = 1;
+Index: linux-5.4.179/net/netfilter/nf_conntrack_ecache.c
+===================================================================
+--- linux-5.4.179.orig/net/netfilter/nf_conntrack_ecache.c
++++ linux-5.4.179/net/netfilter/nf_conntrack_ecache.c
+@@ -158,7 +158,11 @@ int nf_conntrack_eventmask_report(unsign
+
+ rcu_read_lock();
+ notify = rcu_dereference(net->ct.nf_conntrack_event_cb);
++#ifdef CONFIG_NF_CONNTRACK_CHAIN_EVENTS
++ if (!notify && !rcu_dereference_raw(net->ct.nf_conntrack_chain.head))
++#else
+ if (!notify)
++#endif
+ goto out_unlock;
+
+ e = nf_ct_ecache_find(ct);
+@@ -177,7 +181,14 @@ int nf_conntrack_eventmask_report(unsign
+ if (!((eventmask | missed) & e->ctmask))
+ goto out_unlock;
+
++#ifdef CONFIG_NF_CONNTRACK_CHAIN_EVENTS
++ ret = atomic_notifier_call_chain(&net->ct.nf_conntrack_chain,
++ eventmask | missed, &item);
++ if (notify)
++ ret = notify->fcn(eventmask | missed, &item);
++#else
+ ret = notify->fcn(eventmask | missed, &item);
++#endif
+ if (unlikely(ret < 0 || missed)) {
+ spin_lock_bh(&ct->lock);
+ if (ret < 0) {
+@@ -259,7 +270,11 @@ void nf_ct_deliver_cached_events(struct
+
+ rcu_read_lock();
+ notify = rcu_dereference(net->ct.nf_conntrack_event_cb);
++#ifdef CONFIG_NF_CONNTRACK_CHAIN_EVENTS
++ if ((notify == NULL) && !rcu_dereference_raw(net->ct.nf_conntrack_chain.head))
++#else
+ if (notify == NULL)
++#endif
+ goto out_unlock;
+
+ e = nf_ct_ecache_find(ct);
+@@ -283,7 +298,15 @@ void nf_ct_deliver_cached_events(struct
+ item.portid = 0;
+ item.report = 0;
+
++#ifdef CONFIG_NF_CONNTRACK_CHAIN_EVENTS
++ ret = atomic_notifier_call_chain(&net->ct.nf_conntrack_chain,
++ events | missed,
++ &item);
++ if (notify != NULL)
++ ret = notify->fcn(events | missed, &item);
++#else
+ ret = notify->fcn(events | missed, &item);
++#endif
+
+ if (likely(ret == 0 && !missed))
+ goto out_unlock;
+@@ -337,6 +360,11 @@ int nf_conntrack_register_notifier(struc
+ {
+ return atomic_notifier_chain_register(&net->ct.nf_conntrack_chain, nb);
+ }
++int nf_conntrack_register_chain_notifier(struct net *net, struct notifier_block *nb)
++{
++ return atomic_notifier_chain_register(&net->ct.nf_conntrack_chain, nb);
++}
++EXPORT_SYMBOL_GPL(nf_conntrack_register_chain_notifier);
+ #else
+ int nf_conntrack_register_notifier(struct net *net,
+ struct nf_ct_event_notifier *new)
+@@ -366,6 +394,11 @@ int nf_conntrack_unregister_notifier(str
+ {
+ return atomic_notifier_chain_unregister(&net->ct.nf_conntrack_chain, nb);
+ }
++int nf_conntrack_unregister_chain_notifier(struct net *net, struct notifier_block *nb)
++{
++ return atomic_notifier_chain_unregister(&net->ct.nf_conntrack_chain, nb);
++}
++EXPORT_SYMBOL_GPL(nf_conntrack_unregister_chain_notifier);
+ #else
+ void nf_conntrack_unregister_notifier(struct net *net,
+ struct nf_ct_event_notifier *new)
--
2.17.1