From 0bc8c7bf9e7440500fe04f95d6cddc58ea023cd2 Mon Sep 17 00:00:00 2001 From: Sangtae Ha Date: Thu, 28 Feb 2008 22:14:32 -0800 Subject: [PATCH 01/22] [TCP]: BIC web page link is corrected. Signed-off-by: Sangtae Ha Signed-off-by: David S. Miller --- net/ipv4/tcp_bic.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/net/ipv4/tcp_bic.c b/net/ipv4/tcp_bic.c index 5212ed9b0c98..7eb7636db0d0 100644 --- a/net/ipv4/tcp_bic.c +++ b/net/ipv4/tcp_bic.c @@ -1,12 +1,13 @@ /* * Binary Increase Congestion control for TCP - * + * Home page: + * http://netsrv.csc.ncsu.edu/twiki/bin/view/Main/BIC * This is from the implementation of BICTCP in * Lison-Xu, Kahaled Harfoush, and Injong Rhee. * "Binary Increase Congestion Control for Fast, Long Distance * Networks" in InfoComm 2004 * Available from: - * http://www.csc.ncsu.edu/faculty/rhee/export/bitcp.pdf + * http://netsrv.csc.ncsu.edu/export/bitcp.pdf * * Unless BIC is enabled and congestion window is large * this behaves the same as the original Reno. From 5e47879f493e14a017d1facefc601f43c477dbee Mon Sep 17 00:00:00 2001 From: Wang Chen Date: Fri, 29 Feb 2008 10:34:45 -0800 Subject: [PATCH 02/22] [IRDA]: Use proc_create() to setup ->proc_fops first Use proc_create() to make sure that ->proc_fops be setup before gluing PDE to main tree. Signed-off-by: Wang Chen Signed-off-by: David S. Miller --- net/irda/ircomm/ircomm_core.c | 8 +++++--- net/irda/irlan/irlan_common.c | 4 +--- net/irda/irproc.c | 8 +++----- 3 files changed, 9 insertions(+), 11 deletions(-) diff --git a/net/irda/ircomm/ircomm_core.c b/net/irda/ircomm/ircomm_core.c index b825399fc160..6eef1f2a7553 100644 --- a/net/irda/ircomm/ircomm_core.c +++ b/net/irda/ircomm/ircomm_core.c @@ -76,9 +76,11 @@ static int __init ircomm_init(void) #ifdef CONFIG_PROC_FS { struct proc_dir_entry *ent; - ent = create_proc_entry("ircomm", 0, proc_irda); - if (ent) - ent->proc_fops = &ircomm_proc_fops; + ent = proc_create("ircomm", 0, proc_irda, &ircomm_proc_fops); + if (!ent) { + printk(KERN_ERR "ircomm_init: can't create /proc entry!\n"); + return -ENODEV; + } } #endif /* CONFIG_PROC_FS */ diff --git a/net/irda/irlan/irlan_common.c b/net/irda/irlan/irlan_common.c index a4b56e25a917..1eb4bbcb1c9e 100644 --- a/net/irda/irlan/irlan_common.c +++ b/net/irda/irlan/irlan_common.c @@ -128,13 +128,11 @@ static int __init irlan_init(void) #ifdef CONFIG_PROC_FS { struct proc_dir_entry *proc; - proc = create_proc_entry("irlan", 0, proc_irda); + proc = proc_create("irlan", 0, proc_irda, &irlan_fops); if (!proc) { printk(KERN_ERR "irlan_init: can't create /proc entry!\n"); return -ENODEV; } - - proc->proc_fops = &irlan_fops; } #endif /* CONFIG_PROC_FS */ diff --git a/net/irda/irproc.c b/net/irda/irproc.c index cae24fbda966..88e80a312732 100644 --- a/net/irda/irproc.c +++ b/net/irda/irproc.c @@ -72,11 +72,9 @@ void __init irda_proc_register(void) return; proc_irda->owner = THIS_MODULE; - for (i=0; iproc_fops = irda_dirs[i].fops; - } + for (i = 0; i < ARRAY_SIZE(irda_dirs); i++) + d = proc_create(irda_dirs[i].name, 0, proc_irda, + irda_dirs[i].fops); } /* From 459eea74104ad85c30e17541c2b30d776445e985 Mon Sep 17 00:00:00 2001 From: Pavel Emelyanov Date: Fri, 29 Feb 2008 11:24:45 -0800 Subject: [PATCH 03/22] [SCTP]: Use proc_create to setup de->proc_fops. In addition to commit 160f17 ("[SCTP]: Use proc_create() to setup ->proc_fops first") use proc_create in two more places. Signed-off-by: Pavel Emelyanov Signed-off-by: David S. Miller --- net/sctp/proc.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/net/sctp/proc.c b/net/sctp/proc.c index 9e214da82d9e..973f1dbc2ec3 100644 --- a/net/sctp/proc.c +++ b/net/sctp/proc.c @@ -256,12 +256,10 @@ int __init sctp_eps_proc_init(void) { struct proc_dir_entry *p; - p = create_proc_entry("eps", S_IRUGO, proc_net_sctp); + p = proc_create("eps", S_IRUGO, proc_net_sctp, &sctp_eps_seq_fops); if (!p) return -ENOMEM; - p->proc_fops = &sctp_eps_seq_fops; - return 0; } @@ -367,12 +365,11 @@ int __init sctp_assocs_proc_init(void) { struct proc_dir_entry *p; - p = create_proc_entry("assocs", S_IRUGO, proc_net_sctp); + p = proc_create("assocs", S_IRUGO, proc_net_sctp, + &sctp_assocs_seq_fops); if (!p) return -ENOMEM; - p->proc_fops = &sctp_assocs_seq_fops; - return 0; } From 401023710d73aaef1191ab4d6a79d39c51add828 Mon Sep 17 00:00:00 2001 From: "Kim B. Heino" Date: Fri, 29 Feb 2008 12:26:21 -0800 Subject: [PATCH 04/22] [TUN]: Fix RTNL-locking in tun/tap driver Current tun/tap driver sets also net device's hw address when asked to change character device's hw address. This is a good idea, but it misses RTLN-locking, resulting following error message in 2.6.25-rc3's inetdev_event() function: RTNL: assertion failed at net/ipv4/devinet.c (1050) Attached patch fixes this problem. Signed-off-by: Kim B. Heino Signed-off-by: David S. Miller --- drivers/net/tun.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/net/tun.c b/drivers/net/tun.c index 038c1ef94d2e..7b816a032957 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c @@ -663,7 +663,11 @@ static int tun_chr_ioctl(struct inode *inode, struct file *file, case SIOCSIFHWADDR: { /* try to set the actual net device's hw address */ - int ret = dev_set_mac_address(tun->dev, &ifr.ifr_hwaddr); + int ret; + + rtnl_lock(); + ret = dev_set_mac_address(tun->dev, &ifr.ifr_hwaddr); + rtnl_unlock(); if (ret == 0) { /** Set the character device's hardware address. This is used when From d152a7d88ab4134a895f91a9e00f70d118696039 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ilpo=20J=C3=A4rvinen?= Date: Mon, 3 Mar 2008 12:10:16 -0800 Subject: [PATCH 05/22] [TCP]: Must count fack_count also when skipping MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It makes fackets_out to grow too slowly compared with the real write queue. This shouldn't cause those BUG_TRAP(packets <= tp->packets_out) to trigger but how knows how such inconsistent fackets_out affects here and there around TCP when everything is nowadays assuming accurate fackets_out. So lets see if this silences them all. Reported by Guillaume Chazarain . Signed-off-by: Ilpo Järvinen Signed-off-by: David S. Miller --- net/ipv4/tcp_input.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index 19c449f62672..7facdb0f6960 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -1367,7 +1367,7 @@ static struct sk_buff *tcp_sacktag_walk(struct sk_buff *skb, struct sock *sk, * a normal way */ static struct sk_buff *tcp_sacktag_skip(struct sk_buff *skb, struct sock *sk, - u32 skip_to_seq) + u32 skip_to_seq, int *fack_count) { tcp_for_write_queue_from(skb, sk) { if (skb == tcp_send_head(sk)) @@ -1375,6 +1375,8 @@ static struct sk_buff *tcp_sacktag_skip(struct sk_buff *skb, struct sock *sk, if (!before(TCP_SKB_CB(skb)->end_seq, skip_to_seq)) break; + + *fack_count += tcp_skb_pcount(skb); } return skb; } @@ -1390,7 +1392,7 @@ static struct sk_buff *tcp_maybe_skipping_dsack(struct sk_buff *skb, return skb; if (before(next_dup->start_seq, skip_to_seq)) { - skb = tcp_sacktag_skip(skb, sk, next_dup->start_seq); + skb = tcp_sacktag_skip(skb, sk, next_dup->start_seq, fack_count); tcp_sacktag_walk(skb, sk, NULL, next_dup->start_seq, next_dup->end_seq, 1, fack_count, reord, flag); @@ -1537,7 +1539,8 @@ tcp_sacktag_write_queue(struct sock *sk, struct sk_buff *ack_skb, /* Head todo? */ if (before(start_seq, cache->start_seq)) { - skb = tcp_sacktag_skip(skb, sk, start_seq); + skb = tcp_sacktag_skip(skb, sk, start_seq, + &fack_count); skb = tcp_sacktag_walk(skb, sk, next_dup, start_seq, cache->start_seq, @@ -1565,7 +1568,8 @@ tcp_sacktag_write_queue(struct sock *sk, struct sk_buff *ack_skb, goto walk; } - skb = tcp_sacktag_skip(skb, sk, cache->end_seq); + skb = tcp_sacktag_skip(skb, sk, cache->end_seq, + &fack_count); /* Check overlap against next cached too (past this one already) */ cache++; continue; @@ -1577,7 +1581,7 @@ tcp_sacktag_write_queue(struct sock *sk, struct sk_buff *ack_skb, break; fack_count = tp->fackets_out; } - skb = tcp_sacktag_skip(skb, sk, start_seq); + skb = tcp_sacktag_skip(skb, sk, start_seq, &fack_count); walk: skb = tcp_sacktag_walk(skb, sk, next_dup, start_seq, end_seq, From c3d84a4dd22c727f5ed64453c72183c242ac9c19 Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Mon, 3 Mar 2008 12:12:33 -0800 Subject: [PATCH 06/22] iucv: fix build error on !SMP Since a5fbb6d1064be885d2a6b82f625186753cf74848 "KVM: fix !SMP build error" smp_call_function isn't a define anymore that folds into nothing but a define that calls up_smp_call_function with all parameters. Hence we cannot #ifdef out the unused code anymore... This seems to be the preferred method, so do this for s390 as well. net/iucv/iucv.c: In function 'iucv_cleanup_queue': net/iucv/iucv.c:657: error: '__iucv_cleanup_queue' undeclared Signed-off-by: Heiko Carstens Signed-off-by: Josef 'Jeff' Sipek Signed-off-by: Ursula Braun Signed-off-by: David S. Miller --- net/iucv/iucv.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/net/iucv/iucv.c b/net/iucv/iucv.c index 2753b0c448f3..d764f4c1b7e4 100644 --- a/net/iucv/iucv.c +++ b/net/iucv/iucv.c @@ -621,7 +621,6 @@ static int iucv_sever_pathid(u16 pathid, u8 userdata[16]) return iucv_call_b2f0(IUCV_SEVER, parm); } -#ifdef CONFIG_SMP /** * __iucv_cleanup_queue * @dummy: unused dummy argument @@ -632,7 +631,6 @@ static int iucv_sever_pathid(u16 pathid, u8 userdata[16]) static void __iucv_cleanup_queue(void *dummy) { } -#endif /** * iucv_cleanup_queue From 7e36763b2c204d59de4e88087f84a2c0c8421f25 Mon Sep 17 00:00:00 2001 From: Frank Blaschka Date: Mon, 3 Mar 2008 12:16:04 -0800 Subject: [PATCH 07/22] [NET]: Fix race in generic address resolution. neigh_update sends skb from neigh->arp_queue while neigh_timer_handler has increased skbs refcount and calls solicit with the skb. neigh_timer_handler should not increase skbs refcount but make a copy of the skb and do solicit with the copy. Signed-off-by: Frank Blaschka Signed-off-by: David S. Miller --- net/core/neighbour.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/core/neighbour.c b/net/core/neighbour.c index aef01533dfb6..d9a02b2cc289 100644 --- a/net/core/neighbour.c +++ b/net/core/neighbour.c @@ -839,7 +839,7 @@ static void neigh_timer_handler(unsigned long arg) struct sk_buff *skb = skb_peek(&neigh->arp_queue); /* keep skb alive even if arp_queue overflows */ if (skb) - skb_get(skb); + skb = skb_copy(skb, GFP_ATOMIC); write_unlock(&neigh->lock); neigh->ops->solicit(neigh, skb); atomic_inc(&neigh->probes); From 8e8440f53593b5f9c695f18b493b535873dbb9da Mon Sep 17 00:00:00 2001 From: Dave Young Date: Mon, 3 Mar 2008 12:18:55 -0800 Subject: [PATCH 08/22] [BLUETOOTH]: l2cap info_timer delete fix in hci_conn_del When the l2cap info_timer is active the info_state will be set to L2CAP_INFO_FEAT_MASK_REQ_SENT, and it will be unset after the timer is deleted or timeout triggered. Here in l2cap_conn_del only call del_timer_sync when the info_state is set to L2CAP_INFO_FEAT_MASK_REQ_SENT. Signed-off-by: Dave Young Acked-by: Marcel Holtmann Signed-off-by: David S. Miller --- net/bluetooth/l2cap.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c index 7c5459c8e8ef..34f8bf98bc05 100644 --- a/net/bluetooth/l2cap.c +++ b/net/bluetooth/l2cap.c @@ -417,7 +417,8 @@ static void l2cap_conn_del(struct hci_conn *hcon, int err) l2cap_sock_kill(sk); } - del_timer_sync(&conn->info_timer); + if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) + del_timer_sync(&conn->info_timer); hcon->l2cap_data = NULL; kfree(conn); From c8fff1cf4e4e5e420c929469a09427aa37342928 Mon Sep 17 00:00:00 2001 From: Jarek Poplawski Date: Mon, 3 Mar 2008 20:48:53 -0800 Subject: [PATCH 09/22] Subject: [PPPOL2TP] add missing sock_put() in pppol2tp_recv_dequeue() Every skb removed from session->reorder_q needs sock_put(). Signed-off-by: Jarek Poplawski Acked-by: James Chapman Signed-off-by: David S. Miller --- drivers/net/pppol2tp.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/pppol2tp.c b/drivers/net/pppol2tp.c index e0b072d9fdb7..dcd499118b95 100644 --- a/drivers/net/pppol2tp.c +++ b/drivers/net/pppol2tp.c @@ -455,6 +455,7 @@ static void pppol2tp_recv_dequeue(struct pppol2tp_session *session) skb_queue_len(&session->reorder_q)); __skb_unlink(skb, &session->reorder_q); kfree_skb(skb); + sock_put(session->sock); continue; } From ec9b6add7d81f902f6094e71f595da4a362f3348 Mon Sep 17 00:00:00 2001 From: Jarek Poplawski Date: Mon, 3 Mar 2008 20:49:34 -0800 Subject: [PATCH 10/22] [PPPOL2TP]: Add missing sock_put() in pppol2tp_tunnel_closeall() Every skb removed from session->reorder_q needs sock_put(). Signed-off-by: Jarek Poplawski Acked-by: James Chapman Signed-off-by: David S. Miller --- drivers/net/pppol2tp.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/net/pppol2tp.c b/drivers/net/pppol2tp.c index dcd499118b95..86e5dba079fe 100644 --- a/drivers/net/pppol2tp.c +++ b/drivers/net/pppol2tp.c @@ -1111,6 +1111,8 @@ static void pppol2tp_tunnel_closeall(struct pppol2tp_tunnel *tunnel) for (hash = 0; hash < PPPOL2TP_HASH_SIZE; hash++) { again: hlist_for_each_safe(walk, tmp, &tunnel->session_hlist[hash]) { + struct sk_buff *skb; + session = hlist_entry(walk, struct pppol2tp_session, hlist); sk = session->sock; @@ -1139,7 +1141,10 @@ static void pppol2tp_tunnel_closeall(struct pppol2tp_tunnel *tunnel) /* Purge any queued data */ skb_queue_purge(&sk->sk_receive_queue); skb_queue_purge(&sk->sk_write_queue); - skb_queue_purge(&session->reorder_q); + while ((skb = skb_dequeue(&session->reorder_q))) { + kfree_skb(skb); + sock_put(sk); + } release_sock(sk); sock_put(sk); From d9452e9f81e997cbd0c9bface8d2c2a4b064cc3e Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Tue, 4 Mar 2008 12:28:49 -0800 Subject: [PATCH 11/22] [NETPOLL]: Revert two bogus cleanups that broke netconsole. Based upon a report by Andrew Morton and code analysis done by Jarek Poplawski. This reverts 33f807ba0d9259e7c75c7a2ce8bd2787e5b540c7 ("[NETPOLL]: Kill NETPOLL_RX_DROP, set but never tested.") and c7b6ea24b43afb5749cb704e143df19d70e23dea ("[NETPOLL]: Don't need rx_flags."). The rx_flags did get tested for zero vs. non-zero and therefore we do need those tests and that code which sets NETPOLL_RX_DROP et al. Signed-off-by: David S. Miller --- include/linux/netpoll.h | 7 ++++--- net/core/netpoll.c | 12 ++++++++---- 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/include/linux/netpoll.h b/include/linux/netpoll.h index a0525a1f4715..e3d79593fb3a 100644 --- a/include/linux/netpoll.h +++ b/include/linux/netpoll.h @@ -25,6 +25,7 @@ struct netpoll { struct netpoll_info { atomic_t refcnt; + int rx_flags; spinlock_t rx_lock; struct netpoll *rx_np; /* netpoll that registered an rx_hook */ struct sk_buff_head arp_tx; /* list of arp requests to reply to */ @@ -50,12 +51,12 @@ static inline int netpoll_rx(struct sk_buff *skb) unsigned long flags; int ret = 0; - if (!npinfo || !npinfo->rx_np) + if (!npinfo || (!npinfo->rx_np && !npinfo->rx_flags)) return 0; spin_lock_irqsave(&npinfo->rx_lock, flags); - /* check rx_np again with the lock held */ - if (npinfo->rx_np && __netpoll_rx(skb)) + /* check rx_flags again with the lock held */ + if (npinfo->rx_flags && __netpoll_rx(skb)) ret = 1; spin_unlock_irqrestore(&npinfo->rx_lock, flags); diff --git a/net/core/netpoll.c b/net/core/netpoll.c index 6faa128a4c8e..4b7e756181c9 100644 --- a/net/core/netpoll.c +++ b/net/core/netpoll.c @@ -39,6 +39,8 @@ static struct sk_buff_head skb_pool; static atomic_t trapped; #define USEC_PER_POLL 50 +#define NETPOLL_RX_ENABLED 1 +#define NETPOLL_RX_DROP 2 #define MAX_SKB_SIZE \ (MAX_UDP_CHUNK + sizeof(struct udphdr) + \ @@ -126,11 +128,13 @@ static int poll_one_napi(struct netpoll_info *npinfo, if (!test_bit(NAPI_STATE_SCHED, &napi->state)) return budget; + npinfo->rx_flags |= NETPOLL_RX_DROP; atomic_inc(&trapped); work = napi->poll(napi, budget); atomic_dec(&trapped); + npinfo->rx_flags &= ~NETPOLL_RX_DROP; return budget - work; } @@ -472,7 +476,7 @@ int __netpoll_rx(struct sk_buff *skb) if (skb->dev->type != ARPHRD_ETHER) goto out; - /* if receive ARP during middle of NAPI poll, then queue */ + /* check if netpoll clients need ARP */ if (skb->protocol == htons(ETH_P_ARP) && atomic_read(&trapped)) { skb_queue_tail(&npi->arp_tx, skb); @@ -534,9 +538,6 @@ int __netpoll_rx(struct sk_buff *skb) return 1; out: - /* If packet received while already in poll then just - * silently drop. - */ if (atomic_read(&trapped)) { kfree_skb(skb); return 1; @@ -675,6 +676,7 @@ int netpoll_setup(struct netpoll *np) goto release; } + npinfo->rx_flags = 0; npinfo->rx_np = NULL; spin_lock_init(&npinfo->rx_lock); @@ -756,6 +758,7 @@ int netpoll_setup(struct netpoll *np) if (np->rx_hook) { spin_lock_irqsave(&npinfo->rx_lock, flags); + npinfo->rx_flags |= NETPOLL_RX_ENABLED; npinfo->rx_np = np; spin_unlock_irqrestore(&npinfo->rx_lock, flags); } @@ -797,6 +800,7 @@ void netpoll_cleanup(struct netpoll *np) if (npinfo->rx_np == np) { spin_lock_irqsave(&npinfo->rx_lock, flags); npinfo->rx_np = NULL; + npinfo->rx_flags &= ~NETPOLL_RX_ENABLED; spin_unlock_irqrestore(&npinfo->rx_lock, flags); } From 7adc3830f90df04a13366914d80a3ed407db5381 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Tue, 4 Mar 2008 14:28:41 -0800 Subject: [PATCH 12/22] [TCP]: Improve ipv4 established hash function. If all of the entropy is in the local and foreign addresses, but xor'ing together would cancel out that entropy, the current hash performs poorly. Suggested by Cosmin Ratiu: Basically, the situation is as follows: There is a client machine and a server machine. Both create 15000 virtual interfaces, open up a socket for each pair of interfaces and do SIP traffic. By profiling I noticed that there is a lot of time spent walking the established hash chains with this particular setup. The addresses were distributed like this: client interfaces were 198.18.0.1/16 with increments of 1 and server interfaces were 198.18.128.1/16 with increments of 1. As I said, there were 15000 interfaces. Source and destination ports were 5060 for each connection. So in this case, ports don't matter for hashing purposes, and the bits from the address pairs used cancel each other, meaning there are no differences in the whole lot of pairs, so they all end up in the same hash chain. Signed-off-by: David S. Miller --- include/net/inet_sock.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/include/net/inet_sock.h b/include/net/inet_sock.h index 70013c5f4e59..89cd011edb99 100644 --- a/include/net/inet_sock.h +++ b/include/net/inet_sock.h @@ -175,7 +175,8 @@ extern void build_ehash_secret(void); static inline unsigned int inet_ehashfn(const __be32 laddr, const __u16 lport, const __be32 faddr, const __be16 fport) { - return jhash_2words((__force __u32) laddr ^ (__force __u32) faddr, + return jhash_3words((__force __u32) laddr, + (__force __u32) faddr, ((__u32) lport) << 16 | (__force __u32)fport, inet_ehash_secret); } From ed58dd41f3aeefc11a7f634db90687f92ea8632e Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Tue, 4 Mar 2008 14:29:21 -0800 Subject: [PATCH 13/22] [ESP]: Add select on AUTHENC Now the ESP uses the AEAD interface even for algorithms which are not combined mode, we need to select CONFIG_CRYPTO_AUTHENC as otherwise only combined mode algorithms will work. Signed-off-by: Herbert Xu Signed-off-by: David S. Miller --- net/ipv4/Kconfig | 2 +- net/ipv6/Kconfig | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/net/ipv4/Kconfig b/net/ipv4/Kconfig index 19880b086e71..9c7e5ffb223d 100644 --- a/net/ipv4/Kconfig +++ b/net/ipv4/Kconfig @@ -343,7 +343,7 @@ config INET_ESP tristate "IP: ESP transformation" select XFRM select CRYPTO - select CRYPTO_AEAD + select CRYPTO_AUTHENC select CRYPTO_HMAC select CRYPTO_MD5 select CRYPTO_CBC diff --git a/net/ipv6/Kconfig b/net/ipv6/Kconfig index 3ffb0323668c..58219dfffef8 100644 --- a/net/ipv6/Kconfig +++ b/net/ipv6/Kconfig @@ -85,7 +85,7 @@ config INET6_ESP depends on IPV6 select XFRM select CRYPTO - select CRYPTO_AEAD + select CRYPTO_AUTHENC select CRYPTO_HMAC select CRYPTO_MD5 select CRYPTO_CBC From 1d60ab0574fae362b1cca0ef52181ef75fd46832 Mon Sep 17 00:00:00 2001 From: Stefano Brivio Date: Sun, 2 Mar 2008 11:33:10 +0100 Subject: [PATCH 14/22] rc80211-pid: fix rate adjustment Merge rate_control_pid_shift_adjust() to rate_control_pid_adjust_rate() in order to make the learning algorithm aware of constraints on rates. Also add some comments and rename variables. This fixes a bug which prevented 802.11b/g non-AP STAs from working with 802.11b only AP STAs. This patch was originally destined for 2.6.26, and is being backported to fix a user reported problem in post-2.6.24 kernels. Signed-off-by: Stefano Brivio Signed-off-by: John W. Linville --- net/mac80211/rc80211_pid_algo.c | 92 +++++++++++++++------------------ 1 file changed, 43 insertions(+), 49 deletions(-) diff --git a/net/mac80211/rc80211_pid_algo.c b/net/mac80211/rc80211_pid_algo.c index c339571632b2..3b77410588e7 100644 --- a/net/mac80211/rc80211_pid_algo.c +++ b/net/mac80211/rc80211_pid_algo.c @@ -2,7 +2,7 @@ * Copyright 2002-2005, Instant802 Networks, Inc. * Copyright 2005, Devicescape Software, Inc. * Copyright 2007, Mattias Nissler - * Copyright 2007, Stefano Brivio + * Copyright 2007-2008, Stefano Brivio * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -63,72 +63,66 @@ * RC_PID_ARITH_SHIFT. */ - -/* Shift the adjustment so that we won't switch to a lower rate if it exhibited - * a worse failed frames behaviour and we'll choose the highest rate whose - * failed frames behaviour is not worse than the one of the original rate - * target. While at it, check that the adjustment is within the ranges. Then, - * provide the new rate index. */ -static int rate_control_pid_shift_adjust(struct rc_pid_rateinfo *r, - int adj, int cur, int l) -{ - int i, j, k, tmp; - - j = r[cur].rev_index; - i = j + adj; - - if (i < 0) - return r[0].index; - if (i >= l - 1) - return r[l - 1].index; - - tmp = i; - - if (adj < 0) { - for (k = j; k >= i; k--) - if (r[k].diff <= r[j].diff) - tmp = k; - } else { - for (k = i + 1; k + i < l; k++) - if (r[k].diff <= r[i].diff) - tmp = k; - } - - return r[tmp].index; -} - +/* Adjust the rate while ensuring that we won't switch to a lower rate if it + * exhibited a worse failed frames behaviour and we'll choose the highest rate + * whose failed frames behaviour is not worse than the one of the original rate + * target. While at it, check that the new rate is valid. */ static void rate_control_pid_adjust_rate(struct ieee80211_local *local, struct sta_info *sta, int adj, struct rc_pid_rateinfo *rinfo) { struct ieee80211_sub_if_data *sdata; struct ieee80211_hw_mode *mode; - int newidx; - int maxrate; - int back = (adj > 0) ? 1 : -1; + int cur_sorted, new_sorted, probe, tmp, n_bitrates; + int cur = sta->txrate; sdata = IEEE80211_DEV_TO_SUB_IF(sta->dev); mode = local->oper_hw_mode; - maxrate = sdata->bss ? sdata->bss->max_ratectrl_rateidx : -1; + n_bitrates = mode->num_rates; - newidx = rate_control_pid_shift_adjust(rinfo, adj, sta->txrate, - mode->num_rates); + /* Map passed arguments to sorted values. */ + cur_sorted = rinfo[cur].rev_index; + new_sorted = cur_sorted + adj; - while (newidx != sta->txrate) { - if (rate_supported(sta, mode, newidx) && - (maxrate < 0 || newidx <= maxrate)) { - sta->txrate = newidx; + /* Check limits. */ + if (new_sorted < 0) + new_sorted = rinfo[0].rev_index; + else if (new_sorted >= n_bitrates) + new_sorted = rinfo[n_bitrates - 1].rev_index; + + tmp = new_sorted; + + if (adj < 0) { + /* Ensure that the rate decrease isn't disadvantageous. */ + for (probe = cur_sorted; probe >= new_sorted; probe--) + if (rinfo[probe].diff <= rinfo[cur_sorted].diff && + rate_supported(sta, mode, rinfo[probe].index)) + tmp = probe; + } else { + /* Look for rate increase with zero (or below) cost. */ + for (probe = new_sorted + 1; probe < n_bitrates; probe++) + if (rinfo[probe].diff <= rinfo[new_sorted].diff && + rate_supported(sta, mode, rinfo[probe].index)) + tmp = probe; + } + + /* Fit the rate found to the nearest supported rate. */ + do { + if (rate_supported(sta, mode, rinfo[tmp].index)) { + sta->txrate = rinfo[tmp].index; break; } - - newidx += back; - } + if (adj < 0) + tmp--; + else + tmp++; + } while (tmp < n_bitrates && tmp >= 0); #ifdef CONFIG_MAC80211_DEBUGFS rate_control_pid_event_rate_change( &((struct rc_pid_sta_info *)sta->rate_ctrl_priv)->events, - newidx, mode->rates[newidx].rate); + cur, mode->rates[cur].rate); #endif } From dc63644b0ee3b447e879ef8e124657b40e9ea81c Mon Sep 17 00:00:00 2001 From: Yoichi Yuasa Date: Fri, 29 Feb 2008 11:09:31 +0100 Subject: [PATCH 15/22] ssb: Add pcibios_enable_device() return value check This patch has added pcibios_enable_device() return value check. Signed-off-by: Yoichi Yuasa Signed-off-by: Michael Buesch Signed-off-by: John W. Linville --- drivers/ssb/driver_pcicore.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/ssb/driver_pcicore.c b/drivers/ssb/driver_pcicore.c index 07ab48d9ceab..74b9a8aea52b 100644 --- a/drivers/ssb/driver_pcicore.c +++ b/drivers/ssb/driver_pcicore.c @@ -111,7 +111,10 @@ static void __init ssb_fixup_pcibridge(struct pci_dev *dev) /* Enable PCI bridge bus mastering and memory space */ pci_set_master(dev); - pcibios_enable_device(dev, ~0); + if (pcibios_enable_device(dev, ~0) < 0) { + ssb_printk(KERN_ERR "PCI: SSB bridge enable failed\n"); + return; + } /* Enable PCI bridge BAR1 prefetch and burst */ pci_write_config_dword(dev, SSB_BAR1_CONTROL, 3); From 8c28293f5514f64ba064bac7946aebeda4a663c6 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 29 Feb 2008 13:56:33 +0100 Subject: [PATCH 16/22] p54: fix EEPROM structure endianness Since the EEPROM structure is read from hardware, it is always little endian, annotate that in the struct and make sure to convert where applicable. Signed-off-by: Johannes Berg Cc: Michael Wu Tested-by: Florian Fainelli Signed-off-by: John W. Linville --- drivers/net/wireless/p54common.c | 2 +- drivers/net/wireless/p54common.h | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/net/wireless/p54common.c b/drivers/net/wireless/p54common.c index 5cda49aff3a8..56aabec73c20 100644 --- a/drivers/net/wireless/p54common.c +++ b/drivers/net/wireless/p54common.c @@ -172,7 +172,7 @@ int p54_parse_eeprom(struct ieee80211_hw *dev, void *eeprom, int len) int err; wrap = (struct eeprom_pda_wrap *) eeprom; - entry = (void *)wrap->data + wrap->len; + entry = (void *)wrap->data + le16_to_cpu(wrap->len); i += 2; i += le16_to_cpu(entry->len)*2; while (i < len) { diff --git a/drivers/net/wireless/p54common.h b/drivers/net/wireless/p54common.h index a721334e20d9..b67ff34e26fe 100644 --- a/drivers/net/wireless/p54common.h +++ b/drivers/net/wireless/p54common.h @@ -53,10 +53,10 @@ struct pda_entry { } __attribute__ ((packed)); struct eeprom_pda_wrap { - u32 magic; - u16 pad; - u16 len; - u32 arm_opcode; + __le32 magic; + __le16 pad; + __le16 len; + __le32 arm_opcode; u8 data[0]; } __attribute__ ((packed)); From c2f2d3a06f8b628d444cf4f396d6c6ddd47e1d1f Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 29 Feb 2008 23:28:25 +0100 Subject: [PATCH 17/22] p54: fix eeprom parser length sanity checks When I called p54_parse_eeprom() on a hand-coded structure I managed to make a small mistake with wrap->len which caused a segfault a few lines down when trying to read entry->len. This patch changes the validation code to avoid such problems. Signed-off-by: Johannes Berg Tested-by: Florian Fainelli Signed-off-by: John W. Linville --- drivers/net/wireless/p54common.c | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/drivers/net/wireless/p54common.c b/drivers/net/wireless/p54common.c index 56aabec73c20..d191e055a788 100644 --- a/drivers/net/wireless/p54common.c +++ b/drivers/net/wireless/p54common.c @@ -166,18 +166,23 @@ int p54_parse_eeprom(struct ieee80211_hw *dev, void *eeprom, int len) struct p54_common *priv = dev->priv; struct eeprom_pda_wrap *wrap = NULL; struct pda_entry *entry; - int i = 0; unsigned int data_len, entry_len; void *tmp; int err; + u8 *end = (u8 *)eeprom + len; wrap = (struct eeprom_pda_wrap *) eeprom; entry = (void *)wrap->data + le16_to_cpu(wrap->len); - i += 2; - i += le16_to_cpu(entry->len)*2; - while (i < len) { + + /* verify that at least the entry length/code fits */ + while ((u8 *)entry <= end - sizeof(*entry)) { entry_len = le16_to_cpu(entry->len); data_len = ((entry_len - 1) << 1); + + /* abort if entry exceeds whole structure */ + if ((u8 *)entry + sizeof(*entry) + data_len > end) + break; + switch (le16_to_cpu(entry->code)) { case PDR_MAC_ADDRESS: SET_IEEE80211_PERM_ADDR(dev, entry->data); @@ -249,13 +254,12 @@ int p54_parse_eeprom(struct ieee80211_hw *dev, void *eeprom, int len) priv->version = *(u8 *)(entry->data + 1); break; case PDR_END: - i = len; + /* make it overrun */ + entry_len = len; break; } entry = (void *)entry + (entry_len + 1)*2; - i += 2; - i += entry_len*2; } if (!priv->iq_autocal || !priv->output_limit || !priv->curve_data) { From 6305f498604df6c66bdb4cc533ce6332fa5ab61f Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Mon, 3 Mar 2008 12:20:12 +0100 Subject: [PATCH 18/22] libertas: fix sanity check on sequence number in command response Slightly more useful if we compare it against the sequence number of the command we have outstanding, rather than comparing the reply with itself. Doh. Pointed out by Sebastian Siewior Signed-off-by: David Woodhouse Acked-by: Dan Williams Signed-off-by: John W. Linville --- drivers/net/wireless/libertas/cmdresp.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/libertas/cmdresp.c b/drivers/net/wireless/libertas/cmdresp.c index 159216a91903..e2b0746c6cb9 100644 --- a/drivers/net/wireless/libertas/cmdresp.c +++ b/drivers/net/wireless/libertas/cmdresp.c @@ -572,9 +572,9 @@ int lbs_process_rx_command(struct lbs_private *priv) respcmd, le16_to_cpu(resp->seqnum), priv->upld_len, jiffies); lbs_deb_hex(LBS_DEB_HOST, "CMD_RESP", (void *) resp, priv->upld_len); - if (resp->seqnum != resp->seqnum) { + if (resp->seqnum != priv->cur_cmd->cmdbuf->seqnum) { lbs_pr_info("Received CMD_RESP with invalid sequence %d (expected %d)\n", - le16_to_cpu(resp->seqnum), le16_to_cpu(resp->seqnum)); + le16_to_cpu(resp->seqnum), le16_to_cpu(priv->cur_cmd->cmdbuf->seqnum)); spin_unlock_irqrestore(&priv->driver_lock, flags); ret = -1; goto done; From 8a96df80b3ddb2410045a26ea19eeccb5f2d2d11 Mon Sep 17 00:00:00 2001 From: Sebastian Siewior Date: Tue, 4 Mar 2008 18:22:27 +0100 Subject: [PATCH 19/22] libertas: compare the current command with response instead of with itself. Signed-off-by: Sebastian Siewior Signed-off-by: John W. Linville --- drivers/net/wireless/libertas/cmdresp.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/net/wireless/libertas/cmdresp.c b/drivers/net/wireless/libertas/cmdresp.c index e2b0746c6cb9..bdc6a1cc2103 100644 --- a/drivers/net/wireless/libertas/cmdresp.c +++ b/drivers/net/wireless/libertas/cmdresp.c @@ -562,9 +562,7 @@ int lbs_process_rx_command(struct lbs_private *priv) } resp = (void *)priv->upld_buf; - - curcmd = le16_to_cpu(resp->command); - + curcmd = le16_to_cpu(priv->cur_cmd->cmdbuf->command); respcmd = le16_to_cpu(resp->command); result = le16_to_cpu(resp->result); From cdb2a9fe63575dd1eb82b724bbd0aa5e0dd89fa0 Mon Sep 17 00:00:00 2001 From: Jussi Kivilinna Date: Tue, 4 Mar 2008 20:05:27 +0200 Subject: [PATCH 20/22] rndis_wlan: fix broken data copy Replace broken code that attempted to copy 6 byte array to 64-bit integer. Due to missing cast to 64-bit integer, left shift operation were 32-bit and lead to bytes been copied over each other. New code uses simple memcpy, for greater readability and efficiency. Signed-off-by: Jussi Kivilinna Signed-off-by: John W. Linville --- drivers/net/wireless/rndis_wlan.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/drivers/net/wireless/rndis_wlan.c b/drivers/net/wireless/rndis_wlan.c index d9460aed1f22..10b776c1adc5 100644 --- a/drivers/net/wireless/rndis_wlan.c +++ b/drivers/net/wireless/rndis_wlan.c @@ -260,7 +260,7 @@ struct NDIS_802_11_KEY { __le32 KeyLength; u8 Bssid[6]; u8 Padding[6]; - __le64 KeyRSC; + u8 KeyRSC[8]; u8 KeyMaterial[32]; } __attribute__((packed)); @@ -1508,7 +1508,7 @@ static int rndis_iw_set_encode_ext(struct net_device *dev, struct usbnet *usbdev = dev->priv; struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev); struct NDIS_802_11_KEY ndis_key; - int i, keyidx, ret; + int keyidx, ret; u8 *addr; keyidx = wrqu->encoding.flags & IW_ENCODE_INDEX; @@ -1543,9 +1543,7 @@ static int rndis_iw_set_encode_ext(struct net_device *dev, ndis_key.KeyIndex = cpu_to_le32(keyidx); if (ext->ext_flags & IW_ENCODE_EXT_RX_SEQ_VALID) { - for (i = 0; i < 6; i++) - ndis_key.KeyRSC |= - cpu_to_le64(ext->rx_seq[i] << (i * 8)); + memcpy(ndis_key.KeyRSC, ext->rx_seq, 6); ndis_key.KeyIndex |= cpu_to_le32(1 << 29); } From c256e05b7b30fab484deacb4f8cff59ce649c75e Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Tue, 4 Mar 2008 20:31:13 +0100 Subject: [PATCH 21/22] b43legacy: Fix module init message This fixes the module init message to tell that the legacy driver loaded. This makes it less confusing, in case both drivers are loaded. Signed-off-by: Michael Buesch Signed-off-by: John W. Linville --- drivers/net/wireless/b43legacy/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/b43legacy/main.c b/drivers/net/wireless/b43legacy/main.c index c39de422e220..5f3f34e1dbfd 100644 --- a/drivers/net/wireless/b43legacy/main.c +++ b/drivers/net/wireless/b43legacy/main.c @@ -3829,7 +3829,7 @@ static void b43legacy_print_driverinfo(void) #ifdef CONFIG_B43LEGACY_DMA feat_dma = "D"; #endif - printk(KERN_INFO "Broadcom 43xx driver loaded " + printk(KERN_INFO "Broadcom 43xx-legacy driver loaded " "[ Features: %s%s%s%s%s, Firmware-ID: " B43legacy_SUPPORTED_FIRMWARE_ID " ]\n", feat_pci, feat_leds, feat_rfkill, feat_pio, feat_dma); From dea75bdfa57f75a7a7ec2961ec28db506c18e5db Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Tue, 4 Mar 2008 17:03:49 -0800 Subject: [PATCH 22/22] [IPCONFIG]: The kernel gets no IP from some DHCP servers From: Stephen Hemminger Based upon a patch by Marcel Wappler: This patch fixes a DHCP issue of the kernel: some DHCP servers (i.e. in the Linksys WRT54Gv5) are very strict about the contents of the DHCPDISCOVER packet they receive from clients. Table 5 in RFC2131 page 36 requests the fields 'ciaddr' and 'siaddr' MUST be set to '0'. These DHCP servers ignore Linux kernel's DHCP discovery packets with these two fields set to '255.255.255.255' (in contrast to popular DHCP clients, such as 'dhclient' or 'udhcpc'). This leads to a not booting system. Signed-off-by: David S. Miller --- net/ipv4/ipconfig.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/net/ipv4/ipconfig.c b/net/ipv4/ipconfig.c index 10013ccee8dd..5dd938579eeb 100644 --- a/net/ipv4/ipconfig.c +++ b/net/ipv4/ipconfig.c @@ -753,9 +753,9 @@ static void __init ic_bootp_send_if(struct ic_device *d, unsigned long jiffies_d printk("Unknown ARP type 0x%04x for device %s\n", dev->type, dev->name); b->htype = dev->type; /* can cause undefined behavior */ } + + /* server_ip and your_ip address are both already zero per RFC2131 */ b->hlen = dev->addr_len; - b->your_ip = NONE; - b->server_ip = NONE; memcpy(b->hw_addr, dev->dev_addr, dev->addr_len); b->secs = htons(jiffies_diff / HZ); b->xid = d->xid;