Netdev List
 help / color / mirror / Atom feed
* Re: [ovs-discuss] [ovs-dev] [PATCH] datapath: fix crash when ipv6 fragment pkt recalculate L4 checksum
From: Tonghao Zhang @ 2021-12-10  4:48 UTC (permalink / raw)
  To: zhounan (E)
  Cc: netdev@vger.kernel.org, dev@openvswitch.org, bugs@openvswitch.org,
	pravin.ovn@gmail.com, Lichunhe, liucheng (J),
	Hejiajun (he jiajun, SOCF&uDF ), Greg Rose
In-Reply-To: <396da6f61fa948ac854531e935921dfc@huawei.com>

On Fri, Dec 10, 2021 at 10:59 AM zhounan (E) via discuss
<ovs-discuss@openvswitch.org> wrote:
>
> From: Zhou Nan <zhounan14@huawei.com>
>
> When we set ipv6 addr, we need to recalculate checksum of L4 header.
> In our testcase, after send ipv6 fragment package, KASAN detect "use after free" when calling function update_ipv6_checksum, and crash occurred after a while.
> If ipv6 package is fragment, and it is not first seg, we should not recalculate checksum of L4 header since this kind of package has no
> L4 header.
> To prevent crash, we set "recalc_csum" "false" when calling function "set_ipv6_addr".
> We also find that function skb_ensure_writable (make sure L4 header is writable) is helpful before calling inet_proto_csum_replace16 to recalculate checksum.
>
> Fixes: ada5efce102d6191e5c66fc385ba52a2d340ef50
>        ("datapath: Fix IPv6 later frags parsing")
>
> Signed-off-by: Zhou Nan <zhounan14@huawei.com>
> ---
>  datapath/actions.c | 20 +++++++++++++++++++-
>  1 file changed, 19 insertions(+), 1 deletion(-)
>
> diff --git a/datapath/actions.c b/datapath/actions.c index fbf4457..52cf03e 100644
> --- a/datapath/actions.c
> +++ b/datapath/actions.c
> @@ -456,12 +456,21 @@ static void update_ipv6_checksum(struct sk_buff *skb, u8 l4_proto,
>                                  __be32 addr[4], const __be32 new_addr[4])  {
>         int transport_len = skb->len - skb_transport_offset(skb);
> +       int err;
>
>         if (l4_proto == NEXTHDR_TCP) {
> +               err = skb_ensure_writable(skb, skb_transport_offset(skb) +
> +                               sizeof(struct tcphdr));
> +               if (unlikely(err))
> +                       return;
>                 if (likely(transport_len >= sizeof(struct tcphdr)))
>                         inet_proto_csum_replace16(&tcp_hdr(skb)->check, skb,
>                                                   addr, new_addr, true);
>         } else if (l4_proto == NEXTHDR_UDP) {
> +               err = skb_ensure_writable(skb, skb_transport_offset(skb) +
> +                               sizeof(struct udphdr));
> +               if (unlikely(err))
> +                       return;
>                 if (likely(transport_len >= sizeof(struct udphdr))) {
>                         struct udphdr *uh = udp_hdr(skb);
>
> @@ -473,6 +482,10 @@ static void update_ipv6_checksum(struct sk_buff *skb, u8 l4_proto,
>                         }
>                 }
>         } else if (l4_proto == NEXTHDR_ICMP) {
> +               err = skb_ensure_writable(skb, skb_transport_offset(skb) +
> +                               sizeof(struct icmp6hdr));
> +               if (unlikely(err))
> +                       return;
>                 if (likely(transport_len >= sizeof(struct icmp6hdr)))
>                         inet_proto_csum_replace16(&icmp6_hdr(skb)->icmp6_cksum,
>                                                   skb, addr, new_addr, true);
> @@ -589,12 +602,15 @@ static int set_ipv6(struct sk_buff *skb, struct sw_flow_key *flow_key,
>         if (is_ipv6_mask_nonzero(mask->ipv6_src)) {
>                 __be32 *saddr = (__be32 *)&nh->saddr;
>                 __be32 masked[4];
> +               bool recalc_csum = true;
>
>                 mask_ipv6_addr(saddr, key->ipv6_src, mask->ipv6_src, masked);
>
>                 if (unlikely(memcmp(saddr, masked, sizeof(masked)))) {
> +                       if (flow_key->ip.frag == OVS_FRAG_TYPE_LATER)
> +                               recalc_csum = false;
>                         set_ipv6_addr(skb, flow_key->ip.proto, saddr, masked,
> -                                     true);
> +                                     recalc_csum);
>                         memcpy(&flow_key->ipv6.addr.src, masked,
>                                sizeof(flow_key->ipv6.addr.src));
>                 }
> @@ -614,6 +630,8 @@ static int set_ipv6(struct sk_buff *skb, struct sw_flow_key *flow_key,
>                                                              NEXTHDR_ROUTING,
>                                                              NULL, &flags)
>                                                != NEXTHDR_ROUTING);
> +                       if (flow_key->ip.frag == OVS_FRAG_TYPE_LATER)
> +                               recalc_csum = false;
>
>                         set_ipv6_addr(skb, flow_key->ip.proto, daddr, masked,
>                                       recalc_csum);
> --
> 2.27.0
>
> _______________________________________________
> discuss mailing list

As Gregory said, you should rebase your patch on linux upstream. and
patch is reviewd in netdev@vger.kernel.org mail list.
OvS kernel module in upstream is:
https://git.kernel.org/pub/scm/linux/kernel/git/netdev/net-next.git/tree/net/openvswitch

When the patch is applied in linux upstream, you can backport it.
Please see the section "Changes to Linux kernel components"
https://docs.openvswitch.org/en/latest/internals/contributing/backporting-patches/

> discuss@openvswitch.org
> https://mail.openvswitch.org/mailman/listinfo/ovs-discuss



-- 
Best regards, Tonghao

^ permalink raw reply

* Re: [PATCH] net: bonding: Add support for IPV6 ns/na
From: 孙守鑫 @ 2021-12-10  7:09 UTC (permalink / raw)
  To: Jay Vosburgh; +Cc: vfalico, andy, davem, kuba, netdev, linux-kernel, huyd12
In-Reply-To: <27832.1639081353@famine>


在 2021/12/10 4:22, Jay Vosburgh 写道:
> Sun Shouxin <sunshouxin@chinatelecom.cn> wrote:
>
>> Since ipv6 neighbor solicitation and advertisement messages
>> isn't handled gracefully in bonding6 driver, we can see packet
>> drop due to inconsistency bewteen mac address in the option
>> message and source MAC .
> 	Could you provide a specific example where this occurs?

                       Border-Leaf
                       /        \
                      /          \
                  Tunnel1    Tunnel2
                    /              \
                   /                \
                 Leaf-1--Tunnel3--Leaf-2
                   \                /
                    \              /
                     \            /
                      \          /
                     NIC1    NIC2
                        \      /
                         server

We can see in our lab the Border-Leaf receives occasionally a NA packet 
which is assgined to NIC1 mac in ND/NS option message, but actaully send 
out via NIC2 mac due to tx-alb,
as a result, it will cause inconsistency between MAC table and ND Table 
in Border-Leaf, i.e, NIC1 = Tunnel2 in ND table and  NIC1 = Tunnel1 in 
mac table.

And then, Border-Leaf starts to forward packet destinated to the Server, 
it will only check the ND table entry in some switch to encapsulate the 
destination MAC of the message as NIC1 MAC,
and then send it out from Tunnel2 by ND table.
Then, Leaf-2 receives the packet, it notices the destination MAC of 
message is NIC1 MAC and should forword it to Tunne1 by Tunnel3.
However, this traffic forward will be failure due to split horizon of 
VxLAN tunnels.

>
>> Another examples is ipv6 neighbor solicitation and advertisement
>> messages from VM via tap attached to host brighe, the src mac
>> mighe be changed through balance-alb mode, but it is not synced
>> with Link-layer address in the option message.
> 	What happens if the MAC assignment changes because alb does a
> rebalance?
The same result occurs as above, it just is specific to virtualization 
conext.
In this case, the src mac of packet send out by host is from VM' tap and 
not NIC1/NIC2 in host.
>
>> The patch implements bond6's tx handle for ipv6 neighbor
>> solicitation and advertisement messages.
> 	A few additional minor comments below.
Thanks your comment, I'll adjust it and send out V2 soon.
>
>> Suggested-by: Hu Yadi <huyd12@chinatelecom.cn>
>> Signed-off-by: Sun Shouxin <sunshouxin@chinatelecom.cn>
>> ---
>> drivers/net/bonding/bond_alb.c | 127 +++++++++++++++++++++++++++++++++++++++++
>> 1 file changed, 127 insertions(+)
>>
>> diff --git a/drivers/net/bonding/bond_alb.c b/drivers/net/bonding/bond_alb.c
>> index 2ec8e01..01566ba 100644
>> --- a/drivers/net/bonding/bond_alb.c
>> +++ b/drivers/net/bonding/bond_alb.c
>> @@ -22,6 +22,7 @@
>> #include <asm/byteorder.h>
>> #include <net/bonding.h>
>> #include <net/bond_alb.h>
>> +#include <net/ndisc.h>
>>
>> static const u8 mac_v6_allmcast[ETH_ALEN + 2] __long_aligned = {
>> 	0x33, 0x33, 0x00, 0x00, 0x00, 0x01
>> @@ -1269,6 +1270,112 @@ static int alb_set_mac_address(struct bonding *bond, void *addr)
>> 	return res;
>> }
>>
>> +static void alb_change_nd_option(struct sk_buff *skb, void *data)
>> +{
>> +	struct nd_msg *msg = (struct nd_msg *)skb_transport_header(skb);
>> +	struct nd_opt_hdr *nd_opt = (struct nd_opt_hdr *)msg->opt;
>> +	struct net_device *dev = skb->dev;
>> +	struct icmp6hdr *icmp6h = icmp6_hdr(skb);
>> +	struct ipv6hdr *ip6hdr = ipv6_hdr(skb);
>> +	u8 *lladdr = NULL;
>> +	u32 ndoptlen = skb_tail_pointer(skb) - (skb_transport_header(skb) +
>> +				offsetof(struct nd_msg, opt));
>> +
>> +	while (ndoptlen) {
>> +		int l;
>> +
>> +		switch (nd_opt->nd_opt_type) {
>> +		case ND_OPT_SOURCE_LL_ADDR:
>> +		case ND_OPT_TARGET_LL_ADDR:
>> +		lladdr = ndisc_opt_addr_data(nd_opt, dev);
>> +		break;
>> +
>> +		default:
>> +		break;
>> +		}
>> +
>> +		l = nd_opt->nd_opt_len << 3;
>> +
>> +		if (ndoptlen < l || l == 0)
>> +			return;
>> +
>> +		if (lladdr) {
>> +			memcpy(lladdr, data, dev->addr_len);
>> +			lladdr = NULL;
>> +			icmp6h->icmp6_cksum = 0;
>> +
>> +			icmp6h->icmp6_cksum = csum_ipv6_magic(&ip6hdr->saddr,
>> +							      &ip6hdr->daddr,
>> +						ntohs(ip6hdr->payload_len),
>> +						IPPROTO_ICMPV6,
>> +						csum_partial(icmp6h,
>> +							     ntohs(ip6hdr->payload_len), 0));
>> +			lladdr = NULL;
> 	"lladdr = NULL" could be in the default: case, above, instead of
> being done here (and it's here twice).
>
>> +		}
>> +		ndoptlen -= l;
>> +		nd_opt = ((void *)nd_opt) + l;
>> +	}
>> +}
>> +
>> +static u8 *alb_get_lladdr(struct sk_buff *skb)
>> +{
>> +	struct nd_msg *msg = (struct nd_msg *)skb_transport_header(skb);
>> +	struct nd_opt_hdr *nd_opt = (struct nd_opt_hdr *)msg->opt;
>> +	struct net_device *dev = skb->dev;
>> +	u8 *lladdr = NULL;
>> +	u32 ndoptlen = skb_tail_pointer(skb) - (skb_transport_header(skb) +
>> +				offsetof(struct nd_msg, opt));
>> +
>> +	while (ndoptlen) {
>> +		int l;
>> +
>> +		switch (nd_opt->nd_opt_type) {
>> +		case ND_OPT_SOURCE_LL_ADDR:
>> +		case ND_OPT_TARGET_LL_ADDR:
>> +			lladdr = ndisc_opt_addr_data(nd_opt, dev);
>> +			break;
>> +
>> +		default:
>> +			break;
>> +		}
>> +
>> +		l = nd_opt->nd_opt_len << 3;
>> +
>> +		if (ndoptlen < l || l == 0)
>> +			return lladdr;
>> +
>> +		if (lladdr)
>> +			return lladdr;
>> +
>> +		ndoptlen -= l;
>> +		nd_opt = ((void *)nd_opt) + l;
>> +	}
>> +
>> +	return lladdr;
>> +}
>> +
>> +static void alb_set_nd_option(struct sk_buff *skb, struct bonding *bond,
>> +			      struct slave *tx_slave)
>> +{
>> +	struct ipv6hdr *ip6hdr;
>> +	struct icmp6hdr *hdr = NULL;
>> +
>> +	if (tx_slave && tx_slave != rcu_access_pointer(bond->curr_active_slave)) {
>> +		if (ntohs(skb->protocol) == ETH_P_IPV6) {
> 	Nit: use "skb->protocol == htons(ETH_P_IPV6)" as the compiler
> should optimize the htons() of a constant.  Also, you may want to
> consider reordering the tests here, as IPv6 NA/NS traffic is likely to
> be the vast minority.
>
>> +			ip6hdr = ipv6_hdr(skb);
>> +			if (ip6hdr->nexthdr == IPPROTO_ICMPV6) {
>> +				hdr = icmp6_hdr(skb);
>> +				if (hdr->icmp6_type ==
>> +				    NDISC_NEIGHBOUR_ADVERTISEMENT ||
>> +				     hdr->icmp6_type ==
>> +				     NDISC_NEIGHBOUR_SOLICITATION) {
> 	This construct appears twice, perhaps it deserves its own
> boolean-return function?
>
> 	-J
>
>> +					alb_change_nd_option(skb, tx_slave->dev->dev_addr);
>> +				}
>> +			}
>> +		}
>> +	}
>> +}
>> +
>> /************************ exported alb functions ************************/
>>
>> int bond_alb_initialize(struct bonding *bond, int rlb_enabled)
>> @@ -1415,6 +1522,7 @@ struct slave *bond_xmit_alb_slave_get(struct bonding *bond,
>> 	}
>> 	case ETH_P_IPV6: {
>> 		const struct ipv6hdr *ip6hdr;
>> +		struct icmp6hdr *hdr = NULL;
>>
>> 		/* IPv6 doesn't really use broadcast mac address, but leave
>> 		 * that here just in case.
>> @@ -1446,6 +1554,24 @@ struct slave *bond_xmit_alb_slave_get(struct bonding *bond,
>> 			break;
>> 		}
>>
>> +		if (ip6hdr->nexthdr == IPPROTO_ICMPV6) {
>> +			hdr = icmp6_hdr(skb);
>> +			if (hdr->icmp6_type ==
>> +			    NDISC_NEIGHBOUR_ADVERTISEMENT ||
>> +			    hdr->icmp6_type ==
>> +			    NDISC_NEIGHBOUR_SOLICITATION) {
>> +				u8 *lladdr = NULL;
>> +
>> +				lladdr = alb_get_lladdr(skb);
>> +				if (lladdr) {
>> +					if (!bond_slave_has_mac_rx(bond, lladdr)) {
>> +						do_tx_balance = false;
>> +						break;
>> +					}
>> +				}
>> +			}
>> +		}
>> +
>> 		hash_start = (char *)&ip6hdr->daddr;
>> 		hash_size = sizeof(ip6hdr->daddr);
>> 		break;
>> @@ -1489,6 +1615,7 @@ netdev_tx_t bond_alb_xmit(struct sk_buff *skb, struct net_device *bond_dev)
>> 	struct slave *tx_slave = NULL;
>>
>> 	tx_slave = bond_xmit_alb_slave_get(bond, skb);
>> +	alb_set_nd_option(skb, bond, tx_slave);
>> 	return bond_do_alb_xmit(skb, bond, tx_slave);
>> }
>>
>> -- 
>> 1.8.3.1
>>
> ---
> 	-Jay Vosburgh, jay.vosburgh@canonical.com

^ permalink raw reply

* [PATCH] selftests: mptcp: remove duplicate include in mptcp_inq.c
From: cgel.zte @ 2021-12-10  7:14 UTC (permalink / raw)
  To: mathew.j.martineau
  Cc: matthieu.baerts, davem, kuba, shuah, netdev, mptcp,
	linux-kselftest, linux-kernel, Ye Guojin, ZealRobot

From: Ye Guojin <ye.guojin@zte.com.cn>

'sys/ioctl.h' included in 'mptcp_inq.c' is duplicated.

Reported-by: ZealRobot <zealci@zte.com.cn>
Signed-off-by: Ye Guojin <ye.guojin@zte.com.cn>
---
 tools/testing/selftests/net/mptcp/mptcp_inq.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/tools/testing/selftests/net/mptcp/mptcp_inq.c b/tools/testing/selftests/net/mptcp/mptcp_inq.c
index b8debd4fb5ed..29f75e2a1116 100644
--- a/tools/testing/selftests/net/mptcp/mptcp_inq.c
+++ b/tools/testing/selftests/net/mptcp/mptcp_inq.c
@@ -17,7 +17,6 @@
 #include <unistd.h>
 #include <time.h>
 
-#include <sys/ioctl.h>
 #include <sys/ioctl.h>
 #include <sys/socket.h>
 #include <sys/types.h>
-- 
2.25.1


^ permalink raw reply related

* Re: [PATCH] selftests: icmp_redirect: pass xfail=0 to log_test() for non-xfail cases
From: Po-Hsu Lin @ 2021-12-10  7:16 UTC (permalink / raw)
  To: Jakub Kicinski; +Cc: netdev, linux-kselftest, linux-kernel, davem, skhan
In-Reply-To: <20211209184620.78d02085@kicinski-fedora-pc1c0hjn.dhcp.thefacebook.com>

On Fri, Dec 10, 2021 at 10:46 AM Jakub Kicinski <kuba@kernel.org> wrote:
>
> On Wed,  8 Dec 2021 15:11:51 +0800 Po-Hsu Lin wrote:
> > If any sub-test in this icmp_redirect.sh is failing but not expected
> > to fail. The script will complain:
> >     ./icmp_redirect.sh: line 72: [: 1: unary operator expected
> >
> > This is because when the sub-test is not expected to fail, we won't
> > pass any value for the xfail local variable in log_test() and thus
> > it's empty. Fix this by passing 0 as the 4th variable to log_test()
> > for non-xfail cases.
> >
> > Signed-off-by: Po-Hsu Lin <po-hsu.lin@canonical.com>
>
> Thanks, could you please add a fixes tag (even if the breakage is only
> present in linux-next) and CC David Ahern on v2?

Sure thing,
I will add fixes tag for this commit:
0a36a75c selftests: icmp_redirect: support expected failures

thanks for the feedback.

^ permalink raw reply

* [PATCHv2] selftests: icmp_redirect: pass xfail=0 to log_test()
From: Po-Hsu Lin @ 2021-12-10  7:25 UTC (permalink / raw)
  To: po-hsu.lin, netdev, linux-kselftest, linux-kernel
  Cc: davem, kuba, skhan, andrea.righi, dsahern

If any sub-test in this icmp_redirect.sh is failing but not expected
to fail. The script will complain:
    ./icmp_redirect.sh: line 72: [: 1: unary operator expected

This is because when the sub-test is not expected to fail, we won't
pass any value for the xfail local variable in log_test() and thus
it's empty. Fix this by passing 0 as the 4th variable to log_test()
for non-xfail cases.

v2: added fixes tag

Fixes: 0a36a75c6818 ("selftests: icmp_redirect: support expected failures")
Signed-off-by: Po-Hsu Lin <po-hsu.lin@canonical.com>
---
 tools/testing/selftests/net/icmp_redirect.sh | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/tools/testing/selftests/net/icmp_redirect.sh b/tools/testing/selftests/net/icmp_redirect.sh
index ecbf57f..7b9d6e3 100755
--- a/tools/testing/selftests/net/icmp_redirect.sh
+++ b/tools/testing/selftests/net/icmp_redirect.sh
@@ -311,7 +311,7 @@ check_exception()
 		ip -netns h1 ro get ${H1_VRF_ARG} ${H2_N2_IP} | \
 		grep -E -v 'mtu|redirected' | grep -q "cache"
 	fi
-	log_test $? 0 "IPv4: ${desc}"
+	log_test $? 0 "IPv4: ${desc}" 0
 
 	# No PMTU info for test "redirect" and "mtu exception plus redirect"
 	if [ "$with_redirect" = "yes" ] && [ "$desc" != "redirect exception plus mtu" ]; then
-- 
2.7.4


^ permalink raw reply related

* Re: [PATCH v5 3/5] can: do not copy the payload of RTR frames
From: Marc Kleine-Budde @ 2021-12-10  7:35 UTC (permalink / raw)
  To: Vincent Mailhol
  Cc: linux-can, Oliver Hartkopp, Jimmy Assarsson, netdev, linux-kernel,
	linux-arm-kernel, linux-sunxi, Yasushi SHOJI
In-Reply-To: <20211207121531.42941-4-mailhol.vincent@wanadoo.fr>

[-- Attachment #1: Type: text/plain, Size: 983 bytes --]

On 07.12.2021 21:15:29, Vincent Mailhol wrote:
> The actual payload length of the CAN Remote Transmission Request (RTR)
> frames is always 0, i.e. nothing is transmitted on the wire. However,
                           ^^^^^^^
I've changed this to "no payload" to make it more unambiguous.

> those RTR frames still use the DLC to indicate the length of the
> requested frame.
> 
> For this reason, it is incorrect to copy the payload of RTR frames
> (the payload buffer would only contain garbage data). This patch
> encapsulates the payload copy in a check toward the RTR flag.
> 
> CC: Yasushi SHOJI <yashi@spacecubics.com>
> Signed-off-by: Vincent Mailhol <mailhol.vincent@wanadoo.fr>

Marc

-- 
Pengutronix e.K.                 | Marc Kleine-Budde           |
Embedded Linux                   | https://www.pengutronix.de  |
Vertretung West/Dortmund         | Phone: +49-231-2826-924     |
Amtsgericht Hildesheim, HRA 2686 | Fax:   +49-5121-206917-5555 |

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply

* Re: [PATCH net-next v8] net: openvswitch: IPv6: Add IPv6 extension header support
From: Pravin Shelar @ 2021-12-10  7:36 UTC (permalink / raw)
  To: Cpp Code
  Cc: Linux Kernel Network Developers, David S. Miller, Jakub Kicinski,
	ovs dev, LKML
In-Reply-To: <CAASuNyUKj+dsf++7mhdkjm2mabQggYW4x42_BV=y+VPPSBFqfA@mail.gmail.com>

()

On Mon, Dec 6, 2021 at 3:00 PM Cpp Code <cpp.code.lv@gmail.com> wrote:
>
> On Thu, Dec 2, 2021 at 9:28 PM Pravin Shelar <pravin.ovn@gmail.com> wrote:
> >
> > On Thu, Dec 2, 2021 at 12:20 PM Cpp Code <cpp.code.lv@gmail.com> wrote:
> > >
> > > On Wed, Dec 1, 2021 at 11:34 PM Pravin Shelar <pravin.ovn@gmail.com> wrote:
> > > >
> > > > On Wed, Nov 24, 2021 at 11:33 AM Toms Atteka <cpp.code.lv@gmail.com> wrote:
> > > > >
> > > > > This change adds a new OpenFlow field OFPXMT_OFB_IPV6_EXTHDR and
> > > > > packets can be filtered using ipv6_ext flag.
> > > > >
> > > > > Signed-off-by: Toms Atteka <cpp.code.lv@gmail.com>
> > > > > ---
> > > > >  include/uapi/linux/openvswitch.h |   6 ++
> > > > >  net/openvswitch/flow.c           | 140 +++++++++++++++++++++++++++++++
> > > > >  net/openvswitch/flow.h           |  14 ++++
> > > > >  net/openvswitch/flow_netlink.c   |  26 +++++-
> > > > >  4 files changed, 184 insertions(+), 2 deletions(-)
> > > > >
> > > > > diff --git a/include/uapi/linux/openvswitch.h b/include/uapi/linux/openvswitch.h
> > > > > index a87b44cd5590..43790f07e4a2 100644
> > > > > --- a/include/uapi/linux/openvswitch.h
> > > > > +++ b/include/uapi/linux/openvswitch.h
> > > > > @@ -342,6 +342,7 @@ enum ovs_key_attr {
> > > > >         OVS_KEY_ATTR_CT_ORIG_TUPLE_IPV4,   /* struct ovs_key_ct_tuple_ipv4 */
> > > > >         OVS_KEY_ATTR_CT_ORIG_TUPLE_IPV6,   /* struct ovs_key_ct_tuple_ipv6 */
> > > > >         OVS_KEY_ATTR_NSH,       /* Nested set of ovs_nsh_key_* */
> > > > > +       OVS_KEY_ATTR_IPV6_EXTHDRS,  /* struct ovs_key_ipv6_exthdr */
> > > > >
> > > > >  #ifdef __KERNEL__
> > > > >         OVS_KEY_ATTR_TUNNEL_INFO,  /* struct ip_tunnel_info */
> > > > > @@ -421,6 +422,11 @@ struct ovs_key_ipv6 {
> > > > >         __u8   ipv6_frag;       /* One of OVS_FRAG_TYPE_*. */
> > > > >  };
> > > > >
> > > > > +/* separate structure to support backward compatibility with older user space */
> > > > > +struct ovs_key_ipv6_exthdrs {
> > > > > +       __u16  hdrs;
> > > > > +};
> > > > > +
> > > > >  struct ovs_key_tcp {
> > > > >         __be16 tcp_src;
> > > > >         __be16 tcp_dst;
> > > > > diff --git a/net/openvswitch/flow.c b/net/openvswitch/flow.c
> > > > > index 9d375e74b607..28acb40437ca 100644
> > > > > --- a/net/openvswitch/flow.c
> > > > > +++ b/net/openvswitch/flow.c
> > > > > @@ -239,6 +239,144 @@ static bool icmphdr_ok(struct sk_buff *skb)
> > > > >                                   sizeof(struct icmphdr));
> > > > >  }
> > > > >
> > > > > +/**
> > > > > + * get_ipv6_ext_hdrs() - Parses packet and sets IPv6 extension header flags.
> > > > > + *
> > > > > + * @skb: buffer where extension header data starts in packet
> > > > > + * @nh: ipv6 header
> > > > > + * @ext_hdrs: flags are stored here
> > > > > + *
> > > > > + * OFPIEH12_UNREP is set if more than one of a given IPv6 extension header
> > > > > + * is unexpectedly encountered. (Two destination options headers may be
> > > > > + * expected and would not cause this bit to be set.)
> > > > > + *
> > > > > + * OFPIEH12_UNSEQ is set if IPv6 extension headers were not in the order
> > > > > + * preferred (but not required) by RFC 2460:
> > > > > + *
> > > > > + * When more than one extension header is used in the same packet, it is
> > > > > + * recommended that those headers appear in the following order:
> > > > > + *      IPv6 header
> > > > > + *      Hop-by-Hop Options header
> > > > > + *      Destination Options header
> > > > > + *      Routing header
> > > > > + *      Fragment header
> > > > > + *      Authentication header
> > > > > + *      Encapsulating Security Payload header
> > > > > + *      Destination Options header
> > > > > + *      upper-layer header
> > > > > + */
> > > > > +static void get_ipv6_ext_hdrs(struct sk_buff *skb, struct ipv6hdr *nh,
> > > > > +                             u16 *ext_hdrs)
> > > > > +{
> > > > > +       u8 next_type = nh->nexthdr;
> > > > > +       unsigned int start = skb_network_offset(skb) + sizeof(struct ipv6hdr);
> > > > > +       int dest_options_header_count = 0;
> > > > > +
> > > > > +       *ext_hdrs = 0;
> > > > > +
> > > > > +       while (ipv6_ext_hdr(next_type)) {
> > > > > +               struct ipv6_opt_hdr _hdr, *hp;
> > > > > +
> > > > > +               switch (next_type) {
> > > > > +               case IPPROTO_NONE:
> > > > > +                       *ext_hdrs |= OFPIEH12_NONEXT;
> > > > > +                       /* stop parsing */
> > > > > +                       return;
> > > > > +
> > > > > +               case IPPROTO_ESP:
> > > > > +                       if (*ext_hdrs & OFPIEH12_ESP)
> > > > > +                               *ext_hdrs |= OFPIEH12_UNREP;
> > > > > +                       if ((*ext_hdrs & ~(OFPIEH12_HOP | OFPIEH12_DEST |
> > > > > +                                          OFPIEH12_ROUTER | IPPROTO_FRAGMENT |
> > > > > +                                          OFPIEH12_AUTH | OFPIEH12_UNREP)) ||
> > > > > +                           dest_options_header_count >= 2) {
> > > > > +                               *ext_hdrs |= OFPIEH12_UNSEQ;
> > > > > +                       }
> > > > > +                       *ext_hdrs |= OFPIEH12_ESP;
> > > > > +                       break;
> > > > you need to check_header() before looking into each extension header.
> > >
> > > Could you elaborate why I need to add check_header(),
> > > skb_header_pointer() is doing sanitization.
> >
> > I mean check_header() would allow you to read the header without
> > copying the bits, it is used in ovs flow extraction so its usual
> > check.
>
> But check_header() will call *__pskb_pull_tail which in turn will copy
> bits if data will be fragmented.
>
OVS flow extract uses this function to extract flow upto L4, so
skb_header_pointer() is not saving any copy operation.

> /* Moves tail of skb head forward, copying data from fragmented part,
>  * when it is necessary.
>  * 1. It may fail due to malloc failure.
>  * 2. It may change skb pointers.
>  *
>  * It is pretty complicated. Luckily, it is called only in exceptional cases.
>  */
> void *__pskb_pull_tail(struct sk_buff *skb, int delta)
>
> as well I noticed that for example commit
> 4a06fa67c4da20148803525151845276cdb995c1 is moving from
> pskb_may_pull() to skb_header_pointer()
ok, I see advantage of using skb_header_pointer() in this case, but
replacing all check_header() with skb_header_pointer() would add lot
of copy operation in flow extract. Anyways for this use case
skb_header_pointer() is fine.

Acked-by: Pravin B Shelar <pshelar@ovn.org>

^ permalink raw reply

* [PATCH V2 net-next 0/6] net: netns refcount tracking, base series
From: Eric Dumazet @ 2021-12-10  7:44 UTC (permalink / raw)
  To: David S . Miller, Jakub Kicinski; +Cc: netdev, Eric Dumazet, Eric Dumazet

From: Eric Dumazet <edumazet@google.com>

We have 100+ syzbot reports about netns being dismantled too soon,
still unresolved as of today.

We think a missing get_net() or an extra put_net() is the root cause.

In order to find the bug(s), and be able to spot future ones,
this patch adds CONFIG_NET_NS_REFCNT_TRACKER and new helpers
to precisely pair all put_net() with corresponding get_net().

To use these helpers, each data structure owning a refcount
should also use a "netns_tracker" to pair the get() and put().

Small sections of codes where the get()/put() are in sight
do not need to have a tracker, because they are short lived,
but in theory it is also possible to declare an on-stack tracker.

v2: Include core networking patches only.

Eric Dumazet (6):
  net: add networking namespace refcount tracker
  net: add netns refcount tracker to struct sock
  net: add netns refcount tracker to struct seq_net_private
  net: sched: add netns refcount tracker to struct tcf_exts
  l2tp: add netns refcount tracker to l2tp_dfs_seq_data
  ppp: add netns refcount tracker

 drivers/net/ppp/ppp_generic.c |  5 +++--
 fs/proc/proc_net.c            | 19 ++++++++++++++++---
 include/linux/netdevice.h     |  9 +--------
 include/linux/seq_file_net.h  |  3 ++-
 include/net/net_namespace.h   | 34 ++++++++++++++++++++++++++++++++++
 include/net/net_trackers.h    | 18 ++++++++++++++++++
 include/net/pkt_cls.h         |  8 ++++++--
 include/net/sock.h            |  2 ++
 net/Kconfig.debug             |  9 +++++++++
 net/core/net_namespace.c      |  3 +++
 net/core/sock.c               |  6 +++---
 net/l2tp/l2tp_debugfs.c       |  9 +++++----
 12 files changed, 102 insertions(+), 23 deletions(-)
 create mode 100644 include/net/net_trackers.h

-- 
2.34.1.173.g76aa8bc2d0-goog


^ permalink raw reply

* [PATCH V2 net-next 1/6] net: add networking namespace refcount tracker
From: Eric Dumazet @ 2021-12-10  7:44 UTC (permalink / raw)
  To: David S . Miller, Jakub Kicinski; +Cc: netdev, Eric Dumazet, Eric Dumazet
In-Reply-To: <20211210074426.279563-1-eric.dumazet@gmail.com>

From: Eric Dumazet <edumazet@google.com>

We have 100+ syzbot reports about netns being dismantled too soon,
still unresolved as of today.

We think a missing get_net() or an extra put_net() is the root cause.

In order to find the bug(s), and be able to spot future ones,
this patch adds CONFIG_NET_NS_REFCNT_TRACKER and new helpers
to precisely pair all put_net() with corresponding get_net().

To use these helpers, each data structure owning a refcount
should also use a "netns_tracker" to pair the get and put.

Signed-off-by: Eric Dumazet <edumazet@google.com>
---
 include/linux/netdevice.h   |  9 +--------
 include/net/net_namespace.h | 34 ++++++++++++++++++++++++++++++++++
 include/net/net_trackers.h  | 18 ++++++++++++++++++
 net/Kconfig.debug           |  9 +++++++++
 net/core/net_namespace.c    |  3 +++
 5 files changed, 65 insertions(+), 8 deletions(-)
 create mode 100644 include/net/net_trackers.h

diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 1a748ee9a421a7dee49f2b78a04976d6a5c80925..235d5d082f1a446c8d898ffcc5b1983df7c04f35 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -48,7 +48,7 @@
 #include <uapi/linux/pkt_cls.h>
 #include <linux/hashtable.h>
 #include <linux/rbtree.h>
-#include <linux/ref_tracker.h>
+#include <net/net_trackers.h>
 
 struct netpoll_info;
 struct device;
@@ -300,13 +300,6 @@ enum netdev_state_t {
 	__LINK_STATE_TESTING,
 };
 
-
-#ifdef CONFIG_NET_DEV_REFCNT_TRACKER
-typedef struct ref_tracker *netdevice_tracker;
-#else
-typedef struct {} netdevice_tracker;
-#endif
-
 struct gro_list {
 	struct list_head	list;
 	int			count;
diff --git a/include/net/net_namespace.h b/include/net/net_namespace.h
index bb5fa59140321ba7c1826f5f4492e5cb607fd99f..5b61c462e534be468c81d2b0f4ef586b209dd4b8 100644
--- a/include/net/net_namespace.h
+++ b/include/net/net_namespace.h
@@ -34,6 +34,7 @@
 #include <net/netns/smc.h>
 #include <net/netns/bpf.h>
 #include <net/netns/mctp.h>
+#include <net/net_trackers.h>
 #include <linux/ns_common.h>
 #include <linux/idr.h>
 #include <linux/skbuff.h>
@@ -87,6 +88,7 @@ struct net {
 	struct idr		netns_ids;
 
 	struct ns_common	ns;
+	struct ref_tracker_dir  refcnt_tracker;
 
 	struct list_head 	dev_base_head;
 	struct proc_dir_entry 	*proc_net;
@@ -240,6 +242,7 @@ void ipx_unregister_sysctl(void);
 #ifdef CONFIG_NET_NS
 void __put_net(struct net *net);
 
+/* Try using get_net_track() instead */
 static inline struct net *get_net(struct net *net)
 {
 	refcount_inc(&net->ns.count);
@@ -258,6 +261,7 @@ static inline struct net *maybe_get_net(struct net *net)
 	return net;
 }
 
+/* Try using put_net_track() instead */
 static inline void put_net(struct net *net)
 {
 	if (refcount_dec_and_test(&net->ns.count))
@@ -308,6 +312,36 @@ static inline int check_net(const struct net *net)
 #endif
 
 
+static inline void netns_tracker_alloc(struct net *net,
+				       netns_tracker *tracker, gfp_t gfp)
+{
+#ifdef CONFIG_NET_NS_REFCNT_TRACKER
+	ref_tracker_alloc(&net->refcnt_tracker, tracker, gfp);
+#endif
+}
+
+static inline void netns_tracker_free(struct net *net,
+				      netns_tracker *tracker)
+{
+#ifdef CONFIG_NET_NS_REFCNT_TRACKER
+       ref_tracker_free(&net->refcnt_tracker, tracker);
+#endif
+}
+
+static inline struct net *get_net_track(struct net *net,
+					netns_tracker *tracker, gfp_t gfp)
+{
+	get_net(net);
+	netns_tracker_alloc(net, tracker, gfp);
+	return net;
+}
+
+static inline void put_net_track(struct net *net, netns_tracker *tracker)
+{
+	netns_tracker_free(net, tracker);
+	put_net(net);
+}
+
 typedef struct {
 #ifdef CONFIG_NET_NS
 	struct net *net;
diff --git a/include/net/net_trackers.h b/include/net/net_trackers.h
new file mode 100644
index 0000000000000000000000000000000000000000..d94c76cf15a9df918441b8ab4ed20422059f7ed9
--- /dev/null
+++ b/include/net/net_trackers.h
@@ -0,0 +1,18 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __NET_NET_TRACKERS_H
+#define __NET_NET_TRACKERS_H
+#include <linux/ref_tracker.h>
+
+#ifdef CONFIG_NET_DEV_REFCNT_TRACKER
+typedef struct ref_tracker *netdevice_tracker;
+#else
+typedef struct {} netdevice_tracker;
+#endif
+
+#ifdef CONFIG_NET_NS_REFCNT_TRACKER
+typedef struct ref_tracker *netns_tracker;
+#else
+typedef struct {} netns_tracker;
+#endif
+
+#endif /* __NET_NET_TRACKERS_H */
diff --git a/net/Kconfig.debug b/net/Kconfig.debug
index fb5c70e01cb3b6f86afce9a9f0aa8f8d7468e1fe..2f50611df858911cf5190a361e4e9316e543ed3a 100644
--- a/net/Kconfig.debug
+++ b/net/Kconfig.debug
@@ -8,3 +8,12 @@ config NET_DEV_REFCNT_TRACKER
 	help
 	  Enable debugging feature to track device references.
 	  This adds memory and cpu costs.
+
+config NET_NS_REFCNT_TRACKER
+	bool "Enable networking namespace refcount tracking"
+	depends on DEBUG_KERNEL && STACKTRACE_SUPPORT
+	select REF_TRACKER
+	default n
+	help
+	  Enable debugging feature to track netns references.
+	  This adds memory and cpu costs.
diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c
index 202fa5eacd0f9bc74fc3246e9cebcd3419759ad5..9b7171c40434985b869c1477975fc75447d78c3b 100644
--- a/net/core/net_namespace.c
+++ b/net/core/net_namespace.c
@@ -311,6 +311,8 @@ static __net_init int setup_net(struct net *net, struct user_namespace *user_ns)
 	LIST_HEAD(net_exit_list);
 
 	refcount_set(&net->ns.count, 1);
+	ref_tracker_dir_init(&net->refcnt_tracker, 128);
+
 	refcount_set(&net->passive, 1);
 	get_random_bytes(&net->hash_mix, sizeof(u32));
 	preempt_disable();
@@ -635,6 +637,7 @@ static DECLARE_WORK(net_cleanup_work, cleanup_net);
 
 void __put_net(struct net *net)
 {
+	ref_tracker_dir_exit(&net->refcnt_tracker);
 	/* Cleanup the network namespace in process context */
 	if (llist_add(&net->cleanup_list, &cleanup_list))
 		queue_work(netns_wq, &net_cleanup_work);
-- 
2.34.1.173.g76aa8bc2d0-goog


^ permalink raw reply related

* [PATCH V2 net-next 2/6] net: add netns refcount tracker to struct sock
From: Eric Dumazet @ 2021-12-10  7:44 UTC (permalink / raw)
  To: David S . Miller, Jakub Kicinski; +Cc: netdev, Eric Dumazet, Eric Dumazet
In-Reply-To: <20211210074426.279563-1-eric.dumazet@gmail.com>

From: Eric Dumazet <edumazet@google.com>

Signed-off-by: Eric Dumazet <edumazet@google.com>
---
 include/net/sock.h | 2 ++
 net/core/sock.c    | 6 +++---
 2 files changed, 5 insertions(+), 3 deletions(-)

diff --git a/include/net/sock.h b/include/net/sock.h
index ae61cd0b650de76d731c8f9b7f9050d9beb3d87e..5d8532f26208fbd05f5b1185afa87207c1c476c9 100644
--- a/include/net/sock.h
+++ b/include/net/sock.h
@@ -350,6 +350,7 @@ struct bpf_local_storage;
   *	@sk_txtime_deadline_mode: set deadline mode for SO_TXTIME
   *	@sk_txtime_report_errors: set report errors mode for SO_TXTIME
   *	@sk_txtime_unused: unused txtime flags
+  *	@ns_tracker: tracker for netns reference
   */
 struct sock {
 	/*
@@ -538,6 +539,7 @@ struct sock {
 	struct bpf_local_storage __rcu	*sk_bpf_storage;
 #endif
 	struct rcu_head		sk_rcu;
+	netns_tracker		ns_tracker;
 };
 
 enum sk_pacing {
diff --git a/net/core/sock.c b/net/core/sock.c
index 4a499d255f401e61fff2fbab3b0fd9337da77f7e..1a6a925397906508a33e1443b1ec27ac19d036e1 100644
--- a/net/core/sock.c
+++ b/net/core/sock.c
@@ -1983,7 +1983,7 @@ struct sock *sk_alloc(struct net *net, int family, gfp_t priority,
 		sock_lock_init(sk);
 		sk->sk_net_refcnt = kern ? 0 : 1;
 		if (likely(sk->sk_net_refcnt)) {
-			get_net(net);
+			get_net_track(net, &sk->ns_tracker, priority);
 			sock_inuse_add(net, 1);
 		}
 
@@ -2039,7 +2039,7 @@ static void __sk_destruct(struct rcu_head *head)
 	put_pid(sk->sk_peer_pid);
 
 	if (likely(sk->sk_net_refcnt))
-		put_net(sock_net(sk));
+		put_net_track(sock_net(sk), &sk->ns_tracker);
 	sk_prot_free(sk->sk_prot_creator, sk);
 }
 
@@ -2126,7 +2126,7 @@ struct sock *sk_clone_lock(const struct sock *sk, const gfp_t priority)
 
 	/* SANITY */
 	if (likely(newsk->sk_net_refcnt)) {
-		get_net(sock_net(newsk));
+		get_net_track(sock_net(newsk), &newsk->ns_tracker, priority);
 		sock_inuse_add(sock_net(newsk), 1);
 	}
 	sk_node_init(&newsk->sk_node);
-- 
2.34.1.173.g76aa8bc2d0-goog


^ permalink raw reply related

* [PATCH V2 net-next 6/6] ppp: add netns refcount tracker
From: Eric Dumazet @ 2021-12-10  7:44 UTC (permalink / raw)
  To: David S . Miller, Jakub Kicinski; +Cc: netdev, Eric Dumazet, Eric Dumazet
In-Reply-To: <20211210074426.279563-1-eric.dumazet@gmail.com>

From: Eric Dumazet <edumazet@google.com>

Signed-off-by: Eric Dumazet <edumazet@google.com>
---
 drivers/net/ppp/ppp_generic.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/drivers/net/ppp/ppp_generic.c b/drivers/net/ppp/ppp_generic.c
index 1180a0e2445fbfb3204fea785f1c1cf48bc77141..9e52c5d2d77fce39b230605ec96fed9798858a13 100644
--- a/drivers/net/ppp/ppp_generic.c
+++ b/drivers/net/ppp/ppp_generic.c
@@ -173,6 +173,7 @@ struct channel {
 	spinlock_t	downl;		/* protects `chan', file.xq dequeue */
 	struct ppp	*ppp;		/* ppp unit we're connected to */
 	struct net	*chan_net;	/* the net channel belongs to */
+	netns_tracker	ns_tracker;
 	struct list_head clist;		/* link in list of channels per unit */
 	rwlock_t	upl;		/* protects `ppp' and 'bridge' */
 	struct channel __rcu *bridge;	/* "bridged" ppp channel */
@@ -2879,7 +2880,7 @@ int ppp_register_net_channel(struct net *net, struct ppp_channel *chan)
 
 	pch->ppp = NULL;
 	pch->chan = chan;
-	pch->chan_net = get_net(net);
+	pch->chan_net = get_net_track(net, &pch->ns_tracker, GFP_KERNEL);
 	chan->ppp = pch;
 	init_ppp_file(&pch->file, CHANNEL);
 	pch->file.hdrlen = chan->hdrlen;
@@ -3519,7 +3520,7 @@ ppp_disconnect_channel(struct channel *pch)
  */
 static void ppp_destroy_channel(struct channel *pch)
 {
-	put_net(pch->chan_net);
+	put_net_track(pch->chan_net, &pch->ns_tracker);
 	pch->chan_net = NULL;
 
 	atomic_dec(&channel_count);
-- 
2.34.1.173.g76aa8bc2d0-goog


^ permalink raw reply related

* [PATCH V2 net-next 4/6] net: sched: add netns refcount tracker to struct tcf_exts
From: Eric Dumazet @ 2021-12-10  7:44 UTC (permalink / raw)
  To: David S . Miller, Jakub Kicinski; +Cc: netdev, Eric Dumazet, Eric Dumazet
In-Reply-To: <20211210074426.279563-1-eric.dumazet@gmail.com>

From: Eric Dumazet <edumazet@google.com>

Signed-off-by: Eric Dumazet <edumazet@google.com>
---
 include/net/pkt_cls.h | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/include/net/pkt_cls.h b/include/net/pkt_cls.h
index 193f88ebf629bd5a66c2d155346b40695e259a13..cebc1bd713b68e9c9c7b7656f569e749c0dc9297 100644
--- a/include/net/pkt_cls.h
+++ b/include/net/pkt_cls.h
@@ -202,7 +202,8 @@ struct tcf_exts {
 	__u32	type; /* for backward compat(TCA_OLD_COMPAT) */
 	int nr_actions;
 	struct tc_action **actions;
-	struct net *net;
+	struct net	*net;
+	netns_tracker	ns_tracker;
 #endif
 	/* Map to export classifier specific extension TLV types to the
 	 * generic extensions API. Unsupported extensions must be set to 0.
@@ -218,6 +219,7 @@ static inline int tcf_exts_init(struct tcf_exts *exts, struct net *net,
 	exts->type = 0;
 	exts->nr_actions = 0;
 	exts->net = net;
+	netns_tracker_alloc(net, &exts->ns_tracker, GFP_KERNEL);
 	exts->actions = kcalloc(TCA_ACT_MAX_PRIO, sizeof(struct tc_action *),
 				GFP_KERNEL);
 	if (!exts->actions)
@@ -236,6 +238,8 @@ static inline bool tcf_exts_get_net(struct tcf_exts *exts)
 {
 #ifdef CONFIG_NET_CLS_ACT
 	exts->net = maybe_get_net(exts->net);
+	if (exts->net)
+		netns_tracker_alloc(exts->net, &exts->ns_tracker, GFP_KERNEL);
 	return exts->net != NULL;
 #else
 	return true;
@@ -246,7 +250,7 @@ static inline void tcf_exts_put_net(struct tcf_exts *exts)
 {
 #ifdef CONFIG_NET_CLS_ACT
 	if (exts->net)
-		put_net(exts->net);
+		put_net_track(exts->net, &exts->ns_tracker);
 #endif
 }
 
-- 
2.34.1.173.g76aa8bc2d0-goog


^ permalink raw reply related

* [PATCH V2 net-next 5/6] l2tp: add netns refcount tracker to l2tp_dfs_seq_data
From: Eric Dumazet @ 2021-12-10  7:44 UTC (permalink / raw)
  To: David S . Miller, Jakub Kicinski; +Cc: netdev, Eric Dumazet, Eric Dumazet
In-Reply-To: <20211210074426.279563-1-eric.dumazet@gmail.com>

From: Eric Dumazet <edumazet@google.com>

Signed-off-by: Eric Dumazet <edumazet@google.com>
---
 net/l2tp/l2tp_debugfs.c | 9 +++++----
 1 file changed, 5 insertions(+), 4 deletions(-)

diff --git a/net/l2tp/l2tp_debugfs.c b/net/l2tp/l2tp_debugfs.c
index acf6e1343b88e070004f422e00d8fc697b4e4130..9d1aafe75f92dd7643c6908b83f4eb60ea79b025 100644
--- a/net/l2tp/l2tp_debugfs.c
+++ b/net/l2tp/l2tp_debugfs.c
@@ -32,7 +32,8 @@
 static struct dentry *rootdir;
 
 struct l2tp_dfs_seq_data {
-	struct net *net;
+	struct net	*net;
+	netns_tracker	ns_tracker;
 	int tunnel_idx;			/* current tunnel */
 	int session_idx;		/* index of session within current tunnel */
 	struct l2tp_tunnel *tunnel;
@@ -281,7 +282,7 @@ static int l2tp_dfs_seq_open(struct inode *inode, struct file *file)
 		rc = PTR_ERR(pd->net);
 		goto err_free_pd;
 	}
-
+	netns_tracker_alloc(pd->net, &pd->ns_tracker, GFP_KERNEL);
 	rc = seq_open(file, &l2tp_dfs_seq_ops);
 	if (rc)
 		goto err_free_net;
@@ -293,7 +294,7 @@ static int l2tp_dfs_seq_open(struct inode *inode, struct file *file)
 	return rc;
 
 err_free_net:
-	put_net(pd->net);
+	put_net_track(pd->net, &pd->ns_tracker);
 err_free_pd:
 	kfree(pd);
 	goto out;
@@ -307,7 +308,7 @@ static int l2tp_dfs_seq_release(struct inode *inode, struct file *file)
 	seq = file->private_data;
 	pd = seq->private;
 	if (pd->net)
-		put_net(pd->net);
+		put_net_track(pd->net, &pd->ns_tracker);
 	kfree(pd);
 	seq_release(inode, file);
 
-- 
2.34.1.173.g76aa8bc2d0-goog


^ permalink raw reply related

* [PATCH V2 net-next 3/6] net: add netns refcount tracker to struct seq_net_private
From: Eric Dumazet @ 2021-12-10  7:44 UTC (permalink / raw)
  To: David S . Miller, Jakub Kicinski; +Cc: netdev, Eric Dumazet, Eric Dumazet
In-Reply-To: <20211210074426.279563-1-eric.dumazet@gmail.com>

From: Eric Dumazet <edumazet@google.com>

Signed-off-by: Eric Dumazet <edumazet@google.com>
---
 fs/proc/proc_net.c           | 19 ++++++++++++++++---
 include/linux/seq_file_net.h |  3 ++-
 2 files changed, 18 insertions(+), 4 deletions(-)

diff --git a/fs/proc/proc_net.c b/fs/proc/proc_net.c
index 15c2e55d2ed2c4b8b00209ecf9b18caa1a47f1b7..39b823ab2564edf62fd08983ec44560b1120ee24 100644
--- a/fs/proc/proc_net.c
+++ b/fs/proc/proc_net.c
@@ -61,15 +61,27 @@ static int seq_open_net(struct inode *inode, struct file *file)
 	}
 #ifdef CONFIG_NET_NS
 	p->net = net;
+	netns_tracker_alloc(net, &p->ns_tracker, GFP_KERNEL);
 #endif
 	return 0;
 }
 
+static void seq_file_net_put_net(struct seq_file *seq)
+{
+#ifdef CONFIG_NET_NS
+	struct seq_net_private *priv = seq->private;
+
+	put_net_track(priv->net, &priv->ns_tracker);
+#else
+	put_net(&init_net);
+#endif
+}
+
 static int seq_release_net(struct inode *ino, struct file *f)
 {
 	struct seq_file *seq = f->private_data;
 
-	put_net(seq_file_net(seq));
+	seq_file_net_put_net(seq);
 	seq_release_private(ino, f);
 	return 0;
 }
@@ -87,7 +99,8 @@ int bpf_iter_init_seq_net(void *priv_data, struct bpf_iter_aux_info *aux)
 #ifdef CONFIG_NET_NS
 	struct seq_net_private *p = priv_data;
 
-	p->net = get_net(current->nsproxy->net_ns);
+	p->net = get_net_track(current->nsproxy->net_ns, &p->ns_tracker,
+			       GFP_KERNEL);
 #endif
 	return 0;
 }
@@ -97,7 +110,7 @@ void bpf_iter_fini_seq_net(void *priv_data)
 #ifdef CONFIG_NET_NS
 	struct seq_net_private *p = priv_data;
 
-	put_net(p->net);
+	put_net_track(p->net, &p->ns_tracker);
 #endif
 }
 
diff --git a/include/linux/seq_file_net.h b/include/linux/seq_file_net.h
index 0fdbe1ddd8d1bd53269c4ca49297544860f3d3e5..b97912fdbae78304be7c3c45c862dce880e08dd4 100644
--- a/include/linux/seq_file_net.h
+++ b/include/linux/seq_file_net.h
@@ -9,7 +9,8 @@ extern struct net init_net;
 
 struct seq_net_private {
 #ifdef CONFIG_NET_NS
-	struct net *net;
+	struct net	*net;
+	netns_tracker	ns_tracker;
 #endif
 };
 
-- 
2.34.1.173.g76aa8bc2d0-goog


^ permalink raw reply related

* Re: [PATCH] net/batman-adv:remove unneeded variable
From: Sven Eckelmann @ 2021-12-10  7:52 UTC (permalink / raw)
  To: mareklindner, cgel.zte
  Cc: sw, a, davem, kuba, b.a.t.m.a.n, netdev, linux-kernel,
	Minghao Chi
In-Reply-To: <20211210021917.423912-1-chi.minghao@zte.com.cn>

[-- Attachment #1: Type: text/plain, Size: 466 bytes --]

On Friday, 10 December 2021 03:19:17 CET cgel.zte@gmail.com wrote:
> From: Minghao Chi <chi.minghao@zte.com.cn>
> 
> Return status directly from function called.
> 
> Reported-by: Zeal Robot <zealci@zte.com.cm>

And the Reported-by (robot) using a mail address which is bouncing.

   <zealci@zte.com.cm>: Host or domain name not found. Name service error for
       name=zte.com.cm type=AAAA: Host not found

Please fix this too in your scripts.

Kind regards,
	Sven

[-- Attachment #2: This is a digitally signed message part. --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply

* Re: [PATCH] net/batman-adv:remove unneeded variable
From: Sven Eckelmann @ 2021-12-10  7:49 UTC (permalink / raw)
  To: mareklindner, cgel.zte
  Cc: sw, a, davem, kuba, b.a.t.m.a.n, netdev, linux-kernel,
	Minghao Chi, Zeal Robot
In-Reply-To: <20211210021917.423912-1-chi.minghao@zte.com.cn>

[-- Attachment #1: Type: text/plain, Size: 417 bytes --]

On Friday, 10 December 2021 03:19:17 CET cgel.zte@gmail.com wrote:
> From: Minghao Chi <chi.minghao@zte.com.cn>
> 
> Return status directly from function called.
> 
> Reported-by: Zeal Robot <zealci@zte.com.cm>
> Signed-off-by: Minghao Chi <chi.minghao@zte.com.cn>

Applied after fixing obvious coding style problems.

Please try to fix the script which creates these automated patch submissions.

Kind regards,
	Sven

[-- Attachment #2: This is a digitally signed message part. --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply

* Re: [PATCH v5 3/5] can: do not copy the payload of RTR frames
From: Marc Kleine-Budde @ 2021-12-10  8:02 UTC (permalink / raw)
  To: Vincent Mailhol
  Cc: linux-can, Oliver Hartkopp, Jimmy Assarsson, netdev, linux-kernel,
	linux-arm-kernel, linux-sunxi, Yasushi SHOJI
In-Reply-To: <20211210073545.qdldwmaykts5dr4u@pengutronix.de>

[-- Attachment #1: Type: text/plain, Size: 665 bytes --]

On 10.12.2021 08:35:45, Marc Kleine-Budde wrote:
> On 07.12.2021 21:15:29, Vincent Mailhol wrote:
> > The actual payload length of the CAN Remote Transmission Request (RTR)
> > frames is always 0, i.e. nothing is transmitted on the wire. However,
>                            ^^^^^^^
> I've changed this to "no payload" to make it more unambiguous.

Same for the other patches.

Marc

-- 
Pengutronix e.K.                 | Marc Kleine-Budde           |
Embedded Linux                   | https://www.pengutronix.de  |
Vertretung West/Dortmund         | Phone: +49-231-2826-924     |
Amtsgericht Hildesheim, HRA 2686 | Fax:   +49-5121-206917-5555 |

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply

* Re: [PATCH] net/netfilter/x_tables.c: Use kvalloc to make your code better
From: Florian Westphal @ 2021-12-10  8:12 UTC (permalink / raw)
  To: lizhe
  Cc: pablo, kadlec, fw, davem, kuba, netfilter-devel, coreteam, netdev,
	linux-kernel
In-Reply-To: <20211210031244.13372-1-sensor1010@163.com>

lizhe <sensor1010@163.com> wrote:
> Use kvzalloc () instead of kvmalloc () and memset
> 
> Signed-off-by: lizhe <sensor1010@163.com>
> ---
>  net/netfilter/x_tables.c | 3 +--
>  1 file changed, 1 insertion(+), 2 deletions(-)
> 
> diff --git a/net/netfilter/x_tables.c b/net/netfilter/x_tables.c
> index 25524e393349..8d6ffed7d526 100644
> --- a/net/netfilter/x_tables.c
> +++ b/net/netfilter/x_tables.c
> @@ -1189,11 +1189,10 @@ struct xt_table_info *xt_alloc_table_info(unsigned int size)
>  	if (sz < sizeof(*info) || sz >= XT_MAX_TABLE_SIZE)
>  		return NULL;
>  
> -	info = kvmalloc(sz, GFP_KERNEL_ACCOUNT);
> +	info = kvzalloc(sz, GFP_KERNEL_ACCOUNT);
>  	if (!info)
>  		return NULL;
>  
> -	memset(info, 0, sizeof(*info));

sz != sizeof(*info)

^ permalink raw reply

* [PATCH net] sch_cake: do not call cake_destroy() from cake_init()
From: Eric Dumazet @ 2021-12-10  8:15 UTC (permalink / raw)
  To: David S . Miller, Jakub Kicinski
  Cc: netdev, Eric Dumazet, Eric Dumazet, syzbot,
	Toke Høiland-Jørgensen

From: Eric Dumazet <edumazet@google.com>

qdiscs are not supposed to call their own destroy() method
from init(), because core stack already does that.

syzbot was able to trigger use after free:

DEBUG_LOCKS_WARN_ON(lock->magic != lock)
WARNING: CPU: 0 PID: 21902 at kernel/locking/mutex.c:586 __mutex_lock_common kernel/locking/mutex.c:586 [inline]
WARNING: CPU: 0 PID: 21902 at kernel/locking/mutex.c:586 __mutex_lock+0x9ec/0x12f0 kernel/locking/mutex.c:740
Modules linked in:
CPU: 0 PID: 21902 Comm: syz-executor189 Not tainted 5.16.0-rc4-syzkaller #0
Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/01/2011
RIP: 0010:__mutex_lock_common kernel/locking/mutex.c:586 [inline]
RIP: 0010:__mutex_lock+0x9ec/0x12f0 kernel/locking/mutex.c:740
Code: 08 84 d2 0f 85 19 08 00 00 8b 05 97 38 4b 04 85 c0 0f 85 27 f7 ff ff 48 c7 c6 20 00 ac 89 48 c7 c7 a0 fe ab 89 e8 bf 76 ba ff <0f> 0b e9 0d f7 ff ff 48 8b 44 24 40 48 8d b8 c8 08 00 00 48 89 f8
RSP: 0018:ffffc9000627f290 EFLAGS: 00010282
RAX: 0000000000000000 RBX: 0000000000000000 RCX: 0000000000000000
RDX: ffff88802315d700 RSI: ffffffff815f1db8 RDI: fffff52000c4fe44
RBP: ffff88818f28e000 R08: 0000000000000000 R09: 0000000000000000
R10: ffffffff815ebb5e R11: 0000000000000000 R12: 0000000000000000
R13: dffffc0000000000 R14: ffffc9000627f458 R15: 0000000093c30000
FS:  0000555556abc400(0000) GS:ffff8880b9c00000(0000) knlGS:0000000000000000
CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 00007fda689c3303 CR3: 000000001cfbb000 CR4: 0000000000350ef0
Call Trace:
 <TASK>
 tcf_chain0_head_change_cb_del+0x2e/0x3d0 net/sched/cls_api.c:810
 tcf_block_put_ext net/sched/cls_api.c:1381 [inline]
 tcf_block_put_ext net/sched/cls_api.c:1376 [inline]
 tcf_block_put+0xbc/0x130 net/sched/cls_api.c:1394
 cake_destroy+0x3f/0x80 net/sched/sch_cake.c:2695
 qdisc_create.constprop.0+0x9da/0x10f0 net/sched/sch_api.c:1293
 tc_modify_qdisc+0x4c5/0x1980 net/sched/sch_api.c:1660
 rtnetlink_rcv_msg+0x413/0xb80 net/core/rtnetlink.c:5571
 netlink_rcv_skb+0x153/0x420 net/netlink/af_netlink.c:2496
 netlink_unicast_kernel net/netlink/af_netlink.c:1319 [inline]
 netlink_unicast+0x533/0x7d0 net/netlink/af_netlink.c:1345
 netlink_sendmsg+0x904/0xdf0 net/netlink/af_netlink.c:1921
 sock_sendmsg_nosec net/socket.c:704 [inline]
 sock_sendmsg+0xcf/0x120 net/socket.c:724
 ____sys_sendmsg+0x6e8/0x810 net/socket.c:2409
 ___sys_sendmsg+0xf3/0x170 net/socket.c:2463
 __sys_sendmsg+0xe5/0x1b0 net/socket.c:2492
 do_syscall_x64 arch/x86/entry/common.c:50 [inline]
 do_syscall_64+0x35/0xb0 arch/x86/entry/common.c:80
 entry_SYSCALL_64_after_hwframe+0x44/0xae
RIP: 0033:0x7f1bb06badb9
Code: Unable to access opcode bytes at RIP 0x7f1bb06bad8f.
RSP: 002b:00007fff3012a658 EFLAGS: 00000246 ORIG_RAX: 000000000000002e
RAX: ffffffffffffffda RBX: 0000000000000003 RCX: 00007f1bb06badb9
RDX: 0000000000000000 RSI: 00000000200007c0 RDI: 0000000000000003
RBP: 0000000000000000 R08: 0000000000000003 R09: 0000000000000003
R10: 0000000000000003 R11: 0000000000000246 R12: 00007fff3012a688
R13: 00007fff3012a6a0 R14: 00007fff3012a6e0 R15: 00000000000013c2
 </TASK>

Fixes: 046f6fd5daef ("sched: Add Common Applications Kept Enhanced (cake) qdisc")
Signed-off-by: Eric Dumazet <edumazet@google.com>
Reported-by: syzbot <syzkaller@googlegroups.com>
Signed-off-by: Toke Høiland-Jørgensen <toke@toke.dk>
---
 net/sched/sch_cake.c | 6 +-----
 1 file changed, 1 insertion(+), 5 deletions(-)

diff --git a/net/sched/sch_cake.c b/net/sched/sch_cake.c
index 3c2300d144681869a37ada0d20966f9b5b145653..857aaebd49f4315502928fb1f75d2c85eb63eb51 100644
--- a/net/sched/sch_cake.c
+++ b/net/sched/sch_cake.c
@@ -2736,7 +2736,7 @@ static int cake_init(struct Qdisc *sch, struct nlattr *opt,
 	q->tins = kvcalloc(CAKE_MAX_TINS, sizeof(struct cake_tin_data),
 			   GFP_KERNEL);
 	if (!q->tins)
-		goto nomem;
+		return -ENOMEM;
 
 	for (i = 0; i < CAKE_MAX_TINS; i++) {
 		struct cake_tin_data *b = q->tins + i;
@@ -2766,10 +2766,6 @@ static int cake_init(struct Qdisc *sch, struct nlattr *opt,
 	q->min_netlen = ~0;
 	q->min_adjlen = ~0;
 	return 0;
-
-nomem:
-	cake_destroy(sch);
-	return -ENOMEM;
 }
 
 static int cake_dump(struct Qdisc *sch, struct sk_buff *skb)
-- 
2.34.1.173.g76aa8bc2d0-goog


^ permalink raw reply related

* [PATCH] rtw88: 8821c: disable the ASPM of RTL8821CE
From: Jian-Hong Pan @ 2021-12-10  8:17 UTC (permalink / raw)
  To: Ping-Ke Shih, Yan-Hsuan Chuang, Kalle Valo
  Cc: linux-wireless, netdev, linux-kernel, linux, Jian-Hong Pan

More and more laptops become frozen, due to the equipped RTL8821CE.

This patch follows the idea mentioned in commits 956c6d4f20c5 ("rtw88:
add quirks to disable pci capabilities") and 1d4dcaf3db9bd ("rtw88: add
quirk to disable pci caps on HP Pavilion 14-ce0xxx"), but disables its
PCI ASPM capability of RTL8821CE directly, instead of checking DMI.

Buglink:https://bugzilla.kernel.org/show_bug.cgi?id=215239
Fixes: 1d4dcaf3db9bd ("rtw88: add quirk to disable pci caps on HP Pavilion 14-ce0xxx")
Signed-off-by: Jian-Hong Pan <jhp@endlessos.org>
---
 drivers/net/wireless/realtek/rtw88/main.h     |  3 ++
 drivers/net/wireless/realtek/rtw88/pci.c      | 33 ++-----------------
 drivers/net/wireless/realtek/rtw88/pci.h      |  5 +++
 drivers/net/wireless/realtek/rtw88/rtw8821c.c |  3 ++
 4 files changed, 14 insertions(+), 30 deletions(-)

diff --git a/drivers/net/wireless/realtek/rtw88/main.h b/drivers/net/wireless/realtek/rtw88/main.h
index bbdd535b64e7..31cd427a0949 100644
--- a/drivers/net/wireless/realtek/rtw88/main.h
+++ b/drivers/net/wireless/realtek/rtw88/main.h
@@ -1259,6 +1259,9 @@ struct rtw_chip_info {
 	const struct rtw_hw_reg *btg_reg;
 	const struct rtw_reg_domain *coex_info_hw_regs;
 	u32 wl_fw_desired_ver;
+
+	/* quirk flags */
+	u32 pci_quirk_data;
 };
 
 enum rtw_coex_bt_state_cnt {
diff --git a/drivers/net/wireless/realtek/rtw88/pci.c b/drivers/net/wireless/realtek/rtw88/pci.c
index a7a6ebfaa203..0a858db2d515 100644
--- a/drivers/net/wireless/realtek/rtw88/pci.c
+++ b/drivers/net/wireless/realtek/rtw88/pci.c
@@ -1702,14 +1702,9 @@ static void rtw_pci_napi_deinit(struct rtw_dev *rtwdev)
 	netif_napi_del(&rtwpci->napi);
 }
 
-enum rtw88_quirk_dis_pci_caps {
-	QUIRK_DIS_PCI_CAP_MSI,
-	QUIRK_DIS_PCI_CAP_ASPM,
-};
-
-static int disable_pci_caps(const struct dmi_system_id *dmi)
+static int disable_pci_caps_by_chip(const struct rtw_chip_info *chip)
 {
-	uintptr_t dis_caps = (uintptr_t)dmi->driver_data;
+	u32 dis_caps = chip->pci_quirk_data;
 
 	if (dis_caps & BIT(QUIRK_DIS_PCI_CAP_MSI))
 		rtw_disable_msi = true;
@@ -1719,28 +1714,6 @@ static int disable_pci_caps(const struct dmi_system_id *dmi)
 	return 1;
 }
 
-static const struct dmi_system_id rtw88_pci_quirks[] = {
-	{
-		.callback = disable_pci_caps,
-		.ident = "Protempo Ltd L116HTN6SPW",
-		.matches = {
-			DMI_MATCH(DMI_SYS_VENDOR, "Protempo Ltd"),
-			DMI_MATCH(DMI_PRODUCT_NAME, "L116HTN6SPW"),
-		},
-		.driver_data = (void *)BIT(QUIRK_DIS_PCI_CAP_ASPM),
-	},
-	{
-		.callback = disable_pci_caps,
-		.ident = "HP HP Pavilion Laptop 14-ce0xxx",
-		.matches = {
-			DMI_MATCH(DMI_SYS_VENDOR, "HP"),
-			DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion Laptop 14-ce0xxx"),
-		},
-		.driver_data = (void *)BIT(QUIRK_DIS_PCI_CAP_ASPM),
-	},
-	{}
-};
-
 int rtw_pci_probe(struct pci_dev *pdev,
 		  const struct pci_device_id *id)
 {
@@ -1791,7 +1764,7 @@ int rtw_pci_probe(struct pci_dev *pdev,
 		goto err_destroy_pci;
 	}
 
-	dmi_check_system(rtw88_pci_quirks);
+	disable_pci_caps_by_chip(rtwdev->chip);
 	rtw_pci_phy_cfg(rtwdev);
 
 	ret = rtw_register_hw(rtwdev, hw);
diff --git a/drivers/net/wireless/realtek/rtw88/pci.h b/drivers/net/wireless/realtek/rtw88/pci.h
index 66f78eb7757c..f470387fbb9a 100644
--- a/drivers/net/wireless/realtek/rtw88/pci.h
+++ b/drivers/net/wireless/realtek/rtw88/pci.h
@@ -274,4 +274,9 @@ struct rtw_pci_tx_buffer_desc *get_tx_buffer_desc(struct rtw_pci_tx_ring *ring,
 	return (struct rtw_pci_tx_buffer_desc *)buf_desc;
 }
 
+enum rtw88_quirk_dis_pci_caps {
+	QUIRK_DIS_PCI_CAP_MSI,
+	QUIRK_DIS_PCI_CAP_ASPM,
+};
+
 #endif
diff --git a/drivers/net/wireless/realtek/rtw88/rtw8821c.c b/drivers/net/wireless/realtek/rtw88/rtw8821c.c
index 80a6f4da6acd..4d684534fa1e 100644
--- a/drivers/net/wireless/realtek/rtw88/rtw8821c.c
+++ b/drivers/net/wireless/realtek/rtw88/rtw8821c.c
@@ -15,6 +15,7 @@
 #include "debug.h"
 #include "bf.h"
 #include "regd.h"
+#include "pci.h"
 
 static const s8 lna_gain_table_0[8] = {22, 8, -6, -22, -31, -40, -46, -52};
 static const s8 lna_gain_table_1[16] = {10, 6, 2, -2, -6, -10, -14, -17,
@@ -1947,6 +1948,8 @@ struct rtw_chip_info rtw8821c_hw_spec = {
 
 	.coex_info_hw_regs_num = ARRAY_SIZE(coex_info_hw_regs_8821c),
 	.coex_info_hw_regs = coex_info_hw_regs_8821c,
+
+	.pci_quirk_data = BIT(QUIRK_DIS_PCI_CAP_ASPM),
 };
 EXPORT_SYMBOL(rtw8821c_hw_spec);
 
-- 
2.34.1


^ permalink raw reply related

* [PATCH v3, 0/2] ADD DM9051 ETHERNET DRIVER
From: JosephCHANG @ 2021-12-10  8:40 UTC (permalink / raw)
  To: David S . Miller, Jakub Kicinski, Rob Herring, Joseph CHANG,
	joseph_chang
  Cc: netdev, devicetree, linux-kernel

DM9051 is a spi interface ethernet controller chip
Fewer connect pins to CPU compare to DM9000.

JosephCHANG (2):
  yaml: Add dm9051 SPI network yaml file
  net: Add dm9051 driver

 .../bindings/net/davicom,dm9051.yaml          |  71 ++
 drivers/net/ethernet/davicom/Kconfig          |  30 +
 drivers/net/ethernet/davicom/Makefile         |   1 +
 drivers/net/ethernet/davicom/dm9051.c         | 861 ++++++++++++++++++
 drivers/net/ethernet/davicom/dm9051.h         | 225 +++++
 5 files changed, 1188 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/net/davicom,dm9051.yaml
 create mode 100644 drivers/net/ethernet/davicom/dm9051.c
 create mode 100644 drivers/net/ethernet/davicom/dm9051.h


base-commit: 9d922f5df53844228b9f7c62f2593f4f06c0b69b
-- 
2.20.1


^ permalink raw reply

* [PATCH v3, 1/2] yaml: Add dm9051 SPI network yaml file
From: JosephCHANG @ 2021-12-10  8:40 UTC (permalink / raw)
  To: David S . Miller, Jakub Kicinski, Rob Herring, Joseph CHANG,
	joseph_chang
  Cc: netdev, devicetree, linux-kernel
In-Reply-To: <20211210084021.13993-1-josright123@gmail.com>

For support davicom dm9051 device tree configure

Signed-off-by: JosephCHANG <josright123@gmail.com>
---
 .../bindings/net/davicom,dm9051.yaml          | 71 +++++++++++++++++++
 1 file changed, 71 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/net/davicom,dm9051.yaml

diff --git a/Documentation/devicetree/bindings/net/davicom,dm9051.yaml b/Documentation/devicetree/bindings/net/davicom,dm9051.yaml
new file mode 100644
index 000000000000..4c2dd0362f7a
--- /dev/null
+++ b/Documentation/devicetree/bindings/net/davicom,dm9051.yaml
@@ -0,0 +1,71 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/net/davicom,dm9051.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Davicom DM9051 SPI Ethernet Controller
+
+maintainers:
+  - Joseph CHANG <josright123@gmail.com>
+
+description: |
+  The DM9051 is a fully integrated and cost-effective low pin count single
+  chip Fast Ethernet controller with a Serial Peripheral Interface (SPI).
+
+allOf:
+  - $ref: ethernet-controller.yaml#
+
+properties:
+  compatible:
+    const: davicom,dm9051
+
+  reg:
+    maxItems: 1
+
+  spi-max-frequency:
+    maximum: 45000000
+
+  interrupts:
+    maxItems: 1
+
+  local-mac-address: true
+
+  mac-address: true
+
+required:
+  - compatible
+  - reg
+  - spi-max-frequency
+  - interrupts
+
+additionalProperties: false
+
+examples:
+  # Raspberry Pi platform
+  - |
+    /* for Raspberry Pi with pin control stuff for GPIO irq */
+    #include <dt-bindings/interrupt-controller/irq.h>
+    #include <dt-bindings/gpio/gpio.h>
+    spi {
+        #address-cells = <1>;
+        #size-cells = <0>;
+
+        dm9051@0 {
+            compatible = "davicom,dm9051";
+            reg = <0>; /* spi chip select */
+            local-mac-address = [00 00 00 00 00 00];
+            pinctrl-names = "default";
+            pinctrl-0 = <&eth_int_pins>;
+            interrupt-parent = <&gpio>;
+            interrupts = <26 IRQ_TYPE_LEVEL_LOW>;
+            spi-max-frequency = <31200000>;
+        };
+    };
+    gpio {
+        eth_int_pins {
+            brcm,pins = <26>;
+            brcm,function = <0>; /* in */
+            brcm,pull = <0>; /* none */
+        };
+    };
-- 
2.20.1


^ permalink raw reply related

* [PATCH v3, 2/2] net: Add dm9051 driver
From: JosephCHANG @ 2021-12-10  8:40 UTC (permalink / raw)
  To: David S . Miller, Jakub Kicinski, Rob Herring, Joseph CHANG,
	joseph_chang
  Cc: netdev, devicetree, linux-kernel
In-Reply-To: <20211210084021.13993-1-josright123@gmail.com>

Add davicom dm9051 spi ethernet driver. The driver work for the
device with its spi master.

Test ok with raspberry pi 2 and pi 4, the spi configure used in
my raspberry pi 4 is spi0.1, spi speed 31200000, and INT by pin 26.

Signed-off-by: JosephCHANG <josright123@gmail.com>
---
 drivers/net/ethernet/davicom/Kconfig  |  30 +
 drivers/net/ethernet/davicom/Makefile |   1 +
 drivers/net/ethernet/davicom/dm9051.c | 861 ++++++++++++++++++++++++++
 drivers/net/ethernet/davicom/dm9051.h | 225 +++++++
 4 files changed, 1117 insertions(+)
 create mode 100644 drivers/net/ethernet/davicom/dm9051.c
 create mode 100644 drivers/net/ethernet/davicom/dm9051.h

diff --git a/drivers/net/ethernet/davicom/Kconfig b/drivers/net/ethernet/davicom/Kconfig
index 7af86b6d4150..9c00328f6e05 100644
--- a/drivers/net/ethernet/davicom/Kconfig
+++ b/drivers/net/ethernet/davicom/Kconfig
@@ -3,6 +3,20 @@
 # Davicom device configuration
 #
 
+config NET_VENDOR_DAVICOM
+	bool "Davicom devices"
+	depends on ARM || MIPS || COLDFIRE || NIOS2 || COMPILE_TEST || SPI
+	default y
+	help
+	  If you have a network (Ethernet) card belonging to this class, say Y.
+
+	  Note that the answer to this question doesn't directly affect the
+	  kernel: saying N will just cause the configurator to skip all
+	  the questions about Davicom devices. If you say Y, you will be asked
+	  for your specific card in the following selections.
+
+if NET_VENDOR_DAVICOM
+
 config DM9000
 	tristate "DM9000 support"
 	depends on ARM || MIPS || COLDFIRE || NIOS2 || COMPILE_TEST
@@ -22,3 +36,19 @@ config DM9000_FORCE_SIMPLE_PHY_POLL
 	  bit to determine if the link is up or down instead of the more
 	  costly MII PHY reads. Note, this will not work if the chip is
 	  operating with an external PHY.
+
+config DM9051
+	tristate "DM9051 SPI support"
+	depends on SPI
+	select CRC32
+	select MII
+	help
+	  Support for DM9051 SPI chipset.
+
+	  To compile this driver as a module, choose M here.  The module
+	  will be called dm9051.
+
+	  The SPI mode for the host's SPI master to access DM9051 is mode
+	  0 on the SPI bus.
+
+endif # NET_VENDOR_DAVICOM
diff --git a/drivers/net/ethernet/davicom/Makefile b/drivers/net/ethernet/davicom/Makefile
index 173c87d21076..225f85bc1f53 100644
--- a/drivers/net/ethernet/davicom/Makefile
+++ b/drivers/net/ethernet/davicom/Makefile
@@ -4,3 +4,4 @@
 #
 
 obj-$(CONFIG_DM9000) += dm9000.o
+obj-$(CONFIG_DM9051) += dm9051.o
diff --git a/drivers/net/ethernet/davicom/dm9051.c b/drivers/net/ethernet/davicom/dm9051.c
new file mode 100644
index 000000000000..c942bcebd5ba
--- /dev/null
+++ b/drivers/net/ethernet/davicom/dm9051.c
@@ -0,0 +1,861 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2021 Davicom Semiconductor,Inc.
+ * Davicom DM9051 SPI Fast Ethernet Linux driver
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/interrupt.h>
+#include <linux/skbuff.h>
+#include <linux/spinlock.h>
+#include <linux/cache.h>
+#include <linux/crc32.h>
+#include <linux/mii.h>
+#include <linux/ethtool.h>
+#include <linux/delay.h>
+#include <linux/irq.h>
+#include <linux/slab.h>
+#include <linux/gpio.h>
+#include <linux/iopoll.h>
+#include <linux/of_gpio.h>
+#include <linux/spi/spi.h>
+
+#include "dm9051.h"
+
+/* spi low level code */
+static int
+dm9051_xfer(struct board_info *db, u8 cmdphase, u8 *txb, u8 *rxb, unsigned int len)
+{
+	struct device *dev = &db->spidev->dev;
+	int ret = 0;
+
+	db->cmd[0] = cmdphase;
+	db->spi_xfer2[0].tx_buf = &db->cmd[0];
+	db->spi_xfer2[0].rx_buf = NULL;
+	db->spi_xfer2[0].len = 1;
+	if (!rxb) {
+		db->spi_xfer2[1].tx_buf = txb;
+		db->spi_xfer2[1].rx_buf = NULL;
+		db->spi_xfer2[1].len = len;
+	} else {
+		db->spi_xfer2[1].tx_buf = txb;
+		db->spi_xfer2[1].rx_buf = rxb;
+		db->spi_xfer2[1].len = len;
+	}
+	ret = spi_sync(db->spidev, &db->spi_msg2);
+	if (ret < 0)
+		dev_err(dev, "dm9Err spi burst cmd 0x%02x, ret=%d\n", cmdphase, ret);
+	return ret;
+}
+
+static u8 std_spi_read_reg(struct board_info *db, unsigned int reg)
+{
+	u8 rxb[1];
+
+	dm9051_xfer(db, DM_SPI_RD | reg, NULL, rxb, 1);
+	return rxb[0];
+}
+
+/* chip ID display */
+static u8 disp_spi_read_reg(struct device *dev, struct board_info *db,
+			    unsigned int reg)
+{
+	u8 rxdata;
+
+	rxdata = std_spi_read_reg(db, reg);
+	if (reg == DM9051_PIDL || reg == DM9051_PIDH)
+		dev_info(dev, "dm905.MOSI.p.[%02x][..]\n", reg);
+	if (reg == DM9051_PIDL || reg == DM9051_PIDH)
+		dev_info(dev, "dm905.MISO.e.[..][%02x]\n", rxdata);
+	return rxdata;
+}
+
+static void std_spi_write_reg(struct board_info *db, unsigned int reg,
+			      unsigned int val)
+{
+	u8 txb[1];
+
+	txb[0] = val;
+	dm9051_xfer(db, DM_SPI_WR | reg, txb, NULL, 1);
+}
+
+static void std_read_rx_buf_ncpy(struct board_info *db, u8 *buff, unsigned int len)
+{
+	u8 txb[1];
+
+	dm9051_xfer(db, DM_SPI_RD | DM_SPI_MRCMD, txb, buff, len);
+}
+
+static int std_write_tx_buf(struct board_info *db, u8 *buff, unsigned int len)
+{
+	dm9051_xfer(db, DM_SPI_WR | DM_SPI_MWCMD, buff, NULL, len);
+	return 0;
+}
+
+/* basic read/write to phy
+ */
+static int dm_phy_read_func(struct board_info *db, int reg)
+{
+	int ret;
+	u8 check_val;
+
+	iow(db, DM9051_EPAR, DM9051_PHY | reg);
+	iow(db, DM9051_EPCR, EPCR_ERPRR | EPCR_EPOS);
+	read_poll_timeout(ior, check_val, !(check_val & EPCR_ERRE), 100, 10000,
+			  true, db, DM9051_EPCR);
+	iow(db, DM9051_EPCR, 0x0);
+	ret = (ior(db, DM9051_EPDRH) << 8) | ior(db, DM9051_EPDRL);
+	return ret;
+}
+
+static void dm_phy_write_func(struct board_info *db, int reg, int value)
+{
+	u8 check_val;
+
+	iow(db, DM9051_EPAR, DM9051_PHY | reg);
+	iow(db, DM9051_EPDRL, value);
+	iow(db, DM9051_EPDRH, value >> 8);
+	iow(db, DM9051_EPCR, EPCR_EPOS | EPCR_ERPRW);
+	read_poll_timeout(ior, check_val, !(check_val & EPCR_ERRE), 100, 10000,
+			  true, db, DM9051_EPCR);
+	iow(db, DM9051_EPCR, 0x0);
+}
+
+/* Read a word data from SROM
+ */
+static void dm_read_eeprom_func(struct board_info *db, int offset, u8 *to)
+{
+	u8 check_val;
+
+	mutex_lock(&db->addr_lock);
+	iow(db, DM9051_EPAR, offset);
+	iow(db, DM9051_EPCR, EPCR_ERPRR);
+	read_poll_timeout(ior, check_val, !(check_val & EPCR_ERRE), 100, 10000,
+			  true, db, DM9051_EPCR);
+	iow(db, DM9051_EPCR, 0x0);
+	to[0] = ior(db, DM9051_EPDRL);
+	to[1] = ior(db, DM9051_EPDRH);
+	mutex_unlock(&db->addr_lock);
+}
+
+/* Write a word data to SROM
+ */
+static void dm_write_eeprom_func(struct board_info *db, int offset, u8 *data)
+{
+	u8 check_val;
+
+	mutex_lock(&db->addr_lock);
+	iow(db, DM9051_EPAR, offset);
+	iow(db, DM9051_EPDRH, data[1]);
+	iow(db, DM9051_EPDRL, data[0]);
+	iow(db, DM9051_EPCR, EPCR_WEP | EPCR_ERPRW);
+	read_poll_timeout(ior, check_val, !(check_val & EPCR_ERRE), 100, 10000,
+			  true, db, DM9051_EPCR);
+	iow(db, DM9051_EPCR, 0);
+	mutex_unlock(&db->addr_lock);
+}
+
+static int dm9051_phy_read_lock(struct net_device *dev, int phy_reg_unused, int reg)
+{
+	int val;
+	struct board_info *db = netdev_priv(dev);
+
+	mutex_lock(&db->addr_lock);
+	val = dm_phy_read_func(db, reg);
+	mutex_unlock(&db->addr_lock);
+	return val;
+}
+
+static void dm9051_phy_write_lock(struct net_device *dev, int phyaddr_unused, int reg, int value)
+{
+	struct board_info *db = netdev_priv(dev);
+
+	mutex_lock(&db->addr_lock);
+	dm_phy_write_func(db, reg, value);
+	mutex_unlock(&db->addr_lock);
+}
+
+/* read chip id
+ */
+static unsigned int dm9051_chipid(struct device *dev, struct board_info *db)
+{
+	unsigned int chipid;
+
+	chipid = iior(dev, db, DM9051_PIDL);
+	chipid |= (unsigned int)iior(dev, db, DM9051_PIDH) << 8;
+	if (chipid == DM9051_ID)
+		return chipid;
+	chipid = iior(dev, db, DM9051_PIDL);
+	chipid |= (unsigned int)iior(dev, db, DM9051_PIDH) << 8;
+	if (chipid == DM9051_ID)
+		return chipid;
+	dev_dbg(dev, "Read [DM9051_PID] = %04x\n", chipid);
+	dev_dbg(dev, "Read [DM9051_PID] error!\n");
+	return chipid;
+}
+
+static void dm9051_reset(struct board_info *db)
+{
+	mdelay(2); /* need before NCR_RST */
+	ncr_reg_reset(db);
+	mdelay(1);
+	mbd_reg_byte(db);
+	mdelay(1);
+	dm_phy_write_func(db, MII_ADVERTISE, ADVERTISE_PAUSE_CAP |
+			  ADVERTISE_ALL | ADVERTISE_CSMA); /* for fcr, essential */
+	fcr_reg_enable(db);
+	ppcr_reg_seeting(db);
+	ledcr_reg_setting(db, db->lcr_all);
+	intcr_reg_setval(db);
+}
+
+/* ESSENTIAL, ensure rxFifoPoint control, disable/enable the interrupt mask
+ */
+static void dm_imr_disable_lock_essential(struct board_info *db)
+{
+	mutex_lock(&db->addr_lock);
+	imr_reg_stop(db);
+	mutex_unlock(&db->addr_lock);
+}
+
+static void dm_imr_enable_lock_essential(struct board_info *db)
+{
+	mutex_lock(&db->addr_lock);
+	imr_reg_start(db, db->imr_all); /* rxp to 0xc00 */
+	mutex_unlock(&db->addr_lock);
+}
+
+/* functions process mac address is major from EEPROM
+ */
+static void dm9051_read_mac_to_dev(struct device *dev, struct net_device *ndev,
+				   struct board_info *db)
+{
+	int i;
+
+	for (i = 0; i < ETH_ALEN; i++)
+		ndev->dev_addr[i] = ior(db, DM9051_PAR + i);
+	if (!is_valid_ether_addr(ndev->dev_addr)) {
+		eth_hw_addr_random(ndev);
+		dev_dbg(dev, "dm9 [reg_netdev][%s][chip MAC: %pM (%s)]\n",
+			ndev->name, ndev->dev_addr, "FIX-1");
+	}
+}
+
+/* set mac permanently
+ */
+static void dm_set_mac_lock(struct board_info *db)
+{
+	struct net_device *ndev = db->ndev;
+	int i, oft;
+
+	netdev_dbg(ndev, "set_mac_address %pM\n", ndev->dev_addr);
+
+	/* write to net device and chip */
+	mutex_lock(&db->addr_lock);
+	for (i = 0, oft = DM9051_PAR; i < ETH_ALEN; i++, oft++)
+		iow(db, oft, ndev->dev_addr[i]);
+	mutex_unlock(&db->addr_lock);
+
+	/* write to EEPROM */
+	for (i = 0; i < ETH_ALEN; i += 2)
+		dm_write_eeprom_func(db, i / 2, (u8 *)&ndev->dev_addr[i]);
+}
+
+/* netdev-ops
+ */
+static const struct of_device_id dm9051_match_table[] = {
+	{ .compatible = "davicom,dm9051", },
+	{},
+};
+
+static const struct spi_device_id dm9051_id_table[] = {
+	{ "dm9051", 0 },
+	{},
+};
+
+static
+const struct net_device_ops dm9051_netdev_ops = {
+	.ndo_open = dm9051_open,
+	.ndo_stop = dm9051_stop,
+	.ndo_start_xmit = dm9051_start_xmit,
+	.ndo_set_rx_mode = dm9051_set_multicast_list_schedule,
+	.ndo_validate_addr = eth_validate_addr,
+	.ndo_set_mac_address = dm9051_set_mac_address,
+};
+
+/* ethtool-ops
+ */
+static void
+dm9051_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
+{
+	strscpy(info->driver, DRVNAME_9051, sizeof(info->driver));
+}
+
+static void dm9051_set_msglevel(struct net_device *dev, u32 value)
+{
+	struct board_info *dm = to_dm9051_board(dev);
+
+	dm->msg_enable = value;
+}
+
+static u32 dm9051_get_msglevel(struct net_device *dev)
+{
+	struct board_info *dm = to_dm9051_board(dev);
+
+	return dm->msg_enable;
+}
+
+static int dm9051_get_link_ksettings(struct net_device *dev,
+				     struct ethtool_link_ksettings *cmd)
+{
+	struct board_info *dm = to_dm9051_board(dev);
+
+	mii_ethtool_get_link_ksettings(&dm->mii, cmd);
+	return 0;
+}
+
+static int dm9051_set_link_ksettings(struct net_device *dev,
+				     const struct ethtool_link_ksettings *cmd)
+{
+	struct board_info *dm = to_dm9051_board(dev);
+
+	return mii_ethtool_set_link_ksettings(&dm->mii, cmd);
+}
+
+static int dm9051_nway_reset(struct net_device *dev)
+{
+	struct board_info *dm = to_dm9051_board(dev);
+
+	return mii_nway_restart(&dm->mii);
+}
+
+static u32 dm9051_get_link(struct net_device *dev)
+{
+	struct board_info *db = to_dm9051_board(dev);
+
+	return mii_link_ok(&db->mii);
+}
+
+static int dm9051_get_eeprom_len(struct net_device *dev)
+{
+	return 128;
+}
+
+static int dm9051_get_eeprom(struct net_device *dev,
+			     struct ethtool_eeprom *ee, u8 *data)
+{
+	struct board_info *dm = to_dm9051_board(dev);
+	int offset = ee->offset;
+	int len = ee->len;
+	int i;
+
+	if ((len & 1) != 0 || (offset & 1) != 0)
+		return -EINVAL;
+
+	ee->magic = DM_EEPROM_MAGIC;
+
+	for (i = 0; i < len; i += 2)
+		dm_read_eeprom_func(dm, (offset + i) / 2, data + i);
+	return 0;
+}
+
+static int dm9051_set_eeprom(struct net_device *dev,
+			     struct ethtool_eeprom *ee, u8 *data)
+{
+	struct board_info *dm = to_dm9051_board(dev);
+	int offset = ee->offset;
+	int len = ee->len;
+	int i;
+
+	if ((len & 1) != 0 || (offset & 1) != 0)
+		return -EINVAL;
+
+	if (ee->magic != DM_EEPROM_MAGIC)
+		return -EINVAL;
+
+	for (i = 0; i < len; i += 2)
+		dm_write_eeprom_func(dm, (offset + i) / 2, data + i);
+	return 0;
+}
+
+const struct ethtool_ops dm9051_ethtool_ops = {
+	.get_drvinfo = dm9051_get_drvinfo,
+	.get_link_ksettings = dm9051_get_link_ksettings,
+	.set_link_ksettings = dm9051_set_link_ksettings,
+	.get_msglevel = dm9051_get_msglevel,
+	.set_msglevel = dm9051_set_msglevel,
+	.nway_reset = dm9051_nway_reset,
+	.get_link = dm9051_get_link,
+	.get_eeprom_len = dm9051_get_eeprom_len,
+	.get_eeprom = dm9051_get_eeprom,
+	.set_eeprom = dm9051_set_eeprom,
+};
+
+static void dm_operation_clear(struct board_info *db)
+{
+	db->bc.mac_ovrsft_counter = 0;
+	db->bc.large_err_counter = 0;
+	db->bc.DO_FIFO_RST_counter = 0;
+}
+
+/* reset and increase the RST counter
+ */
+static void dm9051_fifo_reset(u8 state, u8 *hstr, struct board_info *db)
+{
+	db->bc.DO_FIFO_RST_counter++;
+	dm9051_reset(db);
+}
+
+static void dm9051_reset_dm9051(struct board_info *db, int rxlen)
+{
+	struct net_device *ndev = db->ndev;
+	char *sbuff = (char *)db->prxhdr;
+	char hstr[72];
+
+	netdev_dbg(ndev, "dm9-pkt-Wrong RxLen over-range (%x= %d > %x= %d)\n",
+		   rxlen, rxlen, DM9051_PKT_MAX, DM9051_PKT_MAX);
+
+	db->bc.large_err_counter++;
+	db->bc.mac_ovrsft_counter++;
+	dm9051_fifo_reset(11, hstr, db);
+	sprintf(hstr, "dmfifo_reset( 11 RxLenErr ) rxhdr %02x %02x %02x %02x (quick)",
+		sbuff[0], sbuff[1], sbuff[2], sbuff[3]);
+	netdev_dbg(ndev, "%s\n", hstr);
+	netdev_dbg(ndev, " RxLenErr&MacOvrSft_Er %d, RST_c %d\n",
+		   db->bc.mac_ovrsft_counter, db->bc.DO_FIFO_RST_counter);
+}
+
+/* loop rx
+ */
+static int dm9051_lrx(struct board_info *db)
+{
+	struct net_device *ndev = db->ndev;
+	u8 rxbyte;
+	int rxlen;
+	char sbuff[DM_RXHDR_SIZE];
+	struct sk_buff *skb;
+	u8 *rdptr;
+	int scanrr = 0;
+
+	while (1) {
+		rxbyte = ior(db, DM_SPI_MRCMDX); /* Dummy read */
+		rxbyte = ior(db, DM_SPI_MRCMDX); /* Dummy read */
+		if (rxbyte != DM9051_PKT_RDY) {
+			isr_reg_clear_to_stop_mrcmd(db);
+			break; /* exhaust-empty */
+		}
+		dm9inblk(db, sbuff, DM_RXHDR_SIZE);
+		isr_reg_clear_to_stop_mrcmd(db);
+
+		db->prxhdr = (struct dm9051_rxhdr *)sbuff;
+		if (db->prxhdr->rxstatus & 0xbf) {
+			netdev_dbg(ndev, "warn : rxhdr.status 0x%02x\n",
+				   db->prxhdr->rxstatus);
+		}
+		if (db->prxhdr->rxlen > DM9051_PKT_MAX) {
+			dm9051_reset_dm9051(db, rxlen);
+			return scanrr;
+		}
+
+		rxlen = db->prxhdr->rxlen;
+		skb = dev_alloc_skb(rxlen + 4);
+		if (!skb) {
+			netdev_dbg(ndev, "alloc skb size %d fail\n", rxlen + 4);
+			return scanrr;
+		}
+		skb_reserve(skb, 2);
+		rdptr = (u8 *)skb_put(skb, rxlen - 4);
+
+		dm9inblk(db, rdptr, rxlen);
+		isr_reg_clear_to_stop_mrcmd(db);
+
+		skb->protocol = eth_type_trans(skb, db->ndev);
+		if (db->ndev->features & NETIF_F_RXCSUM)
+			skb_checksum_none_assert(skb);
+		if (in_interrupt())
+			netif_rx(skb);
+		else
+			netif_rx_ni(skb);
+		db->ndev->stats.rx_bytes += rxlen;
+		db->ndev->stats.rx_packets++;
+		scanrr++;
+	}
+	return scanrr;
+}
+
+/* single tx
+ */
+static int dm9051_stx(struct board_info *db, u8 *buff, unsigned int len)
+{
+	int ret;
+	u8 check_val;
+
+	/* shorter waiting time with tx-end check */
+	ret = read_poll_timeout(ior, check_val, check_val & (NSR_TX2END | NSR_TX1END),
+				1, 20, false, db, DM9051_NSR);
+	dm9outblk(db, buff, len);
+	iow(db, DM9051_TXPLL, len);
+	iow(db, DM9051_TXPLH, len >> 8);
+	iow(db, DM9051_TCR, TCR_TXREQ);
+	return ret;
+}
+
+static int dm9051_send(struct board_info *db)
+{
+	struct net_device *ndev = db->ndev;
+	int ntx = 0;
+
+	while (!skb_queue_empty(&db->txq)) {
+		struct sk_buff *skb;
+
+		skb = dm_sk_buff_get(db);
+		if (skb) {
+			ntx++;
+			if (dm9051_stx(db, skb->data, skb->len))
+				netdev_dbg(ndev, "timeout %d--- WARNING---do-ntx\n", ntx);
+			ndev->stats.tx_bytes += skb->len;
+			ndev->stats.tx_packets++;
+			dev_kfree_skb(skb);
+		}
+	}
+	return ntx;
+}
+
+/* end with enable the interrupt mask
+ */
+static irqreturn_t dm9051_rx_threaded_irq(int irq, void *pw)
+{
+	struct board_info *db = pw;
+	int nrx;
+
+	mutex_lock(&db->spi_lock); /* dlywork essential */
+	dm_imr_disable_lock_essential(db); /* set imr disable */
+	if (netif_carrier_ok(db->ndev)) {
+		mutex_lock(&db->addr_lock);
+		do {
+			nrx = dm9051_lrx(db);
+			dm9051_send(db); /* for more performance */
+		} while (nrx);
+		mutex_unlock(&db->addr_lock);
+	}
+	dm_imr_enable_lock_essential(db); /* set imr enable */
+	mutex_unlock(&db->spi_lock); /* dlywork essential */
+	return IRQ_HANDLED;
+}
+
+/* end with enable the interrupt mask
+ */
+static int dm_opencode_receiving(struct net_device *ndev, struct board_info *db)
+{
+	int ret;
+	struct spi_device *spi = db->spidev;
+
+	ndev->irq = spi->irq; /* by dts */
+	ret = request_threaded_irq(spi->irq, NULL, dm9051_rx_threaded_irq,
+				   IRQF_TRIGGER_LOW | IRQF_ONESHOT,
+				   ndev->name, db);
+	if (ret < 0) {
+		netdev_err(ndev, "failed to get irq\n");
+		return ret;
+	}
+	dm_imr_enable_lock_essential(db);
+	schedule_delayed_work(&db->phy_poll, HZ * 1); /* sched_start */
+	netdev_info(ndev, "[dm_open] %pM irq_no %d ACTIVE_LOW\n", ndev->dev_addr, ndev->irq);
+	return 0;
+}
+
+static void int_tx_delay(struct work_struct *w)
+{
+	struct delayed_work *dw = to_delayed_work(w);
+	struct board_info *db = container_of(dw, struct board_info, tx_work);
+
+	mutex_lock(&db->spi_lock); /* dlywork essential */
+	mutex_lock(&db->addr_lock);
+	dm9051_send(db);
+	mutex_unlock(&db->addr_lock);
+	mutex_unlock(&db->spi_lock); /* dlywork essential */
+}
+
+static void int_rxctl_delay(struct work_struct *w)
+{
+	struct delayed_work *dw = to_delayed_work(w);
+	struct board_info *db = container_of(dw, struct board_info, rxctrl_work);
+	struct net_device *ndev = db->ndev;
+	int i, oft;
+
+	mutex_lock(&db->addr_lock);
+
+	for (i = 0, oft = DM9051_PAR; i < ETH_ALEN; i++, oft++)
+		iow(db, oft, ndev->dev_addr[i]);
+
+	/* Write the hash table */
+	for (i = 0, oft = DM9051_MAR; i < 4; i++) {
+		iow(db, oft++, db->hash_table[i]);
+		iow(db, oft++, db->hash_table[i] >> 8);
+	}
+
+	rcr_reg_start(db, db->rcr_all);
+
+	mutex_unlock(&db->addr_lock);
+}
+
+static void int_phy_poll(struct work_struct *w)
+{
+	struct delayed_work *dw = to_delayed_work(w);
+	struct board_info *db = container_of(dw, struct board_info, phy_poll);
+
+	dm_carrier_poll(db);
+	schedule_delayed_work(&db->phy_poll, HZ * 1);
+}
+
+/* Irq free and schedule delays cancel
+ */
+static void dm_stopcode_release(struct board_info *db)
+{
+	free_irq(db->spidev->irq, db);
+	cancel_delayed_work_sync(&db->phy_poll);
+	cancel_delayed_work_sync(&db->rxctrl_work);
+	cancel_delayed_work_sync(&db->tx_work);
+}
+
+static void dm_control_init(struct board_info *db)
+{
+	mutex_init(&db->spi_lock);
+	mutex_init(&db->addr_lock);
+	INIT_DELAYED_WORK(&db->phy_poll, int_phy_poll);
+	INIT_DELAYED_WORK(&db->rxctrl_work, int_rxctl_delay);
+	INIT_DELAYED_WORK(&db->tx_work, int_tx_delay);
+}
+
+static void dm9051_init_dm9051(struct net_device *dev)
+{
+	struct board_info *db = netdev_priv(dev);
+
+	dm9051_fifo_reset(1, NULL, db);
+	imr_reg_stop(db);
+}
+
+static void dm_opencode_lock(struct net_device *dev, struct board_info *db)
+{
+	mutex_lock(&db->addr_lock); /* Note: must */
+	iow(db, DM9051_GPR, 0); /* Reg 1F is not set by reset, REG_1F bit0 activate phyxcer */
+	mdelay(1); /* delay needs for activate phyxcer */
+	db->imr_all = IMR_PAR | IMR_PRM;
+	db->rcr_all = RCR_DIS_LONG | RCR_DIS_CRC | RCR_RXEN;
+	db->lcr_all = LMCR_MODE1;
+	dm9051_init_dm9051(dev);
+	mutex_unlock(&db->addr_lock);
+}
+
+static void dm_stopcode_lock(struct board_info *db)
+{
+	mutex_lock(&db->addr_lock);
+	dm_phy_write_func(db, MII_BMCR, BMCR_RESET); /* PHY RESET */
+	iow(db, DM9051_GPR, 0x01); /* Power-Down PHY */
+	rcr_reg_stop(db); /* Disable RX */
+	mutex_unlock(&db->addr_lock);
+}
+
+static void dm_opencode_net(struct net_device *ndev, struct board_info *db)
+{
+	dm_sk_buff_head_init(db);
+	netif_start_queue(ndev);
+	netif_wake_queue(ndev);
+	dm_carrier_init(db);
+}
+
+static void dm_stopcode_net(struct net_device *ndev)
+{
+	netif_stop_queue(ndev);
+	dm_carrier_off(ndev);
+}
+
+/* Open network device
+ * Called when the network device is marked active, such as a user executing
+ * 'ifconfig up' on the device.
+ */
+static int dm9051_open(struct net_device *ndev)
+{
+	struct board_info *db = netdev_priv(ndev);
+
+	dm_opencode_lock(ndev, db);
+	dm_opencode_net(ndev, db);
+	return dm_opencode_receiving(ndev, db);
+}
+
+/* Close network device
+ * Called to close down a network device which has been active. Cancell any
+ * work, shutdown the RX and TX process and then place the chip into a low
+ * power state while it is not being used.
+ */
+static int dm9051_stop(struct net_device *ndev)
+{
+	struct board_info *db = netdev_priv(ndev);
+
+	dm_stopcode_release(db);
+	dm_stopcode_net(ndev);
+	dm_stopcode_lock(db);
+	return 0;
+}
+
+/* event: play a schedule starter in condition
+ */
+static netdev_tx_t dm9051_start_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+	struct board_info *db = netdev_priv(dev);
+
+	dm_sk_buff_set(db, skb); /* add to skb */
+	schedule_delayed_work(&db->tx_work, 0);
+	return NETDEV_TX_OK;
+}
+
+/* event: play with a schedule starter
+ */
+static void dm9051_set_multicast_list_schedule(struct net_device *ndev)
+{
+	struct board_info *db = netdev_priv(ndev);
+	u8 rcr = RCR_DIS_LONG | RCR_DIS_CRC | RCR_RXEN;
+	struct netdev_hw_addr *ha;
+	u32 hash_val;
+
+	/* rxctl */
+	if (ndev->flags & IFF_PROMISC) {
+		rcr |= RCR_PRMSC;
+		netdev_dbg(ndev, "set_multicast rcr |= RCR_PRMSC, rcr= %02x\n", rcr);
+	}
+
+	if (ndev->flags & IFF_ALLMULTI) {
+		rcr |= RCR_ALL;
+		netdev_dbg(ndev, "set_multicast rcr |= RCR_ALLMULTI, rcr= %02x\n", rcr);
+	}
+
+	db->rcr_all = rcr;
+
+	/* broadcast address */
+	db->hash_table[0] = 0;
+	db->hash_table[1] = 0;
+	db->hash_table[2] = 0;
+	db->hash_table[3] = 0x8000;
+
+	/* the multicast address in Hash Table : 64 bits */
+	netdev_for_each_mc_addr(ha, ndev) {
+		hash_val = ether_crc_le(6, ha->addr) & 0x3f;
+		db->hash_table[hash_val / 16] |= (u16)1 << (hash_val % 16);
+	}
+
+	schedule_delayed_work(&db->rxctrl_work, 0);
+}
+
+/* event: NOT play with a schedule starter! will iow() directly.
+ */
+static int dm9051_set_mac_address(struct net_device *ndev, void *p)
+{
+	struct board_info *db = netdev_priv(ndev);
+	int ret = eth_mac_addr(ndev, p);
+
+	if (ret < 0)
+		return ret;
+
+	dm_set_mac_lock(db);
+	return 0;
+}
+
+/* probe subs
+ */
+static void dm_netdev_and_db(struct net_device *ndev, struct board_info *db)
+{
+	ndev->mtu = 1500;
+	ndev->if_port = IF_PORT_100BASET;
+	ndev->netdev_ops = &dm9051_netdev_ops;
+	ndev->ethtool_ops = &dm9051_ethtool_ops;
+	db->mii.dev = ndev;
+	db->mii.phy_id = 1;
+	db->mii.phy_id_mask = 1;
+	db->mii.reg_num_mask = 0x1f;
+	db->mii.mdio_read = dm9051_phy_read_lock;
+	db->mii.mdio_write = dm9051_phy_write_lock;
+}
+
+static void dm_spimsg_addtail(struct board_info *db)
+{
+	memset(&db->spi_xfer2, 0, sizeof(struct spi_transfer) * 2);
+	spi_message_init(&db->spi_msg2);
+	spi_message_add_tail(&db->spi_xfer2[0], &db->spi_msg2);
+	spi_message_add_tail(&db->spi_xfer2[1], &db->spi_msg2);
+}
+
+static int dm_chipid_detect(struct device *dev, struct board_info *db)
+{
+	if (dm9051_chipid(dev, db) == DM9051_ID)
+		return 0;
+	return -ENODEV;
+}
+
+static int dm9051_probe(struct spi_device *spi)
+{
+	struct device *dev = &spi->dev;
+	struct net_device *ndev;
+	struct board_info *db;
+	int ret = 0;
+
+	ndev = alloc_etherdev(sizeof(struct board_info));
+	if (!ndev)
+		return -ENOMEM;
+	SET_NETDEV_DEV(ndev, dev);
+	dev_set_drvdata(dev, ndev);
+	db = netdev_priv(ndev);
+	memset(db, 0, sizeof(struct board_info));
+	db->msg_enable = 0;
+	db->spidev = spi;
+	db->ndev = ndev;
+	dm_netdev_and_db(ndev, db);
+
+	dm_spimsg_addtail(db);
+	dm_control_init(db); /* init_delayed_works */
+	ret = dm_chipid_detect(dev, db);
+	if (ret) {
+		dev_err(dev, "chip id error\n");
+		goto err_netdev;
+	}
+	dm9051_read_mac_to_dev(dev, ndev, db);
+	ret = register_netdev(ndev);
+	if (ret) {
+		dev_err(dev, "failed to register network device\n");
+		goto err_netdev;
+	}
+	dm_operation_clear(db);
+	dm_carrier_off(ndev);
+	return 0;
+err_netdev:
+	free_netdev(ndev);
+	return ret;
+}
+
+static int dm9051_drv_remove(struct spi_device *spi)
+{
+	struct device *dev = &spi->dev;
+	struct net_device *ndev = dev_get_drvdata(dev);
+	struct board_info *db = netdev_priv(ndev);
+
+	unregister_netdev(db->ndev);
+	free_netdev(db->ndev);
+	return 0;
+}
+
+static struct spi_driver dm9051_driver = {
+	.driver = {
+		.name = DRVNAME_9051,
+		.of_match_table = dm9051_match_table,
+	},
+	.probe = dm9051_probe,
+	.remove = dm9051_drv_remove,
+	.id_table = dm9051_id_table,
+};
+module_spi_driver(dm9051_driver);
+
+MODULE_AUTHOR("Joseph CHANG <joseph_chang@davicom.com.tw>");
+MODULE_DESCRIPTION("Davicom DM9051 network SPI driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/net/ethernet/davicom/dm9051.h b/drivers/net/ethernet/davicom/dm9051.h
new file mode 100644
index 000000000000..24354d6e5909
--- /dev/null
+++ b/drivers/net/ethernet/davicom/dm9051.h
@@ -0,0 +1,225 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (c) 2021 Davicom Semiconductor,Inc.
+ * Davicom DM9051 SPI Fast Ethernet Linux driver
+ */
+
+#ifndef _DM9051_H_
+#define _DM9051_H_
+
+#define DRVNAME_9051		"dm9051"
+
+#define DM9051_ID		0x9051
+
+#define DM9051_NCR		0x00
+#define DM9051_NSR		0x01
+#define DM9051_TCR		0x02
+#define DM9051_RCR		0x05
+#define DM9051_BPTR		0x08
+#define DM9051_FCR		0x0A
+#define DM9051_EPCR		0x0B
+#define DM9051_EPAR		0x0C
+#define DM9051_EPDRL		0x0D
+#define DM9051_EPDRH		0x0E
+#define DM9051_PAR		0x10
+#define DM9051_MAR		0x16
+#define DM9051_GPCR		0x1E
+#define DM9051_GPR		0x1F
+
+#define DM9051_PIDL		0x2A
+#define DM9051_PIDH		0x2B
+#define DM9051_SMCR		0x2F
+#define	DM9051_ATCR		0x30
+#define	DM9051_SPIBCR		0x38
+#define DM9051_INTCR		0x39
+#define DM9051_PPCR		0x3D
+
+#define DM9051_MPCR		0x55
+#define DM9051_LMCR		0x57
+#define DM9051_MBNDRY		0x5E
+
+#define DM9051_MRRL		0x74
+#define DM9051_MRRH		0x75
+#define DM9051_MWRL		0x7A
+#define DM9051_MWRH		0x7B
+#define DM9051_TXPLL		0x7C
+#define DM9051_TXPLH		0x7D
+#define DM9051_ISR		0x7E
+#define DM9051_IMR		0x7F
+
+#define DM_SPI_MRCMDX		(0x70)
+#define DM_SPI_MRCMD		(0x72)
+#define DM_SPI_MWCMD		(0x78)
+
+#define DM_SPI_RD		(0x00)
+#define DM_SPI_WR		(0x80)
+
+/* dm9051 Ethernet
+ */
+//0x00
+#define NCR_WAKEEN		BIT(6)
+#define NCR_FDX			BIT(3)
+#define NCR_RST			BIT(0)
+//0x02
+#define TCR_DIS_JABBER_TIMER	BIT(6) /* for Jabber Packet support */
+#define TCR_TXREQ		BIT(0)
+//0x01
+#define NSR_SPEED		BIT(7)
+#define NSR_LINKST		BIT(6)
+#define NSR_WAKEST		BIT(5)
+#define NSR_TX2END		BIT(3)
+#define NSR_TX1END		BIT(2)
+//0x05
+#define RCR_DIS_WATCHDOG_TIMER	BIT(6)  /* for Jabber Packet support */
+#define RCR_DIS_LONG		BIT(5)
+#define RCR_DIS_CRC		BIT(4)
+#define RCR_ALL			BIT(3)
+#define RCR_PRMSC		BIT(1)
+#define RCR_RXEN		BIT(0)
+#define RCR_RX_DISABLE		(RCR_DIS_LONG | RCR_DIS_CRC)
+//0x06
+#define RSR_RF			BIT(7)
+#define RSR_MF			BIT(6)
+#define RSR_LCS			BIT(5)
+#define RSR_RWTO		BIT(4)
+#define RSR_PLE			BIT(3)
+#define RSR_AE			BIT(2)
+#define RSR_CE			BIT(1)
+#define RSR_FOE			BIT(0)
+//0x0A
+#define FCR_TXPEN		BIT(5)
+#define FCR_BKPM		BIT(3)
+#define FCR_FLCE		BIT(0)
+#define FCR_FLOW_ENABLE		(FCR_TXPEN | FCR_BKPM | FCR_FLCE)
+//0x0B
+#define EPCR_WEP		BIT(4)
+#define EPCR_EPOS		BIT(3)
+#define EPCR_ERPRR		BIT(2)
+#define EPCR_ERPRW		BIT(1)
+#define EPCR_ERRE		BIT(0)
+//0x1E
+#define GPCR_GEP_CNTL		BIT(0)
+//0x30
+#define	ATCR_AUTO_TX		BIT(7)
+//0x39
+#define INTCR_POL_LOW		BIT(0)
+#define INTCR_POL_HIGH		(0 << 0)
+//0x3D
+// Pause Packet Control Register - default = 1
+#define PPCR_PAUSE_COUNT	0x08
+//0x55
+#define MPCR_RSTTX		BIT(1)
+#define MPCR_RSTRX		BIT(0)
+//0x57
+// LEDMode Control Register - LEDMode1
+// Value 0x81 : bit[7] = 1, bit[2] = 0, bit[1:0] = 01b
+#define LMCR_NEWMOD		BIT(7)
+#define LMCR_TYPED1		BIT(1)
+#define LMCR_TYPED0		BIT(0)
+#define LMCR_MODE1		(LMCR_NEWMOD | LMCR_TYPED0)
+//0x5E
+#define MBNDRY_BYTE		BIT(7)
+//0xFE
+#define ISR_MBS			BIT(7)
+#define ISR_ROOS		BIT(3)
+#define ISR_ROS			BIT(2)
+#define ISR_PTS			BIT(1)
+#define ISR_PRS			BIT(0)
+#define ISR_CLR_STATUS		(ISR_ROOS | ISR_ROS | ISR_PTS | ISR_PRS)
+//0xFF
+#define IMR_PAR			BIT(7)
+#define IMR_LNKCHGI		BIT(5)
+#define IMR_PTM			BIT(1)
+#define IMR_PRM			BIT(0)
+
+/* Const
+ */
+#define DM9051_PHY		0x40	/* PHY address 0x01 */
+#define DM9051_PKT_RDY		0x01	/* Packet ready to receive */
+#define DM9051_PKT_MAX		1536	/* Received packet max size */
+#define DM_EEPROM_MAGIC		(0x9051)
+
+/* netdev_ops
+ */
+static int dm9051_open(struct net_device *dev);
+static int dm9051_stop(struct net_device *dev);
+static netdev_tx_t dm9051_start_xmit(struct sk_buff *skb, struct net_device *dev);
+static void dm9051_set_multicast_list_schedule(struct net_device *dev);
+static int dm9051_set_mac_address(struct net_device *dev, void *p);
+
+static inline struct board_info *to_dm9051_board(struct net_device *dev)
+{
+	return netdev_priv(dev);
+}
+
+/* carrier
+ */
+#define	dm_carrier_init(db)			mii_check_link(&(db)->mii)
+#define	dm_carrier_poll(db)			mii_check_link(&(db)->mii)
+#define	dm_carrier_off(dev)			netif_carrier_off(dev)
+
+/* xmit support
+ */
+#define	dm_sk_buff_head_init(db)		skb_queue_head_init(&(db)->txq)
+#define	dm_sk_buff_get(db)			skb_dequeue(&(db)->txq)
+#define	dm_sk_buff_set(db, skb)			skb_queue_tail(&(db)->txq, skb)
+
+/* spi transfers
+ */
+#define ior					std_spi_read_reg			// read reg
+#define iior					disp_spi_read_reg			// read disp
+#define iow					std_spi_write_reg			// write reg
+#define dm9inblk				std_read_rx_buf_ncpy			// read buff
+#define dm9outblk				std_write_tx_buf			// write buf
+
+#define	ncr_reg_reset(db)			iow(db, DM9051_NCR, NCR_RST)		// reset
+#define	mbd_reg_byte(db)			iow(db, DM9051_MBNDRY, MBNDRY_BYTE)	// MemBound
+#define	fcr_reg_enable(db)			iow(db, DM9051_FCR, FCR_FLOW_ENABLE)	// FlowCtrl
+#define	ppcr_reg_seeting(db)			iow(db, DM9051_PPCR, PPCR_PAUSE_COUNT)	// PauPktCn
+#define	isr_reg_clear_to_stop_mrcmd(db)		iow(db, DM9051_ISR, 0xff)		// ClearISR
+#define rcr_reg_stop(db)			iow(db, DM9051_RCR, RCR_RX_DISABLE)	// DisabRX
+#define imr_reg_stop(db)			iow(db, DM9051_IMR, IMR_PAR)		// DisabAll
+#define rcr_reg_start(db, rcr_all)		iow(db, DM9051_RCR, rcr_all)		// EnabRX
+#define imr_reg_start(db, imr_all)		iow(db, DM9051_IMR, imr_all)		// Re-enab
+#define	intcr_reg_setval(db)			iow(db, DM9051_INTCR, INTCR_POL_LOW)	// INTCR
+#define	ledcr_reg_setting(db, lcr_all)		iow(db, DM9051_LMCR, lcr_all)		// LEDMode1
+
+/* structure definitions
+ */
+struct rx_ctl_mach {
+	u16				large_err_counter;  /* The error of 'Large Err' */
+	u16				mac_ovrsft_counter;  /* The error of 'MacOvrSft_Er' */
+	u16				DO_FIFO_RST_counter; /* The counter of 'fifo_reset' */
+};
+
+struct dm9051_rxhdr {
+	u8				rxpktready;
+	u8				rxstatus;
+	__le16				rxlen;
+};
+
+struct board_info {
+	u8				cmd[2] ____cacheline_aligned;
+	struct spi_transfer		spi_xfer2[2] ____cacheline_aligned;
+	struct spi_message		spi_msg2 ____cacheline_aligned;
+	struct rx_ctl_mach		bc ____cacheline_aligned;
+	struct dm9051_rxhdr		*prxhdr ____cacheline_aligned;
+	struct spi_device		*spidev;
+	struct net_device		*ndev;
+	struct mii_if_info		mii;
+	struct sk_buff_head		txq;
+	struct mutex			spi_lock;	// delayed_work's lock
+	struct mutex			addr_lock;	// dm9051's REG lock
+	struct delayed_work		phy_poll;
+	struct delayed_work		rxctrl_work;
+	struct delayed_work		tx_work;
+	u16				hash_table[4];
+	u32				msg_enable ____cacheline_aligned;
+	u8				imr_all;
+	u8				rcr_all;
+	u8				lcr_all;
+};
+
+#define	DM_RXHDR_SIZE			sizeof(struct dm9051_rxhdr)
+
+#endif /* _DM9051_H_ */
-- 
2.20.1


^ permalink raw reply related

* Re: [PATCH v5 3/5] can: do not copy the payload of RTR frames
From: Yasushi SHOJI @ 2021-12-10  8:57 UTC (permalink / raw)
  To: Vincent Mailhol
  Cc: Marc Kleine-Budde, linux-can, Oliver Hartkopp, Jimmy Assarsson,
	netdev, linux-kernel, linux-arm-kernel, linux-sunxi
In-Reply-To: <20211207121531.42941-4-mailhol.vincent@wanadoo.fr>

Hi Vincent,

On Tue, Dec 7, 2021 at 9:16 PM Vincent Mailhol
<mailhol.vincent@wanadoo.fr> wrote:
>
> The actual payload length of the CAN Remote Transmission Request (RTR)
> frames is always 0, i.e. nothing is transmitted on the wire. However,
> those RTR frames still use the DLC to indicate the length of the
> requested frame.
>
> For this reason, it is incorrect to copy the payload of RTR frames
> (the payload buffer would only contain garbage data). This patch
> encapsulates the payload copy in a check toward the RTR flag.
>
> CC: Yasushi SHOJI <yashi@spacecubics.com>
> Signed-off-by: Vincent Mailhol <mailhol.vincent@wanadoo.fr>

It works and LGTM.

Tested-by: Yasushi SHOJI <yashi@spacecubics.com>
-- 
              yashi

^ permalink raw reply

* [PATCHv3 net-next 0/2] net: add new hwtstamp flag HWTSTAMP_FLAG_BONDED_PHC_INDEX
From: Hangbin Liu @ 2021-12-10  8:59 UTC (permalink / raw)
  To: netdev
  Cc: Jay Vosburgh, Veaceslav Falico, Andy Gospodarek, David S . Miller,
	Jakub Kicinski, Richard Cochran, Heiner Kallweit, Hangbin Liu

This patchset add a new hwtstamp_config flag HWTSTAMP_FLAG_BONDED_PHC_INDEX.
When user want to get bond active interface's PHC, they need to add this flag
and aware the PHC index may changed.

v3: Use bitwise test to check the flags validation
v2: rename the flag to HWTSTAMP_FLAG_BONDED_PHC_INDEX

Hangbin Liu (2):
  net_tstamp: add new flag HWTSTAMP_FLAG_BONDED_PHC_INDEX
  Bonding: force user to add HWTSTAMP_FLAG_BONDED_PHC_INDEX when get/set
    HWTSTAMP

 drivers/net/bonding/bond_main.c               | 33 ++++++++++++-------
 .../net/dsa/hirschmann/hellcreek_hwtstamp.c   |  4 ---
 drivers/net/dsa/mv88e6xxx/hwtstamp.c          |  4 ---
 drivers/net/ethernet/amd/xgbe/xgbe-drv.c      |  3 --
 .../net/ethernet/aquantia/atlantic/aq_main.c  |  3 --
 .../net/ethernet/broadcom/bnx2x/bnx2x_main.c  |  5 ---
 drivers/net/ethernet/broadcom/bnxt/bnxt_ptp.c |  3 --
 drivers/net/ethernet/broadcom/tg3.c           |  3 --
 drivers/net/ethernet/cadence/macb_ptp.c       |  4 ---
 .../net/ethernet/cavium/liquidio/lio_main.c   |  3 --
 .../ethernet/cavium/liquidio/lio_vf_main.c    |  3 --
 .../net/ethernet/cavium/octeon/octeon_mgmt.c  |  3 --
 .../net/ethernet/cavium/thunder/nicvf_main.c  |  4 ---
 drivers/net/ethernet/engleder/tsnep_ptp.c     |  3 --
 drivers/net/ethernet/freescale/fec_ptp.c      |  4 ---
 drivers/net/ethernet/freescale/gianfar.c      |  4 ---
 drivers/net/ethernet/intel/e1000e/netdev.c    |  4 ---
 drivers/net/ethernet/intel/i40e/i40e_ptp.c    |  4 ---
 drivers/net/ethernet/intel/ice/ice_ptp.c      |  4 ---
 drivers/net/ethernet/intel/igb/igb_ptp.c      |  4 ---
 drivers/net/ethernet/intel/igc/igc_ptp.c      |  4 ---
 drivers/net/ethernet/intel/ixgbe/ixgbe_ptp.c  |  4 ---
 .../net/ethernet/marvell/mvpp2/mvpp2_main.c   |  3 --
 .../ethernet/marvell/octeontx2/nic/otx2_pf.c  |  4 ---
 .../net/ethernet/mellanox/mlx4/en_netdev.c    |  4 ---
 drivers/net/ethernet/microchip/lan743x_ptp.c  |  6 ----
 drivers/net/ethernet/mscc/ocelot.c            |  4 ---
 .../net/ethernet/neterion/vxge/vxge-main.c    |  4 ---
 .../ethernet/oki-semi/pch_gbe/pch_gbe_main.c  |  3 --
 drivers/net/ethernet/qlogic/qede/qede_ptp.c   |  5 ---
 drivers/net/ethernet/renesas/ravb_main.c      |  4 ---
 drivers/net/ethernet/sfc/ptp.c                |  3 --
 .../net/ethernet/stmicro/stmmac/stmmac_main.c |  4 ---
 drivers/net/ethernet/ti/cpsw_priv.c           |  4 ---
 drivers/net/ethernet/ti/netcp_ethss.c         |  4 ---
 drivers/net/ethernet/xscale/ixp4xx_eth.c      |  3 --
 drivers/net/phy/dp83640.c                     |  3 --
 drivers/net/phy/mscc/mscc_ptp.c               |  3 --
 drivers/ptp/ptp_ines.c                        |  4 ---
 include/uapi/linux/net_tstamp.h               | 16 ++++++++-
 net/core/dev_ioctl.c                          |  2 +-
 41 files changed, 37 insertions(+), 156 deletions(-)

-- 
2.31.1


^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox