* Re: Crash due to mutex genl_lock called from RCU context
From: subashab @ 2016-11-26 5:59 UTC (permalink / raw)
To: Eric Dumazet; +Cc: tgraf, netdev, netdev-owner
In-Reply-To: <1480136078.8455.589.camel@edumazet-glaptop3.roam.corp.google.com>
> Oh well, this wont work, since sk->sk_destruct will be called from RCU
> callback.
>
> Grabbing the mutex should not be done from netlink_sock_destruct() but
> from netlink_release()
>
> Maybe this patch would be better :
>
> diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c
> index 62bea4591054..cce10e3c9b68 100644
> --- a/net/netlink/af_netlink.c
> +++ b/net/netlink/af_netlink.c
> @@ -324,16 +324,6 @@ static void netlink_skb_set_owner_r(struct
> sk_buff *skb, struct sock *sk)
>
> static void netlink_sock_destruct(struct sock *sk)
> {
> - struct netlink_sock *nlk = nlk_sk(sk);
> -
> - if (nlk->cb_running) {
> - if (nlk->cb.done)
> - nlk->cb.done(&nlk->cb);
> -
> - module_put(nlk->cb.module);
> - kfree_skb(nlk->cb.skb);
> - }
> -
> skb_queue_purge(&sk->sk_receive_queue);
>
> if (!sock_flag(sk, SOCK_DEAD)) {
> @@ -456,8 +446,9 @@ static struct sock *netlink_lookup(struct net
> *net, int protocol, u32 portid)
>
> rcu_read_lock();
> sk = __netlink_lookup(table, portid, net);
> - if (sk)
> - sock_hold(sk);
> + if (sk && !atomic_inc_not_zero(&sk->sk_refcnt))
> + sk = NULL;
> +
> rcu_read_unlock();
>
> return sk;
> @@ -581,6 +572,7 @@ static int __netlink_create(struct net *net,
> struct socket *sock,
> }
> init_waitqueue_head(&nlk->wait);
>
> + sock_set_flag(sk, SOCK_RCU_FREE);
> sk->sk_destruct = netlink_sock_destruct;
> sk->sk_protocol = protocol;
> return 0;
> @@ -645,13 +637,6 @@ static int netlink_create(struct net *net, struct
> socket *sock, int protocol,
> goto out;
> }
>
> -static void deferred_put_nlk_sk(struct rcu_head *head)
> -{
> - struct netlink_sock *nlk = container_of(head, struct netlink_sock,
> rcu);
> -
> - sock_put(&nlk->sk);
> -}
> -
> static int netlink_release(struct socket *sock)
> {
> struct sock *sk = sock->sk;
> @@ -724,7 +709,19 @@ static int netlink_release(struct socket *sock)
> local_bh_disable();
> sock_prot_inuse_add(sock_net(sk), &netlink_proto, -1);
> local_bh_enable();
> - call_rcu(&nlk->rcu, deferred_put_nlk_sk);
> + if (nlk->cb_running) {
> + mutex_lock(nlk->cb_mutex);
> + if (nlk->cb_running) {
> + if (nlk->cb.done)
> + nlk->cb.done(&nlk->cb);
> +
> + module_put(nlk->cb.module);
> + kfree_skb(nlk->cb.skb);
> + nlk->cb_running = false;
> + }
> + mutex_unlock(nlk->cb_mutex);
> + }
> + sock_put(sk);
> return 0;
> }
>
> diff --git a/net/netlink/af_netlink.h b/net/netlink/af_netlink.h
> index 3cfd6cc60504..5dc08a7b0a2b 100644
> --- a/net/netlink/af_netlink.h
> +++ b/net/netlink/af_netlink.h
> @@ -32,7 +32,6 @@ struct netlink_sock {
> struct module *module;
>
> struct rhash_head node;
> - struct rcu_head rcu;
> };
>
> static inline struct netlink_sock *nlk_sk(struct sock *sk)
Thanks Eric! I'll try this and get back with results over this weekend.
^ permalink raw reply
* Re: [Patch net-next] net_sched: move the empty tp check from ->destroy() to ->delete()
From: Cong Wang @ 2016-11-26 6:46 UTC (permalink / raw)
To: Daniel Borkmann
Cc: Roi Dayan, Linux Kernel Network Developers, Jiri Pirko,
John Fastabend
In-Reply-To: <58370558.9070004@iogearbox.net>
On Thu, Nov 24, 2016 at 7:20 AM, Daniel Borkmann <daniel@iogearbox.net> wrote:
>
> Ok, strange, qdisc_destroy() calls into ops->destroy(), where ingress
> drops its entire chain via tcf_destroy_chain(), so that will be NULL
> eventually. The tps are freed by call_rcu() as well as qdisc itself
> later on via qdisc_rcu_free(), where it frees per-cpu bstats as well.
> Outstanding readers should either bail out due to if (!cl) or can still
> process the chain until read section ends, but during that time, cl->q
> resp. bstats should be good. Do you happen to know what's at address
> ffff880a68b04028? I was wondering wrt call_rcu() vs call_rcu_bh(), but
> at least on ingress (netif_receive_skb_internal()) we hold rcu_read_lock()
> here. The KASAN report is reliably happening at this location, right?
I am confused as well, I don't see how it could be related to my patch yet.
I will take a deep look in the weekend.
Thanks!
^ permalink raw reply
* Xmas Offer
From: Mrs Julie Leach @ 2016-11-26 7:02 UTC (permalink / raw)
To: Recipients
You are a recipient to Mrs Julie Leach Donation of $3 million USD. Contact ( julieleach93@gmail.com ) for claims.
^ permalink raw reply
* [PATCH net-next] cgroup, bpf: remove unnecessary #include
From: Alexei Starovoitov @ 2016-11-26 7:23 UTC (permalink / raw)
To: David S . Miller; +Cc: Daniel Borkmann, Daniel Mack, Tejun Heo, netdev
this #include is unnecessary and brings whole set of
other headers into cgroup-defs.h. Remove it.
Fixes: 3007098494be ("cgroup: add support for eBPF programs")
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
---
include/linux/bpf-cgroup.h | 1 -
1 file changed, 1 deletion(-)
diff --git a/include/linux/bpf-cgroup.h b/include/linux/bpf-cgroup.h
index ec80d0c0953e..0cf1adfadd2d 100644
--- a/include/linux/bpf-cgroup.h
+++ b/include/linux/bpf-cgroup.h
@@ -1,7 +1,6 @@
#ifndef _BPF_CGROUP_H
#define _BPF_CGROUP_H
-#include <linux/bpf.h>
#include <linux/jump_label.h>
#include <uapi/linux/bpf.h>
--
2.8.0
^ permalink raw reply related
* net: stmmac: Meson GXBB: attempting to execute userspace memory
From: Heinrich Schuchardt @ 2016-11-26 7:53 UTC (permalink / raw)
To: Carlo Caione, Kevin Hilman
Cc: Giuseppe Cavallaro, Alexandre Torgue, netdev, linux-arm-kernel,
linux-amlogic, lkml
For Odroid C2 I have compiled kernel
4.9.0-rc6-next-20161124-00001-gbf7e142
with one additional patch
https://github.com/xypron/kernel-odroid-c2/blob/master/patch/0001-stmmac-RTL8211F-Meson-GXBB-TX-throughput-problems.patch
I repeatedly see faults like the one below:
[ 2557.400796] Unhandled fault: synchronous external abort (0x92000010)
at 0x000040001e8ee4b0
[ 2557.952413] CPU: 0 PID: 22837 Comm: cc1 Tainted: G D
4.9.0-rc6-next-20161124-00001-gbf7e142 #1
[ 2557.962062] Hardware name: Hardkernel ODROID-C2 (DT)
[ 2557.966980] task: ffff80006ddb7080 task.stack: ffff80006dd9c000
[ 2557.972846] PC is at 0x6a0d98
[ 2557.975776] LR is at 0x6a0e54
[ 2557.978709] pc : [<00000000006a0d98>] lr : [<00000000006a0e54>]
pstate: 80000000
[ 2557.986040] sp : 0000fffff3ee5f80
[ 2557.989318] x29: 0000fffff3ee5f80 x28: 000040000b3f1240
[ 2557.994578] x27: 00000000012a7000 x26: 000040000b3f1288
[ 2557.999840] x25: 0000000000f58f88 x24: 000040000b3f1240
[ 2558.005101] x23: 0000000000000000 x22: 0000000000000001
[ 2558.010362] x21: 0000000000000001 x20: 000040000b3f1250
[ 2558.015623] x19: 0000000000000054 x18: 0000000000000001
[ 2558.020885] x17: 0000400008acaa10 x16: 0000000001285050
[ 2558.026146] x15: 000040000ad96dc8 x14: 000000000000001f
[ 2558.031407] x13: 000040000b3f1270 x12: 000040000b3f1258
[ 2558.036668] x11: 0000000001347000 x10: 0000000000000661
[ 2558.041930] x9 : 0000000000000005 x8 : 0000000000000003
[ 2558.047191] x7 : 000040000b3f1240 x6 : 0000000020020033
[ 2558.052452] x5 : 000040000b402020 x4 : 000040000b3e1aa0
[ 2558.057713] x3 : 000000000000000c x2 : 0000000000000020
[ 2558.062974] x1 : 0000000000f45000 x0 : 0000000000000065
[ 2558.068235]
[ 2558.069712] Internal error: Attempting to execute userspace memory:
8600000f [#7] PREEMPT SMP
[ 2558.078155] Modules linked in: meson_rng rng_core meson_gxbb_wdt
ip_tables x_tables ipv6 dwmac_generic realtek dwmac_meson8b
stmmac_platform stmmac
[ 2558.091267] CPU: 0 PID: 22837 Comm: cc1 Tainted: G D
4.9.0-rc6-next-20161124-00001-gbf7e142 #1
[ 2558.100925] Hardware name: Hardkernel ODROID-C2 (DT)
[ 2558.105841] task: ffff80006ddb7080 task.stack: ffff80006dd9c000
[ 2558.111706] PC is at 0x6a0e54
[ 2558.114638] LR is at 0x6a0e54
[ 2558.117571] pc : [<00000000006a0e54>] lr : [<00000000006a0e54>]
pstate: 600003c5
[ 2558.124902] sp : ffff80006dd9fec0
[ 2558.128179] x29: 0000000000000000 x28: ffff80006ddb7080
[ 2558.133441] x27: 00000000012a7000 x26: 000040000b3f1288
[ 2558.138702] x25: 0000000000f58f88 x24: 000040000b3f1240
[ 2558.143963] x23: 0000000080000000 x22: 00000000006a0d98
[ 2558.149225] x21: ffffffffffffffff x20: 000080006e223000
[ 2558.154486] x19: 0000000000000000 x18: 0000000000000010
[ 2558.159747] x17: 0000400008acaa10 x16: 0000000001285050
[ 2558.165008] x15: ffff000088e91f07 x14: 0000000000000006
[ 2558.170270] x13: ffff000008e91f15 x12: 000000000000000f
[ 2558.175531] x11: 0000000000000002 x10: 00000000000002ea
[ 2558.180792] x9 : ffff80006dd9fb40 x8 : 0000000000010a8b
[ 2558.186053] x7 : 0000000000000000 x6 : 000000000000020e
[ 2558.191315] x5 : 00000000020f020e x4 : 0000000000000000
[ 2558.196576] x3 : 0000000000000000 x2 : 000000000000020f
[ 2558.201837] x1 : ffff80006ddb7080 x0 : 0000000000000000
[ 2558.207098]
[ 2558.208565] Process cc1 (pid: 22837, stack limit = 0xffff80006dd9c000)
[ 2558.215035] Stack: (0xffff80006dd9fec0 to 0xffff80006dda0000)
[ 2558.220728] fec0: 0000000000000065 0000000000f45000 0000000000000020
000000000000000c
[ 2558.228490] fee0: 000040000b3e1aa0 000040000b402020 0000000020020033
000040000b3f1240
[ 2558.236253] ff00: 0000000000000003 0000000000000005 0000000000000661
0000000001347000
[ 2558.244015] ff20: 000040000b3f1258 000040000b3f1270 000000000000001f
000040000ad96dc8
[ 2558.251778] ff40: 0000000001285050 0000400008acaa10 0000000000000001
0000000000000054
[ 2558.259540] ff60: 000040000b3f1250 0000000000000001 0000000000000001
0000000000000000
[ 2558.267303] ff80: 000040000b3f1240 0000000000f58f88 000040000b3f1288
00000000012a7000
[ 2558.275065] ffa0: 000040000b3f1240 0000fffff3ee5f80 00000000006a0e54
0000fffff3ee5f80
[ 2558.282828] ffc0: 00000000006a0d98 0000000080000000 0000000000000003
ffffffffffffffff
[ 2558.290590] ffe0: 0000000000000000 0000000000000000 0000000000000000
0000000000000000
[ 2558.298351] Call trace:
[ 2558.300769] Exception stack(0xffff80006dd9fcf0 to 0xffff80006dd9fe20)
[ 2558.307149] fce0: 0000000000000000
0001000000000000
[ 2558.314913] fd00: ffff80006dd9fec0 00000000006a0e54 ffff800073acf500
0000000000000004
[ 2558.322675] fd20: 0000000000000000 ffff000008dbbc18 ffff80006ddb7080
000000006dd9fdd0
[ 2558.330438] fd40: ffff80006dd9fd90 ffff0000080ca878 ffff80006dd9fe40
ffff80006ddb7080
[ 2558.338200] fd60: 0000000000000004 00000000000003c0 ffff80006dd9fe40
000040000b3f1240
[ 2558.345963] fd80: 0000000000f58f88 000040000b3f1288 0000000000000000
ffff80006ddb7080
[ 2558.353725] fda0: 000000000000020f 0000000000000000 0000000000000000
00000000020f020e
[ 2558.361487] fdc0: 000000000000020e 0000000000000000 0000000000010a8b
ffff80006dd9fb40
[ 2558.369250] fde0: 00000000000002ea 0000000000000002 000000000000000f
ffff000008e91f15
[ 2558.377012] fe00: 0000000000000006 ffff000088e91f07 0000000001285050
0000400008acaa10
[ 2558.384775] [<00000000006a0e54>] 0x6a0e54
[ 2558.388743] Code: d503201f f9400280 2a1703e1 97ffff0a (aa0003f3)
[ 2558.395241] ---[ end trace 7d280955c14d4ff1 ]---
[ 2558.584022] Bad mode in Error handler detected on CPU0, code
0xbf000000 -- SError
[ 2558.585871] CPU: 0 PID: 22867 Comm: cc1 Tainted: G D
4.9.0-rc6-next-20161124-00001-gbf7e142 #1
[ 2558.595527] Hardware name: Hardkernel ODROID-C2 (DT)
[ 2558.600444] task: ffff80007454d780 task.stack: ffff8000660bc000
[ 2558.606310] PC is at 0x631928
[ 2558.609240] LR is at 0xb59ce0
[ 2558.612172] pc : [<0000000000631928>] lr : [<0000000000b59ce0>]
pstate: 80000000
[ 2558.619503] sp : 0000ffffed764d90
[ 2558.622782] x29: 0000ffffed764d90 x28: 0000000000000028
[ 2558.628042] x27: 000000001a1062f0 x26: 0000000001299198
[ 2558.633303] x25: 0000000000000001 x24: 0000000000000000
[ 2558.638564] x23: 0000000000000004 x22: 00000000013513c8
[ 2558.643825] x21: 0000400039d43488 x20: 0000000000000000
[ 2558.649086] x19: 0000400039d2d730 x18: 0000000000000000
[ 2558.654348] x17: 0000400039a7c378 x16: 0000000001285138
[ 2558.659609] x15: 0000000000000001 x14: 0000000000000000
[ 2558.664870] x13: ffffff0000000000 x12: 0000000000000000
[ 2558.670131] x11: 0000000000000028 x10: 000000000129b2b8
[ 2558.675393] x9 : 0000000000000041 x8 : 0000000000000003
[ 2558.680654] x7 : 0000000000000050 x6 : 000000000003d2c8
[ 2558.685915] x5 : 0000000000000002 x4 : 0000000000000004
[ 2558.691176] x3 : 0000000000000003 x2 : 0000000001349000
[ 2558.696438] x1 : 000000000003cb90 x0 : 0000400039d45050
[ 2558.701699]
[ 2558.703177] Internal error: Attempting to execute userspace memory:
8600000f [#8] PREEMPT SMP
[ 2558.711618] Modules linked in: meson_rng rng_core meson_gxbb_wdt
ip_tables x_tables ipv6 dwmac_generic realtek dwmac_meson8b
stmmac_platform stmmac
[ 2558.724731] CPU: 0 PID: 22867 Comm: cc1 Tainted: G D
4.9.0-rc6-next-20161124-00001-gbf7e142 #1
[ 2558.734388] Hardware name: Hardkernel ODROID-C2 (DT)
[ 2558.739304] task: ffff80007454d780 task.stack: ffff8000660bc000
[ 2558.745169] PC is at 0xb59ce0
[ 2558.748102] LR is at 0xb59ce0
[ 2558.751035] pc : [<0000000000b59ce0>] lr : [<0000000000b59ce0>]
pstate: 600003c5
[ 2558.758365] sp : ffff8000660bfec0
[ 2558.761643] x29: 0000000000000000 x28: ffff80007454d780
[ 2558.766904] x27: 000000001a1062f0 x26: 0000000001299198
[ 2558.772165] x25: 0000000000000001 x24: 0000000000000000
[ 2558.777426] x23: 0000000080000000 x22: 0000000000631928
[ 2558.782688] x21: ffffffffffffffff x20: 000080006e223000
[ 2558.787949] x19: 0000000000000000 x18: 0000000000000010
[ 2558.793210] x17: 0000400039a7c378 x16: 0000000001285138
[ 2558.798471] x15: ffff000088e91f07 x14: 0000000000000006
[ 2558.803733] x13: ffff000008e91f15 x12: 000000000000000f
[ 2558.808994] x11: 0000000000000002 x10: 0000000000000336
[ 2558.814255] x9 : ffff8000660bfb40 x8 : 00000000000ab503
[ 2558.819516] x7 : 0000000000000000 x6 : 00000000000000dd
[ 2558.824778] x5 : 0000000000de00dd x4 : 0000000000000000
[ 2558.830039] x3 : 0000000000000000 x2 : 00000000000000de
[ 2558.835300] x1 : ffff80007454d780 x0 : 0000000000000000
[ 2558.840561]
[ 2558.842029] Process cc1 (pid: 22867, stack limit = 0xffff8000660bc000)
[ 2558.848498] Stack: (0xffff8000660bfec0 to 0xffff8000660c0000)
[ 2558.854191] fec0: 0000400039d45050 000000000003cb90 0000000001349000
0000000000000003
[ 2558.861953] fee0: 0000000000000004 0000000000000002 000000000003d2c8
0000000000000050
[ 2558.869716] ff00: 0000000000000003 0000000000000041 000000000129b2b8
0000000000000028
[ 2558.877478] ff20: 0000000000000000 ffffff0000000000 0000000000000000
0000000000000001
[ 2558.885241] ff40: 0000000001285138 0000400039a7c378 0000000000000000
0000400039d2d730
[ 2558.893003] ff60: 0000000000000000 0000400039d43488 00000000013513c8
0000000000000004
[ 2558.900766] ff80: 0000000000000000 0000000000000001 0000000001299198
000000001a1062f0
[ 2558.908529] ffa0: 0000000000000028 0000ffffed764d90 0000000000b59ce0
0000ffffed764d90
[ 2558.916291] ffc0: 0000000000631928 0000000080000000 000000001a18c000
ffffffffffffffff
[ 2558.924053] ffe0: 0000000000000000 0000000000000000 0000000000000000
0000000000000000
[ 2558.931814] Call trace:
[ 2558.934232] Exception stack(0xffff8000660bfcf0 to 0xffff8000660bfe20)
[ 2558.940613] fce0: 0000000000000000
0001000000000000
[ 2558.948376] fd00: ffff8000660bfec0 0000000000b59ce0 ffff800073acf640
0000000000000004
[ 2558.956138] fd20: 0000000000000000 ffff000008dbbc18 ffff80007454d780
00000000660bfdd0
[ 2558.963901] fd40: ffff8000660bfd90 ffff0000080ca878 ffff8000660bfe40
ffff80007454d780
[ 2558.971663] fd60: 0000000000000004 00000000000003c0 ffff8000660bfe40
0000000000000000
[ 2558.979426] fd80: 0000000000000001 0000000001299198 0000000000000000
ffff80007454d780
[ 2558.987188] fda0: 00000000000000de 0000000000000000 0000000000000000
0000000000de00dd
[ 2558.994951] fdc0: 00000000000000dd 0000000000000000 00000000000ab503
ffff8000660bfb40
[ 2559.002713] fde0: 0000000000000336 0000000000000002 000000000000000f
ffff000008e91f15
[ 2559.010476] fe00: 0000000000000006 ffff000088e91f07 0000000001285138
0000400039a7c378
[ 2559.018238] [<0000000000b59ce0>] 0xb59ce0
[ 2559.022207] Code: d2800001 d2800002 d2800500 97eb5e9d (a9007c1f)
[ 2559.028376] ---[ end trace 7d280955c14d4ff2 ]---
[ 2559.034397] Bad mode in Error handler detected on CPU2, code
0xbf000000 -- SError
[ 2559.040235] CPU: 2 PID: 22866 Comm: gcc Tainted: G D
4.9.0-rc6-next-20161124-00001-gbf7e142 #1
[ 2559.049892] Hardware name: Hardkernel ODROID-C2 (DT)
[ 2559.054808] task: ffff80007454e400 task.stack: ffff80006de9c000
[ 2559.060674] PC is at 0x40003c0400d8
[ 2559.064122] LR is at 0x46d4e0
[ 2559.067055] pc : [<000040003c0400d8>] lr : [<000000000046d4e0>]
pstate: 80000000
[ 2559.074385] sp : 0000ffffe6387270
[ 2559.077664] x29: 0000ffffe6387270 x28: 0000000016c0ff90
[ 2559.082924] x27: 0000000000000002 x26: 0000000000000001
[ 2559.088185] x25: 0000ffffe63873f4 x24: 0000ffffe63873f8
[ 2559.093447] x23: 0000ffffe63873f4 x22: 0000ffffe63873f8
[ 2559.098708] x21: 0000000016c104e0 x20: 0000000000005953
[ 2559.103969] x19: 0000000000000000 [ 2559.107102] Unhandled fault:
synchronous external abort (0x96000010) at 0xffff800000c1e000
[ 2559.107108] Internal error: : 96000010 [#9] PREEMPT SMP
[ 2559.107110] Modules linked in:
[ 2559.107113] meson_rng rng_core meson_gxbb_wdt ip_tables x_tables
ipv6 dwmac_generic realtek dwmac_meson8b stmmac_platform stmmac[
2559.107131] CPU: 0 PID: 1124 Comm: mmcqd/1 Tainted: G D 1
[ 2559.107132] Hardware name: Hardkernel ODROID-C2 (DT)
[ 2559.107135] task: ffff8000704abe80 task.stack: ffff8000734d0000
[ 2559.107147] PC is at __memcpy+0x100/0x180
[ 2559.107152] LR is at sg_copy_buffer+0xb0/0x110
[ 2559.107155] pc : [<ffff00000837ee00>] lr : [<ffff00000838e928>]
pstate: 200001c5
[ 2559.107155] sp : ffff8000734d3bb0
[ 2559.107157] x29: ffff8000734d3bb0
[ 2559.107158] x28: ffff800073a14800 x27: ffff800073a14b68
[ 2559.107162] x26: 0000000000000000 x25: 0000000000000140
[ 2559.107165] x24: 0000000000000001 x23: 0000000000001000
[ 2559.107168] x22: ffff8000746a2000 x21: 0000000000001000
[ 2559.107170] x20: 0000000000000000 x19: 0000000000001000
[ 2559.107172] x18: 0000000000000000 x17: ffffffffffffffff
[ 2559.107175] x16: 00000000000006be x15: ffff000008c34000
[ 2559.107178] x14: 747962342e090a34 x13: 3278302038323162
[ 2559.107181] x12: 656c752e090a3864 x11: ffff800073866800
[ 2559.107183] x10: ffff80006bf68eb0 x9 : 0000000000000000
[ 2559.107186] x8 : ffff800073a94920 x7 : 0000000000000000
[ 2559.107188] x6 : ffff8000746a2000 x5 : 0000820000000000
[ 2559.107191] x4 : 0000000000000000 x3 : 0000000000000000
[ 2559.107193] x2 : 0000000000000f80 x1 : ffff800000c1e000
[ 2559.107196] x0 : ffff8000746a2000
[ 2559.107199] Process mmcqd/1 (pid: 1124, stack limit = 0xffff8000734d0000)
[ 2559.107202] Stack: (0xffff8000734d3bb0 to 0xffff8000734d4000)
[ 2559.107205] 3ba0: ffff8000734d3c50
ffff00000838e9bc
[ 2559.107208] 3bc0: ffff800073a14000 ffff800073a14a30 ffff80006bf68eb0
ffff800073a14a28
[ 2559.107212] 3be0: ffff800073a14818 ffff800073a14800 0000000000000000
ffff00000838e1c4
[ 2559.107215] 3c00: ffff800073a94900 ffff7e0000030780 ffff800000c1e000
0000000000001000
[ 2559.107218] 3c20: 0000000000001000 ffff800073ad0a00 0000000100000000
0000000000000001
[ 2559.107221] 3c40: 0000100000000000 0000000000000005 ffff8000734d3c60
ffff00000874c1bc
[ 2559.107224] 3c60: ffff8000734d3c70 ffff000008748010 ffff8000734d3cd0
ffff000008749908
[ 2559.107228] 3c80: ffff80006bf68eb0 ffff800073a14000 ffff8000734c8000
ffff800073a14818
[ 2559.107231] 3ca0: ffff800073a14800 ffff800073a14800 ffff80006bf68eb0
ffff800073a14a28
[ 2559.107234] 3cc0: ffff80006bf68eb0 ffff000008749bc8 ffff8000734d3d70
ffff00000874b298
[ 2559.107237] 3ce0: ffff800073a14000 ffff800073a14818 ffff8000734c8000
0000000000000000
[ 2559.107240] 3d00: ffff800073a14800 ffff800073a14800 ffff800073a13800
0000000000000000
[ 2559.107243] 3d20: ffff80006bf68eb0 0000000000000000 00000000012853f0
ffff000008c0fcb8
[ 2559.107246] 3d40: 0000000000000000 000000000835bf14 ffff000008a05f58
ffff800000000000
[ 2559.107249] 3d60: ffff8000734c8000 0000000000000001 ffff8000734d3de0
ffff00000874b6f4
[ 2559.107252] 3d80: ffff800073a14818 ffff80006bf68eb0 ffff8000734c8000
0000000000000001
[ 2559.107255] 3da0: ffff800073a14828 0000000000000000 0000000000000000
0000000000000000
[ 2559.107258] 3dc0: 0000000000000000 0000000000000000 ffff800073a14818
ffff00000874b6c4
[ 2559.107261] 3de0: ffff8000734d3e20 ffff0000080daa84 ffff800073a94980
ffff000008e8eb08
[ 2559.107264] 3e00: ffff000008b75b50 ffff800073a14818 ffff00000874b658
0000000000000000
[ 2559.107267] 3e20: 0000000000000000 ffff000008082ec0 ffff0000080da9b8
ffff800073a94980
[ 2559.107270] 3e40: 0000000000000000 0000000000000000 0000000000000000
000003ff01893600
[ 2559.107273] 3e60: ffff8000734d3ea0 0000000000000000 ffff0000080da9b8
ffff800073a14818
[ 2559.107276] 3e80: 0000000000000000 0000000000000000 ffff8000734d3e90
ffff8000734d3e90
[ 2559.107279] 3ea0: 0000000000000000 ffff000000000000 ffff8000734d3eb0
ffff8000734d3eb0
[ 2559.107281] 3ec0: 0000000000000000 0000000000000000 0000000000000000
0000000000000000
[ 2559.107284] 3ee0: 0000000000000000 0000000000000000 0000000000000000
0000000000000000
[ 2559.107287] 3f00: 0000000000000000 0000000000000000 0000000000000000
0000000000000000
[ 2559.107290] 3f20: 0000000000000000 0000000000000000 0000000000000000
0000000000000000
[ 2559.107293] 3f40: 0000000000000000 0000000000000000 0000000000000000
0000000000000000
[ 2559.107295] 3f60: 0000000000000000 0000000000000000 0000000000000000
0000000000000000
[ 2559.107298] 3f80: 0000000000000000 0000000000000000 0000000000000000
0000000000000000
[ 2559.107300] 3fa0: 0000000000000000 0000000000000000 0000000000000000
0000000000000000
[ 2559.107303] 3fc0: 0000000000000000 0000000000000005 0000000000000000
0000000000000000
[ 2559.107306] 3fe0: 0000000000000000 0000000000000000 0000001800002cba
26000000a01b3800
[ 2559.107308] Call trace:
[ 2559.107312] Exception stack(0xffff8000734d39e0 to 0xffff8000734d3b10)
[ 2559.107315] 39e0: 0000000000001000 0001000000000000 ffff8000734d3bb0
ffff00000837ee00
[ 2559.107318] 3a00: 0000000000000007 ffff800000000000 ffff800000c1e000
0000000100100010
[ 2559.107321] 3a20: ffff8000734d3ac0 ffff000008748d88 ffff8000734d3b8c
0000000000000001
[ 2559.107324] 3a40: ffff8000734d3b40 ffff0000081c9dac ffff800074401d00
ffff0000081745d8
[ 2559.107327] 3a60: ffff7e0001b72f80 ffff80006dcbe300 00000000031fda40
0000000000000000
[ 2559.107330] 3a80: ffff8000746a2000 ffff800000c1e000 0000000000000f80
0000000000000000
[ 2559.107333] 3aa0: 0000000000000000 0000820000000000 ffff8000746a2000
0000000000000000
[ 2559.107336] 3ac0: ffff800073a94920 0000000000000000 ffff80006bf68eb0
ffff800073866800
[ 2559.107339] 3ae0: 656c752e090a3864 3278302038323162 747962342e090a34
ffff000008c34000
[ 2559.107341] 3b00: 00000000000006be ffffffffffffffff
[ 2559.107346] [<ffff00000837ee00>] __memcpy+0x100/0x180
[ 2559.107349] [<ffff00000838e9bc>] sg_copy_to_buffer+0x14/0x20
[ 2559.107357] [<ffff00000874c1bc>] mmc_queue_bounce_pre+0x34/0x40
[ 2559.107362] [<ffff000008748010>] mmc_blk_rw_rq_prep+0x288/0x3a0
[ 2559.107365] [<ffff000008749908>] mmc_blk_issue_rw_rq+0x3c0/0x998
[ 2559.107368] [<ffff00000874b298>] mmc_blk_issue_rq+0x150/0x510
[ 2559.107371] [<ffff00000874b6f4>] mmc_queue_thread+0x9c/0x140
[ 2559.107377] [<ffff0000080daa84>] kthread+0xcc/0xe0
[ 2559.107383] [<ffff000008082ec0>] ret_from_fork+0x10/0x50
[ 2559.107387] Code: d503201f d503201f d503201f d503201f (a8c12027)
[ 2559.107409] ---[ end trace 7d280955c14d4ff3 ]---
[ 2559.107417] note: mmcqd/1[1124] exited with preempt_count 1
[ 2559.688313] x18: 0000000000040900 x17: 0000000000590578 x16:
000040003c0400a8
[ 2559.695471] x15: 000000000000065c x14: 0000000000000000
[ 2559.700733] x13: 002f362f756e672d x12: 78756e696c2d3436
[ 2559.705994] x11: 0000000000000001 x10: 0101010101010101
[ 2559.711255] x9 : 0000000000000001 x8 : 0000000000000104
[ 2559.716516] x7 : 000000000046d448 x6 : 0000ffffe63873f4
[ 2559.721778] x5 : 0000ffffe63873f8 x4 : 0000000000000000
[ 2559.727039] x3 : 0000000000000000 x2 : 0000000000000000
[ 2559.732300] x1 : 0000000016c104e0 x0 : 0000000000005953
[ 2559.737561]
[ 2559.739036] Internal error: Attempting to execute userspace memory:
8600000f [#10] PREEMPT SMP
[ 2559.747566] Modules linked in: meson_rng rng_core meson_gxbb_wdt
ip_tables x_tables ipv6 dwmac_generic realtek dwmac_meson8b
stmmac_platform stmmac
[ 2559.760678] CPU: 2 PID: 22866 Comm: gcc Tainted: G D
4.9.0-rc6-next-20161124-00001-gbf7e142 #1
[ 2559.770337] Hardware name: Hardkernel ODROID-C2 (DT)
[ 2559.775254] task: ffff80007454e400 task.stack: ffff80006de9c000
[ 2559.781118] PC is at 0x46d4e0
[ 2559.784051] LR is at 0x46d4e0
[ 2559.786983] pc : [<000000000046d4e0>] lr : [<000000000046d4e0>]
pstate: 600003c5
[ 2559.794314] sp : ffff80006de9fec0
[ 2559.797591] x29: 0000000000000000 x28: ffff80007454e400
[ 2559.802853] x27: 0000000000000002 x26: 0000000000000001
[ 2559.808114] x25: 0000ffffe63873f4 x24: 0000ffffe63873f8
[ 2559.813375] x23: 0000000080000000 x22: 000040003c0400d8
[ 2559.818636] x21: ffffffffffffffff x20: 000080006e24d000
[ 2559.823898] x19: 0000000000000000 x18: 0000000000000010
[ 2559.829159] x17: 0000000000590578 x16: 000040003c0400a8
[ 2559.834420] x15: ffff000088e91f07 x14: 0000000000000006
[ 2559.839682] x13: ffff000008e91f15 x12: 000000000000000f
[ 2559.844943] x11: 0000000000000002 x10: 00000000000003f4
[ 2559.850204] x9 : ffff80006de9fb40 x8 : 00000000000b4119
[ 2559.855465] x7 : 0000000000000000 x6 : 000000000000019d
[ 2559.860726] x5 : 00000000019e019d x4 : 0000000000000000
[ 2559.865988] x3 : 0000000000000002 x2 : 000000000000019e
[ 2559.871249] x1 : ffff80007454e400 x0 : 0000000000000000
[ 2559.876510]
[ 2559.877977] Process gcc (pid: 22866, stack limit = 0xffff80006de9c000)
[ 2559.884446] Stack: (0xffff80006de9fec0 to 0xffff80006dea0000)
[ 2559.890140] fec0: 0000000000005953 0000000016c104e0 0000000000000000
0000000000000000
[ 2559.897902] fee0: 0000000000000000 0000ffffe63873f8 0000ffffe63873f4
000000000046d448
[ 2559.905664] ff00: 0000000000000104 0000000000000001 0101010101010101
0000000000000001
[ 2559.913427] ff20: 78756e696c2d3436 002f362f756e672d 0000000000000000
000000000000065c
[ 2559.921190] ff40: 000040003c0400a8 0000000000590578 0000000000040900
0000000000000000
[ 2559.928952] ff60: 0000000000005953 0000000016c104e0 0000ffffe63873f8
0000ffffe63873f4
[ 2559.936714] ff80: 0000ffffe63873f8 0000ffffe63873f4 0000000000000001
0000000000000002
[ 2559.944477] ffa0: 0000000016c0ff90 0000ffffe6387270 000000000046d4e0
0000ffffe6387270
[ 2559.952240] ffc0: 000040003c0400d8 0000000080000000 0000000000005953
ffffffffffffffff
[ 2559.960002] ffe0: 0000000000000000 0000000000000000 0000000000000000
0000000000000000
[ 2559.967762] Call trace:
[ 2559.970179] Exception stack(0xffff80006de9fcf0 to 0xffff80006de9fe20)
[ 2559.976561] fce0: 0000000000000000
0001000000000000
[ 2559.984324] fd00: ffff80006de9fec0 000000000046d4e0 ffff80007366f8c0
0000000000000004
[ 2559.992087] fd20: 0000000000000000 ffff000008dbbc18 ffff80007454e400
000000006de9fdd0
[ 2559.999850] fd40: ffff80006de9fd90 ffff0000080ca878 ffff80006de9fe40
ffff80007454e400
[ 2560.007612] fd60: 0000000000000004 00000000000003c0 ffff80006de9fe40
0000ffffe63873f8
[ 2560.015374] fd80: 0000ffffe63873f4 0000000000000001 0000000000000000
ffff80007454e400
[ 2560.023137] fda0: 000000000000019e 0000000000000002 0000000000000000
00000000019e019d
[ 2560.030899] fdc0: 000000000000019d 0000000000000000 00000000000b4119
ffff80006de9fb40
[ 2560.038662] fde0: 00000000000003f4 0000000000000002 000000000000000f
ffff000008e91f15
[ 2560.046425] fe00: 0000000000000006 ffff000088e91f07 000040003c0400a8
0000000000590578
[ 2560.054186] [<000000000046d4e0>] 0x46d4e0
[ 2560.058155] Code: aa1503e1 2a1403e0 52800002 97fe895d (2a0003e1)
[ 2560.064244] ---[ end trace 7d280955c14d4ff4 ]---
^ permalink raw reply
* Re: net: stmmac: Meson GXBB: attempting to execute userspace memory
From: Martin Blumenstingl @ 2016-11-26 9:08 UTC (permalink / raw)
To: Heinrich Schuchardt
Cc: Carlo Caione, Kevin Hilman, Alexandre Torgue, netdev, lkml,
linux-amlogic, Giuseppe Cavallaro, linux-arm-kernel
In-Reply-To: <c8280798-453e-bd1d-bd4d-bf0956a169cc@gmx.de>
Hello Heinrich,
On Sat, Nov 26, 2016 at 8:53 AM, Heinrich Schuchardt
<heinrich.schuchardt@gmx.de> wrote:
> For Odroid C2 I have compiled kernel
> 4.9.0-rc6-next-20161124-00001-gbf7e142
> with one additional patch
> https://github.com/xypron/kernel-odroid-c2/blob/master/patch/0001-stmmac-RTL8211F-Meson-GXBB-TX-throughput-problems.patch
>
> I repeatedly see faults like the one below:
do you see the same errors with the RTL8211F patch *not* applied?
> [ 2557.400796] Unhandled fault: synchronous external abort (0x92000010)
> at 0x000040001e8ee4b0
> [ 2557.952413] CPU: 0 PID: 22837 Comm: cc1 Tainted: G D
> 4.9.0-rc6-next-20161124-00001-gbf7e142 #1
> [ 2557.962062] Hardware name: Hardkernel ODROID-C2 (DT)
> [ 2557.966980] task: ffff80006ddb7080 task.stack: ffff80006dd9c000
> [ 2557.972846] PC is at 0x6a0d98
> [ 2557.975776] LR is at 0x6a0e54
> [ 2557.978709] pc : [<00000000006a0d98>] lr : [<00000000006a0e54>]
> pstate: 80000000
> [ 2557.986040] sp : 0000fffff3ee5f80
> [ 2557.989318] x29: 0000fffff3ee5f80 x28: 000040000b3f1240
> [ 2557.994578] x27: 00000000012a7000 x26: 000040000b3f1288
> [ 2557.999840] x25: 0000000000f58f88 x24: 000040000b3f1240
> [ 2558.005101] x23: 0000000000000000 x22: 0000000000000001
> [ 2558.010362] x21: 0000000000000001 x20: 000040000b3f1250
> [ 2558.015623] x19: 0000000000000054 x18: 0000000000000001
> [ 2558.020885] x17: 0000400008acaa10 x16: 0000000001285050
> [ 2558.026146] x15: 000040000ad96dc8 x14: 000000000000001f
> [ 2558.031407] x13: 000040000b3f1270 x12: 000040000b3f1258
> [ 2558.036668] x11: 0000000001347000 x10: 0000000000000661
> [ 2558.041930] x9 : 0000000000000005 x8 : 0000000000000003
> [ 2558.047191] x7 : 000040000b3f1240 x6 : 0000000020020033
> [ 2558.052452] x5 : 000040000b402020 x4 : 000040000b3e1aa0
> [ 2558.057713] x3 : 000000000000000c x2 : 0000000000000020
> [ 2558.062974] x1 : 0000000000f45000 x0 : 0000000000000065
> [ 2558.068235]
> [ 2558.069712] Internal error: Attempting to execute userspace memory:
> 8600000f [#7] PREEMPT SMP
> [ 2558.078155] Modules linked in: meson_rng rng_core meson_gxbb_wdt
> ip_tables x_tables ipv6 dwmac_generic realtek dwmac_meson8b
> stmmac_platform stmmac
> [ 2558.091267] CPU: 0 PID: 22837 Comm: cc1 Tainted: G D
> 4.9.0-rc6-next-20161124-00001-gbf7e142 #1
> [ 2558.100925] Hardware name: Hardkernel ODROID-C2 (DT)
> [ 2558.105841] task: ffff80006ddb7080 task.stack: ffff80006dd9c000
> [ 2558.111706] PC is at 0x6a0e54
> [ 2558.114638] LR is at 0x6a0e54
> [ 2558.117571] pc : [<00000000006a0e54>] lr : [<00000000006a0e54>]
> pstate: 600003c5
> [ 2558.124902] sp : ffff80006dd9fec0
> [ 2558.128179] x29: 0000000000000000 x28: ffff80006ddb7080
> [ 2558.133441] x27: 00000000012a7000 x26: 000040000b3f1288
> [ 2558.138702] x25: 0000000000f58f88 x24: 000040000b3f1240
> [ 2558.143963] x23: 0000000080000000 x22: 00000000006a0d98
> [ 2558.149225] x21: ffffffffffffffff x20: 000080006e223000
> [ 2558.154486] x19: 0000000000000000 x18: 0000000000000010
> [ 2558.159747] x17: 0000400008acaa10 x16: 0000000001285050
> [ 2558.165008] x15: ffff000088e91f07 x14: 0000000000000006
> [ 2558.170270] x13: ffff000008e91f15 x12: 000000000000000f
> [ 2558.175531] x11: 0000000000000002 x10: 00000000000002ea
> [ 2558.180792] x9 : ffff80006dd9fb40 x8 : 0000000000010a8b
> [ 2558.186053] x7 : 0000000000000000 x6 : 000000000000020e
> [ 2558.191315] x5 : 00000000020f020e x4 : 0000000000000000
> [ 2558.196576] x3 : 0000000000000000 x2 : 000000000000020f
> [ 2558.201837] x1 : ffff80006ddb7080 x0 : 0000000000000000
> [ 2558.207098]
> [ 2558.208565] Process cc1 (pid: 22837, stack limit = 0xffff80006dd9c000)
> [ 2558.215035] Stack: (0xffff80006dd9fec0 to 0xffff80006dda0000)
> [ 2558.220728] fec0: 0000000000000065 0000000000f45000 0000000000000020
> 000000000000000c
> [ 2558.228490] fee0: 000040000b3e1aa0 000040000b402020 0000000020020033
> 000040000b3f1240
> [ 2558.236253] ff00: 0000000000000003 0000000000000005 0000000000000661
> 0000000001347000
> [ 2558.244015] ff20: 000040000b3f1258 000040000b3f1270 000000000000001f
> 000040000ad96dc8
> [ 2558.251778] ff40: 0000000001285050 0000400008acaa10 0000000000000001
> 0000000000000054
> [ 2558.259540] ff60: 000040000b3f1250 0000000000000001 0000000000000001
> 0000000000000000
> [ 2558.267303] ff80: 000040000b3f1240 0000000000f58f88 000040000b3f1288
> 00000000012a7000
> [ 2558.275065] ffa0: 000040000b3f1240 0000fffff3ee5f80 00000000006a0e54
> 0000fffff3ee5f80
> [ 2558.282828] ffc0: 00000000006a0d98 0000000080000000 0000000000000003
> ffffffffffffffff
> [ 2558.290590] ffe0: 0000000000000000 0000000000000000 0000000000000000
> 0000000000000000
> [ 2558.298351] Call trace:
> [ 2558.300769] Exception stack(0xffff80006dd9fcf0 to 0xffff80006dd9fe20)
> [ 2558.307149] fce0: 0000000000000000
> 0001000000000000
> [ 2558.314913] fd00: ffff80006dd9fec0 00000000006a0e54 ffff800073acf500
> 0000000000000004
> [ 2558.322675] fd20: 0000000000000000 ffff000008dbbc18 ffff80006ddb7080
> 000000006dd9fdd0
> [ 2558.330438] fd40: ffff80006dd9fd90 ffff0000080ca878 ffff80006dd9fe40
> ffff80006ddb7080
> [ 2558.338200] fd60: 0000000000000004 00000000000003c0 ffff80006dd9fe40
> 000040000b3f1240
> [ 2558.345963] fd80: 0000000000f58f88 000040000b3f1288 0000000000000000
> ffff80006ddb7080
> [ 2558.353725] fda0: 000000000000020f 0000000000000000 0000000000000000
> 00000000020f020e
> [ 2558.361487] fdc0: 000000000000020e 0000000000000000 0000000000010a8b
> ffff80006dd9fb40
> [ 2558.369250] fde0: 00000000000002ea 0000000000000002 000000000000000f
> ffff000008e91f15
> [ 2558.377012] fe00: 0000000000000006 ffff000088e91f07 0000000001285050
> 0000400008acaa10
> [ 2558.384775] [<00000000006a0e54>] 0x6a0e54
> [ 2558.388743] Code: d503201f f9400280 2a1703e1 97ffff0a (aa0003f3)
> [ 2558.395241] ---[ end trace 7d280955c14d4ff1 ]---
> [ 2558.584022] Bad mode in Error handler detected on CPU0, code
> 0xbf000000 -- SError
> [ 2558.585871] CPU: 0 PID: 22867 Comm: cc1 Tainted: G D
> 4.9.0-rc6-next-20161124-00001-gbf7e142 #1
> [ 2558.595527] Hardware name: Hardkernel ODROID-C2 (DT)
> [ 2558.600444] task: ffff80007454d780 task.stack: ffff8000660bc000
> [ 2558.606310] PC is at 0x631928
> [ 2558.609240] LR is at 0xb59ce0
> [ 2558.612172] pc : [<0000000000631928>] lr : [<0000000000b59ce0>]
> pstate: 80000000
> [ 2558.619503] sp : 0000ffffed764d90
> [ 2558.622782] x29: 0000ffffed764d90 x28: 0000000000000028
> [ 2558.628042] x27: 000000001a1062f0 x26: 0000000001299198
> [ 2558.633303] x25: 0000000000000001 x24: 0000000000000000
> [ 2558.638564] x23: 0000000000000004 x22: 00000000013513c8
> [ 2558.643825] x21: 0000400039d43488 x20: 0000000000000000
> [ 2558.649086] x19: 0000400039d2d730 x18: 0000000000000000
> [ 2558.654348] x17: 0000400039a7c378 x16: 0000000001285138
> [ 2558.659609] x15: 0000000000000001 x14: 0000000000000000
> [ 2558.664870] x13: ffffff0000000000 x12: 0000000000000000
> [ 2558.670131] x11: 0000000000000028 x10: 000000000129b2b8
> [ 2558.675393] x9 : 0000000000000041 x8 : 0000000000000003
> [ 2558.680654] x7 : 0000000000000050 x6 : 000000000003d2c8
> [ 2558.685915] x5 : 0000000000000002 x4 : 0000000000000004
> [ 2558.691176] x3 : 0000000000000003 x2 : 0000000001349000
> [ 2558.696438] x1 : 000000000003cb90 x0 : 0000400039d45050
> [ 2558.701699]
> [ 2558.703177] Internal error: Attempting to execute userspace memory:
> 8600000f [#8] PREEMPT SMP
> [ 2558.711618] Modules linked in: meson_rng rng_core meson_gxbb_wdt
> ip_tables x_tables ipv6 dwmac_generic realtek dwmac_meson8b
> stmmac_platform stmmac
> [ 2558.724731] CPU: 0 PID: 22867 Comm: cc1 Tainted: G D
> 4.9.0-rc6-next-20161124-00001-gbf7e142 #1
> [ 2558.734388] Hardware name: Hardkernel ODROID-C2 (DT)
> [ 2558.739304] task: ffff80007454d780 task.stack: ffff8000660bc000
> [ 2558.745169] PC is at 0xb59ce0
> [ 2558.748102] LR is at 0xb59ce0
> [ 2558.751035] pc : [<0000000000b59ce0>] lr : [<0000000000b59ce0>]
> pstate: 600003c5
> [ 2558.758365] sp : ffff8000660bfec0
> [ 2558.761643] x29: 0000000000000000 x28: ffff80007454d780
> [ 2558.766904] x27: 000000001a1062f0 x26: 0000000001299198
> [ 2558.772165] x25: 0000000000000001 x24: 0000000000000000
> [ 2558.777426] x23: 0000000080000000 x22: 0000000000631928
> [ 2558.782688] x21: ffffffffffffffff x20: 000080006e223000
> [ 2558.787949] x19: 0000000000000000 x18: 0000000000000010
> [ 2558.793210] x17: 0000400039a7c378 x16: 0000000001285138
> [ 2558.798471] x15: ffff000088e91f07 x14: 0000000000000006
> [ 2558.803733] x13: ffff000008e91f15 x12: 000000000000000f
> [ 2558.808994] x11: 0000000000000002 x10: 0000000000000336
> [ 2558.814255] x9 : ffff8000660bfb40 x8 : 00000000000ab503
> [ 2558.819516] x7 : 0000000000000000 x6 : 00000000000000dd
> [ 2558.824778] x5 : 0000000000de00dd x4 : 0000000000000000
> [ 2558.830039] x3 : 0000000000000000 x2 : 00000000000000de
> [ 2558.835300] x1 : ffff80007454d780 x0 : 0000000000000000
> [ 2558.840561]
> [ 2558.842029] Process cc1 (pid: 22867, stack limit = 0xffff8000660bc000)
> [ 2558.848498] Stack: (0xffff8000660bfec0 to 0xffff8000660c0000)
> [ 2558.854191] fec0: 0000400039d45050 000000000003cb90 0000000001349000
> 0000000000000003
> [ 2558.861953] fee0: 0000000000000004 0000000000000002 000000000003d2c8
> 0000000000000050
> [ 2558.869716] ff00: 0000000000000003 0000000000000041 000000000129b2b8
> 0000000000000028
> [ 2558.877478] ff20: 0000000000000000 ffffff0000000000 0000000000000000
> 0000000000000001
> [ 2558.885241] ff40: 0000000001285138 0000400039a7c378 0000000000000000
> 0000400039d2d730
> [ 2558.893003] ff60: 0000000000000000 0000400039d43488 00000000013513c8
> 0000000000000004
> [ 2558.900766] ff80: 0000000000000000 0000000000000001 0000000001299198
> 000000001a1062f0
> [ 2558.908529] ffa0: 0000000000000028 0000ffffed764d90 0000000000b59ce0
> 0000ffffed764d90
> [ 2558.916291] ffc0: 0000000000631928 0000000080000000 000000001a18c000
> ffffffffffffffff
> [ 2558.924053] ffe0: 0000000000000000 0000000000000000 0000000000000000
> 0000000000000000
> [ 2558.931814] Call trace:
> [ 2558.934232] Exception stack(0xffff8000660bfcf0 to 0xffff8000660bfe20)
> [ 2558.940613] fce0: 0000000000000000
> 0001000000000000
> [ 2558.948376] fd00: ffff8000660bfec0 0000000000b59ce0 ffff800073acf640
> 0000000000000004
> [ 2558.956138] fd20: 0000000000000000 ffff000008dbbc18 ffff80007454d780
> 00000000660bfdd0
> [ 2558.963901] fd40: ffff8000660bfd90 ffff0000080ca878 ffff8000660bfe40
> ffff80007454d780
> [ 2558.971663] fd60: 0000000000000004 00000000000003c0 ffff8000660bfe40
> 0000000000000000
> [ 2558.979426] fd80: 0000000000000001 0000000001299198 0000000000000000
> ffff80007454d780
> [ 2558.987188] fda0: 00000000000000de 0000000000000000 0000000000000000
> 0000000000de00dd
> [ 2558.994951] fdc0: 00000000000000dd 0000000000000000 00000000000ab503
> ffff8000660bfb40
> [ 2559.002713] fde0: 0000000000000336 0000000000000002 000000000000000f
> ffff000008e91f15
> [ 2559.010476] fe00: 0000000000000006 ffff000088e91f07 0000000001285138
> 0000400039a7c378
> [ 2559.018238] [<0000000000b59ce0>] 0xb59ce0
> [ 2559.022207] Code: d2800001 d2800002 d2800500 97eb5e9d (a9007c1f)
> [ 2559.028376] ---[ end trace 7d280955c14d4ff2 ]---
> [ 2559.034397] Bad mode in Error handler detected on CPU2, code
> 0xbf000000 -- SError
> [ 2559.040235] CPU: 2 PID: 22866 Comm: gcc Tainted: G D
> 4.9.0-rc6-next-20161124-00001-gbf7e142 #1
> [ 2559.049892] Hardware name: Hardkernel ODROID-C2 (DT)
> [ 2559.054808] task: ffff80007454e400 task.stack: ffff80006de9c000
> [ 2559.060674] PC is at 0x40003c0400d8
> [ 2559.064122] LR is at 0x46d4e0
> [ 2559.067055] pc : [<000040003c0400d8>] lr : [<000000000046d4e0>]
> pstate: 80000000
> [ 2559.074385] sp : 0000ffffe6387270
> [ 2559.077664] x29: 0000ffffe6387270 x28: 0000000016c0ff90
> [ 2559.082924] x27: 0000000000000002 x26: 0000000000000001
> [ 2559.088185] x25: 0000ffffe63873f4 x24: 0000ffffe63873f8
> [ 2559.093447] x23: 0000ffffe63873f4 x22: 0000ffffe63873f8
> [ 2559.098708] x21: 0000000016c104e0 x20: 0000000000005953
> [ 2559.103969] x19: 0000000000000000 [ 2559.107102] Unhandled fault:
> synchronous external abort (0x96000010) at 0xffff800000c1e000
> [ 2559.107108] Internal error: : 96000010 [#9] PREEMPT SMP
> [ 2559.107110] Modules linked in:
> [ 2559.107113] meson_rng rng_core meson_gxbb_wdt ip_tables x_tables
> ipv6 dwmac_generic realtek dwmac_meson8b stmmac_platform stmmac[
> 2559.107131] CPU: 0 PID: 1124 Comm: mmcqd/1 Tainted: G D 1
> [ 2559.107132] Hardware name: Hardkernel ODROID-C2 (DT)
> [ 2559.107135] task: ffff8000704abe80 task.stack: ffff8000734d0000
> [ 2559.107147] PC is at __memcpy+0x100/0x180
> [ 2559.107152] LR is at sg_copy_buffer+0xb0/0x110
> [ 2559.107155] pc : [<ffff00000837ee00>] lr : [<ffff00000838e928>]
> pstate: 200001c5
> [ 2559.107155] sp : ffff8000734d3bb0
> [ 2559.107157] x29: ffff8000734d3bb0
> [ 2559.107158] x28: ffff800073a14800 x27: ffff800073a14b68
> [ 2559.107162] x26: 0000000000000000 x25: 0000000000000140
> [ 2559.107165] x24: 0000000000000001 x23: 0000000000001000
> [ 2559.107168] x22: ffff8000746a2000 x21: 0000000000001000
> [ 2559.107170] x20: 0000000000000000 x19: 0000000000001000
> [ 2559.107172] x18: 0000000000000000 x17: ffffffffffffffff
> [ 2559.107175] x16: 00000000000006be x15: ffff000008c34000
> [ 2559.107178] x14: 747962342e090a34 x13: 3278302038323162
> [ 2559.107181] x12: 656c752e090a3864 x11: ffff800073866800
> [ 2559.107183] x10: ffff80006bf68eb0 x9 : 0000000000000000
> [ 2559.107186] x8 : ffff800073a94920 x7 : 0000000000000000
> [ 2559.107188] x6 : ffff8000746a2000 x5 : 0000820000000000
> [ 2559.107191] x4 : 0000000000000000 x3 : 0000000000000000
> [ 2559.107193] x2 : 0000000000000f80 x1 : ffff800000c1e000
> [ 2559.107196] x0 : ffff8000746a2000
> [ 2559.107199] Process mmcqd/1 (pid: 1124, stack limit = 0xffff8000734d0000)
> [ 2559.107202] Stack: (0xffff8000734d3bb0 to 0xffff8000734d4000)
> [ 2559.107205] 3ba0: ffff8000734d3c50
> ffff00000838e9bc
> [ 2559.107208] 3bc0: ffff800073a14000 ffff800073a14a30 ffff80006bf68eb0
> ffff800073a14a28
> [ 2559.107212] 3be0: ffff800073a14818 ffff800073a14800 0000000000000000
> ffff00000838e1c4
> [ 2559.107215] 3c00: ffff800073a94900 ffff7e0000030780 ffff800000c1e000
> 0000000000001000
> [ 2559.107218] 3c20: 0000000000001000 ffff800073ad0a00 0000000100000000
> 0000000000000001
> [ 2559.107221] 3c40: 0000100000000000 0000000000000005 ffff8000734d3c60
> ffff00000874c1bc
> [ 2559.107224] 3c60: ffff8000734d3c70 ffff000008748010 ffff8000734d3cd0
> ffff000008749908
> [ 2559.107228] 3c80: ffff80006bf68eb0 ffff800073a14000 ffff8000734c8000
> ffff800073a14818
> [ 2559.107231] 3ca0: ffff800073a14800 ffff800073a14800 ffff80006bf68eb0
> ffff800073a14a28
> [ 2559.107234] 3cc0: ffff80006bf68eb0 ffff000008749bc8 ffff8000734d3d70
> ffff00000874b298
> [ 2559.107237] 3ce0: ffff800073a14000 ffff800073a14818 ffff8000734c8000
> 0000000000000000
> [ 2559.107240] 3d00: ffff800073a14800 ffff800073a14800 ffff800073a13800
> 0000000000000000
> [ 2559.107243] 3d20: ffff80006bf68eb0 0000000000000000 00000000012853f0
> ffff000008c0fcb8
> [ 2559.107246] 3d40: 0000000000000000 000000000835bf14 ffff000008a05f58
> ffff800000000000
> [ 2559.107249] 3d60: ffff8000734c8000 0000000000000001 ffff8000734d3de0
> ffff00000874b6f4
> [ 2559.107252] 3d80: ffff800073a14818 ffff80006bf68eb0 ffff8000734c8000
> 0000000000000001
> [ 2559.107255] 3da0: ffff800073a14828 0000000000000000 0000000000000000
> 0000000000000000
> [ 2559.107258] 3dc0: 0000000000000000 0000000000000000 ffff800073a14818
> ffff00000874b6c4
> [ 2559.107261] 3de0: ffff8000734d3e20 ffff0000080daa84 ffff800073a94980
> ffff000008e8eb08
> [ 2559.107264] 3e00: ffff000008b75b50 ffff800073a14818 ffff00000874b658
> 0000000000000000
> [ 2559.107267] 3e20: 0000000000000000 ffff000008082ec0 ffff0000080da9b8
> ffff800073a94980
> [ 2559.107270] 3e40: 0000000000000000 0000000000000000 0000000000000000
> 000003ff01893600
> [ 2559.107273] 3e60: ffff8000734d3ea0 0000000000000000 ffff0000080da9b8
> ffff800073a14818
> [ 2559.107276] 3e80: 0000000000000000 0000000000000000 ffff8000734d3e90
> ffff8000734d3e90
> [ 2559.107279] 3ea0: 0000000000000000 ffff000000000000 ffff8000734d3eb0
> ffff8000734d3eb0
> [ 2559.107281] 3ec0: 0000000000000000 0000000000000000 0000000000000000
> 0000000000000000
> [ 2559.107284] 3ee0: 0000000000000000 0000000000000000 0000000000000000
> 0000000000000000
> [ 2559.107287] 3f00: 0000000000000000 0000000000000000 0000000000000000
> 0000000000000000
> [ 2559.107290] 3f20: 0000000000000000 0000000000000000 0000000000000000
> 0000000000000000
> [ 2559.107293] 3f40: 0000000000000000 0000000000000000 0000000000000000
> 0000000000000000
> [ 2559.107295] 3f60: 0000000000000000 0000000000000000 0000000000000000
> 0000000000000000
> [ 2559.107298] 3f80: 0000000000000000 0000000000000000 0000000000000000
> 0000000000000000
> [ 2559.107300] 3fa0: 0000000000000000 0000000000000000 0000000000000000
> 0000000000000000
> [ 2559.107303] 3fc0: 0000000000000000 0000000000000005 0000000000000000
> 0000000000000000
> [ 2559.107306] 3fe0: 0000000000000000 0000000000000000 0000001800002cba
> 26000000a01b3800
> [ 2559.107308] Call trace:
> [ 2559.107312] Exception stack(0xffff8000734d39e0 to 0xffff8000734d3b10)
> [ 2559.107315] 39e0: 0000000000001000 0001000000000000 ffff8000734d3bb0
> ffff00000837ee00
> [ 2559.107318] 3a00: 0000000000000007 ffff800000000000 ffff800000c1e000
> 0000000100100010
> [ 2559.107321] 3a20: ffff8000734d3ac0 ffff000008748d88 ffff8000734d3b8c
> 0000000000000001
> [ 2559.107324] 3a40: ffff8000734d3b40 ffff0000081c9dac ffff800074401d00
> ffff0000081745d8
> [ 2559.107327] 3a60: ffff7e0001b72f80 ffff80006dcbe300 00000000031fda40
> 0000000000000000
> [ 2559.107330] 3a80: ffff8000746a2000 ffff800000c1e000 0000000000000f80
> 0000000000000000
> [ 2559.107333] 3aa0: 0000000000000000 0000820000000000 ffff8000746a2000
> 0000000000000000
> [ 2559.107336] 3ac0: ffff800073a94920 0000000000000000 ffff80006bf68eb0
> ffff800073866800
> [ 2559.107339] 3ae0: 656c752e090a3864 3278302038323162 747962342e090a34
> ffff000008c34000
> [ 2559.107341] 3b00: 00000000000006be ffffffffffffffff
> [ 2559.107346] [<ffff00000837ee00>] __memcpy+0x100/0x180
> [ 2559.107349] [<ffff00000838e9bc>] sg_copy_to_buffer+0x14/0x20
> [ 2559.107357] [<ffff00000874c1bc>] mmc_queue_bounce_pre+0x34/0x40
> [ 2559.107362] [<ffff000008748010>] mmc_blk_rw_rq_prep+0x288/0x3a0
> [ 2559.107365] [<ffff000008749908>] mmc_blk_issue_rw_rq+0x3c0/0x998
> [ 2559.107368] [<ffff00000874b298>] mmc_blk_issue_rq+0x150/0x510
> [ 2559.107371] [<ffff00000874b6f4>] mmc_queue_thread+0x9c/0x140
> [ 2559.107377] [<ffff0000080daa84>] kthread+0xcc/0xe0
> [ 2559.107383] [<ffff000008082ec0>] ret_from_fork+0x10/0x50
> [ 2559.107387] Code: d503201f d503201f d503201f d503201f (a8c12027)
> [ 2559.107409] ---[ end trace 7d280955c14d4ff3 ]---
> [ 2559.107417] note: mmcqd/1[1124] exited with preempt_count 1
> [ 2559.688313] x18: 0000000000040900 x17: 0000000000590578 x16:
> 000040003c0400a8
> [ 2559.695471] x15: 000000000000065c x14: 0000000000000000
> [ 2559.700733] x13: 002f362f756e672d x12: 78756e696c2d3436
> [ 2559.705994] x11: 0000000000000001 x10: 0101010101010101
> [ 2559.711255] x9 : 0000000000000001 x8 : 0000000000000104
> [ 2559.716516] x7 : 000000000046d448 x6 : 0000ffffe63873f4
> [ 2559.721778] x5 : 0000ffffe63873f8 x4 : 0000000000000000
> [ 2559.727039] x3 : 0000000000000000 x2 : 0000000000000000
> [ 2559.732300] x1 : 0000000016c104e0 x0 : 0000000000005953
> [ 2559.737561]
> [ 2559.739036] Internal error: Attempting to execute userspace memory:
> 8600000f [#10] PREEMPT SMP
> [ 2559.747566] Modules linked in: meson_rng rng_core meson_gxbb_wdt
> ip_tables x_tables ipv6 dwmac_generic realtek dwmac_meson8b
> stmmac_platform stmmac
> [ 2559.760678] CPU: 2 PID: 22866 Comm: gcc Tainted: G D
> 4.9.0-rc6-next-20161124-00001-gbf7e142 #1
> [ 2559.770337] Hardware name: Hardkernel ODROID-C2 (DT)
> [ 2559.775254] task: ffff80007454e400 task.stack: ffff80006de9c000
> [ 2559.781118] PC is at 0x46d4e0
> [ 2559.784051] LR is at 0x46d4e0
> [ 2559.786983] pc : [<000000000046d4e0>] lr : [<000000000046d4e0>]
> pstate: 600003c5
> [ 2559.794314] sp : ffff80006de9fec0
> [ 2559.797591] x29: 0000000000000000 x28: ffff80007454e400
> [ 2559.802853] x27: 0000000000000002 x26: 0000000000000001
> [ 2559.808114] x25: 0000ffffe63873f4 x24: 0000ffffe63873f8
> [ 2559.813375] x23: 0000000080000000 x22: 000040003c0400d8
> [ 2559.818636] x21: ffffffffffffffff x20: 000080006e24d000
> [ 2559.823898] x19: 0000000000000000 x18: 0000000000000010
> [ 2559.829159] x17: 0000000000590578 x16: 000040003c0400a8
> [ 2559.834420] x15: ffff000088e91f07 x14: 0000000000000006
> [ 2559.839682] x13: ffff000008e91f15 x12: 000000000000000f
> [ 2559.844943] x11: 0000000000000002 x10: 00000000000003f4
> [ 2559.850204] x9 : ffff80006de9fb40 x8 : 00000000000b4119
> [ 2559.855465] x7 : 0000000000000000 x6 : 000000000000019d
> [ 2559.860726] x5 : 00000000019e019d x4 : 0000000000000000
> [ 2559.865988] x3 : 0000000000000002 x2 : 000000000000019e
> [ 2559.871249] x1 : ffff80007454e400 x0 : 0000000000000000
> [ 2559.876510]
> [ 2559.877977] Process gcc (pid: 22866, stack limit = 0xffff80006de9c000)
> [ 2559.884446] Stack: (0xffff80006de9fec0 to 0xffff80006dea0000)
> [ 2559.890140] fec0: 0000000000005953 0000000016c104e0 0000000000000000
> 0000000000000000
> [ 2559.897902] fee0: 0000000000000000 0000ffffe63873f8 0000ffffe63873f4
> 000000000046d448
> [ 2559.905664] ff00: 0000000000000104 0000000000000001 0101010101010101
> 0000000000000001
> [ 2559.913427] ff20: 78756e696c2d3436 002f362f756e672d 0000000000000000
> 000000000000065c
> [ 2559.921190] ff40: 000040003c0400a8 0000000000590578 0000000000040900
> 0000000000000000
> [ 2559.928952] ff60: 0000000000005953 0000000016c104e0 0000ffffe63873f8
> 0000ffffe63873f4
> [ 2559.936714] ff80: 0000ffffe63873f8 0000ffffe63873f4 0000000000000001
> 0000000000000002
> [ 2559.944477] ffa0: 0000000016c0ff90 0000ffffe6387270 000000000046d4e0
> 0000ffffe6387270
> [ 2559.952240] ffc0: 000040003c0400d8 0000000080000000 0000000000005953
> ffffffffffffffff
> [ 2559.960002] ffe0: 0000000000000000 0000000000000000 0000000000000000
> 0000000000000000
> [ 2559.967762] Call trace:
> [ 2559.970179] Exception stack(0xffff80006de9fcf0 to 0xffff80006de9fe20)
> [ 2559.976561] fce0: 0000000000000000
> 0001000000000000
> [ 2559.984324] fd00: ffff80006de9fec0 000000000046d4e0 ffff80007366f8c0
> 0000000000000004
> [ 2559.992087] fd20: 0000000000000000 ffff000008dbbc18 ffff80007454e400
> 000000006de9fdd0
> [ 2559.999850] fd40: ffff80006de9fd90 ffff0000080ca878 ffff80006de9fe40
> ffff80007454e400
> [ 2560.007612] fd60: 0000000000000004 00000000000003c0 ffff80006de9fe40
> 0000ffffe63873f8
> [ 2560.015374] fd80: 0000ffffe63873f4 0000000000000001 0000000000000000
> ffff80007454e400
> [ 2560.023137] fda0: 000000000000019e 0000000000000002 0000000000000000
> 00000000019e019d
> [ 2560.030899] fdc0: 000000000000019d 0000000000000000 00000000000b4119
> ffff80006de9fb40
> [ 2560.038662] fde0: 00000000000003f4 0000000000000002 000000000000000f
> ffff000008e91f15
> [ 2560.046425] fe00: 0000000000000006 ffff000088e91f07 000040003c0400a8
> 0000000000590578
> [ 2560.054186] [<000000000046d4e0>] 0x46d4e0
> [ 2560.058155] Code: aa1503e1 2a1403e0 52800002 97fe895d (2a0003e1)
> [ 2560.064244] ---[ end trace 7d280955c14d4ff4 ]---
I am asking because when you look at the affected processes you'll get
this list: cc1, mmcqd/1, gcc
it doesn't sound like any of these using ethernet but rather MMC instead.
Regards,
Martin
^ permalink raw reply
* Re: [Patch net-next] net_sched: move the empty tp check from ->destroy() to ->delete()
From: Daniel Borkmann @ 2016-11-26 11:09 UTC (permalink / raw)
To: Cong Wang
Cc: Roi Dayan, Linux Kernel Network Developers, Jiri Pirko,
John Fastabend
In-Reply-To: <CAM_iQpVxevmk3rgsnALC0JCqx7pOF2OBc=kpg9QDK8Cwb6P9Zw@mail.gmail.com>
On 11/26/2016 07:46 AM, Cong Wang wrote:
> On Thu, Nov 24, 2016 at 7:20 AM, Daniel Borkmann <daniel@iogearbox.net> wrote:
>>
>> Ok, strange, qdisc_destroy() calls into ops->destroy(), where ingress
>> drops its entire chain via tcf_destroy_chain(), so that will be NULL
>> eventually. The tps are freed by call_rcu() as well as qdisc itself
>> later on via qdisc_rcu_free(), where it frees per-cpu bstats as well.
>> Outstanding readers should either bail out due to if (!cl) or can still
>> process the chain until read section ends, but during that time, cl->q
>> resp. bstats should be good. Do you happen to know what's at address
>> ffff880a68b04028? I was wondering wrt call_rcu() vs call_rcu_bh(), but
>> at least on ingress (netif_receive_skb_internal()) we hold rcu_read_lock()
>> here. The KASAN report is reliably happening at this location, right?
>
> I am confused as well, I don't see how it could be related to my patch yet.
> I will take a deep look in the weekend.
Ok, I'm currently on the run. Got too late yesterday night, but I'll
write what I found in the evening today, not related to ingress though.
Cheers,
Daniel
^ permalink raw reply
* Gigabit ethernet driver for Alacritechs SLIC devices (v3)
From: Lino Sanfilippo @ 2016-11-26 12:20 UTC (permalink / raw)
To: davem, charrer, liodot, gregkh, andrew; +Cc: devel, netdev, linux-kernel
Hi,
this is the third version of the slicoss gigabit ethernet driver (which is a
rework of the driver from Alacritech which can currently be found under
drivers/staging/slicoss). The driver is supposed to support Mojave, Oasis and
Kalahari cards, for both copper and fiber.
If this code is accepted the staging version can be removed.
The driver has been tested on a SEN2104ET adapter (4 Port PCIe copper).
v3:
- dont add defines to pci.h but instead put it into the drivers header file
(requested by Greg Kroah-Hartman)
v2:
- remove unusual padding in statistic strings (suggested by Andrew Lunn)
- for mdio register and bit names use defines from mii.h instead of own ones
(suggested by Andrew Lunn)
- remove unused defines
- ensure PCI flush at two more places
- use mmiowb before lock to prevent mmio writes leaking out of lock
- fix some typos in comments
- add copyright and GPL header
Regards,
Lino
^ permalink raw reply
* [PATCH v3 net-next 1/2] net: ethernet: slicoss: add slicoss gigabit ethernet driver
From: Lino Sanfilippo @ 2016-11-26 12:20 UTC (permalink / raw)
To: davem, charrer, liodot, gregkh, andrew
Cc: devel, netdev, Lino Sanfilippo, linux-kernel
In-Reply-To: <1480162850-8014-1-git-send-email-LinoSanfilippo@gmx.de>
Add driver for Alacritech gigabit ethernet cards with SLIC (session-layer
interface control) technology. The driver provides basic support without
SLIC for the following devices:
- Mojave cards (single port PCI Gigabit) both copper and fiber
- Oasis cards (single and dual port PCI-x Gigabit) copper and fiber
- Kalahari cards (dual and quad port PCI-e Gigabit) copper and fiber
Signed-off-by: Lino Sanfilippo <LinoSanfilippo@gmx.de>
---
drivers/net/ethernet/Kconfig | 1 +
drivers/net/ethernet/Makefile | 1 +
drivers/net/ethernet/alacritech/Kconfig | 28 +
drivers/net/ethernet/alacritech/Makefile | 4 +
drivers/net/ethernet/alacritech/slic.h | 576 +++++++++
drivers/net/ethernet/alacritech/slicoss.c | 1867 +++++++++++++++++++++++++++++
6 files changed, 2477 insertions(+)
create mode 100644 drivers/net/ethernet/alacritech/Kconfig
create mode 100644 drivers/net/ethernet/alacritech/Makefile
create mode 100644 drivers/net/ethernet/alacritech/slic.h
create mode 100644 drivers/net/ethernet/alacritech/slicoss.c
diff --git a/drivers/net/ethernet/Kconfig b/drivers/net/ethernet/Kconfig
index 2ffd634..a4cc87fe 100644
--- a/drivers/net/ethernet/Kconfig
+++ b/drivers/net/ethernet/Kconfig
@@ -21,6 +21,7 @@ source "drivers/net/ethernet/3com/Kconfig"
source "drivers/net/ethernet/adaptec/Kconfig"
source "drivers/net/ethernet/aeroflex/Kconfig"
source "drivers/net/ethernet/agere/Kconfig"
+source "drivers/net/ethernet/alacritech/Kconfig"
source "drivers/net/ethernet/allwinner/Kconfig"
source "drivers/net/ethernet/alteon/Kconfig"
source "drivers/net/ethernet/altera/Kconfig"
diff --git a/drivers/net/ethernet/Makefile b/drivers/net/ethernet/Makefile
index 1d349e9..b448027 100644
--- a/drivers/net/ethernet/Makefile
+++ b/drivers/net/ethernet/Makefile
@@ -7,6 +7,7 @@ obj-$(CONFIG_NET_VENDOR_8390) += 8390/
obj-$(CONFIG_NET_VENDOR_ADAPTEC) += adaptec/
obj-$(CONFIG_GRETH) += aeroflex/
obj-$(CONFIG_NET_VENDOR_AGERE) += agere/
+obj-$(CONFIG_NET_VENDOR_ALACRITECH) += alacritech/
obj-$(CONFIG_NET_VENDOR_ALLWINNER) += allwinner/
obj-$(CONFIG_NET_VENDOR_ALTEON) += alteon/
obj-$(CONFIG_ALTERA_TSE) += altera/
diff --git a/drivers/net/ethernet/alacritech/Kconfig b/drivers/net/ethernet/alacritech/Kconfig
new file mode 100644
index 0000000..41000a3
--- /dev/null
+++ b/drivers/net/ethernet/alacritech/Kconfig
@@ -0,0 +1,28 @@
+config NET_VENDOR_ALACRITECH
+ bool "Alacritech devices"
+ default y
+ ---help---
+ If you have a network (Ethernet) card belonging to this class, say Y.
+
+ Note that the answer to this question doesn't directly affect the
+ kernel: saying N will just cause the configurator to skip all
+ the questions about Renesas devices. If you say Y, you will be asked
+ for your specific device in the following questions.
+
+if NET_VENDOR_ALACRITECH
+
+config SLICOSS
+ tristate "Alacritech Slicoss support"
+ depends on PCI
+ select CRC32
+ ---help---
+ This driver supports Gigabit Ethernet adapters based on the
+ Session Layer Interface (SLIC) technology by Alacritech.
+
+ Supported are Mojave (1 port) and Oasis (1, 2 and 4 port) cards,
+ both copper and fiber.
+
+ To compile this driver as a module, choose M here: the module
+ will be called slicoss. This is recommended.
+
+endif # NET_VENDOR_ALACRITECH
diff --git a/drivers/net/ethernet/alacritech/Makefile b/drivers/net/ethernet/alacritech/Makefile
new file mode 100644
index 0000000..8790e9e
--- /dev/null
+++ b/drivers/net/ethernet/alacritech/Makefile
@@ -0,0 +1,4 @@
+#
+# Makefile for the Alacritech Slicoss driver
+#
+obj-$(CONFIG_SLICOSS) += slicoss.o
diff --git a/drivers/net/ethernet/alacritech/slic.h b/drivers/net/ethernet/alacritech/slic.h
new file mode 100644
index 0000000..c62d46b
--- /dev/null
+++ b/drivers/net/ethernet/alacritech/slic.h
@@ -0,0 +1,576 @@
+
+#ifndef _SLIC_H
+#define _SLIC_H
+
+#include <linux/types.h>
+#include <linux/netdevice.h>
+#include <linux/spinlock_types.h>
+#include <linux/dma-mapping.h>
+#include <linux/pci.h>
+#include <linux/netdevice.h>
+#include <linux/list.h>
+#include <linux/u64_stats_sync.h>
+
+#define SLIC_VGBSTAT_XPERR 0x40000000
+#define SLIC_VGBSTAT_XERRSHFT 25
+#define SLIC_VGBSTAT_XCSERR 0x23
+#define SLIC_VGBSTAT_XUFLOW 0x22
+#define SLIC_VGBSTAT_XHLEN 0x20
+#define SLIC_VGBSTAT_NETERR 0x01000000
+#define SLIC_VGBSTAT_NERRSHFT 16
+#define SLIC_VGBSTAT_NERRMSK 0x1ff
+#define SLIC_VGBSTAT_NCSERR 0x103
+#define SLIC_VGBSTAT_NUFLOW 0x102
+#define SLIC_VGBSTAT_NHLEN 0x100
+#define SLIC_VGBSTAT_LNKERR 0x00000080
+#define SLIC_VGBSTAT_LERRMSK 0xff
+#define SLIC_VGBSTAT_LDEARLY 0x86
+#define SLIC_VGBSTAT_LBOFLO 0x85
+#define SLIC_VGBSTAT_LCODERR 0x84
+#define SLIC_VGBSTAT_LDBLNBL 0x83
+#define SLIC_VGBSTAT_LCRCERR 0x82
+#define SLIC_VGBSTAT_LOFLO 0x81
+#define SLIC_VGBSTAT_LUFLO 0x80
+
+#define SLIC_IRHDDR_FLEN_MSK 0x0000ffff
+#define SLIC_IRHDDR_SVALID 0x80000000
+#define SLIC_IRHDDR_ERR 0x10000000
+
+#define SLIC_VRHSTAT_802OE 0x80000000
+#define SLIC_VRHSTAT_TPOFLO 0x10000000
+#define SLIC_VRHSTATB_802UE 0x80000000
+#define SLIC_VRHSTATB_RCVE 0x40000000
+#define SLIC_VRHSTATB_BUFF 0x20000000
+#define SLIC_VRHSTATB_CARRE 0x08000000
+#define SLIC_VRHSTATB_LONGE 0x02000000
+#define SLIC_VRHSTATB_PREA 0x01000000
+#define SLIC_VRHSTATB_CRC 0x00800000
+#define SLIC_VRHSTATB_DRBL 0x00400000
+#define SLIC_VRHSTATB_CODE 0x00200000
+#define SLIC_VRHSTATB_TPCSUM 0x00100000
+#define SLIC_VRHSTATB_TPHLEN 0x00080000
+#define SLIC_VRHSTATB_IPCSUM 0x00040000
+#define SLIC_VRHSTATB_IPLERR 0x00020000
+#define SLIC_VRHSTATB_IPHERR 0x00010000
+
+#define SLIC_CMD_XMT_REQ 0x01
+#define SLIC_CMD_TYPE_DUMB 3
+
+#define SLIC_RESET_MAGIC 0xDEAD
+#define SLIC_ICR_INT_OFF 0
+#define SLIC_ICR_INT_ON 1
+#define SLIC_ICR_INT_MASK 2
+
+#define SLIC_ISR_ERR 0x80000000
+#define SLIC_ISR_RCV 0x40000000
+#define SLIC_ISR_CMD 0x20000000
+#define SLIC_ISR_IO 0x60000000
+#define SLIC_ISR_UPC 0x10000000
+#define SLIC_ISR_LEVENT 0x08000000
+#define SLIC_ISR_RMISS 0x02000000
+#define SLIC_ISR_UPCERR 0x01000000
+#define SLIC_ISR_XDROP 0x00800000
+#define SLIC_ISR_UPCBSY 0x00020000
+
+#define SLIC_ISR_PING_MASK 0x00700000
+#define SLIC_ISR_UPCERR_MASK (SLIC_ISR_UPCERR | SLIC_ISR_UPCBSY)
+#define SLIC_ISR_UPC_MASK (SLIC_ISR_UPC | SLIC_ISR_UPCERR_MASK)
+#define SLIC_WCS_START 0x80000000
+#define SLIC_WCS_COMPARE 0x40000000
+#define SLIC_RCVWCS_BEGIN 0x40000000
+#define SLIC_RCVWCS_FINISH 0x80000000
+
+#define SLIC_MIICR_REG_16 0x00100000
+#define SLIC_MRV_REG16_XOVERON 0x0068
+
+#define SLIC_GIG_LINKUP 0x0001
+#define SLIC_GIG_FULLDUPLEX 0x0002
+#define SLIC_GIG_SPEED_MASK 0x000C
+#define SLIC_GIG_SPEED_1000 0x0008
+#define SLIC_GIG_SPEED_100 0x0004
+#define SLIC_GIG_SPEED_10 0x0000
+
+#define SLIC_GMCR_RESET 0x80000000
+#define SLIC_GMCR_GBIT 0x20000000
+#define SLIC_GMCR_FULLD 0x10000000
+#define SLIC_GMCR_GAPBB_SHIFT 14
+#define SLIC_GMCR_GAPR1_SHIFT 7
+#define SLIC_GMCR_GAPR2_SHIFT 0
+#define SLIC_GMCR_GAPBB_1000 0x60
+#define SLIC_GMCR_GAPR1_1000 0x2C
+#define SLIC_GMCR_GAPR2_1000 0x40
+#define SLIC_GMCR_GAPBB_100 0x70
+#define SLIC_GMCR_GAPR1_100 0x2C
+#define SLIC_GMCR_GAPR2_100 0x40
+
+#define SLIC_XCR_RESET 0x80000000
+#define SLIC_XCR_XMTEN 0x40000000
+#define SLIC_XCR_PAUSEEN 0x20000000
+#define SLIC_XCR_LOADRNG 0x10000000
+
+#define SLIC_GXCR_RESET 0x80000000
+#define SLIC_GXCR_XMTEN 0x40000000
+#define SLIC_GXCR_PAUSEEN 0x20000000
+
+#define SLIC_GRCR_RESET 0x80000000
+#define SLIC_GRCR_RCVEN 0x40000000
+#define SLIC_GRCR_RCVALL 0x20000000
+#define SLIC_GRCR_RCVBAD 0x10000000
+#define SLIC_GRCR_CTLEN 0x08000000
+#define SLIC_GRCR_ADDRAEN 0x02000000
+#define SLIC_GRCR_HASHSIZE_SHIFT 17
+#define SLIC_GRCR_HASHSIZE 14
+
+/* Reset Register */
+#define SLIC_REG_RESET 0x0000
+/* Interrupt Control Register */
+#define SLIC_REG_ICR 0x0008
+/* Interrupt status pointer */
+#define SLIC_REG_ISP 0x0010
+/* Interrupt status */
+#define SLIC_REG_ISR 0x0018
+/* Header buffer address reg
+ * 31-8 - phy addr of set of contiguous hdr buffers
+ * 7-0 - number of buffers passed
+ * Buffers are 256 bytes long on 256-byte boundaries.
+ */
+#define SLIC_REG_HBAR 0x0020
+/* Data buffer handle & address reg
+ * 4 sets of registers; Buffers are 2K bytes long 2 per 4K page.
+ */
+#define SLIC_REG_DBAR 0x0028
+/* Xmt Cmd buf addr regs.
+ * 1 per XMT interface
+ * 31-5 - phy addr of host command buffer
+ * 4-0 - length of cmd in multiples of 32 bytes
+ * Buffers are 32 bytes up to 512 bytes long
+ */
+#define SLIC_REG_CBAR 0x0030
+/* Write control store */
+#define SLIC_REG_WCS 0x0034
+/*Response buffer address reg.
+ * 31-8 - phy addr of set of contiguous response buffers
+ * 7-0 - number of buffers passed
+ * Buffers are 32 bytes long on 32-byte boundaries.
+ */
+#define SLIC_REG_RBAR 0x0038
+/* Read statistics (UPR) */
+#define SLIC_REG_RSTAT 0x0040
+/* Read link status */
+#define SLIC_REG_LSTAT 0x0048
+/* Write Mac Config */
+#define SLIC_REG_WMCFG 0x0050
+/* Write phy register */
+#define SLIC_REG_WPHY 0x0058
+/* Rcv Cmd buf addr reg */
+#define SLIC_REG_RCBAR 0x0060
+/* Read SLIC Config*/
+#define SLIC_REG_RCONFIG 0x0068
+/* Interrupt aggregation time */
+#define SLIC_REG_INTAGG 0x0070
+/* Write XMIT config reg */
+#define SLIC_REG_WXCFG 0x0078
+/* Write RCV config reg */
+#define SLIC_REG_WRCFG 0x0080
+/* Write rcv addr a low */
+#define SLIC_REG_WRADDRAL 0x0088
+/* Write rcv addr a high */
+#define SLIC_REG_WRADDRAH 0x0090
+/* Write rcv addr b low */
+#define SLIC_REG_WRADDRBL 0x0098
+/* Write rcv addr b high */
+#define SLIC_REG_WRADDRBH 0x00a0
+/* Low bits of mcast mask */
+#define SLIC_REG_MCASTLOW 0x00a8
+/* High bits of mcast mask */
+#define SLIC_REG_MCASTHIGH 0x00b0
+/* Ping the card */
+#define SLIC_REG_PING 0x00b8
+/* Dump command */
+#define SLIC_REG_DUMP_CMD 0x00c0
+/* Dump data pointer */
+#define SLIC_REG_DUMP_DATA 0x00c8
+/* Read card's pci_status register */
+#define SLIC_REG_PCISTATUS 0x00d0
+/* Write hostid field */
+#define SLIC_REG_WRHOSTID 0x00d8
+/* Put card in a low power state */
+#define SLIC_REG_LOW_POWER 0x00e0
+/* Force slic into quiescent state before soft reset */
+#define SLIC_REG_QUIESCE 0x00e8
+/* Reset interface queues */
+#define SLIC_REG_RESET_IFACE 0x00f0
+/* Register is only written when it has changed.
+ * Bits 63-32 for host i/f addrs.
+ */
+#define SLIC_REG_ADDR_UPPER 0x00f8
+/* 64 bit Header buffer address reg */
+#define SLIC_REG_HBAR64 0x0100
+/* 64 bit Data buffer handle & address reg */
+#define SLIC_REG_DBAR64 0x0108
+/* 64 bit Xmt Cmd buf addr regs. */
+#define SLIC_REG_CBAR64 0x0110
+/* 64 bit Response buffer address reg.*/
+#define SLIC_REG_RBAR64 0x0118
+/* 64 bit Rcv Cmd buf addr reg*/
+#define SLIC_REG_RCBAR64 0x0120
+/* Read statistics (64 bit UPR) */
+#define SLIC_REG_RSTAT64 0x0128
+/* Download Gigabit RCV sequencer ucode */
+#define SLIC_REG_RCV_WCS 0x0130
+/* Write VlanId field */
+#define SLIC_REG_WRVLANID 0x0138
+/* Read Transformer info */
+#define SLIC_REG_READ_XF_INFO 0x0140
+/* Write Transformer info */
+#define SLIC_REG_WRITE_XF_INFO 0x0148
+/* Write card ticks per second */
+#define SLIC_REG_TICKS_PER_SEC 0x0170
+#define SLIC_REG_HOSTID 0x1554
+
+#define PCI_VENDOR_ID_ALACRITECH 0x139A
+#define PCI_DEVICE_ID_ALACRITECH_MOAVE 0x0005
+#define PCI_SUBDEVICE_ID_ALACRITECH_1000X1 0x0005
+#define PCI_SUBDEVICE_ID_ALACRITECH_1000X1_2 0x0006
+#define PCI_SUBDEVICE_ID_ALACRITECH_1000X1F 0x0007
+#define PCI_SUBDEVICE_ID_ALACRITECH_CICADA 0x0008
+#define PCI_SUBDEVICE_ID_ALACRITECH_SES1001T 0x2006
+#define PCI_SUBDEVICE_ID_ALACRITECH_SES1001F 0x2007
+#define PCI_DEVICE_ID_ALACRITECH_OASIS 0x0007
+#define PCI_SUBDEVICE_ID_ALACRITECH_SEN2002XT 0x000B
+#define PCI_SUBDEVICE_ID_ALACRITECH_SEN2002XF 0x000C
+#define PCI_SUBDEVICE_ID_ALACRITECH_SEN2001XT 0x000D
+#define PCI_SUBDEVICE_ID_ALACRITECH_SEN2001XF 0x000E
+#define PCI_SUBDEVICE_ID_ALACRITECH_SEN2104EF 0x000F
+#define PCI_SUBDEVICE_ID_ALACRITECH_SEN2104ET 0x0010
+#define PCI_SUBDEVICE_ID_ALACRITECH_SEN2102EF 0x0011
+#define PCI_SUBDEVICE_ID_ALACRITECH_SEN2102ET 0x0012
+
+/* Note: power of two required for number descriptors */
+#define SLIC_NUM_RX_LES 256
+#define SLIC_RX_BUFF_SIZE 2048
+#define SLIC_RX_BUFF_ALIGN 256
+#define SLIC_RX_BUFF_HDR_SIZE 34
+#define SLIC_MAX_REQ_RX_DESCS 1
+
+#define SLIC_NUM_TX_DESCS 256
+#define SLIC_TX_DESC_ALIGN 32
+#define SLIC_MIN_TX_WAKEUP_DESCS 10
+#define SLIC_MAX_REQ_TX_DESCS 1
+#define SLIC_MAX_TX_COMPLETIONS 100
+
+#define SLIC_NUM_STAT_DESCS 128
+#define SLIC_STATS_DESC_ALIGN 256
+
+#define SLIC_NUM_STAT_DESC_ARRAYS 4
+#define SLIC_INVALID_STAT_DESC_IDX 0xffffffff
+
+#define SLIC_NAPI_WEIGHT 64
+
+#define SLIC_UPR_LSTAT 0
+#define SLIC_UPR_CONFIG 1
+
+#define SLIC_EEPROM_SIZE 128
+#define SLIC_EEPROM_MAGIC 0xa5a5
+
+#define SLIC_FIRMWARE_MOAVE "slicoss/gbdownload.sys"
+#define SLIC_FIRMWARE_OASIS "slicoss/oasisdownload.sys"
+#define SLIC_RCV_FIRMWARE_MOAVE "slicoss/gbrcvucode.sys"
+#define SLIC_RCV_FIRMWARE_OASIS "slicoss/oasisrcvucode.sys"
+#define SLIC_FIRMWARE_MIN_SIZE 64
+#define SLIC_FIRMWARE_MAX_SECTIONS 3
+
+#define SLIC_MODEL_MOJAVE 0
+#define SLIC_MODEL_OASIS 1
+
+#define SLIC_INC_STATS_COUNTER(st, counter) \
+do { \
+ u64_stats_update_begin(&(st)->syncp); \
+ (st)->counter++; \
+ u64_stats_update_end(&(st)->syncp); \
+} while (0)
+
+#define SLIC_GET_STATS_COUNTER(newst, st, counter) \
+{ \
+ unsigned int start; \
+ do { \
+ start = u64_stats_fetch_begin_irq(&(st)->syncp); \
+ newst = (st)->counter; \
+ } while (u64_stats_fetch_retry_irq(&(st)->syncp, start)); \
+}
+
+struct slic_upr {
+ dma_addr_t paddr;
+ unsigned int type;
+ struct list_head list;
+};
+
+struct slic_upr_list {
+ bool pending;
+ struct list_head list;
+ /* upr list lock */
+ spinlock_t lock;
+};
+
+/* SLIC EEPROM structure for Oasis */
+struct slic_mojave_eeprom {
+ __le16 id; /* 00 EEPROM/FLASH Magic code 'A5A5'*/
+ __le16 eeprom_code_size;/* 01 Size of EEPROM Codes (bytes * 4)*/
+ __le16 flash_size; /* 02 Flash size */
+ __le16 eeprom_size; /* 03 EEPROM Size */
+ __le16 vendor_id; /* 04 Vendor ID */
+ __le16 dev_id; /* 05 Device ID */
+ u8 rev_id; /* 06 Revision ID */
+ u8 class_code[3]; /* 07 Class Code */
+ u8 irqpin_dbg; /* 08 Debug Interrupt pin */
+ u8 irqpin; /* Network Interrupt Pin */
+ u8 min_grant; /* 09 Minimum grant */
+ u8 max_lat; /* Maximum Latency */
+ __le16 pci_stat; /* 10 PCI Status */
+ __le16 sub_vendor_id; /* 11 Subsystem Vendor Id */
+ __le16 sub_id; /* 12 Subsystem ID */
+ __le16 dev_id_dbg; /* 13 Debug Device Id */
+ __le16 ramrom; /* 14 Dram/Rom function */
+ __le16 dram_size2pci; /* 15 DRAM size to PCI (bytes * 64K) */
+ __le16 rom_size2pci; /* 16 ROM extension size to PCI (bytes * 4k) */
+ u8 pad[2]; /* 17 Padding */
+ u8 freetime; /* 18 FreeTime setting */
+ u8 ifctrl; /* 10-bit interface control (Mojave only) */
+ __le16 dram_size; /* 19 DRAM size (bytes * 64k) */
+ u8 mac[ETH_ALEN]; /* 20 MAC addresses */
+ u8 mac2[ETH_ALEN];
+ u8 pad2[6];
+ u16 dev_id2; /* Device ID for 2nd PCI function */
+ u8 irqpin2; /* Interrupt pin for 2nd PCI function */
+ u8 class_code2[3]; /* Class Code for 2nd PCI function */
+ u16 cfg_byte6; /* Config Byte 6 */
+ u16 pme_cap; /* Power Mgment capabilities */
+ u16 nwclk_ctrl; /* NetworkClockControls */
+ u8 fru_format; /* Alacritech FRU format type */
+ u8 fru_assembly[6]; /* Alacritech FRU information */
+ u8 fru_rev[2];
+ u8 fru_serial[14];
+ u8 fru_pad[3];
+ u8 oem_fru[28]; /* optional OEM FRU format type */
+ u8 pad3[4]; /* Pad to 128 bytes - includes 2 cksum bytes
+ * (if OEM FRU info exists) and two unusable
+ * bytes at the end
+ */
+};
+
+/* SLIC EEPROM structure for Oasis */
+struct slic_oasis_eeprom {
+ __le16 id; /* 00 EEPROM/FLASH Magic code 'A5A5' */
+ __le16 eeprom_code_size;/* 01 Size of EEPROM Codes (bytes * 4)*/
+ __le16 spidev0_cfg; /* 02 Flash Config for SPI device 0 */
+ __le16 spidev1_cfg; /* 03 Flash Config for SPI device 1 */
+ __le16 vendor_id; /* 04 Vendor ID */
+ __le16 dev_id; /* 05 Device ID (function 0) */
+ u8 rev_id; /* 06 Revision ID */
+ u8 class_code0[3]; /* 07 Class Code for PCI function 0 */
+ u8 irqpin1; /* 08 Interrupt pin for PCI function 1*/
+ u8 class_code1[3]; /* 09 Class Code for PCI function 1 */
+ u8 irqpin2; /* 10 Interrupt pin for PCI function 2*/
+ u8 irqpin0; /* Interrupt pin for PCI function 0*/
+ u8 min_grant; /* 11 Minimum grant */
+ u8 max_lat; /* Maximum Latency */
+ __le16 sub_vendor_id; /* 12 Subsystem Vendor Id */
+ __le16 sub_id; /* 13 Subsystem ID */
+ __le16 flash_size; /* 14 Flash size (bytes / 4K) */
+ __le16 dram_size2pci; /* 15 DRAM size to PCI (bytes / 64K) */
+ __le16 rom_size2pci; /* 16 Flash (ROM extension) size to PCI
+ * (bytes / 4K)
+ */
+ __le16 dev_id1; /* 17 Device Id (function 1) */
+ __le16 dev_id2; /* 18 Device Id (function 2) */
+ __le16 dev_stat_cfg; /* 19 Device Status Config Bytes 6-7 */
+ __le16 pme_cap; /* 20 Power Mgment capabilities */
+ u8 msi_cap; /* 21 MSI capabilities */
+ u8 clock_div; /* Clock divider */
+ __le16 pci_stat_lo; /* 22 PCI Status bits 15:0 */
+ __le16 pci_stat_hi; /* 23 PCI Status bits 31:16 */
+ __le16 dram_cfg_lo; /* 24 DRAM Configuration bits 15:0 */
+ __le16 dram_cfg_hi; /* 25 DRAM Configuration bits 31:16 */
+ __le16 dram_size; /* 26 DRAM size (bytes / 64K) */
+ __le16 gpio_tbi_ctrl; /* 27 GPIO/TBI controls for functions 1/0 */
+ __le16 eeprom_size; /* 28 EEPROM Size */
+ u8 mac[ETH_ALEN]; /* 29 MAC addresses (2 ports) */
+ u8 mac2[ETH_ALEN];
+ u8 fru_format; /* 35 Alacritech FRU format type */
+ u8 fru_assembly[6]; /* Alacritech FRU information */
+ u8 fru_rev[2];
+ u8 fru_serial[14];
+ u8 fru_pad[3];
+ u8 oem_fru[28]; /* optional OEM FRU information */
+ u8 pad[4]; /* Pad to 128 bytes - includes 2 checksum bytes
+ * (if OEM FRU info exists) and two unusable
+ * bytes at the end
+ */
+};
+
+struct slic_stats {
+ u64 rx_packets;
+ u64 rx_bytes;
+ u64 rx_mcasts;
+ u64 rx_errors;
+ u64 tx_packets;
+ u64 tx_bytes;
+ /* HW STATS */
+ u64 rx_buff_miss;
+ u64 tx_dropped;
+ u64 irq_errs;
+ /* transport layer */
+ u64 rx_tpcsum;
+ u64 rx_tpoflow;
+ u64 rx_tphlen;
+ /* ip layer */
+ u64 rx_ipcsum;
+ u64 rx_iplen;
+ u64 rx_iphlen;
+ /* link layer */
+ u64 rx_early;
+ u64 rx_buffoflow;
+ u64 rx_lcode;
+ u64 rx_drbl;
+ u64 rx_crc;
+ u64 rx_oflow802;
+ u64 rx_uflow802;
+ /* oasis only */
+ u64 tx_carrier;
+ struct u64_stats_sync syncp;
+};
+
+struct slic_shmem_data {
+ __le32 isr;
+ __le32 link;
+};
+
+struct slic_shmem {
+ dma_addr_t isr_paddr;
+ dma_addr_t link_paddr;
+ struct slic_shmem_data *shmem_data;
+};
+
+struct slic_rx_info_oasis {
+ __le32 frame_status;
+ __le32 frame_status_b;
+ __le32 time_stamp;
+ __le32 checksum;
+};
+
+struct slic_rx_info_mojave {
+ __le32 frame_status;
+ __le16 byte_cnt;
+ __le16 tp_chksum;
+ __le16 ctx_hash;
+ __le16 mac_hash;
+ __le16 buff_lnk;
+};
+
+struct slic_stat_desc {
+ __le32 hnd;
+ __u8 pad[8];
+ __le32 status;
+ __u8 pad2[16];
+};
+
+struct slic_stat_queue {
+ struct slic_stat_desc *descs[SLIC_NUM_STAT_DESC_ARRAYS];
+ dma_addr_t paddr[SLIC_NUM_STAT_DESC_ARRAYS];
+ unsigned int addr_offset[SLIC_NUM_STAT_DESC_ARRAYS];
+ unsigned int active_array;
+ unsigned int len;
+ unsigned int done_idx;
+ size_t mem_size;
+};
+
+struct slic_tx_desc {
+ __le32 hnd;
+ __le32 rsvd;
+ u8 cmd;
+ u8 flags;
+ __le16 rsvd2;
+ __le32 totlen;
+ __le32 paddrl;
+ __le32 paddrh;
+ __le32 len;
+ __le32 type;
+};
+
+struct slic_tx_buffer {
+ struct sk_buff *skb;
+ DEFINE_DMA_UNMAP_ADDR(map_addr);
+ DEFINE_DMA_UNMAP_LEN(map_len);
+ struct slic_tx_desc *desc;
+ dma_addr_t desc_paddr;
+};
+
+struct slic_tx_queue {
+ struct dma_pool *dma_pool;
+ struct slic_tx_buffer *txbuffs;
+ unsigned int len;
+ unsigned int put_idx;
+ unsigned int done_idx;
+};
+
+struct slic_rx_desc {
+ u8 pad[16];
+ __le32 buffer;
+ __le32 length;
+ __le32 status;
+};
+
+struct slic_rx_buffer {
+ struct sk_buff *skb;
+ DEFINE_DMA_UNMAP_ADDR(map_addr);
+ DEFINE_DMA_UNMAP_LEN(map_len);
+ unsigned int addr_offset;
+};
+
+struct slic_rx_queue {
+ struct slic_rx_buffer *rxbuffs;
+ unsigned int len;
+ unsigned int done_idx;
+ unsigned int put_idx;
+};
+
+struct slic_device {
+ struct pci_dev *pdev;
+ struct net_device *netdev;
+ void __iomem *regs;
+ /* upper address setting lock */
+ spinlock_t upper_lock;
+ struct slic_shmem shmem;
+ struct napi_struct napi;
+ struct slic_rx_queue rxq;
+ struct slic_tx_queue txq;
+ struct slic_stat_queue stq;
+ struct slic_stats stats;
+ struct slic_upr_list upr_list;
+ /* link configuration lock */
+ spinlock_t link_lock;
+ bool promisc;
+ bool autoneg;
+ int speed;
+ int duplex;
+ bool is_fiber;
+ unsigned char model;
+};
+
+static inline u32 slic_read(struct slic_device *sdev, unsigned int reg)
+{
+ return ioread32(sdev->regs + reg);
+}
+
+static inline void slic_write(struct slic_device *sdev, unsigned int reg,
+ u32 val)
+{
+ iowrite32(val, sdev->regs + reg);
+}
+
+static inline void slic_flush_write(struct slic_device *sdev)
+{
+ (void)ioread32(sdev->regs + SLIC_REG_HOSTID);
+}
+
+#endif /* _SLIC_H */
diff --git a/drivers/net/ethernet/alacritech/slicoss.c b/drivers/net/ethernet/alacritech/slicoss.c
new file mode 100644
index 0000000..8cd862a
--- /dev/null
+++ b/drivers/net/ethernet/alacritech/slicoss.c
@@ -0,0 +1,1867 @@
+/*
+ * Driver for Gigabit Ethernet adapters based on the Session Layer
+ * Interface (SLIC) technology by Alacritech. The driver does not
+ * support the hardware acceleration features provided by these cards.
+ *
+ * Copyright (C) 2016 Lino Sanfilippo <LinoSanfilippo@gmx.de>
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/if_ether.h>
+#include <linux/crc32.h>
+#include <linux/dma-mapping.h>
+#include <linux/ethtool.h>
+#include <linux/mii.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/firmware.h>
+#include <linux/list.h>
+#include <linux/u64_stats_sync.h>
+
+#include "slic.h"
+
+#define DRV_NAME "slicoss"
+#define DRV_VERSION "1.0"
+
+static const struct pci_device_id slic_id_tbl[] = {
+ { PCI_DEVICE(PCI_VENDOR_ID_ALACRITECH,
+ PCI_DEVICE_ID_ALACRITECH_MOAVE) },
+ { PCI_DEVICE(PCI_VENDOR_ID_ALACRITECH,
+ PCI_DEVICE_ID_ALACRITECH_OASIS) },
+ { 0 }
+};
+
+static const char slic_stats_strings[][ETH_GSTRING_LEN] = {
+ "rx_packets",
+ "rx_bytes",
+ "rx_multicasts",
+ "rx_errors",
+ "rx_buff_miss",
+ "rx_tp_csum",
+ "rx_tp_oflow",
+ "rx_tp_hlen",
+ "rx_ip_csum",
+ "rx_ip_len",
+ "rx_ip_hdr_len",
+ "rx_early",
+ "rx_buff_oflow",
+ "rx_lcode",
+ "rx_drbl",
+ "rx_crc",
+ "rx_oflow_802",
+ "rx_uflow_802",
+ "tx_packets",
+ "tx_bytes",
+ "tx_carrier",
+ "tx_dropped",
+ "irq_errs",
+};
+
+static inline int slic_next_queue_idx(unsigned int idx, unsigned int qlen)
+{
+ return (idx + 1) & (qlen - 1);
+}
+
+static inline int slic_get_free_queue_descs(unsigned int put_idx,
+ unsigned int done_idx,
+ unsigned int qlen)
+{
+ if (put_idx >= done_idx)
+ return (qlen - (put_idx - done_idx) - 1);
+ return (done_idx - put_idx - 1);
+}
+
+static unsigned int slic_next_compl_idx(struct slic_device *sdev)
+{
+ struct slic_stat_queue *stq = &sdev->stq;
+ unsigned int active = stq->active_array;
+ struct slic_stat_desc *descs;
+ struct slic_stat_desc *stat;
+ unsigned int idx;
+
+ descs = stq->descs[active];
+ stat = &descs[stq->done_idx];
+
+ if (!stat->status)
+ return SLIC_INVALID_STAT_DESC_IDX;
+
+ idx = (le32_to_cpu(stat->hnd) & 0xffff) - 1;
+ /* reset desc */
+ stat->hnd = 0;
+ stat->status = 0;
+
+ stq->done_idx = slic_next_queue_idx(stq->done_idx, stq->len);
+ /* check for wraparound */
+ if (!stq->done_idx) {
+ dma_addr_t paddr = stq->paddr[active];
+
+ slic_write(sdev, SLIC_REG_RBAR, lower_32_bits(paddr) |
+ stq->len);
+ /* make sure new status descriptors are immediately available */
+ slic_flush_write(sdev);
+ active++;
+ active &= (SLIC_NUM_STAT_DESC_ARRAYS - 1);
+ stq->active_array = active;
+ }
+ return idx;
+}
+
+static unsigned int slic_get_free_tx_descs(struct slic_tx_queue *txq)
+{
+ /* ensure tail idx is updated */
+ smp_mb();
+ return slic_get_free_queue_descs(txq->put_idx, txq->done_idx, txq->len);
+}
+
+static unsigned int slic_get_free_rx_descs(struct slic_rx_queue *rxq)
+{
+ return slic_get_free_queue_descs(rxq->put_idx, rxq->done_idx, rxq->len);
+}
+
+static void slic_clear_upr_list(struct slic_upr_list *upr_list)
+{
+ struct slic_upr *upr;
+ struct slic_upr *tmp;
+
+ spin_lock_bh(&upr_list->lock);
+ list_for_each_entry_safe(upr, tmp, &upr_list->list, list) {
+ list_del(&upr->list);
+ kfree(upr);
+ }
+ upr_list->pending = false;
+ spin_unlock_bh(&upr_list->lock);
+}
+
+static void slic_start_upr(struct slic_device *sdev, struct slic_upr *upr)
+{
+ u32 reg;
+
+ reg = (upr->type == SLIC_UPR_CONFIG) ? SLIC_REG_RCONFIG :
+ SLIC_REG_LSTAT;
+ slic_write(sdev, reg, lower_32_bits(upr->paddr));
+ slic_flush_write(sdev);
+}
+
+static void slic_queue_upr(struct slic_device *sdev, struct slic_upr *upr)
+{
+ struct slic_upr_list *upr_list = &sdev->upr_list;
+ bool pending;
+
+ spin_lock_bh(&upr_list->lock);
+ pending = upr_list->pending;
+ INIT_LIST_HEAD(&upr->list);
+ list_add_tail(&upr->list, &upr_list->list);
+ upr_list->pending = true;
+ spin_unlock_bh(&upr_list->lock);
+
+ if (!pending)
+ slic_start_upr(sdev, upr);
+}
+
+static struct slic_upr *slic_dequeue_upr(struct slic_device *sdev)
+{
+ struct slic_upr_list *upr_list = &sdev->upr_list;
+ struct slic_upr *next_upr = NULL;
+ struct slic_upr *upr = NULL;
+
+ spin_lock_bh(&upr_list->lock);
+ if (!list_empty(&upr_list->list)) {
+ upr = list_first_entry(&upr_list->list, struct slic_upr, list);
+ list_del(&upr->list);
+
+ if (list_empty(&upr_list->list))
+ upr_list->pending = false;
+ else
+ next_upr = list_first_entry(&upr_list->list,
+ struct slic_upr, list);
+ }
+ spin_unlock_bh(&upr_list->lock);
+ /* trigger processing of the next upr in list */
+ if (next_upr)
+ slic_start_upr(sdev, next_upr);
+
+ return upr;
+}
+
+static int slic_new_upr(struct slic_device *sdev, unsigned int type,
+ dma_addr_t paddr)
+{
+ struct slic_upr *upr;
+
+ upr = kmalloc(sizeof(*upr), GFP_ATOMIC);
+ if (!upr)
+ return -ENOMEM;
+ upr->type = type;
+ upr->paddr = paddr;
+
+ slic_queue_upr(sdev, upr);
+
+ return 0;
+}
+
+static void slic_set_mcast_bit(u64 *mcmask, unsigned char const *addr)
+{
+ u64 mask = *mcmask;
+ u8 crc;
+ /* Get the CRC polynomial for the mac address: we use bits 1-8 (lsb),
+ * bitwise reversed, msb (= lsb bit 0 before bitrev) is automatically
+ * discarded.
+ */
+ crc = ether_crc(ETH_ALEN, addr) >> 23;
+ /* we only have space on the SLIC for 64 entries */
+ crc &= 0x3F;
+ mask |= (u64)1 << crc;
+ *mcmask = mask;
+}
+
+/* must be called with link_lock held */
+static void slic_configure_rcv(struct slic_device *sdev)
+{
+ u32 val;
+
+ val = SLIC_GRCR_RESET | SLIC_GRCR_ADDRAEN | SLIC_GRCR_RCVEN |
+ SLIC_GRCR_HASHSIZE << SLIC_GRCR_HASHSIZE_SHIFT | SLIC_GRCR_RCVBAD;
+
+ if (sdev->duplex == DUPLEX_FULL)
+ val |= SLIC_GRCR_CTLEN;
+
+ if (sdev->promisc)
+ val |= SLIC_GRCR_RCVALL;
+
+ slic_write(sdev, SLIC_REG_WRCFG, val);
+}
+
+/* must be called with link_lock held */
+static void slic_configure_xmt(struct slic_device *sdev)
+{
+ u32 val;
+
+ val = SLIC_GXCR_RESET | SLIC_GXCR_XMTEN;
+
+ if (sdev->duplex == DUPLEX_FULL)
+ val |= SLIC_GXCR_PAUSEEN;
+
+ slic_write(sdev, SLIC_REG_WXCFG, val);
+}
+
+/* must be called with link_lock held */
+static void slic_configure_mac(struct slic_device *sdev)
+{
+ u32 val;
+
+ if (sdev->speed == SPEED_1000) {
+ val = SLIC_GMCR_GAPBB_1000 << SLIC_GMCR_GAPBB_SHIFT |
+ SLIC_GMCR_GAPR1_1000 << SLIC_GMCR_GAPR1_SHIFT |
+ SLIC_GMCR_GAPR2_1000 << SLIC_GMCR_GAPR2_SHIFT |
+ SLIC_GMCR_GBIT; /* enable GMII */
+ } else {
+ val = SLIC_GMCR_GAPBB_100 << SLIC_GMCR_GAPBB_SHIFT |
+ SLIC_GMCR_GAPR1_100 << SLIC_GMCR_GAPR1_SHIFT |
+ SLIC_GMCR_GAPR2_100 << SLIC_GMCR_GAPR2_SHIFT;
+ }
+
+ if (sdev->duplex == DUPLEX_FULL)
+ val |= SLIC_GMCR_FULLD;
+
+ slic_write(sdev, SLIC_REG_WMCFG, val);
+}
+
+static void slic_configure_link_locked(struct slic_device *sdev,
+ unsigned int speed, unsigned int duplex)
+{
+ struct net_device *dev = sdev->netdev;
+
+ if (sdev->speed == speed && sdev->duplex == duplex)
+ return;
+
+ sdev->speed = speed;
+ sdev->duplex = duplex;
+
+ if (sdev->speed == SPEED_UNKNOWN) {
+ if (netif_carrier_ok(dev))
+ netif_carrier_off(dev);
+ } else {
+ /* (re)configure link settings */
+ slic_configure_mac(sdev);
+ slic_configure_xmt(sdev);
+ slic_configure_rcv(sdev);
+ slic_flush_write(sdev);
+
+ if (!netif_carrier_ok(dev))
+ netif_carrier_on(dev);
+ }
+}
+
+static void slic_configure_link(struct slic_device *sdev, unsigned int speed,
+ unsigned int duplex)
+{
+ spin_lock_bh(&sdev->link_lock);
+ slic_configure_link_locked(sdev, speed, duplex);
+ spin_unlock_bh(&sdev->link_lock);
+}
+
+static void slic_set_rx_mode(struct net_device *dev)
+{
+ struct slic_device *sdev = netdev_priv(dev);
+ struct netdev_hw_addr *hwaddr;
+ bool set_promisc;
+ u64 mcmask;
+
+ if (dev->flags & (IFF_PROMISC | IFF_ALLMULTI)) {
+ /* Turn on all multicast addresses. We have to do this for
+ * promiscuous mode as well as ALLMCAST mode (it saves the
+ * microcode from having to keep state about the MAC
+ * configuration).
+ */
+ mcmask = ~(u64)0;
+ } else {
+ mcmask = 0;
+
+ netdev_for_each_mc_addr(hwaddr, dev) {
+ slic_set_mcast_bit(&mcmask, hwaddr->addr);
+ }
+ }
+
+ slic_write(sdev, SLIC_REG_MCASTLOW, lower_32_bits(mcmask));
+ slic_write(sdev, SLIC_REG_MCASTHIGH, upper_32_bits(mcmask));
+
+ set_promisc = !!(dev->flags & IFF_PROMISC);
+
+ spin_lock_bh(&sdev->link_lock);
+ if (sdev->promisc != set_promisc) {
+ sdev->promisc = set_promisc;
+ slic_configure_rcv(sdev);
+ /* make sure writes to receiver cant leak out of the lock */
+ mmiowb();
+ }
+ spin_unlock_bh(&sdev->link_lock);
+}
+
+static void slic_xmit_complete(struct slic_device *sdev)
+{
+ struct slic_tx_queue *txq = &sdev->txq;
+ struct net_device *dev = sdev->netdev;
+ unsigned int idx = txq->done_idx;
+ struct slic_tx_buffer *buff;
+ unsigned int frames = 0;
+ unsigned int bytes = 0;
+
+ do {
+ idx = slic_next_compl_idx(sdev);
+ if (idx == SLIC_INVALID_STAT_DESC_IDX)
+ break;
+
+ txq->done_idx = idx;
+ buff = &txq->txbuffs[idx];
+
+ if (unlikely(!buff->skb)) {
+ netdev_warn(dev,
+ "no skb found for desc idx %i\n", idx);
+ continue;
+ }
+ dma_unmap_single(&sdev->pdev->dev,
+ dma_unmap_addr(buff, map_addr),
+ dma_unmap_len(buff, map_len), DMA_TO_DEVICE);
+
+ bytes += buff->skb->len;
+ frames++;
+
+ dev_kfree_skb_any(buff->skb);
+ buff->skb = NULL;
+ } while (frames < SLIC_MAX_TX_COMPLETIONS);
+ /* make sure xmit sees the new value for done_idx */
+ smp_wmb();
+
+ u64_stats_update_begin(&sdev->stats.syncp);
+ sdev->stats.tx_bytes += bytes;
+ sdev->stats.tx_packets += frames;
+ u64_stats_update_end(&sdev->stats.syncp);
+
+ netif_tx_lock(dev);
+ if (netif_queue_stopped(dev) &&
+ (slic_get_free_tx_descs(txq) >= SLIC_MIN_TX_WAKEUP_DESCS))
+ netif_wake_queue(dev);
+ netif_tx_unlock(dev);
+}
+
+static void slic_refill_rx_queue(struct slic_device *sdev, gfp_t gfp)
+{
+ const unsigned int ALIGN_MASK = SLIC_RX_BUFF_ALIGN - 1;
+ unsigned int maplen = SLIC_RX_BUFF_SIZE;
+ struct slic_rx_queue *rxq = &sdev->rxq;
+ struct net_device *dev = sdev->netdev;
+ struct slic_rx_buffer *buff;
+ struct slic_rx_desc *desc;
+ unsigned int misalign;
+ unsigned int offset;
+ struct sk_buff *skb;
+ dma_addr_t paddr;
+
+ while (slic_get_free_rx_descs(rxq) > SLIC_MAX_REQ_RX_DESCS) {
+ skb = alloc_skb(maplen + ALIGN_MASK, gfp);
+ if (!skb)
+ break;
+
+ paddr = dma_map_single(&sdev->pdev->dev, skb->data, maplen,
+ DMA_FROM_DEVICE);
+ if (dma_mapping_error(&sdev->pdev->dev, paddr)) {
+ netdev_err(dev, "mapping rx packet failed\n");
+ /* drop skb */
+ dev_kfree_skb_any(skb);
+ break;
+ }
+ /* ensure head buffer descriptors are 256 byte aligned */
+ offset = 0;
+ misalign = paddr & ALIGN_MASK;
+ if (misalign) {
+ offset = SLIC_RX_BUFF_ALIGN - misalign;
+ skb_reserve(skb, offset);
+ }
+ /* the HW expects dma chunks for descriptor + frame data */
+ desc = (struct slic_rx_desc *)skb->data;
+ memset(desc, 0, sizeof(*desc));
+
+ buff = &rxq->rxbuffs[rxq->put_idx];
+ buff->skb = skb;
+ dma_unmap_addr_set(buff, map_addr, paddr);
+ dma_unmap_len_set(buff, map_len, maplen);
+ buff->addr_offset = offset;
+ /* head buffer descriptors are placed immediately before skb */
+ slic_write(sdev, SLIC_REG_HBAR, lower_32_bits(paddr) +
+ offset);
+ rxq->put_idx = slic_next_queue_idx(rxq->put_idx, rxq->len);
+ }
+}
+
+static void slic_handle_frame_error(struct slic_device *sdev,
+ struct sk_buff *skb)
+{
+ struct slic_stats *stats = &sdev->stats;
+
+ if (sdev->model == SLIC_MODEL_OASIS) {
+ struct slic_rx_info_oasis *info;
+ u32 status_b;
+ u32 status;
+
+ info = (struct slic_rx_info_oasis *)skb->data;
+ status = le32_to_cpu(info->frame_status);
+ status_b = le32_to_cpu(info->frame_status_b);
+ /* transport layer */
+ if (status_b & SLIC_VRHSTATB_TPCSUM)
+ SLIC_INC_STATS_COUNTER(stats, rx_tpcsum);
+ if (status & SLIC_VRHSTAT_TPOFLO)
+ SLIC_INC_STATS_COUNTER(stats, rx_tpoflow);
+ if (status_b & SLIC_VRHSTATB_TPHLEN)
+ SLIC_INC_STATS_COUNTER(stats, rx_tphlen);
+ /* ip layer */
+ if (status_b & SLIC_VRHSTATB_IPCSUM)
+ SLIC_INC_STATS_COUNTER(stats, rx_ipcsum);
+ if (status_b & SLIC_VRHSTATB_IPLERR)
+ SLIC_INC_STATS_COUNTER(stats, rx_iplen);
+ if (status_b & SLIC_VRHSTATB_IPHERR)
+ SLIC_INC_STATS_COUNTER(stats, rx_iphlen);
+ /* link layer */
+ if (status_b & SLIC_VRHSTATB_RCVE)
+ SLIC_INC_STATS_COUNTER(stats, rx_early);
+ if (status_b & SLIC_VRHSTATB_BUFF)
+ SLIC_INC_STATS_COUNTER(stats, rx_buffoflow);
+ if (status_b & SLIC_VRHSTATB_CODE)
+ SLIC_INC_STATS_COUNTER(stats, rx_lcode);
+ if (status_b & SLIC_VRHSTATB_DRBL)
+ SLIC_INC_STATS_COUNTER(stats, rx_drbl);
+ if (status_b & SLIC_VRHSTATB_CRC)
+ SLIC_INC_STATS_COUNTER(stats, rx_crc);
+ if (status & SLIC_VRHSTAT_802OE)
+ SLIC_INC_STATS_COUNTER(stats, rx_oflow802);
+ if (status_b & SLIC_VRHSTATB_802UE)
+ SLIC_INC_STATS_COUNTER(stats, rx_uflow802);
+ if (status_b & SLIC_VRHSTATB_CARRE)
+ SLIC_INC_STATS_COUNTER(stats, tx_carrier);
+ } else { /* mojave */
+ struct slic_rx_info_mojave *info;
+ u32 status;
+
+ info = (struct slic_rx_info_mojave *)skb->data;
+ status = le32_to_cpu(info->frame_status);
+ /* transport layer */
+ if (status & SLIC_VGBSTAT_XPERR) {
+ u32 xerr = status >> SLIC_VGBSTAT_XERRSHFT;
+
+ if (xerr == SLIC_VGBSTAT_XCSERR)
+ SLIC_INC_STATS_COUNTER(stats, rx_tpcsum);
+ if (xerr == SLIC_VGBSTAT_XUFLOW)
+ SLIC_INC_STATS_COUNTER(stats, rx_tpoflow);
+ if (xerr == SLIC_VGBSTAT_XHLEN)
+ SLIC_INC_STATS_COUNTER(stats, rx_tphlen);
+ }
+ /* ip layer */
+ if (status & SLIC_VGBSTAT_NETERR) {
+ u32 nerr = status >> SLIC_VGBSTAT_NERRSHFT &
+ SLIC_VGBSTAT_NERRMSK;
+
+ if (nerr == SLIC_VGBSTAT_NCSERR)
+ SLIC_INC_STATS_COUNTER(stats, rx_ipcsum);
+ if (nerr == SLIC_VGBSTAT_NUFLOW)
+ SLIC_INC_STATS_COUNTER(stats, rx_iplen);
+ if (nerr == SLIC_VGBSTAT_NHLEN)
+ SLIC_INC_STATS_COUNTER(stats, rx_iphlen);
+ }
+ /* link layer */
+ if (status & SLIC_VGBSTAT_LNKERR) {
+ u32 lerr = status & SLIC_VGBSTAT_LERRMSK;
+
+ if (lerr == SLIC_VGBSTAT_LDEARLY)
+ SLIC_INC_STATS_COUNTER(stats, rx_early);
+ if (lerr == SLIC_VGBSTAT_LBOFLO)
+ SLIC_INC_STATS_COUNTER(stats, rx_buffoflow);
+ if (lerr == SLIC_VGBSTAT_LCODERR)
+ SLIC_INC_STATS_COUNTER(stats, rx_lcode);
+ if (lerr == SLIC_VGBSTAT_LDBLNBL)
+ SLIC_INC_STATS_COUNTER(stats, rx_drbl);
+ if (lerr == SLIC_VGBSTAT_LCRCERR)
+ SLIC_INC_STATS_COUNTER(stats, rx_crc);
+ if (lerr == SLIC_VGBSTAT_LOFLO)
+ SLIC_INC_STATS_COUNTER(stats, rx_oflow802);
+ if (lerr == SLIC_VGBSTAT_LUFLO)
+ SLIC_INC_STATS_COUNTER(stats, rx_uflow802);
+ }
+ }
+ SLIC_INC_STATS_COUNTER(stats, rx_errors);
+}
+
+static void slic_handle_receive(struct slic_device *sdev, unsigned int todo,
+ unsigned int *done)
+{
+ struct slic_rx_queue *rxq = &sdev->rxq;
+ struct net_device *dev = sdev->netdev;
+ struct slic_rx_buffer *buff;
+ struct slic_rx_desc *desc;
+ unsigned int frames = 0;
+ unsigned int bytes = 0;
+ struct sk_buff *skb;
+ u32 status;
+ u32 len;
+
+ while (todo && (rxq->done_idx != rxq->put_idx)) {
+ buff = &rxq->rxbuffs[rxq->done_idx];
+
+ skb = buff->skb;
+ if (!skb)
+ break;
+
+ desc = (struct slic_rx_desc *)skb->data;
+
+ dma_sync_single_for_cpu(&sdev->pdev->dev,
+ dma_unmap_addr(buff, map_addr),
+ buff->addr_offset + sizeof(*desc),
+ DMA_FROM_DEVICE);
+
+ status = le32_to_cpu(desc->status);
+ if (!(status & SLIC_IRHDDR_SVALID))
+ break;
+
+ buff->skb = NULL;
+
+ dma_unmap_single(&sdev->pdev->dev,
+ dma_unmap_addr(buff, map_addr),
+ dma_unmap_len(buff, map_len),
+ DMA_FROM_DEVICE);
+
+ /* skip rx descriptor that is placed before the frame data */
+ skb_reserve(skb, SLIC_RX_BUFF_HDR_SIZE);
+
+ if (unlikely(status & SLIC_IRHDDR_ERR)) {
+ slic_handle_frame_error(sdev, skb);
+ dev_kfree_skb_any(skb);
+ } else {
+ struct ethhdr *eh = (struct ethhdr *)skb->data;
+
+ if (is_multicast_ether_addr(eh->h_dest))
+ SLIC_INC_STATS_COUNTER(&sdev->stats, rx_mcasts);
+
+ len = le32_to_cpu(desc->length) & SLIC_IRHDDR_FLEN_MSK;
+ skb_put(skb, len);
+ skb->protocol = eth_type_trans(skb, dev);
+ skb->ip_summed = CHECKSUM_UNNECESSARY;
+ skb->dev = dev;
+
+ napi_gro_receive(&sdev->napi, skb);
+
+ bytes += len;
+ frames++;
+ }
+ rxq->done_idx = slic_next_queue_idx(rxq->done_idx, rxq->len);
+ todo--;
+ }
+
+ u64_stats_update_begin(&sdev->stats.syncp);
+ sdev->stats.rx_bytes += bytes;
+ sdev->stats.rx_packets += frames;
+ u64_stats_update_end(&sdev->stats.syncp);
+
+ slic_refill_rx_queue(sdev, GFP_ATOMIC);
+}
+
+static void slic_handle_link_irq(struct slic_device *sdev)
+{
+ struct slic_shmem *sm = &sdev->shmem;
+ struct slic_shmem_data *sm_data = sm->shmem_data;
+ unsigned int duplex;
+ unsigned int speed;
+ u32 link;
+
+ link = le32_to_cpu(sm_data->link);
+
+ if (link & SLIC_GIG_LINKUP) {
+ if (link & SLIC_GIG_SPEED_1000)
+ speed = SPEED_1000;
+ else if (link & SLIC_GIG_SPEED_100)
+ speed = SPEED_100;
+ else
+ speed = SPEED_10;
+
+ duplex = (link & SLIC_GIG_FULLDUPLEX) ? DUPLEX_FULL :
+ DUPLEX_HALF;
+ } else {
+ duplex = DUPLEX_UNKNOWN;
+ speed = SPEED_UNKNOWN;
+ }
+ slic_configure_link(sdev, speed, duplex);
+}
+
+static void slic_handle_upr_irq(struct slic_device *sdev, u32 irqs)
+{
+ struct slic_upr *upr;
+
+ /* remove upr that caused this irq (always the first entry in list) */
+ upr = slic_dequeue_upr(sdev);
+ if (!upr) {
+ netdev_warn(sdev->netdev, "no upr found on list\n");
+ return;
+ }
+
+ if (upr->type == SLIC_UPR_LSTAT) {
+ if (unlikely(irqs & SLIC_ISR_UPCERR_MASK)) {
+ /* try again */
+ slic_queue_upr(sdev, upr);
+ return;
+ }
+ slic_handle_link_irq(sdev);
+ }
+ kfree(upr);
+}
+
+static int slic_handle_link_change(struct slic_device *sdev)
+{
+ return slic_new_upr(sdev, SLIC_UPR_LSTAT, sdev->shmem.link_paddr);
+}
+
+static void slic_handle_err_irq(struct slic_device *sdev, u32 isr)
+{
+ struct slic_stats *stats = &sdev->stats;
+
+ if (isr & SLIC_ISR_RMISS)
+ SLIC_INC_STATS_COUNTER(stats, rx_buff_miss);
+ if (isr & SLIC_ISR_XDROP)
+ SLIC_INC_STATS_COUNTER(stats, tx_dropped);
+ if (!(isr & (SLIC_ISR_RMISS | SLIC_ISR_XDROP)))
+ SLIC_INC_STATS_COUNTER(stats, irq_errs);
+}
+
+static void slic_handle_irq(struct slic_device *sdev, u32 isr,
+ unsigned int todo, unsigned int *done)
+{
+ if (isr & SLIC_ISR_ERR)
+ slic_handle_err_irq(sdev, isr);
+
+ if (isr & SLIC_ISR_LEVENT)
+ slic_handle_link_change(sdev);
+
+ if (isr & SLIC_ISR_UPC_MASK)
+ slic_handle_upr_irq(sdev, isr);
+
+ if (isr & SLIC_ISR_RCV)
+ slic_handle_receive(sdev, todo, done);
+
+ if (isr & SLIC_ISR_CMD)
+ slic_xmit_complete(sdev);
+}
+
+static int slic_poll(struct napi_struct *napi, int todo)
+{
+ struct slic_device *sdev = container_of(napi, struct slic_device, napi);
+ struct slic_shmem *sm = &sdev->shmem;
+ struct slic_shmem_data *sm_data = sm->shmem_data;
+ u32 isr = le32_to_cpu(sm_data->isr);
+ unsigned int done = 0;
+
+ slic_handle_irq(sdev, isr, todo, &done);
+
+ if (done < todo) {
+ napi_complete(napi);
+ /* reenable irqs */
+ sm_data->isr = 0;
+ /* make sure sm_data->isr is cleard before irqs are reenabled */
+ wmb();
+ slic_write(sdev, SLIC_REG_ISR, 0);
+ slic_flush_write(sdev);
+ }
+
+ return done;
+}
+
+static irqreturn_t slic_irq(int irq, void *dev_id)
+{
+ struct slic_device *sdev = dev_id;
+ struct slic_shmem *sm = &sdev->shmem;
+ struct slic_shmem_data *sm_data = sm->shmem_data;
+
+ slic_write(sdev, SLIC_REG_ICR, SLIC_ICR_INT_MASK);
+ slic_flush_write(sdev);
+ /* make sure sm_data->isr is read after ICR_INT_MASK is set */
+ wmb();
+
+ if (!sm_data->isr) {
+ dma_rmb();
+ /* spurious interrupt */
+ slic_write(sdev, SLIC_REG_ISR, 0);
+ slic_flush_write(sdev);
+ return IRQ_NONE;
+ }
+
+ napi_schedule(&sdev->napi);
+
+ return IRQ_HANDLED;
+}
+
+static void slic_card_reset(struct slic_device *sdev)
+{
+ u16 cmd;
+
+ slic_write(sdev, SLIC_REG_RESET, SLIC_RESET_MAGIC);
+ /* flush write by means of config space */
+ pci_read_config_word(sdev->pdev, PCI_COMMAND, &cmd);
+ mdelay(1);
+}
+
+static int slic_init_stat_queue(struct slic_device *sdev)
+{
+ const unsigned int DESC_ALIGN_MASK = SLIC_STATS_DESC_ALIGN - 1;
+ struct slic_stat_queue *stq = &sdev->stq;
+ struct slic_stat_desc *descs;
+ unsigned int misalign;
+ unsigned int offset;
+ dma_addr_t paddr;
+ size_t size;
+ int err;
+ int i;
+
+ stq->len = SLIC_NUM_STAT_DESCS;
+ stq->active_array = 0;
+ stq->done_idx = 0;
+
+ size = stq->len * sizeof(*descs) + DESC_ALIGN_MASK;
+
+ for (i = 0; i < SLIC_NUM_STAT_DESC_ARRAYS; i++) {
+ descs = dma_zalloc_coherent(&sdev->pdev->dev, size, &paddr,
+ GFP_KERNEL);
+ if (!descs) {
+ netdev_err(sdev->netdev,
+ "failed to allocate status descriptors\n");
+ err = -ENOMEM;
+ goto free_descs;
+ }
+ /* ensure correct alignment */
+ offset = 0;
+ misalign = paddr & DESC_ALIGN_MASK;
+ if (misalign) {
+ offset = SLIC_STATS_DESC_ALIGN - misalign;
+ descs += offset;
+ paddr += offset;
+ }
+
+ slic_write(sdev, SLIC_REG_RBAR, lower_32_bits(paddr) |
+ stq->len);
+ stq->descs[i] = descs;
+ stq->paddr[i] = paddr;
+ stq->addr_offset[i] = offset;
+ }
+
+ stq->mem_size = size;
+
+ return 0;
+
+free_descs:
+ while (i--) {
+ dma_free_coherent(&sdev->pdev->dev, stq->mem_size,
+ stq->descs[i] - stq->addr_offset[i],
+ stq->paddr[i] - stq->addr_offset[i]);
+ }
+
+ return err;
+}
+
+static void slic_free_stat_queue(struct slic_device *sdev)
+{
+ struct slic_stat_queue *stq = &sdev->stq;
+ int i;
+
+ for (i = 0; i < SLIC_NUM_STAT_DESC_ARRAYS; i++) {
+ dma_free_coherent(&sdev->pdev->dev, stq->mem_size,
+ stq->descs[i] - stq->addr_offset[i],
+ stq->paddr[i] - stq->addr_offset[i]);
+ }
+}
+
+static int slic_init_tx_queue(struct slic_device *sdev)
+{
+ struct slic_tx_queue *txq = &sdev->txq;
+ struct slic_tx_buffer *buff;
+ struct slic_tx_desc *desc;
+ int err;
+ int i;
+
+ txq->len = SLIC_NUM_TX_DESCS;
+ txq->put_idx = 0;
+ txq->done_idx = 0;
+
+ txq->txbuffs = kcalloc(txq->len, sizeof(*buff), GFP_KERNEL);
+ if (!txq->txbuffs)
+ return -ENOMEM;
+
+ txq->dma_pool = dma_pool_create("slic_pool", &sdev->pdev->dev,
+ sizeof(*desc), SLIC_TX_DESC_ALIGN,
+ 4096);
+ if (!txq->dma_pool) {
+ err = -ENOMEM;
+ netdev_err(sdev->netdev, "failed to create dma pool\n");
+ goto free_buffs;
+ }
+
+ for (i = 0; i < txq->len; i++) {
+ buff = &txq->txbuffs[i];
+ desc = dma_pool_zalloc(txq->dma_pool, GFP_KERNEL,
+ &buff->desc_paddr);
+ if (!desc) {
+ netdev_err(sdev->netdev,
+ "failed to alloc pool chunk (%i)\n", i);
+ err = -ENOMEM;
+ goto free_descs;
+ }
+
+ desc->hnd = cpu_to_le32((u32)(i + 1));
+ desc->cmd = SLIC_CMD_XMT_REQ;
+ desc->flags = 0;
+ desc->type = cpu_to_le32(SLIC_CMD_TYPE_DUMB);
+ buff->desc = desc;
+ }
+
+ return 0;
+
+free_descs:
+ while (i--) {
+ buff = &txq->txbuffs[i];
+ dma_pool_free(txq->dma_pool, buff->desc, buff->desc_paddr);
+ }
+ dma_pool_destroy(txq->dma_pool);
+
+free_buffs:
+ kfree(txq->txbuffs);
+
+ return err;
+}
+
+static void slic_free_tx_queue(struct slic_device *sdev)
+{
+ struct slic_tx_queue *txq = &sdev->txq;
+ struct slic_tx_buffer *buff;
+ int i;
+
+ for (i = 0; i < txq->len; i++) {
+ buff = &txq->txbuffs[i];
+ dma_pool_free(txq->dma_pool, buff->desc, buff->desc_paddr);
+ if (!buff->skb)
+ continue;
+
+ dma_unmap_single(&sdev->pdev->dev,
+ dma_unmap_addr(buff, map_addr),
+ dma_unmap_len(buff, map_len), DMA_TO_DEVICE);
+ consume_skb(buff->skb);
+ }
+ dma_pool_destroy(txq->dma_pool);
+
+ kfree(txq->txbuffs);
+}
+
+static int slic_init_rx_queue(struct slic_device *sdev)
+{
+ struct slic_rx_queue *rxq = &sdev->rxq;
+ struct slic_rx_buffer *buff;
+
+ rxq->len = SLIC_NUM_RX_LES;
+ rxq->done_idx = 0;
+ rxq->put_idx = 0;
+
+ buff = kcalloc(rxq->len, sizeof(*buff), GFP_KERNEL);
+ if (!buff)
+ return -ENOMEM;
+
+ rxq->rxbuffs = buff;
+ slic_refill_rx_queue(sdev, GFP_KERNEL);
+
+ return 0;
+}
+
+static void slic_free_rx_queue(struct slic_device *sdev)
+{
+ struct slic_rx_queue *rxq = &sdev->rxq;
+ struct slic_rx_buffer *buff;
+ int i;
+
+ /* free rx buffers */
+ for (i = 0; i < rxq->len; i++) {
+ buff = &rxq->rxbuffs[i];
+
+ if (!buff->skb)
+ continue;
+
+ dma_unmap_single(&sdev->pdev->dev,
+ dma_unmap_addr(buff, map_addr),
+ dma_unmap_len(buff, map_len),
+ DMA_FROM_DEVICE);
+ consume_skb(buff->skb);
+ }
+ kfree(rxq->rxbuffs);
+}
+
+static void slic_set_link_autoneg(struct slic_device *sdev)
+{
+ unsigned int subid = sdev->pdev->subsystem_device;
+ u32 val;
+
+ if (sdev->is_fiber) {
+ /* We've got a fiber gigabit interface, and register 4 is
+ * different in fiber mode than in copper mode.
+ */
+ /* advertise FD only @1000 Mb */
+ val = MII_ADVERTISE << 16 | ADVERTISE_1000XFULL |
+ ADVERTISE_1000XPAUSE | ADVERTISE_1000XPSE_ASYM;
+ /* enable PAUSE frames */
+ slic_write(sdev, SLIC_REG_WPHY, val);
+ /* reset phy, enable auto-neg */
+ val = MII_BMCR << 16 | BMCR_RESET | BMCR_ANENABLE |
+ BMCR_ANRESTART;
+ slic_write(sdev, SLIC_REG_WPHY, val);
+ } else { /* copper gigabit */
+ /* We've got a copper gigabit interface, and register 4 is
+ * different in copper mode than in fiber mode.
+ */
+ /* advertise 10/100 Mb modes */
+ val = MII_ADVERTISE << 16 | ADVERTISE_100FULL |
+ ADVERTISE_100HALF | ADVERTISE_10FULL | ADVERTISE_10HALF;
+ /* enable PAUSE frames */
+ val |= ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM;
+ /* required by the Cicada PHY */
+ val |= ADVERTISE_CSMA;
+ slic_write(sdev, SLIC_REG_WPHY, val);
+
+ /* advertise FD only @1000 Mb */
+ val = MII_CTRL1000 << 16 | ADVERTISE_1000FULL;
+ slic_write(sdev, SLIC_REG_WPHY, val);
+
+ if (subid != PCI_SUBDEVICE_ID_ALACRITECH_CICADA) {
+ /* if a Marvell PHY enable auto crossover */
+ val = SLIC_MIICR_REG_16 | SLIC_MRV_REG16_XOVERON;
+ slic_write(sdev, SLIC_REG_WPHY, val);
+
+ /* reset phy, enable auto-neg */
+ val = MII_BMCR << 16 | BMCR_RESET | BMCR_ANENABLE |
+ BMCR_ANRESTART;
+ slic_write(sdev, SLIC_REG_WPHY, val);
+ } else {
+ /* enable and restart auto-neg (don't reset) */
+ val = MII_BMCR << 16 | BMCR_ANENABLE | BMCR_ANRESTART;
+ slic_write(sdev, SLIC_REG_WPHY, val);
+ }
+ }
+ sdev->autoneg = true;
+}
+
+static void slic_set_mac_address(struct slic_device *sdev)
+{
+ u8 *addr = sdev->netdev->dev_addr;
+ u32 val;
+
+ val = addr[5] | addr[4] << 8 | addr[3] << 16 | addr[2] << 24;
+
+ slic_write(sdev, SLIC_REG_WRADDRAL, val);
+ slic_write(sdev, SLIC_REG_WRADDRBL, val);
+
+ val = addr[0] << 8 | addr[1];
+
+ slic_write(sdev, SLIC_REG_WRADDRAH, val);
+ slic_write(sdev, SLIC_REG_WRADDRBH, val);
+ slic_flush_write(sdev);
+}
+
+static u32 slic_read_dword_from_firmware(const struct firmware *fw, int *offset)
+{
+ int idx = *offset;
+ __le32 val;
+
+ memcpy(&val, fw->data + *offset, sizeof(val));
+ idx += 4;
+ *offset = idx;
+
+ return le32_to_cpu(val);
+}
+
+MODULE_FIRMWARE(SLIC_RCV_FIRMWARE_MOAVE);
+MODULE_FIRMWARE(SLIC_RCV_FIRMWARE_OASIS);
+
+static int slic_load_rcvseq_firmware(struct slic_device *sdev)
+{
+ const struct firmware *fw;
+ const char *file;
+ u32 codelen;
+ int idx = 0;
+ u32 instr;
+ u32 addr;
+ int err;
+
+ file = (sdev->model == SLIC_MODEL_OASIS) ? SLIC_RCV_FIRMWARE_OASIS :
+ SLIC_RCV_FIRMWARE_MOAVE;
+ err = request_firmware(&fw, file, &sdev->pdev->dev);
+ if (err) {
+ dev_err(&sdev->pdev->dev,
+ "failed to load receive sequencer firmware %s\n", file);
+ return err;
+ }
+ /* Do an initial sanity check concerning firmware size now. A further
+ * check follows below.
+ */
+ if (fw->size < SLIC_FIRMWARE_MIN_SIZE) {
+ dev_err(&sdev->pdev->dev,
+ "invalid firmware size %zu (min %u expected)\n",
+ fw->size, SLIC_FIRMWARE_MIN_SIZE);
+ err = -EINVAL;
+ goto release;
+ }
+
+ codelen = slic_read_dword_from_firmware(fw, &idx);
+
+ /* do another sanity check against firmware size */
+ if ((codelen + 4) > fw->size) {
+ dev_err(&sdev->pdev->dev,
+ "invalid rcv-sequencer firmware size %zu\n", fw->size);
+ err = -EINVAL;
+ goto release;
+ }
+
+ /* download sequencer code to card */
+ slic_write(sdev, SLIC_REG_RCV_WCS, SLIC_RCVWCS_BEGIN);
+ for (addr = 0; addr < codelen; addr++) {
+ __le32 val;
+ /* write out instruction address */
+ slic_write(sdev, SLIC_REG_RCV_WCS, addr);
+
+ instr = slic_read_dword_from_firmware(fw, &idx);
+ /* write out the instruction data low addr */
+ slic_write(sdev, SLIC_REG_RCV_WCS, instr);
+
+ val = (__le32)fw->data[idx];
+ instr = le32_to_cpu(val);
+ idx++;
+ /* write out the instruction data high addr */
+ slic_write(sdev, SLIC_REG_RCV_WCS, instr);
+ }
+ /* finish download */
+ slic_write(sdev, SLIC_REG_RCV_WCS, SLIC_RCVWCS_FINISH);
+ slic_flush_write(sdev);
+release:
+ release_firmware(fw);
+
+ return 0;
+}
+
+MODULE_FIRMWARE(SLIC_FIRMWARE_MOAVE);
+MODULE_FIRMWARE(SLIC_FIRMWARE_OASIS);
+
+static int slic_load_firmware(struct slic_device *sdev)
+{
+ u32 sectstart[SLIC_FIRMWARE_MAX_SECTIONS];
+ u32 sectsize[SLIC_FIRMWARE_MAX_SECTIONS];
+ const struct firmware *fw;
+ unsigned int datalen;
+ const char *file;
+ int code_start;
+ u32 numsects;
+ int idx = 0;
+ u32 sect;
+ u32 instr;
+ u32 addr;
+ u32 base;
+ int err;
+ int i;
+
+ file = (sdev->model == SLIC_MODEL_OASIS) ? SLIC_FIRMWARE_OASIS :
+ SLIC_FIRMWARE_MOAVE;
+ err = request_firmware(&fw, file, &sdev->pdev->dev);
+ if (err) {
+ dev_err(&sdev->pdev->dev, "failed to load firmware %s\n", file);
+ return err;
+ }
+ /* Do an initial sanity check concerning firmware size now. A further
+ * check follows below.
+ */
+ if (fw->size < SLIC_FIRMWARE_MIN_SIZE) {
+ dev_err(&sdev->pdev->dev,
+ "invalid firmware size %zu (min is %u)\n", fw->size,
+ SLIC_FIRMWARE_MIN_SIZE);
+ err = -EINVAL;
+ goto release;
+ }
+
+ numsects = slic_read_dword_from_firmware(fw, &idx);
+ if (numsects == 0 || numsects > SLIC_FIRMWARE_MAX_SECTIONS) {
+ dev_err(&sdev->pdev->dev,
+ "invalid number of sections in firmware: %u", numsects);
+ err = -EINVAL;
+ goto release;
+ }
+
+ datalen = numsects * 8 + 4;
+ for (i = 0; i < numsects; i++) {
+ sectsize[i] = slic_read_dword_from_firmware(fw, &idx);
+ datalen += sectsize[i];
+ }
+
+ /* do another sanity check against firmware size */
+ if (datalen > fw->size) {
+ dev_err(&sdev->pdev->dev,
+ "invalid firmware size %zu (expected >= %u)\n",
+ fw->size, datalen);
+ err = -EINVAL;
+ goto release;
+ }
+ /* get sections */
+ for (i = 0; i < numsects; i++)
+ sectstart[i] = slic_read_dword_from_firmware(fw, &idx);
+
+ code_start = idx;
+ instr = slic_read_dword_from_firmware(fw, &idx);
+
+ for (sect = 0; sect < numsects; sect++) {
+ unsigned int ssize = sectsize[sect] >> 3;
+
+ base = sectstart[sect];
+
+ for (addr = 0; addr < ssize; addr++) {
+ /* write out instruction address */
+ slic_write(sdev, SLIC_REG_WCS, base + addr);
+ /* write out instruction to low addr */
+ slic_write(sdev, SLIC_REG_WCS, instr);
+ instr = slic_read_dword_from_firmware(fw, &idx);
+ /* write out instruction to high addr */
+ slic_write(sdev, SLIC_REG_WCS, instr);
+ instr = slic_read_dword_from_firmware(fw, &idx);
+ }
+ }
+
+ idx = code_start;
+
+ for (sect = 0; sect < numsects; sect++) {
+ unsigned int ssize = sectsize[sect] >> 3;
+
+ instr = slic_read_dword_from_firmware(fw, &idx);
+ base = sectstart[sect];
+ if (base < 0x8000)
+ continue;
+
+ for (addr = 0; addr < ssize; addr++) {
+ /* write out instruction address */
+ slic_write(sdev, SLIC_REG_WCS,
+ SLIC_WCS_COMPARE | (base + addr));
+ /* write out instruction to low addr */
+ slic_write(sdev, SLIC_REG_WCS, instr);
+ instr = slic_read_dword_from_firmware(fw, &idx);
+ /* write out instruction to high addr */
+ slic_write(sdev, SLIC_REG_WCS, instr);
+ instr = slic_read_dword_from_firmware(fw, &idx);
+ }
+ }
+ slic_flush_write(sdev);
+ mdelay(10);
+ /* everything OK, kick off the card */
+ slic_write(sdev, SLIC_REG_WCS, SLIC_WCS_START);
+ slic_flush_write(sdev);
+ /* wait long enough for ucode to init card and reach the mainloop */
+ mdelay(20);
+release:
+ release_firmware(fw);
+
+ return err;
+}
+
+static int slic_init_shmem(struct slic_device *sdev)
+{
+ struct slic_shmem *sm = &sdev->shmem;
+ struct slic_shmem_data *sm_data;
+ dma_addr_t paddr;
+
+ sm_data = dma_zalloc_coherent(&sdev->pdev->dev, sizeof(*sm_data),
+ &paddr, GFP_KERNEL);
+ if (!sm_data) {
+ dev_err(&sdev->pdev->dev, "failed to allocate shared memory\n");
+ return -ENOMEM;
+ }
+
+ sm->shmem_data = sm_data;
+ sm->isr_paddr = paddr;
+ sm->link_paddr = paddr + offsetof(struct slic_shmem_data, link);
+
+ return 0;
+}
+
+static void slic_free_shmem(struct slic_device *sdev)
+{
+ struct slic_shmem *sm = &sdev->shmem;
+ struct slic_shmem_data *sm_data = sm->shmem_data;
+
+ dma_free_coherent(&sdev->pdev->dev, sizeof(*sm_data), sm_data,
+ sm->isr_paddr);
+}
+
+static int slic_init_iface(struct slic_device *sdev)
+{
+ struct slic_shmem *sm = &sdev->shmem;
+ int err;
+
+ sdev->upr_list.pending = false;
+
+ err = slic_init_shmem(sdev);
+ if (err) {
+ netdev_err(sdev->netdev, "failed to load firmware\n");
+ return err;
+ }
+
+ err = slic_load_firmware(sdev);
+ if (err) {
+ netdev_err(sdev->netdev, "failed to load firmware\n");
+ goto free_sm;
+ }
+
+ err = slic_load_rcvseq_firmware(sdev);
+ if (err) {
+ netdev_err(sdev->netdev,
+ "failed to load firmware for receive sequencer\n");
+ goto free_sm;
+ }
+
+ slic_write(sdev, SLIC_REG_ICR, SLIC_ICR_INT_OFF);
+ slic_flush_write(sdev);
+ mdelay(1);
+
+ err = slic_init_rx_queue(sdev);
+ if (err) {
+ netdev_err(sdev->netdev, "failed to init rx queue: %u\n", err);
+ goto free_sm;
+ }
+
+ err = slic_init_tx_queue(sdev);
+ if (err) {
+ netdev_err(sdev->netdev, "failed to init tx queue: %u\n", err);
+ goto free_rxq;
+ }
+
+ err = slic_init_stat_queue(sdev);
+ if (err) {
+ netdev_err(sdev->netdev, "failed to init status queue: %u\n",
+ err);
+ goto free_txq;
+ }
+
+ slic_write(sdev, SLIC_REG_ISP, lower_32_bits(sm->isr_paddr));
+ napi_enable(&sdev->napi);
+ /* disable irq mitigation */
+ slic_write(sdev, SLIC_REG_INTAGG, 0);
+ slic_write(sdev, SLIC_REG_ISR, 0);
+ slic_flush_write(sdev);
+
+ slic_set_mac_address(sdev);
+
+ spin_lock_bh(&sdev->link_lock);
+ sdev->duplex = DUPLEX_UNKNOWN;
+ sdev->speed = SPEED_UNKNOWN;
+ spin_unlock_bh(&sdev->link_lock);
+
+ slic_set_link_autoneg(sdev);
+
+ err = request_irq(sdev->pdev->irq, slic_irq, IRQF_SHARED, DRV_NAME,
+ sdev);
+ if (err) {
+ netdev_err(sdev->netdev, "failed to request irq: %u\n", err);
+ goto disable_napi;
+ }
+
+ slic_write(sdev, SLIC_REG_ICR, SLIC_ICR_INT_ON);
+ slic_flush_write(sdev);
+ /* request initial link status */
+ err = slic_handle_link_change(sdev);
+ if (err)
+ netdev_warn(sdev->netdev,
+ "failed to set initial link state: %u\n", err);
+ return 0;
+
+disable_napi:
+ napi_disable(&sdev->napi);
+ slic_free_stat_queue(sdev);
+free_txq:
+ slic_free_tx_queue(sdev);
+free_rxq:
+ slic_free_rx_queue(sdev);
+free_sm:
+ slic_free_shmem(sdev);
+ slic_card_reset(sdev);
+
+ return err;
+}
+
+static int slic_open(struct net_device *dev)
+{
+ struct slic_device *sdev = netdev_priv(dev);
+ int err;
+
+ netif_carrier_off(dev);
+
+ err = slic_init_iface(sdev);
+ if (err) {
+ netdev_err(dev, "failed to initialize interface: %i\n", err);
+ return err;
+ }
+
+ netif_start_queue(dev);
+
+ return 0;
+}
+
+static int slic_close(struct net_device *dev)
+{
+ struct slic_device *sdev = netdev_priv(dev);
+ u32 val;
+
+ netif_stop_queue(dev);
+
+ /* stop irq handling */
+ napi_disable(&sdev->napi);
+ slic_write(sdev, SLIC_REG_ICR, SLIC_ICR_INT_OFF);
+ slic_write(sdev, SLIC_REG_ISR, 0);
+ slic_flush_write(sdev);
+
+ free_irq(sdev->pdev->irq, sdev);
+ /* turn off RCV and XMT and power down PHY */
+ val = SLIC_GXCR_RESET | SLIC_GXCR_PAUSEEN;
+ slic_write(sdev, SLIC_REG_WXCFG, val);
+
+ val = SLIC_GRCR_RESET | SLIC_GRCR_CTLEN | SLIC_GRCR_ADDRAEN |
+ SLIC_GRCR_HASHSIZE << SLIC_GRCR_HASHSIZE_SHIFT;
+ slic_write(sdev, SLIC_REG_WRCFG, val);
+
+ val = MII_BMCR << 16 | BMCR_PDOWN;
+ slic_write(sdev, SLIC_REG_WPHY, val);
+ slic_flush_write(sdev);
+
+ slic_clear_upr_list(&sdev->upr_list);
+ slic_write(sdev, SLIC_REG_QUIESCE, 0);
+
+ slic_free_stat_queue(sdev);
+ slic_free_tx_queue(sdev);
+ slic_free_rx_queue(sdev);
+ slic_free_shmem(sdev);
+
+ slic_card_reset(sdev);
+ netif_carrier_off(dev);
+
+ return 0;
+}
+
+static netdev_tx_t slic_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+ struct slic_device *sdev = netdev_priv(dev);
+ struct slic_tx_queue *txq = &sdev->txq;
+ struct slic_tx_buffer *buff;
+ struct slic_tx_desc *desc;
+ dma_addr_t paddr;
+ u32 cbar_val;
+ u32 maplen;
+
+ if (unlikely(slic_get_free_tx_descs(txq) < SLIC_MAX_REQ_TX_DESCS)) {
+ netdev_err(dev, "BUG! not enought tx LEs left: %u\n",
+ slic_get_free_tx_descs(txq));
+ return NETDEV_TX_BUSY;
+ }
+
+ maplen = skb_headlen(skb);
+ paddr = dma_map_single(&sdev->pdev->dev, skb->data, maplen,
+ DMA_TO_DEVICE);
+ if (dma_mapping_error(&sdev->pdev->dev, paddr)) {
+ netdev_err(dev, "failed to map tx buffer\n");
+ goto drop_skb;
+ }
+
+ buff = &txq->txbuffs[txq->put_idx];
+ buff->skb = skb;
+ dma_unmap_addr_set(buff, map_addr, paddr);
+ dma_unmap_len_set(buff, map_len, maplen);
+
+ desc = buff->desc;
+ desc->totlen = cpu_to_le32(maplen);
+ desc->paddrl = cpu_to_le32(lower_32_bits(paddr));
+ desc->paddrh = cpu_to_le32(upper_32_bits(paddr));
+ desc->len = cpu_to_le32(maplen);
+
+ txq->put_idx = slic_next_queue_idx(txq->put_idx, txq->len);
+
+ cbar_val = lower_32_bits(buff->desc_paddr) | 1;
+ /* complete writes to RAM and DMA before hardware is informed */
+ wmb();
+
+ slic_write(sdev, SLIC_REG_CBAR, cbar_val);
+
+ if (slic_get_free_tx_descs(txq) < SLIC_MAX_REQ_TX_DESCS)
+ netif_stop_queue(dev);
+ /* make sure writes to io-memory cant leak out of tx queue lock */
+ mmiowb();
+
+ return NETDEV_TX_OK;
+drop_skb:
+ dev_kfree_skb_any(skb);
+
+ return NETDEV_TX_OK;
+}
+
+static struct rtnl_link_stats64 *slic_get_stats(struct net_device *dev,
+ struct rtnl_link_stats64 *lst)
+{
+ struct slic_device *sdev = netdev_priv(dev);
+ struct slic_stats *stats = &sdev->stats;
+
+ SLIC_GET_STATS_COUNTER(lst->rx_packets, stats, rx_packets);
+ SLIC_GET_STATS_COUNTER(lst->tx_packets, stats, tx_packets);
+ SLIC_GET_STATS_COUNTER(lst->rx_bytes, stats, rx_bytes);
+ SLIC_GET_STATS_COUNTER(lst->tx_bytes, stats, tx_bytes);
+ SLIC_GET_STATS_COUNTER(lst->rx_errors, stats, rx_errors);
+ SLIC_GET_STATS_COUNTER(lst->rx_dropped, stats, rx_buff_miss);
+ SLIC_GET_STATS_COUNTER(lst->tx_dropped, stats, tx_dropped);
+ SLIC_GET_STATS_COUNTER(lst->multicast, stats, rx_mcasts);
+ SLIC_GET_STATS_COUNTER(lst->rx_over_errors, stats, rx_buffoflow);
+ SLIC_GET_STATS_COUNTER(lst->rx_crc_errors, stats, rx_crc);
+ SLIC_GET_STATS_COUNTER(lst->rx_fifo_errors, stats, rx_oflow802);
+ SLIC_GET_STATS_COUNTER(lst->tx_carrier_errors, stats, tx_carrier);
+
+ return lst;
+}
+
+static int slic_get_sset_count(struct net_device *dev, int sset)
+{
+ switch (sset) {
+ case ETH_SS_STATS:
+ return ARRAY_SIZE(slic_stats_strings);
+ default:
+ return -EOPNOTSUPP;
+ }
+}
+
+static void slic_get_ethtool_stats(struct net_device *dev,
+ struct ethtool_stats *eth_stats, u64 *data)
+{
+ struct slic_device *sdev = netdev_priv(dev);
+ struct slic_stats *stats = &sdev->stats;
+
+ SLIC_GET_STATS_COUNTER(data[0], stats, rx_packets);
+ SLIC_GET_STATS_COUNTER(data[1], stats, rx_bytes);
+ SLIC_GET_STATS_COUNTER(data[2], stats, rx_mcasts);
+ SLIC_GET_STATS_COUNTER(data[3], stats, rx_errors);
+ SLIC_GET_STATS_COUNTER(data[4], stats, rx_buff_miss);
+ SLIC_GET_STATS_COUNTER(data[5], stats, rx_tpcsum);
+ SLIC_GET_STATS_COUNTER(data[6], stats, rx_tpoflow);
+ SLIC_GET_STATS_COUNTER(data[7], stats, rx_tphlen);
+ SLIC_GET_STATS_COUNTER(data[8], stats, rx_ipcsum);
+ SLIC_GET_STATS_COUNTER(data[9], stats, rx_iplen);
+ SLIC_GET_STATS_COUNTER(data[10], stats, rx_iphlen);
+ SLIC_GET_STATS_COUNTER(data[11], stats, rx_early);
+ SLIC_GET_STATS_COUNTER(data[12], stats, rx_buffoflow);
+ SLIC_GET_STATS_COUNTER(data[13], stats, rx_lcode);
+ SLIC_GET_STATS_COUNTER(data[14], stats, rx_drbl);
+ SLIC_GET_STATS_COUNTER(data[15], stats, rx_crc);
+ SLIC_GET_STATS_COUNTER(data[16], stats, rx_oflow802);
+ SLIC_GET_STATS_COUNTER(data[17], stats, rx_uflow802);
+ SLIC_GET_STATS_COUNTER(data[18], stats, tx_packets);
+ SLIC_GET_STATS_COUNTER(data[19], stats, tx_bytes);
+ SLIC_GET_STATS_COUNTER(data[20], stats, tx_carrier);
+ SLIC_GET_STATS_COUNTER(data[21], stats, tx_dropped);
+ SLIC_GET_STATS_COUNTER(data[22], stats, irq_errs);
+}
+
+static void slic_get_strings(struct net_device *dev, u32 stringset, u8 *data)
+{
+ if (stringset == ETH_SS_STATS) {
+ memcpy(data, slic_stats_strings, sizeof(slic_stats_strings));
+ data += sizeof(slic_stats_strings);
+ }
+}
+
+static void slic_get_drvinfo(struct net_device *dev,
+ struct ethtool_drvinfo *info)
+{
+ struct slic_device *sdev = netdev_priv(dev);
+
+ strlcpy(info->driver, DRV_NAME, sizeof(info->driver));
+ strlcpy(info->version, DRV_VERSION, sizeof(info->version));
+ strlcpy(info->bus_info, pci_name(sdev->pdev), sizeof(info->bus_info));
+}
+
+static const struct ethtool_ops slic_ethtool_ops = {
+ .get_drvinfo = slic_get_drvinfo,
+ .get_link = ethtool_op_get_link,
+ .get_strings = slic_get_strings,
+ .get_ethtool_stats = slic_get_ethtool_stats,
+ .get_sset_count = slic_get_sset_count,
+};
+
+static const struct net_device_ops slic_netdev_ops = {
+ .ndo_open = slic_open,
+ .ndo_stop = slic_close,
+ .ndo_start_xmit = slic_xmit,
+ .ndo_set_mac_address = eth_mac_addr,
+ .ndo_get_stats64 = slic_get_stats,
+ .ndo_set_rx_mode = slic_set_rx_mode,
+ .ndo_change_mtu = eth_change_mtu,
+ .ndo_validate_addr = eth_validate_addr,
+};
+
+static u16 slic_eeprom_csum(unsigned char *eeprom, unsigned int len)
+{
+ unsigned char *ptr = eeprom;
+ u32 csum = 0;
+ __le16 data;
+
+ while (len > 1) {
+ memcpy(&data, ptr, sizeof(data));
+ csum += le16_to_cpu(data);
+ ptr += 2;
+ len -= 2;
+ }
+ if (len > 0)
+ csum += *(u8 *)ptr;
+ while (csum >> 16)
+ csum = (csum & 0xFFFF) + ((csum >> 16) & 0xFFFF);
+ return ~csum;
+}
+
+/* check eeprom size, magic and checksum */
+static bool slic_eeprom_valid(unsigned char *eeprom, unsigned int size)
+{
+ const unsigned int MAX_SIZE = 128;
+ const unsigned int MIN_SIZE = 98;
+ __le16 magic;
+ __le16 csum;
+
+ if (size < MIN_SIZE || size > MAX_SIZE)
+ return false;
+ memcpy(&magic, eeprom, sizeof(magic));
+ if (le16_to_cpu(magic) != SLIC_EEPROM_MAGIC)
+ return false;
+ /* cut checksum bytes */
+ size -= 2;
+ memcpy(&csum, eeprom + size, sizeof(csum));
+
+ return (le16_to_cpu(csum) == slic_eeprom_csum(eeprom, size));
+}
+
+static int slic_read_eeprom(struct slic_device *sdev)
+{
+ unsigned int devfn = PCI_FUNC(sdev->pdev->devfn);
+ struct slic_shmem *sm = &sdev->shmem;
+ struct slic_shmem_data *sm_data = sm->shmem_data;
+ const unsigned int MAX_LOOPS = 5000;
+ unsigned int codesize;
+ unsigned char *eeprom;
+ struct slic_upr *upr;
+ dma_addr_t paddr;
+ int err = 0;
+ u8 *mac[2];
+ int i = 0;
+
+ eeprom = dma_zalloc_coherent(&sdev->pdev->dev, SLIC_EEPROM_SIZE,
+ &paddr, GFP_KERNEL);
+ if (!eeprom)
+ return -ENOMEM;
+
+ slic_write(sdev, SLIC_REG_ICR, SLIC_ICR_INT_OFF);
+ /* setup ISP temporarily */
+ slic_write(sdev, SLIC_REG_ISP, lower_32_bits(sm->isr_paddr));
+
+ err = slic_new_upr(sdev, SLIC_UPR_CONFIG, paddr);
+ if (!err) {
+ for (i = 0; i < MAX_LOOPS; i++) {
+ if (le32_to_cpu(sm_data->isr) & SLIC_ISR_UPC)
+ break;
+ mdelay(1);
+ }
+ if (i == MAX_LOOPS) {
+ dev_err(&sdev->pdev->dev,
+ "timed out while waiting for eeprom data\n");
+ err = -ETIMEDOUT;
+ }
+ upr = slic_dequeue_upr(sdev);
+ kfree(upr);
+ }
+
+ slic_write(sdev, SLIC_REG_ISP, 0);
+ slic_write(sdev, SLIC_REG_ISR, 0);
+ slic_flush_write(sdev);
+
+ if (err)
+ goto free_eeprom;
+
+ if (sdev->model == SLIC_MODEL_OASIS) {
+ struct slic_oasis_eeprom *oee;
+
+ oee = (struct slic_oasis_eeprom *)eeprom;
+ mac[0] = oee->mac;
+ mac[1] = oee->mac2;
+ codesize = le16_to_cpu(oee->eeprom_code_size);
+ } else {
+ struct slic_mojave_eeprom *mee;
+
+ mee = (struct slic_mojave_eeprom *)eeprom;
+ mac[0] = mee->mac;
+ mac[1] = mee->mac2;
+ codesize = le16_to_cpu(mee->eeprom_code_size);
+ }
+
+ if (!slic_eeprom_valid(eeprom, codesize)) {
+ dev_err(&sdev->pdev->dev, "invalid checksum in eeprom\n");
+ err = -EINVAL;
+ goto free_eeprom;
+ }
+ /* set mac address */
+ ether_addr_copy(sdev->netdev->dev_addr, mac[devfn]);
+free_eeprom:
+ dma_free_coherent(&sdev->pdev->dev, SLIC_EEPROM_SIZE, eeprom, paddr);
+
+ return err;
+}
+
+static int slic_init(struct slic_device *sdev)
+{
+ int err;
+
+ spin_lock_init(&sdev->upper_lock);
+ spin_lock_init(&sdev->link_lock);
+ INIT_LIST_HEAD(&sdev->upr_list.list);
+ spin_lock_init(&sdev->upr_list.lock);
+ u64_stats_init(&sdev->stats.syncp);
+
+ slic_card_reset(sdev);
+
+ err = slic_load_firmware(sdev);
+ if (err) {
+ dev_err(&sdev->pdev->dev, "failed to load firmware\n");
+ return err;
+ }
+
+ /* we need the shared memory to read EEPROM so set it up temporarily */
+ err = slic_init_shmem(sdev);
+ if (err) {
+ dev_err(&sdev->pdev->dev, "failed to init shared memory\n");
+ return err;
+ }
+
+ err = slic_read_eeprom(sdev);
+ if (err) {
+ dev_err(&sdev->pdev->dev, "failed to read eeprom\n");
+ goto free_sm;
+ }
+
+ slic_card_reset(sdev);
+ slic_free_shmem(sdev);
+
+ return 0;
+free_sm:
+ slic_free_shmem(sdev);
+
+ return err;
+}
+
+static bool slic_is_fiber(unsigned short subdev)
+{
+ switch (subdev) {
+ /* Mojave */
+ case PCI_SUBDEVICE_ID_ALACRITECH_1000X1F: /* fallthrough */
+ case PCI_SUBDEVICE_ID_ALACRITECH_SES1001F: /* fallthrough */
+ /* Oasis */
+ case PCI_SUBDEVICE_ID_ALACRITECH_SEN2002XF: /* fallthrough */
+ case PCI_SUBDEVICE_ID_ALACRITECH_SEN2001XF: /* fallthrough */
+ case PCI_SUBDEVICE_ID_ALACRITECH_SEN2104EF: /* fallthrough */
+ case PCI_SUBDEVICE_ID_ALACRITECH_SEN2102EF: /* fallthrough */
+ return true;
+ }
+ return false;
+}
+
+static void slic_configure_pci(struct pci_dev *pdev)
+{
+ u16 old;
+ u16 cmd;
+
+ pci_read_config_word(pdev, PCI_COMMAND, &old);
+
+ cmd = old | PCI_COMMAND_PARITY | PCI_COMMAND_SERR;
+ if (old != cmd)
+ pci_write_config_word(pdev, PCI_COMMAND, cmd);
+}
+
+static int slic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+{
+ struct slic_device *sdev;
+ struct net_device *dev;
+ int err;
+
+ err = pci_enable_device(pdev);
+ if (err) {
+ dev_err(&pdev->dev, "failed to enable PCI device\n");
+ return err;
+ }
+
+ pci_set_master(pdev);
+ pci_try_set_mwi(pdev);
+
+ slic_configure_pci(pdev);
+
+ err = dma_set_mask(&pdev->dev, DMA_BIT_MASK(32));
+ if (err) {
+ dev_err(&pdev->dev, "failed to setup DMA\n");
+ goto disable;
+ }
+
+ dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32));
+
+ err = pci_request_regions(pdev, DRV_NAME);
+ if (err) {
+ dev_err(&pdev->dev, "failed to obtain PCI regions\n");
+ goto disable;
+ }
+
+ dev = alloc_etherdev(sizeof(*sdev));
+ if (!dev) {
+ dev_err(&pdev->dev, "failed to alloc ethernet device\n");
+ err = -ENOMEM;
+ goto free_regions;
+ }
+
+ SET_NETDEV_DEV(dev, &pdev->dev);
+ pci_set_drvdata(pdev, dev);
+ dev->irq = pdev->irq;
+ dev->netdev_ops = &slic_netdev_ops;
+ dev->hw_features = NETIF_F_RXCSUM;
+ dev->features |= dev->hw_features;
+
+ dev->ethtool_ops = &slic_ethtool_ops;
+
+ sdev = netdev_priv(dev);
+ sdev->model = (pdev->device == PCI_DEVICE_ID_ALACRITECH_OASIS) ?
+ SLIC_MODEL_OASIS : SLIC_MODEL_MOJAVE;
+ sdev->is_fiber = slic_is_fiber(pdev->subsystem_device);
+ sdev->pdev = pdev;
+ sdev->netdev = dev;
+ sdev->regs = ioremap_nocache(pci_resource_start(pdev, 0),
+ pci_resource_len(pdev, 0));
+ if (!sdev->regs) {
+ dev_err(&pdev->dev, "failed to map registers\n");
+ err = -ENOMEM;
+ goto free_netdev;
+ }
+
+ err = slic_init(sdev);
+ if (err) {
+ dev_err(&pdev->dev, "failed to initialize driver\n");
+ err = -ENOMEM;
+ goto unmap;
+ }
+
+ netif_napi_add(dev, &sdev->napi, slic_poll, SLIC_NAPI_WEIGHT);
+ netif_carrier_off(dev);
+
+ err = register_netdev(dev);
+ if (err) {
+ dev_err(&pdev->dev, "failed to register net device: %i\n",
+ err);
+ goto unmap;
+ }
+
+ return 0;
+
+unmap:
+ iounmap(sdev->regs);
+free_netdev:
+ free_netdev(dev);
+free_regions:
+ pci_release_regions(pdev);
+disable:
+ pci_disable_device(pdev);
+
+ return err;
+}
+
+static void slic_remove(struct pci_dev *pdev)
+{
+ struct net_device *dev = pci_get_drvdata(pdev);
+ struct slic_device *sdev = netdev_priv(dev);
+
+ unregister_netdev(dev);
+ iounmap(sdev->regs);
+ free_netdev(dev);
+ pci_release_regions(pdev);
+ pci_disable_device(pdev);
+}
+
+static struct pci_driver slic_driver = {
+ .name = DRV_NAME,
+ .id_table = slic_id_tbl,
+ .probe = slic_probe,
+ .remove = slic_remove,
+};
+
+static int __init slic_init_module(void)
+{
+ return pci_register_driver(&slic_driver);
+}
+
+static void __exit slic_cleanup_module(void)
+{
+ pci_unregister_driver(&slic_driver);
+}
+
+module_init(slic_init_module);
+module_exit(slic_cleanup_module);
+
+MODULE_DESCRIPTION("Alacritech non-accelerated SLIC driver");
+MODULE_AUTHOR("Lino Sanfilippo <LinoSanfilippo@gmx.de>");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(DRV_VERSION);
--
1.9.1
^ permalink raw reply related
* [PATCH v3 net-next 2/2] MAINTAINERS: add entry for slicoss ethernet driver
From: Lino Sanfilippo @ 2016-11-26 12:20 UTC (permalink / raw)
To: davem, charrer, liodot, gregkh, andrew
Cc: devel, netdev, Lino Sanfilippo, linux-kernel
In-Reply-To: <1480162850-8014-1-git-send-email-LinoSanfilippo@gmx.de>
Add myself as maintainer for the slicoss ethernet driver.
Signed-off-by: Lino Sanfilippo <LinoSanfilippo@gmx.de>
---
MAINTAINERS | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/MAINTAINERS b/MAINTAINERS
index 6781a3f..bb9af28 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -562,6 +562,11 @@ T: git git://linuxtv.org/anttip/media_tree.git
S: Maintained
F: drivers/media/usb/airspy/
+ALACRITECH GIGABIT ETHERNET DRIVER
+M: Lino Sanfilippo <LinoSanfilippo@gmx.de>
+S: Maintained
+F: drivers/net/ethernet/alacritech/*
+
ALCATEL SPEEDTOUCH USB DRIVER
M: Duncan Sands <duncan.sands@free.fr>
L: linux-usb@vger.kernel.org
--
1.9.1
^ permalink raw reply related
* Re: Gigabit ethernet driver for Alacritechs SLIC devices (v3)
From: Lino Sanfilippo @ 2016-11-26 12:36 UTC (permalink / raw)
To: davem, charrer, liodot, gregkh, andrew; +Cc: devel, netdev, linux-kernel
In-Reply-To: <1480162850-8014-1-git-send-email-LinoSanfilippo@gmx.de>
On 26.11.2016 13:20, Lino Sanfilippo wrote:
> v3:
> - dont add defines to pci.h but instead put it into the drivers header file
This should of course be "pci_ids.h".
Regards,
Lino
^ permalink raw reply
* Re: net: stmmac: Meson GXBB: attempting to execute userspace memory
From: Heinrich Schuchardt @ 2016-11-26 12:38 UTC (permalink / raw)
To: Martin Blumenstingl, Heinrich Schuchardt
Cc: Carlo Caione, Kevin Hilman, Alexandre Torgue, netdev, lkml,
linux-amlogic, Giuseppe Cavallaro, linux-arm-kernel
In-Reply-To: <CAFBinCChPSTGp-1sez7rzOa3dw3A6X863FpPmUcjntiQ3-+o+Q@mail.gmail.com>
On 11/26/2016 10:08 AM, Martin Blumenstingl wrote:
> Hello Heinrich,
>
> On Sat, Nov 26, 2016 at 8:53 AM, Heinrich Schuchardt
> <heinrich.schuchardt@gmx.de> wrote:
>> For Odroid C2 I have compiled kernel
>> 4.9.0-rc6-next-20161124-00001-gbf7e142
>> with one additional patch
>> https://github.com/xypron/kernel-odroid-c2/blob/master/patch/0001-stmmac-RTL8211F-Meson-GXBB-TX-throughput-problems.patch
>>
>> I repeatedly see faults like the one below:
> do you see the same errors with the RTL8211F patch *not* applied?
>
>> [ 2557.400796] Unhandled fault: synchronous external abort (0x92000010)
>> at 0x000040001e8ee4b0
>> [ 2557.952413] CPU: 0 PID: 22837 Comm: cc1 Tainted: G D
>> 4.9.0-rc6-next-20161124-00001-gbf7e142 #1
>> [ 2557.962062] Hardware name: Hardkernel ODROID-C2 (DT)
>> [ 2557.966980] task: ffff80006ddb7080 task.stack: ffff80006dd9c000
>> [ 2557.972846] PC is at 0x6a0d98
>> [ 2557.975776] LR is at 0x6a0e54
>> [ 2557.978709] pc : [<00000000006a0d98>] lr : [<00000000006a0e54>]
>> pstate: 80000000
>> [ 2557.986040] sp : 0000fffff3ee5f80
>> [ 2557.989318] x29: 0000fffff3ee5f80 x28: 000040000b3f1240
>> [ 2557.994578] x27: 00000000012a7000 x26: 000040000b3f1288
>> [ 2557.999840] x25: 0000000000f58f88 x24: 000040000b3f1240
>> [ 2558.005101] x23: 0000000000000000 x22: 0000000000000001
>> [ 2558.010362] x21: 0000000000000001 x20: 000040000b3f1250
>> [ 2558.015623] x19: 0000000000000054 x18: 0000000000000001
>> [ 2558.020885] x17: 0000400008acaa10 x16: 0000000001285050
>> [ 2558.026146] x15: 000040000ad96dc8 x14: 000000000000001f
>> [ 2558.031407] x13: 000040000b3f1270 x12: 000040000b3f1258
>> [ 2558.036668] x11: 0000000001347000 x10: 0000000000000661
>> [ 2558.041930] x9 : 0000000000000005 x8 : 0000000000000003
>> [ 2558.047191] x7 : 000040000b3f1240 x6 : 0000000020020033
>> [ 2558.052452] x5 : 000040000b402020 x4 : 000040000b3e1aa0
>> [ 2558.057713] x3 : 000000000000000c x2 : 0000000000000020
>> [ 2558.062974] x1 : 0000000000f45000 x0 : 0000000000000065
>> [ 2558.068235]
>> [ 2558.069712] Internal error: Attempting to execute userspace memory:
>> 8600000f [#7] PREEMPT SMP
>> [ 2558.078155] Modules linked in: meson_rng rng_core meson_gxbb_wdt
>> ip_tables x_tables ipv6 dwmac_generic realtek dwmac_meson8b
>> stmmac_platform stmmac
>> [ 2558.091267] CPU: 0 PID: 22837 Comm: cc1 Tainted: G D
>> 4.9.0-rc6-next-20161124-00001-gbf7e142 #1
>> [ 2558.100925] Hardware name: Hardkernel ODROID-C2 (DT)
>> [ 2558.105841] task: ffff80006ddb7080 task.stack: ffff80006dd9c000
>> [ 2558.111706] PC is at 0x6a0e54
>> [ 2558.114638] LR is at 0x6a0e54
>> [ 2558.117571] pc : [<00000000006a0e54>] lr : [<00000000006a0e54>]
>> pstate: 600003c5
>> [ 2558.124902] sp : ffff80006dd9fec0
>> [ 2558.128179] x29: 0000000000000000 x28: ffff80006ddb7080
>> [ 2558.133441] x27: 00000000012a7000 x26: 000040000b3f1288
>> [ 2558.138702] x25: 0000000000f58f88 x24: 000040000b3f1240
>> [ 2558.143963] x23: 0000000080000000 x22: 00000000006a0d98
>> [ 2558.149225] x21: ffffffffffffffff x20: 000080006e223000
>> [ 2558.154486] x19: 0000000000000000 x18: 0000000000000010
>> [ 2558.159747] x17: 0000400008acaa10 x16: 0000000001285050
>> [ 2558.165008] x15: ffff000088e91f07 x14: 0000000000000006
>> [ 2558.170270] x13: ffff000008e91f15 x12: 000000000000000f
>> [ 2558.175531] x11: 0000000000000002 x10: 00000000000002ea
>> [ 2558.180792] x9 : ffff80006dd9fb40 x8 : 0000000000010a8b
>> [ 2558.186053] x7 : 0000000000000000 x6 : 000000000000020e
>> [ 2558.191315] x5 : 00000000020f020e x4 : 0000000000000000
>> [ 2558.196576] x3 : 0000000000000000 x2 : 000000000000020f
>> [ 2558.201837] x1 : ffff80006ddb7080 x0 : 0000000000000000
>> [ 2558.207098]
>> [ 2558.208565] Process cc1 (pid: 22837, stack limit = 0xffff80006dd9c000)
>> [ 2558.215035] Stack: (0xffff80006dd9fec0 to 0xffff80006dda0000)
>> [ 2558.220728] fec0: 0000000000000065 0000000000f45000 0000000000000020
>> 000000000000000c
>> [ 2558.228490] fee0: 000040000b3e1aa0 000040000b402020 0000000020020033
>> 000040000b3f1240
>> [ 2558.236253] ff00: 0000000000000003 0000000000000005 0000000000000661
>> 0000000001347000
>> [ 2558.244015] ff20: 000040000b3f1258 000040000b3f1270 000000000000001f
>> 000040000ad96dc8
>> [ 2558.251778] ff40: 0000000001285050 0000400008acaa10 0000000000000001
>> 0000000000000054
>> [ 2558.259540] ff60: 000040000b3f1250 0000000000000001 0000000000000001
>> 0000000000000000
>> [ 2558.267303] ff80: 000040000b3f1240 0000000000f58f88 000040000b3f1288
>> 00000000012a7000
>> [ 2558.275065] ffa0: 000040000b3f1240 0000fffff3ee5f80 00000000006a0e54
>> 0000fffff3ee5f80
>> [ 2558.282828] ffc0: 00000000006a0d98 0000000080000000 0000000000000003
>> ffffffffffffffff
>> [ 2558.290590] ffe0: 0000000000000000 0000000000000000 0000000000000000
>> 0000000000000000
>> [ 2558.298351] Call trace:
>> [ 2558.300769] Exception stack(0xffff80006dd9fcf0 to 0xffff80006dd9fe20)
>> [ 2558.307149] fce0: 0000000000000000
>> 0001000000000000
>> [ 2558.314913] fd00: ffff80006dd9fec0 00000000006a0e54 ffff800073acf500
>> 0000000000000004
>> [ 2558.322675] fd20: 0000000000000000 ffff000008dbbc18 ffff80006ddb7080
>> 000000006dd9fdd0
>> [ 2558.330438] fd40: ffff80006dd9fd90 ffff0000080ca878 ffff80006dd9fe40
>> ffff80006ddb7080
>> [ 2558.338200] fd60: 0000000000000004 00000000000003c0 ffff80006dd9fe40
>> 000040000b3f1240
>> [ 2558.345963] fd80: 0000000000f58f88 000040000b3f1288 0000000000000000
>> ffff80006ddb7080
>> [ 2558.353725] fda0: 000000000000020f 0000000000000000 0000000000000000
>> 00000000020f020e
>> [ 2558.361487] fdc0: 000000000000020e 0000000000000000 0000000000010a8b
>> ffff80006dd9fb40
>> [ 2558.369250] fde0: 00000000000002ea 0000000000000002 000000000000000f
>> ffff000008e91f15
>> [ 2558.377012] fe00: 0000000000000006 ffff000088e91f07 0000000001285050
>> 0000400008acaa10
>> [ 2558.384775] [<00000000006a0e54>] 0x6a0e54
>> [ 2558.388743] Code: d503201f f9400280 2a1703e1 97ffff0a (aa0003f3)
>> [ 2558.395241] ---[ end trace 7d280955c14d4ff1 ]---
>> [ 2558.584022] Bad mode in Error handler detected on CPU0, code
>> 0xbf000000 -- SError
>> [ 2558.585871] CPU: 0 PID: 22867 Comm: cc1 Tainted: G D
>> 4.9.0-rc6-next-20161124-00001-gbf7e142 #1
>> [ 2558.595527] Hardware name: Hardkernel ODROID-C2 (DT)
>> [ 2558.600444] task: ffff80007454d780 task.stack: ffff8000660bc000
>> [ 2558.606310] PC is at 0x631928
>> [ 2558.609240] LR is at 0xb59ce0
>> [ 2558.612172] pc : [<0000000000631928>] lr : [<0000000000b59ce0>]
>> pstate: 80000000
>> [ 2558.619503] sp : 0000ffffed764d90
>> [ 2558.622782] x29: 0000ffffed764d90 x28: 0000000000000028
>> [ 2558.628042] x27: 000000001a1062f0 x26: 0000000001299198
>> [ 2558.633303] x25: 0000000000000001 x24: 0000000000000000
>> [ 2558.638564] x23: 0000000000000004 x22: 00000000013513c8
>> [ 2558.643825] x21: 0000400039d43488 x20: 0000000000000000
>> [ 2558.649086] x19: 0000400039d2d730 x18: 0000000000000000
>> [ 2558.654348] x17: 0000400039a7c378 x16: 0000000001285138
>> [ 2558.659609] x15: 0000000000000001 x14: 0000000000000000
>> [ 2558.664870] x13: ffffff0000000000 x12: 0000000000000000
>> [ 2558.670131] x11: 0000000000000028 x10: 000000000129b2b8
>> [ 2558.675393] x9 : 0000000000000041 x8 : 0000000000000003
>> [ 2558.680654] x7 : 0000000000000050 x6 : 000000000003d2c8
>> [ 2558.685915] x5 : 0000000000000002 x4 : 0000000000000004
>> [ 2558.691176] x3 : 0000000000000003 x2 : 0000000001349000
>> [ 2558.696438] x1 : 000000000003cb90 x0 : 0000400039d45050
>> [ 2558.701699]
>> [ 2558.703177] Internal error: Attempting to execute userspace memory:
>> 8600000f [#8] PREEMPT SMP
>> [ 2558.711618] Modules linked in: meson_rng rng_core meson_gxbb_wdt
>> ip_tables x_tables ipv6 dwmac_generic realtek dwmac_meson8b
>> stmmac_platform stmmac
>> [ 2558.724731] CPU: 0 PID: 22867 Comm: cc1 Tainted: G D
>> 4.9.0-rc6-next-20161124-00001-gbf7e142 #1
>> [ 2558.734388] Hardware name: Hardkernel ODROID-C2 (DT)
>> [ 2558.739304] task: ffff80007454d780 task.stack: ffff8000660bc000
>> [ 2558.745169] PC is at 0xb59ce0
>> [ 2558.748102] LR is at 0xb59ce0
>> [ 2558.751035] pc : [<0000000000b59ce0>] lr : [<0000000000b59ce0>]
>> pstate: 600003c5
>> [ 2558.758365] sp : ffff8000660bfec0
>> [ 2558.761643] x29: 0000000000000000 x28: ffff80007454d780
>> [ 2558.766904] x27: 000000001a1062f0 x26: 0000000001299198
>> [ 2558.772165] x25: 0000000000000001 x24: 0000000000000000
>> [ 2558.777426] x23: 0000000080000000 x22: 0000000000631928
>> [ 2558.782688] x21: ffffffffffffffff x20: 000080006e223000
>> [ 2558.787949] x19: 0000000000000000 x18: 0000000000000010
>> [ 2558.793210] x17: 0000400039a7c378 x16: 0000000001285138
>> [ 2558.798471] x15: ffff000088e91f07 x14: 0000000000000006
>> [ 2558.803733] x13: ffff000008e91f15 x12: 000000000000000f
>> [ 2558.808994] x11: 0000000000000002 x10: 0000000000000336
>> [ 2558.814255] x9 : ffff8000660bfb40 x8 : 00000000000ab503
>> [ 2558.819516] x7 : 0000000000000000 x6 : 00000000000000dd
>> [ 2558.824778] x5 : 0000000000de00dd x4 : 0000000000000000
>> [ 2558.830039] x3 : 0000000000000000 x2 : 00000000000000de
>> [ 2558.835300] x1 : ffff80007454d780 x0 : 0000000000000000
>> [ 2558.840561]
>> [ 2558.842029] Process cc1 (pid: 22867, stack limit = 0xffff8000660bc000)
>> [ 2558.848498] Stack: (0xffff8000660bfec0 to 0xffff8000660c0000)
>> [ 2558.854191] fec0: 0000400039d45050 000000000003cb90 0000000001349000
>> 0000000000000003
>> [ 2558.861953] fee0: 0000000000000004 0000000000000002 000000000003d2c8
>> 0000000000000050
>> [ 2558.869716] ff00: 0000000000000003 0000000000000041 000000000129b2b8
>> 0000000000000028
>> [ 2558.877478] ff20: 0000000000000000 ffffff0000000000 0000000000000000
>> 0000000000000001
>> [ 2558.885241] ff40: 0000000001285138 0000400039a7c378 0000000000000000
>> 0000400039d2d730
>> [ 2558.893003] ff60: 0000000000000000 0000400039d43488 00000000013513c8
>> 0000000000000004
>> [ 2558.900766] ff80: 0000000000000000 0000000000000001 0000000001299198
>> 000000001a1062f0
>> [ 2558.908529] ffa0: 0000000000000028 0000ffffed764d90 0000000000b59ce0
>> 0000ffffed764d90
>> [ 2558.916291] ffc0: 0000000000631928 0000000080000000 000000001a18c000
>> ffffffffffffffff
>> [ 2558.924053] ffe0: 0000000000000000 0000000000000000 0000000000000000
>> 0000000000000000
>> [ 2558.931814] Call trace:
>> [ 2558.934232] Exception stack(0xffff8000660bfcf0 to 0xffff8000660bfe20)
>> [ 2558.940613] fce0: 0000000000000000
>> 0001000000000000
>> [ 2558.948376] fd00: ffff8000660bfec0 0000000000b59ce0 ffff800073acf640
>> 0000000000000004
>> [ 2558.956138] fd20: 0000000000000000 ffff000008dbbc18 ffff80007454d780
>> 00000000660bfdd0
>> [ 2558.963901] fd40: ffff8000660bfd90 ffff0000080ca878 ffff8000660bfe40
>> ffff80007454d780
>> [ 2558.971663] fd60: 0000000000000004 00000000000003c0 ffff8000660bfe40
>> 0000000000000000
>> [ 2558.979426] fd80: 0000000000000001 0000000001299198 0000000000000000
>> ffff80007454d780
>> [ 2558.987188] fda0: 00000000000000de 0000000000000000 0000000000000000
>> 0000000000de00dd
>> [ 2558.994951] fdc0: 00000000000000dd 0000000000000000 00000000000ab503
>> ffff8000660bfb40
>> [ 2559.002713] fde0: 0000000000000336 0000000000000002 000000000000000f
>> ffff000008e91f15
>> [ 2559.010476] fe00: 0000000000000006 ffff000088e91f07 0000000001285138
>> 0000400039a7c378
>> [ 2559.018238] [<0000000000b59ce0>] 0xb59ce0
>> [ 2559.022207] Code: d2800001 d2800002 d2800500 97eb5e9d (a9007c1f)
>> [ 2559.028376] ---[ end trace 7d280955c14d4ff2 ]---
>> [ 2559.034397] Bad mode in Error handler detected on CPU2, code
>> 0xbf000000 -- SError
>> [ 2559.040235] CPU: 2 PID: 22866 Comm: gcc Tainted: G D
>> 4.9.0-rc6-next-20161124-00001-gbf7e142 #1
>> [ 2559.049892] Hardware name: Hardkernel ODROID-C2 (DT)
>> [ 2559.054808] task: ffff80007454e400 task.stack: ffff80006de9c000
>> [ 2559.060674] PC is at 0x40003c0400d8
>> [ 2559.064122] LR is at 0x46d4e0
>> [ 2559.067055] pc : [<000040003c0400d8>] lr : [<000000000046d4e0>]
>> pstate: 80000000
>> [ 2559.074385] sp : 0000ffffe6387270
>> [ 2559.077664] x29: 0000ffffe6387270 x28: 0000000016c0ff90
>> [ 2559.082924] x27: 0000000000000002 x26: 0000000000000001
>> [ 2559.088185] x25: 0000ffffe63873f4 x24: 0000ffffe63873f8
>> [ 2559.093447] x23: 0000ffffe63873f4 x22: 0000ffffe63873f8
>> [ 2559.098708] x21: 0000000016c104e0 x20: 0000000000005953
>> [ 2559.103969] x19: 0000000000000000 [ 2559.107102] Unhandled fault:
>> synchronous external abort (0x96000010) at 0xffff800000c1e000
>> [ 2559.107108] Internal error: : 96000010 [#9] PREEMPT SMP
>> [ 2559.107110] Modules linked in:
>> [ 2559.107113] meson_rng rng_core meson_gxbb_wdt ip_tables x_tables
>> ipv6 dwmac_generic realtek dwmac_meson8b stmmac_platform stmmac[
>> 2559.107131] CPU: 0 PID: 1124 Comm: mmcqd/1 Tainted: G D 1
>> [ 2559.107132] Hardware name: Hardkernel ODROID-C2 (DT)
>> [ 2559.107135] task: ffff8000704abe80 task.stack: ffff8000734d0000
>> [ 2559.107147] PC is at __memcpy+0x100/0x180
>> [ 2559.107152] LR is at sg_copy_buffer+0xb0/0x110
>> [ 2559.107155] pc : [<ffff00000837ee00>] lr : [<ffff00000838e928>]
>> pstate: 200001c5
>> [ 2559.107155] sp : ffff8000734d3bb0
>> [ 2559.107157] x29: ffff8000734d3bb0
>> [ 2559.107158] x28: ffff800073a14800 x27: ffff800073a14b68
>> [ 2559.107162] x26: 0000000000000000 x25: 0000000000000140
>> [ 2559.107165] x24: 0000000000000001 x23: 0000000000001000
>> [ 2559.107168] x22: ffff8000746a2000 x21: 0000000000001000
>> [ 2559.107170] x20: 0000000000000000 x19: 0000000000001000
>> [ 2559.107172] x18: 0000000000000000 x17: ffffffffffffffff
>> [ 2559.107175] x16: 00000000000006be x15: ffff000008c34000
>> [ 2559.107178] x14: 747962342e090a34 x13: 3278302038323162
>> [ 2559.107181] x12: 656c752e090a3864 x11: ffff800073866800
>> [ 2559.107183] x10: ffff80006bf68eb0 x9 : 0000000000000000
>> [ 2559.107186] x8 : ffff800073a94920 x7 : 0000000000000000
>> [ 2559.107188] x6 : ffff8000746a2000 x5 : 0000820000000000
>> [ 2559.107191] x4 : 0000000000000000 x3 : 0000000000000000
>> [ 2559.107193] x2 : 0000000000000f80 x1 : ffff800000c1e000
>> [ 2559.107196] x0 : ffff8000746a2000
>> [ 2559.107199] Process mmcqd/1 (pid: 1124, stack limit = 0xffff8000734d0000)
>> [ 2559.107202] Stack: (0xffff8000734d3bb0 to 0xffff8000734d4000)
>> [ 2559.107205] 3ba0: ffff8000734d3c50
>> ffff00000838e9bc
>> [ 2559.107208] 3bc0: ffff800073a14000 ffff800073a14a30 ffff80006bf68eb0
>> ffff800073a14a28
>> [ 2559.107212] 3be0: ffff800073a14818 ffff800073a14800 0000000000000000
>> ffff00000838e1c4
>> [ 2559.107215] 3c00: ffff800073a94900 ffff7e0000030780 ffff800000c1e000
>> 0000000000001000
>> [ 2559.107218] 3c20: 0000000000001000 ffff800073ad0a00 0000000100000000
>> 0000000000000001
>> [ 2559.107221] 3c40: 0000100000000000 0000000000000005 ffff8000734d3c60
>> ffff00000874c1bc
>> [ 2559.107224] 3c60: ffff8000734d3c70 ffff000008748010 ffff8000734d3cd0
>> ffff000008749908
>> [ 2559.107228] 3c80: ffff80006bf68eb0 ffff800073a14000 ffff8000734c8000
>> ffff800073a14818
>> [ 2559.107231] 3ca0: ffff800073a14800 ffff800073a14800 ffff80006bf68eb0
>> ffff800073a14a28
>> [ 2559.107234] 3cc0: ffff80006bf68eb0 ffff000008749bc8 ffff8000734d3d70
>> ffff00000874b298
>> [ 2559.107237] 3ce0: ffff800073a14000 ffff800073a14818 ffff8000734c8000
>> 0000000000000000
>> [ 2559.107240] 3d00: ffff800073a14800 ffff800073a14800 ffff800073a13800
>> 0000000000000000
>> [ 2559.107243] 3d20: ffff80006bf68eb0 0000000000000000 00000000012853f0
>> ffff000008c0fcb8
>> [ 2559.107246] 3d40: 0000000000000000 000000000835bf14 ffff000008a05f58
>> ffff800000000000
>> [ 2559.107249] 3d60: ffff8000734c8000 0000000000000001 ffff8000734d3de0
>> ffff00000874b6f4
>> [ 2559.107252] 3d80: ffff800073a14818 ffff80006bf68eb0 ffff8000734c8000
>> 0000000000000001
>> [ 2559.107255] 3da0: ffff800073a14828 0000000000000000 0000000000000000
>> 0000000000000000
>> [ 2559.107258] 3dc0: 0000000000000000 0000000000000000 ffff800073a14818
>> ffff00000874b6c4
>> [ 2559.107261] 3de0: ffff8000734d3e20 ffff0000080daa84 ffff800073a94980
>> ffff000008e8eb08
>> [ 2559.107264] 3e00: ffff000008b75b50 ffff800073a14818 ffff00000874b658
>> 0000000000000000
>> [ 2559.107267] 3e20: 0000000000000000 ffff000008082ec0 ffff0000080da9b8
>> ffff800073a94980
>> [ 2559.107270] 3e40: 0000000000000000 0000000000000000 0000000000000000
>> 000003ff01893600
>> [ 2559.107273] 3e60: ffff8000734d3ea0 0000000000000000 ffff0000080da9b8
>> ffff800073a14818
>> [ 2559.107276] 3e80: 0000000000000000 0000000000000000 ffff8000734d3e90
>> ffff8000734d3e90
>> [ 2559.107279] 3ea0: 0000000000000000 ffff000000000000 ffff8000734d3eb0
>> ffff8000734d3eb0
>> [ 2559.107281] 3ec0: 0000000000000000 0000000000000000 0000000000000000
>> 0000000000000000
>> [ 2559.107284] 3ee0: 0000000000000000 0000000000000000 0000000000000000
>> 0000000000000000
>> [ 2559.107287] 3f00: 0000000000000000 0000000000000000 0000000000000000
>> 0000000000000000
>> [ 2559.107290] 3f20: 0000000000000000 0000000000000000 0000000000000000
>> 0000000000000000
>> [ 2559.107293] 3f40: 0000000000000000 0000000000000000 0000000000000000
>> 0000000000000000
>> [ 2559.107295] 3f60: 0000000000000000 0000000000000000 0000000000000000
>> 0000000000000000
>> [ 2559.107298] 3f80: 0000000000000000 0000000000000000 0000000000000000
>> 0000000000000000
>> [ 2559.107300] 3fa0: 0000000000000000 0000000000000000 0000000000000000
>> 0000000000000000
>> [ 2559.107303] 3fc0: 0000000000000000 0000000000000005 0000000000000000
>> 0000000000000000
>> [ 2559.107306] 3fe0: 0000000000000000 0000000000000000 0000001800002cba
>> 26000000a01b3800
>> [ 2559.107308] Call trace:
>> [ 2559.107312] Exception stack(0xffff8000734d39e0 to 0xffff8000734d3b10)
>> [ 2559.107315] 39e0: 0000000000001000 0001000000000000 ffff8000734d3bb0
>> ffff00000837ee00
>> [ 2559.107318] 3a00: 0000000000000007 ffff800000000000 ffff800000c1e000
>> 0000000100100010
>> [ 2559.107321] 3a20: ffff8000734d3ac0 ffff000008748d88 ffff8000734d3b8c
>> 0000000000000001
>> [ 2559.107324] 3a40: ffff8000734d3b40 ffff0000081c9dac ffff800074401d00
>> ffff0000081745d8
>> [ 2559.107327] 3a60: ffff7e0001b72f80 ffff80006dcbe300 00000000031fda40
>> 0000000000000000
>> [ 2559.107330] 3a80: ffff8000746a2000 ffff800000c1e000 0000000000000f80
>> 0000000000000000
>> [ 2559.107333] 3aa0: 0000000000000000 0000820000000000 ffff8000746a2000
>> 0000000000000000
>> [ 2559.107336] 3ac0: ffff800073a94920 0000000000000000 ffff80006bf68eb0
>> ffff800073866800
>> [ 2559.107339] 3ae0: 656c752e090a3864 3278302038323162 747962342e090a34
>> ffff000008c34000
>> [ 2559.107341] 3b00: 00000000000006be ffffffffffffffff
>> [ 2559.107346] [<ffff00000837ee00>] __memcpy+0x100/0x180
>> [ 2559.107349] [<ffff00000838e9bc>] sg_copy_to_buffer+0x14/0x20
>> [ 2559.107357] [<ffff00000874c1bc>] mmc_queue_bounce_pre+0x34/0x40
>> [ 2559.107362] [<ffff000008748010>] mmc_blk_rw_rq_prep+0x288/0x3a0
>> [ 2559.107365] [<ffff000008749908>] mmc_blk_issue_rw_rq+0x3c0/0x998
>> [ 2559.107368] [<ffff00000874b298>] mmc_blk_issue_rq+0x150/0x510
>> [ 2559.107371] [<ffff00000874b6f4>] mmc_queue_thread+0x9c/0x140
>> [ 2559.107377] [<ffff0000080daa84>] kthread+0xcc/0xe0
>> [ 2559.107383] [<ffff000008082ec0>] ret_from_fork+0x10/0x50
>> [ 2559.107387] Code: d503201f d503201f d503201f d503201f (a8c12027)
>> [ 2559.107409] ---[ end trace 7d280955c14d4ff3 ]---
>> [ 2559.107417] note: mmcqd/1[1124] exited with preempt_count 1
>> [ 2559.688313] x18: 0000000000040900 x17: 0000000000590578 x16:
>> 000040003c0400a8
>> [ 2559.695471] x15: 000000000000065c x14: 0000000000000000
>> [ 2559.700733] x13: 002f362f756e672d x12: 78756e696c2d3436
>> [ 2559.705994] x11: 0000000000000001 x10: 0101010101010101
>> [ 2559.711255] x9 : 0000000000000001 x8 : 0000000000000104
>> [ 2559.716516] x7 : 000000000046d448 x6 : 0000ffffe63873f4
>> [ 2559.721778] x5 : 0000ffffe63873f8 x4 : 0000000000000000
>> [ 2559.727039] x3 : 0000000000000000 x2 : 0000000000000000
>> [ 2559.732300] x1 : 0000000016c104e0 x0 : 0000000000005953
>> [ 2559.737561]
>> [ 2559.739036] Internal error: Attempting to execute userspace memory:
>> 8600000f [#10] PREEMPT SMP
>> [ 2559.747566] Modules linked in: meson_rng rng_core meson_gxbb_wdt
>> ip_tables x_tables ipv6 dwmac_generic realtek dwmac_meson8b
>> stmmac_platform stmmac
>> [ 2559.760678] CPU: 2 PID: 22866 Comm: gcc Tainted: G D
>> 4.9.0-rc6-next-20161124-00001-gbf7e142 #1
>> [ 2559.770337] Hardware name: Hardkernel ODROID-C2 (DT)
>> [ 2559.775254] task: ffff80007454e400 task.stack: ffff80006de9c000
>> [ 2559.781118] PC is at 0x46d4e0
>> [ 2559.784051] LR is at 0x46d4e0
>> [ 2559.786983] pc : [<000000000046d4e0>] lr : [<000000000046d4e0>]
>> pstate: 600003c5
>> [ 2559.794314] sp : ffff80006de9fec0
>> [ 2559.797591] x29: 0000000000000000 x28: ffff80007454e400
>> [ 2559.802853] x27: 0000000000000002 x26: 0000000000000001
>> [ 2559.808114] x25: 0000ffffe63873f4 x24: 0000ffffe63873f8
>> [ 2559.813375] x23: 0000000080000000 x22: 000040003c0400d8
>> [ 2559.818636] x21: ffffffffffffffff x20: 000080006e24d000
>> [ 2559.823898] x19: 0000000000000000 x18: 0000000000000010
>> [ 2559.829159] x17: 0000000000590578 x16: 000040003c0400a8
>> [ 2559.834420] x15: ffff000088e91f07 x14: 0000000000000006
>> [ 2559.839682] x13: ffff000008e91f15 x12: 000000000000000f
>> [ 2559.844943] x11: 0000000000000002 x10: 00000000000003f4
>> [ 2559.850204] x9 : ffff80006de9fb40 x8 : 00000000000b4119
>> [ 2559.855465] x7 : 0000000000000000 x6 : 000000000000019d
>> [ 2559.860726] x5 : 00000000019e019d x4 : 0000000000000000
>> [ 2559.865988] x3 : 0000000000000002 x2 : 000000000000019e
>> [ 2559.871249] x1 : ffff80007454e400 x0 : 0000000000000000
>> [ 2559.876510]
>> [ 2559.877977] Process gcc (pid: 22866, stack limit = 0xffff80006de9c000)
>> [ 2559.884446] Stack: (0xffff80006de9fec0 to 0xffff80006dea0000)
>> [ 2559.890140] fec0: 0000000000005953 0000000016c104e0 0000000000000000
>> 0000000000000000
>> [ 2559.897902] fee0: 0000000000000000 0000ffffe63873f8 0000ffffe63873f4
>> 000000000046d448
>> [ 2559.905664] ff00: 0000000000000104 0000000000000001 0101010101010101
>> 0000000000000001
>> [ 2559.913427] ff20: 78756e696c2d3436 002f362f756e672d 0000000000000000
>> 000000000000065c
>> [ 2559.921190] ff40: 000040003c0400a8 0000000000590578 0000000000040900
>> 0000000000000000
>> [ 2559.928952] ff60: 0000000000005953 0000000016c104e0 0000ffffe63873f8
>> 0000ffffe63873f4
>> [ 2559.936714] ff80: 0000ffffe63873f8 0000ffffe63873f4 0000000000000001
>> 0000000000000002
>> [ 2559.944477] ffa0: 0000000016c0ff90 0000ffffe6387270 000000000046d4e0
>> 0000ffffe6387270
>> [ 2559.952240] ffc0: 000040003c0400d8 0000000080000000 0000000000005953
>> ffffffffffffffff
>> [ 2559.960002] ffe0: 0000000000000000 0000000000000000 0000000000000000
>> 0000000000000000
>> [ 2559.967762] Call trace:
>> [ 2559.970179] Exception stack(0xffff80006de9fcf0 to 0xffff80006de9fe20)
>> [ 2559.976561] fce0: 0000000000000000
>> 0001000000000000
>> [ 2559.984324] fd00: ffff80006de9fec0 000000000046d4e0 ffff80007366f8c0
>> 0000000000000004
>> [ 2559.992087] fd20: 0000000000000000 ffff000008dbbc18 ffff80007454e400
>> 000000006de9fdd0
>> [ 2559.999850] fd40: ffff80006de9fd90 ffff0000080ca878 ffff80006de9fe40
>> ffff80007454e400
>> [ 2560.007612] fd60: 0000000000000004 00000000000003c0 ffff80006de9fe40
>> 0000ffffe63873f8
>> [ 2560.015374] fd80: 0000ffffe63873f4 0000000000000001 0000000000000000
>> ffff80007454e400
>> [ 2560.023137] fda0: 000000000000019e 0000000000000002 0000000000000000
>> 00000000019e019d
>> [ 2560.030899] fdc0: 000000000000019d 0000000000000000 00000000000b4119
>> ffff80006de9fb40
>> [ 2560.038662] fde0: 00000000000003f4 0000000000000002 000000000000000f
>> ffff000008e91f15
>> [ 2560.046425] fe00: 0000000000000006 ffff000088e91f07 000040003c0400a8
>> 0000000000590578
>> [ 2560.054186] [<000000000046d4e0>] 0x46d4e0
>> [ 2560.058155] Code: aa1503e1 2a1403e0 52800002 97fe895d (2a0003e1)
>> [ 2560.064244] ---[ end trace 7d280955c14d4ff4 ]---
> I am asking because when you look at the affected processes you'll get
> this list: cc1, mmcqd/1, gcc
> it doesn't sound like any of these using ethernet but rather MMC instead.
>
>
> Regards,
> Martin
>
Hello Martin,
the same error occurs without patch
https://github.com/xypron/kernel-odroid-c2/blob/master/patch/0001-stmmac-RTL8211F-Meson-GXBB-TX-throughput-problems.patch
Best regards
Heinrich
^ permalink raw reply
* [PATCH net-next 03/10] net/mlx5e: Read ETS settings directly from firmware
From: Saeed Mahameed @ 2016-11-26 14:18 UTC (permalink / raw)
To: David S. Miller; +Cc: netdev, Huy Nguyen, Saeed Mahameed
In-Reply-To: <1480169914-22347-1-git-send-email-saeedm@mellanox.com>
From: Huy Nguyen <huyn@mellanox.com>
Issue description:
Current implementation saves the ETS settings from user in
a temporal soft copy and returns this settings when user
queries the ETS settings.
With the new DCBX firmware, the ETS settings can be changed
by firmware when the DCBX is in firmware controlled mode. Therefore,
user will obtain wrong values from the temporal soft copy.
Solution:
1. Read the ETS settings directly from firmware.
2. For tc_tsa:
a. Initialize tc_tsa to vendor IEEE_8021QAZ_TSA_VENDOR at netdev
creation.
b. When reading ETS setting from FW, if the traffic class bandwidth
is less than 100, set tc_tsa to IEEE_8021QAZ_TSA_ETS. This
implementation solves the scenarios when the DCBX is in FW control
and willing bit is on which means the ETS setting is dictated
by remote switch.
Signed-off-by: Huy Nguyen <huyn@mellanox.com>
Signed-off-by: Saeed Mahameed <saeedm@mellanox.com>
---
drivers/net/ethernet/mellanox/mlx5/core/en.h | 6 ++--
drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c | 35 ++++++++++++++++++----
drivers/net/ethernet/mellanox/mlx5/core/en_main.c | 28 +++++++++--------
3 files changed, 47 insertions(+), 22 deletions(-)
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en.h b/drivers/net/ethernet/mellanox/mlx5/core/en.h
index 31387ed..60aa13b 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en.h
@@ -214,9 +214,6 @@ struct mlx5e_params {
u8 toeplitz_hash_key[40];
u32 indirection_rqt[MLX5E_INDIR_RQT_SIZE];
bool vlan_strip_disable;
-#ifdef CONFIG_MLX5_CORE_EN_DCB
- struct ieee_ets ets;
-#endif
bool rx_am_enabled;
u32 lro_timeout;
};
@@ -238,6 +235,9 @@ enum {
struct mlx5e_dcbx {
struct mlx5e_cee_config cee_cfg; /* pending configuration */
+
+ /* The only setting that cannot be read from FW */
+ u8 tc_tsa[IEEE_8021QAZ_MAX_TCS];
};
#endif
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c b/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c
index 0595243..8f6b5a7 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c
@@ -45,12 +45,31 @@ static int mlx5e_dcbnl_ieee_getets(struct net_device *netdev,
struct ieee_ets *ets)
{
struct mlx5e_priv *priv = netdev_priv(netdev);
+ struct mlx5_core_dev *mdev = priv->mdev;
+ int i;
+ int err = 0;
if (!MLX5_CAP_GEN(priv->mdev, ets))
return -ENOTSUPP;
- memcpy(ets, &priv->params.ets, sizeof(*ets));
- return 0;
+ ets->ets_cap = mlx5_max_tc(priv->mdev) + 1;
+ for (i = 0; i < ets->ets_cap; i++) {
+ err = mlx5_query_port_prio_tc(mdev, i, &ets->prio_tc[i]);
+ if (err)
+ return err;
+ }
+
+ for (i = 0; i < ets->ets_cap; i++) {
+ err = mlx5_query_port_tc_bw_alloc(mdev, i, &ets->tc_tx_bw[i]);
+ if (err)
+ return err;
+ if (ets->tc_tx_bw[i] < MLX5E_MAX_BW_ALLOC)
+ priv->dcbx.tc_tsa[i] = IEEE_8021QAZ_TSA_ETS;
+ }
+
+ memcpy(ets->tc_tsa, priv->dcbx.tc_tsa, sizeof(ets->tc_tsa));
+
+ return err;
}
enum {
@@ -127,7 +146,14 @@ int mlx5e_dcbnl_ieee_setets_core(struct mlx5e_priv *priv, struct ieee_ets *ets)
if (err)
return err;
- return mlx5_set_port_tc_bw_alloc(mdev, tc_tx_bw);
+ err = mlx5_set_port_tc_bw_alloc(mdev, tc_tx_bw);
+
+ if (err)
+ return err;
+
+ memcpy(priv->dcbx.tc_tsa, ets->tc_tsa, sizeof(ets->tc_tsa));
+
+ return err;
}
static int mlx5e_dbcnl_validate_ets(struct net_device *netdev,
@@ -181,9 +207,6 @@ static int mlx5e_dcbnl_ieee_setets(struct net_device *netdev,
if (err)
return err;
- memcpy(&priv->params.ets, ets, sizeof(*ets));
- priv->params.ets.ets_cap = mlx5_max_tc(priv->mdev) + 1;
-
return 0;
}
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
index 2b42112..9743c4c 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
@@ -3329,17 +3329,23 @@ u16 mlx5e_get_max_inline_cap(struct mlx5_core_dev *mdev)
static void mlx5e_ets_init(struct mlx5e_priv *priv)
{
int i;
-
- priv->params.ets.ets_cap = mlx5_max_tc(priv->mdev) + 1;
- for (i = 0; i < priv->params.ets.ets_cap; i++) {
- priv->params.ets.tc_tx_bw[i] = MLX5E_MAX_BW_ALLOC;
- priv->params.ets.tc_tsa[i] = IEEE_8021QAZ_TSA_VENDOR;
- priv->params.ets.prio_tc[i] = i;
+ struct ieee_ets ets;
+
+ memset(&ets, 0, sizeof(ets));
+ ets.ets_cap = mlx5_max_tc(priv->mdev) + 1;
+ for (i = 0; i < ets.ets_cap; i++) {
+ ets.tc_tx_bw[i] = MLX5E_MAX_BW_ALLOC;
+ ets.tc_tsa[i] = IEEE_8021QAZ_TSA_VENDOR;
+ ets.prio_tc[i] = i;
}
+ memcpy(priv->dcbx.tc_tsa, ets.tc_tsa, sizeof(ets.tc_tsa));
+
/* tclass[prio=0]=1, tclass[prio=1]=0, tclass[prio=i]=i (for i>1) */
- priv->params.ets.prio_tc[0] = 1;
- priv->params.ets.prio_tc[1] = 0;
+ ets.prio_tc[0] = 1;
+ ets.prio_tc[1] = 0;
+
+ mlx5e_dcbnl_ieee_setets_core(priv, &ets);
}
#endif
@@ -3509,10 +3515,6 @@ static void mlx5e_build_nic_netdev_priv(struct mlx5_core_dev *mdev,
MLX5E_SET_PRIV_FLAG(priv, MLX5E_PFLAG_RX_CQE_BASED_MODER,
priv->params.rx_cq_period_mode == MLX5_CQ_PERIOD_MODE_START_FROM_CQE);
-#ifdef CONFIG_MLX5_CORE_EN_DCB
- mlx5e_ets_init(priv);
-#endif
-
mutex_init(&priv->state_lock);
INIT_WORK(&priv->update_carrier_work, mlx5e_update_carrier_work);
@@ -3789,7 +3791,7 @@ static int mlx5e_init_nic_tx(struct mlx5e_priv *priv)
}
#ifdef CONFIG_MLX5_CORE_EN_DCB
- mlx5e_dcbnl_ieee_setets_core(priv, &priv->params.ets);
+ mlx5e_ets_init(priv);
#endif
return 0;
}
--
2.7.4
^ permalink raw reply related
* [PATCH net-next 06/10] net/mlx5e: Add DCBX control interface
From: Saeed Mahameed @ 2016-11-26 14:18 UTC (permalink / raw)
To: David S. Miller; +Cc: netdev, Huy Nguyen, Saeed Mahameed
In-Reply-To: <1480169914-22347-1-git-send-email-saeedm@mellanox.com>
From: Huy Nguyen <huyn@mellanox.com>
Use setdcbx interface to set the DCBX mode to firmware or os.
If setdcbx is called with mode value of zero, the DCBX mode
is set to firmware.
Signed-off-by: Huy Nguyen <huyn@mellanox.com>
Signed-off-by: Saeed Mahameed <saeedm@mellanox.com>
---
drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c | 27 +++++++++++++++++++---
1 file changed, 24 insertions(+), 3 deletions(-)
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c b/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c
index 2e94717..64c45e9 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c
@@ -288,13 +288,34 @@ static int mlx5e_dcbnl_ieee_setpfc(struct net_device *dev,
static u8 mlx5e_dcbnl_getdcbx(struct net_device *dev)
{
- return DCB_CAP_DCBX_HOST |
- DCB_CAP_DCBX_VER_IEEE |
- DCB_CAP_DCBX_VER_CEE;
+ struct mlx5e_priv *priv = netdev_priv(dev);
+ struct mlx5e_dcbx *dcbx = &priv->dcbx;
+ u8 mode = DCB_CAP_DCBX_VER_IEEE | DCB_CAP_DCBX_VER_CEE;
+
+ if (dcbx->mode == MLX5E_DCBX_PARAM_VER_OPER_HOST)
+ mode |= DCB_CAP_DCBX_HOST;
+
+ return mode;
}
static u8 mlx5e_dcbnl_setdcbx(struct net_device *dev, u8 mode)
{
+ struct mlx5e_priv *priv = netdev_priv(dev);
+ struct mlx5e_dcbx *dcbx = &priv->dcbx;
+
+ if ((!mode) && MLX5_CAP_GEN(priv->mdev, dcbx)) {
+ if (dcbx->mode == MLX5E_DCBX_PARAM_VER_OPER_AUTO)
+ return 0;
+
+ /* set dcbx to fw controlled */
+ if (!mlx5e_dcbnl_set_dcbx_mode(priv, MLX5E_DCBX_PARAM_VER_OPER_AUTO)) {
+ dcbx->mode = MLX5E_DCBX_PARAM_VER_OPER_AUTO;
+ return 0;
+ }
+
+ return 1;
+ }
+
if (mlx5e_dcbnl_switch_to_host_mode(netdev_priv(dev)))
return 1;
--
2.7.4
^ permalink raw reply related
* [PATCH net-next 08/10] net/mlx5e: Add support for loopback selftest
From: Saeed Mahameed @ 2016-11-26 14:18 UTC (permalink / raw)
To: David S. Miller; +Cc: netdev, Saeed Mahameed, Kamal Heib
In-Reply-To: <1480169914-22347-1-git-send-email-saeedm@mellanox.com>
Extend the self diagnostic tests to support loopback test.
The loopback test doesn't require the offline flag, it will use the
generic dev_queue_xmit and a dedicated packet_type to capture and verify
mlx5e selftest loopback packets.
Signed-off-by: Saeed Mahameed <saeedm@mellanox.com>
Signed-off-by: Kamal Heib <kamalh@mellanox.com>
---
drivers/net/ethernet/mellanox/mlx5/core/en.h | 3 +-
.../net/ethernet/mellanox/mlx5/core/en_common.c | 7 +-
drivers/net/ethernet/mellanox/mlx5/core/en_main.c | 2 +-
.../net/ethernet/mellanox/mlx5/core/en_selftest.c | 218 +++++++++++++++++++++
4 files changed, 227 insertions(+), 3 deletions(-)
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en.h b/drivers/net/ethernet/mellanox/mlx5/core/en.h
index f7bb4a7..9cf32d3 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en.h
@@ -885,7 +885,8 @@ void mlx5e_destroy_tir(struct mlx5_core_dev *mdev,
struct mlx5e_tir *tir);
int mlx5e_create_mdev_resources(struct mlx5_core_dev *mdev);
void mlx5e_destroy_mdev_resources(struct mlx5_core_dev *mdev);
-int mlx5e_refresh_tirs_self_loopback_enable(struct mlx5_core_dev *mdev);
+int mlx5e_refresh_tirs_self_loopback(struct mlx5_core_dev *mdev,
+ bool enable_uc_lb);
struct mlx5_eswitch_rep;
int mlx5e_vport_rep_load(struct mlx5_eswitch *esw,
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_common.c b/drivers/net/ethernet/mellanox/mlx5/core/en_common.c
index 029e856..f175518 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_common.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_common.c
@@ -137,7 +137,8 @@ void mlx5e_destroy_mdev_resources(struct mlx5_core_dev *mdev)
mlx5_unmap_free_uar(mdev, &res->cq_uar);
}
-int mlx5e_refresh_tirs_self_loopback_enable(struct mlx5_core_dev *mdev)
+int mlx5e_refresh_tirs_self_loopback(struct mlx5_core_dev *mdev,
+ bool enable_uc_lb)
{
struct mlx5e_tir *tir;
void *in;
@@ -149,6 +150,10 @@ int mlx5e_refresh_tirs_self_loopback_enable(struct mlx5_core_dev *mdev)
if (!in)
return -ENOMEM;
+ if (enable_uc_lb)
+ MLX5_SET(modify_tir_in, in, ctx.self_lb_block,
+ MLX5_TIRC_SELF_LB_BLOCK_BLOCK_UNICAST_);
+
MLX5_SET(modify_tir_in, in, bitmask.self_lb_en, 1);
list_for_each_entry(tir, &mdev->mlx5e_res.td.tirs_list, list) {
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
index f5b93c2..89d5c65 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
@@ -2136,7 +2136,7 @@ int mlx5e_open_locked(struct net_device *netdev)
goto err_clear_state_opened_flag;
}
- err = mlx5e_refresh_tirs_self_loopback_enable(priv->mdev);
+ err = mlx5e_refresh_tirs_self_loopback(priv->mdev, false);
if (err) {
netdev_err(netdev, "%s: mlx5e_refresh_tirs_self_loopback_enable failed, %d\n",
__func__, err);
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_selftest.c b/drivers/net/ethernet/mellanox/mlx5/core/en_selftest.c
index a25dfc5..a823054 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_selftest.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_selftest.c
@@ -30,12 +30,16 @@
* SOFTWARE.
*/
+#include <linux/ip.h>
+#include <linux/udp.h>
+#include <net/udp.h>
#include "en.h"
enum {
MLX5E_ST_LINK_STATE,
MLX5E_ST_LINK_SPEED,
MLX5E_ST_HEALTH_INFO,
+ MLX5E_ST_LOOPBACK,
MLX5E_ST_NUM,
};
@@ -43,6 +47,7 @@ const char mlx5e_self_tests[MLX5E_ST_NUM][ETH_GSTRING_LEN] = {
"Link Test",
"Speed Test",
"Health Test",
+ "Loopback Test",
};
int mlx5e_self_test_num(struct mlx5e_priv *priv)
@@ -88,10 +93,223 @@ static int mlx5e_test_link_speed(struct mlx5e_priv *priv)
return 1;
}
+/* loopback test */
+#define MLX5E_TEST_PKT_SIZE (MLX5_MPWRQ_SMALL_PACKET_THRESHOLD - NET_IP_ALIGN)
+static const char mlx5e_test_text[ETH_GSTRING_LEN] = "MLX5E SELF TEST";
+#define MLX5E_TEST_MAGIC 0x5AEED15C001
+
+struct mlx5ehdr {
+ __be32 version;
+ __be64 magic;
+ char text[ETH_GSTRING_LEN];
+};
+
+static struct sk_buff *mlx5e_test_get_udp_skb(struct mlx5e_priv *priv)
+{
+ struct sk_buff *skb = NULL;
+ struct mlx5ehdr *mlxh;
+ struct ethhdr *ethh;
+ struct udphdr *udph;
+ struct iphdr *iph;
+ int datalen, iplen;
+
+ datalen = MLX5E_TEST_PKT_SIZE -
+ (sizeof(*ethh) + sizeof(*iph) + sizeof(*udph));
+
+ skb = netdev_alloc_skb(priv->netdev, MLX5E_TEST_PKT_SIZE);
+ if (!skb) {
+ netdev_err(priv->netdev, "\tFailed to alloc loopback skb\n");
+ return NULL;
+ }
+
+ prefetchw(skb->data);
+ skb_reserve(skb, NET_IP_ALIGN);
+
+ /* Reserve for ethernet and IP header */
+ ethh = (struct ethhdr *)skb_push(skb, ETH_HLEN);
+ skb_reset_mac_header(skb);
+
+ skb_set_network_header(skb, skb->len);
+ iph = (struct iphdr *)skb_put(skb, sizeof(struct iphdr));
+
+ skb_set_transport_header(skb, skb->len);
+ udph = (struct udphdr *)skb_put(skb, sizeof(struct udphdr));
+
+ /* Fill ETH header */
+ ether_addr_copy(ethh->h_dest, priv->netdev->dev_addr);
+ eth_zero_addr(ethh->h_source);
+ ethh->h_proto = htons(ETH_P_IP);
+
+ /* Fill UDP header */
+ udph->source = htons(9);
+ udph->dest = htons(9); /* Discard Protocol */
+ udph->len = htons(datalen + sizeof(struct udphdr));
+ udph->check = 0;
+
+ /* Fill IP header */
+ iph->ihl = 5;
+ iph->ttl = 32;
+ iph->version = 4;
+ iph->protocol = IPPROTO_UDP;
+ iplen = sizeof(struct iphdr) + sizeof(struct udphdr) + datalen;
+ iph->tot_len = htons(iplen);
+ iph->frag_off = 0;
+ iph->saddr = 0;
+ iph->daddr = 0;
+ iph->tos = 0;
+ iph->id = 0;
+ ip_send_check(iph);
+
+ /* Fill test header and data */
+ mlxh = (struct mlx5ehdr *)skb_put(skb, sizeof(*mlxh));
+ mlxh->version = 0;
+ mlxh->magic = cpu_to_be64(MLX5E_TEST_MAGIC);
+ strlcpy(mlxh->text, mlx5e_test_text, sizeof(mlxh->text));
+ datalen -= sizeof(*mlxh);
+ memset(skb_put(skb, datalen), 0, datalen);
+
+ skb->csum = 0;
+ skb->ip_summed = CHECKSUM_PARTIAL;
+ udp4_hwcsum(skb, iph->saddr, iph->daddr);
+
+ skb->protocol = htons(ETH_P_IP);
+ skb->pkt_type = PACKET_HOST;
+ skb->dev = priv->netdev;
+
+ return skb;
+}
+
+struct mlx5e_lbt_priv {
+ struct packet_type pt;
+ struct completion comp;
+ bool loopback_ok;
+};
+
+static int
+mlx5e_test_loopback_validate(struct sk_buff *skb,
+ struct net_device *ndev,
+ struct packet_type *pt,
+ struct net_device *orig_ndev)
+{
+ struct mlx5e_lbt_priv *lbtp = pt->af_packet_priv;
+ struct mlx5ehdr *mlxh;
+ struct ethhdr *ethh;
+ struct udphdr *udph;
+ struct iphdr *iph;
+
+ /* We are only going to peek, no need to clone the SKB */
+ if (skb->protocol != htons(ETH_P_IP))
+ goto out;
+
+ if (MLX5E_TEST_PKT_SIZE - ETH_HLEN > skb_headlen(skb))
+ goto out;
+
+ ethh = (struct ethhdr *)skb_mac_header(skb);
+ if (!ether_addr_equal(ethh->h_dest, orig_ndev->dev_addr))
+ goto out;
+
+ iph = ip_hdr(skb);
+ if (iph->protocol != IPPROTO_UDP)
+ goto out;
+
+ udph = udp_hdr(skb);
+ if (udph->dest != htons(9))
+ goto out;
+
+ mlxh = (struct mlx5ehdr *)((char *)udph + sizeof(*udph));
+ if (mlxh->magic != cpu_to_be64(MLX5E_TEST_MAGIC))
+ goto out; /* so close ! */
+
+ /* bingo */
+ lbtp->loopback_ok = true;
+ complete(&lbtp->comp);
+out:
+ kfree_skb(skb);
+ return 0;
+}
+
+static int mlx5e_test_loopback_setup(struct mlx5e_priv *priv,
+ struct mlx5e_lbt_priv *lbtp)
+{
+ int err = 0;
+
+ err = mlx5e_refresh_tirs_self_loopback(priv->mdev, true);
+ if (err) {
+ netdev_err(priv->netdev,
+ "\tFailed to enable UC loopback err(%d)\n", err);
+ return err;
+ }
+
+ lbtp->loopback_ok = false;
+ init_completion(&lbtp->comp);
+
+ lbtp->pt.type = htons(ETH_P_ALL);
+ lbtp->pt.func = mlx5e_test_loopback_validate;
+ lbtp->pt.dev = priv->netdev;
+ lbtp->pt.af_packet_priv = lbtp;
+ dev_add_pack(&lbtp->pt);
+ return err;
+}
+
+static void mlx5e_test_loopback_cleanup(struct mlx5e_priv *priv,
+ struct mlx5e_lbt_priv *lbtp)
+{
+ dev_remove_pack(&lbtp->pt);
+ mlx5e_refresh_tirs_self_loopback(priv->mdev, false);
+}
+
+#define MLX5E_LB_VERIFY_TIMEOUT (msecs_to_jiffies(200))
+static int mlx5e_test_loopback(struct mlx5e_priv *priv)
+{
+ struct mlx5e_lbt_priv *lbtp;
+ struct sk_buff *skb = NULL;
+ int err;
+
+ if (!test_bit(MLX5E_STATE_OPENED, &priv->state)) {
+ netdev_err(priv->netdev,
+ "\tCan't perform loobpack test while device is down\n");
+ return -ENODEV;
+ }
+
+ lbtp = kzalloc(sizeof(*lbtp), GFP_KERNEL);
+ if (!lbtp)
+ return -ENOMEM;
+ lbtp->loopback_ok = false;
+
+ err = mlx5e_test_loopback_setup(priv, lbtp);
+ if (err)
+ goto out;
+
+ skb = mlx5e_test_get_udp_skb(priv);
+ if (!skb) {
+ err = -ENOMEM;
+ goto cleanup;
+ }
+
+ skb_set_queue_mapping(skb, 0);
+ err = dev_queue_xmit(skb);
+ if (err) {
+ netdev_err(priv->netdev,
+ "\tFailed to xmit loopback packet err(%d)\n",
+ err);
+ goto cleanup;
+ }
+
+ wait_for_completion_timeout(&lbtp->comp, MLX5E_LB_VERIFY_TIMEOUT);
+ err = !lbtp->loopback_ok;
+
+cleanup:
+ mlx5e_test_loopback_cleanup(priv, lbtp);
+out:
+ kfree(lbtp);
+ return err;
+}
+
int (*mlx5e_st_func[MLX5E_ST_NUM])(struct mlx5e_priv *) = {
mlx5e_test_link_state,
mlx5e_test_link_speed,
mlx5e_test_health_info,
+ mlx5e_test_loopback
};
void mlx5e_self_test(struct net_device *ndev, struct ethtool_test *etest,
--
2.7.4
^ permalink raw reply related
* [PATCH net-next 05/10] net/mlx5e: ConnectX-4 firmware support for DCBX
From: Saeed Mahameed @ 2016-11-26 14:18 UTC (permalink / raw)
To: David S. Miller; +Cc: netdev, Huy Nguyen, Saeed Mahameed
In-Reply-To: <1480169914-22347-1-git-send-email-saeedm@mellanox.com>
From: Huy Nguyen <huyn@mellanox.com>
This patch sets up the infrastructure to support the new
DCBX firmware.
Signed-off-by: Huy Nguyen <huyn@mellanox.com>
Signed-off-by: Saeed Mahameed <saeedm@mellanox.com>
---
drivers/net/ethernet/mellanox/mlx5/core/en.h | 2 +
drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c | 92 ++++++++++++++++++++++
drivers/net/ethernet/mellanox/mlx5/core/en_main.c | 26 +-----
3 files changed, 95 insertions(+), 25 deletions(-)
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en.h b/drivers/net/ethernet/mellanox/mlx5/core/en.h
index 60aa13b..6c954cd 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en.h
@@ -234,6 +234,7 @@ enum {
};
struct mlx5e_dcbx {
+ enum mlx5_dcbx_oper_mode mode;
struct mlx5e_cee_config cee_cfg; /* pending configuration */
/* The only setting that cannot be read from FW */
@@ -843,6 +844,7 @@ extern const struct ethtool_ops mlx5e_ethtool_ops;
#ifdef CONFIG_MLX5_CORE_EN_DCB
extern const struct dcbnl_rtnl_ops mlx5e_dcbnl_ops;
int mlx5e_dcbnl_ieee_setets_core(struct mlx5e_priv *priv, struct ieee_ets *ets);
+void mlx5e_dcbnl_initialize(struct mlx5e_priv *priv);
#endif
#ifndef CONFIG_RFS_ACCEL
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c b/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c
index 8f6b5a7..2e94717 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c
@@ -41,6 +41,43 @@
#define MLX5E_CEE_STATE_UP 1
#define MLX5E_CEE_STATE_DOWN 0
+/* If dcbx mode is non-host set the dcbx mode to host.
+ */
+static int mlx5e_dcbnl_set_dcbx_mode(struct mlx5e_priv *priv,
+ enum mlx5_dcbx_oper_mode mode)
+{
+ struct mlx5_core_dev *mdev = priv->mdev;
+ u32 param[MLX5_ST_SZ_DW(dcbx_param)];
+ int err;
+
+ err = mlx5_query_port_dcbx_param(mdev, param);
+ if (err)
+ return err;
+
+ MLX5_SET(dcbx_param, param, version_admin, mode);
+ if (mode != MLX5E_DCBX_PARAM_VER_OPER_HOST)
+ MLX5_SET(dcbx_param, param, willing_admin, 1);
+
+ return mlx5_set_port_dcbx_param(mdev, param);
+}
+
+static int mlx5e_dcbnl_switch_to_host_mode(struct mlx5e_priv *priv)
+{
+ struct mlx5e_dcbx *dcbx = &priv->dcbx;
+
+ if (!MLX5_CAP_GEN(priv->mdev, dcbx))
+ return 0;
+
+ if (dcbx->mode == MLX5E_DCBX_PARAM_VER_OPER_HOST)
+ return 0;
+
+ if (mlx5e_dcbnl_set_dcbx_mode(priv, MLX5E_DCBX_PARAM_VER_OPER_HOST))
+ return 1;
+
+ dcbx->mode = MLX5E_DCBX_PARAM_VER_OPER_HOST;
+ return 0;
+}
+
static int mlx5e_dcbnl_ieee_getets(struct net_device *netdev,
struct ieee_ets *ets)
{
@@ -199,6 +236,9 @@ static int mlx5e_dcbnl_ieee_setets(struct net_device *netdev,
struct mlx5e_priv *priv = netdev_priv(netdev);
int err;
+ if (!MLX5_CAP_GEN(priv->mdev, ets))
+ return -ENOTSUPP;
+
err = mlx5e_dbcnl_validate_ets(netdev, ets);
if (err)
return err;
@@ -255,6 +295,9 @@ static u8 mlx5e_dcbnl_getdcbx(struct net_device *dev)
static u8 mlx5e_dcbnl_setdcbx(struct net_device *dev, u8 mode)
{
+ if (mlx5e_dcbnl_switch_to_host_mode(netdev_priv(dev)))
+ return 1;
+
if ((mode & DCB_CAP_DCBX_LLD_MANAGED) ||
!(mode & DCB_CAP_DCBX_VER_CEE) ||
!(mode & DCB_CAP_DCBX_VER_IEEE) ||
@@ -634,3 +677,52 @@ const struct dcbnl_rtnl_ops mlx5e_dcbnl_ops = {
.getpfcstate = mlx5e_dcbnl_getpfcstate,
.setpfcstate = mlx5e_dcbnl_setpfcstate,
};
+
+static void mlx5e_dcbnl_query_dcbx_mode(struct mlx5e_priv *priv,
+ enum mlx5_dcbx_oper_mode *mode)
+{
+ u32 out[MLX5_ST_SZ_DW(dcbx_param)];
+
+ *mode = MLX5E_DCBX_PARAM_VER_OPER_HOST;
+
+ if (!mlx5_query_port_dcbx_param(priv->mdev, out))
+ *mode = MLX5_GET(dcbx_param, out, version_oper);
+
+ /* From driver's point of view, we only care if the mode
+ * is host (HOST) or non-host (AUTO)
+ */
+ if (*mode != MLX5E_DCBX_PARAM_VER_OPER_HOST)
+ *mode = MLX5E_DCBX_PARAM_VER_OPER_AUTO;
+}
+
+static void mlx5e_ets_init(struct mlx5e_priv *priv)
+{
+ int i;
+ struct ieee_ets ets;
+
+ memset(&ets, 0, sizeof(ets));
+ ets.ets_cap = mlx5_max_tc(priv->mdev) + 1;
+ for (i = 0; i < ets.ets_cap; i++) {
+ ets.tc_tx_bw[i] = MLX5E_MAX_BW_ALLOC;
+ ets.tc_tsa[i] = IEEE_8021QAZ_TSA_VENDOR;
+ ets.prio_tc[i] = i;
+ }
+
+ memcpy(priv->dcbx.tc_tsa, ets.tc_tsa, sizeof(ets.tc_tsa));
+
+ /* tclass[prio=0]=1, tclass[prio=1]=0, tclass[prio=i]=i (for i>1) */
+ ets.prio_tc[0] = 1;
+ ets.prio_tc[1] = 0;
+
+ mlx5e_dcbnl_ieee_setets_core(priv, &ets);
+}
+
+void mlx5e_dcbnl_initialize(struct mlx5e_priv *priv)
+{
+ struct mlx5e_dcbx *dcbx = &priv->dcbx;
+
+ if (MLX5_CAP_GEN(priv->mdev, dcbx))
+ mlx5e_dcbnl_query_dcbx_mode(priv, &dcbx->mode);
+
+ mlx5e_ets_init(priv);
+}
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
index 9743c4c..f5b93c2 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
@@ -3325,30 +3325,6 @@ u16 mlx5e_get_max_inline_cap(struct mlx5_core_dev *mdev)
2 /*sizeof(mlx5e_tx_wqe.inline_hdr_start)*/;
}
-#ifdef CONFIG_MLX5_CORE_EN_DCB
-static void mlx5e_ets_init(struct mlx5e_priv *priv)
-{
- int i;
- struct ieee_ets ets;
-
- memset(&ets, 0, sizeof(ets));
- ets.ets_cap = mlx5_max_tc(priv->mdev) + 1;
- for (i = 0; i < ets.ets_cap; i++) {
- ets.tc_tx_bw[i] = MLX5E_MAX_BW_ALLOC;
- ets.tc_tsa[i] = IEEE_8021QAZ_TSA_VENDOR;
- ets.prio_tc[i] = i;
- }
-
- memcpy(priv->dcbx.tc_tsa, ets.tc_tsa, sizeof(ets.tc_tsa));
-
- /* tclass[prio=0]=1, tclass[prio=1]=0, tclass[prio=i]=i (for i>1) */
- ets.prio_tc[0] = 1;
- ets.prio_tc[1] = 0;
-
- mlx5e_dcbnl_ieee_setets_core(priv, &ets);
-}
-#endif
-
void mlx5e_build_default_indir_rqt(struct mlx5_core_dev *mdev,
u32 *indirection_rqt, int len,
int num_channels)
@@ -3791,7 +3767,7 @@ static int mlx5e_init_nic_tx(struct mlx5e_priv *priv)
}
#ifdef CONFIG_MLX5_CORE_EN_DCB
- mlx5e_ets_init(priv);
+ mlx5e_dcbnl_initialize(priv);
#endif
return 0;
}
--
2.7.4
^ permalink raw reply related
* [PATCH net-next 10/10] net/mlx5e: Add CQE compression user control
From: Saeed Mahameed @ 2016-11-26 14:18 UTC (permalink / raw)
To: David S. Miller; +Cc: netdev, Shaker Daibes, Saeed Mahameed
In-Reply-To: <1480169914-22347-1-git-send-email-saeedm@mellanox.com>
From: Shaker Daibes <shakerd@mellanox.com>
The user can now override the automatic driver decision using the
rx_cqe_compress flag, which is the preference for CQE compression.
The flag is initialized with the automatic driver decision.
Signed-off-by: Shaker Daibes <shakerd@mellanox.com>
Signed-off-by: Saeed Mahameed <saeedm@mellanox.com>
---
drivers/net/ethernet/mellanox/mlx5/core/en.h | 5 +--
drivers/net/ethernet/mellanox/mlx5/core/en_clock.c | 3 +-
.../net/ethernet/mellanox/mlx5/core/en_ethtool.c | 39 ++++++++++++++++++++--
drivers/net/ethernet/mellanox/mlx5/core/en_main.c | 13 ++++----
drivers/net/ethernet/mellanox/mlx5/core/en_rx.c | 4 +--
5 files changed, 51 insertions(+), 13 deletions(-)
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en.h b/drivers/net/ethernet/mellanox/mlx5/core/en.h
index 84ac78f..442dbc3 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en.h
@@ -171,10 +171,12 @@ extern const char mlx5e_self_tests[][ETH_GSTRING_LEN];
static const char mlx5e_priv_flags[][ETH_GSTRING_LEN] = {
"rx_cqe_moder",
+ "rx_cqe_compress",
};
enum mlx5e_priv_flag {
MLX5E_PFLAG_RX_CQE_BASED_MODER = (1 << 0),
+ MLX5E_PFLAG_RX_CQE_COMPRESS = (1 << 1),
};
#define MLX5E_SET_PFLAG(priv, pflag, enable) \
@@ -205,8 +207,7 @@ struct mlx5e_params {
u16 num_channels;
u8 num_tc;
u8 rx_cq_period_mode;
- bool rx_cqe_compress_admin;
- bool rx_cqe_compress;
+ bool rx_cqe_compress_def;
struct mlx5e_cq_moder rx_cq_moderation;
struct mlx5e_cq_moder tx_cq_moderation;
u16 min_rx_wqes;
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_clock.c b/drivers/net/ethernet/mellanox/mlx5/core/en_clock.c
index 13dc388..2cd8e56 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_clock.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_clock.c
@@ -94,7 +94,7 @@ int mlx5e_hwstamp_set(struct net_device *dev, struct ifreq *ifr)
switch (config.rx_filter) {
case HWTSTAMP_FILTER_NONE:
/* Reset CQE compression to Admin default */
- mlx5e_modify_rx_cqe_compression(priv, priv->params.rx_cqe_compress_admin);
+ mlx5e_modify_rx_cqe_compression(priv, priv->params.rx_cqe_compress_def);
break;
case HWTSTAMP_FILTER_ALL:
case HWTSTAMP_FILTER_SOME:
@@ -111,6 +111,7 @@ int mlx5e_hwstamp_set(struct net_device *dev, struct ifreq *ifr)
case HWTSTAMP_FILTER_PTP_V2_SYNC:
case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ:
/* Disable CQE compression */
+ netdev_warn(dev, "Disabling cqe compression");
mlx5e_modify_rx_cqe_compression(priv, false);
config.rx_filter = HWTSTAMP_FILTER_ALL;
break;
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c b/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c
index d2bdccb..aa963d7 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c
@@ -1481,6 +1481,35 @@ static int set_pflag_rx_cqe_based_moder(struct net_device *netdev, bool enable)
return err;
}
+static int set_pflag_rx_cqe_compress(struct net_device *netdev,
+ bool enable)
+{
+ struct mlx5e_priv *priv = netdev_priv(netdev);
+ struct mlx5_core_dev *mdev = priv->mdev;
+ int err = 0;
+ bool reset;
+
+ if (!MLX5_CAP_GEN(mdev, cqe_compression))
+ return -ENOTSUPP;
+
+ if (enable && priv->tstamp.hwtstamp_config.rx_filter != HWTSTAMP_FILTER_NONE) {
+ netdev_err(netdev, "Can't enable cqe compression while timestamping is enabled.\n");
+ return -EINVAL;
+ }
+
+ reset = test_bit(MLX5E_STATE_OPENED, &priv->state);
+
+ if (reset)
+ mlx5e_close_locked(netdev);
+
+ MLX5E_SET_PFLAG(priv, MLX5E_PFLAG_RX_CQE_COMPRESS, enable);
+ priv->params.rx_cqe_compress_def = enable;
+
+ if (reset)
+ err = mlx5e_open_locked(netdev);
+ return err;
+}
+
static int mlx5e_handle_pflag(struct net_device *netdev,
u32 wanted_flags,
enum mlx5e_priv_flag flag,
@@ -1511,13 +1540,19 @@ static int mlx5e_set_priv_flags(struct net_device *netdev, u32 pflags)
int err;
mutex_lock(&priv->state_lock);
-
err = mlx5e_handle_pflag(netdev, pflags,
MLX5E_PFLAG_RX_CQE_BASED_MODER,
set_pflag_rx_cqe_based_moder);
+ if (err)
+ goto out;
+ err = mlx5e_handle_pflag(netdev, pflags,
+ MLX5E_PFLAG_RX_CQE_COMPRESS,
+ set_pflag_rx_cqe_compress);
+
+out:
mutex_unlock(&priv->state_lock);
- return err ? -EINVAL : 0;
+ return err;
}
static u32 mlx5e_get_priv_flags(struct net_device *netdev)
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
index 004940a..6b492ca 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
@@ -84,7 +84,8 @@ static void mlx5e_set_rq_type_params(struct mlx5e_priv *priv, u8 rq_type)
switch (priv->params.rq_wq_type) {
case MLX5_WQ_TYPE_LINKED_LIST_STRIDING_RQ:
priv->params.log_rq_size = MLX5E_PARAMS_DEFAULT_LOG_RQ_SIZE_MPW;
- priv->params.mpwqe_log_stride_sz = priv->params.rx_cqe_compress ?
+ priv->params.mpwqe_log_stride_sz =
+ MLX5E_GET_PFLAG(priv, MLX5E_PFLAG_RX_CQE_COMPRESS) ?
MLX5_MPWRQ_LOG_STRIDE_SIZE_CQE_COMPRESS :
MLX5_MPWRQ_LOG_STRIDE_SIZE;
priv->params.mpwqe_log_num_strides = MLX5_MPWRQ_LOG_WQE_SZ -
@@ -101,7 +102,7 @@ static void mlx5e_set_rq_type_params(struct mlx5e_priv *priv, u8 rq_type)
priv->params.rq_wq_type == MLX5_WQ_TYPE_LINKED_LIST_STRIDING_RQ,
BIT(priv->params.log_rq_size),
BIT(priv->params.mpwqe_log_stride_sz),
- priv->params.rx_cqe_compress_admin);
+ MLX5E_GET_PFLAG(priv, MLX5E_PFLAG_RX_CQE_COMPRESS));
}
static void mlx5e_set_rq_priv_params(struct mlx5e_priv *priv)
@@ -1664,7 +1665,7 @@ static void mlx5e_build_rx_cq_param(struct mlx5e_priv *priv,
}
MLX5_SET(cqc, cqc, log_cq_size, log_cq_size);
- if (priv->params.rx_cqe_compress) {
+ if (MLX5E_GET_PFLAG(priv, MLX5E_PFLAG_RX_CQE_COMPRESS)) {
MLX5_SET(cqc, cqc, mini_cqe_res_format, MLX5_CQE_FORMAT_CSUM);
MLX5_SET(cqc, cqc, cqe_comp_en, 1);
}
@@ -3447,17 +3448,16 @@ static void mlx5e_build_nic_netdev_priv(struct mlx5_core_dev *mdev,
priv->params.log_sq_size = MLX5E_PARAMS_DEFAULT_LOG_SQ_SIZE;
/* set CQE compression */
- priv->params.rx_cqe_compress_admin = false;
+ priv->params.rx_cqe_compress_def = false;
if (MLX5_CAP_GEN(mdev, cqe_compression) &&
MLX5_CAP_GEN(mdev, vport_group_manager)) {
mlx5e_get_max_linkspeed(mdev, &link_speed);
mlx5e_get_pci_bw(mdev, &pci_bw);
mlx5_core_dbg(mdev, "Max link speed = %d, PCI BW = %d\n",
link_speed, pci_bw);
- priv->params.rx_cqe_compress_admin =
+ priv->params.rx_cqe_compress_def =
cqe_compress_heuristic(link_speed, pci_bw);
}
- priv->params.rx_cqe_compress = priv->params.rx_cqe_compress_admin;
mlx5e_set_rq_priv_params(priv);
if (priv->params.rq_wq_type == MLX5_WQ_TYPE_LINKED_LIST_STRIDING_RQ)
@@ -3490,6 +3490,7 @@ static void mlx5e_build_nic_netdev_priv(struct mlx5_core_dev *mdev,
/* Initialize pflags */
MLX5E_SET_PFLAG(priv, MLX5E_PFLAG_RX_CQE_BASED_MODER,
priv->params.rx_cq_period_mode == MLX5_CQ_PERIOD_MODE_START_FROM_CQE);
+ MLX5E_SET_PFLAG(priv, MLX5E_PFLAG_RX_CQE_COMPRESS, priv->params.rx_cqe_compress_def);
mutex_init(&priv->state_lock);
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c b/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c
index c6de6fb..b036710 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c
@@ -164,14 +164,14 @@ void mlx5e_modify_rx_cqe_compression(struct mlx5e_priv *priv, bool val)
mutex_lock(&priv->state_lock);
- if (priv->params.rx_cqe_compress == val)
+ if (MLX5E_GET_PFLAG(priv, MLX5E_PFLAG_RX_CQE_COMPRESS) == val)
goto unlock;
was_opened = test_bit(MLX5E_STATE_OPENED, &priv->state);
if (was_opened)
mlx5e_close_locked(priv->netdev);
- priv->params.rx_cqe_compress = val;
+ MLX5E_SET_PFLAG(priv, MLX5E_PFLAG_RX_CQE_COMPRESS, val);
if (was_opened)
mlx5e_open_locked(priv->netdev);
--
2.7.4
^ permalink raw reply related
* [PATCH net-next 07/10] net/mlx5e: Add support for ethtool self diagnostics test
From: Saeed Mahameed @ 2016-11-26 14:18 UTC (permalink / raw)
To: David S. Miller; +Cc: netdev, Kamal Heib, Saeed Mahameed
In-Reply-To: <1480169914-22347-1-git-send-email-saeedm@mellanox.com>
From: Kamal Heib <kamalh@mellanox.com>
The self diagnostics test implementaion include the following features:
1. Link Test: Check that link is in up state.
2. Speed Test: Check that link was negotiated correctly.
3. Health Test: Check the device health.
Signed-off-by: Kamal Heib <kamalh@mellanox.com>
Signed-off-by: Saeed Mahameed <saeedm@mellanox.com>
---
drivers/net/ethernet/mellanox/mlx5/core/Makefile | 2 +-
drivers/net/ethernet/mellanox/mlx5/core/en.h | 5 +
.../net/ethernet/mellanox/mlx5/core/en_ethtool.c | 8 +-
.../net/ethernet/mellanox/mlx5/core/en_selftest.c | 126 +++++++++++++++++++++
4 files changed, 139 insertions(+), 2 deletions(-)
create mode 100644 drivers/net/ethernet/mellanox/mlx5/core/en_selftest.c
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/Makefile b/drivers/net/ethernet/mellanox/mlx5/core/Makefile
index 0343725..9f43beb 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/Makefile
+++ b/drivers/net/ethernet/mellanox/mlx5/core/Makefile
@@ -8,6 +8,6 @@ mlx5_core-y := main.o cmd.o debugfs.o fw.o eq.o uar.o pagealloc.o \
mlx5_core-$(CONFIG_MLX5_CORE_EN) += wq.o eswitch.o eswitch_offloads.o \
en_main.o en_common.o en_fs.o en_ethtool.o en_tx.o \
en_rx.o en_rx_am.o en_txrx.o en_clock.o vxlan.o \
- en_tc.o en_arfs.o en_rep.o en_fs_ethtool.o
+ en_tc.o en_arfs.o en_rep.o en_fs_ethtool.o en_selftest.o
mlx5_core-$(CONFIG_MLX5_CORE_EN_DCB) += en_dcbnl.o
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en.h b/drivers/net/ethernet/mellanox/mlx5/core/en.h
index 6c954cd..f7bb4a7 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en.h
@@ -167,6 +167,8 @@ struct mlx5e_umr_wqe {
struct mlx5_wqe_data_seg data;
};
+extern const char mlx5e_self_tests[][ETH_GSTRING_LEN];
+
static const char mlx5e_priv_flags[][ETH_GSTRING_LEN] = {
"rx_cqe_moder",
};
@@ -754,6 +756,9 @@ int mlx5e_create_flow_steering(struct mlx5e_priv *priv);
void mlx5e_destroy_flow_steering(struct mlx5e_priv *priv);
void mlx5e_init_l2_addr(struct mlx5e_priv *priv);
void mlx5e_destroy_flow_table(struct mlx5e_flow_table *ft);
+int mlx5e_self_test_num(struct mlx5e_priv *priv);
+void mlx5e_self_test(struct net_device *ndev, struct ethtool_test *etest,
+ u64 *buf);
int mlx5e_ethtool_get_flow(struct mlx5e_priv *priv, struct ethtool_rxnfc *info,
int location);
int mlx5e_ethtool_get_all_flows(struct mlx5e_priv *priv,
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c b/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c
index 9ea7b37..839c4e9 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c
@@ -180,6 +180,8 @@ static int mlx5e_get_sset_count(struct net_device *dev, int sset)
case ETH_SS_PRIV_FLAGS:
return ARRAY_SIZE(mlx5e_priv_flags);
+ case ETH_SS_TEST:
+ return mlx5e_self_test_num(priv);
/* fallthrough */
default:
return -EOPNOTSUPP;
@@ -286,6 +288,9 @@ static void mlx5e_get_strings(struct net_device *dev,
break;
case ETH_SS_TEST:
+ for (i = 0; i < mlx5e_self_test_num(priv); i++)
+ strcpy(data + i * ETH_GSTRING_LEN,
+ mlx5e_self_tests[i]);
break;
case ETH_SS_STATS:
@@ -1573,5 +1578,6 @@ const struct ethtool_ops mlx5e_ethtool_ops = {
.get_module_info = mlx5e_get_module_info,
.get_module_eeprom = mlx5e_get_module_eeprom,
.get_priv_flags = mlx5e_get_priv_flags,
- .set_priv_flags = mlx5e_set_priv_flags
+ .set_priv_flags = mlx5e_set_priv_flags,
+ .self_test = mlx5e_self_test,
};
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_selftest.c b/drivers/net/ethernet/mellanox/mlx5/core/en_selftest.c
new file mode 100644
index 0000000..a25dfc5
--- /dev/null
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_selftest.c
@@ -0,0 +1,126 @@
+/*
+ * Copyright (c) 2016, Mellanox Technologies, Ltd. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "en.h"
+
+enum {
+ MLX5E_ST_LINK_STATE,
+ MLX5E_ST_LINK_SPEED,
+ MLX5E_ST_HEALTH_INFO,
+ MLX5E_ST_NUM,
+};
+
+const char mlx5e_self_tests[MLX5E_ST_NUM][ETH_GSTRING_LEN] = {
+ "Link Test",
+ "Speed Test",
+ "Health Test",
+};
+
+int mlx5e_self_test_num(struct mlx5e_priv *priv)
+{
+ return ARRAY_SIZE(mlx5e_self_tests);
+}
+
+static int mlx5e_test_health_info(struct mlx5e_priv *priv)
+{
+ struct mlx5_core_health *health = &priv->mdev->priv.health;
+
+ return health->sick ? 1 : 0;
+}
+
+static int mlx5e_test_link_state(struct mlx5e_priv *priv)
+{
+ u8 port_state;
+
+ if (!netif_carrier_ok(priv->netdev))
+ return 1;
+
+ port_state = mlx5_query_vport_state(priv->mdev, MLX5_QUERY_VPORT_STATE_IN_OP_MOD_VNIC_VPORT, 0);
+ return port_state == VPORT_STATE_UP ? 0 : 1;
+}
+
+static int mlx5e_test_link_speed(struct mlx5e_priv *priv)
+{
+ u32 out[MLX5_ST_SZ_DW(ptys_reg)];
+ u32 eth_proto_oper;
+ int i;
+
+ if (!netif_carrier_ok(priv->netdev))
+ return 1;
+
+ if (mlx5_query_port_ptys(priv->mdev, out, sizeof(out), MLX5_PTYS_EN, 1))
+ return 1;
+
+ eth_proto_oper = MLX5_GET(ptys_reg, out, eth_proto_oper);
+ for (i = 0; i < MLX5E_LINK_MODES_NUMBER; i++) {
+ if (eth_proto_oper & MLX5E_PROT_MASK(i))
+ return 0;
+ }
+ return 1;
+}
+
+int (*mlx5e_st_func[MLX5E_ST_NUM])(struct mlx5e_priv *) = {
+ mlx5e_test_link_state,
+ mlx5e_test_link_speed,
+ mlx5e_test_health_info,
+};
+
+void mlx5e_self_test(struct net_device *ndev, struct ethtool_test *etest,
+ u64 *buf)
+{
+ struct mlx5e_priv *priv = netdev_priv(ndev);
+ int i;
+
+ memset(buf, 0, sizeof(u64) * MLX5E_ST_NUM);
+
+ mutex_lock(&priv->state_lock);
+ netdev_info(ndev, "Self test begin..\n");
+
+ for (i = 0; i < MLX5E_ST_NUM; i++) {
+ netdev_info(ndev, "\t[%d] %s start..\n",
+ i, mlx5e_self_tests[i]);
+ buf[i] = mlx5e_st_func[i](priv);
+ netdev_info(ndev, "\t[%d] %s end: result(%lld)\n",
+ i, mlx5e_self_tests[i], buf[i]);
+ }
+
+ mutex_unlock(&priv->state_lock);
+
+ for (i = 0; i < MLX5E_ST_NUM; i++) {
+ if (buf[i]) {
+ etest->flags |= ETH_TEST_FL_FAILED;
+ break;
+ }
+ }
+ netdev_info(ndev, "Self test out: status flags(0x%x)\n",
+ etest->flags);
+}
--
2.7.4
^ permalink raw reply related
* [PATCH net-next 00/10] Mellanox 100G mlx5 DCBX and ethtool updates
From: Saeed Mahameed @ 2016-11-26 14:18 UTC (permalink / raw)
To: David S. Miller; +Cc: netdev, Saeed Mahameed
Hi Dave,
This series provides the following mlx5 updates:
>From Huy:
DCBX CEE API and DCBX firmware/host modes support.
- 1st patch ensures the dcbnl_rtnl_ops is published only when the qos
capability bits is on.
- 2nd patch adds the support for CEE interfaces into mlx5 dcbnl_rtnl_ops
- 3rd patch refactors ETS query to read ETS configuration directly from
firmware rather than having a software shadow to it. The existing IEEE
interfaces stays the same.
- 4th patch adds the support for MLX5_REG_DCBX_PARAM and MLX5_REG_DCBX_APP
firmware commands to manipulate mlx5 DCBX mode.
- 5th patch adds the driver support for the new DCBX firmware. This ensures
the backward compatibility versus the old and new firmware. With the new DCBX
firmware, qos settings can be controlled by either firmware or software
depending on the DCBX mode.
>From Kamal and Saeed:
- mlx5 self-test support.
>From Shaker:
- Private flag to give the user the ability to enable/disable mlx5 CQE
compression.
This series was generated against commit:
e5f12b3f5ebb ("Merge branch 'mlxsw-trap-groups-and-policers'")
Thenks
Saeed.
Huy Nguyen (6):
net/mlx5e: Add qos capability check
net/mlx5e: Support DCBX CEE API
net/mlx5e: Read ETS settings directly from firmware
net/mlx5: Add DCBX firmware commands support
net/mlx5e: ConnectX-4 firmware support for DCBX
net/mlx5e: Add DCBX control interface
Kamal Heib (1):
net/mlx5e: Add support for ethtool self diagnostics test
Saeed Mahameed (1):
net/mlx5e: Add support for loopback selftest
Shaker Daibes (2):
net/mlx5e: Moves pflags to priv->params
net/mlx5e: Add CQE compression user control
drivers/net/ethernet/mellanox/mlx5/core/Makefile | 2 +-
drivers/net/ethernet/mellanox/mlx5/core/en.h | 61 ++-
drivers/net/ethernet/mellanox/mlx5/core/en_clock.c | 3 +-
.../net/ethernet/mellanox/mlx5/core/en_common.c | 7 +-
drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c | 449 ++++++++++++++++++++-
.../net/ethernet/mellanox/mlx5/core/en_ethtool.c | 53 ++-
drivers/net/ethernet/mellanox/mlx5/core/en_main.c | 46 +--
drivers/net/ethernet/mellanox/mlx5/core/en_rx.c | 4 +-
.../net/ethernet/mellanox/mlx5/core/en_selftest.c | 344 ++++++++++++++++
drivers/net/ethernet/mellanox/mlx5/core/port.c | 63 +++
include/linux/mlx5/driver.h | 7 +
include/linux/mlx5/port.h | 6 +
12 files changed, 980 insertions(+), 65 deletions(-)
create mode 100644 drivers/net/ethernet/mellanox/mlx5/core/en_selftest.c
--
2.7.4
^ permalink raw reply
* [PATCH net-next 01/10] net/mlx5e: Add qos capability check
From: Saeed Mahameed @ 2016-11-26 14:18 UTC (permalink / raw)
To: David S. Miller; +Cc: netdev, Huy Nguyen, Saeed Mahameed
In-Reply-To: <1480169914-22347-1-git-send-email-saeedm@mellanox.com>
From: Huy Nguyen <huyn@mellanox.com>
Make sure firmware supports qos before exposing the DCB API.
Signed-off-by: Huy Nguyen <huyn@mellanox.com>
Signed-off-by: Saeed Mahameed <saeedm@mellanox.com>
---
drivers/net/ethernet/mellanox/mlx5/core/en_main.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
index 19403d6..2b42112 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
@@ -3549,7 +3549,8 @@ static void mlx5e_build_nic_netdev(struct net_device *netdev)
if (MLX5_CAP_GEN(mdev, vport_group_manager)) {
netdev->netdev_ops = &mlx5e_netdev_ops_sriov;
#ifdef CONFIG_MLX5_CORE_EN_DCB
- netdev->dcbnl_ops = &mlx5e_dcbnl_ops;
+ if (MLX5_CAP_GEN(mdev, qos))
+ netdev->dcbnl_ops = &mlx5e_dcbnl_ops;
#endif
} else {
netdev->netdev_ops = &mlx5e_netdev_ops_basic;
--
2.7.4
^ permalink raw reply related
* [PATCH net-next 04/10] net/mlx5: Add DCBX firmware commands support
From: Saeed Mahameed @ 2016-11-26 14:18 UTC (permalink / raw)
To: David S. Miller; +Cc: netdev, Huy Nguyen, Saeed Mahameed
In-Reply-To: <1480169914-22347-1-git-send-email-saeedm@mellanox.com>
From: Huy Nguyen <huyn@mellanox.com>
Add set/query commands for DCBX_PARAM register
Signed-off-by: Huy Nguyen <huyn@mellanox.com>
Signed-off-by: Saeed Mahameed <saeedm@mellanox.com>
---
drivers/net/ethernet/mellanox/mlx5/core/port.c | 20 ++++++++++++++++++++
include/linux/mlx5/driver.h | 7 +++++++
include/linux/mlx5/port.h | 2 ++
3 files changed, 29 insertions(+)
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/port.c b/drivers/net/ethernet/mellanox/mlx5/core/port.c
index ed4898f..d2ec9d2 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/port.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/port.c
@@ -548,6 +548,26 @@ int mlx5_max_tc(struct mlx5_core_dev *mdev)
return num_tc - 1;
}
+int mlx5_query_port_dcbx_param(struct mlx5_core_dev *mdev, u32 *out)
+{
+ u32 in[MLX5_ST_SZ_DW(dcbx_param)] = {0};
+
+ MLX5_SET(dcbx_param, in, port_number, 1);
+
+ return mlx5_core_access_reg(mdev, in, sizeof(in), out,
+ sizeof(in), MLX5_REG_DCBX_PARAM, 0, 0);
+}
+
+int mlx5_set_port_dcbx_param(struct mlx5_core_dev *mdev, u32 *in)
+{
+ u32 out[MLX5_ST_SZ_DW(dcbx_param)];
+
+ MLX5_SET(dcbx_param, in, port_number, 1);
+
+ return mlx5_core_access_reg(mdev, in, sizeof(out), out,
+ sizeof(out), MLX5_REG_DCBX_PARAM, 0, 1);
+}
+
int mlx5_set_port_prio_tc(struct mlx5_core_dev *mdev, u8 *prio_tc)
{
u32 in[MLX5_ST_SZ_DW(qtct_reg)] = {0};
diff --git a/include/linux/mlx5/driver.h b/include/linux/mlx5/driver.h
index ae1f451..68b85ef 100644
--- a/include/linux/mlx5/driver.h
+++ b/include/linux/mlx5/driver.h
@@ -104,6 +104,8 @@ enum {
enum {
MLX5_REG_QETCR = 0x4005,
MLX5_REG_QTCT = 0x400a,
+ MLX5_REG_DCBX_PARAM = 0x4020,
+ MLX5_REG_DCBX_APP = 0x4021,
MLX5_REG_PCAP = 0x5001,
MLX5_REG_PMTU = 0x5003,
MLX5_REG_PTYS = 0x5004,
@@ -124,6 +126,11 @@ enum {
MLX5_REG_MPCNT = 0x9051,
};
+enum mlx5_dcbx_oper_mode {
+ MLX5E_DCBX_PARAM_VER_OPER_HOST = 0x0,
+ MLX5E_DCBX_PARAM_VER_OPER_AUTO = 0x3,
+};
+
enum {
MLX5_ATOMIC_OPS_CMP_SWAP = 1 << 0,
MLX5_ATOMIC_OPS_FETCH_ADD = 1 << 1,
diff --git a/include/linux/mlx5/port.h b/include/linux/mlx5/port.h
index bdee439..e527732 100644
--- a/include/linux/mlx5/port.h
+++ b/include/linux/mlx5/port.h
@@ -162,4 +162,6 @@ void mlx5_query_port_fcs(struct mlx5_core_dev *mdev, bool *supported,
int mlx5_query_module_eeprom(struct mlx5_core_dev *dev,
u16 offset, u16 size, u8 *data);
+int mlx5_query_port_dcbx_param(struct mlx5_core_dev *mdev, u32 *out);
+int mlx5_set_port_dcbx_param(struct mlx5_core_dev *mdev, u32 *in);
#endif /* __MLX5_PORT_H__ */
--
2.7.4
^ permalink raw reply related
* [PATCH net-next 02/10] net/mlx5e: Support DCBX CEE API
From: Saeed Mahameed @ 2016-11-26 14:18 UTC (permalink / raw)
To: David S. Miller; +Cc: netdev, Huy Nguyen, Saeed Mahameed
In-Reply-To: <1480169914-22347-1-git-send-email-saeedm@mellanox.com>
From: Huy Nguyen <huyn@mellanox.com>
Add DCBX CEE API interface for ConnectX-4. Configurations are stored in
a temporary structure and are applied to the card's firmware when
the CEE's setall callback function is called.
Note:
priority group in CEE is equivalent to traffic class in ConnectX-4
hardware spec.
bw allocation per priority in CEE is not supported because ConnectX-4
only supports bw allocation per traffic class.
user priority in CEE does not have an equivalent term in ConnectX-4.
Therefore, user priority to priority mapping in CEE is not supported.
Signed-off-by: Huy Nguyen <huyn@mellanox.com>
Signed-off-by: Saeed Mahameed <saeedm@mellanox.com>
---
drivers/net/ethernet/mellanox/mlx5/core/en.h | 24 ++
drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c | 301 ++++++++++++++++++++-
drivers/net/ethernet/mellanox/mlx5/core/port.c | 43 +++
include/linux/mlx5/port.h | 4 +
4 files changed, 370 insertions(+), 2 deletions(-)
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en.h b/drivers/net/ethernet/mellanox/mlx5/core/en.h
index a2b32ed..31387ed 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en.h
@@ -221,6 +221,26 @@ struct mlx5e_params {
u32 lro_timeout;
};
+#ifdef CONFIG_MLX5_CORE_EN_DCB
+struct mlx5e_cee_config {
+ /* bw pct for priority group */
+ u8 pg_bw_pct[CEE_DCBX_MAX_PGS];
+ u8 prio_to_pg_map[CEE_DCBX_MAX_PRIO];
+ bool pfc_setting[CEE_DCBX_MAX_PRIO];
+ bool pfc_enable;
+};
+
+enum {
+ MLX5_DCB_CHG_RESET,
+ MLX5_DCB_NO_CHG,
+ MLX5_DCB_CHG_NO_RESET,
+};
+
+struct mlx5e_dcbx {
+ struct mlx5e_cee_config cee_cfg; /* pending configuration */
+};
+#endif
+
struct mlx5e_tstamp {
rwlock_t lock;
struct cyclecounter cycles;
@@ -688,6 +708,10 @@ struct mlx5e_priv {
struct mlx5e_stats stats;
struct mlx5e_tstamp tstamp;
u16 q_counter;
+#ifdef CONFIG_MLX5_CORE_EN_DCB
+ struct mlx5e_dcbx dcbx;
+#endif
+
const struct mlx5e_profile *profile;
void *ppriv;
};
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c b/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c
index 762af16..0595243 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c
@@ -38,6 +38,9 @@
#define MLX5E_100MB (100000)
#define MLX5E_1GB (1000000)
+#define MLX5E_CEE_STATE_UP 1
+#define MLX5E_CEE_STATE_DOWN 0
+
static int mlx5e_dcbnl_ieee_getets(struct net_device *netdev,
struct ieee_ets *ets)
{
@@ -222,13 +225,15 @@ static int mlx5e_dcbnl_ieee_setpfc(struct net_device *dev,
static u8 mlx5e_dcbnl_getdcbx(struct net_device *dev)
{
- return DCB_CAP_DCBX_HOST | DCB_CAP_DCBX_VER_IEEE;
+ return DCB_CAP_DCBX_HOST |
+ DCB_CAP_DCBX_VER_IEEE |
+ DCB_CAP_DCBX_VER_CEE;
}
static u8 mlx5e_dcbnl_setdcbx(struct net_device *dev, u8 mode)
{
if ((mode & DCB_CAP_DCBX_LLD_MANAGED) ||
- (mode & DCB_CAP_DCBX_VER_CEE) ||
+ !(mode & DCB_CAP_DCBX_VER_CEE) ||
!(mode & DCB_CAP_DCBX_VER_IEEE) ||
!(mode & DCB_CAP_DCBX_HOST))
return 1;
@@ -304,6 +309,281 @@ static int mlx5e_dcbnl_ieee_setmaxrate(struct net_device *netdev,
return mlx5_modify_port_ets_rate_limit(mdev, max_bw_value, max_bw_unit);
}
+static u8 mlx5e_dcbnl_setall(struct net_device *netdev)
+{
+ struct mlx5e_priv *priv = netdev_priv(netdev);
+ struct mlx5e_cee_config *cee_cfg = &priv->dcbx.cee_cfg;
+ struct mlx5_core_dev *mdev = priv->mdev;
+ struct ieee_ets ets;
+ struct ieee_pfc pfc;
+ int err;
+ int i;
+
+ memset(&ets, 0, sizeof(ets));
+ memset(&pfc, 0, sizeof(pfc));
+
+ ets.ets_cap = IEEE_8021QAZ_MAX_TCS;
+ for (i = 0; i < CEE_DCBX_MAX_PGS; i++) {
+ ets.tc_tx_bw[i] = cee_cfg->pg_bw_pct[i];
+ ets.tc_rx_bw[i] = cee_cfg->pg_bw_pct[i];
+ ets.tc_tsa[i] = IEEE_8021QAZ_TSA_ETS;
+ ets.prio_tc[i] = cee_cfg->prio_to_pg_map[i];
+ }
+
+ err = mlx5e_dbcnl_validate_ets(netdev, &ets);
+ if (err) {
+ netdev_err(netdev,
+ "%s, Failed to validate ETS: %d\n", __func__, err);
+ goto out;
+ }
+
+ err = mlx5e_dcbnl_ieee_setets_core(priv, &ets);
+ if (err) {
+ netdev_err(netdev,
+ "%s, Failed to set ETS: %d\n", __func__, err);
+ goto out;
+ }
+
+ /* Set PFC */
+ pfc.pfc_cap = mlx5_max_tc(mdev) + 1;
+ if (!cee_cfg->pfc_enable)
+ pfc.pfc_en = 0;
+ else
+ for (i = 0; i < CEE_DCBX_MAX_PRIO; i++)
+ pfc.pfc_en |= cee_cfg->pfc_setting[i] << i;
+
+ err = mlx5e_dcbnl_ieee_setpfc(netdev, &pfc);
+ if (err) {
+ netdev_err(netdev,
+ "%s, Failed to set PFC: %d\n", __func__, err);
+ goto out;
+ }
+out:
+ return err ? MLX5_DCB_NO_CHG : MLX5_DCB_CHG_RESET;
+}
+
+static u8 mlx5e_dcbnl_getstate(struct net_device *netdev)
+{
+ return MLX5E_CEE_STATE_UP;
+}
+
+static void mlx5e_dcbnl_getpermhwaddr(struct net_device *netdev,
+ u8 *perm_addr)
+{
+ struct mlx5e_priv *priv = netdev_priv(netdev);
+
+ if (!perm_addr)
+ return;
+
+ mlx5_query_nic_vport_mac_address(priv->mdev, 0, perm_addr);
+}
+
+static void mlx5e_dcbnl_setpgtccfgtx(struct net_device *netdev,
+ int priority, u8 prio_type,
+ u8 pgid, u8 bw_pct, u8 up_map)
+{
+ struct mlx5e_priv *priv = netdev_priv(netdev);
+ struct mlx5e_cee_config *cee_cfg = &priv->dcbx.cee_cfg;
+
+ if (priority >= CEE_DCBX_MAX_PRIO) {
+ netdev_err(netdev,
+ "%s, priority is out of range\n", __func__);
+ return;
+ }
+
+ if (pgid >= CEE_DCBX_MAX_PGS) {
+ netdev_err(netdev,
+ "%s, priority group is out of range\n", __func__);
+ return;
+ }
+
+ cee_cfg->prio_to_pg_map[priority] = pgid;
+}
+
+static void mlx5e_dcbnl_setpgbwgcfgtx(struct net_device *netdev,
+ int pgid, u8 bw_pct)
+{
+ struct mlx5e_priv *priv = netdev_priv(netdev);
+ struct mlx5e_cee_config *cee_cfg = &priv->dcbx.cee_cfg;
+
+ if (pgid >= CEE_DCBX_MAX_PGS) {
+ netdev_err(netdev,
+ "%s, priority group is out of range\n", __func__);
+ return;
+ }
+
+ cee_cfg->pg_bw_pct[pgid] = bw_pct;
+}
+
+static void mlx5e_dcbnl_getpgtccfgtx(struct net_device *netdev,
+ int priority, u8 *prio_type,
+ u8 *pgid, u8 *bw_pct, u8 *up_map)
+{
+ struct mlx5e_priv *priv = netdev_priv(netdev);
+ struct mlx5_core_dev *mdev = priv->mdev;
+
+ if (priority >= CEE_DCBX_MAX_PRIO) {
+ netdev_err(netdev,
+ "%s, priority is out of range\n", __func__);
+ return;
+ }
+
+ *prio_type = 0;
+ *bw_pct = 0;
+ *up_map = 0;
+
+ if (mlx5_query_port_prio_tc(mdev, priority, pgid))
+ *pgid = 0;
+}
+
+static void mlx5e_dcbnl_getpgbwgcfgtx(struct net_device *netdev,
+ int pgid, u8 *bw_pct)
+{
+ struct mlx5e_priv *priv = netdev_priv(netdev);
+ struct mlx5_core_dev *mdev = priv->mdev;
+
+ if (pgid >= CEE_DCBX_MAX_PGS) {
+ netdev_err(netdev,
+ "%s, priority group is out of range\n", __func__);
+ return;
+ }
+
+ if (mlx5_query_port_tc_bw_alloc(mdev, pgid, bw_pct))
+ *bw_pct = 0;
+}
+
+static void mlx5e_dcbnl_setpfccfg(struct net_device *netdev,
+ int priority, u8 setting)
+{
+ struct mlx5e_priv *priv = netdev_priv(netdev);
+ struct mlx5e_cee_config *cee_cfg = &priv->dcbx.cee_cfg;
+
+ if (priority >= CEE_DCBX_MAX_PRIO) {
+ netdev_err(netdev,
+ "%s, priority is out of range\n", __func__);
+ return;
+ }
+
+ if (setting > 1)
+ return;
+
+ cee_cfg->pfc_setting[priority] = setting;
+}
+
+static int
+mlx5e_dcbnl_get_priority_pfc(struct net_device *netdev,
+ int priority, u8 *setting)
+{
+ struct ieee_pfc pfc;
+ int err;
+
+ err = mlx5e_dcbnl_ieee_getpfc(netdev, &pfc);
+
+ if (err)
+ *setting = 0;
+ else
+ *setting = (pfc.pfc_en >> priority) & 0x01;
+
+ return err;
+}
+
+static void mlx5e_dcbnl_getpfccfg(struct net_device *netdev,
+ int priority, u8 *setting)
+{
+ if (priority >= CEE_DCBX_MAX_PRIO) {
+ netdev_err(netdev,
+ "%s, priority is out of range\n", __func__);
+ return;
+ }
+
+ if (!setting)
+ return;
+
+ mlx5e_dcbnl_get_priority_pfc(netdev, priority, setting);
+}
+
+static u8 mlx5e_dcbnl_getcap(struct net_device *netdev,
+ int capid, u8 *cap)
+{
+ struct mlx5e_priv *priv = netdev_priv(netdev);
+ struct mlx5_core_dev *mdev = priv->mdev;
+ u8 rval = 0;
+
+ switch (capid) {
+ case DCB_CAP_ATTR_PG:
+ *cap = true;
+ break;
+ case DCB_CAP_ATTR_PFC:
+ *cap = true;
+ break;
+ case DCB_CAP_ATTR_UP2TC:
+ *cap = false;
+ break;
+ case DCB_CAP_ATTR_PG_TCS:
+ *cap = 1 << mlx5_max_tc(mdev);
+ break;
+ case DCB_CAP_ATTR_PFC_TCS:
+ *cap = 1 << mlx5_max_tc(mdev);
+ break;
+ case DCB_CAP_ATTR_GSP:
+ *cap = false;
+ break;
+ case DCB_CAP_ATTR_BCN:
+ *cap = false;
+ break;
+ case DCB_CAP_ATTR_DCBX:
+ *cap = (DCB_CAP_DCBX_LLD_MANAGED |
+ DCB_CAP_DCBX_VER_CEE |
+ DCB_CAP_DCBX_STATIC);
+ break;
+ default:
+ *cap = 0;
+ rval = 1;
+ break;
+ }
+
+ return rval;
+}
+
+static int mlx5e_dcbnl_getnumtcs(struct net_device *netdev,
+ int tcs_id, u8 *num)
+{
+ struct mlx5e_priv *priv = netdev_priv(netdev);
+ struct mlx5_core_dev *mdev = priv->mdev;
+
+ switch (tcs_id) {
+ case DCB_NUMTCS_ATTR_PG:
+ case DCB_NUMTCS_ATTR_PFC:
+ *num = mlx5_max_tc(mdev) + 1;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static u8 mlx5e_dcbnl_getpfcstate(struct net_device *netdev)
+{
+ struct ieee_pfc pfc;
+
+ if (mlx5e_dcbnl_ieee_getpfc(netdev, &pfc))
+ return MLX5E_CEE_STATE_DOWN;
+
+ return pfc.pfc_en ? MLX5E_CEE_STATE_UP : MLX5E_CEE_STATE_DOWN;
+}
+
+static void mlx5e_dcbnl_setpfcstate(struct net_device *netdev, u8 state)
+{
+ struct mlx5e_priv *priv = netdev_priv(netdev);
+ struct mlx5e_cee_config *cee_cfg = &priv->dcbx.cee_cfg;
+
+ if ((state != MLX5E_CEE_STATE_UP) && (state != MLX5E_CEE_STATE_DOWN))
+ return;
+
+ cee_cfg->pfc_enable = state;
+}
+
const struct dcbnl_rtnl_ops mlx5e_dcbnl_ops = {
.ieee_getets = mlx5e_dcbnl_ieee_getets,
.ieee_setets = mlx5e_dcbnl_ieee_setets,
@@ -313,4 +593,21 @@ const struct dcbnl_rtnl_ops mlx5e_dcbnl_ops = {
.ieee_setpfc = mlx5e_dcbnl_ieee_setpfc,
.getdcbx = mlx5e_dcbnl_getdcbx,
.setdcbx = mlx5e_dcbnl_setdcbx,
+
+/* CEE interfaces */
+ .setall = mlx5e_dcbnl_setall,
+ .getstate = mlx5e_dcbnl_getstate,
+ .getpermhwaddr = mlx5e_dcbnl_getpermhwaddr,
+
+ .setpgtccfgtx = mlx5e_dcbnl_setpgtccfgtx,
+ .setpgbwgcfgtx = mlx5e_dcbnl_setpgbwgcfgtx,
+ .getpgtccfgtx = mlx5e_dcbnl_getpgtccfgtx,
+ .getpgbwgcfgtx = mlx5e_dcbnl_getpgbwgcfgtx,
+
+ .setpfccfg = mlx5e_dcbnl_setpfccfg,
+ .getpfccfg = mlx5e_dcbnl_getpfccfg,
+ .getcap = mlx5e_dcbnl_getcap,
+ .getnumtcs = mlx5e_dcbnl_getnumtcs,
+ .getpfcstate = mlx5e_dcbnl_getpfcstate,
+ .setpfcstate = mlx5e_dcbnl_setpfcstate,
};
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/port.c b/drivers/net/ethernet/mellanox/mlx5/core/port.c
index b77928f..ed4898f 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/port.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/port.c
@@ -572,6 +572,28 @@ int mlx5_set_port_prio_tc(struct mlx5_core_dev *mdev, u8 *prio_tc)
}
EXPORT_SYMBOL_GPL(mlx5_set_port_prio_tc);
+int mlx5_query_port_prio_tc(struct mlx5_core_dev *mdev,
+ u8 prio, u8 *tc)
+{
+ u32 in[MLX5_ST_SZ_DW(qtct_reg)];
+ u32 out[MLX5_ST_SZ_DW(qtct_reg)];
+ int err;
+
+ memset(in, 0, sizeof(in));
+ memset(out, 0, sizeof(out));
+
+ MLX5_SET(qtct_reg, in, port_number, 1);
+ MLX5_SET(qtct_reg, in, prio, prio);
+
+ err = mlx5_core_access_reg(mdev, in, sizeof(in), out,
+ sizeof(out), MLX5_REG_QTCT, 0, 0);
+ if (!err)
+ *tc = MLX5_GET(qtct_reg, out, tclass);
+
+ return err;
+}
+EXPORT_SYMBOL_GPL(mlx5_query_port_prio_tc);
+
static int mlx5_set_port_qetcr_reg(struct mlx5_core_dev *mdev, u32 *in,
int inlen)
{
@@ -625,6 +647,27 @@ int mlx5_set_port_tc_bw_alloc(struct mlx5_core_dev *mdev, u8 *tc_bw)
}
EXPORT_SYMBOL_GPL(mlx5_set_port_tc_bw_alloc);
+int mlx5_query_port_tc_bw_alloc(struct mlx5_core_dev *mdev,
+ u8 tc, u8 *bw_pct)
+{
+ u32 out[MLX5_ST_SZ_DW(qetc_reg)];
+ void *ets_tcn_conf;
+ int err;
+
+ err = mlx5_query_port_qetcr_reg(mdev, out, sizeof(out));
+ if (err)
+ return err;
+
+ ets_tcn_conf = MLX5_ADDR_OF(qetc_reg, out,
+ tc_configuration[tc]);
+
+ *bw_pct = MLX5_GET(ets_tcn_config_reg, ets_tcn_conf,
+ bw_allocation);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(mlx5_query_port_tc_bw_alloc);
+
int mlx5_modify_port_ets_rate_limit(struct mlx5_core_dev *mdev,
u8 *max_bw_value,
u8 *max_bw_units)
diff --git a/include/linux/mlx5/port.h b/include/linux/mlx5/port.h
index dde8c7e..bdee439 100644
--- a/include/linux/mlx5/port.h
+++ b/include/linux/mlx5/port.h
@@ -141,8 +141,12 @@ int mlx5_query_port_pfc(struct mlx5_core_dev *dev, u8 *pfc_en_tx,
int mlx5_max_tc(struct mlx5_core_dev *mdev);
int mlx5_set_port_prio_tc(struct mlx5_core_dev *mdev, u8 *prio_tc);
+int mlx5_query_port_prio_tc(struct mlx5_core_dev *mdev,
+ u8 prio, u8 *tc);
int mlx5_set_port_tc_group(struct mlx5_core_dev *mdev, u8 *tc_group);
int mlx5_set_port_tc_bw_alloc(struct mlx5_core_dev *mdev, u8 *tc_bw);
+int mlx5_query_port_tc_bw_alloc(struct mlx5_core_dev *mdev,
+ u8 tc, u8 *bw_pct);
int mlx5_modify_port_ets_rate_limit(struct mlx5_core_dev *mdev,
u8 *max_bw_value,
u8 *max_bw_unit);
--
2.7.4
^ permalink raw reply related
* [PATCH net-next 09/10] net/mlx5e: Moves pflags to priv->params
From: Saeed Mahameed @ 2016-11-26 14:18 UTC (permalink / raw)
To: David S. Miller; +Cc: netdev, Shaker Daibes, Saeed Mahameed
In-Reply-To: <1480169914-22347-1-git-send-email-saeedm@mellanox.com>
From: Shaker Daibes <shakerd@mellanox.com>
pflags is a configuration parameter for the netdev, naturally it belongs
to priv->params.
Also introduce MLX5E_GET_PFLAG
Signed-off-by: Shaker Daibes <shakerd@mellanox.com>
Signed-off-by: Saeed Mahameed <saeedm@mellanox.com>
---
drivers/net/ethernet/mellanox/mlx5/core/en.h | 16 +++++++++-------
drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c | 6 +++---
drivers/net/ethernet/mellanox/mlx5/core/en_main.c | 4 ++--
3 files changed, 14 insertions(+), 12 deletions(-)
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en.h b/drivers/net/ethernet/mellanox/mlx5/core/en.h
index 9cf32d3..84ac78f 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en.h
@@ -177,14 +177,16 @@ enum mlx5e_priv_flag {
MLX5E_PFLAG_RX_CQE_BASED_MODER = (1 << 0),
};
-#define MLX5E_SET_PRIV_FLAG(priv, pflag, enable) \
- do { \
- if (enable) \
- priv->pflags |= pflag; \
- else \
- priv->pflags &= ~pflag; \
+#define MLX5E_SET_PFLAG(priv, pflag, enable) \
+ do { \
+ if (enable) \
+ (priv)->params.pflags |= (pflag); \
+ else \
+ (priv)->params.pflags &= ~(pflag); \
} while (0)
+#define MLX5E_GET_PFLAG(priv, pflag) (!!((priv)->params.pflags & (pflag)))
+
#ifdef CONFIG_MLX5_CORE_EN_DCB
#define MLX5E_MAX_BW_ALLOC 100 /* Max percentage of BW allocation */
#endif
@@ -218,6 +220,7 @@ struct mlx5e_params {
bool vlan_strip_disable;
bool rx_am_enabled;
u32 lro_timeout;
+ u32 pflags;
};
#ifdef CONFIG_MLX5_CORE_EN_DCB
@@ -705,7 +708,6 @@ struct mlx5e_priv {
struct work_struct tx_timeout_work;
struct delayed_work update_stats_work;
- u32 pflags;
struct mlx5_core_dev *mdev;
struct net_device *netdev;
struct mlx5e_stats stats;
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c b/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c
index 839c4e9..d2bdccb 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c
@@ -1488,7 +1488,7 @@ static int mlx5e_handle_pflag(struct net_device *netdev,
{
struct mlx5e_priv *priv = netdev_priv(netdev);
bool enable = !!(wanted_flags & flag);
- u32 changes = wanted_flags ^ priv->pflags;
+ u32 changes = wanted_flags ^ priv->params.pflags;
int err;
if (!(changes & flag))
@@ -1501,7 +1501,7 @@ static int mlx5e_handle_pflag(struct net_device *netdev,
return err;
}
- MLX5E_SET_PRIV_FLAG(priv, flag, enable);
+ MLX5E_SET_PFLAG(priv, flag, enable);
return 0;
}
@@ -1524,7 +1524,7 @@ static u32 mlx5e_get_priv_flags(struct net_device *netdev)
{
struct mlx5e_priv *priv = netdev_priv(netdev);
- return priv->pflags;
+ return priv->params.pflags;
}
static int mlx5e_set_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd)
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
index 89d5c65..004940a 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
@@ -3488,8 +3488,8 @@ static void mlx5e_build_nic_netdev_priv(struct mlx5_core_dev *mdev,
SKB_DATA_ALIGN(sizeof(struct skb_shared_info));
/* Initialize pflags */
- MLX5E_SET_PRIV_FLAG(priv, MLX5E_PFLAG_RX_CQE_BASED_MODER,
- priv->params.rx_cq_period_mode == MLX5_CQ_PERIOD_MODE_START_FROM_CQE);
+ MLX5E_SET_PFLAG(priv, MLX5E_PFLAG_RX_CQE_BASED_MODER,
+ priv->params.rx_cq_period_mode == MLX5_CQ_PERIOD_MODE_START_FROM_CQE);
mutex_init(&priv->state_lock);
--
2.7.4
^ permalink raw reply related
* netlink: GPF in sock_sndtimeo
From: Dmitry Vyukov @ 2016-11-26 15:44 UTC (permalink / raw)
To: David Miller, Johannes Berg, Florian Westphal, Cong Wang,
Eric Dumazet, Herbert Xu, netdev, LKML
Cc: syzkaller
Hello,
The following program triggers GPF in sock_sndtimeo:
https://gist.githubusercontent.com/dvyukov/c19cadd309791cf5cb9b2bf936d3f48d/raw/1743ba0211079a5465d039512b427bc6b59b1a76/gistfile1.txt
On commit 16ae16c6e5616c084168740990fc508bda6655d4 (Nov 24).
general protection fault: 0000 [#1] SMP DEBUG_PAGEALLOC KASAN
Dumping ftrace buffer:
(ftrace buffer empty)
Modules linked in:
CPU: 1 PID: 19950 Comm: syz-executor Not tainted 4.9.0-rc5+ #54
Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Bochs 01/01/2011
task: ffff88002a0d0840 task.stack: ffff880036920000
RIP: 0010:[<ffffffff86cb35e1>] [< inline >] sock_sndtimeo
include/net/sock.h:2075
RIP: 0010:[<ffffffff86cb35e1>] [<ffffffff86cb35e1>]
netlink_unicast+0xe1/0x730 net/netlink/af_netlink.c:1232
RSP: 0018:ffff880036926f68 EFLAGS: 00010202
RAX: 0000000000000068 RBX: ffff880036927000 RCX: ffffc900021d0000
RDX: 0000000000000d63 RSI: 00000000024000c0 RDI: 0000000000000340
RBP: ffff880036927028 R08: ffffed0006ea7aab R09: ffffed0006ea7aab
R10: 0000000000000001 R11: ffffed0006ea7aaa R12: dffffc0000000000
R13: 0000000000000000 R14: ffff880035de3400 R15: ffff880035de3400
FS: 00007f90a2fc7700(0000) GS:ffff88003ed00000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 00000000006de0c0 CR3: 0000000035de6000 CR4: 00000000000006e0
Stack:
ffff880035de3400 ffffffff819f02a1 1ffff10006d24df4 0000000000000004
00004db400000014 ffff880036926fd8 ffffffff00000000 0000000041b58ab3
ffffffff89653c11 ffffffff86cb3500 ffffffff819f0345 ffff880035de3400
Call Trace:
[< inline >] audit_replace kernel/audit.c:817
[<ffffffff816c34b9>] audit_receive_msg+0x22c9/0x2ce0 kernel/audit.c:894
[< inline >] audit_receive_skb kernel/audit.c:1120
[<ffffffff816c40ac>] audit_receive+0x1dc/0x360 kernel/audit.c:1133
[< inline >] netlink_unicast_kernel net/netlink/af_netlink.c:1214
[<ffffffff86cb3a14>] netlink_unicast+0x514/0x730 net/netlink/af_netlink.c:1240
[<ffffffff86cb46d4>] netlink_sendmsg+0xaa4/0xe50 net/netlink/af_netlink.c:1786
[< inline >] sock_sendmsg_nosec net/socket.c:621
[<ffffffff86a6d54f>] sock_sendmsg+0xcf/0x110 net/socket.c:631
[<ffffffff86a6d8bb>] sock_write_iter+0x32b/0x620 net/socket.c:829
[< inline >] new_sync_write fs/read_write.c:499
[<ffffffff81a6f24e>] __vfs_write+0x4fe/0x830 fs/read_write.c:512
[<ffffffff81a70cf5>] vfs_write+0x175/0x4e0 fs/read_write.c:560
[< inline >] SYSC_write fs/read_write.c:607
[<ffffffff81a75180>] SyS_write+0x100/0x240 fs/read_write.c:599
[<ffffffff81009a24>] do_syscall_64+0x2f4/0x940 arch/x86/entry/common.c:280
[<ffffffff88149e8d>] entry_SYSCALL64_slow_path+0x25/0x25
Code: fe 4c 89 f7 e8 31 16 ff ff 8b 8d 70 ff ff ff 49 89 c7 31 c0 85
c9 75 25 e8 7d 4a a3 fa 49 8d bd 40 03 00 00 48 89 f8 48 c1 e8 03 <42>
80 3c 20 00 0f 85 3a 06 00 00 49 8b 85 40 03 00 00 4c 8d 73
RIP [< inline >] sock_sndtimeo include/net/sock.h:2075
RIP [<ffffffff86cb35e1>] netlink_unicast+0xe1/0x730
net/netlink/af_netlink.c:1232
RSP <ffff880036926f68>
---[ end trace 8383a15fba6fdc59 ]---
^ permalink raw reply
* Re: [PATCH v3 net-next 1/2] net: ethernet: slicoss: add slicoss gigabit ethernet driver
From: Rami Rosen @ 2016-11-26 15:48 UTC (permalink / raw)
To: Lino Sanfilippo
Cc: devel, andrew, gregkh, linux-kernel@vger.kernel.org, liodot,
Netdev, David Miller
In-Reply-To: <1480162850-8014-2-git-send-email-LinoSanfilippo@gmx.de>
Hi, Lino,
...
> @@ -0,0 +1,28 @@
> +config NET_VENDOR_ALACRITECH
> + bool "Alacritech devices"
> + default y
> + ---help---
> + If you have a network (Ethernet) card belonging to this class, say Y.
> +
> + Note that the answer to this question doesn't directly affect the
> + kernel: saying N will just cause the configurator to skip all
Shouldn't it be "Alacritech devices" here, as appears earlier ?
> + the questions about Renesas devices. If you say Y, you will be asked
> + for your specific device in the following questions.
> +
...
...
...
> +struct slic_device {
> + struct pci_dev *pdev;
...
> + bool promisc;
Seems that the autoneg boolean is not used anywhere, apart from
setting it once to true in
the slic_set_link_autoneg() method. Apart from this member it is not
accessed anywhere, so it seems it should be removed.
> + bool autoneg;
> + int speed;
...
...
> +static int slic_load_rcvseq_firmware(struct slic_device *sdev)
> +{
> + const struct firmware *fw;
> + const char *file;
> + u32 codelen;
> + int idx = 0;
> + u32 instr;
> + u32 addr;
> + int err;
> +
...
> + /* Do an initial sanity check concerning firmware size now. A further
> + * check follows below.
> + */
> + if (fw->size < SLIC_FIRMWARE_MIN_SIZE) {
> + dev_err(&sdev->pdev->dev,
> + "invalid firmware size %zu (min %u expected)\n",
> + fw->size, SLIC_FIRMWARE_MIN_SIZE);
> + err = -EINVAL;
in the release label, always 0 is returned:
> + goto release;
> + }
> +
> + codelen = slic_read_dword_from_firmware(fw, &idx);
> +
> + /* do another sanity check against firmware size */
> + if ((codelen + 4) > fw->size) {
> + dev_err(&sdev->pdev->dev,
> + "invalid rcv-sequencer firmware size %zu\n", fw->size);
> + err = -EINVAL;
Again, in the release label, always 0 is returned:
> + goto release;
> + }
> +
>
> +release:
> + release_firmware(fw);
> +
> + return 0;
> +}
> +
Regards,
Rami Rosen
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox