Netdev List
 help / color / mirror / Atom feed
* Re: Performance regression with virtio_net
From: Michael S. Tsirkin @ 2017-07-27 21:30 UTC (permalink / raw)
  To: Seth Forshee; +Cc: netdev, virtualization
In-Reply-To: <20170727211430.viki2jcxbzk2u62c@ubuntu-hedt>

On Thu, Jul 27, 2017 at 04:14:30PM -0500, Seth Forshee wrote:
> On Thu, Jul 27, 2017 at 11:38:52PM +0300, Michael S. Tsirkin wrote:
> > On Thu, Jul 27, 2017 at 12:09:42PM -0500, Seth Forshee wrote:
> > > I'm seeing a performance regression with virtio_net that looks to have
> > > started in 4.12-rc1. I only see it in one context though, downloading
> > > snap packages from the Ubuntu snap store. For example:
> > > 
> > >  https://api.snapcraft.io/api/v1/snaps/download/b8X2psL1ryVrPt5WEmpYiqfr5emixTd7_1797.snap
> > > 
> > > which redirects to Internap's CDN. Normally this downloads in a few
> > > seconds at ~10 MB/s, but with 4.12 and 4.13 it takes minutes with a rate
> > > of ~150 KB/s. Everything else I've tried downloads as normal speeds.
> > 
> > So just wget that URL should be enough?
> 
> Yes. Note that sometimes it starts out faster then slows down.
> > > I bisected this to 680557cf79f8 "virtio_net: rework mergeable buffer
> > > handling". If I revert this on top of 4.13-rc2 (along with other changes
> > > needed to successfully revert it) speeds return to normal.
> > > 
> > > Thanks,
> > > Seth
> > 
> > 
> > Interesting. A more likely suspect would be
> > e377fcc8486d40867c6c217077ad0fa40977e060 - could you please try
> > reverting that one instead?
> 
> I tried it, and I still get slow download speeds. I did test at
> 680557cf79f82623e2c4fd42733077d60a843513 during the bisect so I'm
> reasonably confident that this is the one where things went bad.
> > Also, could you please look at mergeable_rx_buffer_size in sysfs with
> > and without the change?
> 
> In all cases (stock 4.13-rc2, 680557cf79f8 reverted, and e377fcc8486d
> reverted) mergeable_rx_buffer_size was 1536.
> 
> Thanks,
> Seth

Do you see any error counters incrementing after it slows down?

-- 
MST

^ permalink raw reply

* Re: [PATCH net] xgene: Don't fail probe, if there is no clk resource for SGMII interfaces
From: Tom Bogendoerfer @ 2017-07-27 21:39 UTC (permalink / raw)
  To: Laura Abbott; +Cc: isubramanian, kchudgar, qnguyen, netdev, linux-kernel
In-Reply-To: <22ee6284-7b23-7664-d6cf-23687f09a3be@redhat.com>

