* [PATCH] net:netfilter alloc xt_byteslimit_htable with wrong size
From: zhizhou.tian @ 2017-09-08 3:00 UTC (permalink / raw)
To: pablo, kadlec, fw, davem, netfilter-devel, coreteam, netdev,
linux-kernel
Cc: Zhizhou Tian
From: Zhizhou Tian <zhizhou.tian@gmail.com>
struct xt_byteslimit_htable used hlist_head,
but alloc memory with sizeof(struct list_head)
Change-Id: I75bc60e47e0823700d4303c9d763b7995e3b7bb3
Signed-off-by: Zhizhou Tian <zhizhou.tian@gmail.com>
---
net/netfilter/xt_hashlimit.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/net/netfilter/xt_hashlimit.c b/net/netfilter/xt_hashlimit.c
index 10d4823..962ea4a 100644
--- a/net/netfilter/xt_hashlimit.c
+++ b/net/netfilter/xt_hashlimit.c
@@ -279,7 +279,7 @@ static int htable_create(struct net *net, struct hashlimit_cfg3 *cfg,
size = cfg->size;
} else {
size = (totalram_pages << PAGE_SHIFT) / 16384 /
- sizeof(struct list_head);
+ sizeof(struct hlist_head);
if (totalram_pages > 1024 * 1024 * 1024 / PAGE_SIZE)
size = 8192;
if (size < 16)
@@ -287,7 +287,7 @@ static int htable_create(struct net *net, struct hashlimit_cfg3 *cfg,
}
/* FIXME: don't use vmalloc() here or anywhere else -HW */
hinfo = vmalloc(sizeof(struct xt_hashlimit_htable) +
- sizeof(struct list_head) * size);
+ sizeof(struct hlist_head) * size);
if (hinfo == NULL)
return -ENOMEM;
*out_hinfo = hinfo;
--
2.7.4
^ permalink raw reply related
* Re: [PATCH net] ip6_gre: update mtu properly in ip6gre_err
From: David Miller @ 2017-09-08 3:00 UTC (permalink / raw)
To: lucien.xin; +Cc: netdev
In-Reply-To: <bcd5956b4342a889e686a475e2ec4fcb36db3e57.1504603593.git.lucien.xin@gmail.com>
From: Xin Long <lucien.xin@gmail.com>
Date: Tue, 5 Sep 2017 17:26:33 +0800
> Now when probessing ICMPV6_PKT_TOOBIG, ip6gre_err only subtracts the
> offset of gre header from mtu info. The expected mtu of gre device
> should also subtract gre header. Otherwise, the next packets still
> can't be sent out.
>
> Jianlin found this issue when using the topo:
> client(ip6gre)<---->(nic1)route(nic2)<----->(ip6gre)server
>
> and reducing nic2's mtu, then both tcp and sctp's performance with
> big size data became 0.
>
> This patch is to fix it by also subtracting grehdr (tun->tun_hlen)
> from mtu info when updating gre device's mtu in ip6gre_err(). It
> also needs to subtract ETH_HLEN if gre dev'type is ARPHRD_ETHER.
>
> Reported-by: Jianlin Shi <jishi@redhat.com>
> Signed-off-by: Xin Long <lucien.xin@gmail.com>
Applied and queued up for -stable, thanks.
^ permalink raw reply
* Re: [PATCH net] udp: drop head states only when all skb references are gone
From: David Miller @ 2017-09-08 3:03 UTC (permalink / raw)
To: pabeni; +Cc: netdev, edumazet, hannes
In-Reply-To: <1d0596e2a1926e7c0e8c7f691ef42c713daa3396.1504701206.git.pabeni@redhat.com>
From: Paolo Abeni <pabeni@redhat.com>
Date: Wed, 6 Sep 2017 14:44:36 +0200
> After commit 0ddf3fb2c43d ("udp: preserve skb->dst if required
> for IP options processing") we clear the skb head state as soon
> as the skb carrying them is first processed.
>
> Since the same skb can be processed several times when MSG_PEEK
> is used, we can end up lacking the required head states, and
> eventually oopsing.
>
> Fix this clearing the skb head state only when processing the
> last skb reference.
>
> Reported-by: Eric Dumazet <edumazet@google.com>
> Fixes: 0ddf3fb2c43d ("udp: preserve skb->dst if required for IP options processing")
> Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Applied and queued up for -stable, thanks.
^ permalink raw reply
* Re: [PATCH] isdn: isdnloop: fix logic error in isdnloop_sendbuf
From: David Miller @ 2017-09-08 3:04 UTC (permalink / raw)
To: arnd; +Cc: isdn, joe, netdev, linux-kernel
In-Reply-To: <20170906133928.3152020-1-arnd@arndb.de>
From: Arnd Bergmann <arnd@arndb.de>
Date: Wed, 6 Sep 2017 15:38:58 +0200
> gcc-7 found an ancient bug in the loop driver, leading to a condition that
> is always false, meaning we ignore the contents of 'card->flags' here:
>
> drivers/isdn/isdnloop/isdnloop.c:412:37: error: ?: using integer constants in boolean context, the expression will always evaluate to 'true' [-Werror=int-in-bool-context]
>
> This changes the braces in the expression to ensure we actually
> compare the flag bits, rather than comparing a constant. As Joe Perches
> pointed out, an earlier patch of mine incorrectly assumed this was a
> false-positive warning.
>
> Cc: Joe Perches <joe@perches.com>
> Link: https://patchwork.kernel.org/patch/9840289/
> Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Applied, thank you.
^ permalink raw reply
* Re: [PATCH net v2] rds: Fix incorrect statistics counting
From: David Miller @ 2017-09-08 3:07 UTC (permalink / raw)
To: Haakon.Bugge
Cc: santosh.shilimkar, netdev, linux-rdma, rds-devel, linux-kernel,
knut.omang
In-Reply-To: <20170906163551.20387-1-Haakon.Bugge@oracle.com>
From: Håkon Bugge <Haakon.Bugge@oracle.com>
Date: Wed, 6 Sep 2017 18:35:51 +0200
> In rds_send_xmit() there is logic to batch the sends. However, if
> another thread has acquired the lock and has incremented the send_gen,
> it is considered a race and we yield. The code incrementing the
> s_send_lock_queue_raced statistics counter did not count this event
> correctly.
>
> This commit counts the race condition correctly.
>
> Changes from v1:
> - Removed check for *someone_on_xmit()*
> - Fixed incorrect indentation
>
> Signed-off-by: Håkon Bugge <haakon.bugge@oracle.com>
> Reviewed-by: Knut Omang <knut.omang@oracle.com>
Applied.
^ permalink raw reply
* Re: Use after free in __dst_destroy_metrics_generic
From: Subash Abhinov Kasiviswanathan @ 2017-09-08 3:27 UTC (permalink / raw)
To: David Miller; +Cc: netdev, eric.dumazet, lorenzo
In-Reply-To: <20170907.191324.852949594923852324.davem@davemloft.net>
>> [ 3489.194392] __ion_alloc+0x180/0x988
>
> I do not see the __ion_alloc function in my tree.
Hi David
This function seems to be defined in an Android specific change.
https://android.googlesource.com/kernel/msm/+/20a5411d0115b16826f3d327b6abb0192c8a2001
--
Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, a
Linux Foundation Collaborative Project
^ permalink raw reply
* [PATCH 0/3] net: TCP/IP: A few minor cleanups
From: Michael Witten @ 2017-09-08 5:05 UTC (permalink / raw)
To: David S. Miller, Alexey Kuznetsov, Hideaki YOSHIFUJI; +Cc: netdev, linux-kernel
The following patch series is an ad hoc "cleanup" that I made
while perusing the code (I'm not well versed in this code, so I
would not be surprised if there were objections to the changes):
[1] net: __sock_cmsg_send(): Remove unused parameter `msg'
[2] net: inet_recvmsg(): Remove unnecessary bitwise operation.
[3] net: skb_queue_purge(): lock/unlock the list only once
Each patch will be sent as an individiual email; the total diff
is appended below for your convenience.
You may also fetch these patches from GitHub:
git checkout -b test 5969d1bb3082b41eba8fd2c826559abe38ccb6df
git pull https://github.com/mfwitten/linux.git net/tcp-ip/01-cleanup/00
Overall:
include/net/sock.h | 2 +-
net/core/skbuff.c | 6 +++++-
net/core/sock.c | 4 ++--
net/ipv4/af_inet.c | 2 +-
net/ipv4/ip_sockglue.c | 2 +-
net/ipv6/datagram.c | 2 +-
6 files changed, 11 insertions(+), 7 deletions(-)
Sincerly,
Michael Witten
diff --git a/include/net/sock.h b/include/net/sock.h
index 03a362568357..83373d7148a9 100644
--- a/include/net/sock.h
+++ b/include/net/sock.h
@@ -1562,7 +1562,7 @@ struct sockcm_cookie {
u16 tsflags;
};
-int __sock_cmsg_send(struct sock *sk, struct msghdr *msg, struct cmsghdr *cmsg,
+int __sock_cmsg_send(struct sock *sk, struct cmsghdr *cmsg,
struct sockcm_cookie *sockc);
int sock_cmsg_send(struct sock *sk, struct msghdr *msg,
struct sockcm_cookie *sockc);
diff --git a/net/core/sock.c b/net/core/sock.c
index 9b7b6bbb2a23..425e03fe1c56 100644
--- a/net/core/sock.c
+++ b/net/core/sock.c
@@ -2091,7 +2091,7 @@ struct sk_buff *sock_alloc_send_skb(struct sock *sk, unsigned long size,
}
EXPORT_SYMBOL(sock_alloc_send_skb);
-int __sock_cmsg_send(struct sock *sk, struct msghdr *msg, struct cmsghdr *cmsg,
+int __sock_cmsg_send(struct sock *sk, struct cmsghdr *cmsg,
struct sockcm_cookie *sockc)
{
u32 tsflags;
@@ -2137,7 +2137,7 @@ int sock_cmsg_send(struct sock *sk, struct msghdr *msg,
return -EINVAL;
if (cmsg->cmsg_level != SOL_SOCKET)
continue;
- ret = __sock_cmsg_send(sk, msg, cmsg, sockc);
+ ret = __sock_cmsg_send(sk, cmsg, sockc);
if (ret)
return ret;
}
diff --git a/net/ipv4/ip_sockglue.c b/net/ipv4/ip_sockglue.c
index e558e4f9597b..c79b7822b0b9 100644
--- a/net/ipv4/ip_sockglue.c
+++ b/net/ipv4/ip_sockglue.c
@@ -263,7 +263,7 @@ int ip_cmsg_send(struct sock *sk, struct msghdr *msg, struct ipcm_cookie *ipc,
}
#endif
if (cmsg->cmsg_level == SOL_SOCKET) {
- err = __sock_cmsg_send(sk, msg, cmsg, &ipc->sockc);
+ err = __sock_cmsg_send(sk, cmsg, &ipc->sockc);
if (err)
return err;
continue;
diff --git a/net/ipv6/datagram.c b/net/ipv6/datagram.c
index a1f918713006..1d1926a4cbe2 100644
--- a/net/ipv6/datagram.c
+++ b/net/ipv6/datagram.c
@@ -756,7 +756,7 @@ int ip6_datagram_send_ctl(struct net *net, struct sock *sk,
}
if (cmsg->cmsg_level == SOL_SOCKET) {
- err = __sock_cmsg_send(sk, msg, cmsg, sockc);
+ err = __sock_cmsg_send(sk, cmsg, sockc);
if (err)
return err;
continue;
diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c
index e31108e5ef79..2dbed042a412 100644
--- a/net/ipv4/af_inet.c
+++ b/net/ipv4/af_inet.c
@@ -791,7 +791,7 @@ int inet_recvmsg(struct socket *sock, struct msghdr *msg, size_t size,
sock_rps_record_flow(sk);
err = sk->sk_prot->recvmsg(sk, msg, size, flags & MSG_DONTWAIT,
- flags & ~MSG_DONTWAIT, &addr_len);
+ flags, &addr_len);
if (err >= 0)
msg->msg_namelen = addr_len;
return err;
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index 68065d7d383f..66c0731a2a5f 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -2834,9 +2834,13 @@ EXPORT_SYMBOL(skb_dequeue_tail);
*/
void skb_queue_purge(struct sk_buff_head *list)
{
+ unsigned long flags;
struct sk_buff *skb;
- while ((skb = skb_dequeue(list)) != NULL)
+
+ spin_lock_irqsave(&list->lock, flags);
+ while ((skb = __skb_dequeue(list)) != NULL)
kfree_skb(skb);
+ spin_unlock_irqrestore(&list->lock, flags);
}
EXPORT_SYMBOL(skb_queue_purge);
--
2.14.1
^ permalink raw reply related
* [PATCH 1/3] net: __sock_cmsg_send(): Remove unused parameter `msg'
From: Michael Witten @ 2017-09-08 5:05 UTC (permalink / raw)
To: David S. Miller, Alexey Kuznetsov, Hideaki YOSHIFUJI; +Cc: netdev, linux-kernel
In-Reply-To: <45aab5effc0c424a992646a97cf2ec14-mfwitten@gmail.com>
Date: Thu, 7 Sep 2017 03:21:38 +0000
Signed-off-by: Michael Witten <mfwitten@gmail.com>
---
include/net/sock.h | 2 +-
net/core/sock.c | 4 ++--
net/ipv4/ip_sockglue.c | 2 +-
net/ipv6/datagram.c | 2 +-
4 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/include/net/sock.h b/include/net/sock.h
index 03a362568357..83373d7148a9 100644
--- a/include/net/sock.h
+++ b/include/net/sock.h
@@ -1562,7 +1562,7 @@ struct sockcm_cookie {
u16 tsflags;
};
-int __sock_cmsg_send(struct sock *sk, struct msghdr *msg, struct cmsghdr *cmsg,
+int __sock_cmsg_send(struct sock *sk, struct cmsghdr *cmsg,
struct sockcm_cookie *sockc);
int sock_cmsg_send(struct sock *sk, struct msghdr *msg,
struct sockcm_cookie *sockc);
diff --git a/net/core/sock.c b/net/core/sock.c
index 9b7b6bbb2a23..425e03fe1c56 100644
--- a/net/core/sock.c
+++ b/net/core/sock.c
@@ -2091,7 +2091,7 @@ struct sk_buff *sock_alloc_send_skb(struct sock *sk, unsigned long size,
}
EXPORT_SYMBOL(sock_alloc_send_skb);
-int __sock_cmsg_send(struct sock *sk, struct msghdr *msg, struct cmsghdr *cmsg,
+int __sock_cmsg_send(struct sock *sk, struct cmsghdr *cmsg,
struct sockcm_cookie *sockc)
{
u32 tsflags;
@@ -2137,7 +2137,7 @@ int sock_cmsg_send(struct sock *sk, struct msghdr *msg,
return -EINVAL;
if (cmsg->cmsg_level != SOL_SOCKET)
continue;
- ret = __sock_cmsg_send(sk, msg, cmsg, sockc);
+ ret = __sock_cmsg_send(sk, cmsg, sockc);
if (ret)
return ret;
}
diff --git a/net/ipv4/ip_sockglue.c b/net/ipv4/ip_sockglue.c
index e558e4f9597b..c79b7822b0b9 100644
--- a/net/ipv4/ip_sockglue.c
+++ b/net/ipv4/ip_sockglue.c
@@ -263,7 +263,7 @@ int ip_cmsg_send(struct sock *sk, struct msghdr *msg, struct ipcm_cookie *ipc,
}
#endif
if (cmsg->cmsg_level == SOL_SOCKET) {
- err = __sock_cmsg_send(sk, msg, cmsg, &ipc->sockc);
+ err = __sock_cmsg_send(sk, cmsg, &ipc->sockc);
if (err)
return err;
continue;
diff --git a/net/ipv6/datagram.c b/net/ipv6/datagram.c
index a1f918713006..1d1926a4cbe2 100644
--- a/net/ipv6/datagram.c
+++ b/net/ipv6/datagram.c
@@ -756,7 +756,7 @@ int ip6_datagram_send_ctl(struct net *net, struct sock *sk,
}
if (cmsg->cmsg_level == SOL_SOCKET) {
- err = __sock_cmsg_send(sk, msg, cmsg, sockc);
+ err = __sock_cmsg_send(sk, cmsg, sockc);
if (err)
return err;
continue;
--
2.14.1
^ permalink raw reply related
* Re: [PATCH net] bpf: don't select potentially stale ri->map from buggy xdp progs
From: Jesper Dangaard Brouer @ 2017-09-08 5:06 UTC (permalink / raw)
To: Daniel Borkmann; +Cc: davem, ast, john.fastabend, andy, netdev, brouer
In-Reply-To: <01d69254802986ad3a8b18a8650c45df3df95def.1504821825.git.daniel@iogearbox.net>
On Fri, 8 Sep 2017 00:14:51 +0200
Daniel Borkmann <daniel@iogearbox.net> wrote:
> + /* This is really only caused by a deliberately crappy
> + * BPF program, normally we would never hit that case,
> + * so no need to inform someone via tracepoints either,
> + * just bail out.
> + */
> + if (unlikely(map_owner != xdp_prog))
> + return -EINVAL;
IMHO we do need to call the tracepoint here. It is not just crappy
BPF-progs that cause this situation, it is also drivers not implementing
XDP_REDIRECT yet (which is all but ixgbe). Due to the level XDP
operates at, tracepoints are the only way users can runtime troubleshoot
their XDP programs.
--
Best regards,
Jesper Dangaard Brouer
MSc.CS, Principal Kernel Engineer at Red Hat
LinkedIn: http://www.linkedin.com/in/brouer
^ permalink raw reply
* [PATCH 2/3] net: inet_recvmsg(): Remove unnecessary bitwise operation
From: Michael Witten @ 2017-09-08 5:06 UTC (permalink / raw)
To: David S. Miller, Alexey Kuznetsov, Hideaki YOSHIFUJI; +Cc: netdev, linux-kernel
In-Reply-To: <45aab5effc0c424a992646a97cf2ec14-mfwitten@gmail.com>
Date: Fri, 8 Sep 2017 00:47:49 +0000
The flag `MSG_DONTWAIT' is handled by passing an argument through
the dedicated parameter `nonblock' of the function `tcp_recvmsg()'.
Presumably because `MSG_DONTWAIT' is handled so explicitly, it is
unset in the collection of flags that are passed to `tcp_recvmsg()';
yet, this unsetting appears to be unnecessary, and so this commit
removes the bitwise operation that performs the unsetting.
Signed-off-by: Michael Witten <mfwitten@gmail.com>
---
net/ipv4/af_inet.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c
index e31108e5ef79..2dbed042a412 100644
--- a/net/ipv4/af_inet.c
+++ b/net/ipv4/af_inet.c
@@ -791,7 +791,7 @@ int inet_recvmsg(struct socket *sock, struct msghdr *msg, size_t size,
sock_rps_record_flow(sk);
err = sk->sk_prot->recvmsg(sk, msg, size, flags & MSG_DONTWAIT,
- flags & ~MSG_DONTWAIT, &addr_len);
+ flags, &addr_len);
if (err >= 0)
msg->msg_namelen = addr_len;
return err;
--
2.14.1
^ permalink raw reply related
* [PATCH 3/3] net: skb_queue_purge(): lock/unlock the list only once
From: Michael Witten @ 2017-09-08 5:06 UTC (permalink / raw)
To: David S. Miller, Alexey Kuznetsov, Hideaki YOSHIFUJI; +Cc: netdev, linux-kernel
In-Reply-To: <45aab5effc0c424a992646a97cf2ec14-mfwitten@gmail.com>
Date: Thu, 7 Sep 2017 20:07:40 +0000
With this commit, the list's lock is locked/unlocked only once
for the duration of `skb_queue_purge()'.
Hitherto, the list's lock has been locked/unlocked every time
an item is dequeued; this seems not only inefficient, but also
incorrect, as the whole point of `skb_queue_purge()' is to clear
the list, presumably without giving anything else a chance to
manipulate the list in the interim.
Signed-off-by: Michael Witten <mfwitten@gmail.com>
---
net/core/skbuff.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index 68065d7d383f..66c0731a2a5f 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -2834,9 +2834,13 @@ EXPORT_SYMBOL(skb_dequeue_tail);
*/
void skb_queue_purge(struct sk_buff_head *list)
{
+ unsigned long flags;
struct sk_buff *skb;
- while ((skb = skb_dequeue(list)) != NULL)
+
+ spin_lock_irqsave(&list->lock, flags);
+ while ((skb = __skb_dequeue(list)) != NULL)
kfree_skb(skb);
+ spin_unlock_irqrestore(&list->lock, flags);
}
EXPORT_SYMBOL(skb_queue_purge);
--
2.14.1
^ permalink raw reply related
* [PATCH v2] netfilter: xt_hashlimit: fix build error caused by 64bit division
From: Vishwanath Pai @ 2017-09-08 5:38 UTC (permalink / raw)
To: pablo, netfilter-devel, torvalds, davem
Cc: kadlec, johunt, fw, netdev, pai.vishwain, mingo, ilubashe, bp,
luto, x86, linux-kernel, brgerst, andrew.cooper3, jgross,
boris.ostrovsky, keescook, akpm, arnd
64bit division causes build/link errors on 32bit architectures. It
prints out error messages like:
ERROR: "__aeabi_uldivmod" [net/netfilter/xt_hashlimit.ko] undefined!
The value of avg passed through by userspace in BYTE mode cannot exceed
U32_MAX. Which means 64bit division in user2rate_bytes is unnecessary.
To fix this I have changed the type of param 'user' to u32.
Since anything greater than U32_MAX is an invalid input we error out in
hashlimit_mt_check_common() when this is the case.
Changes in v2:
Making return type as u32 would cause an overflow for small
values of 'user' (for example 2, 3 etc). To avoid this I bumped up
'r' to u64 again as well as the return type. This is OK since the
variable that stores the result is u64. We still avoid 64bit
division here since 'user' is u32.
Fixes: bea74641e378 ("netfilter: xt_hashlimit: add rate match mode")
Signed-off-by: Vishwanath Pai <vpai@akamai.com>
---
net/netfilter/xt_hashlimit.c | 12 +++++++-----
1 file changed, 7 insertions(+), 5 deletions(-)
diff --git a/net/netfilter/xt_hashlimit.c b/net/netfilter/xt_hashlimit.c
index 10d4823..1c1941e 100644
--- a/net/netfilter/xt_hashlimit.c
+++ b/net/netfilter/xt_hashlimit.c
@@ -35,6 +35,7 @@
#include <linux/netfilter_ipv6/ip6_tables.h>
#include <linux/netfilter/xt_hashlimit.h>
#include <linux/mutex.h>
+#include <linux/kernel.h>
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>");
@@ -527,12 +528,12 @@ static u64 user2rate(u64 user)
}
}
-static u64 user2rate_bytes(u64 user)
+static u64 user2rate_bytes(u32 user)
{
u64 r;
- r = user ? 0xFFFFFFFFULL / user : 0xFFFFFFFFULL;
- r = (r - 1) << 4;
+ r = user ? U32_MAX / user : U32_MAX;
+ r = (r - 1) << XT_HASHLIMIT_BYTE_SHIFT;
return r;
}
@@ -588,7 +589,8 @@ static void rateinfo_init(struct dsthash_ent *dh,
dh->rateinfo.prev_window = 0;
dh->rateinfo.current_rate = 0;
if (hinfo->cfg.mode & XT_HASHLIMIT_BYTES) {
- dh->rateinfo.rate = user2rate_bytes(hinfo->cfg.avg);
+ dh->rateinfo.rate =
+ user2rate_bytes((u32)hinfo->cfg.avg);
if (hinfo->cfg.burst)
dh->rateinfo.burst =
hinfo->cfg.burst * dh->rateinfo.rate;
@@ -870,7 +872,7 @@ static int hashlimit_mt_check_common(const struct xt_mtchk_param *par,
/* Check for overflow. */
if (revision >= 3 && cfg->mode & XT_HASHLIMIT_RATE_MATCH) {
- if (cfg->avg == 0) {
+ if (cfg->avg == 0 || cfg->avg > U32_MAX) {
pr_info("hashlimit invalid rate\n");
return -ERANGE;
}
--
1.9.1
^ permalink raw reply related
* Re: [patch net-next] team: fall back to hash if table entry is empty
From: Jiri Pirko @ 2017-09-08 5:55 UTC (permalink / raw)
To: Jim Hanko; +Cc: netdev
In-Reply-To: <1504837512-16395-1-git-send-email-hanko@drivescale.com>
Fri, Sep 08, 2017 at 04:25:12AM CEST, hanko@drivescale.com wrote:
>If the hash to port mapping table does not have a valid port (i.e. when
>a port goes down), fall back to the simple hashing mechanism to avoid
>dropping packets.
>
>Signed-off-by: Jim Hanko <hanko@drivescale.com>
Acked-by: Jiri Pirko <jiri@mellanox.com>
net-next is closed for now (will open after rc1 is out). Please re-send
the patch (including my ack) then.
Thanks.
^ permalink raw reply
* [PATCH net-next v8] openvswitch: enable NSH support
From: Yi Yang @ 2017-09-08 5:58 UTC (permalink / raw)
To: netdev; +Cc: davem, dev, jbenc, e, blp, jan.scheurich, Yi Yang
v7->v8
- Rework nested value and mask for OVS_KEY_ATTR_NSH
- Change pop_nsh to adapt to nsh kernel module
- Fix many issues per comments from Jiri Benc
v6->v7
- Remove NSH GSO patches in v6 because Jiri Benc
reworked it as another patch series and they have
been merged.
- Change it to adapt to nsh kernel module added by NSH
GSO patch series
v5->v6
- Fix the rest comments for v4.
- Add NSH GSO support for VxLAN-gpe + NSH and
Eth + NSH.
v4->v5
- Fix many comments by Jiri Benc and Eric Garver
for v4.
v3->v4
- Add new NSH match field ttl
- Update NSH header to the latest format
which will be final format and won't change
per its author's confirmation.
- Fix comments for v3.
v2->v3
- Change OVS_KEY_ATTR_NSH to nested key to handle
length-fixed attributes and length-variable
attriubte more flexibly.
- Remove struct ovs_action_push_nsh completely
- Add code to handle nested attribute for SET_MASKED
- Change PUSH_NSH to use the nested OVS_KEY_ATTR_NSH
to transfer NSH header data.
- Fix comments and coding style issues by Jiri and Eric
v1->v2
- Change encap_nsh and decap_nsh to push_nsh and pop_nsh
- Dynamically allocate struct ovs_action_push_nsh for
length-variable metadata.
OVS master and 2.8 branch has merged NSH userspace
patch series, this patch is to enable NSH support
in kernel data path in order that OVS can support
NSH in compat mode by porting this.
Signed-off-by: Yi Yang <yi.y.yang@intel.com>
---
include/net/nsh.h | 3 +
include/uapi/linux/openvswitch.h | 29 ++++
net/nsh/nsh.c | 53 +++++++
net/openvswitch/actions.c | 113 ++++++++++++++
net/openvswitch/flow.c | 51 ++++++
net/openvswitch/flow.h | 11 ++
net/openvswitch/flow_netlink.c | 324 ++++++++++++++++++++++++++++++++++++++-
net/openvswitch/flow_netlink.h | 5 +
8 files changed, 588 insertions(+), 1 deletion(-)
diff --git a/include/net/nsh.h b/include/net/nsh.h
index a1eaea2..b886d33 100644
--- a/include/net/nsh.h
+++ b/include/net/nsh.h
@@ -304,4 +304,7 @@ static inline void nsh_set_flags_ttl_len(struct nshhdr *nsh, u8 flags,
NSH_FLAGS_MASK | NSH_TTL_MASK | NSH_LEN_MASK);
}
+int skb_push_nsh(struct sk_buff *skb, const struct nshhdr *src_nsh_hdr);
+int skb_pop_nsh(struct sk_buff *skb);
+
#endif /* __NET_NSH_H */
diff --git a/include/uapi/linux/openvswitch.h b/include/uapi/linux/openvswitch.h
index 156ee4c..c1a785c 100644
--- a/include/uapi/linux/openvswitch.h
+++ b/include/uapi/linux/openvswitch.h
@@ -333,6 +333,7 @@ enum ovs_key_attr {
OVS_KEY_ATTR_CT_LABELS, /* 16-octet connection tracking label */
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_* */
#ifdef __KERNEL__
OVS_KEY_ATTR_TUNNEL_INFO, /* struct ip_tunnel_info */
@@ -491,6 +492,30 @@ struct ovs_key_ct_tuple_ipv6 {
__u8 ipv6_proto;
};
+enum ovs_nsh_key_attr {
+ OVS_NSH_KEY_ATTR_UNSPEC,
+ OVS_NSH_KEY_ATTR_BASE, /* struct ovs_nsh_key_base. */
+ OVS_NSH_KEY_ATTR_MD1, /* struct ovs_nsh_key_md1. */
+ OVS_NSH_KEY_ATTR_MD2, /* variable-length octets for MD type 2. */
+ __OVS_NSH_KEY_ATTR_MAX
+};
+
+#define OVS_NSH_KEY_ATTR_MAX (__OVS_NSH_KEY_ATTR_MAX - 1)
+
+struct ovs_nsh_key_base {
+ __u8 flags;
+ __u8 ttl;
+ __u8 mdtype;
+ __u8 np;
+ __be32 path_hdr;
+};
+
+#define NSH_MD1_CONTEXT_SIZE 4
+
+struct ovs_nsh_key_md1 {
+ __be32 context[NSH_MD1_CONTEXT_SIZE];
+};
+
/**
* enum ovs_flow_attr - attributes for %OVS_FLOW_* commands.
* @OVS_FLOW_ATTR_KEY: Nested %OVS_KEY_ATTR_* attributes specifying the flow
@@ -806,6 +831,8 @@ struct ovs_action_push_eth {
* packet.
* @OVS_ACTION_ATTR_POP_ETH: Pop the outermost Ethernet header off the
* packet.
+ * @OVS_ACTION_ATTR_PUSH_NSH: push NSH header to the packet.
+ * @OVS_ACTION_ATTR_POP_NSH: pop the outermost NSH header off the packet.
*
* Only a single header can be set with a single %OVS_ACTION_ATTR_SET. Not all
* fields within a header are modifiable, e.g. the IPv4 protocol and fragment
@@ -835,6 +862,8 @@ enum ovs_action_attr {
OVS_ACTION_ATTR_TRUNC, /* u32 struct ovs_action_trunc. */
OVS_ACTION_ATTR_PUSH_ETH, /* struct ovs_action_push_eth. */
OVS_ACTION_ATTR_POP_ETH, /* No argument. */
+ OVS_ACTION_ATTR_PUSH_NSH, /* Nested OVS_NSH_KEY_ATTR_*. */
+ OVS_ACTION_ATTR_POP_NSH, /* No argument. */
__OVS_ACTION_ATTR_MAX, /* Nothing past this will be accepted
* from userspace. */
diff --git a/net/nsh/nsh.c b/net/nsh/nsh.c
index 58fb827..54334ca 100644
--- a/net/nsh/nsh.c
+++ b/net/nsh/nsh.c
@@ -14,6 +14,59 @@
#include <net/nsh.h>
#include <net/tun_proto.h>
+int skb_push_nsh(struct sk_buff *skb, const struct nshhdr *src_nsh_hdr)
+{
+ struct nshhdr *nsh_hdr;
+ size_t length = nsh_hdr_len(src_nsh_hdr);
+ u8 next_proto;
+
+ if (skb->mac_len) {
+ next_proto = TUN_P_ETHERNET;
+ } else {
+ next_proto = tun_p_from_eth_p(skb->protocol);
+ if (!next_proto)
+ return -EAFNOSUPPORT;
+ }
+
+ /* Add the NSH header */
+ if (skb_cow_head(skb, length) < 0)
+ return -ENOMEM;
+
+ skb_push(skb, length);
+ nsh_hdr = (struct nshhdr *)(skb->data);
+ memcpy(nsh_hdr, src_nsh_hdr, length);
+ nsh_hdr->np = next_proto;
+
+ skb->protocol = htons(ETH_P_NSH);
+ skb_reset_mac_header(skb);
+ skb_reset_mac_len(skb);
+ skb_reset_network_header(skb);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(skb_push_nsh);
+
+int skb_pop_nsh(struct sk_buff *skb)
+{
+ struct nshhdr *nsh_hdr = (struct nshhdr *)(skb->data);
+ size_t length;
+ u16 inner_proto;
+
+ inner_proto = tun_p_to_eth_p(nsh_hdr->np);
+ if (!inner_proto)
+ return -EAFNOSUPPORT;
+
+ length = nsh_hdr_len(nsh_hdr);
+ skb_pull(skb, length);
+ skb_reset_mac_header(skb);
+ skb_reset_mac_len(skb);
+ skb_reset_network_header(skb);
+ skb->protocol = inner_proto;
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(skb_pop_nsh);
+
static struct sk_buff *nsh_gso_segment(struct sk_buff *skb,
netdev_features_t features)
{
diff --git a/net/openvswitch/actions.c b/net/openvswitch/actions.c
index a54a556..30ac07c 100644
--- a/net/openvswitch/actions.c
+++ b/net/openvswitch/actions.c
@@ -38,11 +38,13 @@
#include <net/dsfield.h>
#include <net/mpls.h>
#include <net/sctp/checksum.h>
+#include <net/tun_proto.h>
#include "datapath.h"
#include "flow.h"
#include "conntrack.h"
#include "vport.h"
+#include "flow_netlink.h"
struct deferred_action {
struct sk_buff *skb;
@@ -380,6 +382,45 @@ static int push_eth(struct sk_buff *skb, struct sw_flow_key *key,
return 0;
}
+static int push_nsh(struct sk_buff *skb, struct sw_flow_key *key,
+ const struct nshhdr *src_nsh_hdr)
+{
+ int err;
+
+ err = skb_push_nsh(skb, src_nsh_hdr);
+ if (err)
+ return err;
+
+ key->eth.type = htons(ETH_P_NSH);
+
+ /* safe right before invalidate_flow_key */
+ key->mac_proto = MAC_PROTO_NONE;
+ invalidate_flow_key(key);
+ return 0;
+}
+
+static int pop_nsh(struct sk_buff *skb, struct sw_flow_key *key)
+{
+ int err;
+
+ if (ovs_key_mac_proto(key) != MAC_PROTO_NONE ||
+ skb->protocol != htons(ETH_P_NSH)) {
+ return -EINVAL;
+ }
+
+ err = skb_pop_nsh(skb);
+ if (err)
+ return err;
+
+ /* safe right before invalidate_flow_key */
+ if (skb->protocol == htons(ETH_P_TEB))
+ key->mac_proto = MAC_PROTO_ETHERNET;
+ else
+ key->mac_proto = MAC_PROTO_NONE;
+ invalidate_flow_key(key);
+ return 0;
+}
+
static void update_ip_l4_checksum(struct sk_buff *skb, struct iphdr *nh,
__be32 addr, __be32 new_addr)
{
@@ -602,6 +643,59 @@ static int set_ipv6(struct sk_buff *skb, struct sw_flow_key *flow_key,
return 0;
}
+static int set_nsh(struct sk_buff *skb, struct sw_flow_key *flow_key,
+ const struct nlattr *a)
+{
+ struct nshhdr *nsh_hdr;
+ int err;
+ u8 flags;
+ u8 ttl;
+ int i;
+
+ struct ovs_key_nsh key;
+ struct ovs_key_nsh mask;
+
+ err = nsh_key_from_nlattr(a, &key, &mask);
+ if (err)
+ return err;
+
+ err = skb_ensure_writable(skb, skb_network_offset(skb) +
+ sizeof(struct nshhdr));
+ if (unlikely(err))
+ return err;
+
+ nsh_hdr = (struct nshhdr *)skb_network_header(skb);
+
+ flags = nsh_get_flags(nsh_hdr);
+ flags = OVS_MASKED(flags, key.flags, mask.flags);
+ flow_key->nsh.flags = flags;
+ ttl = nsh_get_ttl(nsh_hdr);
+ ttl = OVS_MASKED(ttl, key.ttl, mask.ttl);
+ flow_key->nsh.ttl = ttl;
+ nsh_set_flags_and_ttl(nsh_hdr, flags, ttl);
+ nsh_hdr->path_hdr = OVS_MASKED(nsh_hdr->path_hdr, key.path_hdr,
+ mask.path_hdr);
+ flow_key->nsh.path_hdr = nsh_hdr->path_hdr;
+ switch (nsh_hdr->mdtype) {
+ case NSH_M_TYPE1:
+ for (i = 0; i < NSH_MD1_CONTEXT_SIZE; i++) {
+ nsh_hdr->md1.context[i] =
+ OVS_MASKED(nsh_hdr->md1.context[i], key.context[i],
+ mask.context[i]);
+ }
+ memcpy(flow_key->nsh.context, nsh_hdr->md1.context,
+ sizeof(nsh_hdr->md1.context));
+ break;
+ case NSH_M_TYPE2:
+ memset(flow_key->nsh.context, 0,
+ sizeof(flow_key->nsh.context));
+ break;
+ default:
+ return -EINVAL;
+ }
+ return 0;
+}
+
/* Must follow skb_ensure_writable() since that can move the skb data. */
static void set_tp_port(struct sk_buff *skb, __be16 *port,
__be16 new_port, __sum16 *check)
@@ -1024,6 +1118,10 @@ static int execute_masked_set_action(struct sk_buff *skb,
get_mask(a, struct ovs_key_ethernet *));
break;
+ case OVS_KEY_ATTR_NSH:
+ err = set_nsh(skb, flow_key, a);
+ break;
+
case OVS_KEY_ATTR_IPV4:
err = set_ipv4(skb, flow_key, nla_data(a),
get_mask(a, struct ovs_key_ipv4 *));
@@ -1210,6 +1308,21 @@ static int do_execute_actions(struct datapath *dp, struct sk_buff *skb,
case OVS_ACTION_ATTR_POP_ETH:
err = pop_eth(skb, key);
break;
+
+ case OVS_ACTION_ATTR_PUSH_NSH: {
+ u8 buffer[NSH_HDR_MAX_LEN];
+ struct nshhdr *nsh_hdr = (struct nshhdr *)buffer;
+ const struct nshhdr *src_nsh_hdr = nsh_hdr;
+
+ nsh_hdr_from_nlattr(nla_data(a), nsh_hdr,
+ NSH_HDR_MAX_LEN);
+ err = push_nsh(skb, key, src_nsh_hdr);
+ break;
+ }
+
+ case OVS_ACTION_ATTR_POP_NSH:
+ err = pop_nsh(skb, key);
+ break;
}
if (unlikely(err)) {
diff --git a/net/openvswitch/flow.c b/net/openvswitch/flow.c
index 8c94cef..67fb6d9 100644
--- a/net/openvswitch/flow.c
+++ b/net/openvswitch/flow.c
@@ -46,6 +46,7 @@
#include <net/ipv6.h>
#include <net/mpls.h>
#include <net/ndisc.h>
+#include <net/nsh.h>
#include "conntrack.h"
#include "datapath.h"
@@ -490,6 +491,52 @@ static int parse_icmpv6(struct sk_buff *skb, struct sw_flow_key *key,
return 0;
}
+static int parse_nsh(struct sk_buff *skb, struct sw_flow_key *key)
+{
+ struct nshhdr *nsh_hdr;
+ unsigned int nh_ofs = skb_network_offset(skb);
+ u8 version, length;
+ int err;
+
+ err = check_header(skb, nh_ofs + NSH_BASE_HDR_LEN);
+ if (unlikely(err))
+ return err;
+
+ nsh_hdr = (struct nshhdr *)skb_network_header(skb);
+ version = nsh_get_ver(nsh_hdr);
+ length = nsh_hdr_len(nsh_hdr);
+
+ if (version != 0)
+ return -EINVAL;
+
+ err = check_header(skb, nh_ofs + length);
+ if (unlikely(err))
+ return err;
+
+ nsh_hdr = (struct nshhdr *)skb_network_header(skb);
+ key->nsh.flags = nsh_get_flags(nsh_hdr);
+ key->nsh.ttl = nsh_get_ttl(nsh_hdr);
+ key->nsh.mdtype = nsh_hdr->mdtype;
+ key->nsh.np = nsh_hdr->np;
+ key->nsh.path_hdr = nsh_hdr->path_hdr;
+ switch (key->nsh.mdtype) {
+ case NSH_M_TYPE1:
+ if (length != NSH_M_TYPE1_LEN)
+ return -EINVAL;
+ memcpy(key->nsh.context, nsh_hdr->md1.context,
+ sizeof(nsh_hdr->md1));
+ break;
+ case NSH_M_TYPE2:
+ memset(key->nsh.context, 0,
+ sizeof(nsh_hdr->md1));
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
/**
* key_extract - extracts a flow key from an Ethernet frame.
* @skb: sk_buff that contains the frame, with skb->data pointing to the
@@ -735,6 +782,10 @@ static int key_extract(struct sk_buff *skb, struct sw_flow_key *key)
memset(&key->tp, 0, sizeof(key->tp));
}
}
+ } else if (key->eth.type == htons(ETH_P_NSH)) {
+ error = parse_nsh(skb, key);
+ if (error)
+ return error;
}
return 0;
}
diff --git a/net/openvswitch/flow.h b/net/openvswitch/flow.h
index 1875bba..6a3cd9c 100644
--- a/net/openvswitch/flow.h
+++ b/net/openvswitch/flow.h
@@ -35,6 +35,7 @@
#include <net/inet_ecn.h>
#include <net/ip_tunnels.h>
#include <net/dst_metadata.h>
+#include <net/nsh.h>
struct sk_buff;
@@ -66,6 +67,15 @@ struct vlan_head {
(offsetof(struct sw_flow_key, recirc_id) + \
FIELD_SIZEOF(struct sw_flow_key, recirc_id))
+struct ovs_key_nsh {
+ u8 flags;
+ u8 ttl;
+ u8 mdtype;
+ u8 np;
+ __be32 path_hdr;
+ __be32 context[NSH_MD1_CONTEXT_SIZE];
+};
+
struct sw_flow_key {
u8 tun_opts[IP_TUNNEL_OPTS_MAX];
u8 tun_opts_len;
@@ -144,6 +154,7 @@ struct sw_flow_key {
};
} ipv6;
};
+ struct ovs_key_nsh nsh; /* network service header */
struct {
/* Connection tracking fields not packed above. */
struct {
diff --git a/net/openvswitch/flow_netlink.c b/net/openvswitch/flow_netlink.c
index e8eb427..278bbb3 100644
--- a/net/openvswitch/flow_netlink.c
+++ b/net/openvswitch/flow_netlink.c
@@ -48,6 +48,7 @@
#include <net/ndisc.h>
#include <net/mpls.h>
#include <net/vxlan.h>
+#include <net/tun_proto.h>
#include "flow_netlink.h"
@@ -78,9 +79,11 @@ static bool actions_may_change_flow(const struct nlattr *actions)
case OVS_ACTION_ATTR_HASH:
case OVS_ACTION_ATTR_POP_ETH:
case OVS_ACTION_ATTR_POP_MPLS:
+ case OVS_ACTION_ATTR_POP_NSH:
case OVS_ACTION_ATTR_POP_VLAN:
case OVS_ACTION_ATTR_PUSH_ETH:
case OVS_ACTION_ATTR_PUSH_MPLS:
+ case OVS_ACTION_ATTR_PUSH_NSH:
case OVS_ACTION_ATTR_PUSH_VLAN:
case OVS_ACTION_ATTR_SAMPLE:
case OVS_ACTION_ATTR_SET:
@@ -322,12 +325,27 @@ size_t ovs_tun_key_attr_size(void)
+ nla_total_size(2); /* OVS_TUNNEL_KEY_ATTR_TP_DST */
}
+size_t ovs_nsh_key_attr_size(void)
+{
+ /* Whenever adding new OVS_NSH_KEY_ FIELDS, we should consider
+ * updating this function.
+ */
+ return nla_total_size(NSH_BASE_HDR_LEN) /* OVS_NSH_KEY_ATTR_BASE */
+ /* OVS_NSH_KEY_ATTR_MD1 and OVS_NSH_KEY_ATTR_MD2 are
+ * mutually exclusive, so the bigger one can cover
+ * the small one.
+ *
+ * OVS_NSH_KEY_ATTR_MD2
+ */
+ + nla_total_size(NSH_CTX_HDRS_MAX_LEN);
+}
+
size_t ovs_key_attr_size(void)
{
/* Whenever adding new OVS_KEY_ FIELDS, we should consider
* updating this function.
*/
- BUILD_BUG_ON(OVS_KEY_ATTR_TUNNEL_INFO != 28);
+ BUILD_BUG_ON(OVS_KEY_ATTR_TUNNEL_INFO != 29);
return nla_total_size(4) /* OVS_KEY_ATTR_PRIORITY */
+ nla_total_size(0) /* OVS_KEY_ATTR_TUNNEL */
@@ -341,6 +359,8 @@ size_t ovs_key_attr_size(void)
+ nla_total_size(4) /* OVS_KEY_ATTR_CT_MARK */
+ nla_total_size(16) /* OVS_KEY_ATTR_CT_LABELS */
+ nla_total_size(40) /* OVS_KEY_ATTR_CT_ORIG_TUPLE_IPV6 */
+ + nla_total_size(0) /* OVS_KEY_ATTR_NSH */
+ + ovs_nsh_key_attr_size()
+ nla_total_size(12) /* OVS_KEY_ATTR_ETHERNET */
+ nla_total_size(2) /* OVS_KEY_ATTR_ETHERTYPE */
+ nla_total_size(4) /* OVS_KEY_ATTR_VLAN */
@@ -373,6 +393,13 @@ static const struct ovs_len_tbl ovs_tunnel_key_lens[OVS_TUNNEL_KEY_ATTR_MAX + 1]
[OVS_TUNNEL_KEY_ATTR_IPV6_DST] = { .len = sizeof(struct in6_addr) },
};
+static const struct ovs_len_tbl
+ovs_nsh_key_attr_lens[OVS_NSH_KEY_ATTR_MAX + 1] = {
+ [OVS_NSH_KEY_ATTR_BASE] = { .len = sizeof(struct ovs_nsh_key_base) },
+ [OVS_NSH_KEY_ATTR_MD1] = { .len = sizeof(struct ovs_nsh_key_md1) },
+ [OVS_NSH_KEY_ATTR_MD2] = { .len = OVS_ATTR_VARIABLE },
+};
+
/* The size of the argument for each %OVS_KEY_ATTR_* Netlink attribute. */
static const struct ovs_len_tbl ovs_key_lens[OVS_KEY_ATTR_MAX + 1] = {
[OVS_KEY_ATTR_ENCAP] = { .len = OVS_ATTR_NESTED },
@@ -405,6 +432,8 @@ static const struct ovs_len_tbl ovs_key_lens[OVS_KEY_ATTR_MAX + 1] = {
.len = sizeof(struct ovs_key_ct_tuple_ipv4) },
[OVS_KEY_ATTR_CT_ORIG_TUPLE_IPV6] = {
.len = sizeof(struct ovs_key_ct_tuple_ipv6) },
+ [OVS_KEY_ATTR_NSH] = { .len = OVS_ATTR_NESTED,
+ .next = ovs_nsh_key_attr_lens, },
};
static bool check_attr_len(unsigned int attr_len, unsigned int expected_len)
@@ -1179,6 +1208,222 @@ static int metadata_from_nlattrs(struct net *net, struct sw_flow_match *match,
return 0;
}
+int nsh_hdr_from_nlattr(const struct nlattr *attr,
+ struct nshhdr *nsh, size_t size)
+{
+ struct nlattr *a;
+ int rem;
+ u8 flags = 0;
+ u8 ttl = 0;
+ int mdlen = 0;
+
+ /* validate_nsh has check this, so we needn't do duplicate check here
+ */
+ nla_for_each_nested(a, attr, rem) {
+ int type = nla_type(a);
+
+ switch (type) {
+ case OVS_NSH_KEY_ATTR_BASE: {
+ const struct ovs_nsh_key_base *base =
+ (struct ovs_nsh_key_base *)nla_data(a);
+ flags = base->flags;
+ ttl = base->ttl;
+ nsh->np = base->np;
+ nsh->mdtype = base->mdtype;
+ nsh->path_hdr = base->path_hdr;
+ break;
+ }
+ case OVS_NSH_KEY_ATTR_MD1: {
+ const struct ovs_nsh_key_md1 *md1 =
+ (struct ovs_nsh_key_md1 *)nla_data(a);
+ struct nsh_md1_ctx *md1_dst = &nsh->md1;
+
+ mdlen = nla_len(a);
+ memcpy(md1_dst, md1, mdlen);
+ break;
+ }
+ case OVS_NSH_KEY_ATTR_MD2: {
+ const struct u8 *md2 = nla_data(a);
+ struct nsh_md2_tlv *md2_dst = &nsh->md2;
+
+ mdlen = nla_len(a);
+ memcpy(md2_dst, md2, mdlen);
+ break;
+ }
+ default:
+ return -EINVAL;
+ }
+ }
+
+ /* nsh header length = NSH_BASE_HDR_LEN + mdlen */
+ nsh->ver_flags_ttl_len = 0;
+ nsh_set_flags_ttl_len(nsh, flags, ttl, NSH_BASE_HDR_LEN + mdlen);
+
+ return 0;
+}
+
+int nsh_key_from_nlattr(const struct nlattr *attr,
+ struct ovs_key_nsh *nsh, struct ovs_key_nsh *nsh_mask)
+{
+ struct nlattr *a;
+ int rem;
+
+ /* validate_nsh has check this, so we needn't do duplicate check here
+ */
+ nla_for_each_nested(a, attr, rem) {
+ int type = nla_type(a);
+
+ switch (type) {
+ case OVS_NSH_KEY_ATTR_BASE: {
+ const struct ovs_nsh_key_base *base =
+ (struct ovs_nsh_key_base *)nla_data(a);
+ const struct ovs_nsh_key_base *base_mask = base + 1;
+
+ memcpy(nsh, base, sizeof(*base));
+ memcpy(nsh, base_mask, sizeof(*base_mask));
+ break;
+ }
+ case OVS_NSH_KEY_ATTR_MD1: {
+ const struct ovs_nsh_key_md1 *md1 =
+ (struct ovs_nsh_key_md1 *)nla_data(a);
+ const struct ovs_nsh_key_md1 *md1_mask = md1 + 1;
+
+ memcpy(nsh->context, md1->context, sizeof(*md1));
+ memcpy(nsh_mask->context, md1_mask->context,
+ sizeof(*md1_mask));
+ break;
+ }
+ case OVS_NSH_KEY_ATTR_MD2:
+ /* Not supported yet */
+ return -ENOTSUPP;
+ default:
+ return -EINVAL;
+ }
+ }
+
+ return 0;
+}
+
+static int nsh_key_put_from_nlattr(const struct nlattr *attr,
+ struct sw_flow_match *match, bool is_mask,
+ bool is_push_nsh, bool log)
+{
+ struct nlattr *a;
+ int rem;
+ bool has_base = false;
+ bool has_md1 = false;
+ bool has_md2 = false;
+ u8 mdtype = 0;
+ int mdlen = 0;
+
+ if (unlikely(is_push_nsh && is_mask))
+ return -EINVAL;
+
+ nla_for_each_nested(a, attr, rem) {
+ int type = nla_type(a);
+ int i;
+
+ if (type > OVS_NSH_KEY_ATTR_MAX) {
+ OVS_NLERR(log, "nsh attr %d is out of range max %d",
+ type, OVS_NSH_KEY_ATTR_MAX);
+ return -EINVAL;
+ }
+
+ if (!check_attr_len(nla_len(a),
+ ovs_nsh_key_attr_lens[type].len)) {
+ OVS_NLERR(
+ log,
+ "nsh attr %d has unexpected len %d expected %d",
+ type,
+ nla_len(a),
+ ovs_nsh_key_attr_lens[type].len
+ );
+ return -EINVAL;
+ }
+
+ switch (type) {
+ case OVS_NSH_KEY_ATTR_BASE: {
+ const struct ovs_nsh_key_base *base =
+ (struct ovs_nsh_key_base *)nla_data(a);
+
+ has_base = true;
+ mdtype = base->mdtype;
+ SW_FLOW_KEY_PUT(match, nsh.flags,
+ base->flags, is_mask);
+ SW_FLOW_KEY_PUT(match, nsh.ttl,
+ base->ttl, is_mask);
+ SW_FLOW_KEY_PUT(match, nsh.mdtype,
+ base->mdtype, is_mask);
+ SW_FLOW_KEY_PUT(match, nsh.np,
+ base->np, is_mask);
+ SW_FLOW_KEY_PUT(match, nsh.path_hdr,
+ base->path_hdr, is_mask);
+ break;
+ }
+ case OVS_NSH_KEY_ATTR_MD1: {
+ const struct ovs_nsh_key_md1 *md1 =
+ (struct ovs_nsh_key_md1 *)nla_data(a);
+
+ has_md1 = true;
+ for (i = 0; i < NSH_MD1_CONTEXT_SIZE; i++)
+ SW_FLOW_KEY_PUT(match, nsh.context[i],
+ md1->context[i], is_mask);
+ break;
+ }
+ case OVS_NSH_KEY_ATTR_MD2:
+ if (!is_push_nsh) /* Not supported MD type 2 yet */
+ return -ENOTSUPP;
+
+ has_md2 = true;
+ mdlen = nla_len(a);
+ if ((mdlen > NSH_CTX_HDRS_MAX_LEN) ||
+ (mdlen <= 0)) {
+ WARN_ON_ONCE(1);
+ return -EINVAL;
+ }
+ break;
+ default:
+ OVS_NLERR(log, "Unknown nsh attribute %d",
+ type);
+ return -EINVAL;
+ }
+ }
+
+ if (rem > 0) {
+ OVS_NLERR(log, "nsh attribute has %d unknown bytes.", rem);
+ return -EINVAL;
+ }
+
+ if (has_md1 && has_md2) {
+ OVS_NLERR(
+ 1,
+ "invalid nsh attribute: md1 and md2 are exclusive."
+ );
+ return -EINVAL;
+ }
+
+ if (!is_mask) {
+ if ((has_md1 && mdtype != NSH_M_TYPE1) ||
+ (has_md2 && mdtype != NSH_M_TYPE2)) {
+ OVS_NLERR(1, "nsh attribute has unmatched MD type %d.",
+ mdtype);
+ return -EINVAL;
+ }
+
+ if (is_push_nsh &&
+ (!has_base || (!has_md1 && !has_md2))) {
+ OVS_NLERR(
+ 1,
+ "push nsh attributes are invalid for type %d.",
+ mdtype
+ );
+ return -EINVAL;
+ }
+ }
+
+ return 0;
+}
+
static int ovs_key_from_nlattrs(struct net *net, struct sw_flow_match *match,
u64 attrs, const struct nlattr **a,
bool is_mask, bool log)
@@ -1306,6 +1551,13 @@ static int ovs_key_from_nlattrs(struct net *net, struct sw_flow_match *match,
attrs &= ~(1 << OVS_KEY_ATTR_ARP);
}
+ if (attrs & (1 << OVS_KEY_ATTR_NSH)) {
+ if (nsh_key_put_from_nlattr(a[OVS_KEY_ATTR_NSH], match,
+ is_mask, false, log) < 0)
+ return -EINVAL;
+ attrs &= ~(1 << OVS_KEY_ATTR_NSH);
+ }
+
if (attrs & (1 << OVS_KEY_ATTR_MPLS)) {
const struct ovs_key_mpls *mpls_key;
@@ -1622,6 +1874,40 @@ static int ovs_nla_put_vlan(struct sk_buff *skb, const struct vlan_head *vh,
return 0;
}
+static int nsh_key_to_nlattr(const struct ovs_key_nsh *nsh, bool is_mask,
+ struct sk_buff *skb)
+{
+ struct nlattr *start;
+ struct ovs_nsh_key_base base;
+ struct ovs_nsh_key_md1 md1;
+
+ memcpy(&base, nsh, sizeof(base));
+
+ if (is_mask || nsh->mdtype == NSH_M_TYPE1)
+ memcpy(md1.context, nsh->context, sizeof(md1));
+
+ start = nla_nest_start(skb, OVS_KEY_ATTR_NSH);
+ if (!start)
+ return -EMSGSIZE;
+
+ if (nla_put(skb, OVS_NSH_KEY_ATTR_BASE, sizeof(base), &base))
+ goto nla_put_failure;
+
+ if (is_mask || nsh->mdtype == NSH_M_TYPE1) {
+ if (nla_put(skb, OVS_NSH_KEY_ATTR_MD1, sizeof(md1), &md1))
+ goto nla_put_failure;
+ }
+
+ /* Don't support MD type 2 yet */
+
+ nla_nest_end(skb, start);
+
+ return 0;
+
+nla_put_failure:
+ return -EMSGSIZE;
+}
+
static int __ovs_nla_put_key(const struct sw_flow_key *swkey,
const struct sw_flow_key *output, bool is_mask,
struct sk_buff *skb)
@@ -1750,6 +2036,9 @@ static int __ovs_nla_put_key(const struct sw_flow_key *swkey,
ipv6_key->ipv6_tclass = output->ip.tos;
ipv6_key->ipv6_hlimit = output->ip.ttl;
ipv6_key->ipv6_frag = output->ip.frag;
+ } else if (swkey->eth.type == htons(ETH_P_NSH)) {
+ if (nsh_key_to_nlattr(&output->nsh, is_mask, skb))
+ goto nla_put_failure;
} else if (swkey->eth.type == htons(ETH_P_ARP) ||
swkey->eth.type == htons(ETH_P_RARP)) {
struct ovs_key_arp *arp_key;
@@ -2242,6 +2531,19 @@ static int validate_and_copy_set_tun(const struct nlattr *attr,
return err;
}
+static bool validate_nsh(const struct nlattr *attr, bool is_mask,
+ bool is_push_nsh, bool log)
+{
+ struct sw_flow_match match;
+ struct sw_flow_key key;
+ int ret = 0;
+
+ ovs_match_init(&match, &key, true, NULL);
+ ret = nsh_key_put_from_nlattr(attr, &match, is_mask,
+ is_push_nsh, log);
+ return ((ret != 0) ? false : true);
+}
+
/* Return false if there are any non-masked bits set.
* Mask follows data immediately, before any netlink padding.
*/
@@ -2384,6 +2686,11 @@ static int validate_set(const struct nlattr *a,
break;
+ case OVS_KEY_ATTR_NSH:
+ if (!validate_nsh(nla_data(a), masked, false, log))
+ return -EINVAL;
+ break;
+
default:
return -EINVAL;
}
@@ -2482,6 +2789,8 @@ static int __ovs_nla_copy_actions(struct net *net, const struct nlattr *attr,
[OVS_ACTION_ATTR_TRUNC] = sizeof(struct ovs_action_trunc),
[OVS_ACTION_ATTR_PUSH_ETH] = sizeof(struct ovs_action_push_eth),
[OVS_ACTION_ATTR_POP_ETH] = 0,
+ [OVS_ACTION_ATTR_PUSH_NSH] = (u32)-1,
+ [OVS_ACTION_ATTR_POP_NSH] = 0,
};
const struct ovs_action_push_vlan *vlan;
int type = nla_type(a);
@@ -2636,6 +2945,19 @@ static int __ovs_nla_copy_actions(struct net *net, const struct nlattr *attr,
mac_proto = MAC_PROTO_ETHERNET;
break;
+ case OVS_ACTION_ATTR_PUSH_NSH:
+ mac_proto = MAC_PROTO_NONE;
+ if (!validate_nsh(nla_data(a), false, true, true))
+ return -EINVAL;
+ break;
+
+ case OVS_ACTION_ATTR_POP_NSH:
+ if (key->nsh.np == TUN_P_ETHERNET)
+ mac_proto = MAC_PROTO_ETHERNET;
+ else
+ mac_proto = MAC_PROTO_NONE;
+ break;
+
default:
OVS_NLERR(log, "Unknown Action type %d", type);
return -EINVAL;
diff --git a/net/openvswitch/flow_netlink.h b/net/openvswitch/flow_netlink.h
index 929c665..4b80083 100644
--- a/net/openvswitch/flow_netlink.h
+++ b/net/openvswitch/flow_netlink.h
@@ -79,4 +79,9 @@ int ovs_nla_put_actions(const struct nlattr *attr,
void ovs_nla_free_flow_actions(struct sw_flow_actions *);
void ovs_nla_free_flow_actions_rcu(struct sw_flow_actions *);
+int nsh_key_from_nlattr(const struct nlattr *attr, struct ovs_key_nsh *nsh,
+ struct ovs_key_nsh *nsh_mask);
+int nsh_hdr_from_nlattr(const struct nlattr *attr, struct nshhdr *src_nsh_hdr,
+ size_t size);
+
#endif /* flow_netlink.h */
--
2.5.5
^ permalink raw reply related
* Re: [RFC net-next 0/5] TSN: Add qdisc-based config interfaces for traffic shapers
From: Henrik Austad @ 2017-09-08 6:06 UTC (permalink / raw)
To: Guedes, Andre
Cc: Gomes, Vinicius, jiri@resnulli.us, jhs@mojatatu.com,
Ong, Boon Leong, xiyou.wangcong@gmail.com,
Sanchez-Palencia, Jesus, richardcochran@gmail.com,
netdev@vger.kernel.org, Briano, Ivan,
intel-wired-lan@lists.osuosl.org
In-Reply-To: <1504814332.2117.3.camel@intel.com>
[-- Attachment #1: Type: text/plain, Size: 3863 bytes --]
On Thu, Sep 07, 2017 at 07:58:53PM +0000, Guedes, Andre wrote:
> Hi Henrik,
>
> Thanks for your feedback! I'll address some of your comments below.
>
> On Thu, 2017-09-07 at 07:34 +0200, Henrik Austad wrote:
> > > As for the shapers config interface:
> > >
> > > * CBS (802.1Qav)
> > >
> > > This patchset is proposing a new qdisc called 'cbs'. Its 'tc' cmd line
> > > is:
> > > $ tc qdisc add dev IFACE parent ID cbs locredit N hicredit M sendslope S
> > > \
> > > idleslope I
> >
> > So this confuses me a bit, why specify sendSlope?
> >
> > sendSlope = portTransmitRate - idleSlope
> >
> > and portTransmitRate is the speed of the MAC (which you get from the
> > driver). Adding sendSlope here is just redundant I think.
>
> Yes, this was something we've spent quite a few time discussing before this RFC
> series. After reading the Annex L from 802.1Q-2014 (operation of CBS algorithm)
> so many times, we've came up with the rationale explained below.
>
> The rationale here is that sendSlope is just another parameter from CBS
> algorithm like idleSlope, hiCredit and loCredit. As such, its calculation
> should be done at the same "layer" as the others parameters (in this case, user
> space) in order to keep consistency. Moreover, in this design, the driver layer
> is dead simple: all the device driver has to do is applying CBS parameters to
> hardware. Having any CBS parameter calculation in the driver layer means all
> device drivers must implement that calculation.
Ok, that actually makes a lot of sense, and anything that keeps this kind
of arithmetic outside the kernel is a good thing!
Thanks for the clarification!
> > Also, does this mean that when you create the qdisc, you have locked the
> > bandwidth for the scheduler? Meaning, if I later want to add another
> > stream that requires more bandwidth, I have to close all active streams,
> > reconfigure the qdisc and then restart?
>
> If we want to reserve more bandwidth to "accommodate" a new stream, we don't
> need to close all active streams. All we have to do is changing the CBS qdisc
> and pass the new CBS parameters. Here is what the command-line would look like:
>
> $ tc qdisc change dev enp0s4 parent 8001:5 cbs locredit -1470 hicredit 30
> sendslope -980000 idleslope 20000
>
> No application/stream is interrupted while new CBS parameters are applied.
Ah, good.
> > > Note that the parameters for this qdisc are the ones defined by the
> > > 802.1Q-2014 spec, so no hardware specific functionality is exposed here.
> >
> > You do need to know if the link is brought up as 100 or 1000 though - which
> > the driver already knows.
>
> User space knows that information via ethtool or /sys.
Fair point.
> > > Testing this RFC
> > > ================
> > >
> > > For testing the patches of this RFC only, you can refer to the samples and
> > > helper script being added to samples/tsn/ and the use the 'mqprio' qdisc to
> > > setup the priorities to Tx queues mapping, together with the 'cbs' qdisc to
> > > configure the HW shaper of the i210 controller:
> >
> > I will test it, feedback will be provided soon! :)
>
> That's great! Please let us know if you find any issue and thanks for you
> support.
>
> > > 8) You can also run a Talker for class B (prio 2 here)
> > > $ ./talker -i enp3s0 -p 2
> > >
> > > * The bandwidth displayed on the listener output now should increase to
> > > very
> > > close to the one configured for class A + class B.
> >
> > Because you grab both class A *and* B, or because B will eat what A does
> > not use?
>
> Because the listener application grabs both class A and B traffic.
Right, got it.
Thanks for the feedback, I'm getting really excited about this! :D
--
Henrik Austad
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 181 bytes --]
^ permalink raw reply
* Re: [PATCH net-next v7] openvswitch: enable NSH support
From: Yang, Yi @ 2017-09-08 6:13 UTC (permalink / raw)
To: Jiri Benc
Cc: dev-yBygre7rU0TnMu66kgdUjQ@public.gmane.org,
netdev-u79uwXL29TY76Z2rM5mHXA@public.gmane.org, e@erig.me,
davem-fT/PcQaiUtIeIZ0/mPfg9Q@public.gmane.org
In-Reply-To: <20170831124516.0c5db686@griffin>
On Thu, Aug 31, 2017 at 06:45:16PM +0800, Jiri Benc wrote:
> On Wed, 30 Aug 2017 20:39:12 +0800, Yi Yang wrote:
> > + nsh->md1.context[i] =
> > + OVS_MASKED(nsh->md1.context[i], key->context[i],
> > + mask->context[i]);
> > + }
> > + memcpy(flow_key->nsh.context, nsh->md1.context,
> > + sizeof(nsh->md1.context));
>
> Do you follow the discussion that Hannes Sowa started on the ovs list
> regarding matching on the context fields? It would be better to hold on this
> until there's a conclusion reached.
We had several back-and-forth discussions, Jan was also involved, the
conslusion is current way is still the best way we can have, we need
set and match for context fields.
> > + type,
> > + nla_len(a),
> > + ovs_nsh_key_attr_lens[type].len
> > + );
> > + return -EINVAL;
> > + }
>
> These checks should be done only once when the action is configured, not for
> each packet.
in v8, nsh_key_put_from_nlattr is only one check point, validate_nsh calls it
for set and push_nsh, nsh_hdr_from_nlattr and nsh_key_from_nlattr
haven't these checked anymore because validate_nsh has done them.
> > + if (unlikely(!has_md1 && !has_md2)) {
> > + OVS_NLERR(1, "neither nsh md1 nor md2 attribute is there");
> > + return -EINVAL;
> > + }
>
> Ditto. Plus I don't see a check that the OVS_NSH_KEY_ATTR_BASE attribute is
> present. Seems that the compiler warned you about possibly unitialized flags
> and ttl variables and you just silenced the warning without considering
> whether it's not actually justified.
nsh_key_put_from_nlattr is used for both set and push_nsh, so
OVS_NSH_KEY_ATTR_BASE check is valid only for push_nsh, it is possible
for set not to have OVS_NSH_KEY_ATTR_BASE. v8 has been successfully built
without any warnings, it is also verified in sfc test environment.
I think v8 has fixed all the comments for v7, I have sent out v8 to
mailing list, please help review it, thanks a lot.
^ permalink raw reply
* Re: Re: [PATCH] mm/vmstats: add counters for the page frag cache
From: Kyeongdon Kim @ 2017-09-08 7:11 UTC (permalink / raw)
To: Konstantin Khlebnikov, akpm, sfr
Cc: ying.huang, vbabka, hannes, xieyisheng1, luto, shli, mhocko,
mgorman, hillf.zj, kemi.wang, rientjes, bigeasy, iamjoonsoo.kim,
bongkyu.kim, linux-kernel, linux-mm, netdev
In-Reply-To: <d6120888-344a-4449-4ca6-ac98508bb3cf@yandex-team.ru>
On 2017-09-04 오후 5:30, Konstantin Khlebnikov wrote:
> On 04.09.2017 04:35, Kyeongdon Kim wrote:
> > Thanks for your reply,
> > But I couldn't find "NR_FRAGMENT_PAGES" in linux-next.git .. is that
> vmstat counter? or others?
> >
>
> I mean rather than adding bunch vmstat counters for operations it
> might be
> worth to add page counter which will show current amount of these pages.
> But this seems too low-level for tracking, common counters for all
> network
> buffers would be more useful but much harder to implement.
>
Ok, thanks for the comment.
> As I can see page owner is able to save stacktrace where allocation
> happened,
> this makes debugging mostly trivial without any counters. If it adds
> too much
> overhead - just track random 1% of pages, should be enough for finding
> leak.
>
As I said, we already used page owner tools to resolve the leak issue.
But that's extremely difficult to figure it out,
too much callstack and too much allocation orders(0 or more).
We couldn't easily get a clue event if we track 1% of pages..
In fact, I was writing another email to send a new patch with debug config.
We added a hash function to pick out address with callstack by using
debugfs,
It could be showing the only page_frag_cache leak with owner.
for exmaple code :
+++ /mm/page_alloc.c
@@ -4371,7 +4371,9 @@ void *page_frag_alloc(struct page_frag_cache *nc,
nc->pagecnt_bias--;
nc->offset = offset;
+#ifdef CONFIG_PGFRAG_DEBUG
+ page_frag_debug_alloc(nc->va + offset);
+#endif
return nc->va + offset;
}
EXPORT_SYMBOL(page_frag_alloc);
@@ -4382,7 +4384,9 @@ EXPORT_SYMBOL(page_frag_alloc);
void page_frag_free(void *addr)
{
struct page *page = virt_to_head_page(addr);
+#ifdef CONFIG_PGFRAG_DEBUG
+ page_frag_debug_free(addr);
+#endif
if (unlikely(put_page_testzero(page)))
Those counters that I added may be too much for the linux server or
something.
However, I think the other systems may need to simple debugging method.
(like Android OS)
So if you can accept the patch with debug feature,
I will send it including counters.
but still thinking those counters don't need. I won't.
Anyway, I'm grateful for your feedback, means a lot to me.
Thanks,
Kyeongdon Kim
> > As you know, page_frag_alloc() directly calls
> __alloc_pages_nodemask() function,
> > so that makes too difficult to see memory usage in real time even
> though we have "/meminfo or /slabinfo.." information.
> > If there was a way already to figure out the memory leakage from
> page_frag_cache in mainline, I agree your opinion
> > but I think we don't have it now.
> >
> > If those counters too much in my patch,
> > I can say two values (pgfrag_alloc and pgfrag_free) are enough to
> guess what will happen
> > and would remove pgfrag_alloc_calls and pgfrag_free_calls.
> >
> > Thanks,
> > Kyeongdon Kim
> >
>
> >> IMHO that's too much counters.
> >> Per-node NR_FRAGMENT_PAGES should be enough for guessing what's
> going on.
> >> Perf probes provides enough features for furhter debugging.
> >>
> >> On 01.09.2017 02:37, Kyeongdon Kim wrote:
> >> > There was a memory leak problem when we did stressful test
> >> > on Android device.
> >> > The root cause of this was from page_frag_cache alloc
> >> > and it was very hard to find out.
> >> >
> >> > We add to count the page frag allocation and free with function
> call.
> >> > The gap between pgfrag_alloc and pgfrag_free is good to to calculate
> >> > for the amount of page.
> >> > The gap between pgfrag_alloc_calls and pgfrag_free_calls is for
> >> > sub-indicator.
> >> > They can see trends of memory usage during the test.
> >> > Without it, it's difficult to check page frag usage so I believe we
> >> > should add it.
> >> >
> >> > Signed-off-by: Kyeongdon Kim <kyeongdon.kim@lge.com>
> >> > ---
^ permalink raw reply
* [PATCH v5 00/10] net: stmmac: dwmac-sun8i: Handle integrated PHY
From: Corentin Labbe @ 2017-09-08 7:11 UTC (permalink / raw)
To: robh+dt-DgEjT+Ai2ygdnm+yROfE0A, mark.rutland-5wv7dgnIgG8,
maxime.ripard-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8, wens-jdAy2FN1RRM,
linux-I+IVW8TIWO2tmTQ+vhA3Yw, catalin.marinas-5wv7dgnIgG8,
will.deacon-5wv7dgnIgG8, peppe.cavallaro-qxv4g6HH51o,
alexandre.torgue-qxv4g6HH51o, andrew-g2DYL2Zd6BY,
f.fainelli-Re5JQEeQqe8AvxtiuMwx3w
Cc: netdev-u79uwXL29TY76Z2rM5mHXA, devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
linux-kernel-u79uwXL29TY76Z2rM5mHXA, Corentin Labbe
Hello
The current way to find if the PHY is internal is to compare DT phy-mode
and emac_variant/internal_phy.
But it will negate a possible future SoC where an external PHY use the
same phy mode than the integrated one.
This patchs series adds a new way to find if the PHY is integrated, via
the phy-is-integrated DT property.
Since it exists both integrated and external ethernet-phy@1, they are merged in
the final DTB and so share all properties.
For avoiding this, and better represent the reality, we use a MDIO mux.
The first try was to create a new MDIO mux "mdio-mux-syscon".
mdio-mux-syscon working the same way than mdio-mux-mmioreg with the exception
that the register is used via syscon/regmap.
But this solution does not work for two reason:
- changing the MDIO selection need the reset of MAC which cannot be done by the
mdio-mux-syscon driver
- There were driver loading order problem:
- mdio-mux-syscon needing that stmmac register the parent MDIO
- stmmac needing that child MDIO was registered just after registering parent MDIO
So we cannot use any external MDIO-mux.
The final solution was to represent a mdio-mux and let the MAC handle all things.
Note that phy-is-integrated is still needed (even if we use a MDIO mux) since
some properties apply only on integrated PHY and we need to know the final MDIO
bus in mdio_mux_syscon_switch_fn().
Since DT bits was reverted in 4.13, this patch series include the revert of the revert.
So
- the first four patchs bring back DT/stmmac stuff that was in 4.13 (and reverted)
- fifth patch document how DT MDIO mux is implemented
- patch 6 and 7 modify DT
- patch 8, 9, 10 Modify stmmac according to the new bindings
I have let patch splited for easy review. (for seeing what's new)
But the final serie could have some patch squashed if someone want.
Like squashing patch and 2 and 5 (documentation)
Since DT worked well in 4.13, could it be targeted for 4.14 ?
If necessary I could split this serie in two:
- bring back A64/A83T (patchs 1, 2, 4, 7, 9)
- add MXIO-mux and H3 (patchs 3, 4, 5, 6, 8, 10)
Regards
Changes since v4:
- Update documentation for new bindings
- Added 4 patchs for bring back reverted stuff of 4.13
- dwmac-sun8i now handle mdio-mux
- MDIO use now compatible = "snps,dwmac-mdio";
Changes since v3:
- Added a patch for handling fixed-link
- Updated documentation
Changes since v2:
- Add a MDIO mux for creating distinction between integrated and external MDIO.
- phy-is-integrated is not set in dtsi.
Changes since v1:
- Dropped phy-is-integrated documentation patch since another same patch was already merged
- Moved phy-is-integrated from SoC dtsi to final board DT.
Corentin Labbe (10):
arm64: dts: allwinner: Restore EMAC changes
dt-bindings: net: Restore sun8i dwmac binding
arm: dts: sunxi: Restore EMAC changes
net: stmmac: sun8i: Restore the compatibles
dt-bindings: net: dwmac-sun8i: update documentation about integrated
PHY
ARM: dts: sunxi: h3/h5: represent the mdio switch used by
sun8i-h3-emac
arm64: dts: allwinner: add snps,dwmac-mdio compatible to emac/mdio
net: stmmac: dwmac-sun8i: choose internal PHY via phy-is-integrated
net: stmmac: snps,dwmac-mdio MDIOs are automatically registered
net: stmmac: dwmac-sun8i: Handle integrated/external MDIOs
.../devicetree/bindings/net/dwmac-sun8i.txt | 197 +++++++++++++++++++++
arch/arm/boot/dts/sun8i-h2-plus-orangepi-zero.dts | 9 +
arch/arm/boot/dts/sun8i-h3-bananapi-m2-plus.dts | 19 ++
arch/arm/boot/dts/sun8i-h3-nanopi-neo.dts | 7 +
arch/arm/boot/dts/sun8i-h3-orangepi-2.dts | 8 +
arch/arm/boot/dts/sun8i-h3-orangepi-one.dts | 8 +
arch/arm/boot/dts/sun8i-h3-orangepi-pc-plus.dts | 5 +
arch/arm/boot/dts/sun8i-h3-orangepi-pc.dts | 8 +
arch/arm/boot/dts/sun8i-h3-orangepi-plus.dts | 22 +++
arch/arm/boot/dts/sun8i-h3-orangepi-plus2e.dts | 16 ++
arch/arm/boot/dts/sunxi-h3-h5.dtsi | 46 +++++
.../boot/dts/allwinner/sun50i-a64-bananapi-m64.dts | 16 ++
.../boot/dts/allwinner/sun50i-a64-pine64-plus.dts | 15 ++
.../arm64/boot/dts/allwinner/sun50i-a64-pine64.dts | 17 ++
.../dts/allwinner/sun50i-a64-sopine-baseboard.dts | 16 ++
arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi | 21 +++
.../boot/dts/allwinner/sun50i-h5-nanopi-neo2.dts | 17 ++
.../boot/dts/allwinner/sun50i-h5-orangepi-pc2.dts | 17 ++
.../dts/allwinner/sun50i-h5-orangepi-prime.dts | 17 ++
drivers/net/ethernet/stmicro/stmmac/Kconfig | 1 +
drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c | 140 ++++++++++++---
.../net/ethernet/stmicro/stmmac/stmmac_platform.c | 4 -
22 files changed, 601 insertions(+), 25 deletions(-)
create mode 100644 Documentation/devicetree/bindings/net/dwmac-sun8i.txt
--
2.13.5
--
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
* [PATCH v5 01/10] arm64: dts: allwinner: Restore EMAC changes
From: Corentin Labbe @ 2017-09-08 7:11 UTC (permalink / raw)
To: robh+dt, mark.rutland, maxime.ripard, wens, linux,
catalin.marinas, will.deacon, peppe.cavallaro, alexandre.torgue,
andrew, f.fainelli
Cc: netdev, Corentin Labbe, linux-kernel, linux-arm-kernel,
devicetree
In-Reply-To: <20170908071156.5115-1-clabbe.montjoie@gmail.com>
This patch restore arm64 DT about dwmac-sun8i
This reverts commit 87e1f5e8bb4b ("arm64: dts: allwinner: Revert EMAC changes")
Signed-off-by: Corentin Labbe <clabbe.montjoie@gmail.com>
---
.../boot/dts/allwinner/sun50i-a64-bananapi-m64.dts | 16 ++++++++++++++++
.../boot/dts/allwinner/sun50i-a64-pine64-plus.dts | 15 +++++++++++++++
arch/arm64/boot/dts/allwinner/sun50i-a64-pine64.dts | 17 +++++++++++++++++
.../dts/allwinner/sun50i-a64-sopine-baseboard.dts | 16 ++++++++++++++++
arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi | 20 ++++++++++++++++++++
.../boot/dts/allwinner/sun50i-h5-nanopi-neo2.dts | 17 +++++++++++++++++
.../boot/dts/allwinner/sun50i-h5-orangepi-pc2.dts | 17 +++++++++++++++++
.../boot/dts/allwinner/sun50i-h5-orangepi-prime.dts | 17 +++++++++++++++++
8 files changed, 135 insertions(+)
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64-bananapi-m64.dts b/arch/arm64/boot/dts/allwinner/sun50i-a64-bananapi-m64.dts
index d347f52e27f6..45bdbfb96126 100644
--- a/arch/arm64/boot/dts/allwinner/sun50i-a64-bananapi-m64.dts
+++ b/arch/arm64/boot/dts/allwinner/sun50i-a64-bananapi-m64.dts
@@ -51,6 +51,7 @@
compatible = "sinovoip,bananapi-m64", "allwinner,sun50i-a64";
aliases {
+ ethernet0 = &emac;
serial0 = &uart0;
serial1 = &uart1;
};
@@ -69,6 +70,14 @@
status = "okay";
};
+&emac {
+ pinctrl-names = "default";
+ pinctrl-0 = <&rgmii_pins>;
+ phy-mode = "rgmii";
+ phy-handle = <&ext_rgmii_phy>;
+ status = "okay";
+};
+
&i2c1 {
pinctrl-names = "default";
pinctrl-0 = <&i2c1_pins>;
@@ -79,6 +88,13 @@
bias-pull-up;
};
+&mdio {
+ ext_rgmii_phy: ethernet-phy@1 {
+ compatible = "ethernet-phy-ieee802.3-c22";
+ reg = <1>;
+ };
+};
+
&mmc0 {
pinctrl-names = "default";
pinctrl-0 = <&mmc0_pins>;
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64-pine64-plus.dts b/arch/arm64/boot/dts/allwinner/sun50i-a64-pine64-plus.dts
index f82ccf332c0f..24f1aac366d6 100644
--- a/arch/arm64/boot/dts/allwinner/sun50i-a64-pine64-plus.dts
+++ b/arch/arm64/boot/dts/allwinner/sun50i-a64-pine64-plus.dts
@@ -48,3 +48,18 @@
/* TODO: Camera, touchscreen, etc. */
};
+
+&emac {
+ pinctrl-names = "default";
+ pinctrl-0 = <&rgmii_pins>;
+ phy-mode = "rgmii";
+ phy-handle = <&ext_rgmii_phy>;
+ status = "okay";
+};
+
+&mdio {
+ ext_rgmii_phy: ethernet-phy@1 {
+ compatible = "ethernet-phy-ieee802.3-c22";
+ reg = <1>;
+ };
+};
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64-pine64.dts b/arch/arm64/boot/dts/allwinner/sun50i-a64-pine64.dts
index caf8b6fbe5e3..6f209bb10a2f 100644
--- a/arch/arm64/boot/dts/allwinner/sun50i-a64-pine64.dts
+++ b/arch/arm64/boot/dts/allwinner/sun50i-a64-pine64.dts
@@ -51,6 +51,7 @@
compatible = "pine64,pine64", "allwinner,sun50i-a64";
aliases {
+ ethernet0 = &emac;
serial0 = &uart0;
serial1 = &uart1;
serial2 = &uart2;
@@ -78,6 +79,15 @@
status = "okay";
};
+&emac {
+ pinctrl-names = "default";
+ pinctrl-0 = <&rmii_pins>;
+ phy-mode = "rmii";
+ phy-handle = <&ext_rmii_phy1>;
+ status = "okay";
+
+};
+
&i2c1 {
pinctrl-names = "default";
pinctrl-0 = <&i2c1_pins>;
@@ -88,6 +98,13 @@
bias-pull-up;
};
+&mdio {
+ ext_rmii_phy1: ethernet-phy@1 {
+ compatible = "ethernet-phy-ieee802.3-c22";
+ reg = <1>;
+ };
+};
+
&mmc0 {
pinctrl-names = "default";
pinctrl-0 = <&mmc0_pins>;
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64-sopine-baseboard.dts b/arch/arm64/boot/dts/allwinner/sun50i-a64-sopine-baseboard.dts
index 17ccc12b58df..0eb2acedf8c3 100644
--- a/arch/arm64/boot/dts/allwinner/sun50i-a64-sopine-baseboard.dts
+++ b/arch/arm64/boot/dts/allwinner/sun50i-a64-sopine-baseboard.dts
@@ -53,6 +53,7 @@
"allwinner,sun50i-a64";
aliases {
+ ethernet0 = &emac;
serial0 = &uart0;
};
@@ -76,6 +77,21 @@
status = "okay";
};
+&emac {
+ pinctrl-names = "default";
+ pinctrl-0 = <&rgmii_pins>;
+ phy-mode = "rgmii";
+ phy-handle = <&ext_rgmii_phy>;
+ status = "okay";
+};
+
+&mdio {
+ ext_rgmii_phy: ethernet-phy@1 {
+ compatible = "ethernet-phy-ieee802.3-c22";
+ reg = <1>;
+ };
+};
+
&mmc2 {
pinctrl-names = "default";
pinctrl-0 = <&mmc2_pins>;
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi
index 75e8d3182535..4dd9ffef0d80 100644
--- a/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi
+++ b/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi
@@ -461,6 +461,26 @@
#size-cells = <0>;
};
+ emac: ethernet@1c30000 {
+ compatible = "allwinner,sun50i-a64-emac";
+ syscon = <&syscon>;
+ reg = <0x01c30000 0x10000>;
+ interrupts = <GIC_SPI 82 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "macirq";
+ resets = <&ccu RST_BUS_EMAC>;
+ reset-names = "stmmaceth";
+ clocks = <&ccu CLK_BUS_EMAC>;
+ clock-names = "stmmaceth";
+ status = "disabled";
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ mdio: mdio {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+ };
+
gic: interrupt-controller@1c81000 {
compatible = "arm,gic-400";
reg = <0x01c81000 0x1000>,
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h5-nanopi-neo2.dts b/arch/arm64/boot/dts/allwinner/sun50i-h5-nanopi-neo2.dts
index 1c2387bd5df6..968908761194 100644
--- a/arch/arm64/boot/dts/allwinner/sun50i-h5-nanopi-neo2.dts
+++ b/arch/arm64/boot/dts/allwinner/sun50i-h5-nanopi-neo2.dts
@@ -50,6 +50,7 @@
compatible = "friendlyarm,nanopi-neo2", "allwinner,sun50i-h5";
aliases {
+ ethernet0 = &emac;
serial0 = &uart0;
};
@@ -108,6 +109,22 @@
status = "okay";
};
+&emac {
+ pinctrl-names = "default";
+ pinctrl-0 = <&emac_rgmii_pins>;
+ phy-supply = <®_gmac_3v3>;
+ phy-handle = <&ext_rgmii_phy>;
+ phy-mode = "rgmii";
+ status = "okay";
+};
+
+&mdio {
+ ext_rgmii_phy: ethernet-phy@7 {
+ compatible = "ethernet-phy-ieee802.3-c22";
+ reg = <7>;
+ };
+};
+
&mmc0 {
pinctrl-names = "default";
pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin>;
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h5-orangepi-pc2.dts b/arch/arm64/boot/dts/allwinner/sun50i-h5-orangepi-pc2.dts
index 4f77c8470f6c..a8296feee884 100644
--- a/arch/arm64/boot/dts/allwinner/sun50i-h5-orangepi-pc2.dts
+++ b/arch/arm64/boot/dts/allwinner/sun50i-h5-orangepi-pc2.dts
@@ -59,6 +59,7 @@
};
aliases {
+ ethernet0 = &emac;
serial0 = &uart0;
};
@@ -136,12 +137,28 @@
status = "okay";
};
+&emac {
+ pinctrl-names = "default";
+ pinctrl-0 = <&emac_rgmii_pins>;
+ phy-supply = <®_gmac_3v3>;
+ phy-handle = <&ext_rgmii_phy>;
+ phy-mode = "rgmii";
+ status = "okay";
+};
+
&ir {
pinctrl-names = "default";
pinctrl-0 = <&ir_pins_a>;
status = "okay";
};
+&mdio {
+ ext_rgmii_phy: ethernet-phy@1 {
+ compatible = "ethernet-phy-ieee802.3-c22";
+ reg = <1>;
+ };
+};
+
&mmc0 {
pinctrl-names = "default";
pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin>;
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h5-orangepi-prime.dts b/arch/arm64/boot/dts/allwinner/sun50i-h5-orangepi-prime.dts
index 6be06873e5af..d906b302cbcd 100644
--- a/arch/arm64/boot/dts/allwinner/sun50i-h5-orangepi-prime.dts
+++ b/arch/arm64/boot/dts/allwinner/sun50i-h5-orangepi-prime.dts
@@ -54,6 +54,7 @@
compatible = "xunlong,orangepi-prime", "allwinner,sun50i-h5";
aliases {
+ ethernet0 = &emac;
serial0 = &uart0;
};
@@ -143,12 +144,28 @@
status = "okay";
};
+&emac {
+ pinctrl-names = "default";
+ pinctrl-0 = <&emac_rgmii_pins>;
+ phy-supply = <®_gmac_3v3>;
+ phy-handle = <&ext_rgmii_phy>;
+ phy-mode = "rgmii";
+ status = "okay";
+};
+
&ir {
pinctrl-names = "default";
pinctrl-0 = <&ir_pins_a>;
status = "okay";
};
+&mdio {
+ ext_rgmii_phy: ethernet-phy@1 {
+ compatible = "ethernet-phy-ieee802.3-c22";
+ reg = <1>;
+ };
+};
+
&mmc0 {
pinctrl-names = "default";
pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin>;
--
2.13.5
^ permalink raw reply related
* [PATCH v5 02/10] dt-bindings: net: Restore sun8i dwmac binding
From: Corentin Labbe @ 2017-09-08 7:11 UTC (permalink / raw)
To: robh+dt, mark.rutland, maxime.ripard, wens, linux,
catalin.marinas, will.deacon, peppe.cavallaro, alexandre.torgue,
andrew, f.fainelli
Cc: netdev, devicetree, linux-arm-kernel, linux-kernel,
Corentin Labbe
In-Reply-To: <20170908071156.5115-1-clabbe.montjoie@gmail.com>
This patch restore dt-bindings documentation about dwmac-sun8i
This reverts commit 8aa33ec2f481 ("dt-bindings: net: Revert sun8i dwmac binding")
Signed-off-by: Corentin Labbe <clabbe.montjoie@gmail.com>
---
.../devicetree/bindings/net/dwmac-sun8i.txt | 84 ++++++++++++++++++++++
1 file changed, 84 insertions(+)
create mode 100644 Documentation/devicetree/bindings/net/dwmac-sun8i.txt
diff --git a/Documentation/devicetree/bindings/net/dwmac-sun8i.txt b/Documentation/devicetree/bindings/net/dwmac-sun8i.txt
new file mode 100644
index 000000000000..725f3b187886
--- /dev/null
+++ b/Documentation/devicetree/bindings/net/dwmac-sun8i.txt
@@ -0,0 +1,84 @@
+* Allwinner sun8i GMAC ethernet controller
+
+This device is a platform glue layer for stmmac.
+Please see stmmac.txt for the other unchanged properties.
+
+Required properties:
+- compatible: should be one of the following string:
+ "allwinner,sun8i-a83t-emac"
+ "allwinner,sun8i-h3-emac"
+ "allwinner,sun8i-v3s-emac"
+ "allwinner,sun50i-a64-emac"
+- reg: address and length of the register for the device.
+- interrupts: interrupt for the device
+- interrupt-names: should be "macirq"
+- clocks: A phandle to the reference clock for this device
+- clock-names: should be "stmmaceth"
+- resets: A phandle to the reset control for this device
+- reset-names: should be "stmmaceth"
+- phy-mode: See ethernet.txt
+- phy-handle: See ethernet.txt
+- #address-cells: shall be 1
+- #size-cells: shall be 0
+- syscon: A phandle to the syscon of the SoC with one of the following
+ compatible string:
+ - allwinner,sun8i-h3-system-controller
+ - allwinner,sun8i-v3s-system-controller
+ - allwinner,sun50i-a64-system-controller
+ - allwinner,sun8i-a83t-system-controller
+
+Optional properties:
+- allwinner,tx-delay-ps: TX clock delay chain value in ps. Range value is 0-700. Default is 0)
+- allwinner,rx-delay-ps: RX clock delay chain value in ps. Range value is 0-3100. Default is 0)
+Both delay properties need to be a multiple of 100. They control the delay for
+external PHY.
+
+Optional properties for the following compatibles:
+ - "allwinner,sun8i-h3-emac",
+ - "allwinner,sun8i-v3s-emac":
+- allwinner,leds-active-low: EPHY LEDs are active low
+
+Required child node of emac:
+- mdio bus node: should be named mdio
+
+Required properties of the mdio node:
+- #address-cells: shall be 1
+- #size-cells: shall be 0
+
+The device node referenced by "phy" or "phy-handle" should be a child node
+of the mdio node. See phy.txt for the generic PHY bindings.
+
+Required properties of the phy node with the following compatibles:
+ - "allwinner,sun8i-h3-emac",
+ - "allwinner,sun8i-v3s-emac":
+- clocks: a phandle to the reference clock for the EPHY
+- resets: a phandle to the reset control for the EPHY
+
+Example:
+
+emac: ethernet@1c0b000 {
+ compatible = "allwinner,sun8i-h3-emac";
+ syscon = <&syscon>;
+ reg = <0x01c0b000 0x104>;
+ interrupts = <GIC_SPI 82 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "macirq";
+ resets = <&ccu RST_BUS_EMAC>;
+ reset-names = "stmmaceth";
+ clocks = <&ccu CLK_BUS_EMAC>;
+ clock-names = "stmmaceth";
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ phy-handle = <&int_mii_phy>;
+ phy-mode = "mii";
+ allwinner,leds-active-low;
+ mdio: mdio {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ int_mii_phy: ethernet-phy@1 {
+ reg = <1>;
+ clocks = <&ccu CLK_BUS_EPHY>;
+ resets = <&ccu RST_BUS_EPHY>;
+ };
+ };
+};
--
2.13.5
^ permalink raw reply related
* [PATCH v5 04/10] net: stmmac: sun8i: Restore the compatibles
From: Corentin Labbe @ 2017-09-08 7:11 UTC (permalink / raw)
To: robh+dt-DgEjT+Ai2ygdnm+yROfE0A, mark.rutland-5wv7dgnIgG8,
maxime.ripard-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8, wens-jdAy2FN1RRM,
linux-I+IVW8TIWO2tmTQ+vhA3Yw, catalin.marinas-5wv7dgnIgG8,
will.deacon-5wv7dgnIgG8, peppe.cavallaro-qxv4g6HH51o,
alexandre.torgue-qxv4g6HH51o, andrew-g2DYL2Zd6BY,
f.fainelli-Re5JQEeQqe8AvxtiuMwx3w
Cc: netdev-u79uwXL29TY76Z2rM5mHXA, devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
linux-kernel-u79uwXL29TY76Z2rM5mHXA, Corentin Labbe
In-Reply-To: <20170908071156.5115-1-clabbe.montjoie-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
This patch restore compatibles about dwmac-sun8i
This reverts commit ad4540cc5aa3 ("net: stmmac: sun8i: Remove the compatibles")
Signed-off-by: Corentin Labbe <clabbe.montjoie-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
---
drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c
index 39c2122a4f26..fffd6d5fc907 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c
@@ -979,6 +979,14 @@ static int sun8i_dwmac_probe(struct platform_device *pdev)
}
static const struct of_device_id sun8i_dwmac_match[] = {
+ { .compatible = "allwinner,sun8i-h3-emac",
+ .data = &emac_variant_h3 },
+ { .compatible = "allwinner,sun8i-v3s-emac",
+ .data = &emac_variant_v3s },
+ { .compatible = "allwinner,sun8i-a83t-emac",
+ .data = &emac_variant_a83t },
+ { .compatible = "allwinner,sun50i-a64-emac",
+ .data = &emac_variant_a64 },
{ }
};
MODULE_DEVICE_TABLE(of, sun8i_dwmac_match);
--
2.13.5
--
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 v5 05/10] dt-bindings: net: dwmac-sun8i: update documentation about integrated PHY
From: Corentin Labbe @ 2017-09-08 7:11 UTC (permalink / raw)
To: robh+dt, mark.rutland, maxime.ripard, wens, linux,
catalin.marinas, will.deacon, peppe.cavallaro, alexandre.torgue,
andrew, f.fainelli
Cc: netdev, devicetree, linux-arm-kernel, linux-kernel,
Corentin Labbe
In-Reply-To: <20170908071156.5115-1-clabbe.montjoie@gmail.com>
This patch add documentation about the MDIO switch used on sun8i-h3-emac
for integrated PHY.
Signed-off-by: Corentin Labbe <clabbe.montjoie@gmail.com>
---
.../devicetree/bindings/net/dwmac-sun8i.txt | 127 +++++++++++++++++++--
1 file changed, 120 insertions(+), 7 deletions(-)
diff --git a/Documentation/devicetree/bindings/net/dwmac-sun8i.txt b/Documentation/devicetree/bindings/net/dwmac-sun8i.txt
index 725f3b187886..3fa0e54825ea 100644
--- a/Documentation/devicetree/bindings/net/dwmac-sun8i.txt
+++ b/Documentation/devicetree/bindings/net/dwmac-sun8i.txt
@@ -39,7 +39,7 @@ Optional properties for the following compatibles:
- allwinner,leds-active-low: EPHY LEDs are active low
Required child node of emac:
-- mdio bus node: should be named mdio
+- mdio bus node: should be labelled mdio
Required properties of the mdio node:
- #address-cells: shall be 1
@@ -48,14 +48,28 @@ Required properties of the mdio node:
The device node referenced by "phy" or "phy-handle" should be a child node
of the mdio node. See phy.txt for the generic PHY bindings.
-Required properties of the phy node with the following compatibles:
+The following compatibles require an mdio-mux node called "mdio-mux":
+ - "allwinner,sun8i-h3-emac"
+ - "allwinner,sun8i-v3s-emac":
+Required properties for the mdio-mux node:
+ - compatible = "mdio-mux"
+ - one child mdio for the integrated mdio
+ - one child mdio for the external mdio if present (V3s have none)
+Required properties for the mdio-mux children node:
+ - reg: 0 for internal MDIO bus, 1 for external MDIO bus
+
+The following compatibles require a PHY node representing the integrated
+PHY, under the integrated MDIO bus node if an mdio-mux node is used:
- "allwinner,sun8i-h3-emac",
- "allwinner,sun8i-v3s-emac":
+
+Required properties of the integrated phy node:
- clocks: a phandle to the reference clock for the EPHY
- resets: a phandle to the reset control for the EPHY
+- phy-is-integrated
+- Should be a child of the integrated mdio
-Example:
-
+Example with integrated PHY:
emac: ethernet@1c0b000 {
compatible = "allwinner,sun8i-h3-emac";
syscon = <&syscon>;
@@ -72,13 +86,112 @@ emac: ethernet@1c0b000 {
phy-handle = <&int_mii_phy>;
phy-mode = "mii";
allwinner,leds-active-low;
+
+ mdio0: mdio {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "snps,dwmac-mdio";
+ };
+
+ mdio-mux {
+ compatible = "mdio-mux";
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ int_mdio: mdio@1 {
+ reg = <0>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ int_mii_phy: ethernet-phy@1 {
+ reg = <1>;
+ clocks = <&ccu CLK_BUS_EPHY>;
+ resets = <&ccu RST_BUS_EPHY>;
+ phy-is-integrated
+ };
+ };
+ ext_mdio: mdio@0 {
+ reg = <1>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+ };
+};
+
+Example with external PHY:
+emac: ethernet@1c0b000 {
+ compatible = "allwinner,sun8i-h3-emac";
+ syscon = <&syscon>;
+ reg = <0x01c0b000 0x104>;
+ interrupts = <GIC_SPI 82 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "macirq";
+ resets = <&ccu RST_BUS_EMAC>;
+ reset-names = "stmmaceth";
+ clocks = <&ccu CLK_BUS_EMAC>;
+ clock-names = "stmmaceth";
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ phy-handle = <&ext_rgmii_phy>;
+ phy-mode = "rgmii";
+ allwinner,leds-active-low;
+
+ mdio0: mdio {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "snps,dwmac-mdio";
+ };
+
+ mdio-mux {
+ compatible = "mdio-mux";
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ int_mdio: mdio@1 {
+ reg = <0>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ int_mii_phy: ethernet-phy@1 {
+ reg = <1>;
+ clocks = <&ccu CLK_BUS_EPHY>;
+ resets = <&ccu RST_BUS_EPHY>;
+ phy-is-integrated
+ };
+ };
+ ext_mdio: mdio@0 {
+ reg = <1>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ ext_rgmii_phy: ethernet-phy@1 {
+ reg = <1>;
+ };
+ };
+ };
+};
+
+Example with SoC without integrated PHY
+
+emac: ethernet@1c0b000 {
+ compatible = "allwinner,sun8i-a83t-emac";
+ syscon = <&syscon>;
+ reg = <0x01c0b000 0x104>;
+ interrupts = <GIC_SPI 82 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "macirq";
+ resets = <&ccu RST_BUS_EMAC>;
+ reset-names = "stmmaceth";
+ clocks = <&ccu CLK_BUS_EMAC>;
+ clock-names = "stmmaceth";
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ phy-handle = <&ext_rgmii_phy>;
+ phy-mode = "rgmii";
+
mdio: mdio {
+ compatible = "snps,dwmac-mdio";
#address-cells = <1>;
#size-cells = <0>;
- int_mii_phy: ethernet-phy@1 {
+ ext_rgmii_phy: ethernet-phy@1 {
reg = <1>;
- clocks = <&ccu CLK_BUS_EPHY>;
- resets = <&ccu RST_BUS_EPHY>;
};
};
};
--
2.13.5
^ permalink raw reply related
* [PATCH v5 06/10] ARM: dts: sunxi: h3/h5: represent the mdio switch used by sun8i-h3-emac
From: Corentin Labbe @ 2017-09-08 7:11 UTC (permalink / raw)
To: robh+dt, mark.rutland, maxime.ripard, wens, linux,
catalin.marinas, will.deacon, peppe.cavallaro, alexandre.torgue,
andrew, f.fainelli
Cc: netdev, devicetree, linux-arm-kernel, linux-kernel,
Corentin Labbe
In-Reply-To: <20170908071156.5115-1-clabbe.montjoie@gmail.com>
Since dwmac-sun8i could use either an integrated PHY or an external PHY
(which could be at same MDIO address), we need to represent this selection
by a MDIO switch.
Signed-off-by: Corentin Labbe <clabbe.montjoie@gmail.com>
---
arch/arm/boot/dts/sunxi-h3-h5.dtsi | 30 +++++++++++++++++++++++++-----
1 file changed, 25 insertions(+), 5 deletions(-)
diff --git a/arch/arm/boot/dts/sunxi-h3-h5.dtsi b/arch/arm/boot/dts/sunxi-h3-h5.dtsi
index 4b599b5d26f6..e137377b312d 100644
--- a/arch/arm/boot/dts/sunxi-h3-h5.dtsi
+++ b/arch/arm/boot/dts/sunxi-h3-h5.dtsi
@@ -417,14 +417,34 @@
#size-cells = <0>;
status = "disabled";
- mdio: mdio {
+ mdio0: mdio {
#address-cells = <1>;
#size-cells = <0>;
- int_mii_phy: ethernet-phy@1 {
- compatible = "ethernet-phy-ieee802.3-c22";
+ compatible = "snps,dwmac-mdio";
+ };
+
+ mdio-mux {
+ compatible = "mdio-mux";
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ /* Only one MDIO is usable at the time */
+ internal_mdio: mdio@1 {
+ reg = <0>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ int_mii_phy: ethernet-phy@1 {
+ compatible = "ethernet-phy-ieee802.3-c22";
+ reg = <1>;
+ clocks = <&ccu CLK_BUS_EPHY>;
+ resets = <&ccu RST_BUS_EPHY>;
+ phy-is-integrated;
+ };
+ };
+ mdio: mdio@0 {
reg = <1>;
- clocks = <&ccu CLK_BUS_EPHY>;
- resets = <&ccu RST_BUS_EPHY>;
+ #address-cells = <1>;
+ #size-cells = <0>;
};
};
};
--
2.13.5
^ permalink raw reply related
* [PATCH v5 07/10] arm64: dts: allwinner: add snps,dwmac-mdio compatible to emac/mdio
From: Corentin Labbe @ 2017-09-08 7:11 UTC (permalink / raw)
To: robh+dt, mark.rutland, maxime.ripard, wens, linux,
catalin.marinas, will.deacon, peppe.cavallaro, alexandre.torgue,
andrew, f.fainelli
Cc: netdev, devicetree, linux-arm-kernel, linux-kernel,
Corentin Labbe
In-Reply-To: <20170908071156.5115-1-clabbe.montjoie@gmail.com>
stmmac bindings docs said that its mdio node must have
compatible = "snps,dwmac-mdio";
Since dwmac-sun8i does not have any good reasons to not doing it, all
their MDIO node must have it.
Signed-off-by: Corentin Labbe <clabbe.montjoie@gmail.com>
---
arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi | 1 +
1 file changed, 1 insertion(+)
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi
index 4dd9ffef0d80..5dceebd81f09 100644
--- a/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi
+++ b/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi
@@ -476,6 +476,7 @@
#size-cells = <0>;
mdio: mdio {
+ compatible = "snps,dwmac-mdio";
#address-cells = <1>;
#size-cells = <0>;
};
--
2.13.5
^ permalink raw reply related
* [PATCH v5 08/10] net: stmmac: dwmac-sun8i: choose internal PHY via phy-is-integrated
From: Corentin Labbe @ 2017-09-08 7:11 UTC (permalink / raw)
To: robh+dt, mark.rutland, maxime.ripard, wens, linux,
catalin.marinas, will.deacon, peppe.cavallaro, alexandre.torgue,
andrew, f.fainelli
Cc: netdev, devicetree, linux-arm-kernel, linux-kernel,
Corentin Labbe
In-Reply-To: <20170908071156.5115-1-clabbe.montjoie@gmail.com>
The current way to find if the phy is internal is to compare DT phy-mode
and emac_variant/internal_phy.
But it will negate a possible future SoC where an external PHY use the
same phy mode than the internal one.
This patch adds a new way to find if the PHY is internal, via
the phy-is-integrated property.
Since the internal_phy variable does not need anymore to contain the xMII mode
used by the internal PHY, it is still used for knowing the presence of an
internal PHY, so it is modified to a boolean soc_has_internal_phy.
Signed-off-by: Corentin Labbe <clabbe.montjoie@gmail.com>
Acked-by: Chen-Yu Tsai <wens@csie.org>
Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
---
drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c | 16 ++++++++--------
1 file changed, 8 insertions(+), 8 deletions(-)
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c
index fffd6d5fc907..672553b652bd 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c
@@ -41,14 +41,14 @@
* This value is used for disabling properly EMAC
* and used as a good starting value in case of the
* boot process(uboot) leave some stuff.
- * @internal_phy: Does the MAC embed an internal PHY
+ * @soc_has_internal_phy: Does the MAC embed an internal PHY
* @support_mii: Does the MAC handle MII
* @support_rmii: Does the MAC handle RMII
* @support_rgmii: Does the MAC handle RGMII
*/
struct emac_variant {
u32 default_syscon_value;
- int internal_phy;
+ bool soc_has_internal_phy;
bool support_mii;
bool support_rmii;
bool support_rgmii;
@@ -75,7 +75,7 @@ struct sunxi_priv_data {
static const struct emac_variant emac_variant_h3 = {
.default_syscon_value = 0x58000,
- .internal_phy = PHY_INTERFACE_MODE_MII,
+ .soc_has_internal_phy = true,
.support_mii = true,
.support_rmii = true,
.support_rgmii = true
@@ -83,20 +83,20 @@ static const struct emac_variant emac_variant_h3 = {
static const struct emac_variant emac_variant_v3s = {
.default_syscon_value = 0x38000,
- .internal_phy = PHY_INTERFACE_MODE_MII,
+ .soc_has_internal_phy = true,
.support_mii = true
};
static const struct emac_variant emac_variant_a83t = {
.default_syscon_value = 0,
- .internal_phy = 0,
+ .soc_has_internal_phy = false,
.support_mii = true,
.support_rgmii = true
};
static const struct emac_variant emac_variant_a64 = {
.default_syscon_value = 0,
- .internal_phy = 0,
+ .soc_has_internal_phy = false,
.support_mii = true,
.support_rmii = true,
.support_rgmii = true
@@ -648,7 +648,7 @@ static int sun8i_dwmac_set_syscon(struct stmmac_priv *priv)
"Current syscon value is not the default %x (expect %x)\n",
val, reg);
- if (gmac->variant->internal_phy) {
+ if (gmac->variant->soc_has_internal_phy) {
if (!gmac->use_internal_phy) {
/* switch to external PHY interface */
reg &= ~H3_EPHY_SELECT;
@@ -932,7 +932,7 @@ static int sun8i_dwmac_probe(struct platform_device *pdev)
}
plat_dat->interface = of_get_phy_mode(dev->of_node);
- if (plat_dat->interface == gmac->variant->internal_phy) {
+ if (of_property_read_bool(plat_dat->phy_node, "phy-is-integrated")) {
dev_info(&pdev->dev, "Will use internal PHY\n");
gmac->use_internal_phy = true;
gmac->ephy_clk = of_clk_get(plat_dat->phy_node, 0);
--
2.13.5
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox