From d3b8d0071d584b93c9b17dd6984f380b04052483 Mon Sep 17 00:00:00 2001 From: Takashi ISHIKAWA Date: Tue, 15 Nov 2022 22:50:27 +0900 Subject: [PATCH] ipq806x: fix l2tpv2 and tunipip6 NSS offloading, add WG2600HP support ipq806x: add NEC WG2600HP NSS offloading support ipq806x: fix qca-nss-l2tpv2 compile ipq806x: fix qca-nss-tunipip6 lock ipq806x: fix kernel panic at /sys/kernel/debug/qcom_socinfo/*/* Signed-off-by: Takashi ISHIKAWA --- .../patches-5.15/999-004-fix-socinfo.patch | 46 ++ .../999-005-add-wg2600hp-nss-support.patch | 54 +++ ...-nss-clients-l2tp-offloading-support.patch | 402 ++++++++++++++++++ ...a-nss-clients-iptunnel-lock-this-cpu.patch | 22 + 4 files changed, 524 insertions(+) create mode 100644 target/linux/ipq806x/patches-5.15/999-004-fix-socinfo.patch create mode 100644 target/linux/ipq806x/patches-5.15/999-005-add-wg2600hp-nss-support.patch create mode 100644 target/linux/ipq806x/patches-5.15/999-206-qca-nss-clients-l2tp-offloading-support.patch create mode 100644 target/linux/ipq806x/patches-5.15/999-207-qca-nss-clients-iptunnel-lock-this-cpu.patch diff --git a/target/linux/ipq806x/patches-5.15/999-004-fix-socinfo.patch b/target/linux/ipq806x/patches-5.15/999-004-fix-socinfo.patch new file mode 100644 index 0000000000..f0b85bb3b2 --- /dev/null +++ b/target/linux/ipq806x/patches-5.15/999-004-fix-socinfo.patch @@ -0,0 +1,46 @@ +--- a/drivers/soc/qcom/socinfo.c 2022-11-07 08:55:57.097003500 +0900 ++++ b/drivers/soc/qcom/socinfo.c 2022-11-07 09:03:58.447003500 +0900 +@@ -230,6 +230,7 @@ static const struct soc_id soc_id[] = { + { 198, "MSM8126" }, + { 199, "APQ8026" }, + { 200, "MSM8926" }, ++ { 202, "IPQ8064" }, + { 205, "MSM8326" }, + { 206, "MSM8916" }, + { 207, "MSM8994" }, +@@ -414,11 +415,13 @@ QCOM_OPEN(pmic_die_rev, qcom_show_pmic_d + QCOM_OPEN(chip_id, qcom_show_chip_id); + + #define DEFINE_IMAGE_OPS(type) \ +-static int show_image_##type(struct seq_file *seq, void *p) \ ++static int show_image_##type(struct seq_file *seq, void *p) \ + { \ + struct smem_image_version *image_version = seq->private; \ +- if (image_version->type[0] != '\0') \ +- seq_printf(seq, "%s\n", image_version->type); \ ++ if(!image_version && !image_version->type[0]) { \ ++ seq_puts(seq, image_version->type); \ ++ seq_puts(seq, "\n"); \ ++ } \ + return 0; \ + } \ + static int open_image_##type(struct inode *inode, struct file *file) \ +@@ -606,7 +609,7 @@ static int qcom_socinfo_probe(struct pla + if (!qs) + return -ENOMEM; + +- qs->attr.family = "Snapdragon"; ++ qs->attr.family = "IPQ"; + qs->attr.machine = socinfo_machine(&pdev->dev, + le32_to_cpu(info->id)); + qs->attr.soc_id = devm_kasprintf(&pdev->dev, GFP_KERNEL, "%u", +@@ -623,6 +626,9 @@ static int qcom_socinfo_probe(struct pla + if (IS_ERR(qs->soc_dev)) + return PTR_ERR(qs->soc_dev); + ++ pr_info("CPU: %s, SoC Version: %s\ id: %d fmt: %x\n", qs->attr.machine, ++ qs->attr.revision, info->id, qs->info.fmt); ++ + socinfo_debugfs_init(qs, info, item_size); + + /* Feed the soc specific unique data into entropy pool */ diff --git a/target/linux/ipq806x/patches-5.15/999-005-add-wg2600hp-nss-support.patch b/target/linux/ipq806x/patches-5.15/999-005-add-wg2600hp-nss-support.patch new file mode 100644 index 0000000000..6c00d2f4f6 --- /dev/null +++ b/target/linux/ipq806x/patches-5.15/999-005-add-wg2600hp-nss-support.patch @@ -0,0 +1,54 @@ +--- a/arch/arm/boot/dts/qcom-ipq8064-wg2600hp.dts ++++ b/arch/arm/boot/dts/qcom-ipq8064-wg2600hp.dts +@@ -161,9 +161,25 @@ + &gmac1 { + status = "okay"; + ++ compatible = "qcom,nss-gmac"; ++ reg = <0x37200000 0x200000>; ++ interrupts = ; ++ + phy-mode = "rgmii"; + qcom,id = <1>; + ++ qcom,pcs-chanid = <0>; ++ qcom,phy-mdio-addr = <4>; /* AKRO: 4->1 */ ++ qcom,poll-required = <0>; /* AKRO: 0->1 */ ++ qcom,rgmii-delay = <1>; /* AKRO: 1->0 */ ++ qcom,phy_mii_type = <0>; /* AKRO: 0->8(PHY_INTERFACE_MODE_RGMII) */ ++ qcom,emulation = <0>; ++ qcom,forced-speed = <1000>; ++ qcom,forced-duplex = <1>; ++ qcom,socver = <0>; ++ qcom,irq = <255>; ++ mdiobus = <&mdio0>; ++ + pinctrl-0 = <&rgmii2_pins>; + pinctrl-names = "default"; + +@@ -179,9 +195,25 @@ + &gmac2 { + status = "okay"; + ++ compatible = "qcom,nss-gmac"; ++ reg = <0x37400000 0x200000>; ++ interrupts = ; ++ + phy-mode = "sgmii"; + qcom,id = <2>; + ++ qcom,pcs-chanid = <1>; ++ qcom,phy-mdio-addr = <0>; /* AKRO: 0->0 */ ++ qcom,poll-required = <0>; /* no polling */ ++ qcom,rgmii-delay = <0>; ++ qcom,phy_mii_type = <1>; /* AKRO: 1->4(PHY_INTERFACE_MODE_SGMII) */ ++ qcom,emulation = <0>; ++ qcom,forced-speed = <1000>; ++ qcom,forced-duplex = <1>; ++ qcom,socver = <0>; ++ qcom,irq = <258>; ++ mdiobus = <&mdio0>; ++ + nvmem-cells = <&macaddr_PRODUCTDATA_0>; + nvmem-cell-names = "mac-address"; + diff --git a/target/linux/ipq806x/patches-5.15/999-206-qca-nss-clients-l2tp-offloading-support.patch b/target/linux/ipq806x/patches-5.15/999-206-qca-nss-clients-l2tp-offloading-support.patch new file mode 100644 index 0000000000..e254066fcc --- /dev/null +++ b/target/linux/ipq806x/patches-5.15/999-206-qca-nss-clients-l2tp-offloading-support.patch @@ -0,0 +1,402 @@ +--- a/include/linux/ppp_channel.h ++++ b/include/linux/ppp_channel.h +@@ -45,6 +56,47 @@ struct ppp_channel { + }; + + #ifdef __KERNEL__ ++/* Call this to obtain the underlying protocol of the PPP channel, ++ * e.g. PX_PROTO_OE ++ */ ++extern int ppp_channel_get_protocol(struct ppp_channel *); ++ ++/* Call this to hold a channel */ ++extern bool ppp_channel_hold(struct ppp_channel *); ++ ++/* Call this to release a hold you have upon a channel */ ++extern void ppp_channel_release(struct ppp_channel *); ++ ++/* Release hold on PPP channels */ ++extern void ppp_release_channels(struct ppp_channel *channels[], ++ unsigned int chan_sz); ++ ++/* Test if ppp xmit lock is locked */ ++extern bool ppp_is_xmit_locked(struct net_device *dev); ++ ++/* Call this get protocol version */ ++extern int ppp_channel_get_proto_version(struct ppp_channel *); ++ ++/* Get the device index associated with a channel, or 0, if none */ ++extern int ppp_dev_index(struct ppp_channel *); ++ ++/* Hold PPP channels for the PPP device */ ++extern int ppp_hold_channels(struct net_device *dev, ++ struct ppp_channel *channels[], ++ unsigned int chan_sz); ++ ++/* Test if the ppp device is a multi-link ppp device */ ++extern int ppp_is_multilink(struct net_device *dev); ++ ++/* Update statistics of the PPP net_device by incrementing related ++ * statistics field value with corresponding parameter ++ */ ++extern void ppp_update_stats(struct net_device *dev, unsigned long rx_packets, ++ unsigned long rx_bytes, unsigned long tx_packets, ++ unsigned long tx_bytes, unsigned long rx_errors, ++ unsigned long tx_errors, unsigned long rx_dropped, ++ unsigned long tx_dropped); ++ + /* Called by the channel when it can send some more data. */ + extern void ppp_output_wakeup(struct ppp_channel *); + +@@ -83,5 +135,17 @@ extern char *ppp_dev_name(struct ppp_cha + * that ppp_unregister_channel returns. + */ + ++/* QCA NSS Clients Support - Start */ ++/* PPP channel connection event types */ ++#define PPP_CHANNEL_DISCONNECT 0 ++#define PPP_CHANNEL_CONNECT 1 ++ ++/* Register the PPP channel connect notifier */ ++extern void ppp_channel_connection_register_notify(struct notifier_block *nb); ++ ++/* Unregister the PPP channel connect notifier */ ++extern void ppp_channel_connection_unregister_notify(struct notifier_block *nb); ++/* QCA NSS Clients Support - End */ ++ + #endif /* __KERNEL__ */ + #endif +--- a/include/linux/if_pppol2tp.h ++++ b/include/linux/if_pppol2tp.h +@@ -14,4 +14,30 @@ + #include + #include + ++/* QCA NSS ECM support - Start */ ++/* ++ * Holds L2TP channel info ++ */ ++struct pppol2tp_common_addr { ++ int tunnel_version; /* v2 or v3 */ ++ __u32 local_tunnel_id, remote_tunnel_id; /* tunnel id */ ++ __u32 local_session_id, remote_session_id; /* session id */ ++ struct sockaddr_in local_addr, remote_addr; /* ip address and port */ ++}; ++ ++/* ++ * L2TP channel operations ++ */ ++struct pppol2tp_channel_ops { ++ struct ppp_channel_ops ops; /* ppp channel ops */ ++}; ++ ++/* ++ * exported function which calls pppol2tp channel's get addressing ++ * function ++ */ ++extern int pppol2tp_channel_addressing_get(struct ppp_channel *, ++ struct pppol2tp_common_addr *); ++/* QCA NSS ECM support - End */ ++ + #endif +--- a/net/l2tp/l2tp_ppp.c ++++ b/net/l2tp/l2tp_ppp.c +@@ -380,6 +392,13 @@ static int pppol2tp_xmit(struct ppp_chan + skb->data[0] = PPP_ALLSTATIONS; + skb->data[1] = PPP_UI; + ++ /* QCA NSS ECM support - start */ ++ /* set incoming interface as the ppp interface */ ++ if ((skb->protocol == htons(ETH_P_IP)) || ++ (skb->protocol == htons(ETH_P_IPV6))) ++ skb->skb_iif = ppp_dev_index(chan); ++ /* QCA NSS ECM support - End */ ++ + local_bh_disable(); + l2tp_xmit_skb(session, skb, session->hdr_len); + local_bh_enable(); +@@ -1749,6 +1768,109 @@ static void __exit pppol2tp_exit(void) + unregister_pernet_device(&pppol2tp_net_ops); + } + ++/* QCA NSS ECM support - Start */ ++/* pppol2tp_hold_chan() */ ++static void pppol2tp_hold_chan(struct ppp_channel *chan) ++{ ++ struct sock *sk = (struct sock *)chan->private; ++ ++ sock_hold(sk); ++} ++ ++/* pppol2tp_release_chan() */ ++static void pppol2tp_release_chan(struct ppp_channel *chan) ++{ ++ struct sock *sk = (struct sock *)chan->private; ++ ++ sock_put(sk); ++} ++ ++/* pppol2tp_get_channel_protocol() ++ * Return the protocol type of the L2TP over PPP protocol ++ */ ++static int pppol2tp_get_channel_protocol(struct ppp_channel *chan) ++{ ++ return PX_PROTO_OL2TP; ++} ++ ++/* pppol2tp_get_channel_protocol_ver() ++ * Return the protocol version of the L2TP over PPP protocol ++ */ ++static int pppol2tp_get_channel_protocol_ver(struct ppp_channel *chan) ++{ ++ struct sock *sk; ++ struct l2tp_session *session; ++ struct l2tp_tunnel *tunnel; ++ int version = 0; ++ ++ if (chan && chan->private) ++ sk = (struct sock *)chan->private; ++ else ++ return -1; ++ ++ /* Get session and tunnel contexts from the socket */ ++ session = pppol2tp_sock_to_session(sk); ++ if (!session) ++ return -1; ++ ++ tunnel = session->tunnel; ++ if (!tunnel) { ++ sock_put(sk); ++ return -1; ++ } ++ ++ version = tunnel->version; ++ ++ sock_put(sk); ++ ++ return version; ++} ++ ++/* pppol2tp_get_addressing() */ ++static int pppol2tp_get_addressing(struct ppp_channel *chan, ++ struct pppol2tp_common_addr *addr) ++{ ++ struct sock *sk = (struct sock *)chan->private; ++ struct l2tp_session *session; ++ struct l2tp_tunnel *tunnel; ++ struct inet_sock *isk = NULL; ++ int err = -ENXIO; ++ ++ /* Get session and tunnel contexts from the socket */ ++ session = pppol2tp_sock_to_session(sk); ++ if (!session) ++ return err; ++ ++ tunnel = session->tunnel; ++ if (!tunnel) { ++ sock_put(sk); ++ return err; ++ } ++ isk = inet_sk(tunnel->sock); ++ ++ addr->local_tunnel_id = tunnel->tunnel_id; ++ addr->remote_tunnel_id = tunnel->peer_tunnel_id; ++ addr->local_session_id = session->session_id; ++ addr->remote_session_id = session->peer_session_id; ++ ++ addr->local_addr.sin_port = isk->inet_sport; ++ addr->remote_addr.sin_port = isk->inet_dport; ++ addr->local_addr.sin_addr.s_addr = isk->inet_saddr; ++ addr->remote_addr.sin_addr.s_addr = isk->inet_daddr; ++ ++ sock_put(sk); ++ return 0; ++} ++ ++/* pppol2tp_channel_addressing_get() */ ++int pppol2tp_channel_addressing_get(struct ppp_channel *chan, ++ struct pppol2tp_common_addr *addr) ++{ ++ return pppol2tp_get_addressing(chan, addr); ++} ++EXPORT_SYMBOL(pppol2tp_channel_addressing_get); ++/* QCA NSS ECM support - End */ ++ + module_init(pppol2tp_init); + module_exit(pppol2tp_exit); + +*** a/drivers/net/ppp/ppp_generic.c 2022-04-06 17:25:52.144576100 +0900 +--- b/drivers/net/ppp/ppp_generic.c 2022-04-06 17:32:55.164576100 +0900 +*************** int ppp_is_multilink(struct net_device * +*** 3502,3507 **** +--- 3502,3533 ---- + } + EXPORT_SYMBOL(ppp_is_multilink); + ++ /* __ppp_is_multilink() ++ * Returns >0 if the device is a multilink PPP netdevice, 0 if not or < 0 ++ * if the device is not PPP. Caller should acquire ppp_lock before calling ++ * this function ++ */ ++ int __ppp_is_multilink(struct net_device *dev) ++ { ++ struct ppp *ppp; ++ unsigned int flags; ++ ++ if (!dev) ++ return -1; ++ ++ if (dev->type != ARPHRD_PPP) ++ return -1; ++ ++ ppp = netdev_priv(dev); ++ flags = ppp->flags; ++ ++ if (flags & SC_MULTILINK) ++ return 1; ++ ++ return 0; ++ } ++ EXPORT_SYMBOL(__ppp_is_multilink); ++ + /* ppp_channel_get_protocol() + * Call this to obtain the underlying protocol of the PPP channel, + * e.g. PX_PROTO_OE +*************** int ppp_hold_channels(struct net_device +*** 3606,3611 **** +--- 3632,3690 ---- + } + EXPORT_SYMBOL(ppp_hold_channels); + ++ /* __ppp_hold_channels() ++ * Returns the PPP channels of the PPP device, storing each one into ++ * channels[]. ++ * ++ * channels[] has chan_sz elements. ++ * This function returns the number of channels stored, up to chan_sz. ++ * It will return < 0 if the device is not PPP. ++ * ++ * You MUST release the channels using ppp_release_channels(). ++ */ ++ int __ppp_hold_channels(struct net_device *dev, struct ppp_channel *channels[], ++ unsigned int chan_sz) ++ { ++ struct ppp *ppp; ++ int c; ++ struct channel *pch; ++ ++ if (!dev) ++ return -1; ++ ++ if (dev->type != ARPHRD_PPP) ++ return -1; ++ ++ ppp = netdev_priv(dev); ++ ++ c = 0; ++ list_for_each_entry(pch, &ppp->channels, clist) { ++ struct ppp_channel *chan; ++ ++ if (!pch->chan) { ++ /* Channel is going / gone away */ ++ continue; ++ } ++ ++ if (c == chan_sz) { ++ /* No space to record channel */ ++ return c; ++ } ++ ++ /* Hold the channel, if supported */ ++ chan = pch->chan; ++ if (!chan->ops->hold) ++ continue; ++ ++ chan->ops->hold(chan); ++ ++ /* Record the channel */ ++ channels[c++] = chan; ++ } ++ return c; ++ } ++ EXPORT_SYMBOL(__ppp_hold_channels); ++ + /* ppp_release_channels() + * Releases channels + */ +--- a/net/l2tp/l2tp_core.h ++++ b/net/l2tp/l2tp_core.h +@@ -232,6 +232,9 @@ struct l2tp_session *l2tp_session_get_nt + struct l2tp_session *l2tp_session_get_by_ifname(const struct net *net, + const char *ifname); + ++void l2tp_stats_update(struct l2tp_tunnel *tunnel, struct l2tp_session *session, ++ struct l2tp_stats *stats); ++ + /* Tunnel and session lifetime management. + * Creation of a new instance is a two-step process: create, then register. + * Destruction is triggered using the *_delete functions, and completes asynchronously. +*** a/net/l2tp/l2tp_ppp.c 2022-08-20 11:19:37.748454800 +0900 +--- b/net/l2tp/l2tp_ppp.c 2022-08-20 11:24:40.138454800 +0900 +*************** struct pppol2tp_session { +*** 123,131 **** + }; + + static int pppol2tp_xmit(struct ppp_channel *chan, struct sk_buff *skb); +! +! static const struct ppp_channel_ops pppol2tp_chan_ops = { +! .start_xmit = pppol2tp_xmit, + }; + + static const struct proto_ops pppol2tp_ops; +--- 123,139 ---- + }; + + static int pppol2tp_xmit(struct ppp_channel *chan, struct sk_buff *skb); +! static int pppol2tp_get_channel_protocol(struct ppp_channel *); +! static int pppol2tp_get_channel_protocol_ver(struct ppp_channel *); +! static void pppol2tp_hold_chan(struct ppp_channel *); +! static void pppol2tp_release_chan(struct ppp_channel *); +! +! static const struct pppol2tp_channel_ops pppol2tp_chan_ops = { +! .ops.start_xmit = pppol2tp_xmit, +! .ops.get_channel_protocol = pppol2tp_get_channel_protocol, +! .ops.get_channel_protocol_ver = pppol2tp_get_channel_protocol_ver, +! .ops.hold = pppol2tp_hold_chan, +! .ops.release = pppol2tp_release_chan, + }; + + static const struct proto_ops pppol2tp_ops; +*************** static int pppol2tp_connect(struct socke +*** 809,815 **** + po->chan.hdrlen = PPPOL2TP_L2TP_HDR_SIZE_NOSEQ; + + po->chan.private = sk; +! po->chan.ops = &pppol2tp_chan_ops; + po->chan.mtu = pppol2tp_tunnel_mtu(tunnel); + + error = ppp_register_net_channel(sock_net(sk), &po->chan); +--- 875,881 ---- + po->chan.hdrlen = PPPOL2TP_L2TP_HDR_SIZE_NOSEQ; + + po->chan.private = sk; +! po->chan.ops = (struct ppp_channel_ops *)&pppol2tp_chan_ops.ops; + po->chan.mtu = pppol2tp_tunnel_mtu(tunnel); + + error = ppp_register_net_channel(sock_net(sk), &po->chan); +--- a/include/linux/ppp_channel.h 2022-11-08 21:01:55.607003500 +0900 ++++ b/include/linux/ppp_channel.h 2022-11-08 21:03:40.027003500 +0900 +@@ -87,9 +87,13 @@ extern int ppp_dev_index(struct ppp_chan + extern int ppp_hold_channels(struct net_device *dev, + struct ppp_channel *channels[], + unsigned int chan_sz); ++extern int __ppp_hold_channels(struct net_device *dev, ++ struct ppp_channel *channels[], ++ unsigned int chan_sz); + + /* Test if the ppp device is a multi-link ppp device */ + extern int ppp_is_multilink(struct net_device *dev); ++extern int __ppp_is_multilink(struct net_device *dev); + + /* Update statistics of the PPP net_device by incrementing related + * statistics field value with corresponding parameter diff --git a/target/linux/ipq806x/patches-5.15/999-207-qca-nss-clients-iptunnel-lock-this-cpu.patch b/target/linux/ipq806x/patches-5.15/999-207-qca-nss-clients-iptunnel-lock-this-cpu.patch new file mode 100644 index 0000000000..25df2e3bbf --- /dev/null +++ b/target/linux/ipq806x/patches-5.15/999-207-qca-nss-clients-iptunnel-lock-this-cpu.patch @@ -0,0 +1,22 @@ +--- a/net/ipv6/ip6_tunnel.c 2022-11-08 20:48:53.057003500 +0900 ++++ b/net/ipv6/ip6_tunnel.c 2022-11-08 20:49:15.247003500 +0900 +@@ -2435,7 +2435,7 @@ nla_put_failure: + */ + void ip6_update_offload_stats(struct net_device *dev, void *ptr) + { +- struct pcpu_sw_netstats *tstats = per_cpu_ptr(dev->tstats, 0); ++ struct pcpu_sw_netstats *tstats = this_cpu_ptr(dev->tstats); + const struct pcpu_sw_netstats *offload_stats = + (struct pcpu_sw_netstats *)ptr; + +--- a/net/ipv6/sit.c 2022-11-08 20:49:54.917003500 +0900 ++++ b/net/ipv6/sit.c 2022-11-08 20:50:05.637003500 +0900 +@@ -1797,7 +1797,7 @@ nla_put_failure: + /* QCA NSS Clients Support - Start */ + void ipip6_update_offload_stats(struct net_device *dev, void *ptr) + { +- struct pcpu_sw_netstats *tstats = per_cpu_ptr(dev->tstats, 0); ++ struct pcpu_sw_netstats *tstats = this_cpu_ptr(dev->tstats); + const struct pcpu_sw_netstats *offload_stats = + (struct pcpu_sw_netstats *)ptr; +