Netdev List
 help / color / mirror / Atom feed
* [patch net-next v2 1/3] net: sched: change name of zombie chain to "held_by_acts_only"
From: Jiri Pirko @ 2018-08-01 10:36 UTC (permalink / raw)
  To: netdev; +Cc: davem, jhs, xiyou.wangcong, jakub.kicinski, mlxsw
In-Reply-To: <20180801103657.10532-1-jiri@resnulli.us>

From: Jiri Pirko <jiri@mellanox.com>

As mentioned by Cong and Jakub during the review process, it is a bit
odd to sometimes (act flow) create a new chain which would be
immediately a "zombie". So just rename it to "held_by_acts_only".

Signed-off-by: Jiri Pirko <jiri@mellanox.com>
Suggested-by: Cong Wang <xiyou.wangcong@gmail.com>
Suggested-by: Jakub Kicinski <jakub.kicinski@netronome.com>
Acked-by: Cong Wang <xiyou.wangcong@gmail.com>
---
 net/sched/cls_api.c | 14 ++++++--------
 1 file changed, 6 insertions(+), 8 deletions(-)

diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c
index e20aad1987b8..2f78341f2888 100644
--- a/net/sched/cls_api.c
+++ b/net/sched/cls_api.c
@@ -272,11 +272,10 @@ static void tcf_chain_release_by_act(struct tcf_chain *chain)
 	--chain->action_refcnt;
 }
 
-static bool tcf_chain_is_zombie(struct tcf_chain *chain)
+static bool tcf_chain_held_by_acts_only(struct tcf_chain *chain)
 {
 	/* In case all the references are action references, this
-	 * chain is a zombie and should not be listed in the chain
-	 * dump list.
+	 * chain should not be shown to the user.
 	 */
 	return chain->refcnt == chain->action_refcnt;
 }
