From aea7427f70cce5fa8f99ce447b213e9e3b49f24c Mon Sep 17 00:00:00 2001 From: Shan Wei Date: Thu, 19 Jun 2008 16:29:39 -0700 Subject: ipv6: Remove options header when setsockopt's optlen is 0 Remove the sticky Hop-by-Hop options header by calling setsockopt() for IPV6_HOPOPTS with a zero option length, per RFC3542. Routing header and Destination options header does the same as Hop-by-Hop options header. Signed-off-by: Shan Wei Acked-by: YOSHIFUJI Hideaki Signed-off-by: David S. Miller diff --git a/net/ipv6/ipv6_sockglue.c b/net/ipv6/ipv6_sockglue.c index c042ce1..86e28a7 100644 --- a/net/ipv6/ipv6_sockglue.c +++ b/net/ipv6/ipv6_sockglue.c @@ -345,18 +345,21 @@ static int do_ipv6_setsockopt(struct sock *sk, int level, int optname, case IPV6_DSTOPTS: { struct ipv6_txoptions *opt; + + /* remove any sticky options header with a zero option + * length, per RFC3542. + */ if (optlen == 0) optval = NULL; + else if (optlen < sizeof(struct ipv6_opt_hdr) || + optlen & 0x7 || optlen > 8 * 255) + goto e_inval; /* hop-by-hop / destination options are privileged option */ retv = -EPERM; if (optname != IPV6_RTHDR && !capable(CAP_NET_RAW)) break; - if (optlen < sizeof(struct ipv6_opt_hdr) || - optlen & 0x7 || optlen > 8 * 255) - goto e_inval; - opt = ipv6_renew_options(sk, np->opt, optname, (struct ipv6_opt_hdr __user *)optval, optlen); -- cgit v0.10.2 From f630e43a215a3129d0c1173cae0bce6ea4855cf7 Mon Sep 17 00:00:00 2001 From: YOSHIFUJI Hideaki Date: Thu, 19 Jun 2008 16:33:57 -0700 Subject: ipv6: Drop packets for loopback address from outside of the box. [ Based upon original report and patch by Karsten Keil. Karsten has verified that this fixes the TAHI test case "ICMPv6 test v6LC.5.1.2 Part F". -DaveM ] Signed-off-by: YOSHIFUJI Hideaki Signed-off-by: David S. Miller diff --git a/include/net/ipv6.h b/include/net/ipv6.h index e0a612b..f422f72 100644 --- a/include/net/ipv6.h +++ b/include/net/ipv6.h @@ -367,6 +367,12 @@ static inline int ipv6_addr_any(const struct in6_addr *a) a->s6_addr32[2] | a->s6_addr32[3] ) == 0); } +static inline int ipv6_addr_loopback(const struct in6_addr *a) +{ + return ((a->s6_addr32[0] | a->s6_addr32[1] | + a->s6_addr32[2] | (a->s6_addr32[3] ^ htonl(1))) == 0); +} + static inline int ipv6_addr_v4mapped(const struct in6_addr *a) { return ((a->s6_addr32[0] | a->s6_addr32[1] | diff --git a/net/ipv6/ip6_input.c b/net/ipv6/ip6_input.c index 4e5c861..17eb48b 100644 --- a/net/ipv6/ip6_input.c +++ b/net/ipv6/ip6_input.c @@ -102,6 +102,15 @@ int ipv6_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt if (hdr->version != 6) goto err; + /* + * RFC4291 2.5.3 + * A packet received on an interface with a destination address + * of loopback must be dropped. + */ + if (!(dev->flags & IFF_LOOPBACK) && + ipv6_addr_loopback(&hdr->daddr)) + goto err; + skb->transport_header = skb->network_header + sizeof(*hdr); IP6CB(skb)->nhoff = offsetof(struct ipv6hdr, nexthdr); -- cgit v0.10.2 From 2645a3c3761ac25498db2e627271016c849c68e1 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Fri, 20 Jun 2008 21:58:02 -0700 Subject: pppoe: warning fix Fix warning: drivers/net/pppoe.c: In function 'pppoe_recvmsg': drivers/net/pppoe.c:945: warning: comparison of distinct pointer types lacks a cast because skb->len is unsigned int and total_len is size_t Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller diff --git a/drivers/net/pppoe.c b/drivers/net/pppoe.c index bafb69b..fc6f4b8 100644 --- a/drivers/net/pppoe.c +++ b/drivers/net/pppoe.c @@ -942,7 +942,7 @@ static int pppoe_recvmsg(struct kiocb *iocb, struct socket *sock, m->msg_namelen = 0; if (skb) { - total_len = min(total_len, skb->len); + total_len = min_t(size_t, total_len, skb->len); error = skb_copy_datagram_iovec(skb, 0, m->msg_iov, total_len); if (error == 0) error = total_len; -- cgit v0.10.2 From 735ce972fbc8a65fb17788debd7bbe7b4383cc62 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Fri, 20 Jun 2008 22:04:34 -0700 Subject: sctp: Make sure N * sizeof(union sctp_addr) does not overflow. As noticed by Gabriel Campana, the kmalloc() length arg passed in by sctp_getsockopt_local_addrs_old() can overflow if ->addr_num is large enough. Therefore, enforce an appropriate limit. Signed-off-by: David S. Miller diff --git a/net/sctp/socket.c b/net/sctp/socket.c index e7e3baf..0dbcde6 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c @@ -4401,7 +4401,9 @@ static int sctp_getsockopt_local_addrs_old(struct sock *sk, int len, if (copy_from_user(&getaddrs, optval, len)) return -EFAULT; - if (getaddrs.addr_num <= 0) return -EINVAL; + if (getaddrs.addr_num <= 0 || + getaddrs.addr_num >= (INT_MAX / sizeof(union sctp_addr))) + return -EINVAL; /* * For UDP-style sockets, id specifies the association to query. * If the id field is set to the value '0' then the locally bound -- cgit v0.10.2 From b9f75f45a6b46a0ab4eb0857d437a0845871f314 Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Fri, 20 Jun 2008 22:16:51 -0700 Subject: netns: Don't receive new packets in a dead network namespace. Alexey Dobriyan writes: > Subject: ICMP sockets destruction vs ICMP packets oops > After icmp_sk_exit() nuked ICMP sockets, we get an interrupt. > icmp_reply() wants ICMP socket. > > Steps to reproduce: > > launch shell in new netns > move real NIC to netns > setup routing > ping -i 0 > exit from shell > > BUG: unable to handle kernel NULL pointer dereference at 0000000000000000 > IP: [] icmp_sk+0x17/0x30 > PGD 17f3cd067 PUD 17f3ce067 PMD 0 > Oops: 0000 [1] PREEMPT SMP DEBUG_PAGEALLOC > CPU 0 > Modules linked in: usblp usbcore > Pid: 0, comm: swapper Not tainted 2.6.26-rc6-netns-ct #4 > RIP: 0010:[] [] icmp_sk+0x17/0x30 > RSP: 0018:ffffffff8057fc30 EFLAGS: 00010286 > RAX: 0000000000000000 RBX: 0000000000000000 RCX: ffff81017c7db900 > RDX: 0000000000000034 RSI: ffff81017c7db900 RDI: ffff81017dc41800 > RBP: ffffffff8057fc40 R08: 0000000000000001 R09: 000000000000a815 > R10: 0000000000000000 R11: 0000000000000001 R12: ffffffff8057fd28 > R13: ffffffff8057fd00 R14: ffff81017c7db938 R15: ffff81017dc41800 > FS: 0000000000000000(0000) GS:ffffffff80525000(0000) knlGS:0000000000000000 > CS: 0010 DS: 0018 ES: 0018 CR0: 000000008005003b > CR2: 0000000000000000 CR3: 000000017fcda000 CR4: 00000000000006e0 > DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 > DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400 > Process swapper (pid: 0, threadinfo ffffffff8053a000, task ffffffff804fa4a0) > Stack: 0000000000000000 ffff81017c7db900 ffffffff8057fcf0 ffffffff803fcfe4 > ffffffff804faa38 0000000000000246 0000000000005a40 0000000000000246 > 000000000001ffff ffff81017dd68dc0 0000000000005a40 0000000055342436 > Call Trace: > [] icmp_reply+0x44/0x1e0 > [] ? ip_route_input+0x23a/0x1360 > [] icmp_echo+0x65/0x70 > [] icmp_rcv+0x180/0x1b0 > [] ip_local_deliver+0xf4/0x1f0 > [] ip_rcv+0x33b/0x650 > [] netif_receive_skb+0x27a/0x340 > [] process_backlog+0x9d/0x100 > [] net_rx_action+0x18d/0x250 > [] __do_softirq+0x75/0x100 > [] call_softirq+0x1c/0x30 > [] do_softirq+0x65/0xa0 > [] irq_exit+0x97/0xa0 > [] do_IRQ+0xa8/0x130 > [] ? mwait_idle+0x0/0x60 > [] ret_from_intr+0x0/0xf > [] ? mwait_idle+0x4c/0x60 > [] ? mwait_idle+0x43/0x60 > [] ? cpu_idle+0x57/0xa0 > [] ? rest_init+0x70/0x80 > Code: 10 5b 41 5c 41 5d 41 5e c9 c3 66 2e 0f 1f 84 00 00 00 00 00 55 48 89 e5 53 > 48 83 ec 08 48 8b 9f 78 01 00 00 e8 2b c7 f1 ff 89 c0 <48> 8b 04 c3 48 83 c4 08 > 5b c9 c3 66 66 66 66 66 2e 0f 1f 84 00 > RIP [] icmp_sk+0x17/0x30 > RSP > CR2: 0000000000000000 > ---[ end trace ea161157b76b33e8 ]--- > Kernel panic - not syncing: Aiee, killing interrupt handler! Receiving packets while we are cleaning up a network namespace is a racy proposition. It is possible when the packet arrives that we have removed some but not all of the state we need to fully process it. We have the choice of either playing wack-a-mole with the cleanup routines or simply dropping packets when we don't have a network namespace to handle them. Since the check looks inexpensive in netif_receive_skb let's just drop the incoming packets. Signed-off-by: Eric W. Biederman Signed-off-by: David S. Miller diff --git a/include/net/net_namespace.h b/include/net/net_namespace.h index aa540e6..d9dd0f7 100644 --- a/include/net/net_namespace.h +++ b/include/net/net_namespace.h @@ -95,6 +95,11 @@ extern struct list_head net_namespace_list; #ifdef CONFIG_NET_NS extern void __put_net(struct net *net); +static inline int net_alive(struct net *net) +{ + return net && atomic_read(&net->count); +} + static inline struct net *get_net(struct net *net) { atomic_inc(&net->count); @@ -125,6 +130,12 @@ int net_eq(const struct net *net1, const struct net *net2) return net1 == net2; } #else + +static inline int net_alive(struct net *net) +{ + return 1; +} + static inline struct net *get_net(struct net *net) { return net; diff --git a/net/core/dev.c b/net/core/dev.c index 68d8df0..c421a1f 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -2077,6 +2077,10 @@ int netif_receive_skb(struct sk_buff *skb) rcu_read_lock(); + /* Don't receive packets in an exiting network namespace */ + if (!net_alive(dev_net(skb->dev))) + goto out; + #ifdef CONFIG_NET_CLS_ACT if (skb->tc_verd & TC_NCLS) { skb->tc_verd = CLR_TC_NCLS(skb->tc_verd); diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c index 72b4c18..7c52fe2 100644 --- a/net/core/net_namespace.c +++ b/net/core/net_namespace.c @@ -140,6 +140,9 @@ static void cleanup_net(struct work_struct *work) struct pernet_operations *ops; struct net *net; + /* Be very certain incoming network packets will not find us */ + rcu_barrier(); + net = container_of(work, struct net, work); mutex_lock(&net_mutex); -- cgit v0.10.2 From 88a6f4ad76be425f47df7f892baf913bcd466fb3 Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Tue, 24 Jun 2008 13:30:45 -0700 Subject: netfilter: ip6table_mangle: don't reroute in LOCAL_IN Rerouting should only happen in LOCAL_OUT, in INPUT its useless since the packet has already chosen its final destination. Noticed by Alexey Dobriyan . Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller diff --git a/net/ipv6/netfilter/ip6table_mangle.c b/net/ipv6/netfilter/ip6table_mangle.c index 27a5e8b..f405cea 100644 --- a/net/ipv6/netfilter/ip6table_mangle.c +++ b/net/ipv6/netfilter/ip6table_mangle.c @@ -129,7 +129,7 @@ static struct nf_hook_ops ip6t_ops[] __read_mostly = { .priority = NF_IP6_PRI_MANGLE, }, { - .hook = ip6t_local_hook, + .hook = ip6t_route_hook, .owner = THIS_MODULE, .pf = PF_INET6, .hooknum = NF_INET_LOCAL_IN, -- cgit v0.10.2 From 59d393ad92f719d9ef36b96eae56d4817a7eeb10 Mon Sep 17 00:00:00 2001 From: Tony Vroon Date: Wed, 11 Jun 2008 16:23:56 -0400 Subject: mac80211: implement EU regulatory domain Implement missing EU regulatory domain for mac80211. Based on the information in IEEE 802.11-2007 (specifically pages 1142, 1143 & 1148) and ETSI 301 893 (V1.4.1). With thanks to Johannes Berg. Signed-off-by: Tony Vroon Acked-by: Johannes Berg Signed-off-by: John W. Linville diff --git a/net/wireless/reg.c b/net/wireless/reg.c index 185488d..855bff4 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c @@ -80,6 +80,23 @@ static const struct ieee80211_channel_range ieee80211_JP_channels[] = { IEEE80211_CHAN_RADAR), }; +static const struct ieee80211_channel_range ieee80211_EU_channels[] = { + /* IEEE 802.11b/g, channels 1..13 */ + RANGE_PWR(2412, 2472, 20, 6, 0), + /* IEEE 802.11a, channel 36*/ + RANGE_PWR(5180, 5180, 23, 6, IEEE80211_CHAN_PASSIVE_SCAN), + /* IEEE 802.11a, channel 40*/ + RANGE_PWR(5200, 5200, 23, 6, IEEE80211_CHAN_PASSIVE_SCAN), + /* IEEE 802.11a, channel 44*/ + RANGE_PWR(5220, 5220, 23, 6, IEEE80211_CHAN_PASSIVE_SCAN), + /* IEEE 802.11a, channels 48..64 */ + RANGE_PWR(5240, 5320, 23, 6, IEEE80211_CHAN_NO_IBSS | + IEEE80211_CHAN_RADAR), + /* IEEE 802.11a, channels 100..140 */ + RANGE_PWR(5500, 5700, 30, 6, IEEE80211_CHAN_NO_IBSS | + IEEE80211_CHAN_RADAR), +}; + #define REGDOM(_code) \ { \ .code = __stringify(_code), \ @@ -90,6 +107,7 @@ static const struct ieee80211_channel_range ieee80211_JP_channels[] = { static const struct ieee80211_regdomain ieee80211_regdoms[] = { REGDOM(US), REGDOM(JP), + REGDOM(EU), }; -- cgit v0.10.2 From c9e8eae0935f03e2d03a7ad7af80d8fc6c53e68c Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Sun, 15 Jun 2008 15:17:29 +0200 Subject: b43: Do not return TX_BUSY from op_tx Never return TX_BUSY from op_tx. It doesn't make sense to return TX_BUSY, if we can not transmit the packet. Drop the packet and return TX_OK. This will fix the resume hang. Signed-off-by: Michael Buesch Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index fa4b0d8..a708277 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c @@ -2883,12 +2883,11 @@ static int b43_op_tx(struct ieee80211_hw *hw, if (unlikely(skb->len < 2 + 2 + 6)) { /* Too short, this can't be a valid frame. */ - dev_kfree_skb_any(skb); - return NETDEV_TX_OK; + goto drop_packet; } B43_WARN_ON(skb_shinfo(skb)->nr_frags); if (unlikely(!dev)) - return NETDEV_TX_BUSY; + goto drop_packet; /* Transmissions on seperate queues can run concurrently. */ read_lock_irqsave(&wl->tx_lock, flags); @@ -2904,7 +2903,12 @@ static int b43_op_tx(struct ieee80211_hw *hw, read_unlock_irqrestore(&wl->tx_lock, flags); if (unlikely(err)) - return NETDEV_TX_BUSY; + goto drop_packet; + return NETDEV_TX_OK; + +drop_packet: + /* We can not transmit this packet. Drop it. */ + dev_kfree_skb_any(skb); return NETDEV_TX_OK; } -- cgit v0.10.2 From 664f200610a3c9641ff58fc91b986b804cb1cc2d Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Sun, 15 Jun 2008 15:27:49 +0200 Subject: b43legacy: Do not return TX_BUSY from op_tx Never return TX_BUSY from op_tx. It doesn't make sense to return TX_BUSY, if we can not transmit the packet. Drop the packet and return TX_OK. Signed-off-by: Michael Buesch Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/b43legacy/main.c b/drivers/net/wireless/b43legacy/main.c index 204077c..3e612d0 100644 --- a/drivers/net/wireless/b43legacy/main.c +++ b/drivers/net/wireless/b43legacy/main.c @@ -2378,8 +2378,10 @@ static int b43legacy_op_tx(struct ieee80211_hw *hw, } else err = b43legacy_dma_tx(dev, skb, ctl); out: - if (unlikely(err)) - return NETDEV_TX_BUSY; + if (unlikely(err)) { + /* Drop the packet. */ + dev_kfree_skb_any(skb); + } return NETDEV_TX_OK; } -- cgit v0.10.2 From 7b3abfc87ec13a81b255012b6e1bd4caeeb05aec Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Sun, 15 Jun 2008 16:01:24 +0200 Subject: b43: Fix possible MMIO access while device is down This fixes a possible MMIO access while the device is still down from a suspend cycle. MMIO accesses with the device powered down may cause crashes on certain devices. Signed-off-by: Michael Buesch Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/b43/leds.c b/drivers/net/wireless/b43/leds.c index 36a9c42..76f4c7b 100644 --- a/drivers/net/wireless/b43/leds.c +++ b/drivers/net/wireless/b43/leds.c @@ -72,6 +72,9 @@ static void b43_led_brightness_set(struct led_classdev *led_dev, struct b43_wldev *dev = led->dev; bool radio_enabled; + if (unlikely(b43_status(dev) < B43_STAT_INITIALIZED)) + return; + /* Checking the radio-enabled status here is slightly racy, * but we want to avoid the locking overhead and we don't care * whether the LED has the wrong state for a second. */ -- cgit v0.10.2 From 2f9ec47d0954f9d2e5a00209c2689cbc477a8c89 Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Fri, 20 Jun 2008 11:40:46 +0200 Subject: b43legacy: Fix possible NULL pointer dereference in DMA code This fixes a possible NULL pointer dereference in an error path of the DMA allocation error checking code. This is also necessary for a future DMA API change that is on its way into the mainline kernel that adds an additional dev parameter to dma_mapping_error(). Signed-off-by: Michael Buesch Cc: stable Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/b43legacy/dma.c b/drivers/net/wireless/b43legacy/dma.c index c990f87..93ddc1c 100644 --- a/drivers/net/wireless/b43legacy/dma.c +++ b/drivers/net/wireless/b43legacy/dma.c @@ -876,6 +876,7 @@ struct b43legacy_dmaring *b43legacy_setup_dmaring(struct b43legacy_wldev *dev, if (!ring) goto out; ring->type = type; + ring->dev = dev; nr_slots = B43legacy_RXRING_SLOTS; if (for_tx) @@ -922,7 +923,6 @@ struct b43legacy_dmaring *b43legacy_setup_dmaring(struct b43legacy_wldev *dev, DMA_TO_DEVICE); } - ring->dev = dev; ring->nr_slots = nr_slots; ring->mmio_base = b43legacy_dmacontroller_base(type, controller_index); ring->index = controller_index; -- cgit v0.10.2 From 99ade2597e3f7f0ad463c489aaccd6cc605e242c Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Fri, 20 Jun 2008 22:11:00 +0200 Subject: rt2x00: Fix unbalanced mutex locking The usb_cache_mutex was not correctly released under all circumstances. Both rt73usb as rt2500usb didn't release the mutex under certain conditions when the register access failed. Obviously such failure would lead to deadlocks. In addition under similar circumstances when the bbp register couldn't be read the value must be set to 0xff to indicate that the value is wrong. This too didn't happen under all circumstances. Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c index fdbd0ef..61e59c1 100644 --- a/drivers/net/wireless/rt2x00/rt2500usb.c +++ b/drivers/net/wireless/rt2x00/rt2500usb.c @@ -138,11 +138,8 @@ static void rt2500usb_bbp_write(struct rt2x00_dev *rt2x00dev, * Wait until the BBP becomes ready. */ reg = rt2500usb_bbp_check(rt2x00dev); - if (rt2x00_get_field16(reg, PHY_CSR8_BUSY)) { - ERROR(rt2x00dev, "PHY_CSR8 register busy. Write failed.\n"); - mutex_unlock(&rt2x00dev->usb_cache_mutex); - return; - } + if (rt2x00_get_field16(reg, PHY_CSR8_BUSY)) + goto exit_fail; /* * Write the data into the BBP. @@ -155,6 +152,13 @@ static void rt2500usb_bbp_write(struct rt2x00_dev *rt2x00dev, rt2500usb_register_write_lock(rt2x00dev, PHY_CSR7, reg); mutex_unlock(&rt2x00dev->usb_cache_mutex); + + return; + +exit_fail: + mutex_unlock(&rt2x00dev->usb_cache_mutex); + + ERROR(rt2x00dev, "PHY_CSR8 register busy. Write failed.\n"); } static void rt2500usb_bbp_read(struct rt2x00_dev *rt2x00dev, @@ -168,10 +172,8 @@ static void rt2500usb_bbp_read(struct rt2x00_dev *rt2x00dev, * Wait until the BBP becomes ready. */ reg = rt2500usb_bbp_check(rt2x00dev); - if (rt2x00_get_field16(reg, PHY_CSR8_BUSY)) { - ERROR(rt2x00dev, "PHY_CSR8 register busy. Read failed.\n"); - return; - } + if (rt2x00_get_field16(reg, PHY_CSR8_BUSY)) + goto exit_fail; /* * Write the request into the BBP. @@ -186,17 +188,21 @@ static void rt2500usb_bbp_read(struct rt2x00_dev *rt2x00dev, * Wait until the BBP becomes ready. */ reg = rt2500usb_bbp_check(rt2x00dev); - if (rt2x00_get_field16(reg, PHY_CSR8_BUSY)) { - ERROR(rt2x00dev, "PHY_CSR8 register busy. Read failed.\n"); - *value = 0xff; - mutex_unlock(&rt2x00dev->usb_cache_mutex); - return; - } + if (rt2x00_get_field16(reg, PHY_CSR8_BUSY)) + goto exit_fail; rt2500usb_register_read_lock(rt2x00dev, PHY_CSR7, ®); *value = rt2x00_get_field16(reg, PHY_CSR7_DATA); mutex_unlock(&rt2x00dev->usb_cache_mutex); + + return; + +exit_fail: + mutex_unlock(&rt2x00dev->usb_cache_mutex); + + ERROR(rt2x00dev, "PHY_CSR8 register busy. Read failed.\n"); + *value = 0xff; } static void rt2500usb_rf_write(struct rt2x00_dev *rt2x00dev, diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c index fff8386..83cc014 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.c +++ b/drivers/net/wireless/rt2x00/rt73usb.c @@ -134,11 +134,8 @@ static void rt73usb_bbp_write(struct rt2x00_dev *rt2x00dev, * Wait until the BBP becomes ready. */ reg = rt73usb_bbp_check(rt2x00dev); - if (rt2x00_get_field32(reg, PHY_CSR3_BUSY)) { - ERROR(rt2x00dev, "PHY_CSR3 register busy. Write failed.\n"); - mutex_unlock(&rt2x00dev->usb_cache_mutex); - return; - } + if (rt2x00_get_field32(reg, PHY_CSR3_BUSY)) + goto exit_fail; /* * Write the data into the BBP. @@ -151,6 +148,13 @@ static void rt73usb_bbp_write(struct rt2x00_dev *rt2x00dev, rt73usb_register_write_lock(rt2x00dev, PHY_CSR3, reg); mutex_unlock(&rt2x00dev->usb_cache_mutex); + + return; + +exit_fail: + mutex_unlock(&rt2x00dev->usb_cache_mutex); + + ERROR(rt2x00dev, "PHY_CSR3 register busy. Write failed.\n"); } static void rt73usb_bbp_read(struct rt2x00_dev *rt2x00dev, @@ -164,11 +168,8 @@ static void rt73usb_bbp_read(struct rt2x00_dev *rt2x00dev, * Wait until the BBP becomes ready. */ reg = rt73usb_bbp_check(rt2x00dev); - if (rt2x00_get_field32(reg, PHY_CSR3_BUSY)) { - ERROR(rt2x00dev, "PHY_CSR3 register busy. Read failed.\n"); - mutex_unlock(&rt2x00dev->usb_cache_mutex); - return; - } + if (rt2x00_get_field32(reg, PHY_CSR3_BUSY)) + goto exit_fail; /* * Write the request into the BBP. @@ -184,14 +185,19 @@ static void rt73usb_bbp_read(struct rt2x00_dev *rt2x00dev, * Wait until the BBP becomes ready. */ reg = rt73usb_bbp_check(rt2x00dev); - if (rt2x00_get_field32(reg, PHY_CSR3_BUSY)) { - ERROR(rt2x00dev, "PHY_CSR3 register busy. Read failed.\n"); - *value = 0xff; - return; - } + if (rt2x00_get_field32(reg, PHY_CSR3_BUSY)) + goto exit_fail; *value = rt2x00_get_field32(reg, PHY_CSR3_VALUE); mutex_unlock(&rt2x00dev->usb_cache_mutex); + + return; + +exit_fail: + mutex_unlock(&rt2x00dev->usb_cache_mutex); + + ERROR(rt2x00dev, "PHY_CSR3 register busy. Read failed.\n"); + *value = 0xff; } static void rt73usb_rf_write(struct rt2x00_dev *rt2x00dev, -- cgit v0.10.2 From 66b5004d85164a6439d3ba1e7757734472ee2cac Mon Sep 17 00:00:00 2001 From: Ron Rindjunsky Date: Wed, 25 Jun 2008 16:46:31 +0800 Subject: iwlwifi: improve scanning band selection management This patch modifies the band selection management when scanning, so bands are now scanned according to HW band support. Signed-off-by: Ron Rindjunsky Signed-off-by: Tomas Winkler Signed-off-by: Zhu Yi Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 13925b6..b1b3c52 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -2227,7 +2227,10 @@ static int iwl3945_scan_initiate(struct iwl3945_priv *priv) } IWL_DEBUG_INFO("Starting scan...\n"); - priv->scan_bands = 2; + if (priv->cfg->sku & IWL_SKU_G) + priv->scan_bands |= BIT(IEEE80211_BAND_2GHZ); + if (priv->cfg->sku & IWL_SKU_A) + priv->scan_bands |= BIT(IEEE80211_BAND_5GHZ); set_bit(STATUS_SCANNING, &priv->status); priv->scan_start = jiffies; priv->scan_pass_start = priv->scan_start; @@ -3352,13 +3355,18 @@ static void iwl3945_rx_scan_complete_notif(struct iwl3945_priv *priv, cancel_delayed_work(&priv->scan_check); IWL_DEBUG_INFO("Scan pass on %sGHz took %dms\n", - (priv->scan_bands == 2) ? "2.4" : "5.2", + (priv->scan_bands & BIT(IEEE80211_BAND_2GHZ)) ? + "2.4" : "5.2", jiffies_to_msecs(elapsed_jiffies (priv->scan_pass_start, jiffies))); - /* Remove this scanned band from the list - * of pending bands to scan */ - priv->scan_bands--; + /* Remove this scanned band from the list of pending + * bands to scan, band G precedes A in order of scanning + * as seen in iwl3945_bg_request_scan */ + if (priv->scan_bands & BIT(IEEE80211_BAND_2GHZ)) + priv->scan_bands &= ~BIT(IEEE80211_BAND_2GHZ); + else if (priv->scan_bands & BIT(IEEE80211_BAND_5GHZ)) + priv->scan_bands &= ~BIT(IEEE80211_BAND_5GHZ); /* If a request to abort was given, or the scan did not succeed * then we reset the scan state machine and terminate, @@ -4972,7 +4980,7 @@ static int iwl3945_get_channels_for_scan(struct iwl3945_priv *priv, ch_info = iwl3945_get_channel_info(priv, band, scan_ch->channel); if (!is_channel_valid(ch_info)) { - IWL_DEBUG_SCAN("Channel %d is INVALID for this SKU.\n", + IWL_DEBUG_SCAN("Channel %d is INVALID for this band.\n", scan_ch->channel); continue; } @@ -6315,21 +6323,16 @@ static void iwl3945_bg_request_scan(struct work_struct *data) /* flags + rate selection */ - switch (priv->scan_bands) { - case 2: + if (priv->scan_bands & BIT(IEEE80211_BAND_2GHZ)) { scan->flags = RXON_FLG_BAND_24G_MSK | RXON_FLG_AUTO_DETECT_MSK; scan->tx_cmd.rate = IWL_RATE_1M_PLCP; scan->good_CRC_th = 0; band = IEEE80211_BAND_2GHZ; - break; - - case 1: + } else if (priv->scan_bands & BIT(IEEE80211_BAND_5GHZ)) { scan->tx_cmd.rate = IWL_RATE_6M_PLCP; scan->good_CRC_th = IWL_GOOD_CRC_TH; band = IEEE80211_BAND_5GHZ; - break; - - default: + } else { IWL_WARNING("Invalid scan band count\n"); goto done; } @@ -6770,7 +6773,7 @@ static int iwl3945_mac_config(struct ieee80211_hw *hw, struct ieee80211_conf *co ch_info = iwl3945_get_channel_info(priv, conf->channel->band, conf->channel->hw_value); if (!is_channel_valid(ch_info)) { - IWL_DEBUG_SCAN("Channel %d [%d] is INVALID for this SKU.\n", + IWL_DEBUG_SCAN("Channel %d [%d] is INVALID for this band.\n", conf->channel->hw_value, conf->channel->band); IWL_DEBUG_MAC80211("leave - invalid channel\n"); spin_unlock_irqrestore(&priv->lock, flags); diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c index 883b42f..5ed16ce 100644 --- a/drivers/net/wireless/iwlwifi/iwl4965-base.c +++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c @@ -1774,7 +1774,10 @@ static int iwl4965_scan_initiate(struct iwl_priv *priv) } IWL_DEBUG_INFO("Starting scan...\n"); - priv->scan_bands = 2; + if (priv->cfg->sku & IWL_SKU_G) + priv->scan_bands |= BIT(IEEE80211_BAND_2GHZ); + if (priv->cfg->sku & IWL_SKU_A) + priv->scan_bands |= BIT(IEEE80211_BAND_5GHZ); set_bit(STATUS_SCANNING, &priv->status); priv->scan_start = jiffies; priv->scan_pass_start = priv->scan_start; @@ -3023,8 +3026,9 @@ static void iwl4965_rx_reply_tx(struct iwl_priv *priv, IWL_DEBUG_TX_REPLY("Tx queue reclaim %d\n", index); if (index != -1) { - int freed = iwl4965_tx_queue_reclaim(priv, txq_id, index); #ifdef CONFIG_IWL4965_HT + int freed = iwl4965_tx_queue_reclaim(priv, txq_id, index); + if (tid != MAX_TID_COUNT) priv->stations[sta_id].tid[tid].tfds_in_queue -= freed; if (iwl4965_queue_space(&txq->q) > txq->q.low_mark && @@ -3276,13 +3280,18 @@ static void iwl4965_rx_scan_complete_notif(struct iwl_priv *priv, cancel_delayed_work(&priv->scan_check); IWL_DEBUG_INFO("Scan pass on %sGHz took %dms\n", - (priv->scan_bands == 2) ? "2.4" : "5.2", + (priv->scan_bands & BIT(IEEE80211_BAND_2GHZ)) ? + "2.4" : "5.2", jiffies_to_msecs(elapsed_jiffies (priv->scan_pass_start, jiffies))); - /* Remove this scanned band from the list - * of pending bands to scan */ - priv->scan_bands--; + /* Remove this scanned band from the list of pending + * bands to scan, band G precedes A in order of scanning + * as seen in iwl_bg_request_scan */ + if (priv->scan_bands & BIT(IEEE80211_BAND_2GHZ)) + priv->scan_bands &= ~BIT(IEEE80211_BAND_2GHZ); + else if (priv->scan_bands & BIT(IEEE80211_BAND_5GHZ)) + priv->scan_bands &= ~BIT(IEEE80211_BAND_5GHZ); /* If a request to abort was given, or the scan did not succeed * then we reset the scan state machine and terminate, @@ -3292,7 +3301,7 @@ static void iwl4965_rx_scan_complete_notif(struct iwl_priv *priv, clear_bit(STATUS_SCAN_ABORTING, &priv->status); } else { /* If there are more bands on this scan pass reschedule */ - if (priv->scan_bands > 0) + if (priv->scan_bands) goto reschedule; } @@ -4635,10 +4644,9 @@ static int iwl4965_get_channels_for_scan(struct iwl_priv *priv, scan_ch->channel = ieee80211_frequency_to_channel(channels[i].center_freq); - ch_info = iwl_get_channel_info(priv, band, - scan_ch->channel); + ch_info = iwl_get_channel_info(priv, band, scan_ch->channel); if (!is_channel_valid(ch_info)) { - IWL_DEBUG_SCAN("Channel %d is INVALID for this SKU.\n", + IWL_DEBUG_SCAN("Channel %d is INVALID for this band.\n", scan_ch->channel); continue; } @@ -5830,8 +5838,7 @@ static void iwl4965_bg_request_scan(struct work_struct *data) scan->tx_cmd.stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE; - switch (priv->scan_bands) { - case 2: + if (priv->scan_bands & BIT(IEEE80211_BAND_2GHZ)) { scan->flags = RXON_FLG_BAND_24G_MSK | RXON_FLG_AUTO_DETECT_MSK; scan->tx_cmd.rate_n_flags = iwl4965_hw_set_rate_n_flags(IWL_RATE_1M_PLCP, @@ -5839,17 +5846,13 @@ static void iwl4965_bg_request_scan(struct work_struct *data) scan->good_CRC_th = 0; band = IEEE80211_BAND_2GHZ; - break; - - case 1: + } else if (priv->scan_bands & BIT(IEEE80211_BAND_5GHZ)) { scan->tx_cmd.rate_n_flags = iwl4965_hw_set_rate_n_flags(IWL_RATE_6M_PLCP, RATE_MCS_ANT_B_MSK); scan->good_CRC_th = IWL_GOOD_CRC_TH; band = IEEE80211_BAND_5GHZ; - break; - - default: + } else { IWL_WARNING("Invalid scan band count\n"); goto done; } -- cgit v0.10.2 From f471f92339860c35b561cf45ad563ab1ff07c386 Mon Sep 17 00:00:00 2001 From: Michal Schmidt Date: Thu, 26 Jun 2008 16:06:19 +0200 Subject: s2io: fix documentation about intr_type The documentation for intr_type module parameter of the s2io driver is not consistent with the code. The comments in drivers/net/s2io.c are OK, but Documentation/networking/s2io.txt is wrong. Pointed out by Andrew Hecox. Signed-off-by: Michal Schmidt Signed-off-by: Jeff Garzik diff --git a/Documentation/networking/s2io.txt b/Documentation/networking/s2io.txt index 4bde53e..1e28e2d 100644 --- a/Documentation/networking/s2io.txt +++ b/Documentation/networking/s2io.txt @@ -83,9 +83,9 @@ Valid range: Limited by memory on system Default: 30 e. intr_type -Specifies interrupt type. Possible values 1(INTA), 2(MSI), 3(MSI-X) -Valid range: 1-3 -Default: 1 +Specifies interrupt type. Possible values 0(INTA), 2(MSI-X) +Valid values: 0, 2 +Default: 2 5. Performance suggestions General: -- cgit v0.10.2 From 59524a37446e18a672188d86d23c8c76fd488621 Mon Sep 17 00:00:00 2001 From: Atsushi Nemoto Date: Wed, 25 Jun 2008 11:41:01 +0900 Subject: tc35815: Mark carrier-off before starting PHY Call netif_carrier_off() before starting PHY device. This is a behavior before converting to generic PHY layer. Signed-off-by: Atsushi Nemoto Signed-off-by: Jeff Garzik diff --git a/drivers/net/tc35815.c b/drivers/net/tc35815.c index 10e4e85..dccea52 100644 --- a/drivers/net/tc35815.c +++ b/drivers/net/tc35815.c @@ -1394,6 +1394,7 @@ tc35815_open(struct net_device *dev) tc35815_chip_init(dev); spin_unlock_irq(&lp->lock); + netif_carrier_off(dev); /* schedule a link state check */ phy_start(lp->phy_dev); @@ -2453,6 +2454,7 @@ static int tc35815_resume(struct pci_dev *pdev) return 0; pci_set_power_state(pdev, PCI_D0); tc35815_restart(dev); + netif_carrier_off(dev); if (lp->phy_dev) phy_start(lp->phy_dev); netif_device_attach(dev); -- cgit v0.10.2 From ccc57aac9c9532b4540968632a8c4a0b946dbcc4 Mon Sep 17 00:00:00 2001 From: Atsushi Nemoto Date: Thu, 26 Jun 2008 17:14:15 +0900 Subject: tc35815: Fix receiver hangup on Rx FIFO overflow On Rx FIFO overflow error, the controller consume a buffer descriptor but currently the driver does not give it back to the controller. This results unrecoverable 'Buffer List Exhausted' condition. This patch fix this problem by moving a "fbl_count--" line to proper place. Signed-off-by: Atsushi Nemoto Signed-off-by: Jeff Garzik diff --git a/drivers/net/tc35815.c b/drivers/net/tc35815.c index dccea52..b07b8cb 100644 --- a/drivers/net/tc35815.c +++ b/drivers/net/tc35815.c @@ -1736,7 +1736,6 @@ tc35815_rx(struct net_device *dev) skb = lp->rx_skbs[cur_bd].skb; prefetch(skb->data); lp->rx_skbs[cur_bd].skb = NULL; - lp->fbl_count--; pci_unmap_single(lp->pci_dev, lp->rx_skbs[cur_bd].skb_dma, RX_BUF_SIZE, PCI_DMA_FROMDEVICE); @@ -1792,6 +1791,7 @@ tc35815_rx(struct net_device *dev) #ifdef TC35815_USE_PACKEDBUFFER while (lp->fbl_curid != id) #else + lp->fbl_count--; while (lp->fbl_count < RX_BUF_NUM) #endif { -- cgit v0.10.2 From 6f4a0e45c6392f84436004d4c04d31b8ff5071c5 Mon Sep 17 00:00:00 2001 From: Paul Larson Date: Tue, 24 Jun 2008 17:00:56 -0700 Subject: ixgbe: fix EEH recovery during reset on PPC EEh is not recovering in a resonable amount of time on PPC during ixgbe_down(). Signed-off-by: Paul Larson Signed-off-by: Jesse Brandeburg Signed-off-by: Jeff Kirsher Signed-off-by: Jeff Garzik diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index 7b85922..8f04609 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c @@ -1969,7 +1969,8 @@ void ixgbe_down(struct ixgbe_adapter *adapter) netif_carrier_off(netdev); netif_stop_queue(netdev); - ixgbe_reset(adapter); + if (!pci_channel_offline(adapter->pdev)) + ixgbe_reset(adapter); ixgbe_clean_all_tx_rings(adapter); ixgbe_clean_all_rx_rings(adapter); -- cgit v0.10.2 From 3023682e74bc17debc6aa5e234ae1d0b0e198719 Mon Sep 17 00:00:00 2001 From: Jeff Kirsher Date: Tue, 24 Jun 2008 17:01:15 -0700 Subject: igb: fix EEH recovery during reset on PPC EEH is not recovering in a reasonable amount of time on PPC during igb_down(). Signed-off-by: Jeff Kirsher Signed-off-by: Jesse Brandeburg Signed-off-by: Jeff Garzik diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c index ae398f0..e79a26a 100644 --- a/drivers/net/igb/igb_main.c +++ b/drivers/net/igb/igb_main.c @@ -718,7 +718,8 @@ void igb_down(struct igb_adapter *adapter) adapter->link_speed = 0; adapter->link_duplex = 0; - igb_reset(adapter); + if (!pci_channel_offline(adapter->pdev)) + igb_reset(adapter); igb_clean_all_tx_rings(adapter); igb_clean_all_rx_rings(adapter); } -- cgit v0.10.2 From 52cc30862a8f90c98be8eb527d00e5e06d398b22 Mon Sep 17 00:00:00 2001 From: Jeff Kirsher Date: Tue, 24 Jun 2008 17:01:29 -0700 Subject: e1000e: fix EEH recovery during reset on PPC EEH is not recovering in a reasonable amount of time on PPC during e1000e_down(). Signed-off-by: Jeff Kirsher Signed-off-by: Jesse Brandeburg Signed-off-by: Jeff Garzik diff --git a/drivers/net/e1000e/netdev.c b/drivers/net/e1000e/netdev.c index cab1835..648a87b 100644 --- a/drivers/net/e1000e/netdev.c +++ b/drivers/net/e1000e/netdev.c @@ -2535,7 +2535,8 @@ void e1000e_down(struct e1000_adapter *adapter) adapter->link_speed = 0; adapter->link_duplex = 0; - e1000e_reset(adapter); + if (!pci_channel_offline(adapter->pdev)) + e1000e_reset(adapter); e1000_clean_tx_ring(adapter); e1000_clean_rx_ring(adapter); -- cgit v0.10.2 From 54299ef7e9ae4b5d47b02f3abea168cdc62a6f70 Mon Sep 17 00:00:00 2001 From: Komuro Date: Sat, 7 Jun 2008 21:37:56 +0900 Subject: pcnet_cs, axnet_cs: clear bogus interrupt before request_irq Signed-off-by: Komuro Signed-off-by: Jeff Garzik diff --git a/drivers/net/pcmcia/axnet_cs.c b/drivers/net/pcmcia/axnet_cs.c index ce95c5d..70d012e 100644 --- a/drivers/net/pcmcia/axnet_cs.c +++ b/drivers/net/pcmcia/axnet_cs.c @@ -525,12 +525,14 @@ static int axnet_open(struct net_device *dev) int ret; axnet_dev_t *info = PRIV(dev); struct pcmcia_device *link = info->p_dev; + unsigned int nic_base = dev->base_addr; DEBUG(2, "axnet_open('%s')\n", dev->name); if (!pcmcia_dev_present(link)) return -ENODEV; + outb_p(0xFF, nic_base + EN0_ISR); /* Clear bogus intr. */ ret = request_irq(dev->irq, ei_irq_wrapper, IRQF_SHARED, "axnet_cs", dev); if (ret) return ret; diff --git a/drivers/net/pcmcia/pcnet_cs.c b/drivers/net/pcmcia/pcnet_cs.c index fd8158a..2d4c4ad 100644 --- a/drivers/net/pcmcia/pcnet_cs.c +++ b/drivers/net/pcmcia/pcnet_cs.c @@ -969,6 +969,7 @@ static int pcnet_open(struct net_device *dev) int ret; pcnet_dev_t *info = PRIV(dev); struct pcmcia_device *link = info->p_dev; + unsigned int nic_base = dev->base_addr; DEBUG(2, "pcnet_open('%s')\n", dev->name); @@ -976,6 +977,8 @@ static int pcnet_open(struct net_device *dev) return -ENODEV; set_misc_reg(dev); + + outb_p(0xFF, nic_base + EN0_ISR); /* Clear bogus intr. */ ret = request_irq(dev->irq, ei_irq_wrapper, IRQF_SHARED, dev_info, dev); if (ret) return ret; -- cgit v0.10.2 From 3f6602ad56dc538a846367bd6a05ac7ac4d3e641 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Mon, 23 Jun 2008 23:12:31 +0200 Subject: drivers/net/r6040.c: Eliminate double sizeof Taking sizeof the result of sizeof is quite strange and does not seem to be what is wanted here. This was fixed using the following semantic patch. (http://www.emn.fr/x-info/coccinelle/) // @@ expression E; @@ - sizeof ( sizeof (E) - ) // Signed-off-by: Julia Lawall Signed-off-by: Jeff Garzik diff --git a/drivers/net/r6040.c b/drivers/net/r6040.c index 858b191..504a48f 100644 --- a/drivers/net/r6040.c +++ b/drivers/net/r6040.c @@ -273,7 +273,7 @@ static void r6040_init_ring_desc(struct r6040_descriptor *desc_ring, dma_addr_t mapping = desc_dma; while (size-- > 0) { - mapping += sizeof(sizeof(*desc)); + mapping += sizeof(*desc); desc->ndesc = cpu_to_le32(mapping); desc->vndescp = desc + 1; desc++; -- cgit v0.10.2 From ecfecfb5e39165b3f7f6d93aacd268edfe7c3524 Mon Sep 17 00:00:00 2001 From: Pekka Enberg Date: Mon, 23 Jun 2008 14:34:29 +0300 Subject: ipg: fix jumbo frame compilation Make jumbo frame support compile again. It was broken by the cleanup series before the merge because the code is hidden under JUMBO_FRAME #ifdef. Tested-by: Andrew Savchenko Signed-off-by: Pekka Enberg Signed-off-by: Jeff Garzik diff --git a/drivers/net/ipg.c b/drivers/net/ipg.c index 679a082..dbb77e3 100644 --- a/drivers/net/ipg.c +++ b/drivers/net/ipg.c @@ -1271,7 +1271,7 @@ static void ipg_nic_rx_with_end(struct net_device *dev, framelen = le64_to_cpu(rxfd->rfs) & IPG_RFS_RXFRAMELEN; - endframeLen = framelen - jumbo->current_size; + endframelen = framelen - jumbo->current_size; /* if (framelen > IPG_RXFRAG_SIZE) framelen=IPG_RXFRAG_SIZE; @@ -1279,8 +1279,8 @@ static void ipg_nic_rx_with_end(struct net_device *dev, if (framelen > IPG_RXSUPPORT_SIZE) dev_kfree_skb_irq(jumbo->skb); else { - memcpy(skb_put(jumbo->skb, endframeLen), - skb->data, endframeLen); + memcpy(skb_put(jumbo->skb, endframelen), + skb->data, endframelen); jumbo->skb->protocol = eth_type_trans(jumbo->skb, dev); @@ -1352,16 +1352,16 @@ static int ipg_nic_rx(struct net_device *dev) switch (ipg_nic_rx_check_frame_type(dev)) { case FRAME_WITH_START_WITH_END: - ipg_nic_rx_with_start_and_end(dev, tp, rxfd, entry); + ipg_nic_rx_with_start_and_end(dev, sp, rxfd, entry); break; case FRAME_WITH_START: - ipg_nic_rx_with_start(dev, tp, rxfd, entry); + ipg_nic_rx_with_start(dev, sp, rxfd, entry); break; case FRAME_WITH_END: - ipg_nic_rx_with_end(dev, tp, rxfd, entry); + ipg_nic_rx_with_end(dev, sp, rxfd, entry); break; case FRAME_NO_START_NO_END: - ipg_nic_rx_no_start_no_end(dev, tp, rxfd, entry); + ipg_nic_rx_no_start_no_end(dev, sp, rxfd, entry); break; } } -- cgit v0.10.2 From e8399fed7e9f2e76eb65852612b16732129b9f3f Mon Sep 17 00:00:00 2001 From: Pekka Enberg Date: Mon, 23 Jun 2008 14:34:50 +0300 Subject: ipg: use NULL, not zero, for pointers Fixes a sparse warning in a code block that's hidden under JUMBO_FRAME #ifdef. Tested-by: Andrew Savchenko Signed-off-by: Pekka Enberg Signed-off-by: Jeff Garzik diff --git a/drivers/net/ipg.c b/drivers/net/ipg.c index dbb77e3..2c03f4e 100644 --- a/drivers/net/ipg.c +++ b/drivers/net/ipg.c @@ -1808,7 +1808,7 @@ static int ipg_nic_open(struct net_device *dev) /* initialize JUMBO Frame control variable */ sp->jumbo.found_start = 0; sp->jumbo.current_size = 0; - sp->jumbo.skb = 0; + sp->jumbo.skb = NULL; dev->mtu = IPG_TXFRAG_SIZE; #endif -- cgit v0.10.2 From c5643cab7bf663ae049b11be43de8819683176dd Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Mon, 23 Jun 2008 10:41:23 +0200 Subject: [netdrvr] 3c59x: remove irqs_disabled warning from local_bh_enable Original Author: Michael Buesch net, vortex: fix lockup Ingo Molnar reported: -tip testing found that Johannes Berg's "softirq: remove irqs_disabled warning from local_bh_enable" enhancement to lockdep triggers a new warning on an old testbox that uses 3c59x vortex and netlogging: -----> calling vortex_init+0x0/0xb0 PCI: Found IRQ 10 for device 0000:00:0b.0 PCI: Sharing IRQ 10 with 0000:00:0a.0 PCI: Sharing IRQ 10 with 0000:00:0b.1 3c59x: Donald Becker and others. 0000:00:0b.0: 3Com PCI 3c556 Laptop Tornado at e0800400. PCI: Enabling bus mastering for device 0000:00:0b.0 initcall vortex_init+0x0/0xb0 returned 0 after 47 msecs ... calling init_netconsole+0x0/0x1b0 netconsole: local port 4444 netconsole: local IP 10.0.1.9 netconsole: interface eth0 netconsole: remote port 4444 netconsole: remote IP 10.0.1.16 netconsole: remote ethernet address 00:19:xx:xx:xx:xx netconsole: device eth0 not up yet, forcing it eth0: setting half-duplex. eth0: setting full-duplex. ------------[ cut here ]------------ WARNING: at kernel/softirq.c:137 local_bh_enable_ip+0xd1/0xe0() Pid: 1, comm: swapper Not tainted 2.6.26-rc6-tip #2091 [] warn_on_slowpath+0x4f/0x70 [] ? release_console_sem+0x1b4/0x1d0 [] ? vprintk+0x2a0/0x450 [] ? __mod_timer+0xa5/0xc0 [] ? mdio_sync+0x3d/0x50 [] ? marker_probe_cb+0x46/0xa0 [] ? printk+0x27/0x50 [] ? vortex_set_duplex+0x43/0xc0 [] ? vortex_set_duplex+0xa1/0xc0 [] ? vortex_timer+0xe2/0x3e0 [] local_bh_enable_ip+0xd1/0xe0 [] _spin_unlock_bh+0x2f/0x40 [] vortex_timer+0xe2/0x3e0 [] ? trace_hardirqs_on+0xb/0x10 [] ? trace_hardirqs_on_caller+0x88/0x160 [] run_timer_softirq+0x162/0x1c0 [] ? vortex_timer+0x0/0x3e0 [] local_bh_enable_ip+0xd1/0xe0 [] _spin_unlock_bh+0x2f/0x40 [] vortex_timer+0xe2/0x3e0 [] ? trace_hardirqs_on+0xb/0x10 [] ? trace_hardirqs_on_caller+0x88/0x160 [] run_timer_softirq+0x162/0x1c0 [] ? vortex_timer+0x0/0x3e0 [] ? vortex_timer+0x0/0x3e0 [] __do_softirq+0x9a/0x160 [] ? __do_softirq+0x0/0x160 [] call_on_stack+0x15/0x30 [] ? irq_exit+0x55/0x60 [] ? do_IRQ+0x85/0xd0 [] ? trace_hardirqs_on_caller+0xc1/0x160 [] ? common_interrupt+0x28/0x30 [] ? mutex_unlock+0x8/0x10 [] ? _cond_resched+0x10/0x30 [] ? netpoll_setup+0x117/0x390 [] ? init_netconsole+0x14e/0x1b0 [] ? ktime_get+0x19/0x40 [] ? kernel_init+0x1b2/0x2c0 [] ? init_netconsole+0x0/0x1b0 [] ? trace_hardirqs_on_thunk+0xc/0x10 [] ? restore_nocheck_notrace+0x0/0xe [] ? kernel_init+0x0/0x2c0 [] ? kernel_init+0x0/0x2c0 [] ? kernel_thread_helper+0x7/0x10 ======================= ---[ end trace 37f9c502aff112e0 ]--- console [netcon0] enabled netconsole: network logging started initcall init_netconsole+0x0/0x1b0 returned 0 after 2914 msecs looking at the driver I think the bug is real and the fix actually is trivial. vp->lock is also taken in hardware IRQ context, so we _have_ to always use irqsafe locking. As we run in a timer with IRQs disabled, we can simply use spin_lock. Cc: Signed-off-by: Ingo Molnar Signed-off-by: Jeff Garzik diff --git a/drivers/net/3c59x.c b/drivers/net/3c59x.c index 2edda8c..aabad8c 100644 --- a/drivers/net/3c59x.c +++ b/drivers/net/3c59x.c @@ -1768,9 +1768,10 @@ vortex_timer(unsigned long data) case XCVR_MII: case XCVR_NWAY: { ok = 1; - spin_lock_bh(&vp->lock); + /* Interrupts are already disabled */ + spin_lock(&vp->lock); vortex_check_media(dev, 0); - spin_unlock_bh(&vp->lock); + spin_unlock(&vp->lock); } break; default: /* Other media types handled by Tx timeouts. */ -- cgit v0.10.2 From 70081ac55df939363b27c1ebd27c51f510129139 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Mon, 23 Jun 2008 02:04:50 +0100 Subject: [netdrvr] netxen: fix netxen_pci_tbl[] breakage PCI_DEVICE_CLASS sets .device and .vendor to PCI_ANY_DEV, which overrides the effect of preceding PCI_DEVICE() and makes all elements of netxen_pci_tbl[] identical. Introduced in the commit dcd56fdbaeae1008044687b973c4a3e852e8a726. Signed-off-by: Al Viro Signed-off-by: Jeff Garzik diff --git a/drivers/net/netxen/netxen_nic_main.c b/drivers/net/netxen/netxen_nic_main.c index 6797ed0..63cd67b 100644 --- a/drivers/net/netxen/netxen_nic_main.c +++ b/drivers/net/netxen/netxen_nic_main.c @@ -71,14 +71,18 @@ static irqreturn_t netxen_intr(int irq, void *data); static irqreturn_t netxen_msi_intr(int irq, void *data); /* PCI Device ID Table */ +#define ENTRY(device) \ + {PCI_DEVICE(0x4040, (device)), \ + .class = PCI_CLASS_NETWORK_ETHERNET << 8, .class_mask = ~0} + static struct pci_device_id netxen_pci_tbl[] __devinitdata = { - {PCI_DEVICE(0x4040, 0x0001), PCI_DEVICE_CLASS(0x020000, ~0)}, - {PCI_DEVICE(0x4040, 0x0002), PCI_DEVICE_CLASS(0x020000, ~0)}, - {PCI_DEVICE(0x4040, 0x0003), PCI_DEVICE_CLASS(0x020000, ~0)}, - {PCI_DEVICE(0x4040, 0x0004), PCI_DEVICE_CLASS(0x020000, ~0)}, - {PCI_DEVICE(0x4040, 0x0005), PCI_DEVICE_CLASS(0x020000, ~0)}, - {PCI_DEVICE(0x4040, 0x0024), PCI_DEVICE_CLASS(0x020000, ~0)}, - {PCI_DEVICE(0x4040, 0x0025), PCI_DEVICE_CLASS(0x020000, ~0)}, + ENTRY(0x0001), + ENTRY(0x0002), + ENTRY(0x0003), + ENTRY(0x0004), + ENTRY(0x0005), + ENTRY(0x0024), + ENTRY(0x0025), {0,} }; -- cgit v0.10.2 From 1923815d855e1daec931fc9f2221fb73ca708870 Mon Sep 17 00:00:00 2001 From: Kevin Hao Date: Sat, 21 Jun 2008 18:20:35 +0800 Subject: e100: Do pci_dma_sync after skb_alloc for proper operation on ixp4xx The E100 device can't work on current kernel (2.6.26-rc6) and will cause kernel corruption on intel ixdp4xx. Signed-off-by: Jeff Garzik diff --git a/drivers/net/e100.c b/drivers/net/e100.c index f3cba5e..1037b13 100644 --- a/drivers/net/e100.c +++ b/drivers/net/e100.c @@ -1803,6 +1803,8 @@ static int e100_rx_alloc_skb(struct nic *nic, struct rx *rx) if (rx->prev->skb) { struct rfd *prev_rfd = (struct rfd *)rx->prev->skb->data; put_unaligned_le32(rx->dma_addr, &prev_rfd->link); + pci_dma_sync_single_for_device(nic->pdev, rx->prev->dma_addr, + sizeof(struct rfd), PCI_DMA_TODEVICE); } return 0; -- cgit v0.10.2 From 581abbc26a7adb693fb8b913f1be18d1c349c1ab Mon Sep 17 00:00:00 2001 From: Andy Gospodarek Date: Thu, 19 Jun 2008 17:19:02 -0400 Subject: e1000: only enable TSO6 via ethtool when using correct hardware When enabling TSO via ethool on e1000, it is possible to set NETIF_F_TSO6 on hardware that does not support it. Setting TSO via ethtool now matches the settings used when the hardware is probed. Signed-off-by: Andy Gospodarek Signed-off-by: Jeff Garzik diff --git a/drivers/net/e1000/e1000_ethtool.c b/drivers/net/e1000/e1000_ethtool.c index 701531e..a3f6a9c 100644 --- a/drivers/net/e1000/e1000_ethtool.c +++ b/drivers/net/e1000/e1000_ethtool.c @@ -347,7 +347,7 @@ e1000_set_tso(struct net_device *netdev, u32 data) else netdev->features &= ~NETIF_F_TSO; - if (data) + if (data && (adapter->hw.mac_type > e1000_82547_rev_2)) netdev->features |= NETIF_F_TSO6; else netdev->features &= ~NETIF_F_TSO6; -- cgit v0.10.2 From 64c42f697661e27c9688a32c1ba61d0228e81d84 Mon Sep 17 00:00:00 2001 From: Andi Kleen Date: Wed, 18 Jun 2008 13:58:36 +0200 Subject: [netdrvr] Fix IOMMU overflow checking in s2io.c s2io has IOMMU overflow checking, but unfortunately it is wrong. It didn't use the standard macros, which meant that it only worked on POWER and SPARC because only those define DMA_ERROR_CODE. Convert it to use the standard macros instead. I also commented two more bugs in the IOMMU handling. It assumes that 0 DMA addresses cannot happen, but that's not true in all IOMMU setups. The information if a buffer has been already mapped needs to be stored elsewhere. Didn't fix those because it needs careful checking of the buffer handling by the maintainers. Cc: ram.vepa@neterion.com Cc: santosh.rastapur@neterion.com Cc: sivakumar.subramani@neterion.com Cc: sreenivasa.honnur@neterion.com Signed-off-by: Andi Kleen Signed-off-by: Jeff Garzik diff --git a/drivers/net/s2io.c b/drivers/net/s2io.c index b5c1e66..ae7b697 100644 --- a/drivers/net/s2io.c +++ b/drivers/net/s2io.c @@ -2625,9 +2625,7 @@ static int fill_rx_buffers(struct ring_info *ring) rxdp1->Buffer0_ptr = pci_map_single (ring->pdev, skb->data, size - NET_IP_ALIGN, PCI_DMA_FROMDEVICE); - if( (rxdp1->Buffer0_ptr == 0) || - (rxdp1->Buffer0_ptr == - DMA_ERROR_CODE)) + if(pci_dma_mapping_error(rxdp1->Buffer0_ptr)) goto pci_map_failed; rxdp->Control_2 = @@ -2657,6 +2655,7 @@ static int fill_rx_buffers(struct ring_info *ring) skb->data = (void *) (unsigned long)tmp; skb_reset_tail_pointer(skb); + /* AK: check is wrong. 0 can be valid dma address */ if (!(rxdp3->Buffer0_ptr)) rxdp3->Buffer0_ptr = pci_map_single(ring->pdev, ba->ba_0, @@ -2665,8 +2664,7 @@ static int fill_rx_buffers(struct ring_info *ring) pci_dma_sync_single_for_device(ring->pdev, (dma_addr_t) rxdp3->Buffer0_ptr, BUF0_LEN, PCI_DMA_FROMDEVICE); - if( (rxdp3->Buffer0_ptr == 0) || - (rxdp3->Buffer0_ptr == DMA_ERROR_CODE)) + if (pci_dma_mapping_error(rxdp3->Buffer0_ptr)) goto pci_map_failed; rxdp->Control_2 = SET_BUFFER0_SIZE_3(BUF0_LEN); @@ -2681,18 +2679,17 @@ static int fill_rx_buffers(struct ring_info *ring) (ring->pdev, skb->data, ring->mtu + 4, PCI_DMA_FROMDEVICE); - if( (rxdp3->Buffer2_ptr == 0) || - (rxdp3->Buffer2_ptr == DMA_ERROR_CODE)) + if (pci_dma_mapping_error(rxdp3->Buffer2_ptr)) goto pci_map_failed; + /* AK: check is wrong */ if (!rxdp3->Buffer1_ptr) rxdp3->Buffer1_ptr = pci_map_single(ring->pdev, ba->ba_1, BUF1_LEN, PCI_DMA_FROMDEVICE); - if( (rxdp3->Buffer1_ptr == 0) || - (rxdp3->Buffer1_ptr == DMA_ERROR_CODE)) { + if (pci_dma_mapping_error(rxdp3->Buffer1_ptr)) { pci_unmap_single (ring->pdev, (dma_addr_t)(unsigned long) @@ -4264,16 +4261,14 @@ static int s2io_xmit(struct sk_buff *skb, struct net_device *dev) txdp->Buffer_Pointer = pci_map_single(sp->pdev, fifo->ufo_in_band_v, sizeof(u64), PCI_DMA_TODEVICE); - if((txdp->Buffer_Pointer == 0) || - (txdp->Buffer_Pointer == DMA_ERROR_CODE)) + if (pci_dma_mapping_error(txdp->Buffer_Pointer)) goto pci_map_failed; txdp++; } txdp->Buffer_Pointer = pci_map_single (sp->pdev, skb->data, frg_len, PCI_DMA_TODEVICE); - if((txdp->Buffer_Pointer == 0) || - (txdp->Buffer_Pointer == DMA_ERROR_CODE)) + if (pci_dma_mapping_error(txdp->Buffer_Pointer)) goto pci_map_failed; txdp->Host_Control = (unsigned long) skb; @@ -6884,10 +6879,8 @@ static int set_rxd_buffer_pointer(struct s2io_nic *sp, struct RxD_t *rxdp, pci_map_single( sp->pdev, (*skb)->data, size - NET_IP_ALIGN, PCI_DMA_FROMDEVICE); - if( (rxdp1->Buffer0_ptr == 0) || - (rxdp1->Buffer0_ptr == DMA_ERROR_CODE)) { + if (pci_dma_mapping_error(rxdp1->Buffer0_ptr)) goto memalloc_failed; - } rxdp->Host_Control = (unsigned long) (*skb); } } else if ((sp->rxd_mode == RXD_MODE_3B) && (rxdp->Host_Control == 0)) { @@ -6913,15 +6906,12 @@ static int set_rxd_buffer_pointer(struct s2io_nic *sp, struct RxD_t *rxdp, pci_map_single(sp->pdev, (*skb)->data, dev->mtu + 4, PCI_DMA_FROMDEVICE); - if( (rxdp3->Buffer2_ptr == 0) || - (rxdp3->Buffer2_ptr == DMA_ERROR_CODE)) { + if (pci_dma_mapping_error(rxdp3->Buffer2_ptr)) goto memalloc_failed; - } rxdp3->Buffer0_ptr = *temp0 = pci_map_single( sp->pdev, ba->ba_0, BUF0_LEN, PCI_DMA_FROMDEVICE); - if( (rxdp3->Buffer0_ptr == 0) || - (rxdp3->Buffer0_ptr == DMA_ERROR_CODE)) { + if (pci_dma_mapping_error(rxdp3->Buffer0_ptr)) { pci_unmap_single (sp->pdev, (dma_addr_t)rxdp3->Buffer2_ptr, dev->mtu + 4, PCI_DMA_FROMDEVICE); @@ -6933,8 +6923,7 @@ static int set_rxd_buffer_pointer(struct s2io_nic *sp, struct RxD_t *rxdp, rxdp3->Buffer1_ptr = *temp1 = pci_map_single(sp->pdev, ba->ba_1, BUF1_LEN, PCI_DMA_FROMDEVICE); - if( (rxdp3->Buffer1_ptr == 0) || - (rxdp3->Buffer1_ptr == DMA_ERROR_CODE)) { + if (pci_dma_mapping_error(rxdp3->Buffer1_ptr)) { pci_unmap_single (sp->pdev, (dma_addr_t)rxdp3->Buffer0_ptr, BUF0_LEN, PCI_DMA_FROMDEVICE); diff --git a/drivers/net/s2io.h b/drivers/net/s2io.h index 4706f7f..1827b66 100644 --- a/drivers/net/s2io.h +++ b/drivers/net/s2io.h @@ -75,10 +75,6 @@ static int debug_level = ERR_DBG; /* DEBUG message print. */ #define DBG_PRINT(dbg_level, args...) if(!(debug_level Date: Tue, 6 May 2008 19:36:26 +0100 Subject: qla3xxx: Hold RTNL while calling dev_close() dev_close() must be called holding the RTNL. Compile-tested only. Signed-off-by: Ben Hutchings Signed-off-by: Jeff Garzik diff --git a/drivers/net/qla3xxx.c b/drivers/net/qla3xxx.c index b7f7b22..bccee68 100644 --- a/drivers/net/qla3xxx.c +++ b/drivers/net/qla3xxx.c @@ -3701,7 +3701,9 @@ static int ql_cycle_adapter(struct ql3_adapter *qdev, int reset) printk(KERN_ERR PFX "%s: Driver up/down cycle failed, " "closing device\n",qdev->ndev->name); + rtnl_lock(); dev_close(qdev->ndev); + rtnl_unlock(); return -1; } return 0; -- cgit v0.10.2 From 3e3cda96d014b69f7723d1d4507897e5be6aceb7 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Tue, 6 May 2008 19:41:48 +0100 Subject: Hold RTNL while calling dev_close() dev_close() must be called holding the RTNL. Compile-tested only. Signed-off-by: Ben Hutchings Signed-off-by: Jeff Garzik diff --git a/drivers/net/wan/x25_asy.c b/drivers/net/wan/x25_asy.c index 249e180..069f8bb 100644 --- a/drivers/net/wan/x25_asy.c +++ b/drivers/net/wan/x25_asy.c @@ -32,6 +32,7 @@ #include #include #include +#include #include "x25_asy.h" #include @@ -601,8 +602,10 @@ static void x25_asy_close_tty(struct tty_struct *tty) if (!sl || sl->magic != X25_ASY_MAGIC) return; + rtnl_lock(); if (sl->dev->flags & IFF_UP) dev_close(sl->dev); + rtnl_unlock(); tty->disc_data = NULL; sl->tty = NULL; -- cgit v0.10.2 From 980dfcb93232907034a2c92d62d3a7d6ac7bef44 Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Wed, 25 Jun 2008 21:27:00 +0200 Subject: rt2x00: Fix lock dependency errror This fixes a circular locking dependency in the workqueue handling. The interface work task uses the mac80211 function ieee80211_iterate_active_interfaces() which grabs the RTNL lock. However when the interface is brough down, this happens under the RTNL lock as well, this causes problems because mac80211 will flush the workqueue during the ifdown event. This causes mac80211 to wait until the driver has completed all work which can't finish because it is waiting on the RTNL lock. This is fixed by moving rt2x00 workqueue tasks on a different workqueue, this workqueue can be flushed when the ieee80211_hw structure is removed by the driver (when the driver is unloaded) which does not happen under the RTNL lock. Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h index 611d983..b4bf1e0 100644 --- a/drivers/net/wireless/rt2x00/rt2x00.h +++ b/drivers/net/wireless/rt2x00/rt2x00.h @@ -821,6 +821,7 @@ struct rt2x00_dev { /* * Scheduled work. */ + struct workqueue_struct *workqueue; struct work_struct intf_work; struct work_struct filter_work; diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c index 2673d56..c997d4f 100644 --- a/drivers/net/wireless/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c @@ -75,7 +75,7 @@ static void rt2x00lib_start_link_tuner(struct rt2x00_dev *rt2x00dev) rt2x00lib_reset_link_tuner(rt2x00dev); - queue_delayed_work(rt2x00dev->hw->workqueue, + queue_delayed_work(rt2x00dev->workqueue, &rt2x00dev->link.work, LINK_TUNE_INTERVAL); } @@ -137,14 +137,6 @@ void rt2x00lib_disable_radio(struct rt2x00_dev *rt2x00dev) return; /* - * Stop all scheduled work. - */ - if (work_pending(&rt2x00dev->intf_work)) - cancel_work_sync(&rt2x00dev->intf_work); - if (work_pending(&rt2x00dev->filter_work)) - cancel_work_sync(&rt2x00dev->filter_work); - - /* * Stop the TX queues. */ ieee80211_stop_queues(rt2x00dev->hw); @@ -398,8 +390,8 @@ static void rt2x00lib_link_tuner(struct work_struct *work) * Increase tuner counter, and reschedule the next link tuner run. */ rt2x00dev->link.count++; - queue_delayed_work(rt2x00dev->hw->workqueue, &rt2x00dev->link.work, - LINK_TUNE_INTERVAL); + queue_delayed_work(rt2x00dev->workqueue, + &rt2x00dev->link.work, LINK_TUNE_INTERVAL); } static void rt2x00lib_packetfilter_scheduled(struct work_struct *work) @@ -433,6 +425,15 @@ static void rt2x00lib_intf_scheduled_iter(void *data, u8 *mac, spin_unlock(&intf->lock); + /* + * It is possible the radio was disabled while the work had been + * scheduled. If that happens we should return here immediately, + * note that in the spinlock protected area above the delayed_flags + * have been cleared correctly. + */ + if (!test_bit(DEVICE_ENABLED_RADIO, &rt2x00dev->flags)) + return; + if (delayed_flags & DELAYED_UPDATE_BEACON) { skb = ieee80211_beacon_get(rt2x00dev->hw, vif, &control); if (skb && rt2x00dev->ops->hw->beacon_update(rt2x00dev->hw, @@ -441,7 +442,7 @@ static void rt2x00lib_intf_scheduled_iter(void *data, u8 *mac, } if (delayed_flags & DELAYED_CONFIG_ERP) - rt2x00lib_config_erp(rt2x00dev, intf, &intf->conf); + rt2x00lib_config_erp(rt2x00dev, intf, &conf); if (delayed_flags & DELAYED_LED_ASSOC) rt2x00leds_led_assoc(rt2x00dev, !!rt2x00dev->intf_associated); @@ -487,7 +488,7 @@ void rt2x00lib_beacondone(struct rt2x00_dev *rt2x00dev) rt2x00lib_beacondone_iter, rt2x00dev); - queue_work(rt2x00dev->hw->workqueue, &rt2x00dev->intf_work); + queue_work(rt2x00dev->workqueue, &rt2x00dev->intf_work); } EXPORT_SYMBOL_GPL(rt2x00lib_beacondone); @@ -1130,6 +1131,10 @@ int rt2x00lib_probe_dev(struct rt2x00_dev *rt2x00dev) /* * Initialize configuration work. */ + rt2x00dev->workqueue = create_singlethread_workqueue("rt2x00lib"); + if (!rt2x00dev->workqueue) + goto exit; + INIT_WORK(&rt2x00dev->intf_work, rt2x00lib_intf_scheduled); INIT_WORK(&rt2x00dev->filter_work, rt2x00lib_packetfilter_scheduled); INIT_DELAYED_WORK(&rt2x00dev->link.work, rt2x00lib_link_tuner); @@ -1190,6 +1195,13 @@ void rt2x00lib_remove_dev(struct rt2x00_dev *rt2x00dev) rt2x00leds_unregister(rt2x00dev); /* + * Stop all queued work. Note that most tasks will already be halted + * during rt2x00lib_disable_radio() and rt2x00lib_uninitialize(). + */ + flush_workqueue(rt2x00dev->workqueue); + destroy_workqueue(rt2x00dev->workqueue); + + /* * Free ieee80211_hw memory. */ rt2x00lib_remove_hw(rt2x00dev); diff --git a/drivers/net/wireless/rt2x00/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c index 87e280a..9cb023e 100644 --- a/drivers/net/wireless/rt2x00/rt2x00mac.c +++ b/drivers/net/wireless/rt2x00/rt2x00mac.c @@ -428,7 +428,7 @@ void rt2x00mac_configure_filter(struct ieee80211_hw *hw, if (!test_bit(DRIVER_REQUIRE_SCHEDULED, &rt2x00dev->flags)) rt2x00dev->ops->lib->config_filter(rt2x00dev, *total_flags); else - queue_work(rt2x00dev->hw->workqueue, &rt2x00dev->filter_work); + queue_work(rt2x00dev->workqueue, &rt2x00dev->filter_work); } EXPORT_SYMBOL_GPL(rt2x00mac_configure_filter); @@ -509,7 +509,7 @@ void rt2x00mac_bss_info_changed(struct ieee80211_hw *hw, memcpy(&intf->conf, bss_conf, sizeof(*bss_conf)); if (delayed) { intf->delayed_flags |= delayed; - queue_work(rt2x00dev->hw->workqueue, &rt2x00dev->intf_work); + queue_work(rt2x00dev->workqueue, &rt2x00dev->intf_work); } spin_unlock(&intf->lock); } -- cgit v0.10.2 From 5f4a6fae46a214c4dce3bd63a6219a5f1c818c78 Mon Sep 17 00:00:00 2001 From: Harvey Harrison Date: Wed, 25 Jun 2008 14:20:37 -0700 Subject: prism: islpci_eth.c endianness fix clock is already cpu-endian (see le32_to_cpu slightly before), so le64_to_cpu doesn't make much sense. Signed-off-by: Harvey Harrison Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/prism54/islpci_eth.c b/drivers/net/wireless/prism54/islpci_eth.c index 762e85b..e43bae9 100644 --- a/drivers/net/wireless/prism54/islpci_eth.c +++ b/drivers/net/wireless/prism54/islpci_eth.c @@ -290,7 +290,7 @@ islpci_monitor_rx(islpci_private *priv, struct sk_buff **skb) avs->version = cpu_to_be32(P80211CAPTURE_VERSION); avs->length = cpu_to_be32(sizeof (struct avs_80211_1_header)); - avs->mactime = cpu_to_be64(le64_to_cpu(clock)); + avs->mactime = cpu_to_be64(clock); avs->hosttime = cpu_to_be64(jiffies); avs->phytype = cpu_to_be32(6); /*OFDM: 6 for (g), 8 for (a) */ avs->channel = cpu_to_be32(channel_of_freq(freq)); -- cgit v0.10.2 From 00eb7fe77eb455f807c396f9917f0f623d4c84bb Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Thu, 26 Jun 2008 12:13:46 +0300 Subject: mac80211: fix an oops in several failure paths in key allocation This patch fixes an oops in several failure paths in key allocation. This Oops occurs when freeing a key that has not been linked yet, so the key->sdata is not set. Signed-off-by: Emmanuel Grumbach Signed-off-by: Tomas Winkler Acked-by: Johannes Berg Signed-off-by: John W. Linville diff --git a/net/mac80211/key.c b/net/mac80211/key.c index 150d66d..220e83b 100644 --- a/net/mac80211/key.c +++ b/net/mac80211/key.c @@ -380,6 +380,15 @@ void ieee80211_key_free(struct ieee80211_key *key) if (!key) return; + if (!key->sdata) { + /* The key has not been linked yet, simply free it + * and don't Oops */ + if (key->conf.alg == ALG_CCMP) + ieee80211_aes_key_free(key->u.ccmp.tfm); + kfree(key); + return; + } + spin_lock_irqsave(&key->sdata->local->key_lock, flags); __ieee80211_key_free(key); spin_unlock_irqrestore(&key->sdata->local->key_lock, flags); -- cgit v0.10.2 From 479798211967cd828e09ce27775b8cbfe99462ab Mon Sep 17 00:00:00 2001 From: Andre Haupt Date: Fri, 27 Jun 2008 17:22:08 -0700 Subject: hamradio: remove unused variable Signed-off-by: Andre Haupt Signed-off-by: David S. Miller diff --git a/drivers/net/hamradio/dmascc.c b/drivers/net/hamradio/dmascc.c index 0b94833..e8cfade 100644 --- a/drivers/net/hamradio/dmascc.c +++ b/drivers/net/hamradio/dmascc.c @@ -1077,8 +1077,6 @@ static inline void rx_off(struct scc_priv *priv) static void start_timer(struct scc_priv *priv, int t, int r15) { - unsigned long flags; - outb(priv->tmr_mode, priv->tmr_ctrl); if (t == 0) { tm_isr(priv); -- cgit v0.10.2 From 57413ebc4e0f1e471a3b4db4aff9a85c083d090e Mon Sep 17 00:00:00 2001 From: Miquel van Smoorenburg Date: Fri, 27 Jun 2008 17:23:57 -0700 Subject: tcp: calculate tcp_mem based on low memory instead of all memory The tcp_mem array which contains limits on the total amount of memory used by TCP sockets is calculated based on nr_all_pages. On a 32 bits x86 system, we should base this on the number of lowmem pages. Signed-off-by: Miquel van Smoorenburg Signed-off-by: David S. Miller diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index fc54a48..850825d 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c @@ -260,6 +260,8 @@ #include #include #include +#include +#include #include #include #include @@ -2620,7 +2622,7 @@ __setup("thash_entries=", set_thash_entries); void __init tcp_init(void) { struct sk_buff *skb = NULL; - unsigned long limit; + unsigned long nr_pages, limit; int order, i, max_share; BUILD_BUG_ON(sizeof(struct tcp_skb_cb) > sizeof(skb->cb)); @@ -2689,8 +2691,9 @@ void __init tcp_init(void) * is up to 1/2 at 256 MB, decreasing toward zero with the amount of * memory, with a floor of 128 pages. */ - limit = min(nr_all_pages, 1UL<<(28-PAGE_SHIFT)) >> (20-PAGE_SHIFT); - limit = (limit * (nr_all_pages >> (20-PAGE_SHIFT))) >> (PAGE_SHIFT-11); + nr_pages = totalram_pages - totalhigh_pages; + limit = min(nr_pages, 1UL<<(28-PAGE_SHIFT)) >> (20-PAGE_SHIFT); + limit = (limit * (nr_pages >> (20-PAGE_SHIFT))) >> (PAGE_SHIFT-11); limit = max(limit, 128UL); sysctl_tcp_mem[0] = limit / 4 * 3; sysctl_tcp_mem[1] = limit; -- cgit v0.10.2 From db43a282d3ec92ea45109c5551fff3dcc5afef02 Mon Sep 17 00:00:00 2001 From: Octavian Purdila Date: Fri, 27 Jun 2008 17:27:21 -0700 Subject: tcp: fix for splice receive when used with software LRO If an skb has nr_frags set to zero but its frag_list is not empty (as it can happen if software LRO is enabled), and a previous tcp_read_sock has consumed the linear part of the skb, then __skb_splice_bits: (a) incorrectly reports an error and (b) forgets to update the offset to account for the linear part Any of the two problems will cause the subsequent __skb_splice_bits call (the one that handles the frag_list skbs) to either skip data, or, if the unadjusted offset is greater then the size of the next skb in the frag_list, make tcp_splice_read loop forever. Signed-off-by: Octavian Purdila Signed-off-by: David S. Miller diff --git a/net/core/skbuff.c b/net/core/skbuff.c index 1e556d3..3666216 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c @@ -1292,12 +1292,14 @@ static int __skb_splice_bits(struct sk_buff *skb, unsigned int *offset, { unsigned int nr_pages = spd->nr_pages; unsigned int poff, plen, len, toff, tlen; - int headlen, seg; + int headlen, seg, error = 0; toff = *offset; tlen = *total_len; - if (!tlen) + if (!tlen) { + error = 1; goto err; + } /* * if the offset is greater than the linear part, go directly to @@ -1339,7 +1341,8 @@ static int __skb_splice_bits(struct sk_buff *skb, unsigned int *offset, * just jump directly to update and return, no point * in going over fragments when the output is full. */ - if (spd_fill_page(spd, virt_to_page(p), plen, poff, skb)) + error = spd_fill_page(spd, virt_to_page(p), plen, poff, skb); + if (error) goto done; tlen -= plen; @@ -1369,7 +1372,8 @@ map_frag: if (!plen) break; - if (spd_fill_page(spd, f->page, plen, poff, skb)) + error = spd_fill_page(spd, f->page, plen, poff, skb); + if (error) break; tlen -= plen; @@ -1382,7 +1386,10 @@ done: return 0; } err: - return 1; + /* update the offset to reflect the linear part skip, if any */ + if (!error) + *offset = toff; + return error; } /* -- cgit v0.10.2 From ec0d215f9420564fc8286dcf93d2d068bb53a07e Mon Sep 17 00:00:00 2001 From: Rainer Weikusat Date: Fri, 27 Jun 2008 19:34:18 -0700 Subject: af_unix: fix 'poll for write'/connected DGRAM sockets For n:1 'datagram connections' (eg /dev/log), the unix_dgram_sendmsg routine implements a form of receiver-imposed flow control by comparing the length of the receive queue of the 'peer socket' with the max_ack_backlog value stored in the corresponding sock structure, either blocking the thread which caused the send-routine to be called or returning EAGAIN. This routine is used by both SOCK_DGRAM and SOCK_SEQPACKET sockets. The poll-implementation for these socket types is datagram_poll from core/datagram.c. A socket is deemed to be writeable by this routine when the memory presently consumed by datagrams owned by it is less than the configured socket send buffer size. This is always wrong for PF_UNIX non-stream sockets connected to server sockets dealing with (potentially) multiple clients if the abovementioned receive queue is currently considered to be full. 'poll' will then return, indicating that the socket is writeable, but a subsequent write result in EAGAIN, effectively causing an (usual) application to 'poll for writeability by repeated send request with O_NONBLOCK set' until it has consumed its time quantum. The change below uses a suitably modified variant of the datagram_poll routines for both type of PF_UNIX sockets, which tests if the recv-queue of the peer a socket is connected to is presently considered to be 'full' as part of the 'is this socket writeable'-checking code. The socket being polled is additionally put onto the peer_wait wait queue associated with its peer, because the unix_dgram_recvmsg routine does a wake up on this queue after a datagram was received and the 'other wakeup call' is done implicitly as part of skb destruction, meaning, a process blocked in poll because of a full peer receive queue could otherwise sleep forever if no datagram owned by its socket was already sitting on this queue. Among this change is a small (inline) helper routine named 'unix_recvq_full', which consolidates the actual testing code (in three different places) into a single location. Signed-off-by: Rainer Weikusat Signed-off-by: David S. Miller diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c index 657835f..783317d 100644 --- a/net/unix/af_unix.c +++ b/net/unix/af_unix.c @@ -487,8 +487,8 @@ static int unix_socketpair(struct socket *, struct socket *); static int unix_accept(struct socket *, struct socket *, int); static int unix_getname(struct socket *, struct sockaddr *, int *, int); static unsigned int unix_poll(struct file *, struct socket *, poll_table *); -static unsigned int unix_datagram_poll(struct file *, struct socket *, - poll_table *); +static unsigned int unix_dgram_poll(struct file *, struct socket *, + poll_table *); static int unix_ioctl(struct socket *, unsigned int, unsigned long); static int unix_shutdown(struct socket *, int); static int unix_stream_sendmsg(struct kiocb *, struct socket *, @@ -534,7 +534,7 @@ static const struct proto_ops unix_dgram_ops = { .socketpair = unix_socketpair, .accept = sock_no_accept, .getname = unix_getname, - .poll = unix_datagram_poll, + .poll = unix_dgram_poll, .ioctl = unix_ioctl, .listen = sock_no_listen, .shutdown = unix_shutdown, @@ -555,7 +555,7 @@ static const struct proto_ops unix_seqpacket_ops = { .socketpair = unix_socketpair, .accept = unix_accept, .getname = unix_getname, - .poll = unix_datagram_poll, + .poll = unix_dgram_poll, .ioctl = unix_ioctl, .listen = unix_listen, .shutdown = unix_shutdown, @@ -1994,29 +1994,13 @@ static unsigned int unix_poll(struct file * file, struct socket *sock, poll_tabl return mask; } -static unsigned int unix_datagram_poll(struct file *file, struct socket *sock, - poll_table *wait) +static unsigned int unix_dgram_poll(struct file *file, struct socket *sock, + poll_table *wait) { - struct sock *sk = sock->sk, *peer; - unsigned int mask; + struct sock *sk = sock->sk, *other; + unsigned int mask, writable; poll_wait(file, sk->sk_sleep, wait); - - peer = unix_peer_get(sk); - if (peer) { - if (peer != sk) { - /* - * Writability of a connected socket additionally - * depends on the state of the receive queue of the - * peer. - */ - poll_wait(file, &unix_sk(peer)->peer_wait, wait); - } else { - sock_put(peer); - peer = NULL; - } - } - mask = 0; /* exceptional events? */ @@ -2042,14 +2026,26 @@ static unsigned int unix_datagram_poll(struct file *file, struct socket *sock, } /* writable? */ - if (unix_writable(sk) && !(peer && unix_recvq_full(peer))) + writable = unix_writable(sk); + if (writable) { + other = unix_peer_get(sk); + if (other) { + if (unix_peer(other) != sk) { + poll_wait(file, &unix_sk(other)->peer_wait, + wait); + if (unix_recvq_full(other)) + writable = 0; + } + + sock_put(other); + } + } + + if (writable) mask |= POLLOUT | POLLWRNORM | POLLWRBAND; else set_bit(SOCK_ASYNC_NOSPACE, &sk->sk_socket->flags); - if (peer) - sock_put(peer); - return mask; } -- cgit v0.10.2 From 5dbaec5dc6a4895db8bf9765a867418481ed7311 Mon Sep 17 00:00:00 2001 From: Wang Chen Date: Fri, 27 Jun 2008 19:35:16 -0700 Subject: netdevice: Fix typo of dev_unicast_add() comment Signed-off-by: Wang Chen Signed-off-by: David S. Miller diff --git a/net/core/dev.c b/net/core/dev.c index c421a1f..56b4657 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -2973,7 +2973,7 @@ EXPORT_SYMBOL(dev_unicast_delete); /** * dev_unicast_add - add a secondary unicast address * @dev: device - * @addr: address to delete + * @addr: address to add * @alen: length of @addr * * Add a secondary unicast address to the device or increase -- cgit v0.10.2 From 01e123d79a23000f85c4cfb12a957908c0b2c3d8 Mon Sep 17 00:00:00 2001 From: WANG Cong Date: Fri, 27 Jun 2008 19:51:35 -0700 Subject: pkt_sched: ERR_PTR() ususally encodes an negative errno, not positive. Note, in the following patch, 'err' is initialized as: int err = -ENOBUFS; Signed-off-by: WANG Cong Signed-off-by: David S. Miller diff --git a/net/sched/sch_generic.c b/net/sched/sch_generic.c index d355e5e..13afa72 100644 --- a/net/sched/sch_generic.c +++ b/net/sched/sch_generic.c @@ -468,7 +468,7 @@ struct Qdisc *qdisc_alloc(struct net_device *dev, struct Qdisc_ops *ops) return sch; errout: - return ERR_PTR(-err); + return ERR_PTR(err); } struct Qdisc * qdisc_create_dflt(struct net_device *dev, struct Qdisc_ops *ops, -- cgit v0.10.2 From ede16af4cdbd21fa15d4178beb7c6fcbcccd07e9 Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Fri, 27 Jun 2008 19:54:05 -0700 Subject: pkt_sched: Remove CONFIG_NET_SCH_RR Commit d62733c8e437fdb58325617c4b3331769ba82d70 ([SCHED]: Qdisc changes and sch_rr added for multiqueue) added a NET_SCH_RR option that was unused since the code went unconditionally into sch_prio. Reported-by: Robert P. J. Day Signed-off-by: Adrian Bunk Signed-off-by: David S. Miller diff --git a/net/sched/Kconfig b/net/sched/Kconfig index 82adfe6..9437b27 100644 --- a/net/sched/Kconfig +++ b/net/sched/Kconfig @@ -106,17 +106,6 @@ config NET_SCH_PRIO To compile this code as a module, choose M here: the module will be called sch_prio. -config NET_SCH_RR - tristate "Multi Band Round Robin Queuing (RR)" - select NET_SCH_PRIO - ---help--- - Say Y here if you want to use an n-band round robin packet - scheduler. - - The module uses sch_prio for its framework and is aliased as - sch_rr, so it will load sch_prio, although it is referred - to using sch_rr. - config NET_SCH_RED tristate "Random Early Detection (RED)" ---help--- -- cgit v0.10.2 From c88e6f51c2154c7606f7e281bcca2d1a2c89d7b2 Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Fri, 27 Jun 2008 19:54:54 -0700 Subject: include/linux/netdevice.h: don't export MAX_HEADER to userspace Due to the CONFIG_'s the value is anyway not correct in userspace. Signed-off-by: Adrian Bunk Signed-off-by: David S. Miller diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index f27fd20..25f8710 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -88,6 +88,8 @@ struct wireless_dev; #define NETDEV_TX_BUSY 1 /* driver tx path was busy*/ #define NETDEV_TX_LOCKED -1 /* driver tx lock was already taken */ +#ifdef __KERNEL__ + /* * Compute the worst case header length according to the protocols * used. @@ -114,6 +116,8 @@ struct wireless_dev; #define MAX_HEADER (LL_MAX_HEADER + 48) #endif +#endif /* __KERNEL__ */ + struct net_device_subqueue { /* Give a control state for each queue. This struct may contain -- cgit v0.10.2 From 7be87351a1f6430426e88b4fcde353ab3330caff Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Fri, 27 Jun 2008 20:00:19 -0700 Subject: tcp: /proc/net/tcp rto,ato values not scaled properly (v2) I found another case where we are sending information to userspace in the wrong HZ scale. This should have been fixed back in 2.5 :-( This means an ABI change but as it stands there is no way for an application like ss to get the right value. Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 12695be..ffe869a 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -2291,7 +2291,7 @@ static void get_tcp4_sock(struct sock *sk, struct seq_file *f, int i, int *len) } seq_printf(f, "%4d: %08X:%04X %08X:%04X %02X %08X:%08X %02X:%08lX " - "%08X %5d %8d %lu %d %p %u %u %u %u %d%n", + "%08X %5d %8d %lu %d %p %lu %lu %u %u %d%n", i, src, srcp, dest, destp, sk->sk_state, tp->write_seq - tp->snd_una, sk->sk_state == TCP_LISTEN ? sk->sk_ack_backlog : @@ -2303,8 +2303,8 @@ static void get_tcp4_sock(struct sock *sk, struct seq_file *f, int i, int *len) icsk->icsk_probes_out, sock_i_ino(sk), atomic_read(&sk->sk_refcnt), sk, - icsk->icsk_rto, - icsk->icsk_ack.ato, + jiffies_to_clock_t(icsk->icsk_rto), + jiffies_to_clock_t(icsk->icsk_ack.ato), (icsk->icsk_ack.quick << 1) | icsk->icsk_ack.pingpong, tp->snd_cwnd, tp->snd_ssthresh >= 0xFFFF ? -1 : tp->snd_ssthresh, diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index cb46749..40ea9c3 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c @@ -2036,7 +2036,7 @@ static void get_tcp6_sock(struct seq_file *seq, struct sock *sp, int i) seq_printf(seq, "%4d: %08X%08X%08X%08X:%04X %08X%08X%08X%08X:%04X " - "%02X %08X:%08X %02X:%08lX %08X %5d %8d %lu %d %p %u %u %u %u %d\n", + "%02X %08X:%08X %02X:%08lX %08X %5d %8d %lu %d %p %lu %lu %u %u %d\n", i, src->s6_addr32[0], src->s6_addr32[1], src->s6_addr32[2], src->s6_addr32[3], srcp, @@ -2052,8 +2052,8 @@ static void get_tcp6_sock(struct seq_file *seq, struct sock *sp, int i) icsk->icsk_probes_out, sock_i_ino(sp), atomic_read(&sp->sk_refcnt), sp, - icsk->icsk_rto, - icsk->icsk_ack.ato, + jiffies_to_clock_t(icsk->icsk_rto), + jiffies_to_clock_t(icsk->icsk_ack.ato), (icsk->icsk_ack.quick << 1 ) | icsk->icsk_ack.pingpong, tp->snd_cwnd, tp->snd_ssthresh>=0xFFFF?-1:tp->snd_ssthresh ); -- cgit v0.10.2 From 10b595aff138961b520bfed51d664fd99980f6e9 Mon Sep 17 00:00:00 2001 From: Julius Volz Date: Fri, 27 Jun 2008 20:02:14 -0700 Subject: netlink: Fix some doc comments in net/netlink/attr.c Fix some doc comments to match function and attribute names in net/netlink/attr.c. Signed-off-by: Julius Volz Signed-off-by: David S. Miller diff --git a/net/netlink/attr.c b/net/netlink/attr.c index 47bbf45..2d106cf 100644 --- a/net/netlink/attr.c +++ b/net/netlink/attr.c @@ -132,6 +132,7 @@ errout: * @maxtype: maximum attribute type to be expected * @head: head of attribute stream * @len: length of attribute stream + * @policy: validation policy * * Parses a stream of attributes and stores a pointer to each attribute in * the tb array accessable via the attribute type. Attributes with a type @@ -194,7 +195,7 @@ struct nlattr *nla_find(struct nlattr *head, int len, int attrtype) /** * nla_strlcpy - Copy string attribute payload into a sized buffer * @dst: where to copy the string to - * @src: attribute to copy the string from + * @nla: attribute to copy the string from * @dstsize: size of destination buffer * * Copies at most dstsize - 1 bytes into the destination buffer. @@ -340,9 +341,9 @@ struct nlattr *nla_reserve(struct sk_buff *skb, int attrtype, int attrlen) } /** - * nla_reserve - reserve room for attribute without header + * nla_reserve_nohdr - reserve room for attribute without header * @skb: socket buffer to reserve room on - * @len: length of attribute payload + * @attrlen: length of attribute payload * * Reserves room for attribute payload without a header. * -- cgit v0.10.2 From a0a61a604c60c14accc3962ecfeee9acc7a3c08a Mon Sep 17 00:00:00 2001 From: Li Zefan Date: Fri, 27 Jun 2008 20:03:24 -0700 Subject: CONNECTOR: add a proc entry to list connectors I got a problem when I wanted to check if the kernel supports process event connector, and It seems there's no way to do this check. At best I can check if the kernel supports connector or not, by looking into /proc/net/netlink, or maybe checking the return value of bind() to see if it's ENOENT. So it would be useful to add /proc/net/connector to list all supported connectors: # cat /proc/net/connector Name ID connector 4294967295:4294967295 cn_proc 1:1 w1 3:1 Changelog: - fix memory leak: s/seq_release/single_release - use spin_lock_bh instead of spin_lock_irqsave Signed-off-by: Li Zefan Acked-by: Evgeniy Polyakov Signed-off-by: David S. Miller diff --git a/drivers/connector/connector.c b/drivers/connector/connector.c index 85e2ba7..bf48300 100644 --- a/drivers/connector/connector.c +++ b/drivers/connector/connector.c @@ -27,6 +27,8 @@ #include #include #include +#include +#include #include @@ -403,6 +405,40 @@ static void cn_callback(void *data) mutex_unlock(¬ify_lock); } +static int cn_proc_show(struct seq_file *m, void *v) +{ + struct cn_queue_dev *dev = cdev.cbdev; + struct cn_callback_entry *cbq; + + seq_printf(m, "Name ID\n"); + + spin_lock_bh(&dev->queue_lock); + + list_for_each_entry(cbq, &dev->queue_list, callback_entry) { + seq_printf(m, "%-15s %u:%u\n", + cbq->id.name, + cbq->id.id.idx, + cbq->id.id.val); + } + + spin_unlock_bh(&dev->queue_lock); + + return 0; +} + +static int cn_proc_open(struct inode *inode, struct file *file) +{ + return single_open(file, cn_proc_show, NULL); +} + +static const struct file_operations cn_file_ops = { + .owner = THIS_MODULE, + .open = cn_proc_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release +}; + static int __devinit cn_init(void) { struct cn_dev *dev = &cdev; @@ -434,6 +470,8 @@ static int __devinit cn_init(void) return -EINVAL; } + proc_net_fops_create(&init_net, "connector", S_IRUGO, &cn_file_ops); + return 0; } @@ -443,6 +481,8 @@ static void __devexit cn_fini(void) cn_already_initialized = 0; + proc_net_remove(&init_net, "connector"); + cn_del_callback(&dev->id); cn_queue_free_dev(dev->cbdev); netlink_kernel_release(dev->nls); -- cgit v0.10.2 From 9a375803feaadb6c34e0807bd9325885dcca5c00 Mon Sep 17 00:00:00 2001 From: Pavel Emelyanov Date: Fri, 27 Jun 2008 20:06:08 -0700 Subject: inet fragments: fix race between inet_frag_find and inet_frag_secret_rebuild The problem is that while we work w/o the inet_frags.lock even read-locked the secret rebuild timer may occur (on another CPU, since BHs are still disabled in the inet_frag_find) and change the rnd seed for ipv4/6 fragments. It was caused by my patch fd9e63544cac30a34c951f0ec958038f0529e244 ([INET]: Omit double hash calculations in xxx_frag_intern) late in the 2.6.24 kernel, so this should probably be queued to -stable. Signed-off-by: Pavel Emelyanov Signed-off-by: David S. Miller diff --git a/net/ipv4/inet_fragment.c b/net/ipv4/inet_fragment.c index 4ed429b..0546a0b 100644 --- a/net/ipv4/inet_fragment.c +++ b/net/ipv4/inet_fragment.c @@ -192,14 +192,21 @@ EXPORT_SYMBOL(inet_frag_evictor); static struct inet_frag_queue *inet_frag_intern(struct netns_frags *nf, struct inet_frag_queue *qp_in, struct inet_frags *f, - unsigned int hash, void *arg) + void *arg) { struct inet_frag_queue *qp; #ifdef CONFIG_SMP struct hlist_node *n; #endif + unsigned int hash; write_lock(&f->lock); + /* + * While we stayed w/o the lock other CPU could update + * the rnd seed, so we need to re-calculate the hash + * chain. Fortunatelly the qp_in can be used to get one. + */ + hash = f->hashfn(qp_in); #ifdef CONFIG_SMP /* With SMP race we have to recheck hash table, because * such entry could be created on other cpu, while we @@ -247,7 +254,7 @@ static struct inet_frag_queue *inet_frag_alloc(struct netns_frags *nf, } static struct inet_frag_queue *inet_frag_create(struct netns_frags *nf, - struct inet_frags *f, void *arg, unsigned int hash) + struct inet_frags *f, void *arg) { struct inet_frag_queue *q; @@ -255,7 +262,7 @@ static struct inet_frag_queue *inet_frag_create(struct netns_frags *nf, if (q == NULL) return NULL; - return inet_frag_intern(nf, q, f, hash, arg); + return inet_frag_intern(nf, q, f, arg); } struct inet_frag_queue *inet_frag_find(struct netns_frags *nf, @@ -264,7 +271,6 @@ struct inet_frag_queue *inet_frag_find(struct netns_frags *nf, struct inet_frag_queue *q; struct hlist_node *n; - read_lock(&f->lock); hlist_for_each_entry(q, n, &f->hash[hash], list) { if (q->net == nf && f->match(q, key)) { atomic_inc(&q->refcnt); @@ -274,6 +280,6 @@ struct inet_frag_queue *inet_frag_find(struct netns_frags *nf, } read_unlock(&f->lock); - return inet_frag_create(nf, f, key, hash); + return inet_frag_create(nf, f, key); } EXPORT_SYMBOL(inet_frag_find); diff --git a/net/ipv4/ip_fragment.c b/net/ipv4/ip_fragment.c index cd6ce6a..37221f6 100644 --- a/net/ipv4/ip_fragment.c +++ b/net/ipv4/ip_fragment.c @@ -229,6 +229,8 @@ static inline struct ipq *ip_find(struct net *net, struct iphdr *iph, u32 user) arg.iph = iph; arg.user = user; + + read_lock(&ip4_frags.lock); hash = ipqhashfn(iph->id, iph->saddr, iph->daddr, iph->protocol); q = inet_frag_find(&net->ipv4.frags, &ip4_frags, &arg, hash); diff --git a/net/ipv6/netfilter/nf_conntrack_reasm.c b/net/ipv6/netfilter/nf_conntrack_reasm.c index e65e26e..cf20bc4 100644 --- a/net/ipv6/netfilter/nf_conntrack_reasm.c +++ b/net/ipv6/netfilter/nf_conntrack_reasm.c @@ -207,9 +207,10 @@ fq_find(__be32 id, struct in6_addr *src, struct in6_addr *dst) arg.id = id; arg.src = src; arg.dst = dst; + + read_lock_bh(&nf_frags.lock); hash = ip6qhashfn(id, src, dst); - local_bh_disable(); q = inet_frag_find(&nf_init_frags, &nf_frags, &arg, hash); local_bh_enable(); if (q == NULL) diff --git a/net/ipv6/reassembly.c b/net/ipv6/reassembly.c index 798cabc..a60d7d1 100644 --- a/net/ipv6/reassembly.c +++ b/net/ipv6/reassembly.c @@ -247,6 +247,8 @@ fq_find(struct net *net, __be32 id, struct in6_addr *src, struct in6_addr *dst, arg.id = id; arg.src = src; arg.dst = dst; + + read_lock(&ip6_frags.lock); hash = ip6qhashfn(id, src, dst); q = inet_frag_find(&net->ipv6.frags, &ip6_frags, &arg, hash); -- cgit v0.10.2 From 251a4b320f2352598f84e4452ab538aa8064af52 Mon Sep 17 00:00:00 2001 From: Eli Cohen Date: Fri, 27 Jun 2008 20:09:00 -0700 Subject: net/inet_lro: remove setting skb->ip_summed when not LRO-able When an SKB cannot be chained to a session, the current code attempts to "restore" its ip_summed field from lro_mgr->ip_summed. However, lro_mgr->ip_summed does not hold the original value; in fact, we'd better not touch skb->ip_summed since it is not modified by the code in the path leading to a failure to chain it. Also use a cleaer comment to the describe the ip_summed field of struct net_lro_mgr. Issue raised by Or Gerlitz Signed-off-by: Eli Cohen Signed-off-by: David S. Miller diff --git a/include/linux/inet_lro.h b/include/linux/inet_lro.h index 80335b7..c4335fa 100644 --- a/include/linux/inet_lro.h +++ b/include/linux/inet_lro.h @@ -84,7 +84,11 @@ struct net_lro_mgr { from received packets and eth protocol is still ETH_P_8021Q */ - u32 ip_summed; /* Set in non generated SKBs in page mode */ + /* + * Set for generated SKBs that are not added to + * the frag list in fragmented mode + */ + u32 ip_summed; u32 ip_summed_aggr; /* Set in aggregated SKBs: CHECKSUM_UNNECESSARY * or CHECKSUM_NONE */ diff --git a/net/ipv4/inet_lro.c b/net/ipv4/inet_lro.c index 4a4d49f..cfd034a 100644 --- a/net/ipv4/inet_lro.c +++ b/net/ipv4/inet_lro.c @@ -383,8 +383,7 @@ static int __lro_proc_skb(struct net_lro_mgr *lro_mgr, struct sk_buff *skb, out2: /* send aggregated SKBs to stack */ lro_flush(lro_mgr, lro_desc); -out: /* Original SKB has to be posted to stack */ - skb->ip_summed = lro_mgr->ip_summed; +out: return 1; } -- cgit v0.10.2 From 59d88c00cafe5192b058abf4f3ce17c2e27d1c09 Mon Sep 17 00:00:00 2001 From: Paul Moore Date: Fri, 27 Jun 2008 20:12:32 -0700 Subject: netlabel: Fix a problem when dumping the default IPv6 static labels There is a missing "!" in a conditional statement which is causing entries to be skipped when dumping the default IPv6 static label entries. This can be demonstrated by running the following: # netlabelctl unlbl add default address:::1 \ label:system_u:object_r:unlabeled_t:s0 # netlabelctl -p unlbl list ... you will notice that the entry for the IPv6 localhost address is not displayed but does exist (works correctly, causes collisions when attempting to add duplicate entries, etc.). Signed-off-by: Paul Moore Signed-off-by: David S. Miller diff --git a/net/netlabel/netlabel_unlabeled.c b/net/netlabel/netlabel_unlabeled.c index 0099da5..52b2611 100644 --- a/net/netlabel/netlabel_unlabeled.c +++ b/net/netlabel/netlabel_unlabeled.c @@ -1534,7 +1534,7 @@ static int netlbl_unlabel_staticlistdef(struct sk_buff *skb, } } list_for_each_entry_rcu(addr6, &iface->addr6_list, list) { - if (addr6->valid || iter_addr6++ < skip_addr6) + if (!addr6->valid || iter_addr6++ < skip_addr6) continue; if (netlbl_unlabel_staticlist_gen(NLBL_UNLABEL_C_STATICLISTDEF, iface, -- cgit v0.10.2 From d420895efb259a78dda50f95289571faa6e10e41 Mon Sep 17 00:00:00 2001 From: YOSHIFUJI Hideaki Date: Fri, 27 Jun 2008 20:14:54 -0700 Subject: ipv6 route: Convert rt6_device_match() to use RT6_LOOKUP_F_xxx flags. The commit 77d16f450ae0452d7d4b009f78debb1294fb435c ("[IPV6] ROUTE: Unify RT6_F_xxx and RT6_SELECT_F_xxx flags") intended to pass various routing lookup hints around RT6_LOOKUP_F_xxx flags, but conversion was missing for rt6_device_match(). Signed-off-by: YOSHIFUJI Hideaki Signed-off-by: David S. Miller diff --git a/net/ipv6/route.c b/net/ipv6/route.c index d1f3e19..7ff6870 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c @@ -240,7 +240,7 @@ static inline int rt6_need_strict(struct in6_addr *daddr) static inline struct rt6_info *rt6_device_match(struct net *net, struct rt6_info *rt, int oif, - int strict) + int flags) { struct rt6_info *local = NULL; struct rt6_info *sprt; @@ -253,7 +253,7 @@ static inline struct rt6_info *rt6_device_match(struct net *net, if (dev->flags & IFF_LOOPBACK) { if (sprt->rt6i_idev == NULL || sprt->rt6i_idev->dev->ifindex != oif) { - if (strict && oif) + if (flags & RT6_LOOKUP_F_IFACE && oif) continue; if (local && (!oif || local->rt6i_idev->dev->ifindex == oif)) @@ -266,7 +266,7 @@ static inline struct rt6_info *rt6_device_match(struct net *net, if (local) return local; - if (strict) + if (flags & RT6_LOOKUP_F_IFACE) return net->ipv6.ip6_null_entry; } return rt; -- cgit v0.10.2