On Thu, Jul 27, 2017 at 02:03:42PM -0700, Laura Abbott wrote:
> This change causes boot failures for me on my APM Mustang system running
> Fedora rawhide:
> 
> [   16.669089] Synchronous External Abort: synchronous external abort (0x9600000
> [   16.669099] Internal error: : 96000010 [#1] SMP                              
> [   16.669103] Modules linked in: xgene_enet(+) at803x realtek mdio_xgene xgenes
> [   16.669127] CPU: 2 PID: 534 Comm: systemd-udevd Not tainted 4.13.0-0.rc1.git1
> [   16.669128] Hardware name: AppliedMicro X-Gene Mustang Board/X-Gene Mustang 6
> [   16.669131] task: ffff8003e6f8ce00 task.stack: ffff8003e4fd8000              
> [   16.669144] PC is at xgene_enet_wr_mac+0xa0/0x128 [xgene_enet]               
> [   16.669152] LR is at xgene_enet_wr_mac+0x64/0x128 [xgene_enet] 

on the first glance I don't see anything clock related there.

What firmware version is installed on your mustang board ? I saw
ethernet related crashes with mustang boards because the device tree
in firmware was too old for the xgene ethernet driver.

Thoms.

-- 
Crap can work. Given enough thrust pigs will fly, but it's not necessarily a
good idea.                                                [ RFC1925, 2.3 ]

^ permalink raw reply

* [PATCH] mwifiex: fix spelling mistake: "Insuffient" -> "Insufficient"
From: Colin King @ 2017-07-27 22:06 UTC (permalink / raw)
  To: Amitkumar Karwar, Nishant Sarmukadam, Ganapathi Bhat, Xinming Hu,
	Kalle Valo, linux-wireless, netdev
  Cc: linux-kernel

From: Colin Ian King <colin.king@canonical.com>

Trivial fix to spelling mistake in mwifiex_dbg debug message

Signed-off-by: Colin Ian King <colin.king@canonical.com>
---
 drivers/net/wireless/marvell/mwifiex/tdls.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/net/wireless/marvell/mwifiex/tdls.c b/drivers/net/wireless/marvell/mwifiex/tdls.c
index 39cd677d4159..e76af2866a19 100644
--- a/drivers/net/wireless/marvell/mwifiex/tdls.c
+++ b/drivers/net/wireless/marvell/mwifiex/tdls.c
@@ -130,7 +130,7 @@ mwifiex_tdls_append_rates_ie(struct mwifiex_private *priv,
 
 	if (skb_tailroom(skb) < rates_size + 4) {
 		mwifiex_dbg(priv->adapter, ERROR,
-			    "Insuffient space while adding rates\n");
+			    "Insufficient space while adding rates\n");
 		return -ENOMEM;
 	}
 
-- 
2.11.0

^ permalink raw reply related

* [PATCH] wl3501_cs: fix spelling mistake: "Insupported" -> "Unsupported"
From: Colin King @ 2017-07-27 22:09 UTC (permalink / raw)
  To: Kalle Valo, linux-wireless, netdev; +Cc: linux-kernel

From: Colin Ian King <colin.king@canonical.com>

Trivial fix to spelling mistake in printk message

Signed-off-by: Colin Ian King <colin.king@canonical.com>
---
 drivers/net/wireless/wl3501_cs.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/net/wireless/wl3501_cs.c b/drivers/net/wireless/wl3501_cs.c
index acec0d9ec422..da62220b9c01 100644
--- a/drivers/net/wireless/wl3501_cs.c
+++ b/drivers/net/wireless/wl3501_cs.c
@@ -965,7 +965,7 @@ static inline void wl3501_md_ind_interrupt(struct net_device *dev,
 			    &addr4, sizeof(addr4));
 	if (!(addr4[0] == 0xAA && addr4[1] == 0xAA &&
 	      addr4[2] == 0x03 && addr4[4] == 0x00)) {
-		printk(KERN_INFO "Insupported packet type!\n");
+		printk(KERN_INFO "Unsupported packet type!\n");
 		return;
 	}
 	pkt_len = sig.size + 12 - 24 - 4 - 6;
-- 
2.11.0

^ permalink raw reply related

* [PATCH] net: tc35815: fix spelling mistake: "Intterrupt" -> "Interrupt"
From: Colin King @ 2017-07-27 22:15 UTC (permalink / raw)
  To: David S . Miller, Dan Carpenter, Jarod Wilson, Andrew Morton,
	Kees Cook, Eric Dumazet, netdev
  Cc: linux-kernel

From: Colin Ian King <colin.king@canonical.com>

Trivial fix to spelling mistake in printk message

Signed-off-by: Colin Ian King <colin.king@canonical.com>
---
 drivers/net/ethernet/toshiba/tc35815.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/net/ethernet/toshiba/tc35815.c b/drivers/net/ethernet/toshiba/tc35815.c
index d9db8a06afd2..cce9c9ed46aa 100644
--- a/drivers/net/ethernet/toshiba/tc35815.c
+++ b/drivers/net/ethernet/toshiba/tc35815.c
@@ -1338,7 +1338,7 @@ static int tc35815_send_packet(struct sk_buff *skb, struct net_device *dev)
 static void tc35815_fatal_error_interrupt(struct net_device *dev, u32 status)
 {
 	static int count;
-	printk(KERN_WARNING "%s: Fatal Error Intterrupt (%#x):",
+	printk(KERN_WARNING "%s: Fatal Error Interrupt (%#x):",
 	       dev->name, status);
 	if (status & Int_IntPCI)
 		printk(" IntPCI");
-- 
2.11.0

^ permalink raw reply related

* Re: [PATCH v3 1/3] ptp: introduce ptp auxiliary worker
From: Grygorii Strashko @ 2017-07-27 22:36 UTC (permalink / raw)
  To: Richard Cochran
  Cc: David S. Miller, netdev, Sekhar Nori, linux-kernel, linux-omap,
	Wingman Kwok, Ivan Khoronzhuk, John Stultz, Thomas Gleixner
In-Reply-To: <20170727200829.cqe2gb6kl4lfzyux@localhost.localdomain>



On 07/27/2017 03:08 PM, Richard Cochran wrote:
> On Wed, Jul 26, 2017 at 05:11:36PM -0500, Grygorii Strashko wrote:
>> @@ -217,6 +231,19 @@ struct ptp_clock *ptp_clock_register(struct ptp_clock_info *info,
>>   	mutex_init(&ptp->pincfg_mux);
>>   	init_waitqueue_head(&ptp->tsev_wq);
>>   
>> +	if (ptp->info->do_aux_work) {
>> +		char *worker_name = kasprintf(GFP_KERNEL, "ptp%d", ptp->index);
> 
> This string is allocated but never freed.
> 
>> +		kthread_init_delayed_work(&ptp->aux_work, ptp_aux_kworker);
>> +		ptp->kworker = kthread_create_worker(0, worker_name ?
>> +						     worker_name : info->name);

Ops. Right need to add kfree(worker_name) here.


>> +		if (IS_ERR(ptp->kworker)) {
>> +			err = PTR_ERR(ptp->kworker);
>> +			pr_err("failed to create ptp aux_worker %d\n", err);
>> +			goto kworker_err;
>> +		}
>> +	}
>> +
> 
> Thanks,
> Richard
> 

-- 
regards,
-grygorii

^ permalink raw reply

* Re: [PATCH net] xgene: Don't fail probe, if there is no clk resource for SGMII interfaces
From: Laura Abbott @ 2017-07-27 22:39 UTC (permalink / raw)
  To: Tom Bogendoerfer; +Cc: isubramanian, kchudgar, qnguyen, netdev, linux-kernel
In-Reply-To: <20170727213915.GA4902@alpha.franken.de>

On 07/27/2017 02:39 PM, Tom Bogendoerfer wrote:
> On Thu, Jul 27, 2017 at 02:03:42PM -0700, Laura Abbott wrote:
>> This change causes boot failures for me on my APM Mustang system running
>> Fedora rawhide:
>>
>> [   16.669089] Synchronous External Abort: synchronous external abort (0x9600000
>> [   16.669099] Internal error: : 96000010 [#1] SMP                              
>> [   16.669103] Modules linked in: xgene_enet(+) at803x realtek mdio_xgene xgenes
>> [   16.669127] CPU: 2 PID: 534 Comm: systemd-udevd Not tainted 4.13.0-0.rc1.git1
>> [   16.669128] Hardware name: AppliedMicro X-Gene Mustang Board/X-Gene Mustang 6
>> [   16.669131] task: ffff8003e6f8ce00 task.stack: ffff8003e4fd8000              
>> [   16.669144] PC is at xgene_enet_wr_mac+0xa0/0x128 [xgene_enet]               
>> [   16.669152] LR is at xgene_enet_wr_mac+0x64/0x128 [xgene_enet] 
> 
> on the first glance I don't see anything clock related there.
> 

I don't know the intricacies of the Mustang hardware but external
aborts have been a symptom of missing clocks on other hardware.

> What firmware version is installed on your mustang board ? I saw
> ethernet related crashes with mustang boards because the device tree
> in firmware was too old for the xgene ethernet driver.
> 
> Thoms.
> 

TianoCore 3.06.12 UEFI 2.4.0 Aug 12 2016 13:30:51
CPU: APM ARM 64-bit Potenza Rev B0 2400MHz PCP 2400MHz
     32 KB ICACHE, 32 KB DCACHE
     SOC 2000MHz IOBAXI 400MHz AXI 250MHz AHB 200MHz GFC 125MHz
Board: X-Gene Mustang Board
Little Endian build
Slimpro FW:
        Ver: 3.5 (build 03.06.12.00 2016/08/12)
        PMD: 1000 mV
        SOC: 950 mV


Thanks,
Laura

^ permalink raw reply

* [RFC net-next 0/6] tcp: remove prequeue and header prediction
From: Florian Westphal @ 2017-07-27 23:31 UTC (permalink / raw)
  To: netdev; +Cc: ycheng, ncardwell, edumazet, soheil, weiwan, brakmo

This RFC removes tcp prequeueing and header prediction support.

After a hallway discussion with Eric Dumazet some
maybe-not-so-useful-anymore TCP stack features came up, HP and
Prequeue among these.

So this RFC proposes to axe both.

In brief, TCP prequeue assumes a single-process-blocking-read
design, which is not that common anymore, and the most frequently
used high-performance networking program that does this is netperf :)

With more commong (e)poll designs, prequeue doesn't work.

The idea behind prequeueing isn't so bad in itself; it moves
part of tcp processing -- including ack processing (including
retransmit queue processing) into process context.
However, removing it would not just avoid some code, for most
programs it elimiates dead code.

As processing then always occurs in BH context, it would allow us
to experiment e.g. with bulk-freeing of skb heads when a packet acks
data on the retransmit queue.

Header prediction is also less useful nowadays.
For packet trains, GRO will aggregate packets so we do not get
a per-packet benefit.
Header prediction will also break down with light packet loss due to SACK.

So, In short: What do others think?

Florian Westphal (6):
      tcp: remove prequeue support
      tcp: reindent two spots after prequeue removal
      tcp: remove low_latency sysctl
      tcp: remove header prediction
      tcp: remove CA_ACK_SLOWPATH
      tcp: remove unused mib counters

 Documentation/networking/ip-sysctl.txt |    7 
 include/linux/tcp.h                    |   15 -
 include/net/tcp.h                      |   40 ----
 include/uapi/linux/snmp.h              |    8 
 net/ipv4/proc.c                        |    8 
 net/ipv4/sysctl_net_ipv4.c             |    3 
 net/ipv4/tcp.c                         |  109 -----------
 net/ipv4/tcp_input.c                   |  303 +++------------------------------
 net/ipv4/tcp_ipv4.c                    |   63 ------
 net/ipv4/tcp_minisocks.c               |    3 
 net/ipv4/tcp_output.c                  |    2 
 net/ipv4/tcp_timer.c                   |   12 -
 net/ipv4/tcp_westwood.c                |   31 ---
 net/ipv6/tcp_ipv6.c                    |    3 
 14 files changed, 43 insertions(+), 564 deletions(-)

^ permalink raw reply

* [RFC PATCH net-next 1/6] tcp: remove prequeue support
From: Florian Westphal @ 2017-07-27 23:31 UTC (permalink / raw)
  To: netdev
  Cc: ycheng, ncardwell, edumazet, soheil, weiwan, brakmo,
	Florian Westphal
In-Reply-To: <20170727233117.29695-1-fw@strlen.de>

prequeue is a tcp receive optimization that moves part of rx processing from
bh to process context.

This only works if the socket being processed belongs to a process that
blocks in recv on this socket.  In practice, this doesn't happen anymore that
often, as servers normally use an event driven (epoll) model.

Even normal clients (e.g. web browsers) commonly use many tcp connections
in parallel.

Lets remove this.

This has measure impact only on netperf from host to local vm.
There are no changes with bulk transfers that use select/poll etc. to
get notified about new data.

I also see no changes when using netperf between two physical hosts
with ixgbe interfaces.

Signed-off-by: Florian Westphal <fw@strlen.de>
---
 include/linux/tcp.h      |   9 ----
 include/net/tcp.h        |  11 -----
 net/ipv4/tcp.c           | 105 -----------------------------------------------
 net/ipv4/tcp_input.c     |  62 ----------------------------
 net/ipv4/tcp_ipv4.c      |  61 +--------------------------
 net/ipv4/tcp_minisocks.c |   1 -
 net/ipv4/tcp_timer.c     |  12 ------
 net/ipv6/tcp_ipv6.c      |   3 +-
 8 files changed, 2 insertions(+), 262 deletions(-)

diff --git a/include/linux/tcp.h b/include/linux/tcp.h
index 542ca1ae02c4..32fb37cfb0d1 100644
--- a/include/linux/tcp.h
+++ b/include/linux/tcp.h
@@ -192,15 +192,6 @@ struct tcp_sock {
 
 	struct list_head tsq_node; /* anchor in tsq_tasklet.head list */
 
-	/* Data for direct copy to user */
-	struct {
-		struct sk_buff_head	prequeue;
-		struct task_struct	*task;
-		struct msghdr		*msg;
-		int			memory;
-		int			len;
-	} ucopy;
-
 	u32	snd_wl1;	/* Sequence for window update		*/
 	u32	snd_wnd;	/* The window we expect to receive	*/
 	u32	max_window;	/* Maximal window ever seen from peer	*/
diff --git a/include/net/tcp.h b/include/net/tcp.h
index 12d68335acd4..93f115cfc8f8 100644
--- a/include/net/tcp.h
+++ b/include/net/tcp.h
@@ -1244,17 +1244,6 @@ static inline bool tcp_checksum_complete(struct sk_buff *skb)
 		__tcp_checksum_complete(skb);
 }
 
-/* Prequeue for VJ style copy to user, combined with checksumming. */
-
-static inline void tcp_prequeue_init(struct tcp_sock *tp)
-{
-	tp->ucopy.task = NULL;
-	tp->ucopy.len = 0;
-	tp->ucopy.memory = 0;
-	skb_queue_head_init(&tp->ucopy.prequeue);
-}
-
-bool tcp_prequeue(struct sock *sk, struct sk_buff *skb);
 bool tcp_add_backlog(struct sock *sk, struct sk_buff *skb);
 int tcp_filter(struct sock *sk, struct sk_buff *skb);
 
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
index 71ce33decd97..62018ea6f45f 100644
--- a/net/ipv4/tcp.c
+++ b/net/ipv4/tcp.c
@@ -400,7 +400,6 @@ void tcp_init_sock(struct sock *sk)
 
 	tp->out_of_order_queue = RB_ROOT;
 	tcp_init_xmit_timers(sk);
-	tcp_prequeue_init(tp);
 	INIT_LIST_HEAD(&tp->tsq_node);
 
 	icsk->icsk_rto = TCP_TIMEOUT_INIT;
@@ -1525,20 +1524,6 @@ static void tcp_cleanup_rbuf(struct sock *sk, int copied)
 		tcp_send_ack(sk);
 }
 
-static void tcp_prequeue_process(struct sock *sk)
-{
-	struct sk_buff *skb;
-	struct tcp_sock *tp = tcp_sk(sk);
-
-	NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPPREQUEUED);
-
-	while ((skb = __skb_dequeue(&tp->ucopy.prequeue)) != NULL)
-		sk_backlog_rcv(sk, skb);
-
-	/* Clear memory counter. */
-	tp->ucopy.memory = 0;
-}
-
 static struct sk_buff *tcp_recv_skb(struct sock *sk, u32 seq, u32 *off)
 {
 	struct sk_buff *skb;
@@ -1671,7 +1656,6 @@ int tcp_recvmsg(struct sock *sk, struct msghdr *msg, size_t len, int nonblock,
 	int err;
 	int target;		/* Read at least this many bytes */
 	long timeo;
-	struct task_struct *user_recv = NULL;
 	struct sk_buff *skb, *last;
 	u32 urg_hole = 0;
 
@@ -1806,51 +1790,6 @@ int tcp_recvmsg(struct sock *sk, struct msghdr *msg, size_t len, int nonblock,
 
 		tcp_cleanup_rbuf(sk, copied);
 
-		if (!sysctl_tcp_low_latency && tp->ucopy.task == user_recv) {
-			/* Install new reader */
-			if (!user_recv && !(flags & (MSG_TRUNC | MSG_PEEK))) {
-				user_recv = current;
-				tp->ucopy.task = user_recv;
-				tp->ucopy.msg = msg;
-			}
-
-			tp->ucopy.len = len;
-
-			WARN_ON(tp->copied_seq != tp->rcv_nxt &&
-				!(flags & (MSG_PEEK | MSG_TRUNC)));
-
-			/* Ugly... If prequeue is not empty, we have to
-			 * process it before releasing socket, otherwise
-			 * order will be broken at second iteration.
-			 * More elegant solution is required!!!
-			 *
-			 * Look: we have the following (pseudo)queues:
-			 *
-			 * 1. packets in flight
-			 * 2. backlog
-			 * 3. prequeue
-			 * 4. receive_queue
-			 *
-			 * Each queue can be processed only if the next ones
-			 * are empty. At this point we have empty receive_queue.
-			 * But prequeue _can_ be not empty after 2nd iteration,
-			 * when we jumped to start of loop because backlog
-			 * processing added something to receive_queue.
-			 * We cannot release_sock(), because backlog contains
-			 * packets arrived _after_ prequeued ones.
-			 *
-			 * Shortly, algorithm is clear --- to process all
-			 * the queues in order. We could make it more directly,
-			 * requeueing packets from backlog to prequeue, if
-			 * is not empty. It is more elegant, but eats cycles,
-			 * unfortunately.
-			 */
-			if (!skb_queue_empty(&tp->ucopy.prequeue))
-				goto do_prequeue;
-
-			/* __ Set realtime policy in scheduler __ */
-		}
-
 		if (copied >= target) {
 			/* Do not sleep, just process backlog. */
 			release_sock(sk);
@@ -1859,31 +1798,6 @@ int tcp_recvmsg(struct sock *sk, struct msghdr *msg, size_t len, int nonblock,
 			sk_wait_data(sk, &timeo, last);
 		}
 
-		if (user_recv) {
-			int chunk;
-
-			/* __ Restore normal policy in scheduler __ */
-
-			chunk = len - tp->ucopy.len;
-			if (chunk != 0) {
-				NET_ADD_STATS(sock_net(sk), LINUX_MIB_TCPDIRECTCOPYFROMBACKLOG, chunk);
-				len -= chunk;
-				copied += chunk;
-			}
-
-			if (tp->rcv_nxt == tp->copied_seq &&
-			    !skb_queue_empty(&tp->ucopy.prequeue)) {
-do_prequeue:
-				tcp_prequeue_process(sk);
-
-				chunk = len - tp->ucopy.len;
-				if (chunk != 0) {
-					NET_ADD_STATS(sock_net(sk), LINUX_MIB_TCPDIRECTCOPYFROMPREQUEUE, chunk);
-					len -= chunk;
-					copied += chunk;
-				}
-			}
-		}
 		if ((flags & MSG_PEEK) &&
 		    (peek_seq - copied - urg_hole != tp->copied_seq)) {
 			net_dbg_ratelimited("TCP(%s:%d): Application bug, race in MSG_PEEK\n",
@@ -1955,25 +1869,6 @@ int tcp_recvmsg(struct sock *sk, struct msghdr *msg, size_t len, int nonblock,
 		break;
 	} while (len > 0);
 
-	if (user_recv) {
-		if (!skb_queue_empty(&tp->ucopy.prequeue)) {
-			int chunk;
-
-			tp->ucopy.len = copied > 0 ? len : 0;
-
-			tcp_prequeue_process(sk);
-
-			if (copied > 0 && (chunk = len - tp->ucopy.len) != 0) {
-				NET_ADD_STATS(sock_net(sk), LINUX_MIB_TCPDIRECTCOPYFROMPREQUEUE, chunk);
-				len -= chunk;
-				copied += chunk;
-			}
-		}
-
-		tp->ucopy.task = NULL;
-		tp->ucopy.len = 0;
-	}
-
 	/* According to UNIX98, msg_name/msg_namelen are ignored
 	 * on connected socket. I was just happy when found this 8) --ANK
 	 */
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
index adc3f3e9468c..770ce6cb3eca 100644
--- a/net/ipv4/tcp_input.c
+++ b/net/ipv4/tcp_input.c
@@ -4611,22 +4611,6 @@ static void tcp_data_queue(struct sock *sk, struct sk_buff *skb)
 			goto out_of_window;
 
 		/* Ok. In sequence. In window. */
-		if (tp->ucopy.task == current &&
-		    tp->copied_seq == tp->rcv_nxt && tp->ucopy.len &&
-		    sock_owned_by_user(sk) && !tp->urg_data) {
-			int chunk = min_t(unsigned int, skb->len,
-					  tp->ucopy.len);
-
-			__set_current_state(TASK_RUNNING);
-
-			if (!skb_copy_datagram_msg(skb, 0, tp->ucopy.msg, chunk)) {
-				tp->ucopy.len -= chunk;
-				tp->copied_seq += chunk;
-				eaten = (chunk == skb->len);
-				tcp_rcv_space_adjust(sk);
-			}
-		}
-
 		if (eaten <= 0) {
 queue_and_out:
 			if (eaten < 0) {
@@ -5186,26 +5170,6 @@ static void tcp_urg(struct sock *sk, struct sk_buff *skb, const struct tcphdr *t
 	}
 }
 
-static int tcp_copy_to_iovec(struct sock *sk, struct sk_buff *skb, int hlen)
-{
-	struct tcp_sock *tp = tcp_sk(sk);
-	int chunk = skb->len - hlen;
-	int err;
-
-	if (skb_csum_unnecessary(skb))
-		err = skb_copy_datagram_msg(skb, hlen, tp->ucopy.msg, chunk);
-	else
-		err = skb_copy_and_csum_datagram_msg(skb, hlen, tp->ucopy.msg);
-
-	if (!err) {
-		tp->ucopy.len -= chunk;
-		tp->copied_seq += chunk;
-		tcp_rcv_space_adjust(sk);
-	}
-
-	return err;
-}
-
 /* Accept RST for rcv_nxt - 1 after a FIN.
  * When tcp connections are abruptly terminated from Mac OSX (via ^C), a
  * FIN is sent followed by a RST packet. The RST is sent with the same
@@ -5446,32 +5410,6 @@ void tcp_rcv_established(struct sock *sk, struct sk_buff *skb,
 			int eaten = 0;
 			bool fragstolen = false;
 
-			if (tp->ucopy.task == current &&
-			    tp->copied_seq == tp->rcv_nxt &&
-			    len - tcp_header_len <= tp->ucopy.len &&
-			    sock_owned_by_user(sk)) {
-				__set_current_state(TASK_RUNNING);
-
-				if (!tcp_copy_to_iovec(sk, skb, tcp_header_len)) {
-					/* Predicted packet is in window by definition.
-					 * seq == rcv_nxt and rcv_wup <= rcv_nxt.
-					 * Hence, check seq<=rcv_wup reduces to:
-					 */
-					if (tcp_header_len ==
-					    (sizeof(struct tcphdr) +
-					     TCPOLEN_TSTAMP_ALIGNED) &&
-					    tp->rcv_nxt == tp->rcv_wup)
-						tcp_store_ts_recent(tp);
-
-					tcp_rcv_rtt_measure_ts(sk, skb);
-
-					__skb_pull(skb, tcp_header_len);
-					tcp_rcv_nxt_update(tp, TCP_SKB_CB(skb)->end_seq);
-					NET_INC_STATS(sock_net(sk),
-							LINUX_MIB_TCPHPHITSTOUSER);
-					eaten = 1;
-				}
-			}
 			if (!eaten) {
 				if (tcp_checksum_complete(skb))
 					goto csum_error;
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
index 3a19ea28339f..a68eb4577d36 100644
--- a/net/ipv4/tcp_ipv4.c
+++ b/net/ipv4/tcp_ipv4.c
@@ -1541,61 +1541,6 @@ void tcp_v4_early_demux(struct sk_buff *skb)
 	}
 }
 
-/* Packet is added to VJ-style prequeue for processing in process
- * context, if a reader task is waiting. Apparently, this exciting
- * idea (VJ's mail "Re: query about TCP header on tcp-ip" of 07 Sep 93)
- * failed somewhere. Latency? Burstiness? Well, at least now we will
- * see, why it failed. 8)8)				  --ANK
- *
- */
-bool tcp_prequeue(struct sock *sk, struct sk_buff *skb)
-{
-	struct tcp_sock *tp = tcp_sk(sk);
-
-	if (sysctl_tcp_low_latency || !tp->ucopy.task)
-		return false;
-
-	if (skb->len <= tcp_hdrlen(skb) &&
-	    skb_queue_len(&tp->ucopy.prequeue) == 0)
-		return false;
-
-	/* Before escaping RCU protected region, we need to take care of skb
-	 * dst. Prequeue is only enabled for established sockets.
-	 * For such sockets, we might need the skb dst only to set sk->sk_rx_dst
-	 * Instead of doing full sk_rx_dst validity here, let's perform
-	 * an optimistic check.
-	 */
-	if (likely(sk->sk_rx_dst))
-		skb_dst_drop(skb);
-	else
-		skb_dst_force_safe(skb);
-
-	__skb_queue_tail(&tp->ucopy.prequeue, skb);
-	tp->ucopy.memory += skb->truesize;
-	if (skb_queue_len(&tp->ucopy.prequeue) >= 32 ||
-	    tp->ucopy.memory + atomic_read(&sk->sk_rmem_alloc) > sk->sk_rcvbuf) {
-		struct sk_buff *skb1;
-
-		BUG_ON(sock_owned_by_user(sk));
-		__NET_ADD_STATS(sock_net(sk), LINUX_MIB_TCPPREQUEUEDROPPED,
-				skb_queue_len(&tp->ucopy.prequeue));
-
-		while ((skb1 = __skb_dequeue(&tp->ucopy.prequeue)) != NULL)
-			sk_backlog_rcv(sk, skb1);
-
-		tp->ucopy.memory = 0;
-	} else if (skb_queue_len(&tp->ucopy.prequeue) == 1) {
-		wake_up_interruptible_sync_poll(sk_sleep(sk),
-					   POLLIN | POLLRDNORM | POLLRDBAND);
-		if (!inet_csk_ack_scheduled(sk))
-			inet_csk_reset_xmit_timer(sk, ICSK_TIME_DACK,
-						  (3 * tcp_rto_min(sk)) / 4,
-						  TCP_RTO_MAX);
-	}
-	return true;
-}
-EXPORT_SYMBOL(tcp_prequeue);
-
 bool tcp_add_backlog(struct sock *sk, struct sk_buff *skb)
 {
 	u32 limit = sk->sk_rcvbuf + sk->sk_sndbuf;
@@ -1770,8 +1715,7 @@ int tcp_v4_rcv(struct sk_buff *skb)
 	tcp_segs_in(tcp_sk(sk), skb);
 	ret = 0;
 	if (!sock_owned_by_user(sk)) {
-		if (!tcp_prequeue(sk, skb))
-			ret = tcp_v4_do_rcv(sk, skb);
+		ret = tcp_v4_do_rcv(sk, skb);
 	} else if (tcp_add_backlog(sk, skb)) {
 		goto discard_and_relse;
 	}
@@ -1936,9 +1880,6 @@ void tcp_v4_destroy_sock(struct sock *sk)
 	}
 #endif
 
-	/* Clean prequeue, it must be empty really */
-	__skb_queue_purge(&tp->ucopy.prequeue);
-
 	/* Clean up a referenced TCP bind bucket. */
 	if (inet_csk(sk)->icsk_bind_hash)
 		inet_put_port(sk);
diff --git a/net/ipv4/tcp_minisocks.c b/net/ipv4/tcp_minisocks.c
index 0ff83c1637d8..188a6f31356d 100644
--- a/net/ipv4/tcp_minisocks.c
+++ b/net/ipv4/tcp_minisocks.c
@@ -445,7 +445,6 @@ struct sock *tcp_create_openreq_child(const struct sock *sk,
 		newtp->snd_sml = newtp->snd_una =
 		newtp->snd_nxt = newtp->snd_up = treq->snt_isn + 1;
 
-		tcp_prequeue_init(newtp);
 		INIT_LIST_HEAD(&newtp->tsq_node);
 
 		tcp_init_wl(newtp, treq->rcv_isn);
diff --git a/net/ipv4/tcp_timer.c b/net/ipv4/tcp_timer.c
index c0feeeef962a..f753f9d2fee3 100644
--- a/net/ipv4/tcp_timer.c
+++ b/net/ipv4/tcp_timer.c
@@ -239,7 +239,6 @@ static int tcp_write_timeout(struct sock *sk)
 /* Called with BH disabled */
 void tcp_delack_timer_handler(struct sock *sk)
 {
-	struct tcp_sock *tp = tcp_sk(sk);
 	struct inet_connection_sock *icsk = inet_csk(sk);
 
 	sk_mem_reclaim_partial(sk);
@@ -254,17 +253,6 @@ void tcp_delack_timer_handler(struct sock *sk)
 	}
 	icsk->icsk_ack.pending &= ~ICSK_ACK_TIMER;
 
-	if (!skb_queue_empty(&tp->ucopy.prequeue)) {
-		struct sk_buff *skb;
-
-		__NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPSCHEDULERFAILED);
-
-		while ((skb = __skb_dequeue(&tp->ucopy.prequeue)) != NULL)
-			sk_backlog_rcv(sk, skb);
-
-		tp->ucopy.memory = 0;
-	}
-
 	if (inet_csk_ack_scheduled(sk)) {
 		if (!icsk->icsk_ack.pingpong) {
 			/* Delayed ACK missed: inflate ATO. */
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
index 90a32576c3d0..ced5dcf37465 100644
--- a/net/ipv6/tcp_ipv6.c
+++ b/net/ipv6/tcp_ipv6.c
@@ -1505,8 +1505,7 @@ static int tcp_v6_rcv(struct sk_buff *skb)
 	tcp_segs_in(tcp_sk(sk), skb);
 	ret = 0;
 	if (!sock_owned_by_user(sk)) {
-		if (!tcp_prequeue(sk, skb))
-			ret = tcp_v6_do_rcv(sk, skb);
+		ret = tcp_v6_do_rcv(sk, skb);
 	} else if (tcp_add_backlog(sk, skb)) {
 		goto discard_and_relse;
 	}
-- 
2.13.0

^ permalink raw reply related

* [RFC PATCH net-next 2/6] tcp: reindent two spots after prequeue removal
From: Florian Westphal @ 2017-07-27 23:31 UTC (permalink / raw)
  To: netdev
  Cc: ycheng, ncardwell, edumazet, soheil, weiwan, brakmo,
	Florian Westphal
In-Reply-To: <20170727233117.29695-1-fw@strlen.de>

These two branches are now always true, remove the conditional.
objdiff shows no changes.

Signed-off-by: Florian Westphal <fw@strlen.de>
---
 net/ipv4/tcp_input.c | 50 +++++++++++++++++++++++---------------------------
 1 file changed, 23 insertions(+), 27 deletions(-)

diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
index 770ce6cb3eca..87efde9f5a90 100644
--- a/net/ipv4/tcp_input.c
+++ b/net/ipv4/tcp_input.c
@@ -4611,16 +4611,14 @@ static void tcp_data_queue(struct sock *sk, struct sk_buff *skb)
 			goto out_of_window;
 
 		/* Ok. In sequence. In window. */
-		if (eaten <= 0) {
 queue_and_out:
-			if (eaten < 0) {
-				if (skb_queue_len(&sk->sk_receive_queue) == 0)
-					sk_forced_mem_schedule(sk, skb->truesize);
-				else if (tcp_try_rmem_schedule(sk, skb, skb->truesize))
-					goto drop;
-			}
-			eaten = tcp_queue_rcv(sk, skb, 0, &fragstolen);
+		if (eaten < 0) {
+			if (skb_queue_len(&sk->sk_receive_queue) == 0)
+				sk_forced_mem_schedule(sk, skb->truesize);
+			else if (tcp_try_rmem_schedule(sk, skb, skb->truesize))
+				goto drop;
 		}
+		eaten = tcp_queue_rcv(sk, skb, 0, &fragstolen);
 		tcp_rcv_nxt_update(tp, TCP_SKB_CB(skb)->end_seq);
 		if (skb->len)
 			tcp_event_data_recv(sk, skb);
@@ -5410,30 +5408,28 @@ void tcp_rcv_established(struct sock *sk, struct sk_buff *skb,
 			int eaten = 0;
 			bool fragstolen = false;
 
-			if (!eaten) {
-				if (tcp_checksum_complete(skb))
-					goto csum_error;
+			if (tcp_checksum_complete(skb))
+				goto csum_error;
 
-				if ((int)skb->truesize > sk->sk_forward_alloc)
-					goto step5;
+			if ((int)skb->truesize > sk->sk_forward_alloc)
+				goto step5;
 
-				/* Predicted packet is in window by definition.
-				 * seq == rcv_nxt and rcv_wup <= rcv_nxt.
-				 * Hence, check seq<=rcv_wup reduces to:
-				 */
-				if (tcp_header_len ==
-				    (sizeof(struct tcphdr) + TCPOLEN_TSTAMP_ALIGNED) &&
-				    tp->rcv_nxt == tp->rcv_wup)
-					tcp_store_ts_recent(tp);
+			/* Predicted packet is in window by definition.
+			 * seq == rcv_nxt and rcv_wup <= rcv_nxt.
+			 * Hence, check seq<=rcv_wup reduces to:
+			 */
+			if (tcp_header_len ==
+			    (sizeof(struct tcphdr) + TCPOLEN_TSTAMP_ALIGNED) &&
+			    tp->rcv_nxt == tp->rcv_wup)
+				tcp_store_ts_recent(tp);
 
-				tcp_rcv_rtt_measure_ts(sk, skb);
+			tcp_rcv_rtt_measure_ts(sk, skb);
 
-				NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPHPHITS);
+			NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPHPHITS);
 
-				/* Bulk data transfer: receiver */
-				eaten = tcp_queue_rcv(sk, skb, tcp_header_len,
-						      &fragstolen);
-			}
+			/* Bulk data transfer: receiver */
+			eaten = tcp_queue_rcv(sk, skb, tcp_header_len,
+					      &fragstolen);
 
 			tcp_event_data_recv(sk, skb);
 
-- 
2.13.0

^ permalink raw reply related

* [RFC PATCH net-next 3/6] tcp: remove low_latency sysctl
From: Florian Westphal @ 2017-07-27 23:31 UTC (permalink / raw)
  To: netdev
  Cc: ycheng, ncardwell, edumazet, soheil, weiwan, brakmo,
	Florian Westphal
In-Reply-To: <20170727233117.29695-1-fw@strlen.de>

this option was used by the removed prequeue code, it has no effect
anymore.

Signed-off-by: Florian Westphal <fw@strlen.de>
---
 Documentation/networking/ip-sysctl.txt | 7 +------
 include/net/tcp.h                      | 1 -
 net/ipv4/sysctl_net_ipv4.c             | 3 +++
 net/ipv4/tcp_ipv4.c                    | 2 --
 4 files changed, 4 insertions(+), 9 deletions(-)

diff --git a/Documentation/networking/ip-sysctl.txt b/Documentation/networking/ip-sysctl.txt
index f485d553e65c..84c9b8cee780 100644
--- a/Documentation/networking/ip-sysctl.txt
+++ b/Documentation/networking/ip-sysctl.txt
@@ -353,12 +353,7 @@ tcp_l3mdev_accept - BOOLEAN
 	compiled with CONFIG_NET_L3_MASTER_DEV.
 
 tcp_low_latency - BOOLEAN
-	If set, the TCP stack makes decisions that prefer lower
-	latency as opposed to higher throughput.  By default, this
-	option is not set meaning that higher throughput is preferred.
-	An example of an application where this default should be
-	changed would be a Beowulf compute cluster.
-	Default: 0
+	This is a legacy option, it has no effect anymore.
 
 tcp_max_orphans - INTEGER
 	Maximal number of TCP sockets not attached to any user file handle,
diff --git a/include/net/tcp.h b/include/net/tcp.h
index 93f115cfc8f8..8507c81fb0e9 100644
--- a/include/net/tcp.h
+++ b/include/net/tcp.h
@@ -256,7 +256,6 @@ extern int sysctl_tcp_rmem[3];
 extern int sysctl_tcp_app_win;
 extern int sysctl_tcp_adv_win_scale;
 extern int sysctl_tcp_frto;
-extern int sysctl_tcp_low_latency;
 extern int sysctl_tcp_nometrics_save;
 extern int sysctl_tcp_moderate_rcvbuf;
 extern int sysctl_tcp_tso_win_divisor;
diff --git a/net/ipv4/sysctl_net_ipv4.c b/net/ipv4/sysctl_net_ipv4.c
index 9bf809726066..0d3c038d7b04 100644
--- a/net/ipv4/sysctl_net_ipv4.c
+++ b/net/ipv4/sysctl_net_ipv4.c
@@ -45,6 +45,9 @@ static int tcp_syn_retries_max = MAX_TCP_SYNCNT;
 static int ip_ping_group_range_min[] = { 0, 0 };
 static int ip_ping_group_range_max[] = { GID_T_MAX, GID_T_MAX };
 
+/* obsolete */
+static int sysctl_tcp_low_latency __read_mostly;
+
 /* Update system visible IP port range */
 static void set_local_port_range(struct net *net, int range[2])
 {
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
index a68eb4577d36..9b51663cd5a4 100644
--- a/net/ipv4/tcp_ipv4.c
+++ b/net/ipv4/tcp_ipv4.c
@@ -85,8 +85,6 @@
 #include <crypto/hash.h>
 #include <linux/scatterlist.h>
 
-int sysctl_tcp_low_latency __read_mostly;
-
 #ifdef CONFIG_TCP_MD5SIG
 static int tcp_v4_md5_hash_hdr(char *md5_hash, const struct tcp_md5sig_key *key,
 			       __be32 daddr, __be32 saddr, const struct tcphdr *th);
-- 
2.13.0

^ permalink raw reply related

* [RFC PATCH net-next 4/6] tcp: remove header prediction
From: Florian Westphal @ 2017-07-27 23:31 UTC (permalink / raw)
  To: netdev
  Cc: ycheng, ncardwell, edumazet, soheil, weiwan, brakmo,
	Florian Westphal
In-Reply-To: <20170727233117.29695-1-fw@strlen.de>

Like prequeue, I am not sure this is overly useful nowadays.

If we receive a train of packets, GRO will aggregate them if the
headers are the same (HP predates GRO by several years) so we don't
get a per-packet benefit, only a per-aggregated-packet one.

Signed-off-by: Florian Westphal <fw@strlen.de>
---
 include/linux/tcp.h      |   6 --
 include/net/tcp.h        |  23 ------
 net/ipv4/tcp.c           |   4 +-
 net/ipv4/tcp_input.c     | 192 +++--------------------------------------------
 net/ipv4/tcp_minisocks.c |   2 -
 net/ipv4/tcp_output.c    |   2 -
 6 files changed, 10 insertions(+), 219 deletions(-)

diff --git a/include/linux/tcp.h b/include/linux/tcp.h
index 32fb37cfb0d1..d7389ea36e10 100644
--- a/include/linux/tcp.h
+++ b/include/linux/tcp.h
@@ -148,12 +148,6 @@ struct tcp_sock {
 	u16	gso_segs;	/* Max number of segs per GSO packet	*/
 
 /*
- *	Header prediction flags
- *	0x5?10 << 16 + snd_wnd in net byte order
- */
-	__be32	pred_flags;
-
-/*
  *	RFC793 variables by their proper names. This means you can
  *	read the code and the spec side by side (and laugh ...)
  *	See RFC793 and RFC1122. The RFC writes these in capitals.
diff --git a/include/net/tcp.h b/include/net/tcp.h
index 8507c81fb0e9..8f11b82b5b5a 100644
--- a/include/net/tcp.h
+++ b/include/net/tcp.h
@@ -631,29 +631,6 @@ static inline u32 __tcp_set_rto(const struct tcp_sock *tp)
 	return usecs_to_jiffies((tp->srtt_us >> 3) + tp->rttvar_us);
 }
 
-static inline void __tcp_fast_path_on(struct tcp_sock *tp, u32 snd_wnd)
-{
-	tp->pred_flags = htonl((tp->tcp_header_len << 26) |
-			       ntohl(TCP_FLAG_ACK) |
-			       snd_wnd);
-}
-
-static inline void tcp_fast_path_on(struct tcp_sock *tp)
-{
-	__tcp_fast_path_on(tp, tp->snd_wnd >> tp->rx_opt.snd_wscale);
-}
-
-static inline void tcp_fast_path_check(struct sock *sk)
-{
-	struct tcp_sock *tp = tcp_sk(sk);
-
-	if (RB_EMPTY_ROOT(&tp->out_of_order_queue) &&
-	    tp->rcv_wnd &&
-	    atomic_read(&sk->sk_rmem_alloc) < sk->sk_rcvbuf &&
-	    !tp->urg_data)
-		tcp_fast_path_on(tp);
-}
-
 /* Compute the actual rto_min value */
 static inline u32 tcp_rto_min(struct sock *sk)
 {
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
index 62018ea6f45f..e022874d509f 100644
--- a/net/ipv4/tcp.c
+++ b/net/ipv4/tcp.c
@@ -1848,10 +1848,8 @@ int tcp_recvmsg(struct sock *sk, struct msghdr *msg, size_t len, int nonblock,
 		tcp_rcv_space_adjust(sk);
 
 skip_copy:
-		if (tp->urg_data && after(tp->copied_seq, tp->urg_seq)) {
+		if (tp->urg_data && after(tp->copied_seq, tp->urg_seq))
 			tp->urg_data = 0;
-			tcp_fast_path_check(sk);
-		}
 		if (used + offset < skb->len)
 			continue;
 
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
index 87efde9f5a90..bfde9d7d210e 100644
--- a/net/ipv4/tcp_input.c
+++ b/net/ipv4/tcp_input.c
@@ -103,7 +103,6 @@ int sysctl_tcp_invalid_ratelimit __read_mostly = HZ/2;
 #define FLAG_DATA_SACKED	0x20 /* New SACK.				*/
 #define FLAG_ECE		0x40 /* ECE in this ACK				*/
 #define FLAG_LOST_RETRANS	0x80 /* This ACK marks some retransmission lost */
-#define FLAG_SLOWPATH		0x100 /* Do not skip RFC checks for window update.*/
 #define FLAG_ORIG_SACK_ACKED	0x200 /* Never retransmitted data are (s)acked	*/
 #define FLAG_SND_UNA_ADVANCED	0x400 /* Snd_una was changed (!= FLAG_DATA_ACKED) */
 #define FLAG_DSACKING_ACK	0x800 /* SACK blocks contained D-SACK info */
@@ -3367,12 +3366,6 @@ static int tcp_ack_update_window(struct sock *sk, const struct sk_buff *skb, u32
 		if (tp->snd_wnd != nwin) {
 			tp->snd_wnd = nwin;
 
-			/* Note, it is the only place, where
-			 * fast path is recovered for sending TCP.
-			 */
-			tp->pred_flags = 0;
-			tcp_fast_path_check(sk);
-
 			if (tcp_send_head(sk))
 				tcp_slow_start_after_idle_check(sk);
 
@@ -3597,19 +3590,7 @@ static int tcp_ack(struct sock *sk, const struct sk_buff *skb, int flag)
 	if (flag & FLAG_UPDATE_TS_RECENT)
 		tcp_replace_ts_recent(tp, TCP_SKB_CB(skb)->seq);
 
-	if (!(flag & FLAG_SLOWPATH) && after(ack, prior_snd_una)) {
-		/* Window is constant, pure forward advance.
-		 * No more checks are required.
-		 * Note, we use the fact that SND.UNA>=SND.WL2.
-		 */
-		tcp_update_wl(tp, ack_seq);
-		tcp_snd_una_update(tp, ack);
-		flag |= FLAG_WIN_UPDATE;
-
-		tcp_in_ack_event(sk, CA_ACK_WIN_UPDATE);
-
-		NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPHPACKS);
-	} else {
+	{
 		u32 ack_ev_flags = CA_ACK_SLOWPATH;
 
 		if (ack_seq != TCP_SKB_CB(skb)->end_seq)
@@ -4398,8 +4379,6 @@ static void tcp_data_queue_ofo(struct sock *sk, struct sk_buff *skb)
 		return;
 	}
 
-	/* Disable header prediction. */
-	tp->pred_flags = 0;
 	inet_csk_schedule_ack(sk);
 
 	NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPOFOQUEUE);
@@ -4638,8 +4617,6 @@ static void tcp_data_queue(struct sock *sk, struct sk_buff *skb)
 		if (tp->rx_opt.num_sacks)
 			tcp_sack_remove(tp);
 
-		tcp_fast_path_check(sk);
-
 		if (eaten > 0)
 			kfree_skb_partial(skb, fragstolen);
 		if (!sock_flag(sk, SOCK_DEAD))
@@ -4965,7 +4942,6 @@ static int tcp_prune_queue(struct sock *sk)
 	NET_INC_STATS(sock_net(sk), LINUX_MIB_RCVPRUNED);
 
 	/* Massive buffer overcommit. */
-	tp->pred_flags = 0;
 	return -1;
 }
 
@@ -5137,9 +5113,6 @@ static void tcp_check_urg(struct sock *sk, const struct tcphdr *th)
 
 	tp->urg_data = TCP_URG_NOTYET;
 	tp->urg_seq = ptr;
-
-	/* Disable header prediction. */
-	tp->pred_flags = 0;
 }
 
 /* This is the 'fast' part of urgent handling. */
@@ -5298,26 +5271,6 @@ static bool tcp_validate_incoming(struct sock *sk, struct sk_buff *skb,
 
 /*
  *	TCP receive function for the ESTABLISHED state.
- *
- *	It is split into a fast path and a slow path. The fast path is
- * 	disabled when:
- *	- A zero window was announced from us - zero window probing
- *        is only handled properly in the slow path.
- *	- Out of order segments arrived.
- *	- Urgent data is expected.
- *	- There is no buffer space left
- *	- Unexpected TCP flags/window values/header lengths are received
- *	  (detected by checking the TCP header against pred_flags)
- *	- Data is sent in both directions. Fast path only supports pure senders
- *	  or pure receivers (this means either the sequence number or the ack
- *	  value must stay constant)
- *	- Unexpected TCP option.
- *
- *	When these conditions are not satisfied it drops into a standard
- *	receive procedure patterned after RFC793 to handle all cases.
- *	The first three cases are guaranteed by proper pred_flags setting,
- *	the rest is checked inline. Fast processing is turned on in
- *	tcp_data_queue when everything is OK.
  */
 void tcp_rcv_established(struct sock *sk, struct sk_buff *skb,
 			 const struct tcphdr *th)
@@ -5328,144 +5281,19 @@ void tcp_rcv_established(struct sock *sk, struct sk_buff *skb,
 	tcp_mstamp_refresh(tp);
 	if (unlikely(!sk->sk_rx_dst))
 		inet_csk(sk)->icsk_af_ops->sk_rx_dst_set(sk, skb);
-	/*
-	 *	Header prediction.
-	 *	The code loosely follows the one in the famous
-	 *	"30 instruction TCP receive" Van Jacobson mail.
-	 *
-	 *	Van's trick is to deposit buffers into socket queue
-	 *	on a device interrupt, to call tcp_recv function
-	 *	on the receive process context and checksum and copy
-	 *	the buffer to user space. smart...
-	 *
-	 *	Our current scheme is not silly either but we take the
-	 *	extra cost of the net_bh soft interrupt processing...
-	 *	We do checksum and copy also but from device to kernel.
-	 */
 
 	tp->rx_opt.saw_tstamp = 0;
 
-	/*	pred_flags is 0xS?10 << 16 + snd_wnd
-	 *	if header_prediction is to be made
-	 *	'S' will always be tp->tcp_header_len >> 2
-	 *	'?' will be 0 for the fast path, otherwise pred_flags is 0 to
-	 *  turn it off	(when there are holes in the receive
-	 *	 space for instance)
-	 *	PSH flag is ignored.
-	 */
-
-	if ((tcp_flag_word(th) & TCP_HP_BITS) == tp->pred_flags &&
-	    TCP_SKB_CB(skb)->seq == tp->rcv_nxt &&
-	    !after(TCP_SKB_CB(skb)->ack_seq, tp->snd_nxt)) {
-		int tcp_header_len = tp->tcp_header_len;
-
-		/* Timestamp header prediction: tcp_header_len
-		 * is automatically equal to th->doff*4 due to pred_flags
-		 * match.
-		 */
-
-		/* Check timestamp */
-		if (tcp_header_len == sizeof(struct tcphdr) + TCPOLEN_TSTAMP_ALIGNED) {
-			/* No? Slow path! */
-			if (!tcp_parse_aligned_timestamp(tp, th))
-				goto slow_path;
-
-			/* If PAWS failed, check it more carefully in slow path */
-			if ((s32)(tp->rx_opt.rcv_tsval - tp->rx_opt.ts_recent) < 0)
-				goto slow_path;
-
-			/* DO NOT update ts_recent here, if checksum fails
-			 * and timestamp was corrupted part, it will result
-			 * in a hung connection since we will drop all
-			 * future packets due to the PAWS test.
-			 */
-		}
-
-		if (len <= tcp_header_len) {
-			/* Bulk data transfer: sender */
-			if (len == tcp_header_len) {
-				/* Predicted packet is in window by definition.
-				 * seq == rcv_nxt and rcv_wup <= rcv_nxt.
-				 * Hence, check seq<=rcv_wup reduces to:
-				 */
-				if (tcp_header_len ==
-				    (sizeof(struct tcphdr) + TCPOLEN_TSTAMP_ALIGNED) &&
-				    tp->rcv_nxt == tp->rcv_wup)
-					tcp_store_ts_recent(tp);
-
-				/* We know that such packets are checksummed
-				 * on entry.
-				 */
-				tcp_ack(sk, skb, 0);
-				__kfree_skb(skb);
-				tcp_data_snd_check(sk);
-				return;
-			} else { /* Header too small */
-				TCP_INC_STATS(sock_net(sk), TCP_MIB_INERRS);
-				goto discard;
-			}
-		} else {
-			int eaten = 0;
-			bool fragstolen = false;
-
-			if (tcp_checksum_complete(skb))
-				goto csum_error;
-
-			if ((int)skb->truesize > sk->sk_forward_alloc)
-				goto step5;
-
-			/* Predicted packet is in window by definition.
-			 * seq == rcv_nxt and rcv_wup <= rcv_nxt.
-			 * Hence, check seq<=rcv_wup reduces to:
-			 */
-			if (tcp_header_len ==
-			    (sizeof(struct tcphdr) + TCPOLEN_TSTAMP_ALIGNED) &&
-			    tp->rcv_nxt == tp->rcv_wup)
-				tcp_store_ts_recent(tp);
-
-			tcp_rcv_rtt_measure_ts(sk, skb);
-
-			NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPHPHITS);
-
-			/* Bulk data transfer: receiver */
-			eaten = tcp_queue_rcv(sk, skb, tcp_header_len,
-					      &fragstolen);
-
-			tcp_event_data_recv(sk, skb);
-
-			if (TCP_SKB_CB(skb)->ack_seq != tp->snd_una) {
-				/* Well, only one small jumplet in fast path... */
-				tcp_ack(sk, skb, FLAG_DATA);
-				tcp_data_snd_check(sk);
-				if (!inet_csk_ack_scheduled(sk))
-					goto no_ack;
-			}
-
-			__tcp_ack_snd_check(sk, 0);
-no_ack:
-			if (eaten)
-				kfree_skb_partial(skb, fragstolen);
-			sk->sk_data_ready(sk);
-			return;
-		}
-	}
-
-slow_path:
 	if (len < (th->doff << 2) || tcp_checksum_complete(skb))
 		goto csum_error;
 
 	if (!th->ack && !th->rst && !th->syn)
 		goto discard;
 
-	/*
-	 *	Standard slow path.
-	 */
-
 	if (!tcp_validate_incoming(sk, skb, th, 1))
 		return;
 
-step5:
-	if (tcp_ack(sk, skb, FLAG_SLOWPATH | FLAG_UPDATE_TS_RECENT) < 0)
+	if (tcp_ack(sk, skb, FLAG_UPDATE_TS_RECENT) < 0)
 		goto discard;
 
 	tcp_rcv_rtt_measure_ts(sk, skb);
@@ -5519,11 +5347,10 @@ void tcp_finish_connect(struct sock *sk, struct sk_buff *skb)
 	if (sock_flag(sk, SOCK_KEEPOPEN))
 		inet_csk_reset_keepalive_timer(sk, keepalive_time_when(tp));
 
-	if (!tp->rx_opt.snd_wscale)
-		__tcp_fast_path_on(tp, tp->snd_wnd);
-	else
-		tp->pred_flags = 0;
-
+	if (!sock_flag(sk, SOCK_DEAD)) {
+		sk->sk_state_change(sk);
+		sk_wake_async(sk, SOCK_WAKE_IO, POLL_OUT);
+	}
 }
 
 static bool tcp_rcv_fastopen_synack(struct sock *sk, struct sk_buff *synack,
@@ -5652,7 +5479,7 @@ static int tcp_rcv_synsent_state_process(struct sock *sk, struct sk_buff *skb,
 		tcp_ecn_rcv_synack(tp, th);
 
 		tcp_init_wl(tp, TCP_SKB_CB(skb)->seq);
-		tcp_ack(sk, skb, FLAG_SLOWPATH);
+		tcp_ack(sk, skb, 0);
 
 		/* Ok.. it's good. Set up sequence numbers and
 		 * move to established.
@@ -5888,8 +5715,8 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb)
 		return 0;
 
 	/* step 5: check the ACK field */
-	acceptable = tcp_ack(sk, skb, FLAG_SLOWPATH |
-				      FLAG_UPDATE_TS_RECENT |
+
+	acceptable = tcp_ack(sk, skb, FLAG_UPDATE_TS_RECENT |
 				      FLAG_NO_CHALLENGE_ACK) > 0;
 
 	if (!acceptable) {
@@ -5957,7 +5784,6 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb)
 		tp->lsndtime = tcp_jiffies32;
 
 		tcp_initialize_rcv_mss(sk);
-		tcp_fast_path_on(tp);
 		break;
 
 	case TCP_FIN_WAIT1: {
diff --git a/net/ipv4/tcp_minisocks.c b/net/ipv4/tcp_minisocks.c
index 188a6f31356d..1537b87c657f 100644
--- a/net/ipv4/tcp_minisocks.c
+++ b/net/ipv4/tcp_minisocks.c
@@ -436,8 +436,6 @@ struct sock *tcp_create_openreq_child(const struct sock *sk,
 		struct tcp_sock *newtp = tcp_sk(newsk);
 
 		/* Now setup tcp_sock */
-		newtp->pred_flags = 0;
-
 		newtp->rcv_wup = newtp->copied_seq =
 		newtp->rcv_nxt = treq->rcv_isn + 1;
 		newtp->segs_in = 1;
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c
index 886d874775df..8380464aead1 100644
--- a/net/ipv4/tcp_output.c
+++ b/net/ipv4/tcp_output.c
@@ -295,9 +295,7 @@ static u16 tcp_select_window(struct sock *sk)
 	/* RFC1323 scaling applied */
 	new_win >>= tp->rx_opt.rcv_wscale;
 
-	/* If we advertise zero window, disable fast path. */
 	if (new_win == 0) {
-		tp->pred_flags = 0;
 		if (old_win)
 			NET_INC_STATS(sock_net(sk),
 				      LINUX_MIB_TCPTOZEROWINDOWADV);
-- 
2.13.0

^ permalink raw reply related

* [RFC PATCH net-next 5/6] tcp: remove CA_ACK_SLOWPATH
From: Florian Westphal @ 2017-07-27 23:31 UTC (permalink / raw)
  To: netdev
  Cc: ycheng, ncardwell, edumazet, soheil, weiwan, brakmo,
	Florian Westphal
In-Reply-To: <20170727233117.29695-1-fw@strlen.de>

re-indent tcp_ack, and remove CA_ACK_SLOWPATH; it is always set now.

Signed-off-by: Florian Westphal <fw@strlen.de>
---
 include/net/tcp.h       |  5 ++---
 net/ipv4/tcp_input.c    | 35 ++++++++++++++++-------------------
 net/ipv4/tcp_westwood.c | 31 ++++---------------------------
 3 files changed, 22 insertions(+), 49 deletions(-)

diff --git a/include/net/tcp.h b/include/net/tcp.h
index 8f11b82b5b5a..3ecb62811004 100644
--- a/include/net/tcp.h
+++ b/include/net/tcp.h
@@ -880,9 +880,8 @@ enum tcp_ca_event {
 
 /* Information about inbound ACK, passed to cong_ops->in_ack_event() */
 enum tcp_ca_ack_event_flags {
-	CA_ACK_SLOWPATH		= (1 << 0),	/* In slow path processing */
-	CA_ACK_WIN_UPDATE	= (1 << 1),	/* ACK updated window */
-	CA_ACK_ECE		= (1 << 2),	/* ECE bit is set on ack */
+	CA_ACK_WIN_UPDATE	= (1 << 0),	/* ACK updated window */
+	CA_ACK_ECE		= (1 << 1),	/* ECE bit is set on ack */
 };
 
 /*
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
index bfde9d7d210e..af0a98d54b62 100644
--- a/net/ipv4/tcp_input.c
+++ b/net/ipv4/tcp_input.c
@@ -3547,6 +3547,7 @@ static int tcp_ack(struct sock *sk, const struct sk_buff *skb, int flag)
 	u32 lost = tp->lost;
 	int acked = 0; /* Number of packets newly acked */
 	int rexmit = REXMIT_NONE; /* Flag to (re)transmit to recover losses */
+	u32 ack_ev_flags = 0;
 
 	sack_state.first_sackt = 0;
 	sack_state.rate = &rs;
@@ -3590,30 +3591,26 @@ static int tcp_ack(struct sock *sk, const struct sk_buff *skb, int flag)
 	if (flag & FLAG_UPDATE_TS_RECENT)
 		tcp_replace_ts_recent(tp, TCP_SKB_CB(skb)->seq);
 
-	{
-		u32 ack_ev_flags = CA_ACK_SLOWPATH;
-
-		if (ack_seq != TCP_SKB_CB(skb)->end_seq)
-			flag |= FLAG_DATA;
-		else
-			NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPPUREACKS);
+	if (ack_seq != TCP_SKB_CB(skb)->end_seq)
+		flag |= FLAG_DATA;
+	else
+		NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPPUREACKS);
 
-		flag |= tcp_ack_update_window(sk, skb, ack, ack_seq);
+	flag |= tcp_ack_update_window(sk, skb, ack, ack_seq);
 
-		if (TCP_SKB_CB(skb)->sacked)
-			flag |= tcp_sacktag_write_queue(sk, skb, prior_snd_una,
-							&sack_state);
+	if (TCP_SKB_CB(skb)->sacked)
+		flag |= tcp_sacktag_write_queue(sk, skb, prior_snd_una,
+						&sack_state);
 
-		if (tcp_ecn_rcv_ecn_echo(tp, tcp_hdr(skb))) {
-			flag |= FLAG_ECE;
-			ack_ev_flags |= CA_ACK_ECE;
-		}
+	if (tcp_ecn_rcv_ecn_echo(tp, tcp_hdr(skb))) {
+		flag |= FLAG_ECE;
+		ack_ev_flags = CA_ACK_ECE;
+	}
 
-		if (flag & FLAG_WIN_UPDATE)
-			ack_ev_flags |= CA_ACK_WIN_UPDATE;
+	if (flag & FLAG_WIN_UPDATE)
+		ack_ev_flags |= CA_ACK_WIN_UPDATE;
 
-		tcp_in_ack_event(sk, ack_ev_flags);
-	}
+	tcp_in_ack_event(sk, ack_ev_flags);
 
 	/* We passed data and got it acked, remove any soft error
 	 * log. Something worked...
diff --git a/net/ipv4/tcp_westwood.c b/net/ipv4/tcp_westwood.c
index bec9cafbe3f9..e5de84310949 100644
--- a/net/ipv4/tcp_westwood.c
+++ b/net/ipv4/tcp_westwood.c
@@ -154,24 +154,6 @@ static inline void update_rtt_min(struct westwood *w)
 }
 
 /*
- * @westwood_fast_bw
- * It is called when we are in fast path. In particular it is called when
- * header prediction is successful. In such case in fact update is
- * straight forward and doesn't need any particular care.
- */
-static inline void westwood_fast_bw(struct sock *sk)
-{
-	const struct tcp_sock *tp = tcp_sk(sk);
-	struct westwood *w = inet_csk_ca(sk);
-
-	westwood_update_window(sk);
-
-	w->bk += tp->snd_una - w->snd_una;
-	w->snd_una = tp->snd_una;
-	update_rtt_min(w);
-}
-
-/*
  * @westwood_acked_count
  * This function evaluates cumul_ack for evaluating bk in case of
  * delayed or partial acks.
@@ -223,17 +205,12 @@ static u32 tcp_westwood_bw_rttmin(const struct sock *sk)
 
 static void tcp_westwood_ack(struct sock *sk, u32 ack_flags)
 {
-	if (ack_flags & CA_ACK_SLOWPATH) {
-		struct westwood *w = inet_csk_ca(sk);
-
-		westwood_update_window(sk);
-		w->bk += westwood_acked_count(sk);
+	struct westwood *w = inet_csk_ca(sk);
 
-		update_rtt_min(w);
-		return;
-	}
+	westwood_update_window(sk);
+	w->bk += westwood_acked_count(sk);
 
-	westwood_fast_bw(sk);
+	update_rtt_min(w);
 }
 
 static void tcp_westwood_event(struct sock *sk, enum tcp_ca_event event)
-- 
2.13.0

^ permalink raw reply related

* [RFC PATCH net-next 6/6] tcp: remove unused mib counters
From: Florian Westphal @ 2017-07-27 23:31 UTC (permalink / raw)
  To: netdev
  Cc: ycheng, ncardwell, edumazet, soheil, weiwan, brakmo,
	Florian Westphal
In-Reply-To: <20170727233117.29695-1-fw@strlen.de>

was used by tcp prequeue, TCPFORWARDRETRANS use was removed in january.

Signed-off-by: Florian Westphal <fw@strlen.de>
---
 include/uapi/linux/snmp.h | 8 --------
 net/ipv4/proc.c           | 8 --------
 2 files changed, 16 deletions(-)

diff --git a/include/uapi/linux/snmp.h b/include/uapi/linux/snmp.h
index d85693295798..73c15719fd35 100644
--- a/include/uapi/linux/snmp.h
+++ b/include/uapi/linux/snmp.h
@@ -185,13 +185,7 @@ enum
 	LINUX_MIB_LISTENOVERFLOWS,		/* ListenOverflows */
 	LINUX_MIB_LISTENDROPS,			/* ListenDrops */
 	LINUX_MIB_TCPPREQUEUED,			/* TCPPrequeued */
-	LINUX_MIB_TCPDIRECTCOPYFROMBACKLOG,	/* TCPDirectCopyFromBacklog */
-	LINUX_MIB_TCPDIRECTCOPYFROMPREQUEUE,	/* TCPDirectCopyFromPrequeue */
-	LINUX_MIB_TCPPREQUEUEDROPPED,		/* TCPPrequeueDropped */
-	LINUX_MIB_TCPHPHITS,			/* TCPHPHits */
-	LINUX_MIB_TCPHPHITSTOUSER,		/* TCPHPHitsToUser */
 	LINUX_MIB_TCPPUREACKS,			/* TCPPureAcks */
-	LINUX_MIB_TCPHPACKS,			/* TCPHPAcks */
 	LINUX_MIB_TCPRENORECOVERY,		/* TCPRenoRecovery */
 	LINUX_MIB_TCPSACKRECOVERY,		/* TCPSackRecovery */
 	LINUX_MIB_TCPSACKRENEGING,		/* TCPSACKReneging */
@@ -208,14 +202,12 @@ enum
 	LINUX_MIB_TCPSACKFAILURES,		/* TCPSackFailures */
 	LINUX_MIB_TCPLOSSFAILURES,		/* TCPLossFailures */
 	LINUX_MIB_TCPFASTRETRANS,		/* TCPFastRetrans */
-	LINUX_MIB_TCPFORWARDRETRANS,		/* TCPForwardRetrans */
 	LINUX_MIB_TCPSLOWSTARTRETRANS,		/* TCPSlowStartRetrans */
 	LINUX_MIB_TCPTIMEOUTS,			/* TCPTimeouts */
 	LINUX_MIB_TCPLOSSPROBES,		/* TCPLossProbes */
 	LINUX_MIB_TCPLOSSPROBERECOVERY,		/* TCPLossProbeRecovery */
 	LINUX_MIB_TCPRENORECOVERYFAIL,		/* TCPRenoRecoveryFail */
 	LINUX_MIB_TCPSACKRECOVERYFAIL,		/* TCPSackRecoveryFail */
-	LINUX_MIB_TCPSCHEDULERFAILED,		/* TCPSchedulerFailed */
 	LINUX_MIB_TCPRCVCOLLAPSED,		/* TCPRcvCollapsed */
 	LINUX_MIB_TCPDSACKOLDSENT,		/* TCPDSACKOldSent */
 	LINUX_MIB_TCPDSACKOFOSENT,		/* TCPDSACKOfoSent */
diff --git a/net/ipv4/proc.c b/net/ipv4/proc.c
index 43eb6567b3a0..e2c91375cadc 100644
--- a/net/ipv4/proc.c
+++ b/net/ipv4/proc.c
@@ -207,13 +207,7 @@ static const struct snmp_mib snmp4_net_list[] = {
 	SNMP_MIB_ITEM("ListenOverflows", LINUX_MIB_LISTENOVERFLOWS),
 	SNMP_MIB_ITEM("ListenDrops", LINUX_MIB_LISTENDROPS),
 	SNMP_MIB_ITEM("TCPPrequeued", LINUX_MIB_TCPPREQUEUED),
-	SNMP_MIB_ITEM("TCPDirectCopyFromBacklog", LINUX_MIB_TCPDIRECTCOPYFROMBACKLOG),
-	SNMP_MIB_ITEM("TCPDirectCopyFromPrequeue", LINUX_MIB_TCPDIRECTCOPYFROMPREQUEUE),
-	SNMP_MIB_ITEM("TCPPrequeueDropped", LINUX_MIB_TCPPREQUEUEDROPPED),
-	SNMP_MIB_ITEM("TCPHPHits", LINUX_MIB_TCPHPHITS),
-	SNMP_MIB_ITEM("TCPHPHitsToUser", LINUX_MIB_TCPHPHITSTOUSER),
 	SNMP_MIB_ITEM("TCPPureAcks", LINUX_MIB_TCPPUREACKS),
-	SNMP_MIB_ITEM("TCPHPAcks", LINUX_MIB_TCPHPACKS),
 	SNMP_MIB_ITEM("TCPRenoRecovery", LINUX_MIB_TCPRENORECOVERY),
 	SNMP_MIB_ITEM("TCPSackRecovery", LINUX_MIB_TCPSACKRECOVERY),
 	SNMP_MIB_ITEM("TCPSACKReneging", LINUX_MIB_TCPSACKRENEGING),
@@ -230,14 +224,12 @@ static const struct snmp_mib snmp4_net_list[] = {
 	SNMP_MIB_ITEM("TCPSackFailures", LINUX_MIB_TCPSACKFAILURES),
 	SNMP_MIB_ITEM("TCPLossFailures", LINUX_MIB_TCPLOSSFAILURES),
 	SNMP_MIB_ITEM("TCPFastRetrans", LINUX_MIB_TCPFASTRETRANS),
-	SNMP_MIB_ITEM("TCPForwardRetrans", LINUX_MIB_TCPFORWARDRETRANS),
 	SNMP_MIB_ITEM("TCPSlowStartRetrans", LINUX_MIB_TCPSLOWSTARTRETRANS),
 	SNMP_MIB_ITEM("TCPTimeouts", LINUX_MIB_TCPTIMEOUTS),
 	SNMP_MIB_ITEM("TCPLossProbes", LINUX_MIB_TCPLOSSPROBES),
 	SNMP_MIB_ITEM("TCPLossProbeRecovery", LINUX_MIB_TCPLOSSPROBERECOVERY),
 	SNMP_MIB_ITEM("TCPRenoRecoveryFail", LINUX_MIB_TCPRENORECOVERYFAIL),
 	SNMP_MIB_ITEM("TCPSackRecoveryFail", LINUX_MIB_TCPSACKRECOVERYFAIL),
-	SNMP_MIB_ITEM("TCPSchedulerFailed", LINUX_MIB_TCPSCHEDULERFAILED),
 	SNMP_MIB_ITEM("TCPRcvCollapsed", LINUX_MIB_TCPRCVCOLLAPSED),
 	SNMP_MIB_ITEM("TCPDSACKOldSent", LINUX_MIB_TCPDSACKOLDSENT),
 	SNMP_MIB_ITEM("TCPDSACKOfoSent", LINUX_MIB_TCPDSACKOFOSENT),
-- 
2.13.0

^ permalink raw reply related

* RE: [PATCH V4 net-next 2/8] net: hns3: Add support of the HNAE3 framework
From: Salil Mehta @ 2017-07-27 23:44 UTC (permalink / raw)
  To: Leon Romanovsky
  Cc: davem-fT/PcQaiUtIeIZ0/mPfg9Q@public.gmane.org,
	Zhuangyuzeng (Yisen), huangdaode, lipeng (Y),
	mehta.salil.lnk-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org,
	netdev-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
	linux-rdma-u79uwXL29TY76Z2rM5mHXA@public.gmane.org, Linuxarm
In-Reply-To: <20170723131530.GJ3259-U/DQcQFIOTAAJjI8aNfphQ@public.gmane.org>

Hi Leon

> -----Original Message-----
> From: linux-rdma-owner-u79uwXL29TY76Z2rM5mHXA@public.gmane.org [mailto:linux-rdma-
> owner-u79uwXL29TY76Z2rM5mHXA@public.gmane.org] On Behalf Of Leon Romanovsky
> Sent: Sunday, July 23, 2017 2:16 PM
> To: Salil Mehta
> Cc: davem-fT/PcQaiUtIeIZ0/mPfg9Q@public.gmane.org; Zhuangyuzeng (Yisen); huangdaode; lipeng (Y);
> mehta.salil.lnk-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org; netdev-u79uwXL29TY76Z2rM5mHXA@public.gmane.org; linux-
> kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org; linux-rdma-u79uwXL29TY76Z2rM5mHXA@public.gmane.org; Linuxarm
> Subject: Re: [PATCH V4 net-next 2/8] net: hns3: Add support of the
> HNAE3 framework
> 
> On Sat, Jul 22, 2017 at 11:09:36PM +0100, Salil Mehta wrote:
> > This patch adds the support of the HNAE3 (Hisilicon Network
> > Acceleration Engine 3) framework support to the HNS3 driver.
> >
> > Framework facilitates clients like ENET(HNS3 Ethernet Driver), RoCE
> > and user-space Ethernet drivers (like ODP etc.) to register with
> HNAE3
> > devices and their associated operations.
> >
> > Signed-off-by: Daode Huang <huangdaode-C8/M+/jPZTeaMJb+Lgu22Q@public.gmane.org>
> > Signed-off-by: lipeng <lipeng321-hv44wF8Li93QT0dZR+AlfA@public.gmane.org>
> > Signed-off-by: Salil Mehta <salil.mehta-hv44wF8Li93QT0dZR+AlfA@public.gmane.org>
> > Signed-off-by: Yisen Zhuang <yisen.zhuang-hv44wF8Li93QT0dZR+AlfA@public.gmane.org>
> > ---
> > Patch V4: Addressed following comments
> >   1. Andrew Lunn:
> >      https://lkml.org/lkml/2017/6/17/233
> >      https://lkml.org/lkml/2017/6/18/105
> >   2. Bo Yu:
> >      https://lkml.org/lkml/2017/6/18/112
> >   3. Stephen Hamminger:
> >      https://lkml.org/lkml/2017/6/19/778
> > Patch V3: Addressed below comments
> >   1. Andrew Lunn:
> >      https://lkml.org/lkml/2017/6/13/1025
> > Patch V2: No change
> > Patch V1: Initial Submit
> > ---
> >  drivers/net/ethernet/hisilicon/hns3/hnae3.c | 319
> ++++++++++++++++++++
> >  drivers/net/ethernet/hisilicon/hns3/hnae3.h | 449
> ++++++++++++++++++++++++++++
> >  2 files changed, 768 insertions(+)
> >  create mode 100644 drivers/net/ethernet/hisilicon/hns3/hnae3.c
> >  create mode 100644 drivers/net/ethernet/hisilicon/hns3/hnae3.h
> >
> > diff --git a/drivers/net/ethernet/hisilicon/hns3/hnae3.c
> b/drivers/net/ethernet/hisilicon/hns3/hnae3.c
> > new file mode 100644
> > index 000000000000..7a11aaff0a23
> > --- /dev/null
> > +++ b/drivers/net/ethernet/hisilicon/hns3/hnae3.c
> > @@ -0,0 +1,319 @@
> > +/*
> > + * Copyright (c) 2016-2017 Hisilicon Limited.
> > + *
> > + * This program is free software; you can redistribute it and/or
> modify
> > + * it under the terms of the GNU General Public License as published
> by
> > + * the Free Software Foundation; either version 2 of the License, or
> > + * (at your option) any later version.
> > + */
> > +
> > +#include <linux/slab.h>
> > +#include <linux/list.h>
> > +#include <linux/spinlock.h>
> > +
> > +#include "hnae3.h"
> > +
> > +static LIST_HEAD(hnae3_ae_algo_list);
> > +static LIST_HEAD(hnae3_client_list);
> > +static LIST_HEAD(hnae3_ae_dev_list);
> > +
> > +/* we are keeping things simple and using single lock for all the
> > + * list. This is a non-critical code so other updations, if happen
> > + * in parallel, can wait.
> > + */
> > +static DEFINE_MUTEX(hnae3_common_lock);
> > +
> > +static bool hnae3_client_match(enum hnae3_client_type client_type,
> > +			       enum hnae3_dev_type dev_type)
> > +{
> > +	if (dev_type == HNAE3_DEV_KNIC) {
> > +		switch (client_type) {
> > +		case HNAE3_CLIENT_KNIC:
> > +		case HNAE3_CLIENT_ROCE:
> > +			return true;
> > +		default:
> > +			return false;
> > +		}
> > +	} else if (dev_type == HNAE3_DEV_UNIC) {
> > +		switch (client_type) {
> > +		case HNAE3_CLIENT_UNIC:
> > +			return true;
> > +		default:
> > +			return false;
> > +		}
> > +	} else {
> > +		return false;
> > +	}
> > +}
> > +
> > +static int hnae3_match_n_instantiate(struct hnae3_client *client,
> > +				     struct hnae3_ae_dev *ae_dev,
> > +				     bool is_reg, bool *matched)
> > +{
> > +	int ret;
> > +
> > +	*matched = false;
> > +
> > +	/* check if this client matches the type of ae_dev */
> > +	if (!(hnae3_client_match(client->type, ae_dev->dev_type) &&
> > +	      hnae_get_bit(ae_dev->flag, HNAE3_DEV_INITED_B))) {
> > +		return 0;
> > +	}
> > +	/* there is a match of client and dev */
> > +	*matched = true;
> > +
> > +	if (!(ae_dev->ops && ae_dev->ops->init_client_instance &&
> > +	      ae_dev->ops->uninit_client_instance)) {
> > +		dev_err(&ae_dev->pdev->dev,
> > +			"ae_dev or client init/uninit ops are null\n");
> > +		return -EOPNOTSUPP;
> > +	}
> > +
> > +	/* now, (un-)instantiate client by calling lower layer */
> > +	if (is_reg) {
> > +		ret = ae_dev->ops->init_client_instance(client, ae_dev);
> > +		if (ret)
> > +			dev_err(&ae_dev->pdev->dev,
> > +				"fail to instantiate client\n");
> > +		return ret;
> > +	}
> > +
> > +	ae_dev->ops->uninit_client_instance(client, ae_dev);
> > +	return 0;
> > +}
> > +
> > +int hnae3_register_client(struct hnae3_client *client)
> > +{
> > +	struct hnae3_client *client_tmp;
> > +	struct hnae3_ae_dev *ae_dev;
> > +	bool matched;
> > +	int ret = 0;
> > +
> > +	mutex_lock(&hnae3_common_lock);
> > +	/* one system should only have one client for every type */
> > +	list_for_each_entry(client_tmp, &hnae3_client_list, node) {
> > +		if (client_tmp->type == client->type)
> > +			goto exit;
> > +	}
> > +
> > +	list_add_tail(&client->node, &hnae3_client_list);
> > +
> > +	/* initialize the client on every matched port */
> > +	list_for_each_entry(ae_dev, &hnae3_ae_dev_list, node) {
> > +		/* if the client could not be initialized on current port,
> for
> > +		 * any error reasons, move on to next available port
> > +		 */
> > +		ret = hnae3_match_n_instantiate(client, ae_dev, true,
> &matched);
> > +		if (ret)
> > +			dev_err(&ae_dev->pdev->dev,
> > +				"match and instantiation failed for port\n");
> > +	}
> > +
> > +exit:
> > +	mutex_unlock(&hnae3_common_lock);
> > +
> > +	return ret;
> > +}
> > +EXPORT_SYMBOL(hnae3_register_client);
> > +
> > +void hnae3_unregister_client(struct hnae3_client *client)
> > +{
> > +	struct hnae3_ae_dev *ae_dev;
> > +	bool matched;
> > +
> > +	mutex_lock(&hnae3_common_lock);
> > +	/* un-initialize the client on every matched port */
> > +	list_for_each_entry(ae_dev, &hnae3_ae_dev_list, node) {
> > +		hnae3_match_n_instantiate(client, ae_dev, false, &matched);
> > +	}
> > +
> > +	list_del(&client->node);
> > +	mutex_unlock(&hnae3_common_lock);
> > +}
> > +EXPORT_SYMBOL(hnae3_unregister_client);
> > +
> > +/* hnae_ae_register - register a AE engine to hnae framework
> > + * @hdev: the hnae ae engine device
> > + * @owner:  the module who provides this dev
> > + * NOTE: the duplicated name will not be checked
> > + */
> > +int hnae3_register_ae_algo(struct hnae3_ae_algo *ae_algo)
> > +{
> > +	const struct pci_device_id *id;
> > +	struct hnae3_ae_dev *ae_dev;
> > +	struct hnae3_client *client;
> > +	bool matched;
> > +	int ret = 0;
> > +
> > +	mutex_lock(&hnae3_common_lock);
> > +
> > +	list_add_tail(&ae_algo->node, &hnae3_ae_algo_list);
> > +
> > +	/* Check if this algo/ops matches the list of ae_devs */
> > +	list_for_each_entry(ae_dev, &hnae3_ae_dev_list, node) {
> > +		id = pci_match_id(ae_algo->pdev_id_table, ae_dev->pdev);
> > +		if (!id)
> > +			continue;
> > +
> > +		/* ae_dev init should set flag */
> > +		ae_dev->ops = ae_algo->ops;
> > +		ret = ae_algo->ops->init_ae_dev(ae_dev);
> > +		if (ret) {
> > +			dev_err(&ae_dev->pdev->dev, "init ae_dev error.\n");
> > +			continue;
> > +		}
> > +
> > +		hnae_set_bit(ae_dev->flag, HNAE3_DEV_INITED_B, 1);
> > +
> > +		/* check the client list for the match with this ae_dev
> type and
> > +		 * initialize the figure out client instance
> > +		 */
> > +		list_for_each_entry(client, &hnae3_client_list, node) {
> > +			ret = hnae3_match_n_instantiate(client, ae_dev, true,
> > +							&matched);
> > +			if (ret)
> > +				dev_err(&ae_dev->pdev->dev,
> > +					"match and instantiation failed\n");
> > +			if (matched)
> > +				break;
> > +		}
> > +	}
> > +
> > +	mutex_unlock(&hnae3_common_lock);
> > +
> > +	return ret;
> > +}
> > +EXPORT_SYMBOL(hnae3_register_ae_algo);
> > +
> > +/* hnae_ae_unregister - unregisters a HNAE AE engine
> > + * @cdev: the device to unregister
> > + */
> > +void hnae3_unregister_ae_algo(struct hnae3_ae_algo *ae_algo)
> > +{
> > +	const struct pci_device_id *id;
> > +	struct hnae3_ae_dev *ae_dev;
> > +	struct hnae3_client *client;
> > +	bool matched;
> > +
> > +	mutex_lock(&hnae3_common_lock);
> > +	/* Check if there are matched ae_dev */
> > +	list_for_each_entry(ae_dev, &hnae3_ae_dev_list, node) {
> > +		id = pci_match_id(ae_algo->pdev_id_table, ae_dev->pdev);
> > +		if (!id)
> > +			continue;
> > +
> > +		/* check the client list for the match with this ae_dev
> type and
> > +		 * un-initialize the figure out client instance
> > +		 */
> > +		list_for_each_entry(client, &hnae3_client_list, node) {
> > +			hnae3_match_n_instantiate(client, ae_dev, false,
> > +						  &matched);
> > +			if (matched)
> > +				break;
> > +		}
> > +
> > +		ae_algo->ops->uninit_ae_dev(ae_dev);
> > +		hnae_set_bit(ae_dev->flag, HNAE3_DEV_INITED_B, 0);
> > +	}
> > +
> > +	list_del(&ae_algo->node);
> > +	mutex_unlock(&hnae3_common_lock);
> > +}
> > +EXPORT_SYMBOL(hnae3_unregister_ae_algo);
> > +
> > +/* hnae_ae_register - register a AE engine to hnae framework
> > + * @hdev: the hnae ae engine device
> > + * @owner:  the module who provides this dev
> > + * NOTE: the duplicated name will not be checked
> > + */
> > +int hnae3_register_ae_dev(struct hnae3_ae_dev *ae_dev)
> > +{
> > +	const struct pci_device_id *id;
> > +	struct hnae3_ae_algo *ae_algo;
> > +	struct hnae3_client *client;
> > +	bool matched;
> > +	int ret = 0;
> > +
> > +	mutex_lock(&hnae3_common_lock);
> > +	list_add_tail(&ae_dev->node, &hnae3_ae_dev_list);
> > +
> > +	/* Check if there are matched ae_algo */
> > +	list_for_each_entry(ae_algo, &hnae3_ae_algo_list, node) {
> > +		id = pci_match_id(ae_algo->pdev_id_table, ae_dev->pdev);
> > +		if (!id)
> > +			continue;
> > +
> > +		ae_dev->ops = ae_algo->ops;
> > +
> > +		if (!ae_dev->ops) {
> > +			dev_err(&ae_dev->pdev->dev, "ae_dev ops are null\n");
> > +			goto out_err;
> > +		}
> > +
> > +		/* ae_dev init should set flag */
> > +		ret = ae_dev->ops->init_ae_dev(ae_dev);
> > +		if (ret) {
> > +			dev_err(&ae_dev->pdev->dev, "init ae_dev error\n");
> > +			goto out_err;
> > +		}
> > +
> > +		hnae_set_bit(ae_dev->flag, HNAE3_DEV_INITED_B, 1);
> > +		break;
> > +	}
> > +
> > +	/* check the client list for the match with this ae_dev type and
> > +	 * initialize the figure out client instance
> > +	 */
> > +	list_for_each_entry(client, &hnae3_client_list, node) {
> > +		ret = hnae3_match_n_instantiate(client, ae_dev, true,
> > +						&matched);
> > +		if (ret)
> > +			dev_err(&ae_dev->pdev->dev,
> > +				"match and instantiation failed\n");
> > +		if (matched)
> > +			break;
> > +	}
> > +
> > +out_err:
> > +	mutex_unlock(&hnae3_common_lock);
> > +
> > +	return ret;
> > +}
> > +EXPORT_SYMBOL(hnae3_register_ae_dev);
> > +
> > +/* hnae_ae_unregister - unregisters a HNAE AE engine
> > + * @cdev: the device to unregister
> > + */
> > +void hnae3_unregister_ae_dev(struct hnae3_ae_dev *ae_dev)
> > +{
> > +	const struct pci_device_id *id;
> > +	struct hnae3_ae_algo *ae_algo;
> > +	struct hnae3_client *client;
> > +	bool matched;
> > +
> > +	mutex_lock(&hnae3_common_lock);
> > +	/* Check if there are matched ae_algo */
> > +	list_for_each_entry(ae_algo, &hnae3_ae_algo_list, node) {
> > +		id = pci_match_id(ae_algo->pdev_id_table, ae_dev->pdev);
> > +		if (!id)
> > +			continue;
> > +
> > +		list_for_each_entry(client, &hnae3_client_list, node) {
> > +			hnae3_match_n_instantiate(client, ae_dev, false,
> > +						  &matched);
> > +			if (matched)
> > +				break;
> > +		}
> > +
> > +		ae_algo->ops->uninit_ae_dev(ae_dev);
> > +		hnae_set_bit(ae_dev->flag, HNAE3_DEV_INITED_B, 0);
> > +	}
> > +
> > +	list_del(&ae_dev->node);
> > +	mutex_unlock(&hnae3_common_lock);
> > +}
> > +EXPORT_SYMBOL(hnae3_unregister_ae_dev);
> > +
> > +MODULE_AUTHOR("Huawei Tech. Co., Ltd.");
> > +MODULE_LICENSE("GPL");
> > +MODULE_DESCRIPTION("HNAE3(Hisilicon Network Acceleration Engine)
> Framework");
> > diff --git a/drivers/net/ethernet/hisilicon/hns3/hnae3.h
> b/drivers/net/ethernet/hisilicon/hns3/hnae3.h
> > new file mode 100644
> > index 000000000000..88655c121769
> > --- /dev/null
> > +++ b/drivers/net/ethernet/hisilicon/hns3/hnae3.h
> > @@ -0,0 +1,449 @@
> > +/*
> > + * Copyright (c) 2016-2017 Hisilicon Limited.
> > + *
> > + * This program is free software; you can redistribute it and/or
> modify
> > + * it under the terms of the GNU General Public License as published
> by
> > + * the Free Software Foundation; either version 2 of the License, or
> > + * (at your option) any later version.
> > + */
> > +
> > +#ifndef __HNAE_H
> > +#define __HNAE_H
> > +
> > +/* Names used in this framework:
> > + *      ae handle (handle):
> > + *        a set of queues provided by AE
> > + *      ring buffer queue (rbq):
> > + *        the channel between upper layer and the AE, can do tx and
> rx
> > + *      ring:
> > + *        a tx or rx channel within a rbq
> > + *      ring description (desc):
> > + *        an element in the ring with packet information
> > + *      buffer:
> > + *        a memory region referred by desc with the full packet
> payload
> > + *
> > + * "num" means a static number set as a parameter, "count" mean a
> dynamic
> > + *   number set while running
> > + * "cb" means control block
> > + */
> > +
> > +#include <linux/acpi.h>
> > +#include <linux/delay.h>
> > +#include <linux/device.h>
> > +#include <linux/module.h>
> > +#include <linux/netdevice.h>
> > +#include <linux/pci.h>
> > +#include <linux/types.h>
> > +
> > +#define HNAE_DRIVER_VERSION "1.0"
> 
> Please no driver versions.
We need this in ethtool. Most of the driver are using it.

> 
> > +#define HNAE_DRIVER_NAME "hns3"
> > +#define HNAE_COPYRIGHT "Copyright(c) 2017 Huawei Corporation."
> > +#define HNAE_DRIVER_STRING "Hisilicon Network Subsystem Driver"
> > +#define HNAE_DEFAULT_DEVICE_DESCR "Hisilicon Network Subsystem"
> 
> You are not subsystem yet.
Hisilicon Network System is the network related hardware within
Hip08 SoC of Hisilicon. This does not means HNS is Linux network
subsystem.

> 
> > +
> > +/* Device IDs */
> > +#define HISILICON				0x19E5
> > +#define HNAE3_DEV_ID_GE				0xA220
> > +#define HNAE3_DEV_ID_25GE			0xA221
> > +#define HNAE3_DEV_ID_25GE_RDMA			0xA222
> > +#define HNAE3_DEV_ID_25GE_RDMA_MACSEC		0xA223
> > +#define HNAE3_DEV_ID_50GE_RDMA			0xA224
> > +#define HNAE3_DEV_ID_50GE_RDMA_MACSEC		0xA225
> > +#define HNAE3_DEV_ID_100G_RDMA_MACSEC		0xA226
> > +#define HNAE3_DEV_ID_100G_VF			0xA22E
> > +#define HNAE3_DEV_ID_100G_RDMA_DCB_PFC_VF	0xA22F
> > +
> > +#define HNAE3_CLASS_NAME_SIZE 16
> > +
> > +#define HNAE3_DEV_INITED_B			0x0
> > +#define HNAE_DEV_SUPPORT_ROCE_B			0x1
> > +
> > +#define ring_ptr_move_fw(ring, p) \
> > +	((ring)->p = ((ring)->p + 1) % (ring)->desc_num)
> > +#define ring_ptr_move_bw(ring, p) \
> > +	((ring)->p = ((ring)->p - 1 + (ring)->desc_num) % (ring)-
> >desc_num)
> > +
> > +enum hns_desc_type {
> > +	DESC_TYPE_SKB,
> > +	DESC_TYPE_PAGE,
> > +};
> > +
> > +struct hnae3_handle;
> > +
> > +struct hnae3_queue {
> > +	void __iomem *io_base;
> > +	struct hnae3_ae_algo *ae_algo;
> > +	struct hnae3_handle *handle;
> > +	int tqp_index;	/* index in a handle */
> > +	u32 buf_size;	/* size for hnae_desc->addr, preset by AE */
> > +	u16 desc_num;	/* total number of desc */
> > +};
> > +
> > +/*hnae3 loop mode*/
> > +enum hnae3_loop {
> > +	HNAE3_MAC_INTER_LOOP_MAC,
> > +	HNAE3_MAC_INTER_LOOP_SERDES,
> > +	HNAE3_MAC_INTER_LOOP_PHY,
> > +	HNAE3_MAC_LOOP_NONE,
> > +};
> > +
> > +enum hnae3_client_type {
> > +	HNAE3_CLIENT_KNIC,
> > +	HNAE3_CLIENT_UNIC,
> > +	HNAE3_CLIENT_ROCE,
> > +};
> > +
> > +enum hnae3_dev_type {
> > +	HNAE3_DEV_KNIC,
> > +	HNAE3_DEV_UNIC,
> > +};
> > +
> > +/* mac media type */
> > +enum hnae3_media_type {
> > +	HNAE3_MEDIA_TYPE_UNKNOWN,
> > +	HNAE3_MEDIA_TYPE_FIBER,
> > +	HNAE3_MEDIA_TYPE_COPPER,
> > +	HNAE3_MEDIA_TYPE_BACKPLANE,
> > +};
> > +
> > +struct hnae3_vector_info {
> > +	u8 __iomem *io_addr;
> > +	int vector;
> > +};
> > +
> > +#define HNAE3_RING_TYPE_B 0
> > +#define HNAE3_RING_TYPE_TX 0
> > +#define HNAE3_RING_TYPE_RX 1
> > +
> > +struct hnae3_ring_chain_node {
> > +	struct hnae3_ring_chain_node *next;
> > +	u32 tqp_index;
> > +	u32 flag;
> > +};
> > +
> > +#define HNAE3_IS_TX_RING(node) \
> > +	(((node)->flag & (1 << HNAE3_RING_TYPE_B)) == HNAE3_RING_TYPE_TX)
> > +
> > +struct hnae3_client_ops {
> > +	int (*init_instance)(struct hnae3_handle *handle);
> > +	void (*uninit_instance)(struct hnae3_handle *handle, bool reset);
> > +	void (*link_status_change)(struct hnae3_handle *handle, bool
> state);
> > +};
> > +
> > +#define HNAE3_CLIENT_NAME_LENGTH 16
> > +struct hnae3_client {
> > +	char name[HNAE3_CLIENT_NAME_LENGTH];
> > +	u16 version;
> > +	unsigned long state;
> > +	enum hnae3_client_type type;
> > +	const struct hnae3_client_ops *ops;
> > +	struct list_head node;
> > +};
> > +
> > +struct hnae3_ae_dev {
> > +	struct pci_dev *pdev;
> > +	const struct hnae3_ae_ops *ops;
> > +	struct list_head node;
> > +	u32 flag;
> > +	enum hnae3_dev_type dev_type;
> > +	void *priv;
> > +};
> > +
> > +/* This struct defines the operation on the handle.
> > + *
> > + * init_ae_dev(): (mandatory)
> > + *   Get PF configure from pci_dev and initialize PF hardware
> > + * uninit_ae_dev()
> > + *   Disable PF device and release PF resource
> > + * register_client
> > + *   Register client to ae_dev
> > + * unregister_client()
> > + *   Unregister client from ae_dev
> > + * start()
> > + *   Enable the hardware
> > + * stop()
> > + *   Disable the hardware
> > + * get_status()
> > + *   Get the carrier state of the back channel of the handle, 1 for
> ok, 0 for
> > + *   non-ok
> > + * get_ksettings_an_result()
> > + *   Get negotiation status,speed and duplex
> > + * update_speed_duplex_h()
> > + *   Update hardware speed and duplex
> > + * get_media_type()
> > + *   Get media type of MAC
> > + * adjust_link()
> > + *   Adjust link status
> > + * set_loopback()
> > + *   Set loopback
> > + * set_promisc_mode
> > + *   Set promisc mode
> > + * set_mtu()
> > + *   set mtu
> > + * get_pauseparam()
> > + *   get tx and rx of pause frame use
> > + * set_pauseparam()
> > + *   set tx and rx of pause frame use
> > + * set_autoneg()
> > + *   set auto autonegotiation of pause frame use
> > + * get_autoneg()
> > + *   get auto autonegotiation of pause frame use
> > + * get_coalesce_usecs()
> > + *   get usecs to delay a TX interrupt after a packet is sent
> > + * get_rx_max_coalesced_frames()
> > + *   get Maximum number of packets to be sent before a TX interrupt.
> > + * set_coalesce_usecs()
> > + *   set usecs to delay a TX interrupt after a packet is sent
> > + * set_coalesce_frames()
> > + *   set Maximum number of packets to be sent before a TX interrupt.
> > + * get_mac_addr()
> > + *   get mac address
> > + * set_mac_addr()
> > + *   set mac address
> > + * add_uc_addr
> > + *   Add unicast addr to mac table
> > + * rm_uc_addr
> > + *   Remove unicast addr from mac table
> > + * set_mc_addr()
> > + *   Set multicast address
> > + * add_mc_addr
> > + *   Add multicast address to mac table
> > + * rm_mc_addr
> > + *   Remove multicast address from mac table
> > + * update_stats()
> > + *   Update Old network device statistics
> > + * get_ethtool_stats()
> > + *   Get ethtool network device statistics
> > + * get_strings()
> > + *   Get a set of strings that describe the requested objects
> > + * get_sset_count()
> > + *   Get number of strings that @get_strings will write
> > + * update_led_status()
> > + *   Update the led status
> > + * set_led_id()
> > + *   Set led id
> > + * get_regs()
> > + *   Get regs dump
> > + * get_regs_len()
> > + *   Get the len of the regs dump
> > + * get_rss_key_size()
> > + *   Get rss key size
> > + * get_rss_indir_size()
> > + *   Get rss indirection table size
> > + * get_rss()
> > + *   Get rss table
> > + * set_rss()
> > + *   Set rss table
> > + * get_tc_size()
> > + *   Get tc size of handle
> > + * get_vector()
> > + *   Get vector number and vector information
> > + * map_ring_to_vector()
> > + *   Map rings to vector
> > + * unmap_ring_from_vector()
> > + *   Unmap rings from vector
> > + * add_tunnel_udp()
> > + *   Add tunnel information to hardware
> > + * del_tunnel_udp()
> > + *   Delete tunnel information from hardware
> > + * reset_queue()
> > + *   Reset queue
> > + * get_fw_version()
> > + *   Get firmware version
> > + * get_mdix_mode()
> > + *   Get media typr of phy
> > + * set_vlan_filter()
> > + *   Set vlan filter config of Ports
> > + * set_vf_vlan_filter()
> > + *   Set vlan filter config of vf
> > + */
> > +struct hnae3_ae_ops {
> > +	int (*init_ae_dev)(struct hnae3_ae_dev *ae_dev);
> > +	void (*uninit_ae_dev)(struct hnae3_ae_dev *ae_dev);
> > +
> > +	int (*init_client_instance)(struct hnae3_client *client,
> > +				    struct hnae3_ae_dev *ae_dev);
> > +	void (*uninit_client_instance)(struct hnae3_client *client,
> > +				       struct hnae3_ae_dev *ae_dev);
> > +	int (*start)(struct hnae3_handle *handle);
> > +	void (*stop)(struct hnae3_handle *handle);
> > +	int (*get_status)(struct hnae3_handle *handle);
> > +	void (*get_ksettings_an_result)(struct hnae3_handle *handle,
> > +					u8 *auto_neg, u32 *speed, u8 *duplex);
> > +
> > +	int (*update_speed_duplex_h)(struct hnae3_handle *handle);
> > +	int (*cfg_mac_speed_dup_h)(struct hnae3_handle *handle, int
> speed,
> > +				   u8 duplex);
> > +
> > +	void (*get_media_type)(struct hnae3_handle *handle, u8
> *media_type);
> > +	void (*adjust_link)(struct hnae3_handle *handle, int speed, int
> duplex);
> > +	int (*set_loopback)(struct hnae3_handle *handle,
> > +			    enum hnae3_loop loop_mode, bool en);
> > +
> > +	void (*set_promisc_mode)(struct hnae3_handle *handle, u32 en);
> > +	int (*set_mtu)(struct hnae3_handle *handle, int new_mtu);
> > +
> > +	void (*get_pauseparam)(struct hnae3_handle *handle,
> > +			       u32 *auto_neg, u32 *rx_en, u32 *tx_en);
> > +	int (*set_pauseparam)(struct hnae3_handle *handle,
> > +			      u32 auto_neg, u32 rx_en, u32 tx_en);
> > +
> > +	int (*set_autoneg)(struct hnae3_handle *handle, bool enable);
> > +	int (*get_autoneg)(struct hnae3_handle *handle);
> > +
> > +	void (*get_coalesce_usecs)(struct hnae3_handle *handle,
> > +				   u32 *tx_usecs, u32 *rx_usecs);
> > +	void (*get_rx_max_coalesced_frames)(struct hnae3_handle *handle,
> > +					    u32 *tx_frames, u32 *rx_frames);
> > +	int (*set_coalesce_usecs)(struct hnae3_handle *handle, u32
> timeout);
> > +	int (*set_coalesce_frames)(struct hnae3_handle *handle,
> > +				   u32 coalesce_frames);
> > +	void (*get_coalesce_range)(struct hnae3_handle *handle,
> > +				   u32 *tx_frames_low, u32 *rx_frames_low,
> > +				   u32 *tx_frames_high, u32 *rx_frames_high,
> > +				   u32 *tx_usecs_low, u32 *rx_usecs_low,
> > +				   u32 *tx_usecs_high, u32 *rx_usecs_high);
> > +
> > +	void (*get_mac_addr)(struct hnae3_handle *handle, u8 *p);
> > +	int (*set_mac_addr)(struct hnae3_handle *handle, void *p);
> > +	int (*add_uc_addr)(struct hnae3_handle *handle,
> > +			   const unsigned char *addr);
> > +	int (*rm_uc_addr)(struct hnae3_handle *handle,
> > +			  const unsigned char *addr);
> > +	int (*set_mc_addr)(struct hnae3_handle *handle, void *addr);
> > +	int (*add_mc_addr)(struct hnae3_handle *handle,
> > +			   const unsigned char *addr);
> > +	int (*rm_mc_addr)(struct hnae3_handle *handle,
> > +			  const unsigned char *addr);
> > +
> > +	void (*set_tso_stats)(struct hnae3_handle *handle, int enable);
> > +	void (*update_stats)(struct hnae3_handle *handle,
> > +			     struct net_device_stats *net_stats);
> > +	void (*get_stats)(struct hnae3_handle *handle, u64 *data);
> > +
> > +	void (*get_strings)(struct hnae3_handle *handle,
> > +			    u32 stringset, u8 *data);
> > +	int (*get_sset_count)(struct hnae3_handle *handle, int
> stringset);
> > +
> > +	void (*get_regs)(struct hnae3_handle *handle, void *data);
> > +	int (*get_regs_len)(struct hnae3_handle *handle);
> > +
> > +	u32 (*get_rss_key_size)(struct hnae3_handle *handle);
> > +	u32 (*get_rss_indir_size)(struct hnae3_handle *handle);
> > +	int (*get_rss)(struct hnae3_handle *handle, u32 *indir, u8 *key,
> > +		       u8 *hfunc);
> > +	int (*set_rss)(struct hnae3_handle *handle, const u32 *indir,
> > +		       const u8 *key, const u8 hfunc);
> > +
> > +	int (*get_tc_size)(struct hnae3_handle *handle);
> > +
> > +	int (*get_vector)(struct hnae3_handle *handle, u16 vector_num,
> > +			  struct hnae3_vector_info *vector_info);
> > +	int (*map_ring_to_vector)(struct hnae3_handle *handle,
> > +				  int vector_num,
> > +				  struct hnae3_ring_chain_node *vr_chain);
> > +	int (*unmap_ring_from_vector)(struct hnae3_handle *handle,
> > +				      int vector_num,
> > +				      struct hnae3_ring_chain_node *vr_chain);
> > +
> > +	int (*add_tunnel_udp)(struct hnae3_handle *handle, u16 port_num);
> > +	int (*del_tunnel_udp)(struct hnae3_handle *handle, u16 port_num);
> > +
> > +	void (*reset_queue)(struct hnae3_handle *handle, u16 queue_id);
> > +	u32 (*get_fw_version)(struct hnae3_handle *handle);
> > +	void (*get_mdix_mode)(struct hnae3_handle *handle,
> > +			      u8 *tp_mdix_ctrl, u8 *tp_mdix);
> > +
> > +	int (*set_vlan_filter)(struct hnae3_handle *handle, __be16 proto,
> > +			       u16 vlan_id, bool is_kill);
> > +	int (*set_vf_vlan_filter)(struct hnae3_handle *handle, int vfid,
> > +				  u16 vlan, u8 qos, __be16 proto);
> > +};
> > +
> > +struct hnae3_ae_algo {
> > +	const struct hnae3_ae_ops *ops;
> > +	struct list_head node;
> > +	char name[HNAE3_CLASS_NAME_SIZE];
> > +	const struct pci_device_id *pdev_id_table;
> > +};
> > +
> > +#define HNAE3_INT_NAME_LEN        (IFNAMSIZ + 16)
> > +#define HNAE3_ITR_COUNTDOWN_START 100
> > +
> > +struct hnae3_tc_info {
> > +	u16	tqp_offset;	/* TQP offset from base TQP */
> > +	u16	tqp_count;	/* Total TQPs */
> > +	u8	up;		/* user priority */
> > +	u8	tc;		/* TC index */
> > +	bool	enable;		/* If this TC is enable or not */
> > +};
> > +
> > +#define HNAE3_MAX_TC		8
> > +struct hnae3_knic_private_info {
> > +	struct net_device *netdev; /* Set by KNIC client when init
> instance */
> > +	u16 rss_size;		   /* Allocated RSS queues */
> > +	u16 rx_buf_len;
> > +	u16 num_desc;
> > +
> > +	u8 num_tc;		   /* Total number of enabled TCs */
> > +	struct hnae3_tc_info tc_info[HNAE3_MAX_TC]; /* Idx of array is HW
> TC */
> > +
> > +	u16 num_tqps;		  /* total number of TQPs in this handle
> */
> > +	struct hnae3_queue **tqp;  /* array base of all TQPs in this
> instance */
> > +};
> > +
> > +struct hnae3_roce_private_info {
> > +	void __iomem *roce_io_base;
> > +	struct net_device *netdev;
> > +	int base_vector;
> > +	int num_vectors;
> > +};
> > +
> > +struct hnae3_unic_private_info {
> > +	u16 rx_buf_len;
> > +	u16 num_desc;
> > +	u16 num_tqps;	/* total number of tqps in this handle */
> > +	struct hnae3_queue **tqp;  /* array base of all TQPs of this
> instance */
> > +};
> > +
> > +#define HNAE3_SUPPORT_MAC_LOOPBACK    1
> > +#define HNAE3_SUPPORT_PHY_LOOPBACK    2
> > +#define HNAE3_SUPPORT_SERDES_LOOPBACK 4
> > +
> > +struct hnae3_handle {
> > +	struct hnae3_client *client;
> > +	struct pci_dev *pdev;
> > +	void *priv;
> > +	struct hnae3_ae_algo *ae_algo;  /* the class who provides this
> handle */
> > +	u64 flags; /* Indicate the capabilities for this handle*/
> > +
> > +	union {
> > +		struct hnae3_knic_private_info kinfo;
> > +		struct hnae3_unic_private_info uinfo;
> > +		struct hnae3_roce_private_info rinfo;
> > +	};
> > +
> > +	u32 numa_node_mask;	/* for multi-chip support */
> > +};
> > +
> > +#define hnae_set_field(origin, mask, shift, val) \
> > +	do { \
> > +		(origin) &= (~(mask)); \
> > +		(origin) |= ((val) << (shift)) & (mask); \
> > +	} while (0)
> > +#define hnae_get_field(origin, mask, shift) (((origin) & (mask)) >>
> (shift))
> > +
> > +#define hnae_set_bit(origin, shift, val) \
> > +	hnae_set_field((origin), (0x1 << (shift)), (shift), (val))
> > +#define hnae_get_bit(origin, shift) \
> > +	hnae_get_field((origin), (0x1 << (shift)), (shift))
> > +
> > +int hnae3_register_ae_dev(struct hnae3_ae_dev *ae_dev);
> > +void hnae3_unregister_ae_dev(struct hnae3_ae_dev *ae_dev);
> > +
> > +void hnae3_unregister_ae_algo(struct hnae3_ae_algo *ae_algo);
> > +int hnae3_register_ae_algo(struct hnae3_ae_algo *ae_algo);
> > +
> > +void hnae3_unregister_client(struct hnae3_client *client);
> > +int hnae3_register_client(struct hnae3_client *client);
> > +#endif
> > --
> > 2.11.0
> >
> >
--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* [PATCH net-next v2 0/3] ethtool: support for forward error correction mode setting on a link
From: Roopa Prabhu @ 2017-07-27 23:47 UTC (permalink / raw)
  To: davem, linville
  Cc: netdev, vidya.chowdary, dustin, olson, leedom, kubakici, galp,
	andrew, manojmalviya, santosh, yuval.mintz, odedw, ariela,
	jeffrey.t.kirsher

From: Roopa Prabhu <roopa@cumulusnetworks.com>

Forward Error Correction (FEC) modes i.e Base-R
and Reed-Solomon modes are introduced in 25G/40G/100G standards
for providing good BER at high speeds. Various networking devices
which support 25G/40G/100G provides ability to manage supported FEC
modes and the lack of FEC encoding control and reporting today is a
source for interoperability issues for many vendors.
FEC capability as well as specific FEC mode i.e. Base-R
or RS modes can be requested or advertised through bits D44:47 of base link
codeword.

This patch set intends to provide option under ethtool to manage and
report FEC encoding settings for networking devices as per IEEE 802.3
bj, bm and by specs.

v2 :
        - minor patch format fixes and typos pointed out by Andrew
        - there was a pending discussion on the use of 'auto' vs
          'automatic' for fec settings. I have left it as 'auto'
          because in most cases today auto is used in place of
          automatic to represent automatically generated values.
          We use it in other networking config too. I would prefer
          leaving it as auto.

Casey Leedom (2):
  cxgb4: core hardware/firmware support for Forward Error Correction on
    a link
  cxgb4: ethtool forward error correction management support

Vidya Sagar Ravipati (1):
  net: ethtool: add support for forward error correction modes

 drivers/net/ethernet/chelsio/cxgb4/cxgb4_ethtool.c |  99 ++++++++++++++
 drivers/net/ethernet/chelsio/cxgb4/t4_hw.c         | 151 ++++++++++++++++-----
 include/linux/ethtool.h                            |   4 +
 include/uapi/linux/ethtool.h                       |  48 ++++++-
 net/core/ethtool.c                                 |  34 +++++
 5 files changed, 300 insertions(+), 36 deletions(-)

-- 
2.1.4

^ permalink raw reply

* [PATCH net-next v2 1/3] net: ethtool: add support for forward error correction modes
From: Roopa Prabhu @ 2017-07-27 23:47 UTC (permalink / raw)
  To: davem, linville
  Cc: netdev, vidya.chowdary, dustin, olson, leedom, kubakici, galp,
	andrew, manojmalviya, santosh, yuval.mintz, odedw, ariela,
	jeffrey.t.kirsher
In-Reply-To: <1501199248-24695-1-git-send-email-roopa@cumulusnetworks.com>

From: Vidya Sagar Ravipati <vidya.chowdary@gmail.com>

Forward Error Correction (FEC) modes i.e Base-R
and Reed-Solomon modes are introduced in 25G/40G/100G standards
for providing good BER at high speeds. Various networking devices
which support 25G/40G/100G provides ability to manage supported FEC
modes and the lack of FEC encoding control and reporting today is a
source for interoperability issues for many vendors.
FEC capability as well as specific FEC mode i.e. Base-R
or RS modes can be requested or advertised through bits D44:47 of
base link codeword.

This patch set intends to provide option under ethtool to manage
and report FEC encoding settings for networking devices as per
IEEE 802.3 bj, bm and by specs.

set-fec/show-fec option(s) are designed to provide control and
report the FEC encoding on the link.

SET FEC option:
root@tor: ethtool --set-fec  swp1 encoding [off | RS | BaseR | auto]

Encoding: Types of encoding
Off    :  Turning off any encoding
RS     :  enforcing RS-FEC encoding on supported speeds
BaseR  :  enforcing Base R encoding on supported speeds
Auto   :  IEEE defaults for the speed/medium combination

Here are a few examples of what we would expect if encoding=auto:
- if autoneg is on, we are  expecting FEC to be negotiated as on or off
  as long as protocol supports it
- if the hardware is capable of detecting the FEC encoding on it's
      receiver it will reconfigure its encoder to match
- in absence of the above, the configuration would be set to IEEE
  defaults.

>From our  understanding , this is essentially what most hardware/driver
combinations are doing today in the absence of a way for users to
control the behavior.

SHOW FEC option:
root@tor: ethtool --show-fec  swp1
FEC parameters for swp1:
Active FEC encodings: RS
Configured FEC encodings:  RS | BaseR

ETHTOOL DEVNAME output modification:

ethtool devname output:
root@tor:~# ethtool swp1
Settings for swp1:
root@hpe-7712-03:~# ethtool swp18
Settings for swp18:
    Supported ports: [ FIBRE ]
    Supported link modes:   40000baseCR4/Full
                            40000baseSR4/Full
                            40000baseLR4/Full
                            100000baseSR4/Full
                            100000baseCR4/Full
                            100000baseLR4_ER4/Full
    Supported pause frame use: No
    Supports auto-negotiation: Yes
    Supported FEC modes: [RS | BaseR | None | Not reported]
    Advertised link modes:  Not reported
    Advertised pause frame use: No
    Advertised auto-negotiation: No
    Advertised FEC modes: [RS | BaseR | None | Not reported]
<<<< One or more FEC modes
    Speed: 100000Mb/s
    Duplex: Full
    Port: FIBRE
    PHYAD: 106
    Transceiver: internal
    Auto-negotiation: off
    Link detected: yes

This patch includes following changes
a) New ETHTOOL_SFECPARAM/SFECPARAM API, handled by
  the new get_fecparam/set_fecparam callbacks, provides support
  for configuration of forward error correction modes.
b) Link mode bits for FEC modes i.e. None (No FEC mode), RS, BaseR/FC
  are defined so that users can configure these fec modes for supported
  and advertising fields as part of link autonegotiation.

Signed-off-by: Vidya Sagar Ravipati <vidya.chowdary@gmail.com>
Signed-off-by: Dustin Byford <dustin@cumulusnetworks.com>
Signed-off-by: Roopa Prabhu <roopa@cumulusnetworks.com>
---
 include/linux/ethtool.h      |  4 ++++
 include/uapi/linux/ethtool.h | 48 +++++++++++++++++++++++++++++++++++++++++++-
 net/core/ethtool.c           | 34 +++++++++++++++++++++++++++++++
 3 files changed, 85 insertions(+), 1 deletion(-)

diff --git a/include/linux/ethtool.h b/include/linux/ethtool.h
index 83cc986..afdbb70 100644
--- a/include/linux/ethtool.h
+++ b/include/linux/ethtool.h
@@ -374,5 +374,9 @@ struct ethtool_ops {
 				      struct ethtool_link_ksettings *);
 	int	(*set_link_ksettings)(struct net_device *,
 				      const struct ethtool_link_ksettings *);
+	int	(*get_fecparam)(struct net_device *,
+				      struct ethtool_fecparam *);
+	int	(*set_fecparam)(struct net_device *,
+				      struct ethtool_fecparam *);
 };
 #endif /* _LINUX_ETHTOOL_H */
diff --git a/include/uapi/linux/ethtool.h b/include/uapi/linux/ethtool.h
index 7d4a594..9c041da 100644
--- a/include/uapi/linux/ethtool.h
+++ b/include/uapi/linux/ethtool.h
@@ -1238,6 +1238,47 @@ struct ethtool_per_queue_op {
 	char	data[];
 };
 
+/**
+ * struct ethtool_fecparam - Ethernet forward error correction(fec) parameters
+ * @cmd: Command number = %ETHTOOL_GFECPARAM or %ETHTOOL_SFECPARAM
+ * @active_fec: FEC mode which is active on porte
+ * @fec: Bitmask of supported/configured FEC modes
+ * @rsvd: Reserved for future extensions. i.e FEC bypass feature.
+ *
+ * Drivers should reject a non-zero setting of @autoneg when
+ * autoneogotiation is disabled (or not supported) for the link.
+ *
+ */
+struct ethtool_fecparam {
+	__u32   cmd;
+	/* bitmask of FEC modes */
+	__u32   active_fec;
+	__u32   fec;
+	__u32   reserved;
+};
+
+/**
+ * enum ethtool_fec_config_bits - flags definition of ethtool_fec_configuration
+ * @ETHTOOL_FEC_NONE: FEC mode configuration is not supported
+ * @ETHTOOL_FEC_AUTO: Default/Best FEC mode provided by driver
+ * @ETHTOOL_FEC_OFF: No FEC Mode
+ * @ETHTOOL_FEC_RS: Reed-Solomon Forward Error Detection mode
+ * @ETHTOOL_FEC_BASER: Base-R/Reed-Solomon Forward Error Detection mode
+ */
+enum ethtool_fec_config_bits {
+	ETHTOOL_FEC_NONE_BIT,
+	ETHTOOL_FEC_AUTO_BIT,
+	ETHTOOL_FEC_OFF_BIT,
+	ETHTOOL_FEC_RS_BIT,
+	ETHTOOL_FEC_BASER_BIT,
+};
+
+#define ETHTOOL_FEC_NONE		(1 << ETHTOOL_FEC_NONE_BIT)
+#define ETHTOOL_FEC_AUTO		(1 << ETHTOOL_FEC_AUTO_BIT)
+#define ETHTOOL_FEC_OFF			(1 << ETHTOOL_FEC_OFF_BIT)
+#define ETHTOOL_FEC_RS			(1 << ETHTOOL_FEC_RS_BIT)
+#define ETHTOOL_FEC_BASER		(1 << ETHTOOL_FEC_BASER_BIT)
+
 /* CMDs currently supported */
 #define ETHTOOL_GSET		0x00000001 /* DEPRECATED, Get settings.
 					    * Please use ETHTOOL_GLINKSETTINGS
@@ -1330,6 +1371,8 @@ struct ethtool_per_queue_op {
 #define ETHTOOL_SLINKSETTINGS	0x0000004d /* Set ethtool_link_settings */
 #define ETHTOOL_PHY_GTUNABLE	0x0000004e /* Get PHY tunable configuration */
 #define ETHTOOL_PHY_STUNABLE	0x0000004f /* Set PHY tunable configuration */
+#define ETHTOOL_GFECPARAM	0x00000050 /* Get FEC settings */
+#define ETHTOOL_SFECPARAM	0x00000051 /* Set FEC settings */
 
 /* compatibility with older code */
 #define SPARC_ETH_GSET		ETHTOOL_GSET
@@ -1387,6 +1430,9 @@ enum ethtool_link_mode_bit_indices {
 	ETHTOOL_LINK_MODE_2500baseT_Full_BIT	= 47,
 	ETHTOOL_LINK_MODE_5000baseT_Full_BIT	= 48,
 
+	ETHTOOL_LINK_MODE_FEC_NONE_BIT	= 49,
+	ETHTOOL_LINK_MODE_FEC_RS_BIT	= 50,
+	ETHTOOL_LINK_MODE_FEC_BASER_BIT	= 51,
 
 	/* Last allowed bit for __ETHTOOL_LINK_MODE_LEGACY_MASK is bit
 	 * 31. Please do NOT define any SUPPORTED_* or ADVERTISED_*
@@ -1395,7 +1441,7 @@ enum ethtool_link_mode_bit_indices {
 	 */
 
 	__ETHTOOL_LINK_MODE_LAST
-	  = ETHTOOL_LINK_MODE_5000baseT_Full_BIT,
+	  = ETHTOOL_LINK_MODE_FEC_BASER_BIT,
 };
 
 #define __ETHTOOL_LINK_MODE_LEGACY_MASK(base_name)	\
diff --git a/net/core/ethtool.c b/net/core/ethtool.c
index b987bc4..6a582ae 100644
--- a/net/core/ethtool.c
+++ b/net/core/ethtool.c
@@ -2512,6 +2512,33 @@ static int set_phy_tunable(struct net_device *dev, void __user *useraddr)
 	return ret;
 }
 
+static int ethtool_get_fecparam(struct net_device *dev, void __user *useraddr)
+{
+	struct ethtool_fecparam fecparam = { ETHTOOL_GFECPARAM };
+
+	if (!dev->ethtool_ops->get_fecparam)
+		return -EOPNOTSUPP;
+
+	dev->ethtool_ops->get_fecparam(dev, &fecparam);
+
+	if (copy_to_user(useraddr, &fecparam, sizeof(fecparam)))
+		return -EFAULT;
+	return 0;
+}
+
+static int ethtool_set_fecparam(struct net_device *dev, void __user *useraddr)
+{
+	struct ethtool_fecparam fecparam;
+
+	if (!dev->ethtool_ops->set_fecparam)
+		return -EOPNOTSUPP;
+
+	if (copy_from_user(&fecparam, useraddr, sizeof(fecparam)))
+		return -EFAULT;
+
+	return dev->ethtool_ops->set_fecparam(dev, &fecparam);
+}
+
 /* The main entry point in this file.  Called from net/core/dev_ioctl.c */
 
 int dev_ethtool(struct net *net, struct ifreq *ifr)
@@ -2570,6 +2597,7 @@ int dev_ethtool(struct net *net, struct ifreq *ifr)
 	case ETHTOOL_GTUNABLE:
 	case ETHTOOL_PHY_GTUNABLE:
 	case ETHTOOL_GLINKSETTINGS:
+	case ETHTOOL_GFECPARAM:
 		break;
 	default:
 		if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
@@ -2779,6 +2807,12 @@ int dev_ethtool(struct net *net, struct ifreq *ifr)
 	case ETHTOOL_PHY_STUNABLE:
 		rc = set_phy_tunable(dev, useraddr);
 		break;
+	case ETHTOOL_GFECPARAM:
+		rc = ethtool_get_fecparam(dev, useraddr);
+		break;
+	case ETHTOOL_SFECPARAM:
+		rc = ethtool_set_fecparam(dev, useraddr);
+		break;
 	default:
 		rc = -EOPNOTSUPP;
 	}
-- 
2.1.4

^ permalink raw reply related

* [PATCH net-next v2 2/3] cxgb4: core hardware/firmware support for Forward Error Correction on a link
From: Roopa Prabhu @ 2017-07-27 23:47 UTC (permalink / raw)
  To: davem, linville
  Cc: netdev, vidya.chowdary, dustin, olson, leedom, kubakici, galp,
	andrew, manojmalviya, santosh, yuval.mintz, odedw, ariela,
	jeffrey.t.kirsher
In-Reply-To: <1501199248-24695-1-git-send-email-roopa@cumulusnetworks.com>

From: Casey Leedom <leedom@chelsio.com>

Signed-off-by: Casey Leedom <leedom@chelsio.com>
---
 drivers/net/ethernet/chelsio/cxgb4/t4_hw.c | 152 ++++++++++++++++++++++-------
 1 file changed, 117 insertions(+), 35 deletions(-)

diff --git a/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c b/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c
index db41b3e..24087c8 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c
@@ -3840,11 +3840,64 @@ void t4_ulprx_read_la(struct adapter *adap, u32 *la_buf)
 		     FW_PORT_CAP_SPEED_40G | FW_PORT_CAP_SPEED_100G | \
 		     FW_PORT_CAP_ANEG)
 
+/* Translate Firmware Port Capabilities Pause specification to Common Code */
+static inline unsigned int fwcap_to_cc_pause(unsigned int fw_pause)
+{
+	unsigned int cc_pause = 0;
+
+	if (fw_pause & FW_PORT_CAP_FC_RX)
+		cc_pause |= PAUSE_RX;
+	if (fw_pause & FW_PORT_CAP_FC_TX)
+		cc_pause |= PAUSE_TX;
+
+	return cc_pause;
+}
+
+/* Translate Common Code Pause specification into Firmware Port Capabilities */
+static inline unsigned int cc_to_fwcap_pause(unsigned int cc_pause)
+{
+	unsigned int fw_pause = 0;
+
+	if (cc_pause & PAUSE_RX)
+		fw_pause |= FW_PORT_CAP_FC_RX;
+	if (cc_pause & PAUSE_TX)
+		fw_pause |= FW_PORT_CAP_FC_TX;
+
+	return fw_pause;
+}
+
+/* Translate Firmware Forward Error Correction specification to Common Code */
+static inline unsigned int fwcap_to_cc_fec(unsigned int fw_fec)
+{
+	unsigned int cc_fec = 0;
+
+	if (fw_fec & FW_PORT_CAP_FEC_RS)
+		cc_fec |= FEC_RS;
+	if (fw_fec & FW_PORT_CAP_FEC_BASER_RS)
+		cc_fec |= FEC_BASER_RS;
+
+	return cc_fec;
+}
+
+/* Translate Common Code Forward Error Correction specification to Firmware */
+static inline unsigned int cc_to_fwcap_fec(unsigned int cc_fec)
+{
+	unsigned int fw_fec = 0;
+
+	if (cc_fec & FEC_RS)
+		fw_fec |= FW_PORT_CAP_FEC_RS;
+	if (cc_fec & FEC_BASER_RS)
+		fw_fec |= FW_PORT_CAP_FEC_BASER_RS;
+
+	return fw_fec;
+}
+
 /**
  *	t4_link_l1cfg - apply link configuration to MAC/PHY
- *	@phy: the PHY to setup
- *	@mac: the MAC to setup
- *	@lc: the requested link configuration
+ *	@adapter: the adapter
+ *	@mbox: the Firmware Mailbox to use
+ *	@port: the Port ID
+ *	@lc: the Port's Link Configuration
  *
  *	Set up a port's MAC and PHY according to a desired link configuration.
  *	- If the PHY can auto-negotiate first decide what to advertise, then
@@ -3857,22 +3910,46 @@ int t4_link_l1cfg(struct adapter *adap, unsigned int mbox, unsigned int port,
 		  struct link_config *lc)
 {
 	struct fw_port_cmd c;
-	unsigned int mdi = FW_PORT_CAP_MDI_V(FW_PORT_CAP_MDI_AUTO);
-	unsigned int fc = 0, fec = 0, fw_fec = 0;
+	unsigned int fw_mdi = FW_PORT_CAP_MDI_V(FW_PORT_CAP_MDI_AUTO);
+	unsigned int fw_fc, cc_fec, fw_fec;
+	unsigned int rcap;
 
 	lc->link_ok = 0;
-	if (lc->requested_fc & PAUSE_RX)
-		fc |= FW_PORT_CAP_FC_RX;
-	if (lc->requested_fc & PAUSE_TX)
-		fc |= FW_PORT_CAP_FC_TX;
 
-	fec = lc->requested_fec & FEC_AUTO ? lc->auto_fec : lc->requested_fec;
+	/* Convert driver coding of Pause Frame Flow Control settings into the
+	 * Firmware's API.
+	 */
+	fw_fc = cc_to_fwcap_pause(lc->requested_fc);
+
+	/* Convert Common Code Forward Error Control settings into the
+	 * Firmware's API.  If the current Requested FEC has "Automatic"
+	 * (IEEE 802.3) specified, then we use whatever the Firmware
+	 * sent us as part of it's IEEE 802.3-based interpratation of
+	 * the Transceiver Module EPROM FEC parameters.  Otherwise we
+	 * use whatever is in the current Requested FEC settings.
+	 */
+	if (lc->requested_fec & FEC_AUTO)
+		cc_fec = lc->auto_fec;
+	else
+		cc_fec = lc->requested_fec;
+	fw_fec = cc_to_fwcap_fec(cc_fec);
 
-	if (fec & FEC_RS)
-		fw_fec |= FW_PORT_CAP_FEC_RS;
-	if (fec & FEC_BASER_RS)
-		fw_fec |= FW_PORT_CAP_FEC_BASER_RS;
+	/* Figure out what our Requested Port Capabilities are going to be.
+	 */
+	if (!(lc->supported & FW_PORT_CAP_ANEG)) {
+		rcap = (lc->supported & ADVERT_MASK) | fw_fc | fw_fec;
+		lc->fc = lc->requested_fc & (PAUSE_RX | PAUSE_TX);
+		lc->fec = cc_fec;
+	} else if (lc->autoneg == AUTONEG_DISABLE) {
+		rcap = lc->requested_speed | fw_fc | fw_fec | fw_mdi;
+		lc->fc = lc->requested_fc & (PAUSE_RX | PAUSE_TX);
+		lc->fec = cc_fec;
+	} else {
+		rcap = lc->advertising | fw_fc | fw_fec | fw_mdi;
+	}
 
+	/* And send that on to the Firmware ...
+	 */
 	memset(&c, 0, sizeof(c));
 	c.op_to_portid = cpu_to_be32(FW_CMD_OP_V(FW_PORT_CMD) |
 				     FW_CMD_REQUEST_F | FW_CMD_EXEC_F |
@@ -3880,19 +3957,7 @@ int t4_link_l1cfg(struct adapter *adap, unsigned int mbox, unsigned int port,
 	c.action_to_len16 =
 		cpu_to_be32(FW_PORT_CMD_ACTION_V(FW_PORT_ACTION_L1_CFG) |
 			    FW_LEN16(c));
-
-	if (!(lc->supported & FW_PORT_CAP_ANEG)) {
-		c.u.l1cfg.rcap = cpu_to_be32((lc->supported & ADVERT_MASK) |
-					     fc | fw_fec);
-		lc->fc = lc->requested_fc & (PAUSE_RX | PAUSE_TX);
-	} else if (lc->autoneg == AUTONEG_DISABLE) {
-		c.u.l1cfg.rcap = cpu_to_be32(lc->requested_speed | fc |
-					     fw_fec | mdi);
-		lc->fc = lc->requested_fc & (PAUSE_RX | PAUSE_TX);
-	} else
-		c.u.l1cfg.rcap = cpu_to_be32(lc->advertising | fc |
-					     fw_fec | mdi);
-
+	c.u.l1cfg.rcap = cpu_to_be32(rcap);
 	return t4_wr_mbox(adap, mbox, &c, sizeof(c), NULL);
 }
 
@@ -7630,19 +7695,28 @@ static const char *t4_link_down_rc_str(unsigned char link_down_rc)
 void t4_handle_get_port_info(struct port_info *pi, const __be64 *rpl)
 {
 	const struct fw_port_cmd *p = (const void *)rpl;
+	unsigned int acaps = be16_to_cpu(p->u.info.acap);
 	struct adapter *adap = pi->adapter;
 
 	/* link/module state change message */
-	int speed = 0, fc = 0;
+	int speed = 0, fc, fec;
 	struct link_config *lc;
 	u32 stat = be32_to_cpu(p->u.info.lstatus_to_modtype);
 	int link_ok = (stat & FW_PORT_CMD_LSTATUS_F) != 0;
 	u32 mod = FW_PORT_CMD_MODTYPE_G(stat);
 
+	/* Unfortunately the format of the Link Status returned by the
+	 * Firmware isn't the same as the Firmware Port Capabilities bitfield
+	 * used everywhere else ...
+	 */
+	fc = 0;
 	if (stat & FW_PORT_CMD_RXPAUSE_F)
 		fc |= PAUSE_RX;
 	if (stat & FW_PORT_CMD_TXPAUSE_F)
 		fc |= PAUSE_TX;
+
+	fec = fwcap_to_cc_fec(acaps);
+
 	if (stat & FW_PORT_CMD_LSPEED_V(FW_PORT_CAP_SPEED_100M))
 		speed = 100;
 	else if (stat & FW_PORT_CMD_LSPEED_V(FW_PORT_CAP_SPEED_1G))
@@ -7659,11 +7733,20 @@ void t4_handle_get_port_info(struct port_info *pi, const __be64 *rpl)
 	lc = &pi->link_cfg;
 
 	if (mod != pi->mod_type) {
+		/* When a new Transceiver Module is inserted, the Firmware
+		 * will examine any Forward Error Correction parameters
+		 * present in the Transceiver Module i2c EPROM and determine
+		 * the supported and recommended FEC settings from those
+		 * based on IEEE 802.3 standards.  We always record the
+		 * IEEE 802.3 recommended "automatic" settings.
+		 */
+		lc->auto_fec = fec;
+
 		pi->mod_type = mod;
 		t4_os_portmod_changed(adap, pi->port_id);
 	}
 	if (link_ok != lc->link_ok || speed != lc->speed ||
-	    fc != lc->fc) {	/* something changed */
+	    fc != lc->fc || fec != lc->fec) {	/* something changed */
 		if (!link_ok && lc->link_ok) {
 			unsigned char rc = FW_PORT_CMD_LINKDNRC_G(stat);
 
@@ -7675,6 +7758,8 @@ void t4_handle_get_port_info(struct port_info *pi, const __be64 *rpl)
 		lc->link_ok = link_ok;
 		lc->speed = speed;
 		lc->fc = fc;
+		lc->fec = fec;
+
 		lc->supported = be16_to_cpu(p->u.info.pcap);
 		lc->lp_advertising = be16_to_cpu(p->u.info.lpacap);
 
@@ -7764,7 +7849,8 @@ static void get_pci_mode(struct adapter *adapter, struct pci_params *p)
 /**
  *	init_link_config - initialize a link's SW state
  *	@lc: structure holding the link state
- *	@caps: link capabilities
+ *	@pcaps: link Port Capabilities
+ *	@acaps: link current Advertised Port Capabilities
  *
  *	Initializes the SW state maintained for each link, including the link's
  *	capabilities and default speed/flow-control/autonegotiation settings.
@@ -7777,15 +7863,11 @@ static void init_link_config(struct link_config *lc, unsigned int pcaps,
 	lc->requested_speed = 0;
 	lc->speed = 0;
 	lc->requested_fc = lc->fc = PAUSE_RX | PAUSE_TX;
-	lc->auto_fec = 0;
 
 	/* For Forward Error Control, we default to whatever the Firmware
 	 * tells us the Link is currently advertising.
 	 */
-	if (acaps & FW_PORT_CAP_FEC_RS)
-		lc->auto_fec |= FEC_RS;
-	if (acaps & FW_PORT_CAP_FEC_BASER_RS)
-		lc->auto_fec |= FEC_BASER_RS;
+	lc->auto_fec = fwcap_to_cc_fec(acaps);
 	lc->requested_fec = FEC_AUTO;
 	lc->fec = lc->auto_fec;
 
-- 
2.1.4

^ permalink raw reply related

* [PATCH net-next v2 3/3] cxgb4: ethtool forward error correction management support
From: Roopa Prabhu @ 2017-07-27 23:47 UTC (permalink / raw)
  To: davem, linville
  Cc: netdev, vidya.chowdary, dustin, olson, leedom, kubakici, galp,
	andrew, manojmalviya, santosh, yuval.mintz, odedw, ariela,
	jeffrey.t.kirsher
In-Reply-To: <1501199248-24695-1-git-send-email-roopa@cumulusnetworks.com>

From: Casey Leedom <leedom@chelsio.com>

Signed-off-by: Casey Leedom <leedom@chelsio.com>
---
 drivers/net/ethernet/chelsio/cxgb4/cxgb4_ethtool.c | 100 +++++++++++++++++++++
 1 file changed, 100 insertions(+)

diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_ethtool.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_ethtool.c
index 26eb00a..03f593e 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_ethtool.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_ethtool.c
@@ -801,6 +801,104 @@ static int set_link_ksettings(struct net_device *dev,
 	return ret;
 }
 
+/* Translate the Firmware FEC value into the ethtool value. */
+static inline unsigned int fwcap_to_eth_fec(unsigned int fw_fec)
+{
+	unsigned int eth_fec = 0;
+
+	if (fw_fec & FW_PORT_CAP_FEC_RS)
+		eth_fec |= ETHTOOL_FEC_RS;
+	if (fw_fec & FW_PORT_CAP_FEC_BASER_RS)
+		eth_fec |= ETHTOOL_FEC_BASER;
+
+	/* if nothing is set, then FEC is off */
+	if (!eth_fec)
+		eth_fec = ETHTOOL_FEC_OFF;
+
+	return eth_fec;
+}
+
+/* Translate Common Code FEC value into ethtool value. */
+static inline unsigned int cc_to_eth_fec(unsigned int cc_fec)
+{
+	unsigned int eth_fec = 0;
+
+	if (cc_fec & FEC_AUTO)
+		eth_fec |= ETHTOOL_FEC_AUTO;
+	if (cc_fec & FEC_RS)
+		eth_fec |= ETHTOOL_FEC_RS;
+	if (cc_fec & FEC_BASER_RS)
+		eth_fec |= ETHTOOL_FEC_BASER;
+
+	/* if nothing is set, then FEC is off */
+	if (!eth_fec)
+		eth_fec = ETHTOOL_FEC_OFF;
+
+	return eth_fec;
+}
+
+/* Translate ethtool FEC value into Common Code value. */
+static inline unsigned int eth_to_cc_fec(unsigned int eth_fec)
+{
+	unsigned int cc_fec = 0;
+
+	if (eth_fec & ETHTOOL_FEC_OFF)
+		return cc_fec;
+
+	if (eth_fec & ETHTOOL_FEC_AUTO)
+		cc_fec |= FEC_AUTO;
+	if (eth_fec & ETHTOOL_FEC_RS)
+		cc_fec |= FEC_RS;
+	if (eth_fec & ETHTOOL_FEC_BASER)
+		cc_fec |= FEC_BASER_RS;
+
+	return cc_fec;
+}
+
+static int get_fecparam(struct net_device *dev, struct ethtool_fecparam *fec)
+{
+	const struct port_info *pi = netdev_priv(dev);
+	const struct link_config *lc = &pi->link_cfg;
+
+	/* Translate the Firmware FEC Support into the ethtool value.  We
+	 * always support IEEE 802.3 "automatic" selection of Link FEC type if
+	 * any FEC is supported.
+	 */
+	fec->fec = fwcap_to_eth_fec(lc->supported);
+	if (fec->fec != ETHTOOL_FEC_OFF)
+		fec->fec |= ETHTOOL_FEC_AUTO;
+
+	/* Translate the current internal FEC parameters into the
+	 * ethtool values.
+	 */
+	fec->active_fec = cc_to_eth_fec(lc->fec);
+
+	return 0;
+}
+
+static int set_fecparam(struct net_device *dev, struct ethtool_fecparam *fec)
+{
+	struct port_info *pi = netdev_priv(dev);
+	struct link_config *lc = &pi->link_cfg;
+	struct link_config old_lc;
+	int ret;
+
+	/* Save old Link Configuration in case the L1 Configure below
+	 * fails.
+	 */
+	old_lc = *lc;
+
+	/* Try to perform the L1 Configure and return the result of that
+	 * effort.  If it fails, revert the attempted change.
+	 */
+	lc->requested_fec = eth_to_cc_fec(fec->fec);
+	ret = t4_link_l1cfg(pi->adapter, pi->adapter->mbox,
+			    pi->tx_chan, lc);
+	if (ret)
+		*lc = old_lc;
+	return ret;
+}
+
 static void get_pauseparam(struct net_device *dev,
 			   struct ethtool_pauseparam *epause)
 {
@@ -1255,6 +1353,8 @@ static int get_rxnfc(struct net_device *dev, struct ethtool_rxnfc *info,
 static const struct ethtool_ops cxgb_ethtool_ops = {
 	.get_link_ksettings = get_link_ksettings,
 	.set_link_ksettings = set_link_ksettings,
+	.get_fecparam      = get_fecparam,
+	.set_fecparam      = set_fecparam,
 	.get_drvinfo       = get_drvinfo,
 	.get_msglevel      = get_msglevel,
 	.set_msglevel      = set_msglevel,
-- 
2.1.4

^ permalink raw reply related

* Re: [PATCH 1/2] net: phy: rework Kconfig settings for MDIO_BUS
From: David Miller @ 2017-07-28  0:20 UTC (permalink / raw)
  To: arnd
  Cc: netdev, kishon, andrew, f.fainelli, linux-kernel,
	raviteja.garimella, Raju.Lakkaraju
In-Reply-To: <20170726151442.3913622-1-arnd@arndb.de>

From: Arnd Bergmann <arnd@arndb.de>
Date: Wed, 26 Jul 2017 17:13:59 +0200

> I still see build errors in randconfig builds and have had this
> patch for a while to locally work around it:
> 
> drivers/built-in.o: In function `xgene_mdio_probe':
> mux-core.c:(.text+0x352154): undefined reference to `of_mdiobus_register'
> mux-core.c:(.text+0x352168): undefined reference to `mdiobus_free'
> mux-core.c:(.text+0x3521c0): undefined reference to `mdiobus_alloc_size'
> 
> The idea is that CONFIG_MDIO_BUS now reflects whether the mdio_bus
> code is built-in or a module, and other drivers that use the core
> code can simply depend on that, instead of having a complex
> dependency line.
> 
> Fixes: 90eff9096c01 ("net: phy: Allow splitting MDIO bus/device support from PHYs")
> Signed-off-by: Arnd Bergmann <arnd@arndb.de>
> Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>

Applied.

^ permalink raw reply

* Re: [PATCH 2/2] phy: bcm-ns-usb3: fix MDIO_BUS dependency
From: David Miller @ 2017-07-28  0:20 UTC (permalink / raw)
  To: arnd
  Cc: netdev, kishon, andrew, f.fainelli, linux-kernel,
	raviteja.garimella, rafal
In-Reply-To: <20170726151442.3913622-2-arnd@arndb.de>

From: Arnd Bergmann <arnd@arndb.de>
Date: Wed, 26 Jul 2017 17:14:00 +0200

> The driver attempts to 'select MDIO_DEVICE', but the code
> is actually a loadable module when PHYLIB=m:
> 
> drivers/phy/broadcom/phy-bcm-ns-usb3.o: In function `bcm_ns_usb3_mdiodev_phy_write':
> phy-bcm-ns-usb3.c:(.text.bcm_ns_usb3_mdiodev_phy_write+0x28): undefined reference to `mdiobus_write'
> drivers/phy/broadcom/phy-bcm-ns-usb3.o: In function `bcm_ns_usb3_module_exit':
> phy-bcm-ns-usb3.c:(.exit.text+0x18): undefined reference to `mdio_driver_unregister'
> drivers/phy/broadcom/phy-bcm-ns-usb3.o: In function `bcm_ns_usb3_module_init':
> phy-bcm-ns-usb3.c:(.init.text+0x18): undefined reference to `mdio_driver_register'
> phy-bcm-ns-usb3.c:(.init.text+0x38): undefined reference to `mdio_driver_unregister'
> 
> Using 'depends on MDIO_BUS' instead will avoid the link error.
> 
> Fixes: af850e14a7ae ("phy: bcm-ns-usb3: add MDIO driver using proper bus layer")
> Signed-off-by: Arnd Bergmann <arnd@arndb.de>
> Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>

Applied.

^ permalink raw reply

* Re: [PATCH net-next 0/3] nfp: extend firmware request logic
From: David Miller @ 2017-07-28  0:26 UTC (permalink / raw)
  To: jakub.kicinski; +Cc: netdev, oss-drivers
In-Reply-To: <20170726180948.3220-1-jakub.kicinski@netronome.com>

From: Jakub Kicinski <jakub.kicinski@netronome.com>
Date: Wed, 26 Jul 2017 11:09:45 -0700

> We have been pondering for some time how to support loading different
> application firmwares onto NFP.  We want to support both users selecting
> one of the firmware images provided by Netronome (which are optimized
> for different use cases each) as well as firmware images created  by 
> users themselves or other companies.
> 
> In the end we decided to go with the simplest solution - depending on
> the right firmware image being placed in /lib/firmware.  This vastly
> simplifies driver logic and also doesn't require any new API.
> 
> Different NICs on one system may want to run different applications
> therefore we first try to load firmware specific to the device (by 
> serial number of PCI slot) and if not present try the device model
> based name we have been using so far.

Series applied, thanks Jakub.

^ permalink raw reply

* Re: [PATCH net-next] net: phy: Remove stale comments referencing timer
From: David Miller @ 2017-07-28  0:27 UTC (permalink / raw)
  To: f.fainelli; +Cc: netdev, andrew, slash.tmp
In-Reply-To: <20170726190538.27674-1-f.fainelli@gmail.com>

From: Florian Fainelli <f.fainelli@gmail.com>
Date: Wed, 26 Jul 2017 12:05:38 -0700

> Since commit a390d1f379cf ("phylib: convert state_queue work to
> delayed_work"), the PHYLIB state machine was converted to use delayed
> workqueues, yet some functions were still referencing the PHY library
> timer in their comments, fix that and remove the now unused
> linux/timer.h include.
> 
> Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>

Applied.

^ permalink raw reply

* Re: [PATCH v3 net-next 0/2] liquidio: standardization and cleanup
From: David Miller @ 2017-07-28  0:29 UTC (permalink / raw)
  To: felix.manlunas
  Cc: netdev, raghu.vatsavayi, derek.chickles, satananda.burla,
	ricardo.farrington
In-Reply-To: <20170726190945.GA1152@felix-thinkpad.cavium.com>

From: Felix Manlunas <felix.manlunas@cavium.com>
Date: Wed, 26 Jul 2017 12:09:45 -0700

> From: Rick Farrington <ricardo.farrington@cavium.com>
> 
> This patchset corrects some non-standard macro usage.
> 
> 1. Replaced custom MIN macro with use of standard 'min_t'.
> 2. Removed cryptic and misleading macro 'CAST_ULL'.
> 
> change log:
> V1 -> V2:
>   1. Add driver cleanup of macro 'CAST_ULL'.
> V2 -> V3:
>   1. Remove extra parentheses from previous usage of macro 'CAST_ULL'.

Series applied, thank you.

^ permalink raw reply

* [PATCH v4 net-next] net: systemport: Support 64bit statistics
From: Jianming.qiao @ 2017-07-28  0:43 UTC (permalink / raw)
  To: f.fainelli, davem, netdev

When using Broadcom Systemport device in 32bit Platform, ifconfig can
only report up to 4G tx,rx status, which will be wrapped to 0 when the
number of incoming or outgoing packets exceeds 4G, only taking
around 2 hours in busy network environment (such as streaming).
Therefore, it makes hard for network diagnostic tool to get reliable
statistical result, so the patch is used to add 64bit support for
Broadcom Systemport device in 32bit Platform.

Signed-off-by: Jianming.qiao <kiki-good@hotmail.com>
---
 drivers/net/ethernet/broadcom/bcmsysport.c | 74 ++++++++++++++++++++----------
 drivers/net/ethernet/broadcom/bcmsysport.h |  9 +++-
 2 files changed, 57 insertions(+), 26 deletions(-)

diff --git a/drivers/net/ethernet/broadcom/bcmsysport.c b/drivers/net/ethernet/broadcom/bcmsysport.c
index 5274501..16cd8a6 100644
--- a/drivers/net/ethernet/broadcom/bcmsysport.c
+++ b/drivers/net/ethernet/broadcom/bcmsysport.c
@@ -662,6 +662,7 @@ static int bcm_sysport_alloc_rx_bufs(struct bcm_sysport_priv *priv)
 static unsigned int bcm_sysport_desc_rx(struct bcm_sysport_priv *priv,
 					unsigned int budget)
 {
+	struct bcm_sysport_stats *stats64 = &priv->stats64;
 	struct net_device *ndev = priv->netdev;
 	unsigned int processed = 0, to_process;
 	struct bcm_sysport_cb *cb;
@@ -765,6 +766,10 @@ static unsigned int bcm_sysport_desc_rx(struct bcm_sysport_priv *priv,
 		skb->protocol = eth_type_trans(skb, ndev);
 		ndev->stats.rx_packets++;
 		ndev->stats.rx_bytes += len;
+		u64_stats_update_begin(&stats64->syncp);
+		stats64->rx_packets++;
+		stats64->rx_bytes += len;
+		u64_stats_update_end(&stats64->syncp);
 
 		napi_gro_receive(&priv->napi, skb);
 next:
@@ -784,24 +789,32 @@ static void bcm_sysport_tx_reclaim_one(struct bcm_sysport_tx_ring *ring,
 				       unsigned int *pkts_compl)
 {
 	struct bcm_sysport_priv *priv = ring->priv;
+	struct bcm_sysport_stats *stats64 = &priv->stats64;
 	struct device *kdev = &priv->pdev->dev;
+	unsigned int len = 0;
 
 	if (cb->skb) {
-		ring->bytes += cb->skb->len;
-		*bytes_compl += cb->skb->len;
+		len = cb->skb->len;
+		*bytes_compl += len;
 		dma_unmap_single(kdev, dma_unmap_addr(cb, dma_addr),
 				 dma_unmap_len(cb, dma_len),
 				 DMA_TO_DEVICE);
-		ring->packets++;
 		(*pkts_compl)++;
-		bcm_sysport_free_cb(cb);
 	/* SKB fragment */
 	} else if (dma_unmap_addr(cb, dma_addr)) {
-		ring->bytes += dma_unmap_len(cb, dma_len);
+		len = dma_unmap_len(cb, dma_len);
 		dma_unmap_page(kdev, dma_unmap_addr(cb, dma_addr),
 			       dma_unmap_len(cb, dma_len), DMA_TO_DEVICE);
 		dma_unmap_addr_set(cb, dma_addr, 0);
 	}
+
+	u64_stats_update_begin(&stats64->syncp);
+	ring->bytes += len;
+	if (cb->skb) {
+		ring->packets++;
+		bcm_sysport_free_cb(cb);
+	}
+	u64_stats_update_end(&stats64->syncp);
 }
 
 /* Reclaim queued SKBs for transmission completion, lockless version */
@@ -1671,24 +1684,6 @@ static int bcm_sysport_change_mac(struct net_device *dev, void *p)
 	return 0;
 }
 
-static struct net_device_stats *bcm_sysport_get_nstats(struct net_device *dev)
-{
-	struct bcm_sysport_priv *priv = netdev_priv(dev);
-	unsigned long tx_bytes = 0, tx_packets = 0;
-	struct bcm_sysport_tx_ring *ring;
-	unsigned int q;
-
-	for (q = 0; q < dev->num_tx_queues; q++) {
-		ring = &priv->tx_rings[q];
-		tx_bytes += ring->bytes;
-		tx_packets += ring->packets;
-	}
-
-	dev->stats.tx_bytes = tx_bytes;
-	dev->stats.tx_packets = tx_packets;
-	return &dev->stats;
-}
-
 static void bcm_sysport_netif_start(struct net_device *dev)
 {
 	struct bcm_sysport_priv *priv = netdev_priv(dev);
@@ -1923,6 +1918,37 @@ static int bcm_sysport_stop(struct net_device *dev)
 	return 0;
 }
 
+static void bcm_sysport_get_stats64(struct net_device *dev,
+				    struct rtnl_link_stats64 *stats)
+{
+	struct bcm_sysport_priv *priv = netdev_priv(dev);
+	struct bcm_sysport_stats *stats64 = &priv->stats64;
+	struct bcm_sysport_tx_ring *ring;
+	u64 tx_packets = 0, tx_bytes = 0;
+	unsigned int start;
+	unsigned int q;
+
+	netdev_stats_to_stats64(stats, &dev->stats);
+
+	for (q = 0; q < dev->num_tx_queues; q++) {
+		ring = &priv->tx_rings[q];
+		do {
+			start = u64_stats_fetch_begin_irq(&stats64->syncp);
+			tx_bytes += ring->bytes;
+			tx_packets += ring->packets;
+		} while (u64_stats_fetch_retry_irq(&stats64->syncp, start));
+	}
+
+	stats->tx_packets = tx_packets;
+	stats->tx_bytes = tx_bytes;
+
+	do {
+		start = u64_stats_fetch_begin_irq(&stats64->syncp);
+		stats->rx_packets = stats64->rx_packets;
+		stats->rx_bytes = stats64->rx_bytes;
+	} while (u64_stats_fetch_retry_irq(&stats64->syncp, start));
+}
+
 static const struct ethtool_ops bcm_sysport_ethtool_ops = {
 	.get_drvinfo		= bcm_sysport_get_drvinfo,
 	.get_msglevel		= bcm_sysport_get_msglvl,
@@ -1950,7 +1976,7 @@ static int bcm_sysport_stop(struct net_device *dev)
 #ifdef CONFIG_NET_POLL_CONTROLLER
 	.ndo_poll_controller	= bcm_sysport_poll_controller,
 #endif
-	.ndo_get_stats		= bcm_sysport_get_nstats,
+	.ndo_get_stats64	= bcm_sysport_get_stats64,
 };
 
 #define REV_FMT	"v%2x.%02x"
diff --git a/drivers/net/ethernet/broadcom/bcmsysport.h b/drivers/net/ethernet/broadcom/bcmsysport.h
index 77a51c1..c03a176 100644
--- a/drivers/net/ethernet/broadcom/bcmsysport.h
+++ b/drivers/net/ethernet/broadcom/bcmsysport.h
@@ -657,6 +657,9 @@ struct bcm_sysport_stats {
 	enum bcm_sysport_stat_type type;
 	/* reg offset from UMAC base for misc counters */
 	u16 reg_offset;
+	u64     rx_packets;
+	u64     rx_bytes;
+	struct u64_stats_sync   syncp;
 };
 
 /* Software house keeping helper structure */
@@ -693,8 +696,8 @@ struct bcm_sysport_tx_ring {
 	struct bcm_sysport_cb *cbs;	/* Transmit control blocks */
 	struct dma_desc	*desc_cpu;	/* CPU view of the descriptor */
 	struct bcm_sysport_priv *priv;	/* private context backpointer */
-	unsigned long	packets;	/* packets statistics */
-	unsigned long	bytes;		/* bytes statistics */
+	u64	packets;		/* packets statistics */
+	u64	bytes;			/* bytes statistics */
 };
 
 /* Driver private structure */
@@ -743,5 +746,7 @@ struct bcm_sysport_priv {
 
 	/* Ethtool */
 	u32			msg_enable;
+	/* 64bit stats on 32bit/64bit Machine */
+	struct bcm_sysport_stats stats64;
 };
 #endif /* __BCM_SYSPORT_H */
-- 
1.9.1

^ 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