* [PATCH] /proc/net/tcp, overhead removed
From: Yakov Lerner @ 2009-09-28 23:01 UTC (permalink / raw)
To: netdev, eric.dumazet, davem; +Cc: Yakov Lerner
Take 2.
"Sharp improvement in performance of /proc/net/tcp when number of
sockets is large and hashsize is large.
O(numsock * hashsize) time becomes O(numsock + hashsize). On slow
processors, speed difference can be x100 and more."
I must say that I'm not fully satisfied with my choice of "st->sbucket"
for the new preserved index. The better name would be "st->snum".
Re-using "st->sbucket" saves 4 bytes, and keeps the patch to one sourcefile.
But "st->sbucket" has different meaning in OPENREQ and LISTEN states;
this can be confusing.
Maybe better add "snum" member to struct tcp_iter_state ?
Shall I change subject when sending "take N+1", or keep the old subject ?
Signed-off-by: Yakov Lerner <iler.ml@gmail.com>
---
net/ipv4/tcp_ipv4.c | 35 +++++++++++++++++++++++++++++++++--
1 files changed, 33 insertions(+), 2 deletions(-)
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
index 7cda24b..e4c4f19 100644
--- a/net/ipv4/tcp_ipv4.c
+++ b/net/ipv4/tcp_ipv4.c
@@ -1994,13 +1994,14 @@ static inline int empty_bucket(struct tcp_iter_state *st)
hlist_nulls_empty(&tcp_hashinfo.ehash[st->bucket].twchain);
}
-static void *established_get_first(struct seq_file *seq)
+static void *established_get_first_after(struct seq_file *seq, int bucket)
{
struct tcp_iter_state *st = seq->private;
struct net *net = seq_file_net(seq);
void *rc = NULL;
- for (st->bucket = 0; st->bucket < tcp_hashinfo.ehash_size; ++st->bucket) {
+ for (st->bucket = bucket; st->bucket < tcp_hashinfo.ehash_size;
+ ++st->bucket) {
struct sock *sk;
struct hlist_nulls_node *node;
struct inet_timewait_sock *tw;
@@ -2010,6 +2011,8 @@ static void *established_get_first(struct seq_file *seq)
if (empty_bucket(st))
continue;
+ st->sbucket = st->num;
+
spin_lock_bh(lock);
sk_nulls_for_each(sk, node, &tcp_hashinfo.ehash[st->bucket].chain) {
if (sk->sk_family != st->family ||
@@ -2036,6 +2039,11 @@ out:
return rc;
}
+static void *established_get_first(struct seq_file *seq)
+{
+ return established_get_first_after(seq, 0);
+}
+
static void *established_get_next(struct seq_file *seq, void *cur)
{
struct sock *sk = cur;
@@ -2064,6 +2072,9 @@ get_tw:
while (++st->bucket < tcp_hashinfo.ehash_size &&
empty_bucket(st))
;
+
+ st->sbucket = st->num;
+
if (st->bucket >= tcp_hashinfo.ehash_size)
return NULL;
@@ -2107,6 +2118,7 @@ static void *tcp_get_idx(struct seq_file *seq, loff_t pos)
if (!rc) {
st->state = TCP_SEQ_STATE_ESTABLISHED;
+ st->sbucket = 0;
rc = established_get_idx(seq, pos);
}
@@ -2116,6 +2128,25 @@ static void *tcp_get_idx(struct seq_file *seq, loff_t pos)
static void *tcp_seq_start(struct seq_file *seq, loff_t *pos)
{
struct tcp_iter_state *st = seq->private;
+
+ if (*pos && *pos >= st->sbucket &&
+ (st->state == TCP_SEQ_STATE_ESTABLISHED ||
+ st->state == TCP_SEQ_STATE_TIME_WAIT)) {
+ void *cur;
+ int nskip;
+
+ /* for states estab and tw, st->sbucket is index (*pos) */
+ /* corresponding to the beginning of bucket st->bucket */
+
+ st->num = st->sbucket;
+ /* jump to st->bucket, then skip (*pos - st->sbucket) items */
+ st->state = TCP_SEQ_STATE_ESTABLISHED;
+ cur = established_get_first_after(seq, st->bucket);
+ for (nskip = *pos - st->num; cur && nskip > 0; --nskip)
+ cur = established_get_next(seq, cur);
+ return cur;
+ }
+
st->state = TCP_SEQ_STATE_LISTENING;
st->num = 0;
return *pos ? tcp_get_idx(seq, *pos - 1) : SEQ_START_TOKEN;
--
1.6.5.rc2
^ permalink raw reply related
* Re: [PATCH] /proc/net/tcp, overhead removed
From: Eric Dumazet @ 2009-09-28 22:20 UTC (permalink / raw)
To: Yakov Lerner; +Cc: netdev, Eric Dumazet, David Miller
In-Reply-To: <f36b08ee0909281510y282d621etb4264ecd92cbe8f0@mail.gmail.com>
Yakov Lerner a écrit :
> On Sun, Sep 27, 2009 at 12:53, Eric Dumazet <eric.dumazet@gmail.com> wrote:
>> Yakov Lerner a écrit :
>>> /proc/net/tcp does 20,000 sockets in 60-80 milliseconds, with this patch.
>>>
>>> The overhead was in tcp_seq_start(). See analysis (3) below.
>>> The patch is against Linus git tree (1). The patch is small.
>>>
>>> ------------ ----------- ------------------------------------
>>> Before patch After patch 20,000 sockets (10,000 tw + 10,000 estab)(2)
>>> ------------ ----------- ------------------------------------
>>> 6 sec 0.06 sec dd bs=1k if=/proc/net/tcp >/dev/null
>>> 1.5 sec 0.06 sec dd bs=4k if=/proc/net/tcp >/dev/null
>>>
>>> 1.9 sec 0.16 sec netstat -4ant >/dev/null
>>> ------------ ----------- ------------------------------------
>>>
>>> This is ~ x25 improvement.
>>> The new time is not dependent on read blockize.
>>> Speed of netstat, naturally, improves, too; both -4 and -6.
>>> /proc/net/tcp6 does 20,000 sockets in 100 millisec.
>>>
>>> (1) against git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git
>>>
>>> (2) Used 'manysock' utility to stress system with large number of sockets:
>>> "manysock 10000 10000" - 10,000 tw + 10,000 estab ip4 sockets.
>>> "manysock -6 10000 10000" - 10,000 tw + 10,000 estab ip6 sockets.
>>> Found at http://ilerner.3b1.org/manysock/manysock.c
>>>
>>> (3) Algorithmic analysis.
>>> Old algorithm.
>>>
>>> During 'cat </proc/net/tcp', tcp_seq_start() is called O(numsockets) times (4).
>>> On average, every call to tcp_seq_start() scans half the whole hashtable. Ouch.
>>> This is O(numsockets * hashsize). 95-99% of 'cat </proc/net/tcp' is spent in
>>> tcp_seq_start()->tcp_get_idx. This overhead is eliminated by new algorithm,
>>> which is O(numsockets + hashsize).
>>>
>>> New algorithm.
>>>
>>> New algorithms is O(numsockets + hashsize). We jump to the right
>>> hash bucket in tcp_seq_start(), without scanning half the hash.
>>> To jump right to the hash bucket corresponding to *pos in tcp_seq_start(),
>>> we reuse three pieces of state (st->num, st->bucket, st->sbucket)
>>> as follows:
>>> - we check that requested pos >= last seen pos (st->num), the typical case.
>>> - if so, we jump to bucket st->bucket
>>> - to arrive to the right item after beginning of st->bucket, we
>>> keep in st->sbucket the position corresponding to the beginning of
>>> bucket.
>>>
>>> (4) Explanation of O( numsockets * hashsize) of old algorithm.
>>>
>>> tcp_seq_start() is called once for every ~7 lines of netstat output
>>> if readsize is 1kb, or once for every ~28 lines if readsize >= 4kb.
>>> Since record length of /proc/net/tcp records is 150 bytes, formula for
>>> number of calls to tcp_seq_start() is
>>> (numsockets * 150 / min(4096,readsize)).
>>> Netstat uses 4kb readsize (newer versions), or 1kb (older versions).
>>> Note that speed of old algorithm does not improve above 4kb blocksize.
>>>
>>> Speed of the new algorithm does not depend on blocksize.
>>>
>>> Speed of the new algorithm does not perceptibly depend on hashsize (which
>>> depends on ramsize). Speed of old algorithm drops with bigger hashsize.
>>>
>>> (5) Reporting order.
>>>
>>> Reporting order is exactly same as before if hash does not change underfoot.
>>> When hash elements come and go during report, reporting order will be
>>> same as that of tcpdiag.
>>>
>>> Signed-off-by: Yakov Lerner <iler.ml@gmail.com>
>>> ---
>>> net/ipv4/tcp_ipv4.c | 26 ++++++++++++++++++++++++--
>>> 1 files changed, 24 insertions(+), 2 deletions(-)
>>>
>>> diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
>>> index 7cda24b..7d9421a 100644
>>> --- a/net/ipv4/tcp_ipv4.c
>>> +++ b/net/ipv4/tcp_ipv4.c
>>> @@ -1994,13 +1994,14 @@ static inline int empty_bucket(struct tcp_iter_state *st)
>>> hlist_nulls_empty(&tcp_hashinfo.ehash[st->bucket].twchain);
>>> }
>>>
>>> -static void *established_get_first(struct seq_file *seq)
>>> +static void *established_get_first_after(struct seq_file *seq, int bucket)
>>> {
>>> struct tcp_iter_state *st = seq->private;
>>> struct net *net = seq_file_net(seq);
>>> void *rc = NULL;
>>>
>>> - for (st->bucket = 0; st->bucket < tcp_hashinfo.ehash_size; ++st->bucket) {
>>> + for (st->bucket = bucket; st->bucket < tcp_hashinfo.ehash_size;
>>> + ++st->bucket) {
>>> struct sock *sk;
>>> struct hlist_nulls_node *node;
>>> struct inet_timewait_sock *tw;
>>> @@ -2036,6 +2037,11 @@ out:
>>> return rc;
>>> }
>>>
>>> +static void *established_get_first(struct seq_file *seq)
>>> +{
>>> + return established_get_first_after(seq, 0);
>>> +}
>>> +
>>> static void *established_get_next(struct seq_file *seq, void *cur)
>>> {
>>> struct sock *sk = cur;
>>> @@ -2045,6 +2051,7 @@ static void *established_get_next(struct seq_file *seq, void *cur)
>>> struct net *net = seq_file_net(seq);
>>>
>>> ++st->num;
>>> + st->sbucket = st->num;
>> Hello Yakov
>>
>> Intention of your patch is very good, but not currently working.
>>
>> It seems you believe there is at most one entry per hash slot or something like that
>>
>> Please reboot your test machine with "thash_entries=4096" so that tcp hash
>> size is 4096, and try to fill 20000 tcp sockets with a test program.
>>
>> then :
>>
>> # ss | wc -l
>> 20001
>> (ok)
>>
>> # cat /proc/net/tcp | wc -l
>> 22160
>> (not quite correct ...)
>>
>> # netstat -tn | wc -l
>> <never ends>
>>
>>
>> # dd if=/proc/net/tcp ibs=1024 | wc -l
>> <never ends>
>>
>>
>> Please send your next patch on netdev@vger.kernel.org , DaveM only , were netdev people
>> are reviewing netdev patches, there is no need include other people for first submissions.
>>
>> Thank you
>>
>>
>> #include <sys/types.h>
>> #include <sys/socket.h>
>> #include <netinet/in.h>
>> #include <string.h>
>> int fdlisten;
>> main()
>> {
>> int i;
>> struct sockaddr_in sockaddr;
>>
>> fdlisten = socket(AF_INET, SOCK_STREAM, 0);
>> memset(&sockaddr, 0, sizeof(sockaddr));
>> sockaddr.sin_family = AF_INET;
>> sockaddr.sin_port = htons(2222);
>> if (bind(fdlisten, (struct sockaddr *)&sockaddr, sizeof(sockaddr))== -1) {
>> perror("bind");
>> return 1;
>> }
>> if (listen(fdlisten, 10)== -1) {
>> perror("listen");
>> return 1;
>> }
>> if (fork() == 0) {
>> while (1) {
>> socklen_t len = sizeof(sockaddr);
>> int newfd = accept(fdlisten, (struct sockaddr *)&sockaddr, &len);
>> }
>> }
>> for (i = 0 ; i < 10000; i++) {
>> int fd = socket(AF_INET, SOCK_STREAM, 0);
>> if (fd == -1) {
>> perror("socket");
>> break;
>> }
>> connect(fd, (struct sockaddr *)&sockaddr, sizeof(sockaddr));
>> }
>> pause();
>> }
>>
>
> Hello Eric,
>
> I found the problem, thanks. I'll re-send after testing.
OK good !
>
> In the meantime, I'd like to ask you whether it makes sense to
> add the /proc/net entry, to switch between "old way" and "new way".
> The switch would allow quick compare/test between new way and
> old way not only by line count, but by full contents, without reboot.
>
Well, this switch wont be needed for patch validation, but it might help
you to test your patch of course.
Actually I found the error reading your patch, and I made a quick test to
confirm my understanding :)
See you tomorrow, its rather late here :)
^ permalink raw reply
* Re: [PATCH] /proc/net/tcp, overhead removed
From: Yakov Lerner @ 2009-09-28 22:10 UTC (permalink / raw)
To: netdev, Eric Dumazet, David Miller
In-Reply-To: <4ABF360E.7080301@gmail.com>
On Sun, Sep 27, 2009 at 12:53, Eric Dumazet <eric.dumazet@gmail.com> wrote:
> Yakov Lerner a écrit :
>> /proc/net/tcp does 20,000 sockets in 60-80 milliseconds, with this patch.
>>
>> The overhead was in tcp_seq_start(). See analysis (3) below.
>> The patch is against Linus git tree (1). The patch is small.
>>
>> ------------ ----------- ------------------------------------
>> Before patch After patch 20,000 sockets (10,000 tw + 10,000 estab)(2)
>> ------------ ----------- ------------------------------------
>> 6 sec 0.06 sec dd bs=1k if=/proc/net/tcp >/dev/null
>> 1.5 sec 0.06 sec dd bs=4k if=/proc/net/tcp >/dev/null
>>
>> 1.9 sec 0.16 sec netstat -4ant >/dev/null
>> ------------ ----------- ------------------------------------
>>
>> This is ~ x25 improvement.
>> The new time is not dependent on read blockize.
>> Speed of netstat, naturally, improves, too; both -4 and -6.
>> /proc/net/tcp6 does 20,000 sockets in 100 millisec.
>>
>> (1) against git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git
>>
>> (2) Used 'manysock' utility to stress system with large number of sockets:
>> "manysock 10000 10000" - 10,000 tw + 10,000 estab ip4 sockets.
>> "manysock -6 10000 10000" - 10,000 tw + 10,000 estab ip6 sockets.
>> Found at http://ilerner.3b1.org/manysock/manysock.c
>>
>> (3) Algorithmic analysis.
>> Old algorithm.
>>
>> During 'cat </proc/net/tcp', tcp_seq_start() is called O(numsockets) times (4).
>> On average, every call to tcp_seq_start() scans half the whole hashtable. Ouch.
>> This is O(numsockets * hashsize). 95-99% of 'cat </proc/net/tcp' is spent in
>> tcp_seq_start()->tcp_get_idx. This overhead is eliminated by new algorithm,
>> which is O(numsockets + hashsize).
>>
>> New algorithm.
>>
>> New algorithms is O(numsockets + hashsize). We jump to the right
>> hash bucket in tcp_seq_start(), without scanning half the hash.
>> To jump right to the hash bucket corresponding to *pos in tcp_seq_start(),
>> we reuse three pieces of state (st->num, st->bucket, st->sbucket)
>> as follows:
>> - we check that requested pos >= last seen pos (st->num), the typical case.
>> - if so, we jump to bucket st->bucket
>> - to arrive to the right item after beginning of st->bucket, we
>> keep in st->sbucket the position corresponding to the beginning of
>> bucket.
>>
>> (4) Explanation of O( numsockets * hashsize) of old algorithm.
>>
>> tcp_seq_start() is called once for every ~7 lines of netstat output
>> if readsize is 1kb, or once for every ~28 lines if readsize >= 4kb.
>> Since record length of /proc/net/tcp records is 150 bytes, formula for
>> number of calls to tcp_seq_start() is
>> (numsockets * 150 / min(4096,readsize)).
>> Netstat uses 4kb readsize (newer versions), or 1kb (older versions).
>> Note that speed of old algorithm does not improve above 4kb blocksize.
>>
>> Speed of the new algorithm does not depend on blocksize.
>>
>> Speed of the new algorithm does not perceptibly depend on hashsize (which
>> depends on ramsize). Speed of old algorithm drops with bigger hashsize.
>>
>> (5) Reporting order.
>>
>> Reporting order is exactly same as before if hash does not change underfoot.
>> When hash elements come and go during report, reporting order will be
>> same as that of tcpdiag.
>>
>> Signed-off-by: Yakov Lerner <iler.ml@gmail.com>
>> ---
>> net/ipv4/tcp_ipv4.c | 26 ++++++++++++++++++++++++--
>> 1 files changed, 24 insertions(+), 2 deletions(-)
>>
>> diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
>> index 7cda24b..7d9421a 100644
>> --- a/net/ipv4/tcp_ipv4.c
>> +++ b/net/ipv4/tcp_ipv4.c
>> @@ -1994,13 +1994,14 @@ static inline int empty_bucket(struct tcp_iter_state *st)
>> hlist_nulls_empty(&tcp_hashinfo.ehash[st->bucket].twchain);
>> }
>>
>> -static void *established_get_first(struct seq_file *seq)
>> +static void *established_get_first_after(struct seq_file *seq, int bucket)
>> {
>> struct tcp_iter_state *st = seq->private;
>> struct net *net = seq_file_net(seq);
>> void *rc = NULL;
>>
>> - for (st->bucket = 0; st->bucket < tcp_hashinfo.ehash_size; ++st->bucket) {
>> + for (st->bucket = bucket; st->bucket < tcp_hashinfo.ehash_size;
>> + ++st->bucket) {
>> struct sock *sk;
>> struct hlist_nulls_node *node;
>> struct inet_timewait_sock *tw;
>> @@ -2036,6 +2037,11 @@ out:
>> return rc;
>> }
>>
>> +static void *established_get_first(struct seq_file *seq)
>> +{
>> + return established_get_first_after(seq, 0);
>> +}
>> +
>> static void *established_get_next(struct seq_file *seq, void *cur)
>> {
>> struct sock *sk = cur;
>> @@ -2045,6 +2051,7 @@ static void *established_get_next(struct seq_file *seq, void *cur)
>> struct net *net = seq_file_net(seq);
>>
>> ++st->num;
>> + st->sbucket = st->num;
>
> Hello Yakov
>
> Intention of your patch is very good, but not currently working.
>
> It seems you believe there is at most one entry per hash slot or something like that
>
> Please reboot your test machine with "thash_entries=4096" so that tcp hash
> size is 4096, and try to fill 20000 tcp sockets with a test program.
>
> then :
>
> # ss | wc -l
> 20001
> (ok)
>
> # cat /proc/net/tcp | wc -l
> 22160
> (not quite correct ...)
>
> # netstat -tn | wc -l
> <never ends>
>
>
> # dd if=/proc/net/tcp ibs=1024 | wc -l
> <never ends>
>
>
> Please send your next patch on netdev@vger.kernel.org , DaveM only , were netdev people
> are reviewing netdev patches, there is no need include other people for first submissions.
>
> Thank you
>
>
> #include <sys/types.h>
> #include <sys/socket.h>
> #include <netinet/in.h>
> #include <string.h>
> int fdlisten;
> main()
> {
> int i;
> struct sockaddr_in sockaddr;
>
> fdlisten = socket(AF_INET, SOCK_STREAM, 0);
> memset(&sockaddr, 0, sizeof(sockaddr));
> sockaddr.sin_family = AF_INET;
> sockaddr.sin_port = htons(2222);
> if (bind(fdlisten, (struct sockaddr *)&sockaddr, sizeof(sockaddr))== -1) {
> perror("bind");
> return 1;
> }
> if (listen(fdlisten, 10)== -1) {
> perror("listen");
> return 1;
> }
> if (fork() == 0) {
> while (1) {
> socklen_t len = sizeof(sockaddr);
> int newfd = accept(fdlisten, (struct sockaddr *)&sockaddr, &len);
> }
> }
> for (i = 0 ; i < 10000; i++) {
> int fd = socket(AF_INET, SOCK_STREAM, 0);
> if (fd == -1) {
> perror("socket");
> break;
> }
> connect(fd, (struct sockaddr *)&sockaddr, sizeof(sockaddr));
> }
> pause();
> }
>
Hello Eric,
I found the problem, thanks. I'll re-send after testing.
In the meantime, I'd like to ask you whether it makes sense to
add the /proc/net entry, to switch between "old way" and "new way".
The switch would allow quick compare/test between new way and
old way not only by line count, but by full contents, without reboot.
Yakov
^ permalink raw reply
* Re: [PATCH 2/4 v3] bonding: make sure tx and rx hash tables stay in sync when using alb mode
From: Jay Vosburgh @ 2009-09-28 22:09 UTC (permalink / raw)
To: Andy Gospodarek; +Cc: netdev, bonding-devel
In-Reply-To: <20090928220020.GC4436@gospo.rdu.redhat.com>
Andy Gospodarek <andy@greyhouse.net> wrote:
>On Fri, Sep 18, 2009 at 11:56:45AM -0400, Andy Gospodarek wrote:
>> On Fri, Sep 18, 2009 at 11:36:22AM -0400, Andy Gospodarek wrote:
>> > On Wed, Sep 16, 2009 at 04:36:09PM -0700, Jay Vosburgh wrote:
>> > > Andy Gospodarek <andy@greyhouse.net> wrote:
>> > >
>> > > >
>> > > >Subject: [PATCH] bonding: make sure tx and rx hash tables stay in sync when using alb mode
>> > >
>> > > When testing this, I'm getting a lockdep warning. It appears to
>> > > be unhappy that tlb_choose_channel acquires the tx / rx hash table locks
>> > > in the order tx then rx, but rlb_choose_channel -> alb_get_best_slave
>> > > acquires the locks in the other order. I applied all four patches, but
>> > > it looks like the change that trips lockdep is in this patch (#2).
>> > >
>> > > I haven't gotten an actual deadlock from this, although it seems
>> > > plausible if there are two cpus in bond_alb_xmit at the same time, and
>> > > one of them is sending an ARP.
>> > >
>> > > One fairly straightforward fix would be to combine the rx and tx
>> > > hash table locks into a single lock. I suspect that wouldn't have any
>> > > real performance penalty, since the rx hash table lock is generally not
>> > > acquired very often (unlike the tx lock, which is taken for every packet
>> > > that goes out).
>> > >
>> > > Also, FYI, two of the four patches had trailing whitespace. I
>> > > believe it was #2 and #4.
>> > >
>> > > Thoughts?
>> >
>> > Jay,
>> >
>> > This patch should address both the the deadlock and whitespace conerns.
>> > I ran a kernel with LOCKDEP enabled and saw no warnings while passing
>> > traffic on the bond while pulling cables and while removing the module.
>> > Here it is....
>> >
>>
>> Adding the version and signed-off-by lines might be nice, eh?
>>
>> [PATCH v3] bonding: make sure tx and rx hash tables stay in sync when using alb mode
>>
>> I noticed that it was easy for alb (mode 6) bonding to get into a state
>> where the tx hash-table and rx hash-table are out of sync (there is
>> really nothing to keep them synchronized), and we will transmit traffic
>> destined for a host on one slave and send ARP frames to the same slave
>> from another interface using a different source MAC.
>>
>> There is no compelling reason to do this, so this patch makes sure the
>> rx hash-table changes whenever the tx hash-table is updated based on
>> device load. This patch also drops the code that does rlb re-balancing
>> since the balancing will not be controlled by the tx hash-table based on
In addition to my response in the other thread, I changed the
"not" above to "now," which I suspect is what you meant.
>> transmit load. In order to address an issue found with the initial
>> patch, I have also combined the rx and tx hash table lock into a single
>> lock. This will facilitate moving these into a single table at some
>> point.
>>
>> Signed-off-by: Andy Gospodarek <andy@greyhouse.net>
>>
>> ---
>> drivers/net/bonding/bond_alb.c | 203 +++++++++++++++-------------------------
>> drivers/net/bonding/bond_alb.h | 3 +-
>> 2 files changed, 75 insertions(+), 131 deletions(-)
>>
>> diff --git a/drivers/net/bonding/bond_alb.c b/drivers/net/bonding/bond_alb.c
>> index bcf25c6..04b7055 100644
>> --- a/drivers/net/bonding/bond_alb.c
>> +++ b/drivers/net/bonding/bond_alb.c
>> @@ -111,6 +111,7 @@ static inline struct arp_pkt *arp_pkt(const struct sk_buff *skb)
>>
>> /* Forward declaration */
>> static void alb_send_learning_packets(struct slave *slave, u8 mac_addr[]);
>> +static struct slave *alb_get_best_slave(struct bonding *bond, u32 hash_index);
>>
>> static inline u8 _simple_hash(const u8 *hash_start, int hash_size)
>> {
>> @@ -124,18 +125,18 @@ static inline u8 _simple_hash(const u8 *hash_start, int hash_size)
>> return hash;
>> }
>>
>> -/*********************** tlb specific functions ***************************/
>> -
>> -static inline void _lock_tx_hashtbl(struct bonding *bond)
>> +/********************* hash table lock functions *************************/
>> +static inline void _lock_hashtbl(struct bonding *bond)
>> {
>> - spin_lock_bh(&(BOND_ALB_INFO(bond).tx_hashtbl_lock));
>> + spin_lock_bh(&(BOND_ALB_INFO(bond).hashtbl_lock));
>> }
>>
>> -static inline void _unlock_tx_hashtbl(struct bonding *bond)
>> +static inline void _unlock_hashtbl(struct bonding *bond)
>> {
>> - spin_unlock_bh(&(BOND_ALB_INFO(bond).tx_hashtbl_lock));
>> + spin_unlock_bh(&(BOND_ALB_INFO(bond).hashtbl_lock));
>> }
>>
>> +/*********************** tlb specific functions ***************************/
>> /* Caller must hold tx_hashtbl lock */
>> static inline void tlb_init_table_entry(struct tlb_client_info *entry, int save_load)
>> {
>> @@ -163,7 +164,7 @@ static void tlb_clear_slave(struct bonding *bond, struct slave *slave, int save_
>> struct tlb_client_info *tx_hash_table;
>> u32 index;
>>
>> - _lock_tx_hashtbl(bond);
>> + _lock_hashtbl(bond);
>>
>> /* clear slave from tx_hashtbl */
>> tx_hash_table = BOND_ALB_INFO(bond).tx_hashtbl;
>> @@ -180,7 +181,7 @@ static void tlb_clear_slave(struct bonding *bond, struct slave *slave, int save_
>>
>> tlb_init_slave(slave);
>>
>> - _unlock_tx_hashtbl(bond);
>> + _unlock_hashtbl(bond);
>> }
>>
>> /* Must be called before starting the monitor timer */
>> @@ -191,7 +192,7 @@ static int tlb_initialize(struct bonding *bond)
>> struct tlb_client_info *new_hashtbl;
>> int i;
>>
>> - spin_lock_init(&(bond_info->tx_hashtbl_lock));
>> + spin_lock_init(&(bond_info->hashtbl_lock));
>>
>> new_hashtbl = kzalloc(size, GFP_KERNEL);
>> if (!new_hashtbl) {
>> @@ -200,7 +201,7 @@ static int tlb_initialize(struct bonding *bond)
>> bond->dev->name);
>> return -1;
>> }
>> - _lock_tx_hashtbl(bond);
>> + _lock_hashtbl(bond);
>>
>> bond_info->tx_hashtbl = new_hashtbl;
>>
>> @@ -208,7 +209,7 @@ static int tlb_initialize(struct bonding *bond)
>> tlb_init_table_entry(&bond_info->tx_hashtbl[i], 1);
>> }
>>
>> - _unlock_tx_hashtbl(bond);
>> + _unlock_hashtbl(bond);
>>
>> return 0;
>> }
>> @@ -218,12 +219,12 @@ static void tlb_deinitialize(struct bonding *bond)
>> {
>> struct alb_bond_info *bond_info = &(BOND_ALB_INFO(bond));
>>
>> - _lock_tx_hashtbl(bond);
>> + _lock_hashtbl(bond);
>>
>> kfree(bond_info->tx_hashtbl);
>> bond_info->tx_hashtbl = NULL;
>>
>> - _unlock_tx_hashtbl(bond);
>> + _unlock_hashtbl(bond);
>> }
>>
>> /* Caller must hold bond lock for read */
>> @@ -264,24 +265,6 @@ static struct slave *tlb_get_least_loaded_slave(struct bonding *bond)
>> return least_loaded;
>> }
>>
>> -/* Caller must hold bond lock for read and hashtbl lock */
>> -static struct slave *tlb_get_best_slave(struct bonding *bond, u32 hash_index)
>> -{
>> - struct alb_bond_info *bond_info = &(BOND_ALB_INFO(bond));
>> - struct tlb_client_info *tx_hash_table = bond_info->tx_hashtbl;
>> - struct slave *last_slave = tx_hash_table[hash_index].last_slave;
>> - struct slave *next_slave = NULL;
>> -
>> - if (last_slave && SLAVE_IS_OK(last_slave)) {
>> - /* Use the last slave listed in the tx hashtbl if:
>> - the last slave currently is essentially unloaded. */
>> - if (SLAVE_TLB_INFO(last_slave).load < 10)
>> - next_slave = last_slave;
>> - }
>> -
>> - return next_slave ? next_slave : tlb_get_least_loaded_slave(bond);
>> -}
>> -
>> /* Caller must hold bond lock for read */
>> static struct slave *tlb_choose_channel(struct bonding *bond, u32 hash_index, u32 skb_len)
>> {
>> @@ -289,13 +272,12 @@ static struct slave *tlb_choose_channel(struct bonding *bond, u32 hash_index, u3
>> struct tlb_client_info *hash_table;
>> struct slave *assigned_slave;
>>
>> - _lock_tx_hashtbl(bond);
>> + _lock_hashtbl(bond);
>>
>> hash_table = bond_info->tx_hashtbl;
>> assigned_slave = hash_table[hash_index].tx_slave;
>> if (!assigned_slave) {
>> - assigned_slave = tlb_get_best_slave(bond, hash_index);
>> -
>> + assigned_slave = alb_get_best_slave(bond, hash_index);
>> if (assigned_slave) {
>> struct tlb_slave_info *slave_info =
>> &(SLAVE_TLB_INFO(assigned_slave));
>> @@ -319,20 +301,52 @@ static struct slave *tlb_choose_channel(struct bonding *bond, u32 hash_index, u3
>> hash_table[hash_index].tx_bytes += skb_len;
>> }
>>
>> - _unlock_tx_hashtbl(bond);
>> + _unlock_hashtbl(bond);
>>
>> return assigned_slave;
>> }
>>
>> /*********************** rlb specific functions ***************************/
>> -static inline void _lock_rx_hashtbl(struct bonding *bond)
>> +
>> +/* Caller must hold bond lock for read and hashtbl lock */
>> +static struct slave *rlb_update_rx_table(struct bonding *bond, struct slave *next_slave, u32 hash_index)
>> {
>> - spin_lock_bh(&(BOND_ALB_INFO(bond).rx_hashtbl_lock));
>> + struct alb_bond_info *bond_info = &(BOND_ALB_INFO(bond));
>> +
>> + /* check rlb table and correct it if wrong */
>> + if (bond_info->rlb_enabled) {
>> + struct rlb_client_info *rx_client_info = &(bond_info->rx_hashtbl[hash_index]);
>> +
>> + /* if the new slave computed by tlb checks doesn't match rlb, stop rlb from using it */
>> + if (next_slave && (next_slave != rx_client_info->slave))
>> + rx_client_info->slave = next_slave;
>> + }
>> + return next_slave;
>> }
>>
>> -static inline void _unlock_rx_hashtbl(struct bonding *bond)
>> +/* Caller must hold bond lock for read and hashtbl lock */
>> +static struct slave *alb_get_best_slave(struct bonding *bond, u32 hash_index)
>> {
>> - spin_unlock_bh(&(BOND_ALB_INFO(bond).rx_hashtbl_lock));
>> + struct alb_bond_info *bond_info = &(BOND_ALB_INFO(bond));
>> + struct tlb_client_info *tx_hash_table = bond_info->tx_hashtbl;
>> + struct slave *last_slave = tx_hash_table[hash_index].last_slave;
>> + struct slave *next_slave = NULL;
>> +
>> + /* presume the next slave will be the least loaded one */
>> + next_slave = tlb_get_least_loaded_slave(bond);
>> +
>> + if (last_slave && SLAVE_IS_OK(last_slave)) {
>> + /* Use the last slave listed in the tx hashtbl if:
>> + the last slave currently is essentially unloaded. */
>> + if (SLAVE_TLB_INFO(last_slave).load < 10)
>> + next_slave = last_slave;
>> + }
>> +
>> + /* update the rlb hashtbl if there was a previous entry */
>> + if (bond_info->rlb_enabled)
>> + rlb_update_rx_table(bond, next_slave, hash_index);
>> +
>> + return next_slave;
>> }
>>
>> /* when an ARP REPLY is received from a client update its info
>> @@ -344,7 +358,7 @@ static void rlb_update_entry_from_arp(struct bonding *bond, struct arp_pkt *arp)
>> struct rlb_client_info *client_info;
>> u32 hash_index;
>>
>> - _lock_rx_hashtbl(bond);
>> + _lock_hashtbl(bond);
>>
>> hash_index = _simple_hash((u8*)&(arp->ip_src), sizeof(arp->ip_src));
>> client_info = &(bond_info->rx_hashtbl[hash_index]);
>> @@ -358,7 +372,7 @@ static void rlb_update_entry_from_arp(struct bonding *bond, struct arp_pkt *arp)
>> bond_info->rx_ntt = 1;
>> }
>>
>> - _unlock_rx_hashtbl(bond);
>> + _unlock_hashtbl(bond);
>> }
>>
>> static int rlb_arp_recv(struct sk_buff *skb, struct net_device *bond_dev, struct packet_type *ptype, struct net_device *orig_dev)
>> @@ -402,38 +416,6 @@ out:
>> return res;
>> }
>>
>> -/* Caller must hold bond lock for read */
>> -static struct slave *rlb_next_rx_slave(struct bonding *bond)
>> -{
>> - struct alb_bond_info *bond_info = &(BOND_ALB_INFO(bond));
>> - struct slave *rx_slave, *slave, *start_at;
>> - int i = 0;
>> -
>> - if (bond_info->next_rx_slave) {
>> - start_at = bond_info->next_rx_slave;
>> - } else {
>> - start_at = bond->first_slave;
>> - }
>> -
>> - rx_slave = NULL;
>> -
>> - bond_for_each_slave_from(bond, slave, i, start_at) {
>> - if (SLAVE_IS_OK(slave)) {
>> - if (!rx_slave) {
>> - rx_slave = slave;
>> - } else if (slave->speed > rx_slave->speed) {
>> - rx_slave = slave;
>> - }
>> - }
>> - }
>> -
>> - if (rx_slave) {
>> - bond_info->next_rx_slave = rx_slave->next;
>> - }
>> -
>> - return rx_slave;
>> -}
>> -
>> /* teach the switch the mac of a disabled slave
>> * on the primary for fault tolerance
>> *
>> @@ -468,14 +450,14 @@ static void rlb_clear_slave(struct bonding *bond, struct slave *slave)
>> u32 index, next_index;
>>
>> /* clear slave from rx_hashtbl */
>> - _lock_rx_hashtbl(bond);
>> + _lock_hashtbl(bond);
>>
>> rx_hash_table = bond_info->rx_hashtbl;
>> index = bond_info->rx_hashtbl_head;
>> for (; index != RLB_NULL_INDEX; index = next_index) {
>> next_index = rx_hash_table[index].next;
>> if (rx_hash_table[index].slave == slave) {
>> - struct slave *assigned_slave = rlb_next_rx_slave(bond);
>> + struct slave *assigned_slave = alb_get_best_slave(bond, index);
>>
>> if (assigned_slave) {
>> rx_hash_table[index].slave = assigned_slave;
>> @@ -499,7 +481,7 @@ static void rlb_clear_slave(struct bonding *bond, struct slave *slave)
>> }
>> }
>>
>> - _unlock_rx_hashtbl(bond);
>> + _unlock_hashtbl(bond);
>>
>> write_lock_bh(&bond->curr_slave_lock);
>>
>> @@ -558,7 +540,7 @@ static void rlb_update_rx_clients(struct bonding *bond)
>> struct rlb_client_info *client_info;
>> u32 hash_index;
>>
>> - _lock_rx_hashtbl(bond);
>> + _lock_hashtbl(bond);
>>
>> hash_index = bond_info->rx_hashtbl_head;
>> for (; hash_index != RLB_NULL_INDEX; hash_index = client_info->next) {
>> @@ -576,7 +558,7 @@ static void rlb_update_rx_clients(struct bonding *bond)
>> */
>> bond_info->rlb_update_delay_counter = RLB_UPDATE_DELAY;
>>
>> - _unlock_rx_hashtbl(bond);
>> + _unlock_hashtbl(bond);
>> }
>>
>> /* The slave was assigned a new mac address - update the clients */
>> @@ -587,7 +569,7 @@ static void rlb_req_update_slave_clients(struct bonding *bond, struct slave *sla
>> int ntt = 0;
>> u32 hash_index;
>>
>> - _lock_rx_hashtbl(bond);
>> + _lock_hashtbl(bond);
>>
>> hash_index = bond_info->rx_hashtbl_head;
>> for (; hash_index != RLB_NULL_INDEX; hash_index = client_info->next) {
>> @@ -607,7 +589,7 @@ static void rlb_req_update_slave_clients(struct bonding *bond, struct slave *sla
>> bond_info->rlb_update_retry_counter = RLB_UPDATE_RETRY;
>> }
>>
>> - _unlock_rx_hashtbl(bond);
>> + _unlock_hashtbl(bond);
>> }
>>
>> /* mark all clients using src_ip to be updated */
>> @@ -617,7 +599,7 @@ static void rlb_req_update_subnet_clients(struct bonding *bond, __be32 src_ip)
>> struct rlb_client_info *client_info;
>> u32 hash_index;
>>
>> - _lock_rx_hashtbl(bond);
>> + _lock_hashtbl(bond);
>>
>> hash_index = bond_info->rx_hashtbl_head;
>> for (; hash_index != RLB_NULL_INDEX; hash_index = client_info->next) {
>> @@ -643,7 +625,7 @@ static void rlb_req_update_subnet_clients(struct bonding *bond, __be32 src_ip)
>> }
>> }
>>
>> - _unlock_rx_hashtbl(bond);
>> + _unlock_hashtbl(bond);
>> }
>>
>> /* Caller must hold both bond and ptr locks for read */
>> @@ -655,7 +637,7 @@ static struct slave *rlb_choose_channel(struct sk_buff *skb, struct bonding *bon
>> struct rlb_client_info *client_info;
>> u32 hash_index = 0;
>>
>> - _lock_rx_hashtbl(bond);
>> + _lock_hashtbl(bond);
>>
>> hash_index = _simple_hash((u8 *)&arp->ip_dst, sizeof(arp->ip_src));
>> client_info = &(bond_info->rx_hashtbl[hash_index]);
>> @@ -671,7 +653,7 @@ static struct slave *rlb_choose_channel(struct sk_buff *skb, struct bonding *bon
>>
>> assigned_slave = client_info->slave;
>> if (assigned_slave) {
>> - _unlock_rx_hashtbl(bond);
>> + _unlock_hashtbl(bond);
>> return assigned_slave;
>> }
>> } else {
>> @@ -687,7 +669,7 @@ static struct slave *rlb_choose_channel(struct sk_buff *skb, struct bonding *bon
>> }
>> }
>> /* assign a new slave */
>> - assigned_slave = rlb_next_rx_slave(bond);
>> + assigned_slave = alb_get_best_slave(bond, hash_index);
>>
>> if (assigned_slave) {
>> client_info->ip_src = arp->ip_src;
>> @@ -723,7 +705,7 @@ static struct slave *rlb_choose_channel(struct sk_buff *skb, struct bonding *bon
>> }
>> }
>>
>> - _unlock_rx_hashtbl(bond);
>> + _unlock_hashtbl(bond);
>>
>> return assigned_slave;
>> }
>> @@ -771,36 +753,6 @@ static struct slave *rlb_arp_xmit(struct sk_buff *skb, struct bonding *bond)
>> return tx_slave;
>> }
>>
>> -/* Caller must hold bond lock for read */
>> -static void rlb_rebalance(struct bonding *bond)
>> -{
>> - struct alb_bond_info *bond_info = &(BOND_ALB_INFO(bond));
>> - struct slave *assigned_slave;
>> - struct rlb_client_info *client_info;
>> - int ntt;
>> - u32 hash_index;
>> -
>> - _lock_rx_hashtbl(bond);
>> -
>> - ntt = 0;
>> - hash_index = bond_info->rx_hashtbl_head;
>> - for (; hash_index != RLB_NULL_INDEX; hash_index = client_info->next) {
>> - client_info = &(bond_info->rx_hashtbl[hash_index]);
>> - assigned_slave = rlb_next_rx_slave(bond);
>> - if (assigned_slave && (client_info->slave != assigned_slave)) {
>> - client_info->slave = assigned_slave;
>> - client_info->ntt = 1;
>> - ntt = 1;
>> - }
>> - }
>> -
>> - /* update the team's flag only after the whole iteration */
>> - if (ntt) {
>> - bond_info->rx_ntt = 1;
>> - }
>> - _unlock_rx_hashtbl(bond);
>> -}
>> -
>> /* Caller must hold rx_hashtbl lock */
>> static void rlb_init_table_entry(struct rlb_client_info *entry)
>> {
>> @@ -817,8 +769,6 @@ static int rlb_initialize(struct bonding *bond)
>> int size = RLB_HASH_TABLE_SIZE * sizeof(struct rlb_client_info);
>> int i;
>>
>> - spin_lock_init(&(bond_info->rx_hashtbl_lock));
>> -
>> new_hashtbl = kmalloc(size, GFP_KERNEL);
>> if (!new_hashtbl) {
>> printk(KERN_ERR DRV_NAME
>> @@ -826,7 +776,7 @@ static int rlb_initialize(struct bonding *bond)
>> bond->dev->name);
>> return -1;
>> }
>> - _lock_rx_hashtbl(bond);
>> + _lock_hashtbl(bond);
>>
>> bond_info->rx_hashtbl = new_hashtbl;
>>
>> @@ -836,7 +786,7 @@ static int rlb_initialize(struct bonding *bond)
>> rlb_init_table_entry(bond_info->rx_hashtbl + i);
>> }
>>
>> - _unlock_rx_hashtbl(bond);
>> + _unlock_hashtbl(bond);
>>
>> /*initialize packet type*/
>> pk_type->type = cpu_to_be16(ETH_P_ARP);
>> @@ -855,13 +805,13 @@ static void rlb_deinitialize(struct bonding *bond)
>>
>> dev_remove_pack(&(bond_info->rlb_pkt_type));
>>
>> - _lock_rx_hashtbl(bond);
>> + _lock_hashtbl(bond);
>>
>> kfree(bond_info->rx_hashtbl);
>> bond_info->rx_hashtbl = NULL;
>> bond_info->rx_hashtbl_head = RLB_NULL_INDEX;
>>
>> - _unlock_rx_hashtbl(bond);
>> + _unlock_hashtbl(bond);
>> }
>>
>> static void rlb_clear_vlan(struct bonding *bond, unsigned short vlan_id)
>> @@ -869,7 +819,7 @@ static void rlb_clear_vlan(struct bonding *bond, unsigned short vlan_id)
>> struct alb_bond_info *bond_info = &(BOND_ALB_INFO(bond));
>> u32 curr_index;
>>
>> - _lock_rx_hashtbl(bond);
>> + _lock_hashtbl(bond);
>>
>> curr_index = bond_info->rx_hashtbl_head;
>> while (curr_index != RLB_NULL_INDEX) {
>> @@ -894,7 +844,7 @@ static void rlb_clear_vlan(struct bonding *bond, unsigned short vlan_id)
>> curr_index = next_index;
>> }
>>
>> - _unlock_rx_hashtbl(bond);
>> + _unlock_hashtbl(bond);
>> }
>>
>> /*********************** tlb/rlb shared functions *********************/
>> @@ -1521,11 +1471,6 @@ void bond_alb_monitor(struct work_struct *work)
>> read_lock(&bond->lock);
>> }
>>
>> - if (bond_info->rlb_rebalance) {
>> - bond_info->rlb_rebalance = 0;
>> - rlb_rebalance(bond);
>> - }
>> -
>> /* check if clients need updating */
>> if (bond_info->rx_ntt) {
>> if (bond_info->rlb_update_delay_counter) {
>> diff --git a/drivers/net/bonding/bond_alb.h b/drivers/net/bonding/bond_alb.h
>> index b65fd29..09d755a 100644
>> --- a/drivers/net/bonding/bond_alb.h
>> +++ b/drivers/net/bonding/bond_alb.h
>> @@ -90,7 +90,7 @@ struct tlb_slave_info {
>> struct alb_bond_info {
>> struct timer_list alb_timer;
>> struct tlb_client_info *tx_hashtbl; /* Dynamically allocated */
>> - spinlock_t tx_hashtbl_lock;
>> + spinlock_t hashtbl_lock; /* lock for both tables */
>> u32 unbalanced_load;
>> int tx_rebalance_counter;
>> int lp_counter;
>> @@ -98,7 +98,6 @@ struct alb_bond_info {
>> int rlb_enabled;
>> struct packet_type rlb_pkt_type;
>> struct rlb_client_info *rx_hashtbl; /* Receive hash table */
>> - spinlock_t rx_hashtbl_lock;
>> u32 rx_hashtbl_head;
>> u8 rx_ntt; /* flag - need to transmit
>> * to all rx clients
>
>Any thoughts on this, Jay?
-J
---
-Jay Vosburgh, IBM Linux Technology Center, fubar@us.ibm.com
^ permalink raw reply
* Re: [PATCH 4/4 v2] bonding: add sysfs files to display tlb and alb hash table contents
From: Jay Vosburgh @ 2009-09-28 22:06 UTC (permalink / raw)
To: Andy Gospodarek; +Cc: netdev, bonding-devel
In-Reply-To: <20090928220117.GD4436@gospo.rdu.redhat.com>
Andy Gospodarek <andy@greyhouse.net> wrote:
>On Fri, Sep 18, 2009 at 11:53:11AM -0400, Andy Gospodarek wrote:
>> On Fri, Sep 11, 2009 at 05:13:17PM -0400, Andy Gospodarek wrote:
>> >
>> > bonding: add sysfs files to display tlb and alb hash table contents
>> >
>> > While debugging some problems with alb (mode 6) bonding I realized that
>> > being able to output the contents of both hash tables would be helpful.
>> > This is what the output looks like for the two files:
>> >
>> > device load
>> > eth1 491
>> > eth2 491
>> > hash device last device tx bytes load next previous
>> > 2 eth1 eth1 2254 491 0 0
>> > 3 eth2 eth2 2744 491 0 0
>> > 6 eth2 0 488 0 0
>> > 8 eth2 0 461698 0 0
>> > 1b eth2 0 249 0 0
>> > eb eth2 0 21 0 0
>> > ff eth2 0 22 0 0
>> >
>> > hash ip_src ip_dst mac_dst slave assign ntt
>> > 2 10.0.3.2 10.0.3.11 00:e0:81:71:ee:a9 eth1 1 0
>> > 3 10.0.3.2 10.0.3.10 00:e0:81:71:ee:a9 eth2 1 0
>> > 8 10.0.3.2 10.0.3.1 00:e0:81:71:ee:a9 eth2 1 0
>> >
>> > These were a great help debugging the fixes I have just posted and they
>> > might be helpful for others, so I decided to include them in my
>> > patchset.
>> >
>> > Signed-off-by: Andy Gospodarek <andy@greyhouse.net>
>> >
>>
>> Needed to repost since patch 2/4 changed and first patch had whitespace
>> issues:
>>
>> [PATCH v2] bonding: add sysfs files to display tlb and alb hash table contents
>>
>> While debugging some problems with alb (mode 6) bonding I realized that
>> being able to output the contents of both hash tables would be helpful.
>> This is what the output looks like for the two files:
>>
>> device load
>> eth1 491
>> eth2 491
>> hash device last device tx bytes load next previous
>> 2 eth1 eth1 2254 491 0 0
>> 3 eth2 eth2 2744 491 0 0
>> 6 eth2 0 488 0 0
>> 8 eth2 0 461698 0 0
>> 1b eth2 0 249 0 0
>> eb eth2 0 21 0 0
>> ff eth2 0 22 0 0
>>
>> hash ip_src ip_dst mac_dst slave assign ntt
>> 2 10.0.3.2 10.0.3.11 00:e0:81:71:ee:a9 eth1 1 0
>> 3 10.0.3.2 10.0.3.10 00:e0:81:71:ee:a9 eth2 1 0
>> 8 10.0.3.2 10.0.3.1 00:e0:81:71:ee:a9 eth2 1 0
>>
>> These were a great help debugging the fixes I have just posted and they
>> might be helpful for others, so I decided to include them in my post.
>>
>> Signed-off-by: Andy Gospodarek <andy@greyhouse.net>
>>
>> ---
>> drivers/net/bonding/bond_alb.c | 61 ++++++++++++++++++++++++++++++++++++++
>> drivers/net/bonding/bond_alb.h | 2 +
>> drivers/net/bonding/bond_sysfs.c | 40 +++++++++++++++++++++++++
>> 3 files changed, 103 insertions(+), 0 deletions(-)
>>
>> diff --git a/drivers/net/bonding/bond_alb.c b/drivers/net/bonding/bond_alb.c
>> index 5d51489..adc5acd 100644
>> --- a/drivers/net/bonding/bond_alb.c
>> +++ b/drivers/net/bonding/bond_alb.c
>> @@ -750,6 +750,67 @@ static struct slave *rlb_arp_xmit(struct sk_buff *skb, struct bonding *bond)
>> return tx_slave;
>> }
>>
>> +int rlb_print_rx_hashtbl(struct bonding *bond, char *buf)
>> +{
>> + struct alb_bond_info *bond_info = &(BOND_ALB_INFO(bond));
>> + struct rlb_client_info *client_info;
>> + u32 hash_index;
>> + u32 count = 0;
>> +
>> + _lock_hashtbl(bond);
>> +
>> + count = sprintf(buf, "hash ip_src ip_dst mac_dst slave assign ntt\n");
>> + hash_index = bond_info->rx_hashtbl_head;
>> + for (; hash_index != RLB_NULL_INDEX; hash_index = client_info->next) {
>> + client_info = &(bond_info->rx_hashtbl[hash_index]);
>> + count += sprintf(buf + count,"%-4x %-15pi4 %-15pi4 %pM %-5s %-6d %d\n",
>> + hash_index,
>> + &client_info->ip_src,
>> + &client_info->ip_dst,
>> + client_info->mac_dst,
>> + client_info->slave->dev->name,
>> + client_info->assigned,
>> + client_info->ntt);
>> + }
>> +
>> + _unlock_hashtbl(bond);
>> + return count;
>> +}
>> +
>> +int tlb_print_tx_hashtbl(struct bonding *bond, char *buf)
>> +{
>> + struct alb_bond_info *bond_info = &(BOND_ALB_INFO(bond));
>> + u32 hash_index;
>> + u32 count = 0;
>> + struct slave *slave;
>> + int i;
>> +
>> + _lock_hashtbl(bond);
>> +
>> + count += sprintf(buf, "device load\n");
>> + bond_for_each_slave(bond, slave, i) {
>> + struct tlb_slave_info *slave_info = &(SLAVE_TLB_INFO(slave));
>> + count += sprintf(buf + count,"%-7s %d\n",slave->dev->name,slave_info->load);
>> + }
>> + count += sprintf(buf + count, "hash device last device tx bytes load next previous\n");
>> + for (hash_index = 0; hash_index < TLB_HASH_TABLE_SIZE; hash_index++) {
>> + struct tlb_client_info *client_info = &(bond_info->tx_hashtbl[hash_index]);
>> + if (client_info->tx_slave || client_info->last_slave) {
>> + count += sprintf(buf + count,"%-4x %-8s %-13s %-14d %-11d %-4x %d\n",
>> + hash_index,
>> + (client_info->tx_slave) ? client_info->tx_slave->dev->name : "",
>> + (client_info->last_slave) ? client_info->last_slave->dev->name : "",
>> + client_info->tx_bytes,
>> + client_info->load_history,
>> + (client_info->next != TLB_NULL_INDEX) ? client_info->next : 0,
>> + (client_info->prev != TLB_NULL_INDEX) ? client_info->prev : 0);
>> + }
>> + }
>> +
>> + _unlock_hashtbl(bond);
>> + return count;
>> +}
>> +
>> /* Caller must hold rx_hashtbl lock */
>> static void rlb_init_table_entry(struct rlb_client_info *entry)
>> {
>> diff --git a/drivers/net/bonding/bond_alb.h b/drivers/net/bonding/bond_alb.h
>> index 09d755a..57e761b 100644
>> --- a/drivers/net/bonding/bond_alb.h
>> +++ b/drivers/net/bonding/bond_alb.h
>> @@ -131,5 +131,7 @@ int bond_alb_xmit(struct sk_buff *skb, struct net_device *bond_dev);
>> void bond_alb_monitor(struct work_struct *);
>> int bond_alb_set_mac_address(struct net_device *bond_dev, void *addr);
>> void bond_alb_clear_vlan(struct bonding *bond, unsigned short vlan_id);
>> +int rlb_print_rx_hashtbl(struct bonding *bond, char *buf);
>> +int tlb_print_tx_hashtbl(struct bonding *bond, char *buf);
>> #endif /* __BOND_ALB_H__ */
>>
>> diff --git a/drivers/net/bonding/bond_sysfs.c b/drivers/net/bonding/bond_sysfs.c
>> index 55bf34f..1123e1f 100644
>> --- a/drivers/net/bonding/bond_sysfs.c
>> +++ b/drivers/net/bonding/bond_sysfs.c
>> @@ -1480,6 +1480,44 @@ static ssize_t bonding_show_ad_partner_mac(struct device *d,
>> static DEVICE_ATTR(ad_partner_mac, S_IRUGO, bonding_show_ad_partner_mac, NULL);
>>
>>
>> +/*
>> + * Show current tlb/alb tx hash table.
>> + */
>> +static ssize_t bonding_show_tlb_tx_hash(struct device *d,
>> + struct device_attribute *attr,
>> + char *buf)
>> +{
>> + int count = 0;
>> + struct bonding *bond = to_bond(d);
>> +
>> + if (bond->params.mode == BOND_MODE_ALB ||
>> + bond->params.mode == BOND_MODE_TLB) {
>> + count = tlb_print_tx_hashtbl(bond, buf);
>> + }
>> +
>> + return count;
>> +}
>> +static DEVICE_ATTR(tlb_tx_hash, S_IRUGO, bonding_show_tlb_tx_hash, NULL);
>> +
>> +
>> +/*
>> + * Show current alb rx hash table.
>> + */
>> +static ssize_t bonding_show_alb_rx_hash(struct device *d,
>> + struct device_attribute *attr,
>> + char *buf)
>> +{
>> + int count = 0;
>> + struct bonding *bond = to_bond(d);
>> +
>> + if (bond->params.mode == BOND_MODE_ALB) {
>> + count = rlb_print_rx_hashtbl(bond, buf);
>> + }
>> +
>> + return count;
>> +}
>> +static DEVICE_ATTR(alb_rx_hash, S_IRUGO, bonding_show_alb_rx_hash, NULL);
>> +
>>
>> static struct attribute *per_bond_attrs[] = {
>> &dev_attr_slaves.attr,
>> @@ -1505,6 +1543,8 @@ static struct attribute *per_bond_attrs[] = {
>> &dev_attr_ad_actor_key.attr,
>> &dev_attr_ad_partner_key.attr,
>> &dev_attr_ad_partner_mac.attr,
>> + &dev_attr_alb_rx_hash.attr,
>> + &dev_attr_tlb_tx_hash.attr,
>> NULL,
>> };
>>
>
>Any thoughts on this one as well, Jay?
>
I've been testing with them last Friday and today. Seem to work
ok so far. I've made a couple of minor changes (removed some remaining
vestiges of the rlb rebalance code, changed the mode of the sysfs hash
table files to 0400 after some testing with ping and concurrent "while 1
cat > /dev/null" loops).
Unless something awful comes up, I'll post them with my changes
later today or tomorrow.
-J
---
-Jay Vosburgh, IBM Linux Technology Center, fubar@us.ibm.com
^ permalink raw reply
* Re: [PATCH 4/4 v2] bonding: add sysfs files to display tlb and alb hash table contents
From: Andy Gospodarek @ 2009-09-28 22:01 UTC (permalink / raw)
To: netdev, fubar, bonding-devel
In-Reply-To: <20090918155311.GA4436@gospo.rdu.redhat.com>
On Fri, Sep 18, 2009 at 11:53:11AM -0400, Andy Gospodarek wrote:
> On Fri, Sep 11, 2009 at 05:13:17PM -0400, Andy Gospodarek wrote:
> >
> > bonding: add sysfs files to display tlb and alb hash table contents
> >
> > While debugging some problems with alb (mode 6) bonding I realized that
> > being able to output the contents of both hash tables would be helpful.
> > This is what the output looks like for the two files:
> >
> > device load
> > eth1 491
> > eth2 491
> > hash device last device tx bytes load next previous
> > 2 eth1 eth1 2254 491 0 0
> > 3 eth2 eth2 2744 491 0 0
> > 6 eth2 0 488 0 0
> > 8 eth2 0 461698 0 0
> > 1b eth2 0 249 0 0
> > eb eth2 0 21 0 0
> > ff eth2 0 22 0 0
> >
> > hash ip_src ip_dst mac_dst slave assign ntt
> > 2 10.0.3.2 10.0.3.11 00:e0:81:71:ee:a9 eth1 1 0
> > 3 10.0.3.2 10.0.3.10 00:e0:81:71:ee:a9 eth2 1 0
> > 8 10.0.3.2 10.0.3.1 00:e0:81:71:ee:a9 eth2 1 0
> >
> > These were a great help debugging the fixes I have just posted and they
> > might be helpful for others, so I decided to include them in my
> > patchset.
> >
> > Signed-off-by: Andy Gospodarek <andy@greyhouse.net>
> >
>
> Needed to repost since patch 2/4 changed and first patch had whitespace
> issues:
>
> [PATCH v2] bonding: add sysfs files to display tlb and alb hash table contents
>
> While debugging some problems with alb (mode 6) bonding I realized that
> being able to output the contents of both hash tables would be helpful.
> This is what the output looks like for the two files:
>
> device load
> eth1 491
> eth2 491
> hash device last device tx bytes load next previous
> 2 eth1 eth1 2254 491 0 0
> 3 eth2 eth2 2744 491 0 0
> 6 eth2 0 488 0 0
> 8 eth2 0 461698 0 0
> 1b eth2 0 249 0 0
> eb eth2 0 21 0 0
> ff eth2 0 22 0 0
>
> hash ip_src ip_dst mac_dst slave assign ntt
> 2 10.0.3.2 10.0.3.11 00:e0:81:71:ee:a9 eth1 1 0
> 3 10.0.3.2 10.0.3.10 00:e0:81:71:ee:a9 eth2 1 0
> 8 10.0.3.2 10.0.3.1 00:e0:81:71:ee:a9 eth2 1 0
>
> These were a great help debugging the fixes I have just posted and they
> might be helpful for others, so I decided to include them in my post.
>
> Signed-off-by: Andy Gospodarek <andy@greyhouse.net>
>
> ---
> drivers/net/bonding/bond_alb.c | 61 ++++++++++++++++++++++++++++++++++++++
> drivers/net/bonding/bond_alb.h | 2 +
> drivers/net/bonding/bond_sysfs.c | 40 +++++++++++++++++++++++++
> 3 files changed, 103 insertions(+), 0 deletions(-)
>
> diff --git a/drivers/net/bonding/bond_alb.c b/drivers/net/bonding/bond_alb.c
> index 5d51489..adc5acd 100644
> --- a/drivers/net/bonding/bond_alb.c
> +++ b/drivers/net/bonding/bond_alb.c
> @@ -750,6 +750,67 @@ static struct slave *rlb_arp_xmit(struct sk_buff *skb, struct bonding *bond)
> return tx_slave;
> }
>
> +int rlb_print_rx_hashtbl(struct bonding *bond, char *buf)
> +{
> + struct alb_bond_info *bond_info = &(BOND_ALB_INFO(bond));
> + struct rlb_client_info *client_info;
> + u32 hash_index;
> + u32 count = 0;
> +
> + _lock_hashtbl(bond);
> +
> + count = sprintf(buf, "hash ip_src ip_dst mac_dst slave assign ntt\n");
> + hash_index = bond_info->rx_hashtbl_head;
> + for (; hash_index != RLB_NULL_INDEX; hash_index = client_info->next) {
> + client_info = &(bond_info->rx_hashtbl[hash_index]);
> + count += sprintf(buf + count,"%-4x %-15pi4 %-15pi4 %pM %-5s %-6d %d\n",
> + hash_index,
> + &client_info->ip_src,
> + &client_info->ip_dst,
> + client_info->mac_dst,
> + client_info->slave->dev->name,
> + client_info->assigned,
> + client_info->ntt);
> + }
> +
> + _unlock_hashtbl(bond);
> + return count;
> +}
> +
> +int tlb_print_tx_hashtbl(struct bonding *bond, char *buf)
> +{
> + struct alb_bond_info *bond_info = &(BOND_ALB_INFO(bond));
> + u32 hash_index;
> + u32 count = 0;
> + struct slave *slave;
> + int i;
> +
> + _lock_hashtbl(bond);
> +
> + count += sprintf(buf, "device load\n");
> + bond_for_each_slave(bond, slave, i) {
> + struct tlb_slave_info *slave_info = &(SLAVE_TLB_INFO(slave));
> + count += sprintf(buf + count,"%-7s %d\n",slave->dev->name,slave_info->load);
> + }
> + count += sprintf(buf + count, "hash device last device tx bytes load next previous\n");
> + for (hash_index = 0; hash_index < TLB_HASH_TABLE_SIZE; hash_index++) {
> + struct tlb_client_info *client_info = &(bond_info->tx_hashtbl[hash_index]);
> + if (client_info->tx_slave || client_info->last_slave) {
> + count += sprintf(buf + count,"%-4x %-8s %-13s %-14d %-11d %-4x %d\n",
> + hash_index,
> + (client_info->tx_slave) ? client_info->tx_slave->dev->name : "",
> + (client_info->last_slave) ? client_info->last_slave->dev->name : "",
> + client_info->tx_bytes,
> + client_info->load_history,
> + (client_info->next != TLB_NULL_INDEX) ? client_info->next : 0,
> + (client_info->prev != TLB_NULL_INDEX) ? client_info->prev : 0);
> + }
> + }
> +
> + _unlock_hashtbl(bond);
> + return count;
> +}
> +
> /* Caller must hold rx_hashtbl lock */
> static void rlb_init_table_entry(struct rlb_client_info *entry)
> {
> diff --git a/drivers/net/bonding/bond_alb.h b/drivers/net/bonding/bond_alb.h
> index 09d755a..57e761b 100644
> --- a/drivers/net/bonding/bond_alb.h
> +++ b/drivers/net/bonding/bond_alb.h
> @@ -131,5 +131,7 @@ int bond_alb_xmit(struct sk_buff *skb, struct net_device *bond_dev);
> void bond_alb_monitor(struct work_struct *);
> int bond_alb_set_mac_address(struct net_device *bond_dev, void *addr);
> void bond_alb_clear_vlan(struct bonding *bond, unsigned short vlan_id);
> +int rlb_print_rx_hashtbl(struct bonding *bond, char *buf);
> +int tlb_print_tx_hashtbl(struct bonding *bond, char *buf);
> #endif /* __BOND_ALB_H__ */
>
> diff --git a/drivers/net/bonding/bond_sysfs.c b/drivers/net/bonding/bond_sysfs.c
> index 55bf34f..1123e1f 100644
> --- a/drivers/net/bonding/bond_sysfs.c
> +++ b/drivers/net/bonding/bond_sysfs.c
> @@ -1480,6 +1480,44 @@ static ssize_t bonding_show_ad_partner_mac(struct device *d,
> static DEVICE_ATTR(ad_partner_mac, S_IRUGO, bonding_show_ad_partner_mac, NULL);
>
>
> +/*
> + * Show current tlb/alb tx hash table.
> + */
> +static ssize_t bonding_show_tlb_tx_hash(struct device *d,
> + struct device_attribute *attr,
> + char *buf)
> +{
> + int count = 0;
> + struct bonding *bond = to_bond(d);
> +
> + if (bond->params.mode == BOND_MODE_ALB ||
> + bond->params.mode == BOND_MODE_TLB) {
> + count = tlb_print_tx_hashtbl(bond, buf);
> + }
> +
> + return count;
> +}
> +static DEVICE_ATTR(tlb_tx_hash, S_IRUGO, bonding_show_tlb_tx_hash, NULL);
> +
> +
> +/*
> + * Show current alb rx hash table.
> + */
> +static ssize_t bonding_show_alb_rx_hash(struct device *d,
> + struct device_attribute *attr,
> + char *buf)
> +{
> + int count = 0;
> + struct bonding *bond = to_bond(d);
> +
> + if (bond->params.mode == BOND_MODE_ALB) {
> + count = rlb_print_rx_hashtbl(bond, buf);
> + }
> +
> + return count;
> +}
> +static DEVICE_ATTR(alb_rx_hash, S_IRUGO, bonding_show_alb_rx_hash, NULL);
> +
>
> static struct attribute *per_bond_attrs[] = {
> &dev_attr_slaves.attr,
> @@ -1505,6 +1543,8 @@ static struct attribute *per_bond_attrs[] = {
> &dev_attr_ad_actor_key.attr,
> &dev_attr_ad_partner_key.attr,
> &dev_attr_ad_partner_mac.attr,
> + &dev_attr_alb_rx_hash.attr,
> + &dev_attr_tlb_tx_hash.attr,
> NULL,
> };
>
Any thoughts on this one as well, Jay?
^ permalink raw reply
* Re: [PATCH 2/4 v3] bonding: make sure tx and rx hash tables stay in sync when using alb mode
From: Andy Gospodarek @ 2009-09-28 22:00 UTC (permalink / raw)
To: Jay Vosburgh, netdev, bonding-devel
In-Reply-To: <20090918155645.GB4436@gospo.rdu.redhat.com>
On Fri, Sep 18, 2009 at 11:56:45AM -0400, Andy Gospodarek wrote:
> On Fri, Sep 18, 2009 at 11:36:22AM -0400, Andy Gospodarek wrote:
> > On Wed, Sep 16, 2009 at 04:36:09PM -0700, Jay Vosburgh wrote:
> > > Andy Gospodarek <andy@greyhouse.net> wrote:
> > >
> > > >
> > > >Subject: [PATCH] bonding: make sure tx and rx hash tables stay in sync when using alb mode
> > >
> > > When testing this, I'm getting a lockdep warning. It appears to
> > > be unhappy that tlb_choose_channel acquires the tx / rx hash table locks
> > > in the order tx then rx, but rlb_choose_channel -> alb_get_best_slave
> > > acquires the locks in the other order. I applied all four patches, but
> > > it looks like the change that trips lockdep is in this patch (#2).
> > >
> > > I haven't gotten an actual deadlock from this, although it seems
> > > plausible if there are two cpus in bond_alb_xmit at the same time, and
> > > one of them is sending an ARP.
> > >
> > > One fairly straightforward fix would be to combine the rx and tx
> > > hash table locks into a single lock. I suspect that wouldn't have any
> > > real performance penalty, since the rx hash table lock is generally not
> > > acquired very often (unlike the tx lock, which is taken for every packet
> > > that goes out).
> > >
> > > Also, FYI, two of the four patches had trailing whitespace. I
> > > believe it was #2 and #4.
> > >
> > > Thoughts?
> >
> > Jay,
> >
> > This patch should address both the the deadlock and whitespace conerns.
> > I ran a kernel with LOCKDEP enabled and saw no warnings while passing
> > traffic on the bond while pulling cables and while removing the module.
> > Here it is....
> >
>
> Adding the version and signed-off-by lines might be nice, eh?
>
> [PATCH v3] bonding: make sure tx and rx hash tables stay in sync when using alb mode
>
> I noticed that it was easy for alb (mode 6) bonding to get into a state
> where the tx hash-table and rx hash-table are out of sync (there is
> really nothing to keep them synchronized), and we will transmit traffic
> destined for a host on one slave and send ARP frames to the same slave
> from another interface using a different source MAC.
>
> There is no compelling reason to do this, so this patch makes sure the
> rx hash-table changes whenever the tx hash-table is updated based on
> device load. This patch also drops the code that does rlb re-balancing
> since the balancing will not be controlled by the tx hash-table based on
> transmit load. In order to address an issue found with the initial
> patch, I have also combined the rx and tx hash table lock into a single
> lock. This will facilitate moving these into a single table at some
> point.
>
> Signed-off-by: Andy Gospodarek <andy@greyhouse.net>
>
> ---
> drivers/net/bonding/bond_alb.c | 203 +++++++++++++++-------------------------
> drivers/net/bonding/bond_alb.h | 3 +-
> 2 files changed, 75 insertions(+), 131 deletions(-)
>
> diff --git a/drivers/net/bonding/bond_alb.c b/drivers/net/bonding/bond_alb.c
> index bcf25c6..04b7055 100644
> --- a/drivers/net/bonding/bond_alb.c
> +++ b/drivers/net/bonding/bond_alb.c
> @@ -111,6 +111,7 @@ static inline struct arp_pkt *arp_pkt(const struct sk_buff *skb)
>
> /* Forward declaration */
> static void alb_send_learning_packets(struct slave *slave, u8 mac_addr[]);
> +static struct slave *alb_get_best_slave(struct bonding *bond, u32 hash_index);
>
> static inline u8 _simple_hash(const u8 *hash_start, int hash_size)
> {
> @@ -124,18 +125,18 @@ static inline u8 _simple_hash(const u8 *hash_start, int hash_size)
> return hash;
> }
>
> -/*********************** tlb specific functions ***************************/
> -
> -static inline void _lock_tx_hashtbl(struct bonding *bond)
> +/********************* hash table lock functions *************************/
> +static inline void _lock_hashtbl(struct bonding *bond)
> {
> - spin_lock_bh(&(BOND_ALB_INFO(bond).tx_hashtbl_lock));
> + spin_lock_bh(&(BOND_ALB_INFO(bond).hashtbl_lock));
> }
>
> -static inline void _unlock_tx_hashtbl(struct bonding *bond)
> +static inline void _unlock_hashtbl(struct bonding *bond)
> {
> - spin_unlock_bh(&(BOND_ALB_INFO(bond).tx_hashtbl_lock));
> + spin_unlock_bh(&(BOND_ALB_INFO(bond).hashtbl_lock));
> }
>
> +/*********************** tlb specific functions ***************************/
> /* Caller must hold tx_hashtbl lock */
> static inline void tlb_init_table_entry(struct tlb_client_info *entry, int save_load)
> {
> @@ -163,7 +164,7 @@ static void tlb_clear_slave(struct bonding *bond, struct slave *slave, int save_
> struct tlb_client_info *tx_hash_table;
> u32 index;
>
> - _lock_tx_hashtbl(bond);
> + _lock_hashtbl(bond);
>
> /* clear slave from tx_hashtbl */
> tx_hash_table = BOND_ALB_INFO(bond).tx_hashtbl;
> @@ -180,7 +181,7 @@ static void tlb_clear_slave(struct bonding *bond, struct slave *slave, int save_
>
> tlb_init_slave(slave);
>
> - _unlock_tx_hashtbl(bond);
> + _unlock_hashtbl(bond);
> }
>
> /* Must be called before starting the monitor timer */
> @@ -191,7 +192,7 @@ static int tlb_initialize(struct bonding *bond)
> struct tlb_client_info *new_hashtbl;
> int i;
>
> - spin_lock_init(&(bond_info->tx_hashtbl_lock));
> + spin_lock_init(&(bond_info->hashtbl_lock));
>
> new_hashtbl = kzalloc(size, GFP_KERNEL);
> if (!new_hashtbl) {
> @@ -200,7 +201,7 @@ static int tlb_initialize(struct bonding *bond)
> bond->dev->name);
> return -1;
> }
> - _lock_tx_hashtbl(bond);
> + _lock_hashtbl(bond);
>
> bond_info->tx_hashtbl = new_hashtbl;
>
> @@ -208,7 +209,7 @@ static int tlb_initialize(struct bonding *bond)
> tlb_init_table_entry(&bond_info->tx_hashtbl[i], 1);
> }
>
> - _unlock_tx_hashtbl(bond);
> + _unlock_hashtbl(bond);
>
> return 0;
> }
> @@ -218,12 +219,12 @@ static void tlb_deinitialize(struct bonding *bond)
> {
> struct alb_bond_info *bond_info = &(BOND_ALB_INFO(bond));
>
> - _lock_tx_hashtbl(bond);
> + _lock_hashtbl(bond);
>
> kfree(bond_info->tx_hashtbl);
> bond_info->tx_hashtbl = NULL;
>
> - _unlock_tx_hashtbl(bond);
> + _unlock_hashtbl(bond);
> }
>
> /* Caller must hold bond lock for read */
> @@ -264,24 +265,6 @@ static struct slave *tlb_get_least_loaded_slave(struct bonding *bond)
> return least_loaded;
> }
>
> -/* Caller must hold bond lock for read and hashtbl lock */
> -static struct slave *tlb_get_best_slave(struct bonding *bond, u32 hash_index)
> -{
> - struct alb_bond_info *bond_info = &(BOND_ALB_INFO(bond));
> - struct tlb_client_info *tx_hash_table = bond_info->tx_hashtbl;
> - struct slave *last_slave = tx_hash_table[hash_index].last_slave;
> - struct slave *next_slave = NULL;
> -
> - if (last_slave && SLAVE_IS_OK(last_slave)) {
> - /* Use the last slave listed in the tx hashtbl if:
> - the last slave currently is essentially unloaded. */
> - if (SLAVE_TLB_INFO(last_slave).load < 10)
> - next_slave = last_slave;
> - }
> -
> - return next_slave ? next_slave : tlb_get_least_loaded_slave(bond);
> -}
> -
> /* Caller must hold bond lock for read */
> static struct slave *tlb_choose_channel(struct bonding *bond, u32 hash_index, u32 skb_len)
> {
> @@ -289,13 +272,12 @@ static struct slave *tlb_choose_channel(struct bonding *bond, u32 hash_index, u3
> struct tlb_client_info *hash_table;
> struct slave *assigned_slave;
>
> - _lock_tx_hashtbl(bond);
> + _lock_hashtbl(bond);
>
> hash_table = bond_info->tx_hashtbl;
> assigned_slave = hash_table[hash_index].tx_slave;
> if (!assigned_slave) {
> - assigned_slave = tlb_get_best_slave(bond, hash_index);
> -
> + assigned_slave = alb_get_best_slave(bond, hash_index);
> if (assigned_slave) {
> struct tlb_slave_info *slave_info =
> &(SLAVE_TLB_INFO(assigned_slave));
> @@ -319,20 +301,52 @@ static struct slave *tlb_choose_channel(struct bonding *bond, u32 hash_index, u3
> hash_table[hash_index].tx_bytes += skb_len;
> }
>
> - _unlock_tx_hashtbl(bond);
> + _unlock_hashtbl(bond);
>
> return assigned_slave;
> }
>
> /*********************** rlb specific functions ***************************/
> -static inline void _lock_rx_hashtbl(struct bonding *bond)
> +
> +/* Caller must hold bond lock for read and hashtbl lock */
> +static struct slave *rlb_update_rx_table(struct bonding *bond, struct slave *next_slave, u32 hash_index)
> {
> - spin_lock_bh(&(BOND_ALB_INFO(bond).rx_hashtbl_lock));
> + struct alb_bond_info *bond_info = &(BOND_ALB_INFO(bond));
> +
> + /* check rlb table and correct it if wrong */
> + if (bond_info->rlb_enabled) {
> + struct rlb_client_info *rx_client_info = &(bond_info->rx_hashtbl[hash_index]);
> +
> + /* if the new slave computed by tlb checks doesn't match rlb, stop rlb from using it */
> + if (next_slave && (next_slave != rx_client_info->slave))
> + rx_client_info->slave = next_slave;
> + }
> + return next_slave;
> }
>
> -static inline void _unlock_rx_hashtbl(struct bonding *bond)
> +/* Caller must hold bond lock for read and hashtbl lock */
> +static struct slave *alb_get_best_slave(struct bonding *bond, u32 hash_index)
> {
> - spin_unlock_bh(&(BOND_ALB_INFO(bond).rx_hashtbl_lock));
> + struct alb_bond_info *bond_info = &(BOND_ALB_INFO(bond));
> + struct tlb_client_info *tx_hash_table = bond_info->tx_hashtbl;
> + struct slave *last_slave = tx_hash_table[hash_index].last_slave;
> + struct slave *next_slave = NULL;
> +
> + /* presume the next slave will be the least loaded one */
> + next_slave = tlb_get_least_loaded_slave(bond);
> +
> + if (last_slave && SLAVE_IS_OK(last_slave)) {
> + /* Use the last slave listed in the tx hashtbl if:
> + the last slave currently is essentially unloaded. */
> + if (SLAVE_TLB_INFO(last_slave).load < 10)
> + next_slave = last_slave;
> + }
> +
> + /* update the rlb hashtbl if there was a previous entry */
> + if (bond_info->rlb_enabled)
> + rlb_update_rx_table(bond, next_slave, hash_index);
> +
> + return next_slave;
> }
>
> /* when an ARP REPLY is received from a client update its info
> @@ -344,7 +358,7 @@ static void rlb_update_entry_from_arp(struct bonding *bond, struct arp_pkt *arp)
> struct rlb_client_info *client_info;
> u32 hash_index;
>
> - _lock_rx_hashtbl(bond);
> + _lock_hashtbl(bond);
>
> hash_index = _simple_hash((u8*)&(arp->ip_src), sizeof(arp->ip_src));
> client_info = &(bond_info->rx_hashtbl[hash_index]);
> @@ -358,7 +372,7 @@ static void rlb_update_entry_from_arp(struct bonding *bond, struct arp_pkt *arp)
> bond_info->rx_ntt = 1;
> }
>
> - _unlock_rx_hashtbl(bond);
> + _unlock_hashtbl(bond);
> }
>
> static int rlb_arp_recv(struct sk_buff *skb, struct net_device *bond_dev, struct packet_type *ptype, struct net_device *orig_dev)
> @@ -402,38 +416,6 @@ out:
> return res;
> }
>
> -/* Caller must hold bond lock for read */
> -static struct slave *rlb_next_rx_slave(struct bonding *bond)
> -{
> - struct alb_bond_info *bond_info = &(BOND_ALB_INFO(bond));
> - struct slave *rx_slave, *slave, *start_at;
> - int i = 0;
> -
> - if (bond_info->next_rx_slave) {
> - start_at = bond_info->next_rx_slave;
> - } else {
> - start_at = bond->first_slave;
> - }
> -
> - rx_slave = NULL;
> -
> - bond_for_each_slave_from(bond, slave, i, start_at) {
> - if (SLAVE_IS_OK(slave)) {
> - if (!rx_slave) {
> - rx_slave = slave;
> - } else if (slave->speed > rx_slave->speed) {
> - rx_slave = slave;
> - }
> - }
> - }
> -
> - if (rx_slave) {
> - bond_info->next_rx_slave = rx_slave->next;
> - }
> -
> - return rx_slave;
> -}
> -
> /* teach the switch the mac of a disabled slave
> * on the primary for fault tolerance
> *
> @@ -468,14 +450,14 @@ static void rlb_clear_slave(struct bonding *bond, struct slave *slave)
> u32 index, next_index;
>
> /* clear slave from rx_hashtbl */
> - _lock_rx_hashtbl(bond);
> + _lock_hashtbl(bond);
>
> rx_hash_table = bond_info->rx_hashtbl;
> index = bond_info->rx_hashtbl_head;
> for (; index != RLB_NULL_INDEX; index = next_index) {
> next_index = rx_hash_table[index].next;
> if (rx_hash_table[index].slave == slave) {
> - struct slave *assigned_slave = rlb_next_rx_slave(bond);
> + struct slave *assigned_slave = alb_get_best_slave(bond, index);
>
> if (assigned_slave) {
> rx_hash_table[index].slave = assigned_slave;
> @@ -499,7 +481,7 @@ static void rlb_clear_slave(struct bonding *bond, struct slave *slave)
> }
> }
>
> - _unlock_rx_hashtbl(bond);
> + _unlock_hashtbl(bond);
>
> write_lock_bh(&bond->curr_slave_lock);
>
> @@ -558,7 +540,7 @@ static void rlb_update_rx_clients(struct bonding *bond)
> struct rlb_client_info *client_info;
> u32 hash_index;
>
> - _lock_rx_hashtbl(bond);
> + _lock_hashtbl(bond);
>
> hash_index = bond_info->rx_hashtbl_head;
> for (; hash_index != RLB_NULL_INDEX; hash_index = client_info->next) {
> @@ -576,7 +558,7 @@ static void rlb_update_rx_clients(struct bonding *bond)
> */
> bond_info->rlb_update_delay_counter = RLB_UPDATE_DELAY;
>
> - _unlock_rx_hashtbl(bond);
> + _unlock_hashtbl(bond);
> }
>
> /* The slave was assigned a new mac address - update the clients */
> @@ -587,7 +569,7 @@ static void rlb_req_update_slave_clients(struct bonding *bond, struct slave *sla
> int ntt = 0;
> u32 hash_index;
>
> - _lock_rx_hashtbl(bond);
> + _lock_hashtbl(bond);
>
> hash_index = bond_info->rx_hashtbl_head;
> for (; hash_index != RLB_NULL_INDEX; hash_index = client_info->next) {
> @@ -607,7 +589,7 @@ static void rlb_req_update_slave_clients(struct bonding *bond, struct slave *sla
> bond_info->rlb_update_retry_counter = RLB_UPDATE_RETRY;
> }
>
> - _unlock_rx_hashtbl(bond);
> + _unlock_hashtbl(bond);
> }
>
> /* mark all clients using src_ip to be updated */
> @@ -617,7 +599,7 @@ static void rlb_req_update_subnet_clients(struct bonding *bond, __be32 src_ip)
> struct rlb_client_info *client_info;
> u32 hash_index;
>
> - _lock_rx_hashtbl(bond);
> + _lock_hashtbl(bond);
>
> hash_index = bond_info->rx_hashtbl_head;
> for (; hash_index != RLB_NULL_INDEX; hash_index = client_info->next) {
> @@ -643,7 +625,7 @@ static void rlb_req_update_subnet_clients(struct bonding *bond, __be32 src_ip)
> }
> }
>
> - _unlock_rx_hashtbl(bond);
> + _unlock_hashtbl(bond);
> }
>
> /* Caller must hold both bond and ptr locks for read */
> @@ -655,7 +637,7 @@ static struct slave *rlb_choose_channel(struct sk_buff *skb, struct bonding *bon
> struct rlb_client_info *client_info;
> u32 hash_index = 0;
>
> - _lock_rx_hashtbl(bond);
> + _lock_hashtbl(bond);
>
> hash_index = _simple_hash((u8 *)&arp->ip_dst, sizeof(arp->ip_src));
> client_info = &(bond_info->rx_hashtbl[hash_index]);
> @@ -671,7 +653,7 @@ static struct slave *rlb_choose_channel(struct sk_buff *skb, struct bonding *bon
>
> assigned_slave = client_info->slave;
> if (assigned_slave) {
> - _unlock_rx_hashtbl(bond);
> + _unlock_hashtbl(bond);
> return assigned_slave;
> }
> } else {
> @@ -687,7 +669,7 @@ static struct slave *rlb_choose_channel(struct sk_buff *skb, struct bonding *bon
> }
> }
> /* assign a new slave */
> - assigned_slave = rlb_next_rx_slave(bond);
> + assigned_slave = alb_get_best_slave(bond, hash_index);
>
> if (assigned_slave) {
> client_info->ip_src = arp->ip_src;
> @@ -723,7 +705,7 @@ static struct slave *rlb_choose_channel(struct sk_buff *skb, struct bonding *bon
> }
> }
>
> - _unlock_rx_hashtbl(bond);
> + _unlock_hashtbl(bond);
>
> return assigned_slave;
> }
> @@ -771,36 +753,6 @@ static struct slave *rlb_arp_xmit(struct sk_buff *skb, struct bonding *bond)
> return tx_slave;
> }
>
> -/* Caller must hold bond lock for read */
> -static void rlb_rebalance(struct bonding *bond)
> -{
> - struct alb_bond_info *bond_info = &(BOND_ALB_INFO(bond));
> - struct slave *assigned_slave;
> - struct rlb_client_info *client_info;
> - int ntt;
> - u32 hash_index;
> -
> - _lock_rx_hashtbl(bond);
> -
> - ntt = 0;
> - hash_index = bond_info->rx_hashtbl_head;
> - for (; hash_index != RLB_NULL_INDEX; hash_index = client_info->next) {
> - client_info = &(bond_info->rx_hashtbl[hash_index]);
> - assigned_slave = rlb_next_rx_slave(bond);
> - if (assigned_slave && (client_info->slave != assigned_slave)) {
> - client_info->slave = assigned_slave;
> - client_info->ntt = 1;
> - ntt = 1;
> - }
> - }
> -
> - /* update the team's flag only after the whole iteration */
> - if (ntt) {
> - bond_info->rx_ntt = 1;
> - }
> - _unlock_rx_hashtbl(bond);
> -}
> -
> /* Caller must hold rx_hashtbl lock */
> static void rlb_init_table_entry(struct rlb_client_info *entry)
> {
> @@ -817,8 +769,6 @@ static int rlb_initialize(struct bonding *bond)
> int size = RLB_HASH_TABLE_SIZE * sizeof(struct rlb_client_info);
> int i;
>
> - spin_lock_init(&(bond_info->rx_hashtbl_lock));
> -
> new_hashtbl = kmalloc(size, GFP_KERNEL);
> if (!new_hashtbl) {
> printk(KERN_ERR DRV_NAME
> @@ -826,7 +776,7 @@ static int rlb_initialize(struct bonding *bond)
> bond->dev->name);
> return -1;
> }
> - _lock_rx_hashtbl(bond);
> + _lock_hashtbl(bond);
>
> bond_info->rx_hashtbl = new_hashtbl;
>
> @@ -836,7 +786,7 @@ static int rlb_initialize(struct bonding *bond)
> rlb_init_table_entry(bond_info->rx_hashtbl + i);
> }
>
> - _unlock_rx_hashtbl(bond);
> + _unlock_hashtbl(bond);
>
> /*initialize packet type*/
> pk_type->type = cpu_to_be16(ETH_P_ARP);
> @@ -855,13 +805,13 @@ static void rlb_deinitialize(struct bonding *bond)
>
> dev_remove_pack(&(bond_info->rlb_pkt_type));
>
> - _lock_rx_hashtbl(bond);
> + _lock_hashtbl(bond);
>
> kfree(bond_info->rx_hashtbl);
> bond_info->rx_hashtbl = NULL;
> bond_info->rx_hashtbl_head = RLB_NULL_INDEX;
>
> - _unlock_rx_hashtbl(bond);
> + _unlock_hashtbl(bond);
> }
>
> static void rlb_clear_vlan(struct bonding *bond, unsigned short vlan_id)
> @@ -869,7 +819,7 @@ static void rlb_clear_vlan(struct bonding *bond, unsigned short vlan_id)
> struct alb_bond_info *bond_info = &(BOND_ALB_INFO(bond));
> u32 curr_index;
>
> - _lock_rx_hashtbl(bond);
> + _lock_hashtbl(bond);
>
> curr_index = bond_info->rx_hashtbl_head;
> while (curr_index != RLB_NULL_INDEX) {
> @@ -894,7 +844,7 @@ static void rlb_clear_vlan(struct bonding *bond, unsigned short vlan_id)
> curr_index = next_index;
> }
>
> - _unlock_rx_hashtbl(bond);
> + _unlock_hashtbl(bond);
> }
>
> /*********************** tlb/rlb shared functions *********************/
> @@ -1521,11 +1471,6 @@ void bond_alb_monitor(struct work_struct *work)
> read_lock(&bond->lock);
> }
>
> - if (bond_info->rlb_rebalance) {
> - bond_info->rlb_rebalance = 0;
> - rlb_rebalance(bond);
> - }
> -
> /* check if clients need updating */
> if (bond_info->rx_ntt) {
> if (bond_info->rlb_update_delay_counter) {
> diff --git a/drivers/net/bonding/bond_alb.h b/drivers/net/bonding/bond_alb.h
> index b65fd29..09d755a 100644
> --- a/drivers/net/bonding/bond_alb.h
> +++ b/drivers/net/bonding/bond_alb.h
> @@ -90,7 +90,7 @@ struct tlb_slave_info {
> struct alb_bond_info {
> struct timer_list alb_timer;
> struct tlb_client_info *tx_hashtbl; /* Dynamically allocated */
> - spinlock_t tx_hashtbl_lock;
> + spinlock_t hashtbl_lock; /* lock for both tables */
> u32 unbalanced_load;
> int tx_rebalance_counter;
> int lp_counter;
> @@ -98,7 +98,6 @@ struct alb_bond_info {
> int rlb_enabled;
> struct packet_type rlb_pkt_type;
> struct rlb_client_info *rx_hashtbl; /* Receive hash table */
> - spinlock_t rx_hashtbl_lock;
> u32 rx_hashtbl_head;
> u8 rx_ntt; /* flag - need to transmit
> * to all rx clients
Any thoughts on this, Jay?
^ permalink raw reply
* Re: tg3 and Broadcom PHY driver
From: David Miller @ 2009-09-28 21:55 UTC (permalink / raw)
To: felix; +Cc: mcarlson, netdev
In-Reply-To: <4AC13036.8030506@embedded-sol.com>
From: Felix Radensky <felix@embedded-sol.com>
Date: Mon, 28 Sep 2009 23:52:54 +0200
> Yes, moving CONFIG_TIGON3 right after CONFIG_PHYLIB in
> drivers/net/Makefile fixes the problem for me.
Thanks for testing.
We really need to fix this generically.
Does anyone think that moving the MDIO/MII/PHY layer objects
to the top of drivers/net/Makefile will break anything?
If not, that's what we should do I think.
^ permalink raw reply
* Re: tg3 and Broadcom PHY driver
From: Felix Radensky @ 2009-09-28 21:52 UTC (permalink / raw)
To: David Miller; +Cc: mcarlson, netdev
In-Reply-To: <20090928.141527.193009676.davem@davemloft.net>
Hi, David
David Miller wrote:
> From: Felix Radensky <felix@embedded-sol.com>
> Date: Mon, 28 Sep 2009 22:53:15 +0200
>
>
>> Hi, Matt
>>
>> Matt Carlson wrote:
>>
>>> On Sat, Sep 26, 2009 at 02:32:18PM -0700, Felix Radensky wrote:
>>>
>>> Is the broadcom module also compiled into the kernel?
>>>
>>>
>>>
>> Yes.
>>
>
> I bet this is all because the tg3 driver is linked into the kernel
> before the PHY layer and drivers subdirectory or something like that.
>
> Link order determines the order in which built-in initializations
> occur (within the same init type).
>
Yes, moving CONFIG_TIGON3 right after CONFIG_PHYLIB in drivers/net/Makefile
fixes the problem for me.
Thanks a lot.
Felix.
^ permalink raw reply
* Re: pull request: wireless-2.6 2009-09-28
From: David Miller @ 2009-09-28 21:51 UTC (permalink / raw)
To: linville; +Cc: linux-wireless, netdev, linux-kernel
In-Reply-To: <20090928214047.GF4737@tuxdriver.com>
From: "John W. Linville" <linville@tuxdriver.com>
Date: Mon, 28 Sep 2009 17:40:48 -0400
> There are number of small fixes to core wireless infrastructure from
> Johannes Berg. These have been bounced around on the list quite a bit
> during the last several days, so I think they are solid. Also included
> is one that improves some debugging messages.
>
> There are a few fixes for the iwlwifi family of drivers, including a
> buffer overrun, a memory leak, and another debugging message fix.
>
> Arjan showed-up with a bounds checking fix in some ancient wext code. I
> included it due to the potential security implications.
>
> The sony-laptop fixes may seem a bit out of place, but they are related
> to rfkill. Also, they are "Acked-by: Mattia Dongili <malattia@linux.it>",
> who is the listed maintainer for that code. I put them at the end, so
> if you want you can pull from 8f1546cadf7ac5e9a40d54089a1c7302264ec49b
> instead of master.
>
> Please let me know if there are problems!
Pulled, thanks a lot John!
^ permalink raw reply
* pull request: wireless-2.6 2009-09-28
From: John W. Linville @ 2009-09-28 21:40 UTC (permalink / raw)
To: davem; +Cc: linux-wireless, netdev, linux-kernel
Dave,
This group of fixes is intended for the 2.6.32 train...
There are number of small fixes to core wireless infrastructure from
Johannes Berg. These have been bounced around on the list quite a bit
during the last several days, so I think they are solid. Also included
is one that improves some debugging messages.
There are a few fixes for the iwlwifi family of drivers, including a
buffer overrun, a memory leak, and another debugging message fix.
Arjan showed-up with a bounds checking fix in some ancient wext code. I
included it due to the potential security implications.
The sony-laptop fixes may seem a bit out of place, but they are related
to rfkill. Also, they are "Acked-by: Mattia Dongili <malattia@linux.it>",
who is the listed maintainer for that code. I put them at the end, so
if you want you can pull from 8f1546cadf7ac5e9a40d54089a1c7302264ec49b
instead of master.
Please let me know if there are problems!
Thanks,
John
---
Individual patches are available here:
http://www.kernel.org/pub/linux/kernel/people/linville/wireless-2.6/
---
The following changes since commit d1f8297a96b0d70f17704296a6666468f2087ce6:
Sascha Hlusiak (1):
Revert "sit: stateless autoconf for isatap"
are available in the git repository at:
ssh://master.kernel.org/pub/scm/linux/kernel/git/linville/wireless-2.6.git master
Alan Jenkins (2):
sony-laptop: check for rfkill hard block at load time
sony-laptop: re-read the rfkill state when resuming from suspend
Arjan van de Ven (1):
wext: Add bound checks for copy_from_user
Johannes Berg (5):
cfg80211: wext: don't display BSSID unless associated
cfg80211: don't set privacy w/o key
cfg80211: always get BSS
mac80211: improve/fix mlme messages
wext: add back wireless/ dir in sysfs for cfg80211 interfaces
Reinette Chatre (3):
iwlwifi: fix debugfs buffer handling
iwlwifi: fix memory leak in command queue handling
iwlwifi: fix 3945 ucode info retrieval after failure
drivers/net/wireless/iwlwifi/iwl-1000.c | 2 +
drivers/net/wireless/iwlwifi/iwl-3945.c | 2 +
drivers/net/wireless/iwlwifi/iwl-3945.h | 2 +
drivers/net/wireless/iwlwifi/iwl-4965.c | 2 +
drivers/net/wireless/iwlwifi/iwl-5000.c | 4 +
drivers/net/wireless/iwlwifi/iwl-6000.c | 2 +
drivers/net/wireless/iwlwifi/iwl-agn.c | 185 ++++++++++++++++++++++++++
drivers/net/wireless/iwlwifi/iwl-core.c | 187 +--------------------------
drivers/net/wireless/iwlwifi/iwl-core.h | 14 ++
drivers/net/wireless/iwlwifi/iwl-debugfs.c | 8 +-
drivers/net/wireless/iwlwifi/iwl-tx.c | 6 +
drivers/net/wireless/iwlwifi/iwl3945-base.c | 31 ++---
drivers/platform/x86/sony-laptop.c | 9 ++
include/net/wext.h | 1 +
net/core/net-sysfs.c | 12 +-
net/mac80211/mlme.c | 18 ++--
net/wireless/sme.c | 5 +-
net/wireless/wext-sme.c | 8 +-
net/wireless/wext.c | 11 +-
19 files changed, 274 insertions(+), 235 deletions(-)
diff --git a/drivers/net/wireless/iwlwifi/iwl-1000.c b/drivers/net/wireless/iwlwifi/iwl-1000.c
index a95caa0..2716b91 100644
--- a/drivers/net/wireless/iwlwifi/iwl-1000.c
+++ b/drivers/net/wireless/iwlwifi/iwl-1000.c
@@ -99,6 +99,8 @@ static struct iwl_lib_ops iwl1000_lib = {
.setup_deferred_work = iwl5000_setup_deferred_work,
.is_valid_rtc_data_addr = iwl5000_hw_valid_rtc_data_addr,
.load_ucode = iwl5000_load_ucode,
+ .dump_nic_event_log = iwl_dump_nic_event_log,
+ .dump_nic_error_log = iwl_dump_nic_error_log,
.init_alive_start = iwl5000_init_alive_start,
.alive_notify = iwl5000_alive_notify,
.send_tx_power = iwl5000_send_tx_power,
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c
index e9a685d..e70c5b0 100644
--- a/drivers/net/wireless/iwlwifi/iwl-3945.c
+++ b/drivers/net/wireless/iwlwifi/iwl-3945.c
@@ -2839,6 +2839,8 @@ static struct iwl_lib_ops iwl3945_lib = {
.txq_free_tfd = iwl3945_hw_txq_free_tfd,
.txq_init = iwl3945_hw_tx_queue_init,
.load_ucode = iwl3945_load_bsm,
+ .dump_nic_event_log = iwl3945_dump_nic_event_log,
+ .dump_nic_error_log = iwl3945_dump_nic_error_log,
.apm_ops = {
.init = iwl3945_apm_init,
.reset = iwl3945_apm_reset,
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.h b/drivers/net/wireless/iwlwifi/iwl-3945.h
index f240369..21679bf 100644
--- a/drivers/net/wireless/iwlwifi/iwl-3945.h
+++ b/drivers/net/wireless/iwlwifi/iwl-3945.h
@@ -209,6 +209,8 @@ extern int __must_check iwl3945_send_cmd(struct iwl_priv *priv,
struct iwl_host_cmd *cmd);
extern unsigned int iwl3945_fill_beacon_frame(struct iwl_priv *priv,
struct ieee80211_hdr *hdr,int left);
+extern void iwl3945_dump_nic_event_log(struct iwl_priv *priv);
+extern void iwl3945_dump_nic_error_log(struct iwl_priv *priv);
/*
* Currently used by iwl-3945-rs... look at restructuring so that it doesn't
diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c
index 3259b88..a22a050 100644
--- a/drivers/net/wireless/iwlwifi/iwl-4965.c
+++ b/drivers/net/wireless/iwlwifi/iwl-4965.c
@@ -2298,6 +2298,8 @@ static struct iwl_lib_ops iwl4965_lib = {
.alive_notify = iwl4965_alive_notify,
.init_alive_start = iwl4965_init_alive_start,
.load_ucode = iwl4965_load_bsm,
+ .dump_nic_event_log = iwl_dump_nic_event_log,
+ .dump_nic_error_log = iwl_dump_nic_error_log,
.apm_ops = {
.init = iwl4965_apm_init,
.reset = iwl4965_apm_reset,
diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c
index a6391c7..eb08f44 100644
--- a/drivers/net/wireless/iwlwifi/iwl-5000.c
+++ b/drivers/net/wireless/iwlwifi/iwl-5000.c
@@ -1535,6 +1535,8 @@ struct iwl_lib_ops iwl5000_lib = {
.rx_handler_setup = iwl5000_rx_handler_setup,
.setup_deferred_work = iwl5000_setup_deferred_work,
.is_valid_rtc_data_addr = iwl5000_hw_valid_rtc_data_addr,
+ .dump_nic_event_log = iwl_dump_nic_event_log,
+ .dump_nic_error_log = iwl_dump_nic_error_log,
.load_ucode = iwl5000_load_ucode,
.init_alive_start = iwl5000_init_alive_start,
.alive_notify = iwl5000_alive_notify,
@@ -1585,6 +1587,8 @@ static struct iwl_lib_ops iwl5150_lib = {
.rx_handler_setup = iwl5000_rx_handler_setup,
.setup_deferred_work = iwl5000_setup_deferred_work,
.is_valid_rtc_data_addr = iwl5000_hw_valid_rtc_data_addr,
+ .dump_nic_event_log = iwl_dump_nic_event_log,
+ .dump_nic_error_log = iwl_dump_nic_error_log,
.load_ucode = iwl5000_load_ucode,
.init_alive_start = iwl5000_init_alive_start,
.alive_notify = iwl5000_alive_notify,
diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c
index 82b9c93..c295b8e 100644
--- a/drivers/net/wireless/iwlwifi/iwl-6000.c
+++ b/drivers/net/wireless/iwlwifi/iwl-6000.c
@@ -100,6 +100,8 @@ static struct iwl_lib_ops iwl6000_lib = {
.setup_deferred_work = iwl5000_setup_deferred_work,
.is_valid_rtc_data_addr = iwl5000_hw_valid_rtc_data_addr,
.load_ucode = iwl5000_load_ucode,
+ .dump_nic_event_log = iwl_dump_nic_event_log,
+ .dump_nic_error_log = iwl_dump_nic_error_log,
.init_alive_start = iwl5000_init_alive_start,
.alive_notify = iwl5000_alive_notify,
.send_tx_power = iwl5000_send_tx_power,
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c
index 00457bf..cdc07c4 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn.c
@@ -1526,6 +1526,191 @@ static int iwl_read_ucode(struct iwl_priv *priv)
return ret;
}
+#ifdef CONFIG_IWLWIFI_DEBUG
+static const char *desc_lookup_text[] = {
+ "OK",
+ "FAIL",
+ "BAD_PARAM",
+ "BAD_CHECKSUM",
+ "NMI_INTERRUPT_WDG",
+ "SYSASSERT",
+ "FATAL_ERROR",
+ "BAD_COMMAND",
+ "HW_ERROR_TUNE_LOCK",
+ "HW_ERROR_TEMPERATURE",
+ "ILLEGAL_CHAN_FREQ",
+ "VCC_NOT_STABLE",
+ "FH_ERROR",
+ "NMI_INTERRUPT_HOST",
+ "NMI_INTERRUPT_ACTION_PT",
+ "NMI_INTERRUPT_UNKNOWN",
+ "UCODE_VERSION_MISMATCH",
+ "HW_ERROR_ABS_LOCK",
+ "HW_ERROR_CAL_LOCK_FAIL",
+ "NMI_INTERRUPT_INST_ACTION_PT",
+ "NMI_INTERRUPT_DATA_ACTION_PT",
+ "NMI_TRM_HW_ER",
+ "NMI_INTERRUPT_TRM",
+ "NMI_INTERRUPT_BREAK_POINT"
+ "DEBUG_0",
+ "DEBUG_1",
+ "DEBUG_2",
+ "DEBUG_3",
+ "UNKNOWN"
+};
+
+static const char *desc_lookup(int i)
+{
+ int max = ARRAY_SIZE(desc_lookup_text) - 1;
+
+ if (i < 0 || i > max)
+ i = max;
+
+ return desc_lookup_text[i];
+}
+
+#define ERROR_START_OFFSET (1 * sizeof(u32))
+#define ERROR_ELEM_SIZE (7 * sizeof(u32))
+
+void iwl_dump_nic_error_log(struct iwl_priv *priv)
+{
+ u32 data2, line;
+ u32 desc, time, count, base, data1;
+ u32 blink1, blink2, ilink1, ilink2;
+
+ if (priv->ucode_type == UCODE_INIT)
+ base = le32_to_cpu(priv->card_alive_init.error_event_table_ptr);
+ else
+ base = le32_to_cpu(priv->card_alive.error_event_table_ptr);
+
+ if (!priv->cfg->ops->lib->is_valid_rtc_data_addr(base)) {
+ IWL_ERR(priv, "Not valid error log pointer 0x%08X\n", base);
+ return;
+ }
+
+ count = iwl_read_targ_mem(priv, base);
+
+ if (ERROR_START_OFFSET <= count * ERROR_ELEM_SIZE) {
+ IWL_ERR(priv, "Start IWL Error Log Dump:\n");
+ IWL_ERR(priv, "Status: 0x%08lX, count: %d\n",
+ priv->status, count);
+ }
+
+ desc = iwl_read_targ_mem(priv, base + 1 * sizeof(u32));
+ blink1 = iwl_read_targ_mem(priv, base + 3 * sizeof(u32));
+ blink2 = iwl_read_targ_mem(priv, base + 4 * sizeof(u32));
+ ilink1 = iwl_read_targ_mem(priv, base + 5 * sizeof(u32));
+ ilink2 = iwl_read_targ_mem(priv, base + 6 * sizeof(u32));
+ data1 = iwl_read_targ_mem(priv, base + 7 * sizeof(u32));
+ data2 = iwl_read_targ_mem(priv, base + 8 * sizeof(u32));
+ line = iwl_read_targ_mem(priv, base + 9 * sizeof(u32));
+ time = iwl_read_targ_mem(priv, base + 11 * sizeof(u32));
+
+ IWL_ERR(priv, "Desc Time "
+ "data1 data2 line\n");
+ IWL_ERR(priv, "%-28s (#%02d) %010u 0x%08X 0x%08X %u\n",
+ desc_lookup(desc), desc, time, data1, data2, line);
+ IWL_ERR(priv, "blink1 blink2 ilink1 ilink2\n");
+ IWL_ERR(priv, "0x%05X 0x%05X 0x%05X 0x%05X\n", blink1, blink2,
+ ilink1, ilink2);
+
+}
+
+#define EVENT_START_OFFSET (4 * sizeof(u32))
+
+/**
+ * iwl_print_event_log - Dump error event log to syslog
+ *
+ */
+static void iwl_print_event_log(struct iwl_priv *priv, u32 start_idx,
+ u32 num_events, u32 mode)
+{
+ u32 i;
+ u32 base; /* SRAM byte address of event log header */
+ u32 event_size; /* 2 u32s, or 3 u32s if timestamp recorded */
+ u32 ptr; /* SRAM byte address of log data */
+ u32 ev, time, data; /* event log data */
+
+ if (num_events == 0)
+ return;
+ if (priv->ucode_type == UCODE_INIT)
+ base = le32_to_cpu(priv->card_alive_init.log_event_table_ptr);
+ else
+ base = le32_to_cpu(priv->card_alive.log_event_table_ptr);
+
+ if (mode == 0)
+ event_size = 2 * sizeof(u32);
+ else
+ event_size = 3 * sizeof(u32);
+
+ ptr = base + EVENT_START_OFFSET + (start_idx * event_size);
+
+ /* "time" is actually "data" for mode 0 (no timestamp).
+ * place event id # at far right for easier visual parsing. */
+ for (i = 0; i < num_events; i++) {
+ ev = iwl_read_targ_mem(priv, ptr);
+ ptr += sizeof(u32);
+ time = iwl_read_targ_mem(priv, ptr);
+ ptr += sizeof(u32);
+ if (mode == 0) {
+ /* data, ev */
+ IWL_ERR(priv, "EVT_LOG:0x%08x:%04u\n", time, ev);
+ } else {
+ data = iwl_read_targ_mem(priv, ptr);
+ ptr += sizeof(u32);
+ IWL_ERR(priv, "EVT_LOGT:%010u:0x%08x:%04u\n",
+ time, data, ev);
+ }
+ }
+}
+
+void iwl_dump_nic_event_log(struct iwl_priv *priv)
+{
+ u32 base; /* SRAM byte address of event log header */
+ u32 capacity; /* event log capacity in # entries */
+ u32 mode; /* 0 - no timestamp, 1 - timestamp recorded */
+ u32 num_wraps; /* # times uCode wrapped to top of log */
+ u32 next_entry; /* index of next entry to be written by uCode */
+ u32 size; /* # entries that we'll print */
+
+ if (priv->ucode_type == UCODE_INIT)
+ base = le32_to_cpu(priv->card_alive_init.log_event_table_ptr);
+ else
+ base = le32_to_cpu(priv->card_alive.log_event_table_ptr);
+
+ if (!priv->cfg->ops->lib->is_valid_rtc_data_addr(base)) {
+ IWL_ERR(priv, "Invalid event log pointer 0x%08X\n", base);
+ return;
+ }
+
+ /* event log header */
+ capacity = iwl_read_targ_mem(priv, base);
+ mode = iwl_read_targ_mem(priv, base + (1 * sizeof(u32)));
+ num_wraps = iwl_read_targ_mem(priv, base + (2 * sizeof(u32)));
+ next_entry = iwl_read_targ_mem(priv, base + (3 * sizeof(u32)));
+
+ size = num_wraps ? capacity : next_entry;
+
+ /* bail out if nothing in log */
+ if (size == 0) {
+ IWL_ERR(priv, "Start IWL Event Log Dump: nothing in log\n");
+ return;
+ }
+
+ IWL_ERR(priv, "Start IWL Event Log Dump: display count %d, wraps %d\n",
+ size, num_wraps);
+
+ /* if uCode has wrapped back to top of log, start at the oldest entry,
+ * i.e the next one that uCode would fill. */
+ if (num_wraps)
+ iwl_print_event_log(priv, next_entry,
+ capacity - next_entry, mode);
+ /* (then/else) start at top of log */
+ iwl_print_event_log(priv, 0, next_entry, mode);
+
+}
+#endif
+
/**
* iwl_alive_start - called after REPLY_ALIVE notification received
* from protocol/runtime uCode (initialization uCode's
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c
index fd26c0d..484d5c1 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.c
+++ b/drivers/net/wireless/iwlwifi/iwl-core.c
@@ -1309,189 +1309,6 @@ static void iwl_print_rx_config_cmd(struct iwl_priv *priv)
IWL_DEBUG_RADIO(priv, "u8[6] bssid_addr: %pM\n", rxon->bssid_addr);
IWL_DEBUG_RADIO(priv, "u16 assoc_id: 0x%x\n", le16_to_cpu(rxon->assoc_id));
}
-
-static const char *desc_lookup_text[] = {
- "OK",
- "FAIL",
- "BAD_PARAM",
- "BAD_CHECKSUM",
- "NMI_INTERRUPT_WDG",
- "SYSASSERT",
- "FATAL_ERROR",
- "BAD_COMMAND",
- "HW_ERROR_TUNE_LOCK",
- "HW_ERROR_TEMPERATURE",
- "ILLEGAL_CHAN_FREQ",
- "VCC_NOT_STABLE",
- "FH_ERROR",
- "NMI_INTERRUPT_HOST",
- "NMI_INTERRUPT_ACTION_PT",
- "NMI_INTERRUPT_UNKNOWN",
- "UCODE_VERSION_MISMATCH",
- "HW_ERROR_ABS_LOCK",
- "HW_ERROR_CAL_LOCK_FAIL",
- "NMI_INTERRUPT_INST_ACTION_PT",
- "NMI_INTERRUPT_DATA_ACTION_PT",
- "NMI_TRM_HW_ER",
- "NMI_INTERRUPT_TRM",
- "NMI_INTERRUPT_BREAK_POINT"
- "DEBUG_0",
- "DEBUG_1",
- "DEBUG_2",
- "DEBUG_3",
- "UNKNOWN"
-};
-
-static const char *desc_lookup(int i)
-{
- int max = ARRAY_SIZE(desc_lookup_text) - 1;
-
- if (i < 0 || i > max)
- i = max;
-
- return desc_lookup_text[i];
-}
-
-#define ERROR_START_OFFSET (1 * sizeof(u32))
-#define ERROR_ELEM_SIZE (7 * sizeof(u32))
-
-static void iwl_dump_nic_error_log(struct iwl_priv *priv)
-{
- u32 data2, line;
- u32 desc, time, count, base, data1;
- u32 blink1, blink2, ilink1, ilink2;
-
- if (priv->ucode_type == UCODE_INIT)
- base = le32_to_cpu(priv->card_alive_init.error_event_table_ptr);
- else
- base = le32_to_cpu(priv->card_alive.error_event_table_ptr);
-
- if (!priv->cfg->ops->lib->is_valid_rtc_data_addr(base)) {
- IWL_ERR(priv, "Not valid error log pointer 0x%08X\n", base);
- return;
- }
-
- count = iwl_read_targ_mem(priv, base);
-
- if (ERROR_START_OFFSET <= count * ERROR_ELEM_SIZE) {
- IWL_ERR(priv, "Start IWL Error Log Dump:\n");
- IWL_ERR(priv, "Status: 0x%08lX, count: %d\n",
- priv->status, count);
- }
-
- desc = iwl_read_targ_mem(priv, base + 1 * sizeof(u32));
- blink1 = iwl_read_targ_mem(priv, base + 3 * sizeof(u32));
- blink2 = iwl_read_targ_mem(priv, base + 4 * sizeof(u32));
- ilink1 = iwl_read_targ_mem(priv, base + 5 * sizeof(u32));
- ilink2 = iwl_read_targ_mem(priv, base + 6 * sizeof(u32));
- data1 = iwl_read_targ_mem(priv, base + 7 * sizeof(u32));
- data2 = iwl_read_targ_mem(priv, base + 8 * sizeof(u32));
- line = iwl_read_targ_mem(priv, base + 9 * sizeof(u32));
- time = iwl_read_targ_mem(priv, base + 11 * sizeof(u32));
-
- IWL_ERR(priv, "Desc Time "
- "data1 data2 line\n");
- IWL_ERR(priv, "%-28s (#%02d) %010u 0x%08X 0x%08X %u\n",
- desc_lookup(desc), desc, time, data1, data2, line);
- IWL_ERR(priv, "blink1 blink2 ilink1 ilink2\n");
- IWL_ERR(priv, "0x%05X 0x%05X 0x%05X 0x%05X\n", blink1, blink2,
- ilink1, ilink2);
-
-}
-
-#define EVENT_START_OFFSET (4 * sizeof(u32))
-
-/**
- * iwl_print_event_log - Dump error event log to syslog
- *
- */
-static void iwl_print_event_log(struct iwl_priv *priv, u32 start_idx,
- u32 num_events, u32 mode)
-{
- u32 i;
- u32 base; /* SRAM byte address of event log header */
- u32 event_size; /* 2 u32s, or 3 u32s if timestamp recorded */
- u32 ptr; /* SRAM byte address of log data */
- u32 ev, time, data; /* event log data */
-
- if (num_events == 0)
- return;
- if (priv->ucode_type == UCODE_INIT)
- base = le32_to_cpu(priv->card_alive_init.log_event_table_ptr);
- else
- base = le32_to_cpu(priv->card_alive.log_event_table_ptr);
-
- if (mode == 0)
- event_size = 2 * sizeof(u32);
- else
- event_size = 3 * sizeof(u32);
-
- ptr = base + EVENT_START_OFFSET + (start_idx * event_size);
-
- /* "time" is actually "data" for mode 0 (no timestamp).
- * place event id # at far right for easier visual parsing. */
- for (i = 0; i < num_events; i++) {
- ev = iwl_read_targ_mem(priv, ptr);
- ptr += sizeof(u32);
- time = iwl_read_targ_mem(priv, ptr);
- ptr += sizeof(u32);
- if (mode == 0) {
- /* data, ev */
- IWL_ERR(priv, "EVT_LOG:0x%08x:%04u\n", time, ev);
- } else {
- data = iwl_read_targ_mem(priv, ptr);
- ptr += sizeof(u32);
- IWL_ERR(priv, "EVT_LOGT:%010u:0x%08x:%04u\n",
- time, data, ev);
- }
- }
-}
-
-void iwl_dump_nic_event_log(struct iwl_priv *priv)
-{
- u32 base; /* SRAM byte address of event log header */
- u32 capacity; /* event log capacity in # entries */
- u32 mode; /* 0 - no timestamp, 1 - timestamp recorded */
- u32 num_wraps; /* # times uCode wrapped to top of log */
- u32 next_entry; /* index of next entry to be written by uCode */
- u32 size; /* # entries that we'll print */
-
- if (priv->ucode_type == UCODE_INIT)
- base = le32_to_cpu(priv->card_alive_init.log_event_table_ptr);
- else
- base = le32_to_cpu(priv->card_alive.log_event_table_ptr);
-
- if (!priv->cfg->ops->lib->is_valid_rtc_data_addr(base)) {
- IWL_ERR(priv, "Invalid event log pointer 0x%08X\n", base);
- return;
- }
-
- /* event log header */
- capacity = iwl_read_targ_mem(priv, base);
- mode = iwl_read_targ_mem(priv, base + (1 * sizeof(u32)));
- num_wraps = iwl_read_targ_mem(priv, base + (2 * sizeof(u32)));
- next_entry = iwl_read_targ_mem(priv, base + (3 * sizeof(u32)));
-
- size = num_wraps ? capacity : next_entry;
-
- /* bail out if nothing in log */
- if (size == 0) {
- IWL_ERR(priv, "Start IWL Event Log Dump: nothing in log\n");
- return;
- }
-
- IWL_ERR(priv, "Start IWL Event Log Dump: display count %d, wraps %d\n",
- size, num_wraps);
-
- /* if uCode has wrapped back to top of log, start at the oldest entry,
- * i.e the next one that uCode would fill. */
- if (num_wraps)
- iwl_print_event_log(priv, next_entry,
- capacity - next_entry, mode);
- /* (then/else) start at top of log */
- iwl_print_event_log(priv, 0, next_entry, mode);
-
-}
#endif
/**
* iwl_irq_handle_error - called for HW or SW error interrupt from card
@@ -1506,8 +1323,8 @@ void iwl_irq_handle_error(struct iwl_priv *priv)
#ifdef CONFIG_IWLWIFI_DEBUG
if (iwl_get_debug_level(priv) & IWL_DL_FW_ERRORS) {
- iwl_dump_nic_error_log(priv);
- iwl_dump_nic_event_log(priv);
+ priv->cfg->ops->lib->dump_nic_error_log(priv);
+ priv->cfg->ops->lib->dump_nic_event_log(priv);
iwl_print_rx_config_cmd(priv);
}
#endif
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h
index 7ff9ffb..e50103a 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.h
+++ b/drivers/net/wireless/iwlwifi/iwl-core.h
@@ -166,6 +166,8 @@ struct iwl_lib_ops {
int (*is_valid_rtc_data_addr)(u32 addr);
/* 1st ucode load */
int (*load_ucode)(struct iwl_priv *priv);
+ void (*dump_nic_event_log)(struct iwl_priv *priv);
+ void (*dump_nic_error_log)(struct iwl_priv *priv);
/* power management */
struct iwl_apm_ops apm_ops;
@@ -540,7 +542,19 @@ int iwl_pci_resume(struct pci_dev *pdev);
/*****************************************************
* Error Handling Debugging
******************************************************/
+#ifdef CONFIG_IWLWIFI_DEBUG
void iwl_dump_nic_event_log(struct iwl_priv *priv);
+void iwl_dump_nic_error_log(struct iwl_priv *priv);
+#else
+static inline void iwl_dump_nic_event_log(struct iwl_priv *priv)
+{
+}
+
+static inline void iwl_dump_nic_error_log(struct iwl_priv *priv)
+{
+}
+#endif
+
void iwl_clear_isr_stats(struct iwl_priv *priv);
/*****************************************************
diff --git a/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-debugfs.c
index fb84485..a198bcf 100644
--- a/drivers/net/wireless/iwlwifi/iwl-debugfs.c
+++ b/drivers/net/wireless/iwlwifi/iwl-debugfs.c
@@ -410,7 +410,7 @@ static ssize_t iwl_dbgfs_nvm_read(struct file *file,
pos += scnprintf(buf + pos, buf_size - pos, "0x%.4x ", ofs);
hex_dump_to_buffer(ptr + ofs, 16 , 16, 2, buf + pos,
buf_size - pos, 0);
- pos += strlen(buf);
+ pos += strlen(buf + pos);
if (buf_size - pos > 0)
buf[pos++] = '\n';
}
@@ -436,7 +436,7 @@ static ssize_t iwl_dbgfs_log_event_write(struct file *file,
if (sscanf(buf, "%d", &event_log_flag) != 1)
return -EFAULT;
if (event_log_flag == 1)
- iwl_dump_nic_event_log(priv);
+ priv->cfg->ops->lib->dump_nic_event_log(priv);
return count;
}
@@ -909,7 +909,7 @@ static ssize_t iwl_dbgfs_traffic_log_read(struct file *file,
"0x%.4x ", ofs);
hex_dump_to_buffer(ptr + ofs, 16, 16, 2,
buf + pos, bufsz - pos, 0);
- pos += strlen(buf);
+ pos += strlen(buf + pos);
if (bufsz - pos > 0)
buf[pos++] = '\n';
}
@@ -932,7 +932,7 @@ static ssize_t iwl_dbgfs_traffic_log_read(struct file *file,
"0x%.4x ", ofs);
hex_dump_to_buffer(ptr + ofs, 16, 16, 2,
buf + pos, bufsz - pos, 0);
- pos += strlen(buf);
+ pos += strlen(buf + pos);
if (bufsz - pos > 0)
buf[pos++] = '\n';
}
diff --git a/drivers/net/wireless/iwlwifi/iwl-tx.c b/drivers/net/wireless/iwlwifi/iwl-tx.c
index a7422e5..c189075 100644
--- a/drivers/net/wireless/iwlwifi/iwl-tx.c
+++ b/drivers/net/wireless/iwlwifi/iwl-tx.c
@@ -197,6 +197,12 @@ void iwl_cmd_queue_free(struct iwl_priv *priv)
pci_free_consistent(dev, priv->hw_params.tfd_size *
txq->q.n_bd, txq->tfds, txq->q.dma_addr);
+ /* deallocate arrays */
+ kfree(txq->cmd);
+ kfree(txq->meta);
+ txq->cmd = NULL;
+ txq->meta = NULL;
+
/* 0-fill queue descriptor structure */
memset(txq, 0, sizeof(*txq));
}
diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c
index 4f2d439..c390dbd 100644
--- a/drivers/net/wireless/iwlwifi/iwl3945-base.c
+++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c
@@ -1481,6 +1481,7 @@ static inline void iwl_synchronize_irq(struct iwl_priv *priv)
tasklet_kill(&priv->irq_tasklet);
}
+#ifdef CONFIG_IWLWIFI_DEBUG
static const char *desc_lookup(int i)
{
switch (i) {
@@ -1504,7 +1505,7 @@ static const char *desc_lookup(int i)
#define ERROR_START_OFFSET (1 * sizeof(u32))
#define ERROR_ELEM_SIZE (7 * sizeof(u32))
-static void iwl3945_dump_nic_error_log(struct iwl_priv *priv)
+void iwl3945_dump_nic_error_log(struct iwl_priv *priv)
{
u32 i;
u32 desc, time, count, base, data1;
@@ -1598,7 +1599,7 @@ static void iwl3945_print_event_log(struct iwl_priv *priv, u32 start_idx,
}
}
-static void iwl3945_dump_nic_event_log(struct iwl_priv *priv)
+void iwl3945_dump_nic_event_log(struct iwl_priv *priv)
{
u32 base; /* SRAM byte address of event log header */
u32 capacity; /* event log capacity in # entries */
@@ -1640,6 +1641,16 @@ static void iwl3945_dump_nic_event_log(struct iwl_priv *priv)
iwl3945_print_event_log(priv, 0, next_entry, mode);
}
+#else
+void iwl3945_dump_nic_event_log(struct iwl_priv *priv)
+{
+}
+
+void iwl3945_dump_nic_error_log(struct iwl_priv *priv)
+{
+}
+
+#endif
static void iwl3945_irq_tasklet(struct iwl_priv *priv)
{
@@ -3683,21 +3694,6 @@ static ssize_t dump_error_log(struct device *d,
static DEVICE_ATTR(dump_errors, S_IWUSR, NULL, dump_error_log);
-static ssize_t dump_event_log(struct device *d,
- struct device_attribute *attr,
- const char *buf, size_t count)
-{
- struct iwl_priv *priv = dev_get_drvdata(d);
- char *p = (char *)buf;
-
- if (p[0] == '1')
- iwl3945_dump_nic_event_log(priv);
-
- return strnlen(buf, count);
-}
-
-static DEVICE_ATTR(dump_events, S_IWUSR, NULL, dump_event_log);
-
/*****************************************************************************
*
* driver setup and tear down
@@ -3742,7 +3738,6 @@ static struct attribute *iwl3945_sysfs_entries[] = {
&dev_attr_antenna.attr,
&dev_attr_channels.attr,
&dev_attr_dump_errors.attr,
- &dev_attr_dump_events.attr,
&dev_attr_flags.attr,
&dev_attr_filter_flags.attr,
#ifdef CONFIG_IWL3945_SPECTRUM_MEASUREMENT
diff --git a/drivers/platform/x86/sony-laptop.c b/drivers/platform/x86/sony-laptop.c
index f9f68e0..afdbdaa 100644
--- a/drivers/platform/x86/sony-laptop.c
+++ b/drivers/platform/x86/sony-laptop.c
@@ -1041,6 +1041,9 @@ static int sony_nc_resume(struct acpi_device *device)
sony_backlight_update_status(sony_backlight_device) < 0)
printk(KERN_WARNING DRV_PFX "unable to restore brightness level\n");
+ /* re-read rfkill state */
+ sony_nc_rfkill_update();
+
return 0;
}
@@ -1078,6 +1081,8 @@ static int sony_nc_setup_rfkill(struct acpi_device *device,
struct rfkill *rfk;
enum rfkill_type type;
const char *name;
+ int result;
+ bool hwblock;
switch (nc_type) {
case SONY_WIFI:
@@ -1105,6 +1110,10 @@ static int sony_nc_setup_rfkill(struct acpi_device *device,
if (!rfk)
return -ENOMEM;
+ sony_call_snc_handle(0x124, 0x200, &result);
+ hwblock = !(result & 0x1);
+ rfkill_set_hw_state(rfk, hwblock);
+
err = rfkill_register(rfk);
if (err) {
rfkill_destroy(rfk);
diff --git a/include/net/wext.h b/include/net/wext.h
index 6d76a39..3f2b94d 100644
--- a/include/net/wext.h
+++ b/include/net/wext.h
@@ -14,6 +14,7 @@ extern int wext_handle_ioctl(struct net *net, struct ifreq *ifr, unsigned int cm
void __user *arg);
extern int compat_wext_handle_ioctl(struct net *net, unsigned int cmd,
unsigned long arg);
+extern struct iw_statistics *get_wireless_stats(struct net_device *dev);
#else
static inline int wext_proc_init(struct net *net)
{
diff --git a/net/core/net-sysfs.c b/net/core/net-sysfs.c
index 7d4c575..821d309 100644
--- a/net/core/net-sysfs.c
+++ b/net/core/net-sysfs.c
@@ -16,7 +16,7 @@
#include <net/sock.h>
#include <linux/rtnetlink.h>
#include <linux/wireless.h>
-#include <net/iw_handler.h>
+#include <net/wext.h>
#include "net-sysfs.h"
@@ -363,15 +363,13 @@ static ssize_t wireless_show(struct device *d, char *buf,
char *))
{
struct net_device *dev = to_net_dev(d);
- const struct iw_statistics *iw = NULL;
+ const struct iw_statistics *iw;
ssize_t ret = -EINVAL;
read_lock(&dev_base_lock);
if (dev_isalive(dev)) {
- if (dev->wireless_handlers &&
- dev->wireless_handlers->get_wireless_stats)
- iw = dev->wireless_handlers->get_wireless_stats(dev);
- if (iw != NULL)
+ iw = get_wireless_stats(dev);
+ if (iw)
ret = (*format)(iw, buf);
}
read_unlock(&dev_base_lock);
@@ -505,7 +503,7 @@ int netdev_register_kobject(struct net_device *net)
*groups++ = &netstat_group;
#ifdef CONFIG_WIRELESS_EXT_SYSFS
- if (net->wireless_handlers && net->wireless_handlers->get_wireless_stats)
+ if (net->wireless_handlers || net->ieee80211_ptr)
*groups++ = &wireless_group;
#endif
#endif /* CONFIG_SYSFS */
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index 97a278a..8d26e9b 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -1388,8 +1388,8 @@ ieee80211_rx_mgmt_disassoc(struct ieee80211_sub_if_data *sdata,
reason_code = le16_to_cpu(mgmt->u.disassoc.reason_code);
- printk(KERN_DEBUG "%s: disassociated (Reason: %u)\n",
- sdata->dev->name, reason_code);
+ printk(KERN_DEBUG "%s: disassociated from %pM (Reason: %u)\n",
+ sdata->dev->name, mgmt->sa, reason_code);
ieee80211_set_disassoc(sdata, false);
return RX_MGMT_CFG80211_DISASSOC;
@@ -1675,7 +1675,7 @@ static void ieee80211_rx_mgmt_probe_resp(struct ieee80211_sub_if_data *sdata,
/* direct probe may be part of the association flow */
if (wk && wk->state == IEEE80211_MGD_STATE_PROBE) {
- printk(KERN_DEBUG "%s direct probe responded\n",
+ printk(KERN_DEBUG "%s: direct probe responded\n",
sdata->dev->name);
wk->tries = 0;
wk->state = IEEE80211_MGD_STATE_AUTH;
@@ -2502,9 +2502,6 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata,
struct ieee80211_mgd_work *wk;
const u8 *bssid = NULL;
- printk(KERN_DEBUG "%s: deauthenticating by local choice (reason=%d)\n",
- sdata->dev->name, req->reason_code);
-
mutex_lock(&ifmgd->mtx);
if (ifmgd->associated && &ifmgd->associated->cbss == req->bss) {
@@ -2532,6 +2529,9 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata,
mutex_unlock(&ifmgd->mtx);
+ printk(KERN_DEBUG "%s: deauthenticating from %pM by local choice (reason=%d)\n",
+ sdata->dev->name, bssid, req->reason_code);
+
ieee80211_send_deauth_disassoc(sdata, bssid,
IEEE80211_STYPE_DEAUTH, req->reason_code,
cookie);
@@ -2545,9 +2545,6 @@ int ieee80211_mgd_disassoc(struct ieee80211_sub_if_data *sdata,
{
struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
- printk(KERN_DEBUG "%s: disassociating by local choice (reason=%d)\n",
- sdata->dev->name, req->reason_code);
-
mutex_lock(&ifmgd->mtx);
/*
@@ -2561,6 +2558,9 @@ int ieee80211_mgd_disassoc(struct ieee80211_sub_if_data *sdata,
return -ENOLINK;
}
+ printk(KERN_DEBUG "%s: disassociating from %pM by local choice (reason=%d)\n",
+ sdata->dev->name, req->bss->bssid, req->reason_code);
+
ieee80211_set_disassoc(sdata, false);
mutex_unlock(&ifmgd->mtx);
diff --git a/net/wireless/sme.c b/net/wireless/sme.c
index 7fae7ee..93c3ed3 100644
--- a/net/wireless/sme.c
+++ b/net/wireless/sme.c
@@ -762,9 +762,8 @@ int __cfg80211_connect(struct cfg80211_registered_device *rdev,
wdev->conn->params.ssid = wdev->ssid;
wdev->conn->params.ssid_len = connect->ssid_len;
- /* don't care about result -- but fill bssid & channel */
- if (!wdev->conn->params.bssid || !wdev->conn->params.channel)
- bss = cfg80211_get_conn_bss(wdev);
+ /* see if we have the bss already */
+ bss = cfg80211_get_conn_bss(wdev);
wdev->sme_state = CFG80211_SME_CONNECTING;
wdev->connect_keys = connkeys;
diff --git a/net/wireless/wext-sme.c b/net/wireless/wext-sme.c
index bf72527..5615a88 100644
--- a/net/wireless/wext-sme.c
+++ b/net/wireless/wext-sme.c
@@ -30,7 +30,8 @@ int cfg80211_mgd_wext_connect(struct cfg80211_registered_device *rdev,
if (wdev->wext.keys) {
wdev->wext.keys->def = wdev->wext.default_key;
wdev->wext.keys->defmgmt = wdev->wext.default_mgmt_key;
- wdev->wext.connect.privacy = true;
+ if (wdev->wext.default_key != -1)
+ wdev->wext.connect.privacy = true;
}
if (!wdev->wext.connect.ssid_len)
@@ -229,8 +230,7 @@ int cfg80211_mgd_wext_giwessid(struct net_device *dev,
data->flags = 1;
data->length = wdev->wext.connect.ssid_len;
memcpy(ssid, wdev->wext.connect.ssid, data->length);
- } else
- data->flags = 0;
+ }
wdev_unlock(wdev);
return 0;
@@ -306,8 +306,6 @@ int cfg80211_mgd_wext_giwap(struct net_device *dev,
wdev_lock(wdev);
if (wdev->current_bss)
memcpy(ap_addr->sa_data, wdev->current_bss->pub.bssid, ETH_ALEN);
- else if (wdev->wext.connect.bssid)
- memcpy(ap_addr->sa_data, wdev->wext.connect.bssid, ETH_ALEN);
else
memset(ap_addr->sa_data, 0, ETH_ALEN);
wdev_unlock(wdev);
diff --git a/net/wireless/wext.c b/net/wireless/wext.c
index 5b4a0ce..60fe577 100644
--- a/net/wireless/wext.c
+++ b/net/wireless/wext.c
@@ -470,7 +470,7 @@ static iw_handler get_handler(struct net_device *dev, unsigned int cmd)
/*
* Get statistics out of the driver
*/
-static struct iw_statistics *get_wireless_stats(struct net_device *dev)
+struct iw_statistics *get_wireless_stats(struct net_device *dev)
{
/* New location */
if ((dev->wireless_handlers != NULL) &&
@@ -773,10 +773,13 @@ static int ioctl_standard_iw_point(struct iw_point *iwp, unsigned int cmd,
essid_compat = 1;
else if (IW_IS_SET(cmd) && (iwp->length != 0)) {
char essid[IW_ESSID_MAX_SIZE + 1];
+ unsigned int len;
+ len = iwp->length * descr->token_size;
- err = copy_from_user(essid, iwp->pointer,
- iwp->length *
- descr->token_size);
+ if (len > IW_ESSID_MAX_SIZE)
+ return -EFAULT;
+
+ err = copy_from_user(essid, iwp->pointer, len);
if (err)
return -EFAULT;
--
John W. Linville Someday the world will need a hero, and you
linville@tuxdriver.com might be all we have. Be ready.
^ permalink raw reply related
* Re: tg3 and Broadcom PHY driver
From: David Miller @ 2009-09-28 21:15 UTC (permalink / raw)
To: felix; +Cc: mcarlson, netdev
In-Reply-To: <4AC1223B.8070903@embedded-sol.com>
From: Felix Radensky <felix@embedded-sol.com>
Date: Mon, 28 Sep 2009 22:53:15 +0200
> Hi, Matt
>
> Matt Carlson wrote:
>> On Sat, Sep 26, 2009 at 02:32:18PM -0700, Felix Radensky wrote:
>>
>> Is the broadcom module also compiled into the kernel?
>>
>>
> Yes.
I bet this is all because the tg3 driver is linked into the kernel
before the PHY layer and drivers subdirectory or something like that.
Link order determines the order in which built-in initializations
occur (within the same init type).
^ permalink raw reply
* Re: [2.6.31-git17] WARNING: at kernel/hrtimer.c:648 hres_timers_resume+0x40/0x50()/WARNING: at drivers/base/sys.c:353 __sysdev_resume+0xc3/0xe0()
From: Rafael J. Wysocki @ 2009-09-28 21:13 UTC (permalink / raw)
To: Maciej Rutecki
Cc: Yong Zhang, Linux Kernel Mailing List, clemens,
venkatesh.pallipadi, gregkh, zambrano, davem, netdev
In-Reply-To: <8db1092f0909281308s36c35c80s65c18dcbcf9fff2b@mail.gmail.com>
On Monday 28 September 2009, Maciej Rutecki wrote:
> 2009/9/28 Maciej Rutecki <maciej.rutecki@gmail.com>:
> >
> > Add patch and remove previous:
> > http://unixy.pl/maciek/download/kernel/2.6.31-git17/gumis/dmesg-debug.txt
> >
> > s2disk&resume twice.
> >
> > no "timekeeping_resume() called with IRQs enabled!".
> >
> > I found some interesting thing, warnings appear only once, during
> > first s2disk, on second don't appear.
>
> Already I test 2.6-32-rc1 few times; warnings has gone. Any patches
> has been add since 2.6.31-git17?
Quite some of them, actually.
Thanks,
Rafael
^ permalink raw reply
* Re: tg3 and Broadcom PHY driver
From: Felix Radensky @ 2009-09-28 20:53 UTC (permalink / raw)
To: Matt Carlson; +Cc: netdev@vger.kernel.org
In-Reply-To: <20090928205226.GB12652@xw6200.broadcom.net>
Hi, Matt
Matt Carlson wrote:
> On Sat, Sep 26, 2009 at 02:32:18PM -0700, Felix Radensky wrote:
>
>> Hi,
>>
>> I've noticed that in linux-2.6.31 I have to make tg3 driver modular, due to
>> its dependency on Broadcom PHY driver. If both tg3 and PHY driver are
>> compiled into the kernel, tg3 fails to detect a PHY, apparently because PHY
>> driver is loaded later. I'm using BCM57760 on embedded powerpc platform
>> (MPC8536).
>>
>> How can I make tg3 work when it's compiled into the kernel ?
>>
>> Thanks.
>>
>
> Is the broadcom module also compiled into the kernel?
>
>
Yes.
^ permalink raw reply
* Re: tg3 and Broadcom PHY driver
From: Matt Carlson @ 2009-09-28 20:52 UTC (permalink / raw)
To: Felix Radensky; +Cc: netdev@vger.kernel.org
In-Reply-To: <4ABE8862.3060308@embedded-sol.com>
On Sat, Sep 26, 2009 at 02:32:18PM -0700, Felix Radensky wrote:
> Hi,
>
> I've noticed that in linux-2.6.31 I have to make tg3 driver modular, due to
> its dependency on Broadcom PHY driver. If both tg3 and PHY driver are
> compiled into the kernel, tg3 fails to detect a PHY, apparently because PHY
> driver is loaded later. I'm using BCM57760 on embedded powerpc platform
> (MPC8536).
>
> How can I make tg3 work when it's compiled into the kernel ?
>
> Thanks.
Is the broadcom module also compiled into the kernel?
^ permalink raw reply
* Re: tg3: Badness at kernel/mutex.c:207
From: Matt Carlson @ 2009-09-28 20:51 UTC (permalink / raw)
To: Felix Radensky; +Cc: netdev@vger.kernel.org
In-Reply-To: <4ABE85B9.3020304@embedded-sol.com>
On Sat, Sep 26, 2009 at 02:20:57PM -0700, Felix Radensky wrote:
> Hi,
>
> I'm running linux-2.6.31 on a custom MPC8536 based board with BCM57760 chip.
> Both tg3 driver, and Broadcom PHY driver are modules.
>
> Each time I run ifconfig eth2 up, I get the following error message:
>
> Badness at kernel/mutex.c:207
> NIP: c025132c LR: c0251314 CTR: c0251334
> REGS: efbedbd0 TRAP: 0700 Not tainted (2.6.31)
> MSR: 00029000 <EE,ME,CE> CR: 24020422 XER: 00000000
> TASK = efacce10[1080] 'ifconfig' THREAD: efbec000
> GPR00: 00000000 efbedc80 efacce10 00000001 00007020 00000002 00000000
> 00000200
> GPR08: 00029000 c0350000 c0330000 00000001 24020424 10057d94 000002a0
> 1000d82c
> GPR16: 1000d81c 1000d814 10010000 10050000 ef897a0c efbede18 ffff8914
> ef897a00
> GPR24: 00008000 c034b480 efbec000 efb0122c c0350000 efacce10 ef82d2c0
> efb01228
> NIP [c025132c] __mutex_lock_slowpath+0x1f0/0x1f8
> LR [c0251314] __mutex_lock_slowpath+0x1d8/0x1f8
> Call Trace:
> [efbedcd0] [c025134c] mutex_lock+0x18/0x34
> [efbedcf0] [f534a228] tg3_chip_reset+0x7cc/0x9f8 [tg3]
> [efbedd20] [f534a8f0] tg3_reset_hw+0x58/0x2360 [tg3]
> [efbedd70] [f5351dd4] tg3_open+0x610/0x910 [tg3]
> [efbeddb0] [c01e1c6c] dev_open+0x100/0x138
> [efbeddd0] [c01dff20] dev_change_flags+0x80/0x1ac
> [efbeddf0] [c02232cc] devinet_ioctl+0x648/0x824
> [efbede60] [c0223de4] inet_ioctl+0xcc/0xf8
> [efbede70] [c01cdf44] sock_ioctl+0x60/0x300
> [efbede90] [c008a35c] vfs_ioctl+0x34/0x8c
> [efbedea0] [c008a580] do_vfs_ioctl+0x88/0x724
> [efbedf10] [c008ac5c] sys_ioctl+0x40/0x74
> [efbedf40] [c000f814] ret_from_syscall+0x0/0x3c
> Instruction dump:
> 0fe00000 4bfffe80 801a000c 5409016f 4182fe60 4bf0f6d9 2f830000 41befe54
> 3d20c035 8009c2c0 2f800000 40befe44 <0fe00000> 4bfffe3c 9421ffe0 7c0802a6
>
> Does it indicate a real problem, or something that can be ignored ?
>
> Additional information from kernel log:
>
> tg3.c:v3.99 (April 20, 2009)
> tg3 0002:05:00.0: enabling bus mastering
> tg3 0002:05:00.0: PME# disabled
> tg3 mdio bus: probed
> eth2: Tigon3 [partno(BCM57760) rev 57780001] (PCI Express) MAC address
> 00:10:18:00:00:00
> eth2: attached PHY driver [Broadcom BCM57780] (mii_bus:phy_addr=500:01)
> eth2: RXcsums[1] LinkChgREG[0] MIirq[0] ASF[0] TSOcap[1]
> eth2: dma_rwctrl[76180000] dma_mask[64-bit]
> tg3 0002:05:00.0: PME# disabled
Yes, this is a real problem. The driver is taking the MDIO bus lock
while holding the device's own spinlock. I think I may have a
workaround. Let me test it and get back to you.
^ permalink raw reply
* Re: 2.6.31 regression: e1000e jumbo frames no longer work: 'Unsupported MTU setting'
From: Nix @ 2009-09-28 20:51 UTC (permalink / raw)
To: Alexander Duyck; +Cc: e1000-devel, netdev, bruce.w.allan, linux-kernel
In-Reply-To: <5f2db9d90909261914l3a927f4cya1dc5e4548688bce@mail.gmail.com>
On 27 Sep 2009, Alexander Duyck said:
> It looks like the problem is that the 82574 and 82583 seem to have
> their max_hw_frame_size values swapped. You might try applying the
> patch below. I am not sure if it will apply since I hand generated it
Applies fine: works fine. Thank you!
> using the git patch that seems to have introduced the problem, and I
> am sending the patch through an untested account that may mangle the
> patch.
Unmangled.
> I will see about submitting an official patch for this
> sometime next few days.
I wonder if this belongs in -stable? People with an 82574 who are using
jumbo frames may well find their networks not coming up, if like me
they set a bunch of properties in one /sbin/ip call.
------------------------------------------------------------------------------
Come build with us! The BlackBerry® Developer Conference in SF, CA
is the only developer event you need to attend this year. Jumpstart your
developing skills, take BlackBerry mobile applications to market and stay
ahead of the curve. Join us from November 9-12, 2009. Register now!
http://p.sf.net/sfu/devconf
^ permalink raw reply
* Re: [2.6.31-git17] WARNING: at kernel/hrtimer.c:648 hres_timers_resume+0x40/0x50()/WARNING: at drivers/base/sys.c:353 __sysdev_resume+0xc3/0xe0()
From: Maciej Rutecki @ 2009-09-28 20:08 UTC (permalink / raw)
To: Yong Zhang
Cc: Linux Kernel Mailing List, Rafael J. Wysocki, clemens,
venkatesh.pallipadi, gregkh, zambrano, davem, netdev
In-Reply-To: <8db1092f0909281138t18a379d1qdf999b0610ed6414@mail.gmail.com>
2009/9/28 Maciej Rutecki <maciej.rutecki@gmail.com>:
>
> Add patch and remove previous:
> http://unixy.pl/maciek/download/kernel/2.6.31-git17/gumis/dmesg-debug.txt
>
> s2disk&resume twice.
>
> no "timekeeping_resume() called with IRQs enabled!".
>
> I found some interesting thing, warnings appear only once, during
> first s2disk, on second don't appear.
Already I test 2.6-32-rc1 few times; warnings has gone. Any patches
has been add since 2.6.31-git17?
Regards
--
Maciej Rutecki
http://www.maciek.unixy.pl
^ permalink raw reply
* Re: [PATCH 9/9] Add explicit bound checks in net/socket.c
From: David Miller @ 2009-09-28 19:57 UTC (permalink / raw)
To: arjan; +Cc: gorcunov, linux-kernel, torvalds, mingo, netdev
In-Reply-To: <20090926212302.0ce64a5c@infradead.org>
From: Arjan van de Ven <arjan@infradead.org>
Date: Sat, 26 Sep 2009 21:23:02 +0200
> The sys_socketcall() function has a very clever system for the copy
> size of its arguments. Unfortunately, gcc cannot deal with this in
> terms of proving that the copy_from_user() is then always in bounds.
> This is the last (well 9th of this series, but last in the kernel) such
> case around.
>
> With this patch, we can turn on code to make having the boundary provably
> right for the whole kernel, and detect introduction of new security
> accidents of this type early on.
>
> Signed-off-by: Arjan van de Ven <arjan@linux.intel.com>
Applied, thanks.
^ permalink raw reply
* Re: [PATCH] isdn: fix netjet/isdnhdlc build errors
From: David Miller @ 2009-09-28 19:47 UTC (permalink / raw)
To: randy.dunlap; +Cc: torvalds, linux-kernel, keil, netdev
In-Reply-To: <20090928092520.b6f921de.randy.dunlap@oracle.com>
From: Randy Dunlap <randy.dunlap@oracle.com>
Date: Mon, 28 Sep 2009 09:25:20 -0700
> From: Randy Dunlap <randy.dunlap@oracle.com>
>
> Commit cb3824bade2549d7ad059d5802da43312540fdee didn't fix this problem.
>
> Fix build errors in netjet, using isdnhdlc module:
...
> Signed-off-by: Randy Dunlap <randy.dunlap@oracle.com>
Since Karsten has been unresonspive to ISDN stuff for weeks,
I'm going to apply this directly.
Thanks!
^ permalink raw reply
* Re: [PATCH] atm: dereference of he_dev->rbps_virt in he_init_group()
From: David Miller @ 2009-09-28 19:46 UTC (permalink / raw)
To: roel.kluin; +Cc: joe, chas, linux-atm-general, netdev, akpm
In-Reply-To: <4AC07AC3.1090707@gmail.com>
From: Roel Kluin <roel.kluin@gmail.com>
Date: Mon, 28 Sep 2009 10:58:43 +0200
> From: Juha Leppanen <juha_motorsportcom@luukku.com>
> Date: Sat, Sep 26, 2009 at 12:34 AM
> Subject: atm: he: memleak/negative indexing of arrays in he_init_group()
>
> The prefix decrement causes a very long loop if pci_pool_alloc() failed
> in the first iteration. Also I swapped rbps and rbpl arguments.
>
> Reported-by: Juha Leppanen <juha_motorsportcom@luukku.com>
> Signed-off-by: Roel Kluin <roel.kluin@gmail.com>
Applied, thanks.
Note that, by putting that From: line with Juha's info in it,
I assume that you want this person to be listed as the author
of the patch instead of you.
^ permalink raw reply
* Re: [PATCH] get rid of read/write lock in gen_estimator
From: David Miller @ 2009-09-28 19:42 UTC (permalink / raw)
To: eric.dumazet; +Cc: shemminger, netdev
In-Reply-To: <4AC10574.6070406@gmail.com>
From: Eric Dumazet <eric.dumazet@gmail.com>
Date: Mon, 28 Sep 2009 20:50:28 +0200
> Stephen Hemminger a écrit :
>> Don't need a read/write lock here sinc there already is a spin lock that
>> is being acquired.
>>
>> Signed-off-by: Stephen Hemminger <shemminger@vyatta.com>
...
>> @@ -270,9 +265,9 @@ void gen_kill_estimator(struct gnet_stat
>> while ((e = gen_find_node(bstats, rate_est))) {
>> rb_erase(&e->node, &est_root);
>>
>> - write_lock_bh(&est_lock);
>> + spin_lock(e->stats_lock);
>
> Are you sure _bh() variant is not needed here ?
Right, that need to be fixed to be spin_lock_bh() and spin_unlock_bh()
in the next hunk.
^ permalink raw reply
* Re: [PATCH] ax25: Add missing dev_put in ax25_setsockopt
From: David Miller @ 2009-09-28 19:26 UTC (permalink / raw)
To: ralf; +Cc: jarkao2, f6bvp, bernard.pidoux, netdev, linux-hams
In-Reply-To: <20090928125313.GA14250@linux-mips.org>
From: Ralf Baechle <ralf@linux-mips.org>
Date: Mon, 28 Sep 2009 13:53:13 +0100
> ax25_setsockopt SO_BINDTODEVICE is missing a dev_put call in case of
> success. Re-order code to fix this bug. While at it also reformat two
> lines of code to comply with the Linux coding style.
>
> Initial patch by Jarek Poplawski <jarkao2@gmail.com>.
>
> Reported-by: Bernard Pidoux F6BVP <f6bvp@free.fr>
> Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
>
> ---
> Counter-proposal. Reordering all the code avoids the need for a 2nd dev_put
> and is more readable.
Looks good to me, applied.
^ permalink raw reply
* Re: [PATCH] get rid of read/write lock in gen_estimator
From: Eric Dumazet @ 2009-09-28 18:50 UTC (permalink / raw)
To: Stephen Hemminger; +Cc: David Miller, netdev
In-Reply-To: <20090928113855.52eab44b@nehalam>
Stephen Hemminger a écrit :
> Don't need a read/write lock here sinc there already is a spin lock that
> is being acquired.
>
> Signed-off-by: Stephen Hemminger <shemminger@vyatta.com>
>
> --- a/net/core/gen_estimator.c 2009-09-24 16:27:01.239755070 -0700
> +++ b/net/core/gen_estimator.c 2009-09-24 16:41:09.290751273 -0700
> @@ -101,9 +101,6 @@ struct gen_estimator_head
>
> static struct gen_estimator_head elist[EST_MAX_INTERVAL+1];
>
> -/* Protects against NULL dereference */
> -static DEFINE_RWLOCK(est_lock);
> -
> /* Protects against soft lockup during large deletion */
> static struct rb_root est_root = RB_ROOT;
>
> @@ -118,9 +115,8 @@ static void est_timer(unsigned long arg)
> u64 brate;
> u32 npackets;
> u32 rate;
> -
> +
> spin_lock(e->stats_lock);
> - read_lock(&est_lock);
> if (e->bstats == NULL)
> goto skip;
>
> @@ -136,7 +132,6 @@ static void est_timer(unsigned long arg)
> e->avpps += (rate >> e->ewma_log) - (e->avpps >> e->ewma_log);
> e->rate_est->pps = (e->avpps+0x1FF)>>10;
> skip:
> - read_unlock(&est_lock);
> spin_unlock(e->stats_lock);
> }
>
> @@ -270,9 +265,9 @@ void gen_kill_estimator(struct gnet_stat
> while ((e = gen_find_node(bstats, rate_est))) {
> rb_erase(&e->node, &est_root);
>
> - write_lock_bh(&est_lock);
> + spin_lock(e->stats_lock);
Are you sure _bh() variant is not needed here ?
> e->bstats = NULL;
> - write_unlock_bh(&est_lock);
> + spin_unlock(e->stats_lock);
>
> list_del_rcu(&e->list);
> call_rcu(&e->e_rcu, __gen_kill_estimator);
^ permalink raw reply
* Re: b43 is broken in latest net-2.6 and linux-2.6
From: John W. Linville @ 2009-09-28 18:42 UTC (permalink / raw)
To: Oliver Hartkopp; +Cc: Michael Buesch, Linux Netdev List
In-Reply-To: <4AB4BF1F.7070501@hartkopp.net>
On Sat, Sep 19, 2009 at 01:23:11PM +0200, Oliver Hartkopp wrote:
> Hello Michael,
>
> my b43 wireless card (Dell 830) is not working with the latest net-2.6 (and
> also linux-2.6 2.6.31-05767-gdf58bee).
>
> net-2.6 2.6.31-03263-gc29854e is working
> net-2.6 2.6.31-03301-ga97e178 is broken
>
> I removed the patch with the work_queue stuff which did not help - so it's
> probably the other patch you added to b43 recently.
>
> Don't know ... the wlan0 link does not become ready anymore.
>
> If you need some more information - please let me know.
Is this working better now, with 2.6.31-rc1?
John
--
John W. Linville Someday the world will need a hero, and you
linville@tuxdriver.com might be all we have. Be ready.
^ 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