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 <tishi-github@tthy.org>
This commit is contained in:
Takashi ISHIKAWA
2022-11-15 22:50:27 +09:00
committed by Lucas Asvio
parent c4bde93fa8
commit d3b8d0071d
4 changed files with 524 additions and 0 deletions

View File

@@ -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 */

View File

@@ -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 = <GIC_SPI 223 IRQ_TYPE_LEVEL_HIGH>;
+
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 = <GIC_SPI 226 IRQ_TYPE_LEVEL_HIGH>;
+
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";

View File

@@ -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 <linux/in6.h>
#include <uapi/linux/if_pppol2tp.h>
+/* 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

View File

@@ -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;