Netdev List
 help / color / mirror / Atom feed
* Re: [patch net-next v2 00/20] net: sched: convert cls ndo_setup_tc offload calls to per-block callbacks
From: Jiri Pirko @ 2017-10-25 12:15 UTC (permalink / raw)
  To: Alexander Duyck
  Cc: David Miller, Netdev, Jamal Hadi Salim, Cong Wang, mlxsw,
	Andrew Lunn, Vivien Didelot, Florian Fainelli, Michael Chan,
	Ganesh Goudar, Jeff Kirsher, Saeed Mahameed, Matan Barak,
	Leon Romanovsky, idosch, Jakub Kicinski, Alexei Starovoitov,
	Daniel Borkmann, Simon Horman, pieter.jansenvanvuuren, john.hurl
In-Reply-To: <CAKgT0Ud0RJLZ6mz9Ysb9A7PdkcwBYt2+ASvLZQxMGPK2BwvqKw@mail.gmail.com>

Tue, Oct 24, 2017 at 06:01:34PM CEST, alexander.duyck@gmail.com wrote:

[...]

>1.       To offload filter into HW, the hw-tc-offload feature flag has
>to be turned on before creating the ingress qdisc.
>
>Previously, this could also be turned on after the qdisc was created
>and the filters could still be offloaded. Looks like this is because,
>previously the offload flag was checked as a part of filter
>integration in the classifier, and now it is checked as part of qdisc
>creation (ingress_init). So, if no offload capability is advertised at
>ingress qdisc creation time then hardware will not be asked to offload
>filters later if the flag is enabled.

I have patchset that fixes this in my queue now. Will do some smoke
testing and send later today.


>
>2.       Deleting the ingress qdisc fails to remove filters added in
>HW. Filters in SW gets deleted.
>
>We haven’t exactly root-caused this, the changes being extensive, but
>our guess is again something wrong with the offload check or similar
>while unregistering the block callback (tcf_block_cb_unregister) and
>further to the classifier (CLS_U32/CLS_FLOWER etc.) with the
>DESTROY/REMOVE command.

Hmm. How does this worked previously. I mean, do you see change of
behaviour? I'm asking because I don't see how rules added only to HW
could be removed, driver should care of it. Or are you talking about
rules added to both SW and HW?

Thanks!

^ permalink raw reply

* Re: [PATCH] drivers/net: hippi: Convert timers to use timer_setup()
From: Jes Sorensen @ 2017-10-25 12:58 UTC (permalink / raw)
  To: Kees Cook, David S. Miller
  Cc: Jes Sorensen, linux-hippi, netdev, linux-kernel
In-Reply-To: <20171025105129.GA146547@beast>

On 10/25/2017 06:51 AM, Kees Cook wrote:
> In preparation for unconditionally passing the struct timer_list pointer to
> all timer callbacks, switch to using the new timer_setup() and from_timer()
> to pass the timer pointer explicitly.
> 
> Cc: Jes Sorensen <jes@trained-monkey.org>
> Cc: linux-hippi@sunsite.dk
> Cc: netdev@vger.kernel.org
> Signed-off-by: Kees Cook <keescook@chromium.org>
> ---
>   drivers/net/hippi/rrunner.c | 8 ++++----
>   1 file changed, 4 insertions(+), 4 deletions(-)

Looks good to me.

Jes

