* [PATCH net-next] gre/ipip: use be16 variants of netlink functions
From: Sabrina Dubroca @ 2015-02-06 16:22 UTC (permalink / raw)
To: davem; +Cc: netdev, Sabrina Dubroca
encap.sport and encap.dport are __be16, use nla_{get,put}_be16 instead
of nla_{get,put}_u16.
Fixes the sparse warnings:
warning: incorrect type in assignment (different base types)
expected restricted __be32 [addressable] [usertype] o_key
got restricted __be16 [addressable] [usertype] i_flags
warning: incorrect type in assignment (different base types)
expected restricted __be16 [usertype] sport
got unsigned short
warning: incorrect type in assignment (different base types)
expected restricted __be16 [usertype] dport
got unsigned short
warning: incorrect type in argument 3 (different base types)
expected unsigned short [unsigned] [usertype] value
got restricted __be16 [usertype] sport
warning: incorrect type in argument 3 (different base types)
expected unsigned short [unsigned] [usertype] value
got restricted __be16 [usertype] dport
Signed-off-by: Sabrina Dubroca <sd@queasysnail.net>
---
net/ipv4/ip_gre.c | 12 ++++++------
net/ipv4/ipip.c | 12 ++++++------
2 files changed, 12 insertions(+), 12 deletions(-)
diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c
index 6e7727f27393..6207275fc749 100644
--- a/net/ipv4/ip_gre.c
+++ b/net/ipv4/ip_gre.c
@@ -659,12 +659,12 @@ static bool ipgre_netlink_encap_parms(struct nlattr *data[],
if (data[IFLA_GRE_ENCAP_SPORT]) {
ret = true;
- ipencap->sport = nla_get_u16(data[IFLA_GRE_ENCAP_SPORT]);
+ ipencap->sport = nla_get_be16(data[IFLA_GRE_ENCAP_SPORT]);
}
if (data[IFLA_GRE_ENCAP_DPORT]) {
ret = true;
- ipencap->dport = nla_get_u16(data[IFLA_GRE_ENCAP_DPORT]);
+ ipencap->dport = nla_get_be16(data[IFLA_GRE_ENCAP_DPORT]);
}
return ret;
@@ -786,10 +786,10 @@ static int ipgre_fill_info(struct sk_buff *skb, const struct net_device *dev)
if (nla_put_u16(skb, IFLA_GRE_ENCAP_TYPE,
t->encap.type) ||
- nla_put_u16(skb, IFLA_GRE_ENCAP_SPORT,
- t->encap.sport) ||
- nla_put_u16(skb, IFLA_GRE_ENCAP_DPORT,
- t->encap.dport) ||
+ nla_put_be16(skb, IFLA_GRE_ENCAP_SPORT,
+ t->encap.sport) ||
+ nla_put_be16(skb, IFLA_GRE_ENCAP_DPORT,
+ t->encap.dport) ||
nla_put_u16(skb, IFLA_GRE_ENCAP_FLAGS,
t->encap.flags))
goto nla_put_failure;
diff --git a/net/ipv4/ipip.c b/net/ipv4/ipip.c
index b58d6689874c..915d215a7d14 100644
--- a/net/ipv4/ipip.c
+++ b/net/ipv4/ipip.c
@@ -366,12 +366,12 @@ static bool ipip_netlink_encap_parms(struct nlattr *data[],
if (data[IFLA_IPTUN_ENCAP_SPORT]) {
ret = true;
- ipencap->sport = nla_get_u16(data[IFLA_IPTUN_ENCAP_SPORT]);
+ ipencap->sport = nla_get_be16(data[IFLA_IPTUN_ENCAP_SPORT]);
}
if (data[IFLA_IPTUN_ENCAP_DPORT]) {
ret = true;
- ipencap->dport = nla_get_u16(data[IFLA_IPTUN_ENCAP_DPORT]);
+ ipencap->dport = nla_get_be16(data[IFLA_IPTUN_ENCAP_DPORT]);
}
return ret;
@@ -460,10 +460,10 @@ static int ipip_fill_info(struct sk_buff *skb, const struct net_device *dev)
if (nla_put_u16(skb, IFLA_IPTUN_ENCAP_TYPE,
tunnel->encap.type) ||
- nla_put_u16(skb, IFLA_IPTUN_ENCAP_SPORT,
- tunnel->encap.sport) ||
- nla_put_u16(skb, IFLA_IPTUN_ENCAP_DPORT,
- tunnel->encap.dport) ||
+ nla_put_be16(skb, IFLA_IPTUN_ENCAP_SPORT,
+ tunnel->encap.sport) ||
+ nla_put_be16(skb, IFLA_IPTUN_ENCAP_DPORT,
+ tunnel->encap.dport) ||
nla_put_u16(skb, IFLA_IPTUN_ENCAP_FLAGS,
tunnel->encap.flags))
goto nla_put_failure;
--
2.3.0
^ permalink raw reply related
* [PATCH net-next] rhashtable: Fix remove logic to avoid cross references between buckets
From: Thomas Graf @ 2015-02-06 16:08 UTC (permalink / raw)
To: Ying Xue; +Cc: davem, netdev, herbert
In-Reply-To: <54D42892.3030808@windriver.com>
The remove logic properly searched the remaining chain for a matching
entry with an identical hash but it did this while searching from both
the old and new table. Instead in order to not leave stale references
behind we need to:
1. When growing and searching from the new table:
Search remaining chain for entry with same hash to avoid having
the new table directly point to a entry with a different hash.
2. When shrinking and searching from the old table:
Check if the element after the removed would create a cross
reference and avoid it if so.
These bugs were present from the beginning in nft_hash.
Also, both insert functions calculated the hash based on the mask of
the new table. This worked while growing. Wwhile shrinking, the mask
of the inew table is smaller than the mask of the old table. This lead
to a bit not being taken into account when selecting the bucket lock
and thus caused the wrong bucket to be locked eventually.
Fixes: 7e1e77636e36 ("lib: Resizable, Scalable, Concurrent Hash Table")
Fixes: 97defe1ecf86 ("rhashtable: Per bucket locks & deferred expansion/shrinking")
Reported-by: Ying Xue <ying.xue@windriver.com>
Signed-off-by: Thomas Graf <tgraf@suug.ch>
---
lib/rhashtable.c | 28 +++++++++++++++++-----------
1 file changed, 17 insertions(+), 11 deletions(-)
diff --git a/lib/rhashtable.c b/lib/rhashtable.c
index 5919d63..e96fc00 100644
--- a/lib/rhashtable.c
+++ b/lib/rhashtable.c
@@ -552,8 +552,10 @@ static void rhashtable_wakeup_worker(struct rhashtable *ht)
static void __rhashtable_insert(struct rhashtable *ht, struct rhash_head *obj,
struct bucket_table *tbl, u32 hash)
{
- struct rhash_head *head = rht_dereference_bucket(tbl->buckets[hash],
- tbl, hash);
+ struct rhash_head *head;
+
+ hash = rht_bucket_index(tbl, hash);
+ head = rht_dereference_bucket(tbl->buckets[hash], tbl, hash);
ASSERT_BUCKET_LOCK(ht, tbl, hash);
@@ -593,7 +595,7 @@ void rhashtable_insert(struct rhashtable *ht, struct rhash_head *obj)
tbl = rht_dereference_rcu(ht->future_tbl, ht);
old_tbl = rht_dereference_rcu(ht->tbl, ht);
- hash = head_hashfn(ht, tbl, obj);
+ hash = obj_raw_hashfn(ht, rht_obj(ht, obj));
lock_buckets(tbl, old_tbl, hash);
__rhashtable_insert(ht, obj, tbl, hash);
@@ -627,8 +629,8 @@ bool rhashtable_remove(struct rhashtable *ht, struct rhash_head *obj)
bool ret = false;
rcu_read_lock();
- tbl = old_tbl = rht_dereference_rcu(ht->tbl, ht);
- new_tbl = rht_dereference_rcu(ht->future_tbl, ht);
+ old_tbl = rht_dereference_rcu(ht->tbl, ht);
+ tbl = new_tbl = rht_dereference_rcu(ht->future_tbl, ht);
new_hash = obj_raw_hashfn(ht, rht_obj(ht, obj));
lock_buckets(new_tbl, old_tbl, new_hash);
@@ -643,15 +645,19 @@ restart:
ASSERT_BUCKET_LOCK(ht, tbl, hash);
- if (unlikely(new_tbl != tbl)) {
- rht_for_each_continue(he2, he->next, tbl, hash) {
+ if (old_tbl->size > new_tbl->size && tbl == old_tbl &&
+ !rht_is_a_nulls(obj->next) &&
+ head_hashfn(ht, tbl, obj->next) != hash) {
+ rcu_assign_pointer(*pprev, (struct rhash_head *) rht_marker(ht, hash));
+ } else if (unlikely(old_tbl->size < new_tbl->size && tbl == new_tbl)) {
+ rht_for_each_continue(he2, obj->next, tbl, hash) {
if (head_hashfn(ht, tbl, he2) == hash) {
rcu_assign_pointer(*pprev, he2);
goto found;
}
}
- INIT_RHT_NULLS_HEAD(*pprev, ht, hash);
+ rcu_assign_pointer(*pprev, (struct rhash_head *) rht_marker(ht, hash));
} else {
rcu_assign_pointer(*pprev, obj->next);
}
@@ -666,8 +672,8 @@ found:
* resizing. Thus traversing both is fine and the added cost is
* very rare.
*/
- if (tbl != new_tbl) {
- tbl = new_tbl;
+ if (tbl != old_tbl) {
+ tbl = old_tbl;
goto restart;
}
@@ -835,7 +841,7 @@ bool rhashtable_lookup_compare_insert(struct rhashtable *ht,
rcu_read_lock();
old_tbl = rht_dereference_rcu(ht->tbl, ht);
new_tbl = rht_dereference_rcu(ht->future_tbl, ht);
- new_hash = head_hashfn(ht, new_tbl, obj);
+ new_hash = obj_raw_hashfn(ht, rht_obj(ht, obj));
lock_buckets(new_tbl, old_tbl, new_hash);
--
1.9.3
^ permalink raw reply related
* [PATCH] ethtool: return non-zero from do_sset() when any of ETHTOOL_{G,S}* fails
From: Ivan Vecera @ 2015-02-06 15:24 UTC (permalink / raw)
To: netdev; +Cc: Ben Hutchings
Function do_sset returns unconditionally zero error code without regard
to return value of ETHTOOL_{G,S}* ioctls.
Cc: Ben Hutchings <ben@decadent.org.uk>
Signed-off-by: Ivan Vecera <ivecera@redhat.com>
---
ethtool.c | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/ethtool.c b/ethtool.c
index bf583f3..c004d41 100644
--- a/ethtool.c
+++ b/ethtool.c
@@ -2357,7 +2357,7 @@ static int do_sset(struct cmd_context *ctx)
int argc = ctx->argc;
char **argp = ctx->argp;
int i;
- int err;
+ int err, result = 0;
for (i = 0; i < ARRAY_SIZE(flags_msglvl); i++)
flag_to_cmdline_info(flags_msglvl[i].name,
@@ -2617,6 +2617,7 @@ static int do_sset(struct cmd_context *ctx)
fprintf(stderr, " not setting transceiver\n");
if (mdix_wanted != -1)
fprintf(stderr, " not setting mdix\n");
+ result = err;
}
}
@@ -2650,6 +2651,7 @@ static int do_sset(struct cmd_context *ctx)
fprintf(stderr, " not setting wol\n");
if (sopass_change)
fprintf(stderr, " not setting sopass\n");
+ result = err;
}
}
@@ -2668,9 +2670,10 @@ static int do_sset(struct cmd_context *ctx)
if (err < 0)
perror("Cannot set new msglvl");
}
+ result = err;
}
- return 0;
+ return result;
}
static int do_gregs(struct cmd_context *ctx)
--
2.0.5
^ permalink raw reply related
* Re: [RFC PATCH 00/29] net: VRF support
From: Nicolas Dichtel @ 2015-02-06 15:10 UTC (permalink / raw)
To: David Ahern, netdev; +Cc: ebiederm, Roopa Prabhu
In-Reply-To: <1423100070-31848-1-git-send-email-dsahern@gmail.com>
Le 05/02/2015 02:34, David Ahern a écrit :
[snip]
>
> Design
> ------
> Namespaces provide excellent separation of the networking stack from the
> netdevices and up. The intent of VRFs is to provide an additional,
> logical separation at the L3 layer within a namespace.
>
> +----------------------------------------------------------+
> | Namespace foo |
> | +---------------+ |
> | +------+ | L3/L4 service | |
> | | lldp | | (VRF any) | |
> | +------+ +---------------+ |
> | |
> | +-------------------------+ |
> | | VRF M | |
> | +---------------------+ +-------------------------+ | |
> | | VRF 1 (default) | | VRF N | | |
> | | +---------------+ | | +---------------+ | | |
> | | | L3/L4 service | | | | L3/L4 service | | | |
> | | | (VRF unaware) | | | | (VRF unaware) | | | |
> | | +---------------+ | | +---------------+ | | |
> | | | | | | |
> | |+-----+ +----------+ | | +-----+ +----------+ | | |
> | || FIB | | neighbor | | | | FIB | | neighbor | | | |
> | |+-----+ +----------+ | | +-----+ +----------+ | | |
> | | | | |-+ |
> | | {dev 1} {dev 2} | | {dev 3} {dev 4} {dev 5} | |
> | +---------------------+ +-------------------------+ |
> +----------------------------------------------------------+
>
Another question: how is the loopback managed?
If I understand well, there is only one loopback for all vrf.
If I add an address on this loopback, is this address visible from all VRF?
Can an app in VRF1 talks to an app in VRF2 via the loopback?
^ permalink raw reply
* Re: [RFC PATCH 00/29] net: VRF support
From: Nicolas Dichtel @ 2015-02-06 15:08 UTC (permalink / raw)
To: David Ahern, Eric W. Biederman; +Cc: Stephen Hemminger, netdev
In-Reply-To: <54D45C15.7090602@gmail.com>
Le 06/02/2015 07:15, David Ahern a écrit :
[snip]
> Application code -- open source daemons -- can be modified to be VRF aware as
> needed. Kernel side VRF support would be made a CONFIG option that defaults off.
> The macros will ensure anything VRF related falls out, so server deployments
> would not be impacted.
Most of distributions enables all kernel options.
^ permalink raw reply
* Re: Throughput regression with `tcp: refine TSO autosizing`
From: Eric Dumazet @ 2015-02-06 15:02 UTC (permalink / raw)
To: David Laight
Cc: Michal Kazior, Neal Cardwell, linux-wireless, Network Development,
eyalpe-LDSdmyG8hGV8YrgS2mwiifqBs+8SCbDb@public.gmane.org
In-Reply-To: <063D6719AE5E284EB5DD2968C1650D6D1CADF4EC-VkEWCZq2GCInGFn1LkZF6NBPR1lH4CV8@public.gmane.org>
On Fri, 2015-02-06 at 14:31 +0000, David Laight wrote:
> From: Eric Dumazet
> > On Fri, 2015-02-06 at 05:53 -0800, Eric Dumazet wrote:
> >
> >
> > > wifi could eventually do that, providing in skb->tx_completion_delay_us
> > > the time spent in wifi driver.
> > >
> > > This way, we would have no penalty for network devices doing normal skb
> > > orphaning (loopback interface, ethernet, ...)
> >
> > Another way would be that wifi does an automatic orphaning after 1 or
> > 2ms.
>
> Couldn't you do byte counting?
> So orphan enough packets to keep a few ms of tx traffic (at the current
> tx rate) orphaned.
> You might need to give the hardware both orphaned and non-orphaned (parented?)
> packets and orphan some when you get a tx complete for an orphaned packet.
We already have byte counting.
The thing is : A driver can keep an skb for itself, but calling
skb_orphan() in time to allow a socket to send more packets.
For say a UDP server, it would be quite mandatory, as it usually uses a
single UDP socket to receive and send messages.
--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* [PATCH net-next] net: silence sparse endianness warnings in checksums
From: Sabrina Dubroca @ 2015-02-06 14:43 UTC (permalink / raw)
To: davem; +Cc: netdev, eric.dumazet, therbert, Sabrina Dubroca
In __skb_checksum_validate_complete and its callers, we only test that
the return value is non-zero, so it's safe to __force the type.
Callers of gso_make_checksum pass a __sum16, use that.
Signed-off-by: Sabrina Dubroca <sd@queasysnail.net>
---
include/linux/skbuff.h | 8 ++++----
net/ipv4/udp.c | 4 ++--
net/ipv6/ip6_checksum.c | 4 ++--
3 files changed, 8 insertions(+), 8 deletions(-)
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index 111e665455c3..7b35b4884f58 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -3019,7 +3019,7 @@ static inline __sum16 __skb_checksum_validate_complete(struct sk_buff *skb,
}
} else if (skb->csum_bad) {
/* ip_summed == CHECKSUM_NONE in this case */
- return 1;
+ return (__force __sum16) 1;
}
skb->csum = psum;
@@ -3308,15 +3308,15 @@ static inline int gso_pskb_expand_head(struct sk_buff *skb, int extra)
* is in the res argument (i.e. normally zero or ~ of checksum of a pseudo
* header.
*/
-static inline __sum16 gso_make_checksum(struct sk_buff *skb, __wsum res)
+static inline __sum16 gso_make_checksum(struct sk_buff *skb, __sum16 res)
{
int plen = SKB_GSO_CB(skb)->csum_start - skb_headroom(skb) -
skb_transport_offset(skb);
- __u16 csum;
+ __sum16 csum;
csum = csum_fold(csum_partial(skb_transport_header(skb),
plen, skb->csum));
- skb->csum = res;
+ skb->csum = (__force __wsum) res;
SKB_GSO_CB(skb)->csum_start -= plen;
return csum;
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
index 97ef1f8b7be8..1f1ff4eaa34b 100644
--- a/net/ipv4/udp.c
+++ b/net/ipv4/udp.c
@@ -1738,8 +1738,8 @@ static inline int udp4_csum_init(struct sk_buff *skb, struct udphdr *uh,
return err;
}
- return skb_checksum_init_zero_check(skb, proto, uh->check,
- inet_compute_pseudo);
+ return (__force int)skb_checksum_init_zero_check(skb, proto, uh->check,
+ inet_compute_pseudo);
}
/*
diff --git a/net/ipv6/ip6_checksum.c b/net/ipv6/ip6_checksum.c
index 9a4d7322fb22..9a1c766a84f0 100644
--- a/net/ipv6/ip6_checksum.c
+++ b/net/ipv6/ip6_checksum.c
@@ -80,8 +80,8 @@ int udp6_csum_init(struct sk_buff *skb, struct udphdr *uh, int proto)
* for the UDP packet we'll check if that socket allows zero checksum
* for IPv6 (set by socket option).
*/
- return skb_checksum_init_zero_check(skb, proto, uh->check,
- ip6_compute_pseudo);
+ return (__force int)skb_checksum_init_zero_check(skb, proto, uh->check,
+ ip6_compute_pseudo);
}
EXPORT_SYMBOL(udp6_csum_init);
--
2.3.0
^ permalink raw reply related
* Re: Throughput regression with `tcp: refine TSO autosizing`
From: Eric Dumazet @ 2015-02-06 14:35 UTC (permalink / raw)
To: Michal Kazior
Cc: Neal Cardwell, linux-wireless, Network Development, Eyal Perry
In-Reply-To: <CA+BoTQnEvF_mi68gyFns67oKC=8jEYdi3tLuW5dNj20KwUNs9A-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
On Fri, 2015-02-06 at 15:08 +0100, Michal Kazior wrote:
> Hmm.. I confirm it works. However the value at which I get full rate
> on a single flow is more than 2048K. Also using non-default
> wmem_default seems to introduce packet loss as per iperf reports at
> the receiver. I suppose this is kind of expected but on the other hand
> wmem_default=262992 and 5 flows of UDP max the device out with 0
> packet loss.
If you increase ability to flood on one flow, then you need to make sure
receiver has big rcvbuf as well.
echo 2000000 >/proc/sys/net/core/rmem_default
Otherwise it might drop bursts.
This is the kind of things that TCP does automatically, not UDP.
--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* RE: Throughput regression with `tcp: refine TSO autosizing`
From: David Laight @ 2015-02-06 14:31 UTC (permalink / raw)
To: 'Eric Dumazet', Michal Kazior
Cc: Neal Cardwell, linux-wireless, Network Development,
eyalpe@dev.mellanox.co.il
In-Reply-To: <1423231841.31870.133.camel@edumazet-glaptop2.roam.corp.google.com>
From: Eric Dumazet
> On Fri, 2015-02-06 at 05:53 -0800, Eric Dumazet wrote:
>
>
> > wifi could eventually do that, providing in skb->tx_completion_delay_us
> > the time spent in wifi driver.
> >
> > This way, we would have no penalty for network devices doing normal skb
> > orphaning (loopback interface, ethernet, ...)
>
> Another way would be that wifi does an automatic orphaning after 1 or
> 2ms.
Couldn't you do byte counting?
So orphan enough packets to keep a few ms of tx traffic (at the current
tx rate) orphaned.
You might need to give the hardware both orphaned and non-orphaned (parented?)
packets and orphan some when you get a tx complete for an orphaned packet.
David
^ permalink raw reply
* Re: Throughput regression with `tcp: refine TSO autosizing`
From: Eric Dumazet @ 2015-02-06 14:10 UTC (permalink / raw)
To: Michal Kazior; +Cc: Neal Cardwell, linux-wireless, Network Development, eyalpe
In-Reply-To: <1423230785.31870.131.camel@edumazet-glaptop2.roam.corp.google.com>
On Fri, 2015-02-06 at 05:53 -0800, Eric Dumazet wrote:
> wifi could eventually do that, providing in skb->tx_completion_delay_us
> the time spent in wifi driver.
>
> This way, we would have no penalty for network devices doing normal skb
> orphaning (loopback interface, ethernet, ...)
Another way would be that wifi does an automatic orphaning after 1 or
2ms.
^ permalink raw reply
* Re: Throughput regression with `tcp: refine TSO autosizing`
From: Michal Kazior @ 2015-02-06 14:09 UTC (permalink / raw)
To: Eric Dumazet
Cc: Neal Cardwell, linux-wireless, Network Development, Eyal Perry
In-Reply-To: <1423230785.31870.131.camel@edumazet-glaptop2.roam.corp.google.com>
On 6 February 2015 at 14:53, Eric Dumazet <eric.dumazet@gmail.com> wrote:
> On Fri, 2015-02-06 at 05:40 -0800, Eric Dumazet wrote:
>
>> tcp_wfree() could maintain in tp->tx_completion_delay_ms an EWMA
>> of TX completion delay. But this would require yet another expensive
>> call to ktime_get() if HZ < 1000.
>>
>> Then tcp_write_xmit() could use it to adjust :
>>
>> limit = max(2 * skb->truesize, sk->sk_pacing_rate >> 9);
>>
>> to
>>
>> amount = (2 + tp->tx_completion_delay_ms) * sk->sk_pacing_rate
>>
>> limit = max(2 * skb->truesize, amount / 1000);
>>
>> I'll cook a patch.
>
> Hmm... doing this in all protocols would be too expensive,
> and we do not want to include time spent in qdiscs.
>
> wifi could eventually do that, providing in skb->tx_completion_delay_us
> the time spent in wifi driver.
>
> This way, we would have no penalty for network devices doing normal skb
> orphaning (loopback interface, ethernet, ...)
I'll play around with this idea and report back later.
Michał
^ permalink raw reply
* Re: Throughput regression with `tcp: refine TSO autosizing`
From: Michal Kazior @ 2015-02-06 14:08 UTC (permalink / raw)
To: Eric Dumazet
Cc: Neal Cardwell, linux-wireless, Network Development, Eyal Perry
In-Reply-To: <1423230001.31870.128.camel-XN9IlZ5yJG9HTL0Zs8A6p/gx64E7kk8eUsxypvmhUTTZJqsBc5GL+g@public.gmane.org>
On 6 February 2015 at 14:40, Eric Dumazet <eric.dumazet-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:
> On Fri, 2015-02-06 at 10:42 +0100, Michal Kazior wrote:
>
>> The above brings back previous behaviour, i.e. I can get 600mbps TCP
>> on 5 flows again. Single flow is still (as it was before TSO
>> autosizing) limited to roughly ~280mbps.
>>
>> I never really bothered before to understand why I need to push a few
>> flows through ath10k to max it out, i.e. if I run a single UDP flow I
>> get ~300mbps while with, e.g. 5 I get 670mbps easily.
>>
>
> For single UDP flow, tweaking /proc/sys/net/core/wmem_default might be
> enough : UDP has no callback from TX completion to feed following frames
> (No write queue like TCP)
>
> # cat /proc/sys/net/core/wmem_default
> 212992
> # ethtool -C eth1 tx-usecs 1024 tx-frames 120
> # ./netperf -H remote -t UDP_STREAM -- -m 1450
> Socket Message Elapsed Messages
> Size Size Time Okay Errors Throughput
> bytes bytes secs # # 10^6bits/sec
>
> 212992 1450 10.00 697705 0 809.27
> 212992 10.00 673412 781.09
>
> # echo 800000 >/proc/sys/net/core/wmem_default
> # ./netperf -H remote -t UDP_STREAM -- -m 1450
> Socket Message Elapsed Messages
> Size Size Time Okay Errors Throughput
> bytes bytes secs # # 10^6bits/sec
>
> 800000 1450 10.00 7329221 0 8501.84
> 212992 10.00 7284051 8449.44
Hmm.. I confirm it works. However the value at which I get full rate
on a single flow is more than 2048K. Also using non-default
wmem_default seems to introduce packet loss as per iperf reports at
the receiver. I suppose this is kind of expected but on the other hand
wmem_default=262992 and 5 flows of UDP max the device out with 0
packet loss.
Michał
--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* [PATCHv2 net-next 5/5] cxgb4: Add support in debugfs to dump the congestion control table
From: Hariprasad Shenai @ 2015-02-06 14:02 UTC (permalink / raw)
To: netdev; +Cc: davem, leedom, anish, nirranjan, kumaras, Hariprasad Shenai
In-Reply-To: <1423231375-28004-1-git-send-email-hariprasad@chelsio.com>
Dump Transport Processor modules congestion control configuration
Signed-off-by: Hariprasad Shenai <hariprasad@chelsio.com>
---
drivers/net/ethernet/chelsio/cxgb4/cxgb4.h | 1 +
drivers/net/ethernet/chelsio/cxgb4/cxgb4_debugfs.c | 28 ++++++++++++++++++++
drivers/net/ethernet/chelsio/cxgb4/t4_hw.c | 21 +++++++++++++++
drivers/net/ethernet/chelsio/cxgb4/t4_regs.h | 3 ++
4 files changed, 53 insertions(+), 0 deletions(-)
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h b/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h
index b8fee60..d6cda17 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h
@@ -1174,6 +1174,7 @@ void t4_read_cimq_cfg(struct adapter *adap, u16 *base, u16 *size, u16 *thres);
const char *t4_get_port_type_description(enum fw_port_type port_type);
void t4_get_port_stats(struct adapter *adap, int idx, struct port_stats *p);
void t4_read_mtu_tbl(struct adapter *adap, u16 *mtus, u8 *mtu_log);
+void t4_read_cong_tbl(struct adapter *adap, u16 incr[NMTUS][NCCTRL_WIN]);
void t4_tp_wr_bits_indirect(struct adapter *adap, unsigned int addr,
unsigned int mask, unsigned int val);
void t4_tp_read_la(struct adapter *adap, u64 *la_buf, unsigned int *wrptr);
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_debugfs.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_debugfs.c
index 83e2932..a1029ee 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_debugfs.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_debugfs.c
@@ -663,6 +663,33 @@ static const struct file_operations pm_stats_debugfs_fops = {
.write = pm_stats_clear
};
+static int cctrl_tbl_show(struct seq_file *seq, void *v)
+{
+ static const char * const dec_fac[] = {
+ "0.5", "0.5625", "0.625", "0.6875", "0.75", "0.8125", "0.875",
+ "0.9375" };
+
+ int i;
+ u16 incr[NMTUS][NCCTRL_WIN];
+ struct adapter *adap = seq->private;
+
+ t4_read_cong_tbl(adap, incr);
+
+ for (i = 0; i < NCCTRL_WIN; ++i) {
+ seq_printf(seq, "%2d: %4u %4u %4u %4u %4u %4u %4u %4u\n", i,
+ incr[0][i], incr[1][i], incr[2][i], incr[3][i],
+ incr[4][i], incr[5][i], incr[6][i], incr[7][i]);
+ seq_printf(seq, "%8u %4u %4u %4u %4u %4u %4u %4u %5u %s\n",
+ incr[8][i], incr[9][i], incr[10][i], incr[11][i],
+ incr[12][i], incr[13][i], incr[14][i], incr[15][i],
+ adap->params.a_wnd[i],
+ dec_fac[adap->params.b_wnd[i]]);
+ }
+ return 0;
+}
+
+DEFINE_SIMPLE_DEBUGFS_FILE(cctrl_tbl);
+
/* Format a value in a unit that differs from the value's native unit by the
* given factor.
*/
@@ -1990,6 +2017,7 @@ int t4_setup_debugfs(struct adapter *adap)
{ "ulprx_la", &ulprx_la_fops, S_IRUSR, 0 },
{ "sensors", &sensors_debugfs_fops, S_IRUSR, 0 },
{ "pm_stats", &pm_stats_debugfs_fops, S_IRUSR, 0 },
+ { "cctrl", &cctrl_tbl_debugfs_fops, S_IRUSR, 0 },
#if IS_ENABLED(CONFIG_IPV6)
{ "clip_tbl", &clip_tbl_debugfs_fops, S_IRUSR, 0 },
#endif
diff --git a/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c b/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c
index 5871c00..4d643b6 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c
@@ -2456,6 +2456,27 @@ void t4_read_mtu_tbl(struct adapter *adap, u16 *mtus, u8 *mtu_log)
}
/**
+ * t4_read_cong_tbl - reads the congestion control table
+ * @adap: the adapter
+ * @incr: where to store the alpha values
+ *
+ * Reads the additive increments programmed into the HW congestion
+ * control table.
+ */
+void t4_read_cong_tbl(struct adapter *adap, u16 incr[NMTUS][NCCTRL_WIN])
+{
+ unsigned int mtu, w;
+
+ for (mtu = 0; mtu < NMTUS; ++mtu)
+ for (w = 0; w < NCCTRL_WIN; ++w) {
+ t4_write_reg(adap, TP_CCTRL_TABLE_A,
+ ROWINDEX_V(0xffff) | (mtu << 5) | w);
+ incr[mtu][w] = (u16)t4_read_reg(adap,
+ TP_CCTRL_TABLE_A) & 0x1fff;
+ }
+}
+
+/**
* t4_tp_wr_bits_indirect - set/clear bits in an indirect TP register
* @adap: the adapter
* @addr: the indirect TP register address
diff --git a/drivers/net/ethernet/chelsio/cxgb4/t4_regs.h b/drivers/net/ethernet/chelsio/cxgb4/t4_regs.h
index 3f18d5c..231a725 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/t4_regs.h
+++ b/drivers/net/ethernet/chelsio/cxgb4/t4_regs.h
@@ -1292,6 +1292,9 @@
#define KEEPALIVEMAXR2_V(x) ((x) << KEEPALIVEMAXR2_S)
#define KEEPALIVEMAXR2_G(x) (((x) >> KEEPALIVEMAXR2_S) & KEEPALIVEMAXR2_M)
+#define ROWINDEX_S 16
+#define ROWINDEX_V(x) ((x) << ROWINDEX_S)
+
#define TP_CCTRL_TABLE_A 0x7ddc
#define TP_MTU_TABLE_A 0x7de4
--
1.7.1
^ permalink raw reply related
* [PATCHv2 net-next 4/5] cxgb4: Add support to dump mailbox content in debugfs
From: Hariprasad Shenai @ 2015-02-06 14:02 UTC (permalink / raw)
To: netdev; +Cc: davem, leedom, anish, nirranjan, kumaras, Hariprasad Shenai
In-Reply-To: <1423231375-28004-1-git-send-email-hariprasad@chelsio.com>
Adds support to dump the current contents of mailbox and the driver which owns
it.
Signed-off-by: Hariprasad Shenai <hariprasad@chelsio.com>
---
drivers/net/ethernet/chelsio/cxgb4/cxgb4_debugfs.c | 85 ++++++++++++++++++++
drivers/net/ethernet/chelsio/cxgb4/t4_regs.h | 1 +
drivers/net/ethernet/chelsio/cxgb4/t4_values.h | 5 +
3 files changed, 91 insertions(+), 0 deletions(-)
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_debugfs.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_debugfs.c
index 5a46273..83e2932 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_debugfs.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_debugfs.c
@@ -40,6 +40,7 @@
#include "cxgb4.h"
#include "t4_regs.h"
+#include "t4_values.h"
#include "t4fw_api.h"
#include "cxgb4_debugfs.h"
#include "clip_tbl.h"
@@ -920,6 +921,82 @@ static const struct file_operations devlog_fops = {
.release = seq_release_private
};
+static int mbox_show(struct seq_file *seq, void *v)
+{
+ static const char * const owner[] = { "none", "FW", "driver",
+ "unknown" };
+
+ int i;
+ unsigned int mbox = (uintptr_t)seq->private & 7;
+ struct adapter *adap = seq->private - mbox;
+ void __iomem *addr = adap->regs + PF_REG(mbox, CIM_PF_MAILBOX_DATA_A);
+ unsigned int ctrl_reg = (is_t4(adap->params.chip)
+ ? CIM_PF_MAILBOX_CTRL_A
+ : CIM_PF_MAILBOX_CTRL_SHADOW_COPY_A);
+ void __iomem *ctrl = adap->regs + PF_REG(mbox, ctrl_reg);
+
+ i = MBOWNER_G(readl(ctrl));
+ seq_printf(seq, "mailbox owned by %s\n\n", owner[i]);
+
+ for (i = 0; i < MBOX_LEN; i += 8)
+ seq_printf(seq, "%016llx\n",
+ (unsigned long long)readq(addr + i));
+ return 0;
+}
+
+static int mbox_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, mbox_show, inode->i_private);
+}
+
+static ssize_t mbox_write(struct file *file, const char __user *buf,
+ size_t count, loff_t *pos)
+{
+ int i;
+ char c = '\n', s[256];
+ unsigned long long data[8];
+ const struct inode *ino;
+ unsigned int mbox;
+ struct adapter *adap;
+ void __iomem *addr;
+ void __iomem *ctrl;
+
+ if (count > sizeof(s) - 1 || !count)
+ return -EINVAL;
+ if (copy_from_user(s, buf, count))
+ return -EFAULT;
+ s[count] = '\0';
+
+ if (sscanf(s, "%llx %llx %llx %llx %llx %llx %llx %llx%c", &data[0],
+ &data[1], &data[2], &data[3], &data[4], &data[5], &data[6],
+ &data[7], &c) < 8 || c != '\n')
+ return -EINVAL;
+
+ ino = FILE_DATA(file);
+ mbox = (uintptr_t)ino->i_private & 7;
+ adap = ino->i_private - mbox;
+ addr = adap->regs + PF_REG(mbox, CIM_PF_MAILBOX_DATA_A);
+ ctrl = addr + MBOX_LEN;
+
+ if (MBOWNER_G(readl(ctrl)) != X_MBOWNER_PL)
+ return -EBUSY;
+
+ for (i = 0; i < 8; i++)
+ writeq(data[i], addr + 8 * i);
+
+ writel(MBMSGVALID_F | MBOWNER_V(X_MBOWNER_FW), ctrl);
+ return count;
+}
+
+static const struct file_operations mbox_debugfs_fops = {
+ .owner = THIS_MODULE,
+ .open = mbox_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+ .write = mbox_write
+};
+
static ssize_t flash_read(struct file *file, char __user *buf, size_t count,
loff_t *ppos)
{
@@ -1881,6 +1958,14 @@ int t4_setup_debugfs(struct adapter *adap)
{ "cim_qcfg", &cim_qcfg_fops, S_IRUSR, 0 },
{ "clk", &clk_debugfs_fops, S_IRUSR, 0 },
{ "devlog", &devlog_fops, S_IRUSR, 0 },
+ { "mbox0", &mbox_debugfs_fops, S_IRUSR | S_IWUSR, 0 },
+ { "mbox1", &mbox_debugfs_fops, S_IRUSR | S_IWUSR, 1 },
+ { "mbox2", &mbox_debugfs_fops, S_IRUSR | S_IWUSR, 2 },
+ { "mbox3", &mbox_debugfs_fops, S_IRUSR | S_IWUSR, 3 },
+ { "mbox4", &mbox_debugfs_fops, S_IRUSR | S_IWUSR, 4 },
+ { "mbox5", &mbox_debugfs_fops, S_IRUSR | S_IWUSR, 5 },
+ { "mbox6", &mbox_debugfs_fops, S_IRUSR | S_IWUSR, 6 },
+ { "mbox7", &mbox_debugfs_fops, S_IRUSR | S_IWUSR, 7 },
{ "l2t", &t4_l2t_fops, S_IRUSR, 0},
{ "mps_tcam", &mps_tcam_debugfs_fops, S_IRUSR, 0 },
{ "rss", &rss_debugfs_fops, S_IRUSR, 0 },
diff --git a/drivers/net/ethernet/chelsio/cxgb4/t4_regs.h b/drivers/net/ethernet/chelsio/cxgb4/t4_regs.h
index 91e0ea1..3f18d5c 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/t4_regs.h
+++ b/drivers/net/ethernet/chelsio/cxgb4/t4_regs.h
@@ -947,6 +947,7 @@
/* registers for module CIM */
#define CIM_BOOT_CFG_A 0x7b00
+#define CIM_PF_MAILBOX_CTRL_SHADOW_COPY_A 0x290
#define BOOTADDR_M 0xffffff00U
diff --git a/drivers/net/ethernet/chelsio/cxgb4/t4_values.h b/drivers/net/ethernet/chelsio/cxgb4/t4_values.h
index 997ec87..19b2dcf 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/t4_values.h
+++ b/drivers/net/ethernet/chelsio/cxgb4/t4_values.h
@@ -79,6 +79,11 @@
#define SGE_UDB_GTS 20
#define SGE_UDB_WCDOORBELL 64
+/* CIM register field values.
+ */
+#define X_MBOWNER_FW 1
+#define X_MBOWNER_PL 2
+
/* PCI-E definitions */
#define WINDOW_SHIFT_X 10
#define PCIEOFST_SHIFT_X 10
--
1.7.1
^ permalink raw reply related
* [PATCHv2 net-next 3/5] cxgb4: Add support for ULP RX logic analyzer output in debugfs
From: Hariprasad Shenai @ 2015-02-06 14:02 UTC (permalink / raw)
To: netdev; +Cc: davem, leedom, anish, nirranjan, kumaras, Hariprasad Shenai
In-Reply-To: <1423231375-28004-1-git-send-email-hariprasad@chelsio.com>
Dump Upper Layer Protocol RX module command trace
Signed-off-by: Hariprasad Shenai <hariprasad@chelsio.com>
---
drivers/net/ethernet/chelsio/cxgb4/cxgb4.h | 2 +
drivers/net/ethernet/chelsio/cxgb4/cxgb4_debugfs.c | 36 ++++++++++++++++++++
drivers/net/ethernet/chelsio/cxgb4/t4_hw.c | 15 ++++++++
drivers/net/ethernet/chelsio/cxgb4/t4_hw.h | 1 +
drivers/net/ethernet/chelsio/cxgb4/t4_regs.h | 4 ++
5 files changed, 58 insertions(+), 0 deletions(-)
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h b/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h
index 574e51f..b8fee60 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h
@@ -1182,6 +1182,8 @@ void t4_tp_get_tcp_stats(struct adapter *adap, struct tp_tcp_stats *v4,
void t4_load_mtus(struct adapter *adap, const unsigned short *mtus,
const unsigned short *alpha, const unsigned short *beta);
+void t4_ulprx_read_la(struct adapter *adap, u32 *la_buf);
+
void t4_mk_filtdelwr(unsigned int ftid, struct fw_filter_wr *wr, int qid);
void t4_wol_magic_enable(struct adapter *adap, unsigned int port,
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_debugfs.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_debugfs.c
index 1304fe0..5a46273 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_debugfs.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_debugfs.c
@@ -562,6 +562,41 @@ static const struct file_operations tp_la_fops = {
.write = tp_la_write
};
+static int ulprx_la_show(struct seq_file *seq, void *v, int idx)
+{
+ const u32 *p = v;
+
+ if (v == SEQ_START_TOKEN)
+ seq_puts(seq, " Pcmd Type Message"
+ " Data\n");
+ else
+ seq_printf(seq, "%08x%08x %4x %08x %08x%08x%08x%08x\n",
+ p[1], p[0], p[2], p[3], p[7], p[6], p[5], p[4]);
+ return 0;
+}
+
+static int ulprx_la_open(struct inode *inode, struct file *file)
+{
+ struct seq_tab *p;
+ struct adapter *adap = inode->i_private;
+
+ p = seq_open_tab(file, ULPRX_LA_SIZE, 8 * sizeof(u32), 1,
+ ulprx_la_show);
+ if (!p)
+ return -ENOMEM;
+
+ t4_ulprx_read_la(adap, (u32 *)p->data);
+ return 0;
+}
+
+static const struct file_operations ulprx_la_fops = {
+ .owner = THIS_MODULE,
+ .open = ulprx_la_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = seq_release_private
+};
+
/* Show the PM memory stats. These stats include:
*
* TX:
@@ -1867,6 +1902,7 @@ int t4_setup_debugfs(struct adapter *adap)
{ "obq_sge", &cim_obq_fops, S_IRUSR, 4 },
{ "obq_ncsi", &cim_obq_fops, S_IRUSR, 5 },
{ "tp_la", &tp_la_fops, S_IRUSR, 0 },
+ { "ulprx_la", &ulprx_la_fops, S_IRUSR, 0 },
{ "sensors", &sensors_debugfs_fops, S_IRUSR, 0 },
{ "pm_stats", &pm_stats_debugfs_fops, S_IRUSR, 0 },
#if IS_ENABLED(CONFIG_IPV6)
diff --git a/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c b/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c
index 96cfa0a..5871c00 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c
@@ -1300,6 +1300,21 @@ int t4_fwcache(struct adapter *adap, enum fw_params_param_dev_fwcache op)
return t4_wr_mbox(adap, adap->mbox, &c, sizeof(c), NULL);
}
+void t4_ulprx_read_la(struct adapter *adap, u32 *la_buf)
+{
+ unsigned int i, j;
+
+ for (i = 0; i < 8; i++) {
+ u32 *p = la_buf + i;
+
+ t4_write_reg(adap, ULP_RX_LA_CTL_A, i);
+ j = t4_read_reg(adap, ULP_RX_LA_WRPTR_A);
+ t4_write_reg(adap, ULP_RX_LA_RDPTR_A, j);
+ for (j = 0; j < ULPRX_LA_SIZE; j++, p += 8)
+ *p = t4_read_reg(adap, ULP_RX_LA_RDDATA_A);
+ }
+}
+
#define ADVERT_MASK (FW_PORT_CAP_SPEED_100M | FW_PORT_CAP_SPEED_1G |\
FW_PORT_CAP_SPEED_10G | FW_PORT_CAP_SPEED_40G | \
FW_PORT_CAP_ANEG)
diff --git a/drivers/net/ethernet/chelsio/cxgb4/t4_hw.h b/drivers/net/ethernet/chelsio/cxgb4/t4_hw.h
index f0b98d7..380b15c 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/t4_hw.h
+++ b/drivers/net/ethernet/chelsio/cxgb4/t4_hw.h
@@ -64,6 +64,7 @@ enum {
CIM_IBQ_SIZE = 128, /* # of 128-bit words in a CIM IBQ */
CIM_OBQ_SIZE = 128, /* # of 128-bit words in a CIM OBQ */
TPLA_SIZE = 128, /* # of 64-bit words in TP LA */
+ ULPRX_LA_SIZE = 512, /* # of 256-bit words in ULP_RX LA */
};
enum {
diff --git a/drivers/net/ethernet/chelsio/cxgb4/t4_regs.h b/drivers/net/ethernet/chelsio/cxgb4/t4_regs.h
index 15d0ecc..91e0ea1 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/t4_regs.h
+++ b/drivers/net/ethernet/chelsio/cxgb4/t4_regs.h
@@ -2270,6 +2270,10 @@
#define ULP_RX_INT_CAUSE_A 0x19158
#define ULP_RX_ISCSI_TAGMASK_A 0x19164
#define ULP_RX_ISCSI_PSZ_A 0x19168
+#define ULP_RX_LA_CTL_A 0x1923c
+#define ULP_RX_LA_RDPTR_A 0x19240
+#define ULP_RX_LA_RDDATA_A 0x19244
+#define ULP_RX_LA_WRPTR_A 0x19248
#define HPZ3_S 24
#define HPZ3_V(x) ((x) << HPZ3_S)
--
1.7.1
^ permalink raw reply related
* [PATCHv2 net-next 2/5] cxgb4: Added support in debugfs to display TP logic analyzer output
From: Hariprasad Shenai @ 2015-02-06 14:02 UTC (permalink / raw)
To: netdev; +Cc: davem, leedom, anish, nirranjan, kumaras, Hariprasad Shenai
In-Reply-To: <1423231375-28004-1-git-send-email-hariprasad@chelsio.com>
Dump Transport Processor event trace.
Signed-off-by: Hariprasad Shenai <hariprasad@chelsio.com>
---
drivers/net/ethernet/chelsio/cxgb4/cxgb4.h | 2 +
drivers/net/ethernet/chelsio/cxgb4/cxgb4_debugfs.c | 248 ++++++++++++++++++++
drivers/net/ethernet/chelsio/cxgb4/t4_hw.c | 47 ++++
drivers/net/ethernet/chelsio/cxgb4/t4_hw.h | 1 +
drivers/net/ethernet/chelsio/cxgb4/t4_regs.h | 22 ++
5 files changed, 320 insertions(+), 0 deletions(-)
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h b/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h
index 63231bf..574e51f 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h
@@ -221,6 +221,7 @@ struct sge_params {
struct tp_params {
unsigned int ntxchan; /* # of Tx channels */
unsigned int tre; /* log2 of core clocks per TP tick */
+ unsigned int la_mask; /* what events are recorded by TP LA */
unsigned short tx_modq_map; /* TX modulation scheduler queue to */
/* channel map */
@@ -1175,6 +1176,7 @@ void t4_get_port_stats(struct adapter *adap, int idx, struct port_stats *p);
void t4_read_mtu_tbl(struct adapter *adap, u16 *mtus, u8 *mtu_log);
void t4_tp_wr_bits_indirect(struct adapter *adap, unsigned int addr,
unsigned int mask, unsigned int val);
+void t4_tp_read_la(struct adapter *adap, u64 *la_buf, unsigned int *wrptr);
void t4_tp_get_tcp_stats(struct adapter *adap, struct tp_tcp_stats *v4,
struct tp_tcp_stats *v6);
void t4_load_mtus(struct adapter *adap, const unsigned short *mtus,
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_debugfs.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_debugfs.c
index 35ec230..1304fe0 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_debugfs.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_debugfs.c
@@ -315,6 +315,253 @@ static const struct file_operations cim_obq_fops = {
.release = seq_release_private
};
+struct field_desc {
+ const char *name;
+ unsigned int start;
+ unsigned int width;
+};
+
+static void field_desc_show(struct seq_file *seq, u64 v,
+ const struct field_desc *p)
+{
+ char buf[32];
+ int line_size = 0;
+
+ while (p->name) {
+ u64 mask = (1ULL << p->width) - 1;
+ int len = scnprintf(buf, sizeof(buf), "%s: %llu", p->name,
+ ((unsigned long long)v >> p->start) & mask);
+
+ if (line_size + len >= 79) {
+ line_size = 8;
+ seq_puts(seq, "\n ");
+ }
+ seq_printf(seq, "%s ", buf);
+ line_size += len + 1;
+ p++;
+ }
+ seq_putc(seq, '\n');
+}
+
+static struct field_desc tp_la0[] = {
+ { "RcfOpCodeOut", 60, 4 },
+ { "State", 56, 4 },
+ { "WcfState", 52, 4 },
+ { "RcfOpcSrcOut", 50, 2 },
+ { "CRxError", 49, 1 },
+ { "ERxError", 48, 1 },
+ { "SanityFailed", 47, 1 },
+ { "SpuriousMsg", 46, 1 },
+ { "FlushInputMsg", 45, 1 },
+ { "FlushInputCpl", 44, 1 },
+ { "RssUpBit", 43, 1 },
+ { "RssFilterHit", 42, 1 },
+ { "Tid", 32, 10 },
+ { "InitTcb", 31, 1 },
+ { "LineNumber", 24, 7 },
+ { "Emsg", 23, 1 },
+ { "EdataOut", 22, 1 },
+ { "Cmsg", 21, 1 },
+ { "CdataOut", 20, 1 },
+ { "EreadPdu", 19, 1 },
+ { "CreadPdu", 18, 1 },
+ { "TunnelPkt", 17, 1 },
+ { "RcfPeerFin", 16, 1 },
+ { "RcfReasonOut", 12, 4 },
+ { "TxCchannel", 10, 2 },
+ { "RcfTxChannel", 8, 2 },
+ { "RxEchannel", 6, 2 },
+ { "RcfRxChannel", 5, 1 },
+ { "RcfDataOutSrdy", 4, 1 },
+ { "RxDvld", 3, 1 },
+ { "RxOoDvld", 2, 1 },
+ { "RxCongestion", 1, 1 },
+ { "TxCongestion", 0, 1 },
+ { NULL }
+};
+
+static int tp_la_show(struct seq_file *seq, void *v, int idx)
+{
+ const u64 *p = v;
+
+ field_desc_show(seq, *p, tp_la0);
+ return 0;
+}
+
+static int tp_la_show2(struct seq_file *seq, void *v, int idx)
+{
+ const u64 *p = v;
+
+ if (idx)
+ seq_putc(seq, '\n');
+ field_desc_show(seq, p[0], tp_la0);
+ if (idx < (TPLA_SIZE / 2 - 1) || p[1] != ~0ULL)
+ field_desc_show(seq, p[1], tp_la0);
+ return 0;
+}
+
+static int tp_la_show3(struct seq_file *seq, void *v, int idx)
+{
+ static struct field_desc tp_la1[] = {
+ { "CplCmdIn", 56, 8 },
+ { "CplCmdOut", 48, 8 },
+ { "ESynOut", 47, 1 },
+ { "EAckOut", 46, 1 },
+ { "EFinOut", 45, 1 },
+ { "ERstOut", 44, 1 },
+ { "SynIn", 43, 1 },
+ { "AckIn", 42, 1 },
+ { "FinIn", 41, 1 },
+ { "RstIn", 40, 1 },
+ { "DataIn", 39, 1 },
+ { "DataInVld", 38, 1 },
+ { "PadIn", 37, 1 },
+ { "RxBufEmpty", 36, 1 },
+ { "RxDdp", 35, 1 },
+ { "RxFbCongestion", 34, 1 },
+ { "TxFbCongestion", 33, 1 },
+ { "TxPktSumSrdy", 32, 1 },
+ { "RcfUlpType", 28, 4 },
+ { "Eread", 27, 1 },
+ { "Ebypass", 26, 1 },
+ { "Esave", 25, 1 },
+ { "Static0", 24, 1 },
+ { "Cread", 23, 1 },
+ { "Cbypass", 22, 1 },
+ { "Csave", 21, 1 },
+ { "CPktOut", 20, 1 },
+ { "RxPagePoolFull", 18, 2 },
+ { "RxLpbkPkt", 17, 1 },
+ { "TxLpbkPkt", 16, 1 },
+ { "RxVfValid", 15, 1 },
+ { "SynLearned", 14, 1 },
+ { "SetDelEntry", 13, 1 },
+ { "SetInvEntry", 12, 1 },
+ { "CpcmdDvld", 11, 1 },
+ { "CpcmdSave", 10, 1 },
+ { "RxPstructsFull", 8, 2 },
+ { "EpcmdDvld", 7, 1 },
+ { "EpcmdFlush", 6, 1 },
+ { "EpcmdTrimPrefix", 5, 1 },
+ { "EpcmdTrimPostfix", 4, 1 },
+ { "ERssIp4Pkt", 3, 1 },
+ { "ERssIp6Pkt", 2, 1 },
+ { "ERssTcpUdpPkt", 1, 1 },
+ { "ERssFceFipPkt", 0, 1 },
+ { NULL }
+ };
+ static struct field_desc tp_la2[] = {
+ { "CplCmdIn", 56, 8 },
+ { "MpsVfVld", 55, 1 },
+ { "MpsPf", 52, 3 },
+ { "MpsVf", 44, 8 },
+ { "SynIn", 43, 1 },
+ { "AckIn", 42, 1 },
+ { "FinIn", 41, 1 },
+ { "RstIn", 40, 1 },
+ { "DataIn", 39, 1 },
+ { "DataInVld", 38, 1 },
+ { "PadIn", 37, 1 },
+ { "RxBufEmpty", 36, 1 },
+ { "RxDdp", 35, 1 },
+ { "RxFbCongestion", 34, 1 },
+ { "TxFbCongestion", 33, 1 },
+ { "TxPktSumSrdy", 32, 1 },
+ { "RcfUlpType", 28, 4 },
+ { "Eread", 27, 1 },
+ { "Ebypass", 26, 1 },
+ { "Esave", 25, 1 },
+ { "Static0", 24, 1 },
+ { "Cread", 23, 1 },
+ { "Cbypass", 22, 1 },
+ { "Csave", 21, 1 },
+ { "CPktOut", 20, 1 },
+ { "RxPagePoolFull", 18, 2 },
+ { "RxLpbkPkt", 17, 1 },
+ { "TxLpbkPkt", 16, 1 },
+ { "RxVfValid", 15, 1 },
+ { "SynLearned", 14, 1 },
+ { "SetDelEntry", 13, 1 },
+ { "SetInvEntry", 12, 1 },
+ { "CpcmdDvld", 11, 1 },
+ { "CpcmdSave", 10, 1 },
+ { "RxPstructsFull", 8, 2 },
+ { "EpcmdDvld", 7, 1 },
+ { "EpcmdFlush", 6, 1 },
+ { "EpcmdTrimPrefix", 5, 1 },
+ { "EpcmdTrimPostfix", 4, 1 },
+ { "ERssIp4Pkt", 3, 1 },
+ { "ERssIp6Pkt", 2, 1 },
+ { "ERssTcpUdpPkt", 1, 1 },
+ { "ERssFceFipPkt", 0, 1 },
+ { NULL }
+ };
+ const u64 *p = v;
+
+ if (idx)
+ seq_putc(seq, '\n');
+ field_desc_show(seq, p[0], tp_la0);
+ if (idx < (TPLA_SIZE / 2 - 1) || p[1] != ~0ULL)
+ field_desc_show(seq, p[1], (p[0] & BIT(17)) ? tp_la2 : tp_la1);
+ return 0;
+}
+
+static int tp_la_open(struct inode *inode, struct file *file)
+{
+ struct seq_tab *p;
+ struct adapter *adap = inode->i_private;
+
+ switch (DBGLAMODE_G(t4_read_reg(adap, TP_DBG_LA_CONFIG_A))) {
+ case 2:
+ p = seq_open_tab(file, TPLA_SIZE / 2, 2 * sizeof(u64), 0,
+ tp_la_show2);
+ break;
+ case 3:
+ p = seq_open_tab(file, TPLA_SIZE / 2, 2 * sizeof(u64), 0,
+ tp_la_show3);
+ break;
+ default:
+ p = seq_open_tab(file, TPLA_SIZE, sizeof(u64), 0, tp_la_show);
+ }
+ if (!p)
+ return -ENOMEM;
+
+ t4_tp_read_la(adap, (u64 *)p->data, NULL);
+ return 0;
+}
+
+static ssize_t tp_la_write(struct file *file, const char __user *buf,
+ size_t count, loff_t *pos)
+{
+ int err;
+ char s[32];
+ unsigned long val;
+ size_t size = min(sizeof(s) - 1, count);
+ struct adapter *adap = FILE_DATA(file)->i_private;
+
+ if (copy_from_user(s, buf, size))
+ return -EFAULT;
+ s[size] = '\0';
+ err = kstrtoul(s, 0, &val);
+ if (err)
+ return err;
+ if (val > 0xffff)
+ return -EINVAL;
+ adap->params.tp.la_mask = val << 16;
+ t4_set_reg_field(adap, TP_DBG_LA_CONFIG_A, 0xffff0000U,
+ adap->params.tp.la_mask);
+ return count;
+}
+
+static const struct file_operations tp_la_fops = {
+ .owner = THIS_MODULE,
+ .open = tp_la_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = seq_release_private,
+ .write = tp_la_write
+};
+
/* Show the PM memory stats. These stats include:
*
* TX:
@@ -1619,6 +1866,7 @@ int t4_setup_debugfs(struct adapter *adap)
{ "obq_ulp3", &cim_obq_fops, S_IRUSR, 3 },
{ "obq_sge", &cim_obq_fops, S_IRUSR, 4 },
{ "obq_ncsi", &cim_obq_fops, S_IRUSR, 5 },
+ { "tp_la", &tp_la_fops, S_IRUSR, 0 },
{ "sensors", &sensors_debugfs_fops, S_IRUSR, 0 },
{ "pm_stats", &pm_stats_debugfs_fops, S_IRUSR, 0 },
#if IS_ENABLED(CONFIG_IPV6)
diff --git a/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c b/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c
index ae69796..96cfa0a 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c
@@ -4819,3 +4819,50 @@ restart:
}
return ret;
}
+
+/**
+ * t4_tp_read_la - read TP LA capture buffer
+ * @adap: the adapter
+ * @la_buf: where to store the LA data
+ * @wrptr: the HW write pointer within the capture buffer
+ *
+ * Reads the contents of the TP LA buffer with the most recent entry at
+ * the end of the returned data and with the entry at @wrptr first.
+ * We leave the LA in the running state we find it in.
+ */
+void t4_tp_read_la(struct adapter *adap, u64 *la_buf, unsigned int *wrptr)
+{
+ bool last_incomplete;
+ unsigned int i, cfg, val, idx;
+
+ cfg = t4_read_reg(adap, TP_DBG_LA_CONFIG_A) & 0xffff;
+ if (cfg & DBGLAENABLE_F) /* freeze LA */
+ t4_write_reg(adap, TP_DBG_LA_CONFIG_A,
+ adap->params.tp.la_mask | (cfg ^ DBGLAENABLE_F));
+
+ val = t4_read_reg(adap, TP_DBG_LA_CONFIG_A);
+ idx = DBGLAWPTR_G(val);
+ last_incomplete = DBGLAMODE_G(val) >= 2 && (val & DBGLAWHLF_F) == 0;
+ if (last_incomplete)
+ idx = (idx + 1) & DBGLARPTR_M;
+ if (wrptr)
+ *wrptr = idx;
+
+ val &= 0xffff;
+ val &= ~DBGLARPTR_V(DBGLARPTR_M);
+ val |= adap->params.tp.la_mask;
+
+ for (i = 0; i < TPLA_SIZE; i++) {
+ t4_write_reg(adap, TP_DBG_LA_CONFIG_A, DBGLARPTR_V(idx) | val);
+ la_buf[i] = t4_read_reg64(adap, TP_DBG_LA_DATAL_A);
+ idx = (idx + 1) & DBGLARPTR_M;
+ }
+
+ /* Wipe out last entry if it isn't valid */
+ if (last_incomplete)
+ la_buf[TPLA_SIZE - 1] = ~0ULL;
+
+ if (cfg & DBGLAENABLE_F) /* restore running state */
+ t4_write_reg(adap, TP_DBG_LA_CONFIG_A,
+ cfg | adap->params.tp.la_mask);
+}
diff --git a/drivers/net/ethernet/chelsio/cxgb4/t4_hw.h b/drivers/net/ethernet/chelsio/cxgb4/t4_hw.h
index 664375f..f0b98d7 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/t4_hw.h
+++ b/drivers/net/ethernet/chelsio/cxgb4/t4_hw.h
@@ -63,6 +63,7 @@ enum {
CIMLA_SIZE = 2048, /* # of 32-bit words in CIM LA */
CIM_IBQ_SIZE = 128, /* # of 128-bit words in a CIM IBQ */
CIM_OBQ_SIZE = 128, /* # of 128-bit words in a CIM OBQ */
+ TPLA_SIZE = 128, /* # of 64-bit words in TP LA */
};
enum {
diff --git a/drivers/net/ethernet/chelsio/cxgb4/t4_regs.h b/drivers/net/ethernet/chelsio/cxgb4/t4_regs.h
index 940b56c..15d0ecc 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/t4_regs.h
+++ b/drivers/net/ethernet/chelsio/cxgb4/t4_regs.h
@@ -1183,9 +1183,31 @@
#define RSVDSPACEINT_F RSVDSPACEINT_V(1U)
/* registers for module TP */
+#define DBGLAWHLF_S 23
+#define DBGLAWHLF_V(x) ((x) << DBGLAWHLF_S)
+#define DBGLAWHLF_F DBGLAWHLF_V(1U)
+
+#define DBGLAWPTR_S 16
+#define DBGLAWPTR_M 0x7fU
+#define DBGLAWPTR_G(x) (((x) >> DBGLAWPTR_S) & DBGLAWPTR_M)
+
+#define DBGLAENABLE_S 12
+#define DBGLAENABLE_V(x) ((x) << DBGLAENABLE_S)
+#define DBGLAENABLE_F DBGLAENABLE_V(1U)
+
+#define DBGLARPTR_S 0
+#define DBGLARPTR_M 0x7fU
+#define DBGLARPTR_V(x) ((x) << DBGLARPTR_S)
+
+#define TP_DBG_LA_DATAL_A 0x7ed8
+#define TP_DBG_LA_CONFIG_A 0x7ed4
#define TP_OUT_CONFIG_A 0x7d04
#define TP_GLOBAL_CONFIG_A 0x7d08
+#define DBGLAMODE_S 14
+#define DBGLAMODE_M 0x3U
+#define DBGLAMODE_G(x) (((x) >> DBGLAMODE_S) & DBGLAMODE_M)
+
#define FIVETUPLELOOKUP_S 17
#define FIVETUPLELOOKUP_M 0x3U
#define FIVETUPLELOOKUP_V(x) ((x) << FIVETUPLELOOKUP_S)
--
1.7.1
^ permalink raw reply related
* [PATCHv2 net-next 1/5] cxgb4: Add support in debugfs to display sensor information
From: Hariprasad Shenai @ 2015-02-06 14:02 UTC (permalink / raw)
To: netdev; +Cc: davem, leedom, anish, nirranjan, kumaras, Hariprasad Shenai
In-Reply-To: <1423231375-28004-1-git-send-email-hariprasad@chelsio.com>
Dump out various chip sensor information. Currently Chip Temperature
and Core Voltage.
Signed-off-by: Hariprasad Shenai <hariprasad@chelsio.com>
---
drivers/net/ethernet/chelsio/cxgb4/cxgb4_debugfs.c | 36 ++++++++++++++++++++
drivers/net/ethernet/chelsio/cxgb4/t4fw_api.h | 6 +++
2 files changed, 42 insertions(+), 0 deletions(-)
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_debugfs.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_debugfs.c
index 61c000a..35ec230 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_debugfs.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_debugfs.c
@@ -813,6 +813,41 @@ static const struct file_operations mps_tcam_debugfs_fops = {
.release = seq_release,
};
+/* Display various sensor information.
+ */
+static int sensors_show(struct seq_file *seq, void *v)
+{
+ struct adapter *adap = seq->private;
+ u32 param[7], val[7];
+ int ret;
+
+ /* Note that if the sensors haven't been initialized and turned on
+ * we'll get values of 0, so treat those as "<unknown>" ...
+ */
+ param[0] = (FW_PARAMS_MNEM_V(FW_PARAMS_MNEM_DEV) |
+ FW_PARAMS_PARAM_X_V(FW_PARAMS_PARAM_DEV_DIAG) |
+ FW_PARAMS_PARAM_Y_V(FW_PARAM_DEV_DIAG_TMP));
+ param[1] = (FW_PARAMS_MNEM_V(FW_PARAMS_MNEM_DEV) |
+ FW_PARAMS_PARAM_X_V(FW_PARAMS_PARAM_DEV_DIAG) |
+ FW_PARAMS_PARAM_Y_V(FW_PARAM_DEV_DIAG_VDD));
+ ret = t4_query_params(adap, adap->mbox, adap->fn, 0, 2,
+ param, val);
+
+ if (ret < 0 || val[0] == 0)
+ seq_puts(seq, "Temperature: <unknown>\n");
+ else
+ seq_printf(seq, "Temperature: %dC\n", val[0]);
+
+ if (ret < 0 || val[1] == 0)
+ seq_puts(seq, "Core VDD: <unknown>\n");
+ else
+ seq_printf(seq, "Core VDD: %dmV\n", val[1]);
+
+ return 0;
+}
+
+DEFINE_SIMPLE_DEBUGFS_FILE(sensors);
+
#if IS_ENABLED(CONFIG_IPV6)
static int clip_tbl_open(struct inode *inode, struct file *file)
{
@@ -1584,6 +1619,7 @@ int t4_setup_debugfs(struct adapter *adap)
{ "obq_ulp3", &cim_obq_fops, S_IRUSR, 3 },
{ "obq_sge", &cim_obq_fops, S_IRUSR, 4 },
{ "obq_ncsi", &cim_obq_fops, S_IRUSR, 5 },
+ { "sensors", &sensors_debugfs_fops, S_IRUSR, 0 },
{ "pm_stats", &pm_stats_debugfs_fops, S_IRUSR, 0 },
#if IS_ENABLED(CONFIG_IPV6)
{ "clip_tbl", &clip_tbl_debugfs_fops, S_IRUSR, 0 },
diff --git a/drivers/net/ethernet/chelsio/cxgb4/t4fw_api.h b/drivers/net/ethernet/chelsio/cxgb4/t4fw_api.h
index c009627..9b353a8 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/t4fw_api.h
+++ b/drivers/net/ethernet/chelsio/cxgb4/t4fw_api.h
@@ -1059,6 +1059,7 @@ enum fw_params_param_dev {
FW_PARAMS_PARAM_DEV_FWREV = 0x0B,
FW_PARAMS_PARAM_DEV_TPREV = 0x0C,
FW_PARAMS_PARAM_DEV_CF = 0x0D,
+ FW_PARAMS_PARAM_DEV_DIAG = 0x11,
FW_PARAMS_PARAM_DEV_MAXORDIRD_QP = 0x13, /* max supported QP IRD/ORD */
FW_PARAMS_PARAM_DEV_MAXIRD_ADAPTER = 0x14, /* max supported adap IRD */
FW_PARAMS_PARAM_DEV_ULPTX_MEMWRITE_DSGL = 0x17,
@@ -1122,6 +1123,11 @@ enum fw_params_param_dmaq {
FW_PARAMS_PARAM_DMAQ_EQ_DCBPRIO_ETH = 0x13,
};
+enum fw_params_param_dev_diag {
+ FW_PARAM_DEV_DIAG_TMP = 0x00,
+ FW_PARAM_DEV_DIAG_VDD = 0x01,
+};
+
enum fw_params_param_dev_fwcache {
FW_PARAM_DEV_FWCACHE_FLUSH = 0x00,
FW_PARAM_DEV_FWCACHE_FLUSHINV = 0x01,
--
1.7.1
^ permalink raw reply related
* [PATCHv2 net-next 0/5] Add support to dump some hw debug info
From: Hariprasad Shenai @ 2015-02-06 14:02 UTC (permalink / raw)
To: netdev; +Cc: davem, leedom, anish, nirranjan, kumaras, Hariprasad Shenai
Hi,
This patch series adds support to dump sensor info, dump Transport Processor
event trace, dump Upper Layer Protocol RX module command trace, dump mailbox
contents and dump Transport Processor congestion control configuration.
Will send a separate patch series for all the hw stats patches, by moving them
to ethtool.
The patches series is created against 'net-next' tree.
And includes patches on cxgb4 driver.
We have included all the maintainers of respective drivers. Kindly review the
change and let us know in case of any review comments.
Thanks
V2: Dopped all hw stats related patches. Added a new patch which adds support to
dump congestion control table.
Hariprasad Shenai (5):
cxgb4: Add support in debugfs to display sensor information
cxgb4: Added support in debugfs to display TP logic analyzer output
cxgb4: Add support for ULP RX logic analyzer output in debugfs
cxgb4: Add support to dump mailbox content in debugfs
cxgb4: Add support in debugfs to dump the congestion control table
drivers/net/ethernet/chelsio/cxgb4/cxgb4.h | 5 +
drivers/net/ethernet/chelsio/cxgb4/cxgb4_debugfs.c | 433 ++++++++++++++++++++
drivers/net/ethernet/chelsio/cxgb4/t4_hw.c | 83 ++++
drivers/net/ethernet/chelsio/cxgb4/t4_hw.h | 2 +
drivers/net/ethernet/chelsio/cxgb4/t4_regs.h | 30 ++
drivers/net/ethernet/chelsio/cxgb4/t4_values.h | 5 +
drivers/net/ethernet/chelsio/cxgb4/t4fw_api.h | 6 +
7 files changed, 564 insertions(+), 0 deletions(-)
^ permalink raw reply
* Re: Ethernet: how to disable gigabit support
From: Pavel Machek @ 2015-02-06 13:57 UTC (permalink / raw)
To: Florian Fainelli; +Cc: kernel list, netdev
In-Reply-To: <54D3F267.3000908@gmail.com>
On Thu 2015-02-05 14:44:55, Florian Fainelli wrote:
> On 05/02/15 12:25, Pavel Machek wrote:
> > Hi!
> >
> > This happened on more than one project: there's gigabit-capable chip,
> > but the connector is not designed for gigabit speed.
> >
> > I'd like to have speed autonegotiation, but not offer gigabit (as it
> > will not work).
> >
> > Is there way to do that without hacking the kernel? Should mii-tool do
> > that?
>
> Since you use the PHY library, you should be able to do something like
> this in your PHY driver prior to starting the PHY state machine:
>
> phydev->supported &= PHY_BASIC_FEATURES (effectively masking Gigabit
> capability)
Thanks, that did the trick.
Pavel
(But still it would be nice to have a generic way of doing this,
using something like mii-tool.)
--
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html
^ permalink raw reply
* Re: Throughput regression with `tcp: refine TSO autosizing`
From: Eric Dumazet @ 2015-02-06 13:53 UTC (permalink / raw)
To: Michal Kazior
Cc: Neal Cardwell, linux-wireless, Network Development,
eyalpe-LDSdmyG8hGV8YrgS2mwiifqBs+8SCbDb
In-Reply-To: <1423230001.31870.128.camel-XN9IlZ5yJG9HTL0Zs8A6p/gx64E7kk8eUsxypvmhUTTZJqsBc5GL+g@public.gmane.org>
On Fri, 2015-02-06 at 05:40 -0800, Eric Dumazet wrote:
> tcp_wfree() could maintain in tp->tx_completion_delay_ms an EWMA
> of TX completion delay. But this would require yet another expensive
> call to ktime_get() if HZ < 1000.
>
> Then tcp_write_xmit() could use it to adjust :
>
> limit = max(2 * skb->truesize, sk->sk_pacing_rate >> 9);
>
> to
>
> amount = (2 + tp->tx_completion_delay_ms) * sk->sk_pacing_rate
>
> limit = max(2 * skb->truesize, amount / 1000);
>
> I'll cook a patch.
Hmm... doing this in all protocols would be too expensive,
and we do not want to include time spent in qdiscs.
wifi could eventually do that, providing in skb->tx_completion_delay_us
the time spent in wifi driver.
This way, we would have no penalty for network devices doing normal skb
orphaning (loopback interface, ethernet, ...)
--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [PATCH net] pktgen: fix UDP checksum computation
From: Sabrina Dubroca @ 2015-02-06 13:46 UTC (permalink / raw)
To: Eric Dumazet; +Cc: Tom Herbert, David Miller, Linux Netdev List, Thomas Graf
In-Reply-To: <1423182482.31870.99.camel@edumazet-glaptop2.roam.corp.google.com>
2015-02-05, 16:28:02 -0800, Eric Dumazet wrote:
> On Thu, 2015-02-05 at 15:57 -0800, Tom Herbert wrote:
>
> > Would it be possible to use udp_set_csum to handle all of this?
I will look.
> This reminds me we have following sparse errors with checksum code,
> could you take a look Tom ?
>
> make C=2 CF=-D__CHECK_ENDIAN__ ...
>
> include/linux/skbuff.h:3022:24: warning: incorrect type in return expression (different base types)
> include/linux/skbuff.h:3022:24: expected restricted __sum16
> include/linux/skbuff.h:3022:24: got int
>
> net/ipv6/ip6_checksum.c:83:16: warning: incorrect type in return expression (different base types)
> net/ipv6/ip6_checksum.c:83:16: expected int
> net/ipv6/ip6_checksum.c:83:16: got restricted __sum16 [assigned] [usertype] __ret
>
> CHECK net/ipv4/tcp_offload.c
> net/ipv4/tcp_offload.c:139:60: warning: incorrect type in argument 2 (different base types)
> net/ipv4/tcp_offload.c:139:60: expected restricted __wsum [usertype] res
> net/ipv4/tcp_offload.c:139:60: got fouled restricted __sum16
> include/linux/skbuff.h:3317:14: warning: incorrect type in assignment (different base types)
> include/linux/skbuff.h:3317:14: expected unsigned short [unsigned] [usertype] csum
> include/linux/skbuff.h:3317:14: got restricted __sum16
> include/linux/skbuff.h:3322:16: warning: incorrect type in return expression (different base types)
> include/linux/skbuff.h:3322:16: expected restricted __sum16
> include/linux/skbuff.h:3322:16: got unsigned short [unsigned] [usertype] csum
> net/ipv4/tcp_offload.c:173:52: warning: incorrect type in argument 2 (different base types)
> net/ipv4/tcp_offload.c:173:52: expected restricted __wsum [usertype] res
> net/ipv4/tcp_offload.c:173:52: got fouled restricted __sum16
> include/linux/skbuff.h:3317:14: warning: incorrect type in assignment (different base types)
> include/linux/skbuff.h:3317:14: expected unsigned short [unsigned] [usertype] csum
> include/linux/skbuff.h:3317:14: got restricted __sum16
> include/linux/skbuff.h:3322:16: warning: incorrect type in return expression (different base types)
> include/linux/skbuff.h:3322:16: expected restricted __sum16
> include/linux/skbuff.h:3322:16: got unsigned short [unsigned] [usertype] csum
I have patches ready for that and other sparse warnings, I just need
to check and send them.
Thanks
--
Sabrina
^ permalink raw reply
* Re: Throughput regression with `tcp: refine TSO autosizing`
From: Eric Dumazet @ 2015-02-06 13:40 UTC (permalink / raw)
To: Michal Kazior
Cc: Neal Cardwell, linux-wireless, Network Development,
eyalpe-LDSdmyG8hGV8YrgS2mwiifqBs+8SCbDb
In-Reply-To: <CA+BoTQ=WaKLV=r6qWaWAEfyDr2pqMWpm4NDmnek92TEVndnxRQ-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
On Fri, 2015-02-06 at 10:42 +0100, Michal Kazior wrote:
> The above brings back previous behaviour, i.e. I can get 600mbps TCP
> on 5 flows again. Single flow is still (as it was before TSO
> autosizing) limited to roughly ~280mbps.
>
> I never really bothered before to understand why I need to push a few
> flows through ath10k to max it out, i.e. if I run a single UDP flow I
> get ~300mbps while with, e.g. 5 I get 670mbps easily.
>
For single UDP flow, tweaking /proc/sys/net/core/wmem_default might be
enough : UDP has no callback from TX completion to feed following frames
(No write queue like TCP)
# cat /proc/sys/net/core/wmem_default
212992
# ethtool -C eth1 tx-usecs 1024 tx-frames 120
# ./netperf -H remote -t UDP_STREAM -- -m 1450
Socket Message Elapsed Messages
Size Size Time Okay Errors Throughput
bytes bytes secs # # 10^6bits/sec
212992 1450 10.00 697705 0 809.27
212992 10.00 673412 781.09
# echo 800000 >/proc/sys/net/core/wmem_default
# ./netperf -H remote -t UDP_STREAM -- -m 1450
Socket Message Elapsed Messages
Size Size Time Okay Errors Throughput
bytes bytes secs # # 10^6bits/sec
800000 1450 10.00 7329221 0 8501.84
212992 10.00 7284051 8449.44
> I guess it was the tx completion latency all along.
>
> I just put an extra debug to ath10k to see the latency between
> submission and completion. Here's a log
> (http://www.filedropper.com/complete-log) of 2s run of UDP iperf
> trying to push 1gbps but managing only 300mbps.
>
> I've made sure to not hold any locks nor introduce internal to ath10k
> delays. Frames get completed between 2-4ms in avarage during load.
tcp_wfree() could maintain in tp->tx_completion_delay_ms an EWMA
of TX completion delay. But this would require yet another expensive
call to ktime_get() if HZ < 1000.
Then tcp_write_xmit() could use it to adjust :
limit = max(2 * skb->truesize, sk->sk_pacing_rate >> 9);
to
amount = (2 + tp->tx_completion_delay_ms) * sk->sk_pacing_rate
limit = max(2 * skb->truesize, amount / 1000);
I'll cook a patch.
Thanks.
--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* [PATCH] brcm80211: drop unreachable else case
From: Nicholas Mc Guire @ 2015-02-06 13:26 UTC (permalink / raw)
To: Brett Rudley
Cc: Arend van Spriel, Franky (Zhenhui) Lin, Hante Meuleman,
Kalle Valo, Fabian Frederick, John W. Linville, David S. Miller,
linux-wireless, brcm80211-dev-list, netdev, linux-kernel,
Nicholas Mc Guire
the if/elseif/else is exhaustive - there is no 4th case given the
rssi_ctrl_mask = RADIO_2055_NBRSSI_SEL | RADIO_2055_WBRSSI_G1_SEL |
RADIO_2055_WBRSSI_G2_SEL;
so this unreachable else case (dead code) can be dropped.
Signed-off-by: Nicholas Mc Guire <hofrat@osadl.org>
---
It seems that there are only three cases:
RADIO_2055_NBRSSI_SEL | RADIO_2055_WBRSSI_G1_SEL | RADIO_2055_WBRSSI_G2_SEL
The conditional call to wlc_phy_rssisel_nphy(... NPHY_RSSI_SEL_*) thus do
not seem to have a 4th case which would be covered by the final else.
If the final else is there to accommodate extensions then this patch is
of course wrong - in that case it would be good though to comment the
final else as it appears to be dead-code at the moment.
Patch was only compile tested with x86_64_defconfig + CONFIG_BRCMSMAC=m
Patch is against 3.19.0-rc7 (localversion-next is -next-20150204)
drivers/net/wireless/brcm80211/brcmsmac/phy/phy_n.c | 11 ++---------
1 file changed, 2 insertions(+), 9 deletions(-)
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_n.c b/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_n.c
index 084f18f..99dac9b 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_n.c
+++ b/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_n.c
@@ -23041,10 +23041,7 @@ static void wlc_phy_rssi_cal_nphy_rev2(struct brcms_phy *pi, u8 rssi_type)
else if (rssi_ctrl_state[0] == RADIO_2055_WBRSSI_G1_SEL)
wlc_phy_rssisel_nphy(pi, RADIO_MIMO_CORESEL_CORE1,
NPHY_RSSI_SEL_W1);
- else if (rssi_ctrl_state[0] == RADIO_2055_WBRSSI_G2_SEL)
- wlc_phy_rssisel_nphy(pi, RADIO_MIMO_CORESEL_CORE1,
- NPHY_RSSI_SEL_W2);
- else
+ else /* RADIO_2055_WBRSSI_G2_SEL */
wlc_phy_rssisel_nphy(pi, RADIO_MIMO_CORESEL_CORE1,
NPHY_RSSI_SEL_W2);
if (rssi_ctrl_state[1] == RADIO_2055_NBRSSI_SEL)
@@ -23053,13 +23050,9 @@ static void wlc_phy_rssi_cal_nphy_rev2(struct brcms_phy *pi, u8 rssi_type)
else if (rssi_ctrl_state[1] == RADIO_2055_WBRSSI_G1_SEL)
wlc_phy_rssisel_nphy(pi, RADIO_MIMO_CORESEL_CORE2,
NPHY_RSSI_SEL_W1);
- else if (rssi_ctrl_state[1] == RADIO_2055_WBRSSI_G2_SEL)
+ else /* RADIO_2055_WBRSSI_G1_SEL */
wlc_phy_rssisel_nphy(pi, RADIO_MIMO_CORESEL_CORE2,
NPHY_RSSI_SEL_W2);
- else
- wlc_phy_rssisel_nphy(pi, RADIO_MIMO_CORESEL_CORE2,
- NPHY_RSSI_SEL_W2);
-
wlc_phy_rssisel_nphy(pi, RADIO_MIMO_CORESEL_OFF, rssi_type);
write_phy_reg(pi, 0x91, rfctrlintc_state[0]);
--
1.7.10.4
^ permalink raw reply related
* [PATCH net-next 8/9] be2net: process port misconfig async event
From: Sathya Perla @ 2015-02-06 13:18 UTC (permalink / raw)
To: netdev
In-Reply-To: <1423228723-10919-1-git-send-email-sathya.perla@emulex.com>
From: Vasundhara Volam <vasundhara.volam@emulex.com>
This patch adds support for processing the port misconfigure async
event generated by the FW. This event is generated typically when an
optical module is incorrectly installed or is faulty.
This patch also moves the port_name field to the adapter struct for
logging the event. As the be_cmd_query_port_name() call is now moved
to be_get_config(), it is modified to use the mailbox instead of MCCQ
Signed-off-by: Sathya Perla <sathya.perla@emulex.com>
---
drivers/net/ethernet/emulex/benet/be.h | 6 ++
drivers/net/ethernet/emulex/benet/be_cmds.c | 119 ++++++++++++++++++++++------
drivers/net/ethernet/emulex/benet/be_cmds.h | 16 +++-
drivers/net/ethernet/emulex/benet/be_main.c | 28 +++++--
4 files changed, 139 insertions(+), 30 deletions(-)
diff --git a/drivers/net/ethernet/emulex/benet/be.h b/drivers/net/ethernet/emulex/benet/be.h
index 98716e1..27de37a 100644
--- a/drivers/net/ethernet/emulex/benet/be.h
+++ b/drivers/net/ethernet/emulex/benet/be.h
@@ -368,6 +368,7 @@ enum vf_state {
#define BE_FLAGS_QNQ_ASYNC_EVT_RCVD BIT(7)
#define BE_FLAGS_VXLAN_OFFLOADS BIT(8)
#define BE_FLAGS_SETUP_DONE BIT(9)
+#define BE_FLAGS_EVT_INCOMPATIBLE_SFP BIT(10)
#define BE_UC_PMAC_COUNT 30
#define BE_VF_UC_PMAC_COUNT 2
@@ -377,6 +378,8 @@ enum vf_state {
#define LANCER_DELETE_FW_DUMP 0x2
struct phy_info {
+/* From SFF-8472 spec */
+#define SFP_VENDOR_NAME_LEN 17
u8 transceiver;
u8 autoneg;
u8 fc_autoneg;
@@ -390,6 +393,8 @@ struct phy_info {
u32 advertising;
u32 supported;
u8 cable_type;
+ u8 vendor_name[SFP_VENDOR_NAME_LEN];
+ u8 vendor_pn[SFP_VENDOR_NAME_LEN];
};
struct be_resources {
@@ -478,6 +483,7 @@ struct be_adapter {
bool hw_error;
u32 port_num;
+ char port_name;
u8 mc_type;
u32 function_mode;
u32 function_caps;
diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.c b/drivers/net/ethernet/emulex/benet/be_cmds.c
index 1c85bbf..f0276f5 100644
--- a/drivers/net/ethernet/emulex/benet/be_cmds.c
+++ b/drivers/net/ethernet/emulex/benet/be_cmds.c
@@ -19,6 +19,22 @@
#include "be.h"
#include "be_cmds.h"
+static char *be_port_misconfig_evt_desc[] = {
+ "A valid SFP module detected",
+ "Optics faulted/ incorrectly installed/ not installed.",
+ "Optics of two types installed.",
+ "Incompatible optics.",
+ "Unknown port SFP status"
+};
+
+static char *be_port_misconfig_remedy_desc[] = {
+ "",
+ "Reseat optics. If issue not resolved, replace",
+ "Remove one optic or install matching pair of optics",
+ "Replace with compatible optics for card to function",
+ ""
+};
+
static struct be_cmd_priv_map cmd_priv_map[] = {
{
OPCODE_ETH_ACPI_WOL_MAGIC_CONFIG,
@@ -249,6 +265,29 @@ static void be_async_link_state_process(struct be_adapter *adapter,
evt->port_link_status & LINK_STATUS_MASK);
}
+static void be_async_port_misconfig_event_process(struct be_adapter *adapter,
+ struct be_mcc_compl *compl)
+{
+ struct be_async_event_misconfig_port *evt =
+ (struct be_async_event_misconfig_port *)compl;
+ u32 sfp_mismatch_evt = le32_to_cpu(evt->event_data_word1);
+ struct device *dev = &adapter->pdev->dev;
+ u8 port_misconfig_evt;
+
+ port_misconfig_evt =
+ ((sfp_mismatch_evt >> (adapter->hba_port_num * 8)) & 0xff);
+
+ /* Log an error message that would allow a user to determine
+ * whether the SFPs have an issue
+ */
+ dev_info(dev, "Port %c: %s %s", adapter->port_name,
+ be_port_misconfig_evt_desc[port_misconfig_evt],
+ be_port_misconfig_remedy_desc[port_misconfig_evt]);
+
+ if (port_misconfig_evt == INCOMPATIBLE_SFP)
+ adapter->flags |= BE_FLAGS_EVT_INCOMPATIBLE_SFP;
+}
+
/* Grp5 CoS Priority evt */
static void be_async_grp5_cos_priority_process(struct be_adapter *adapter,
struct be_mcc_compl *compl)
@@ -334,6 +373,16 @@ static void be_async_dbg_evt_process(struct be_adapter *adapter,
}
}
+static void be_async_sliport_evt_process(struct be_adapter *adapter,
+ struct be_mcc_compl *cmp)
+{
+ u8 event_type = (cmp->flags >> ASYNC_EVENT_TYPE_SHIFT) &
+ ASYNC_EVENT_TYPE_MASK;
+
+ if (event_type == ASYNC_EVENT_PORT_MISCONFIG)
+ be_async_port_misconfig_event_process(adapter, cmp);
+}
+
static inline bool is_link_state_evt(u32 flags)
{
return ((flags >> ASYNC_EVENT_CODE_SHIFT) & ASYNC_EVENT_CODE_MASK) ==
@@ -352,6 +401,12 @@ static inline bool is_dbg_evt(u32 flags)
ASYNC_EVENT_CODE_QNQ;
}
+static inline bool is_sliport_evt(u32 flags)
+{
+ return ((flags >> ASYNC_EVENT_CODE_SHIFT) & ASYNC_EVENT_CODE_MASK) ==
+ ASYNC_EVENT_CODE_SLIPORT;
+}
+
static void be_mcc_event_process(struct be_adapter *adapter,
struct be_mcc_compl *compl)
{
@@ -361,6 +416,8 @@ static void be_mcc_event_process(struct be_adapter *adapter,
be_async_grp5_evt_process(adapter, compl);
else if (is_dbg_evt(compl->flags))
be_async_dbg_evt_process(adapter, compl);
+ else if (is_sliport_evt(compl->flags))
+ be_async_sliport_evt_process(adapter, compl);
}
static struct be_mcc_compl *be_mcc_compl_get(struct be_adapter *adapter)
@@ -1171,9 +1228,15 @@ static int be_cmd_mccq_ext_create(struct be_adapter *adapter,
ctxt, 1);
}
- /* Subscribe to Link State and Group 5 Events(bits 1 and 5 set) */
- req->async_event_bitmap[0] = cpu_to_le32(0x00000022);
- req->async_event_bitmap[0] |= cpu_to_le32(1 << ASYNC_EVENT_CODE_QNQ);
+ /* Subscribe to Link State, Sliport Event and Group 5 Events
+ * (bits 1, 5 and 17 set)
+ */
+ req->async_event_bitmap[0] =
+ cpu_to_le32(BIT(ASYNC_EVENT_CODE_LINK_STATE) |
+ BIT(ASYNC_EVENT_CODE_GRP_5) |
+ BIT(ASYNC_EVENT_CODE_QNQ) |
+ BIT(ASYNC_EVENT_CODE_SLIPORT));
+
be_dws_cpu_to_le(ctxt, sizeof(req->context));
be_cmd_page_addrs_prepare(req->pages, ARRAY_SIZE(req->pages), q_mem);
@@ -2344,6 +2407,24 @@ int be_cmd_query_cable_type(struct be_adapter *adapter)
return status;
}
+int be_cmd_query_sfp_info(struct be_adapter *adapter)
+{
+ u8 page_data[PAGE_DATA_LEN];
+ int status;
+
+ status = be_cmd_read_port_transceiver_data(adapter, TR_PAGE_A0,
+ page_data);
+ if (!status) {
+ strlcpy(adapter->phy.vendor_name, page_data +
+ SFP_VENDOR_NAME_OFFSET, SFP_VENDOR_NAME_LEN - 1);
+ strlcpy(adapter->phy.vendor_pn,
+ page_data + SFP_VENDOR_PN_OFFSET,
+ SFP_VENDOR_NAME_LEN - 1);
+ }
+
+ return status;
+}
+
int lancer_cmd_delete_object(struct be_adapter *adapter, const char *obj_name)
{
struct lancer_cmd_req_delete_object *req;
@@ -3437,42 +3518,34 @@ err:
return status;
}
-int be_cmd_query_port_name(struct be_adapter *adapter, u8 *port_name)
+int be_cmd_query_port_name(struct be_adapter *adapter)
{
- struct be_mcc_wrb *wrb;
struct be_cmd_req_get_port_name *req;
+ struct be_mcc_wrb *wrb;
int status;
- if (!lancer_chip(adapter)) {
- *port_name = adapter->hba_port_num + '0';
- return 0;
- }
-
- spin_lock_bh(&adapter->mcc_lock);
-
- wrb = wrb_from_mccq(adapter);
- if (!wrb) {
- status = -EBUSY;
- goto err;
- }
+ if (mutex_lock_interruptible(&adapter->mbox_lock))
+ return -1;
+ wrb = wrb_from_mbox(adapter);
req = embedded_payload(wrb);
be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
OPCODE_COMMON_GET_PORT_NAME, sizeof(*req), wrb,
NULL);
- req->hdr.version = 1;
+ if (!BEx_chip(adapter))
+ req->hdr.version = 1;
- status = be_mcc_notify_wait(adapter);
+ status = be_mbox_notify_wait(adapter);
if (!status) {
struct be_cmd_resp_get_port_name *resp = embedded_payload(wrb);
- *port_name = resp->port_name[adapter->hba_port_num];
+ adapter->port_name = resp->port_name[adapter->hba_port_num];
} else {
- *port_name = adapter->hba_port_num + '0';
+ adapter->port_name = adapter->hba_port_num + '0';
}
-err:
- spin_unlock_bh(&adapter->mcc_lock);
+
+ mutex_unlock(&adapter->mbox_lock);
return status;
}
diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.h b/drivers/net/ethernet/emulex/benet/be_cmds.h
index cf9d870..db761e8e 100644
--- a/drivers/net/ethernet/emulex/benet/be_cmds.h
+++ b/drivers/net/ethernet/emulex/benet/be_cmds.h
@@ -102,6 +102,8 @@ struct be_mcc_compl {
#define ASYNC_EVENT_PVID_STATE 0x3
#define ASYNC_EVENT_CODE_QNQ 0x6
#define ASYNC_DEBUG_EVENT_TYPE_QNQ 1
+#define ASYNC_EVENT_CODE_SLIPORT 0x11
+#define ASYNC_EVENT_PORT_MISCONFIG 0x9
enum {
LINK_DOWN = 0x0,
@@ -169,6 +171,15 @@ struct be_async_event_qnq {
u32 flags;
} __packed;
+#define INCOMPATIBLE_SFP 0x3
+/* async event indicating misconfigured port */
+struct be_async_event_misconfig_port {
+ u32 event_data_word1;
+ u32 event_data_word2;
+ u32 rsvd0;
+ u32 flags;
+} __packed;
+
struct be_mcc_mailbox {
struct be_mcc_wrb wrb;
struct be_mcc_compl compl;
@@ -1028,6 +1039,8 @@ enum {
#define SFP_PLUS_SFF_8472_COMP 0x5E
#define SFP_PLUS_CABLE_TYPE_OFFSET 0x8
#define SFP_PLUS_COPPER_CABLE 0x4
+#define SFP_VENDOR_NAME_OFFSET 0x14
+#define SFP_VENDOR_PN_OFFSET 0x28
#define PAGE_DATA_LEN 256
struct be_cmd_resp_port_type {
@@ -2259,6 +2272,7 @@ int be_cmd_get_beacon_state(struct be_adapter *adapter, u8 port_num,
int be_cmd_read_port_transceiver_data(struct be_adapter *adapter,
u8 page_num, u8 *data);
int be_cmd_query_cable_type(struct be_adapter *adapter);
+int be_cmd_query_sfp_info(struct be_adapter *adapter);
int be_cmd_write_flashrom(struct be_adapter *adapter, struct be_dma_mem *cmd,
u32 flash_oper, u32 flash_opcode, u32 img_offset,
u32 buf_size);
@@ -2326,7 +2340,7 @@ int lancer_initiate_dump(struct be_adapter *adapter);
int lancer_delete_dump(struct be_adapter *adapter);
bool dump_present(struct be_adapter *adapter);
int lancer_test_and_set_rdy_state(struct be_adapter *adapter);
-int be_cmd_query_port_name(struct be_adapter *adapter, u8 *port_name);
+int be_cmd_query_port_name(struct be_adapter *adapter);
int be_cmd_get_func_config(struct be_adapter *adapter,
struct be_resources *res);
int be_cmd_get_profile_config(struct be_adapter *adapter,
diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c
index fbe7b6f..5936b24 100644
--- a/drivers/net/ethernet/emulex/benet/be_main.c
+++ b/drivers/net/ethernet/emulex/benet/be_main.c
@@ -3682,7 +3682,9 @@ static int be_get_config(struct be_adapter *adapter)
if (status)
return status;
- if (be_physfn(adapter)) {
+ be_cmd_query_port_name(adapter);
+
+ if (be_physfn(adapter)) {
status = be_cmd_get_active_profile(adapter, &profile_id);
if (!status)
dev_info(&adapter->pdev->dev,
@@ -5051,6 +5053,20 @@ static void be_func_recovery_task(struct work_struct *work)
msecs_to_jiffies(1000));
}
+static void be_log_sfp_info(struct be_adapter *adapter)
+{
+ int status;
+
+ status = be_cmd_query_sfp_info(adapter);
+ if (!status) {
+ dev_err(&adapter->pdev->dev,
+ "Unqualified SFP+ detected on %c from %s part no: %s",
+ adapter->port_name, adapter->phy.vendor_name,
+ adapter->phy.vendor_pn);
+ }
+ adapter->flags &= ~BE_FLAGS_EVT_INCOMPATIBLE_SFP;
+}
+
static void be_worker(struct work_struct *work)
{
struct be_adapter *adapter =
@@ -5089,6 +5105,9 @@ static void be_worker(struct work_struct *work)
be_eqd_update(adapter);
+ if (adapter->flags & BE_FLAGS_EVT_INCOMPATIBLE_SFP)
+ be_log_sfp_info(adapter);
+
reschedule:
adapter->work_counter++;
schedule_delayed_work(&adapter->work, msecs_to_jiffies(1000));
@@ -5157,10 +5176,9 @@ static inline char *nic_name(struct pci_dev *pdev)
static int be_probe(struct pci_dev *pdev, const struct pci_device_id *pdev_id)
{
- int status = 0;
struct be_adapter *adapter;
struct net_device *netdev;
- char port_name;
+ int status = 0;
dev_info(&pdev->dev, "%s version is %s\n", DRV_NAME, DRV_VER);
@@ -5254,10 +5272,8 @@ static int be_probe(struct pci_dev *pdev, const struct pci_device_id *pdev_id)
schedule_delayed_work(&adapter->func_recovery_work,
msecs_to_jiffies(1000));
- be_cmd_query_port_name(adapter, &port_name);
-
dev_info(&pdev->dev, "%s: %s %s port %c\n", nic_name(pdev),
- func_name(adapter), mc_name(adapter), port_name);
+ func_name(adapter), mc_name(adapter), adapter->port_name);
return 0;
--
2.2.0
^ permalink raw reply related
* [PATCH net-next 3/9] be2net: refactor code that checks flash file compatibility
From: Sathya Perla @ 2015-02-06 13:18 UTC (permalink / raw)
To: netdev
In-Reply-To: <1423228723-10919-1-git-send-email-sathya.perla@emulex.com>
From: Vasundhara Volam <vasundhara.volam@emulex.com>
This patch re-factors the code that checks for flash file compatibility with
the chip type, for better readability, as follows:
- be_get_ufi_type() returns the UFI type from the flash file
- be_check_ufi_compatibility() checks if the UFI type is compatible
with the adapter/chip that is being flashed
Signed-off-by: Vasundhara Volam <vasundhara.volam@emulex.com>
Signed-off-by: Sathya Perla <sathya.perla@emulex.com>
---
drivers/net/ethernet/emulex/benet/be_cmds.h | 8 ++
drivers/net/ethernet/emulex/benet/be_main.c | 138 ++++++++++++++--------------
2 files changed, 78 insertions(+), 68 deletions(-)
diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.h b/drivers/net/ethernet/emulex/benet/be_cmds.h
index c231e45..bed4a32 100644
--- a/drivers/net/ethernet/emulex/benet/be_cmds.h
+++ b/drivers/net/ethernet/emulex/benet/be_cmds.h
@@ -1091,6 +1091,9 @@ struct be_cmd_req_query_fw_cfg {
u32 rsvd[31];
};
+/* ASIC revisions */
+#define ASIC_REV_B0 0x10
+
struct be_cmd_resp_query_fw_cfg {
struct be_cmd_resp_hdr hdr;
u32 be_config_number;
@@ -1260,6 +1263,11 @@ struct flash_file_hdr_g2 {
u8 build[24];
};
+/* First letter of the build version of the image */
+#define BLD_STR_UFI_TYPE_BE2 '2'
+#define BLD_STR_UFI_TYPE_BE3 '3'
+#define BLD_STR_UFI_TYPE_SH '4'
+
struct flash_file_hdr_g3 {
u8 sign[52];
u8 ufi_version[4];
diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c
index 4231a70..ddc5966 100644
--- a/drivers/net/ethernet/emulex/benet/be_main.c
+++ b/drivers/net/ethernet/emulex/benet/be_main.c
@@ -4058,6 +4058,7 @@ static int be_flash_BEx(struct be_adapter *adapter,
pflashcomp = gen2_flash_types;
filehdr_size = sizeof(struct flash_file_hdr_g2);
num_comp = ARRAY_SIZE(gen2_flash_types);
+ img_hdrs_size = 0;
}
/* Get flash section info*/
@@ -4331,98 +4332,99 @@ static int lancer_fw_download(struct be_adapter *adapter,
return 0;
}
-#define UFI_TYPE2 2
-#define UFI_TYPE3 3
-#define UFI_TYPE3R 10
-#define UFI_TYPE4 4
+#define BE2_UFI 2
+#define BE3_UFI 3
+#define BE3R_UFI 10
+#define SH_UFI 4
+
static int be_get_ufi_type(struct be_adapter *adapter,
struct flash_file_hdr_g3 *fhdr)
{
- if (!fhdr)
- goto be_get_ufi_exit;
+ if (!fhdr) {
+ dev_err(&adapter->pdev->dev, "Invalid FW UFI file");
+ return -1;
+ }
- if (skyhawk_chip(adapter) && fhdr->build[0] == '4')
- return UFI_TYPE4;
- else if (BE3_chip(adapter) && fhdr->build[0] == '3') {
- if (fhdr->asic_type_rev == 0x10)
- return UFI_TYPE3R;
- else
- return UFI_TYPE3;
- } else if (BE2_chip(adapter) && fhdr->build[0] == '2')
- return UFI_TYPE2;
+ /* First letter of the build version is used to identify
+ * which chip this image file is meant for.
+ */
+ switch (fhdr->build[0]) {
+ case BLD_STR_UFI_TYPE_SH:
+ return SH_UFI;
+ case BLD_STR_UFI_TYPE_BE3:
+ return (fhdr->asic_type_rev == ASIC_REV_B0) ? BE3R_UFI :
+ BE3_UFI;
+ case BLD_STR_UFI_TYPE_BE2:
+ return BE2_UFI;
+ default:
+ return -1;
+ }
+}
-be_get_ufi_exit:
- dev_err(&adapter->pdev->dev,
- "UFI and Interface are not compatible for flashing\n");
- return -1;
+/* Check if the flash image file is compatible with the adapter that
+ * is being flashed.
+ * BE3 chips with asic-rev B0 must be flashed only with BE3R_UFI type.
+ */
+static bool be_check_ufi_compatibility(struct be_adapter *adapter,
+ struct flash_file_hdr_g3 *fhdr)
+{
+ int ufi_type = be_get_ufi_type(adapter, fhdr);
+
+ switch (ufi_type) {
+ case SH_UFI:
+ return skyhawk_chip(adapter);
+ case BE3R_UFI:
+ return BE3_chip(adapter);
+ case BE3_UFI:
+ return (BE3_chip(adapter) && adapter->asic_rev < ASIC_REV_B0);
+ case BE2_UFI:
+ return BE2_chip(adapter);
+ default:
+ return false;
+ }
}
static int be_fw_download(struct be_adapter *adapter, const struct firmware* fw)
{
+ struct device *dev = &adapter->pdev->dev;
struct flash_file_hdr_g3 *fhdr3;
- struct image_hdr *img_hdr_ptr = NULL;
+ struct image_hdr *img_hdr_ptr;
+ int status = 0, i, num_imgs;
struct be_dma_mem flash_cmd;
- const u8 *p;
- int status = 0, i = 0, num_imgs = 0, ufi_type = 0;
- flash_cmd.size = sizeof(struct be_cmd_write_flashrom);
- flash_cmd.va = dma_alloc_coherent(&adapter->pdev->dev, flash_cmd.size,
- &flash_cmd.dma, GFP_KERNEL);
- if (!flash_cmd.va) {
- status = -ENOMEM;
- goto be_fw_exit;
+ fhdr3 = (struct flash_file_hdr_g3 *)fw->data;
+ if (!be_check_ufi_compatibility(adapter, fhdr3)) {
+ dev_err(dev, "Flash image is not compatible with adapter\n");
+ return -EINVAL;
}
- p = fw->data;
- fhdr3 = (struct flash_file_hdr_g3 *)p;
-
- ufi_type = be_get_ufi_type(adapter, fhdr3);
+ flash_cmd.size = sizeof(struct be_cmd_write_flashrom);
+ flash_cmd.va = dma_alloc_coherent(dev, flash_cmd.size, &flash_cmd.dma,
+ GFP_KERNEL);
+ if (!flash_cmd.va)
+ return -ENOMEM;
num_imgs = le32_to_cpu(fhdr3->num_imgs);
for (i = 0; i < num_imgs; i++) {
img_hdr_ptr = (struct image_hdr *)(fw->data +
(sizeof(struct flash_file_hdr_g3) +
i * sizeof(struct image_hdr)));
- if (le32_to_cpu(img_hdr_ptr->imageid) == 1) {
- switch (ufi_type) {
- case UFI_TYPE4:
- status = be_flash_skyhawk(adapter, fw,
- &flash_cmd, num_imgs);
- break;
- case UFI_TYPE3R:
- status = be_flash_BEx(adapter, fw, &flash_cmd,
- num_imgs);
- break;
- case UFI_TYPE3:
- /* Do not flash this ufi on BE3-R cards */
- if (adapter->asic_rev < 0x10)
- status = be_flash_BEx(adapter, fw,
- &flash_cmd,
- num_imgs);
- else {
- status = -EINVAL;
- dev_err(&adapter->pdev->dev,
- "Can't load BE3 UFI on BE3R\n");
- }
- }
- }
- }
-
- if (ufi_type == UFI_TYPE2)
- status = be_flash_BEx(adapter, fw, &flash_cmd, 0);
- else if (ufi_type == -1)
- status = -EINVAL;
+ if (!BE2_chip(adapter) &&
+ le32_to_cpu(img_hdr_ptr->imageid) != 1)
+ continue;
- dma_free_coherent(&adapter->pdev->dev, flash_cmd.size, flash_cmd.va,
- flash_cmd.dma);
- if (status) {
- dev_err(&adapter->pdev->dev, "Firmware load error\n");
- goto be_fw_exit;
+ if (skyhawk_chip(adapter))
+ status = be_flash_skyhawk(adapter, fw, &flash_cmd,
+ num_imgs);
+ else
+ status = be_flash_BEx(adapter, fw, &flash_cmd,
+ num_imgs);
}
- dev_info(&adapter->pdev->dev, "Firmware flashed successfully\n");
+ dma_free_coherent(dev, flash_cmd.size, flash_cmd.va, flash_cmd.dma);
+ if (!status)
+ dev_info(dev, "Firmware flashed successfully\n");
-be_fw_exit:
return status;
}
--
2.2.0
^ permalink raw reply related
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