Netdev List
 help / color / mirror / Atom feed
* Re: [PATCH v2 2/5] dpaa_eth: move of_phy_connect() to the eth driver
From: Andrew Lunn @ 2017-10-15 18:33 UTC (permalink / raw)
  To: Madalin Bucur
  Cc: netdev, davem, f.fainelli, vivien.didelot, junote, linux-kernel
In-Reply-To: <1507906212-10076-3-git-send-email-madalin.bucur@nxp.com>

On Fri, Oct 13, 2017 at 05:50:09PM +0300, Madalin Bucur wrote:
> Signed-off-by: Madalin Bucur <madalin.bucur@nxp.com>
> ---
>  drivers/net/ethernet/freescale/dpaa/dpaa_eth.c | 48 +++++++++++--
>  drivers/net/ethernet/freescale/fman/mac.c      | 97 ++++++--------------------
>  drivers/net/ethernet/freescale/fman/mac.h      |  5 +-
>  3 files changed, 66 insertions(+), 84 deletions(-)
> 
> diff --git a/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c b/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c
> index 4225806..7cf61d6 100644
> --- a/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c
> +++ b/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c
> @@ -2435,6 +2435,48 @@ static void dpaa_eth_napi_disable(struct dpaa_priv *priv)
>  	}
>  }
>  
> +static void dpaa_adjust_link(struct net_device *net_dev)
> +{
> +	struct mac_device *mac_dev;
> +	struct dpaa_priv *priv;
> +
> +	priv = netdev_priv(net_dev);
> +	mac_dev = priv->mac_dev;
> +	mac_dev->adjust_link(mac_dev);
> +}
> +
> +static int dpaa_phy_init(struct net_device *net_dev)
> +{
> +	struct mac_device *mac_dev;
> +	struct phy_device *phy_dev;
> +	struct dpaa_priv *priv;
> +
> +	priv = netdev_priv(net_dev);
> +	mac_dev = priv->mac_dev;
> +
> +	phy_dev = of_phy_connect(net_dev, mac_dev->phy_node,
> +				 &dpaa_adjust_link, 0,
> +				 mac_dev->phy_if);
> +	if (!phy_dev) {
> +		netif_err(priv, ifup, net_dev, "init_phy() failed\n");
> +		return -ENODEV;
> +	}
> +
> +	/* Remove any features not supported by the controller */
> +	phy_dev->supported &= mac_dev->if_support;
> +
> +	/* Enable the symmetric and asymmetric PAUSE frame advertisements,
> +	 * as most of the PHY drivers do not enable them by default.
> +	 */

Hi Madalin

This is just moving code around, so the patch is O.K. However, it
would be nice to have a followup patch. This comment is wrong. The phy
driver should never enable symmetric and asymmetric PAUSE frames. The
MAC needs to, because only the MAC knows if the MAC supports pause
frames.

	Andrew

^ permalink raw reply

* [PATCH] net: dccp: mark expected switch fall-throughs
From: Gustavo A. R. Silva @ 2017-10-15 18:22 UTC (permalink / raw)
  To: Gerrit Renker, David S. Miller
  Cc: dccp, netdev, linux-kernel, Gustavo A. R. Silva

In preparation to enabling -Wimplicit-fallthrough, mark switch cases
where we are expecting to fall through.

Notice that for options.c file, I placed the "fall through" comment
on its own line, which is what GCC is expecting to find.

Signed-off-by: Gustavo A. R. Silva <garsilva@embeddedor.com>
---
This code was tested by compilation only (GCC 7.2.0 was used).
Please, verify if the actual intention of the code is to fall through.

 net/dccp/input.c   | 1 +
 net/dccp/options.c | 2 +-
 2 files changed, 2 insertions(+), 1 deletion(-)

diff --git a/net/dccp/input.c b/net/dccp/input.c
index fa6be97..d28d46b 100644
--- a/net/dccp/input.c
+++ b/net/dccp/input.c
@@ -534,6 +534,7 @@ static int dccp_rcv_respond_partopen_state_process(struct sock *sk,
 	case DCCP_PKT_DATA:
 		if (sk->sk_state == DCCP_RESPOND)
 			break;
+		/* fall through */
 	case DCCP_PKT_DATAACK:
 	case DCCP_PKT_ACK:
 		/*
diff --git a/net/dccp/options.c b/net/dccp/options.c
index 51cdfc3..4e40db0 100644
--- a/net/dccp/options.c
+++ b/net/dccp/options.c
@@ -227,8 +227,8 @@ int dccp_parse_options(struct sock *sk, struct dccp_request_sock *dreq,
 			 * Ack vectors are processed by the TX CCID if it is
 			 * interested. The RX CCID need not parse Ack Vectors,
 			 * since it is only interested in clearing old state.
-			 * Fall through.
 			 */
+			/* fall through */
 		case DCCPO_MIN_TX_CCID_SPECIFIC ... DCCPO_MAX_TX_CCID_SPECIFIC:
 			if (ccid_hc_tx_parse_options(dp->dccps_hc_tx_ccid, sk,
 						     pkt_type, opt, value, len))
-- 
2.7.4

^ permalink raw reply related

* Re: [PATCH net-next] ipv6: only update __use and lastusetime once per jiffy at most
From: Martin KaFai Lau @ 2017-10-15 18:19 UTC (permalink / raw)
  To: Eric Dumazet; +Cc: Wei Wang, David Miller, netdev, Paolo Abeni
In-Reply-To: <CANn89i+09PB1=J8mXO495iOK4oe4hsnRF=YsOQQJAsnw5ydeoA@mail.gmail.com>

On Sat, Oct 14, 2017 at 12:26:28AM +0000, Eric Dumazet wrote:
> On Fri, Oct 13, 2017 at 5:09 PM, Martin KaFai Lau <kafai@fb.com> wrote:
> > On Fri, Oct 13, 2017 at 10:08:07PM +0000, Wei Wang wrote:
> >> From: Wei Wang <weiwan@google.com>
> >>
> >> In order to not dirty the cacheline too often, we try to only update
> >> dst->__use and dst->lastusetime at most once per jiffy.
> >
> >
> >> As dst->lastusetime is only used by ipv6 garbage collector, it should
> >> be good enough time resolution.
> > Make sense.
> >
> >> And __use is only used in ipv6_route_seq_show() to show how many times a
> >> dst has been used. And as __use is not atomic_t right now, it does not
> >> show the precise number of usage times anyway. So we think it should be
> >> OK to only update it at most once per jiffy.
> > If __use is only bumped HZ number of times per second and we can do ~3Mpps now,
> > would __use be way off?
> 
> It is not used in the kernel, and is not even reported by user space
> (iproute2) currently.
> 
> With the percpu stuff, we never did the sum anyway.
The pcpu_rt currently does not track __use.

> 
> I believe we should be fine by being very lazy on this field.
> 
> If really someones complain, we will see, but insuring ~one update per
> HZ seems fine.
Fair point.  Make sense.
We currently also don't find the ipv6_route proc-file very useful
other than debugging purpose.

^ permalink raw reply

* [PATCH] xen/9pfs: mark expected switch fall-through in xen_9pfs_front_changed
From: Gustavo A. R. Silva @ 2017-10-15 18:08 UTC (permalink / raw)
  To: Eric Van Hensbergen, Ron Minnich, Latchesar Ionkov,
	David S. Miller
  Cc: v9fs-developer, netdev, linux-kernel, Gustavo A. R. Silva

In preparation to enabling -Wimplicit-fallthrough, mark switch cases
where we are expecting to fall through.

Notice that in this particular case, I placed the "fall through" comment
on its own line, which is what GCC is expecting to find.

Signed-off-by: Gustavo A. R. Silva <garsilva@embeddedor.com>
---
This code was tested by compilation only (GCC 7.2.0 was used).

 net/9p/trans_xen.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/net/9p/trans_xen.c b/net/9p/trans_xen.c
index 6ad3e04..7ec5df9 100644
--- a/net/9p/trans_xen.c
+++ b/net/9p/trans_xen.c
@@ -510,7 +510,8 @@ static void xen_9pfs_front_changed(struct xenbus_device *dev,
 	case XenbusStateClosed:
 		if (dev->state == XenbusStateClosed)
 			break;
-		/* Missed the backend's CLOSING state -- fallthrough */
+		/* Missed the backend's CLOSING state */
+		/* fall through */
 	case XenbusStateClosing:
 		xenbus_frontend_closed(dev);
 		break;
-- 
2.7.4

^ permalink raw reply related

* Re: [PATCH net-next 00/10] korina cleanups/optimizations
From: Florian Fainelli @ 2017-10-15 17:36 UTC (permalink / raw)
  To: Roman Yeryomin, netdev
In-Reply-To: <c3a2f516dcceb7dee9ea4dde634b58ed@advem.lv>

On October 15, 2017 9:46:02 AM PDT, Roman Yeryomin <roman@advem.lv> wrote:
>On 2017-10-15 19:38, Florian Fainelli wrote:
>> On October 15, 2017 9:22:26 AM PDT, Roman Yeryomin <roman@advem.lv> 
>> wrote:
>>> TX optimizations have led to ~15% performance increase (35->40Mbps)
>>> in local tx usecase (tested with iperf v3.2).
>> 
>> Could you avoid empty commit messages and write a paragraph or two
>for
>> each commit that explains what and why are you changing? The changes
>> look fine but they lack any explanation.
>
>I thought that short descriptions are already self explanatory and just
>
>didn't know what to write more.
>To me they are very obvious.

You can't assume what is obvious to you will be to the reviewers.

>Do you really want me to make up something more?

It's up to David as a maintainer to decide, but if this was up to me I would ask you to respin with a least a paragraph for each commit (except the version bump) why you did these changes.

>
>>> 
>>> Roman Yeryomin (10):
>>>  net: korina: optimize korina_send_packet logic
>>>  net: korina: reorder functions
>>>  net: korina: introduce and use interrupt disable/enable helpers
>>>  net: korina: optimize tx/rx interrupt handlers
>>>  net: korina: remove unused korina_private members
>>>  net: korina: optimize tx descriptor flags processing
>>>  net: korina: move tx to napi context
>>>  net: korina: optimize tx_full condition
>>>  net: korina: use dma api instead of dma_cache_* functions
>>>  net: korina: bump version
>>> 
>>> drivers/net/ethernet/korina.c | 503
>>> +++++++++++++++++-------------------------
>>> 1 file changed, 204 insertions(+), 299 deletions(-)


-- 
Florian

^ permalink raw reply

* [PATCH] net: ceph: mark expected switch fall-throughs
From: Gustavo A. R. Silva @ 2017-10-15 17:55 UTC (permalink / raw)
  To: Ilya Dryomov, Yan, Zheng, Sage Weil, David S. Miller
  Cc: ceph-devel, netdev, linux-kernel, Gustavo A. R. Silva

In preparation to enabling -Wimplicit-fallthrough, mark switch cases
where we are expecting to fall through.

Signed-off-by: Gustavo A. R. Silva <garsilva@embeddedor.com>
---
 net/ceph/ceph_hash.c  | 12 +++++++++++-
 net/ceph/messenger.c  |  1 +
 net/ceph/mon_client.c |  1 +
 3 files changed, 13 insertions(+), 1 deletion(-)

diff --git a/net/ceph/ceph_hash.c b/net/ceph/ceph_hash.c
index 67bb1f1..9a5850f2 100644
--- a/net/ceph/ceph_hash.c
+++ b/net/ceph/ceph_hash.c
@@ -47,28 +47,38 @@ unsigned int ceph_str_hash_rjenkins(const char *str, unsigned int length)
 
 	/* handle the last 11 bytes */
 	c = c + length;
-	switch (len) {            /* all the case statements fall through */
+	switch (len) {
 	case 11:
 		c = c + ((__u32)k[10] << 24);
+		/* fall through */
 	case 10:
 		c = c + ((__u32)k[9] << 16);
+		/* fall through */
 	case 9:
 		c = c + ((__u32)k[8] << 8);
 		/* the first byte of c is reserved for the length */
+		/* fall through */
 	case 8:
 		b = b + ((__u32)k[7] << 24);
+		/* fall through */
 	case 7:
 		b = b + ((__u32)k[6] << 16);
+		/* fall through */
 	case 6:
 		b = b + ((__u32)k[5] << 8);
+		/* fall through */
 	case 5:
 		b = b + k[4];
+		/* fall through */
 	case 4:
 		a = a + ((__u32)k[3] << 24);
+		/* fall through */
 	case 3:
 		a = a + ((__u32)k[2] << 16);
+		/* fall through */
 	case 2:
 		a = a + ((__u32)k[1] << 8);
+		/* fall through */
 	case 1:
 		a = a + k[0];
 		/* case 0: nothing left to add */
diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c
index a67298c..73dac9d 100644
--- a/net/ceph/messenger.c
+++ b/net/ceph/messenger.c
@@ -429,6 +429,7 @@ static void ceph_sock_state_change(struct sock *sk)
 	switch (sk->sk_state) {
 	case TCP_CLOSE:
 		dout("%s TCP_CLOSE\n", __func__);
+		/* fall through */
 	case TCP_CLOSE_WAIT:
 		dout("%s TCP_CLOSE_WAIT\n", __func__);
 		con_sock_state_closing(con);
diff --git a/net/ceph/mon_client.c b/net/ceph/mon_client.c
index 63edc6e..b97c047 100644
--- a/net/ceph/mon_client.c
+++ b/net/ceph/mon_client.c
@@ -1281,6 +1281,7 @@ static struct ceph_msg *mon_alloc_msg(struct ceph_connection *con,
 		 * request had a non-zero tid.  Workaround this weirdness
 		 * by falling through to the allocate case.
 		 */
+		/* fall through */
 	case CEPH_MSG_MON_MAP:
 	case CEPH_MSG_MDS_MAP:
 	case CEPH_MSG_OSD_MAP:
-- 
2.7.4

^ permalink raw reply related

* Re: [RFC PATCH v2 5/5] wave: Added TCP Wave
From: Eric Dumazet @ 2017-10-15 17:43 UTC (permalink / raw)
  To: Natale Patriciello
  Cc: David S . Miller, netdev, Ahmed Said, Francesco Zampognaro,
	Cesare Roseti
In-Reply-To: <20171014114714.3694-6-natale.patriciello@gmail.com>

On Sat, 2017-10-14 at 13:47 +0200, Natale Patriciello wrote:
> TCP Wave (TCPW) replaces the window-based transmission paradigm of the
> standard TCP with a burst-based transmission, the ACK-clock scheduling
> with a self-managed timer and the RTT-based congestion control loop
> with an Ack-based Capacity and Congestion Estimation (ACCE) module. In
> non-technical words, it sends data down the stack when its internal
> timer expires, and the timing of the received ACKs contribute to
> updating this timer regularly.
> 


> It is the first TCP congestion control that uses the timing constraint
> developed in the Linux kernel.

You seem to have missed BBR.



This is against what we have worked in the last years, preventing bursts
in the first place.

If this series is to address WIFI peculiarities with TSQ (this is a well
known problem, still waiting for a fix), I would rather not add all this
code in TCP and find better alternatives.

Since you do not provide information and testing results, there is no
chance we accept such patches.

Your work seems to be a variation of TSQ, and a very complex one.

^ permalink raw reply

* Re: [RFC PATCH v2 3/5] tcp: added get_segs_per_round
From: Eric Dumazet @ 2017-10-15 17:32 UTC (permalink / raw)
  To: Natale Patriciello
  Cc: David S . Miller, netdev, Ahmed Said, Francesco Zampognaro,
	Cesare Roseti
In-Reply-To: <20171014114714.3694-4-natale.patriciello@gmail.com>

On Sat, 2017-10-14 at 13:47 +0200, Natale Patriciello wrote:
> Usually, the pacing time is provided per-segment. In some occasion, this
> time refers to the time between a group of segments. With this commit, add
> the possibility for the congestion control module to tell the TCP socket
> how many segments can be sent out before pausing and setting a pacing
> timer.
> 
> Signed-off-by: Natale Patriciello <natale.patriciello@gmail.com>
> ---
>  include/net/tcp.h     |  2 ++
>  net/ipv4/tcp_output.c | 13 +++++++++----
>  2 files changed, 11 insertions(+), 4 deletions(-)
> 
> diff --git a/include/net/tcp.h b/include/net/tcp.h
> index e817f0669d0e..3561eca5a61f 100644
> --- a/include/net/tcp.h
> +++ b/include/net/tcp.h
> @@ -1019,6 +1019,8 @@ struct tcp_congestion_ops {
>  	u64 (*get_pacing_time)(struct sock *sk);
>  	/* the pacing timer is expired (optional) */
>  	void (*pacing_timer_expired)(struct sock *sk);
> +	/* get the # segs to send out when the timer expires (optional) */
> +	u32 (*get_segs_per_round)(struct sock *sk);
>  
>  	char 		name[TCP_CA_NAME_MAX];
>  	struct module 	*owner;
> diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c
> index 25b4cf0802f2..e37941e4328b 100644
> --- a/net/ipv4/tcp_output.c
> +++ b/net/ipv4/tcp_output.c
> @@ -2249,6 +2249,7 @@ static bool tcp_write_xmit(struct sock *sk, unsigned int mss_now, int nonagle,
>  	int result;
>  	bool is_cwnd_limited = false, is_rwnd_limited = false;
>  	u32 max_segs;
> +	u32 pacing_allowed_segs = 0;
>  
>  	sent_pkts = 0;
>  
> @@ -2265,14 +2266,18 @@ static bool tcp_write_xmit(struct sock *sk, unsigned int mss_now, int nonagle,
>  	max_segs = tcp_tso_segs(sk, mss_now);
>  	tcp_mstamp_refresh(tp);
>  
> -	if (!tcp_pacing_timer_check(sk) &&
> -	    ca_ops && ca_ops->pacing_timer_expired)
> -		ca_ops->pacing_timer_expired(sk);
> +	if (!tcp_pacing_timer_check(sk)) {
> +		pacing_allowed_segs = 1;
> +		if (ca_ops && ca_ops->pacing_timer_expired)
> +			ca_ops->pacing_timer_expired(sk);
> +		if (ca_ops && ca_ops->get_segs_per_round)
> +			pacing_allowed_segs = ca_ops->get_segs_per_round(sk);
> +	}
>  
>  	while ((skb = tcp_send_head(sk))) {
>  		unsigned int limit;
>  
> -		if (tcp_pacing_check(sk))
> +		if (sent_pkts >= pacing_allowed_segs)
>  			break;
>  

So, if pacing_allowed_segs == 0, we break immediately of the loop ????

Are you sure you have tested this patch with normal CC like CUBIC and
BBR ?

^ permalink raw reply

* Re: [RFC PATCH v2 2/5] tcp: implemented pacing_expired
From: Eric Dumazet @ 2017-10-15 17:30 UTC (permalink / raw)
  To: Natale Patriciello
  Cc: David S . Miller, netdev, Ahmed Said, Francesco Zampognaro,
	Cesare Roseti
In-Reply-To: <20171014114714.3694-3-natale.patriciello@gmail.com>

On Sat, 2017-10-14 at 13:47 +0200, Natale Patriciello wrote:
> Inform the congestion control that the pacing timer, previously set,
> has expired. The commit does not consider situations in which another
> kind of timer has expired (e.g., a tail loss probe, a retransmission
> timer...)
> 
> Signed-off-by: Natale Patriciello <natale.patriciello@gmail.com>
> ---
>  include/net/tcp.h     | 2 ++
>  net/ipv4/tcp_output.c | 6 ++++++
>  2 files changed, 8 insertions(+)
> 
> diff --git a/include/net/tcp.h b/include/net/tcp.h
> index 42c7aa96c4cf..e817f0669d0e 100644
> --- a/include/net/tcp.h
> +++ b/include/net/tcp.h
> @@ -1017,6 +1017,8 @@ struct tcp_congestion_ops {
>  			   union tcp_cc_info *info);
>  	/* get the expiration time for the pacing timer (optional) */
>  	u64 (*get_pacing_time)(struct sock *sk);
> +	/* the pacing timer is expired (optional) */
> +	void (*pacing_timer_expired)(struct sock *sk);
>  
>  	char 		name[TCP_CA_NAME_MAX];
>  	struct module 	*owner;
> diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c
> index ec5977156c26..25b4cf0802f2 100644
> --- a/net/ipv4/tcp_output.c
> +++ b/net/ipv4/tcp_output.c
> @@ -2241,6 +2241,7 @@ void tcp_chrono_stop(struct sock *sk, const enum tcp_chrono type)
>  static bool tcp_write_xmit(struct sock *sk, unsigned int mss_now, int nonagle,
>  			   int push_one, gfp_t gfp)
>  {
> +	const struct tcp_congestion_ops *ca_ops = inet_csk(sk)->icsk_ca_ops;
>  	struct tcp_sock *tp = tcp_sk(sk);
>  	struct sk_buff *skb;
>  	unsigned int tso_segs, sent_pkts;
> @@ -2263,6 +2264,11 @@ static bool tcp_write_xmit(struct sock *sk, unsigned int mss_now, int nonagle,
>  
>  	max_segs = tcp_tso_segs(sk, mss_now);
>  	tcp_mstamp_refresh(tp);
> +
> +	if (!tcp_pacing_timer_check(sk) &&
> +	    ca_ops && ca_ops->pacing_timer_expired)
> +		ca_ops->pacing_timer_expired(sk);
> +
>  

1) We do not want hrtimer_active() being called for each
tcp_write_xmit() ... :/

2) ca_ops can not be NULL.


->
       if (ca_ops->pacing_timer_expired && !tcp_pacing_timer_check(sk))
               ca_ops->pacing_timer_expired(sk);

^ permalink raw reply

* routing UAPI mismatch invalid state behavior?
From: Alexander Aring @ 2017-10-15 17:02 UTC (permalink / raw)
  To: netdev; +Cc: Jamal Hadi Salim

Hi,

I figure out some problem, easy to reproduce:

# setup dummy
$ modprobe dummy
$ ip link set dummy0 up

# issue
$ ip route replace default via 169.254.65.37 dev dummy0
RTNETLINK answers: Network is unreachable

so it will forbid me to do that, but:

$ ip route replace 169.254.65.37 dev dummy0
$ ip route replace default via 169.254.65.37 dev dummy0
$ ip route del 169.254.65.37 dev dummy0

allows me to do that. Is there now a invalid state in my routing table
or is it an expected behavior?

- Alex

^ permalink raw reply

* [PATCH] ipv6: addrconf: Use normal debugging style
From: Joe Perches @ 2017-10-15 16:49 UTC (permalink / raw)
  To: David S. Miller, Alexey Kuznetsov, Hideaki YOSHIFUJI
  Cc: David Ahern, netdev, linux-kernel
In-Reply-To: <1507935733-18950-3-git-send-email-dsahern@gmail.com>

Remove local ADBG macro and use netdev_dbg/pr_debug

Miscellanea:

o Remove unnecessary debug message after allocation failure as there
  already is a dump_stack() on the failure paths
o Leave the allocation failure message on snmp6_alloc_dev as there
  is one code path that does not do a dump_stack()

Signed-off-by: Joe Perches <joe@perches.com>
---

o This is on top of David Ahern's proposed patch
  net: ipv6: Make inet6addr_validator a blocking notifier

 net/ipv6/addrconf.c | 28 ++++++++--------------------
 1 file changed, 8 insertions(+), 20 deletions(-)

diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index 31ff12277bcf..c505e84dda1f 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -94,15 +94,6 @@
 #include <linux/seq_file.h>
 #include <linux/export.h>
 
-/* Set to 3 to get tracing... */
-#define ACONF_DEBUG 2
-
-#if ACONF_DEBUG >= 3
-#define ADBG(fmt, ...) printk(fmt, ##__VA_ARGS__)
-#else
-#define ADBG(fmt, ...) do { if (0) printk(fmt, ##__VA_ARGS__); } while (0)
-#endif
-
 #define	INFINITY_LIFE_TIME	0xFFFFFFFF
 
 #define IPV6_MAX_STRLEN \
@@ -409,9 +400,8 @@ static struct inet6_dev *ipv6_add_dev(struct net_device *dev)
 	dev_hold(dev);
 
 	if (snmp6_alloc_dev(ndev) < 0) {
-		ADBG(KERN_WARNING
-			"%s: cannot allocate memory for statistics; dev=%s.\n",
-			__func__, dev->name);
+		netdev_dbg(dev, "%s: cannot allocate memory for statistics\n",
+			   __func__);
 		neigh_parms_release(&nd_tbl, ndev->nd_parms);
 		dev_put(dev);
 		kfree(ndev);
@@ -419,9 +409,8 @@ static struct inet6_dev *ipv6_add_dev(struct net_device *dev)
 	}
 
 	if (snmp6_register_dev(ndev) < 0) {
-		ADBG(KERN_WARNING
-			"%s: cannot create /proc/net/dev_snmp6/%s\n",
-			__func__, dev->name);
+		netdev_dbg(dev, "%s: cannot create /proc/net/dev_snmp6/%s\n",
+			   __func__, dev->name);
 		goto err_release;
 	}
 
@@ -966,7 +955,7 @@ static int ipv6_add_addr_hash(struct net_device *dev, struct inet6_ifaddr *ifa)
 
 	/* Ignore adding duplicate addresses on an interface */
 	if (ipv6_chk_same_addr(dev_net(dev), &ifa->addr, dev)) {
-		ADBG("ipv6_add_addr: already assigned\n");
+		netdev_dbg(dev, "ipv6_add_addr: already assigned\n");
 		err = -EEXIST;
 		goto out;
 	}
@@ -1029,7 +1018,6 @@ ipv6_add_addr(struct inet6_dev *idev, const struct in6_addr *addr,
 
 	ifa = kzalloc(sizeof(*ifa), gfp_flags);
 	if (!ifa) {
-		ADBG("ipv6_add_addr: malloc failed\n");
 		err = -ENOBUFS;
 		goto out;
 	}
@@ -2575,7 +2563,7 @@ void addrconf_prefix_rcv(struct net_device *dev, u8 *opt, int len, bool sllao)
 	pinfo = (struct prefix_info *) opt;
 
 	if (len < sizeof(struct prefix_info)) {
-		ADBG("addrconf: prefix option too short\n");
+		netdev_dbg(dev, "addrconf: prefix option too short\n");
 		return;
 	}
 
@@ -4373,8 +4361,8 @@ static void addrconf_verify_rtnl(void)
 	if (time_before(next_sched, jiffies + ADDRCONF_TIMER_FUZZ_MAX))
 		next_sched = jiffies + ADDRCONF_TIMER_FUZZ_MAX;
 
-	ADBG(KERN_DEBUG "now = %lu, schedule = %lu, rounded schedule = %lu => %lu\n",
-	      now, next, next_sec, next_sched);
+	pr_debug("now = %lu, schedule = %lu, rounded schedule = %lu => %lu\n",
+		 now, next, next_sec, next_sched);
 	mod_delayed_work(addrconf_wq, &addr_chk_work, next_sched - now);
 	rcu_read_unlock_bh();
 }
-- 
2.10.0.rc2.1.g053435c

^ permalink raw reply related

* Re: [PATCH net-next 00/10] korina cleanups/optimizations
From: Roman Yeryomin @ 2017-10-15 16:46 UTC (permalink / raw)
  To: Florian Fainelli, netdev
In-Reply-To: <0FA80CB3-C0DC-4B30-B638-26B5D46AE69E@gmail.com>

On 2017-10-15 19:38, Florian Fainelli wrote:
> On October 15, 2017 9:22:26 AM PDT, Roman Yeryomin <roman@advem.lv> 
> wrote:
>> TX optimizations have led to ~15% performance increase (35->40Mbps)
>> in local tx usecase (tested with iperf v3.2).
> 
> Could you avoid empty commit messages and write a paragraph or two for
> each commit that explains what and why are you changing? The changes
> look fine but they lack any explanation.

I thought that short descriptions are already self explanatory and just 
didn't know what to write more.
To me they are very obvious.
Do you really want me to make up something more?

>> 
>> Roman Yeryomin (10):
>>  net: korina: optimize korina_send_packet logic
>>  net: korina: reorder functions
>>  net: korina: introduce and use interrupt disable/enable helpers
>>  net: korina: optimize tx/rx interrupt handlers
>>  net: korina: remove unused korina_private members
>>  net: korina: optimize tx descriptor flags processing
>>  net: korina: move tx to napi context
>>  net: korina: optimize tx_full condition
>>  net: korina: use dma api instead of dma_cache_* functions
>>  net: korina: bump version
>> 
>> drivers/net/ethernet/korina.c | 503
>> +++++++++++++++++-------------------------
>> 1 file changed, 204 insertions(+), 299 deletions(-)

^ permalink raw reply

* Re: [PATCH net-next 00/10] korina cleanups/optimizations
From: Florian Fainelli @ 2017-10-15 16:38 UTC (permalink / raw)
  To: Roman Yeryomin, netdev
In-Reply-To: <20171015162226.606-1-roman@advem.lv>

On October 15, 2017 9:22:26 AM PDT, Roman Yeryomin <roman@advem.lv> wrote:
>TX optimizations have led to ~15% performance increase (35->40Mbps)
>in local tx usecase (tested with iperf v3.2).

Could you avoid empty commit messages and write a paragraph or two for each commit that explains what and why are you changing? The changes look fine but they lack any explanation.

>
>Roman Yeryomin (10):
>  net: korina: optimize korina_send_packet logic
>  net: korina: reorder functions
>  net: korina: introduce and use interrupt disable/enable helpers
>  net: korina: optimize tx/rx interrupt handlers
>  net: korina: remove unused korina_private members
>  net: korina: optimize tx descriptor flags processing
>  net: korina: move tx to napi context
>  net: korina: optimize tx_full condition
>  net: korina: use dma api instead of dma_cache_* functions
>  net: korina: bump version
>
>drivers/net/ethernet/korina.c | 503
>+++++++++++++++++-------------------------
> 1 file changed, 204 insertions(+), 299 deletions(-)


-- 
Florian

^ permalink raw reply

* [PATCH net-next 07/10] net: korina: move tx to napi context
From: Roman Yeryomin @ 2017-10-15 16:23 UTC (permalink / raw)
  To: netdev

Signed-off-by: Roman Yeryomin <roman@advem.lv>
---
 drivers/net/ethernet/korina.c | 79 +++++++++++--------------------------------
 1 file changed, 20 insertions(+), 59 deletions(-)

diff --git a/drivers/net/ethernet/korina.c b/drivers/net/ethernet/korina.c
index a076b0c49e6e..f606f1e01af1 100644
--- a/drivers/net/ethernet/korina.c
+++ b/drivers/net/ethernet/korina.c
@@ -185,10 +185,6 @@ static inline void korina_abort_dma(struct net_device *dev,
 {
 	if (readl(&ch->dmac) & DMA_CHAN_RUN_BIT) {
 		writel(0x10, &ch->dmac);
-
-		while (!(readl(&ch->dmas) & DMA_STAT_HALT))
-			netif_trans_update(dev);
-
 		writel(0, &ch->dmas);
 	}
 
@@ -260,12 +256,9 @@ static void mdio_write(struct net_device *dev, int mii_id, int reg, int val)
 static int korina_send_packet(struct sk_buff *skb, struct net_device *dev)
 {
 	struct korina_private *lp = netdev_priv(dev);
-	unsigned long flags;
 	u32 chain_prev, chain_next, dmandptr;
 	struct dma_desc *td;
 
-	spin_lock_irqsave(&lp->lock, flags);
-
 	td = &lp->td_ring[lp->tx_chain_tail];
 
 	/* stop queue when full, drop pkts if queue already full */
@@ -276,7 +269,6 @@ static int korina_send_packet(struct sk_buff *skb, struct net_device *dev)
 		if (lp->tx_count > (KORINA_NUM_TDS - 2)) {
 			dev->stats.tx_dropped++;
 			dev_kfree_skb_any(skb);
-			spin_unlock_irqrestore(&lp->lock, flags);
 
 			return NETDEV_TX_BUSY;
 		}
@@ -319,9 +311,6 @@ static int korina_send_packet(struct sk_buff *skb, struct net_device *dev)
 
 	dma_cache_wback((u32) td, sizeof(*td));
 
-	netif_trans_update(dev);
-	spin_unlock_irqrestore(&lp->lock, flags);
-
 	return NETDEV_TX_OK;
 }
 
@@ -332,8 +321,6 @@ static void korina_tx(struct net_device *dev)
 	u32 devcs;
 	u32 dmas;
 
-	spin_lock(&lp->lock);
-
 	/* Process all desc that are done */
 	while (IS_DMA_FINISHED(td->control)) {
 		if (lp->tx_full == 1) {
@@ -389,10 +376,6 @@ static void korina_tx(struct net_device *dev)
 	/* Clear the DMA status register */
 	dmas = readl(&lp->tx_dma_regs->dmas);
 	writel(~dmas, &lp->tx_dma_regs->dmas);
-
-	korina_int_enable_tx(lp);
-
-	spin_unlock(&lp->lock);
 }
 
 static int korina_rx(struct net_device *dev, int limit)
@@ -513,67 +496,47 @@ static int korina_poll(struct napi_struct *napi, int budget)
 	struct net_device *dev = lp->dev;
 	int work_done;
 
+	korina_tx(dev);
+
 	work_done = korina_rx(dev, budget);
 	if (work_done < budget) {
 		napi_complete_done(napi, work_done);
+		spin_lock_bh(&lp->lock);
+		korina_int_enable_tx(lp);
 		korina_int_enable_rx(lp);
+		spin_unlock_bh(&lp->lock);
 	}
 	return work_done;
 }
 
-static irqreturn_t
-korina_tx_dma_interrupt(int irq, void *dev_id)
-{
-	struct net_device *dev = dev_id;
-	struct korina_private *lp = netdev_priv(dev);
-	u32 dmas;
-
-	dmas = readl(&lp->tx_dma_regs->dmas);
-
-	if (likely(dmas & KORINA_INT_TX)) {
-		korina_int_disable_tx(lp);
-
-		korina_tx(dev);
-
-		if (lp->tx_chain_status == desc_filled &&
-			(readl(&(lp->tx_dma_regs->dmandptr)) == 0)) {
-			writel(CPHYSADDR(&lp->td_ring[lp->tx_chain_head]),
-				&(lp->tx_dma_regs->dmandptr));
-			lp->tx_chain_status = desc_empty;
-			lp->tx_chain_head = lp->tx_chain_tail;
-			netif_trans_update(dev);
-		}
-
-		if (unlikely(dmas & DMA_STAT_ERR))
-			lp->dma_halt_cnt++;
-
-		return IRQ_HANDLED;
-	}
-
-	return IRQ_NONE;
-}
-
 /* Ethernet Rx DMA interrupt */
-static irqreturn_t korina_rx_dma_interrupt(int irq, void *dev_id)
+static irqreturn_t korina_dma_interrupt(int irq, void *dev_id)
 {
 	struct net_device *dev = dev_id;
 	struct korina_private *lp = netdev_priv(dev);
 	u32 dmas;
+	unsigned long flags;
+	irqreturn_t ret = IRQ_NONE;
 
-	dmas = readl(&lp->rx_dma_regs->dmas);
+	spin_lock_irqsave(&lp->lock, flags);
 
-	if (likely(dmas & KORINA_INT_RX)) {
+	dmas = readl(&lp->tx_dma_regs->dmas);
+	dmas |= readl(&lp->rx_dma_regs->dmas);
+
+	if (likely(dmas & KORINA_INT_TXRX)) {
 		korina_int_disable_rx(lp);
+		korina_int_disable_tx(lp);
 
 		napi_schedule(&lp->napi);
 
 		if (unlikely(dmas & DMA_STAT_ERR))
 			lp->dma_halt_cnt++;
 
-		return IRQ_HANDLED;
+		ret = IRQ_HANDLED;
 	}
 
-	return IRQ_NONE;
+	spin_unlock_irqrestore(&lp->lock, flags);
+	return ret;
 }
 
 /*
@@ -792,8 +755,6 @@ static int korina_init(struct net_device *dev)
 
 	/* reset ethernet logic */
 	writel(0, &lp->eth_regs->ethintfc);
-	while ((readl(&lp->eth_regs->ethintfc) & ETH_INT_FC_RIP))
-		netif_trans_update(dev);
 
 	/* Enable Ethernet Interface */
 	writel(ETH_INT_FC_EN, &lp->eth_regs->ethintfc);
@@ -897,7 +858,7 @@ static void korina_tx_timeout(struct net_device *dev)
 static void korina_poll_controller(struct net_device *dev)
 {
 	disable_irq(dev->irq);
-	korina_tx_dma_interrupt(dev->irq, dev);
+	korina_dma_interrupt(dev->irq, dev);
 	enable_irq(dev->irq);
 }
 #endif
@@ -916,14 +877,14 @@ static int korina_open(struct net_device *dev)
 
 	/* Install the interrupt handler
 	 * that handles the Done Finished */
-	ret = request_irq(lp->rx_irq, korina_rx_dma_interrupt,
+	ret = request_irq(lp->rx_irq, korina_dma_interrupt,
 			0, "Korina ethernet Rx", dev);
 	if (ret < 0) {
 		printk(KERN_ERR "%s: unable to get Rx DMA IRQ %d\n",
 			dev->name, lp->rx_irq);
 		goto err_release;
 	}
-	ret = request_irq(lp->tx_irq, korina_tx_dma_interrupt,
+	ret = request_irq(lp->tx_irq, korina_dma_interrupt,
 			0, "Korina ethernet Tx", dev);
 	if (ret < 0) {
 		printk(KERN_ERR "%s: unable to get Tx DMA IRQ %d\n",
-- 
2.11.0

^ permalink raw reply related

* [PATCH net-next 09/10] net: korina: use dma api instead of dma_cache_* functions
From: Roman Yeryomin @ 2017-10-15 16:24 UTC (permalink / raw)
  To: netdev

Signed-off-by: Roman Yeryomin <roman@advem.lv>
---
 drivers/net/ethernet/korina.c | 44 ++++++++++++++++++-------------------------
 1 file changed, 18 insertions(+), 26 deletions(-)

diff --git a/drivers/net/ethernet/korina.c b/drivers/net/ethernet/korina.c
index 9520fa1e35a2..8fa60d1fe022 100644
--- a/drivers/net/ethernet/korina.c
+++ b/drivers/net/ethernet/korina.c
@@ -113,6 +113,7 @@ struct korina_private {
 	struct dma_reg *tx_dma_regs;
 	struct dma_desc *td_ring; /* transmit descriptor ring */
 	struct dma_desc *rd_ring; /* receive descriptor ring  */
+	dma_addr_t ring_dma;
 
 	struct sk_buff *tx_skb[KORINA_NUM_TDS];
 	struct sk_buff *rx_skb[KORINA_NUM_RDS];
@@ -257,6 +258,7 @@ static int korina_send_packet(struct sk_buff *skb, struct net_device *dev)
 	struct korina_private *lp = netdev_priv(dev);
 	u32 chain_prev, chain_next, dmandptr;
 	struct dma_desc *td;
+	dma_addr_t dma_addr;
 
 	td = &lp->td_ring[lp->tx_chain_tail];
 
@@ -267,10 +269,10 @@ static int korina_send_packet(struct sk_buff *skb, struct net_device *dev)
 	lp->tx_count++;
 	lp->tx_skb[lp->tx_chain_tail] = skb;
 
-	dma_cache_wback((u32)skb->data, skb->len);
+	dma_addr = dma_map_single(&dev->dev, skb->data, skb->len, DMA_TO_DEVICE);
 
-	/* Setup the transmit descriptor. */
-	dma_cache_inv((u32) td, sizeof(*td));
+	/* flush descriptor */
+	wmb();
 
 	td->ca = CPHYSADDR(skb->data);
 	chain_prev = (lp->tx_chain_tail - 1) & KORINA_TDS_MASK;
@@ -299,7 +301,7 @@ static int korina_send_packet(struct sk_buff *skb, struct net_device *dev)
 		lp->tx_chain_status = desc_filled;
 	}
 
-	dma_cache_wback((u32) td, sizeof(*td));
+	dma_unmap_single(&dev->dev, dma_addr, skb->len, DMA_TO_DEVICE);
 
 	return NETDEV_TX_OK;
 }
@@ -375,8 +377,6 @@ static int korina_rx(struct net_device *dev, int limit)
 	u32 devcs, pkt_len, dmas;
 	int count;
 
-	dma_cache_inv((u32)rd, sizeof(*rd));
-
 	for (count = 0; count < limit; count++) {
 		skb = lp->rx_skb[lp->rx_next_done];
 		skb_new = NULL;
@@ -416,9 +416,6 @@ static int korina_rx(struct net_device *dev, int limit)
 		 * descriptor then */
 		pkt_buf = (u8 *)lp->rx_skb[lp->rx_next_done]->data;
 
-		/* invalidate the cache */
-		dma_cache_inv((unsigned long)pkt_buf, pkt_len - 4);
-
 		/* Malloc up new buffer. */
 		skb_new = netdev_alloc_skb_ip_align(dev, KORINA_RBSIZE);
 
@@ -455,7 +452,6 @@ static int korina_rx(struct net_device *dev, int limit)
 			~DMA_DESC_COD;
 
 		lp->rx_next_done = (lp->rx_next_done + 1) & KORINA_RDS_MASK;
-		dma_cache_wback((u32)rd, sizeof(*rd));
 		rd = &lp->rd_ring[lp->rx_next_done];
 		writel(~DMA_STAT_DONE, &lp->rx_dma_regs->dmas);
 	}
@@ -470,7 +466,6 @@ static int korina_rx(struct net_device *dev, int limit)
 		rd->devcs = 0;
 		skb = lp->rx_skb[lp->rx_next_done];
 		rd->ca = CPHYSADDR(skb->data);
-		dma_cache_wback((u32)rd, sizeof(*rd));
 		korina_chain_rx(lp, rd);
 	}
 
@@ -676,6 +671,13 @@ static int korina_alloc_ring(struct net_device *dev)
 	struct sk_buff *skb;
 	int i;
 
+	lp->td_ring = dma_alloc_coherent(NULL, TD_RING_SIZE + RD_RING_SIZE,
+						&lp->ring_dma, GFP_ATOMIC);
+	if (!lp->td_ring)
+		return -ENOMEM;
+
+	lp->rd_ring = &lp->td_ring[KORINA_NUM_TDS];
+
 	/* Initialize the transmit descriptors */
 	for (i = 0; i < KORINA_NUM_TDS; i++) {
 		lp->td_ring[i].control = DMA_DESC_IOF;
@@ -707,6 +709,8 @@ static int korina_alloc_ring(struct net_device *dev)
 
 	lp->rx_next_done  = 0;
 
+	wmb();
+
 	return 0;
 }
 
@@ -728,6 +732,9 @@ static void korina_free_ring(struct net_device *dev)
 			dev_kfree_skb_any(lp->tx_skb[i]);
 		lp->tx_skb[i] = NULL;
 	}
+
+	dma_free_coherent(NULL, TD_RING_SIZE + RD_RING_SIZE,
+					lp->td_ring, lp->ring_dma);
 }
 
 /*
@@ -979,19 +986,6 @@ static int korina_probe(struct platform_device *pdev)
 		goto probe_err_dma_tx;
 	}
 
-	lp->td_ring = kmalloc(TD_RING_SIZE + RD_RING_SIZE, GFP_KERNEL);
-	if (!lp->td_ring) {
-		rc = -ENXIO;
-		goto probe_err_td_ring;
-	}
-
-	dma_cache_inv((unsigned long)(lp->td_ring),
-			TD_RING_SIZE + RD_RING_SIZE);
-
-	/* now convert TD_RING pointer to KSEG1 */
-	lp->td_ring = (struct dma_desc *)KSEG1ADDR(lp->td_ring);
-	lp->rd_ring = &lp->td_ring[KORINA_NUM_TDS];
-
 	spin_lock_init(&lp->lock);
 	/* just use the rx dma irq */
 	dev->irq = lp->rx_irq;
@@ -1026,8 +1020,6 @@ static int korina_probe(struct platform_device *pdev)
 	return rc;
 
 probe_err_register:
-	kfree(lp->td_ring);
-probe_err_td_ring:
 	iounmap(lp->tx_dma_regs);
 probe_err_dma_tx:
 	iounmap(lp->rx_dma_regs);
-- 
2.11.0

^ permalink raw reply related

* [PATCH net-next 08/10] net: korina: optimize tx_full condition
From: Roman Yeryomin @ 2017-10-15 16:24 UTC (permalink / raw)
  To: netdev

Signed-off-by: Roman Yeryomin <roman@advem.lv>
---
 drivers/net/ethernet/korina.c | 20 ++++----------------
 1 file changed, 4 insertions(+), 16 deletions(-)

diff --git a/drivers/net/ethernet/korina.c b/drivers/net/ethernet/korina.c
index f606f1e01af1..9520fa1e35a2 100644
--- a/drivers/net/ethernet/korina.c
+++ b/drivers/net/ethernet/korina.c
@@ -124,7 +124,6 @@ struct korina_private {
 	int tx_chain_tail;
 	enum chain_status tx_chain_status;
 	int tx_count;
-	int tx_full;
 
 	int rx_irq;
 	int tx_irq;
@@ -261,19 +260,10 @@ static int korina_send_packet(struct sk_buff *skb, struct net_device *dev)
 
 	td = &lp->td_ring[lp->tx_chain_tail];
 
-	/* stop queue when full, drop pkts if queue already full */
-	if (lp->tx_count >= (KORINA_NUM_TDS - 2)) {
-		lp->tx_full = 1;
+	/* stop queue when full */
+	if (unlikely(lp->tx_count > (KORINA_NUM_TDS - 3)))
 		netif_stop_queue(dev);
 
-		if (lp->tx_count > (KORINA_NUM_TDS - 2)) {
-			dev->stats.tx_dropped++;
-			dev_kfree_skb_any(skb);
-
-			return NETDEV_TX_BUSY;
-		}
-	}
-
 	lp->tx_count++;
 	lp->tx_skb[lp->tx_chain_tail] = skb;
 
@@ -323,10 +313,8 @@ static void korina_tx(struct net_device *dev)
 
 	/* Process all desc that are done */
 	while (IS_DMA_FINISHED(td->control)) {
-		if (lp->tx_full == 1) {
+		if (unlikely(lp->tx_count > (KORINA_NUM_TDS - 2)))
 			netif_wake_queue(dev);
-			lp->tx_full = 0;
-		}
 
 		devcs = lp->td_ring[lp->tx_next_done].devcs;
 
@@ -696,7 +684,7 @@ static int korina_alloc_ring(struct net_device *dev)
 		lp->td_ring[i].link = 0;
 	}
 	lp->tx_next_done = lp->tx_chain_head = lp->tx_chain_tail =
-			lp->tx_full = lp->tx_count = 0;
+			lp->tx_count = 0;
 	lp->tx_chain_status = desc_empty;
 
 	/* Initialize the receive descriptors */
-- 
2.11.0

^ permalink raw reply related

* [PATCH net-next 10/10] net: korina: bump version
From: Roman Yeryomin @ 2017-10-15 16:24 UTC (permalink / raw)
  To: netdev

Signed-off-by: Roman Yeryomin <roman@advem.lv>
---
 drivers/net/ethernet/korina.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/net/ethernet/korina.c b/drivers/net/ethernet/korina.c
index 8fa60d1fe022..fc8e80487507 100644
--- a/drivers/net/ethernet/korina.c
+++ b/drivers/net/ethernet/korina.c
@@ -66,8 +66,8 @@
 #include <asm/mach-rc32434/dma_v.h>
 
 #define DRV_NAME	"korina"
-#define DRV_VERSION	"0.20"
-#define DRV_RELDATE	"15Sep2017"
+#define DRV_VERSION	"0.21"
+#define DRV_RELDATE	"15Oct2017"
 
 #define STATION_ADDRESS_HIGH(dev) (((dev)->dev_addr[0] << 8) | \
 				   ((dev)->dev_addr[1]))
-- 
2.11.0

^ permalink raw reply related

* [PATCH net-next 05/10] net: korina: remove unused korina_private members
From: Roman Yeryomin @ 2017-10-15 16:23 UTC (permalink / raw)
  To: netdev

Signed-off-by: Roman Yeryomin <roman@advem.lv>
---
 drivers/net/ethernet/korina.c | 7 -------
 1 file changed, 7 deletions(-)

diff --git a/drivers/net/ethernet/korina.c b/drivers/net/ethernet/korina.c
index 64ae32af7539..59d4554c43c9 100644
--- a/drivers/net/ethernet/korina.c
+++ b/drivers/net/ethernet/korina.c
@@ -118,9 +118,6 @@ struct korina_private {
 	struct sk_buff *rx_skb[KORINA_NUM_RDS];
 
 	int rx_next_done;
-	int rx_chain_head;
-	int rx_chain_tail;
-	enum chain_status rx_chain_status;
 
 	int tx_next_done;
 	int tx_chain_head;
@@ -135,7 +132,6 @@ struct korina_private {
 	spinlock_t lock;	/* NIC xmit lock */
 
 	int dma_halt_cnt;
-	int dma_run_cnt;
 	struct napi_struct napi;
 	struct timer_list media_check_timer;
 	struct mii_if_info mii_if;
@@ -770,9 +766,6 @@ static int korina_alloc_ring(struct net_device *dev)
 	lp->rd_ring[i - 1].control |= DMA_DESC_COD;
 
 	lp->rx_next_done  = 0;
-	lp->rx_chain_head = 0;
-	lp->rx_chain_tail = 0;
-	lp->rx_chain_status = desc_empty;
 
 	return 0;
 }
-- 
2.11.0

^ permalink raw reply related

* [PATCH net-next 02/10] net: korina: reorder functions
From: Roman Yeryomin @ 2017-10-15 16:22 UTC (permalink / raw)
  To: netdev

Signed-off-by: Roman Yeryomin <roman@advem.lv>
---
 drivers/net/ethernet/korina.c | 317 +++++++++++++++++++++---------------------
 1 file changed, 158 insertions(+), 159 deletions(-)

diff --git a/drivers/net/ethernet/korina.c b/drivers/net/ethernet/korina.c
index 84b2654e2d06..5545f86aac4a 100644
--- a/drivers/net/ethernet/korina.c
+++ b/drivers/net/ethernet/korina.c
@@ -195,6 +195,35 @@ static void korina_chain_rx(struct korina_private *lp,
 	korina_chain_dma(lp->rx_dma_regs, CPHYSADDR(rd));
 }
 
+static int mdio_read(struct net_device *dev, int mii_id, int reg)
+{
+	struct korina_private *lp = netdev_priv(dev);
+	int ret;
+
+	mii_id = ((lp->rx_irq == 0x2c ? 1 : 0) << 8);
+
+	writel(0, &lp->eth_regs->miimcfg);
+	writel(0, &lp->eth_regs->miimcmd);
+	writel(mii_id | reg, &lp->eth_regs->miimaddr);
+	writel(ETH_MII_CMD_SCN, &lp->eth_regs->miimcmd);
+
+	ret = (int)(readl(&lp->eth_regs->miimrdd));
+	return ret;
+}
+
+static void mdio_write(struct net_device *dev, int mii_id, int reg, int val)
+{
+	struct korina_private *lp = netdev_priv(dev);
+
+	mii_id = ((lp->rx_irq == 0x2c ? 1 : 0) << 8);
+
+	writel(0, &lp->eth_regs->miimcfg);
+	writel(1, &lp->eth_regs->miimcmd);
+	writel(mii_id | reg, &lp->eth_regs->miimaddr);
+	writel(ETH_MII_CMD_SCN, &lp->eth_regs->miimcmd);
+	writel(val, &lp->eth_regs->miimwtd);
+}
+
 /* transmit packet */
 static int korina_send_packet(struct sk_buff *skb, struct net_device *dev)
 {
@@ -264,60 +293,87 @@ static int korina_send_packet(struct sk_buff *skb, struct net_device *dev)
 	return NETDEV_TX_OK;
 }
 
-static int mdio_read(struct net_device *dev, int mii_id, int reg)
+static void korina_tx(struct net_device *dev)
 {
 	struct korina_private *lp = netdev_priv(dev);
-	int ret;
+	struct dma_desc *td = &lp->td_ring[lp->tx_next_done];
+	u32 devcs;
+	u32 dmas;
 
-	mii_id = ((lp->rx_irq == 0x2c ? 1 : 0) << 8);
+	spin_lock(&lp->lock);
 
-	writel(0, &lp->eth_regs->miimcfg);
-	writel(0, &lp->eth_regs->miimcmd);
-	writel(mii_id | reg, &lp->eth_regs->miimaddr);
-	writel(ETH_MII_CMD_SCN, &lp->eth_regs->miimcmd);
+	/* Process all desc that are done */
+	while (IS_DMA_FINISHED(td->control)) {
+		if (lp->tx_full == 1) {
+			netif_wake_queue(dev);
+			lp->tx_full = 0;
+		}
 
-	ret = (int)(readl(&lp->eth_regs->miimrdd));
-	return ret;
-}
+		devcs = lp->td_ring[lp->tx_next_done].devcs;
+		if ((devcs & (ETH_TX_FD | ETH_TX_LD)) !=
+				(ETH_TX_FD | ETH_TX_LD)) {
+			dev->stats.tx_errors++;
+			dev->stats.tx_dropped++;
 
-static void mdio_write(struct net_device *dev, int mii_id, int reg, int val)
-{
-	struct korina_private *lp = netdev_priv(dev);
+			/* Should never happen */
+			printk(KERN_ERR "%s: split tx ignored\n",
+							dev->name);
+		} else if (devcs & ETH_TX_TOK) {
+			dev->stats.tx_packets++;
+			dev->stats.tx_bytes +=
+					lp->tx_skb[lp->tx_next_done]->len;
+		} else {
+			dev->stats.tx_errors++;
+			dev->stats.tx_dropped++;
 
-	mii_id = ((lp->rx_irq == 0x2c ? 1 : 0) << 8);
+			/* Underflow */
+			if (devcs & ETH_TX_UND)
+				dev->stats.tx_fifo_errors++;
 
-	writel(0, &lp->eth_regs->miimcfg);
-	writel(1, &lp->eth_regs->miimcmd);
-	writel(mii_id | reg, &lp->eth_regs->miimaddr);
-	writel(ETH_MII_CMD_SCN, &lp->eth_regs->miimcmd);
-	writel(val, &lp->eth_regs->miimwtd);
-}
+			/* Oversized frame */
+			if (devcs & ETH_TX_OF)
+				dev->stats.tx_aborted_errors++;
 
-/* Ethernet Rx DMA interrupt */
-static irqreturn_t korina_rx_dma_interrupt(int irq, void *dev_id)
-{
-	struct net_device *dev = dev_id;
-	struct korina_private *lp = netdev_priv(dev);
-	u32 dmas, dmasm;
-	irqreturn_t retval;
+			/* Excessive deferrals */
+			if (devcs & ETH_TX_ED)
+				dev->stats.tx_carrier_errors++;
 
-	dmas = readl(&lp->rx_dma_regs->dmas);
-	if (dmas & (DMA_STAT_DONE | DMA_STAT_HALT | DMA_STAT_ERR)) {
-		dmasm = readl(&lp->rx_dma_regs->dmasm);
-		writel(dmasm | (DMA_STAT_DONE |
-				DMA_STAT_HALT | DMA_STAT_ERR),
-				&lp->rx_dma_regs->dmasm);
+			/* Collisions: medium busy */
+			if (devcs & ETH_TX_EC)
+				dev->stats.collisions++;
 
-		napi_schedule(&lp->napi);
+			/* Late collision */
+			if (devcs & ETH_TX_LC)
+				dev->stats.tx_window_errors++;
+		}
 
-		if (dmas & DMA_STAT_ERR)
-			printk(KERN_ERR "%s: DMA error\n", dev->name);
+		/* We must always free the original skb */
+		if (lp->tx_skb[lp->tx_next_done]) {
+			dev_kfree_skb_any(lp->tx_skb[lp->tx_next_done]);
+			lp->tx_skb[lp->tx_next_done] = NULL;
+		}
 
-		retval = IRQ_HANDLED;
-	} else
-		retval = IRQ_NONE;
+		lp->td_ring[lp->tx_next_done].control = DMA_DESC_IOF;
+		lp->td_ring[lp->tx_next_done].devcs = ETH_TX_FD | ETH_TX_LD;
+		lp->td_ring[lp->tx_next_done].link = 0;
+		lp->td_ring[lp->tx_next_done].ca = 0;
+		lp->tx_count--;
 
-	return retval;
+		/* Go on to next transmission */
+		lp->tx_next_done = (lp->tx_next_done + 1) & KORINA_TDS_MASK;
+		td = &lp->td_ring[lp->tx_next_done];
+
+	}
+
+	/* Clear the DMA status register */
+	dmas = readl(&lp->tx_dma_regs->dmas);
+	writel(~dmas, &lp->tx_dma_regs->dmas);
+
+	writel(readl(&lp->tx_dma_regs->dmasm) &
+			~(DMA_STAT_FINI | DMA_STAT_ERR),
+			&lp->tx_dma_regs->dmasm);
+
+	spin_unlock(&lp->lock);
 }
 
 static int korina_rx(struct net_device *dev, int limit)
@@ -449,6 +505,68 @@ static int korina_poll(struct napi_struct *napi, int budget)
 	return work_done;
 }
 
+static irqreturn_t
+korina_tx_dma_interrupt(int irq, void *dev_id)
+{
+	struct net_device *dev = dev_id;
+	struct korina_private *lp = netdev_priv(dev);
+	u32 dmas, dmasm;
+	irqreturn_t retval;
+
+	dmas = readl(&lp->tx_dma_regs->dmas);
+
+	if (dmas & (DMA_STAT_FINI | DMA_STAT_ERR)) {
+		dmasm = readl(&lp->tx_dma_regs->dmasm);
+		writel(dmasm | (DMA_STAT_FINI | DMA_STAT_ERR),
+				&lp->tx_dma_regs->dmasm);
+
+		korina_tx(dev);
+
+		if (lp->tx_chain_status == desc_filled &&
+			(readl(&(lp->tx_dma_regs->dmandptr)) == 0)) {
+			writel(CPHYSADDR(&lp->td_ring[lp->tx_chain_head]),
+				&(lp->tx_dma_regs->dmandptr));
+			lp->tx_chain_status = desc_empty;
+			lp->tx_chain_head = lp->tx_chain_tail;
+			netif_trans_update(dev);
+		}
+		if (dmas & DMA_STAT_ERR)
+			printk(KERN_ERR "%s: DMA error\n", dev->name);
+
+		retval = IRQ_HANDLED;
+	} else
+		retval = IRQ_NONE;
+
+	return retval;
+}
+
+/* Ethernet Rx DMA interrupt */
+static irqreturn_t korina_rx_dma_interrupt(int irq, void *dev_id)
+{
+	struct net_device *dev = dev_id;
+	struct korina_private *lp = netdev_priv(dev);
+	u32 dmas, dmasm;
+	irqreturn_t retval;
+
+	dmas = readl(&lp->rx_dma_regs->dmas);
+	if (dmas & (DMA_STAT_DONE | DMA_STAT_HALT | DMA_STAT_ERR)) {
+		dmasm = readl(&lp->rx_dma_regs->dmasm);
+		writel(dmasm | (DMA_STAT_DONE |
+				DMA_STAT_HALT | DMA_STAT_ERR),
+				&lp->rx_dma_regs->dmasm);
+
+		napi_schedule(&lp->napi);
+
+		if (dmas & DMA_STAT_ERR)
+			printk(KERN_ERR "%s: DMA error\n", dev->name);
+
+		retval = IRQ_HANDLED;
+	} else
+		retval = IRQ_NONE;
+
+	return retval;
+}
+
 /*
  * Set or clear the multicast filter for this adaptor.
  */
@@ -492,125 +610,6 @@ static void korina_multicast_list(struct net_device *dev)
 	spin_unlock_irqrestore(&lp->lock, flags);
 }
 
-static void korina_tx(struct net_device *dev)
-{
-	struct korina_private *lp = netdev_priv(dev);
-	struct dma_desc *td = &lp->td_ring[lp->tx_next_done];
-	u32 devcs;
-	u32 dmas;
-
-	spin_lock(&lp->lock);
-
-	/* Process all desc that are done */
-	while (IS_DMA_FINISHED(td->control)) {
-		if (lp->tx_full == 1) {
-			netif_wake_queue(dev);
-			lp->tx_full = 0;
-		}
-
-		devcs = lp->td_ring[lp->tx_next_done].devcs;
-		if ((devcs & (ETH_TX_FD | ETH_TX_LD)) !=
-				(ETH_TX_FD | ETH_TX_LD)) {
-			dev->stats.tx_errors++;
-			dev->stats.tx_dropped++;
-
-			/* Should never happen */
-			printk(KERN_ERR "%s: split tx ignored\n",
-							dev->name);
-		} else if (devcs & ETH_TX_TOK) {
-			dev->stats.tx_packets++;
-			dev->stats.tx_bytes +=
-					lp->tx_skb[lp->tx_next_done]->len;
-		} else {
-			dev->stats.tx_errors++;
-			dev->stats.tx_dropped++;
-
-			/* Underflow */
-			if (devcs & ETH_TX_UND)
-				dev->stats.tx_fifo_errors++;
-
-			/* Oversized frame */
-			if (devcs & ETH_TX_OF)
-				dev->stats.tx_aborted_errors++;
-
-			/* Excessive deferrals */
-			if (devcs & ETH_TX_ED)
-				dev->stats.tx_carrier_errors++;
-
-			/* Collisions: medium busy */
-			if (devcs & ETH_TX_EC)
-				dev->stats.collisions++;
-
-			/* Late collision */
-			if (devcs & ETH_TX_LC)
-				dev->stats.tx_window_errors++;
-		}
-
-		/* We must always free the original skb */
-		if (lp->tx_skb[lp->tx_next_done]) {
-			dev_kfree_skb_any(lp->tx_skb[lp->tx_next_done]);
-			lp->tx_skb[lp->tx_next_done] = NULL;
-		}
-
-		lp->td_ring[lp->tx_next_done].control = DMA_DESC_IOF;
-		lp->td_ring[lp->tx_next_done].devcs = ETH_TX_FD | ETH_TX_LD;
-		lp->td_ring[lp->tx_next_done].link = 0;
-		lp->td_ring[lp->tx_next_done].ca = 0;
-		lp->tx_count--;
-
-		/* Go on to next transmission */
-		lp->tx_next_done = (lp->tx_next_done + 1) & KORINA_TDS_MASK;
-		td = &lp->td_ring[lp->tx_next_done];
-
-	}
-
-	/* Clear the DMA status register */
-	dmas = readl(&lp->tx_dma_regs->dmas);
-	writel(~dmas, &lp->tx_dma_regs->dmas);
-
-	writel(readl(&lp->tx_dma_regs->dmasm) &
-			~(DMA_STAT_FINI | DMA_STAT_ERR),
-			&lp->tx_dma_regs->dmasm);
-
-	spin_unlock(&lp->lock);
-}
-
-static irqreturn_t
-korina_tx_dma_interrupt(int irq, void *dev_id)
-{
-	struct net_device *dev = dev_id;
-	struct korina_private *lp = netdev_priv(dev);
-	u32 dmas, dmasm;
-	irqreturn_t retval;
-
-	dmas = readl(&lp->tx_dma_regs->dmas);
-
-	if (dmas & (DMA_STAT_FINI | DMA_STAT_ERR)) {
-		dmasm = readl(&lp->tx_dma_regs->dmasm);
-		writel(dmasm | (DMA_STAT_FINI | DMA_STAT_ERR),
-				&lp->tx_dma_regs->dmasm);
-
-		korina_tx(dev);
-
-		if (lp->tx_chain_status == desc_filled &&
-			(readl(&(lp->tx_dma_regs->dmandptr)) == 0)) {
-			writel(CPHYSADDR(&lp->td_ring[lp->tx_chain_head]),
-				&(lp->tx_dma_regs->dmandptr));
-			lp->tx_chain_status = desc_empty;
-			lp->tx_chain_head = lp->tx_chain_tail;
-			netif_trans_update(dev);
-		}
-		if (dmas & DMA_STAT_ERR)
-			printk(KERN_ERR "%s: DMA error\n", dev->name);
-
-		retval = IRQ_HANDLED;
-	} else
-		retval = IRQ_NONE;
-
-	return retval;
-}
-
-
 static void korina_check_media(struct net_device *dev, unsigned int init_media)
 {
 	struct korina_private *lp = netdev_priv(dev);
-- 
2.11.0

^ permalink raw reply related

* [PATCH net-next 04/10] net: korina: optimize tx/rx interrupt handlers
From: Roman Yeryomin @ 2017-10-15 16:23 UTC (permalink / raw)
  To: netdev

Signed-off-by: Roman Yeryomin <roman@advem.lv>
---
 drivers/net/ethernet/korina.c | 30 ++++++++++++++----------------
 1 file changed, 14 insertions(+), 16 deletions(-)

diff --git a/drivers/net/ethernet/korina.c b/drivers/net/ethernet/korina.c
index 04c1a3f38a79..64ae32af7539 100644
--- a/drivers/net/ethernet/korina.c
+++ b/drivers/net/ethernet/korina.c
@@ -542,11 +542,10 @@ korina_tx_dma_interrupt(int irq, void *dev_id)
 	struct net_device *dev = dev_id;
 	struct korina_private *lp = netdev_priv(dev);
 	u32 dmas;
-	irqreturn_t retval;
 
 	dmas = readl(&lp->tx_dma_regs->dmas);
 
-	if (dmas & (DMA_STAT_FINI | DMA_STAT_ERR)) {
+	if (likely(dmas & KORINA_INT_TX)) {
 		korina_int_disable_tx(lp);
 
 		korina_tx(dev);
@@ -559,14 +558,14 @@ korina_tx_dma_interrupt(int irq, void *dev_id)
 			lp->tx_chain_head = lp->tx_chain_tail;
 			netif_trans_update(dev);
 		}
-		if (dmas & DMA_STAT_ERR)
-			printk(KERN_ERR "%s: DMA error\n", dev->name);
 
-		retval = IRQ_HANDLED;
-	} else
-		retval = IRQ_NONE;
+		if (unlikely(dmas & DMA_STAT_ERR))
+			lp->dma_halt_cnt++;
 
-	return retval;
+		return IRQ_HANDLED;
+	}
+
+	return IRQ_NONE;
 }
 
 /* Ethernet Rx DMA interrupt */
@@ -575,22 +574,21 @@ static irqreturn_t korina_rx_dma_interrupt(int irq, void *dev_id)
 	struct net_device *dev = dev_id;
 	struct korina_private *lp = netdev_priv(dev);
 	u32 dmas;
-	irqreturn_t retval;
 
 	dmas = readl(&lp->rx_dma_regs->dmas);
-	if (dmas & (DMA_STAT_DONE | DMA_STAT_HALT | DMA_STAT_ERR)) {
+
+	if (likely(dmas & KORINA_INT_RX)) {
 		korina_int_disable_rx(lp);
 
 		napi_schedule(&lp->napi);
 
-		if (dmas & DMA_STAT_ERR)
-			printk(KERN_ERR "%s: DMA error\n", dev->name);
+		if (unlikely(dmas & DMA_STAT_ERR))
+			lp->dma_halt_cnt++;
 
-		retval = IRQ_HANDLED;
-	} else
-		retval = IRQ_NONE;
+		return IRQ_HANDLED;
+	}
 
-	return retval;
+	return IRQ_NONE;
 }
 
 /*
-- 
2.11.0

^ permalink raw reply related

* [PATCH net-next 03/10] net: korina: introduce and use interrupt disable/enable helpers
From: Roman Yeryomin @ 2017-10-15 16:23 UTC (permalink / raw)
  To: netdev

Signed-off-by: Roman Yeryomin <roman@advem.lv>
---
 drivers/net/ethernet/korina.c | 83 +++++++++++++++++++++++++------------------
 1 file changed, 48 insertions(+), 35 deletions(-)

diff --git a/drivers/net/ethernet/korina.c b/drivers/net/ethernet/korina.c
index 5545f86aac4a..04c1a3f38a79 100644
--- a/drivers/net/ethernet/korina.c
+++ b/drivers/net/ethernet/korina.c
@@ -91,6 +91,10 @@
 #define RD_RING_SIZE	(KORINA_NUM_RDS * sizeof(struct dma_desc))
 #define TD_RING_SIZE	(KORINA_NUM_TDS * sizeof(struct dma_desc))
 
+#define KORINA_INT_TX	(DMA_STAT_FINI | DMA_STAT_ERR)
+#define KORINA_INT_RX	(DMA_STAT_DONE | DMA_STAT_HALT | DMA_STAT_ERR)
+#define KORINA_INT_TXRX	(KORINA_INT_TX | KORINA_INT_RX)
+
 #define TX_TIMEOUT	(6000 * HZ / 1000)
 
 enum chain_status {
@@ -142,6 +146,38 @@ struct korina_private {
 
 extern unsigned int idt_cpu_freq;
 
+static inline void korina_int_disable(u32 *dmasm, u32 ints)
+{
+	u32 tmp = readl(dmasm);
+	writel(tmp | ints, dmasm);
+}
+
+static inline void korina_int_enable(u32 *dmasm, u32 ints)
+{
+	u32 tmp = readl(dmasm);
+	writel(tmp & ~ints, dmasm);
+}
+
+static inline void korina_int_disable_tx(struct korina_private *kp)
+{
+	korina_int_disable(&kp->tx_dma_regs->dmasm, KORINA_INT_TX);
+}
+
+static inline void korina_int_disable_rx(struct korina_private *kp)
+{
+	korina_int_disable(&kp->rx_dma_regs->dmasm, KORINA_INT_RX);
+}
+
+static inline void korina_int_enable_tx(struct korina_private *kp)
+{
+	korina_int_enable(&kp->tx_dma_regs->dmasm, KORINA_INT_TX);
+}
+
+static inline void korina_int_enable_rx(struct korina_private *kp)
+{
+	korina_int_enable(&kp->rx_dma_regs->dmasm, KORINA_INT_RX);
+}
+
 static inline void korina_start_dma(struct dma_reg *ch, u32 dma_addr)
 {
 	writel(0, &ch->dmandptr);
@@ -369,9 +405,7 @@ static void korina_tx(struct net_device *dev)
 	dmas = readl(&lp->tx_dma_regs->dmas);
 	writel(~dmas, &lp->tx_dma_regs->dmas);
 
-	writel(readl(&lp->tx_dma_regs->dmasm) &
-			~(DMA_STAT_FINI | DMA_STAT_ERR),
-			&lp->tx_dma_regs->dmasm);
+	korina_int_enable_tx(lp);
 
 	spin_unlock(&lp->lock);
 }
@@ -497,10 +531,7 @@ static int korina_poll(struct napi_struct *napi, int budget)
 	work_done = korina_rx(dev, budget);
 	if (work_done < budget) {
 		napi_complete_done(napi, work_done);
-
-		writel(readl(&lp->rx_dma_regs->dmasm) &
-			~(DMA_STAT_DONE | DMA_STAT_HALT | DMA_STAT_ERR),
-			&lp->rx_dma_regs->dmasm);
+		korina_int_enable_rx(lp);
 	}
 	return work_done;
 }
@@ -510,15 +541,13 @@ korina_tx_dma_interrupt(int irq, void *dev_id)
 {
 	struct net_device *dev = dev_id;
 	struct korina_private *lp = netdev_priv(dev);
-	u32 dmas, dmasm;
+	u32 dmas;
 	irqreturn_t retval;
 
 	dmas = readl(&lp->tx_dma_regs->dmas);
 
 	if (dmas & (DMA_STAT_FINI | DMA_STAT_ERR)) {
-		dmasm = readl(&lp->tx_dma_regs->dmasm);
-		writel(dmasm | (DMA_STAT_FINI | DMA_STAT_ERR),
-				&lp->tx_dma_regs->dmasm);
+		korina_int_disable_tx(lp);
 
 		korina_tx(dev);
 
@@ -545,15 +574,12 @@ static irqreturn_t korina_rx_dma_interrupt(int irq, void *dev_id)
 {
 	struct net_device *dev = dev_id;
 	struct korina_private *lp = netdev_priv(dev);
-	u32 dmas, dmasm;
+	u32 dmas;
 	irqreturn_t retval;
 
 	dmas = readl(&lp->rx_dma_regs->dmas);
 	if (dmas & (DMA_STAT_DONE | DMA_STAT_HALT | DMA_STAT_ERR)) {
-		dmasm = readl(&lp->rx_dma_regs->dmasm);
-		writel(dmasm | (DMA_STAT_DONE |
-				DMA_STAT_HALT | DMA_STAT_ERR),
-				&lp->rx_dma_regs->dmasm);
+		korina_int_disable_rx(lp);
 
 		napi_schedule(&lp->napi);
 
@@ -803,12 +829,8 @@ static int korina_init(struct net_device *dev)
 	/* Start Rx DMA */
 	korina_start_rx(lp, &lp->rd_ring[0]);
 
-	writel(readl(&lp->tx_dma_regs->dmasm) &
-			~(DMA_STAT_FINI | DMA_STAT_ERR),
-			&lp->tx_dma_regs->dmasm);
-	writel(readl(&lp->rx_dma_regs->dmasm) &
-			~(DMA_STAT_DONE | DMA_STAT_HALT | DMA_STAT_ERR),
-			&lp->rx_dma_regs->dmasm);
+	korina_int_enable_tx(lp);
+	korina_int_enable_rx(lp);
 
 	/* Accept only packets destined for this Ethernet device address */
 	writel(ETH_ARC_AB, &lp->eth_regs->etharc);
@@ -867,12 +889,8 @@ static void korina_restart_task(struct work_struct *work)
 	disable_irq(lp->rx_irq);
 	disable_irq(lp->tx_irq);
 
-	writel(readl(&lp->tx_dma_regs->dmasm) |
-				DMA_STAT_FINI | DMA_STAT_ERR,
-				&lp->tx_dma_regs->dmasm);
-	writel(readl(&lp->rx_dma_regs->dmasm) |
-				DMA_STAT_DONE | DMA_STAT_HALT | DMA_STAT_ERR,
-				&lp->rx_dma_regs->dmasm);
+	korina_int_disable_tx(lp);
+	korina_int_disable_rx(lp);
 
 	napi_disable(&lp->napi);
 
@@ -947,7 +965,6 @@ static int korina_open(struct net_device *dev)
 static int korina_close(struct net_device *dev)
 {
 	struct korina_private *lp = netdev_priv(dev);
-	u32 tmp;
 
 	del_timer(&lp->media_check_timer);
 
@@ -956,14 +973,10 @@ static int korina_close(struct net_device *dev)
 	disable_irq(lp->tx_irq);
 
 	korina_abort_tx(dev);
-	tmp = readl(&lp->tx_dma_regs->dmasm);
-	tmp = tmp | DMA_STAT_FINI | DMA_STAT_ERR;
-	writel(tmp, &lp->tx_dma_regs->dmasm);
+	korina_int_disable_tx(lp);
 
 	korina_abort_rx(dev);
-	tmp = readl(&lp->rx_dma_regs->dmasm);
-	tmp = tmp | DMA_STAT_DONE | DMA_STAT_HALT | DMA_STAT_ERR;
-	writel(tmp, &lp->rx_dma_regs->dmasm);
+	korina_int_disable_rx(lp);
 
 	napi_disable(&lp->napi);
 
-- 
2.11.0

^ permalink raw reply related

* [PATCH net-next 06/10] net: korina: optimize tx descriptor flags processing
From: Roman Yeryomin @ 2017-10-15 16:23 UTC (permalink / raw)
  To: netdev

Signed-off-by: Roman Yeryomin <roman@advem.lv>
---
 drivers/net/ethernet/korina.c | 23 ++++++-----------------
 1 file changed, 6 insertions(+), 17 deletions(-)

diff --git a/drivers/net/ethernet/korina.c b/drivers/net/ethernet/korina.c
index 59d4554c43c9..a076b0c49e6e 100644
--- a/drivers/net/ethernet/korina.c
+++ b/drivers/net/ethernet/korina.c
@@ -342,43 +342,33 @@ static void korina_tx(struct net_device *dev)
 		}
 
 		devcs = lp->td_ring[lp->tx_next_done].devcs;
-		if ((devcs & (ETH_TX_FD | ETH_TX_LD)) !=
-				(ETH_TX_FD | ETH_TX_LD)) {
-			dev->stats.tx_errors++;
-			dev->stats.tx_dropped++;
 
-			/* Should never happen */
-			printk(KERN_ERR "%s: split tx ignored\n",
-							dev->name);
-		} else if (devcs & ETH_TX_TOK) {
-			dev->stats.tx_packets++;
-			dev->stats.tx_bytes +=
-					lp->tx_skb[lp->tx_next_done]->len;
-		} else {
+		if (!(devcs & ETH_TX_TOK)) {
 			dev->stats.tx_errors++;
 			dev->stats.tx_dropped++;
 
 			/* Underflow */
 			if (devcs & ETH_TX_UND)
 				dev->stats.tx_fifo_errors++;
-
 			/* Oversized frame */
 			if (devcs & ETH_TX_OF)
 				dev->stats.tx_aborted_errors++;
-
 			/* Excessive deferrals */
 			if (devcs & ETH_TX_ED)
 				dev->stats.tx_carrier_errors++;
-
 			/* Collisions: medium busy */
 			if (devcs & ETH_TX_EC)
 				dev->stats.collisions++;
-
 			/* Late collision */
 			if (devcs & ETH_TX_LC)
 				dev->stats.tx_window_errors++;
+
+			goto next;
 		}
 
+		dev->stats.tx_packets++;
+		dev->stats.tx_bytes += lp->tx_skb[lp->tx_next_done]->len;
+next:
 		/* We must always free the original skb */
 		if (lp->tx_skb[lp->tx_next_done]) {
 			dev_kfree_skb_any(lp->tx_skb[lp->tx_next_done]);
@@ -394,7 +384,6 @@ static void korina_tx(struct net_device *dev)
 		/* Go on to next transmission */
 		lp->tx_next_done = (lp->tx_next_done + 1) & KORINA_TDS_MASK;
 		td = &lp->td_ring[lp->tx_next_done];
-
 	}
 
 	/* Clear the DMA status register */
-- 
2.11.0

^ permalink raw reply related

* [PATCH net-next 00/10] korina cleanups/optimizations
From: Roman Yeryomin @ 2017-10-15 16:22 UTC (permalink / raw)
  To: netdev

TX optimizations have led to ~15% performance increase (35->40Mbps)
in local tx usecase (tested with iperf v3.2).

Roman Yeryomin (10):
  net: korina: optimize korina_send_packet logic
  net: korina: reorder functions
  net: korina: introduce and use interrupt disable/enable helpers
  net: korina: optimize tx/rx interrupt handlers
  net: korina: remove unused korina_private members
  net: korina: optimize tx descriptor flags processing
  net: korina: move tx to napi context
  net: korina: optimize tx_full condition
  net: korina: use dma api instead of dma_cache_* functions
  net: korina: bump version

 drivers/net/ethernet/korina.c | 503 +++++++++++++++++-------------------------
 1 file changed, 204 insertions(+), 299 deletions(-)

-- 
2.11.0

^ permalink raw reply

* [PATCH net-next 01/10] net: korina: optimize korina_send_packet logic
From: Roman Yeryomin @ 2017-10-15 16:22 UTC (permalink / raw)
  To: netdev

Signed-off-by: Roman Yeryomin <roman@advem.lv>
---
 drivers/net/ethernet/korina.c | 76 ++++++++++++++-----------------------------
 1 file changed, 24 insertions(+), 52 deletions(-)

diff --git a/drivers/net/ethernet/korina.c b/drivers/net/ethernet/korina.c
index 7cecd9dbc111..84b2654e2d06 100644
--- a/drivers/net/ethernet/korina.c
+++ b/drivers/net/ethernet/korina.c
@@ -200,8 +200,7 @@ static int korina_send_packet(struct sk_buff *skb, struct net_device *dev)
 {
 	struct korina_private *lp = netdev_priv(dev);
 	unsigned long flags;
-	u32 length;
-	u32 chain_prev, chain_next;
+	u32 chain_prev, chain_next, dmandptr;
 	struct dma_desc *td;
 
 	spin_lock_irqsave(&lp->lock, flags);
@@ -211,10 +210,9 @@ static int korina_send_packet(struct sk_buff *skb, struct net_device *dev)
 	/* stop queue when full, drop pkts if queue already full */
 	if (lp->tx_count >= (KORINA_NUM_TDS - 2)) {
 		lp->tx_full = 1;
+		netif_stop_queue(dev);
 
-		if (lp->tx_count == (KORINA_NUM_TDS - 2))
-			netif_stop_queue(dev);
-		else {
+		if (lp->tx_count > (KORINA_NUM_TDS - 2)) {
 			dev->stats.tx_dropped++;
 			dev_kfree_skb_any(skb);
 			spin_unlock_irqrestore(&lp->lock, flags);
@@ -224,66 +222,40 @@ static int korina_send_packet(struct sk_buff *skb, struct net_device *dev)
 	}
 
 	lp->tx_count++;
-
 	lp->tx_skb[lp->tx_chain_tail] = skb;
 
-	length = skb->len;
 	dma_cache_wback((u32)skb->data, skb->len);
 
 	/* Setup the transmit descriptor. */
 	dma_cache_inv((u32) td, sizeof(*td));
+
 	td->ca = CPHYSADDR(skb->data);
 	chain_prev = (lp->tx_chain_tail - 1) & KORINA_TDS_MASK;
 	chain_next = (lp->tx_chain_tail + 1) & KORINA_TDS_MASK;
 
-	if (readl(&(lp->tx_dma_regs->dmandptr)) == 0) {
-		if (lp->tx_chain_status == desc_empty) {
-			/* Update tail */
-			td->control = DMA_COUNT(length) |
-					DMA_DESC_COF | DMA_DESC_IOF;
-			/* Move tail */
-			lp->tx_chain_tail = chain_next;
-			/* Write to NDPTR */
-			writel(CPHYSADDR(&lp->td_ring[lp->tx_chain_head]),
+	dmandptr = readl(&(lp->tx_dma_regs->dmandptr));
+	/* Update tail */
+	td->control = DMA_COUNT(skb->len) | DMA_DESC_COF | DMA_DESC_IOF;
+	/* Move tail */
+	lp->tx_chain_tail = chain_next;
+
+	if (lp->tx_chain_status != desc_empty) {
+		/* Link to prev */
+		lp->td_ring[chain_prev].control &= ~DMA_DESC_COF;
+		lp->td_ring[chain_prev].link =  CPHYSADDR(td);
+	}
+
+	if (!dmandptr) {
+		/* Write to NDPTR */
+		writel(CPHYSADDR(&lp->td_ring[lp->tx_chain_head]),
 					&lp->tx_dma_regs->dmandptr);
-			/* Move head to tail */
-			lp->tx_chain_head = lp->tx_chain_tail;
-		} else {
-			/* Update tail */
-			td->control = DMA_COUNT(length) |
-					DMA_DESC_COF | DMA_DESC_IOF;
-			/* Link to prev */
-			lp->td_ring[chain_prev].control &=
-					~DMA_DESC_COF;
-			/* Link to prev */
-			lp->td_ring[chain_prev].link =  CPHYSADDR(td);
-			/* Move tail */
-			lp->tx_chain_tail = chain_next;
-			/* Write to NDPTR */
-			writel(CPHYSADDR(&lp->td_ring[lp->tx_chain_head]),
-					&(lp->tx_dma_regs->dmandptr));
-			/* Move head to tail */
-			lp->tx_chain_head = lp->tx_chain_tail;
-			lp->tx_chain_status = desc_empty;
-		}
+		/* Move head to tail */
+		lp->tx_chain_head = lp->tx_chain_tail;
+		lp->tx_chain_status = desc_empty;
 	} else {
-		if (lp->tx_chain_status == desc_empty) {
-			/* Update tail */
-			td->control = DMA_COUNT(length) |
-					DMA_DESC_COF | DMA_DESC_IOF;
-			/* Move tail */
-			lp->tx_chain_tail = chain_next;
-			lp->tx_chain_status = desc_filled;
-		} else {
-			/* Update tail */
-			td->control = DMA_COUNT(length) |
-					DMA_DESC_COF | DMA_DESC_IOF;
-			lp->td_ring[chain_prev].control &=
-					~DMA_DESC_COF;
-			lp->td_ring[chain_prev].link =  CPHYSADDR(td);
-			lp->tx_chain_tail = chain_next;
-		}
+		lp->tx_chain_status = desc_filled;
 	}
+
 	dma_cache_wback((u32) td, sizeof(*td));
 
 	netif_trans_update(dev);
-- 
2.11.0

^ permalink raw reply related

* Re: [PATCH net-next 1/5] ipv6: addrconf: cleanup locking in ipv6_add_addr
From: David Ahern @ 2017-10-15 16:03 UTC (permalink / raw)
  To: Ido Schimmel; +Cc: netdev, jiri, idosch, kjlx, davem, yoshfuji
In-Reply-To: <20171015155938.GA24270@shredder.mtl.com>

On 10/15/17 9:59 AM, Ido Schimmel wrote:
> On Sun, Oct 15, 2017 at 09:24:07AM -0600, David Ahern wrote:
>> On 10/15/17 1:50 AM, Ido Schimmel wrote:
>>> On Fri, Oct 13, 2017 at 04:02:09PM -0700, David Ahern wrote:
>>>> ipv6_add_addr is called in process context with rtnl lock held
>>>> (e.g., manual config of an address) or during softirq processing
>>>> (e.g., autoconf and address from a router advertisement).
>>>>
>>>> Currently, ipv6_add_addr calls rcu_read_lock_bh shortly after entry
>>>> and does not call unlock until exit, minus the call around the address
>>>> validator notifier. Similarly, addrconf_hash_lock is taken after the
>>>> validator notifier and held until exit. This forces the allocation of
>>>> inet6_ifaddr to always be atomic.
>>>>
>>>> Refactor ipv6_add_addr as follows:
>>>> 1. add an input boolean to discriminate the call path (process context
>>>>    or softirq). This new flag controls whether the alloc can be done
>>>>    with GFP_KERNEL or GFP_ATOMIC.
>>>>
>>>> 2. Move the rcu_read_lock_bh and unlock calls only around functions that
>>>>    do rcu updates.
>>>>
>>>> 3. Remove the in6_dev_hold and put added by 3ad7d2468f79f ("Ipvlan should
>>>>    return an error when an address is already in use."). This was done
>>>>    presumably because rcu_read_unlock_bh needs to be called before calling
>>>>    the validator. Since rcu_read_lock is not needed before the validator
>>>>    runs revert the hold and put added by 3ad7d2468f79f and only do the
>>>>    hold when setting ifp->idev.
>>>>
>>>> 4. move duplicate address check and insertion of new address in the global
>>>>    address hash into a helper. The helper is called after an ifa is
>>>>    allocated and filled in.
>>>>
>>>> This allows the ifa for manually configured addresses to be done with
>>>> GFP_KERNEL and reduces the overall amount of time with rcu_read_lock held
>>>> and hash table spinlock held.
>>>>
>>>> Signed-off-by: David Ahern <dsahern@gmail.com>
>>>
>>> [...]
>>>
>>>> @@ -1073,21 +1085,19 @@ ipv6_add_addr(struct inet6_dev *idev, const struct in6_addr *addr,
>>>>  
>>>>  	in6_ifa_hold(ifa);
>>>>  	write_unlock(&idev->lock);
>>>> -out2:
>>>> +
>>>>  	rcu_read_unlock_bh();
>>>>  
>>>> -	if (likely(err == 0))
>>>> -		inet6addr_notifier_call_chain(NETDEV_UP, ifa);
>>>> -	else {
>>>> +	inet6addr_notifier_call_chain(NETDEV_UP, ifa);
>>>> +out:
>>>> +	if (unlikely(err < 0)) {
>>>> +		if (rt)
>>>> +			ip6_rt_put(rt);
>>>
>>> I believe 'rt' needs to be set to NULL after addrconf_dst_alloc()
>>> fails.
>>
>> The above frees rt and the line below frees the ifa and resets the value
>> to an error, so after the line above rt is no longer referenced.
> 
> Earlier in the code we have:
> 
> rt = addrconf_dst_alloc(idev, addr, false);
> if (IS_ERR(rt)) {
> 	err = PTR_ERR(rt);
> 	goto out;
> }
> 
> So we end up calling ip6_rt_put() with an error value. I believe it
> should be:
> 
> rt = addrconf_dst_alloc(idev, addr, false);
> if (IS_ERR(rt)) {
> 	err = PTR_ERR(rt);
> 	rt = NULL;
> 	goto out;
> }
> 

gotcha. Will fix.

^ permalink raw reply


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