* Re: [RFC][NET_SCHED] explict hold dev tx lock
From: jamal @ 2007-09-20 2:33 UTC (permalink / raw)
To: David Miller; +Cc: herbert, netdev, kaber, dada1, johnpol
In-Reply-To: <20070919.090937.32177545.davem@davemloft.net>
On Wed, 2007-19-09 at 09:09 -0700, David Miller wrote:
> Sure, along with a description as to why you want to make this
> change.
Will do. And if you feel that i should sit on it a little more i can do
that too. The good news is it doesnt make things any worse than they
already are and infact shows a slight improvement in a 4 cpu machine.
> I still don't understand the impetus. :)
I will like to use the effect later on to improve batching.
cheers,
jamal
^ permalink raw reply
* [PATCH 1/2] David Miller's rbtree patches for 2.6.22.6
From: Tom Quetchenbach @ 2007-09-20 1:42 UTC (permalink / raw)
To: netdev
In-Reply-To: <46F1CF35.3030606@gmail.com>
Patch 1: David Miller's red-black tree code, tweaked for 2.6.22.6,
with some bugfixes
-Tom
---
diff -ur linux-2.6.22.6/include/linux/skbuff.h linux-2.6.22.6-rbtree-davem-fixed/include/linux/skbuff.h
--- linux-2.6.22.6/include/linux/skbuff.h 2007-08-30 23:21:01.000000000 -0700
+++ linux-2.6.22.6-rbtree-davem-fixed/include/linux/skbuff.h 2007-09-13 18:23:16.000000000 -0700
@@ -18,6 +18,7 @@
#include <linux/compiler.h>
#include <linux/time.h>
#include <linux/cache.h>
+#include <linux/rbtree.h>
#include <asm/atomic.h>
#include <asm/types.h>
@@ -242,6 +243,8 @@
struct sk_buff *next;
struct sk_buff *prev;
+ struct rb_node rb;
+
struct sock *sk;
ktime_t tstamp;
struct net_device *dev;
diff -ur linux-2.6.22.6/include/linux/tcp.h linux-2.6.22.6-rbtree-davem-fixed/include/linux/tcp.h
--- linux-2.6.22.6/include/linux/tcp.h 2007-08-30 23:21:01.000000000 -0700
+++ linux-2.6.22.6-rbtree-davem-fixed/include/linux/tcp.h 2007-09-13 18:23:16.000000000 -0700
@@ -174,6 +174,7 @@
#include <linux/skbuff.h>
#include <linux/dmaengine.h>
+#include <linux/rbtree.h>
#include <net/sock.h>
#include <net/inet_connection_sock.h>
#include <net/inet_timewait_sock.h>
@@ -321,6 +322,7 @@
u32 snd_cwnd_used;
u32 snd_cwnd_stamp;
+ struct rb_root write_queue_rb;
struct sk_buff_head out_of_order_queue; /* Out of order segments go here */
u32 rcv_wnd; /* Current receiver window */
@@ -339,9 +341,7 @@
struct sk_buff *scoreboard_skb_hint;
struct sk_buff *retransmit_skb_hint;
struct sk_buff *forward_skb_hint;
- struct sk_buff *fastpath_skb_hint;
- int fastpath_cnt_hint;
int lost_cnt_hint;
int retransmit_cnt_hint;
int forward_cnt_hint;
diff -ur linux-2.6.22.6/include/net/tcp.h linux-2.6.22.6-rbtree-davem-fixed/include/net/tcp.h
--- linux-2.6.22.6/include/net/tcp.h 2007-08-30 23:21:01.000000000 -0700
+++ linux-2.6.22.6-rbtree-davem-fixed/include/net/tcp.h 2007-09-19 17:36:07.000000000 -0700
@@ -540,6 +540,7 @@
__u32 seq; /* Starting sequence number */
__u32 end_seq; /* SEQ + FIN + SYN + datalen */
__u32 when; /* used to compute rtt's */
+ unsigned int fack_count; /* speed up SACK processing */
__u8 flags; /* TCP header flags. */
/* NOTE: These must match up to the flags byte in a
@@ -1043,12 +1044,12 @@
}
/*from STCP */
-static inline void clear_all_retrans_hints(struct tcp_sock *tp){
+static inline void clear_all_retrans_hints(struct tcp_sock *tp)
+{
tp->lost_skb_hint = NULL;
tp->scoreboard_skb_hint = NULL;
tp->retransmit_skb_hint = NULL;
tp->forward_skb_hint = NULL;
- tp->fastpath_skb_hint = NULL;
}
/* MD5 Signature */
@@ -1166,6 +1167,7 @@
while ((skb = __skb_dequeue(&sk->sk_write_queue)) != NULL)
sk_stream_free_skb(sk, skb);
+ tcp_sk(sk)->write_queue_rb = RB_ROOT;
sk_stream_mem_reclaim(sk);
}
@@ -1208,7 +1210,7 @@
{
struct tcp_sock *tp = tcp_sk(sk);
- sk->sk_send_head = skb->next;
+ sk->sk_send_head = tcp_write_queue_next(sk, skb);
if (sk->sk_send_head == (struct sk_buff *)&sk->sk_write_queue)
sk->sk_send_head = NULL;
/* Don't override Nagle indefinately with F-RTO */
@@ -1227,9 +1229,61 @@
sk->sk_send_head = NULL;
}
+static inline struct sk_buff *tcp_write_queue_find(struct sock *sk, __u32 seq)
+{
+ struct rb_node *rb_node = tcp_sk(sk)->write_queue_rb.rb_node;
+ struct sk_buff *skb = NULL;
+
+ while (rb_node) {
+ struct sk_buff *tmp = rb_entry(rb_node,struct sk_buff,rb);
+ if (TCP_SKB_CB(tmp)->end_seq > seq) {
+ skb = tmp;
+ if (TCP_SKB_CB(tmp)->seq <= seq)
+ break;
+ rb_node = rb_node->rb_left;
+ } else
+ rb_node = rb_node->rb_right;
+
+ }
+ return skb;
+}
+
+static inline void tcp_rb_insert(struct sk_buff *skb, struct rb_root *root)
+{
+ struct rb_node **rb_link, *rb_parent;
+ __u32 seq = TCP_SKB_CB(skb)->seq;
+
+ rb_link = &root->rb_node;
+ rb_parent = NULL;
+ while (*rb_link != NULL) {
+ struct sk_buff *tmp = rb_entry(*rb_link,struct sk_buff,rb);
+ rb_parent = *rb_link;
+ if (TCP_SKB_CB(tmp)->end_seq > seq) {
+ BUG_ON(TCP_SKB_CB(tmp)->seq <= seq);
+ rb_link = &rb_parent->rb_left;
+ } else {
+ rb_link = &rb_parent->rb_right;
+ }
+ }
+ rb_link_node(&skb->rb, rb_parent, rb_link);
+ rb_insert_color(&skb->rb, root);
+}
+
+static inline void tcp_rb_unlink(struct sk_buff *skb, struct rb_root *root)
+{
+ rb_erase(&skb->rb, root);
+}
+
static inline void __tcp_add_write_queue_tail(struct sock *sk, struct sk_buff *skb)
{
+ struct sk_buff *tail = tcp_write_queue_tail(sk);
+ unsigned int fc = 0;
+
+ if (tail)
+ fc = TCP_SKB_CB(tail)->fack_count + tcp_skb_pcount(tail);
+ TCP_SKB_CB(skb)->fack_count = fc;
__skb_queue_tail(&sk->sk_write_queue, skb);
+ tcp_rb_insert(skb, &tcp_sk(sk)->write_queue_rb);
}
static inline void tcp_add_write_queue_tail(struct sock *sk, struct sk_buff *skb)
@@ -1241,9 +1295,35 @@
sk->sk_send_head = skb;
}
+/* This is only used for tcp_send_synack(), so the write queue should
+ * be empty. If that stops being true, the fack_count assignment
+ * will need to be more elaborate.
+ */
static inline void __tcp_add_write_queue_head(struct sock *sk, struct sk_buff *skb)
{
+ BUG_ON(!skb_queue_empty(&sk->sk_write_queue));
__skb_queue_head(&sk->sk_write_queue, skb);
+ TCP_SKB_CB(skb)->fack_count = 0;
+ tcp_rb_insert(skb, &tcp_sk(sk)->write_queue_rb);
+}
+
+/* An insert into the middle of the write queue causes the fack
+ * counts in subsequent packets to become invalid, fix them up.
+ */
+static inline void tcp_reset_fack_counts(struct sock *sk, struct sk_buff *first)
+{
+ struct sk_buff *prev = first->prev;
+ unsigned int fc = 0;
+
+ if (prev != (struct sk_buff *) &sk->sk_write_queue)
+ fc = TCP_SKB_CB(prev)->fack_count + tcp_skb_pcount(prev);
+
+ while (first != (struct sk_buff *)&sk->sk_write_queue) {
+ TCP_SKB_CB(first)->fack_count = fc;
+
+ fc += tcp_skb_pcount(first);
+ first = first->next;
+ }
}
/* Insert buff after skb on the write queue of sk. */
@@ -1252,19 +1332,24 @@
struct sock *sk)
{
__skb_append(skb, buff, &sk->sk_write_queue);
+ tcp_reset_fack_counts(sk, buff);
+ tcp_rb_insert(buff, &tcp_sk(sk)->write_queue_rb);
}
-/* Insert skb between prev and next on the write queue of sk. */
+/* Insert new before skb on the write queue of sk. */
static inline void tcp_insert_write_queue_before(struct sk_buff *new,
struct sk_buff *skb,
struct sock *sk)
{
__skb_insert(new, skb->prev, skb, &sk->sk_write_queue);
+ tcp_reset_fack_counts(sk, new);
+ tcp_rb_insert(new, &tcp_sk(sk)->write_queue_rb);
}
static inline void tcp_unlink_write_queue(struct sk_buff *skb, struct sock *sk)
{
__skb_unlink(skb, &sk->sk_write_queue);
+ tcp_rb_unlink(skb, &tcp_sk(sk)->write_queue_rb);
}
static inline int tcp_skb_is_last(const struct sock *sk,
diff -ur linux-2.6.22.6/net/ipv4/tcp_input.c linux-2.6.22.6-rbtree-davem-fixed/net/ipv4/tcp_input.c
--- linux-2.6.22.6/net/ipv4/tcp_input.c 2007-08-30 23:21:01.000000000 -0700
+++ linux-2.6.22.6-rbtree-davem-fixed/net/ipv4/tcp_input.c 2007-09-13 18:23:16.000000000 -0700
@@ -947,14 +947,13 @@
unsigned char *ptr = (skb_transport_header(ack_skb) +
TCP_SKB_CB(ack_skb)->sacked);
struct tcp_sack_block_wire *sp = (struct tcp_sack_block_wire *)(ptr+2);
- struct sk_buff *cached_skb;
int num_sacks = (ptr[1] - TCPOLEN_SACK_BASE)>>3;
int reord = tp->packets_out;
int prior_fackets;
u32 lost_retrans = 0;
int flag = 0;
int found_dup_sack = 0;
- int cached_fack_count;
+ int fack_count_base;
int i;
int first_sack_index;
@@ -1020,7 +1019,6 @@
num_sacks = 1;
else {
int j;
- tp->fastpath_skb_hint = NULL;
/* order SACK blocks to allow in order walk of the retrans queue */
for (i = num_sacks-1; i > 0; i--) {
@@ -1045,14 +1043,7 @@
/* clear flag as used for different purpose in following code */
flag = 0;
- /* Use SACK fastpath hint if valid */
- cached_skb = tp->fastpath_skb_hint;
- cached_fack_count = tp->fastpath_cnt_hint;
- if (!cached_skb) {
- cached_skb = tcp_write_queue_head(sk);
- cached_fack_count = 0;
- }
-
+ fack_count_base = TCP_SKB_CB(tcp_write_queue_head(sk))->fack_count;
for (i=0; i<num_sacks; i++, sp++) {
struct sk_buff *skb;
__u32 start_seq = ntohl(sp->start_seq);
@@ -1060,8 +1051,10 @@
int fack_count;
int dup_sack = (found_dup_sack && (i == first_sack_index));
- skb = cached_skb;
- fack_count = cached_fack_count;
+ skb = tcp_write_queue_find(sk, start_seq);
+ if (!skb)
+ continue;
+ fack_count = TCP_SKB_CB(skb)->fack_count - fack_count_base;
/* Event "B" in the comment above. */
if (after(end_seq, tp->high_seq))
@@ -1074,13 +1067,6 @@
if (skb == tcp_send_head(sk))
break;
- cached_skb = skb;
- cached_fack_count = fack_count;
- if (i == first_sack_index) {
- tp->fastpath_skb_hint = skb;
- tp->fastpath_cnt_hint = fack_count;
- }
-
/* The retransmission queue is always in order, so
* we can short-circuit the walk early.
*/
diff -ur linux-2.6.22.6/net/ipv4/tcp_ipv4.c linux-2.6.22.6-rbtree-davem-fixed/net/ipv4/tcp_ipv4.c
--- linux-2.6.22.6/net/ipv4/tcp_ipv4.c 2007-08-30 23:21:01.000000000 -0700
+++ linux-2.6.22.6-rbtree-davem-fixed/net/ipv4/tcp_ipv4.c 2007-09-13 18:23:16.000000000 -0700
@@ -1845,6 +1845,7 @@
struct inet_connection_sock *icsk = inet_csk(sk);
struct tcp_sock *tp = tcp_sk(sk);
+ tp->write_queue_rb = RB_ROOT;
skb_queue_head_init(&tp->out_of_order_queue);
tcp_init_xmit_timers(sk);
tcp_prequeue_init(tp);
diff -ur linux-2.6.22.6/net/ipv4/tcp_minisocks.c linux-2.6.22.6-rbtree-davem-fixed/net/ipv4/tcp_minisocks.c
--- linux-2.6.22.6/net/ipv4/tcp_minisocks.c 2007-08-30 23:21:01.000000000 -0700
+++ linux-2.6.22.6-rbtree-davem-fixed/net/ipv4/tcp_minisocks.c 2007-09-13 18:23:16.000000000 -0700
@@ -421,6 +421,7 @@
tcp_set_ca_state(newsk, TCP_CA_Open);
tcp_init_xmit_timers(newsk);
+ newtp->write_queue_rb = RB_ROOT;
skb_queue_head_init(&newtp->out_of_order_queue);
newtp->write_seq = treq->snt_isn + 1;
newtp->pushed_seq = newtp->write_seq;
diff -ur linux-2.6.22.6/net/ipv4/tcp_output.c linux-2.6.22.6-rbtree-davem-fixed/net/ipv4/tcp_output.c
--- linux-2.6.22.6/net/ipv4/tcp_output.c 2007-08-30 23:21:01.000000000 -0700
+++ linux-2.6.22.6-rbtree-davem-fixed/net/ipv4/tcp_output.c 2007-09-13 18:23:16.000000000 -0700
@@ -1278,11 +1278,11 @@
sk_charge_skb(sk, nskb);
skb = tcp_send_head(sk);
+ TCP_SKB_CB(nskb)->seq = TCP_SKB_CB(skb)->seq;
+ TCP_SKB_CB(nskb)->end_seq = TCP_SKB_CB(skb)->seq + probe_size;
tcp_insert_write_queue_before(nskb, skb, sk);
tcp_advance_send_head(sk, skb);
- TCP_SKB_CB(nskb)->seq = TCP_SKB_CB(skb)->seq;
- TCP_SKB_CB(nskb)->end_seq = TCP_SKB_CB(skb)->seq + probe_size;
TCP_SKB_CB(nskb)->flags = TCPCB_FLAG_ACK;
TCP_SKB_CB(nskb)->sacked = 0;
nskb->csum = 0;
diff -ur linux-2.6.22.6/net/ipv6/tcp_ipv6.c linux-2.6.22.6-rbtree-davem-fixed/net/ipv6/tcp_ipv6.c
--- linux-2.6.22.6/net/ipv6/tcp_ipv6.c 2007-08-30 23:21:01.000000000 -0700
+++ linux-2.6.22.6-rbtree-davem-fixed/net/ipv6/tcp_ipv6.c 2007-09-13 18:23:16.000000000 -0700
@@ -1900,6 +1900,7 @@
struct inet_connection_sock *icsk = inet_csk(sk);
struct tcp_sock *tp = tcp_sk(sk);
+ tp->write_queue_rb = RB_ROOT;
skb_queue_head_init(&tp->out_of_order_queue);
tcp_init_xmit_timers(sk);
tcp_prequeue_init(tp);
^ permalink raw reply
* [PATCH 0/2] David Miller's rbtree patches for 2.6.22.6
From: Tom Quetchenbach @ 2007-09-20 1:39 UTC (permalink / raw)
To: netdev
Hello,
I've been experimenting with David Miller's red-black tree patch for
SACK processing. We're sending TCP traffic between two machines with
10Gbps cards over a 1Gbps bottleneck link and were getting very high CPU
load with large windows. With a few tweaks, this patch seems to provide
a pretty substantial improvement. David: this seems like excellent work
so far.
Here are a couple of patches against 2.6.22.6. The first one is just
David's patches tweaked for 2.6.22.6, with a couple of minor bugfixes to
get it to compile and not crash. (I also changed
__tcp_insert_write_queue_tail() to set the fack_count of the new packet
to the fack_count of the tail plus the packet count of the tail, not the
packet count of the new skb, because I think that's how it was intended
to be. Right?
In the second patch there are a couple of significant changes. One is
(as Baruch suggested) to modify the existing SACK fast path so that we
don't tag packets we've already tagged when we advance by a packet.
The other issue is that the cached fack_counts seem to be wrong, because
they're set when we insert into the queue, but tcp_set_tso_segs() is
called later, just before we send, so all the fack_counts are zero. My
solution was to set the fack_count when we advance the send_head. Also I
changed tcp_reset_fack_counts() so that it exits when it hits an skb
whose tcp_skb_pcount() is zero or whose fack_count is already correct.
(This really helps when TSO is on, since there's lots of inserting into
the middle of the queue.)
Please let me know how I can help get this tested and debugged. Reducing
the SACK processing load is really going to be essential for us to start
testing experimental TCP variants with large windows.
Thanks
-Tom
^ permalink raw reply
* [PATCH 2/2] David Miller's rbtree patches for 2.6.22.6
From: Tom Quetchenbach @ 2007-09-20 1:44 UTC (permalink / raw)
To: netdev
In-Reply-To: <46F1D00B.6030108@gmail.com>
Patch 2: fixes to fack_counts and enhancement of SACK fast path
-Tom
---
diff -ur linux-2.6.22.6-rbtree-davem-fixed/include/net/tcp.h linux-2.6.22.6-rbtree-tomq/include/net/tcp.h
--- linux-2.6.22.6-rbtree-davem-fixed/include/net/tcp.h 2007-09-19 17:36:07.000000000 -0700
+++ linux-2.6.22.6-rbtree-tomq/include/net/tcp.h 2007-09-19 12:22:06.000000000 -0700
@@ -1213,6 +1213,11 @@
sk->sk_send_head = tcp_write_queue_next(sk, skb);
if (sk->sk_send_head == (struct sk_buff *)&sk->sk_write_queue)
sk->sk_send_head = NULL;
+ else
+ /* update fack_count of send_head. Since we've sent skb already,
+ * its packet count must be set by now. */
+ TCP_SKB_CB(sk->sk_send_head)->fack_count =
+ TCP_SKB_CB(skb)->fack_count + tcp_skb_pcount(skb);
/* Don't override Nagle indefinately with F-RTO */
if (tp->frto_counter == 2)
tp->frto_counter = 3;
@@ -1310,19 +1315,22 @@
/* An insert into the middle of the write queue causes the fack
* counts in subsequent packets to become invalid, fix them up.
*/
-static inline void tcp_reset_fack_counts(struct sock *sk, struct sk_buff *first)
+static inline void tcp_reset_fack_counts(struct sock *sk, struct sk_buff *skb)
{
- struct sk_buff *prev = first->prev;
+ struct sk_buff *prev = skb->prev;
unsigned int fc = 0;
if (prev != (struct sk_buff *) &sk->sk_write_queue)
fc = TCP_SKB_CB(prev)->fack_count + tcp_skb_pcount(prev);
- while (first != (struct sk_buff *)&sk->sk_write_queue) {
- TCP_SKB_CB(first)->fack_count = fc;
+ while (skb != (struct sk_buff *)&sk->sk_write_queue) {
+ if (TCP_SKB_CB(skb)->fack_count == fc || !tcp_skb_pcount(skb))
+ break;
- fc += tcp_skb_pcount(first);
- first = first->next;
+ TCP_SKB_CB(skb)->fack_count = fc;
+
+ fc += tcp_skb_pcount(skb);
+ skb = skb->next;
}
}
diff -ur linux-2.6.22.6-rbtree-davem-fixed/net/ipv4/tcp_input.c linux-2.6.22.6-rbtree-tomq/net/ipv4/tcp_input.c
--- linux-2.6.22.6-rbtree-davem-fixed/net/ipv4/tcp_input.c 2007-09-13 18:23:16.000000000 -0700
+++ linux-2.6.22.6-rbtree-tomq/net/ipv4/tcp_input.c 2007-09-19 12:27:42.000000000 -0700
@@ -956,6 +956,7 @@
int fack_count_base;
int i;
int first_sack_index;
+ u32 prev_end_seq = 0;
if (!tp->sacked_out)
tp->fackets_out = 0;
@@ -1000,6 +1001,7 @@
if (i == 0) {
if (tp->recv_sack_cache[i].start_seq != start_seq)
flag = 0;
+ prev_end_seq = ntohl(tp->recv_sack_cache[i].end_seq);
} else {
if ((tp->recv_sack_cache[i].start_seq != start_seq) ||
(tp->recv_sack_cache[i].end_seq != end_seq))
@@ -1016,9 +1018,16 @@
first_sack_index = 0;
if (flag)
+ /* all that has changed is end of first SACK block. So all we
+ * need to do is tag those skbs that were'nt tagged last time. */
num_sacks = 1;
else {
int j;
+
+ /* more than just end of first SACK block has changed; invalidate
+ * prev_end_seq */
+
+ prev_end_seq = 0;
/* order SACK blocks to allow in order walk of the retrans queue */
for (i = num_sacks-1; i > 0; i--) {
@@ -1051,6 +1060,8 @@
int fack_count;
int dup_sack = (found_dup_sack && (i == first_sack_index));
+ if (prev_end_seq) start_seq = prev_end_seq;
+
skb = tcp_write_queue_find(sk, start_seq);
if (!skb)
continue;
^ permalink raw reply
* Re: net-2.6.24 - build failure
From: David Miller @ 2007-09-20 0:18 UTC (permalink / raw)
To: larry.finger; +Cc: joe, netdev, linux-wireless
In-Reply-To: <46F1BAA7.9080701@lwfinger.net>
From: Larry Finger <larry.finger@lwfinger.net>
Date: Wed, 19 Sep 2007 19:11:19 -0500
> The patch below was sent to John Linville yesterday. Obviously, it
> didn't get included before he pushed to you. With this patch, all
> the debugfs names become static, and avoid the namespace clash with
> b43. In addition, Michael Buesch has a similar patch pending for
> b43.
I've applied this patch and if someone sends me the b43 patch
I'll apply that one too.
Thanks Larry!
^ permalink raw reply
* Re: net-2.6.24 - build failure
From: Larry Finger @ 2007-09-20 0:11 UTC (permalink / raw)
To: David Miller
Cc: joe-6d6DIl74uiNBDgjK7y7TUQ, netdev-u79uwXL29TY76Z2rM5mHXA,
linux-wireless-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <20070919.151712.66176476.davem-fT/PcQaiUtIeIZ0/mPfg9Q@public.gmane.org>
David Miller wrote:
> From: Joe Perches <joe-6d6DIl74uiNBDgjK7y7TUQ@public.gmane.org>
> Date: Wed, 19 Sep 2007 14:53:22 -0700
>
>> drivers/net/wireless/b43legacy/built-in.o: In function `tsf_read_file':
>> drivers/net/wireless/b43legacy/debugfs.c:80: multiple definition of `tsf_read_file'
>
> Can one of the wireless folks fix b43legacy to not use the same
> global variable and function names as the b43 driver?
>
David,
The patch below was sent to John Linville yesterday. Obviously, it didn't get included before he
pushed to you. With this patch, all the debugfs names become static, and avoid the namespace clash
with b43. In addition, Michael Buesch has a similar patch pending for b43.
Larry
========================================
There are additional sparse warnings in b43legacy. None of them result
in program errors, but are fixed for completeness.
Signed-off-by: Larry Finger <Larry.Finger-tQ5ms3gMjBLk1uMJSBkQmQ@public.gmane.org>
---
drivers/net/wireless/b43legacy/debugfs.c | 14 +++++++-------
drivers/net/wireless/b43legacy/pio.c | 6 +++---
2 files changed, 10 insertions(+), 10 deletions(-)
Index: wireless-dev/drivers/net/wireless/b43legacy/debugfs.c
===================================================================
--- wireless-dev.orig/drivers/net/wireless/b43legacy/debugfs.c
+++ wireless-dev/drivers/net/wireless/b43legacy/debugfs.c
@@ -39,7 +39,7 @@
/* The root directory. */
-struct dentry *rootdir;
+static struct dentry *rootdir;
struct b43legacy_debugfs_fops {
ssize_t (*read)(struct b43legacy_wldev *dev, char *buf, size_t bufsize);
@@ -76,7 +76,7 @@ struct b43legacy_dfs_file * fops_to_dfs_
/* wl->irq_lock is locked */
-ssize_t tsf_read_file(struct b43legacy_wldev *dev, char *buf, size_t bufsize)
+static ssize_t tsf_read_file(struct b43legacy_wldev *dev, char *buf, size_t bufsize)
{
ssize_t count = 0;
u64 tsf;
@@ -90,7 +90,7 @@ ssize_t tsf_read_file(struct b43legacy_w
}
/* wl->irq_lock is locked */
-int tsf_write_file(struct b43legacy_wldev *dev, const char *buf, size_t count)
+static int tsf_write_file(struct b43legacy_wldev *dev, const char *buf, size_t count)
{
u64 tsf;
@@ -102,7 +102,7 @@ int tsf_write_file(struct b43legacy_wlde
}
/* wl->irq_lock is locked */
-ssize_t ucode_regs_read_file(struct b43legacy_wldev *dev, char *buf, size_t bufsize)
+static ssize_t ucode_regs_read_file(struct b43legacy_wldev *dev, char *buf, size_t bufsize)
{
ssize_t count = 0;
int i;
@@ -116,7 +116,7 @@ ssize_t ucode_regs_read_file(struct b43l
}
/* wl->irq_lock is locked */
-ssize_t shm_read_file(struct b43legacy_wldev *dev, char *buf, size_t bufsize)
+static ssize_t shm_read_file(struct b43legacy_wldev *dev, char *buf, size_t bufsize)
{
ssize_t count = 0;
int i;
@@ -135,7 +135,7 @@ ssize_t shm_read_file(struct b43legacy_w
return count;
}
-ssize_t txstat_read_file(struct b43legacy_wldev *dev, char *buf, size_t bufsize)
+static ssize_t txstat_read_file(struct b43legacy_wldev *dev, char *buf, size_t bufsize)
{
struct b43legacy_txstatus_log *log = &dev->dfsentry->txstatlog;
ssize_t count = 0;
@@ -183,7 +183,7 @@ out_unlock:
}
/* wl->irq_lock is locked */
-int restart_write_file(struct b43legacy_wldev *dev, const char *buf, size_t count)
+static int restart_write_file(struct b43legacy_wldev *dev, const char *buf, size_t count)
{
int err = 0;
Index: wireless-dev/drivers/net/wireless/b43legacy/pio.c
===================================================================
--- wireless-dev.orig/drivers/net/wireless/b43legacy/pio.c
+++ wireless-dev/drivers/net/wireless/b43legacy/pio.c
@@ -66,7 +66,7 @@ static u16 tx_get_next_word(const u8 *tx
source = packet;
i -= txhdr_size;
}
- ret = le16_to_cpu(*((u16 *)(source + i)));
+ ret = le16_to_cpu(*((__le16 *)(source + i)));
*pos += 2;
return ret;
@@ -539,7 +539,7 @@ static void pio_rx_error(struct b43legac
void b43legacy_pio_rx(struct b43legacy_pioqueue *queue)
{
- u16 preamble[21] = { 0 };
+ __le16 preamble[21] = { 0 };
struct b43legacy_rxhdr_fw3 *rxhdr;
u16 tmp;
u16 len;
@@ -609,7 +609,7 @@ data_ready:
skb_put(skb, len);
for (i = 0; i < len - 1; i += 2) {
tmp = b43legacy_pio_read(queue, B43legacy_PIO_RXDATA);
- *((u16 *)(skb->data + i)) = cpu_to_le16(tmp);
+ *((__le16 *)(skb->data + i)) = cpu_to_le16(tmp);
}
if (len % 2) {
tmp = b43legacy_pio_read(queue, B43legacy_PIO_RXDATA);
-------
^ permalink raw reply
* Re: [PATCH]: Preliminary release of Sun Neptune driver
From: David Miller @ 2007-09-19 23:53 UTC (permalink / raw)
To: rick.jones2; +Cc: shemminger, netdev, Ariel.Hendel, greg.onufer, jeff
In-Reply-To: <46F1AEC7.8090604@hp.com>
From: Rick Jones <rick.jones2@hp.com>
Date: Wed, 19 Sep 2007 16:20:39 -0700
> so why "niu?" To what does niu translate anyway?
Network Interface Unit. This is what the Niagara-2 programmers manual
refers to the chip as.
I try to name the files for most drivers I write as a 2 or 3 letter
acronyms, it looks so much better than the usual verbose names. It's
very unix.
^ permalink raw reply
* Re: [PATCH 2.6.23-rc6 Resending] NETWORKING : Edge Triggered EPOLLOUT events get missed for TCP sockets
From: Nagendra Tomar @ 2007-09-19 23:50 UTC (permalink / raw)
To: Davide Libenzi, David Miller
Cc: tomer_iisc, netdev, Linux Kernel Mailing List
In-Reply-To: <Pine.LNX.4.64.0709191552171.2989@alien.or.mcafeemobile.com>
--- Davide Libenzi <davidel@xmailserver.org> wrote:
> On Wed, 19 Sep 2007, David Miller wrote:
>
> > From: Nagendra Tomar <tomer_iisc@yahoo.com>
> > Date: Wed, 19 Sep 2007 15:37:09 -0700 (PDT)
> >
> > > With the SOCK_NOSPACE check in tcp_check_space(), this epoll_wait call will
> > > not return, even when the incoming acks free the buffers.
> > > Note that this patch assumes that the SOCK_NOSPACE check in
> > > tcp_check_space is a trivial optimization which can be safely removed.
> >
> > I already replied to your patch posting explaining that whatever is
> > not setting SOCK_NOSPACE should be fixed instead.
> >
> > Please address that, thanks.
>
> You're not planning of putting the notion of a SOCK_NOSPACE bit inside a
> completely device-unaware interface like epoll, I hope?
>
Definitely not !
The point is that the "tcp write space available"
wakeup does not get called if SOCK_NOSPACE bit is not set. This was
fine when the wakeup was merely a wakeup (since SOCK_NOSPACE bit
indicated that someone really cared abt the wakeup). Now after the
introduction of callback'ed wakeups, we might have some work to
do inside the callback even if there is nobody interested in the wakeup
at that point of time.
In this particular case the ep_poll_callback is not getting called and
hence the socket fd is not getting added to the ready list.
Thanx,
Tomar
___________________________________________________________
Yahoo! Answers - Got a question? Someone out there knows the answer. Try it
now.
http://uk.answers.yahoo.com/
^ permalink raw reply
* RE: [ofa-general] [PATCH] RDMA/CMA: Implement rdma_resolve_ip retry enhancement.
From: Glenn Grundstrom @ 2007-09-19 23:45 UTC (permalink / raw)
To: Sean Hefty; +Cc: netdev, rdreier, general
In-Reply-To: <46F153C4.2070008@ichips.intel.com>
> > If an application is calling rdma_resolve_ip() and a status
> of -ENODATA is returned from addr_resolve_local/remote(), the
> timeout mechanism waits until the application's timeout
> occurs before rechecking the address resolution status; the
> application will wait until it's full timeout occurs. This
> case is seen when the work thread call to process_req() is
> made before the arp packet is processed.
>
> I don't understand the issue. process_req() is invoked whenever a
> network event occurs, which rechecks all pending requests.
Yes, I see the netevent_callback(). I now agree that this patch is not
necessary.
Roland, please disregard.
Glenn.
>
> > This patch is in addition to Steve Wise's neigh_event_send
> patch to initiate neighbour discovery sent on 9/12/2007.
>
> This patch looks unrelated to Steve's patch. Can you clarify the
> relationship?
>
> - Sean
>
^ permalink raw reply
* Re: [PATCH 2.6.23-rc6 Resending] NETWORKING : Edge Triggered EPOLLOUT events get missed for TCP sockets
From: Nagendra Tomar @ 2007-09-19 23:32 UTC (permalink / raw)
To: David Miller; +Cc: netdev, linux-kernel, davidel
In-Reply-To: <20070919.161037.68156707.davem@davemloft.net>
--- David Miller <davem@davemloft.net> wrote:
> From: Nagendra Tomar <tomer_iisc@yahoo.com>
> Date: Wed, 19 Sep 2007 15:55:58 -0700 (PDT)
>
> > I agree that setting SOCK_NOSPACE would have been a more elegant
> > fix. Infact I thought a lot about that before deciding on this fix.
>
> I guess this means you also noticed that you are removing
> the one and only test of this bit too?
>
> You can't remove this, it's critical for performance.
I'm sure you would have seen value in the check that's why the
check is there.
Now we have two critical points to discuss
1. How can we achieve the ET EPOLLOUT event with the SOCK_NOSPACE
check in place ?
2. How much effect will removing the check have (if we cannot
find a way to get the ET EPOLLOUT notification w/ the check
in place) ?
Regding (2), IMHO for a "fast sender" the SOCK_NOSPACE check will
almost always pass as the sender will come back to write (or poll)
before the prev data is drained out. If he doesn't do that, he is
not a "fast sender" by definition". A "fast sender" should always
have some data to send when he practically (per the sndbuf space)
can.
For a "slow sender", do we really care abt the optimization ?
Thanx,
Tomar
___________________________________________________________
Yahoo! Answers - Got a question? Someone out there knows the answer. Try it
now.
http://uk.answers.yahoo.com/
^ permalink raw reply
* Re: [PATCH 3/6] sky2: reorganize chip revision features
From: Rick Jones @ 2007-09-19 23:27 UTC (permalink / raw)
To: Stephen Hemminger; +Cc: Jeff Garzk, netdev
In-Reply-To: <20070919223746.612168285@linux-foundation.org>
Stephen Hemminger wrote:
> This patch should cause no functional changes in driver behaviour.
> There are (too) many revisions of the Yukon 2 chip now. Instead of
> adding more conditionals based on chip revision; rerganize into a
> set of feature flags so adding new versions is less problematic.
> @@ -311,10 +310,8 @@ static void sky2_phy_init(struct sky2_hw
> struct sky2_port *sky2 = netdev_priv(hw->dev[port]);
> u16 ctrl, ct1000, adv, pg, ledctrl, ledover, reg;
>
> - if (sky2->autoneg == AUTONEG_ENABLE
> - && !(hw->chip_id == CHIP_ID_YUKON_XL
> - || hw->chip_id == CHIP_ID_YUKON_EC_U
> - || hw->chip_id == CHIP_ID_YUKON_EX)) {
> + if (sky2->autoneg == AUTONEG_ENABLE &&
> + !(hw->flags & SKY2_HW_NEWER_PHY)) {
Will something like SKY2_HW_NEWER_PHY age well? Won't that leave things
vulnerable to needing a SKY2_HW_NEWER_NEWER_PHY?
> @@ -1436,13 +1428,15 @@ static int sky2_xmit_frame(struct sk_buf
> /* Check for TCP Segmentation Offload */
> mss = skb_shinfo(skb)->gso_size;
> if (mss != 0) {
> - if (hw->chip_id != CHIP_ID_YUKON_EX)
> +
> + if (!(hw->flags & SKY2_HW_NEW_LE))
> mss += ETH_HLEN + ip_hdrlen(skb) + tcp_hdrlen(skb);
Might the same thing apply with SKY2_HW_NEW_LE?
rick jones
^ permalink raw reply
* Re: [PATCH]: Preliminary release of Sun Neptune driver
From: Rick Jones @ 2007-09-19 23:20 UTC (permalink / raw)
To: David Miller; +Cc: Stephen Hemminger, netdev, Ariel.Hendel, greg.onufer, jeff
In-Reply-To: <20070919145900.759ef19e@freepuppy.rosehill.hemminger.net>
>>+#define DRV_MODULE_NAME "niu"
>>+#define PFX DRV_MODULE_NAME ": "
>>+#define DRV_MODULE_VERSION "0.06"
>>+#define DRV_MODULE_RELDATE "September 18, 2007"
>>+
>>+static char version[] __devinitdata =
>>+ DRV_MODULE_NAME ".c:v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n";
>>+
>>+MODULE_AUTHOR("David S. Miller (davem@davemloft.net)");
>>+MODULE_DESCRIPTION("NIU ethernet driver");
>>+MODULE_LICENSE("GPL");
>>+MODULE_VERSION(DRV_MODULE_VERSION);
A somewhat pedantic question... some grepping in a kernel tree suggests
the obvious name "netptune" is at least already taken for PCI ID macros:
hpcpc105:~/linux-2.6.23-rc5# grep -i neptune ./drivers/scsi/lpfc/lpfc_hw.h
#define PCI_DEVICE_ID_NEPTUNE 0xf0f5
#define PCI_DEVICE_ID_NEPTUNE_SCSP 0xf0f6
#define PCI_DEVICE_ID_NEPTUNE_DCSP 0xf0f7
and shows-up in comments elsewhere, but that same (perhaps too cursory?)
search didn't seem to find "neptune" used as an actual module/driver
name, so why "niu?" To what does niu translate anyway?
sincerely,
rick jones
now left with the quandry of whether to run netperf against a driver for
a card from a .com other than his own or an OEM :) On the plus side
though, this driver has no EULA restrictions :)
^ permalink raw reply
* Re: [PATCH]: Preliminary release of Sun Neptune driver
From: David Miller @ 2007-09-19 23:17 UTC (permalink / raw)
To: shemminger; +Cc: netdev, Ariel.Hendel, greg.onufer, jeff
In-Reply-To: <20070919160520.709a6819@freepuppy.rosehill.hemminger.net>
From: Stephen Hemminger <shemminger@linux-foundation.org>
Date: Wed, 19 Sep 2007 16:05:20 -0700
> GCC is not as smart as you think... Try the following test:
Indeed, thanks for pointing that out. I'll have to
macroize it like this to get the check:
static int __niu_wait_bits_clear_mac(void *np, unsigned long reg,
int limit, int delay)
{
...
#define niu_wait_bits_clear_mac(NP, REG, LIM, DELAY) \
({ BUILD_BUG_ON(LIM <= 0 || DELAY < 0); \
__niu_wait_bits_clear_mac(NP, REG, LIM, DELAY); \
})
^ permalink raw reply
* [PATCH 2/6] sky2: ethtool speed report bug
From: Stephen Hemminger @ 2007-09-19 22:36 UTC (permalink / raw)
To: Jeff Garzk; +Cc: netdev
In-Reply-To: <20070919223641.860189786@linux-foundation.org>
[-- Attachment #1: sky2-ethtool-100mbit.patch --]
[-- Type: text/plain, Size: 874 bytes --]
On 100mbit versions, the driver always reports gigabit speed
available. The correct modes are already computed, then overwritten.
Signed-off-by: Stephen Hemminger <shemminger@linux-foundation.org>
--- a/drivers/net/sky2.c 2007-09-19 09:18:50.000000000 -0700
+++ b/drivers/net/sky2.c 2007-09-19 09:19:35.000000000 -0700
@@ -2841,13 +2841,6 @@ static int sky2_get_settings(struct net_
ecmd->supported = sky2_supported_modes(hw);
ecmd->phy_address = PHY_ADDR_MARV;
if (sky2_is_copper(hw)) {
- ecmd->supported = SUPPORTED_10baseT_Half
- | SUPPORTED_10baseT_Full
- | SUPPORTED_100baseT_Half
- | SUPPORTED_100baseT_Full
- | SUPPORTED_1000baseT_Half
- | SUPPORTED_1000baseT_Full
- | SUPPORTED_Autoneg | SUPPORTED_TP;
ecmd->port = PORT_TP;
ecmd->speed = sky2->speed;
} else {
--
Stephen Hemminger <shemminger@linux-foundation.org>
^ permalink raw reply
* [PATCH 1/6] sky2: fix VLAN receive processing (resend)
From: Stephen Hemminger @ 2007-09-19 22:36 UTC (permalink / raw)
To: Jeff Garzk; +Cc: netdev, Pierre-Yves Ritschard
In-Reply-To: <20070919223641.860189786@linux-foundation.org>
[-- Attachment #1: sky2-vlan-len.patch --]
[-- Type: text/plain, Size: 2111 bytes --]
The length check for truncated frames was not correctly handling
the case where VLAN acceleration had already read the tag.
Also, the Yukon EX has some features that use high bit of status
as security tag.
Signed-off-by: Pierre-Yves Ritschard <pyr@spootnik.org>
Signed-off-by: Stephen Hemminger <shemminger@linux-foundation.org>
--- a/drivers/net/sky2.c 2007-09-17 16:51:53.000000000 -0700
+++ b/drivers/net/sky2.c 2007-09-17 17:03:25.000000000 -0700
@@ -2103,6 +2103,13 @@ static struct sk_buff *sky2_receive(stru
struct sky2_port *sky2 = netdev_priv(dev);
struct rx_ring_info *re = sky2->rx_ring + sky2->rx_next;
struct sk_buff *skb = NULL;
+ u16 count = (status & GMR_FS_LEN) >> 16;
+
+#ifdef SKY2_VLAN_TAG_USED
+ /* Account for vlan tag */
+ if (sky2->vlgrp && (status & GMR_FS_VLAN))
+ count -= VLAN_HLEN;
+#endif
if (unlikely(netif_msg_rx_status(sky2)))
printk(KERN_DEBUG PFX "%s: rx slot %u status 0x%x len %d\n",
@@ -2117,7 +2124,8 @@ static struct sk_buff *sky2_receive(stru
if (!(status & GMR_FS_RX_OK))
goto resubmit;
- if (status >> 16 != length)
+ /* if length reported by DMA does not match PHY, packet was truncated */
+ if (length != count)
goto len_mismatch;
if (length < copybreak)
@@ -2133,6 +2141,10 @@ len_mismatch:
/* Truncation of overlength packets
causes PHY length to not match MAC length */
++sky2->net_stats.rx_length_errors;
+ if (netif_msg_rx_err(sky2) && net_ratelimit())
+ pr_info(PFX "%s: rx length mismatch: length %d status %#x\n",
+ dev->name, length, status);
+ goto resubmit;
error:
++sky2->net_stats.rx_errors;
--- a/drivers/net/sky2.h 2007-09-17 16:51:53.000000000 -0700
+++ b/drivers/net/sky2.h 2007-09-17 16:53:25.000000000 -0700
@@ -1668,7 +1668,7 @@ enum {
/* Receive Frame Status Encoding */
enum {
- GMR_FS_LEN = 0xffff<<16, /* Bit 31..16: Rx Frame Length */
+ GMR_FS_LEN = 0x7fff<<16, /* Bit 30..16: Rx Frame Length */
GMR_FS_VLAN = 1<<13, /* VLAN Packet */
GMR_FS_JABBER = 1<<12, /* Jabber Packet */
GMR_FS_UN_SIZE = 1<<11, /* Undersize Packet */
--
Stephen Hemminger <shemminger@linux-foundation.org>
^ permalink raw reply
* [PATCH 4/6] sky2: fe+ chip support
From: Stephen Hemminger @ 2007-09-19 22:36 UTC (permalink / raw)
To: Jeff Garzk; +Cc: netdev
In-Reply-To: <20070919223641.860189786@linux-foundation.org>
[-- Attachment #1: sky2-fe-p.patch --]
[-- Type: text/plain, Size: 11608 bytes --]
Add support for newest Marvell chips.
The Yukon FE plus chip is found in some not yet released laptops.
Tested on hardware evaluation boards.
This version of the patch is for 2.6.23. It supersedes
the two previous patches that are sitting in netdev-2.6 (upstream branch).
Signed-off-by: Stephen Hemminger <shemminger@linux-foundation.org>
--- a/drivers/net/sky2.c 2007-09-19 10:01:34.000000000 -0700
+++ b/drivers/net/sky2.c 2007-09-19 10:05:15.000000000 -0700
@@ -118,12 +118,15 @@ static const struct pci_device_id sky2_i
{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4351) }, /* 88E8036 */
{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4352) }, /* 88E8038 */
{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4353) }, /* 88E8039 */
+ { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4354) }, /* 88E8040 */
{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4356) }, /* 88EC033 */
+ { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x435A) }, /* 88E8048 */
{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4360) }, /* 88E8052 */
{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4361) }, /* 88E8050 */
{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4362) }, /* 88E8053 */
{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4363) }, /* 88E8055 */
{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4364) }, /* 88E8056 */
+ { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4365) }, /* 88E8070 */
{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4366) }, /* 88EC036 */
{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4367) }, /* 88EC032 */
{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4368) }, /* 88EC034 */
@@ -147,6 +150,7 @@ static const char *yukon2_name[] = {
"Extreme", /* 0xb5 */
"EC", /* 0xb6 */
"FE", /* 0xb7 */
+ "FE+", /* 0xb8 */
};
static void sky2_set_multicast(struct net_device *dev);
@@ -331,7 +335,7 @@ static void sky2_phy_init(struct sky2_hw
ctrl = gm_phy_read(hw, port, PHY_MARV_PHY_CTRL);
if (sky2_is_copper(hw)) {
- if (hw->chip_id == CHIP_ID_YUKON_FE) {
+ if (!(hw->flags & SKY2_HW_GIGABIT)) {
/* enable automatic crossover */
ctrl |= PHY_M_PC_MDI_XMODE(PHY_M_PC_ENA_AUTO) >> 1;
} else {
@@ -450,7 +454,7 @@ static void sky2_phy_init(struct sky2_hw
gma_write16(hw, port, GM_GP_CTRL, reg);
- if (hw->chip_id != CHIP_ID_YUKON_FE)
+ if (hw->flags & SKY2_HW_GIGABIT)
gm_phy_write(hw, port, PHY_MARV_1000T_CTRL, ct1000);
gm_phy_write(hw, port, PHY_MARV_AUNE_ADV, adv);
@@ -474,6 +478,23 @@ static void sky2_phy_init(struct sky2_hw
gm_phy_write(hw, port, PHY_MARV_FE_LED_PAR, ctrl);
break;
+ case CHIP_ID_YUKON_FE_P:
+ /* Enable Link Partner Next Page */
+ ctrl = gm_phy_read(hw, port, PHY_MARV_PHY_CTRL);
+ ctrl |= PHY_M_PC_ENA_LIP_NP;
+
+ /* disable Energy Detect and enable scrambler */
+ ctrl &= ~(PHY_M_PC_ENA_ENE_DT | PHY_M_PC_DIS_SCRAMB);
+ gm_phy_write(hw, port, PHY_MARV_PHY_CTRL, ctrl);
+
+ /* set LED2 -> ACT, LED1 -> LINK, LED0 -> SPEED */
+ ctrl = PHY_M_FELP_LED2_CTRL(LED_PAR_CTRL_ACT_BL) |
+ PHY_M_FELP_LED1_CTRL(LED_PAR_CTRL_LINK) |
+ PHY_M_FELP_LED0_CTRL(LED_PAR_CTRL_SPEED);
+
+ gm_phy_write(hw, port, PHY_MARV_FE_LED_PAR, ctrl);
+ break;
+
case CHIP_ID_YUKON_XL:
pg = gm_phy_read(hw, port, PHY_MARV_EXT_ADR);
@@ -543,7 +564,13 @@ static void sky2_phy_init(struct sky2_hw
/* set page register to 0 */
gm_phy_write(hw, port, PHY_MARV_EXT_ADR, 0);
+ } else if (hw->chip_id == CHIP_ID_YUKON_FE_P &&
+ hw->chip_rev == CHIP_REV_YU_FE2_A0) {
+ /* apply workaround for integrated resistors calibration */
+ gm_phy_write(hw, port, PHY_MARV_PAGE_ADDR, 17);
+ gm_phy_write(hw, port, PHY_MARV_PAGE_DATA, 0x3f60);
} else if (hw->chip_id != CHIP_ID_YUKON_EX) {
+ /* no effect on Yukon-XL */
gm_phy_write(hw, port, PHY_MARV_LED_CTRL, ledctrl);
if (sky2->autoneg == AUTONEG_DISABLE || sky2->speed == SPEED_100) {
@@ -664,25 +691,25 @@ static void sky2_wol_init(struct sky2_po
static void sky2_set_tx_stfwd(struct sky2_hw *hw, unsigned port)
{
- if (hw->chip_id == CHIP_ID_YUKON_EX && hw->chip_rev != CHIP_REV_YU_EX_A0) {
+ struct net_device *dev = hw->dev[port];
+
+ if (dev->mtu <= ETH_DATA_LEN)
sky2_write32(hw, SK_REG(port, TX_GMF_CTRL_T),
- TX_STFW_ENA |
- (hw->dev[port]->mtu > ETH_DATA_LEN) ? TX_JUMBO_ENA : TX_JUMBO_DIS);
- } else {
- if (hw->dev[port]->mtu > ETH_DATA_LEN) {
- /* set Tx GMAC FIFO Almost Empty Threshold */
- sky2_write32(hw, SK_REG(port, TX_GMF_AE_THR),
- (ECU_JUMBO_WM << 16) | ECU_AE_THR);
-
- sky2_write32(hw, SK_REG(port, TX_GMF_CTRL_T),
- TX_JUMBO_ENA | TX_STFW_DIS);
-
- /* Can't do offload because of lack of store/forward */
- hw->dev[port]->features &= ~(NETIF_F_TSO | NETIF_F_SG
- | NETIF_F_ALL_CSUM);
- } else
- sky2_write32(hw, SK_REG(port, TX_GMF_CTRL_T),
- TX_JUMBO_DIS | TX_STFW_ENA);
+ TX_JUMBO_DIS | TX_STFW_ENA);
+
+ else if (hw->chip_id != CHIP_ID_YUKON_EC_U)
+ sky2_write32(hw, SK_REG(port, TX_GMF_CTRL_T),
+ TX_STFW_ENA | TX_JUMBO_ENA);
+ else {
+ /* set Tx GMAC FIFO Almost Empty Threshold */
+ sky2_write32(hw, SK_REG(port, TX_GMF_AE_THR),
+ (ECU_JUMBO_WM << 16) | ECU_AE_THR);
+
+ sky2_write32(hw, SK_REG(port, TX_GMF_CTRL_T),
+ TX_JUMBO_ENA | TX_STFW_DIS);
+
+ /* Can't do offload because of lack of store/forward */
+ dev->features &= ~(NETIF_F_TSO | NETIF_F_SG | NETIF_F_ALL_CSUM);
}
}
@@ -768,7 +795,8 @@ static void sky2_mac_init(struct sky2_hw
/* Configure Rx MAC FIFO */
sky2_write8(hw, SK_REG(port, RX_GMF_CTRL_T), GMF_RST_CLR);
rx_reg = GMF_OPER_ON | GMF_RX_F_FL_ON;
- if (hw->chip_id == CHIP_ID_YUKON_EX)
+ if (hw->chip_id == CHIP_ID_YUKON_EX ||
+ hw->chip_id == CHIP_ID_YUKON_FE_P)
rx_reg |= GMF_RX_OVER_ON;
sky2_write32(hw, SK_REG(port, RX_GMF_CTRL_T), rx_reg);
@@ -777,7 +805,12 @@ static void sky2_mac_init(struct sky2_hw
sky2_write16(hw, SK_REG(port, RX_GMF_FL_MSK), GMR_FS_ANY_ERR);
/* Set threshold to 0xa (64 bytes) + 1 to workaround pause bug */
- sky2_write16(hw, SK_REG(port, RX_GMF_FL_THR), RX_GMF_FL_THR_DEF+1);
+ reg = RX_GMF_FL_THR_DEF + 1;
+ /* Another magic mystery workaround from sk98lin */
+ if (hw->chip_id == CHIP_ID_YUKON_FE_P &&
+ hw->chip_rev == CHIP_REV_YU_FE2_A0)
+ reg = 0x178;
+ sky2_write16(hw, SK_REG(port, RX_GMF_FL_THR), reg);
/* Configure Tx MAC FIFO */
sky2_write8(hw, SK_REG(port, TX_GMF_CTRL_T), GMF_RST_CLR);
@@ -1704,8 +1737,12 @@ static u16 sky2_phy_speed(const struct s
if (hw->flags & SKY2_HW_FIBRE_PHY)
return SPEED_1000;
- if (hw->chip_id == CHIP_ID_YUKON_FE)
- return (aux & PHY_M_PS_SPEED_100) ? SPEED_100 : SPEED_10;
+ if (!(hw->flags & SKY2_HW_GIGABIT)) {
+ if (aux & PHY_M_PS_SPEED_100)
+ return SPEED_100;
+ else
+ return SPEED_10;
+ }
switch (aux & PHY_M_PS_SPEED_MSK) {
case PHY_M_PS_SPEED_1000:
@@ -1949,7 +1986,9 @@ static int sky2_change_mtu(struct net_de
if (new_mtu < ETH_ZLEN || new_mtu > ETH_JUMBO_MTU)
return -EINVAL;
- if (new_mtu > ETH_DATA_LEN && hw->chip_id == CHIP_ID_YUKON_FE)
+ if (new_mtu > ETH_DATA_LEN &&
+ (hw->chip_id == CHIP_ID_YUKON_FE ||
+ hw->chip_id == CHIP_ID_YUKON_FE_P))
return -EINVAL;
if (!netif_running(dev)) {
@@ -1966,7 +2005,7 @@ static int sky2_change_mtu(struct net_de
synchronize_irq(hw->pdev->irq);
- if (hw->chip_id == CHIP_ID_YUKON_EC_U || hw->chip_id == CHIP_ID_YUKON_EX)
+ if (!(hw->flags & SKY2_HW_RAMBUFFER))
sky2_set_tx_stfwd(hw, port);
ctl = gma_read16(hw, port, GM_GP_CTRL);
@@ -2205,7 +2244,7 @@ static int sky2_status_intr(struct sky2_
}
/* This chip reports checksum status differently */
- if (hw->chip_id == CHIP_ID_YUKON_EX) {
+ if (hw->flags & SKY2_HW_NEW_LE) {
if (sky2->rx_csum &&
(le->css & (CSS_ISIPV4 | CSS_ISIPV6)) &&
(le->css & CSS_TCPUDPCSOK))
@@ -2246,8 +2285,14 @@ static int sky2_status_intr(struct sky2_
if (!sky2->rx_csum)
break;
- if (hw->chip_id == CHIP_ID_YUKON_EX)
+ /* If this happens then driver assuming wrong format */
+ if (unlikely(hw->flags & SKY2_HW_NEW_LE)) {
+ if (net_ratelimit())
+ printk(KERN_NOTICE "%s: unexpected"
+ " checksum status\n",
+ dev->name);
break;
+ }
/* Both checksum counters are programmed to start at
* the same offset, so unless there is a problem they
@@ -2549,17 +2594,25 @@ static void sky2_netpoll(struct net_devi
#endif
/* Chip internal frequency for clock calculations */
-static inline u32 sky2_mhz(const struct sky2_hw *hw)
+static u32 sky2_mhz(const struct sky2_hw *hw)
{
switch (hw->chip_id) {
case CHIP_ID_YUKON_EC:
case CHIP_ID_YUKON_EC_U:
case CHIP_ID_YUKON_EX:
- return 125; /* 125 Mhz */
+ return 125;
+
case CHIP_ID_YUKON_FE:
- return 100; /* 100 Mhz */
- default: /* YUKON_XL */
- return 156; /* 156 Mhz */
+ return 100;
+
+ case CHIP_ID_YUKON_FE_P:
+ return 50;
+
+ case CHIP_ID_YUKON_XL:
+ return 156;
+
+ default:
+ BUG();
}
}
@@ -2623,6 +2676,12 @@ static int __devinit sky2_init(struct sk
hw->flags = SKY2_HW_RAMBUFFER;
break;
+ case CHIP_ID_YUKON_FE_P:
+ hw->flags = SKY2_HW_NEWER_PHY
+ | SKY2_HW_NEW_LE
+ | SKY2_HW_AUTO_TX_SUM
+ | SKY2_HW_ADV_POWER_CTL;
+ break;
default:
dev_err(&hw->pdev->dev, "unsupported chip type 0x%x\n",
hw->chip_id);
@@ -2827,7 +2886,9 @@ static int sky2_set_wol(struct net_devic
sky2->wol = wol->wolopts;
- if (hw->chip_id == CHIP_ID_YUKON_EC_U || hw->chip_id == CHIP_ID_YUKON_EX)
+ if (hw->chip_id == CHIP_ID_YUKON_EC_U ||
+ hw->chip_id == CHIP_ID_YUKON_EX ||
+ hw->chip_id == CHIP_ID_YUKON_FE_P)
sky2_write32(hw, B0_CTST, sky2->wol
? Y2_HW_WOL_ON : Y2_HW_WOL_OFF);
@@ -3820,6 +3881,13 @@ static __devinit struct net_device *sky2
sky2->hw = hw;
sky2->msg_enable = netif_msg_init(debug, default_msg);
+ /* This chip has hardware problems that generates
+ * bogus PHY receive status so by default shut up the message.
+ */
+ if (hw->chip_id == CHIP_ID_YUKON_FE_P &&
+ hw->chip_rev == CHIP_REV_YU_FE2_A0)
+ sky2->msg_enable &= ~NETIF_MSG_RX_ERR;
+
/* Auto speed and flow control */
sky2->autoneg = AUTONEG_ENABLE;
sky2->flow_mode = FC_BOTH;
@@ -4189,7 +4257,9 @@ static int sky2_resume(struct pci_dev *p
pci_enable_wake(pdev, PCI_D0, 0);
/* Re-enable all clocks */
- if (hw->chip_id == CHIP_ID_YUKON_EX || hw->chip_id == CHIP_ID_YUKON_EC_U)
+ if (hw->chip_id == CHIP_ID_YUKON_EX ||
+ hw->chip_id == CHIP_ID_YUKON_EC_U ||
+ hw->chip_id == CHIP_ID_YUKON_FE_P)
sky2_pci_write32(hw, PCI_DEV_REG3, 0);
sky2_reset(hw);
--- a/drivers/net/sky2.h 2007-09-19 10:01:34.000000000 -0700
+++ b/drivers/net/sky2.h 2007-09-19 10:03:46.000000000 -0700
@@ -470,18 +470,24 @@ enum {
CHIP_ID_YUKON_EX = 0xb5, /* Chip ID for YUKON-2 Extreme */
CHIP_ID_YUKON_EC = 0xb6, /* Chip ID for YUKON-2 EC */
CHIP_ID_YUKON_FE = 0xb7, /* Chip ID for YUKON-2 FE */
-
+ CHIP_ID_YUKON_FE_P = 0xb8, /* Chip ID for YUKON-2 FE+ */
+};
+enum yukon_ec_rev {
CHIP_REV_YU_EC_A1 = 0, /* Chip Rev. for Yukon-EC A1/A0 */
CHIP_REV_YU_EC_A2 = 1, /* Chip Rev. for Yukon-EC A2 */
CHIP_REV_YU_EC_A3 = 2, /* Chip Rev. for Yukon-EC A3 */
-
+};
+enum yukon_ec_u_rev {
CHIP_REV_YU_EC_U_A0 = 1,
CHIP_REV_YU_EC_U_A1 = 2,
CHIP_REV_YU_EC_U_B0 = 3,
-
+};
+enum yukon_fe_rev {
CHIP_REV_YU_FE_A1 = 1,
CHIP_REV_YU_FE_A2 = 2,
-
+};
+enum yukon_fe_p_rev {
+ CHIP_REV_YU_FE2_A0 = 0,
};
enum yukon_ex_rev {
CHIP_REV_YU_EX_A0 = 1,
@@ -1729,6 +1735,10 @@ enum {
GMF_RX_CTRL_DEF = GMF_OPER_ON | GMF_RX_F_FL_ON,
};
+/* TX_GMF_EA 32 bit Tx GMAC FIFO End Address */
+enum {
+ TX_DYN_WM_ENA = 3, /* Yukon-FE+ specific */
+};
/* TX_GMF_CTRL_T 32 bit Tx GMAC FIFO Control/Test */
enum {
--
Stephen Hemminger <shemminger@linux-foundation.org>
^ permalink raw reply
* [PATCH 3/6] sky2: reorganize chip revision features
From: Stephen Hemminger @ 2007-09-19 22:36 UTC (permalink / raw)
To: Jeff Garzk; +Cc: netdev
In-Reply-To: <20070919223641.860189786@linux-foundation.org>
[-- Attachment #1: sky2-flags.patch --]
[-- Type: text/plain, Size: 11779 bytes --]
This patch should cause no functional changes in driver behaviour.
There are (too) many revisions of the Yukon 2 chip now. Instead of
adding more conditionals based on chip revision; rerganize into a
set of feature flags so adding new versions is less problematic.
Signed-off-by: Stephen Hemminger <shemminger@linux-foundation.org>
--- a/drivers/net/sky2.c 2007-09-19 09:19:35.000000000 -0700
+++ b/drivers/net/sky2.c 2007-09-19 09:57:41.000000000 -0700
@@ -217,8 +217,7 @@ static void sky2_power_on(struct sky2_hw
else
sky2_write8(hw, B2_Y2_CLK_GATE, 0);
- if (hw->chip_id == CHIP_ID_YUKON_EC_U ||
- hw->chip_id == CHIP_ID_YUKON_EX) {
+ if (hw->flags & SKY2_HW_ADV_POWER_CTL) {
u32 reg;
sky2_pci_write32(hw, PCI_DEV_REG3, 0);
@@ -311,10 +310,8 @@ static void sky2_phy_init(struct sky2_hw
struct sky2_port *sky2 = netdev_priv(hw->dev[port]);
u16 ctrl, ct1000, adv, pg, ledctrl, ledover, reg;
- if (sky2->autoneg == AUTONEG_ENABLE
- && !(hw->chip_id == CHIP_ID_YUKON_XL
- || hw->chip_id == CHIP_ID_YUKON_EC_U
- || hw->chip_id == CHIP_ID_YUKON_EX)) {
+ if (sky2->autoneg == AUTONEG_ENABLE &&
+ !(hw->flags & SKY2_HW_NEWER_PHY)) {
u16 ectrl = gm_phy_read(hw, port, PHY_MARV_EXT_CTRL);
ectrl &= ~(PHY_M_EC_M_DSC_MSK | PHY_M_EC_S_DSC_MSK |
@@ -346,9 +343,7 @@ static void sky2_phy_init(struct sky2_hw
/* downshift on PHY 88E1112 and 88E1149 is changed */
if (sky2->autoneg == AUTONEG_ENABLE
- && (hw->chip_id == CHIP_ID_YUKON_XL
- || hw->chip_id == CHIP_ID_YUKON_EC_U
- || hw->chip_id == CHIP_ID_YUKON_EX)) {
+ && (hw->flags & SKY2_HW_NEWER_PHY)) {
/* set downshift counter to 3x and enable downshift */
ctrl &= ~PHY_M_PC_DSC_MSK;
ctrl |= PHY_M_PC_DSC(2) | PHY_M_PC_DOWN_S_ENA;
@@ -364,7 +359,7 @@ static void sky2_phy_init(struct sky2_hw
gm_phy_write(hw, port, PHY_MARV_PHY_CTRL, ctrl);
/* special setup for PHY 88E1112 Fiber */
- if (hw->chip_id == CHIP_ID_YUKON_XL && !sky2_is_copper(hw)) {
+ if (hw->chip_id == CHIP_ID_YUKON_XL && (hw->flags & SKY2_HW_FIBRE_PHY)) {
pg = gm_phy_read(hw, port, PHY_MARV_EXT_ADR);
/* Fiber: select 1000BASE-X only mode MAC Specific Ctrl Reg. */
@@ -788,7 +783,7 @@ static void sky2_mac_init(struct sky2_hw
sky2_write8(hw, SK_REG(port, TX_GMF_CTRL_T), GMF_RST_CLR);
sky2_write16(hw, SK_REG(port, TX_GMF_CTRL_T), GMF_OPER_ON);
- if (hw->chip_id == CHIP_ID_YUKON_EC_U || hw->chip_id == CHIP_ID_YUKON_EX) {
+ if (!(hw->flags & SKY2_HW_RAMBUFFER)) {
sky2_write8(hw, SK_REG(port, RX_GMF_LP_THR), 768/8);
sky2_write8(hw, SK_REG(port, RX_GMF_UP_THR), 1024/8);
@@ -967,19 +962,15 @@ static void sky2_rx_unmap_skb(struct pci
*/
static void rx_set_checksum(struct sky2_port *sky2)
{
- struct sky2_rx_le *le;
+ struct sky2_rx_le *le = sky2_next_rx(sky2);
- if (sky2->hw->chip_id != CHIP_ID_YUKON_EX) {
- le = sky2_next_rx(sky2);
- le->addr = cpu_to_le32((ETH_HLEN << 16) | ETH_HLEN);
- le->ctrl = 0;
- le->opcode = OP_TCPSTART | HW_OWNER;
-
- sky2_write32(sky2->hw,
- Q_ADDR(rxqaddr[sky2->port], Q_CSR),
- sky2->rx_csum ? BMU_ENA_RX_CHKSUM : BMU_DIS_RX_CHKSUM);
- }
+ le->addr = cpu_to_le32((ETH_HLEN << 16) | ETH_HLEN);
+ le->ctrl = 0;
+ le->opcode = OP_TCPSTART | HW_OWNER;
+ sky2_write32(sky2->hw,
+ Q_ADDR(rxqaddr[sky2->port], Q_CSR),
+ sky2->rx_csum ? BMU_ENA_RX_CHKSUM : BMU_DIS_RX_CHKSUM);
}
/*
@@ -1175,7 +1166,8 @@ static int sky2_rx_start(struct sky2_por
sky2_prefetch_init(hw, rxq, sky2->rx_le_map, RX_LE_SIZE - 1);
- rx_set_checksum(sky2);
+ if (!(hw->flags & SKY2_HW_NEW_LE))
+ rx_set_checksum(sky2);
/* Space needed for frame data + headers rounded up */
size = roundup(sky2->netdev->mtu + ETH_HLEN + VLAN_HLEN, 8);
@@ -1246,7 +1238,7 @@ static int sky2_up(struct net_device *de
struct sky2_port *sky2 = netdev_priv(dev);
struct sky2_hw *hw = sky2->hw;
unsigned port = sky2->port;
- u32 ramsize, imask;
+ u32 imask;
int cap, err = -ENOMEM;
struct net_device *otherdev = hw->dev[sky2->port^1];
@@ -1301,13 +1293,13 @@ static int sky2_up(struct net_device *de
sky2_mac_init(hw, port);
- /* Register is number of 4K blocks on internal RAM buffer. */
- ramsize = sky2_read8(hw, B2_E_0) * 4;
- printk(KERN_INFO PFX "%s: ram buffer %dK\n", dev->name, ramsize);
-
- if (ramsize > 0) {
+ if (hw->flags & SKY2_HW_RAMBUFFER) {
+ /* Register is number of 4K blocks on internal RAM buffer. */
+ u32 ramsize = sky2_read8(hw, B2_E_0) * 4;
u32 rxspace;
+ printk(KERN_DEBUG PFX "%s: ram buffer %dK\n", dev->name, ramsize);
+
if (ramsize < 16)
rxspace = ramsize / 2;
else
@@ -1436,13 +1428,15 @@ static int sky2_xmit_frame(struct sk_buf
/* Check for TCP Segmentation Offload */
mss = skb_shinfo(skb)->gso_size;
if (mss != 0) {
- if (hw->chip_id != CHIP_ID_YUKON_EX)
+
+ if (!(hw->flags & SKY2_HW_NEW_LE))
mss += ETH_HLEN + ip_hdrlen(skb) + tcp_hdrlen(skb);
if (mss != sky2->tx_last_mss) {
le = get_tx_le(sky2);
le->addr = cpu_to_le32(mss);
- if (hw->chip_id == CHIP_ID_YUKON_EX)
+
+ if (hw->flags & SKY2_HW_NEW_LE)
le->opcode = OP_MSS | HW_OWNER;
else
le->opcode = OP_LRGLEN | HW_OWNER;
@@ -1468,8 +1462,7 @@ static int sky2_xmit_frame(struct sk_buf
/* Handle TCP checksum offload */
if (skb->ip_summed == CHECKSUM_PARTIAL) {
/* On Yukon EX (some versions) encoding change. */
- if (hw->chip_id == CHIP_ID_YUKON_EX
- && hw->chip_rev != CHIP_REV_YU_EX_B0)
+ if (hw->flags & SKY2_HW_AUTO_TX_SUM)
ctrl |= CALSUM; /* auto checksum */
else {
const unsigned offset = skb_transport_offset(skb);
@@ -1708,7 +1701,7 @@ static int sky2_down(struct net_device *
static u16 sky2_phy_speed(const struct sky2_hw *hw, u16 aux)
{
- if (!sky2_is_copper(hw))
+ if (hw->flags & SKY2_HW_FIBRE_PHY)
return SPEED_1000;
if (hw->chip_id == CHIP_ID_YUKON_FE)
@@ -1753,9 +1746,7 @@ static void sky2_link_up(struct sky2_por
sky2_write8(hw, SK_REG(port, LNK_LED_REG),
LINKLED_ON | LINKLED_BLINK_OFF | LINKLED_LINKSYNC_OFF);
- if (hw->chip_id == CHIP_ID_YUKON_XL
- || hw->chip_id == CHIP_ID_YUKON_EC_U
- || hw->chip_id == CHIP_ID_YUKON_EX) {
+ if (hw->flags & SKY2_HW_NEWER_PHY) {
u16 pg = gm_phy_read(hw, port, PHY_MARV_EXT_ADR);
u16 led = PHY_M_LEDC_LOS_CTRL(1); /* link active */
@@ -1847,7 +1838,7 @@ static int sky2_autoneg_done(struct sky2
/* Since the pause result bits seem to in different positions on
* different chips. look at registers.
*/
- if (!sky2_is_copper(hw)) {
+ if (hw->flags & SKY2_HW_FIBRE_PHY) {
/* Shift for bits in fiber PHY */
advert &= ~(ADVERTISE_PAUSE_CAP|ADVERTISE_PAUSE_ASYM);
lpa &= ~(LPA_PAUSE_CAP|LPA_PAUSE_ASYM);
@@ -2593,23 +2584,56 @@ static int __devinit sky2_init(struct sk
sky2_write8(hw, B0_CTST, CS_RST_CLR);
hw->chip_id = sky2_read8(hw, B2_CHIP_ID);
- if (hw->chip_id < CHIP_ID_YUKON_XL || hw->chip_id > CHIP_ID_YUKON_FE) {
+ hw->chip_rev = (sky2_read8(hw, B2_MAC_CFG) & CFG_CHIP_R_MSK) >> 4;
+
+ switch(hw->chip_id) {
+ case CHIP_ID_YUKON_XL:
+ hw->flags = SKY2_HW_GIGABIT
+ | SKY2_HW_NEWER_PHY
+ | SKY2_HW_RAMBUFFER;
+ break;
+
+ case CHIP_ID_YUKON_EC_U:
+ hw->flags = SKY2_HW_GIGABIT
+ | SKY2_HW_NEWER_PHY
+ | SKY2_HW_ADV_POWER_CTL;
+ break;
+
+ case CHIP_ID_YUKON_EX:
+ hw->flags = SKY2_HW_GIGABIT
+ | SKY2_HW_NEWER_PHY
+ | SKY2_HW_NEW_LE
+ | SKY2_HW_ADV_POWER_CTL;
+
+ /* New transmit checksum */
+ if (hw->chip_rev != CHIP_REV_YU_EX_B0)
+ hw->flags |= SKY2_HW_AUTO_TX_SUM;
+ break;
+
+ case CHIP_ID_YUKON_EC:
+ /* This rev is really old, and requires untested workarounds */
+ if (hw->chip_rev == CHIP_REV_YU_EC_A1) {
+ dev_err(&hw->pdev->dev, "unsupported revision Yukon-EC rev A1\n");
+ return -EOPNOTSUPP;
+ }
+ hw->flags = SKY2_HW_GIGABIT | SKY2_HW_RAMBUFFER;
+ break;
+
+ case CHIP_ID_YUKON_FE:
+ hw->flags = SKY2_HW_RAMBUFFER;
+ break;
+
+ default:
dev_err(&hw->pdev->dev, "unsupported chip type 0x%x\n",
hw->chip_id);
return -EOPNOTSUPP;
}
- hw->chip_rev = (sky2_read8(hw, B2_MAC_CFG) & CFG_CHIP_R_MSK) >> 4;
+ hw->pmd_type = sky2_read8(hw, B2_PMD_TYP);
+ if (hw->pmd_type == 'L' || hw->pmd_type == 'S' || hw->pmd_type == 'P')
+ hw->flags |= SKY2_HW_FIBRE_PHY;
- /* This rev is really old, and requires untested workarounds */
- if (hw->chip_id == CHIP_ID_YUKON_EC && hw->chip_rev == CHIP_REV_YU_EC_A1) {
- dev_err(&hw->pdev->dev, "unsupported revision Yukon-%s (0x%x) rev %d\n",
- yukon2_name[hw->chip_id - CHIP_ID_YUKON_XL],
- hw->chip_id, hw->chip_rev);
- return -EOPNOTSUPP;
- }
- hw->pmd_type = sky2_read8(hw, B2_PMD_TYP);
hw->ports = 1;
t8 = sky2_read8(hw, B2_Y2_HW_RES);
if ((t8 & CFG_DUAL_MAC_MSK) == CFG_DUAL_MAC_MSK) {
@@ -2821,7 +2845,7 @@ static u32 sky2_supported_modes(const st
| SUPPORTED_100baseT_Full
| SUPPORTED_Autoneg | SUPPORTED_TP;
- if (hw->chip_id != CHIP_ID_YUKON_FE)
+ if (hw->flags & SKY2_HW_GIGABIT)
modes |= SUPPORTED_1000baseT_Half
| SUPPORTED_1000baseT_Full;
return modes;
@@ -3851,7 +3875,7 @@ static irqreturn_t __devinit sky2_test_i
return IRQ_NONE;
if (status & Y2_IS_IRQ_SW) {
- hw->msi = 1;
+ hw->flags |= SKY2_HW_USE_MSI;
wake_up(&hw->msi_wait);
sky2_write8(hw, B0_CTST, CS_CL_SW_IRQ);
}
@@ -3879,9 +3903,9 @@ static int __devinit sky2_test_msi(struc
sky2_write8(hw, B0_CTST, CS_ST_SW_IRQ);
sky2_read8(hw, B0_CTST);
- wait_event_timeout(hw->msi_wait, hw->msi, HZ/10);
+ wait_event_timeout(hw->msi_wait, (hw->flags & SKY2_HW_USE_MSI), HZ/10);
- if (!hw->msi) {
+ if (!(hw->flags & SKY2_HW_USE_MSI)) {
/* MSI test failed, go back to INTx mode */
dev_info(&pdev->dev, "No interrupt generated using MSI, "
"switching to INTx mode.\n");
@@ -4014,7 +4038,8 @@ static int __devinit sky2_probe(struct p
goto err_out_free_netdev;
}
- err = request_irq(pdev->irq, sky2_intr, hw->msi ? 0 : IRQF_SHARED,
+ err = request_irq(pdev->irq, sky2_intr,
+ (hw->flags & SKY2_HW_USE_MSI) ? 0 : IRQF_SHARED,
dev->name, hw);
if (err) {
dev_err(&pdev->dev, "cannot assign irq %d\n", pdev->irq);
@@ -4047,7 +4072,7 @@ static int __devinit sky2_probe(struct p
return 0;
err_out_unregister:
- if (hw->msi)
+ if (hw->flags & SKY2_HW_USE_MSI)
pci_disable_msi(pdev);
unregister_netdev(dev);
err_out_free_netdev:
@@ -4096,7 +4121,7 @@ static void __devexit sky2_remove(struct
sky2_read8(hw, B0_CTST);
free_irq(pdev->irq, hw);
- if (hw->msi)
+ if (hw->flags & SKY2_HW_USE_MSI)
pci_disable_msi(pdev);
pci_free_consistent(pdev, STATUS_LE_BYTES, hw->st_le, hw->st_dma);
pci_release_regions(pdev);
--- a/drivers/net/sky2.h 2007-09-19 09:18:50.000000000 -0700
+++ b/drivers/net/sky2.h 2007-09-19 09:19:40.000000000 -0700
@@ -2040,6 +2040,15 @@ struct sky2_hw {
void __iomem *regs;
struct pci_dev *pdev;
struct net_device *dev[2];
+ unsigned long flags;
+#define SKY2_HW_USE_MSI 0x00000001
+#define SKY2_HW_FIBRE_PHY 0x00000002
+#define SKY2_HW_GIGABIT 0x00000004
+#define SKY2_HW_NEWER_PHY 0x00000008
+#define SKY2_HW_RAMBUFFER 0x00000010 /* chip has RAM FIFO */
+#define SKY2_HW_NEW_LE 0x00000020 /* new LSOv2 format */
+#define SKY2_HW_AUTO_TX_SUM 0x00000040 /* new IP decode for Tx */
+#define SKY2_HW_ADV_POWER_CTL 0x00000080 /* additional PHY power regs */
u8 chip_id;
u8 chip_rev;
@@ -2053,13 +2062,12 @@ struct sky2_hw {
struct timer_list watchdog_timer;
struct work_struct restart_work;
- int msi;
wait_queue_head_t msi_wait;
};
static inline int sky2_is_copper(const struct sky2_hw *hw)
{
- return !(hw->pmd_type == 'L' || hw->pmd_type == 'S' || hw->pmd_type == 'P');
+ return !(hw->flags & SKY2_HW_FIBRE_PHY);
}
/* Register accessor for memory mapped device */
--
Stephen Hemminger <shemminger@linux-foundation.org>
^ permalink raw reply
* [PATCH 6/6] sky2: version 1.18
From: Stephen Hemminger @ 2007-09-19 22:36 UTC (permalink / raw)
To: Jeff Garzk; +Cc: netdev
In-Reply-To: <20070919223641.860189786@linux-foundation.org>
[-- Attachment #1: sky2-1.19 --]
[-- Type: text/plain, Size: 428 bytes --]
Update version number
Signed-off-by: Stephen Hemminger <shemminger@linux-foundation.org>
--- a/drivers/net/sky2.c 2007-09-19 10:05:28.000000000 -0700
+++ b/drivers/net/sky2.c 2007-09-19 10:05:33.000000000 -0700
@@ -51,7 +51,7 @@
#include "sky2.h"
#define DRV_NAME "sky2"
-#define DRV_VERSION "1.17"
+#define DRV_VERSION "1.18"
#define PFX DRV_NAME " "
/*
--
Stephen Hemminger <shemminger@linux-foundation.org>
^ permalink raw reply
* [PATCH 0/6] sky2: version 1.18 (rev2)
From: Stephen Hemminger @ 2007-09-19 22:36 UTC (permalink / raw)
To: Jeff Garzk; +Cc: netdev
Patches against 2.6.23 to fix bugs and support newest FE+
chip. These patches conflict with those in netdev-2.6
upstream branch, Jeff how do you want to resolve that?
--
Stephen Hemminger <shemminger@linux-foundation.org>
^ permalink raw reply
* [PATCH 5/6] sky2: receive FIFO checking
From: Stephen Hemminger @ 2007-09-19 22:36 UTC (permalink / raw)
To: Jeff Garzk; +Cc: netdev
In-Reply-To: <20070919223641.860189786@linux-foundation.org>
[-- Attachment #1: sky2-rx-watch.patch --]
[-- Type: text/plain, Size: 4319 bytes --]
A driver writer from another operating system hinted that
the versions of Yukon 2 chip with rambuffer (EC and XL) have
a hardware bug that if the FIFO ever gets completely full it
will hang. Sounds like a classic ring full vs ring empty wrap around
bug.
As a workaround, use the existing watchdog timer to check for
ring full lockup.
Signed-off-by: Stephen Hemminger <shemminger@linux-foundation.org>
--- a/drivers/net/sky2.c 2007-09-19 10:05:15.000000000 -0700
+++ b/drivers/net/sky2.c 2007-09-19 10:05:28.000000000 -0700
@@ -1648,9 +1648,6 @@ static int sky2_down(struct net_device *
if (netif_msg_ifdown(sky2))
printk(KERN_INFO PFX "%s: disabling interface\n", dev->name);
- if (netif_carrier_ok(dev) && --hw->active == 0)
- del_timer(&hw->watchdog_timer);
-
/* Stop more packets from being queued */
netif_stop_queue(dev);
@@ -1775,9 +1772,7 @@ static void sky2_link_up(struct sky2_por
netif_carrier_on(sky2->netdev);
- if (hw->active++ == 0)
- mod_timer(&hw->watchdog_timer, jiffies + 1);
-
+ mod_timer(&hw->watchdog_timer, jiffies + 1);
/* Turn on link LED */
sky2_write8(hw, SK_REG(port, LNK_LED_REG),
@@ -1828,11 +1823,6 @@ static void sky2_link_down(struct sky2_p
netif_carrier_off(sky2->netdev);
- /* Stop watchdog if both ports are not active */
- if (--hw->active == 0)
- del_timer(&hw->watchdog_timer);
-
-
/* Turn on link LED */
sky2_write8(hw, SK_REG(port, LNK_LED_REG), LINKLED_OFF);
@@ -2484,20 +2474,72 @@ static void sky2_le_error(struct sky2_hw
sky2_write32(hw, Q_ADDR(q, Q_CSR), BMU_CLR_IRQ_CHK);
}
-/* Check for lost IRQ once a second */
+static int sky2_rx_hung(struct net_device *dev)
+{
+ struct sky2_port *sky2 = netdev_priv(dev);
+ struct sky2_hw *hw = sky2->hw;
+ unsigned port = sky2->port;
+ unsigned rxq = rxqaddr[port];
+ u32 mac_rp = sky2_read32(hw, SK_REG(port, RX_GMF_RP));
+ u8 mac_lev = sky2_read8(hw, SK_REG(port, RX_GMF_RLEV));
+ u8 fifo_rp = sky2_read8(hw, Q_ADDR(rxq, Q_RP));
+ u8 fifo_lev = sky2_read8(hw, Q_ADDR(rxq, Q_RL));
+
+ /* If idle and MAC or PCI is stuck */
+ if (sky2->check.last == dev->last_rx &&
+ ((mac_rp == sky2->check.mac_rp &&
+ mac_lev != 0 && mac_lev >= sky2->check.mac_lev) ||
+ /* Check if the PCI RX hang */
+ (fifo_rp == sky2->check.fifo_rp &&
+ fifo_lev != 0 && fifo_lev >= sky2->check.fifo_lev))) {
+ printk(KERN_DEBUG PFX "%s: hung mac %d:%d fifo %d (%d:%d)\n",
+ dev->name, mac_lev, mac_rp, fifo_lev, fifo_rp,
+ sky2_read8(hw, Q_ADDR(rxq, Q_WP)));
+ return 1;
+ } else {
+ sky2->check.last = dev->last_rx;
+ sky2->check.mac_rp = mac_rp;
+ sky2->check.mac_lev = mac_lev;
+ sky2->check.fifo_rp = fifo_rp;
+ sky2->check.fifo_lev = fifo_lev;
+ return 0;
+ }
+}
+
static void sky2_watchdog(unsigned long arg)
{
struct sky2_hw *hw = (struct sky2_hw *) arg;
+ struct net_device *dev;
+ /* Check for lost IRQ once a second */
if (sky2_read32(hw, B0_ISRC)) {
- struct net_device *dev = hw->dev[0];
-
+ dev = hw->dev[0];
if (__netif_rx_schedule_prep(dev))
__netif_rx_schedule(dev);
+ } else {
+ int i, active = 0;
+
+ for (i = 0; i < hw->ports; i++) {
+ dev = hw->dev[i];
+ if (!netif_running(dev))
+ continue;
+ ++active;
+
+ /* For chips with Rx FIFO, check if stuck */
+ if ((hw->flags & SKY2_HW_RAMBUFFER) &&
+ sky2_rx_hung(dev)) {
+ pr_info(PFX "%s: receiver hang detected\n",
+ dev->name);
+ schedule_work(&hw->restart_work);
+ return;
+ }
+ }
+
+ if (active == 0)
+ return;
}
- if (hw->active > 0)
- mod_timer(&hw->watchdog_timer, round_jiffies(jiffies + HZ));
+ mod_timer(&hw->watchdog_timer, round_jiffies(jiffies + HZ));
}
/* Hardware/software error handling */
--- a/drivers/net/sky2.h 2007-09-19 10:03:46.000000000 -0700
+++ b/drivers/net/sky2.h 2007-09-19 10:05:28.000000000 -0700
@@ -2027,6 +2027,14 @@ struct sky2_port {
u16 rx_tag;
struct vlan_group *vlgrp;
#endif
+ struct {
+ unsigned long last;
+ u32 mac_rp;
+ u8 mac_lev;
+ u8 fifo_rp;
+ u8 fifo_lev;
+ } check;
+
dma_addr_t rx_le_map;
dma_addr_t tx_le_map;
@@ -2064,7 +2072,6 @@ struct sky2_hw {
u8 chip_rev;
u8 pmd_type;
u8 ports;
- u8 active;
struct sky2_status_le *st_le;
u32 st_idx;
--
Stephen Hemminger <shemminger@linux-foundation.org>
^ permalink raw reply
* Re: [PATCH 3/3] [PPP] L2TP: Fix skb handling in pppol2tp_xmit
From: David Miller @ 2007-09-19 23:12 UTC (permalink / raw)
To: bunk; +Cc: herbert, jchapman, mostrows, paulus, toralf.foerster, netdev
In-Reply-To: <20070919231114.GC30564@stusta.de>
From: Adrian Bunk <bunk@kernel.org>
Date: Thu, 20 Sep 2007 01:11:14 +0200
> On Wed, Sep 19, 2007 at 10:45:13AM -0700, David Miller wrote:
> > From: Herbert Xu <herbert@gondor.apana.org.au>
> > Date: Wed, 19 Sep 2007 09:30:18 +0800
> >
> > > [PPP] pppoe: Fix double-free on skb after transmit failure
> > >
> > > When I got rid of the second packet in __pppoe_xmit I created
> > > a double-free on the skb because of the goto abort on failure.
> > > This patch removes that.
> > >
> > > Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
> >
> > Applied.
>
> Please excuse in case this was already clear, but since this regression
> made it into Linus' tree it should be fixed there before 2.6.23.
I will make sure this happens.
I'm just waiting for Alexey to test the SFQ crash fix and
then I'll send everything queued.
^ permalink raw reply
* Re: [PATCH 2.6.23-rc6 Resending] NETWORKING : Edge Triggered EPOLLOUT events get missed for TCP sockets
From: Davide Libenzi @ 2007-09-19 23:11 UTC (permalink / raw)
To: David Miller; +Cc: tomer_iisc, netdev, Linux Kernel Mailing List
In-Reply-To: <20070919.154402.34760338.davem@davemloft.net>
On Wed, 19 Sep 2007, David Miller wrote:
> From: Nagendra Tomar <tomer_iisc@yahoo.com>
> Date: Wed, 19 Sep 2007 15:37:09 -0700 (PDT)
>
> > With the SOCK_NOSPACE check in tcp_check_space(), this epoll_wait call will
> > not return, even when the incoming acks free the buffers.
> > Note that this patch assumes that the SOCK_NOSPACE check in
> > tcp_check_space is a trivial optimization which can be safely removed.
>
> I already replied to your patch posting explaining that whatever is
> not setting SOCK_NOSPACE should be fixed instead.
>
> Please address that, thanks.
You're not planning of putting the notion of a SOCK_NOSPACE bit inside a
completely device-unaware interface like epoll, I hope?
- Davide
^ permalink raw reply
* Re: [PATCH 3/3] [PPP] L2TP: Fix skb handling in pppol2tp_xmit
From: Adrian Bunk @ 2007-09-19 23:11 UTC (permalink / raw)
To: David Miller; +Cc: herbert, jchapman, mostrows, paulus, toralf.foerster, netdev
In-Reply-To: <20070919.104513.71087294.davem@davemloft.net>
On Wed, Sep 19, 2007 at 10:45:13AM -0700, David Miller wrote:
> From: Herbert Xu <herbert@gondor.apana.org.au>
> Date: Wed, 19 Sep 2007 09:30:18 +0800
>
> > [PPP] pppoe: Fix double-free on skb after transmit failure
> >
> > When I got rid of the second packet in __pppoe_xmit I created
> > a double-free on the skb because of the goto abort on failure.
> > This patch removes that.
> >
> > Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
>
> Applied.
Please excuse in case this was already clear, but since this regression
made it into Linus' tree it should be fixed there before 2.6.23.
cu
Adrian
--
"Is there not promise of rain?" Ling Tan asked suddenly out
of the darkness. There had been need of rain for many days.
"Only a promise," Lao Er said.
Pearl S. Buck - Dragon Seed
^ permalink raw reply
* Re: [PATCH 2.6.23-rc6 Resending] NETWORKING : Edge Triggered EPOLLOUT events get missed for TCP sockets
From: David Miller @ 2007-09-19 23:10 UTC (permalink / raw)
To: tomer_iisc; +Cc: netdev, linux-kernel, davidel
In-Reply-To: <640879.56443.qm@web53701.mail.re2.yahoo.com>
From: Nagendra Tomar <tomer_iisc@yahoo.com>
Date: Wed, 19 Sep 2007 15:55:58 -0700 (PDT)
> I agree that setting SOCK_NOSPACE would have been a more elegant
> fix. Infact I thought a lot about that before deciding on this fix.
I guess this means you also noticed that you are removing
the one and only test of this bit too?
You can't remove this, it's critical for performance.
^ permalink raw reply
* Re: [PATCH]: Preliminary release of Sun Neptune driver
From: Stephen Hemminger @ 2007-09-19 23:05 UTC (permalink / raw)
To: David Miller; +Cc: netdev, Ariel.Hendel, greg.onufer, jeff
In-Reply-To: <20070919.150755.38714639.davem@davemloft.net>
On Wed, 19 Sep 2007 15:07:55 -0700 (PDT)
David Miller <davem@davemloft.net> wrote:
> From: Stephen Hemminger <shemminger@linux-foundation.org>
> Date: Wed, 19 Sep 2007 14:59:00 -0700
>
...
> > > +static int niu_wait_bits_clear_mac(struct niu *np, unsigned long reg, u64 bits,
> > > + int limit, int delay)
> > > +{
> > > + BUILD_BUG_ON(limit <= 0 || delay < 0);
> >
> > There is no way compiler can evaluate limit or delay.
>
> Check the callers, they all pass contant values.
GCC is not as smart as you think... Try the following test:
--------------------
#include <stdio.h>
#define BUILD_BUG_ON(condition) ((void)sizeof(char[1 - 2*!!(condition)]))
#define ENODEV -10
static int niu_wait_bits_clear_mac(void *np, unsigned long reg,
int limit, int delay)
{
BUILD_BUG_ON(limit <= 0 || delay < 0);
if (limit < 0)
return -ENODEV;
while (limit > 0)
sleep(delay);
return 0;
}
int main(int argc, char **argv) {
printf("start\n");
niu_wait_bits_clear_mac(NULL, 0, 10, 1);
niu_wait_bits_clear_mac(NULL, 0, -1, 0);
niu_wait_bits_clear_mac(NULL, 0, 0, -1);
return 0;
}
^ 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