> diff --git a/drivers/net/hippi/rrunner.c b/drivers/net/hippi/rrunner.c
> index 76cc140774a2..8483f03d5a41 100644
> --- a/drivers/net/hippi/rrunner.c
> +++ b/drivers/net/hippi/rrunner.c
> @@ -1146,10 +1146,10 @@ static inline void rr_raz_rx(struct rr_private *rrpriv,
>   	}
>   }
>   
> -static void rr_timer(unsigned long data)
> +static void rr_timer(struct timer_list *t)
>   {
> -	struct net_device *dev = (struct net_device *)data;
> -	struct rr_private *rrpriv = netdev_priv(dev);
> +	struct rr_private *rrpriv = from_timer(rrpriv, t, timer);
> +	struct net_device *dev = pci_get_drvdata(rrpriv->pci_dev);
>   	struct rr_regs __iomem *regs = rrpriv->regs;
>   	unsigned long flags;
>   
> @@ -1229,7 +1229,7 @@ static int rr_open(struct net_device *dev)
>   
>   	/* Set the timer to switch to check for link beat and perhaps switch
>   	   to an alternate media type. */
> -	setup_timer(&rrpriv->timer, rr_timer, (unsigned long)dev);
> +	timer_setup(&rrpriv->timer, rr_timer, 0);
>   	rrpriv->timer.expires = RUN_AT(5*HZ);           /* 5 sec. watchdog */
>   	add_timer(&rrpriv->timer);
>   
> 

^ permalink raw reply

* Re: linux kernel – 4.4.45 : VPN test failure
From: gregkh @ 2017-10-25 13:08 UTC (permalink / raw)
  To: Nanjappa, Gangadhar
  Cc: netdev@vger.kernel.org, davem@davemloft.net, kuznet@ms2.inr.ac.ru,
	jmorris@namei.org, yoshfuji@linux-ipv6.org, kaber@trash.net,
	amit.pundir@linaro.org, lorenzo@google.com, andy@greyhouse.net,
	steffen.klassert@secunet.com, herbert@gondor.apana.org.au,
	pablo@netfilter.org, kadlec@blackhole.kfki.hu,
	g.nault@alphalink.fr, jiri@mellanox.com
In-Reply-To: <5fae6d9bd62e42acb24a7a8cfdcc8a86@HIBDWSMB01.ad.harman.com>

On Wed, Oct 25, 2017 at 12:49:09PM +0000, Nanjappa, Gangadhar wrote:
> Hi All,
> Using linux kernel – 4.4.45 (Blurry Fish Butt), VPN test fails. If I
> revert the attached five patches, VPN test passes. But I’m not
> supposed to revert the patches to get the test passed. I’m analyzing
> the patches, please help me to resolve this issue. If the below
> patches are present, in the VpnTest.java file that I’ve attached, the
> failure path is testAppDisallowed()--> checkNoTrafficOnVpn() -->
> checkUdpEcho("192.0.2.251", null) --> fail("Received unexpected
> reply");

4.4.45 is _very_ old, can you duplicate this on 4.4.94?  Do you also
have this problem on 4.14-rc6?

thanks,

greg k-h

^ permalink raw reply

* RE: [PATCH net-next 2/3] xfrm: Fix offload dev state addition to occur after insertion
From: Aviv Heller @ 2017-10-25 13:09 UTC (permalink / raw)
  To: Steffen Klassert, netdev-owner@vger.kernel.org,
	avivh@mellanox.com
  Cc: Herbert Xu, Boris Pismenny, Yossi Kuperman, Yevgeny Kliteynik,
	netdev@vger.kernel.org
In-Reply-To: <20171025072214.GP3323@secunet.com>

-----Original message-----
> From: Steffen Klassert
> Sent: Wednesday, October 25 2017, 10:22 am
> To: avivh@mellanox.com
> Cc: Herbert Xu; Boris Pismenny; Yossi Kuperman; Yevgeny Kliteynik; netdev@vger.kernel.org
> Subject: Re: [PATCH net-next 2/3] xfrm: Fix offload dev state addition to occur after insertion
> 
> On Tue, Oct 24, 2017 at 06:10:30PM +0300, avivh@mellanox.com wrote:
> > From: Aviv Heller <avivh@mellanox.com>
> > 
> > Adding the state to the offload device prior to replay init in
> > xfrm_state_construct() will result in NULL dereference if a matching
> > ESP packet is received in between.
> > 
> > Adding it after insertion also has the benefit of the driver not having
> > to check whether a state with the same match criteria already exists,
> > but forces us to use an atomic type for the offload_handle, to make
> > certain a stack-read/driver-write race won't result in reading corrupt
> > data.
> 
> No, this will add multiple atomic operations to the packet path,
> even in the non offloaded case.
> 
> I think the problem is that we set XFRM_STATE_VALID to early.
> This was not a problem before we had offloading because
> it was not possible to lookup this state before we inserted
> it into the SADB. Now that the driver holds a subset of states
> too, we need to make sure the state is fully initialized
> before we mark it as valid.
> 
> The patch below should do it, in combination with your patch 1/3.
> 
> Could you please test this?
> 
> diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c
> index b997f13..96eb263 100644
> --- a/net/xfrm/xfrm_user.c
> +++ b/net/xfrm/xfrm_user.c
> @@ -587,10 +587,6 @@ static struct xfrm_state *xfrm_state_construct(struct net *net,
>  	if (attrs[XFRMA_OUTPUT_MARK])
>  		x->props.output_mark = nla_get_u32(attrs[XFRMA_OUTPUT_MARK]);
>  
> -	err = __xfrm_init_state(x, false, attrs[XFRMA_OFFLOAD_DEV]);
> -	if (err)
> -		goto error;
> -
>  	if (attrs[XFRMA_SEC_CTX]) {
>  		err = security_xfrm_state_alloc(x,
>  						nla_data(attrs[XFRMA_SEC_CTX]));
> @@ -620,6 +616,10 @@ static struct xfrm_state *xfrm_state_construct(struct net *net,
>  	/* override default values from above */
>  	xfrm_update_ae_params(x, attrs, 0);
>  
> +	err = __xfrm_init_state(x, false, attrs[XFRMA_OFFLOAD_DEV]);
> +	if (err)
> +		goto error;
> +
>  	return x;
>  
>  error:
> 

Hi Steffen,

This patch does not work, due to:
	if (!x->type_offload)
		return -EINVAL;

test in xfrm_dev_state_add().

I agree with your analysis, and that we take a little performance hit due to the atomics, but we get the benefit of calling xfrm_dev_state_add() after the state is completely initialized, and passed the criteria for addition by xfrm_state_add().

Another approach I thought of is to insert the state with an invalid km.state, and only after the HW state addition succeeds, we move km.state to valid.
I did not go for this approach because here again we need to use atomics (or not?), and since state testing is done in quite a few places, was afraid of unexpected consequences.

What do you think?

Thanks,
Aviv




^ permalink raw reply

* Re: [PATCHv4 iproute2 2/2] lib/libnetlink: update rtnl_talk to support malloc buff at run time
From: Hangbin Liu @ 2017-10-25 13:16 UTC (permalink / raw)
  To: Stephen Hemminger; +Cc: netdev, Michal Kubecek, Phil Sutter, Hangbin Liu
In-Reply-To: <20171025124556.14df7d15@shemminger-XPS-13-9360>

On Wed, Oct 25, 2017 at 12:45:56PM +0200, Stephen Hemminger wrote:
> This does not apply cleanly to net-next branch
> 
> Applying: lib/libnetlink: update rtnl_talk to support malloc buff at run time
> error: patch failed: ip/ipl2tp.c:185
> error: ip/ipl2tp.c: patch does not apply
> error: patch failed: ip/iplink.c:1023
> error: ip/iplink.c: patch does not apply
> Patch failed at 0002 lib/libnetlink: update rtnl_talk to support malloc buff at run time
> 
Oh, I will send a new version patch based on latest net-next code ASAP.

Thanks
Hangbin

^ permalink raw reply

* Re: [PATCH] net/unix: don't show information about sockets from other namespaces
From: Eric Dumazet @ 2017-10-25 13:37 UTC (permalink / raw)
  To: Andrei Vagin; +Cc: David S. Miller, netdev
In-Reply-To: <20171025071744.29095-1-avagin@openvz.org>

On Wed, 2017-10-25 at 00:17 -0700, Andrei Vagin wrote:
> socket_diag shows information only about sockets from a namespace where
> a diag socket lives.
> 
> But if we request information about one unix socket, the kernel don't
> check that its netns is matched with a diag socket namespace, so any
> user can get information about any unix socket in a system. This looks
> like a bug.

Then if this a bug please provide a Fixes: tag

This way, we can know exact cutoff for backports.

I suspect that would be 

Fixes: 51d7cccf0723 ("net: make sock diag per-namespace")

Thanks.

^ permalink raw reply

* Re: [patch net-next v2 00/20] net: sched: convert cls ndo_setup_tc offload calls to per-block callbacks
From: Jiri Pirko @ 2017-10-25 13:42 UTC (permalink / raw)
  To: Or Gerlitz
  Cc: Alexander Duyck, David Miller, Netdev, Jamal Hadi Salim,
	Cong Wang, mlxsw, Andrew Lunn, Vivien Didelot, Florian Fainelli,
	Michael Chan, Ganesh Goudar, Jeff Kirsher, Saeed Mahameed,
	Matan Barak, Leon Romanovsky, idosch, Jakub Kicinski,
	Alexei Starovoitov, Daniel Borkmann, Simon Horman
In-Reply-To: <aaa66a3d-766b-f758-692a-eba7f5a8702f@mellanox.com>

Wed, Oct 25, 2017 at 03:29:27PM CEST, ogerlitz@mellanox.com wrote:
>On 10/25/2017 3:15 PM, Jiri Pirko wrote:
>> > 2. Deleting the ingress qdisc fails to remove filters added in
>> > HW. Filters in SW gets deleted.
>> > 
>> > We haven’t exactly root-caused this, the changes being extensive, but our guess is again something wrong with the offload check or similar while unregistering the block callback (tcf_block_cb_unregister) and further to the classifier (CLS_U32/CLS_FLOWER etc.) with the DESTROY/REMOVE command.
>> Hmm. How does this worked previously. I mean, do you see change of
>> behaviour? I'm asking because I don't see how rules added only to HW
>> could be removed, driver should care of it. Or are you talking about
>> rules added to both SW and HW?
>
>Jiri, on a possibly related note, dealing with some other tc/flower problems

Unrelated. What you describe is a separate issue.


>on net, I came across a situation where we fail in the driverto offload some
>flow (return -EINVALtowards the stack), and we immediately get a call from
>the stack to delete this flow (f->cookie)
>
>this is the cookie and thereturn value
>
>mlx5e_configure_flower f->cookie c50e8c80 err -22
>
>and then we getthis cookie for deletion where we fail again, b/c the flow is
>not offloaded
>
>mlx5e_delete_flower f->cookie c50e8c80

Yes, that is intentional. The thing is, there might be multiple block
callbacks registered and to be called. If there is a fail with one, we
need to cleanup all. So in your case you have 1 cb registered, that
means that in case of an error during insertion, you will get cb called
to remove. Driver has to take care of that. I was checking that and was
under impression that mlx5 deals with that.

^ permalink raw reply

* [PATCH net] net/sched: cls_flower: Avoid attempt to delete from hw a flow which was not offloaded
From: Or Gerlitz @ 2017-10-25 13:44 UTC (permalink / raw)
  To: David S. Miller
  Cc: netdev, Jiri Pirko, mlxsw, Roi Dayan, Paul Blakey, Or Gerlitz

If we failed to offload a flow to HW, we should not be attempting to delete
it from the HW. Also, on this case, we should be err-ing only if the flow is
not is SW, fix both issues.

Fixes: 717503b9cf57 ('net: sched: convert cls_flower->egress_dev users to tc_setup_cb_egdev infra')
Signed-off-by: Or Gerlitz <ogerlitz@mellanox.com>
---
 net/sched/cls_flower.c | 11 ++++-------
 1 file changed, 4 insertions(+), 7 deletions(-)

diff --git a/net/sched/cls_flower.c b/net/sched/cls_flower.c
index 16f58ab..b98e0cb 100644
--- a/net/sched/cls_flower.c
+++ b/net/sched/cls_flower.c
@@ -230,15 +230,12 @@ static int fl_hw_replace_filter(struct tcf_proto *tp,
 
 	err = tc_setup_cb_call(block, &f->exts, TC_SETUP_CLSFLOWER,
 			       &cls_flower, skip_sw);
-	if (err < 0) {
-		fl_hw_destroy_filter(tp, f);
-		return err;
-	} else if (err > 0) {
+
+	if (err > 0)
 		f->flags |= TCA_CLS_FLAGS_IN_HW;
-	}
 
-	if (skip_sw && !(f->flags & TCA_CLS_FLAGS_IN_HW))
-		return -EINVAL;
+	if (skip_sw)
+		return err;
 
 	return 0;
 }
-- 
2.5.5

^ permalink raw reply related

* Re: [patch net-next v2 00/20] net: sched: convert cls ndo_setup_tc offload calls to per-block callbacks
From: Or Gerlitz @ 2017-10-25 13:48 UTC (permalink / raw)
  To: Jiri Pirko
  Cc: Alexander Duyck, David Miller, Netdev, Jamal Hadi Salim,
	Cong Wang, mlxsw, Andrew Lunn, Vivien Didelot, Florian Fainelli,
	Michael Chan, Ganesh Goudar, Jeff Kirsher, Saeed Mahameed,
	Matan Barak, Leon Romanovsky, idosch, Jakub Kicinski,
	Alexei Starovoitov, Daniel Borkmann, Simon Horman
In-Reply-To: <20171025134211.GA1976@nanopsycho.orion>

On 10/25/2017 4:42 PM, Jiri Pirko wrote:
> Yes, that is intentional. The thing is, there might be multiple block
> callbacks registered and to be called. If there is a fail with one, we
> need to cleanup all. So in your case you have 1 cb registered, that
> means that in case of an error during insertion, you will get cb called
> to remove. Driver has to take care of that. I was checking that and was
> under impression that mlx5 deals with that.

I see, yeah, in mlx5 we identify that the flow doesn't exist in our 
tables, I sent a patch that deals with that and also another issue, lets 
discuss it there.

^ permalink raw reply

* Re: [RFC] net/unix_diag: Provide UDIAG_SHOW_VFS2 attribute to fetch complete inode number
From: Roman Mashak @ 2017-10-25 13:55 UTC (permalink / raw)
  To: Cyrill Gorcunov
  Cc: NETDEV, LKML, Andrey Vagin, David S. Miller, Pavel Emelyanov
In-Reply-To: <20171024214814.GO5343@uranus>

Cyrill Gorcunov <gorcunov@gmail.com> writes:

> Currently unix_diag_vfs structure reports unix socket inode
> as u32 value which of course doesn't fit to ino_t type and
> the number may be trimmed. Lets rather deprecate old UDIAG_SHOW_VFS
> interface and provide UDIAG_SHOW_VFS2 (with one field "__zero" reserved
> which we could extend in future).
>

[...]

> -static int sk_diag_dump_vfs(struct sock *sk, struct sk_buff *nlskb)
> +static int sk_diag_dump_vfs(struct sock *sk, struct sk_buff *nlskb, unsigned int flags)
>  {
>  	struct dentry *dentry = unix_sk(sk)->path.dentry;
>  
>  	if (dentry) {
> -		struct unix_diag_vfs uv = {
> -			.udiag_vfs_ino = d_backing_inode(dentry)->i_ino,
> -			.udiag_vfs_dev = dentry->d_sb->s_dev,
> -		};
> -
> -		return nla_put(nlskb, UNIX_DIAG_VFS, sizeof(uv), &uv);
> +		if (flags & UDIAG_SHOW_VFS2) {
> +			struct unix_diag_vfs uv = {
> +				.udiag_vfs_ino = d_backing_inode(dentry)->i_ino,
> +				.udiag_vfs_dev = dentry->d_sb->s_dev,
> +			};
> +			return nla_put(nlskb, UNIX_DIAG_VFS, sizeof(uv), &uv);
> +		} else {
> +			struct unix_diag_vfs2 uv = {
> +				.udiag_vfs_ino = d_backing_inode(dentry)->i_ino,
> +				.udiag_vfs_dev = dentry->d_sb->s_dev,
> +			};

I think __zero should be explicitly set to 0.

[...]

^ permalink raw reply

* [PATCH 1/1] l2tp: cleanup l2tp_tunnel_delete calls
From: Jiri Slaby @ 2017-10-25 13:57 UTC (permalink / raw)
  To: davem; +Cc: linux-kernel, Jiri Slaby, Sabrina Dubroca, Guillaume Nault,
	netdev

l2tp_tunnel_delete does not return anything since commit 62b982eeb458
("l2tp: fix race condition in l2tp_tunnel_delete").  But call sites of
l2tp_tunnel_delete still do casts to void to avoid unused return value
warnings.

Kill these now useless casts.

Signed-off-by: Jiri Slaby <jslaby@suse.cz>
Cc: Sabrina Dubroca <sd@queasysnail.net>
Cc: Guillaume Nault <g.nault@alphalink.fr>
Cc: David S. Miller <davem@davemloft.net>
Cc: netdev@vger.kernel.org
---
 net/l2tp/l2tp_core.c    | 2 +-
 net/l2tp/l2tp_netlink.c | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/net/l2tp/l2tp_core.c b/net/l2tp/l2tp_core.c
index 02d61101b108..af22aa8ae35b 100644
--- a/net/l2tp/l2tp_core.c
+++ b/net/l2tp/l2tp_core.c
@@ -1891,7 +1891,7 @@ static __net_exit void l2tp_exit_net(struct net *net)
 
 	rcu_read_lock_bh();
 	list_for_each_entry_rcu(tunnel, &pn->l2tp_tunnel_list, list) {
-		(void)l2tp_tunnel_delete(tunnel);
+		l2tp_tunnel_delete(tunnel);
 	}
 	rcu_read_unlock_bh();
 
diff --git a/net/l2tp/l2tp_netlink.c b/net/l2tp/l2tp_netlink.c
index 7135f4645d3a..c28223d8092b 100644
--- a/net/l2tp/l2tp_netlink.c
+++ b/net/l2tp/l2tp_netlink.c
@@ -282,7 +282,7 @@ static int l2tp_nl_cmd_tunnel_delete(struct sk_buff *skb, struct genl_info *info
 	l2tp_tunnel_notify(&l2tp_nl_family, info,
 			   tunnel, L2TP_CMD_TUNNEL_DELETE);
 
-	(void) l2tp_tunnel_delete(tunnel);
+	l2tp_tunnel_delete(tunnel);
 
 	l2tp_tunnel_dec_refcount(tunnel);
 
-- 
2.14.3

^ permalink raw reply related

* Re: [PATCH net] net/sched: cls_flower: Avoid attempt to delete from hw a flow which was not offloaded
From: Jiri Pirko @ 2017-10-25 13:58 UTC (permalink / raw)
  To: Or Gerlitz
  Cc: David S. Miller, netdev, Jiri Pirko, mlxsw, Roi Dayan,
	Paul Blakey
In-Reply-To: <1508939080-22317-1-git-send-email-ogerlitz@mellanox.com>

Wed, Oct 25, 2017 at 03:44:40PM CEST, ogerlitz@mellanox.com wrote:
>If we failed to offload a flow to HW, we should not be attempting to delete
>it from the HW. Also, on this case, we should be err-ing only if the flow is
>not is SW, fix both issues.
>
>Fixes: 717503b9cf57 ('net: sched: convert cls_flower->egress_dev users to tc_setup_cb_egdev infra')
>Signed-off-by: Or Gerlitz <ogerlitz@mellanox.com>
>---
> net/sched/cls_flower.c | 11 ++++-------
> 1 file changed, 4 insertions(+), 7 deletions(-)
>
>diff --git a/net/sched/cls_flower.c b/net/sched/cls_flower.c
>index 16f58ab..b98e0cb 100644
>--- a/net/sched/cls_flower.c
>+++ b/net/sched/cls_flower.c
>@@ -230,15 +230,12 @@ static int fl_hw_replace_filter(struct tcf_proto *tp,
> 
> 	err = tc_setup_cb_call(block, &f->exts, TC_SETUP_CLSFLOWER,
> 			       &cls_flower, skip_sw);
>-	if (err < 0) {
>-		fl_hw_destroy_filter(tp, f);
>-		return err;


As I wrote in the other thread:
Yes, that is intentional. The thing is, there might be multiple block
callbacks registered and to be called. If there is a fail with one, we
need to cleanup all. So in your case you have 1 cb registered, that
means that in case of an error during insertion, you will get cb called
to remove. Driver has to take care of that. I was checking that and was
under impression that mlx5 deals with that.




>-	} else if (err > 0) {
>+
>+	if (err > 0)
> 		f->flags |= TCA_CLS_FLAGS_IN_HW;
>-	}
> 
>-	if (skip_sw && !(f->flags & TCA_CLS_FLAGS_IN_HW))
>-		return -EINVAL;
>+	if (skip_sw)
>+		return err;
> 
> 	return 0;
> }
>-- 
>2.5.5
>

^ permalink raw reply

* Re: [PATCH net-next 4/4] net: qualcomm: rmnet: Add support for GRO
From: Eric Dumazet @ 2017-10-25 14:00 UTC (permalink / raw)
  To: Subash Abhinov Kasiviswanathan, Tom Herbert; +Cc: davem, netdev
In-Reply-To: <1508907329-1077-5-git-send-email-subashab@codeaurora.org>

On Tue, 2017-10-24 at 22:55 -0600, Subash Abhinov Kasiviswanathan wrote:
> Add gro_cells so that rmnet devices can call gro_cells_receive
> instead of netif_receive_skb.
> 

>  void rmnet_vnd_setup(struct net_device *rmnet_dev)
>  {
> +	struct rmnet_priv *priv = netdev_priv(rmnet_dev);
> +
>  	rmnet_dev->netdev_ops = &rmnet_vnd_ops;
>  	rmnet_dev->mtu = RMNET_DFLT_PACKET_SIZE;
>  	rmnet_dev->needed_headroom = RMNET_NEEDED_HEADROOM;
> @@ -162,6 +164,8 @@ void rmnet_vnd_setup(struct net_device *rmnet_dev)
>  	rmnet_dev->flags &= ~(IFF_BROADCAST | IFF_MULTICAST);
>  
>  	rmnet_dev->needs_free_netdev = true;
> +
> +	gro_cells_init(&priv->gro_cells, rmnet_dev);
>  }


You need to check return code and abort if memory could not be
allocated.

There is a reason this helper has _init() prefix, it does not belong to
_setup() since a _setup() is not expected to fail.

Please take a look at other gro_cells_init() callers, and you will
notice that it is called from ndo_init()

You might have copied the only buggy caller (vxlan).

Tom, if you read me fix vxlan, thanks !

^ permalink raw reply

* [RFC PATCH 0/12] net: Significantly shrink the size of routes.
From: David Miller @ 2017-10-25 14:02 UTC (permalink / raw)
  To: netdev


Through a combination of several things, our route structures are
larger than they need to be.

Mostly this stems from having members in dst_entry which are only used
by one class of routes.  So the majority of the work in this series is
about "un-commoning" these members and pushing them into the type
specific structures.

Unfortunately, IPSEC needed the most surgery.  The majority of the
changes here had to do with bundle creation and management.

The other issue is the refcount alignment in dst_entry.  Once we get
rid of the not-so-common members, it really opens the door to removing
that alignment entirely.

I think the new layout looks really nice, so I'll reproduce it here:

	struct net_device       *dev;
	struct  dst_ops	        *ops;
	unsigned long		_metrics;
	unsigned long           expires;
	struct xfrm_state	*xfrm;
	int			(*input)(struct sk_buff *);
	int			(*output)(struct net *net, struct sock *sk, struct sk_buff *skb);
	unsigned short		flags;
	short			obsolete;
	unsigned short		header_len;
	unsigned short		trailer_len;
	atomic_t		__refcnt;
	int			__use;
	unsigned long		lastuse;
	struct lwtunnel_state   *lwtstate;
	struct rcu_head		rcu_head;
	short			error;
	short			__pad;
	__u32			tclassid;

This is a rough draft, so there are still some problems to resolve.
In particular, the refcount alignment is only sorted out on 64-bit at
this time.  It shouldn't be too hard to either fix 32-bit or decide
that we don't care so much these days or can lower the target
alignment there to 32-bytes rather than 64-bytes.

So, the good news:

1) struct dst_entry shrinks from 160 to 112 bytes.

2) struct rtable shrinks from 216 to 168 bytes.

3) struct rt6_info shrinks from 384 to 320 bytes.

Enjoy.

Signed-off-by: David S. Miller <davem@davemloft.net>

^ permalink raw reply

* Re: [RFC] net/unix_diag: Provide UDIAG_SHOW_VFS2 attribute to fetch complete inode number
From: Cyrill Gorcunov @ 2017-10-25 14:02 UTC (permalink / raw)
  To: Roman Mashak; +Cc: NETDEV, LKML, Andrey Vagin, David S. Miller, Pavel Emelyanov
In-Reply-To: <85bmkvcoxw.fsf@mojatatu.com>

On Wed, Oct 25, 2017 at 09:55:07AM -0400, Roman Mashak wrote:
> 
> I think __zero should be explicitly set to 0.

It will be by compiler default.

^ permalink raw reply

* [PATCH net-next 0/2] net: stmmac: Support DWMAC5 and TSN
From: Jose Abreu @ 2017-10-25 14:02 UTC (permalink / raw)
  To: netdev, linux-kernel, devicetree; +Cc: Jose Abreu

Hi,

This adds support for a new IP version (5) of dwmac and for
TSN features as defined by IEEE802.1Qbv-2015 and IEEE802.1Qbu.

Please review.

Best regards,
Jose Miguel Abreu

Jose Abreu (2):
  net: stmmac: Add support for DWMAC5 with TSN features
  bindings: net: stmmac: Add documentation for TSN parameters

 Documentation/devicetree/bindings/net/stmmac.txt   | 20 +++++
 drivers/net/ethernet/stmicro/stmmac/Makefile       |  2 +-
 drivers/net/ethernet/stmicro/stmmac/common.h       |  4 +
 drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c  | 37 +++++++-
 drivers/net/ethernet/stmicro/stmmac/dwmac5_tsn.c   | 99 ++++++++++++++++++++++
 drivers/net/ethernet/stmicro/stmmac/dwmac5_tsn.h   | 57 +++++++++++++
 drivers/net/ethernet/stmicro/stmmac/stmmac_main.c  |  4 +
 .../net/ethernet/stmicro/stmmac/stmmac_platform.c  | 57 ++++++++++++-
 include/linux/stmmac.h                             | 11 +++
 9 files changed, 288 insertions(+), 3 deletions(-)
 create mode 100644 drivers/net/ethernet/stmicro/stmmac/dwmac5_tsn.c
 create mode 100644 drivers/net/ethernet/stmicro/stmmac/dwmac5_tsn.h

-- 
1.9.1

^ permalink raw reply

* [RFC PATCH 01/12] net: dst->rt_next is unused.
From: David Miller @ 2017-10-25 14:02 UTC (permalink / raw)
  To: netdev


Delete it.

Signed-off-by: David S. Miller <davem@davemloft.net>
---
 include/net/dst.h | 1 -
 1 file changed, 1 deletion(-)

diff --git a/include/net/dst.h b/include/net/dst.h
index 5047e8053d6c..75462861b12f 100644
--- a/include/net/dst.h
+++ b/include/net/dst.h
@@ -100,7 +100,6 @@ struct dst_entry {
 	struct lwtunnel_state   *lwtstate;
 	union {
 		struct dst_entry	*next;
-		struct rtable __rcu	*rt_next;
 		struct rt6_info __rcu	*rt6_next;
 		struct dn_route __rcu	*dn_next;
 	};
-- 
2.13.6

^ permalink raw reply related

* [RFC PATCH 02/12] decnet: Move dn_next into decnet route structure.
From: David Miller @ 2017-10-25 14:02 UTC (permalink / raw)
  To: netdev


Signed-off-by: David S. Miller <davem@davemloft.net>
---
 include/net/dn_route.h |  1 +
 include/net/dst.h      |  1 -
 net/decnet/dn_route.c  | 34 ++++++++++++++++++----------------
 3 files changed, 19 insertions(+), 17 deletions(-)

diff --git a/include/net/dn_route.h b/include/net/dn_route.h
index 55df9939bca2..342d2503cba5 100644
--- a/include/net/dn_route.h
+++ b/include/net/dn_route.h
@@ -69,6 +69,7 @@ int dn_route_rcv(struct sk_buff *skb, struct net_device *dev,
  */
 struct dn_route {
 	struct dst_entry dst;
+	struct dn_route __rcu *dn_next;
 
 	struct neighbour *n;
 
diff --git a/include/net/dst.h b/include/net/dst.h
index 75462861b12f..14a0eec8e7d8 100644
--- a/include/net/dst.h
+++ b/include/net/dst.h
@@ -101,7 +101,6 @@ struct dst_entry {
 	union {
 		struct dst_entry	*next;
 		struct rt6_info __rcu	*rt6_next;
-		struct dn_route __rcu	*dn_next;
 	};
 };
 
diff --git a/net/decnet/dn_route.c b/net/decnet/dn_route.c
index bff5ab88cdbb..fd43c442ab52 100644
--- a/net/decnet/dn_route.c
+++ b/net/decnet/dn_route.c
@@ -199,11 +199,11 @@ static void dn_dst_check_expire(unsigned long dummy)
 						lockdep_is_held(&dn_rt_hash_table[i].lock))) != NULL) {
 			if (atomic_read(&rt->dst.__refcnt) > 1 ||
 			    (now - rt->dst.lastuse) < expire) {
-				rtp = &rt->dst.dn_next;
+				rtp = &rt->dn_next;
 				continue;
 			}
-			*rtp = rt->dst.dn_next;
-			rt->dst.dn_next = NULL;
+			*rtp = rt->dn_next;
+			rt->dn_next = NULL;
 			dst_dev_put(&rt->dst);
 			dst_release(&rt->dst);
 		}
@@ -233,11 +233,11 @@ static int dn_dst_gc(struct dst_ops *ops)
 						lockdep_is_held(&dn_rt_hash_table[i].lock))) != NULL) {
 			if (atomic_read(&rt->dst.__refcnt) > 1 ||
 			    (now - rt->dst.lastuse) < expire) {
-				rtp = &rt->dst.dn_next;
+				rtp = &rt->dn_next;
 				continue;
 			}
-			*rtp = rt->dst.dn_next;
-			rt->dst.dn_next = NULL;
+			*rtp = rt->dn_next;
+			rt->dn_next = NULL;
 			dst_dev_put(&rt->dst);
 			dst_release(&rt->dst);
 			break;
@@ -333,8 +333,8 @@ static int dn_insert_route(struct dn_route *rt, unsigned int hash, struct dn_rou
 						lockdep_is_held(&dn_rt_hash_table[hash].lock))) != NULL) {
 		if (compare_keys(&rth->fld, &rt->fld)) {
 			/* Put it first */
-			*rthp = rth->dst.dn_next;
-			rcu_assign_pointer(rth->dst.dn_next,
+			*rthp = rth->dn_next;
+			rcu_assign_pointer(rth->dn_next,
 					   dn_rt_hash_table[hash].chain);
 			rcu_assign_pointer(dn_rt_hash_table[hash].chain, rth);
 
@@ -345,10 +345,10 @@ static int dn_insert_route(struct dn_route *rt, unsigned int hash, struct dn_rou
 			*rp = rth;
 			return 0;
 		}
-		rthp = &rth->dst.dn_next;
+		rthp = &rth->dn_next;
 	}
 
-	rcu_assign_pointer(rt->dst.dn_next, dn_rt_hash_table[hash].chain);
+	rcu_assign_pointer(rt->dn_next, dn_rt_hash_table[hash].chain);
 	rcu_assign_pointer(dn_rt_hash_table[hash].chain, rt);
 
 	dst_hold_and_use(&rt->dst, now);
@@ -369,8 +369,8 @@ static void dn_run_flush(unsigned long dummy)
 			goto nothing_to_declare;
 
 		for(; rt; rt = next) {
-			next = rcu_dereference_raw(rt->dst.dn_next);
-			RCU_INIT_POINTER(rt->dst.dn_next, NULL);
+			next = rcu_dereference_raw(rt->dn_next);
+			RCU_INIT_POINTER(rt->dn_next, NULL);
 			dst_dev_put(&rt->dst);
 			dst_release(&rt->dst);
 		}
@@ -1183,6 +1183,7 @@ static int dn_route_output_slow(struct dst_entry **pprt, const struct flowidn *o
 	if (rt == NULL)
 		goto e_nobufs;
 
+	rt->dn_next = NULL;
 	memset(&rt->fld, 0, sizeof(rt->fld));
 	rt->fld.saddr        = oldflp->saddr;
 	rt->fld.daddr        = oldflp->daddr;
@@ -1252,7 +1253,7 @@ static int __dn_route_output_key(struct dst_entry **pprt, const struct flowidn *
 	if (!(flags & MSG_TRYHARD)) {
 		rcu_read_lock_bh();
 		for (rt = rcu_dereference_bh(dn_rt_hash_table[hash].chain); rt;
-			rt = rcu_dereference_bh(rt->dst.dn_next)) {
+			rt = rcu_dereference_bh(rt->dn_next)) {
 			if ((flp->daddr == rt->fld.daddr) &&
 			    (flp->saddr == rt->fld.saddr) &&
 			    (flp->flowidn_mark == rt->fld.flowidn_mark) &&
@@ -1448,6 +1449,7 @@ static int dn_route_input_slow(struct sk_buff *skb)
 	if (rt == NULL)
 		goto e_nobufs;
 
+	rt->dn_next = NULL;
 	memset(&rt->fld, 0, sizeof(rt->fld));
 	rt->rt_saddr      = fld.saddr;
 	rt->rt_daddr      = fld.daddr;
@@ -1529,7 +1531,7 @@ static int dn_route_input(struct sk_buff *skb)
 
 	rcu_read_lock();
 	for(rt = rcu_dereference(dn_rt_hash_table[hash].chain); rt != NULL;
-	    rt = rcu_dereference(rt->dst.dn_next)) {
+	    rt = rcu_dereference(rt->dn_next)) {
 		if ((rt->fld.saddr == cb->src) &&
 		    (rt->fld.daddr == cb->dst) &&
 		    (rt->fld.flowidn_oif == 0) &&
@@ -1749,7 +1751,7 @@ int dn_cache_dump(struct sk_buff *skb, struct netlink_callback *cb)
 		rcu_read_lock_bh();
 		for(rt = rcu_dereference_bh(dn_rt_hash_table[h].chain), idx = 0;
 			rt;
-			rt = rcu_dereference_bh(rt->dst.dn_next), idx++) {
+			rt = rcu_dereference_bh(rt->dn_next), idx++) {
 			if (idx < s_idx)
 				continue;
 			skb_dst_set(skb, dst_clone(&rt->dst));
@@ -1795,7 +1797,7 @@ static struct dn_route *dn_rt_cache_get_next(struct seq_file *seq, struct dn_rou
 {
 	struct dn_rt_cache_iter_state *s = seq->private;
 
-	rt = rcu_dereference_bh(rt->dst.dn_next);
+	rt = rcu_dereference_bh(rt->dn_next);
 	while (!rt) {
 		rcu_read_unlock_bh();
 		if (--s->bucket < 0)
-- 
2.13.6

^ permalink raw reply related

* [RFC PATCH 03/12] ipv6: Move rt6_next from dst_entry into ipv6 route structure.
From: David Miller @ 2017-10-25 14:03 UTC (permalink / raw)
  To: netdev


Signed-off-by: David S. Miller <davem@davemloft.net>
---
 include/net/dst.h     |  1 -
 include/net/ip6_fib.h |  5 +++--
 net/ipv6/ip6_fib.c    | 26 +++++++++++++-------------
 net/ipv6/route.c      | 10 +++++-----
 4 files changed, 21 insertions(+), 21 deletions(-)

diff --git a/include/net/dst.h b/include/net/dst.h
index 14a0eec8e7d8..2409e7795ad5 100644
--- a/include/net/dst.h
+++ b/include/net/dst.h
@@ -100,7 +100,6 @@ struct dst_entry {
 	struct lwtunnel_state   *lwtstate;
 	union {
 		struct dst_entry	*next;
-		struct rt6_info __rcu	*rt6_next;
 	};
 };
 
diff --git a/include/net/ip6_fib.h b/include/net/ip6_fib.h
index 10c913816032..281a922f0c62 100644
--- a/include/net/ip6_fib.h
+++ b/include/net/ip6_fib.h
@@ -129,6 +129,7 @@ struct rt6_exception {
 
 struct rt6_info {
 	struct dst_entry		dst;
+	struct rt6_info __rcu		*rt6_next;
 
 	/*
 	 * Tail elements of dst_entry (__refcnt etc.)
@@ -176,11 +177,11 @@ struct rt6_info {
 
 #define for_each_fib6_node_rt_rcu(fn)					\
 	for (rt = rcu_dereference((fn)->leaf); rt;			\
-	     rt = rcu_dereference(rt->dst.rt6_next))
+	     rt = rcu_dereference(rt->rt6_next))
 
 #define for_each_fib6_walker_rt(w)					\
 	for (rt = (w)->leaf; rt;					\
-	     rt = rcu_dereference_protected(rt->dst.rt6_next, 1))
+	     rt = rcu_dereference_protected(rt->rt6_next, 1))
 
 static inline struct inet6_dev *ip6_dst_idev(struct dst_entry *dst)
 {
diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c
index 1ada9672d198..0b2f7fd3e876 100644
--- a/net/ipv6/ip6_fib.c
+++ b/net/ipv6/ip6_fib.c
@@ -890,7 +890,7 @@ static int fib6_add_rt2node(struct fib6_node *fn, struct rt6_info *rt,
 	ins = &fn->leaf;
 
 	for (iter = leaf; iter;
-	     iter = rcu_dereference_protected(iter->dst.rt6_next,
+	     iter = rcu_dereference_protected(iter->rt6_next,
 				lockdep_is_held(&rt->rt6i_table->tb6_lock))) {
 		/*
 		 *	Search for duplicates
@@ -947,7 +947,7 @@ static int fib6_add_rt2node(struct fib6_node *fn, struct rt6_info *rt,
 			break;
 
 next_iter:
-		ins = &iter->dst.rt6_next;
+		ins = &iter->rt6_next;
 	}
 
 	if (fallback_ins && !found) {
@@ -976,7 +976,7 @@ static int fib6_add_rt2node(struct fib6_node *fn, struct rt6_info *rt,
 					      &sibling->rt6i_siblings);
 				break;
 			}
-			sibling = rcu_dereference_protected(sibling->dst.rt6_next,
+			sibling = rcu_dereference_protected(sibling->rt6_next,
 				    lockdep_is_held(&rt->rt6i_table->tb6_lock));
 		}
 		/* For each sibling in the list, increment the counter of
@@ -1006,7 +1006,7 @@ static int fib6_add_rt2node(struct fib6_node *fn, struct rt6_info *rt,
 		if (err)
 			return err;
 
-		rcu_assign_pointer(rt->dst.rt6_next, iter);
+		rcu_assign_pointer(rt->rt6_next, iter);
 		atomic_inc(&rt->rt6i_ref);
 		rcu_assign_pointer(rt->rt6i_node, fn);
 		rcu_assign_pointer(*ins, rt);
@@ -1037,7 +1037,7 @@ static int fib6_add_rt2node(struct fib6_node *fn, struct rt6_info *rt,
 
 		atomic_inc(&rt->rt6i_ref);
 		rcu_assign_pointer(rt->rt6i_node, fn);
-		rt->dst.rt6_next = iter->dst.rt6_next;
+		rt->rt6_next = iter->rt6_next;
 		rcu_assign_pointer(*ins, rt);
 		call_fib6_entry_notifiers(info->nl_net, FIB_EVENT_ENTRY_REPLACE,
 					  rt);
@@ -1056,14 +1056,14 @@ static int fib6_add_rt2node(struct fib6_node *fn, struct rt6_info *rt,
 
 		if (nsiblings) {
 			/* Replacing an ECMP route, remove all siblings */
-			ins = &rt->dst.rt6_next;
+			ins = &rt->rt6_next;
 			iter = rcu_dereference_protected(*ins,
 				    lockdep_is_held(&rt->rt6i_table->tb6_lock));
 			while (iter) {
 				if (iter->rt6i_metric > rt->rt6i_metric)
 					break;
 				if (rt6_qualify_for_ecmp(iter)) {
-					*ins = iter->dst.rt6_next;
+					*ins = iter->rt6_next;
 					iter->rt6i_node = NULL;
 					fib6_purge_rt(iter, fn, info->nl_net);
 					if (rcu_access_pointer(fn->rr_ptr) == iter)
@@ -1072,7 +1072,7 @@ static int fib6_add_rt2node(struct fib6_node *fn, struct rt6_info *rt,
 					nsiblings--;
 					info->nl_net->ipv6.rt6_stats->fib_rt_entries--;
 				} else {
-					ins = &iter->dst.rt6_next;
+					ins = &iter->rt6_next;
 				}
 				iter = rcu_dereference_protected(*ins,
 					lockdep_is_held(&rt->rt6i_table->tb6_lock));
@@ -1641,7 +1641,7 @@ static void fib6_del_route(struct fib6_table *table, struct fib6_node *fn,
 	WARN_ON_ONCE(rt->rt6i_flags & RTF_CACHE);
 
 	/* Unlink it */
-	*rtp = rt->dst.rt6_next;
+	*rtp = rt->rt6_next;
 	rt->rt6i_node = NULL;
 	net->ipv6.rt6_stats->fib_rt_entries--;
 	net->ipv6.rt6_stats->fib_discarded_routes++;
@@ -1669,7 +1669,7 @@ static void fib6_del_route(struct fib6_table *table, struct fib6_node *fn,
 	FOR_WALKERS(net, w) {
 		if (w->state == FWS_C && w->leaf == rt) {
 			RT6_TRACE("walker %p adjusted by delroute\n", w);
-			w->leaf = rcu_dereference_protected(rt->dst.rt6_next,
+			w->leaf = rcu_dereference_protected(rt->rt6_next,
 					    lockdep_is_held(&table->tb6_lock));
 			if (!w->leaf)
 				w->state = FWS_U;
@@ -1728,7 +1728,7 @@ int fib6_del(struct rt6_info *rt, struct nl_info *info)
 			fib6_del_route(table, fn, rtp, info);
 			return 0;
 		}
-		rtp_next = &cur->dst.rt6_next;
+		rtp_next = &cur->rt6_next;
 	}
 	return -ENOENT;
 }
@@ -2203,7 +2203,7 @@ static int ipv6_route_yield(struct fib6_walker *w)
 
 	do {
 		iter->w.leaf = rcu_dereference_protected(
-				iter->w.leaf->dst.rt6_next,
+				iter->w.leaf->rt6_next,
 				lockdep_is_held(&iter->tbl->tb6_lock));
 		iter->skip--;
 		if (!iter->skip && iter->w.leaf)
@@ -2269,7 +2269,7 @@ static void *ipv6_route_seq_next(struct seq_file *seq, void *v, loff_t *pos)
 	if (!v)
 		goto iter_table;
 
-	n = rcu_dereference_bh(((struct rt6_info *)v)->dst.rt6_next);
+	n = rcu_dereference_bh(((struct rt6_info *)v)->rt6_next);
 	if (n) {
 		++*pos;
 		return n;
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index 46c59a53c53f..3c943d252a33 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -497,7 +497,7 @@ static inline struct rt6_info *rt6_device_match(struct net *net,
 	if (!oif && ipv6_addr_any(saddr))
 		goto out;
 
-	for (sprt = rt; sprt; sprt = rcu_dereference(sprt->dst.rt6_next)) {
+	for (sprt = rt; sprt; sprt = rcu_dereference(sprt->rt6_next)) {
 		struct net_device *dev = sprt->dst.dev;
 
 		if (oif) {
@@ -716,7 +716,7 @@ static struct rt6_info *find_rr_leaf(struct fib6_node *fn,
 
 	match = NULL;
 	cont = NULL;
-	for (rt = rr_head; rt; rt = rcu_dereference(rt->dst.rt6_next)) {
+	for (rt = rr_head; rt; rt = rcu_dereference(rt->rt6_next)) {
 		if (rt->rt6i_metric != metric) {
 			cont = rt;
 			break;
@@ -726,7 +726,7 @@ static struct rt6_info *find_rr_leaf(struct fib6_node *fn,
 	}
 
 	for (rt = leaf; rt && rt != rr_head;
-	     rt = rcu_dereference(rt->dst.rt6_next)) {
+	     rt = rcu_dereference(rt->rt6_next)) {
 		if (rt->rt6i_metric != metric) {
 			cont = rt;
 			break;
@@ -738,7 +738,7 @@ static struct rt6_info *find_rr_leaf(struct fib6_node *fn,
 	if (match || !cont)
 		return match;
 
-	for (rt = cont; rt; rt = rcu_dereference(rt->dst.rt6_next))
+	for (rt = cont; rt; rt = rcu_dereference(rt->rt6_next))
 		match = find_match(rt, oif, strict, &mpri, match, do_rr);
 
 	return match;
@@ -776,7 +776,7 @@ static struct rt6_info *rt6_select(struct net *net, struct fib6_node *fn,
 			     &do_rr);
 
 	if (do_rr) {
-		struct rt6_info *next = rcu_dereference(rt0->dst.rt6_next);
+		struct rt6_info *next = rcu_dereference(rt0->rt6_next);
 
 		/* no entries matched; do round-robin */
 		if (!next || next->rt6i_metric != rt0->rt6i_metric)
-- 
2.13.6

^ permalink raw reply related

* [RFC PATCH 04/12] net: Make generic dst->child usage more explicit.
From: David Miller @ 2017-10-25 14:03 UTC (permalink / raw)
  To: netdev


Only IPSEC (xfrm) routes have a dst->child which is non-NULL.
xfrm routes are identified by dst->xfrm being non-NULL.

Codify this explicitly in dst_destroy().

Signed-off-by: David S. Miller <davem@davemloft.net>
---
 net/core/dst.c | 8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/net/core/dst.c b/net/core/dst.c
index 662a2d4a3d19..6a3c21b8fc8d 100644
--- a/net/core/dst.c
+++ b/net/core/dst.c
@@ -116,12 +116,14 @@ EXPORT_SYMBOL(dst_alloc);
 
 struct dst_entry *dst_destroy(struct dst_entry * dst)
 {
-	struct dst_entry *child;
+	struct dst_entry *child = NULL;
 
 	smp_rmb();
 
-	child = dst->child;
-
+#ifdef CONFIG_XFRM
+	if (dst->xfrm)
+		child = dst->child;
+#endif
 	if (!(dst->flags & DST_NOCOUNT))
 		dst_entries_add(dst->ops, -1);
 
-- 
2.13.6

^ permalink raw reply related

* [RFC PATCH 05/12] net: Create and use new helper xfrm_dst_child().
From: David Miller @ 2017-10-25 14:03 UTC (permalink / raw)
  To: netdev


Only IPSEC routes have a non-NULL dst->child pointer.  And IPSEC
routes are identified by a non-NULL dst->xfrm pointer.

Signed-off-by: David S. Miller <davem@davemloft.net>
---
 include/net/xfrm.h           |  9 +++++++++
 net/ipv4/xfrm4_mode_tunnel.c |  2 +-
 net/ipv6/xfrm6_mode_tunnel.c |  2 +-
 net/ipv6/xfrm6_policy.c      |  2 +-
 net/xfrm/xfrm_output.c       |  2 +-
 net/xfrm/xfrm_policy.c       | 12 ++++++------
 security/selinux/xfrm.c      |  2 +-
 7 files changed, 20 insertions(+), 11 deletions(-)

diff --git a/include/net/xfrm.h b/include/net/xfrm.h
index f002a2c5e33c..4fa951112873 100644
--- a/include/net/xfrm.h
+++ b/include/net/xfrm.h
@@ -994,6 +994,15 @@ struct xfrm_dst {
 };
 
 #ifdef CONFIG_XFRM
+static inline struct dst_entry *xfrm_dst_child(const struct dst_entry *dst)
+{
+#ifdef CONFIG_XFRM
+	if (dst->xfrm)
+		return dst->child;
+#endif
+	return NULL;
+}
+
 static inline void xfrm_dst_destroy(struct xfrm_dst *xdst)
 {
 	xfrm_pols_put(xdst->pols, xdst->num_pols);
diff --git a/net/ipv4/xfrm4_mode_tunnel.c b/net/ipv4/xfrm4_mode_tunnel.c
index e6265e2c274e..7d885a44dc9d 100644
--- a/net/ipv4/xfrm4_mode_tunnel.c
+++ b/net/ipv4/xfrm4_mode_tunnel.c
@@ -62,7 +62,7 @@ static int xfrm4_mode_tunnel_output(struct xfrm_state *x, struct sk_buff *skb)
 	top_iph->frag_off = (flags & XFRM_STATE_NOPMTUDISC) ?
 		0 : (XFRM_MODE_SKB_CB(skb)->frag_off & htons(IP_DF));
 
-	top_iph->ttl = ip4_dst_hoplimit(dst->child);
+	top_iph->ttl = ip4_dst_hoplimit(xfrm_dst_child(dst));
 
 	top_iph->saddr = x->props.saddr.a4;
 	top_iph->daddr = x->id.daddr.a4;
diff --git a/net/ipv6/xfrm6_mode_tunnel.c b/net/ipv6/xfrm6_mode_tunnel.c
index 02556e356f87..e66b94f46532 100644
--- a/net/ipv6/xfrm6_mode_tunnel.c
+++ b/net/ipv6/xfrm6_mode_tunnel.c
@@ -59,7 +59,7 @@ static int xfrm6_mode_tunnel_output(struct xfrm_state *x, struct sk_buff *skb)
 	if (x->props.flags & XFRM_STATE_NOECN)
 		dsfield &= ~INET_ECN_MASK;
 	ipv6_change_dsfield(top_iph, 0, dsfield);
-	top_iph->hop_limit = ip6_dst_hoplimit(dst->child);
+	top_iph->hop_limit = ip6_dst_hoplimit(xfrm_dst_child(dst));
 	top_iph->saddr = *(struct in6_addr *)&x->props.saddr;
 	top_iph->daddr = *(struct in6_addr *)&x->id.daddr;
 	return 0;
diff --git a/net/ipv6/xfrm6_policy.c b/net/ipv6/xfrm6_policy.c
index 4ed9f8cc3b6a..e2e6cceef288 100644
--- a/net/ipv6/xfrm6_policy.c
+++ b/net/ipv6/xfrm6_policy.c
@@ -264,7 +264,7 @@ static void xfrm6_dst_ifdown(struct dst_entry *dst, struct net_device *dev,
 			in6_dev_put(xdst->u.rt6.rt6i_idev);
 			xdst->u.rt6.rt6i_idev = loopback_idev;
 			in6_dev_hold(loopback_idev);
-			xdst = (struct xfrm_dst *)xdst->u.dst.child;
+			xdst = (struct xfrm_dst *)xfrm_dst_child(&xdst->u.dst);
 		} while (xdst->u.dst.xfrm);
 
 		__in6_dev_put(loopback_idev);
diff --git a/net/xfrm/xfrm_output.c b/net/xfrm/xfrm_output.c
index 31a2e6d34dba..7fc0932d61ff 100644
--- a/net/xfrm/xfrm_output.c
+++ b/net/xfrm/xfrm_output.c
@@ -44,7 +44,7 @@ static int xfrm_skb_check_space(struct sk_buff *skb)
 
 static struct dst_entry *skb_dst_pop(struct sk_buff *skb)
 {
-	struct dst_entry *child = dst_clone(skb_dst(skb)->child);
+	struct dst_entry *child = dst_clone(xfrm_dst_child(skb_dst(skb)));
 
 	skb_dst_drop(skb);
 	return child;
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
index 4838329bb43a..c68fb3327a68 100644
--- a/net/xfrm/xfrm_policy.c
+++ b/net/xfrm/xfrm_policy.c
@@ -1635,7 +1635,7 @@ static struct dst_entry *xfrm_bundle_create(struct xfrm_policy *policy,
 	xfrm_init_path((struct xfrm_dst *)dst0, dst, nfheader_len);
 	xfrm_init_pmtu(dst_prev);
 
-	for (dst_prev = dst0; dst_prev != dst; dst_prev = dst_prev->child) {
+	for (dst_prev = dst0; dst_prev != dst; dst_prev = xfrm_dst_child(dst_prev)) {
 		struct xfrm_dst *xdst = (struct xfrm_dst *)dst_prev;
 
 		err = xfrm_fill_dst(xdst, dev, fl);
@@ -2570,7 +2570,7 @@ static int stale_bundle(struct dst_entry *dst)
 
 void xfrm_dst_ifdown(struct dst_entry *dst, struct net_device *dev)
 {
-	while ((dst = dst->child) && dst->xfrm && dst->dev == dev) {
+	while ((dst = xfrm_dst_child(dst)) && dst->xfrm && dst->dev == dev) {
 		dst->dev = dev_net(dev)->loopback_dev;
 		dev_hold(dst->dev);
 		dev_put(dev);
@@ -2600,7 +2600,7 @@ static void xfrm_init_pmtu(struct dst_entry *dst)
 		struct xfrm_dst *xdst = (struct xfrm_dst *)dst;
 		u32 pmtu, route_mtu_cached;
 
-		pmtu = dst_mtu(dst->child);
+		pmtu = dst_mtu(xfrm_dst_child(dst));
 		xdst->child_mtu_cached = pmtu;
 
 		pmtu = xfrm_state_mtu(dst->xfrm, pmtu);
@@ -2645,7 +2645,7 @@ static int xfrm_bundle_ok(struct xfrm_dst *first)
 		    xdst->policy_genid != atomic_read(&xdst->pols[0]->genid))
 			return 0;
 
-		mtu = dst_mtu(dst->child);
+		mtu = dst_mtu(xfrm_dst_child(dst));
 		if (xdst->child_mtu_cached != mtu) {
 			last = xdst;
 			xdst->child_mtu_cached = mtu;
@@ -2659,7 +2659,7 @@ static int xfrm_bundle_ok(struct xfrm_dst *first)
 			xdst->route_mtu_cached = mtu;
 		}
 
-		dst = dst->child;
+		dst = xfrm_dst_child(dst);
 	} while (dst->xfrm);
 
 	if (likely(!last))
@@ -2701,7 +2701,7 @@ static const void *xfrm_get_dst_nexthop(const struct dst_entry *dst,
 {
 	const struct dst_entry *path = dst->path;
 
-	for (; dst != path; dst = dst->child) {
+	for (; dst != path; dst = xfrm_dst_child(dst)) {
 		const struct xfrm_state *xfrm = dst->xfrm;
 
 		if (xfrm->props.mode == XFRM_MODE_TRANSPORT)
diff --git a/security/selinux/xfrm.c b/security/selinux/xfrm.c
index 56e354fcdfc6..928188902901 100644
--- a/security/selinux/xfrm.c
+++ b/security/selinux/xfrm.c
@@ -452,7 +452,7 @@ int selinux_xfrm_postroute_last(u32 sk_sid, struct sk_buff *skb,
 	if (dst) {
 		struct dst_entry *iter;
 
-		for (iter = dst; iter != NULL; iter = iter->child) {
+		for (iter = dst; iter != NULL; iter = xfrm_dst_child(iter)) {
 			struct xfrm_state *x = iter->xfrm;
 
 			if (x && selinux_authorizable_xfrm(x))
-- 
2.13.6

^ permalink raw reply related

* pull-request: mac80211 2017-10-25
From: Johannes Berg @ 2017-10-25 14:03 UTC (permalink / raw)
  To: David Miller; +Cc: netdev, linux-wireless

Hi Dave,

Here are a few more fixes for net, we started comprehensive testing
for the security issues and found that the problem wasn't addressed
in TKIP, so that's included, along with a handful other fixes.

Please pull and let me know if there's any problem.

Thanks,
johannes



The following changes since commit 1b72bf5a0777d7cec6c2d857ac15599022b3c123:

  Merge tag 'mac80211-for-davem-2017-10-16' of git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211 (2017-10-16 21:27:16 +0100)

are available in the git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211.git tags/mac80211-for-davem-2017-10-25

for you to fetch changes up to cfbb0d90a7abb289edc91833d0905931f8805f12:

  mac80211: don't compare TKIP TX MIC key in reinstall prevention (2017-10-25 11:04:45 +0200)

----------------------------------------------------------------
Here are:
 * follow-up fixes for the WoWLAN security issue, to fix a
   partial TKIP key material problem and to use crypto_memneq()
 * a change for better enforcement of FQ's memory limit
 * a disconnect/connect handling fix, and
 * a user rate mask validation fix

----------------------------------------------------------------
Jason A. Donenfeld (1):
      mac80211: use constant time comparison with keys

Johannes Berg (3):
      cfg80211: fix connect/disconnect edge cases
      mac80211: validate user rate mask before configuring driver
      mac80211: don't compare TKIP TX MIC key in reinstall prevention

Toke Høiland-Jørgensen (1):
      fq_impl: Properly enforce memory limit

 include/net/fq_impl.h |  9 ++++++---
 net/mac80211/cfg.c    | 12 ++++++------
 net/mac80211/key.c    | 37 +++++++++++++++++++++++++++++++++++--
 net/wireless/sme.c    | 50 +++++++++++++++++++++++++++++++++++++++++---------
 4 files changed, 88 insertions(+), 20 deletions(-)

^ permalink raw reply

* [RFC PATCH 06/12] ipsec: Create and use new helpers for dst child access.
From: David Miller @ 2017-10-25 14:03 UTC (permalink / raw)
  To: netdev


This will make a future change moving the dst->child pointer less
invasive.

Signed-off-by: David S. Miller <davem@davemloft.net>
---
 include/net/xfrm.h     |  5 +++++
 net/xfrm/xfrm_policy.c | 57 +++++++++++++++++++++++++-------------------------
 2 files changed, 33 insertions(+), 29 deletions(-)

diff --git a/include/net/xfrm.h b/include/net/xfrm.h
index 4fa951112873..5a4cc05ff9e8 100644
--- a/include/net/xfrm.h
+++ b/include/net/xfrm.h
@@ -1003,6 +1003,11 @@ static inline struct dst_entry *xfrm_dst_child(const struct dst_entry *dst)
 	return NULL;
 }
 
+static inline void xfrm_dst_set_child(struct xfrm_dst *xdst, struct dst_entry *child)
+{
+	xdst->u.dst.child = child;
+}
+
 static inline void xfrm_dst_destroy(struct xfrm_dst *xdst)
 {
 	xfrm_pols_put(xdst->pols, xdst->num_pols);
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
index c68fb3327a68..206ac90ff4f0 100644
--- a/net/xfrm/xfrm_policy.c
+++ b/net/xfrm/xfrm_policy.c
@@ -1545,8 +1545,8 @@ static struct dst_entry *xfrm_bundle_create(struct xfrm_policy *policy,
 	unsigned long now = jiffies;
 	struct net_device *dev;
 	struct xfrm_mode *inner_mode;
-	struct dst_entry *dst_prev = NULL;
-	struct dst_entry *dst0 = NULL;
+	struct xfrm_dst *xdst_prev = NULL;
+	struct xfrm_dst *xdst0 = NULL;
 	int i = 0;
 	int err;
 	int header_len = 0;
@@ -1572,6 +1572,14 @@ static struct dst_entry *xfrm_bundle_create(struct xfrm_policy *policy,
 			goto put_states;
 		}
 
+		if (!xdst_prev)
+			xdst0 = xdst;
+		else
+			/* Ref count is taken during xfrm_alloc_dst()
+			 * No need to do dst_clone() on dst1
+			 */
+			xfrm_dst_set_child(xdst_prev, &xdst->u.dst);
+
 		if (xfrm[i]->sel.family == AF_UNSPEC) {
 			inner_mode = xfrm_ip2inner_mode(xfrm[i],
 							xfrm_af2proto(family));
@@ -1583,14 +1591,6 @@ static struct dst_entry *xfrm_bundle_create(struct xfrm_policy *policy,
 		} else
 			inner_mode = xfrm[i]->inner_mode;
 
-		if (!dst_prev)
-			dst0 = dst1;
-		else
-			/* Ref count is taken during xfrm_alloc_dst()
-			 * No need to do dst_clone() on dst1
-			 */
-			dst_prev->child = dst1;
-
 		xdst->route = dst;
 		dst_copy_metrics(dst1, dst);
 
@@ -1615,8 +1615,8 @@ static struct dst_entry *xfrm_bundle_create(struct xfrm_policy *policy,
 		dst1->input = dst_discard;
 		dst1->output = inner_mode->afinfo->output;
 
-		dst1->next = dst_prev;
-		dst_prev = dst1;
+		dst1->next = &xdst_prev->u.dst;
+		xdst_prev = xdst;
 
 		header_len += xfrm[i]->props.header_len;
 		if (xfrm[i]->type->flags & XFRM_TYPE_NON_FRAGMENT)
@@ -1624,40 +1624,39 @@ static struct dst_entry *xfrm_bundle_create(struct xfrm_policy *policy,
 		trailer_len += xfrm[i]->props.trailer_len;
 	}
 
-	dst_prev->child = dst;
-	dst0->path = dst;
+	xfrm_dst_set_child(xdst_prev, dst);
+	xdst0->u.dst.path = dst;
 
 	err = -ENODEV;
 	dev = dst->dev;
 	if (!dev)
 		goto free_dst;
 
-	xfrm_init_path((struct xfrm_dst *)dst0, dst, nfheader_len);
-	xfrm_init_pmtu(dst_prev);
-
-	for (dst_prev = dst0; dst_prev != dst; dst_prev = xfrm_dst_child(dst_prev)) {
-		struct xfrm_dst *xdst = (struct xfrm_dst *)dst_prev;
+	xfrm_init_path(xdst0, dst, nfheader_len);
+	xfrm_init_pmtu(&xdst_prev->u.dst);
 
-		err = xfrm_fill_dst(xdst, dev, fl);
+	for (xdst_prev = xdst0; xdst_prev != (struct xfrm_dst *)dst;
+	     xdst_prev = (struct xfrm_dst *) xfrm_dst_child(&xdst_prev->u.dst)) {
+		err = xfrm_fill_dst(xdst_prev, dev, fl);
 		if (err)
 			goto free_dst;
 
-		dst_prev->header_len = header_len;
-		dst_prev->trailer_len = trailer_len;
-		header_len -= xdst->u.dst.xfrm->props.header_len;
-		trailer_len -= xdst->u.dst.xfrm->props.trailer_len;
+		xdst_prev->u.dst.header_len = header_len;
+		xdst_prev->u.dst.trailer_len = trailer_len;
+		header_len -= xdst_prev->u.dst.xfrm->props.header_len;
+		trailer_len -= xdst_prev->u.dst.xfrm->props.trailer_len;
 	}
 
 out:
-	return dst0;
+	return &xdst0->u.dst;
 
 put_states:
 	for (; i < nx; i++)
 		xfrm_state_put(xfrm[i]);
 free_dst:
-	if (dst0)
-		dst_release_immediate(dst0);
-	dst0 = ERR_PTR(err);
+	if (xdst0)
+		dst_release_immediate(&xdst0->u.dst);
+	xdst0 = ERR_PTR(err);
 	goto out;
 }
 
@@ -2005,7 +2004,7 @@ static struct xfrm_dst *xfrm_create_dummy_bundle(struct net *net,
 	dst1->output = xdst_queue_output;
 
 	dst_hold(dst);
-	dst1->child = dst;
+	xfrm_dst_set_child(xdst, dst);
 	dst1->path = dst;
 
 	xfrm_init_path((struct xfrm_dst *)dst1, dst, 0);
-- 
2.13.6

^ permalink raw reply related

* [PATCH net-next 1/2] net: stmmac: Add support for DWMAC5 with TSN features
From: Jose Abreu @ 2017-10-25 14:04 UTC (permalink / raw)
  To: netdev-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA
  Cc: Jose Abreu, David S. Miller, Joao Pinto, Giuseppe Cavallaro,
	Alexandre Torgue
In-Reply-To: <cover.1508938927.git.joabreu-HKixBCOQz3hWk0Htik3J/w@public.gmane.org>

This adds support for IP version 5 of DWMAC. The new introduced
features are the Enhancements to Scheduled Traffic (EST) as
defined by IEEE802.1Qbv-2015 and Frame Preemption (FPE) as
defined by IEEE802.1Qbu.

In order to not break previous setups all the necessary
configuration is only performed when GMAC5 is detected and
only when all the necessary parameters are available in the
Device Tree.

EST:
The IEEE802.1Qbv-2015 defines the schedule for each of the
queues which makes the IP aware of traffic arrival time. This
information can be used to block the lower priority traffic
from transmission in this time window/slot.

FPE:
The IEEE802.1Qbu defines a mechanism which breaks interfering
frames into smaller fragments shuch that we have a more efficient
use of network bandwidth. This needs EST enabled.

Signed-off-by: Jose Abreu <joabreu-HKixBCOQz3hWk0Htik3J/w@public.gmane.org>
Cc: David S. Miller <davem-fT/PcQaiUtIeIZ0/mPfg9Q@public.gmane.org>
Cc: Joao Pinto <jpinto-HKixBCOQz3hWk0Htik3J/w@public.gmane.org>
Cc: Giuseppe Cavallaro <peppe.cavallaro-qxv4g6HH51o@public.gmane.org>
Cc: Alexandre Torgue <alexandre.torgue-qxv4g6HH51o@public.gmane.org>
---
 drivers/net/ethernet/stmicro/stmmac/Makefile       |  2 +-
 drivers/net/ethernet/stmicro/stmmac/common.h       |  4 +
 drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c  | 37 +++++++-
 drivers/net/ethernet/stmicro/stmmac/dwmac5_tsn.c   | 99 ++++++++++++++++++++++
 drivers/net/ethernet/stmicro/stmmac/dwmac5_tsn.h   | 57 +++++++++++++
 drivers/net/ethernet/stmicro/stmmac/stmmac_main.c  |  4 +
 .../net/ethernet/stmicro/stmmac/stmmac_platform.c  | 57 ++++++++++++-
 include/linux/stmmac.h                             | 11 +++
 8 files changed, 268 insertions(+), 3 deletions(-)
 create mode 100644 drivers/net/ethernet/stmicro/stmmac/dwmac5_tsn.c
 create mode 100644 drivers/net/ethernet/stmicro/stmmac/dwmac5_tsn.h

diff --git a/drivers/net/ethernet/stmicro/stmmac/Makefile b/drivers/net/ethernet/stmicro/stmmac/Makefile
index 238307f..45b594e 100644
--- a/drivers/net/ethernet/stmicro/stmmac/Makefile
+++ b/drivers/net/ethernet/stmicro/stmmac/Makefile
@@ -3,7 +3,7 @@ stmmac-objs:= stmmac_main.o stmmac_ethtool.o stmmac_mdio.o ring_mode.o	\
 	      chain_mode.o dwmac_lib.o dwmac1000_core.o dwmac1000_dma.o	\
 	      dwmac100_core.o dwmac100_dma.o enh_desc.o norm_desc.o	\
 	      mmc_core.o stmmac_hwtstamp.o stmmac_ptp.o dwmac4_descs.o	\
-	      dwmac4_dma.o dwmac4_lib.o dwmac4_core.o $(stmmac-y)
+	      dwmac4_dma.o dwmac4_lib.o dwmac4_core.o dwmac5_tsn.o $(stmmac-y)
 
 # Ordering matters. Generic driver must be last.
 obj-$(CONFIG_STMMAC_PLATFORM)	+= stmmac-platform.o
diff --git a/drivers/net/ethernet/stmicro/stmmac/common.h b/drivers/net/ethernet/stmicro/stmmac/common.h
index e1e5ac0..d052b9f 100644
--- a/drivers/net/ethernet/stmicro/stmmac/common.h
+++ b/drivers/net/ethernet/stmicro/stmmac/common.h
@@ -38,6 +38,7 @@
 #define	DWMAC_CORE_3_40	0x34
 #define	DWMAC_CORE_3_50	0x35
 #define	DWMAC_CORE_4_00	0x40
+#define DWMAC_CORE_5_00 0x50
 #define STMMAC_CHAN0	0	/* Always supported and default for all chips */
 
 /* These need to be power of two, and >= 4 */
@@ -501,6 +502,9 @@ struct stmmac_ops {
 	void (*config_cbs)(struct mac_device_info *hw, u32 send_slope,
 			   u32 idle_slope, u32 high_credit, u32 low_credit,
 			   u32 queue);
+	/* Configure TSN features */
+	void (*config_tsn)(struct mac_device_info *hw,
+			   struct plat_stmmacenet_data *plat);
 	/* Dump MAC registers */
 	void (*dump_regs)(struct mac_device_info *hw, u32 *reg_space);
 	/* Handle extra events on specific interrupts hw dependent */
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c b/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c
index 2f7d7ec..54370da 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c
@@ -19,6 +19,7 @@
 #include <linux/io.h>
 #include "stmmac_pcs.h"
 #include "dwmac4.h"
+#include "dwmac5_tsn.h"
 
 static void dwmac4_core_init(struct mac_device_info *hw, int mtu)
 {
@@ -738,6 +739,38 @@ static void dwmac4_debug(void __iomem *ioaddr, struct stmmac_extra_stats *x,
 	.set_filter = dwmac4_set_filter,
 };
 
+static const struct stmmac_ops dwmac5_ops = {
+	.core_init = dwmac4_core_init,
+	.set_mac = stmmac_dwmac4_set_mac,
+	.rx_ipc = dwmac4_rx_ipc_enable,
+	.rx_queue_enable = dwmac4_rx_queue_enable,
+	.rx_queue_prio = dwmac4_rx_queue_priority,
+	.tx_queue_prio = dwmac4_tx_queue_priority,
+	.rx_queue_routing = dwmac4_tx_queue_routing,
+	.prog_mtl_rx_algorithms = dwmac4_prog_mtl_rx_algorithms,
+	.prog_mtl_tx_algorithms = dwmac4_prog_mtl_tx_algorithms,
+	.set_mtl_tx_queue_weight = dwmac4_set_mtl_tx_queue_weight,
+	.map_mtl_to_dma = dwmac4_map_mtl_dma,
+	.config_cbs = dwmac4_config_cbs,
+	.config_tsn = dwmac5_config_tsn,
+	.dump_regs = dwmac4_dump_regs,
+	.host_irq_status = dwmac4_irq_status,
+	.host_mtl_irq_status = dwmac4_irq_mtl_status,
+	.flow_ctrl = dwmac4_flow_ctrl,
+	.pmt = dwmac4_pmt,
+	.set_umac_addr = dwmac4_set_umac_addr,
+	.get_umac_addr = dwmac4_get_umac_addr,
+	.set_eee_mode = dwmac4_set_eee_mode,
+	.reset_eee_mode = dwmac4_reset_eee_mode,
+	.set_eee_timer = dwmac4_set_eee_timer,
+	.set_eee_pls = dwmac4_set_eee_pls,
+	.pcs_ctrl_ane = dwmac4_ctrl_ane,
+	.pcs_rane = dwmac4_rane,
+	.pcs_get_adv_lp = dwmac4_get_adv_lp,
+	.debug = dwmac4_debug,
+	.set_filter = dwmac4_set_filter,
+};
+
 struct mac_device_info *dwmac4_setup(void __iomem *ioaddr, int mcbins,
 				     int perfect_uc_entries, int *synopsys_id)
 {
@@ -778,7 +811,9 @@ struct mac_device_info *dwmac4_setup(void __iomem *ioaddr, int mcbins,
 	else
 		mac->dma = &dwmac4_dma_ops;
 
-	if (*synopsys_id >= DWMAC_CORE_4_00)
+	if (*synopsys_id >= DWMAC_CORE_5_00)
+		mac->mac = &dwmac5_ops;
+	else if (*synopsys_id >= DWMAC_CORE_4_00)
 		mac->mac = &dwmac410_ops;
 	else
 		mac->mac = &dwmac4_ops;
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac5_tsn.c b/drivers/net/ethernet/stmicro/stmmac/dwmac5_tsn.c
new file mode 100644
index 0000000..fa1d506
--- /dev/null
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac5_tsn.c
@@ -0,0 +1,99 @@
+/*
+ * DWMAC5 TSN Core Functions
+ * Copyright (C) 2017 Synopsys, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * Author: Jose Abreu <joabreu-HKixBCOQz3hWk0Htik3J/w@public.gmane.org>
+ */
+
+#include "common.h"
+#include "dwmac5_tsn.h"
+
+static int dwmac5_est_write(void __iomem *ioaddr, u32 reg, u32 val, bool gcla)
+{
+	int timeout_ms = EST_WRITE_TIMEOUT_MS;
+	u32 ctrl = 0x0;
+
+	writel(val, ioaddr + MTL_EST_GCL_DATA);
+
+	ctrl |= reg;
+	ctrl |= gcla ? 0x0 : MTL_EST_GCRR;
+	writel(ctrl, ioaddr + MTL_EST_GCL_CONTROL);
+
+	ctrl |= MTL_EST_SRWO;
+	writel(ctrl, ioaddr + MTL_EST_GCL_CONTROL);
+
+	while (--timeout_ms) {
+		udelay(1000);
+		if (readl(ioaddr + MTL_EST_GCL_CONTROL) & MTL_EST_SRWO)
+			continue;
+		break;
+	}
+
+	if (!timeout_ms)
+		return -ETIMEDOUT;
+	return 0;
+}
+
+static void dwmac5_config_est(struct mac_device_info *hw,
+			      struct plat_stmmacenet_data *plat)
+{
+	struct stmmac_est_cfg *est = &plat->est_cfg;
+	void __iomem *ioaddr = hw->pcsr;
+	u32 ctrl = 0x0, btr[2];
+	struct timespec64 now;
+	int i;
+
+	/* Add real time to offset */
+	ktime_get_real_ts64(&now);
+	btr[0] = (u32)now.tv_nsec + est->btr[0];
+	btr[1] = (u32)now.tv_sec + est->btr[1];
+
+	/* Write parameters */
+	dwmac5_est_write(ioaddr, MTL_EST_BTR_LOW, btr[0], false);
+	dwmac5_est_write(ioaddr, MTL_EST_BTR_HIGH, btr[1], false);
+	dwmac5_est_write(ioaddr, MTL_EST_CTR_LOW, est->ctr[0], false);
+	dwmac5_est_write(ioaddr, MTL_EST_CTR_HIGH, est->ctr[1], false);
+	dwmac5_est_write(ioaddr, MTL_EST_TER, est->ter, false);
+	dwmac5_est_write(ioaddr, MTL_EST_LLR, est->llr, false);
+
+	/* Write GCL table */
+	for (i = 0; i < est->llr; i++) {
+		u32 reg = (i << MTL_EST_ADDR_SHIFT) & MTL_EST_ADDR;
+		dwmac5_est_write(ioaddr, reg, est->gcl[i], true);
+	}
+
+	/* Enable EST */
+	ctrl |= MTL_EST_EEST;
+	writel(ctrl, ioaddr + MTL_EST_CONTROL);
+
+	/* Store table */
+	ctrl |= MTL_EST_SSWL;
+	writel(ctrl, ioaddr + MTL_EST_CONTROL);
+}
+
+void dwmac5_config_fp(struct mac_device_info *hw)
+{
+	void __iomem *ioaddr = hw->pcsr;
+	u32 ctrl;
+
+	/* Enable frame preemption */
+	ctrl = readl(ioaddr + GMAC_FPE_CTRL_STS);
+	ctrl |= GMAC_FPE_EFPE;
+	writel(ctrl, ioaddr + GMAC_FPE_CTRL_STS);
+}
+
+void dwmac5_config_tsn(struct mac_device_info *hw,
+		       struct plat_stmmacenet_data *plat)
+{
+	void __iomem *ioaddr = hw->pcsr;
+	u32 value = readl(ioaddr + GMAC_HW_FEATURE3);
+
+	if ((value & GMAC_HW_FEAT_ESTSEL) && plat->est_en)
+		dwmac5_config_est(hw, plat);
+	if ((value & GMAC_HW_FEAT_FPESEL) && plat->fp_en)
+		dwmac5_config_fp(hw);
+}
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac5_tsn.h b/drivers/net/ethernet/stmicro/stmmac/dwmac5_tsn.h
new file mode 100644
index 0000000..07bda8b
--- /dev/null
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac5_tsn.h
@@ -0,0 +1,57 @@
+/*
+ * DWMAC5 TSN Header File
+ * Copyright (C) 2017 Synopsys, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * Author: Jose Abreu <joabreu-HKixBCOQz3hWk0Htik3J/w@public.gmane.org>
+ */
+
+#ifndef __DWMAC5_TSN_H__
+#define __DWMAC5_TSN_H__
+
+#include <linux/stmmac.h>
+
+/* MAC registers */
+#define GMAC_HW_FEATURE3		0x00000128
+#define GMAC_FPE_CTRL_STS		0x00000234
+
+/* MAC HW features3 bitmap */
+#define GMAC_HW_FEAT_FPESEL		BIT(26)
+#define GMAC_HW_FEAT_ESTSEL		BIT(16)
+
+/* MAC FPE control/status bitmap */
+#define GMAC_FPE_EFPE			BIT(0)
+
+/* MTL registers */
+#define MTL_EST_CONTROL			0x00000c50
+#define MTL_EST_GCL_CONTROL		0x00000c80
+#define MTL_EST_GCL_DATA		0x00000c84
+
+/* EST control bitmap */
+#define MTL_EST_EEST			BIT(0)
+#define MTL_EST_SSWL			BIT(1)
+
+/* EST GCL control bitmap */
+#define MTL_EST_ADDR_SHIFT		8
+#define MTL_EST_ADDR			GENMASK(19, 8)
+#define MTL_EST_GCRR			BIT(2)
+#define MTL_EST_SRWO			BIT(0)
+
+/* EST GCRA addresses */
+#define MTL_EST_BTR_LOW			(0x0 << MTL_EST_ADDR_SHIFT)
+#define MTL_EST_BTR_HIGH		(0x1 << MTL_EST_ADDR_SHIFT)
+#define MTL_EST_CTR_LOW			(0x2 << MTL_EST_ADDR_SHIFT)
+#define MTL_EST_CTR_HIGH		(0x3 << MTL_EST_ADDR_SHIFT)
+#define MTL_EST_TER			(0x4 << MTL_EST_ADDR_SHIFT)
+#define MTL_EST_LLR			(0x5 << MTL_EST_ADDR_SHIFT)
+
+/* Misc */
+#define EST_WRITE_TIMEOUT_MS		5
+
+void dwmac5_config_tsn(struct mac_device_info *hw,
+		       struct plat_stmmacenet_data *plat);
+
+#endif /* __DWMAC5_TSN_H__ */
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index c7a894e..24861e2 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -2418,6 +2418,10 @@ static void stmmac_mtl_configuration(struct stmmac_priv *priv)
 	if (tx_queues_count > 1 && priv->hw->mac->config_cbs)
 		stmmac_configure_cbs(priv);
 
+	/* Configure TSN features */
+	if (tx_queues_count > 1 && priv->hw->mac->config_tsn)
+		priv->hw->mac->config_tsn(priv->hw, priv->plat);
+
 	/* Map RX MTL to DMA channels */
 	if (priv->hw->mac->map_mtl_to_dma)
 		stmmac_rx_queue_dma_chan_map(priv);
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
index 8a280b4..21f59fe 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
@@ -280,6 +280,59 @@ static void stmmac_mtl_setup(struct platform_device *pdev,
 	of_node_put(q_node);
 }
 
+static int stmmac_est_setup(struct device_node *node,
+			    struct platform_device *pdev,
+			    struct plat_stmmacenet_data *plat)
+{
+	struct stmmac_est_cfg *est = &plat->est_cfg;
+	int ret;
+
+	if (of_property_read_u32_array(node, "snps,btr", est->btr, 2))
+		return -EINVAL;
+	if (of_property_read_u32_array(node, "snps,ctr", est->ctr, 2))
+		return -EINVAL;
+	if (of_property_read_u32(node, "snps,ter", &est->ter))
+		return -EINVAL;
+	
+	est->llr = of_property_count_u32_elems(node, "snps,gcl");
+	if (!est->llr)
+		return -EINVAL;
+
+	est->gcl = devm_kzalloc(&pdev->dev, sizeof(*est->gcl) * est->llr,
+			GFP_KERNEL);
+	if (!est->gcl)
+		return -ENOMEM;
+
+	ret = of_property_read_u32_array(node, "snps,gcl", est->gcl, est->llr);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+static void stmmac_tsn_setup(struct platform_device *pdev,
+			     struct plat_stmmacenet_data *plat)
+{
+	struct device_node *node;
+
+	node = of_parse_phandle(pdev->dev.of_node, "snps,tsn-config", 0);
+	if (!node)
+		return;
+
+	/* Parse EST values, if a property is missing EST is disabled */
+	plat->est_en = of_property_read_bool(node, "snps,est");
+	if (plat->est_en && stmmac_est_setup(node, pdev, plat)) {
+		pr_warn("Disabling EST because of bad DT parameters.");
+		plat->est_en = false;
+	}
+
+	/* FP needs EST enabled */
+	if (plat->est_en)
+		plat->fp_en = of_property_read_bool(node, "snps,fp");
+
+	of_node_put(node);
+}
+
 /**
  * stmmac_dt_phy - parse device-tree driver parameters to allocate PHY resources
  * @plat: driver data platform structure
@@ -453,7 +506,8 @@ struct plat_stmmacenet_data *
 	}
 
 	if (of_device_is_compatible(np, "snps,dwmac-4.00") ||
-	    of_device_is_compatible(np, "snps,dwmac-4.10a")) {
+	    of_device_is_compatible(np, "snps,dwmac-4.10a") ||
+	    of_device_is_compatible(np, "snps,dwmac-5.00")) {
 		plat->has_gmac4 = 1;
 		plat->has_gmac = 0;
 		plat->pmt = 1;
@@ -497,6 +551,7 @@ struct plat_stmmacenet_data *
 	plat->axi = stmmac_axi_setup(pdev);
 
 	stmmac_mtl_setup(pdev, plat);
+	stmmac_tsn_setup(pdev, plat);
 
 	/* clock setup */
 	plat->stmmac_clk = devm_clk_get(&pdev->dev,
diff --git a/include/linux/stmmac.h b/include/linux/stmmac.h
index 108739f..9b9a102 100644
--- a/include/linux/stmmac.h
+++ b/include/linux/stmmac.h
@@ -144,6 +144,14 @@ struct stmmac_txq_cfg {
 	u32 prio;
 };
 
+struct stmmac_est_cfg {
+	u32 btr[2];
+	u32 ctr[2];
+	u32 ter;
+	u32 llr;
+	u32 *gcl;
+};
+
 struct plat_stmmacenet_data {
 	int bus_id;
 	int phy_addr;
@@ -190,5 +198,8 @@ struct plat_stmmacenet_data {
 	bool tso_en;
 	int mac_port_sel_speed;
 	bool en_tx_lpi_clockgating;
+	bool est_en;
+	struct stmmac_est_cfg est_cfg;
+	bool fp_en;
 };
 #endif
-- 
1.9.1


--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related

* [PATCH net-next 2/2] bindings: net: stmmac: Add documentation for TSN parameters
From: Jose Abreu @ 2017-10-25 14:04 UTC (permalink / raw)
  To: netdev, linux-kernel, devicetree
  Cc: Jose Abreu, David S. Miller, Joao Pinto, Giuseppe Cavallaro,
	Alexandre Torgue, Rob Herring
In-Reply-To: <cover.1508938927.git.joabreu@synopsys.com>

This adds the documentation for TSN feature EST and FP.

Signed-off-by: Jose Abreu <joabreu@synopsys.com>
Cc: David S. Miller <davem@davemloft.net>
Cc: Joao Pinto <jpinto@synopsys.com>
Cc: Giuseppe Cavallaro <peppe.cavallaro@st.com>
Cc: Alexandre Torgue <alexandre.torgue@st.com>
Cc: Rob Herring <robh+dt@kernel.org>
---
 Documentation/devicetree/bindings/net/stmmac.txt | 20 ++++++++++++++++++++
 1 file changed, 20 insertions(+)

diff --git a/Documentation/devicetree/bindings/net/stmmac.txt b/Documentation/devicetree/bindings/net/stmmac.txt
index c3a7be6..6359df6 100644
--- a/Documentation/devicetree/bindings/net/stmmac.txt
+++ b/Documentation/devicetree/bindings/net/stmmac.txt
@@ -114,6 +114,16 @@ Optional properties:
 			- snps,high_credit: max write outstanding req. limit
 			- snps,low_credit: max read outstanding req. limit
 		- snps,priority: TX queue priority (Range: 0x0 to 0xF)
+- TSN parameters: below the list of all the parameters to configure TSN
+		  features (only applicable for IP version >= 5.00)
+	- snps,est: Enable EST algorithm
+	- If EST enabled provide these parameters:
+		- snps,btr: Array size of 2 with BTR value for EST algorithm
+		- snps,ctr: Array size of 2 with CTR value for EST algorithm
+		- snps,ter: TER value for EST algorithm
+		- snps,gcl: Variable size array with GCL table entries.
+	- snps,fp: Enable FP feature. This needs EST enabled.
+
 Examples:
 
 	stmmac_axi_setup: stmmac-axi-config {
@@ -151,6 +161,15 @@ Examples:
 		};
 	};
 
+	tsn_setup: tsn-config {
+		snps,est;
+		snps,btr = <0x00000000 0x00000001>;
+		snps,ctr = <0x00000000 0x10000000>;
+		snps,ter = <0x00000000>;
+		snps,gcl = <0x00000001 0x00000002 0x00000003>;
+		snps,fp;
+	};
+
 	gmac0: ethernet@e0800000 {
 		compatible = "st,spear600-gmac";
 		reg = <0xe0800000 0x8000>;
@@ -176,4 +195,5 @@ Examples:
 		};
 		snps,mtl-rx-config = <&mtl_rx_setup>;
 		snps,mtl-tx-config = <&mtl_tx_setup>;
+		snps,tsn-config = <&tsn_setup>;
 	};
-- 
1.9.1

^ permalink raw reply related


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