* Re: [PATCH bpf-next v2] tools: bpftool: add "prog run" subcommand to test-run programs
From: Y Song @ 2019-07-05 18:21 UTC (permalink / raw)
To: Quentin Monnet
Cc: Alexei Starovoitov, Daniel Borkmann, bpf, netdev, oss-drivers
In-Reply-To: <20190705175433.22511-1-quentin.monnet@netronome.com>
On Fri, Jul 5, 2019 at 10:54 AM Quentin Monnet
<quentin.monnet@netronome.com> wrote:
>
> Add a new "bpftool prog run" subcommand to run a loaded program on input
> data (and possibly with input context) passed by the user.
>
> Print output data (and output context if relevant) into a file or into
> the console. Print return value and duration for the test run into the
> console.
>
> A "repeat" argument can be passed to run the program several times in a
> row.
>
> The command does not perform any kind of verification based on program
> type (Is this program type allowed to use an input context?) or on data
> consistency (Can I work with empty input data?), this is left to the
> kernel.
>
> Example invocation:
>
> # perl -e 'print "\x0" x 14' | ./bpftool prog run \
> pinned /sys/fs/bpf/sample_ret0 \
> data_in - data_out - repeat 5
> 0000000 0000 0000 0000 0000 0000 0000 0000 | ........ ......
> Return value: 0, duration (average): 260ns
>
> When one of data_in or ctx_in is "-", bpftool reads from standard input,
> in binary format. Other formats (JSON, hexdump) might be supported (via
> an optional command line keyword like "data_fmt_in") in the future if
> relevant, but this would require doing more parsing in bpftool.
>
> v2:
> - Fix argument names for function check_single_stdin(). (Yonghong)
>
> Signed-off-by: Quentin Monnet <quentin.monnet@netronome.com>
> Reviewed-by: Jakub Kicinski <jakub.kicinski@netronome.com>
Acked-by: Yonghong Song <yhs@fb.com>
^ permalink raw reply
* Re: [PATCH v2] rtl8xxxu: Fix wifi low signal strength issue of RTL8723BU
From: Jes Sorensen @ 2019-07-05 18:24 UTC (permalink / raw)
To: Chris Chiu
Cc: Kalle Valo, David Miller, linux-wireless, netdev, Linux Kernel,
Linux Upstreaming Team
In-Reply-To: <CAB4CAwc8jJQ2f8vpoB0Y6sc0fJmmrq+5rRuJ+TqGMMgCczRi+A@mail.gmail.com>
On 7/4/19 10:27 PM, Chris Chiu wrote:
> On Fri, Jul 5, 2019 at 12:43 AM Jes Sorensen <jes.sorensen@gmail.com> wrote:
>>
>> On 7/4/19 6:55 AM, Chris Chiu wrote:
>>> The WiFi tx power of RTL8723BU is extremely low after booting. So
>>> the WiFi scan gives very limited AP list and it always fails to
>>> connect to the selected AP. This module only supports 1x1 antenna
>>> and the antenna is switched to bluetooth due to some incorrect
>>> register settings.
>>>
>>> Compare with the vendor driver https://github.com/lwfinger/rtl8723bu,
>>> we realized that the 8723bu's enable_rf() does the same thing as
>>> rtw_btcoex_HAL_Initialize() in vendor driver. And it by default
>>> sets the antenna path to BTC_ANT_PATH_BT which we verified it's
>>> the cause of the wifi weak tx power. The vendor driver will set
>>> the antenna path to BTC_ANT_PATH_PTA in the consequent btcoexist
>>> mechanism, by the function halbtc8723b1ant_PsTdma.
>>>
>>> This commit hand over the antenna control to PTA(Packet Traffic
>>> Arbitration), which compares the weight of bluetooth/wifi traffic
>>> then determine whether to continue current wifi traffic or not.
>>> After PTA take control, The wifi signal will be back to normal and
>>> the bluetooth scan can also work at the same time. However, the
>>> btcoexist still needs to be handled under different circumstances.
>>> If there's a BT connection established, the wifi still fails to
>>> connect until BT disconnected.
>>>
>>> Signed-off-by: Chris Chiu <chiu@endlessm.com>
>>> ---
>>>
>>>
>>> Note:
>>> v2:
>>> - Replace BIT(11) with the descriptive definition
>>> - Meaningful comment for the REG_S0S1_PATH_SWITCH setting
>>>
>>>
>>> drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8723b.c | 11 ++++++++---
>>> drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c | 3 ++-
>>> 2 files changed, 10 insertions(+), 4 deletions(-)
>>>
>>> diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8723b.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8723b.c
>>> index 3adb1d3d47ac..ceffe05bd65b 100644
>>> --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8723b.c
>>> +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8723b.c
>>> @@ -1525,7 +1525,7 @@ static void rtl8723b_enable_rf(struct rtl8xxxu_priv *priv)
>>> /*
>>> * WLAN action by PTA
>>> */
>>> - rtl8xxxu_write8(priv, REG_WLAN_ACT_CONTROL_8723B, 0x04);
>>> + rtl8xxxu_write8(priv, REG_WLAN_ACT_CONTROL_8723B, 0x0c);
>>>
>>> /*
>>> * BT select S0/S1 controlled by WiFi
>>> @@ -1568,9 +1568,14 @@ static void rtl8723b_enable_rf(struct rtl8xxxu_priv *priv)
>>> rtl8xxxu_gen2_h2c_cmd(priv, &h2c, sizeof(h2c.ant_sel_rsv));
>>>
>>> /*
>>> - * 0x280, 0x00, 0x200, 0x80 - not clear
>>> + * Different settings per different antenna position.
>>> + * Antenna Position: | Normal Inverse
>>> + * --------------------------------------------------
>>> + * Antenna switch to BT: | 0x280, 0x00
>>> + * Antenna switch to WiFi: | 0x0, 0x280
>>> + * Antenna switch to PTA: | 0x200, 0x80
>>> */
>>> - rtl8xxxu_write32(priv, REG_S0S1_PATH_SWITCH, 0x00);
>>> + rtl8xxxu_write32(priv, REG_S0S1_PATH_SWITCH, 0x80);
>>
>> Per the documentation, shouldn't this be set to 0x200 then rather than 0x80?
>>
> Per the code before REG_S0S1_PATH_SWITCH setting, the driver has told
> the co-processor the antenna is inverse.
> memset(&h2c, 0, sizeof(struct h2c_cmd));
> h2c.ant_sel_rsv.cmd = H2C_8723B_ANT_SEL_RSV;
> h2c.ant_sel_rsv.ant_inverse = 1;
> h2c.ant_sel_rsv.int_switch_type = 0;
> rtl8xxxu_gen2_h2c_cmd(priv, &h2c, sizeof(h2c.ant_sel_rsv));
>
> At least the current modification is consistent with the antenna
> inverse setting.
> I'll verify on vendor driver about when/how the inverse be determined.
Fair enough :)
Cheers,
Jes
^ permalink raw reply
* Re: [PATCH] rtl8xxxu: Fix wifi low signal strength issue of RTL8723BU
From: Jes Sorensen @ 2019-07-05 18:27 UTC (permalink / raw)
To: Daniel Drake
Cc: Chris Chiu, Kalle Valo, David Miller, linux-wireless, netdev,
Linux Kernel, Linux Upstreaming Team, Larry Finger
In-Reply-To: <CAD8Lp44HLPgOU+Z+w4Pq6ukLjZv2hM0=uBL7pWzQp+RsdRgG6Q@mail.gmail.com>
On 7/4/19 11:44 PM, Daniel Drake wrote:
> On Wed, Jul 3, 2019 at 8:59 PM Jes Sorensen <jes.sorensen@gmail.com> wrote:
>> My point is this seems to be very dongle dependent :( We have to be
>> careful not breaking it for some users while fixing it for others.
>
> Do you still have your device?
>
> Once we get to the point when you are happy with Chris's two patches
> here on a code review level, we'll reach out to other driver
> contributors plus people who previously complained about these types
> of problems, and see if we can get some wider testing.
I should have them, but I won't have access to them for another 2.5
weeks unfortunately.
Cheers,
Jes
^ permalink raw reply
* [net-next] net: fib_rules: do not flow dissect local packets
From: Petar Penkov @ 2019-07-05 18:46 UTC (permalink / raw)
To: netdev; +Cc: davem, roopa, edumazet, Petar Penkov
Rules matching on loopback iif do not need early flow dissection as the
packet originates from the host. Stop counting such rules in
fib_rule_requires_fldissect
Signed-off-by: Petar Penkov <ppenkov@google.com>
---
include/net/fib_rules.h | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/include/net/fib_rules.h b/include/net/fib_rules.h
index eba8465e1d86..20dcadd8eed9 100644
--- a/include/net/fib_rules.h
+++ b/include/net/fib_rules.h
@@ -180,9 +180,9 @@ static inline bool fib_rule_port_range_compare(struct fib_rule_port_range *a,
static inline bool fib_rule_requires_fldissect(struct fib_rule *rule)
{
- return rule->ip_proto ||
+ return rule->iifindex != LOOPBACK_IFINDEX && (rule->ip_proto ||
fib_rule_port_range_set(&rule->sport_range) ||
- fib_rule_port_range_set(&rule->dport_range);
+ fib_rule_port_range_set(&rule->dport_range));
}
struct fib_rules_ops *fib_rules_register(const struct fib_rules_ops *,
--
2.22.0.410.gd8fdbe21b5-goog
^ permalink raw reply related
* Re: [PATCH 01/10] net: hisilicon: Add support for HI13X1 to hip04_eth
From: David Miller @ 2019-07-05 18:58 UTC (permalink / raw)
To: xiaojiangfeng
Cc: yisen.zhuang, salil.mehta, dingtianhong, robh+dt, mark.rutland,
netdev, devicetree, linux-kernel, leeyou.li, xiekunxun,
jianping.liu, nixiaoming
In-Reply-To: <1562307028-103555-1-git-send-email-xiaojiangfeng@huawei.com>
You must always provide a proper "[PATCH 00/NN]" header posting for
a patch series which describes at a high level what the patch series
is doing, how it is doing it, and why it is doing it this way.
I am tossing this patch series from patchwork, please resubmit this
entire series properly.
Thank you.
^ permalink raw reply
* Re: INFO: rcu detected stall in ext4_write_checks
From: Paul E. McKenney @ 2019-07-05 19:10 UTC (permalink / raw)
To: Dmitry Vyukov
Cc: Theodore Ts'o, syzbot, Andreas Dilger, David Miller, eladr,
Ido Schimmel, Jiri Pirko, John Stultz, linux-ext4, LKML, netdev,
syzkaller-bugs, Thomas Gleixner, Peter Zijlstra, Ingo Molnar
In-Reply-To: <CACT4Y+aNLHrYj1pYbkXO7CKESLeB-5enkSDK7ksgkMA3KtwJ+w@mail.gmail.com>
On Fri, Jul 05, 2019 at 05:48:31PM +0200, Dmitry Vyukov wrote:
> On Fri, Jul 5, 2019 at 5:17 PM Paul E. McKenney <paulmck@linux.ibm.com> wrote:
> >
> > On Fri, Jul 05, 2019 at 03:24:26PM +0200, Dmitry Vyukov wrote:
> > > On Thu, Jun 27, 2019 at 12:47 AM Theodore Ts'o <tytso@mit.edu> wrote:
> > > >
> > > > More details about what is going on. First, it requires root, because
> > > > one of that is required is using sched_setattr (which is enough to
> > > > shoot yourself in the foot):
> > > >
> > > > sched_setattr(0, {size=0, sched_policy=0x6 /* SCHED_??? */, sched_flags=0, sched_nice=0, sched_priority=0, sched_runtime=2251799813724439, sched_deadline=4611686018427453437, sched_period=0}, 0) = 0
> > > >
> > > > This is setting the scheduler policy to be SCHED_DEADLINE, with a
> > > > runtime parameter of 2251799.813724439 seconds (or 26 days) and a
> > > > deadline of 4611686018.427453437 seconds (or 146 *years*). This means
> > > > a particular kernel thread can run for up to 26 **days** before it is
> > > > scheduled away, and if a kernel reads gets woken up or sent a signal,
> > > > no worries, it will wake up roughly seven times the interval that Rip
> > > > Van Winkle spent snoozing in a cave in the Catskill Mountains (in
> > > > Washington Irving's short story).
> > > >
> > > > We then kick off a half-dozen threads all running:
> > > >
> > > > sendfile(fd, fd, &pos, 0x8080fffffffe);
> > > >
> > > > (and since count is a ridiculously large number, this gets cut down to):
> > > >
> > > > sendfile(fd, fd, &pos, 2147479552);
> > > >
> > > > Is it any wonder that we are seeing RCU stalls? :-)
> > >
> > > +Peter, Ingo for sched_setattr and +Paul for rcu
> > >
> > > First of all: is it a semi-intended result of a root (CAP_SYS_NICE)
> > > doing local DoS abusing sched_setattr? It would perfectly reasonable
> > > to starve other processes, but I am not sure about rcu. In the end the
> > > high prio process can use rcu itself, and then it will simply blow
> > > system memory by stalling rcu. So it seems that rcu stalls should not
> > > happen as a result of weird sched_setattr values. If that is the case,
> > > what needs to be fixed? sched_setattr? rcu? sendfile?
> >
> > Does the (untested, probably does not even build) patch shown below help?
> > This patch assumes that the kernel was built with CONFIG_PREEMPT=n.
> > And that I found all the tight loops on the do_sendfile() code path.
>
> The config used when this happened is referenced from here:
> https://syzkaller.appspot.com/bug?extid=4bfbbf28a2e50ab07368
> and it contains:
> CONFIG_PREEMPT=y
>
> So... what does this mean? The loop should have been preempted without
> the cond_resched() then, right?
Exactly, so although my patch might help for CONFIG_PREEMPT=n, it won't
help in your scenario. But looking at the dmesg from your URL above,
I see the following:
rcu: rcu_preempt kthread starved for 10549 jiffies! g8969 f0x2 RCU_GP_WAIT_FQS(5) ->state=0x0 ->cpu=0
And, prior to that:
rcu: All QSes seen, last rcu_preempt kthread activity 10503 (4295056736-4295046233), jiffies_till_next_fqs=1, root ->qsmask 0x0
In other words, the grace period has finished, but RCU's grace-period
kthread hasn't gotten a chance to run, and thus hasn't marked it as
completed. The standard workaround is to set the rcutree.kthread_prio
kernel boot parameter to a comfortably high real-time priority.
At least assuming that syzkaller isn't setting the scheduling priority
of random CPU-bound tasks to RT priority 99 or some such. ;-)
Does that work for you?
Thanx, Paul
> > > If this is semi-intended, the only option I see is to disable
> > > something in syzkaller: sched_setattr entirely, or drop CAP_SYS_NICE,
> > > or ...? Any preference either way?
> >
> > Long-running tight loops in the kernel really should contain
> > cond_resched() or better.
> >
> > Thanx, Paul
> >
> > ------------------------------------------------------------------------
> >
> > diff --git a/fs/splice.c b/fs/splice.c
> > index 25212dcca2df..50aa3286764a 100644
> > --- a/fs/splice.c
> > +++ b/fs/splice.c
> > @@ -985,6 +985,7 @@ ssize_t splice_direct_to_actor(struct file *in, struct splice_desc *sd,
> > sd->pos = prev_pos + ret;
> > goto out_release;
> > }
> > + cond_resched();
> > }
> >
> > done:
> >
>
^ permalink raw reply
* [PATCH] sockfs: switch to ->free_inode()
From: Al Viro @ 2019-07-05 19:13 UTC (permalink / raw)
To: David Miller; +Cc: netdev
we do have an RCU-delayed part there already (freeing the wq),
so it's not like the pipe situation; moreover, it might be
worth considering coallocating wq with the rest of struct sock_alloc.
->sk_wq in struct sock would remain a pointer as it is, but
the object it normally points to would be coallocated with
struct socket...
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
---
net/socket.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/net/socket.c b/net/socket.c
index d97b74f762e8..541719a2443d 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -258,12 +258,12 @@ static struct inode *sock_alloc_inode(struct super_block *sb)
return &ei->vfs_inode;
}
-static void sock_destroy_inode(struct inode *inode)
+static void sock_free_inode(struct inode *inode)
{
struct socket_alloc *ei;
ei = container_of(inode, struct socket_alloc, vfs_inode);
- kfree_rcu(ei->socket.wq, rcu);
+ kfree(ei->socket.wq);
kmem_cache_free(sock_inode_cachep, ei);
}
@@ -288,7 +288,7 @@ static void init_inodecache(void)
static const struct super_operations sockfs_ops = {
.alloc_inode = sock_alloc_inode,
- .destroy_inode = sock_destroy_inode,
+ .free_inode = sock_free_inode,
.statfs = simple_statfs,
};
--
2.11.0
^ permalink raw reply related
* [PATCH] coallocate socket_wq with socket itself
From: Al Viro @ 2019-07-05 19:14 UTC (permalink / raw)
To: David Miller; +Cc: netdev
In-Reply-To: <20190705191322.GK17978@ZenIV.linux.org.uk>
socket->wq is assign-once, set when we are initializing both
struct socket it's in and struct socket_wq it points to. As the
matter of fact, the only reason for separate allocation was the
ability to RCU-delay freeing of socket_wq. RCU-delaying the
freeing of socket itself gets rid of that need, so we can just
fold struct socket_wq into the end of struct socket and simplify
the life both for sock_alloc_inode() (one allocation instead of
two) and for tun/tap oddballs, where we used to embed struct socket
and struct socket_wq into the same structure (now - embedding just
the struct socket).
Note that reference to struct socket_wq in struct sock does remain
a reference - that's unchanged.
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
---
drivers/net/tap.c | 5 ++---
drivers/net/tun.c | 8 +++-----
include/linux/if_tap.h | 1 -
include/linux/net.h | 4 ++--
include/net/sock.h | 4 ++--
net/core/sock.c | 2 +-
net/socket.c | 19 +++++--------------
7 files changed, 15 insertions(+), 28 deletions(-)
diff --git a/drivers/net/tap.c b/drivers/net/tap.c
index 8e01390c738e..dd614c2cd994 100644
--- a/drivers/net/tap.c
+++ b/drivers/net/tap.c
@@ -520,8 +520,7 @@ static int tap_open(struct inode *inode, struct file *file)
goto err;
}
- RCU_INIT_POINTER(q->sock.wq, &q->wq);
- init_waitqueue_head(&q->wq.wait);
+ init_waitqueue_head(&q->sock.wq.wait);
q->sock.type = SOCK_RAW;
q->sock.state = SS_CONNECTED;
q->sock.file = file;
@@ -579,7 +578,7 @@ static __poll_t tap_poll(struct file *file, poll_table *wait)
goto out;
mask = 0;
- poll_wait(file, &q->wq.wait, wait);
+ poll_wait(file, &q->sock.wq.wait, wait);
if (!ptr_ring_empty(&q->ring))
mask |= EPOLLIN | EPOLLRDNORM;
diff --git a/drivers/net/tun.c b/drivers/net/tun.c
index d7c55e0fa8f4..3d443597bd04 100644
--- a/drivers/net/tun.c
+++ b/drivers/net/tun.c
@@ -160,7 +160,6 @@ struct tun_pcpu_stats {
struct tun_file {
struct sock sk;
struct socket socket;
- struct socket_wq wq;
struct tun_struct __rcu *tun;
struct fasync_struct *fasync;
/* only used for fasnyc */
@@ -2165,7 +2164,7 @@ static void *tun_ring_recv(struct tun_file *tfile, int noblock, int *err)
goto out;
}
- add_wait_queue(&tfile->wq.wait, &wait);
+ add_wait_queue(&tfile->socket.wq.wait, &wait);
while (1) {
set_current_state(TASK_INTERRUPTIBLE);
@@ -2185,7 +2184,7 @@ static void *tun_ring_recv(struct tun_file *tfile, int noblock, int *err)
}
__set_current_state(TASK_RUNNING);
- remove_wait_queue(&tfile->wq.wait, &wait);
+ remove_wait_queue(&tfile->socket.wq.wait, &wait);
out:
*err = error;
@@ -3415,8 +3414,7 @@ static int tun_chr_open(struct inode *inode, struct file * file)
tfile->flags = 0;
tfile->ifindex = 0;
- init_waitqueue_head(&tfile->wq.wait);
- RCU_INIT_POINTER(tfile->socket.wq, &tfile->wq);
+ init_waitqueue_head(&tfile->socket.wq.wait);
tfile->socket.file = file;
tfile->socket.ops = &tun_socket_ops;
diff --git a/include/linux/if_tap.h b/include/linux/if_tap.h
index 8e66866c11be..915a187cfabd 100644
--- a/include/linux/if_tap.h
+++ b/include/linux/if_tap.h
@@ -62,7 +62,6 @@ struct tap_dev {
struct tap_queue {
struct sock sk;
struct socket sock;
- struct socket_wq wq;
int vnet_hdr_sz;
struct tap_dev __rcu *tap;
struct file *file;
diff --git a/include/linux/net.h b/include/linux/net.h
index f7d672cf25b5..9cafb5f353a9 100644
--- a/include/linux/net.h
+++ b/include/linux/net.h
@@ -116,11 +116,11 @@ struct socket {
unsigned long flags;
- struct socket_wq *wq;
-
struct file *file;
struct sock *sk;
const struct proto_ops *ops;
+
+ struct socket_wq wq;
};
struct vm_area_struct;
diff --git a/include/net/sock.h b/include/net/sock.h
index 6cbc16136357..228db3998e46 100644
--- a/include/net/sock.h
+++ b/include/net/sock.h
@@ -1822,7 +1822,7 @@ static inline void sock_graft(struct sock *sk, struct socket *parent)
{
WARN_ON(parent->sk);
write_lock_bh(&sk->sk_callback_lock);
- rcu_assign_pointer(sk->sk_wq, parent->wq);
+ rcu_assign_pointer(sk->sk_wq, &parent->wq);
parent->sk = sk;
sk_set_socket(sk, parent);
sk->sk_uid = SOCK_INODE(parent)->i_uid;
@@ -2100,7 +2100,7 @@ static inline void sock_poll_wait(struct file *filp, struct socket *sock,
poll_table *p)
{
if (!poll_does_not_wait(p)) {
- poll_wait(filp, &sock->wq->wait, p);
+ poll_wait(filp, &sock->wq.wait, p);
/* We need to be sure we are in sync with the
* socket flags modification.
*
diff --git a/net/core/sock.c b/net/core/sock.c
index 0eb21384079d..3e073ca6138f 100644
--- a/net/core/sock.c
+++ b/net/core/sock.c
@@ -2847,7 +2847,7 @@ void sock_init_data(struct socket *sock, struct sock *sk)
if (sock) {
sk->sk_type = sock->type;
- RCU_INIT_POINTER(sk->sk_wq, sock->wq);
+ RCU_INIT_POINTER(sk->sk_wq, &sock->wq);
sock->sk = sk;
sk->sk_uid = SOCK_INODE(sock)->i_uid;
} else {
diff --git a/net/socket.c b/net/socket.c
index 541719a2443d..16449d6daeca 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -234,20 +234,13 @@ static struct kmem_cache *sock_inode_cachep __ro_after_init;
static struct inode *sock_alloc_inode(struct super_block *sb)
{
struct socket_alloc *ei;
- struct socket_wq *wq;
ei = kmem_cache_alloc(sock_inode_cachep, GFP_KERNEL);
if (!ei)
return NULL;
- wq = kmalloc(sizeof(*wq), GFP_KERNEL);
- if (!wq) {
- kmem_cache_free(sock_inode_cachep, ei);
- return NULL;
- }
- init_waitqueue_head(&wq->wait);
- wq->fasync_list = NULL;
- wq->flags = 0;
- ei->socket.wq = wq;
+ init_waitqueue_head(&ei->socket.wq.wait);
+ ei->socket.wq.fasync_list = NULL;
+ ei->socket.wq.flags = 0;
ei->socket.state = SS_UNCONNECTED;
ei->socket.flags = 0;
@@ -263,7 +256,6 @@ static void sock_free_inode(struct inode *inode)
struct socket_alloc *ei;
ei = container_of(inode, struct socket_alloc, vfs_inode);
- kfree(ei->socket.wq);
kmem_cache_free(sock_inode_cachep, ei);
}
@@ -599,7 +591,7 @@ static void __sock_release(struct socket *sock, struct inode *inode)
module_put(owner);
}
- if (sock->wq->fasync_list)
+ if (sock->wq.fasync_list)
pr_err("%s: fasync list not empty!\n", __func__);
if (!sock->file) {
@@ -1288,13 +1280,12 @@ static int sock_fasync(int fd, struct file *filp, int on)
{
struct socket *sock = filp->private_data;
struct sock *sk = sock->sk;
- struct socket_wq *wq;
+ struct socket_wq *wq = &sock->wq;
if (sk == NULL)
return -EINVAL;
lock_sock(sk);
- wq = sock->wq;
fasync_helper(fd, filp, on, &wq->fasync_list);
if (!wq->fasync_list)
--
2.11.0
^ permalink raw reply related
* Re: [PATCH net-next v2 1/3] devlink: Introduce PCI PF port flavour and port attribute
From: Jakub Kicinski @ 2019-07-05 19:17 UTC (permalink / raw)
To: Parav Pandit; +Cc: netdev, jiri, saeedm
In-Reply-To: <20190705073711.37854-2-parav@mellanox.com>
On Fri, 5 Jul 2019 02:37:09 -0500, Parav Pandit wrote:
> @@ -38,14 +38,24 @@ struct devlink {
> char priv[0] __aligned(NETDEV_ALIGN);
> };
>
> +struct devlink_port_pci_pf_attrs {
> + u16 pf; /* Associated PCI PF for this port. */
> +};
> +
> struct devlink_port_attrs {
> u8 set:1,
> split:1,
> switch_port:1;
> enum devlink_port_flavour flavour;
> - u32 port_number; /* same value as "split group" */
> + u32 port_number; /* same value as "split group".
> + * Valid only when a port is physical and visible
> + * to the user for a given port flavour.
> + */
port_number can be in the per-flavour union below.
> u32 split_subport_number;
As can split_subport_number.
> struct netdev_phys_item_id switch_id;
> + union {
> + struct devlink_port_pci_pf_attrs pci_pf;
> + };
> };
>
> struct devlink_port {
> @@ -515,8 +523,14 @@ static int devlink_nl_port_attrs_put(struct sk_buff *msg,
> return 0;
> if (nla_put_u16(msg, DEVLINK_ATTR_PORT_FLAVOUR, attrs->flavour))
> return -EMSGSIZE;
> - if (nla_put_u32(msg, DEVLINK_ATTR_PORT_NUMBER, attrs->port_number))
> + if (is_devlink_phy_port_num_supported(devlink_port) &&
> + nla_put_u32(msg, DEVLINK_ATTR_PORT_NUMBER, attrs->port_number))
> return -EMSGSIZE;
> + if (devlink_port->attrs.flavour == DEVLINK_PORT_FLAVOUR_PCI_PF) {
> + if (nla_put_u16(msg, DEVLINK_ATTR_PORT_PCI_PF_NUMBER,
> + attrs->pci_pf.pf))
> + return -EMSGSIZE;
> + }
> if (!attrs->split)
> return 0;
> if (nla_put_u32(msg, DEVLINK_ATTR_PORT_SPLIT_GROUP, attrs->port_number))
Split attributes as well, please:
On Tue, 2 Jul 2019 16:42:52 -0700, Jakub Kicinski wrote:
> port_number, and split attributes should not be exposed for PCI ports.
We have no clear semantics for those, yet, and the phys_port_name
implementation in this patch doesn't handle split PCI, so let's leave
them out for now.
^ permalink raw reply
* Re: [PATCH v6 net-next 2/5] net: ethernet: ti: davinci_cpdma: add dma mapped submit
From: kbuild test robot @ 2019-07-05 19:32 UTC (permalink / raw)
To: Ivan Khoronzhuk
Cc: kbuild-all, grygorii.strashko, hawk, davem, ast, linux-kernel,
linux-omap, xdp-newbies, ilias.apalodimas, netdev, daniel,
jakub.kicinski, john.fastabend, Ivan Khoronzhuk
In-Reply-To: <20190703101903.8411-3-ivan.khoronzhuk@linaro.org>
[-- Attachment #1: Type: text/plain, Size: 5251 bytes --]
Hi Ivan,
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/Ivan-Khoronzhuk/xdp-allow-same-allocator-usage/20190706-003850
config: arm64-allmodconfig (attached as .config)
compiler: aarch64-linux-gcc (GCC) 7.4.0
reproduce:
wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
chmod +x ~/bin/make.cross
# save the attached .config to linux build tree
GCC_VERSION=7.4.0 make.cross ARCH=arm64
If you fix the issue, kindly add following tag
Reported-by: kbuild test robot <lkp@intel.com>
All warnings (new ones prefixed by >>):
drivers/net//ethernet/ti/davinci_cpdma.c: In function 'cpdma_chan_submit_si':
>> drivers/net//ethernet/ti/davinci_cpdma.c:1047:12: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast]
buffer = (u32)si->data;
^
drivers/net//ethernet/ti/davinci_cpdma.c: In function 'cpdma_chan_idle_submit_mapped':
>> drivers/net//ethernet/ti/davinci_cpdma.c:1114:12: warning: cast to pointer from integer of different size [-Wint-to-pointer-cast]
si.data = (void *)(u32)data;
^
drivers/net//ethernet/ti/davinci_cpdma.c: In function 'cpdma_chan_submit_mapped':
drivers/net//ethernet/ti/davinci_cpdma.c:1164:12: warning: cast to pointer from integer of different size [-Wint-to-pointer-cast]
si.data = (void *)(u32)data;
^
vim +1047 drivers/net//ethernet/ti/davinci_cpdma.c
1015
1016 static int cpdma_chan_submit_si(struct submit_info *si)
1017 {
1018 struct cpdma_chan *chan = si->chan;
1019 struct cpdma_ctlr *ctlr = chan->ctlr;
1020 int len = si->len;
1021 int swlen = len;
1022 struct cpdma_desc __iomem *desc;
1023 dma_addr_t buffer;
1024 u32 mode;
1025 int ret;
1026
1027 if (chan->count >= chan->desc_num) {
1028 chan->stats.desc_alloc_fail++;
1029 return -ENOMEM;
1030 }
1031
1032 desc = cpdma_desc_alloc(ctlr->pool);
1033 if (!desc) {
1034 chan->stats.desc_alloc_fail++;
1035 return -ENOMEM;
1036 }
1037
1038 if (len < ctlr->params.min_packet_size) {
1039 len = ctlr->params.min_packet_size;
1040 chan->stats.runt_transmit_buff++;
1041 }
1042
1043 mode = CPDMA_DESC_OWNER | CPDMA_DESC_SOP | CPDMA_DESC_EOP;
1044 cpdma_desc_to_port(chan, mode, si->directed);
1045
1046 if (si->flags & CPDMA_DMA_EXT_MAP) {
> 1047 buffer = (u32)si->data;
1048 dma_sync_single_for_device(ctlr->dev, buffer, len, chan->dir);
1049 swlen |= CPDMA_DMA_EXT_MAP;
1050 } else {
1051 buffer = dma_map_single(ctlr->dev, si->data, len, chan->dir);
1052 ret = dma_mapping_error(ctlr->dev, buffer);
1053 if (ret) {
1054 cpdma_desc_free(ctlr->pool, desc, 1);
1055 return -EINVAL;
1056 }
1057 }
1058
1059 /* Relaxed IO accessors can be used here as there is read barrier
1060 * at the end of write sequence.
1061 */
1062 writel_relaxed(0, &desc->hw_next);
1063 writel_relaxed(buffer, &desc->hw_buffer);
1064 writel_relaxed(len, &desc->hw_len);
1065 writel_relaxed(mode | len, &desc->hw_mode);
1066 writel_relaxed((uintptr_t)si->token, &desc->sw_token);
1067 writel_relaxed(buffer, &desc->sw_buffer);
1068 writel_relaxed(swlen, &desc->sw_len);
1069 desc_read(desc, sw_len);
1070
1071 __cpdma_chan_submit(chan, desc);
1072
1073 if (chan->state == CPDMA_STATE_ACTIVE && chan->rxfree)
1074 chan_write(chan, rxfree, 1);
1075
1076 chan->count++;
1077 return 0;
1078 }
1079
1080 int cpdma_chan_idle_submit(struct cpdma_chan *chan, void *token, void *data,
1081 int len, int directed)
1082 {
1083 struct submit_info si;
1084 unsigned long flags;
1085 int ret;
1086
1087 si.chan = chan;
1088 si.token = token;
1089 si.data = data;
1090 si.len = len;
1091 si.directed = directed;
1092 si.flags = 0;
1093
1094 spin_lock_irqsave(&chan->lock, flags);
1095 if (chan->state == CPDMA_STATE_TEARDOWN) {
1096 spin_unlock_irqrestore(&chan->lock, flags);
1097 return -EINVAL;
1098 }
1099
1100 ret = cpdma_chan_submit_si(&si);
1101 spin_unlock_irqrestore(&chan->lock, flags);
1102 return ret;
1103 }
1104
1105 int cpdma_chan_idle_submit_mapped(struct cpdma_chan *chan, void *token,
1106 dma_addr_t data, int len, int directed)
1107 {
1108 struct submit_info si;
1109 unsigned long flags;
1110 int ret;
1111
1112 si.chan = chan;
1113 si.token = token;
> 1114 si.data = (void *)(u32)data;
1115 si.len = len;
1116 si.directed = directed;
1117 si.flags = CPDMA_DMA_EXT_MAP;
1118
1119 spin_lock_irqsave(&chan->lock, flags);
1120 if (chan->state == CPDMA_STATE_TEARDOWN) {
1121 spin_unlock_irqrestore(&chan->lock, flags);
1122 return -EINVAL;
1123 }
1124
1125 ret = cpdma_chan_submit_si(&si);
1126 spin_unlock_irqrestore(&chan->lock, flags);
1127 return ret;
1128 }
1129
---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation
[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 65617 bytes --]
^ permalink raw reply
* Re: [EXT] Re: [PATCH net-next v2 4/4] qed*: Add devlink support for configuration attributes.
From: Jakub Kicinski @ 2019-07-05 19:39 UTC (permalink / raw)
To: Sudarsana Reddy Kalluru
Cc: davem@davemloft.net, netdev@vger.kernel.org, Michal Kalderon,
Ariel Elior, Jiri Pirko
In-Reply-To: <DM6PR18MB25242BC08136A2C528C1A695D3F50@DM6PR18MB2524.namprd18.prod.outlook.com>
On Fri, 5 Jul 2019 08:22:41 +0000, Sudarsana Reddy Kalluru wrote:
> > On Thu, 4 Jul 2019 06:20:11 -0700, Sudarsana Reddy Kalluru wrote:
> > > This patch adds implementation for devlink callbacks for reading and
> > > configuring the device attributes.
> > >
> > > Signed-off-by: Sudarsana Reddy Kalluru <skalluru@marvell.com>
> > > Signed-off-by: Ariel Elior <aelior@marvell.com>
> > > diff --git a/Documentation/networking/devlink-params-qede.txt
> > > b/Documentation/networking/devlink-params-qede.txt
> > > new file mode 100644
> > > index 0000000..f78a993
> > > --- /dev/null
> > > +++ b/Documentation/networking/devlink-params-qede.txt
> > > @@ -0,0 +1,72 @@
> > > +enable_sriov [DEVICE, GENERIC]
> > > + Configuration mode: Permanent
> > > +
> > > +iwarp_cmt [DEVICE, DRIVER-SPECIFIC]
> > > + Enable iWARP support over 100G device (CMT mode).
> > > + Type: Boolean
> > > + Configuration mode: runtime
> > > +
> > > +entity_id [DEVICE, DRIVER-SPECIFIC]
> > > + Set the entity ID value to be used for this device
> > > + while reading/configuring the devlink attributes.
> > > + Type: u8
> > > + Configuration mode: runtime
> >
> > Can you explain what this is?
>
> Hardware/mfw provides the option to modify/read the config of other
> PFs. A non-zero entity id represents a partition number (or simply a
> PF-id) for which the config need to be read/updated.
Having a parameter which changes the interpretation of other parameters
makes me quite uncomfortable :( Could it be a better idea, perhaps, to
use PCI ports? We have been discussing PCI ports for a while now, and
they will probably become a reality soon. You could then hang the
per-PF parameters off of the PF ports rather than the device instance?
> > > +device_capabilities [DEVICE, DRIVER-SPECIFIC]
> > > + Set the entity ID value to be used for this device
> > > + while reading/configuring the devlink attributes.
> > > + Type: u8
> > > + Configuration mode: runtime
> >
> > Looks like you copied the previous text here.
> Will update it, thanks.
>
> >
> > > +mf_mode [DEVICE, DRIVER-SPECIFIC]
> > > + Configure Multi Function mode for the device.
> > > + Supported MF modes and the assoicated values are,
> > > + MF allowed(0), Default(1), SPIO4(2), NPAR1.0(3),
> > > + NPAR1.5(4), NPAR2.0(5), BD(6) and UFP(7)
> >
> > NPAR should have a proper API in devlink port, what are the other modes?
> >
> These are the different modes supported by the Marvell NIC. In our
> case the mf_mode is per adapter basis, e.g., it's not possible to
> configure one port in NPAR mode and the other in Default mode.
Jiri, what are your thoughts on the NPAR support? It is effectively a
PCI split. If we are going to support mdev split, should we perhaps
have a "depth" or "type" of split and allow for users to configure it
using the same API?
> > > + Type: u8
> > > + Configuration mode: Permanent
> > > +
> > > +dcbx_mode [PORT, DRIVER-SPECIFIC]
> > > + Configure DCBX mode for the device.
> > > + Supported dcbx modes are,
> > > + Disabled(0), IEEE(1), CEE(2) and
> > > Dynamic(3)
> > > + Type: u8
> > > + Configuration mode: Permanent
> >
> > Why is this a permanent parameter?
> >
> This specifies the dcbx_mode to be configured in non-volatile memory.
> The value is persistent and is used in the next load of OS or the mfw.
And it can't be changed at runtime?
^ permalink raw reply
* Re: [net-next 14/14] net/mlx5e: Add kTLS TX HW offload support
From: Jakub Kicinski @ 2019-07-05 19:43 UTC (permalink / raw)
To: Tariq Toukan
Cc: Saeed Mahameed, David S. Miller, netdev@vger.kernel.org,
Eran Ben Elisha, Boris Pismenny
In-Reply-To: <079d4170-d591-18c6-572e-dbec428f169e@mellanox.com>
On Fri, 5 Jul 2019 14:31:29 +0000, Tariq Toukan wrote:
> On 7/4/2019 11:12 PM, Jakub Kicinski wrote:
> > On Thu, 4 Jul 2019 18:16:15 +0000, Saeed Mahameed wrote:
> >> diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_stats.c b/drivers/net/ethernet/mellanox/mlx5/core/en_stats.c
> >> index 483d321d2151..6854f132d505 100644
> >> --- a/drivers/net/ethernet/mellanox/mlx5/core/en_stats.c
> >> +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_stats.c
> >> @@ -50,6 +50,15 @@ static const struct counter_desc sw_stats_desc[] = {
> >> #ifdef CONFIG_MLX5_EN_TLS
> >> { MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, tx_tls_ooo) },
> >> { MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, tx_tls_resync_bytes) },
> >> +
> >> + { MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, tx_ktls_ooo) },
> >
> > Why do you call this stat tx_ktls_ooo, and not tx_tls_ooo (extra 'k')?
> >
> > For nfp I used the stats' names from mlx5 FPGA to make sure we are all
> > consistent. I've added them to the tls-offload.rst doc and Boris has
> > reviewed it.
> >
> > * ``rx_tls_decrypted`` - number of successfully decrypted TLS segments
> > * ``tx_tls_encrypted`` - number of in-order TLS segments passed to device
> > for encryption
> > * ``tx_tls_ooo`` - number of TX packets which were part of a TLS stream
> > but did not arrive in the expected order
> > * ``tx_tls_drop_no_sync_data`` - number of TX packets dropped because
> > they arrived out of order and associated record could not be found
> >
> > Why can't you use the same names for the stats as you used for your mlx5
> > FPGA?
> >
>
> Agree. Fixing.
>
> What about having stats both for packets and bytes?
> tx_tls_encrypted_packets
> tx_tls_encrypted_bytes
Makes sense, I wasn't sure we want too many counters on the fastpath,
therefore I had no bytes counter. Renaming rx_tls_decrypted and
tx_tls_encrypted sounds like a good idea, though! We only have them in
the nfp, and there wasn't any kernel released with nfp TLS offload,
yet, so we can adjust.
Perhaps we should also make it clear in the doc that those counters
count "packets"/bytes on the wire, while the other counters count the
number of skbs, which may be TSO?
Would you be able to make those adjustments if you agree?
^ permalink raw reply
* Re: [PATCH net-next] hinic: add fw version query
From: Jakub Kicinski @ 2019-07-05 19:47 UTC (permalink / raw)
To: Xue Chaojing
Cc: davem, linux-kernel, netdev, luoshaokai, cloud.wangxiaoyun,
chiqijun, wulike1
In-Reply-To: <20190705024028.5768-1-xuechaojing@huawei.com>
On Fri, 5 Jul 2019 02:40:28 +0000, Xue Chaojing wrote:
> This patch adds firmware version query in ethtool -i.
>
> Signed-off-by: Xue Chaojing <xuechaojing@huawei.com>
Reviewed-by: Jakub Kicinski <jakub.kicinski@netronome.com>
^ permalink raw reply
* [PATCH net-next v2 1/8] Documentation/bindings: net: ocelot: document the PTP bank
From: Antoine Tenart @ 2019-07-05 19:52 UTC (permalink / raw)
To: davem, richardcochran, alexandre.belloni, UNGLinuxDriver, ralf,
paul.burton, jhogan
Cc: Antoine Tenart, netdev, linux-mips, thomas.petazzoni,
allan.nielsen
In-Reply-To: <20190705195213.22041-1-antoine.tenart@bootlin.com>
One additional register range needs to be described within the Ocelot
device tree node: the PTP. This patch documents the binding needed to do
so.
Signed-off-by: Antoine Tenart <antoine.tenart@bootlin.com>
---
Documentation/devicetree/bindings/net/mscc-ocelot.txt | 9 ++++++---
1 file changed, 6 insertions(+), 3 deletions(-)
diff --git a/Documentation/devicetree/bindings/net/mscc-ocelot.txt b/Documentation/devicetree/bindings/net/mscc-ocelot.txt
index 9e5c17d426ce..4d05a3b0f786 100644
--- a/Documentation/devicetree/bindings/net/mscc-ocelot.txt
+++ b/Documentation/devicetree/bindings/net/mscc-ocelot.txt
@@ -12,6 +12,7 @@ Required properties:
- "sys"
- "rew"
- "qs"
+ - "ptp" (optional due to backward compatibility)
- "qsys"
- "ana"
- "portX" with X from 0 to the number of last port index available on that
@@ -44,6 +45,7 @@ Example:
reg = <0x1010000 0x10000>,
<0x1030000 0x10000>,
<0x1080000 0x100>,
+ <0x10e0000 0x10000>,
<0x11e0000 0x100>,
<0x11f0000 0x100>,
<0x1200000 0x100>,
@@ -57,9 +59,10 @@ Example:
<0x1280000 0x100>,
<0x1800000 0x80000>,
<0x1880000 0x10000>;
- reg-names = "sys", "rew", "qs", "port0", "port1", "port2",
- "port3", "port4", "port5", "port6", "port7",
- "port8", "port9", "port10", "qsys", "ana";
+ reg-names = "sys", "rew", "qs", "ptp", "port0", "port1",
+ "port2", "port3", "port4", "port5", "port6",
+ "port7", "port8", "port9", "port10", "qsys",
+ "ana";
interrupts = <21 22>;
interrupt-names = "xtr", "inj";
--
2.21.0
^ permalink raw reply related
* [PATCH net-next v2 3/8] Documentation/bindings: net: ocelot: document the PTP ready IRQ
From: Antoine Tenart @ 2019-07-05 19:52 UTC (permalink / raw)
To: davem, richardcochran, alexandre.belloni, UNGLinuxDriver, ralf,
paul.burton, jhogan
Cc: Antoine Tenart, netdev, linux-mips, thomas.petazzoni,
allan.nielsen
In-Reply-To: <20190705195213.22041-1-antoine.tenart@bootlin.com>
One additional interrupt needs to be described within the Ocelot device
tree node: the PTP ready one. This patch documents the binding needed to
do so.
Signed-off-by: Antoine Tenart <antoine.tenart@bootlin.com>
---
Documentation/devicetree/bindings/net/mscc-ocelot.txt | 11 ++++++-----
1 file changed, 6 insertions(+), 5 deletions(-)
diff --git a/Documentation/devicetree/bindings/net/mscc-ocelot.txt b/Documentation/devicetree/bindings/net/mscc-ocelot.txt
index 4d05a3b0f786..3b6290b45ce5 100644
--- a/Documentation/devicetree/bindings/net/mscc-ocelot.txt
+++ b/Documentation/devicetree/bindings/net/mscc-ocelot.txt
@@ -17,9 +17,10 @@ Required properties:
- "ana"
- "portX" with X from 0 to the number of last port index available on that
switch
-- interrupts: Should contain the switch interrupts for frame extraction and
- frame injection
-- interrupt-names: should contain the interrupt names: "xtr", "inj"
+- interrupts: Should contain the switch interrupts for frame extraction,
+ frame injection and PTP ready.
+- interrupt-names: should contain the interrupt names: "xtr", "inj". Can contain
+ "ptp_rdy" which is optional due to backward compatibility.
- ethernet-ports: A container for child nodes representing switch ports.
The ethernet-ports container has the following properties
@@ -63,8 +64,8 @@ Example:
"port2", "port3", "port4", "port5", "port6",
"port7", "port8", "port9", "port10", "qsys",
"ana";
- interrupts = <21 22>;
- interrupt-names = "xtr", "inj";
+ interrupts = <18 21 22>;
+ interrupt-names = "ptp_rdy", "xtr", "inj";
ethernet-ports {
#address-cells = <1>;
--
2.21.0
^ permalink raw reply related
* [PATCH net-next v2 4/8] MIPS: dts: mscc: describe the PTP ready interrupt
From: Antoine Tenart @ 2019-07-05 19:52 UTC (permalink / raw)
To: davem, richardcochran, alexandre.belloni, UNGLinuxDriver, ralf,
paul.burton, jhogan
Cc: Antoine Tenart, netdev, linux-mips, thomas.petazzoni,
allan.nielsen
In-Reply-To: <20190705195213.22041-1-antoine.tenart@bootlin.com>
This patch adds a description of the PTP ready interrupt, which can be
triggered when a PTP timestamp is available on an hardware FIFO.
Signed-off-by: Antoine Tenart <antoine.tenart@bootlin.com>
---
arch/mips/boot/dts/mscc/ocelot.dtsi | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/arch/mips/boot/dts/mscc/ocelot.dtsi b/arch/mips/boot/dts/mscc/ocelot.dtsi
index 1e55a778def5..797d336db54d 100644
--- a/arch/mips/boot/dts/mscc/ocelot.dtsi
+++ b/arch/mips/boot/dts/mscc/ocelot.dtsi
@@ -139,8 +139,8 @@
"port2", "port3", "port4", "port5", "port6",
"port7", "port8", "port9", "port10", "qsys",
"ana", "s2";
- interrupts = <21 22>;
- interrupt-names = "xtr", "inj";
+ interrupts = <18 21 22>;
+ interrupt-names = "ptp_rdy", "xtr", "inj";
ethernet-ports {
#address-cells = <1>;
--
2.21.0
^ permalink raw reply related
* [PATCH net-next v2 5/8] net: mscc: describe the PTP register range
From: Antoine Tenart @ 2019-07-05 19:52 UTC (permalink / raw)
To: davem, richardcochran, alexandre.belloni, UNGLinuxDriver, ralf,
paul.burton, jhogan
Cc: Antoine Tenart, netdev, linux-mips, thomas.petazzoni,
allan.nielsen
In-Reply-To: <20190705195213.22041-1-antoine.tenart@bootlin.com>
This patch adds support for using the PTP register range, and adds a
description of its registers. This bank is used when configuring PTP.
Signed-off-by: Antoine Tenart <antoine.tenart@bootlin.com>
---
drivers/net/ethernet/mscc/ocelot.h | 9 ++++++
drivers/net/ethernet/mscc/ocelot_board.c | 10 +++++-
drivers/net/ethernet/mscc/ocelot_ptp.h | 41 ++++++++++++++++++++++++
drivers/net/ethernet/mscc/ocelot_regs.c | 11 +++++++
4 files changed, 70 insertions(+), 1 deletion(-)
create mode 100644 drivers/net/ethernet/mscc/ocelot_ptp.h
diff --git a/drivers/net/ethernet/mscc/ocelot.h b/drivers/net/ethernet/mscc/ocelot.h
index f7eeb4806897..e0da8b4eddf2 100644
--- a/drivers/net/ethernet/mscc/ocelot.h
+++ b/drivers/net/ethernet/mscc/ocelot.h
@@ -23,6 +23,7 @@
#include "ocelot_sys.h"
#include "ocelot_qs.h"
#include "ocelot_tc.h"
+#include "ocelot_ptp.h"
#define PGID_AGGR 64
#define PGID_SRC 80
@@ -71,6 +72,7 @@ enum ocelot_target {
SYS,
S2,
HSIO,
+ PTP,
TARGET_MAX,
};
@@ -343,6 +345,13 @@ enum ocelot_reg {
S2_CACHE_ACTION_DAT,
S2_CACHE_CNT_DAT,
S2_CACHE_TG_DAT,
+ PTP_PIN_CFG = PTP << TARGET_OFFSET,
+ PTP_PIN_TOD_SEC_MSB,
+ PTP_PIN_TOD_SEC_LSB,
+ PTP_PIN_TOD_NSEC,
+ PTP_CFG_MISC,
+ PTP_CLK_CFG_ADJ_CFG,
+ PTP_CLK_CFG_ADJ_FREQ,
};
enum ocelot_regfield {
diff --git a/drivers/net/ethernet/mscc/ocelot_board.c b/drivers/net/ethernet/mscc/ocelot_board.c
index 58bde1a9eacb..c508e51c1e28 100644
--- a/drivers/net/ethernet/mscc/ocelot_board.c
+++ b/drivers/net/ethernet/mscc/ocelot_board.c
@@ -182,6 +182,7 @@ static int mscc_ocelot_probe(struct platform_device *pdev)
struct {
enum ocelot_target id;
char *name;
+ u8 optional:1;
} res[] = {
{ SYS, "sys" },
{ REW, "rew" },
@@ -189,6 +190,7 @@ static int mscc_ocelot_probe(struct platform_device *pdev)
{ ANA, "ana" },
{ QS, "qs" },
{ S2, "s2" },
+ { PTP, "ptp", 1 },
};
if (!np && !pdev->dev.platform_data)
@@ -205,8 +207,14 @@ static int mscc_ocelot_probe(struct platform_device *pdev)
struct regmap *target;
target = ocelot_io_platform_init(ocelot, pdev, res[i].name);
- if (IS_ERR(target))
+ if (IS_ERR(target)) {
+ if (res[i].optional) {
+ ocelot->targets[res[i].id] = NULL;
+ continue;
+ }
+
return PTR_ERR(target);
+ }
ocelot->targets[res[i].id] = target;
}
diff --git a/drivers/net/ethernet/mscc/ocelot_ptp.h b/drivers/net/ethernet/mscc/ocelot_ptp.h
new file mode 100644
index 000000000000..9ede14a12573
--- /dev/null
+++ b/drivers/net/ethernet/mscc/ocelot_ptp.h
@@ -0,0 +1,41 @@
+/* SPDX-License-Identifier: (GPL-2.0 OR MIT) */
+/*
+ * Microsemi Ocelot Switch driver
+ *
+ * License: Dual MIT/GPL
+ * Copyright (c) 2017 Microsemi Corporation
+ */
+
+#ifndef _MSCC_OCELOT_PTP_H_
+#define _MSCC_OCELOT_PTP_H_
+
+#define PTP_PIN_CFG_RSZ 0x20
+#define PTP_PIN_TOD_SEC_MSB_RSZ PTP_PIN_CFG_RSZ
+#define PTP_PIN_TOD_SEC_LSB_RSZ PTP_PIN_CFG_RSZ
+#define PTP_PIN_TOD_NSEC_RSZ PTP_PIN_CFG_RSZ
+
+#define PTP_PIN_CFG_DOM BIT(0)
+#define PTP_PIN_CFG_SYNC BIT(2)
+#define PTP_PIN_CFG_ACTION(x) ((x) << 3)
+#define PTP_PIN_CFG_ACTION_MASK PTP_PIN_CFG_ACTION(0x7)
+
+enum {
+ PTP_PIN_ACTION_IDLE = 0,
+ PTP_PIN_ACTION_LOAD,
+ PTP_PIN_ACTION_SAVE,
+ PTP_PIN_ACTION_CLOCK,
+ PTP_PIN_ACTION_DELTA,
+ PTP_PIN_ACTION_NOSYNC,
+ PTP_PIN_ACTION_SYNC,
+};
+
+#define PTP_CFG_MISC_PTP_EN BIT(2)
+
+#define PSEC_PER_SEC 1000000000000LL
+
+#define PTP_CFG_CLK_ADJ_CFG_ENA BIT(0)
+#define PTP_CFG_CLK_ADJ_CFG_DIR BIT(1)
+
+#define PTP_CFG_CLK_ADJ_FREQ_NS BIT(30)
+
+#endif
diff --git a/drivers/net/ethernet/mscc/ocelot_regs.c b/drivers/net/ethernet/mscc/ocelot_regs.c
index 6c387f994ec5..e59977d20400 100644
--- a/drivers/net/ethernet/mscc/ocelot_regs.c
+++ b/drivers/net/ethernet/mscc/ocelot_regs.c
@@ -234,6 +234,16 @@ static const u32 ocelot_s2_regmap[] = {
REG(S2_CACHE_TG_DAT, 0x000388),
};
+static const u32 ocelot_ptp_regmap[] = {
+ REG(PTP_PIN_CFG, 0x000000),
+ REG(PTP_PIN_TOD_SEC_MSB, 0x000004),
+ REG(PTP_PIN_TOD_SEC_LSB, 0x000008),
+ REG(PTP_PIN_TOD_NSEC, 0x00000c),
+ REG(PTP_CFG_MISC, 0x0000a0),
+ REG(PTP_CLK_CFG_ADJ_CFG, 0x0000a4),
+ REG(PTP_CLK_CFG_ADJ_FREQ, 0x0000a8),
+};
+
static const u32 *ocelot_regmap[] = {
[ANA] = ocelot_ana_regmap,
[QS] = ocelot_qs_regmap,
@@ -241,6 +251,7 @@ static const u32 *ocelot_regmap[] = {
[REW] = ocelot_rew_regmap,
[SYS] = ocelot_sys_regmap,
[S2] = ocelot_s2_regmap,
+ [PTP] = ocelot_ptp_regmap,
};
static const struct reg_field ocelot_regfields[] = {
--
2.21.0
^ permalink raw reply related
* [PATCH net-next v2 6/8] net: mscc: improve the frame header parsing readability
From: Antoine Tenart @ 2019-07-05 19:52 UTC (permalink / raw)
To: davem, richardcochran, alexandre.belloni, UNGLinuxDriver, ralf,
paul.burton, jhogan
Cc: Antoine Tenart, netdev, linux-mips, thomas.petazzoni,
allan.nielsen
In-Reply-To: <20190705195213.22041-1-antoine.tenart@bootlin.com>
This cosmetic patch improves the frame header parsing readability by
introducing a new macro to access and mask its fields.
Signed-off-by: Antoine Tenart <antoine.tenart@bootlin.com>
---
drivers/net/ethernet/mscc/ocelot_board.c | 24 +++++++++++++-----------
1 file changed, 13 insertions(+), 11 deletions(-)
diff --git a/drivers/net/ethernet/mscc/ocelot_board.c b/drivers/net/ethernet/mscc/ocelot_board.c
index c508e51c1e28..09ad6a123347 100644
--- a/drivers/net/ethernet/mscc/ocelot_board.c
+++ b/drivers/net/ethernet/mscc/ocelot_board.c
@@ -16,24 +16,26 @@
#include "ocelot.h"
-static int ocelot_parse_ifh(u32 *ifh, struct frame_info *info)
+#define IFH_EXTRACT_BITFIELD64(x, o, w) (((x) >> (o)) & GENMASK_ULL((w) - 1, 0))
+
+static int ocelot_parse_ifh(u32 *_ifh, struct frame_info *info)
{
- int i;
u8 llen, wlen;
+ u64 ifh[2];
+
+ ifh[0] = be64_to_cpu(((__force __be64 *)_ifh)[0]);
+ ifh[1] = be64_to_cpu(((__force __be64 *)_ifh)[1]);
- /* The IFH is in network order, switch to CPU order */
- for (i = 0; i < IFH_LEN; i++)
- ifh[i] = ntohl((__force __be32)ifh[i]);
+ wlen = IFH_EXTRACT_BITFIELD64(ifh[0], 7, 8);
+ llen = IFH_EXTRACT_BITFIELD64(ifh[0], 15, 6);
- wlen = (ifh[1] >> 7) & 0xff;
- llen = (ifh[1] >> 15) & 0x3f;
info->len = OCELOT_BUFFER_CELL_SZ * wlen + llen - 80;
- info->port = (ifh[2] & GENMASK(14, 11)) >> 11;
+ info->port = IFH_EXTRACT_BITFIELD64(ifh[1], 43, 4);
- info->cpuq = (ifh[3] & GENMASK(27, 20)) >> 20;
- info->tag_type = (ifh[3] & BIT(16)) >> 16;
- info->vid = ifh[3] & GENMASK(11, 0);
+ info->cpuq = IFH_EXTRACT_BITFIELD64(ifh[1], 20, 8);
+ info->tag_type = IFH_EXTRACT_BITFIELD64(ifh[1], 16, 1);
+ info->vid = IFH_EXTRACT_BITFIELD64(ifh[1], 0, 12);
return 0;
}
--
2.21.0
^ permalink raw reply related
* [PATCH net-next v2 2/8] MIPS: dts: mscc: describe the PTP register range
From: Antoine Tenart @ 2019-07-05 19:52 UTC (permalink / raw)
To: davem, richardcochran, alexandre.belloni, UNGLinuxDriver, ralf,
paul.burton, jhogan
Cc: Antoine Tenart, netdev, linux-mips, thomas.petazzoni,
allan.nielsen
In-Reply-To: <20190705195213.22041-1-antoine.tenart@bootlin.com>
This patch adds one register range within the mscc,vsc7514-switch node,
to describe the PTP registers.
Signed-off-by: Antoine Tenart <antoine.tenart@bootlin.com>
---
arch/mips/boot/dts/mscc/ocelot.dtsi | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/arch/mips/boot/dts/mscc/ocelot.dtsi b/arch/mips/boot/dts/mscc/ocelot.dtsi
index 33ae74aaa1bb..1e55a778def5 100644
--- a/arch/mips/boot/dts/mscc/ocelot.dtsi
+++ b/arch/mips/boot/dts/mscc/ocelot.dtsi
@@ -120,6 +120,7 @@
reg = <0x1010000 0x10000>,
<0x1030000 0x10000>,
<0x1080000 0x100>,
+ <0x10e0000 0x10000>,
<0x11e0000 0x100>,
<0x11f0000 0x100>,
<0x1200000 0x100>,
@@ -134,7 +135,7 @@
<0x1800000 0x80000>,
<0x1880000 0x10000>,
<0x1060000 0x10000>;
- reg-names = "sys", "rew", "qs", "port0", "port1",
+ reg-names = "sys", "rew", "qs", "ptp", "port0", "port1",
"port2", "port3", "port4", "port5", "port6",
"port7", "port8", "port9", "port10", "qsys",
"ana", "s2";
--
2.21.0
^ permalink raw reply related
* [PATCH net-next v2 7/8] net: mscc: remove the frame_info cpuq member
From: Antoine Tenart @ 2019-07-05 19:52 UTC (permalink / raw)
To: davem, richardcochran, alexandre.belloni, UNGLinuxDriver, ralf,
paul.burton, jhogan
Cc: Antoine Tenart, netdev, linux-mips, thomas.petazzoni,
allan.nielsen
In-Reply-To: <20190705195213.22041-1-antoine.tenart@bootlin.com>
In struct frame_info, the cpuq member is never used. This cosmetic patch
removes it from the structure, and from the parsing of the frame header
as it's only set but never used.
Signed-off-by: Antoine Tenart <antoine.tenart@bootlin.com>
---
drivers/net/ethernet/mscc/ocelot.h | 1 -
drivers/net/ethernet/mscc/ocelot_board.c | 1 -
2 files changed, 2 deletions(-)
diff --git a/drivers/net/ethernet/mscc/ocelot.h b/drivers/net/ethernet/mscc/ocelot.h
index e0da8b4eddf2..515dee6fa8a6 100644
--- a/drivers/net/ethernet/mscc/ocelot.h
+++ b/drivers/net/ethernet/mscc/ocelot.h
@@ -45,7 +45,6 @@ struct frame_info {
u32 len;
u16 port;
u16 vid;
- u8 cpuq;
u8 tag_type;
};
diff --git a/drivers/net/ethernet/mscc/ocelot_board.c b/drivers/net/ethernet/mscc/ocelot_board.c
index 09ad6a123347..008a762512b9 100644
--- a/drivers/net/ethernet/mscc/ocelot_board.c
+++ b/drivers/net/ethernet/mscc/ocelot_board.c
@@ -33,7 +33,6 @@ static int ocelot_parse_ifh(u32 *_ifh, struct frame_info *info)
info->port = IFH_EXTRACT_BITFIELD64(ifh[1], 43, 4);
- info->cpuq = IFH_EXTRACT_BITFIELD64(ifh[1], 20, 8);
info->tag_type = IFH_EXTRACT_BITFIELD64(ifh[1], 16, 1);
info->vid = IFH_EXTRACT_BITFIELD64(ifh[1], 0, 12);
--
2.21.0
^ permalink raw reply related
* [PATCH net-next v2 8/8] net: mscc: PTP Hardware Clock (PHC) support
From: Antoine Tenart @ 2019-07-05 19:52 UTC (permalink / raw)
To: davem, richardcochran, alexandre.belloni, UNGLinuxDriver, ralf,
paul.burton, jhogan
Cc: Antoine Tenart, netdev, linux-mips, thomas.petazzoni,
allan.nielsen
In-Reply-To: <20190705195213.22041-1-antoine.tenart@bootlin.com>
This patch adds support for PTP Hardware Clock (PHC) to the Ocelot
switch for both PTP 1-step and 2-step modes.
Signed-off-by: Antoine Tenart <antoine.tenart@bootlin.com>
---
drivers/net/ethernet/mscc/ocelot.c | 393 ++++++++++++++++++++++-
drivers/net/ethernet/mscc/ocelot.h | 37 +++
drivers/net/ethernet/mscc/ocelot_board.c | 106 +++++-
3 files changed, 528 insertions(+), 8 deletions(-)
diff --git a/drivers/net/ethernet/mscc/ocelot.c b/drivers/net/ethernet/mscc/ocelot.c
index b71e4ecbe469..e05f209717e8 100644
--- a/drivers/net/ethernet/mscc/ocelot.c
+++ b/drivers/net/ethernet/mscc/ocelot.c
@@ -14,6 +14,7 @@
#include <linux/module.h>
#include <linux/netdevice.h>
#include <linux/phy.h>
+#include <linux/ptp_clock_kernel.h>
#include <linux/skbuff.h>
#include <linux/iopoll.h>
#include <net/arp.h>
@@ -538,7 +539,7 @@ static int ocelot_port_stop(struct net_device *dev)
*/
static int ocelot_gen_ifh(u32 *ifh, struct frame_info *info)
{
- ifh[0] = IFH_INJ_BYPASS;
+ ifh[0] = IFH_INJ_BYPASS | ((0x1ff & info->rew_op) << 21);
ifh[1] = (0xf00 & info->port) >> 8;
ifh[2] = (0xff & info->port) << 24;
ifh[3] = (info->tag_type << 16) | info->vid;
@@ -548,6 +549,7 @@ static int ocelot_gen_ifh(u32 *ifh, struct frame_info *info)
static int ocelot_port_xmit(struct sk_buff *skb, struct net_device *dev)
{
+ struct skb_shared_info *shinfo = skb_shinfo(skb);
struct ocelot_port *port = netdev_priv(dev);
struct ocelot *ocelot = port->ocelot;
u32 val, ifh[IFH_LEN];
@@ -566,6 +568,14 @@ static int ocelot_port_xmit(struct sk_buff *skb, struct net_device *dev)
info.port = BIT(port->chip_port);
info.tag_type = IFH_TAG_TYPE_C;
info.vid = skb_vlan_tag_get(skb);
+
+ /* Check if timestamping is needed */
+ if (ocelot->ptp && shinfo->tx_flags & SKBTX_HW_TSTAMP) {
+ info.rew_op = port->ptp_cmd;
+ if (port->ptp_cmd == IFH_REW_OP_TWO_STEP_PTP)
+ info.rew_op |= (port->ts_id % 4) << 3;
+ }
+
ocelot_gen_ifh(ifh, &info);
for (i = 0; i < IFH_LEN; i++)
@@ -596,11 +606,50 @@ static int ocelot_port_xmit(struct sk_buff *skb, struct net_device *dev)
dev->stats.tx_packets++;
dev->stats.tx_bytes += skb->len;
- dev_kfree_skb_any(skb);
+
+ if (ocelot->ptp && shinfo->tx_flags & SKBTX_HW_TSTAMP &&
+ port->ptp_cmd == IFH_REW_OP_TWO_STEP_PTP) {
+ struct ocelot_skb *oskb =
+ kzalloc(sizeof(struct ocelot_skb), GFP_KERNEL);
+
+ oskb->skb = skb;
+ oskb->id = port->ts_id % 4;
+ port->ts_id++;
+
+ list_add_tail(&oskb->head, &port->skbs);
+ } else {
+ dev_kfree_skb_any(skb);
+ }
return NETDEV_TX_OK;
}
+void ocelot_get_hwtimestamp(struct ocelot *ocelot, struct timespec64 *ts)
+{
+ unsigned long flags;
+ u32 val;
+
+ spin_lock_irqsave(&ocelot->ptp_clock_lock, flags);
+
+ /* Read current PTP time to get seconds */
+ val = ocelot_read_rix(ocelot, PTP_PIN_CFG, TOD_ACC_PIN);
+
+ val &= ~(PTP_PIN_CFG_SYNC | PTP_PIN_CFG_ACTION_MASK | PTP_PIN_CFG_DOM);
+ val |= PTP_PIN_CFG_ACTION(PTP_PIN_ACTION_SAVE);
+ ocelot_write_rix(ocelot, val, PTP_PIN_CFG, TOD_ACC_PIN);
+ ts->tv_sec = ocelot_read_rix(ocelot, PTP_PIN_TOD_SEC_LSB, TOD_ACC_PIN);
+
+ /* Read packet HW timestamp from FIFO */
+ val = ocelot_read(ocelot, SYS_PTP_TXSTAMP);
+ ts->tv_nsec = SYS_PTP_TXSTAMP_PTP_TXSTAMP(val);
+
+ /* Sec has incremented since the ts was registered */
+ if ((ts->tv_sec & 0x1) != !!(val & SYS_PTP_TXSTAMP_PTP_TXSTAMP_SEC))
+ ts->tv_sec--;
+
+ spin_unlock_irqrestore(&ocelot->ptp_clock_lock, flags);
+}
+
static int ocelot_mc_unsync(struct net_device *dev, const unsigned char *addr)
{
struct ocelot_port *port = netdev_priv(dev);
@@ -917,6 +966,97 @@ static int ocelot_get_port_parent_id(struct net_device *dev,
return 0;
}
+static int ocelot_hwstamp_get(struct ocelot_port *port, struct ifreq *ifr)
+{
+ struct ocelot *ocelot = port->ocelot;
+
+ return copy_to_user(ifr->ifr_data, &ocelot->hwtstamp_config,
+ sizeof(ocelot->hwtstamp_config)) ? -EFAULT : 0;
+}
+
+static int ocelot_hwstamp_set(struct ocelot_port *port, struct ifreq *ifr)
+{
+ struct ocelot *ocelot = port->ocelot;
+ struct hwtstamp_config cfg;
+
+ if (copy_from_user(&cfg, ifr->ifr_data, sizeof(cfg)))
+ return -EFAULT;
+
+ /* reserved for future extensions */
+ if (cfg.flags)
+ return -EINVAL;
+
+ /* Tx type sanity check */
+ switch (cfg.tx_type) {
+ case HWTSTAMP_TX_ON:
+ port->ptp_cmd = IFH_REW_OP_TWO_STEP_PTP;
+ break;
+ case HWTSTAMP_TX_ONESTEP_SYNC:
+ /* IFH_REW_OP_ONE_STEP_PTP updates the correctional field, we
+ * need to update the origin time.
+ */
+ port->ptp_cmd = IFH_REW_OP_ORIGIN_PTP;
+ break;
+ case HWTSTAMP_TX_OFF:
+ port->ptp_cmd = 0;
+ break;
+ default:
+ return -ERANGE;
+ }
+
+ mutex_lock(&ocelot->ptp_lock);
+
+ switch (cfg.rx_filter) {
+ case HWTSTAMP_FILTER_NONE:
+ break;
+ case HWTSTAMP_FILTER_ALL:
+ case HWTSTAMP_FILTER_SOME:
+ case HWTSTAMP_FILTER_PTP_V1_L4_EVENT:
+ case HWTSTAMP_FILTER_PTP_V1_L4_SYNC:
+ case HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ:
+ case HWTSTAMP_FILTER_NTP_ALL:
+ case HWTSTAMP_FILTER_PTP_V2_L4_EVENT:
+ case HWTSTAMP_FILTER_PTP_V2_L4_SYNC:
+ case HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ:
+ case HWTSTAMP_FILTER_PTP_V2_L2_EVENT:
+ case HWTSTAMP_FILTER_PTP_V2_L2_SYNC:
+ case HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ:
+ case HWTSTAMP_FILTER_PTP_V2_EVENT:
+ case HWTSTAMP_FILTER_PTP_V2_SYNC:
+ case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ:
+ cfg.rx_filter = HWTSTAMP_FILTER_PTP_V2_EVENT;
+ break;
+ default:
+ mutex_unlock(&ocelot->ptp_lock);
+ return -ERANGE;
+ }
+
+ /* Commit back the result & save it */
+ memcpy(&ocelot->hwtstamp_config, &cfg, sizeof(cfg));
+ mutex_unlock(&ocelot->ptp_lock);
+
+ return copy_to_user(ifr->ifr_data, &cfg, sizeof(cfg)) ? -EFAULT : 0;
+}
+
+static int ocelot_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
+{
+ struct ocelot_port *port = netdev_priv(dev);
+ struct ocelot *ocelot = port->ocelot;
+
+ /* The function is only used for PTP operations for now */
+ if (!ocelot->ptp)
+ return -EOPNOTSUPP;
+
+ switch (cmd) {
+ case SIOCSHWTSTAMP:
+ return ocelot_hwstamp_set(port, ifr);
+ case SIOCGHWTSTAMP:
+ return ocelot_hwstamp_get(port, ifr);
+ default:
+ return -EOPNOTSUPP;
+ }
+}
+
static const struct net_device_ops ocelot_port_netdev_ops = {
.ndo_open = ocelot_port_open,
.ndo_stop = ocelot_port_stop,
@@ -933,6 +1073,7 @@ static const struct net_device_ops ocelot_port_netdev_ops = {
.ndo_set_features = ocelot_set_features,
.ndo_get_port_parent_id = ocelot_get_port_parent_id,
.ndo_setup_tc = ocelot_setup_tc,
+ .ndo_do_ioctl = ocelot_ioctl,
};
static void ocelot_get_strings(struct net_device *netdev, u32 sset, u8 *data)
@@ -1014,12 +1155,42 @@ static int ocelot_get_sset_count(struct net_device *dev, int sset)
return ocelot->num_stats;
}
+static int ocelot_get_ts_info(struct net_device *dev,
+ struct ethtool_ts_info *info)
+{
+ struct ocelot_port *ocelot_port = netdev_priv(dev);
+ struct ocelot *ocelot = ocelot_port->ocelot;
+ int ret;
+
+ if (!ocelot->ptp)
+ return -EOPNOTSUPP;
+
+ ret = ethtool_op_get_ts_info(dev, info);
+ if (ret)
+ return ret;
+
+ info->phc_index = ocelot->ptp_clock ?
+ ptp_clock_index(ocelot->ptp_clock) : -1;
+ info->so_timestamping |= SOF_TIMESTAMPING_TX_SOFTWARE |
+ SOF_TIMESTAMPING_RX_SOFTWARE |
+ SOF_TIMESTAMPING_SOFTWARE |
+ SOF_TIMESTAMPING_TX_HARDWARE |
+ SOF_TIMESTAMPING_RX_HARDWARE |
+ SOF_TIMESTAMPING_RAW_HARDWARE;
+ info->tx_types = BIT(HWTSTAMP_TX_OFF) | BIT(HWTSTAMP_TX_ON) |
+ BIT(HWTSTAMP_TX_ONESTEP_SYNC);
+ info->rx_filters = BIT(HWTSTAMP_FILTER_NONE) | BIT(HWTSTAMP_FILTER_ALL);
+
+ return 0;
+}
+
static const struct ethtool_ops ocelot_ethtool_ops = {
.get_strings = ocelot_get_strings,
.get_ethtool_stats = ocelot_get_ethtool_stats,
.get_sset_count = ocelot_get_sset_count,
.get_link_ksettings = phy_ethtool_get_link_ksettings,
.set_link_ksettings = phy_ethtool_set_link_ksettings,
+ .get_ts_info = ocelot_get_ts_info,
};
static int ocelot_port_attr_stp_state_set(struct ocelot_port *ocelot_port,
@@ -1629,6 +1800,191 @@ struct notifier_block ocelot_switchdev_blocking_nb __read_mostly = {
};
EXPORT_SYMBOL(ocelot_switchdev_blocking_nb);
+int ocelot_ptp_gettime64(struct ptp_clock_info *ptp, struct timespec64 *ts)
+{
+ struct ocelot *ocelot = container_of(ptp, struct ocelot, ptp_info);
+ unsigned long flags;
+ time64_t s;
+ u32 val;
+ s64 ns;
+
+ spin_lock_irqsave(&ocelot->ptp_clock_lock, flags);
+
+ val = ocelot_read_rix(ocelot, PTP_PIN_CFG, TOD_ACC_PIN);
+ val &= ~(PTP_PIN_CFG_SYNC | PTP_PIN_CFG_ACTION_MASK | PTP_PIN_CFG_DOM);
+ val |= PTP_PIN_CFG_ACTION(PTP_PIN_ACTION_SAVE);
+ ocelot_write_rix(ocelot, val, PTP_PIN_CFG, TOD_ACC_PIN);
+
+ s = ocelot_read_rix(ocelot, PTP_PIN_TOD_SEC_MSB, TOD_ACC_PIN) & 0xffff;
+ s <<= 32;
+ s += ocelot_read_rix(ocelot, PTP_PIN_TOD_SEC_LSB, TOD_ACC_PIN);
+ ns = ocelot_read_rix(ocelot, PTP_PIN_TOD_NSEC, TOD_ACC_PIN);
+
+ spin_unlock_irqrestore(&ocelot->ptp_clock_lock, flags);
+
+ /* Deal with negative values */
+ if (ns >= 0x3ffffff0 && ns <= 0x3fffffff) {
+ s--;
+ ns &= 0xf;
+ ns += 999999984;
+ }
+
+ set_normalized_timespec64(ts, s, ns);
+ return 0;
+}
+
+static int ocelot_ptp_settime64(struct ptp_clock_info *ptp,
+ const struct timespec64 *ts)
+{
+ struct ocelot *ocelot = container_of(ptp, struct ocelot, ptp_info);
+ unsigned long flags;
+ u32 val;
+
+ spin_lock_irqsave(&ocelot->ptp_clock_lock, flags);
+
+ val = ocelot_read_rix(ocelot, PTP_PIN_CFG, TOD_ACC_PIN);
+ val &= ~(PTP_PIN_CFG_SYNC | PTP_PIN_CFG_ACTION_MASK | PTP_PIN_CFG_DOM);
+ val |= PTP_PIN_CFG_ACTION(PTP_PIN_ACTION_IDLE);
+
+ ocelot_write_rix(ocelot, val, PTP_PIN_CFG, TOD_ACC_PIN);
+
+ ocelot_write_rix(ocelot, lower_32_bits(ts->tv_sec), PTP_PIN_TOD_SEC_LSB,
+ TOD_ACC_PIN);
+ ocelot_write_rix(ocelot, upper_32_bits(ts->tv_sec), PTP_PIN_TOD_SEC_MSB,
+ TOD_ACC_PIN);
+ ocelot_write_rix(ocelot, ts->tv_nsec, PTP_PIN_TOD_NSEC, TOD_ACC_PIN);
+
+ val = ocelot_read_rix(ocelot, PTP_PIN_CFG, TOD_ACC_PIN);
+ val &= ~(PTP_PIN_CFG_SYNC | PTP_PIN_CFG_ACTION_MASK | PTP_PIN_CFG_DOM);
+ val |= PTP_PIN_CFG_ACTION(PTP_PIN_ACTION_LOAD);
+
+ ocelot_write_rix(ocelot, val, PTP_PIN_CFG, TOD_ACC_PIN);
+
+ spin_unlock_irqrestore(&ocelot->ptp_clock_lock, flags);
+ return 0;
+}
+
+static int ocelot_ptp_adjtime(struct ptp_clock_info *ptp, s64 delta)
+{
+ if (delta > -(NSEC_PER_SEC / 2) && delta < (NSEC_PER_SEC / 2)) {
+ struct ocelot *ocelot = container_of(ptp, struct ocelot, ptp_info);
+ unsigned long flags;
+ u32 val;
+
+ spin_lock_irqsave(&ocelot->ptp_clock_lock, flags);
+
+ val = ocelot_read_rix(ocelot, PTP_PIN_CFG, TOD_ACC_PIN);
+ val &= ~(PTP_PIN_CFG_SYNC | PTP_PIN_CFG_ACTION_MASK | PTP_PIN_CFG_DOM);
+ val |= PTP_PIN_CFG_ACTION(PTP_PIN_ACTION_IDLE);
+
+ ocelot_write_rix(ocelot, val, PTP_PIN_CFG, TOD_ACC_PIN);
+
+ ocelot_write_rix(ocelot, 0, PTP_PIN_TOD_SEC_LSB, TOD_ACC_PIN);
+ ocelot_write_rix(ocelot, 0, PTP_PIN_TOD_SEC_MSB, TOD_ACC_PIN);
+ ocelot_write_rix(ocelot, delta, PTP_PIN_TOD_NSEC, TOD_ACC_PIN);
+
+ val = ocelot_read_rix(ocelot, PTP_PIN_CFG, TOD_ACC_PIN);
+ val &= ~(PTP_PIN_CFG_SYNC | PTP_PIN_CFG_ACTION_MASK | PTP_PIN_CFG_DOM);
+ val |= PTP_PIN_CFG_ACTION(PTP_PIN_ACTION_DELTA);
+
+ ocelot_write_rix(ocelot, val, PTP_PIN_CFG, TOD_ACC_PIN);
+
+ spin_unlock_irqrestore(&ocelot->ptp_clock_lock, flags);
+ } else {
+ /* Fall back using ocelot_ptp_settime64 which is not exact. */
+ struct timespec64 ts;
+ u64 now;
+
+ ocelot_ptp_gettime64(ptp, &ts);
+
+ now = ktime_to_ns(timespec64_to_ktime(ts));
+ ts = ns_to_timespec64(now + delta);
+
+ ocelot_ptp_settime64(ptp, &ts);
+ }
+ return 0;
+}
+
+static int ocelot_ptp_adjfine(struct ptp_clock_info *ptp, long scaled_ppm)
+{
+ struct ocelot *ocelot = container_of(ptp, struct ocelot, ptp_info);
+ u32 unit = 0, direction = 0;
+ unsigned long flags;
+ u64 adj = 0;
+
+ if (!scaled_ppm)
+ goto disable_adj;
+
+ if (scaled_ppm < 0) {
+ direction = PTP_CFG_CLK_ADJ_CFG_DIR;
+ scaled_ppm = -scaled_ppm;
+ }
+
+ adj = PSEC_PER_SEC << 16;
+ do_div(adj, scaled_ppm);
+ do_div(adj, 1000);
+
+ /* If the adjustment value is too large, use ns instead */
+ if (adj >= (1L << 30)) {
+ unit = PTP_CFG_CLK_ADJ_FREQ_NS;
+ do_div(adj, 1000);
+ }
+
+ spin_lock_irqsave(&ocelot->ptp_clock_lock, flags);
+
+ /* Still too big */
+ if (adj >= (1L << 30))
+ goto disable_adj;
+
+ ocelot_write(ocelot, unit | adj, PTP_CLK_CFG_ADJ_FREQ);
+ ocelot_write(ocelot, PTP_CFG_CLK_ADJ_CFG_ENA | direction,
+ PTP_CLK_CFG_ADJ_CFG);
+
+ spin_unlock_irqrestore(&ocelot->ptp_clock_lock, flags);
+ return 0;
+
+disable_adj:
+ ocelot_write(ocelot, 0, PTP_CLK_CFG_ADJ_CFG);
+
+ spin_unlock_irqrestore(&ocelot->ptp_clock_lock, flags);
+ return 0;
+}
+
+static struct ptp_clock_info ocelot_ptp_clock_info = {
+ .owner = THIS_MODULE,
+ .name = "ocelot ptp",
+ .max_adj = 0x7fffffff,
+ .n_alarm = 0,
+ .n_ext_ts = 0,
+ .n_per_out = 0,
+ .n_pins = 0,
+ .pps = 0,
+ .gettime64 = ocelot_ptp_gettime64,
+ .settime64 = ocelot_ptp_settime64,
+ .adjtime = ocelot_ptp_adjtime,
+ .adjfine = ocelot_ptp_adjfine,
+};
+
+static int ocelot_init_timestamp(struct ocelot *ocelot)
+{
+ ocelot->ptp_info = ocelot_ptp_clock_info;
+
+ ocelot->ptp_clock = ptp_clock_register(&ocelot->ptp_info, ocelot->dev);
+ if (IS_ERR(ocelot->ptp_clock))
+ return PTR_ERR(ocelot->ptp_clock);
+ /* Check if PHC support is missing at the configuration level */
+ if (!ocelot->ptp_clock)
+ return 0;
+
+ ocelot_write(ocelot, SYS_PTP_CFG_PTP_STAMP_WID(30), SYS_PTP_CFG);
+ ocelot_write(ocelot, 0xffffffff, ANA_TABLES_PTP_ID_LOW);
+ ocelot_write(ocelot, 0xffffffff, ANA_TABLES_PTP_ID_HIGH);
+
+ ocelot_write(ocelot, PTP_CFG_MISC_PTP_EN, PTP_CFG_MISC);
+
+ return 0;
+}
+
int ocelot_probe_port(struct ocelot *ocelot, u8 port,
void __iomem *regs,
struct phy_device *phy)
@@ -1661,6 +2017,8 @@ int ocelot_probe_port(struct ocelot *ocelot, u8 port,
ocelot_mact_learn(ocelot, PGID_CPU, dev->dev_addr, ocelot_port->pvid,
ENTRYTYPE_LOCKED);
+ INIT_LIST_HEAD(&ocelot_port->skbs);
+
err = register_netdev(dev);
if (err) {
dev_err(ocelot->dev, "register_netdev failed\n");
@@ -1684,7 +2042,7 @@ EXPORT_SYMBOL(ocelot_probe_port);
int ocelot_init(struct ocelot *ocelot)
{
u32 port;
- int i, cpu = ocelot->num_phys_ports;
+ int i, ret, cpu = ocelot->num_phys_ports;
char queue_name[32];
ocelot->lags = devm_kcalloc(ocelot->dev, ocelot->num_phys_ports,
@@ -1699,6 +2057,8 @@ int ocelot_init(struct ocelot *ocelot)
return -ENOMEM;
mutex_init(&ocelot->stats_lock);
+ mutex_init(&ocelot->ptp_lock);
+ spin_lock_init(&ocelot->ptp_clock_lock);
snprintf(queue_name, sizeof(queue_name), "%s-stats",
dev_name(ocelot->dev));
ocelot->stats_queue = create_singlethread_workqueue(queue_name);
@@ -1812,15 +2172,42 @@ int ocelot_init(struct ocelot *ocelot)
INIT_DELAYED_WORK(&ocelot->stats_work, ocelot_check_stats_work);
queue_delayed_work(ocelot->stats_queue, &ocelot->stats_work,
OCELOT_STATS_CHECK_DELAY);
+
+ if (ocelot->ptp) {
+ ret = ocelot_init_timestamp(ocelot);
+ if (ret) {
+ dev_err(ocelot->dev,
+ "Timestamp initialization failed\n");
+ return ret;
+ }
+ }
+
return 0;
}
EXPORT_SYMBOL(ocelot_init);
void ocelot_deinit(struct ocelot *ocelot)
{
+ struct list_head *pos, *tmp;
+ struct ocelot_port *port;
+ struct ocelot_skb *entry;
+ int i;
+
destroy_workqueue(ocelot->stats_queue);
mutex_destroy(&ocelot->stats_lock);
ocelot_ace_deinit();
+
+ for (i = 0; i < ocelot->num_phys_ports; i++) {
+ port = ocelot->ports[i];
+
+ list_for_each_safe(pos, tmp, &port->skbs) {
+ entry = list_entry(pos, struct ocelot_skb, head);
+
+ list_del(pos);
+ dev_kfree_skb_any(entry->skb);
+ kfree(entry);
+ }
+ }
}
EXPORT_SYMBOL(ocelot_deinit);
diff --git a/drivers/net/ethernet/mscc/ocelot.h b/drivers/net/ethernet/mscc/ocelot.h
index 515dee6fa8a6..bad4b6bbdc32 100644
--- a/drivers/net/ethernet/mscc/ocelot.h
+++ b/drivers/net/ethernet/mscc/ocelot.h
@@ -11,9 +11,11 @@
#include <linux/bitops.h>
#include <linux/etherdevice.h>
#include <linux/if_vlan.h>
+#include <linux/net_tstamp.h>
#include <linux/phy.h>
#include <linux/phy/phy.h>
#include <linux/platform_device.h>
+#include <linux/ptp_clock_kernel.h>
#include <linux/regmap.h>
#include "ocelot_ana.h"
@@ -46,6 +48,8 @@ struct frame_info {
u16 port;
u16 vid;
u8 tag_type;
+ u16 rew_op;
+ u32 timestamp; /* rew_val */
};
#define IFH_INJ_BYPASS BIT(31)
@@ -54,6 +58,12 @@ struct frame_info {
#define IFH_TAG_TYPE_C 0
#define IFH_TAG_TYPE_S 1
+#define IFH_REW_OP_NOOP 0x0
+#define IFH_REW_OP_DSCP 0x1
+#define IFH_REW_OP_ONE_STEP_PTP 0x2
+#define IFH_REW_OP_TWO_STEP_PTP 0x3
+#define IFH_REW_OP_ORIGIN_PTP 0x5
+
#define OCELOT_SPEED_2500 0
#define OCELOT_SPEED_1000 1
#define OCELOT_SPEED_100 2
@@ -401,6 +411,13 @@ enum ocelot_regfield {
REGFIELD_MAX
};
+enum ocelot_clk_pins {
+ ALT_PPS_PIN = 1,
+ EXT_CLK_PIN,
+ ALT_LDST_PIN,
+ TOD_ACC_PIN
+};
+
struct ocelot_multicast {
struct list_head list;
unsigned char addr[ETH_ALEN];
@@ -450,6 +467,13 @@ struct ocelot {
u64 *stats;
struct delayed_work stats_work;
struct workqueue_struct *stats_queue;
+
+ u8 ptp:1;
+ struct ptp_clock *ptp_clock;
+ struct ptp_clock_info ptp_info;
+ struct hwtstamp_config hwtstamp_config;
+ struct mutex ptp_lock; /* Protects the PTP interface state */
+ spinlock_t ptp_clock_lock; /* Protects the PTP clock */
};
struct ocelot_port {
@@ -473,6 +497,16 @@ struct ocelot_port {
struct phy *serdes;
struct ocelot_port_tc tc;
+
+ u8 ptp_cmd;
+ struct list_head skbs;
+ u8 ts_id;
+};
+
+struct ocelot_skb {
+ struct list_head head;
+ struct sk_buff *skb;
+ u8 id;
};
u32 __ocelot_read_ix(struct ocelot *ocelot, u32 reg, u32 offset);
@@ -517,4 +551,7 @@ extern struct notifier_block ocelot_netdevice_nb;
extern struct notifier_block ocelot_switchdev_nb;
extern struct notifier_block ocelot_switchdev_blocking_nb;
+int ocelot_ptp_gettime64(struct ptp_clock_info *ptp, struct timespec64 *ts);
+void ocelot_get_hwtimestamp(struct ocelot *ocelot, struct timespec64 *ts);
+
#endif
diff --git a/drivers/net/ethernet/mscc/ocelot_board.c b/drivers/net/ethernet/mscc/ocelot_board.c
index 008a762512b9..2e7e5944a7b0 100644
--- a/drivers/net/ethernet/mscc/ocelot_board.c
+++ b/drivers/net/ethernet/mscc/ocelot_board.c
@@ -31,6 +31,8 @@ static int ocelot_parse_ifh(u32 *_ifh, struct frame_info *info)
info->len = OCELOT_BUFFER_CELL_SZ * wlen + llen - 80;
+ info->timestamp = IFH_EXTRACT_BITFIELD64(ifh[0], 21, 32);
+
info->port = IFH_EXTRACT_BITFIELD64(ifh[1], 43, 4);
info->tag_type = IFH_EXTRACT_BITFIELD64(ifh[1], 16, 1);
@@ -98,7 +100,11 @@ static irqreturn_t ocelot_xtr_irq_handler(int irq, void *arg)
int sz, len, buf_len;
u32 ifh[4];
u32 val;
- struct frame_info info;
+ struct frame_info info = {};
+ struct timespec64 ts;
+ struct skb_shared_hwtstamps *shhwtstamps;
+ u64 tod_in_ns;
+ u64 full_ts_in_ns;
for (i = 0; i < IFH_LEN; i++) {
err = ocelot_rx_frame_word(ocelot, grp, true, &ifh[i]);
@@ -145,6 +151,22 @@ static irqreturn_t ocelot_xtr_irq_handler(int irq, void *arg)
break;
}
+ if (ocelot->ptp) {
+ ocelot_ptp_gettime64(&ocelot->ptp_info, &ts);
+
+ tod_in_ns = ktime_set(ts.tv_sec, ts.tv_nsec);
+ if ((tod_in_ns & 0xffffffff) < info.timestamp)
+ full_ts_in_ns = (((tod_in_ns >> 32) - 1) << 32) |
+ info.timestamp;
+ else
+ full_ts_in_ns = (tod_in_ns & GENMASK_ULL(63, 32)) |
+ info.timestamp;
+
+ shhwtstamps = skb_hwtstamps(skb);
+ memset(shhwtstamps, 0, sizeof(struct skb_shared_hwtstamps));
+ shhwtstamps->hwtstamp = full_ts_in_ns;
+ }
+
/* Everything we see on an interface that is in the HW bridge
* has already been forwarded.
*/
@@ -164,6 +186,65 @@ static irqreturn_t ocelot_xtr_irq_handler(int irq, void *arg)
return IRQ_HANDLED;
}
+static irqreturn_t ocelot_ptp_rdy_irq_handler(int irq, void *arg)
+{
+ struct ocelot *ocelot = arg;
+
+ do {
+ struct skb_shared_hwtstamps shhwtstamps;
+ struct list_head *pos, *tmp;
+ struct sk_buff *skb = NULL;
+ struct ocelot_skb *entry;
+ struct ocelot_port *port;
+ struct timespec64 ts;
+ u32 val, id, txport;
+
+ val = ocelot_read(ocelot, SYS_PTP_STATUS);
+
+ /* Check if a timestamp can be retrieved */
+ if (!(val & SYS_PTP_STATUS_PTP_MESS_VLD))
+ break;
+
+ WARN_ON(val & SYS_PTP_STATUS_PTP_OVFL);
+
+ /* Retrieve the ts ID and Tx port */
+ id = SYS_PTP_STATUS_PTP_MESS_ID_X(val);
+ txport = SYS_PTP_STATUS_PTP_MESS_TXPORT_X(val);
+
+ /* Retrieve its associated skb */
+ port = ocelot->ports[txport];
+
+ list_for_each_safe(pos, tmp, &port->skbs) {
+ entry = list_entry(pos, struct ocelot_skb, head);
+ if (entry->id != id)
+ continue;
+
+ skb = entry->skb;
+
+ list_del(pos);
+ kfree(entry);
+ }
+
+ /* Next ts */
+ ocelot_write(ocelot, SYS_PTP_NXT_PTP_NXT, SYS_PTP_NXT);
+
+ if (unlikely(!skb))
+ continue;
+
+ /* Get the h/w timestamp */
+ ocelot_get_hwtimestamp(ocelot, &ts);
+
+ /* Set the timestamp into the skb */
+ memset(&shhwtstamps, 0, sizeof(shhwtstamps));
+ shhwtstamps.hwtstamp = ktime_set(ts.tv_sec, ts.tv_nsec);
+ skb_tstamp_tx(skb, &shhwtstamps);
+
+ dev_kfree_skb_any(skb);
+ } while (true);
+
+ return IRQ_HANDLED;
+}
+
static const struct of_device_id mscc_ocelot_match[] = {
{ .compatible = "mscc,vsc7514-switch" },
{ }
@@ -172,8 +253,8 @@ MODULE_DEVICE_TABLE(of, mscc_ocelot_match);
static int mscc_ocelot_probe(struct platform_device *pdev)
{
- int err, irq;
unsigned int i;
+ int err, irq_xtr, irq_ptp_rdy;
struct device_node *np = pdev->dev.of_node;
struct device_node *ports, *portnp;
struct ocelot *ocelot;
@@ -232,16 +313,31 @@ static int mscc_ocelot_probe(struct platform_device *pdev)
if (err)
return err;
- irq = platform_get_irq_byname(pdev, "xtr");
- if (irq < 0)
+ irq_xtr = platform_get_irq_byname(pdev, "xtr");
+ if (irq_xtr < 0)
return -ENODEV;
- err = devm_request_threaded_irq(&pdev->dev, irq, NULL,
+ err = devm_request_threaded_irq(&pdev->dev, irq_xtr, NULL,
ocelot_xtr_irq_handler, IRQF_ONESHOT,
"frame extraction", ocelot);
if (err)
return err;
+
+ irq_ptp_rdy = platform_get_irq_byname(pdev, "ptp_rdy");
+ if (irq_ptp_rdy > 0) {
+ err = devm_request_threaded_irq(&pdev->dev, irq_ptp_rdy, NULL,
+ ocelot_ptp_rdy_irq_handler,
+ IRQF_ONESHOT, "ptp ready",
+ ocelot);
+ if (err)
+ return err;
+
+ /* Check if we can support PTP */
+ if (ocelot->targets[PTP])
+ ocelot->ptp = 1;
+ }
+
regmap_field_write(ocelot->regfields[SYS_RESET_CFG_MEM_INIT], 1);
regmap_field_write(ocelot->regfields[SYS_RESET_CFG_MEM_ENA], 1);
--
2.21.0
^ permalink raw reply related
* Re: [PATCH] selftests: txring_overwrite: fix incorrect test of mmap() return value
From: Willem de Bruijn @ 2019-07-05 19:55 UTC (permalink / raw)
To: Frank de Brabander; +Cc: David S . Miller, Network Development
In-Reply-To: <1562326994-4569-1-git-send-email-debrabander@gmail.com>
On Fri, Jul 5, 2019 at 7:44 AM Frank de Brabander <debrabander@gmail.com> wrote:
>
> If mmap() fails it returns MAP_FAILED, which is defined as ((void *) -1).
> The current if-statement incorrectly tests if *ring is NULL.
>
> Signed-off-by: Frank de Brabander <debrabander@gmail.com>
Acked-by: Willem de Bruijn <willemb@google.com>
Fixes: 358be656406d ("selftests/net: add txring_overwrite")
Thanks Frank. Please mark future networking patches as [PATCH net] or
[PATCH net-next].
^ permalink raw reply
* Re: [PATCH net-next 12/12] net/mlx5e: Add kTLS TX HW offload support
From: Jakub Kicinski @ 2019-07-05 20:17 UTC (permalink / raw)
To: Tariq Toukan
Cc: David S. Miller, netdev, Eran Ben Elisha, Saeed Mahameed, moshe
In-Reply-To: <1562340622-4423-13-git-send-email-tariqt@mellanox.com>
On Fri, 5 Jul 2019 18:30:22 +0300, Tariq Toukan wrote:
> Add support for transmit side kernel-TLS acceleration.
> Offload the crypto encryption to HW.
>
> Per TLS connection:
> - Use a separate TIS to maintain the HW context.
> - Use a separate encryption key.
> - Maintain static and progress HW contexts by posting the proper
> WQEs at creation time, or upon resync.
> - Use a special DUMP opcode to replay the previous frags and sync
> the HW context.
>
> To make sure the SQ is able to serve an xmit request, increase
> SQ stop room to cover:
> - static params WQE,
> - progress params WQE, and
> - resync DUMP per frag.
>
> Currently supporting TLS 1.2, and key size 128bit.
>
> Tested over SimX simulator.
>
> Signed-off-by: Tariq Toukan <tariqt@mellanox.com>
> Signed-off-by: Eran Ben Elisha <eranbe@mellanox.com>
> Signed-off-by: Saeed Mahameed <saeedm@mellanox.com>
> +struct sk_buff *mlx5e_ktls_handle_tx_skb(struct net_device *netdev,
> + struct mlx5e_txqsq *sq,
> + struct sk_buff *skb,
> + struct mlx5e_tx_wqe **wqe, u16 *pi)
> +{
> + struct mlx5e_ktls_offload_context_tx *priv_tx;
> + struct mlx5e_sq_stats *stats = sq->stats;
> + struct mlx5_wqe_ctrl_seg *cseg;
> + struct tls_context *tls_ctx;
> + int datalen;
> + u32 seq;
> +
> + if (!skb->sk || !tls_is_sk_tx_device_offloaded(skb->sk))
> + goto out;
> +
> + datalen = skb->len - (skb_transport_offset(skb) + tcp_hdrlen(skb));
> + if (!datalen)
> + goto out;
> +
> + tls_ctx = tls_get_ctx(skb->sk);
> + if (unlikely(tls_ctx->netdev != netdev))
This really shouldn't happen, could you please add a WARN_ON_ONCE here?
> + goto err_out;
> +
> + priv_tx = mlx5e_get_ktls_tx_priv_ctx(tls_ctx);
> +
> + if (unlikely(mlx5e_ktls_tx_offload_test_and_clear_pending(priv_tx))) {
> + mlx5e_ktls_tx_post_param_wqes(sq, priv_tx, false, false);
> + *wqe = mlx5e_sq_fetch_wqe(sq, sizeof(**wqe), pi);
> + stats->tls_ctx++;
> + }
> +
> + seq = ntohl(tcp_hdr(skb)->seq);
> + if (unlikely(priv_tx->expected_seq != seq)) {
> + skb = mlx5e_ktls_tx_handle_ooo(priv_tx, sq, skb, seq);
> + if (unlikely(!skb))
> + goto out;
> + *wqe = mlx5e_sq_fetch_wqe(sq, sizeof(**wqe), pi);
> + }
> +
> + priv_tx->expected_seq = seq + datalen;
> +
> + cseg = &(*wqe)->ctrl;
> + cseg->imm = cpu_to_be32(priv_tx->tisn);
> +
> + stats->tls_encrypted_packets += skb_is_gso(skb) ? skb_shinfo(skb)->gso_segs : 1;
> + stats->tls_encrypted_bytes += datalen;
> +
> +out:
> + return skb;
> +
> +err_out:
> + dev_kfree_skb_any(skb);
> + return NULL;
> +}
> diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_stats.c b/drivers/net/ethernet/mellanox/mlx5/core/en_stats.c
> index 5f540db47cc9..539b4d3656da 100644
> --- a/drivers/net/ethernet/mellanox/mlx5/core/en_stats.c
> +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_stats.c
> @@ -48,8 +48,15 @@
> { MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, tx_nop) },
>
> #ifdef CONFIG_MLX5_EN_TLS
> + { MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, tx_tls_encrypted_packets) },
As mentioned in the other email could you change this in docs and
the nfp driver (just change the ethtool string)?
> + { MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, tx_tls_encrypted_bytes) },
This one looks like it'd be worth adding to the general doc.
Could you please make it clear this only counts L4 payload data,
not the full frames? Also perhaps worth mentioning for the packet
counter that it doesn't count pure acks and other frames with no
playload.
> + { MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, tx_tls_ctx) },
And this one.
> { MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, tx_tls_ooo) },
> { MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, tx_tls_resync_bytes) },
> + { MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, tx_tls_drop_no_sync_data) },
> + { MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, tx_tls_drop_bypass_req) },
And this one, too.
> + { MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, tx_tls_dump_packets) },
> + { MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, tx_tls_dump_bytes) },
> #endif
>
> { MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, rx_lro_packets) },
> @@ -271,8 +278,15 @@ static void mlx5e_grp_sw_update_stats(struct mlx5e_priv *priv)
> s->tx_csum_none += sq_stats->csum_none;
> s->tx_csum_partial += sq_stats->csum_partial;
> #ifdef CONFIG_MLX5_EN_TLS
> - s->tx_tls_ooo += sq_stats->tls_ooo;
> - s->tx_tls_resync_bytes += sq_stats->tls_resync_bytes;
> + s->tx_tls_encrypted_packets += sq_stats->tls_encrypted_packets;
> + s->tx_tls_encrypted_bytes += sq_stats->tls_encrypted_bytes;
> + s->tx_tls_ctx += sq_stats->tls_ctx;
> + s->tx_tls_ooo += sq_stats->tls_ooo;
> + s->tx_tls_resync_bytes += sq_stats->tls_resync_bytes;
> + s->tx_tls_drop_no_sync_data += sq_stats->tls_drop_no_sync_data;
> + s->tx_tls_drop_bypass_req += sq_stats->tls_drop_bypass_req;
> + s->tx_tls_dump_bytes += sq_stats->tls_dump_bytes;
> + s->tx_tls_dump_packets += sq_stats->tls_dump_packets;
> #endif
> s->tx_cqes += sq_stats->cqes;
> }
> @@ -1293,6 +1307,16 @@ static int mlx5e_grp_tls_fill_stats(struct mlx5e_priv *priv, u64 *data, int idx)
> { MLX5E_DECLARE_TX_STAT(struct mlx5e_sq_stats, csum_partial_inner) },
> { MLX5E_DECLARE_TX_STAT(struct mlx5e_sq_stats, added_vlan_packets) },
> { MLX5E_DECLARE_TX_STAT(struct mlx5e_sq_stats, nop) },
> +#ifdef CONFIG_MLX5_EN_TLS
> + { MLX5E_DECLARE_TX_STAT(struct mlx5e_sq_stats, tls_encrypted_packets) },
> + { MLX5E_DECLARE_TX_STAT(struct mlx5e_sq_stats, tls_encrypted_bytes) },
> + { MLX5E_DECLARE_TX_STAT(struct mlx5e_sq_stats, tls_ctx) },
> + { MLX5E_DECLARE_TX_STAT(struct mlx5e_sq_stats, tls_ooo) },
> + { MLX5E_DECLARE_TX_STAT(struct mlx5e_sq_stats, tls_drop_no_sync_data) },
> + { MLX5E_DECLARE_TX_STAT(struct mlx5e_sq_stats, tls_drop_bypass_req) },
> + { MLX5E_DECLARE_TX_STAT(struct mlx5e_sq_stats, tls_dump_packets) },
> + { MLX5E_DECLARE_TX_STAT(struct mlx5e_sq_stats, tls_dump_bytes) },
> +#endif
> { MLX5E_DECLARE_TX_STAT(struct mlx5e_sq_stats, csum_none) },
> { MLX5E_DECLARE_TX_STAT(struct mlx5e_sq_stats, stopped) },
> { MLX5E_DECLARE_TX_STAT(struct mlx5e_sq_stats, dropped) },
^ permalink raw reply
* Re: [PATCH net-next 00/12] mlx5 TLS TX HW offload support
From: Jakub Kicinski @ 2019-07-05 20:19 UTC (permalink / raw)
To: Tariq Toukan
Cc: David S. Miller, netdev, Eran Ben Elisha, Saeed Mahameed, moshe
In-Reply-To: <1562340622-4423-1-git-send-email-tariqt@mellanox.com>
On Fri, 5 Jul 2019 18:30:10 +0300, Tariq Toukan wrote:
> Hi Dave,
>
> This series from Eran and me, adds TLS TX HW offload support to
> the mlx5 driver.
>
> This offloads the kTLS encryption process from kernel to the
> Mellanox NIC, saving CPU cycles and improving utilization.
>
> Upon a new TLS connection request, driver is responsible to create
> a dedicated HW context and configure it according to the crypto info,
> so HW can do the encryption itself.
>
> When the HW context gets out-of-sync (i.e. due to packets retransmission),
> driver is responsible for the re-sync process.
> This is done by posting special resync descriptors to the HW.
>
> Feature is supported on Mellanox Connect-X 6DX, and newer.
> Series was tested on SimX simulator.
>
> Series generated against net-next commit [1], with Saeed's request pulled [2]:
>
> [1] c4cde5804d51 Merge git://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf-next
> [2] git://git.kernel.org/pub/scm/linux/kernel/git/saeed/linux.git tags/mlx5-updates-2019-07-04-v2
>
> Changes from last pull request:
> Fixed comments from Jakub:
> Patch 4:
> - Replace zero memset with a call to memzero_explicit().
> Patch 11:
> - Fix stats counters names.
> - Drop TLS SKB with non-matching netdev.
You guys probably really want to make 5.3 with this, so please feel free
to follow up on the comments to patch 12 separately.
Acked-by: Jakub Kicinski <jakub.kicinski@netronome.com>
^ permalink raw reply
* [PATCH bpf-next 0/2] libbpf: add an option to reuse maps when loading a program
From: Anton Protopopov @ 2019-07-05 20:40 UTC (permalink / raw)
To: Alexei Starovoitov, Daniel Borkmann, Martin KaFai Lau, Song Liu,
Yonghong Song, netdev, bpf, linux-kernel
Cc: Anton Protopopov
The following two patches add an option for users to reuse existing maps when
loading a program using the bpf_prog_load_xattr function. A user can specify a
directory containing pinned maps inside the bpf_prog_load_attr structure, and in
this case the bpf_prog_load_xattr function will replace (bpf_map__reuse_fd) all
maps defined in the object with file descriptors obtained from corresponding
entries from the specified directory.
Anton Protopopov (2):
bpf, libbpf: add a new API bpf_object__reuse_maps()
bpf, libbpf: add an option to reuse existing maps in bpf_prog_load_xattr
tools/lib/bpf/libbpf.c | 42 ++++++++++++++++++++++++++++++++++++++++
tools/lib/bpf/libbpf.h | 3 +++
tools/lib/bpf/libbpf.map | 1 +
3 files changed, 46 insertions(+)
--
2.19.1
^ permalink raw reply
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