* Re: [PATCH bpf] bpf: Fix integer overflow in queue_stack_map_alloc.
From: Greg KH @ 2018-11-22 16:04 UTC (permalink / raw)
To: Wei Wu; +Cc: Alexei Starovoitov, Daniel Borkmann, netdev, Eric Dumazet
In-Reply-To: <CACmwppz=P2h-uM2OTc2CvnDg_Qgfhtk5-vzk0Jge1SAi2sym+A@mail.gmail.com>
On Thu, Nov 22, 2018 at 11:59:02PM +0800, Wei Wu wrote:
> Integer overflow in queue_stack_map_alloc when calculating size may
> lead to heap overflow of arbitrary length.
> The patch fix it by checking whether attr->max_entries+1 <
> attr->max_entries and bailing out if it is the case.
> The vulnerability is discovered with the assistance of syzkaller.
>
> Reported-by: Wei Wu <ww9210@gmail.com>
> To: Alexei Starovoitov <ast@kernel.org>
> Cc: Daniel Borkmann <daniel@iogearbox.net>
> Cc: netdev <netdev@vger.kernel.org>
> Cc: Eric Dumazet <edumazet@google.com>
> Cc: Greg KH <greg@kroah.com>
> Signed-off-by: Wei Wu <ww9210@gmail.com>
> ---
> kernel/bpf/queue_stack_maps.c | 2 ++
> 1 file changed, 2 insertions(+)
>
> diff --git a/kernel/bpf/queue_stack_maps.c b/kernel/bpf/queue_stack_maps.c
> index 8bbd72d3a121..c35a8a4721c8 100644
> --- a/kernel/bpf/queue_stack_maps.c
> +++ b/kernel/bpf/queue_stack_maps.c
> @@ -67,6 +67,8 @@ static struct bpf_map *queue_stack_map_alloc(union
> bpf_attr *attr)
> u64 queue_size, cost;
>
> size = attr->max_entries + 1;
> + if (size < attr->max_entries)
> + return ERR_PTR(-EINVAL);
> value_size = attr->value_size;
Your tabs got eaten by your email client and they all disappeared,
making the patch impossible to apply :(
Care to try again?
thanks,
greg k-h
^ permalink raw reply
* Re: [PATCH net-next 2/2] net: bridge: add no_linklocal_learn bool option
From: Andrew Lunn @ 2018-11-22 16:04 UTC (permalink / raw)
To: Nikolay Aleksandrov; +Cc: netdev, roopa, davem, bridge
In-Reply-To: <20181122042925.8878-3-nikolay@cumulusnetworks.com>
> int br_boolopt_get(const struct net_bridge *br, enum br_boolopt_id opt)
> {
> - int optval = 0;
> -
> switch (opt) {
> + case BR_BOOLOPT_NO_LL_LEARN:
> + return br_opt_get(br, BROPT_NO_LL_LEARN);
> default:
> break;
> }
>
> - return optval;
> + return 0;
> }
It seems like 1/2 of that change belongs in the previous patch.
> --- a/net/bridge/br_sysfs_br.c
> +++ b/net/bridge/br_sysfs_br.c
> @@ -328,6 +328,27 @@ static ssize_t flush_store(struct device *d,
> }
> static DEVICE_ATTR_WO(flush);
>
> +static ssize_t no_linklocal_learn_show(struct device *d,
> + struct device_attribute *attr,
> + char *buf)
> +{
> + struct net_bridge *br = to_bridge(d);
> + return sprintf(buf, "%d\n", br_boolopt_get(br, BR_BOOLOPT_NO_LL_LEARN));
> +}
> +
> +static int set_no_linklocal_learn(struct net_bridge *br, unsigned long val)
> +{
> + return br_boolopt_toggle(br, BR_BOOLOPT_NO_LL_LEARN, !!val);
> +}
> +
> +static ssize_t no_linklocal_learn_store(struct device *d,
> + struct device_attribute *attr,
> + const char *buf, size_t len)
> +{
> + return store_bridge_parm(d, buf, len, set_no_linklocal_learn);
> +}
> +static DEVICE_ATTR_RW(no_linklocal_learn);
I thought we where trying to move away from sysfs? Do we need to add
new options here? It seems like forcing people to use iproute2 for
newer options is a good way to get people to convert to iproute2.
Andrew
^ permalink raw reply
* Re: [PATCH net-next 1/2] net: bridge: add support for user-controlled bool options
From: Nikolay Aleksandrov @ 2018-11-22 16:01 UTC (permalink / raw)
To: Andrew Lunn; +Cc: netdev, roopa, davem, bridge
In-Reply-To: <20181122153500.GF15403@lunn.ch>
On 22/11/2018 17:35, Andrew Lunn wrote:
> On Thu, Nov 22, 2018 at 06:29:24AM +0200, Nikolay Aleksandrov wrote:
>> We have been adding many new bridge options, a big number of which are
>> boolean but still take up netlink attribute ids and waste space in the skb.
>> Recently we discussed learning from link-local packets[1] and decided
>> yet another new boolean option will be needed, thus introducing this API
>> to save some bridge nl space.
>> The API supports changing the value of multiple boolean options at once
>> via the br_boolopt_multi struct which has an optmask (which options to
>> set, bit per opt) and optval (options' new values). Future boolean
>> options will only be added to the br_boolopt_id enum and then will have
>> to be handled in br_boolopt_toggle/get. The API will automatically
>> add the ability to change and export them via netlink, sysfs can use the
>> single boolopt function versions to do the same. The behaviour with
>> failing/succeeding is the same as with normal netlink option changing.
>>
>> If an option requires mapping to internal kernel flag or needs special
>> configuration to be enabled then it should be handled in
>> br_boolopt_toggle. It should also be able to retrieve an option's current
>> state via br_boolopt_get.
>>
>> [1] https://www.spinics.net/lists/netdev/msg532698.html
>>
>> Signed-off-by: Nikolay Aleksandrov <nikolay@cumulusnetworks.com>
>> ---
>> include/uapi/linux/if_bridge.h | 18 +++++++++
>> include/uapi/linux/if_link.h | 1 +
>> net/bridge/br.c | 68 ++++++++++++++++++++++++++++++++++
>> net/bridge/br_netlink.c | 17 ++++++++-
>> net/bridge/br_private.h | 6 +++
>> net/core/rtnetlink.c | 2 +-
>> 6 files changed, 110 insertions(+), 2 deletions(-)
>>
>> diff --git a/include/uapi/linux/if_bridge.h b/include/uapi/linux/if_bridge.h
>> index e41eda3c71f1..6dc02c03bdf8 100644
>> --- a/include/uapi/linux/if_bridge.h
>> +++ b/include/uapi/linux/if_bridge.h
>> @@ -292,4 +292,22 @@ struct br_mcast_stats {
>> __u64 mcast_bytes[BR_MCAST_DIR_SIZE];
>> __u64 mcast_packets[BR_MCAST_DIR_SIZE];
>> };
>> +
>> +/* bridge boolean options
>> + * IMPORTANT: if adding a new option do not forget to handle
>> + * it in br_boolopt_toggle/get and bridge sysfs
>> + */
>> +enum br_boolopt_id {
>> + BR_BOOLOPT_MAX
>> +};
>> +
>> +/* struct br_boolopt_multi - change multiple bridge boolean options
>> + *
>> + * @optval: new option values (bit per option)
>> + * @optmask: options to change (bit per option)
>> + */
>> +struct br_boolopt_multi {
>> + __u32 optval;
>> + __u32 optmask;
>> +};
>
> Hi Nikolay
>
> Thanks for handling this.
>
> How many boolean options do we already have? What it the likelihood a
> u32 is going to be too small, in a couple of years time?
>
It would mean doubling the number of current options and this is only for
boolean options so I think we're safe.
> I recently went through the pain of converting the u32 for
> representing link modes in the phylib API to a linux bitmap. I'm just
> wondering if in the long run, using a linux bitmap right from the
> beginning would be better?
>
>> +int br_boolopt_multi_toggle(struct net_bridge *br,
>> + struct br_boolopt_multi *bm)
>> +{
>> + unsigned long bitmap = bm->optmask;
>> + int err = 0;
>> + int opt_id;
>> +
>> + for_each_set_bit(opt_id, &bitmap, BR_BOOLOPT_MAX) {
>> + bool on = !!(bm->optval & BIT(opt_id));
>> +
>> + err = br_boolopt_toggle(br, opt_id, on);
>> + if (err) {
>> + br_debug(br, "boolopt multi-toggle error: option: %d current: %d new: %d error: %d\n",
>> + opt_id, br_boolopt_get(br, opt_id), on, err);
>
> Would it be possible to return that to userspace using the extended
> error infrastructure?
>
No, it doesn't support dynamic messages AFAIK.
> Andrew
>
^ permalink raw reply
* [PATCH] bpf: fix check of allowed specifiers in bpf_trace_printk
From: Martynas Pumputis @ 2018-11-22 16:00 UTC (permalink / raw)
To: netdev; +Cc: ast, daniel, m
A format string consisting of "%p" or "%s" followed by an invalid
specifier (e.g. "%p%\n" or "%s%") could pass the check which
would make format_decode (lib/vsprintf.c) to warn.
Reported-by: syzbot+1ec5c5ec949c4adaa0c4@syzkaller.appspotmail.com
Signed-off-by: Martynas Pumputis <m@lambda.lt>
---
kernel/trace/bpf_trace.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/kernel/trace/bpf_trace.c b/kernel/trace/bpf_trace.c
index 08fcfe440c63..9ab05736e1a1 100644
--- a/kernel/trace/bpf_trace.c
+++ b/kernel/trace/bpf_trace.c
@@ -225,6 +225,8 @@ BPF_CALL_5(bpf_trace_printk, char *, fmt, u32, fmt_size, u64, arg1,
(void *) (long) unsafe_addr,
sizeof(buf));
}
+ if (fmt[i] == '%')
+ i--;
continue;
}
--
2.19.1
^ permalink raw reply related
* [PATCH bpf] bpf: Fix integer overflow in queue_stack_map_alloc.
From: Wei Wu @ 2018-11-22 15:59 UTC (permalink / raw)
To: Alexei Starovoitov; +Cc: Daniel Borkmann, netdev, Eric Dumazet, Greg KH
Integer overflow in queue_stack_map_alloc when calculating size may
lead to heap overflow of arbitrary length.
The patch fix it by checking whether attr->max_entries+1 <
attr->max_entries and bailing out if it is the case.
The vulnerability is discovered with the assistance of syzkaller.
Reported-by: Wei Wu <ww9210@gmail.com>
To: Alexei Starovoitov <ast@kernel.org>
Cc: Daniel Borkmann <daniel@iogearbox.net>
Cc: netdev <netdev@vger.kernel.org>
Cc: Eric Dumazet <edumazet@google.com>
Cc: Greg KH <greg@kroah.com>
Signed-off-by: Wei Wu <ww9210@gmail.com>
---
kernel/bpf/queue_stack_maps.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/kernel/bpf/queue_stack_maps.c b/kernel/bpf/queue_stack_maps.c
index 8bbd72d3a121..c35a8a4721c8 100644
--- a/kernel/bpf/queue_stack_maps.c
+++ b/kernel/bpf/queue_stack_maps.c
@@ -67,6 +67,8 @@ static struct bpf_map *queue_stack_map_alloc(union
bpf_attr *attr)
u64 queue_size, cost;
size = attr->max_entries + 1;
+ if (size < attr->max_entries)
+ return ERR_PTR(-EINVAL);
value_size = attr->value_size;
queue_size = sizeof(*qs) + (u64) value_size * size;
^ permalink raw reply related
* Re: [PATCH net-next 1/2] net: bridge: add support for user-controlled bool options
From: Andrew Lunn @ 2018-11-22 15:52 UTC (permalink / raw)
To: Nikolay Aleksandrov; +Cc: netdev, roopa, davem, bridge
In-Reply-To: <20181122042925.8878-2-nikolay@cumulusnetworks.com>
> +void br_boolopt_multi_get(const struct net_bridge *br,
> + struct br_boolopt_multi *bm)
> +{
> + u32 optval = 0;
> + int opt_id;
> +
> + for (opt_id = 0; opt_id < BR_BOOLOPT_MAX; opt_id++)
> + optval |= (br_boolopt_get(br, opt_id) << opt_id);
> +
> + bm->optval = optval;
> + bm->optmask = 0;
Maybe set optmask to indicate which bits this kernel supports?
Andrew
^ permalink raw reply
* [PATCH net-next v2 5/5] netns: enable to dump full nsid translation table
From: Nicolas Dichtel @ 2018-11-22 15:50 UTC (permalink / raw)
To: dsahern; +Cc: netdev, davem, Nicolas Dichtel
In-Reply-To: <20181122155031.3495-1-nicolas.dichtel@6wind.com>
Like the previous patch, the goal is to ease to convert nsids from one
netns to another netns.
A new attribute (NETNSA_CURRENT_NSID) is added to the kernel answer when
NETNSA_TARGET_NSID is provided, thus the user can easily convert nsids.
Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
---
include/uapi/linux/net_namespace.h | 1 +
net/core/net_namespace.c | 30 ++++++++++++++++++++++++------
2 files changed, 25 insertions(+), 6 deletions(-)
diff --git a/include/uapi/linux/net_namespace.h b/include/uapi/linux/net_namespace.h
index 0ed9dd61d32a..9f9956809565 100644
--- a/include/uapi/linux/net_namespace.h
+++ b/include/uapi/linux/net_namespace.h
@@ -17,6 +17,7 @@ enum {
NETNSA_PID,
NETNSA_FD,
NETNSA_TARGET_NSID,
+ NETNSA_CURRENT_NSID,
__NETNSA_MAX,
};
diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c
index dd25fb22ad45..25030e0317a2 100644
--- a/net/core/net_namespace.c
+++ b/net/core/net_namespace.c
@@ -745,6 +745,8 @@ struct net_fill_args {
int flags;
int cmd;
int nsid;
+ bool add_ref;
+ int ref_nsid;
};
static int rtnl_net_fill(struct sk_buff *skb, struct net_fill_args *args)
@@ -763,6 +765,10 @@ static int rtnl_net_fill(struct sk_buff *skb, struct net_fill_args *args)
if (nla_put_s32(skb, NETNSA_NSID, args->nsid))
goto nla_put_failure;
+ if (args->add_ref &&
+ nla_put_s32(skb, NETNSA_CURRENT_NSID, args->ref_nsid))
+ goto nla_put_failure;
+
nlmsg_end(skb, nlh);
return 0;
@@ -782,7 +788,6 @@ static int rtnl_net_getid(struct sk_buff *skb, struct nlmsghdr *nlh,
.cmd = RTM_NEWNSID,
};
struct net *peer, *target = net;
- bool put_target = false;
struct nlattr *nla;
struct sk_buff *msg;
int err;
@@ -824,7 +829,8 @@ static int rtnl_net_getid(struct sk_buff *skb, struct nlmsghdr *nlh,
err = PTR_ERR(target);
goto out;
}
- put_target = true;
+ fillargs.add_ref = true;
+ fillargs.ref_nsid = peernet2id(net, peer);
}
msg = nlmsg_new(rtnl_net_get_size(), GFP_KERNEL);
@@ -844,7 +850,7 @@ static int rtnl_net_getid(struct sk_buff *skb, struct nlmsghdr *nlh,
err_out:
nlmsg_free(msg);
out:
- if (put_target)
+ if (fillargs.add_ref)
put_net(target);
put_net(peer);
return err;
@@ -852,11 +858,11 @@ static int rtnl_net_getid(struct sk_buff *skb, struct nlmsghdr *nlh,
struct rtnl_net_dump_cb {
struct net *tgt_net;
+ struct net *ref_net;
struct sk_buff *skb;
struct net_fill_args fillargs;
int idx;
int s_idx;
- bool put_tgt_net;
};
static int rtnl_net_dumpid_one(int id, void *peer, void *data)
@@ -868,6 +874,8 @@ static int rtnl_net_dumpid_one(int id, void *peer, void *data)
goto cont;
net_cb->fillargs.nsid = id;
+ if (net_cb->fillargs.add_ref)
+ net_cb->fillargs.ref_nsid = __peernet2id(net_cb->ref_net, peer);
ret = rtnl_net_fill(net_cb->skb, &net_cb->fillargs);
if (ret < 0)
return ret;
@@ -904,8 +912,9 @@ static int rtnl_valid_dump_net_req(const struct nlmsghdr *nlh, struct sock *sk,
"Invalid target network namespace id");
return PTR_ERR(net);
}
+ net_cb->fillargs.add_ref = true;
+ net_cb->ref_net = net_cb->tgt_net;
net_cb->tgt_net = net;
- net_cb->put_tgt_net = true;
} else {
NL_SET_BAD_ATTR(extack, tb[i]);
NL_SET_ERR_MSG(extack,
@@ -940,12 +949,21 @@ static int rtnl_net_dumpid(struct sk_buff *skb, struct netlink_callback *cb)
}
spin_lock_bh(&net_cb.tgt_net->nsid_lock);
+ if (net_cb.fillargs.add_ref &&
+ !net_eq(net_cb.ref_net, net_cb.tgt_net) &&
+ !spin_trylock_bh(&net_cb.ref_net->nsid_lock)) {
+ err = -EAGAIN;
+ goto end;
+ }
idr_for_each(&net_cb.tgt_net->netns_ids, rtnl_net_dumpid_one, &net_cb);
+ if (net_cb.fillargs.add_ref &&
+ !net_eq(net_cb.ref_net, net_cb.tgt_net))
+ spin_unlock_bh(&net_cb.ref_net->nsid_lock);
spin_unlock_bh(&net_cb.tgt_net->nsid_lock);
cb->args[0] = net_cb.idx;
end:
- if (net_cb.put_tgt_net)
+ if (net_cb.fillargs.add_ref)
put_net(net_cb.tgt_net);
return err < 0 ? err : skb->len;
}
--
2.18.0
^ permalink raw reply related
* [PATCH net-next v2 3/5] netns: add support of NETNSA_TARGET_NSID
From: Nicolas Dichtel @ 2018-11-22 15:50 UTC (permalink / raw)
To: dsahern; +Cc: netdev, davem, Nicolas Dichtel
In-Reply-To: <20181122155031.3495-1-nicolas.dichtel@6wind.com>
Like it was done for link and address, add the ability to perform get/dump
in another netns by specifying a target nsid attribute.
Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
---
include/uapi/linux/net_namespace.h | 1 +
net/core/net_namespace.c | 86 ++++++++++++++++++++++++++----
2 files changed, 76 insertions(+), 11 deletions(-)
diff --git a/include/uapi/linux/net_namespace.h b/include/uapi/linux/net_namespace.h
index 0187c74d8889..0ed9dd61d32a 100644
--- a/include/uapi/linux/net_namespace.h
+++ b/include/uapi/linux/net_namespace.h
@@ -16,6 +16,7 @@ enum {
NETNSA_NSID,
NETNSA_PID,
NETNSA_FD,
+ NETNSA_TARGET_NSID,
__NETNSA_MAX,
};
diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c
index f8a5966b086c..885c54197e31 100644
--- a/net/core/net_namespace.c
+++ b/net/core/net_namespace.c
@@ -669,6 +669,7 @@ static const struct nla_policy rtnl_net_policy[NETNSA_MAX + 1] = {
[NETNSA_NSID] = { .type = NLA_S32 },
[NETNSA_PID] = { .type = NLA_U32 },
[NETNSA_FD] = { .type = NLA_U32 },
+ [NETNSA_TARGET_NSID] = { .type = NLA_S32 },
};
static int rtnl_net_newid(struct sk_buff *skb, struct nlmsghdr *nlh,
@@ -780,9 +781,10 @@ static int rtnl_net_getid(struct sk_buff *skb, struct nlmsghdr *nlh,
.seq = nlh->nlmsg_seq,
.cmd = RTM_NEWNSID,
};
+ struct net *peer, *target = net;
+ bool put_target = false;
struct nlattr *nla;
struct sk_buff *msg;
- struct net *peer;
int err;
err = nlmsg_parse(nlh, sizeof(struct rtgenmsg), tb, NETNSA_MAX,
@@ -806,13 +808,27 @@ static int rtnl_net_getid(struct sk_buff *skb, struct nlmsghdr *nlh,
return PTR_ERR(peer);
}
+ if (tb[NETNSA_TARGET_NSID]) {
+ int id = nla_get_s32(tb[NETNSA_TARGET_NSID]);
+
+ target = rtnl_get_net_ns_capable(NETLINK_CB(skb).sk, id);
+ if (IS_ERR(target)) {
+ NL_SET_BAD_ATTR(extack, tb[NETNSA_TARGET_NSID]);
+ NL_SET_ERR_MSG(extack,
+ "Target netns reference is invalid");
+ err = PTR_ERR(target);
+ goto out;
+ }
+ put_target = true;
+ }
+
msg = nlmsg_new(rtnl_net_get_size(), GFP_KERNEL);
if (!msg) {
err = -ENOMEM;
goto out;
}
- fillargs.nsid = peernet2id(net, peer);
+ fillargs.nsid = peernet2id(target, peer);
err = rtnl_net_fill(msg, &fillargs);
if (err < 0)
goto err_out;
@@ -823,15 +839,19 @@ static int rtnl_net_getid(struct sk_buff *skb, struct nlmsghdr *nlh,
err_out:
nlmsg_free(msg);
out:
+ if (put_target)
+ put_net(target);
put_net(peer);
return err;
}
struct rtnl_net_dump_cb {
+ struct net *tgt_net;
struct sk_buff *skb;
struct net_fill_args fillargs;
int idx;
int s_idx;
+ bool put_tgt_net;
};
static int rtnl_net_dumpid_one(int id, void *peer, void *data)
@@ -852,10 +872,50 @@ static int rtnl_net_dumpid_one(int id, void *peer, void *data)
return 0;
}
+static int rtnl_valid_dump_net_req(const struct nlmsghdr *nlh, struct sock *sk,
+ struct rtnl_net_dump_cb *net_cb,
+ struct netlink_callback *cb)
+{
+ struct netlink_ext_ack *extack = cb->extack;
+ struct nlattr *tb[NETNSA_MAX + 1];
+ int err, i;
+
+ err = nlmsg_parse_strict(nlh, sizeof(struct rtgenmsg), tb, NETNSA_MAX,
+ rtnl_net_policy, extack);
+ if (err < 0)
+ return err;
+
+ for (i = 0; i <= NETNSA_MAX; i++) {
+ if (!tb[i])
+ continue;
+
+ if (i == NETNSA_TARGET_NSID) {
+ struct net *net;
+
+ net = rtnl_get_net_ns_capable(sk, nla_get_s32(tb[i]));
+ if (IS_ERR(net)) {
+ NL_SET_BAD_ATTR(extack, tb[i]);
+ NL_SET_ERR_MSG(extack,
+ "Invalid target network namespace id");
+ return PTR_ERR(net);
+ }
+ net_cb->tgt_net = net;
+ net_cb->put_tgt_net = true;
+ } else {
+ NL_SET_BAD_ATTR(extack, tb[i]);
+ NL_SET_ERR_MSG(extack,
+ "Unsupported attribute in dump request");
+ return -EINVAL;
+ }
+ }
+
+ return 0;
+}
+
static int rtnl_net_dumpid(struct sk_buff *skb, struct netlink_callback *cb)
{
- struct net *net = sock_net(skb->sk);
struct rtnl_net_dump_cb net_cb = {
+ .tgt_net = sock_net(skb->sk),
.skb = skb,
.fillargs = {
.portid = NETLINK_CB(cb->skb).portid,
@@ -866,19 +926,23 @@ static int rtnl_net_dumpid(struct sk_buff *skb, struct netlink_callback *cb)
.idx = 0,
.s_idx = cb->args[0],
};
+ int err = 0;
- if (cb->strict_check &&
- nlmsg_attrlen(cb->nlh, sizeof(struct rtgenmsg))) {
- NL_SET_ERR_MSG(cb->extack, "Unknown data in network namespace id dump request");
- return -EINVAL;
+ if (cb->strict_check) {
+ err = rtnl_valid_dump_net_req(cb->nlh, skb->sk, &net_cb, cb);
+ if (err < 0)
+ goto end;
}
- spin_lock_bh(&net->nsid_lock);
- idr_for_each(&net->netns_ids, rtnl_net_dumpid_one, &net_cb);
- spin_unlock_bh(&net->nsid_lock);
+ spin_lock_bh(&net_cb.tgt_net->nsid_lock);
+ idr_for_each(&net_cb.tgt_net->netns_ids, rtnl_net_dumpid_one, &net_cb);
+ spin_unlock_bh(&net_cb.tgt_net->nsid_lock);
cb->args[0] = net_cb.idx;
- return skb->len;
+end:
+ if (net_cb.put_tgt_net)
+ put_net(net_cb.tgt_net);
+ return err < 0 ? err : skb->len;
}
static void rtnl_net_notifyid(struct net *net, int cmd, int id)
--
2.18.0
^ permalink raw reply related
* [PATCH net-next v2 2/5] netns: introduce 'struct net_fill_args'
From: Nicolas Dichtel @ 2018-11-22 15:50 UTC (permalink / raw)
To: dsahern; +Cc: netdev, davem, Nicolas Dichtel
In-Reply-To: <20181122155031.3495-1-nicolas.dichtel@6wind.com>
This is a preparatory work. To avoid having to much arguments for the
function rtnl_net_fill(), a new structure is defined.
Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
---
net/core/net_namespace.c | 48 ++++++++++++++++++++++++++++------------
1 file changed, 34 insertions(+), 14 deletions(-)
diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c
index 52b9620e3457..f8a5966b086c 100644
--- a/net/core/net_namespace.c
+++ b/net/core/net_namespace.c
@@ -738,20 +738,28 @@ static int rtnl_net_get_size(void)
;
}
-static int rtnl_net_fill(struct sk_buff *skb, u32 portid, u32 seq, int flags,
- int cmd, int nsid)
+struct net_fill_args {
+ u32 portid;
+ u32 seq;
+ int flags;
+ int cmd;
+ int nsid;
+};
+
+static int rtnl_net_fill(struct sk_buff *skb, struct net_fill_args *args)
{
struct nlmsghdr *nlh;
struct rtgenmsg *rth;
- nlh = nlmsg_put(skb, portid, seq, cmd, sizeof(*rth), flags);
+ nlh = nlmsg_put(skb, args->portid, args->seq, args->cmd, sizeof(*rth),
+ args->flags);
if (!nlh)
return -EMSGSIZE;
rth = nlmsg_data(nlh);
rth->rtgen_family = AF_UNSPEC;
- if (nla_put_s32(skb, NETNSA_NSID, nsid))
+ if (nla_put_s32(skb, NETNSA_NSID, args->nsid))
goto nla_put_failure;
nlmsg_end(skb, nlh);
@@ -767,10 +775,15 @@ static int rtnl_net_getid(struct sk_buff *skb, struct nlmsghdr *nlh,
{
struct net *net = sock_net(skb->sk);
struct nlattr *tb[NETNSA_MAX + 1];
+ struct net_fill_args fillargs = {
+ .portid = NETLINK_CB(skb).portid,
+ .seq = nlh->nlmsg_seq,
+ .cmd = RTM_NEWNSID,
+ };
struct nlattr *nla;
struct sk_buff *msg;
struct net *peer;
- int err, id;
+ int err;
err = nlmsg_parse(nlh, sizeof(struct rtgenmsg), tb, NETNSA_MAX,
rtnl_net_policy, extack);
@@ -799,9 +812,8 @@ static int rtnl_net_getid(struct sk_buff *skb, struct nlmsghdr *nlh,
goto out;
}
- id = peernet2id(net, peer);
- err = rtnl_net_fill(msg, NETLINK_CB(skb).portid, nlh->nlmsg_seq, 0,
- RTM_NEWNSID, id);
+ fillargs.nsid = peernet2id(net, peer);
+ err = rtnl_net_fill(msg, &fillargs);
if (err < 0)
goto err_out;
@@ -817,7 +829,7 @@ static int rtnl_net_getid(struct sk_buff *skb, struct nlmsghdr *nlh,
struct rtnl_net_dump_cb {
struct sk_buff *skb;
- struct netlink_callback *cb;
+ struct net_fill_args fillargs;
int idx;
int s_idx;
};
@@ -830,9 +842,8 @@ static int rtnl_net_dumpid_one(int id, void *peer, void *data)
if (net_cb->idx < net_cb->s_idx)
goto cont;
- ret = rtnl_net_fill(net_cb->skb, NETLINK_CB(net_cb->cb->skb).portid,
- net_cb->cb->nlh->nlmsg_seq, NLM_F_MULTI,
- RTM_NEWNSID, id);
+ net_cb->fillargs.nsid = id;
+ ret = rtnl_net_fill(net_cb->skb, &net_cb->fillargs);
if (ret < 0)
return ret;
@@ -846,7 +857,12 @@ static int rtnl_net_dumpid(struct sk_buff *skb, struct netlink_callback *cb)
struct net *net = sock_net(skb->sk);
struct rtnl_net_dump_cb net_cb = {
.skb = skb,
- .cb = cb,
+ .fillargs = {
+ .portid = NETLINK_CB(cb->skb).portid,
+ .seq = cb->nlh->nlmsg_seq,
+ .flags = NLM_F_MULTI,
+ .cmd = RTM_NEWNSID,
+ },
.idx = 0,
.s_idx = cb->args[0],
};
@@ -867,6 +883,10 @@ static int rtnl_net_dumpid(struct sk_buff *skb, struct netlink_callback *cb)
static void rtnl_net_notifyid(struct net *net, int cmd, int id)
{
+ struct net_fill_args fillargs = {
+ .cmd = cmd,
+ .nsid = id,
+ };
struct sk_buff *msg;
int err = -ENOMEM;
@@ -874,7 +894,7 @@ static void rtnl_net_notifyid(struct net *net, int cmd, int id)
if (!msg)
goto out;
- err = rtnl_net_fill(msg, 0, 0, 0, cmd, id);
+ err = rtnl_net_fill(msg, &fillargs);
if (err < 0)
goto err_out;
--
2.18.0
^ permalink raw reply related
* [PATCH net-next v2 0/5] Ease to interpret net-nsid
From: Nicolas Dichtel @ 2018-11-22 15:50 UTC (permalink / raw)
To: dsahern; +Cc: netdev, davem
In-Reply-To: <20181121110124.5501-1-nicolas.dichtel@6wind.com>
The goal of this series is to ease the interpretation of nsid received in
netlink messages from other netns (when the user uses
NETLINK_F_LISTEN_ALL_NSID).
After this series, with a patched iproute2:
$ ip netns add foo
$ ip netns add bar
$ touch /var/run/netns/init_net
$ mount --bind /proc/1/ns/net /var/run/netns/init_net
$ ip netns set init_net 11
$ ip netns set foo 12
$ ip netns set bar 13
$ ip netns
init_net (id: 11)
bar (id: 13)
foo (id: 12)
$ ip -n foo netns set init_net 21
$ ip -n foo netns set foo 22
$ ip -n foo netns set bar 23
$ ip -n foo netns
init_net (id: 21)
bar (id: 23)
foo (id: 22)
$ ip -n bar netns set init_net 31
$ ip -n bar netns set foo 32
$ ip -n bar netns set bar 33
$ ip -n bar netns
init_net (id: 31)
bar (id: 33)
foo (id: 32)
$ ip netns list-id target-nsid 12
nsid 21 current-nsid 11 (iproute2 netns name: init_net)
nsid 22 current-nsid 12 (iproute2 netns name: foo)
nsid 23 current-nsid 13 (iproute2 netns name: bar)
$ ip -n bar netns list-id target-nsid 32 nsid 31
nsid 21 current-nsid 31 (iproute2 netns name: init_net)
v1 -> v2:
- patch 1/5: remove net from struct rtnl_net_dump_cb
- patch 2/5: new in this version
- patch 3/5: use a bool to know if rtnl_get_net_ns_capable() was called
- patch 5/5: use struct net_fill_args
include/uapi/linux/net_namespace.h | 2 +
net/core/net_namespace.c | 157 +++++++++++++++++++++++++++++++------
2 files changed, 133 insertions(+), 26 deletions(-)
Comments are welcomed,
Regards,
Nicolas
^ permalink raw reply
* [PATCH net-next v2 1/5] netns: remove net arg from rtnl_net_fill()
From: Nicolas Dichtel @ 2018-11-22 15:50 UTC (permalink / raw)
To: dsahern; +Cc: netdev, davem, Nicolas Dichtel
In-Reply-To: <20181122155031.3495-1-nicolas.dichtel@6wind.com>
This argument is not used anymore.
Fixes: cab3c8ec8d57 ("netns: always provide the id to rtnl_net_fill()")
Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
---
net/core/net_namespace.c | 10 ++++------
1 file changed, 4 insertions(+), 6 deletions(-)
diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c
index fefe72774aeb..52b9620e3457 100644
--- a/net/core/net_namespace.c
+++ b/net/core/net_namespace.c
@@ -739,7 +739,7 @@ static int rtnl_net_get_size(void)
}
static int rtnl_net_fill(struct sk_buff *skb, u32 portid, u32 seq, int flags,
- int cmd, struct net *net, int nsid)
+ int cmd, int nsid)
{
struct nlmsghdr *nlh;
struct rtgenmsg *rth;
@@ -801,7 +801,7 @@ static int rtnl_net_getid(struct sk_buff *skb, struct nlmsghdr *nlh,
id = peernet2id(net, peer);
err = rtnl_net_fill(msg, NETLINK_CB(skb).portid, nlh->nlmsg_seq, 0,
- RTM_NEWNSID, net, id);
+ RTM_NEWNSID, id);
if (err < 0)
goto err_out;
@@ -816,7 +816,6 @@ static int rtnl_net_getid(struct sk_buff *skb, struct nlmsghdr *nlh,
}
struct rtnl_net_dump_cb {
- struct net *net;
struct sk_buff *skb;
struct netlink_callback *cb;
int idx;
@@ -833,7 +832,7 @@ static int rtnl_net_dumpid_one(int id, void *peer, void *data)
ret = rtnl_net_fill(net_cb->skb, NETLINK_CB(net_cb->cb->skb).portid,
net_cb->cb->nlh->nlmsg_seq, NLM_F_MULTI,
- RTM_NEWNSID, net_cb->net, id);
+ RTM_NEWNSID, id);
if (ret < 0)
return ret;
@@ -846,7 +845,6 @@ static int rtnl_net_dumpid(struct sk_buff *skb, struct netlink_callback *cb)
{
struct net *net = sock_net(skb->sk);
struct rtnl_net_dump_cb net_cb = {
- .net = net,
.skb = skb,
.cb = cb,
.idx = 0,
@@ -876,7 +874,7 @@ static void rtnl_net_notifyid(struct net *net, int cmd, int id)
if (!msg)
goto out;
- err = rtnl_net_fill(msg, 0, 0, 0, cmd, net, id);
+ err = rtnl_net_fill(msg, 0, 0, 0, cmd, id);
if (err < 0)
goto err_out;
--
2.18.0
^ permalink raw reply related
* [PATCH net-next v2 4/5] netns: enable to specify a nsid for a get request
From: Nicolas Dichtel @ 2018-11-22 15:50 UTC (permalink / raw)
To: dsahern; +Cc: netdev, davem, Nicolas Dichtel
In-Reply-To: <20181122155031.3495-1-nicolas.dichtel@6wind.com>
Combined with NETNSA_TARGET_NSID, it enables to "translate" a nsid from one
netns to a nsid of another netns.
This is useful when using NETLINK_F_LISTEN_ALL_NSID because it helps the
user to interpret a nsid received from an other netns.
Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
---
net/core/net_namespace.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c
index 885c54197e31..dd25fb22ad45 100644
--- a/net/core/net_namespace.c
+++ b/net/core/net_namespace.c
@@ -797,6 +797,11 @@ static int rtnl_net_getid(struct sk_buff *skb, struct nlmsghdr *nlh,
} else if (tb[NETNSA_FD]) {
peer = get_net_ns_by_fd(nla_get_u32(tb[NETNSA_FD]));
nla = tb[NETNSA_FD];
+ } else if (tb[NETNSA_NSID]) {
+ peer = get_net_ns_by_id(net, nla_get_u32(tb[NETNSA_NSID]));
+ if (!peer)
+ peer = ERR_PTR(-ENOENT);
+ nla = tb[NETNSA_NSID];
} else {
NL_SET_ERR_MSG(extack, "Peer netns reference is missing");
return -EINVAL;
--
2.18.0
^ permalink raw reply related
* Re: [PATCH net-next 1/2] net: bridge: add support for user-controlled bool options
From: Andrew Lunn @ 2018-11-22 15:49 UTC (permalink / raw)
To: Nikolay Aleksandrov; +Cc: netdev, roopa, davem, bridge
In-Reply-To: <20181122042925.8878-2-nikolay@cumulusnetworks.com>
> +/* br_boolopt_toggle - change user-controlled boolean option
> + *
> + * @br: bridge device
> + * @opt: id of the option to change
> + * @on: new option value
> + *
> + * Changes the value of the respective boolean option to @on taking care of
> + * any internal option value mapping and configuration.
> + */
> +int br_boolopt_toggle(struct net_bridge *br, enum br_boolopt_id opt, bool on)
> +{
> + int err = -ENOENT;
> +
> + switch (opt) {
> + default:
> + break;
> + }
> +
> + return err;
> +}
> +
> +int br_boolopt_multi_toggle(struct net_bridge *br,
> + struct br_boolopt_multi *bm)
> +{
> + unsigned long bitmap = bm->optmask;
> + int err = 0;
> + int opt_id;
> +
> + for_each_set_bit(opt_id, &bitmap, BR_BOOLOPT_MAX) {
> + bool on = !!(bm->optval & BIT(opt_id));
> +
> + err = br_boolopt_toggle(br, opt_id, on);
> + if (err) {
> + br_debug(br, "boolopt multi-toggle error: option: %d current: %d new: %d error: %d\n",
> + opt_id, br_boolopt_get(br, opt_id), on, err);
> + break;
> + }
An old kernel with a new iproute2 might partially succeed in toggling
some low bits, but then silently ignore a high bit that is not
supported by the kernel. As a user, i want to know the kernel does not
support an option i'm trying to toggle.
Can you walk all the bits in the u32 from the MSB to the LSB? That
should avoid this problem.
Andrew
^ permalink raw reply
* Re: [v5, PATCH 1/2] net:stmmac: dwmac-mediatek: add support for mt2712
From: biao huang @ 2018-11-23 2:17 UTC (permalink / raw)
To: Sean Wang
Cc: davem, robh+dt, mark.rutland, devicetree, nelson.chang,
Andrew Lunn, netdev, Liguo Zhang, linux-kernel, Matthias Brugger,
joabreu, linux-mediatek, honghui.zhang, linux-arm-kernel
In-Reply-To: <CAGp9LzoJTVm4OP+SRWCDk0TUmU5jNMFCsT_yyURXzXxjTF+-=g@mail.gmail.com>
Dear Sean,
Thanks for your comments.
On Thu, 2018-11-22 at 16:54 -0800, Sean Wang wrote:
> On Thu, Nov 22, 2018 at 2:29 AM Biao Huang <biao.huang@mediatek.com> wrote:
> >
> > Add Ethernet support for MediaTek SoCs from the mt2712 family
> >
> > Signed-off-by: Biao Huang <biao.huang@mediatek.com>
> > ---
> > drivers/net/ethernet/stmicro/stmmac/Kconfig | 8 +
> > drivers/net/ethernet/stmicro/stmmac/Makefile | 1 +
> > .../net/ethernet/stmicro/stmmac/dwmac-mediatek.c | 364 ++++++++++++++++++++
> > 3 files changed, 373 insertions(+)
> > create mode 100644 drivers/net/ethernet/stmicro/stmmac/dwmac-mediatek.c
> >
> > diff --git a/drivers/net/ethernet/stmicro/stmmac/Kconfig b/drivers/net/ethernet/stmicro/stmmac/Kconfig
> > index 324049e..6209cc1 100644
> > --- a/drivers/net/ethernet/stmicro/stmmac/Kconfig
> > +++ b/drivers/net/ethernet/stmicro/stmmac/Kconfig
> > @@ -75,6 +75,14 @@ config DWMAC_LPC18XX
> > ---help---
> > Support for NXP LPC18xx/43xx DWMAC Ethernet.
> >
> > +config DWMAC_MEDIATEK
> > + tristate "MediaTek MT27xx GMAC support"
> > + depends on OF && (ARCH_MEDIATEK || COMPILE_TEST)
> > + help
> > + Support for MediaTek GMAC Ethernet controller.
> > +
> > + This selects the MT2712 SoC support for the stmmac driver.
> > +
> > config DWMAC_MESON
> > tristate "Amlogic Meson dwmac support"
> > default ARCH_MESON
> > diff --git a/drivers/net/ethernet/stmicro/stmmac/Makefile b/drivers/net/ethernet/stmicro/stmmac/Makefile
> > index 99967a8..bf09701 100644
> > --- a/drivers/net/ethernet/stmicro/stmmac/Makefile
> > +++ b/drivers/net/ethernet/stmicro/stmmac/Makefile
> > @@ -13,6 +13,7 @@ obj-$(CONFIG_STMMAC_PLATFORM) += stmmac-platform.o
> > obj-$(CONFIG_DWMAC_ANARION) += dwmac-anarion.o
> > obj-$(CONFIG_DWMAC_IPQ806X) += dwmac-ipq806x.o
> > obj-$(CONFIG_DWMAC_LPC18XX) += dwmac-lpc18xx.o
> > +obj-$(CONFIG_DWMAC_MEDIATEK) += dwmac-mediatek.o
> > obj-$(CONFIG_DWMAC_MESON) += dwmac-meson.o dwmac-meson8b.o
> > obj-$(CONFIG_DWMAC_OXNAS) += dwmac-oxnas.o
> > obj-$(CONFIG_DWMAC_ROCKCHIP) += dwmac-rk.o
> > diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-mediatek.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-mediatek.c
> > new file mode 100644
> > index 0000000..dd8d4cc
> > --- /dev/null
> > +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-mediatek.c
> > @@ -0,0 +1,364 @@
> > +// SPDX-License-Identifier: GPL-2.0
> > +/*
> > + * Copyright (c) 2018 MediaTek Inc.
> > + */
> > +#include <linux/io.h>
> > +#include <linux/mfd/syscon.h>
> > +#include <linux/of.h>
> > +#include <linux/of_device.h>
> > +#include <linux/of_net.h>
> > +#include <linux/regmap.h>
> > +#include <linux/stmmac.h>
> > +
> > +#include "stmmac.h"
> > +#include "stmmac_platform.h"
> > +
> > +/* Peri Configuration register for mt2712 */
> > +#define PERI_ETH_PHY_INTF_SEL 0x418
> > +#define PHY_INTF_MII_GMII 0
> > +#define PHY_INTF_RGMII 1
> > +#define PHY_INTF_RMII 4
> > +#define RMII_CLK_SRC_RXC BIT(4)
> > +#define RMII_CLK_SRC_INTERNAL BIT(5)
> > +
> > +#define PERI_ETH_PHY_DLY 0x428
> > +#define PHY_DLY_GTXC_INV BIT(6)
> > +#define PHY_DLY_GTXC_ENABLE BIT(5)
> > +#define PHY_DLY_GTXC_STAGES GENMASK(4, 0)
> > +#define PHY_DLY_TXC_INV BIT(20)
> > +#define PHY_DLY_TXC_ENABLE BIT(19)
> > +#define PHY_DLY_TXC_STAGES GENMASK(18, 14)
> > +#define PHY_DLY_TXC_SHIFT 14
> > +#define PHY_DLY_RXC_INV BIT(13)
> > +#define PHY_DLY_RXC_ENABLE BIT(12)
> > +#define PHY_DLY_RXC_STAGES GENMASK(11, 7)
> > +#define PHY_DLY_RXC_SHIFT 7
> > +
> > +#define PERI_ETH_DLY_FINE 0x800
> > +#define ETH_RMII_DLY_TX_INV BIT(2)
> > +#define ETH_FINE_DLY_GTXC BIT(1)
> > +#define ETH_FINE_DLY_RXC BIT(0)
> > +
> > +struct mac_delay_struct {
> > + u32 tx_delay;
> > + u32 rx_delay;
> > + u32 tx_inv;
> bool should be enough
yes
>
> > + u32 rx_inv;
> bool should be enough
yes
>
> > +};
> > +
> > +struct mediatek_dwmac_plat_data {
> > + const struct mediatek_dwmac_variant *variant;
> > + struct mac_delay_struct mac_delay;
> > + struct clk_bulk_data *clks;
> > + struct device_node *np;
> > + struct regmap *peri_regmap;
> > + struct device *dev;
> > + int fine_tune;
> bool
>
yes
> > + int phy_mode;
> > + int rmii_rxc;
> bool
yes
>
> > +};
> > +
> > +struct mediatek_dwmac_variant {
> > + int (*dwmac_set_phy_interface)(struct mediatek_dwmac_plat_data *plat);
> > + int (*dwmac_set_delay)(struct mediatek_dwmac_plat_data *plat);
> > +
> > + /* clock ids to be requested */
> > + const char * const *clk_list;
> > + int num_clks;
> > +
> > + u32 dma_bit_mask;
> > + u32 rx_delay_max;
> > + u32 tx_delay_max;
> > +};
> > +
> > +/* list of clocks required for mac */
> > +static const char * const mt2712_dwmac_clk_l[] = {
> > + "axi", "apb", "mac_main", "ptp_ref"
> > +};
> > +
> > +static int mt2712_set_interface(struct mediatek_dwmac_plat_data *plat)
> > +{
> > + int rmii_rxc = plat->rmii_rxc ? RMII_CLK_SRC_RXC : 0;
> > + u32 intf_val = 0;
> > +
> > + /* select phy interface in top control domain */
> > + switch (plat->phy_mode) {
> > + case PHY_INTERFACE_MODE_MII:
> > + intf_val |= PHY_INTF_MII_GMII;
> > + break;
> > + case PHY_INTERFACE_MODE_RMII:
> > + intf_val |= PHY_INTF_RMII;
> > + intf_val |= rmii_rxc;
> how about putting into one line such as intf_val |= (PHY_INTF_RMII | rmii_rxc) ?
>
ok, will change in next version.
> > + break;
> > + case PHY_INTERFACE_MODE_RGMII:
> > + case PHY_INTERFACE_MODE_RGMII_TXID:
> > + case PHY_INTERFACE_MODE_RGMII_RXID:
> > + case PHY_INTERFACE_MODE_RGMII_ID:
> > + intf_val |= PHY_INTF_RGMII;
> > + break;
> > + default:
> > + dev_err(plat->dev, "phy interface not supported\n");
> > + return -EINVAL;
> > + }
> > +
> > + regmap_write(plat->peri_regmap, PERI_ETH_PHY_INTF_SEL, intf_val);
> > +
> > + return 0;
> > +}
> > +
> > +static int mt2712_set_delay(struct mediatek_dwmac_plat_data *plat)
> > +{
> > + struct mac_delay_struct *mac_delay = &plat->mac_delay;
> > + u32 delay_val = 0;
> > + u32 fine_val = 0;
> The same type declaration can be put into the one line
>
Got it.
> > +
> > + switch (plat->phy_mode) {
>
> There exists some room for code optimization in the switch statement
> such as PHY_INTERFACE_MODE_MII and PHY_INTERFACE_MODE_RGMII both are
> almost the same and even the configuration for the other PHY modes can
> reuse their partial setup. It appears to be better using a common way
> to set up various PHY modes.
>
I'll try define a function to handle it.
And how about like this:
static u32 delay_setting(u32 delay, bool inv, u32 en_bit, u32
clk_shift, u32 clk_mask, u32 inv_bit) {
u32 value = 0
value |= delay ? en_bit : 0;
value |= (delay << clk_shift) & clk_mask;
value |= inv ? inv_bit : 0;
}
case PHY_INTERFACE_MODE_MII:
delay_value |= delay_setting(mac_delay->tx_delay,
mac_delay->tx_inv,
PHY_DLY_TXC_ENABLE,
PHY_DLY_TXC_SHIFT,
PHY_DLY_TXC_STAGES,
PHY_DLY_TXC_INV);
delay_value |= delay_setting(mac_delay->rx_delay,
mac_delay->rx_inv,
PHY_DLY_RXC_ENABLE,
PHY_DLY_RXC_SHIFT,
PHY_DLY_RXC_STAGES,
PHY_DLY_RXC_INV);
case PHY_INTERFACE_MODE_RMII:
if (plat->rmii_rxc) {
delay_value |= delay_setting(mac_delay->rx_delay,
mac_delay->rx_inv,
PHY_DLY_RXC_ENABLE,
PHY_DLY_RXC_SHIFT,
PHY_DLY_RXC_STAGES,
PHY_DLY_RXC_INV);
fine_val |= mac_delay->tx_inv ?
ETH_RMII_DLY_TX_INV : 0;
} else {
delay_value |= delay_setting(mac_delay->rx_delay,
mac_delay->rx_inv,
PHY_DLY_TXC_ENABLE,
PHY_DLY_TXC_SHIFT,
PHY_DLY_TXC_STAGES,
PHY_DLY_TXC_INV);
fine_val |= mac_delay->tx_inv ?
ETH_RMII_DLY_TX_INV : 0;
}
case PHY_INTERFACE_MODE_RGMII:
fine_val = plat->fine_tune ?
(ETH_FINE_DLY_GTXC | ETH_FINE_DLY_RXC) : 0;
delay_value |= delay_setting(mac_delay->tx_delay,
mac_delay->tx_inv,
PHY_DLY_GTXC_ENABLE,
PHY_DLY_GTXC_SHIFT,
PHY_DLY_GTXC_STAGES,
PHY_DLY_GTXC_INV);
delay_value |= delay_setting(mac_delay->rx_delay,
mac_delay->rx_inv,
PHY_DLY_RXC_ENABLE,
PHY_DLY_RXC_SHIFT,
PHY_DLY_RXC_STAGES,
PHY_DLY_RXC_INV);
case PHY_INTERFACE_MODE_RGMII_TXID:
fine_val = plat->fine_tune ? ETH_FINE_DLY_RXC : 0;
delay_value |= delay_setting(mac_delay->rx_delay,
mac_delay->rx_inv,
PHY_DLY_RXC_ENABLE,
PHY_DLY_RXC_SHIFT,
PHY_DLY_RXC_STAGES,
PHY_DLY_RXC_INV);
case PHY_INTERFACE_MODE_RGMII_RXID:
fine_val = plat->fine_tune ? ETH_FINE_DLY_GTXC : 0;
delay_value |= delay_setting(mac_delay->tx_delay,
mac_delay->tx_inv,
PHY_DLY_GTXC_ENABLE,
PHY_DLY_GTXC_SHIFT,
PHY_DLY_GTXC_STAGES,
PHY_DLY_GTXC_INV);
> > + case PHY_INTERFACE_MODE_MII:
> > + delay_val |= mac_delay->tx_delay ? PHY_DLY_TXC_ENABLE : 0;
> > + delay_val |= (mac_delay->tx_delay << PHY_DLY_TXC_SHIFT) &
> > + PHY_DLY_TXC_STAGES;
> > + delay_val |= mac_delay->tx_inv ? PHY_DLY_TXC_INV : 0;
> > + delay_val |= mac_delay->rx_delay ? PHY_DLY_RXC_ENABLE : 0;
> > + delay_val |= (mac_delay->rx_delay << PHY_DLY_RXC_SHIFT) &
> > + PHY_DLY_RXC_STAGES;
> > + delay_val |= mac_delay->rx_inv ? PHY_DLY_RXC_INV : 0;
> > + break;
> > + case PHY_INTERFACE_MODE_RMII:
> > + if (plat->rmii_rxc) {
> > + delay_val |= mac_delay->rx_delay ?
> > + PHY_DLY_RXC_ENABLE : 0;
> > + delay_val |= (mac_delay->rx_delay <<
> > + PHY_DLY_RXC_SHIFT) & PHY_DLY_RXC_STAGES;
> > + delay_val |= mac_delay->rx_inv ? PHY_DLY_RXC_INV : 0;
> > + fine_val |= mac_delay->tx_inv ?
> > + ETH_RMII_DLY_TX_INV : 0;
> why is fine_val got from tx_inv?
>
becase the tx inv will inverse the tx clock inside mac relative to
reference clock from external phy, and this bit is located in the same
register with fine-tune.
maybe I should rename fine_val to avoid misunderstanding.
> > + } else {
> > + delay_val |= mac_delay->rx_delay ?
> > + PHY_DLY_TXC_ENABLE : 0;
> > + delay_val |= (mac_delay->rx_delay <<
> > + PHY_DLY_TXC_SHIFT) & PHY_DLY_TXC_STAGES;
> > + delay_val |= mac_delay->rx_inv ? PHY_DLY_TXC_INV : 0;
> > + fine_val |= mac_delay->tx_inv ?
> > + ETH_RMII_DLY_TX_INV : 0;
> ditto, why is fine_val got from tx_inv?
>
same as above. ETH_RMII_DLY_TX_INV is only for RMII, and located in the
same register with fine-tune.
> > + }
> > + break;
> > + case PHY_INTERFACE_MODE_RGMII:
> > + fine_val = plat->fine_tune ?
> > + (ETH_FINE_DLY_GTXC | ETH_FINE_DLY_RXC) : 0;
> > + delay_val |= mac_delay->tx_delay ? PHY_DLY_GTXC_ENABLE : 0;
> > + delay_val |= mac_delay->tx_delay & PHY_DLY_GTXC_STAGES;
> > + delay_val |= mac_delay->tx_inv ? PHY_DLY_GTXC_INV : 0;
> > + delay_val |= mac_delay->rx_delay ? PHY_DLY_RXC_ENABLE : 0;
> > + delay_val |= (mac_delay->rx_delay << PHY_DLY_RXC_SHIFT) &
> > + PHY_DLY_RXC_STAGES;
> > + delay_val |= mac_delay->rx_inv ? PHY_DLY_RXC_INV : 0;
> > + break;
> > + case PHY_INTERFACE_MODE_RGMII_TXID:
> > + fine_val = plat->fine_tune ? ETH_FINE_DLY_RXC : 0;
> > + delay_val |= mac_delay->rx_delay ? PHY_DLY_RXC_ENABLE : 0;
> > + delay_val |= (mac_delay->rx_delay << PHY_DLY_RXC_SHIFT) &
> > + PHY_DLY_RXC_STAGES;
> > + delay_val |= mac_delay->rx_inv ? PHY_DLY_RXC_INV : 0;
> why is PHY_INTERFACE_MODE_RGMII_TXID applied with *_RXC_* register
> bits, not with *_TXC_* bits? I'm a little confused about what path the
> register PHY_DLY_RXC_* cause the effects to? MAC to PHY or PHY to MAC?
>
The PHY_INTERFACE_MODE_RGMII_TXID is defined in
Documentation/networking/phy.txt
means phy will handle delay in tx path, so mac need handle delay in rx
path here.
> > + break;
> > + case PHY_INTERFACE_MODE_RGMII_RXID:
> > + fine_val = plat->fine_tune ? ETH_FINE_DLY_GTXC : 0;
> > + delay_val |= mac_delay->tx_delay ? PHY_DLY_GTXC_ENABLE : 0;
> > + delay_val |= mac_delay->tx_delay & PHY_DLY_GTXC_STAGES;
> > + delay_val |= mac_delay->tx_inv ? PHY_DLY_GTXC_INV : 0;
> ditto, as the above quetion
>
Similar answer as above.
> > + break;
> > + case PHY_INTERFACE_MODE_RGMII_ID:
> > + break;
> > + default:
> > + dev_err(plat->dev, "phy interface not supported\n");
> > + return -EINVAL;
> > + }
> > + regmap_write(plat->peri_regmap, PERI_ETH_PHY_DLY, delay_val);
> > + regmap_write(plat->peri_regmap, PERI_ETH_DLY_FINE, fine_val);
> > +
> > + return 0;
> > +}
> > +
> > +static const struct mediatek_dwmac_variant mt2712_gmac_variant = {
> > + .dwmac_set_phy_interface = mt2712_set_interface,
> > + .dwmac_set_delay = mt2712_set_delay,
> > + .clk_list = mt2712_dwmac_clk_l,
> > + .num_clks = ARRAY_SIZE(mt2712_dwmac_clk_l),
> > + .dma_bit_mask = 33,
> > + .rx_delay_max = 32,
> > + .tx_delay_max = 32,
> > +};
> > +
> > +static int mediatek_dwmac_config_dt(struct mediatek_dwmac_plat_data *plat)
> > +{
> > + u32 tx_delay, rx_delay;
> > +
> > + plat->peri_regmap = syscon_regmap_lookup_by_phandle(plat->np, "mediatek,pericfg");
> > + if (IS_ERR(plat->peri_regmap)) {
> > + dev_err(plat->dev, "Failed to get pericfg syscon\n");
> > + return PTR_ERR(plat->peri_regmap);
> > + }
> > +
> > + plat->phy_mode = of_get_phy_mode(plat->np);
> > + if (plat->phy_mode < 0) {
> > + dev_err(plat->dev, "not find phy-mode\n");
> > + return -EINVAL;
> > + }
> > +
> > + if (!of_property_read_u32(plat->np, "mediatek,tx-delay", &tx_delay)) {
> > + if (tx_delay < plat->variant->tx_delay_max) {
> > + plat->mac_delay.tx_delay = tx_delay;
> > + } else {
> > + dev_err(plat->dev, "Invalid TX clock delay: %d\n", tx_delay);
> > + return -EINVAL;
> > + }
> > + }
> > +
> > + if (!of_property_read_u32(plat->np, "mediatek,rx-delay", &rx_delay)) {
> > + if (rx_delay < plat->variant->rx_delay_max) {
> > + plat->mac_delay.rx_delay = rx_delay;
> > + } else {
> > + dev_err(plat->dev, "Invalid RX clock delay: %d\n", rx_delay);
> > + return -EINVAL;
> > + }
> > + }
> > +
> > + plat->mac_delay.tx_inv = of_property_read_bool(plat->np, "mediatek,txc-inverse");
> > + plat->mac_delay.rx_inv = of_property_read_bool(plat->np, "mediatek,rxc-inverse");
> > + plat->fine_tune = of_property_read_bool(plat->np, "mediatek,fine-tune");
> > + plat->rmii_rxc = of_property_read_bool(plat->np, "mediatek,rmii-rxc");
> > +
> > + return 0;
> > +}
> > +
> > +static int mediatek_dwmac_clk_init(struct mediatek_dwmac_plat_data *plat)
> > +{
> > + const struct mediatek_dwmac_variant *variant = plat->variant;
> > + int num = variant->num_clks;
> > + int i;
> put into the same line seems good
>
ok
> > +
> > + plat->clks = devm_kcalloc(plat->dev, num, sizeof(*plat->clks), GFP_KERNEL);
> > + if (!plat->clks)
> > + return -ENOMEM;
> > +
> > + for (i = 0; i < num; i++)
> > + plat->clks[i].id = variant->clk_list[i];
> > +
> > + return devm_clk_bulk_get(plat->dev, num, plat->clks);
> > +}
> > +
> > +static int mediatek_dwmac_init(struct platform_device *pdev, void *priv)
> > +{
> > + struct mediatek_dwmac_plat_data *plat = priv;
> > + const struct mediatek_dwmac_variant *variant = plat->variant;
> > + int ret = 0;
> zero initialized seems unnecessary
>
ok, will not initialized here
> > +
> > + ret = dma_set_mask_and_coherent(plat->dev, DMA_BIT_MASK(variant->dma_bit_mask));
> > + if (ret) {
> > + dev_err(plat->dev, "No suitable DMA available, err = %d\n", ret);
> > + return ret;
> > + }
> > +
> > + ret = variant->dwmac_set_phy_interface(plat);
> > + if (ret) {
> > + dev_err(plat->dev, "failed to set phy interface, err = %d\n", ret);
> > + return ret;
> > + }
> > +
> > + ret = variant->dwmac_set_delay(plat);
> > + if (ret) {
> > + dev_err(plat->dev, "failed to set delay value, err = %d\n", ret);
> > + return ret;
> > + }
> > +
> > + ret = clk_bulk_prepare_enable(variant->num_clks, plat->clks);
> > + if (ret) {
> > + dev_err(plat->dev, "failed to enable clks, err = %d\n", ret);
> > + return ret;
> > + }
> > +
> > + return 0;
> > +}
> > +
> > +static void mediatek_dwmac_exit(struct platform_device *pdev, void *priv)
> > +{
> > + struct mediatek_dwmac_plat_data *plat = priv;
> > + const struct mediatek_dwmac_variant *variant = plat->variant;
> > +
> > + clk_bulk_disable_unprepare(variant->num_clks, plat->clks);
> > +}
> > +
> > +static int mediatek_dwmac_probe(struct platform_device *pdev)
> > +{
> > + struct mediatek_dwmac_plat_data *priv_plat;
> > + struct plat_stmmacenet_data *plat_dat;
> > + struct stmmac_resources stmmac_res;
> > + int ret = 0;
> zero initialized seems unnecessary
>
ok, will not initialized here
> > +
> > + priv_plat = devm_kzalloc(&pdev->dev, sizeof(*priv_plat), GFP_KERNEL);
> > + if (!priv_plat)
> > + return -ENOMEM;
> > +
> > + priv_plat->variant = of_device_get_match_data(&pdev->dev);
> > + if (!priv_plat->variant) {
> > + dev_err(&pdev->dev, "Missing dwmac-mediatek variant\n");
> > + return -EINVAL;
> > + }
> > +
> > + priv_plat->dev = &pdev->dev;
> > + priv_plat->np = pdev->dev.of_node;
> > +
> > + ret = mediatek_dwmac_config_dt(priv_plat);
> > + if (ret)
> > + return ret;
> > +
> > + ret = mediatek_dwmac_clk_init(priv_plat);
> > + if (ret)
> > + return ret;
> > +
> > + ret = stmmac_get_platform_resources(pdev, &stmmac_res);
> > + if (ret)
> > + return ret;
> > +
> > + plat_dat = stmmac_probe_config_dt(pdev, &stmmac_res.mac);
> > + if (IS_ERR(plat_dat))
> > + return PTR_ERR(plat_dat);
> > +
> > + plat_dat->interface = priv_plat->phy_mode;
> > + /* clk_csr_i = 250-300MHz & MDC = clk_csr_i/124 */
> > + plat_dat->clk_csr = 5;
> > + plat_dat->has_gmac4 = 1;
> > + plat_dat->has_gmac = 0;
> > + plat_dat->pmt = 0;
> > + plat_dat->maxmtu = ETH_DATA_LEN;
> > + plat_dat->bsp_priv = priv_plat;
> > + plat_dat->init = mediatek_dwmac_init;
> > + plat_dat->exit = mediatek_dwmac_exit;
> > + mediatek_dwmac_init(pdev, priv_plat);
> > +
> > + ret = stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res);
> > + if (ret) {
> > + stmmac_remove_config_dt(pdev, plat_dat);
> > + return ret;
> > + }
> > +
> > + return 0;
> > +}
> > +
> > +static const struct of_device_id mediatek_dwmac_match[] = {
> > + { .compatible = "mediatek,mt2712-gmac",
> > + .data = &mt2712_gmac_variant },
> > + { }
> > +};
> > +
> > +MODULE_DEVICE_TABLE(of, mediatek_dwmac_match);
> > +
> > +static struct platform_driver mediatek_dwmac_driver = {
> > + .probe = mediatek_dwmac_probe,
> > + .remove = stmmac_pltfr_remove,
> > + .driver = {
> > + .name = "dwmac-mediatek",
> > + .pm = &stmmac_pltfr_pm_ops,
> > + .of_match_table = mediatek_dwmac_match,
> > + },
> > +};
> > +module_platform_driver(mediatek_dwmac_driver);
> > --
> > 1.7.9.5
> >
> >
> > _______________________________________________
> > Linux-mediatek mailing list
> > Linux-mediatek@lists.infradead.org
> > http://lists.infradead.org/mailman/listinfo/linux-mediatek
^ permalink raw reply
* Re: [PATCH net-next 1/2] net: bridge: add support for user-controlled bool options
From: Andrew Lunn @ 2018-11-22 15:35 UTC (permalink / raw)
To: Nikolay Aleksandrov; +Cc: netdev, roopa, davem, bridge
In-Reply-To: <20181122042925.8878-2-nikolay@cumulusnetworks.com>
On Thu, Nov 22, 2018 at 06:29:24AM +0200, Nikolay Aleksandrov wrote:
> We have been adding many new bridge options, a big number of which are
> boolean but still take up netlink attribute ids and waste space in the skb.
> Recently we discussed learning from link-local packets[1] and decided
> yet another new boolean option will be needed, thus introducing this API
> to save some bridge nl space.
> The API supports changing the value of multiple boolean options at once
> via the br_boolopt_multi struct which has an optmask (which options to
> set, bit per opt) and optval (options' new values). Future boolean
> options will only be added to the br_boolopt_id enum and then will have
> to be handled in br_boolopt_toggle/get. The API will automatically
> add the ability to change and export them via netlink, sysfs can use the
> single boolopt function versions to do the same. The behaviour with
> failing/succeeding is the same as with normal netlink option changing.
>
> If an option requires mapping to internal kernel flag or needs special
> configuration to be enabled then it should be handled in
> br_boolopt_toggle. It should also be able to retrieve an option's current
> state via br_boolopt_get.
>
> [1] https://www.spinics.net/lists/netdev/msg532698.html
>
> Signed-off-by: Nikolay Aleksandrov <nikolay@cumulusnetworks.com>
> ---
> include/uapi/linux/if_bridge.h | 18 +++++++++
> include/uapi/linux/if_link.h | 1 +
> net/bridge/br.c | 68 ++++++++++++++++++++++++++++++++++
> net/bridge/br_netlink.c | 17 ++++++++-
> net/bridge/br_private.h | 6 +++
> net/core/rtnetlink.c | 2 +-
> 6 files changed, 110 insertions(+), 2 deletions(-)
>
> diff --git a/include/uapi/linux/if_bridge.h b/include/uapi/linux/if_bridge.h
> index e41eda3c71f1..6dc02c03bdf8 100644
> --- a/include/uapi/linux/if_bridge.h
> +++ b/include/uapi/linux/if_bridge.h
> @@ -292,4 +292,22 @@ struct br_mcast_stats {
> __u64 mcast_bytes[BR_MCAST_DIR_SIZE];
> __u64 mcast_packets[BR_MCAST_DIR_SIZE];
> };
> +
> +/* bridge boolean options
> + * IMPORTANT: if adding a new option do not forget to handle
> + * it in br_boolopt_toggle/get and bridge sysfs
> + */
> +enum br_boolopt_id {
> + BR_BOOLOPT_MAX
> +};
> +
> +/* struct br_boolopt_multi - change multiple bridge boolean options
> + *
> + * @optval: new option values (bit per option)
> + * @optmask: options to change (bit per option)
> + */
> +struct br_boolopt_multi {
> + __u32 optval;
> + __u32 optmask;
> +};
Hi Nikolay
Thanks for handling this.
How many boolean options do we already have? What it the likelihood a
u32 is going to be too small, in a couple of years time?
I recently went through the pain of converting the u32 for
representing link modes in the phylib API to a linux bitmap. I'm just
wondering if in the long run, using a linux bitmap right from the
beginning would be better?
> +int br_boolopt_multi_toggle(struct net_bridge *br,
> + struct br_boolopt_multi *bm)
> +{
> + unsigned long bitmap = bm->optmask;
> + int err = 0;
> + int opt_id;
> +
> + for_each_set_bit(opt_id, &bitmap, BR_BOOLOPT_MAX) {
> + bool on = !!(bm->optval & BIT(opt_id));
> +
> + err = br_boolopt_toggle(br, opt_id, on);
> + if (err) {
> + br_debug(br, "boolopt multi-toggle error: option: %d current: %d new: %d error: %d\n",
> + opt_id, br_boolopt_get(br, opt_id), on, err);
Would it be possible to return that to userspace using the extended
error infrastructure?
Andrew
^ permalink raw reply
* Re: DSA support for Marvell 88e6065 switch
From: Lennert Buytenhek @ 2018-11-22 15:33 UTC (permalink / raw)
To: Pavel Machek; +Cc: Andrew Lunn, netdev, f.fainelli
In-Reply-To: <20181122132123.GA13466@amd>
On Thu, Nov 22, 2018 at 02:21:23PM +0100, Pavel Machek wrote:
> > > If I wanted it to work, what do I need to do? AFAICT phy autoprobing
> > > should just attach it as soon as it is compiled in?
> >
> > Nope. It is a switch, not a PHY. Switches are never auto-probed
> > because they are not guaranteed to have ID registers.
> >
> > You need to use the legacy device tree binding. Look in
> > Documentation/devicetree/bindings/net/dsa/dsa.txt, section Deprecated
> > Binding. You can get more examples if you checkout old kernels. Or
> > kirkwood-rd88f6281.dtsi, the dsa { } node which is disabled.
>
> Thanks; I ported code from mv88e66xx in the meantime, and switch
> appears to be detected.
>
> But I'm running into problems with tagging code, and I guess I'd like
> some help understanding.
>
> tag_trailer: allocates new skb, then copies data around.
>
> tag_qca: does dev->stats.tx_packets++, and reuses existing skb.
>
> tag_brcm: reuses existing skb.
>
> Is qca wrong in adjusting the statistics? Why does trailer allocate
> new skb?
>
> 6065 seems to use 2-byte header between "SFD" and "Destination
> address" in the ethernet frame. That's ... strange place to put
> header, as addresses are now shifted. I need to put ethernet in
> promisc mode (by running tcpdump) to get data moving.. and can not
> figure out what to do in tag_...
Does this switch chip not also support trailer mode?
There's basically four tagging modes for Marvell switch chips: header
mode (the one you described), trailer mode (tag_trailer.c), DSA and
ethertype DSA. The switch chips I worked on that didn't support
(ethertype) DSA tagging did support both header and trailer modes,
and I chose to run them in trailer mode for the reasons you describe
above, but if your chip doesn't support trailer mode, then yes,
you'll have to add support for header mode and put the underlying
interface into promiscuous mode and such.
^ permalink raw reply
* Dear Friend, i know that this mail will come to you as a surprise as we have never met before, i am contacting you independently of my investigation and no one is informed of this communication. I need your urgent assistance in transferring the sum of $10.5million immediately to your private account.The money has been here in our Bank lying dormant for years now without anybody coming for the claim of it. I want to release the money to you as the relative to our deceased customer (the account owner) who died a long with his supposed NEXT OF KIN since July 22, 2003. The Banking laws here does not allow such money to stay more than 16 years, because the money will be recalled to the Bank treasury account as unclaimed fund. I am ready to share with you 40% for you and 60% will be kept for me, by indicating your interest i will send you the full details on how the busines
From: Odo David @ 2018-11-22 15:31 UTC (permalink / raw)
^ permalink raw reply
* [PATCH v2 net-next] ptp: Fix pass zero to ERR_PTR() in ptp_clock_register
From: YueHaibing @ 2018-11-23 1:54 UTC (permalink / raw)
To: davem, richardcochran, dmitry.torokhov; +Cc: linux-kernel, netdev, YueHaibing
Fix smatch warning:
drivers/ptp/ptp_clock.c:298 ptp_clock_register() warn:
passing zero to 'ERR_PTR'
'err' should be set while device_create_with_groups and
pps_register_source fails
Fixes: 85a66e550195 ("ptp: create "pins" together with the rest of attributes")
Signed-off-by: YueHaibing <yuehaibing@huawei.com>
---
v2: fix wrong 'err' set while pps_register_source fails
---
drivers/ptp/ptp_clock.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/drivers/ptp/ptp_clock.c b/drivers/ptp/ptp_clock.c
index 40fda23..8a81eec 100644
--- a/drivers/ptp/ptp_clock.c
+++ b/drivers/ptp/ptp_clock.c
@@ -252,8 +252,10 @@ struct ptp_clock *ptp_clock_register(struct ptp_clock_info *info,
ptp->dev = device_create_with_groups(ptp_class, parent, ptp->devid,
ptp, ptp->pin_attr_groups,
"ptp%d", ptp->index);
- if (IS_ERR(ptp->dev))
+ if (IS_ERR(ptp->dev)) {
+ err = PTR_ERR(ptp->dev);
goto no_device;
+ }
/* Register a new PPS source. */
if (info->pps) {
@@ -264,6 +266,7 @@ struct ptp_clock *ptp_clock_register(struct ptp_clock_info *info,
pps.owner = info->owner;
ptp->pps_source = pps_register_source(&pps, PTP_PPS_DEFAULTS);
if (!ptp->pps_source) {
+ err = -EINVAL;
pr_err("failed to register pps source\n");
goto no_pps;
}
--
2.7.0
^ permalink raw reply related
* Re: [v5, PATCH 2/2] dt-binding: mediatek-dwmac: add binding document for MediaTek MT2712 DWMAC
From: biao huang @ 2018-11-23 1:31 UTC (permalink / raw)
To: Andrew Lunn
Cc: davem, robh+dt, honghui.zhang, yt.shen, liguo.zhang, mark.rutland,
nelson.chang, matthias.bgg, netdev, devicetree, linux-kernel,
linux-arm-kernel, linux-mediatek, joabreu
In-Reply-To: <20181122151932.GD15403@lunn.ch>
Dear Andrew,
Thanks for you remind.
Sincerely, I respect any comment from any reviewer. If I didn't reply
for any comment, really sorry for that.
As to this "tx-delay" issue, the following reply in v3 maybe ignored.
https://lkml.org/lkml/2018/11/19/158
"the delay time in mediatek dwmac design is not so accurate,
the current mt2712 and the following ICs will not use the
same delay design, but will use stages to indicate different
delay time.
so maybe "mediatek.tx-delay" represent the delay stage is a
good choice"
And to make it clearer here.
In mt2712, there are two delay macro circuit: named fine-tune and
coarse-tune.
a. fine-tune, 170+/-50ps per stage, total 32 stages
b. coarse-tune, 0.55+/-0.2ns per stage, total 32 stages
If we only consider mt2712, delay in fine-tune select a integer
multiple of 170ps, delay in coarse-tune select a integer multiple of
550ps, for stage 0~31, the delay in fine-tune will not have the same
value with that in coarse-tune.
OK, It seems the property "fine-tune" can be eliminated .
But the following ic will not have the same accuracy as mt2712,
and maybe will not have two delay macro circuit to be selected.
1. assume two delay macro circuit in the following ic,
fine-tune, 100ps per stage, coarse-tune, 0.55ns per stage,
if we want delay 2.2ns, fine-tune will get a 22, and coarse-tune get a
4. We can't distinguish which delay macro we are choosing.
2. assume only one delay macro circuit is used, a similar case as 1
will also increase the complexity of driver.
Then, we need define more flag property to know which delay macro we
are handling.
The common things for all delay macro circuit in MediaTek mac design is
the stages, not the accuracy. so if we maintain stage info in "mediatek,
tx-delay", we only need care which stage we should choose.
And for each IC, we will recommend a best stage as a candidate.
Above is my personal opinion, may be my understanding is wrong,
welcome for further discussion.
Thanks a lot.
On Thu, 2018-11-22 at 16:19 +0100, Andrew Lunn wrote:
> On Thu, Nov 22, 2018 at 06:28:41PM +0800, Biao Huang wrote:
> > The commit adds the device tree binding documentation for the MediaTek DWMAC
> > found on MediaTek MT2712.
> >
> > Signed-off-by: Biao Huang <biao.huang@mediatek.com>
>
> > +Optional properties:
> > +- mediatek,tx-delay: TX clock delay macro value. Range is 0~31. Default is 0.
> > + It should be defined for rgmii/rgmii-rxid/mii interface.
> > +- mediatek,rx-delay: RX clock delay macro value. Range is 0~31. Default is 0.
> > + It should be defined for rgmii/rgmii-txid/mii/rmii interface.
>
> You have received the same feedback at least twice now, from two
> different maintainers, that the delay should be specified in pS, and
> the driver should figure out what values to place into registers.
>
> You should not ignore feedback like that. If you don't understand the
> feedback, please ask us to explain it. If you don't agree with the
> feedback, you need to argue why you think it is wrong, or why what you
> are doing is better, etc.
>
> We are here to help, but just ignoring us won't get you anywhere.
>
> For the moment:
>
> NACK
>
> Andrew
^ permalink raw reply
* Re: [PATCH net-next] ptp: Fix pass zero to ERR_PTR() in ptp_clock_register
From: YueHaibing @ 2018-11-23 1:24 UTC (permalink / raw)
To: kbuild test robot
Cc: kbuild-all, davem, richardcochran, dmitry.torokhov, linux-kernel,
netdev
In-Reply-To: <201811230114.mywyGh81%fengguang.wu@intel.com>
Sorry for this, I send a wrong patch.
On 2018/11/23 1:30, kbuild test robot wrote:
> Hi YueHaibing,
>
> Thank you for the patch! Perhaps something to improve:
>
> [auto build test WARNING on net-next/master]
>
> url: https://github.com/0day-ci/linux/commits/YueHaibing/ptp-Fix-pass-zero-to-ERR_PTR-in-ptp_clock_register/20181123-010251
> config: x86_64-randconfig-x017-201846 (attached as .config)
> compiler: gcc-7 (Debian 7.3.0-1) 7.3.0
> reproduce:
> # save the attached .config to linux build tree
> make ARCH=x86_64
>
> All warnings (new ones prefixed by >>):
>
> drivers/ptp/ptp_clock.c: In function 'ptp_clock_register':
>>> drivers/ptp/ptp_clock.c:269:18: warning: passing argument 1 of 'PTR_ERR' makes pointer from integer without a cast [-Wint-conversion]
> err = PTR_ERR(-EINVAL);
> ^
> In file included from arch/x86/include/asm/processor.h:32:0,
> from arch/x86/include/asm/cpufeature.h:8,
> from arch/x86/include/asm/thread_info.h:53,
> from include/linux/thread_info.h:38,
> from arch/x86/include/asm/preempt.h:7,
> from include/linux/preempt.h:81,
> from include/linux/radix-tree.h:27,
> from include/linux/idr.h:15,
> from drivers/ptp/ptp_clock.c:20:
> include/linux/err.h:29:33: note: expected 'const void *' but argument is of type 'int'
> static inline long __must_check PTR_ERR(__force const void *ptr)
> ^~~~~~~
> Cyclomatic Complexity 5 include/linux/compiler.h:__write_once_size
> Cyclomatic Complexity 1 arch/x86/include/asm/bitops.h:fls64
> Cyclomatic Complexity 1 include/linux/log2.h:__ilog2_u64
> Cyclomatic Complexity 1 include/linux/list.h:INIT_LIST_HEAD
> Cyclomatic Complexity 1 include/linux/math64.h:div_u64_rem
> Cyclomatic Complexity 1 include/asm-generic/getorder.h:__get_order
> Cyclomatic Complexity 3 include/linux/string.h:memset
> Cyclomatic Complexity 1 include/linux/err.h:ERR_PTR
> Cyclomatic Complexity 1 include/linux/err.h:PTR_ERR
> Cyclomatic Complexity 1 include/linux/spinlock.h:spinlock_check
> Cyclomatic Complexity 1 include/linux/spinlock.h:spin_unlock_irqrestore
> Cyclomatic Complexity 1 include/linux/ktime.h:ktime_to_ns
> Cyclomatic Complexity 1 include/linux/slab.h:kmalloc_type
> Cyclomatic Complexity 28 include/linux/slab.h:kmalloc_index
> Cyclomatic Complexity 68 include/linux/slab.h:kmalloc_large
> Cyclomatic Complexity 4 include/linux/slab.h:kmalloc
> Cyclomatic Complexity 1 include/linux/slab.h:kzalloc
> Cyclomatic Complexity 2 drivers/ptp/ptp_private.h:queue_cnt
> Cyclomatic Complexity 1 drivers/ptp/ptp_clock.c:queue_free
> Cyclomatic Complexity 2 drivers/ptp/ptp_clock.c:enqueue_external_timestamp
> Cyclomatic Complexity 1 drivers/ptp/ptp_clock.c:scaled_ppm_to_ppb
> Cyclomatic Complexity 1 drivers/ptp/ptp_clock.c:ptp_clock_getres
> Cyclomatic Complexity 1 drivers/ptp/ptp_clock.c:ptp_clock_settime
> Cyclomatic Complexity 2 drivers/ptp/ptp_clock.c:ptp_clock_gettime
> Cyclomatic Complexity 1 drivers/ptp/ptp_clock.c:delete_ptp_clock
> Cyclomatic Complexity 2 drivers/ptp/ptp_clock.c:ptp_aux_kworker
> Cyclomatic Complexity 2 include/linux/ktime.h:ktime_set
> Cyclomatic Complexity 1 include/linux/ktime.h:timespec64_to_ktime
> Cyclomatic Complexity 9 drivers/ptp/ptp_clock.c:ptp_clock_adjtime
> Cyclomatic Complexity 1 include/linux/err.h:IS_ERR
> Cyclomatic Complexity 1 include/linux/pps_kernel.h:pps_get_ts
> Cyclomatic Complexity 1 drivers/ptp/ptp_clock.c:ptp_exit
> Cyclomatic Complexity 3 drivers/ptp/ptp_clock.c:ptp_init
> Cyclomatic Complexity 13 drivers/ptp/ptp_clock.c:ptp_clock_register
> Cyclomatic Complexity 3 drivers/ptp/ptp_clock.c:ptp_clock_unregister
> Cyclomatic Complexity 4 drivers/ptp/ptp_clock.c:ptp_clock_event
> Cyclomatic Complexity 1 drivers/ptp/ptp_clock.c:ptp_clock_index
> Cyclomatic Complexity 5 drivers/ptp/ptp_clock.c:ptp_find_pin
> Cyclomatic Complexity 1 drivers/ptp/ptp_clock.c:ptp_schedule_worker
>
> vim +/PTR_ERR +269 drivers/ptp/ptp_clock.c
>
> 205
> 206 struct ptp_clock *ptp_clock_register(struct ptp_clock_info *info,
> 207 struct device *parent)
> 208 {
> 209 struct ptp_clock *ptp;
> 210 int err = 0, index, major = MAJOR(ptp_devt);
> 211
> 212 if (info->n_alarm > PTP_MAX_ALARMS)
> 213 return ERR_PTR(-EINVAL);
> 214
> 215 /* Initialize a clock structure. */
> 216 err = -ENOMEM;
> 217 ptp = kzalloc(sizeof(struct ptp_clock), GFP_KERNEL);
> 218 if (ptp == NULL)
> 219 goto no_memory;
> 220
> 221 index = ida_simple_get(&ptp_clocks_map, 0, MINORMASK + 1, GFP_KERNEL);
> 222 if (index < 0) {
> 223 err = index;
> 224 goto no_slot;
> 225 }
> 226
> 227 ptp->clock.ops = ptp_clock_ops;
> 228 ptp->clock.release = delete_ptp_clock;
> 229 ptp->info = info;
> 230 ptp->devid = MKDEV(major, index);
> 231 ptp->index = index;
> 232 spin_lock_init(&ptp->tsevq.lock);
> 233 mutex_init(&ptp->tsevq_mux);
> 234 mutex_init(&ptp->pincfg_mux);
> 235 init_waitqueue_head(&ptp->tsev_wq);
> 236
> 237 if (ptp->info->do_aux_work) {
> 238 kthread_init_delayed_work(&ptp->aux_work, ptp_aux_kworker);
> 239 ptp->kworker = kthread_create_worker(0, "ptp%d", ptp->index);
> 240 if (IS_ERR(ptp->kworker)) {
> 241 err = PTR_ERR(ptp->kworker);
> 242 pr_err("failed to create ptp aux_worker %d\n", err);
> 243 goto kworker_err;
> 244 }
> 245 }
> 246
> 247 err = ptp_populate_pin_groups(ptp);
> 248 if (err)
> 249 goto no_pin_groups;
> 250
> 251 /* Create a new device in our class. */
> 252 ptp->dev = device_create_with_groups(ptp_class, parent, ptp->devid,
> 253 ptp, ptp->pin_attr_groups,
> 254 "ptp%d", ptp->index);
> 255 if (IS_ERR(ptp->dev)) {
> 256 err = PTR_ERR(ptp->dev);
> 257 goto no_device;
> 258 }
> 259
> 260 /* Register a new PPS source. */
> 261 if (info->pps) {
> 262 struct pps_source_info pps;
> 263 memset(&pps, 0, sizeof(pps));
> 264 snprintf(pps.name, PPS_MAX_NAME_LEN, "ptp%d", index);
> 265 pps.mode = PTP_PPS_MODE;
> 266 pps.owner = info->owner;
> 267 ptp->pps_source = pps_register_source(&pps, PTP_PPS_DEFAULTS);
> 268 if (!ptp->pps_source) {
> > 269 err = PTR_ERR(-EINVAL);
> 270 pr_err("failed to register pps source\n");
> 271 goto no_pps;
> 272 }
> 273 }
> 274
> 275 /* Create a posix clock. */
> 276 err = posix_clock_register(&ptp->clock, ptp->devid);
> 277 if (err) {
> 278 pr_err("failed to create posix clock\n");
> 279 goto no_clock;
> 280 }
> 281
> 282 return ptp;
> 283
> 284 no_clock:
> 285 if (ptp->pps_source)
> 286 pps_unregister_source(ptp->pps_source);
> 287 no_pps:
> 288 device_destroy(ptp_class, ptp->devid);
> 289 no_device:
> 290 ptp_cleanup_pin_groups(ptp);
> 291 no_pin_groups:
> 292 if (ptp->kworker)
> 293 kthread_destroy_worker(ptp->kworker);
> 294 kworker_err:
> 295 mutex_destroy(&ptp->tsevq_mux);
> 296 mutex_destroy(&ptp->pincfg_mux);
> 297 ida_simple_remove(&ptp_clocks_map, index);
> 298 no_slot:
> 299 kfree(ptp);
> 300 no_memory:
> 301 return ERR_PTR(err);
> 302 }
> 303 EXPORT_SYMBOL(ptp_clock_register);
> 304
>
> ---
> 0-DAY kernel test infrastructure Open Source Technology Center
> https://lists.01.org/pipermail/kbuild-all Intel Corporation
>
^ permalink raw reply
* [PATCH net] be2net: Fix NULL pointer dereference in be_tx_timeout()
From: Petr Oros @ 2018-11-22 14:24 UTC (permalink / raw)
To: netdev; +Cc: ivecera, davem
The driver enumerates Tx queues in ndo_tx_timeout() handler, here is
possible race with be_update_queues. For this case we set carrier_off.
It prevents netdev watchdog to be fired after be_clear_queues().
The watchdog timeout doesn't make any sense here as we re-creating queues.
Reproducer:
We can reproduce bug with ethtool when changing queue count
ethtool -L $netif combined 1
ethtool -L $netif combined 32
If oops is not triggered imediately, just run it again or in loop.
Oops:
[ 865.768648] NETDEV WATCHDOG: enp4s0f0 (be2net): transmit queue 0 timed out
[ 865.775539] WARNING: CPU: 3 PID: 0 at net/sched/sch_generic.c:461 dev_watchdog+0x20d/0x220
[ 865.783796] Modules linked in: be2net intel_rapl sb_edac x86_pkg_temp_thermal intel_powerclamp coretemp kvm_intel kvm irqbypass crct10dif_pclmul crc32_pclmul iTCO_wdt iTCO_vendor_support ghash_clmulni_intel mei_me intel_cstate intel_uncore ipmi_ssif mei ipmi_si pcspkr sg i2c_i801 joydev lpc_ich intel_rapl_perf ipmi_devintf ioatdma ipmi_msghandler xfs libcrc32c sd_mod mgag200 drm_kms_helper syscopyarea sysfillrect sysimgblt fb_sys_fops ttm ahci libahci crc32c_intel drm serio_raw libata igb dca i2c_algo_bit wmi dm_mirror dm_region_hash dm_log dm_mod [last unloaded: be2net]
[ 865.834289] CPU: 3 PID: 0 Comm: swapper/3 Not tainted 4.20.0-rc3+ #2
[ 865.840640] Hardware name: Supermicro X9DBU/X9DBU, BIOS 3.2 01/15/2015
[ 865.847168] RIP: 0010:dev_watchdog+0x20d/0x220
[ 865.851612] Code: 00 49 63 4e e0 eb 92 4c 89 e7 c6 05 a5 de c9 00 01 e8 f7 b2 fc ff 89 d9 4c 89 e6 48 c7 c7 a0 d1 b2 99 48 89 c2 e8 7d b0 98 ff <0f> 0b eb c0 0f 1f 44 00 00 66 2e 0f 1f 84 00 00 00 00 00 66 66 66
[ 865.870358] RSP: 0018:ffff9bee73ac3e88 EFLAGS: 00010282
[ 865.875583] RAX: 0000000000000000 RBX: 0000000000000000 RCX: 000000000000083f
[ 865.882707] RDX: 0000000000000000 RSI: 00000000000000f6 RDI: 000000000000003f
[ 865.889832] RBP: ffff9bee5fa0045c R08: 0000000000000824 R09: 0000000000000007
[ 865.896956] R10: 0000000000000000 R11: ffffffff9a3f162d R12: ffff9bee5fa00000
[ 865.904088] R13: 0000000000000003 R14: ffff9bee5fa00480 R15: 0000000000000020
[ 865.911214] FS: 0000000000000000(0000) GS:ffff9bee73ac0000(0000) knlGS:0000000000000000
[ 865.919298] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[ 865.925037] CR2: 00005580497ce040 CR3: 00000002cf60a004 CR4: 00000000000606e0
[ 865.932170] Call Trace:
[ 865.934626] <IRQ>
[ 865.936645] ? pfifo_fast_dequeue+0x160/0x160
[ 865.941005] call_timer_fn+0x2b/0x130
[ 865.944670] run_timer_softirq+0x3b9/0x3f0
[ 865.948768] ? tick_sched_timer+0x37/0x70
[ 865.952779] ? __hrtimer_run_queues+0x110/0x280
[ 865.957314] __do_softirq+0xdd/0x2fe
[ 865.960896] irq_exit+0xfa/0x100
[ 865.964125] smp_apic_timer_interrupt+0x74/0x140
[ 865.968745] apic_timer_interrupt+0xf/0x20
[ 865.972844] </IRQ>
[ 865.974953] RIP: 0010:cpuidle_enter_state+0xb0/0x320
[ 865.979915] Code: 89 c3 66 66 66 66 90 31 ff e8 0c 07 a6 ff 80 7c 24 0b 00 74 12 9c 58 f6 c4 02 0f 85 46 02 00 00 31 ff e8 33 e0 ab ff fb 85 ed <0f> 88 1a 02 00 00 48 b8 ff ff ff ff f3 01 00 00 48 2b 1c 24 48 39
[ 865.998661] RSP: 0018:ffffbc9ac19e7ea0 EFLAGS: 00000206 ORIG_RAX: ffffffffffffff13
[ 866.006225] RAX: ffff9bee73ae1dc0 RBX: 000000c9938e11ae RCX: 000000000000001f
[ 866.013350] RDX: 000000c9938e11ae RSI: 00000000435e532a RDI: 0000000000000000
[ 866.020474] RBP: 0000000000000005 R08: 0000000000000002 R09: 0000000000021640
[ 866.027598] R10: 00009c434b946fde R11: ffff9bee73ae0e44 R12: ffffffff99d27538
[ 866.034723] R13: ffff9bee73aec628 R14: 0000000000000005 R15: 0000000000000000
[ 866.041860] do_idle+0x1f1/0x230
[ 866.045091] cpu_startup_entry+0x19/0x20
[ 866.049016] start_secondary+0x195/0x1e0
[ 866.052943] secondary_startup_64+0xb6/0xc0
[ 866.057129] ---[ end trace dead88c26bcd8261 ]---
[ 866.061750] be2net 0000:04:00.0: TXQ Dump: 0 H: 0 T: 0 used: 0, qid: 0x2
[ 866.068452] BUG: unable to handle kernel NULL pointer dereference at 0000000000000000
[ 866.076273] PGD 0 P4D 0
[ 866.078810] Oops: 0000 [#1] SMP PTI
[ 866.082305] CPU: 3 PID: 0 Comm: swapper/3 Tainted: G W 4.20.0-rc3+ #2
[ 866.090041] Hardware name: Supermicro X9DBU/X9DBU, BIOS 3.2 01/15/2015
[ 866.096566] RIP: 0010:be_tx_timeout+0x7c/0x300 [be2net]
[ 866.101786] Code: 8b 45 1c 41 8b 4d 14 48 89 df 31 ed 45 8b 4d 18 48 c7 c6 80 51 2c c0 50 45 8b 45 10 8b 54 24 14 e8 09 a7 cb d8 4d 8b 7d 20 59 <41> 8b 0c af 45 8b 44 af 04 41 8b 74 af 0c 45 8b 4c af 08 89 ca 44
[ 866.120532] RSP: 0018:ffff9bee73ac3e38 EFLAGS: 00010246
[ 866.125758] RAX: 0000000000000000 RBX: ffff9bee72d6b0b0 RCX: 0000000000000002
[ 866.132882] RDX: 0000000000000000 RSI: 00000000000000f6 RDI: 000000000000003f
[ 866.140014] RBP: 0000000000000000 R08: 000000000000084d R09: 0000000000000007
[ 866.147138] R10: 0000000000000000 R11: ffffffff9a3f162d R12: ffffffffc02c60ab
[ 866.154263] R13: ffff9bee5fa04b40 R14: ffffffffc02c613a R15: 0000000000000000
[ 866.161388] FS: 0000000000000000(0000) GS:ffff9bee73ac0000(0000) knlGS:0000000000000000
[ 866.169472] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[ 866.175210] CR2: 0000000000000000 CR3: 00000002cf60a004 CR4: 00000000000606e0
[ 866.182334] Call Trace:
[ 866.184781] <IRQ>
[ 866.186799] dev_watchdog+0x1e4/0x220
[ 866.190466] ? pfifo_fast_dequeue+0x160/0x160
[ 866.194825] call_timer_fn+0x2b/0x130
[ 866.198491] run_timer_softirq+0x3b9/0x3f0
[ 866.202590] ? tick_sched_timer+0x37/0x70
[ 866.206604] ? __hrtimer_run_queues+0x110/0x280
[ 866.211134] __do_softirq+0xdd/0x2fe
[ 866.214715] irq_exit+0xfa/0x100
[ 866.217948] smp_apic_timer_interrupt+0x74/0x140
[ 866.222566] apic_timer_interrupt+0xf/0x20
[ 866.226664] </IRQ>
[ 866.228762] RIP: 0010:cpuidle_enter_state+0xb0/0x320
[ 866.233727] Code: 89 c3 66 66 66 66 90 31 ff e8 0c 07 a6 ff 80 7c 24 0b 00 74 12 9c 58 f6 c4 02 0f 85 46 02 00 00 31 ff e8 33 e0 ab ff fb 85 ed <0f> 88 1a 02 00 00 48 b8 ff ff ff ff f3 01 00 00 48 2b 1c 24 48 39
[ 866.252465] RSP: 0018:ffffbc9ac19e7ea0 EFLAGS: 00000206 ORIG_RAX: ffffffffffffff13
[ 866.260031] RAX: ffff9bee73ae1dc0 RBX: 000000c9938e11ae RCX: 000000000000001f
[ 866.267164] RDX: 000000c9938e11ae RSI: 00000000435e532a RDI: 0000000000000000
[ 866.274288] RBP: 0000000000000005 R08: 0000000000000002 R09: 0000000000021640
[ 866.281421] R10: 00009c434b946fde R11: ffff9bee73ae0e44 R12: ffffffff99d27538
[ 866.288545] R13: ffff9bee73aec628 R14: 0000000000000005 R15: 0000000000000000
[ 866.295680] do_idle+0x1f1/0x230
[ 866.298913] cpu_startup_entry+0x19/0x20
[ 866.302839] start_secondary+0x195/0x1e0
[ 866.306764] secondary_startup_64+0xb6/0xc0
[ 866.310948] Modules linked in: be2net intel_rapl sb_edac x86_pkg_temp_thermal intel_powerclamp coretemp kvm_intel kvm irqbypass crct10dif_pclmul crc32_pclmul iTCO_wdt iTCO_vendor_support ghash_clmulni_intel mei_me intel_cstate intel_uncore ipmi_ssif mei ipmi_si pcspkr sg i2c_i801 joydev lpc_ich intel_rapl_perf ipmi_devintf ioatdma ipmi_msghandler xfs libcrc32c sd_mod mgag200 drm_kms_helper syscopyarea sysfillrect sysimgblt fb_sys_fops ttm ahci libahci crc32c_intel drm serio_raw libata igb dca i2c_algo_bit wmi dm_mirror dm_region_hash dm_log dm_mod [last unloaded: be2net]
[ 866.361432] CR2: 0000000000000000
[ 866.364748] ---[ end trace dead88c26bcd8262 ]---
[ 866.507013] RIP: 0010:be_tx_timeout+0x7c/0x300 [be2net]
[ 866.512234] Code: 8b 45 1c 41 8b 4d 14 48 89 df 31 ed 45 8b 4d 18 48 c7 c6 80 51 2c c0 50 45 8b 45 10 8b 54 24 14 e8 09 a7 cb d8 4d 8b 7d 20 59 <41> 8b 0c af 45 8b 44 af 04 41 8b 74 af 0c 45 8b 4c af 08 89 ca 44
[ 866.530980] RSP: 0018:ffff9bee73ac3e38 EFLAGS: 00010246
[ 866.536206] RAX: 0000000000000000 RBX: ffff9bee72d6b0b0 RCX: 0000000000000002
[ 866.543330] RDX: 0000000000000000 RSI: 00000000000000f6 RDI: 000000000000003f
[ 866.550454] RBP: 0000000000000000 R08: 000000000000084d R09: 0000000000000007
[ 866.557578] R10: 0000000000000000 R11: ffffffff9a3f162d R12: ffffffffc02c60ab
[ 866.564710] R13: ffff9bee5fa04b40 R14: ffffffffc02c613a R15: 0000000000000000
[ 866.571835] FS: 0000000000000000(0000) GS:ffff9bee73ac0000(0000) knlGS:0000000000000000
[ 866.579920] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[ 866.585658] CR2: 0000000000000000 CR3: 00000002cf60a004 CR4: 00000000000606e0
[ 866.592784] Kernel panic - not syncing: Fatal exception in interrupt
[ 866.599179] Kernel Offset: 0x17a00000 from 0xffffffff81000000 (relocation range: 0xffffffff80000000-0xffffffffbfffffff)
Fixes: c1b3bdb2ffa9 ("be2net: gather debug info and reset adapter (only for Lancer) on a tx-timeout")
Signed-off-by: Petr Oros <poros@redhat.com>
---
drivers/net/ethernet/emulex/benet/be_main.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c
index c5ad7a4f4d83..02202c5e6794 100644
--- a/drivers/net/ethernet/emulex/benet/be_main.c
+++ b/drivers/net/ethernet/emulex/benet/be_main.c
@@ -4700,8 +4700,11 @@ int be_update_queues(struct be_adapter *adapter)
struct net_device *netdev = adapter->netdev;
int status;
- if (netif_running(netdev))
+ if (netif_running(netdev)) {
+ /* prevent netdev watchdog during tx queue destroy */
+ netif_carrier_off(netdev);
be_close(netdev);
+ }
be_cancel_worker(adapter);
--
2.18.1
^ permalink raw reply related
* Re: [v5, PATCH 1/2] net:stmmac: dwmac-mediatek: add support for mt2712
From: Sean Wang @ 2018-11-23 0:54 UTC (permalink / raw)
To: biao.huang
Cc: davem, robh+dt, mark.rutland, devicetree, nelson.chang,
Andrew Lunn, netdev, Liguo Zhang, linux-kernel, Matthias Brugger,
joabreu, linux-mediatek, honghui.zhang, linux-arm-kernel
In-Reply-To: <1542882521-18874-2-git-send-email-biao.huang@mediatek.com>
On Thu, Nov 22, 2018 at 2:29 AM Biao Huang <biao.huang@mediatek.com> wrote:
>
> Add Ethernet support for MediaTek SoCs from the mt2712 family
>
> Signed-off-by: Biao Huang <biao.huang@mediatek.com>
> ---
> drivers/net/ethernet/stmicro/stmmac/Kconfig | 8 +
> drivers/net/ethernet/stmicro/stmmac/Makefile | 1 +
> .../net/ethernet/stmicro/stmmac/dwmac-mediatek.c | 364 ++++++++++++++++++++
> 3 files changed, 373 insertions(+)
> create mode 100644 drivers/net/ethernet/stmicro/stmmac/dwmac-mediatek.c
>
> diff --git a/drivers/net/ethernet/stmicro/stmmac/Kconfig b/drivers/net/ethernet/stmicro/stmmac/Kconfig
> index 324049e..6209cc1 100644
> --- a/drivers/net/ethernet/stmicro/stmmac/Kconfig
> +++ b/drivers/net/ethernet/stmicro/stmmac/Kconfig
> @@ -75,6 +75,14 @@ config DWMAC_LPC18XX
> ---help---
> Support for NXP LPC18xx/43xx DWMAC Ethernet.
>
> +config DWMAC_MEDIATEK
> + tristate "MediaTek MT27xx GMAC support"
> + depends on OF && (ARCH_MEDIATEK || COMPILE_TEST)
> + help
> + Support for MediaTek GMAC Ethernet controller.
> +
> + This selects the MT2712 SoC support for the stmmac driver.
> +
> config DWMAC_MESON
> tristate "Amlogic Meson dwmac support"
> default ARCH_MESON
> diff --git a/drivers/net/ethernet/stmicro/stmmac/Makefile b/drivers/net/ethernet/stmicro/stmmac/Makefile
> index 99967a8..bf09701 100644
> --- a/drivers/net/ethernet/stmicro/stmmac/Makefile
> +++ b/drivers/net/ethernet/stmicro/stmmac/Makefile
> @@ -13,6 +13,7 @@ obj-$(CONFIG_STMMAC_PLATFORM) += stmmac-platform.o
> obj-$(CONFIG_DWMAC_ANARION) += dwmac-anarion.o
> obj-$(CONFIG_DWMAC_IPQ806X) += dwmac-ipq806x.o
> obj-$(CONFIG_DWMAC_LPC18XX) += dwmac-lpc18xx.o
> +obj-$(CONFIG_DWMAC_MEDIATEK) += dwmac-mediatek.o
> obj-$(CONFIG_DWMAC_MESON) += dwmac-meson.o dwmac-meson8b.o
> obj-$(CONFIG_DWMAC_OXNAS) += dwmac-oxnas.o
> obj-$(CONFIG_DWMAC_ROCKCHIP) += dwmac-rk.o
> diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-mediatek.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-mediatek.c
> new file mode 100644
> index 0000000..dd8d4cc
> --- /dev/null
> +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-mediatek.c
> @@ -0,0 +1,364 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright (c) 2018 MediaTek Inc.
> + */
> +#include <linux/io.h>
> +#include <linux/mfd/syscon.h>
> +#include <linux/of.h>
> +#include <linux/of_device.h>
> +#include <linux/of_net.h>
> +#include <linux/regmap.h>
> +#include <linux/stmmac.h>
> +
> +#include "stmmac.h"
> +#include "stmmac_platform.h"
> +
> +/* Peri Configuration register for mt2712 */
> +#define PERI_ETH_PHY_INTF_SEL 0x418
> +#define PHY_INTF_MII_GMII 0
> +#define PHY_INTF_RGMII 1
> +#define PHY_INTF_RMII 4
> +#define RMII_CLK_SRC_RXC BIT(4)
> +#define RMII_CLK_SRC_INTERNAL BIT(5)
> +
> +#define PERI_ETH_PHY_DLY 0x428
> +#define PHY_DLY_GTXC_INV BIT(6)
> +#define PHY_DLY_GTXC_ENABLE BIT(5)
> +#define PHY_DLY_GTXC_STAGES GENMASK(4, 0)
> +#define PHY_DLY_TXC_INV BIT(20)
> +#define PHY_DLY_TXC_ENABLE BIT(19)
> +#define PHY_DLY_TXC_STAGES GENMASK(18, 14)
> +#define PHY_DLY_TXC_SHIFT 14
> +#define PHY_DLY_RXC_INV BIT(13)
> +#define PHY_DLY_RXC_ENABLE BIT(12)
> +#define PHY_DLY_RXC_STAGES GENMASK(11, 7)
> +#define PHY_DLY_RXC_SHIFT 7
> +
> +#define PERI_ETH_DLY_FINE 0x800
> +#define ETH_RMII_DLY_TX_INV BIT(2)
> +#define ETH_FINE_DLY_GTXC BIT(1)
> +#define ETH_FINE_DLY_RXC BIT(0)
> +
> +struct mac_delay_struct {
> + u32 tx_delay;
> + u32 rx_delay;
> + u32 tx_inv;
bool should be enough
> + u32 rx_inv;
bool should be enough
> +};
> +
> +struct mediatek_dwmac_plat_data {
> + const struct mediatek_dwmac_variant *variant;
> + struct mac_delay_struct mac_delay;
> + struct clk_bulk_data *clks;
> + struct device_node *np;
> + struct regmap *peri_regmap;
> + struct device *dev;
> + int fine_tune;
bool
> + int phy_mode;
> + int rmii_rxc;
bool
> +};
> +
> +struct mediatek_dwmac_variant {
> + int (*dwmac_set_phy_interface)(struct mediatek_dwmac_plat_data *plat);
> + int (*dwmac_set_delay)(struct mediatek_dwmac_plat_data *plat);
> +
> + /* clock ids to be requested */
> + const char * const *clk_list;
> + int num_clks;
> +
> + u32 dma_bit_mask;
> + u32 rx_delay_max;
> + u32 tx_delay_max;
> +};
> +
> +/* list of clocks required for mac */
> +static const char * const mt2712_dwmac_clk_l[] = {
> + "axi", "apb", "mac_main", "ptp_ref"
> +};
> +
> +static int mt2712_set_interface(struct mediatek_dwmac_plat_data *plat)
> +{
> + int rmii_rxc = plat->rmii_rxc ? RMII_CLK_SRC_RXC : 0;
> + u32 intf_val = 0;
> +
> + /* select phy interface in top control domain */
> + switch (plat->phy_mode) {
> + case PHY_INTERFACE_MODE_MII:
> + intf_val |= PHY_INTF_MII_GMII;
> + break;
> + case PHY_INTERFACE_MODE_RMII:
> + intf_val |= PHY_INTF_RMII;
> + intf_val |= rmii_rxc;
how about putting into one line such as intf_val |= (PHY_INTF_RMII | rmii_rxc) ?
> + break;
> + case PHY_INTERFACE_MODE_RGMII:
> + case PHY_INTERFACE_MODE_RGMII_TXID:
> + case PHY_INTERFACE_MODE_RGMII_RXID:
> + case PHY_INTERFACE_MODE_RGMII_ID:
> + intf_val |= PHY_INTF_RGMII;
> + break;
> + default:
> + dev_err(plat->dev, "phy interface not supported\n");
> + return -EINVAL;
> + }
> +
> + regmap_write(plat->peri_regmap, PERI_ETH_PHY_INTF_SEL, intf_val);
> +
> + return 0;
> +}
> +
> +static int mt2712_set_delay(struct mediatek_dwmac_plat_data *plat)
> +{
> + struct mac_delay_struct *mac_delay = &plat->mac_delay;
> + u32 delay_val = 0;
> + u32 fine_val = 0;
The same type declaration can be put into the one line
> +
> + switch (plat->phy_mode) {
There exists some room for code optimization in the switch statement
such as PHY_INTERFACE_MODE_MII and PHY_INTERFACE_MODE_RGMII both are
almost the same and even the configuration for the other PHY modes can
reuse their partial setup. It appears to be better using a common way
to set up various PHY modes.
> + case PHY_INTERFACE_MODE_MII:
> + delay_val |= mac_delay->tx_delay ? PHY_DLY_TXC_ENABLE : 0;
> + delay_val |= (mac_delay->tx_delay << PHY_DLY_TXC_SHIFT) &
> + PHY_DLY_TXC_STAGES;
> + delay_val |= mac_delay->tx_inv ? PHY_DLY_TXC_INV : 0;
> + delay_val |= mac_delay->rx_delay ? PHY_DLY_RXC_ENABLE : 0;
> + delay_val |= (mac_delay->rx_delay << PHY_DLY_RXC_SHIFT) &
> + PHY_DLY_RXC_STAGES;
> + delay_val |= mac_delay->rx_inv ? PHY_DLY_RXC_INV : 0;
> + break;
> + case PHY_INTERFACE_MODE_RMII:
> + if (plat->rmii_rxc) {
> + delay_val |= mac_delay->rx_delay ?
> + PHY_DLY_RXC_ENABLE : 0;
> + delay_val |= (mac_delay->rx_delay <<
> + PHY_DLY_RXC_SHIFT) & PHY_DLY_RXC_STAGES;
> + delay_val |= mac_delay->rx_inv ? PHY_DLY_RXC_INV : 0;
> + fine_val |= mac_delay->tx_inv ?
> + ETH_RMII_DLY_TX_INV : 0;
why is fine_val got from tx_inv?
> + } else {
> + delay_val |= mac_delay->rx_delay ?
> + PHY_DLY_TXC_ENABLE : 0;
> + delay_val |= (mac_delay->rx_delay <<
> + PHY_DLY_TXC_SHIFT) & PHY_DLY_TXC_STAGES;
> + delay_val |= mac_delay->rx_inv ? PHY_DLY_TXC_INV : 0;
> + fine_val |= mac_delay->tx_inv ?
> + ETH_RMII_DLY_TX_INV : 0;
ditto, why is fine_val got from tx_inv?
> + }
> + break;
> + case PHY_INTERFACE_MODE_RGMII:
> + fine_val = plat->fine_tune ?
> + (ETH_FINE_DLY_GTXC | ETH_FINE_DLY_RXC) : 0;
> + delay_val |= mac_delay->tx_delay ? PHY_DLY_GTXC_ENABLE : 0;
> + delay_val |= mac_delay->tx_delay & PHY_DLY_GTXC_STAGES;
> + delay_val |= mac_delay->tx_inv ? PHY_DLY_GTXC_INV : 0;
> + delay_val |= mac_delay->rx_delay ? PHY_DLY_RXC_ENABLE : 0;
> + delay_val |= (mac_delay->rx_delay << PHY_DLY_RXC_SHIFT) &
> + PHY_DLY_RXC_STAGES;
> + delay_val |= mac_delay->rx_inv ? PHY_DLY_RXC_INV : 0;
> + break;
> + case PHY_INTERFACE_MODE_RGMII_TXID:
> + fine_val = plat->fine_tune ? ETH_FINE_DLY_RXC : 0;
> + delay_val |= mac_delay->rx_delay ? PHY_DLY_RXC_ENABLE : 0;
> + delay_val |= (mac_delay->rx_delay << PHY_DLY_RXC_SHIFT) &
> + PHY_DLY_RXC_STAGES;
> + delay_val |= mac_delay->rx_inv ? PHY_DLY_RXC_INV : 0;
why is PHY_INTERFACE_MODE_RGMII_TXID applied with *_RXC_* register
bits, not with *_TXC_* bits? I'm a little confused about what path the
register PHY_DLY_RXC_* cause the effects to? MAC to PHY or PHY to MAC?
> + break;
> + case PHY_INTERFACE_MODE_RGMII_RXID:
> + fine_val = plat->fine_tune ? ETH_FINE_DLY_GTXC : 0;
> + delay_val |= mac_delay->tx_delay ? PHY_DLY_GTXC_ENABLE : 0;
> + delay_val |= mac_delay->tx_delay & PHY_DLY_GTXC_STAGES;
> + delay_val |= mac_delay->tx_inv ? PHY_DLY_GTXC_INV : 0;
ditto, as the above quetion
> + break;
> + case PHY_INTERFACE_MODE_RGMII_ID:
> + break;
> + default:
> + dev_err(plat->dev, "phy interface not supported\n");
> + return -EINVAL;
> + }
> + regmap_write(plat->peri_regmap, PERI_ETH_PHY_DLY, delay_val);
> + regmap_write(plat->peri_regmap, PERI_ETH_DLY_FINE, fine_val);
> +
> + return 0;
> +}
> +
> +static const struct mediatek_dwmac_variant mt2712_gmac_variant = {
> + .dwmac_set_phy_interface = mt2712_set_interface,
> + .dwmac_set_delay = mt2712_set_delay,
> + .clk_list = mt2712_dwmac_clk_l,
> + .num_clks = ARRAY_SIZE(mt2712_dwmac_clk_l),
> + .dma_bit_mask = 33,
> + .rx_delay_max = 32,
> + .tx_delay_max = 32,
> +};
> +
> +static int mediatek_dwmac_config_dt(struct mediatek_dwmac_plat_data *plat)
> +{
> + u32 tx_delay, rx_delay;
> +
> + plat->peri_regmap = syscon_regmap_lookup_by_phandle(plat->np, "mediatek,pericfg");
> + if (IS_ERR(plat->peri_regmap)) {
> + dev_err(plat->dev, "Failed to get pericfg syscon\n");
> + return PTR_ERR(plat->peri_regmap);
> + }
> +
> + plat->phy_mode = of_get_phy_mode(plat->np);
> + if (plat->phy_mode < 0) {
> + dev_err(plat->dev, "not find phy-mode\n");
> + return -EINVAL;
> + }
> +
> + if (!of_property_read_u32(plat->np, "mediatek,tx-delay", &tx_delay)) {
> + if (tx_delay < plat->variant->tx_delay_max) {
> + plat->mac_delay.tx_delay = tx_delay;
> + } else {
> + dev_err(plat->dev, "Invalid TX clock delay: %d\n", tx_delay);
> + return -EINVAL;
> + }
> + }
> +
> + if (!of_property_read_u32(plat->np, "mediatek,rx-delay", &rx_delay)) {
> + if (rx_delay < plat->variant->rx_delay_max) {
> + plat->mac_delay.rx_delay = rx_delay;
> + } else {
> + dev_err(plat->dev, "Invalid RX clock delay: %d\n", rx_delay);
> + return -EINVAL;
> + }
> + }
> +
> + plat->mac_delay.tx_inv = of_property_read_bool(plat->np, "mediatek,txc-inverse");
> + plat->mac_delay.rx_inv = of_property_read_bool(plat->np, "mediatek,rxc-inverse");
> + plat->fine_tune = of_property_read_bool(plat->np, "mediatek,fine-tune");
> + plat->rmii_rxc = of_property_read_bool(plat->np, "mediatek,rmii-rxc");
> +
> + return 0;
> +}
> +
> +static int mediatek_dwmac_clk_init(struct mediatek_dwmac_plat_data *plat)
> +{
> + const struct mediatek_dwmac_variant *variant = plat->variant;
> + int num = variant->num_clks;
> + int i;
put into the same line seems good
> +
> + plat->clks = devm_kcalloc(plat->dev, num, sizeof(*plat->clks), GFP_KERNEL);
> + if (!plat->clks)
> + return -ENOMEM;
> +
> + for (i = 0; i < num; i++)
> + plat->clks[i].id = variant->clk_list[i];
> +
> + return devm_clk_bulk_get(plat->dev, num, plat->clks);
> +}
> +
> +static int mediatek_dwmac_init(struct platform_device *pdev, void *priv)
> +{
> + struct mediatek_dwmac_plat_data *plat = priv;
> + const struct mediatek_dwmac_variant *variant = plat->variant;
> + int ret = 0;
zero initialized seems unnecessary
> +
> + ret = dma_set_mask_and_coherent(plat->dev, DMA_BIT_MASK(variant->dma_bit_mask));
> + if (ret) {
> + dev_err(plat->dev, "No suitable DMA available, err = %d\n", ret);
> + return ret;
> + }
> +
> + ret = variant->dwmac_set_phy_interface(plat);
> + if (ret) {
> + dev_err(plat->dev, "failed to set phy interface, err = %d\n", ret);
> + return ret;
> + }
> +
> + ret = variant->dwmac_set_delay(plat);
> + if (ret) {
> + dev_err(plat->dev, "failed to set delay value, err = %d\n", ret);
> + return ret;
> + }
> +
> + ret = clk_bulk_prepare_enable(variant->num_clks, plat->clks);
> + if (ret) {
> + dev_err(plat->dev, "failed to enable clks, err = %d\n", ret);
> + return ret;
> + }
> +
> + return 0;
> +}
> +
> +static void mediatek_dwmac_exit(struct platform_device *pdev, void *priv)
> +{
> + struct mediatek_dwmac_plat_data *plat = priv;
> + const struct mediatek_dwmac_variant *variant = plat->variant;
> +
> + clk_bulk_disable_unprepare(variant->num_clks, plat->clks);
> +}
> +
> +static int mediatek_dwmac_probe(struct platform_device *pdev)
> +{
> + struct mediatek_dwmac_plat_data *priv_plat;
> + struct plat_stmmacenet_data *plat_dat;
> + struct stmmac_resources stmmac_res;
> + int ret = 0;
zero initialized seems unnecessary
> +
> + priv_plat = devm_kzalloc(&pdev->dev, sizeof(*priv_plat), GFP_KERNEL);
> + if (!priv_plat)
> + return -ENOMEM;
> +
> + priv_plat->variant = of_device_get_match_data(&pdev->dev);
> + if (!priv_plat->variant) {
> + dev_err(&pdev->dev, "Missing dwmac-mediatek variant\n");
> + return -EINVAL;
> + }
> +
> + priv_plat->dev = &pdev->dev;
> + priv_plat->np = pdev->dev.of_node;
> +
> + ret = mediatek_dwmac_config_dt(priv_plat);
> + if (ret)
> + return ret;
> +
> + ret = mediatek_dwmac_clk_init(priv_plat);
> + if (ret)
> + return ret;
> +
> + ret = stmmac_get_platform_resources(pdev, &stmmac_res);
> + if (ret)
> + return ret;
> +
> + plat_dat = stmmac_probe_config_dt(pdev, &stmmac_res.mac);
> + if (IS_ERR(plat_dat))
> + return PTR_ERR(plat_dat);
> +
> + plat_dat->interface = priv_plat->phy_mode;
> + /* clk_csr_i = 250-300MHz & MDC = clk_csr_i/124 */
> + plat_dat->clk_csr = 5;
> + plat_dat->has_gmac4 = 1;
> + plat_dat->has_gmac = 0;
> + plat_dat->pmt = 0;
> + plat_dat->maxmtu = ETH_DATA_LEN;
> + plat_dat->bsp_priv = priv_plat;
> + plat_dat->init = mediatek_dwmac_init;
> + plat_dat->exit = mediatek_dwmac_exit;
> + mediatek_dwmac_init(pdev, priv_plat);
> +
> + ret = stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res);
> + if (ret) {
> + stmmac_remove_config_dt(pdev, plat_dat);
> + return ret;
> + }
> +
> + return 0;
> +}
> +
> +static const struct of_device_id mediatek_dwmac_match[] = {
> + { .compatible = "mediatek,mt2712-gmac",
> + .data = &mt2712_gmac_variant },
> + { }
> +};
> +
> +MODULE_DEVICE_TABLE(of, mediatek_dwmac_match);
> +
> +static struct platform_driver mediatek_dwmac_driver = {
> + .probe = mediatek_dwmac_probe,
> + .remove = stmmac_pltfr_remove,
> + .driver = {
> + .name = "dwmac-mediatek",
> + .pm = &stmmac_pltfr_pm_ops,
> + .of_match_table = mediatek_dwmac_match,
> + },
> +};
> +module_platform_driver(mediatek_dwmac_driver);
> --
> 1.7.9.5
>
>
> _______________________________________________
> Linux-mediatek mailing list
> Linux-mediatek@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-mediatek
^ permalink raw reply
* [PATCH V2 net-next 3/8] net: hns3: Add "FD flow table" info query function
From: Salil Mehta @ 2018-11-22 14:09 UTC (permalink / raw)
To: davem
Cc: salil.mehta, yisen.zhuang, lipeng321, mehta.salil, netdev,
linux-kernel, linuxarm, liuzhongzhu
In-Reply-To: <20181122140948.23504-1-salil.mehta@huawei.com>
From: liuzhongzhu <liuzhongzhu@huawei.com>
All the Flow Director rules are stored in tcam blocks.
For each bit of tcam entry, the match value
depends on two input value(x, y).
debugfs command:
echo dump fd tcam > cmd
Sample output:
root@(none)# echo dump fd tcam > cmd
hns3 0000:7d:00.0: read result tcam key x(31):
hns3 0000:7d:00.0: 00000000
hns3 0000:7d:00.0: 00000000
hns3 0000:7d:00.0: 00000000
hns3 0000:7d:00.0: 08000000
hns3 0000:7d:00.0: 00000600
hns3 0000:7d:00.0: 00000000
hns3 0000:7d:00.0: 00000000
hns3 0000:7d:00.0: 00000000
hns3 0000:7d:00.0: 00000000
hns3 0000:7d:00.0: 00000000
hns3 0000:7d:00.0: 00000000
hns3 0000:7d:00.0: 00000000
hns3 0000:7d:00.0: 00000000
hns3 0000:7d:00.0: read result tcam key y(31):
hns3 0000:7d:00.0: 00000000
hns3 0000:7d:00.0: 00000000
hns3 0000:7d:00.0: 00000000
hns3 0000:7d:00.0: f7ff0000
hns3 0000:7d:00.0: 0000f900
hns3 0000:7d:00.0: 00000000
hns3 0000:7d:00.0: 00000000
hns3 0000:7d:00.0: 00000000
hns3 0000:7d:00.0: 00000000
hns3 0000:7d:00.0: 00000000
hns3 0000:7d:00.0: 00000000
hns3 0000:7d:00.0: 00000000
hns3 0000:7d:00.0: 0000fff8
root@(none)#
Signed-off-by: liuzhongzhu <liuzhongzhu@huawei.com>
Signed-off-by: Salil Mehta <salil.mehta@huawei.com>
---
drivers/net/ethernet/hisilicon/hns3/hnae3.h | 1 +
drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c | 2 +
.../net/ethernet/hisilicon/hns3/hns3pf/Makefile | 2 +-
.../ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c | 77 ++++++++++++++++++++++
.../ethernet/hisilicon/hns3/hns3pf/hclge_main.c | 1 +
.../ethernet/hisilicon/hns3/hns3pf/hclge_main.h | 1 +
6 files changed, 83 insertions(+), 1 deletion(-)
create mode 100644 drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c
diff --git a/drivers/net/ethernet/hisilicon/hns3/hnae3.h b/drivers/net/ethernet/hisilicon/hns3/hnae3.h
index f32f075..a1707b7 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hnae3.h
+++ b/drivers/net/ethernet/hisilicon/hns3/hnae3.h
@@ -453,6 +453,7 @@ struct hnae3_ae_ops {
struct ethtool_rxnfc *cmd, u32 *rule_locs);
int (*restore_fd_rules)(struct hnae3_handle *handle);
void (*enable_fd)(struct hnae3_handle *handle, bool enable);
+ int (*dbg_run_cmd)(struct hnae3_handle *handle, char *cmd_buf);
pci_ers_result_t (*process_hw_error)(struct hnae3_ae_dev *ae_dev);
bool (*get_hw_reset_stat)(struct hnae3_handle *handle);
bool (*ae_dev_resetting)(struct hnae3_handle *handle);
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c b/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c
index c0685b3..82fe7b9 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c
@@ -200,6 +200,8 @@ static ssize_t hns3_dbg_cmd_write(struct file *filp, const char __user *buffer,
hns3_dbg_help(handle);
else if (strncmp(cmd_buf, "queue info", 10) == 0)
ret = hns3_dbg_queue_info(handle, cmd_buf);
+ else if (handle->ae_algo->ops->dbg_run_cmd)
+ ret = handle->ae_algo->ops->dbg_run_cmd(handle, cmd_buf);
if (ret)
hns3_dbg_help(handle);
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/Makefile b/drivers/net/ethernet/hisilicon/hns3/hns3pf/Makefile
index 580e817..fffe8c1 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/Makefile
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/Makefile
@@ -6,6 +6,6 @@
ccflags-y := -Idrivers/net/ethernet/hisilicon/hns3
obj-$(CONFIG_HNS3_HCLGE) += hclge.o
-hclge-objs = hclge_main.o hclge_cmd.o hclge_mdio.o hclge_tm.o hclge_mbx.o hclge_err.o
+hclge-objs = hclge_main.o hclge_cmd.o hclge_mdio.o hclge_tm.o hclge_mbx.o hclge_err.o hclge_debugfs.o
hclge-$(CONFIG_HNS3_DCB) += hclge_dcb.o
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c
new file mode 100644
index 0000000..cf1355b
--- /dev/null
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c
@@ -0,0 +1,77 @@
+// SPDX-License-Identifier: GPL-2.0+
+/* Copyright (c) 2018-2019 Hisilicon Limited. */
+
+#include <linux/device.h>
+
+#include "hclge_cmd.h"
+#include "hclge_main.h"
+#include "hnae3.h"
+
+static void hclge_dbg_fd_tcam_read(struct hclge_dev *hdev, u8 stage,
+ bool sel_x, u32 loc)
+{
+ struct hclge_fd_tcam_config_1_cmd *req1;
+ struct hclge_fd_tcam_config_2_cmd *req2;
+ struct hclge_fd_tcam_config_3_cmd *req3;
+ struct hclge_desc desc[3];
+ int ret, i;
+ u32 *req;
+
+ hclge_cmd_setup_basic_desc(&desc[0], HCLGE_OPC_FD_TCAM_OP, true);
+ desc[0].flag |= cpu_to_le16(HCLGE_CMD_FLAG_NEXT);
+ hclge_cmd_setup_basic_desc(&desc[1], HCLGE_OPC_FD_TCAM_OP, true);
+ desc[1].flag |= cpu_to_le16(HCLGE_CMD_FLAG_NEXT);
+ hclge_cmd_setup_basic_desc(&desc[2], HCLGE_OPC_FD_TCAM_OP, true);
+
+ req1 = (struct hclge_fd_tcam_config_1_cmd *)desc[0].data;
+ req2 = (struct hclge_fd_tcam_config_2_cmd *)desc[1].data;
+ req3 = (struct hclge_fd_tcam_config_3_cmd *)desc[2].data;
+
+ req1->stage = stage;
+ req1->xy_sel = sel_x ? 1 : 0;
+ req1->index = cpu_to_le32(loc);
+
+ ret = hclge_cmd_send(&hdev->hw, desc, 3);
+ if (ret)
+ return;
+
+ dev_info(&hdev->pdev->dev, " read result tcam key %s(%u):\n",
+ sel_x ? "x" : "y", loc);
+
+ req = (u32 *)req1->tcam_data;
+ for (i = 0; i < 2; i++)
+ dev_info(&hdev->pdev->dev, "%08x\n", *req++);
+
+ req = (u32 *)req2->tcam_data;
+ for (i = 0; i < 6; i++)
+ dev_info(&hdev->pdev->dev, "%08x\n", *req++);
+
+ req = (u32 *)req3->tcam_data;
+ for (i = 0; i < 5; i++)
+ dev_info(&hdev->pdev->dev, "%08x\n", *req++);
+}
+
+static void hclge_dbg_fd_tcam(struct hclge_dev *hdev)
+{
+ u32 i;
+
+ for (i = 0; i < hdev->fd_cfg.rule_num[0]; i++) {
+ hclge_dbg_fd_tcam_read(hdev, 0, true, i);
+ hclge_dbg_fd_tcam_read(hdev, 0, false, i);
+ }
+}
+
+int hclge_dbg_run_cmd(struct hnae3_handle *handle, char *cmd_buf)
+{
+ struct hclge_vport *vport = hclge_get_vport(handle);
+ struct hclge_dev *hdev = vport->back;
+
+ if (strncmp(cmd_buf, "dump fd tcam", 12) == 0) {
+ hclge_dbg_fd_tcam(hdev);
+ } else {
+ dev_info(&hdev->pdev->dev, "unknown command\n");
+ return -EINVAL;
+ }
+
+ return 0;
+}
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
index f78b8e1..696cb53 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
@@ -7826,6 +7826,7 @@ static const struct hnae3_ae_ops hclge_ops = {
.get_fd_all_rules = hclge_get_all_rules,
.restore_fd_rules = hclge_restore_fd_entries,
.enable_fd = hclge_enable_fd,
+ .dbg_run_cmd = hclge_dbg_run_cmd,
.process_hw_error = hclge_process_ras_hw_error,
.get_hw_reset_stat = hclge_get_hw_reset_stat,
.ae_dev_resetting = hclge_ae_dev_resetting,
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h
index 5f24dd4..4122ad1 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h
@@ -814,4 +814,5 @@ int hclge_func_reset_cmd(struct hclge_dev *hdev, int func_id);
int hclge_vport_start(struct hclge_vport *vport);
void hclge_vport_stop(struct hclge_vport *vport);
int hclge_set_vport_mtu(struct hclge_vport *vport, int new_mtu);
+int hclge_dbg_run_cmd(struct hnae3_handle *handle, char *cmd_buf);
#endif
--
2.7.4
^ permalink raw reply related
* [PATCH V2 net-next 0/8] net: hns3: Adds support of debugfs to HNS3 driver
From: Salil Mehta @ 2018-11-22 14:09 UTC (permalink / raw)
To: davem
Cc: salil.mehta, yisen.zhuang, lipeng321, mehta.salil, netdev,
linux-kernel, linuxarm
This patchset adds support of debugfs to the HNS3 driver.
Support has been added to query info related to below items:
1. Queue related ("echo queue info [queue no] > cmd")
2. Flow Director ("echo dump fd tcam > cmd")
3. TC config ("echo dump tc > cmd")
4. Transmit Module/Scheduler ("echo dump tm > cmd")
5. QoS pause ("echo dump qos pause cfg > cmd")
6. QoS buffer ("echo dump qos pri map > cmd")
7. QoS prio map ("echo dump qos buf cfg > cmd")
NOTE: Above commands are *read-only* and are only intended to
query the information from the SoC(and dump inside the kernel,
for now) and in no way tries to perform write operations for
the purpose of configuration etc.
Change Log
----------
V1-->V2:
* Addressed the comments provided by Jakub Kicinski.
1. Removed the .rej files mistakenly made part of Flow Director patch.
Link: https://lkml.org/lkml/2018/11/20/249
2. Added command summary in the cover letter
Link: https://lkml.org/lkml/2018/11/22/1
liuzhongzhu (8):
net: hns3: Add debugfs framework registration
net: hns3: Add "queue info" query function
net: hns3: Add "FD flow table" info query function
net: hns3: Add "tc config" info query function
net: hns3: Add "tm config" info query function
net: hns3: Add "qos pause" config info query function
net: hns3: Add "qos prio map" info query function
net: hns3: Add "qos buffer" config info query function
drivers/net/ethernet/hisilicon/hns3/Makefile | 2 +-
drivers/net/ethernet/hisilicon/hns3/hnae3.h | 2 +
drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c | 265 +++++++++++
drivers/net/ethernet/hisilicon/hns3/hns3_enet.c | 17 +-
drivers/net/ethernet/hisilicon/hns3/hns3_enet.h | 4 +
.../net/ethernet/hisilicon/hns3/hns3pf/Makefile | 2 +-
.../net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h | 1 +
.../ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c | 487 +++++++++++++++++++++
.../ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.h | 23 +
.../ethernet/hisilicon/hns3/hns3pf/hclge_main.c | 1 +
.../ethernet/hisilicon/hns3/hns3pf/hclge_main.h | 1 +
.../net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.h | 6 +
12 files changed, 807 insertions(+), 4 deletions(-)
create mode 100644 drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c
create mode 100644 drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c
create mode 100644 drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.h
--
2.7.4
^ permalink raw reply
* [PATCH v3 4/4] selftests: add a test for bpf_prog_test_run_xattr
From: Lorenz Bauer @ 2018-11-22 14:09 UTC (permalink / raw)
To: ast, daniel; +Cc: netdev, linux-api, ys114321, Lorenz Bauer
In-Reply-To: <20181122140910.1079-1-lmb@cloudflare.com>
Make sure that bpf_prog_test_run_xattr returns the correct length
and that the kernel respects the output size hint. Also check
that errno indicates ENOSPC if there is a short output buffer given.
Signed-off-by: Lorenz Bauer <lmb@cloudflare.com>
---
tools/testing/selftests/bpf/test_progs.c | 49 ++++++++++++++++++++++++
1 file changed, 49 insertions(+)
diff --git a/tools/testing/selftests/bpf/test_progs.c b/tools/testing/selftests/bpf/test_progs.c
index c1e688f61061..f9f5b1dbcc83 100644
--- a/tools/testing/selftests/bpf/test_progs.c
+++ b/tools/testing/selftests/bpf/test_progs.c
@@ -124,6 +124,54 @@ static void test_pkt_access(void)
bpf_object__close(obj);
}
+static void test_prog_run_xattr(void)
+{
+ const char *file = "./test_pkt_access.o";
+ __u32 duration, retval, size_out;
+ struct bpf_object *obj;
+ char buf[10];
+ int err;
+ struct bpf_prog_test_run_attr tattr = {
+ .repeat = 1,
+ .data = &pkt_v4,
+ .size = sizeof(pkt_v4),
+ .data_out = buf,
+ .size_out = 5,
+ };
+
+ err = bpf_prog_load(file, BPF_PROG_TYPE_SCHED_CLS, &obj,
+ &tattr.prog_fd);
+ if (CHECK(err, "load", "err %d errno %d\n", err, errno))
+ return;
+
+ memset(buf, 0, sizeof(buf));
+
+ err = bpf_prog_test_run_xattr(&tattr, &size_out, &retval, &duration);
+ CHECK(err != -1 || errno != ENOSPC || retval, "run",
+ "err %d errno %d retval %d\n", err, errno, retval);
+
+ CHECK(size_out != sizeof(pkt_v4), "output_size",
+ "incorrect output size, want %lu have %u\n",
+ sizeof(pkt_v4), size_out);
+
+ CHECK(buf[5] != 0, "overflow",
+ "BPF_PROG_TEST_RUN ignored size hint\n");
+
+ tattr.data_out = NULL;
+ tattr.size_out = 0;
+ errno = 0;
+
+ err = bpf_prog_test_run_xattr(&tattr, NULL, &retval, &duration);
+ CHECK(err || errno || retval, "run_no_output",
+ "err %d errno %d retval %d\n", err, errno, retval);
+
+ tattr.size_out = 1;
+ err = bpf_prog_test_run_xattr(&tattr, NULL, NULL, &duration);
+ CHECK(err != -EINVAL, "run_wrong_size_out", "err %d\n", err);
+
+ bpf_object__close(obj);
+}
+
static void test_xdp(void)
{
struct vip key4 = {.protocol = 6, .family = AF_INET};
@@ -1837,6 +1885,7 @@ int main(void)
jit_enabled = is_jit_enabled();
test_pkt_access();
+ test_prog_run_xattr();
test_xdp();
test_xdp_adjust_tail();
test_l4lb_all();
--
2.17.1
^ 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