@@ -1838,10 +1837,9 @@ static int tc_ctl_chain(struct sk_buff *skb, struct nlmsghdr *n,
 	chain = tcf_chain_lookup(block, chain_index);
 	if (n->nlmsg_type == RTM_NEWCHAIN) {
 		if (chain) {
-			if (tcf_chain_is_zombie(chain)) {
+			if (tcf_chain_held_by_acts_only(chain)) {
 				/* The chain exists only because there is
-				 * some action referencing it, meaning it
-				 * is a zombie.
+				 * some action referencing it.
 				 */
 				tcf_chain_hold(chain);
 			} else {
@@ -1860,7 +1858,7 @@ static int tc_ctl_chain(struct sk_buff *skb, struct nlmsghdr *n,
 			}
 		}
 	} else {
-		if (!chain || tcf_chain_is_zombie(chain)) {
+		if (!chain || tcf_chain_held_by_acts_only(chain)) {
 			NL_SET_ERR_MSG(extack, "Cannot find specified filter chain");
 			return -EINVAL;
 		}
@@ -1988,7 +1986,7 @@ static int tc_dump_chain(struct sk_buff *skb, struct netlink_callback *cb)
 			index++;
 			continue;
 		}
-		if (tcf_chain_is_zombie(chain))
+		if (tcf_chain_held_by_acts_only(chain))
 			continue;
 		err = tc_chain_fill_node(chain, net, skb, block,
 					 NETLINK_CB(cb->skb).portid,
-- 
2.14.4

^ permalink raw reply related

* [patch net-next v2 3/3] net: sched: make tcf_chain_{get,put}() static
From: Jiri Pirko @ 2018-08-01 10:36 UTC (permalink / raw)
  To: netdev; +Cc: davem, jhs, xiyou.wangcong, jakub.kicinski, mlxsw
In-Reply-To: <20180801103657.10532-1-jiri@resnulli.us>

From: Jiri Pirko <jiri@mellanox.com>

These are no longer used outside of cls_api.c so make them static.
Move tcf_chain_flush() to avoid fwd declaration of tcf_chain_put().

Signed-off-by: Jiri Pirko <jiri@mellanox.com>

v1->v2:
- new patch
---
 include/net/pkt_cls.h |  3 ---
 net/sched/cls_api.c   | 34 ++++++++++++++++------------------
 2 files changed, 16 insertions(+), 21 deletions(-)

diff --git a/include/net/pkt_cls.h b/include/net/pkt_cls.h
index 22bfc3a13c25..ef727f71336e 100644
--- a/include/net/pkt_cls.h
+++ b/include/net/pkt_cls.h
@@ -40,11 +40,8 @@ struct tcf_block_cb;
 bool tcf_queue_work(struct rcu_work *rwork, work_func_t func);
 
 #ifdef CONFIG_NET_CLS
-struct tcf_chain *tcf_chain_get(struct tcf_block *block, u32 chain_index,
-				bool create);
 struct tcf_chain *tcf_chain_get_by_act(struct tcf_block *block,
 				       u32 chain_index);
-void tcf_chain_put(struct tcf_chain *chain);
 void tcf_chain_put_by_act(struct tcf_chain *chain);
 void tcf_block_netif_keep_dst(struct tcf_block *block);
 int tcf_block_get(struct tcf_block **p_block,
diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c
index b194a5abfc6a..e8b0bbd0883f 100644
--- a/net/sched/cls_api.c
+++ b/net/sched/cls_api.c
@@ -232,19 +232,6 @@ static void tcf_chain0_head_change(struct tcf_chain *chain,
 		tcf_chain_head_change_item(item, tp_head);
 }
 
-static void tcf_chain_flush(struct tcf_chain *chain)
-{
-	struct tcf_proto *tp = rtnl_dereference(chain->filter_chain);
-
-	tcf_chain0_head_change(chain, NULL);
-	while (tp) {
-		RCU_INIT_POINTER(chain->filter_chain, tp->next);
-		tcf_proto_destroy(tp, NULL);
-		tp = rtnl_dereference(chain->filter_chain);
-		tcf_chain_put(chain);
-	}
-}
-
 static void tcf_chain_destroy(struct tcf_chain *chain)
 {
 	struct tcf_block *block = chain->block;
@@ -316,12 +303,11 @@ static struct tcf_chain *__tcf_chain_get(struct tcf_block *block,
 	return chain;
 }
 
-struct tcf_chain *tcf_chain_get(struct tcf_block *block, u32 chain_index,
-				bool create)
+static struct tcf_chain *tcf_chain_get(struct tcf_block *block, u32 chain_index,
+				       bool create)
 {
 	return __tcf_chain_get(block, chain_index, create, false);
 }
-EXPORT_SYMBOL(tcf_chain_get);
 
 struct tcf_chain *tcf_chain_get_by_act(struct tcf_block *block, u32 chain_index)
 {
@@ -347,11 +333,10 @@ static void __tcf_chain_put(struct tcf_chain *chain, bool by_act)
 	}
 }
 
-void tcf_chain_put(struct tcf_chain *chain)
+static void tcf_chain_put(struct tcf_chain *chain)
 {
 	__tcf_chain_put(chain, false);
 }
-EXPORT_SYMBOL(tcf_chain_put);
 
 void tcf_chain_put_by_act(struct tcf_chain *chain)
 {
@@ -365,6 +350,19 @@ static void tcf_chain_put_explicitly_created(struct tcf_chain *chain)
 		tcf_chain_put(chain);
 }
 
+static void tcf_chain_flush(struct tcf_chain *chain)
+{
+	struct tcf_proto *tp = rtnl_dereference(chain->filter_chain);
+
+	tcf_chain0_head_change(chain, NULL);
+	while (tp) {
+		RCU_INIT_POINTER(chain->filter_chain, tp->next);
+		tcf_proto_destroy(tp, NULL);
+		tp = rtnl_dereference(chain->filter_chain);
+		tcf_chain_put(chain);
+	}
+}
+
 static bool tcf_block_offload_in_use(struct tcf_block *block)
 {
 	return block->offloadcnt;
-- 
2.14.4

^ permalink raw reply related

* [patch net-next v2 2/3] net: sched: fix notifications for action-held chains
From: Jiri Pirko @ 2018-08-01 10:36 UTC (permalink / raw)
  To: netdev; +Cc: davem, jhs, xiyou.wangcong, jakub.kicinski, mlxsw
In-Reply-To: <20180801103657.10532-1-jiri@resnulli.us>

From: Jiri Pirko <jiri@mellanox.com>

Chains that only have action references serve as placeholders.
Until a non-action reference is created, user should not be aware
of the chain. Also he should not receive any notifications about it.
So send notifications for the new chain only in case the chain gets
the first non-action reference. Symmetrically to that, when
the last non-action reference is dropped, send the notification about
deleted chain.

Reported-by: Cong Wang <xiyou.wangcong@gmail.com>
Signed-off-by: Jiri Pirko <jiri@mellanox.com>
Acked-by: Cong Wang <xiyou.wangcong@gmail.com>

v1->v2:
- made __tcf_chain_{get,put}() static as suggested by Cong
---
 net/sched/cls_api.c | 71 ++++++++++++++++++++++++++++++++---------------------
 1 file changed, 43 insertions(+), 28 deletions(-)

diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c
index 2f78341f2888..b194a5abfc6a 100644
--- a/net/sched/cls_api.c
+++ b/net/sched/cls_api.c
@@ -262,16 +262,6 @@ static void tcf_chain_hold(struct tcf_chain *chain)
 	++chain->refcnt;
 }
 
-static void tcf_chain_hold_by_act(struct tcf_chain *chain)
-{
-	++chain->action_refcnt;
-}
-
-static void tcf_chain_release_by_act(struct tcf_chain *chain)
-{
-	--chain->action_refcnt;
-}
-
 static bool tcf_chain_held_by_acts_only(struct tcf_chain *chain)
 {
 	/* In case all the references are action references, this
@@ -295,52 +285,77 @@ static struct tcf_chain *tcf_chain_lookup(struct tcf_block *block,
 static int tc_chain_notify(struct tcf_chain *chain, struct sk_buff *oskb,
 			   u32 seq, u16 flags, int event, bool unicast);
 
-struct tcf_chain *tcf_chain_get(struct tcf_block *block, u32 chain_index,
-				bool create)
+static struct tcf_chain *__tcf_chain_get(struct tcf_block *block,
+					 u32 chain_index, bool create,
+					 bool by_act)
 {
 	struct tcf_chain *chain = tcf_chain_lookup(block, chain_index);
 
 	if (chain) {
 		tcf_chain_hold(chain);
-		return chain;
+	} else {
+		if (!create)
+			return NULL;
+		chain = tcf_chain_create(block, chain_index);
+		if (!chain)
+			return NULL;
 	}
 
-	if (!create)
-		return NULL;
-	chain = tcf_chain_create(block, chain_index);
-	if (!chain)
-		return NULL;
-	tc_chain_notify(chain, NULL, 0, NLM_F_CREATE | NLM_F_EXCL,
-			RTM_NEWCHAIN, false);
+	if (by_act)
+		++chain->action_refcnt;
+
+	/* Send notification only in case we got the first
+	 * non-action reference. Until then, the chain acts only as
+	 * a placeholder for actions pointing to it and user ought
+	 * not know about them.
+	 */
+	if (chain->refcnt - chain->action_refcnt == 1 && !by_act)
+		tc_chain_notify(chain, NULL, 0, NLM_F_CREATE | NLM_F_EXCL,
+				RTM_NEWCHAIN, false);
+
 	return chain;
 }
+
+struct tcf_chain *tcf_chain_get(struct tcf_block *block, u32 chain_index,
+				bool create)
+{
+	return __tcf_chain_get(block, chain_index, create, false);
+}
 EXPORT_SYMBOL(tcf_chain_get);
 
 struct tcf_chain *tcf_chain_get_by_act(struct tcf_block *block, u32 chain_index)
 {
-	struct tcf_chain *chain = tcf_chain_get(block, chain_index, true);
-
-	tcf_chain_hold_by_act(chain);
-	return chain;
+	return __tcf_chain_get(block, chain_index, true, true);
 }
 EXPORT_SYMBOL(tcf_chain_get_by_act);
 
 static void tc_chain_tmplt_del(struct tcf_chain *chain);
 
-void tcf_chain_put(struct tcf_chain *chain)
+static void __tcf_chain_put(struct tcf_chain *chain, bool by_act)
 {
-	if (--chain->refcnt == 0) {
+	if (by_act)
+		chain->action_refcnt--;
+	chain->refcnt--;
+
+	/* The last dropped non-action reference will trigger notification. */
+	if (chain->refcnt - chain->action_refcnt == 0 && !by_act)
 		tc_chain_notify(chain, NULL, 0, 0, RTM_DELCHAIN, false);
+
+	if (chain->refcnt == 0) {
 		tc_chain_tmplt_del(chain);
 		tcf_chain_destroy(chain);
 	}
 }
+
+void tcf_chain_put(struct tcf_chain *chain)
+{
+	__tcf_chain_put(chain, false);
+}
 EXPORT_SYMBOL(tcf_chain_put);
 
 void tcf_chain_put_by_act(struct tcf_chain *chain)
 {
-	tcf_chain_release_by_act(chain);
-	tcf_chain_put(chain);
+	__tcf_chain_put(chain, true);
 }
 EXPORT_SYMBOL(tcf_chain_put_by_act);
 
-- 
2.14.4

^ permalink raw reply related

* Re: SLAB_TYPESAFE_BY_RCU without constructors (was Re: [PATCH v4 13/17] khwasan: add hooks implementation)
From: Dmitry Vyukov @ 2018-08-01 10:41 UTC (permalink / raw)
  To: Florian Westphal
  Cc: Linus Torvalds, Christoph Lameter, Andrey Ryabinin,
	Theodore Ts'o, Jan Kara, linux-ext4, Greg Kroah-Hartman,
	Pablo Neira Ayuso, Jozsef Kadlecsik, David Miller, NetFilter,
	coreteam, Network Development, Gerrit Renker, dccp, Jani Nikula,
	Joonas Lahtinen, Rodrigo Vivi, Dave Airlie, intel-gfx
In-Reply-To: <20180801103537.d36t3snzulyuge7g@breakpoint.cc>

On Wed, Aug 1, 2018 at 12:35 PM, Florian Westphal <fw@strlen.de> wrote:
> Dmitry Vyukov <dvyukov@google.com> wrote:
>> Still can't grasp all details.
>> There is state that we read without taking ct->ct_general.use ref
>> first, namely ct->state and what's used by nf_ct_key_equal.
>> So let's say the entry we want to find is in the list, but
>> ____nf_conntrack_find finds a wrong entry earlier because all state it
>> looks at is random garbage, so it returns the wrong entry to
>> __nf_conntrack_find_get.
>
> If an entry can be found, it can't be random garbage.
> We never link entries into global table until state has been set up.


But... we don't hold a reference to the entry. So say it's in the
table with valid state, now ____nf_conntrack_find discovers it, now
the entry is removed and reused a dozen of times will all associated
state reinitialization. And nf_ct_key_equal looks at it concurrently
and decides if it's the entry we are looking for or now. I think
unless we hold a ref to the entry, it's state needs to be considered
random garbage for correctness reasoning.


>> Now (nf_ct_is_dying(ct) || !atomic_inc_not_zero(&ct->ct_general.use))
>> check in __nf_conntrack_find_get passes, and it returns NULL to the
>> caller (which means entry is not present).
>
> So entry is going away or marked as dead which for us is same as
> 'not present', we need to allocate a new entry.
>
>> While in reality the entry
>> is present, but we were just looking at the wrong one.
>
> We never add tuples that are identical to the global table.
>
> If N cores receive identical packets at same time with no prior state, all
> will allocate a new conntrack, but we notice this when we try to insert the
> nf_conn entries into the table.
>
> Only one will succeed, other cpus have to cope with this.
> (worst case: all raced packets are dropped along with their conntrack
>  object).
>
> For lookup, we have following scenarios:
>
> 1. It doesn't exist -> new allocation needed
> 2. It exists, not dead, has nonzero refount -> use it
> 3. It exists, but marked as dying -> new allocation needed
> 4. It exists but has 0 reference count -> new allocation needed
> 5. It exists, we get reference, but 2nd nf_ct_key_equal check
>    fails.  We saw a matching 'old incarnation' that just got
>    re-used on other core.  -> retry lookup
>
>> Also I am not sure about order of checks in (nf_ct_is_dying(ct) ||
>> !atomic_inc_not_zero(&ct->ct_general.use)), because checking state
>> before taking the ref is only a best-effort hint, so it can actually
>> be a dying entry when we take a ref.
>
> Yes, it can also become a dying entry after we took the reference.
>
>> So shouldn't it read something like the following?
>>
>>         rcu_read_lock();
>> begin:
>>         h = ____nf_conntrack_find(net, zone, tuple, hash);
>>         if (h) {
>>                 ct = nf_ct_tuplehash_to_ctrack(h);
>>                 if (!atomic_inc_not_zero(&ct->ct_general.use))
>>                         goto begin;
>>                 if (unlikely(nf_ct_is_dying(ct)) ||
>>                     unlikely(!nf_ct_key_equal(h, tuple, zone, net))) {
>>                         nf_ct_put(ct);
>
> It would be ok to make this change, but dying bit can be set
> at any time e.g. because userspace tells kernel to flush the conntrack table.
> So refcount is always > 0 when the DYING bit is set.
>
> I don't see why it would be a problem.
>
> nf_conn struct will stay valid until all cpus have dropped references.
> The check in lookup function only serves to hide the known-to-go-away entry.

^ permalink raw reply

* [PATCH net] rxrpc: Fix user call ID check in rxrpc_service_prealloc_one
From: David Howells @ 2018-08-01 12:27 UTC (permalink / raw)
  To: netdev; +Cc: dhowells, linux-afs, linux-kernel

From: YueHaibing <yuehaibing@huawei.com>

There just check the user call ID isn't already in use, hence should
compare user_call_ID with xcall->user_call_ID, which is current
node's user_call_ID.

Fixes: 540b1c48c37a ("rxrpc: Fix deadlock between call creation and sendmsg/recvmsg")
Suggested-by: David Howells <dhowells@redhat.com>
Signed-off-by: YueHaibing <yuehaibing@huawei.com>
Signed-off-by: David Howells <dhowells@redhat.com>
---

 net/rxrpc/call_accept.c |    4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/net/rxrpc/call_accept.c b/net/rxrpc/call_accept.c
index a9a9be5519b9..9d1e298b784c 100644
--- a/net/rxrpc/call_accept.c
+++ b/net/rxrpc/call_accept.c
@@ -116,9 +116,9 @@ static int rxrpc_service_prealloc_one(struct rxrpc_sock *rx,
 		while (*pp) {
 			parent = *pp;
 			xcall = rb_entry(parent, struct rxrpc_call, sock_node);
-			if (user_call_ID < call->user_call_ID)
+			if (user_call_ID < xcall->user_call_ID)
 				pp = &(*pp)->rb_left;
-			else if (user_call_ID > call->user_call_ID)
+			else if (user_call_ID > xcall->user_call_ID)
 				pp = &(*pp)->rb_right;
 			else
 				goto id_in_use;

^ permalink raw reply related

* [PATCH net-next 01/10] rxrpc: remove redundant variables 'sp' and 'did_discard'
From: David Howells @ 2018-08-01 12:58 UTC (permalink / raw)
  To: netdev; +Cc: dhowells, linux-afs, linux-kernel
In-Reply-To: <153312832565.27702.15302541876382957550.stgit@warthog.procyon.org.uk>

From: YueHaibing <yuehaibing@huawei.com>

Variables 'sp' and 'did_discard' are being assigned,
but are never used, hence they are redundant and can be removed.

fix following warning:

net/rxrpc/call_event.c:165:25: warning: variable 'sp' set but not used [-Wunused-but-set-variable]
net/rxrpc/conn_client.c:1054:7: warning: variable 'did_discard' set but not used [-Wunused-but-set-variable]

Signed-off-by: YueHaibing <yuehaibing@huawei.com>
Signed-off-by: David Howells <dhowells@redhat.com>
---

 net/rxrpc/call_event.c  |    2 --
 net/rxrpc/conn_client.c |    2 --
 2 files changed, 4 deletions(-)

diff --git a/net/rxrpc/call_event.c b/net/rxrpc/call_event.c
index 20210418904b..8e7434e92097 100644
--- a/net/rxrpc/call_event.c
+++ b/net/rxrpc/call_event.c
@@ -162,7 +162,6 @@ static void rxrpc_congestion_timeout(struct rxrpc_call *call)
  */
 static void rxrpc_resend(struct rxrpc_call *call, unsigned long now_j)
 {
-	struct rxrpc_skb_priv *sp;
 	struct sk_buff *skb;
 	unsigned long resend_at;
 	rxrpc_seq_t cursor, seq, top;
@@ -207,7 +206,6 @@ static void rxrpc_resend(struct rxrpc_call *call, unsigned long now_j)
 
 		skb = call->rxtx_buffer[ix];
 		rxrpc_see_skb(skb, rxrpc_skb_tx_seen);
-		sp = rxrpc_skb(skb);
 
 		if (anno_type == RXRPC_TX_ANNO_UNACK) {
 			if (ktime_after(skb->tstamp, max_age)) {
diff --git a/net/rxrpc/conn_client.c b/net/rxrpc/conn_client.c
index 5736f643c516..e4bfbd7e48a8 100644
--- a/net/rxrpc/conn_client.c
+++ b/net/rxrpc/conn_client.c
@@ -1051,7 +1051,6 @@ void rxrpc_discard_expired_client_conns(struct work_struct *work)
 		container_of(work, struct rxrpc_net, client_conn_reaper);
 	unsigned long expiry, conn_expires_at, now;
 	unsigned int nr_conns;
-	bool did_discard = false;
 
 	_enter("");
 
@@ -1113,7 +1112,6 @@ void rxrpc_discard_expired_client_conns(struct work_struct *work)
 	 * If someone re-sets the flag and re-gets the ref, that's fine.
 	 */
 	rxrpc_put_connection(conn);
-	did_discard = true;
 	nr_conns--;
 	goto next;
 

^ permalink raw reply related

* [PATCH net-next 02/10] rxrpc: Display call expect-receive-by timeout in proc
From: David Howells @ 2018-08-01 12:58 UTC (permalink / raw)
  To: netdev; +Cc: dhowells, linux-afs, linux-kernel
In-Reply-To: <153312832565.27702.15302541876382957550.stgit@warthog.procyon.org.uk>

Display in /proc/net/rxrpc/calls the timeout by which a call next expects
to receive a packet.

This makes it easier to debug timeout issues.

Signed-off-by: David Howells <dhowells@redhat.com>
---

 net/rxrpc/proc.c |   14 +++++++++++---
 1 file changed, 11 insertions(+), 3 deletions(-)

diff --git a/net/rxrpc/proc.c b/net/rxrpc/proc.c
index d9fca8c4bcdc..bc6f27c8869d 100644
--- a/net/rxrpc/proc.c
+++ b/net/rxrpc/proc.c
@@ -63,6 +63,7 @@ static int rxrpc_call_seq_show(struct seq_file *seq, void *v)
 	struct rxrpc_peer *peer;
 	struct rxrpc_call *call;
 	struct rxrpc_net *rxnet = rxrpc_net(seq_file_net(seq));
+	unsigned long timeout = 0, nowj;
 	rxrpc_seq_t tx_hard_ack, rx_hard_ack;
 	char lbuff[50], rbuff[50];
 
@@ -71,7 +72,7 @@ static int rxrpc_call_seq_show(struct seq_file *seq, void *v)
 			 "Proto Local                                          "
 			 " Remote                                         "
 			 " SvID ConnID   CallID   End Use State    Abort   "
-			 " UserID\n");
+			 " UserID           TxSeq    TW RxSeq    RW RxTimo\n");
 		return 0;
 	}
 
@@ -94,11 +95,17 @@ static int rxrpc_call_seq_show(struct seq_file *seq, void *v)
 	else
 		strcpy(rbuff, "no_connection");
 
+	if (call->state != RXRPC_CALL_SERVER_PREALLOC) {
+		timeout = READ_ONCE(call->expect_rx_by);
+		nowj = jiffies;
+		timeout -= jiffies;
+	}
+
 	tx_hard_ack = READ_ONCE(call->tx_hard_ack);
 	rx_hard_ack = READ_ONCE(call->rx_hard_ack);
 	seq_printf(seq,
 		   "UDP   %-47.47s %-47.47s %4x %08x %08x %s %3u"
-		   " %-8.8s %08x %lx %08x %02x %08x %02x\n",
+		   " %-8.8s %08x %lx %08x %02x %08x %02x %06lx\n",
 		   lbuff,
 		   rbuff,
 		   call->service_id,
@@ -110,7 +117,8 @@ static int rxrpc_call_seq_show(struct seq_file *seq, void *v)
 		   call->abort_code,
 		   call->user_call_ID,
 		   tx_hard_ack, READ_ONCE(call->tx_top) - tx_hard_ack,
-		   rx_hard_ack, READ_ONCE(call->rx_top) - rx_hard_ack);
+		   rx_hard_ack, READ_ONCE(call->rx_top) - rx_hard_ack,
+		   timeout);
 
 	return 0;
 }

^ permalink raw reply related

* [PATCH net-next 03/10] rxrpc: Show some more information through /proc files
From: David Howells @ 2018-08-01 12:59 UTC (permalink / raw)
  To: netdev; +Cc: dhowells, linux-afs, linux-kernel
In-Reply-To: <153312832565.27702.15302541876382957550.stgit@warthog.procyon.org.uk>

Show the four current call IDs in /proc/net/rxrpc/conns.

Show the current packet Rx serial number in /proc/net/rxrpc/calls.

Signed-off-by: David Howells <dhowells@redhat.com>
---

 net/rxrpc/proc.c |   13 +++++++++----
 1 file changed, 9 insertions(+), 4 deletions(-)

diff --git a/net/rxrpc/proc.c b/net/rxrpc/proc.c
index bc6f27c8869d..163d05df339d 100644
--- a/net/rxrpc/proc.c
+++ b/net/rxrpc/proc.c
@@ -72,7 +72,7 @@ static int rxrpc_call_seq_show(struct seq_file *seq, void *v)
 			 "Proto Local                                          "
 			 " Remote                                         "
 			 " SvID ConnID   CallID   End Use State    Abort   "
-			 " UserID           TxSeq    TW RxSeq    RW RxTimo\n");
+			 " UserID           TxSeq    TW RxSeq    RW RxSerial RxTimo\n");
 		return 0;
 	}
 
@@ -105,7 +105,7 @@ static int rxrpc_call_seq_show(struct seq_file *seq, void *v)
 	rx_hard_ack = READ_ONCE(call->rx_hard_ack);
 	seq_printf(seq,
 		   "UDP   %-47.47s %-47.47s %4x %08x %08x %s %3u"
-		   " %-8.8s %08x %lx %08x %02x %08x %02x %06lx\n",
+		   " %-8.8s %08x %lx %08x %02x %08x %02x %08x %06lx\n",
 		   lbuff,
 		   rbuff,
 		   call->service_id,
@@ -118,6 +118,7 @@ static int rxrpc_call_seq_show(struct seq_file *seq, void *v)
 		   call->user_call_ID,
 		   tx_hard_ack, READ_ONCE(call->tx_top) - tx_hard_ack,
 		   rx_hard_ack, READ_ONCE(call->rx_top) - rx_hard_ack,
+		   call->rx_serial,
 		   timeout);
 
 	return 0;
@@ -187,7 +188,7 @@ static int rxrpc_connection_seq_show(struct seq_file *seq, void *v)
 print:
 	seq_printf(seq,
 		   "UDP   %-47.47s %-47.47s %4x %08x %s %3u"
-		   " %s %08x %08x %08x\n",
+		   " %s %08x %08x %08x %08x %08x %08x %08x\n",
 		   lbuff,
 		   rbuff,
 		   conn->service_id,
@@ -197,7 +198,11 @@ static int rxrpc_connection_seq_show(struct seq_file *seq, void *v)
 		   rxrpc_conn_states[conn->state],
 		   key_serial(conn->params.key),
 		   atomic_read(&conn->serial),
-		   conn->hi_serial);
+		   conn->hi_serial,
+		   conn->channels[0].call_id,
+		   conn->channels[1].call_id,
+		   conn->channels[2].call_id,
+		   conn->channels[3].call_id);
 
 	return 0;
 }

^ permalink raw reply related

* [PATCH net-next 04/10] rxrpc: Fix the trace for terminal ACK (re)transmission
From: David Howells @ 2018-08-01 12:59 UTC (permalink / raw)
  To: netdev; +Cc: dhowells, linux-afs, linux-kernel
In-Reply-To: <153312832565.27702.15302541876382957550.stgit@warthog.procyon.org.uk>

Fix the trace for terminal ACK (re)transmission to put in the right
parameters.

Signed-off-by: David Howells <dhowells@redhat.com>
---

 net/rxrpc/conn_event.c |    6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/net/rxrpc/conn_event.c b/net/rxrpc/conn_event.c
index 8229a52c2acd..d46a68807f08 100644
--- a/net/rxrpc/conn_event.c
+++ b/net/rxrpc/conn_event.c
@@ -129,8 +129,10 @@ static void rxrpc_conn_retransmit_call(struct rxrpc_connection *conn,
 		_proto("Tx ABORT %%%u { %d } [re]", serial, conn->local_abort);
 		break;
 	case RXRPC_PACKET_TYPE_ACK:
-		trace_rxrpc_tx_ack(NULL, serial, chan->last_seq, 0,
-				   RXRPC_ACK_DUPLICATE, 0);
+		trace_rxrpc_tx_ack(NULL, serial,
+				   ntohl(pkt.ack.firstPacket),
+				   ntohl(pkt.ack.serial),
+				   pkt.ack.reason, 0);
 		_proto("Tx ACK %%%u [re]", serial);
 		break;
 	}

^ permalink raw reply related

* [PATCH net-next 05/10] rxrpc: Trace packet transmission
From: David Howells @ 2018-08-01 12:59 UTC (permalink / raw)
  To: netdev; +Cc: dhowells, linux-afs, linux-kernel
In-Reply-To: <153312832565.27702.15302541876382957550.stgit@warthog.procyon.org.uk>

Trace successful packet transmission (kernel_sendmsg() succeeded, that is)
in AF_RXRPC.  We can share the enum that defines the transmission points
with the trace_rxrpc_tx_fail() tracepoint, so rename its constants to be
applicable to both.

Also, save the internal call->debug_id in the rxrpc_channel struct so that
it can be used in retransmission trace lines.

Signed-off-by: David Howells <dhowells@redhat.com>
---

 include/trace/events/rxrpc.h |  107 ++++++++++++++++++++++++++++--------------
 net/rxrpc/ar-internal.h      |    1 
 net/rxrpc/conn_client.c      |    1 
 net/rxrpc/conn_event.c       |   13 ++++-
 net/rxrpc/input.c            |   11 ++++
 net/rxrpc/local_event.c      |    5 ++
 net/rxrpc/output.c           |   32 ++++++++++---
 net/rxrpc/rxkad.c            |    7 ++-
 8 files changed, 127 insertions(+), 50 deletions(-)

diff --git a/include/trace/events/rxrpc.h b/include/trace/events/rxrpc.h
index 4fff00e9da8a..2aa6f615b60d 100644
--- a/include/trace/events/rxrpc.h
+++ b/include/trace/events/rxrpc.h
@@ -211,18 +211,18 @@ enum rxrpc_congest_change {
 	rxrpc_cong_saw_nack,
 };
 
-enum rxrpc_tx_fail_trace {
-	rxrpc_tx_fail_call_abort,
-	rxrpc_tx_fail_call_ack,
-	rxrpc_tx_fail_call_data_frag,
-	rxrpc_tx_fail_call_data_nofrag,
-	rxrpc_tx_fail_call_final_resend,
-	rxrpc_tx_fail_conn_abort,
-	rxrpc_tx_fail_conn_challenge,
-	rxrpc_tx_fail_conn_response,
-	rxrpc_tx_fail_reject,
-	rxrpc_tx_fail_version_keepalive,
-	rxrpc_tx_fail_version_reply,
+enum rxrpc_tx_point {
+	rxrpc_tx_point_call_abort,
+	rxrpc_tx_point_call_ack,
+	rxrpc_tx_point_call_data_frag,
+	rxrpc_tx_point_call_data_nofrag,
+	rxrpc_tx_point_call_final_resend,
+	rxrpc_tx_point_conn_abort,
+	rxrpc_tx_point_rxkad_challenge,
+	rxrpc_tx_point_rxkad_response,
+	rxrpc_tx_point_reject,
+	rxrpc_tx_point_version_keepalive,
+	rxrpc_tx_point_version_reply,
 };
 
 #endif /* end __RXRPC_DECLARE_TRACE_ENUMS_ONCE_ONLY */
@@ -452,18 +452,18 @@ enum rxrpc_tx_fail_trace {
 	EM(RXRPC_CALL_LOCAL_ERROR,		"LocalError") \
 	E_(RXRPC_CALL_NETWORK_ERROR,		"NetError")
 
-#define rxrpc_tx_fail_traces \
-	EM(rxrpc_tx_fail_call_abort,		"CallAbort") \
-	EM(rxrpc_tx_fail_call_ack,		"CallAck") \
-	EM(rxrpc_tx_fail_call_data_frag,	"CallDataFrag") \
-	EM(rxrpc_tx_fail_call_data_nofrag,	"CallDataNofrag") \
-	EM(rxrpc_tx_fail_call_final_resend,	"CallFinalResend") \
-	EM(rxrpc_tx_fail_conn_abort,		"ConnAbort") \
-	EM(rxrpc_tx_fail_conn_challenge,	"ConnChall") \
-	EM(rxrpc_tx_fail_conn_response,		"ConnResp") \
-	EM(rxrpc_tx_fail_reject,		"Reject") \
-	EM(rxrpc_tx_fail_version_keepalive,	"VerKeepalive") \
-	E_(rxrpc_tx_fail_version_reply,		"VerReply")
+#define rxrpc_tx_points \
+	EM(rxrpc_tx_point_call_abort,		"CallAbort") \
+	EM(rxrpc_tx_point_call_ack,		"CallAck") \
+	EM(rxrpc_tx_point_call_data_frag,	"CallDataFrag") \
+	EM(rxrpc_tx_point_call_data_nofrag,	"CallDataNofrag") \
+	EM(rxrpc_tx_point_call_final_resend,	"CallFinalResend") \
+	EM(rxrpc_tx_point_conn_abort,		"ConnAbort") \
+	EM(rxrpc_tx_point_reject,		"Reject") \
+	EM(rxrpc_tx_point_rxkad_challenge,	"RxkadChall") \
+	EM(rxrpc_tx_point_rxkad_response,	"RxkadResp") \
+	EM(rxrpc_tx_point_version_keepalive,	"VerKeepalive") \
+	E_(rxrpc_tx_point_version_reply,	"VerReply")
 
 /*
  * Export enum symbols via userspace.
@@ -488,7 +488,7 @@ rxrpc_propose_ack_traces;
 rxrpc_propose_ack_outcomes;
 rxrpc_congest_modes;
 rxrpc_congest_changes;
-rxrpc_tx_fail_traces;
+rxrpc_tx_points;
 
 /*
  * Now redefine the EM() and E_() macros to map the enums to the strings that
@@ -801,7 +801,7 @@ TRACE_EVENT(rxrpc_transmit,
 	    );
 
 TRACE_EVENT(rxrpc_rx_data,
-	    TP_PROTO(struct rxrpc_call *call, rxrpc_seq_t seq,
+	    TP_PROTO(unsigned int call, rxrpc_seq_t seq,
 		     rxrpc_serial_t serial, u8 flags, u8 anno),
 
 	    TP_ARGS(call, seq, serial, flags, anno),
@@ -815,7 +815,7 @@ TRACE_EVENT(rxrpc_rx_data,
 			     ),
 
 	    TP_fast_assign(
-		    __entry->call = call->debug_id;
+		    __entry->call = call;
 		    __entry->seq = seq;
 		    __entry->serial = serial;
 		    __entry->flags = flags;
@@ -918,6 +918,37 @@ TRACE_EVENT(rxrpc_rx_rwind_change,
 		      __entry->wake ? " wake" : "")
 	    );
 
+TRACE_EVENT(rxrpc_tx_packet,
+	    TP_PROTO(unsigned int call_id, struct rxrpc_wire_header *whdr,
+		     enum rxrpc_tx_point where),
+
+	    TP_ARGS(call_id, whdr, where),
+
+	    TP_STRUCT__entry(
+		    __field(unsigned int,			call	)
+		    __field(enum rxrpc_tx_point,		where	)
+		    __field_struct(struct rxrpc_wire_header,	whdr	)
+			     ),
+
+	    TP_fast_assign(
+		    __entry->call = call_id;
+		    memcpy(&__entry->whdr, whdr, sizeof(__entry->whdr));
+			   ),
+
+	    TP_printk("c=%08x %08x:%08x:%08x:%04x %08x %08x %02x %02x %s %s",
+		      __entry->call,
+		      ntohl(__entry->whdr.epoch),
+		      ntohl(__entry->whdr.cid),
+		      ntohl(__entry->whdr.callNumber),
+		      ntohs(__entry->whdr.serviceId),
+		      ntohl(__entry->whdr.serial),
+		      ntohl(__entry->whdr.seq),
+		      __entry->whdr.type, __entry->whdr.flags,
+		      __entry->whdr.type <= 15 ?
+		      __print_symbolic(__entry->whdr.type, rxrpc_pkts) : "?UNK",
+		      __print_symbolic(__entry->where, rxrpc_tx_points))
+	    );
+
 TRACE_EVENT(rxrpc_tx_data,
 	    TP_PROTO(struct rxrpc_call *call, rxrpc_seq_t seq,
 		     rxrpc_serial_t serial, u8 flags, bool retrans, bool lose),
@@ -928,6 +959,8 @@ TRACE_EVENT(rxrpc_tx_data,
 		    __field(unsigned int,		call		)
 		    __field(rxrpc_seq_t,		seq		)
 		    __field(rxrpc_serial_t,		serial		)
+		    __field(u32,			cid		)
+		    __field(u32,			call_id		)
 		    __field(u8,				flags		)
 		    __field(bool,			retrans		)
 		    __field(bool,			lose		)
@@ -935,6 +968,8 @@ TRACE_EVENT(rxrpc_tx_data,
 
 	    TP_fast_assign(
 		    __entry->call = call->debug_id;
+		    __entry->cid = call->cid;
+		    __entry->call_id = call->call_id;
 		    __entry->seq = seq;
 		    __entry->serial = serial;
 		    __entry->flags = flags;
@@ -942,8 +977,10 @@ TRACE_EVENT(rxrpc_tx_data,
 		    __entry->lose = lose;
 			   ),
 
-	    TP_printk("c=%08x DATA %08x q=%08x fl=%02x%s%s",
+	    TP_printk("c=%08x DATA %08x:%08x %08x q=%08x fl=%02x%s%s",
 		      __entry->call,
+		      __entry->cid,
+		      __entry->call_id,
 		      __entry->serial,
 		      __entry->seq,
 		      __entry->flags,
@@ -952,7 +989,7 @@ TRACE_EVENT(rxrpc_tx_data,
 	    );
 
 TRACE_EVENT(rxrpc_tx_ack,
-	    TP_PROTO(struct rxrpc_call *call, rxrpc_serial_t serial,
+	    TP_PROTO(unsigned int call, rxrpc_serial_t serial,
 		     rxrpc_seq_t ack_first, rxrpc_serial_t ack_serial,
 		     u8 reason, u8 n_acks),
 
@@ -968,7 +1005,7 @@ TRACE_EVENT(rxrpc_tx_ack,
 			     ),
 
 	    TP_fast_assign(
-		    __entry->call = call ? call->debug_id : 0;
+		    __entry->call = call;
 		    __entry->serial = serial;
 		    __entry->ack_first = ack_first;
 		    __entry->ack_serial = ack_serial;
@@ -1434,29 +1471,29 @@ TRACE_EVENT(rxrpc_rx_icmp,
 
 TRACE_EVENT(rxrpc_tx_fail,
 	    TP_PROTO(unsigned int debug_id, rxrpc_serial_t serial, int ret,
-		     enum rxrpc_tx_fail_trace what),
+		     enum rxrpc_tx_point where),
 
-	    TP_ARGS(debug_id, serial, ret, what),
+	    TP_ARGS(debug_id, serial, ret, where),
 
 	    TP_STRUCT__entry(
 		    __field(unsigned int,		debug_id	)
 		    __field(rxrpc_serial_t,		serial		)
 		    __field(int,			ret		)
-		    __field(enum rxrpc_tx_fail_trace,   what		)
+		    __field(enum rxrpc_tx_point,	where		)
 			     ),
 
 	    TP_fast_assign(
 		    __entry->debug_id = debug_id;
 		    __entry->serial = serial;
 		    __entry->ret = ret;
-		    __entry->what = what;
+		    __entry->where = where;
 			   ),
 
 	    TP_printk("c=%08x r=%x ret=%d %s",
 		      __entry->debug_id,
 		      __entry->serial,
 		      __entry->ret,
-		      __print_symbolic(__entry->what, rxrpc_tx_fail_traces))
+		      __print_symbolic(__entry->where, rxrpc_tx_points))
 	    );
 
 TRACE_EVENT(rxrpc_call_reset,
diff --git a/net/rxrpc/ar-internal.h b/net/rxrpc/ar-internal.h
index 5fb7d3254d9e..7eee955a768a 100644
--- a/net/rxrpc/ar-internal.h
+++ b/net/rxrpc/ar-internal.h
@@ -420,6 +420,7 @@ struct rxrpc_connection {
 	struct rxrpc_channel {
 		unsigned long		final_ack_at;	/* Time at which to issue final ACK */
 		struct rxrpc_call __rcu	*call;		/* Active call */
+		unsigned int		call_debug_id;	/* call->debug_id */
 		u32			call_id;	/* ID of current call */
 		u32			call_counter;	/* Call ID counter */
 		u32			last_call;	/* ID of last call */
diff --git a/net/rxrpc/conn_client.c b/net/rxrpc/conn_client.c
index e4bfbd7e48a8..f8f37188a932 100644
--- a/net/rxrpc/conn_client.c
+++ b/net/rxrpc/conn_client.c
@@ -590,6 +590,7 @@ static void rxrpc_activate_one_channel(struct rxrpc_connection *conn,
 	 */
 	smp_wmb();
 	chan->call_id	= call_id;
+	chan->call_debug_id = call->debug_id;
 	rcu_assign_pointer(chan->call, call);
 	wake_up(&call->waitq);
 }
diff --git a/net/rxrpc/conn_event.c b/net/rxrpc/conn_event.c
index d46a68807f08..84d40ba9856f 100644
--- a/net/rxrpc/conn_event.c
+++ b/net/rxrpc/conn_event.c
@@ -129,7 +129,7 @@ static void rxrpc_conn_retransmit_call(struct rxrpc_connection *conn,
 		_proto("Tx ABORT %%%u { %d } [re]", serial, conn->local_abort);
 		break;
 	case RXRPC_PACKET_TYPE_ACK:
-		trace_rxrpc_tx_ack(NULL, serial,
+		trace_rxrpc_tx_ack(chan->call_debug_id, serial,
 				   ntohl(pkt.ack.firstPacket),
 				   ntohl(pkt.ack.serial),
 				   pkt.ack.reason, 0);
@@ -140,8 +140,11 @@ static void rxrpc_conn_retransmit_call(struct rxrpc_connection *conn,
 	ret = kernel_sendmsg(conn->params.local->socket, &msg, iov, ioc, len);
 	conn->params.peer->last_tx_at = ktime_get_real();
 	if (ret < 0)
-		trace_rxrpc_tx_fail(conn->debug_id, serial, ret,
-				    rxrpc_tx_fail_call_final_resend);
+		trace_rxrpc_tx_fail(chan->call_debug_id, serial, ret,
+				    rxrpc_tx_point_call_final_resend);
+	else
+		trace_rxrpc_tx_packet(chan->call_debug_id, &pkt.whdr,
+				      rxrpc_tx_point_call_final_resend);
 
 	_leave("");
 }
@@ -242,11 +245,13 @@ static int rxrpc_abort_connection(struct rxrpc_connection *conn,
 	ret = kernel_sendmsg(conn->params.local->socket, &msg, iov, 2, len);
 	if (ret < 0) {
 		trace_rxrpc_tx_fail(conn->debug_id, serial, ret,
-				    rxrpc_tx_fail_conn_abort);
+				    rxrpc_tx_point_conn_abort);
 		_debug("sendmsg failed: %d", ret);
 		return -EAGAIN;
 	}
 
+	trace_rxrpc_tx_packet(conn->debug_id, &whdr, rxrpc_tx_point_conn_abort);
+
 	conn->params.peer->last_tx_at = ktime_get_real();
 
 	_leave(" = 0");
diff --git a/net/rxrpc/input.c b/net/rxrpc/input.c
index 608d078a4981..8989d760b6b2 100644
--- a/net/rxrpc/input.c
+++ b/net/rxrpc/input.c
@@ -496,7 +496,7 @@ static void rxrpc_input_data(struct rxrpc_call *call, struct sk_buff *skb,
 			return rxrpc_proto_abort("LSA", call, seq);
 	}
 
-	trace_rxrpc_rx_data(call, seq, serial, flags, annotation);
+	trace_rxrpc_rx_data(call->debug_id, seq, serial, flags, annotation);
 	if (before_eq(seq, hard_ack)) {
 		ack = RXRPC_ACK_DUPLICATE;
 		ack_serial = serial;
@@ -592,6 +592,10 @@ static void rxrpc_input_data(struct rxrpc_call *call, struct sk_buff *skb,
 		rxrpc_propose_ACK(call, ack, skew, ack_serial,
 				  immediate_ack, true,
 				  rxrpc_propose_ack_input_data);
+	else
+		rxrpc_propose_ACK(call, RXRPC_ACK_DELAY, skew, serial,
+				  false, true,
+				  rxrpc_propose_ack_input_data);
 
 	if (sp->hdr.seq == READ_ONCE(call->rx_hard_ack) + 1)
 		rxrpc_notify_socket(call);
@@ -1262,6 +1266,11 @@ void rxrpc_data_ready(struct sock *udp_sk)
 			/* But otherwise we need to retransmit the final packet
 			 * from data cached in the connection record.
 			 */
+			if (sp->hdr.type == RXRPC_PACKET_TYPE_DATA)
+				trace_rxrpc_rx_data(chan->call_debug_id,
+						    sp->hdr.seq,
+						    sp->hdr.serial,
+						    sp->hdr.flags, 0);
 			rxrpc_post_packet_to_conn(conn, skb);
 			goto out_unlock;
 		}
diff --git a/net/rxrpc/local_event.c b/net/rxrpc/local_event.c
index 8325f1b86840..13bd8a4dfac7 100644
--- a/net/rxrpc/local_event.c
+++ b/net/rxrpc/local_event.c
@@ -72,7 +72,10 @@ static void rxrpc_send_version_request(struct rxrpc_local *local,
 	ret = kernel_sendmsg(local->socket, &msg, iov, 2, len);
 	if (ret < 0)
 		trace_rxrpc_tx_fail(local->debug_id, 0, ret,
-				    rxrpc_tx_fail_version_reply);
+				    rxrpc_tx_point_version_reply);
+	else
+		trace_rxrpc_tx_packet(local->debug_id, &whdr,
+				      rxrpc_tx_point_version_reply);
 
 	_leave("");
 }
diff --git a/net/rxrpc/output.c b/net/rxrpc/output.c
index f03de1c59ba3..801dbf3d3478 100644
--- a/net/rxrpc/output.c
+++ b/net/rxrpc/output.c
@@ -183,7 +183,7 @@ int rxrpc_send_ack_packet(struct rxrpc_call *call, bool ping,
 
 	serial = atomic_inc_return(&conn->serial);
 	pkt->whdr.serial = htonl(serial);
-	trace_rxrpc_tx_ack(call, serial,
+	trace_rxrpc_tx_ack(call->debug_id, serial,
 			   ntohl(pkt->ack.firstPacket),
 			   ntohl(pkt->ack.serial),
 			   pkt->ack.reason, pkt->ack.nAcks);
@@ -212,7 +212,10 @@ int rxrpc_send_ack_packet(struct rxrpc_call *call, bool ping,
 	conn->params.peer->last_tx_at = ktime_get_real();
 	if (ret < 0)
 		trace_rxrpc_tx_fail(call->debug_id, serial, ret,
-				    rxrpc_tx_fail_call_ack);
+				    rxrpc_tx_point_call_ack);
+	else
+		trace_rxrpc_tx_packet(call->debug_id, &pkt->whdr,
+				      rxrpc_tx_point_call_ack);
 
 	if (call->state < RXRPC_CALL_COMPLETE) {
 		if (ret < 0) {
@@ -299,7 +302,10 @@ int rxrpc_send_abort_packet(struct rxrpc_call *call)
 	conn->params.peer->last_tx_at = ktime_get_real();
 	if (ret < 0)
 		trace_rxrpc_tx_fail(call->debug_id, serial, ret,
-				    rxrpc_tx_fail_call_abort);
+				    rxrpc_tx_point_call_abort);
+	else
+		trace_rxrpc_tx_packet(call->debug_id, &pkt.whdr,
+				      rxrpc_tx_point_call_abort);
 
 
 	rxrpc_put_connection(conn);
@@ -396,7 +402,10 @@ int rxrpc_send_data_packet(struct rxrpc_call *call, struct sk_buff *skb,
 	up_read(&conn->params.local->defrag_sem);
 	if (ret < 0)
 		trace_rxrpc_tx_fail(call->debug_id, serial, ret,
-				    rxrpc_tx_fail_call_data_nofrag);
+				    rxrpc_tx_point_call_data_nofrag);
+	else
+		trace_rxrpc_tx_packet(call->debug_id, &whdr,
+				      rxrpc_tx_point_call_data_nofrag);
 	if (ret == -EMSGSIZE)
 		goto send_fragmentable;
 
@@ -488,7 +497,10 @@ int rxrpc_send_data_packet(struct rxrpc_call *call, struct sk_buff *skb,
 
 	if (ret < 0)
 		trace_rxrpc_tx_fail(call->debug_id, serial, ret,
-				    rxrpc_tx_fail_call_data_frag);
+				    rxrpc_tx_point_call_data_frag);
+	else
+		trace_rxrpc_tx_packet(call->debug_id, &whdr,
+				      rxrpc_tx_point_call_data_frag);
 
 	up_write(&conn->params.local->defrag_sem);
 	goto done;
@@ -545,7 +557,10 @@ void rxrpc_reject_packets(struct rxrpc_local *local)
 			ret = kernel_sendmsg(local->socket, &msg, iov, 2, size);
 			if (ret < 0)
 				trace_rxrpc_tx_fail(local->debug_id, 0, ret,
-						    rxrpc_tx_fail_reject);
+						    rxrpc_tx_point_reject);
+			else
+				trace_rxrpc_tx_packet(local->debug_id, &whdr,
+						      rxrpc_tx_point_reject);
 		}
 
 		rxrpc_free_skb(skb, rxrpc_skb_rx_freed);
@@ -597,7 +612,10 @@ void rxrpc_send_keepalive(struct rxrpc_peer *peer)
 	ret = kernel_sendmsg(peer->local->socket, &msg, iov, 2, len);
 	if (ret < 0)
 		trace_rxrpc_tx_fail(peer->debug_id, 0, ret,
-				    rxrpc_tx_fail_version_keepalive);
+				    rxrpc_tx_point_version_keepalive);
+	else
+		trace_rxrpc_tx_packet(peer->debug_id, &whdr,
+				      rxrpc_tx_point_version_keepalive);
 
 	peer->last_tx_at = ktime_get_real();
 	_leave("");
diff --git a/net/rxrpc/rxkad.c b/net/rxrpc/rxkad.c
index 278ac0807a60..6988073ae842 100644
--- a/net/rxrpc/rxkad.c
+++ b/net/rxrpc/rxkad.c
@@ -665,11 +665,13 @@ static int rxkad_issue_challenge(struct rxrpc_connection *conn)
 	ret = kernel_sendmsg(conn->params.local->socket, &msg, iov, 2, len);
 	if (ret < 0) {
 		trace_rxrpc_tx_fail(conn->debug_id, serial, ret,
-				    rxrpc_tx_fail_conn_challenge);
+				    rxrpc_tx_point_rxkad_challenge);
 		return -EAGAIN;
 	}
 
 	conn->params.peer->last_tx_at = ktime_get_real();
+	trace_rxrpc_tx_packet(conn->debug_id, &whdr,
+			      rxrpc_tx_point_rxkad_challenge);
 	_leave(" = 0");
 	return 0;
 }
@@ -721,11 +723,12 @@ static int rxkad_send_response(struct rxrpc_connection *conn,
 	ret = kernel_sendmsg(conn->params.local->socket, &msg, iov, 3, len);
 	if (ret < 0) {
 		trace_rxrpc_tx_fail(conn->debug_id, serial, ret,
-				    rxrpc_tx_fail_conn_response);
+				    rxrpc_tx_point_rxkad_response);
 		return -EAGAIN;
 	}
 
 	conn->params.peer->last_tx_at = ktime_get_real();
+	trace_rxrpc_tx_packet(0, &whdr, rxrpc_tx_point_rxkad_response);
 	_leave(" = 0");
 	return 0;
 }

^ permalink raw reply related

* [PATCH net-next 06/10] rxrpc: Fix ACK proposal tracepoint
From: David Howells @ 2018-08-01 12:59 UTC (permalink / raw)
  To: netdev; +Cc: dhowells, linux-afs, linux-kernel
In-Reply-To: <153312832565.27702.15302541876382957550.stgit@warthog.procyon.org.uk>

Fix the ACK proposal tracepoint outcomes list by making the one that's an
empty string not an empty string - which gets rendered as a hex number
string instead.

Signed-off-by: David Howells <dhowells@redhat.com>
---

 include/trace/events/rxrpc.h |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/include/trace/events/rxrpc.h b/include/trace/events/rxrpc.h
index 2aa6f615b60d..c1a800a6dee3 100644
--- a/include/trace/events/rxrpc.h
+++ b/include/trace/events/rxrpc.h
@@ -396,7 +396,7 @@ enum rxrpc_tx_point {
 #define rxrpc_propose_ack_outcomes \
 	EM(rxrpc_propose_ack_subsume,		" Subsume") \
 	EM(rxrpc_propose_ack_update,		" Update") \
-	E_(rxrpc_propose_ack_use,		"")
+	E_(rxrpc_propose_ack_use,		" New")
 
 #define rxrpc_congest_modes \
 	EM(RXRPC_CALL_CONGEST_AVOIDANCE,	"CongAvoid") \

^ permalink raw reply related

* [PATCH net-next 07/10] rxrpc: Trace socket notification
From: David Howells @ 2018-08-01 12:59 UTC (permalink / raw)
  To: netdev; +Cc: dhowells, linux-afs, linux-kernel
In-Reply-To: <153312832565.27702.15302541876382957550.stgit@warthog.procyon.org.uk>

Trace notifications from the softirq side of the socket to the
process-context side.

Signed-off-by: David Howells <dhowells@redhat.com>
---

 include/trace/events/rxrpc.h |   20 ++++++++++++++++++++
 net/rxrpc/input.c            |    4 +++-
 2 files changed, 23 insertions(+), 1 deletion(-)

diff --git a/include/trace/events/rxrpc.h b/include/trace/events/rxrpc.h
index c1a800a6dee3..196587b8f204 100644
--- a/include/trace/events/rxrpc.h
+++ b/include/trace/events/rxrpc.h
@@ -1528,6 +1528,26 @@ TRACE_EVENT(rxrpc_call_reset,
 		      __entry->tx_seq, __entry->rx_seq)
 	    );
 
+TRACE_EVENT(rxrpc_notify_socket,
+	    TP_PROTO(unsigned int debug_id, rxrpc_serial_t serial),
+
+	    TP_ARGS(debug_id, serial),
+
+	    TP_STRUCT__entry(
+		    __field(unsigned int,		debug_id	)
+		    __field(rxrpc_serial_t,		serial		)
+			     ),
+
+	    TP_fast_assign(
+		    __entry->debug_id = debug_id;
+		    __entry->serial = serial;
+			   ),
+
+	    TP_printk("c=%08x r=%08x",
+		      __entry->debug_id,
+		      __entry->serial)
+	    );
+
 #endif /* _TRACE_RXRPC_H */
 
 /* This part must be outside protection */
diff --git a/net/rxrpc/input.c b/net/rxrpc/input.c
index 8989d760b6b2..cfdc199c6351 100644
--- a/net/rxrpc/input.c
+++ b/net/rxrpc/input.c
@@ -597,8 +597,10 @@ static void rxrpc_input_data(struct rxrpc_call *call, struct sk_buff *skb,
 				  false, true,
 				  rxrpc_propose_ack_input_data);
 
-	if (sp->hdr.seq == READ_ONCE(call->rx_hard_ack) + 1)
+	if (sp->hdr.seq == READ_ONCE(call->rx_hard_ack) + 1) {
+		trace_rxrpc_notify_socket(call->debug_id, serial);
 		rxrpc_notify_socket(call);
+	}
 	_leave(" [queued]");
 }
 

^ permalink raw reply related

* [PATCH net-next 08/10] rxrpc: Increase the size of a call's Rx window
From: David Howells @ 2018-08-01 12:59 UTC (permalink / raw)
  To: netdev; +Cc: dhowells, linux-afs, linux-kernel
In-Reply-To: <153312832565.27702.15302541876382957550.stgit@warthog.procyon.org.uk>

Increase the size of a call's Rx window from 32 to 63 - ie. one less than
the size of the ring buffer.  This makes large data transfers perform
better when the Tx window on the other side is around 64 (as is the case
with Auristor's YFS fileserver).

If the server window size is ~32 or smaller, this should make no
difference.

Signed-off-by: David Howells <dhowells@redhat.com>
---

 net/rxrpc/ar-internal.h |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/net/rxrpc/ar-internal.h b/net/rxrpc/ar-internal.h
index 7eee955a768a..e791d35ee34b 100644
--- a/net/rxrpc/ar-internal.h
+++ b/net/rxrpc/ar-internal.h
@@ -589,7 +589,7 @@ struct rxrpc_call {
 	 */
 #define RXRPC_RXTX_BUFF_SIZE	64
 #define RXRPC_RXTX_BUFF_MASK	(RXRPC_RXTX_BUFF_SIZE - 1)
-#define RXRPC_INIT_RX_WINDOW_SIZE 32
+#define RXRPC_INIT_RX_WINDOW_SIZE 63
 	struct sk_buff		**rxtx_buffer;
 	u8			*rxtx_annotations;
 #define RXRPC_TX_ANNO_ACK	0

^ permalink raw reply related

* [PATCH net-next 09/10] rxrpc: Propose, but don't immediately transmit, the final ACK for a call
From: David Howells @ 2018-08-01 12:59 UTC (permalink / raw)
  To: netdev; +Cc: dhowells, linux-afs, linux-kernel
In-Reply-To: <153312832565.27702.15302541876382957550.stgit@warthog.procyon.org.uk>

The final ACK that closes out an rxrpc call needs to be transmitted by the
client unless we're going to follow up with a DATA packet for a new call on
the same channel (which implicitly ACK's the previous call, thereby saving
an ACK).

Currently, we don't do that, so if no follow on call is immediately
forthcoming, the server will resend the last DATA packet - at which point
rxrpc_conn_retransmit_call() will be triggered and will (re)send the final
ACK.  But the server has to hold on to the last packet until the ACK is
received, thereby holding up its resources.

Fix the client side to propose a delayed final ACK, to be transmitted after
a short delay, assuming the call isn't superseded by a new one.

Signed-off-by: David Howells <dhowells@redhat.com>
---

 net/rxrpc/recvmsg.c |    6 ++----
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/net/rxrpc/recvmsg.c b/net/rxrpc/recvmsg.c
index 7bff716e911e..02f1f768e16a 100644
--- a/net/rxrpc/recvmsg.c
+++ b/net/rxrpc/recvmsg.c
@@ -144,13 +144,11 @@ static void rxrpc_end_rx_phase(struct rxrpc_call *call, rxrpc_serial_t serial)
 	trace_rxrpc_receive(call, rxrpc_receive_end, 0, call->rx_top);
 	ASSERTCMP(call->rx_hard_ack, ==, call->rx_top);
 
-#if 0 // TODO: May want to transmit final ACK under some circumstances anyway
 	if (call->state == RXRPC_CALL_CLIENT_RECV_REPLY) {
-		rxrpc_propose_ACK(call, RXRPC_ACK_IDLE, 0, serial, true, false,
+		rxrpc_propose_ACK(call, RXRPC_ACK_IDLE, 0, serial, false, true,
 				  rxrpc_propose_ack_terminal_ack);
-		rxrpc_send_ack_packet(call, false, NULL);
+		//rxrpc_send_ack_packet(call, false, NULL);
 	}
-#endif
 
 	write_lock_bh(&call->state_lock);
 

^ permalink raw reply related

* [PATCH net-next 10/10] rxrpc: Transmit more ACKs during data reception
From: David Howells @ 2018-08-01 12:59 UTC (permalink / raw)
  To: netdev; +Cc: dhowells, linux-afs, linux-kernel
In-Reply-To: <153312832565.27702.15302541876382957550.stgit@warthog.procyon.org.uk>

Immediately flush any outstanding ACK on entry to rxrpc_recvmsg_data() -
which transfers data to the target buffers - if we previously had an Rx
underrun (ie. we returned -EAGAIN because we ran out of received data).
This lets the server know what we've managed to receive something.

Also flush any outstanding ACK after calling the function if it hit -EAGAIN
to let the server know we processed some data.

It might be better to send more ACKs, possibly on a time-based scheme, but
that needs some more consideration.

With this and some additional AFS patches, it is possible to get large
unencrypted O_DIRECT reads to be almost as fast as NFS over TCP.  It looks
like it might be theoretically possible to improve performance yet more for
a server running a single operation as investigation of packet timestamps
indicates that the server keeps stalling.

The issue appears to be that rxrpc runs in to trouble with ACK packets
getting batched together (up to ~32 at a time) somewhere between the IP
transmit queue on the client and the ethernet receive queue on the server.

However, this case isn't too much of a worry as even a lightly loaded
server should be receiving sufficient packet flux to flush the ACK packets
to the UDP socket.

Signed-off-by: David Howells <dhowells@redhat.com>
---

 net/rxrpc/ar-internal.h |    1 +
 net/rxrpc/recvmsg.c     |   17 +++++++++++++++++
 2 files changed, 18 insertions(+)

diff --git a/net/rxrpc/ar-internal.h b/net/rxrpc/ar-internal.h
index e791d35ee34b..9d9278a13d91 100644
--- a/net/rxrpc/ar-internal.h
+++ b/net/rxrpc/ar-internal.h
@@ -479,6 +479,7 @@ enum rxrpc_call_flag {
 	RXRPC_CALL_RETRANS_TIMEOUT,	/* Retransmission due to timeout occurred */
 	RXRPC_CALL_BEGAN_RX_TIMER,	/* We began the expect_rx_by timer */
 	RXRPC_CALL_RX_HEARD,		/* The peer responded at least once to this call */
+	RXRPC_CALL_RX_UNDERRUN,		/* Got data underrun */
 };
 
 /*
diff --git a/net/rxrpc/recvmsg.c b/net/rxrpc/recvmsg.c
index 02f1f768e16a..a57ea96c84ea 100644
--- a/net/rxrpc/recvmsg.c
+++ b/net/rxrpc/recvmsg.c
@@ -313,6 +313,10 @@ static int rxrpc_recvmsg_data(struct socket *sock, struct rxrpc_call *call,
 	unsigned int rx_pkt_offset, rx_pkt_len;
 	int ix, copy, ret = -EAGAIN, ret2;
 
+	if (test_and_clear_bit(RXRPC_CALL_RX_UNDERRUN, &call->flags) &&
+	    call->ackr_reason)
+		rxrpc_send_ack_packet(call, false, NULL);
+
 	rx_pkt_offset = call->rx_pkt_offset;
 	rx_pkt_len = call->rx_pkt_len;
 
@@ -412,6 +416,8 @@ static int rxrpc_recvmsg_data(struct socket *sock, struct rxrpc_call *call,
 done:
 	trace_rxrpc_recvmsg(call, rxrpc_recvmsg_data_return, seq,
 			    rx_pkt_offset, rx_pkt_len, ret);
+	if (ret == -EAGAIN)
+		set_bit(RXRPC_CALL_RX_UNDERRUN, &call->flags);
 	return ret;
 }
 
@@ -684,6 +690,17 @@ int rxrpc_kernel_recv_data(struct socket *sock, struct rxrpc_call *call,
 read_phase_complete:
 	ret = 1;
 out:
+	switch (call->ackr_reason) {
+	case RXRPC_ACK_IDLE:
+		break;
+	case RXRPC_ACK_DELAY:
+		if (ret != -EAGAIN)
+			break;
+		/* Fall through */
+	default:
+		rxrpc_send_ack_packet(call, false, NULL);
+	}
+
 	if (_service)
 		*_service = call->service_id;
 	mutex_unlock(&call->user_mutex);

^ permalink raw reply related

* Re: [PATCH] sunrpc: remove redundant variables 'checksumlen','blocksize' and 'data'
From: J. Bruce Fields @ 2018-08-01 13:00 UTC (permalink / raw)
  To: YueHaibing
  Cc: davem, trond.myklebust, anna.schumaker, jlayton, ebiggers,
	chuck.lever, linux-kernel, netdev, linux-nfs
In-Reply-To: <20180801062810.19752-1-yuehaibing@huawei.com>

Thanks, applying (assuming Chuck's got no objection to the svc_rdma
part).

--b.

On Wed, Aug 01, 2018 at 02:28:10PM +0800, YueHaibing wrote:
> Variables 'checksumlen','blocksize' and 'data' are being assigned,
> but are never used,hence they are redundant and can be removed.
> 
> fix fllowing warning:
> 
> net/sunrpc/auth_gss/gss_krb5_wrap.c:443:7: warning: variable ‘blocksize’ set but not used [-Wunused-but-set-variable]
> net/sunrpc/auth_gss/gss_krb5_crypto.c:376:15: warning: variable ‘checksumlen’ set but not used [-Wunused-but-set-variable]
> net/sunrpc/xprtrdma/svc_rdma.c:97:9: warning: variable ‘data’ set but not used [-Wunused-but-set-variable]
> 
> Signed-off-by: YueHaibing <yuehaibing@huawei.com>
> ---
>  net/sunrpc/auth_gss/gss_krb5_crypto.c | 2 --
>  net/sunrpc/auth_gss/gss_krb5_wrap.c   | 2 --
>  net/sunrpc/xprtrdma/svc_rdma.c        | 2 --
>  3 files changed, 6 deletions(-)
> 
> diff --git a/net/sunrpc/auth_gss/gss_krb5_crypto.c b/net/sunrpc/auth_gss/gss_krb5_crypto.c
> index 8654494..84a16fd 100644
> --- a/net/sunrpc/auth_gss/gss_krb5_crypto.c
> +++ b/net/sunrpc/auth_gss/gss_krb5_crypto.c
> @@ -373,7 +373,6 @@ make_checksum_v2(struct krb5_ctx *kctx, char *header, int hdrlen,
>  	struct scatterlist sg[1];
>  	int err = -1;
>  	u8 *checksumdata;
> -	unsigned int checksumlen;
>  
>  	if (kctx->gk5e->keyed_cksum == 0) {
>  		dprintk("%s: expected keyed hash for %s\n",
> @@ -393,7 +392,6 @@ make_checksum_v2(struct krb5_ctx *kctx, char *header, int hdrlen,
>  	tfm = crypto_alloc_ahash(kctx->gk5e->cksum_name, 0, CRYPTO_ALG_ASYNC);
>  	if (IS_ERR(tfm))
>  		goto out_free_cksum;
> -	checksumlen = crypto_ahash_digestsize(tfm);
>  
>  	req = ahash_request_alloc(tfm, GFP_NOFS);
>  	if (!req)
> diff --git a/net/sunrpc/auth_gss/gss_krb5_wrap.c b/net/sunrpc/auth_gss/gss_krb5_wrap.c
> index a737c2d..9a1347f 100644
> --- a/net/sunrpc/auth_gss/gss_krb5_wrap.c
> +++ b/net/sunrpc/auth_gss/gss_krb5_wrap.c
> @@ -440,7 +440,6 @@ static u32
>  gss_wrap_kerberos_v2(struct krb5_ctx *kctx, u32 offset,
>  		     struct xdr_buf *buf, struct page **pages)
>  {
> -	int		blocksize;
>  	u8		*ptr, *plainhdr;
>  	s32		now;
>  	u8		flags = 0x00;
> @@ -473,7 +472,6 @@ gss_wrap_kerberos_v2(struct krb5_ctx *kctx, u32 offset,
>  	*ptr++ = 0xff;
>  	be16ptr = (__be16 *)ptr;
>  
> -	blocksize = crypto_skcipher_blocksize(kctx->acceptor_enc);
>  	*be16ptr++ = 0;
>  	/* "inner" token header always uses 0 for RRC */
>  	*be16ptr++ = 0;
> diff --git a/net/sunrpc/xprtrdma/svc_rdma.c b/net/sunrpc/xprtrdma/svc_rdma.c
> index 357ba90..134bef6a 100644
> --- a/net/sunrpc/xprtrdma/svc_rdma.c
> +++ b/net/sunrpc/xprtrdma/svc_rdma.c
> @@ -94,7 +94,6 @@ static int read_reset_stat(struct ctl_table *table, int write,
>  		atomic_set(stat, 0);
>  	else {
>  		char str_buf[32];
> -		char *data;
>  		int len = snprintf(str_buf, 32, "%d\n", atomic_read(stat));
>  		if (len >= 32)
>  			return -EFAULT;
> @@ -103,7 +102,6 @@ static int read_reset_stat(struct ctl_table *table, int write,
>  			*lenp = 0;
>  			return 0;
>  		}
> -		data = &str_buf[*ppos];
>  		len -= *ppos;
>  		if (len > *lenp)
>  			len = *lenp;
> -- 
> 2.7.0
> 

^ permalink raw reply

* Re: SLAB_TYPESAFE_BY_RCU without constructors (was Re: [PATCH v4 13/17] khwasan: add hooks implementation)
From: Dmitry Vyukov @ 2018-08-01 11:35 UTC (permalink / raw)
  To: Eric Dumazet
  Cc: Andrey Ryabinin, Linus Torvalds, Christoph Lameter,
	Theodore Ts'o, Jan Kara, linux-ext4, Greg Kroah-Hartman,
	Pablo Neira Ayuso, Jozsef Kadlecsik, Florian Westphal,
	David Miller, NetFilter, coreteam, Network Development,
	Gerrit Renker, dccp, Jani Nikula, Joonas Lahtinen, Rodrigo Vivi,
	Dave Airlie
In-Reply-To: <cf751136-c459-853a-0210-abf16f54ad17@gmail.com>

On Wed, Aug 1, 2018 at 1:28 PM, Eric Dumazet <eric.dumazet@gmail.com> wrote:
> On 08/01/2018 03:34 AM, Dmitry Vyukov wrote:
>> On Wed, Aug 1, 2018 at 12:23 PM, Eric Dumazet <eric.dumazet@gmail.com> wrote:
>>> On 08/01/2018 02:03 AM, Andrey Ryabinin wrote:
>>>
>>>> I can't think of any advantage in not having the constructor.
>>>
>>> I can't see any advantage adding another indirect call,
>>> in RETPOLINE world.
>>
>> Can you please elaborate what's the problem here?
>> If slab ctor call have RETPOLINE, then using ctors more does not
>> introduce any security problems and they are not _that_ slow.
>
> They _are_ slow, when we have dozens of them in a code path.
>
> I object "having to add" yet another indirect call, if this can be avoided [*]
>
> If some people want to use ctor, fine, but do not request this.
>
> [*] This can be tricky, but worth the pain.

But we are trading 1 indirect call for comparable overhead removed
from much more common path. The path that does ctors is also calling
into page alloc, which is much more expensive.
So ctor should be a net win on performance front, no?

^ permalink raw reply

* RE: [PATCH] cfg80211: read wmm rules from regulatory database
From: Dreyfuss, Haim @ 2018-08-01 13:23 UTC (permalink / raw)
  To: Colin Ian King, David S. Miller, Johannes Berg,
	netdev@vger.kernel.org, linux-wireless@vger.kernel.org
  Cc: linux-kernel@vger.kernel.org
In-Reply-To: <9ff30f03-07f1-0abd-8c57-2601af546de0@canonical.com>

> -----Original Message-----
> From: Colin Ian King [mailto:colin.king@canonical.com]
> Sent: Tuesday, July 31, 2018 2:28 PM
> To: Dreyfuss, Haim <haim.dreyfuss@intel.com>; David S. Miller
> <davem@davemloft.net>; Johannes Berg <johannes@sipsolutions.net>;
> netdev@vger.kernel.org; linux-wireless@vger.kernel.org
> Cc: linux-kernel@vger.kernel.org
> Subject: re: [PATCH] cfg80211: read wmm rules from regulatory database
> 
> Hi Haim,
> 
> I think there may be an issue with the commit:
> 
> From 230ebaa189af44d50dccb4a1846e39ca594e347b Mon Sep 17 00:00:00
> 2001
> From: Haim Dreyfuss <haim.dreyfuss@intel.com>
> Date: Wed, 28 Mar 2018 13:24:09 +0300
> Subject: [PATCH] cfg80211: read wmm rules from regulatory database
> 
> specifically in function: reg_copy_regd()
> 
> +       for (i = 0; i < src_regd->n_reg_rules; i++) {
>                 memcpy(&regd->reg_rules[i], &src_regd->reg_rules[i],
>                        sizeof(struct ieee80211_reg_rule));
> +               if (!src_regd->reg_rules[i].wmm_rule)
> +                       continue;
> 
> +               regd->reg_rules[i].wmm_rule = d_wmm +
> +                       (src_regd->reg_rules[i].wmm_rule - s_wmm) /
> +                       sizeof(struct ieee80211_wmm_rule);
> +       }
> 
> The pointer arithmetic (src_regd->reg_rules[i].wmm_rule - s_wmm) is
> performed in terms of the size of struct ieee80211_wmm_rule and not in
> bytes and I believe that the division by sizeof(struct
> ieee80211_wmm_rule) is not required.
> 
> This issue was detected by static analysis with Coverity Scan,
> CID#1467451 ("Extra sizeof expression"), 'suspicious_division'
> 
> I'm not 100% sure that is this a false positive or not, but I think it looks
> incorrect to me.

Yeah you're right, this is not false positive.
Johannes already fixed that and Luca will probably send it in the coming week.
> 

^ permalink raw reply

* AW: AW: AW: PROBLEM: Kernel Oops in UDP stack
From: Marcel Hellwig @ 2018-08-01 13:27 UTC (permalink / raw)
  To: 'Eric Dumazet', Paolo Abeni,
	'davem@davemloft.net', 'kuznet@ms2.inr.ac.ru',
	'yoshfuji@linux-ipv6.org', 'andrew@lunn.ch'
  Cc: 'netdev@vger.kernel.org',
	'linux-kernel@vger.kernel.org', Matthias Wystrik
In-Reply-To: <7feb4b8950b842469265672f4c7b381d@ZCOM03.mut-group.com>

>Another way to spot the problem would be to add a check in 
>pskb_expand_head()
>

Many thanks for this advice. Indeed, by backporting the pskb_expand_head (and build_skb because it didn't exist) from the version 3.5.7 to 3.4.113 fixes (?) the issue for now. We want to test 3 or 4 machines over night and see if any problem occurs. 

Let's see if we can do the same for our 2.6.39.2 kernel (I guess that will be pure pain 😃 ).

Many thanks so far for your support! I will report tomorrow (CEST) if we succeeded.


Mit freundlichen Grüßen / With kind regards

Marcel Hellwig
B. Sc. Informatik
Entwickler

m-u-t GmbH
Am Marienhof 2
22880 Wedel
Germany

Phone:	+49 4103 9308 - 474
Fax:  	+49 4103 9308 - 99
mhellwig@mut-group.com

www.mut-group.com

Geschäftsführer (Managing Director): Fabian Peters Amtsgericht Pinneberg (Commercial Register No.): HRB 10304 PI USt-IdNr. (VAT-No.): DE228275390
WEEE-Reg-Nr.: DE 72271808



^ permalink raw reply

* Re: SLAB_TYPESAFE_BY_RCU without constructors (was Re: [PATCH v4 13/17] khwasan: add hooks implementation)
From: Florian Westphal @ 2018-08-01 13:46 UTC (permalink / raw)
  To: Dmitry Vyukov
  Cc: Florian Westphal, Linus Torvalds, Christoph Lameter,
	Andrey Ryabinin, Theodore Ts'o, Jan Kara, linux-ext4,
	Greg Kroah-Hartman, Pablo Neira Ayuso, Jozsef Kadlecsik,
	David Miller, NetFilter, coreteam, Network Development,
	Gerrit Renker, dccp, Jani Nikula, Joonas Lahtinen, Rodrigo Vivi,
	Dave Airlie
In-Reply-To: <CACT4Y+ZNnYojj0x_DoUxeUREaEgzcf3UG=UW_P4vzsnZNjjgMQ@mail.gmail.com>

Dmitry Vyukov <dvyukov@google.com> wrote:
> If that scenario is possible that a fix would be to make

Looks possible.

> __nf_conntrack_find_get ever return NULL iff it got NULL from
> ____nf_conntrack_find (not if any of the checks has failed).

I don't see why we need to restart on nf_ct_is_dying(), but other
than that this seems ok.

^ permalink raw reply

* Re: [PATCH bpf-next 03/13] docs: net: Add filter to index toctree
From: Jonathan Corbet @ 2018-08-01 13:52 UTC (permalink / raw)
  To: Tobin C. Harding
  Cc: Daniel Borkmann, Alexei Starovoitov, David S. Miller, linux-doc,
	netdev, linux-kernel
In-Reply-To: <20180801050908.29970-4-me@tobin.cc>

On Wed,  1 Aug 2018 15:08:58 +1000
"Tobin C. Harding" <me@tobin.cc> wrote:

> filter.rst was just created (from filter.txt).  We should include it in
> the networking docs toctree.
> 
> Add filter to Documentation/networking/index.rst toctree.

So...the minorest of nits just to prove that I actually looked at
this...:)  Adding it to the toctree at this point is going to make the
docs build messy (OK, even messier than it already is) because the RST
conversion hasn't really been done yet.  I'd do this at the end of the
series, just in case somebody, somewhere, is crazy enough to try to
bisect a docs build.

Something that's a bit more relevant, perhaps: this document is a bit of
a mishmash.  It starts by talking about how to use cBPF for socket
filters, then includes a long discussion about the features of eBPF
which, as I understand it, is still not accessible to user space for
socket filters. That latter part certainly merits being in its own file
where people will actually find it?  And if it were me, I would move that
file into the core API guide, since it will be relevant beyond networking.

Thanks,

jon

^ permalink raw reply

* Re: SLAB_TYPESAFE_BY_RCU without constructors (was Re: [PATCH v4 13/17] khwasan: add hooks implementation)
From: Dmitry Vyukov @ 2018-08-01 13:52 UTC (permalink / raw)
  To: Florian Westphal
  Cc: Linus Torvalds, Christoph Lameter, Andrey Ryabinin,
	Theodore Ts'o, Jan Kara, linux-ext4, Greg Kroah-Hartman,
	Pablo Neira Ayuso, Jozsef Kadlecsik, David Miller, NetFilter,
	coreteam, Network Development, Gerrit Renker, dccp, Jani Nikula,
	Joonas Lahtinen, Rodrigo Vivi, Dave Airlie, intel-gfx
In-Reply-To: <20180801134628.ueyzwg2gszrvk2hc@breakpoint.cc>

On Wed, Aug 1, 2018 at 3:46 PM, Florian Westphal <fw@strlen.de> wrote:
> Dmitry Vyukov <dvyukov@google.com> wrote:
>> If that scenario is possible that a fix would be to make
>
> Looks possible.
>
>> __nf_conntrack_find_get ever return NULL iff it got NULL from
>> ____nf_conntrack_find (not if any of the checks has failed).
>
> I don't see why we need to restart on nf_ct_is_dying(), but other
> than that this seems ok.

Because it can be a wrong entry dying. When we check dying, we don't
yet know if we are looking at the right entry or not. If we
successfully acquire a reference, then recheck nf_ct_key_equal and
_then_ check dying, then we don't need to restart on dying. But with
the current check order, we need to restart on dying too.

^ permalink raw reply

* [PATCH net-next 0/9] Add 10GbE support in stmmac using XGMAC2
From: Jose Abreu @ 2018-08-01 12:10 UTC (permalink / raw)
  To: netdev
  Cc: Jose Abreu, David S. Miller, Joao Pinto, Giuseppe Cavallaro,
	Alexandre Torgue

This series adds support for 10Gigabit IP in stmmac. The IP is called XGMAC2
and has many similarities with GMAC4. Due to this, its relatively easy to
incorporate this new IP into stmmac driver by adding a new block and
filling the necessary callbacks.

The functionality added by this series is still reduced but its only a
starting point which will later be expanded.

I splitted the patches into funcionality and to ease the review. Only the
patch 8/9 really enables the XGMAC2 block by adding a new compatible string.

Cc: David S. Miller <davem@davemloft.net>
Cc: Joao Pinto <jpinto@synopsys.com>
Cc: Giuseppe Cavallaro <peppe.cavallaro@st.com>
Cc: Alexandre Torgue <alexandre.torgue@st.com>

Jose Abreu (9):
  net: stmmac: Add XGMAC 2.10 HWIF entry
  net: stmmac: Add MAC related callbacks for XGMAC2
  net: stmmac: Add DMA related callbacks for XGMAC2
  net: stmmac: Add descriptor related callbacks for XGMAC2
  net: stmmac: Add MDIO related functions for XGMAC2
  net: stmmac: Add PTP support for XGMAC2
  net: stmmac: Integrate XGMAC into main driver flow
  net: stmmac: Add the bindings parsing for XGMAC2
  bindings: net: stmmac: Add the bindings documentation for XGMAC2.

 Documentation/devicetree/bindings/net/stmmac.txt   |   3 +-
 drivers/net/ethernet/stmicro/stmmac/Makefile       |   3 +-
 drivers/net/ethernet/stmicro/stmmac/common.h       |  17 +-
 .../net/ethernet/stmicro/stmmac/dwmac-generic.c    |   2 +
 drivers/net/ethernet/stmicro/stmmac/dwxgmac2.h     | 226 ++++++++++++
 .../net/ethernet/stmicro/stmmac/dwxgmac2_core.c    | 371 +++++++++++++++++++
 .../net/ethernet/stmicro/stmmac/dwxgmac2_descs.c   | 280 ++++++++++++++
 drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c | 410 +++++++++++++++++++++
 drivers/net/ethernet/stmicro/stmmac/hwif.c         |  31 +-
 drivers/net/ethernet/stmicro/stmmac/hwif.h         |   3 +
 drivers/net/ethernet/stmicro/stmmac/stmmac_main.c  |  55 ++-
 drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c  |  88 +++++
 .../net/ethernet/stmicro/stmmac/stmmac_platform.c  |   6 +
 drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.c   |   6 +-
 drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.h   |   1 +
 include/linux/stmmac.h                             |   1 +
 16 files changed, 1481 insertions(+), 22 deletions(-)
 create mode 100644 drivers/net/ethernet/stmicro/stmmac/dwxgmac2.h
 create mode 100644 drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c
 create mode 100644 drivers/net/ethernet/stmicro/stmmac/dwxgmac2_descs.c
 create mode 100644 drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c

-- 
2.7.4

^ permalink raw reply

* [PATCH net-next 1/9] net: stmmac: Add XGMAC 2.10 HWIF entry
From: Jose Abreu @ 2018-08-01 12:10 UTC (permalink / raw)
  To: netdev
  Cc: Jose Abreu, David S. Miller, Joao Pinto, Giuseppe Cavallaro,
	Alexandre Torgue
In-Reply-To: <cover.1533125016.git.joabreu@synopsys.com>

Add a new entry to HWIF table for XGMAC 2.10. For now we fill it with
empty callbacks which will be added in posterior patches.

Signed-off-by: Jose Abreu <joabreu@synopsys.com>
Cc: David S. Miller <davem@davemloft.net>
Cc: Joao Pinto <jpinto@synopsys.com>
Cc: Giuseppe Cavallaro <peppe.cavallaro@st.com>
Cc: Alexandre Torgue <alexandre.torgue@st.com>
---
 drivers/net/ethernet/stmicro/stmmac/common.h | 14 +++++++------
 drivers/net/ethernet/stmicro/stmmac/hwif.c   | 31 ++++++++++++++++++++++++++--
 include/linux/stmmac.h                       |  1 +
 3 files changed, 38 insertions(+), 8 deletions(-)

diff --git a/drivers/net/ethernet/stmicro/stmmac/common.h b/drivers/net/ethernet/stmicro/stmmac/common.h
index 78fd0f8b8e81..3fb81acbd274 100644
--- a/drivers/net/ethernet/stmicro/stmmac/common.h
+++ b/drivers/net/ethernet/stmicro/stmmac/common.h
@@ -36,12 +36,14 @@
 #include "mmc.h"
 
 /* Synopsys Core versions */
-#define	DWMAC_CORE_3_40	0x34
-#define	DWMAC_CORE_3_50	0x35
-#define	DWMAC_CORE_4_00	0x40
-#define DWMAC_CORE_4_10	0x41
-#define DWMAC_CORE_5_00 0x50
-#define DWMAC_CORE_5_10 0x51
+#define	DWMAC_CORE_3_40		0x34
+#define	DWMAC_CORE_3_50		0x35
+#define	DWMAC_CORE_4_00		0x40
+#define DWMAC_CORE_4_10		0x41
+#define DWMAC_CORE_5_00		0x50
+#define DWMAC_CORE_5_10		0x51
+#define DWXGMAC_CORE_2_10	0x21
+
 #define STMMAC_CHAN0	0	/* Always supported and default for all chips */
 
 /* These need to be power of two, and >= 4 */
diff --git a/drivers/net/ethernet/stmicro/stmmac/hwif.c b/drivers/net/ethernet/stmicro/stmmac/hwif.c
index 1f50e83cafb2..24f5ff175aa4 100644
--- a/drivers/net/ethernet/stmicro/stmmac/hwif.c
+++ b/drivers/net/ethernet/stmicro/stmmac/hwif.c
@@ -72,6 +72,7 @@ static int stmmac_dwmac4_quirks(struct stmmac_priv *priv)
 static const struct stmmac_hwif_entry {
 	bool gmac;
 	bool gmac4;
+	bool xgmac;
 	u32 min_id;
 	const struct stmmac_regs_off regs;
 	const void *desc;
@@ -87,6 +88,7 @@ static const struct stmmac_hwif_entry {
 	{
 		.gmac = false,
 		.gmac4 = false,
+		.xgmac = false,
 		.min_id = 0,
 		.regs = {
 			.ptp_off = PTP_GMAC3_X_OFFSET,
@@ -103,6 +105,7 @@ static const struct stmmac_hwif_entry {
 	}, {
 		.gmac = true,
 		.gmac4 = false,
+		.xgmac = false,
 		.min_id = 0,
 		.regs = {
 			.ptp_off = PTP_GMAC3_X_OFFSET,
@@ -119,6 +122,7 @@ static const struct stmmac_hwif_entry {
 	}, {
 		.gmac = false,
 		.gmac4 = true,
+		.xgmac = false,
 		.min_id = 0,
 		.regs = {
 			.ptp_off = PTP_GMAC4_OFFSET,
@@ -135,6 +139,7 @@ static const struct stmmac_hwif_entry {
 	}, {
 		.gmac = false,
 		.gmac4 = true,
+		.xgmac = false,
 		.min_id = DWMAC_CORE_4_00,
 		.regs = {
 			.ptp_off = PTP_GMAC4_OFFSET,
@@ -151,6 +156,7 @@ static const struct stmmac_hwif_entry {
 	}, {
 		.gmac = false,
 		.gmac4 = true,
+		.xgmac = false,
 		.min_id = DWMAC_CORE_4_10,
 		.regs = {
 			.ptp_off = PTP_GMAC4_OFFSET,
@@ -167,6 +173,7 @@ static const struct stmmac_hwif_entry {
 	}, {
 		.gmac = false,
 		.gmac4 = true,
+		.xgmac = false,
 		.min_id = DWMAC_CORE_5_10,
 		.regs = {
 			.ptp_off = PTP_GMAC4_OFFSET,
@@ -180,11 +187,29 @@ static const struct stmmac_hwif_entry {
 		.tc = &dwmac510_tc_ops,
 		.setup = dwmac4_setup,
 		.quirks = NULL,
-	}
+	}, {
+		.gmac = false,
+		.gmac4 = false,
+		.xgmac = true,
+		.min_id = DWXGMAC_CORE_2_10,
+		.regs = {
+			.ptp_off = 0,
+			.mmc_off = 0,
+		},
+		.desc = NULL,
+		.dma = NULL,
+		.mac = NULL,
+		.hwtimestamp = NULL,
+		.mode = NULL,
+		.tc = NULL,
+		.setup = NULL,
+		.quirks = NULL,
+	},
 };
 
 int stmmac_hwif_init(struct stmmac_priv *priv)
 {
+	bool needs_xgmac = priv->plat->has_xgmac;
 	bool needs_gmac4 = priv->plat->has_gmac4;
 	bool needs_gmac = priv->plat->has_gmac;
 	const struct stmmac_hwif_entry *entry;
@@ -195,7 +220,7 @@ int stmmac_hwif_init(struct stmmac_priv *priv)
 
 	if (needs_gmac) {
 		id = stmmac_get_id(priv, GMAC_VERSION);
-	} else if (needs_gmac4) {
+	} else if (needs_gmac4 || needs_xgmac) {
 		id = stmmac_get_id(priv, GMAC4_VERSION);
 	} else {
 		id = 0;
@@ -229,6 +254,8 @@ int stmmac_hwif_init(struct stmmac_priv *priv)
 			continue;
 		if (needs_gmac4 ^ entry->gmac4)
 			continue;
+		if (needs_xgmac ^ entry->xgmac)
+			continue;
 		/* Use synopsys_id var because some setups can override this */
 		if (priv->synopsys_id < entry->min_id)
 			continue;
diff --git a/include/linux/stmmac.h b/include/linux/stmmac.h
index 32feac5bbd75..c43e9a01b892 100644
--- a/include/linux/stmmac.h
+++ b/include/linux/stmmac.h
@@ -190,5 +190,6 @@ struct plat_stmmacenet_data {
 	bool tso_en;
 	int mac_port_sel_speed;
 	bool en_tx_lpi_clockgating;
+	int has_xgmac;
 };
 #endif
-- 
2.7.4

^ permalink raw reply related

* [PATCH net-next 2/9] net: stmmac: Add MAC related callbacks for XGMAC2
From: Jose Abreu @ 2018-08-01 12:10 UTC (permalink / raw)
  To: netdev
  Cc: Jose Abreu, David S. Miller, Joao Pinto, Giuseppe Cavallaro,
	Alexandre Torgue
In-Reply-To: <cover.1533125016.git.joabreu@synopsys.com>

Add the MAC related callbacks for the new IP block XGMAC2.

Signed-off-by: Jose Abreu <joabreu@synopsys.com>
Cc: David S. Miller <davem@davemloft.net>
Cc: Joao Pinto <jpinto@synopsys.com>
Cc: Giuseppe Cavallaro <peppe.cavallaro@st.com>
Cc: Alexandre Torgue <alexandre.torgue@st.com>
---
 drivers/net/ethernet/stmicro/stmmac/Makefile       |   2 +-
 drivers/net/ethernet/stmicro/stmmac/common.h       |   3 +
 drivers/net/ethernet/stmicro/stmmac/dwxgmac2.h     | 140 ++++++++
 .../net/ethernet/stmicro/stmmac/dwxgmac2_core.c    | 371 +++++++++++++++++++++
 drivers/net/ethernet/stmicro/stmmac/hwif.c         |   4 +-
 drivers/net/ethernet/stmicro/stmmac/hwif.h         |   1 +
 6 files changed, 518 insertions(+), 3 deletions(-)
 create mode 100644 drivers/net/ethernet/stmicro/stmmac/dwxgmac2.h
 create mode 100644 drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c

diff --git a/drivers/net/ethernet/stmicro/stmmac/Makefile b/drivers/net/ethernet/stmicro/stmmac/Makefile
index 68e9e2640c62..a6cf632c9592 100644
--- a/drivers/net/ethernet/stmicro/stmmac/Makefile
+++ b/drivers/net/ethernet/stmicro/stmmac/Makefile
@@ -5,7 +5,7 @@ stmmac-objs:= stmmac_main.o stmmac_ethtool.o stmmac_mdio.o ring_mode.o	\
 	      dwmac100_core.o dwmac100_dma.o enh_desc.o norm_desc.o	\
 	      mmc_core.o stmmac_hwtstamp.o stmmac_ptp.o dwmac4_descs.o	\
 	      dwmac4_dma.o dwmac4_lib.o dwmac4_core.o dwmac5.o hwif.o \
-	      stmmac_tc.o $(stmmac-y)
+	      stmmac_tc.o dwxgmac2_core.o $(stmmac-y)
 
 # Ordering matters. Generic driver must be last.
 obj-$(CONFIG_STMMAC_PLATFORM)	+= stmmac-platform.o
diff --git a/drivers/net/ethernet/stmicro/stmmac/common.h b/drivers/net/ethernet/stmicro/stmmac/common.h
index 3fb81acbd274..1854f270ad66 100644
--- a/drivers/net/ethernet/stmicro/stmmac/common.h
+++ b/drivers/net/ethernet/stmicro/stmmac/common.h
@@ -400,6 +400,8 @@ struct mac_link {
 	u32 speed10;
 	u32 speed100;
 	u32 speed1000;
+	u32 speed2500;
+	u32 speed10000;
 	u32 duplex;
 };
 
@@ -441,6 +443,7 @@ struct stmmac_rx_routing {
 int dwmac100_setup(struct stmmac_priv *priv);
 int dwmac1000_setup(struct stmmac_priv *priv);
 int dwmac4_setup(struct stmmac_priv *priv);
+int dwxgmac2_setup(struct stmmac_priv *priv);
 
 void stmmac_set_mac_addr(void __iomem *ioaddr, u8 addr[6],
 			 unsigned int high, unsigned int low);
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2.h b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2.h
new file mode 100644
index 000000000000..ef63a62a699d
--- /dev/null
+++ b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2.h
@@ -0,0 +1,140 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MIT)
+/*
+ * Copyright (c) 2018 Synopsys, Inc. and/or its affiliates.
+ * stmmac XGMAC definitions.
+ */
+
+#ifndef __STMMAC_DWXGMAC2_H__
+#define __STMMAC_DWXGMAC2_H__
+
+#include "common.h"
+
+/* Misc */
+#define XGMAC_JUMBO_LEN			16368
+
+/* MAC Registers */
+#define XGMAC_TX_CONFIG			0x00000000
+#define XGMAC_CONFIG_SS_OFF		29
+#define XGMAC_CONFIG_SS_MASK		GENMASK(30, 29)
+#define XGMAC_CONFIG_SS_10000		(0x0 << XGMAC_CONFIG_SS_OFF)
+#define XGMAC_CONFIG_SS_2500		(0x2 << XGMAC_CONFIG_SS_OFF)
+#define XGMAC_CONFIG_SS_1000		(0x3 << XGMAC_CONFIG_SS_OFF)
+#define XGMAC_CONFIG_SARC		GENMASK(22, 20)
+#define XGMAC_CONFIG_SARC_SHIFT		20
+#define XGMAC_CONFIG_JD			BIT(16)
+#define XGMAC_CONFIG_TE			BIT(0)
+#define XGMAC_CORE_INIT_TX		(XGMAC_CONFIG_JD)
+#define XGMAC_RX_CONFIG			0x00000004
+#define XGMAC_CONFIG_ARPEN		BIT(31)
+#define XGMAC_CONFIG_GPSL		GENMASK(29, 16)
+#define XGMAC_CONFIG_GPSL_SHIFT		16
+#define XGMAC_CONFIG_S2KP		BIT(11)
+#define XGMAC_CONFIG_IPC		BIT(9)
+#define XGMAC_CONFIG_JE			BIT(8)
+#define XGMAC_CONFIG_WD			BIT(7)
+#define XGMAC_CONFIG_GPSLCE		BIT(6)
+#define XGMAC_CONFIG_CST		BIT(2)
+#define XGMAC_CONFIG_ACS		BIT(1)
+#define XGMAC_CONFIG_RE			BIT(0)
+#define XGMAC_CORE_INIT_RX		0
+#define XGMAC_PACKET_FILTER		0x00000008
+#define XGMAC_FILTER_RA			BIT(31)
+#define XGMAC_FILTER_PM			BIT(4)
+#define XGMAC_FILTER_HMC		BIT(2)
+#define XGMAC_FILTER_PR			BIT(0)
+#define XGMAC_HASH_TABLE(x)		(0x00000010 + (x) * 4)
+#define XGMAC_RXQ_CTRL0			0x000000a0
+#define XGMAC_RXQEN(x)			GENMASK((x) * 2 + 1, (x) * 2)
+#define XGMAC_RXQEN_SHIFT(x)		((x) * 2)
+#define XGMAC_RXQ_CTRL2			0x000000a8
+#define XGMAC_RXQ_CTRL3			0x000000ac
+#define XGMAC_PSRQ(x)			GENMASK((x) * 8 + 7, (x) * 8)
+#define XGMAC_PSRQ_SHIFT(x)		((x) * 8)
+#define XGMAC_INT_STATUS		0x000000b0
+#define XGMAC_PMTIS			BIT(4)
+#define XGMAC_INT_EN			0x000000b4
+#define XGMAC_TSIE			BIT(12)
+#define XGMAC_LPIIE			BIT(5)
+#define XGMAC_PMTIE			BIT(4)
+#define XGMAC_INT_DEFAULT_EN		(XGMAC_LPIIE | XGMAC_PMTIE | XGMAC_TSIE)
+#define XGMAC_Qx_TX_FLOW_CTRL(x)	(0x00000070 + (x) * 4)
+#define XGMAC_PT			GENMASK(31, 16)
+#define XGMAC_PT_SHIFT			16
+#define XGMAC_TFE			BIT(1)
+#define XGMAC_RX_FLOW_CTRL		0x00000090
+#define XGMAC_RFE			BIT(0)
+#define XGMAC_PMT			0x000000c0
+#define XGMAC_GLBLUCAST			BIT(9)
+#define XGMAC_RWKPKTEN			BIT(2)
+#define XGMAC_MGKPKTEN			BIT(1)
+#define XGMAC_PWRDWN			BIT(0)
+#define XGMAC_HW_FEATURE0		0x0000011c
+#define XGMAC_HWFEAT_SAVLANINS		BIT(27)
+#define XGMAC_HWFEAT_RXCOESEL		BIT(16)
+#define XGMAC_HWFEAT_TXCOESEL		BIT(14)
+#define XGMAC_HWFEAT_TSSEL		BIT(12)
+#define XGMAC_HWFEAT_AVSEL		BIT(11)
+#define XGMAC_HWFEAT_RAVSEL		BIT(10)
+#define XGMAC_HWFEAT_ARPOFFSEL		BIT(9)
+#define XGMAC_HWFEAT_MGKSEL		BIT(7)
+#define XGMAC_HWFEAT_RWKSEL		BIT(6)
+#define XGMAC_HWFEAT_GMIISEL		BIT(1)
+#define XGMAC_HW_FEATURE1		0x00000120
+#define XGMAC_HWFEAT_TSOEN		BIT(18)
+#define XGMAC_HWFEAT_TXFIFOSIZE		GENMASK(10, 6)
+#define XGMAC_HWFEAT_RXFIFOSIZE		GENMASK(4, 0)
+#define XGMAC_HW_FEATURE2		0x00000124
+#define XGMAC_HWFEAT_PPSOUTNUM		GENMASK(26, 24)
+#define XGMAC_HWFEAT_TXCHCNT		GENMASK(21, 18)
+#define XGMAC_HWFEAT_RXCHCNT		GENMASK(15, 12)
+#define XGMAC_HWFEAT_TXQCNT		GENMASK(9, 6)
+#define XGMAC_HWFEAT_RXQCNT		GENMASK(3, 0)
+#define XGMAC_MDIO_ADDR			0x00000200
+#define XGMAC_MDIO_DATA			0x00000204
+#define XGMAC_ADDR0_HIGH		0x00000300
+#define XGMAC_AE			BIT(31)
+#define XGMAC_DCS			GENMASK(19, 16)
+#define XGMAC_DCS_SHIFT			16
+#define XGMAC_ADDR0_LOW			0x00000304
+#define XGMAC_ARP_ADDR			0x00000c10
+#define XGMAC_TIMESTAMP_STATUS		0x00000d20
+#define XGMAC_TXTSC			BIT(15)
+#define XGMAC_TXTIMESTAMP_NSEC		0x00000d30
+#define XGMAC_TXTSSTSLO			GENMASK(30, 0)
+#define XGMAC_TXTIMESTAMP_SEC		0x00000d34
+
+/* MTL Registers */
+#define XGMAC_MTL_OPMODE		0x00001000
+#define XGMAC_ETSALG			GENMASK(6, 5)
+#define XGMAC_WRR			(0x0 << 5)
+#define XGMAC_WFQ			(0x1 << 5)
+#define XGMAC_DWRR			(0x2 << 5)
+#define XGMAC_RAA			BIT(2)
+#define XGMAC_MTL_INT_STATUS		0x00001020
+#define XGMAC_MTL_RXQ_DMA_MAP0		0x00001030
+#define XGMAC_MTL_RXQ_DMA_MAP1		0x00001034
+#define XGMAC_QxMDMACH(x)		GENMASK((x) * 8 + 3, (x) * 8)
+#define XGMAC_QxMDMACH_SHIFT(x)		((x) * 8)
+#define XGMAC_MTL_TXQ_OPMODE(x)		(0x00001100 + (0x80 * (x)))
+#define XGMAC_TQS			GENMASK(25, 16)
+#define XGMAC_TQS_SHIFT			16
+#define XGMAC_TTC			GENMASK(6, 4)
+#define XGMAC_TTC_SHIFT			4
+#define XGMAC_TXQEN			GENMASK(3, 2)
+#define XGMAC_TXQEN_SHIFT		2
+#define XGMAC_TSF			BIT(1)
+#define XGMAC_MTL_RXQ_OPMODE(x)		(0x00001140 + (0x80 * (x)))
+#define XGMAC_RQS			GENMASK(25, 16)
+#define XGMAC_RQS_SHIFT			16
+#define XGMAC_EHFC			BIT(7)
+#define XGMAC_RSF			BIT(5)
+#define XGMAC_RTC			GENMASK(1, 0)
+#define XGMAC_RTC_SHIFT			0
+#define XGMAC_MTL_QINTEN(x)		(0x00001170 + (0x80 * (x)))
+#define XGMAC_RXOIE			BIT(16)
+#define XGMAC_MTL_QINT_STATUS(x)	(0x00001174 + (0x80 * (x)))
+#define XGMAC_RXOVFIS			BIT(16)
+#define XGMAC_ABPSIS			BIT(1)
+#define XGMAC_TXUNFIS			BIT(0)
+
+#endif /* __STMMAC_DWXGMAC2_H__ */
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c
new file mode 100644
index 000000000000..d182f82f7b58
--- /dev/null
+++ b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c
@@ -0,0 +1,371 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MIT)
+/*
+ * Copyright (c) 2018 Synopsys, Inc. and/or its affiliates.
+ * stmmac XGMAC support.
+ */
+
+#include "stmmac.h"
+#include "dwxgmac2.h"
+
+static void dwxgmac2_core_init(struct mac_device_info *hw,
+			       struct net_device *dev)
+{
+	void __iomem *ioaddr = hw->pcsr;
+	int mtu = dev->mtu;
+	u32 tx, rx;
+
+	tx = readl(ioaddr + XGMAC_TX_CONFIG);
+	rx = readl(ioaddr + XGMAC_RX_CONFIG);
+
+	tx |= XGMAC_CORE_INIT_TX;
+	rx |= XGMAC_CORE_INIT_RX;
+
+	if (mtu >= 9000) {
+		rx |= XGMAC_CONFIG_GPSLCE;
+		rx |= XGMAC_JUMBO_LEN << XGMAC_CONFIG_GPSL_SHIFT;
+		rx |= XGMAC_CONFIG_WD;
+	} else if (mtu > 2000) {
+		rx |= XGMAC_CONFIG_JE;
+	} else if (mtu > 1500) {
+		rx |= XGMAC_CONFIG_S2KP;
+	}
+
+	if (hw->ps) {
+		tx |= XGMAC_CONFIG_TE;
+		tx &= ~hw->link.speed_mask;
+
+		switch (hw->ps) {
+		case SPEED_10000:
+			tx |= hw->link.speed10000;
+			break;
+		case SPEED_2500:
+			tx |= hw->link.speed2500;
+			break;
+		case SPEED_1000:
+		default:
+			tx |= hw->link.speed1000;
+			break;
+		}
+	}
+
+	writel(tx, ioaddr + XGMAC_TX_CONFIG);
+	writel(rx, ioaddr + XGMAC_RX_CONFIG);
+	writel(XGMAC_INT_DEFAULT_EN, ioaddr + XGMAC_INT_EN);
+}
+
+static void dwxgmac2_set_mac(void __iomem *ioaddr, bool enable)
+{
+	u32 tx = readl(ioaddr + XGMAC_TX_CONFIG);
+	u32 rx = readl(ioaddr + XGMAC_RX_CONFIG);
+
+	if (enable) {
+		tx |= XGMAC_CONFIG_TE;
+		rx |= XGMAC_CONFIG_RE;
+	} else {
+		tx &= ~XGMAC_CONFIG_TE;
+		rx &= ~XGMAC_CONFIG_RE;
+	}
+
+	writel(tx, ioaddr + XGMAC_TX_CONFIG);
+	writel(rx, ioaddr + XGMAC_RX_CONFIG);
+}
+
+static int dwxgmac2_rx_ipc(struct mac_device_info *hw)
+{
+	void __iomem *ioaddr = hw->pcsr;
+	u32 value;
+
+	value = readl(ioaddr + XGMAC_RX_CONFIG);
+	if (hw->rx_csum)
+		value |= XGMAC_CONFIG_IPC;
+	else
+		value &= ~XGMAC_CONFIG_IPC;
+	writel(value, ioaddr + XGMAC_RX_CONFIG);
+
+	return !!(readl(ioaddr + XGMAC_RX_CONFIG) & XGMAC_CONFIG_IPC);
+}
+
+static void dwxgmac2_rx_queue_enable(struct mac_device_info *hw, u8 mode,
+				     u32 queue)
+{
+	void __iomem *ioaddr = hw->pcsr;
+	u32 value;
+
+	value = readl(ioaddr + XGMAC_RXQ_CTRL0) & ~XGMAC_RXQEN(queue);
+	if (mode == MTL_QUEUE_AVB)
+		value |= 0x1 << XGMAC_RXQEN_SHIFT(queue);
+	else if (mode == MTL_QUEUE_DCB)
+		value |= 0x2 << XGMAC_RXQEN_SHIFT(queue);
+	writel(value, ioaddr + XGMAC_RXQ_CTRL0);
+}
+
+static void dwxgmac2_rx_queue_prio(struct mac_device_info *hw, u32 prio,
+				   u32 queue)
+{
+	void __iomem *ioaddr = hw->pcsr;
+	u32 value, reg;
+
+	reg = (queue < 4) ? XGMAC_RXQ_CTRL2 : XGMAC_RXQ_CTRL3;
+
+	value = readl(ioaddr + reg);
+	value &= ~XGMAC_PSRQ(queue);
+	value |= (prio << XGMAC_PSRQ_SHIFT(queue)) & XGMAC_PSRQ(queue);
+
+	writel(value, ioaddr + reg);
+}
+
+static void dwxgmac2_prog_mtl_rx_algorithms(struct mac_device_info *hw,
+					    u32 rx_alg)
+{
+	void __iomem *ioaddr = hw->pcsr;
+	u32 value;
+
+	value = readl(ioaddr + XGMAC_MTL_OPMODE);
+	value &= ~XGMAC_RAA;
+
+	switch (rx_alg) {
+	case MTL_RX_ALGORITHM_SP:
+		break;
+	case MTL_RX_ALGORITHM_WSP:
+		value |= XGMAC_RAA;
+		break;
+	default:
+		break;
+	}
+
+	writel(value, ioaddr + XGMAC_MTL_OPMODE);
+}
+
+static void dwxgmac2_prog_mtl_tx_algorithms(struct mac_device_info *hw,
+					    u32 tx_alg)
+{
+	void __iomem *ioaddr = hw->pcsr;
+	u32 value;
+
+	value = readl(ioaddr + XGMAC_MTL_OPMODE);
+	value &= ~XGMAC_ETSALG;
+
+	switch (tx_alg) {
+	case MTL_TX_ALGORITHM_WRR:
+		value |= XGMAC_WRR;
+		break;
+	case MTL_TX_ALGORITHM_WFQ:
+		value |= XGMAC_WFQ;
+		break;
+	case MTL_TX_ALGORITHM_DWRR:
+		value |= XGMAC_DWRR;
+		break;
+	default:
+		break;
+	}
+
+	writel(value, ioaddr + XGMAC_MTL_OPMODE);
+}
+
+static void dwxgmac2_map_mtl_to_dma(struct mac_device_info *hw, u32 queue,
+				    u32 chan)
+{
+	void __iomem *ioaddr = hw->pcsr;
+	u32 value, reg;
+
+	reg = (queue < 4) ? XGMAC_MTL_RXQ_DMA_MAP0 : XGMAC_MTL_RXQ_DMA_MAP1;
+
+	value = readl(ioaddr + reg);
+	value &= ~XGMAC_QxMDMACH(queue);
+	value |= (chan << XGMAC_QxMDMACH_SHIFT(queue)) & XGMAC_QxMDMACH(queue);
+
+	writel(value, ioaddr + reg);
+}
+
+static int dwxgmac2_host_irq_status(struct mac_device_info *hw,
+				    struct stmmac_extra_stats *x)
+{
+	void __iomem *ioaddr = hw->pcsr;
+	u32 stat, en;
+
+	en = readl(ioaddr + XGMAC_INT_EN);
+	stat = readl(ioaddr + XGMAC_INT_STATUS);
+
+	stat &= en;
+
+	if (stat & XGMAC_PMTIS) {
+		x->irq_receive_pmt_irq_n++;
+		readl(ioaddr + XGMAC_PMT);
+	}
+
+	return 0;
+}
+
+static int dwxgmac2_host_mtl_irq_status(struct mac_device_info *hw, u32 chan)
+{
+	void __iomem *ioaddr = hw->pcsr;
+	int ret = 0;
+	u32 status;
+
+	status = readl(ioaddr + XGMAC_MTL_INT_STATUS);
+	if (status & BIT(chan)) {
+		u32 chan_status = readl(ioaddr + XGMAC_MTL_QINT_STATUS(chan));
+
+		if (chan_status & XGMAC_RXOVFIS)
+			ret |= CORE_IRQ_MTL_RX_OVERFLOW;
+
+		writel(~0x0, ioaddr + XGMAC_MTL_QINT_STATUS(chan));
+	}
+
+	return ret;
+}
+
+static void dwxgmac2_flow_ctrl(struct mac_device_info *hw, unsigned int duplex,
+			       unsigned int fc, unsigned int pause_time,
+			       u32 tx_cnt)
+{
+	void __iomem *ioaddr = hw->pcsr;
+	u32 i;
+
+	if (fc & FLOW_RX)
+		writel(XGMAC_RFE, ioaddr + XGMAC_RX_FLOW_CTRL);
+	if (fc & FLOW_TX) {
+		for (i = 0; i < tx_cnt; i++) {
+			u32 value = XGMAC_TFE;
+
+			if (duplex)
+				value |= pause_time << XGMAC_PT_SHIFT;
+
+			writel(value, ioaddr + XGMAC_Qx_TX_FLOW_CTRL(i));
+		}
+	}
+}
+
+static void dwxgmac2_pmt(struct mac_device_info *hw, unsigned long mode)
+{
+	void __iomem *ioaddr = hw->pcsr;
+	u32 val = 0x0;
+
+	if (mode & WAKE_MAGIC)
+		val |= XGMAC_PWRDWN | XGMAC_MGKPKTEN;
+	if (mode & WAKE_UCAST)
+		val |= XGMAC_PWRDWN | XGMAC_GLBLUCAST | XGMAC_RWKPKTEN;
+	if (val) {
+		u32 cfg = readl(ioaddr + XGMAC_RX_CONFIG);
+		cfg |= XGMAC_CONFIG_RE;
+		writel(cfg, ioaddr + XGMAC_RX_CONFIG);
+	}
+
+	writel(val, ioaddr + XGMAC_PMT);
+}
+
+static void dwxgmac2_set_umac_addr(struct mac_device_info *hw,
+				   unsigned char *addr, unsigned int reg_n)
+{
+	void __iomem *ioaddr = hw->pcsr;
+	u32 value;
+
+	value = (addr[5] << 8) | addr[4];
+	writel(value | XGMAC_AE, ioaddr + XGMAC_ADDR0_HIGH);
+
+	value = (addr[3] << 24) | (addr[2] << 16) | (addr[1] << 8) | addr[0];
+	writel(value, ioaddr + XGMAC_ADDR0_LOW);
+}
+
+static void dwxgmac2_get_umac_addr(struct mac_device_info *hw,
+				   unsigned char *addr, unsigned int reg_n)
+{
+	void __iomem *ioaddr = hw->pcsr;
+	u32 hi_addr, lo_addr;
+
+	/* Read the MAC address from the hardware */
+	hi_addr = readl(ioaddr + XGMAC_ADDR0_HIGH);
+	lo_addr = readl(ioaddr + XGMAC_ADDR0_LOW);
+
+	/* Extract the MAC address from the high and low words */
+	addr[0] = lo_addr & 0xff;
+	addr[1] = (lo_addr >> 8) & 0xff;
+	addr[2] = (lo_addr >> 16) & 0xff;
+	addr[3] = (lo_addr >> 24) & 0xff;
+	addr[4] = hi_addr & 0xff;
+	addr[5] = (hi_addr >> 8) & 0xff;
+}
+
+static void dwxgmac2_set_filter(struct mac_device_info *hw,
+				struct net_device *dev)
+{
+	void __iomem *ioaddr = (void __iomem *)dev->base_addr;
+	u32 value = XGMAC_FILTER_RA;
+
+	if (dev->flags & IFF_PROMISC) {
+		value |= XGMAC_FILTER_PR;
+	} else if ((dev->flags & IFF_ALLMULTI) ||
+		   (netdev_mc_count(dev) > HASH_TABLE_SIZE)) {
+		value |= XGMAC_FILTER_PM;
+		writel(~0x0, ioaddr + XGMAC_HASH_TABLE(0));
+		writel(~0x0, ioaddr + XGMAC_HASH_TABLE(1));
+	}
+
+	writel(value, ioaddr + XGMAC_PACKET_FILTER);
+}
+
+const struct stmmac_ops dwxgmac210_ops = {
+	.core_init = dwxgmac2_core_init,
+	.set_mac = dwxgmac2_set_mac,
+	.rx_ipc = dwxgmac2_rx_ipc,
+	.rx_queue_enable = dwxgmac2_rx_queue_enable,
+	.rx_queue_prio = dwxgmac2_rx_queue_prio,
+	.tx_queue_prio = NULL,
+	.rx_queue_routing = NULL,
+	.prog_mtl_rx_algorithms = dwxgmac2_prog_mtl_rx_algorithms,
+	.prog_mtl_tx_algorithms = dwxgmac2_prog_mtl_tx_algorithms,
+	.set_mtl_tx_queue_weight = NULL,
+	.map_mtl_to_dma = dwxgmac2_map_mtl_to_dma,
+	.config_cbs = NULL,
+	.dump_regs = NULL,
+	.host_irq_status = dwxgmac2_host_irq_status,
+	.host_mtl_irq_status = dwxgmac2_host_mtl_irq_status,
+	.flow_ctrl = dwxgmac2_flow_ctrl,
+	.pmt = dwxgmac2_pmt,
+	.set_umac_addr = dwxgmac2_set_umac_addr,
+	.get_umac_addr = dwxgmac2_get_umac_addr,
+	.set_eee_mode = NULL,
+	.reset_eee_mode = NULL,
+	.set_eee_timer = NULL,
+	.set_eee_pls = NULL,
+	.pcs_ctrl_ane = NULL,
+	.pcs_rane = NULL,
+	.pcs_get_adv_lp = NULL,
+	.debug = NULL,
+	.set_filter = dwxgmac2_set_filter,
+};
+
+int dwxgmac2_setup(struct stmmac_priv *priv)
+{
+	struct mac_device_info *mac = priv->hw;
+
+	dev_info(priv->device, "\tXGMAC2\n");
+
+	priv->dev->priv_flags |= IFF_UNICAST_FLT;
+	mac->pcsr = priv->ioaddr;
+	mac->multicast_filter_bins = priv->plat->multicast_filter_bins;
+	mac->unicast_filter_entries = priv->plat->unicast_filter_entries;
+	mac->mcast_bits_log2 = 0;
+
+	if (mac->multicast_filter_bins)
+		mac->mcast_bits_log2 = ilog2(mac->multicast_filter_bins);
+
+	mac->link.duplex = 0;
+	mac->link.speed10 = 0;
+	mac->link.speed100 = 0;
+	mac->link.speed1000 = XGMAC_CONFIG_SS_1000;
+	mac->link.speed2500 = XGMAC_CONFIG_SS_2500;
+	mac->link.speed10000 = XGMAC_CONFIG_SS_10000;
+	mac->link.speed_mask = XGMAC_CONFIG_SS_MASK;
+
+	mac->mii.addr = XGMAC_MDIO_ADDR;
+	mac->mii.data = XGMAC_MDIO_DATA;
+	mac->mii.addr_shift = 16;
+	mac->mii.addr_mask = GENMASK(20, 16);
+	mac->mii.reg_shift = 0;
+	mac->mii.reg_mask = GENMASK(15, 0);
+	mac->mii.clk_csr_shift = 19;
+	mac->mii.clk_csr_mask = GENMASK(21, 19);
+
+	return 0;
+}
diff --git a/drivers/net/ethernet/stmicro/stmmac/hwif.c b/drivers/net/ethernet/stmicro/stmmac/hwif.c
index 24f5ff175aa4..4fa46f064720 100644
--- a/drivers/net/ethernet/stmicro/stmmac/hwif.c
+++ b/drivers/net/ethernet/stmicro/stmmac/hwif.c
@@ -198,11 +198,11 @@ static const struct stmmac_hwif_entry {
 		},
 		.desc = NULL,
 		.dma = NULL,
-		.mac = NULL,
+		.mac = &dwxgmac210_ops,
 		.hwtimestamp = NULL,
 		.mode = NULL,
 		.tc = NULL,
-		.setup = NULL,
+		.setup = dwxgmac2_setup,
 		.quirks = NULL,
 	},
 };
diff --git a/drivers/net/ethernet/stmicro/stmmac/hwif.h b/drivers/net/ethernet/stmicro/stmmac/hwif.h
index 79911eefc2a7..ff0fd6978260 100644
--- a/drivers/net/ethernet/stmicro/stmmac/hwif.h
+++ b/drivers/net/ethernet/stmicro/stmmac/hwif.h
@@ -479,6 +479,7 @@ extern const struct stmmac_ops dwmac410_ops;
 extern const struct stmmac_dma_ops dwmac410_dma_ops;
 extern const struct stmmac_ops dwmac510_ops;
 extern const struct stmmac_tc_ops dwmac510_tc_ops;
+extern const struct stmmac_ops dwxgmac210_ops;
 
 #define GMAC_VERSION		0x00000020	/* GMAC CORE Version */
 #define GMAC4_VERSION		0x00000110	/* GMAC4+ CORE Version */
-- 
2.7.4

^ permalink raw reply related


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