From af2681828af5f2b42e12e8b16ba0cf113cf486c8 Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Thu, 3 Apr 2008 12:52:19 -0700 Subject: [ICMP]: Ensure that ICMP relookup maintains status quo The ICMP relookup path is only meant to modify behaviour when appropriate IPsec policies are in place and marked as requiring relookups. It is certainly not meant to modify behaviour when IPsec policies don't exist at all. However, due to an oversight on the error paths existing behaviour may in fact change should one of the relookup steps fail. This patch corrects this by redirecting all errors on relookup failures to the previous code path. That is, if the initial xfrm_lookup let the packet pass, we will stand by that decision should the relookup fail due to an error. This should be safe from a security point-of-view because compliant systems must install a default deny policy so the packet would'nt have passed in that case. Many thanks to Julian Anastasov for pointing out this error. Signed-off-by: Herbert Xu Signed-off-by: David S. Miller diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c index a944e80..40508ba 100644 --- a/net/ipv4/icmp.c +++ b/net/ipv4/icmp.c @@ -591,7 +591,7 @@ void icmp_send(struct sk_buff *skb_in, int type, int code, __be32 info) } if (xfrm_decode_session_reverse(skb_in, &fl, AF_INET)) - goto ende; + goto relookup_failed; if (inet_addr_type(net, fl.fl4_src) == RTN_LOCAL) err = __ip_route_output_key(net, &rt2, &fl); @@ -601,7 +601,7 @@ void icmp_send(struct sk_buff *skb_in, int type, int code, __be32 info) fl2.fl4_dst = fl.fl4_src; if (ip_route_output_key(net, &rt2, &fl2)) - goto ende; + goto relookup_failed; /* Ugh! */ odst = skb_in->dst; @@ -614,21 +614,23 @@ void icmp_send(struct sk_buff *skb_in, int type, int code, __be32 info) } if (err) - goto ende; + goto relookup_failed; err = xfrm_lookup((struct dst_entry **)&rt2, &fl, NULL, XFRM_LOOKUP_ICMP); - if (err == -ENOENT) { + switch (err) { + case 0: + dst_release(&rt->u.dst); + rt = rt2; + break; + case -EPERM: + goto ende; + default: +relookup_failed: if (!rt) goto out_unlock; - goto route_done; + break; } - - dst_release(&rt->u.dst); - rt = rt2; - - if (err) - goto out_unlock; } route_done: diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c index f204a72..893287e 100644 --- a/net/ipv6/icmp.c +++ b/net/ipv6/icmp.c @@ -436,24 +436,26 @@ void icmpv6_send(struct sk_buff *skb, int type, int code, __u32 info, } if (xfrm_decode_session_reverse(skb, &fl2, AF_INET6)) - goto out_dst_release; + goto relookup_failed; if (ip6_dst_lookup(sk, &dst2, &fl)) - goto out_dst_release; + goto relookup_failed; err = xfrm_lookup(&dst2, &fl, sk, XFRM_LOOKUP_ICMP); - if (err == -ENOENT) { + switch (err) { + case 0: + dst_release(dst); + dst = dst2; + break; + case -EPERM: + goto out_dst_release; + default: +relookup_failed: if (!dst) goto out; - goto route_done; + break; } - dst_release(dst); - dst = dst2; - - if (err) - goto out; - route_done: if (ipv6_addr_is_multicast(&fl.fl6_dst)) hlimit = np->mcast_hops; -- cgit v0.10.2 From 439e23857a21c3a953826eed23c818697a97de1a Mon Sep 17 00:00:00 2001 From: "Denis V. Lunev" Date: Thu, 3 Apr 2008 13:30:17 -0700 Subject: [IPV6]: Event type in addrconf_ifdown is mis-used. addrconf_ifdown is broken in respect to the usage of how parameter. This function is called with (event != NETDEV_DOWN) and (2) on the IPv6 stop. It the latter case inet6_dev from loopback device should be destroyed. Signed-off-by: Denis V. Lunev Signed-off-by: David S. Miller diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index e7a1882..4fa9da0 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c @@ -2469,7 +2469,7 @@ static int addrconf_ifdown(struct net_device *dev, int how) /* Step 1: remove reference to ipv6 device from parent device. Do not dev_put! */ - if (how == 1) { + if (how) { idev->dead = 1; /* protected by rtnl_lock */ @@ -2501,12 +2501,12 @@ static int addrconf_ifdown(struct net_device *dev, int how) write_lock_bh(&idev->lock); /* Step 3: clear flags for stateless addrconf */ - if (how != 1) + if (!how) idev->if_flags &= ~(IF_RS_SENT|IF_RA_RCVD|IF_READY); /* Step 4: clear address list */ #ifdef CONFIG_IPV6_PRIVACY - if (how == 1 && del_timer(&idev->regen_timer)) + if (how && del_timer(&idev->regen_timer)) in6_dev_put(idev); /* clear tempaddr list */ @@ -2543,7 +2543,7 @@ static int addrconf_ifdown(struct net_device *dev, int how) /* Step 5: Discard multicast list */ - if (how == 1) + if (how) ipv6_mc_destroy_dev(idev); else ipv6_mc_down(idev); @@ -2552,7 +2552,7 @@ static int addrconf_ifdown(struct net_device *dev, int how) /* Shot the device (if unregistered) */ - if (how == 1) { + if (how) { addrconf_sysctl_unregister(idev); neigh_parms_release(&nd_tbl, idev->nd_parms); neigh_ifdown(&nd_tbl, dev); -- cgit v0.10.2 From eb867579311a9c1e998d6911af056772c400122a Mon Sep 17 00:00:00 2001 From: "Denis V. Lunev" Date: Thu, 3 Apr 2008 13:31:53 -0700 Subject: [IPV6]: inet6_dev on loopback should be kept until namespace stop. In the other case it will be destroyed when last address will be removed from lo inside a namespace. This will break IPv6 in several places. The most obvious one is ip6_dst_ifdown. Signed-off-by: Denis V. Lunev Signed-off-by: David S. Miller diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index 4fa9da0..a65935a 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c @@ -2456,7 +2456,7 @@ static int addrconf_ifdown(struct net_device *dev, int how) ASSERT_RTNL(); - if (dev == init_net.loopback_dev && how == 1) + if ((dev->flags & IFF_LOOPBACK) && how == 1) how = 0; rt6_ifdown(dev); -- cgit v0.10.2 From 84f59370c519449c70dcc813b050f5cbbf0098e7 Mon Sep 17 00:00:00 2001 From: "Denis V. Lunev" Date: Thu, 3 Apr 2008 13:33:00 -0700 Subject: [IPV6]: Fix refcounting for anycast dst entries. Anycast DST entries allocated inside ipv6_dev_ac_inc are leaked when network device is stopped without removing IPv6 addresses from it. The bug has been observed in the reality on 2.6.18-rhel5 kernel. In the above case addrconf_ifdown marks all entries as obsolete and ip6_del_rt called from __ipv6_dev_ac_dec returns ENOENT. The referrence is not dropped. The fix is simple. DST entry should not keep referrence when stored in the FIB6 tree. Signed-off-by: Denis V. Lunev Signed-off-by: David S. Miller diff --git a/net/ipv6/anycast.c b/net/ipv6/anycast.c index 9c7f83f..e5f56c9 100644 --- a/net/ipv6/anycast.c +++ b/net/ipv6/anycast.c @@ -334,9 +334,7 @@ int ipv6_dev_ac_inc(struct net_device *dev, struct in6_addr *addr) idev->ac_list = aca; write_unlock_bh(&idev->lock); - dst_hold(&rt->u.dst); - if (ip6_ins_rt(rt)) - dst_release(&rt->u.dst); + ip6_ins_rt(rt); addrconf_join_solict(dev, &aca->aca_addr); @@ -378,10 +376,7 @@ int __ipv6_dev_ac_dec(struct inet6_dev *idev, struct in6_addr *addr) addrconf_leave_solict(idev, &aca->aca_addr); dst_hold(&aca->aca_rt->u.dst); - if (ip6_del_rt(aca->aca_rt)) - dst_free(&aca->aca_rt->u.dst); - else - dst_release(&aca->aca_rt->u.dst); + ip6_del_rt(aca->aca_rt); aca_put(aca); return 0; -- cgit v0.10.2 From 61407f80f72970d52d4339f81c6c3cd03f4ca0f0 Mon Sep 17 00:00:00 2001 From: Andi Kleen Date: Thu, 3 Apr 2008 14:07:02 -0700 Subject: [NET]: srandom32 fixes for networking v2 - Let it update the state of all CPUs. The network stack goes into pains to feed the current IP addresses in, but it is not very effective if that is only done for some random CPU instead of all. So change it to feed bits into all CPUs. I decided to do that lockless because well somewhat random results are ok. v2: Drop rename so that this patch doesn't depend on x86 maintainers Signed-off-by: Andi Kleen Signed-off-by: David S. Miller diff --git a/lib/random32.c b/lib/random32.c index ec7f81d..ca87d86 100644 --- a/lib/random32.c +++ b/lib/random32.c @@ -97,13 +97,18 @@ EXPORT_SYMBOL(random32); * @seed: seed value * * Add some additional seeding to the random32() pool. - * Note: this pool is per cpu so it only affects current CPU. */ void srandom32(u32 entropy) { - struct rnd_state *state = &get_cpu_var(net_rand_state); - __set_random32(state, state->s1 ^ entropy); - put_cpu_var(state); + int i; + /* + * No locking on the CPUs, but then somewhat random results are, well, + * expected. + */ + for_each_possible_cpu (i) { + struct rnd_state *state = &per_cpu(net_rand_state, i); + __set_random32(state, state->s1 ^ entropy); + } } EXPORT_SYMBOL(srandom32); -- cgit v0.10.2 From b2a5c19ca0315723cecb9489ff8b67c4f17367b4 Mon Sep 17 00:00:00 2001 From: Matt Carlson Date: Thu, 3 Apr 2008 21:44:44 -0700 Subject: [TG3]: Add PHY workaround for 5784 The 5784 B step and newer chips require the PHY DSPs to be fine-tuned based on one-time programmable values stored in the chip. This is essential to achieve optimal PHY operations especially when using long cables. We also need to properly handle the 10Mbit RX bit in the CPMU_CTRL register during PHY reset. Update version to 3.89. Signed-off-by: Matt Carlson Signed-off-by: Michael Chan Signed-off-by: David S. Miller diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index f9ef8bd..d4655b2 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -64,8 +64,8 @@ #define DRV_MODULE_NAME "tg3" #define PFX DRV_MODULE_NAME ": " -#define DRV_MODULE_VERSION "3.88" -#define DRV_MODULE_RELDATE "March 20, 2008" +#define DRV_MODULE_VERSION "3.89" +#define DRV_MODULE_RELDATE "April 03, 2008" #define TG3_DEF_MAC_MODE 0 #define TG3_DEF_RX_MODE 0 @@ -804,6 +804,12 @@ static int tg3_writephy(struct tg3 *tp, int reg, u32 val) return ret; } +static void tg3_phydsp_write(struct tg3 *tp, u32 reg, u32 val) +{ + tg3_writephy(tp, MII_TG3_DSP_ADDRESS, reg); + tg3_writephy(tp, MII_TG3_DSP_RW_PORT, val); +} + static void tg3_phy_toggle_automdix(struct tg3 *tp, int enable) { u32 phy; @@ -886,6 +892,49 @@ static int tg3_bmcr_reset(struct tg3 *tp) return 0; } +static void tg3_phy_apply_otp(struct tg3 *tp) +{ + u32 otp, phy; + + if (!tp->phy_otp) + return; + + otp = tp->phy_otp; + + /* Enable SM_DSP clock and tx 6dB coding. */ + phy = MII_TG3_AUXCTL_SHDWSEL_AUXCTL | + MII_TG3_AUXCTL_ACTL_SMDSP_ENA | + MII_TG3_AUXCTL_ACTL_TX_6DB; + tg3_writephy(tp, MII_TG3_AUX_CTRL, phy); + + phy = ((otp & TG3_OTP_AGCTGT_MASK) >> TG3_OTP_AGCTGT_SHIFT); + phy |= MII_TG3_DSP_TAP1_AGCTGT_DFLT; + tg3_phydsp_write(tp, MII_TG3_DSP_TAP1, phy); + + phy = ((otp & TG3_OTP_HPFFLTR_MASK) >> TG3_OTP_HPFFLTR_SHIFT) | + ((otp & TG3_OTP_HPFOVER_MASK) >> TG3_OTP_HPFOVER_SHIFT); + tg3_phydsp_write(tp, MII_TG3_DSP_AADJ1CH0, phy); + + phy = ((otp & TG3_OTP_LPFDIS_MASK) >> TG3_OTP_LPFDIS_SHIFT); + phy |= MII_TG3_DSP_AADJ1CH3_ADCCKADJ; + tg3_phydsp_write(tp, MII_TG3_DSP_AADJ1CH3, phy); + + phy = ((otp & TG3_OTP_VDAC_MASK) >> TG3_OTP_VDAC_SHIFT); + tg3_phydsp_write(tp, MII_TG3_DSP_EXP75, phy); + + phy = ((otp & TG3_OTP_10BTAMP_MASK) >> TG3_OTP_10BTAMP_SHIFT); + tg3_phydsp_write(tp, MII_TG3_DSP_EXP96, phy); + + phy = ((otp & TG3_OTP_ROFF_MASK) >> TG3_OTP_ROFF_SHIFT) | + ((otp & TG3_OTP_RCOFF_MASK) >> TG3_OTP_RCOFF_SHIFT); + tg3_phydsp_write(tp, MII_TG3_DSP_EXP97, phy); + + /* Turn off SM_DSP clock. */ + phy = MII_TG3_AUXCTL_SHDWSEL_AUXCTL | + MII_TG3_AUXCTL_ACTL_TX_6DB; + tg3_writephy(tp, MII_TG3_AUX_CTRL, phy); +} + static int tg3_wait_macro_done(struct tg3 *tp) { int limit = 100; @@ -1073,6 +1122,7 @@ static void tg3_link_report(struct tg3 *); */ static int tg3_phy_reset(struct tg3 *tp) { + u32 cpmuctrl; u32 phy_status; int err; @@ -1102,10 +1152,28 @@ static int tg3_phy_reset(struct tg3 *tp) goto out; } + cpmuctrl = 0; + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784 && + GET_CHIP_REV(tp->pci_chip_rev_id) != CHIPREV_5784_AX) { + cpmuctrl = tr32(TG3_CPMU_CTRL); + if (cpmuctrl & CPMU_CTRL_GPHY_10MB_RXONLY) + tw32(TG3_CPMU_CTRL, + cpmuctrl & ~CPMU_CTRL_GPHY_10MB_RXONLY); + } + err = tg3_bmcr_reset(tp); if (err) return err; + if (cpmuctrl & CPMU_CTRL_GPHY_10MB_RXONLY) { + u32 phy; + + phy = MII_TG3_DSP_EXP8_AEDW | MII_TG3_DSP_EXP8_REJ2MHz; + tg3_phydsp_write(tp, MII_TG3_DSP_EXP8, phy); + + tw32(TG3_CPMU_CTRL, cpmuctrl); + } + if (tp->tg3_flags3 & TG3_FLG3_5761_5784_AX_FIXES) { u32 val; @@ -1124,6 +1192,8 @@ static int tg3_phy_reset(struct tg3 *tp) MII_TG3_MISC_SHDW_APD_WKTM_84MS); } + tg3_phy_apply_otp(tp); + out: if (tp->tg3_flags2 & TG3_FLG2_PHY_ADC_BUG) { tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x0c00); @@ -9464,7 +9534,8 @@ static int tg3_test_loopback(struct tg3 *tp) if (err) return TG3_LOOPBACK_FAILED; - if (tp->tg3_flags3 & TG3_FLG3_5761_5784_AX_FIXES) { + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784 || + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761) { int i; u32 status; @@ -9481,17 +9552,23 @@ static int tg3_test_loopback(struct tg3 *tp) if (status != CPMU_MUTEX_GNT_DRIVER) return TG3_LOOPBACK_FAILED; - /* Turn off power management based on link speed. */ + /* Turn off link-based power management. */ cpmuctrl = tr32(TG3_CPMU_CTRL); - tw32(TG3_CPMU_CTRL, - cpmuctrl & ~(CPMU_CTRL_LINK_SPEED_MODE | - CPMU_CTRL_LINK_AWARE_MODE)); + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784 || + GET_CHIP_REV(tp->pci_chip_rev_id) == CHIPREV_5761_AX) + tw32(TG3_CPMU_CTRL, + cpmuctrl & ~(CPMU_CTRL_LINK_SPEED_MODE | + CPMU_CTRL_LINK_AWARE_MODE)); + else + tw32(TG3_CPMU_CTRL, + cpmuctrl & ~CPMU_CTRL_LINK_AWARE_MODE); } if (tg3_run_loopback(tp, TG3_MAC_LOOPBACK)) err |= TG3_MAC_LOOPBACK_FAILED; - if (tp->tg3_flags3 & TG3_FLG3_5761_5784_AX_FIXES) { + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784 || + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761) { tw32(TG3_CPMU_CTRL, cpmuctrl); /* Release the mutex */ @@ -10724,9 +10801,8 @@ static void __devinit tg3_get_eeprom_hw_cfg(struct tg3 *tp) tp->pdev->subsystem_vendor == PCI_VENDOR_ID_DELL) tp->led_ctrl = LED_CTRL_MODE_PHY_2; - if (tp->pci_chip_rev_id == CHIPREV_ID_5784_A0 || - tp->pci_chip_rev_id == CHIPREV_ID_5784_A1) - tp->led_ctrl = LED_CTRL_MODE_MAC; + if (GET_CHIP_REV(tp->pci_chip_rev_id) == CHIPREV_5784_AX) + tp->led_ctrl = LED_CTRL_MODE_PHY_1; if (nic_cfg & NIC_SRAM_DATA_CFG_EEPROM_WP) { tp->tg3_flags |= TG3_FLAG_EEPROM_WRITE_PROT; @@ -10773,6 +10849,55 @@ static void __devinit tg3_get_eeprom_hw_cfg(struct tg3 *tp) } } +static int __devinit tg3_issue_otp_command(struct tg3 *tp, u32 cmd) +{ + int i; + u32 val; + + tw32(OTP_CTRL, cmd | OTP_CTRL_OTP_CMD_START); + tw32(OTP_CTRL, cmd); + + /* Wait for up to 1 ms for command to execute. */ + for (i = 0; i < 100; i++) { + val = tr32(OTP_STATUS); + if (val & OTP_STATUS_CMD_DONE) + break; + udelay(10); + } + + return (val & OTP_STATUS_CMD_DONE) ? 0 : -EBUSY; +} + +/* Read the gphy configuration from the OTP region of the chip. The gphy + * configuration is a 32-bit value that straddles the alignment boundary. + * We do two 32-bit reads and then shift and merge the results. + */ +static u32 __devinit tg3_read_otp_phycfg(struct tg3 *tp) +{ + u32 bhalf_otp, thalf_otp; + + tw32(OTP_MODE, OTP_MODE_OTP_THRU_GRC); + + if (tg3_issue_otp_command(tp, OTP_CTRL_OTP_CMD_INIT)) + return 0; + + tw32(OTP_ADDRESS, OTP_ADDRESS_MAGIC1); + + if (tg3_issue_otp_command(tp, OTP_CTRL_OTP_CMD_READ)) + return 0; + + thalf_otp = tr32(OTP_READ_DATA); + + tw32(OTP_ADDRESS, OTP_ADDRESS_MAGIC2); + + if (tg3_issue_otp_command(tp, OTP_CTRL_OTP_CMD_READ)) + return 0; + + bhalf_otp = tr32(OTP_READ_DATA); + + return ((thalf_otp & 0x0000ffff) << 16) | (bhalf_otp >> 16); +} + static int __devinit tg3_phy_probe(struct tg3 *tp) { u32 hw_phy_id_1, hw_phy_id_2; @@ -11586,6 +11711,13 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) tp->tg3_flags2 |= TG3_FLG2_PHY_BER_BUG; } + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784 && + GET_CHIP_REV(tp->pci_chip_rev_id) != CHIPREV_5784_AX) { + tp->phy_otp = tg3_read_otp_phycfg(tp); + if (tp->phy_otp == 0) + tp->phy_otp = TG3_OTP_DEFAULT; + } + tp->coalesce_mode = 0; if (GET_CHIP_REV(tp->pci_chip_rev_id) != CHIPREV_5700_AX && GET_CHIP_REV(tp->pci_chip_rev_id) != CHIPREV_5700_BX) diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h index 3938eb3..c1075a7 100644 --- a/drivers/net/tg3.h +++ b/drivers/net/tg3.h @@ -138,6 +138,8 @@ #define CHIPREV_5704_BX 0x21 #define CHIPREV_5750_AX 0x40 #define CHIPREV_5750_BX 0x41 +#define CHIPREV_5784_AX 0x57840 +#define CHIPREV_5761_AX 0x57610 #define GET_METAL_REV(CHIP_REV_ID) ((CHIP_REV_ID) & 0xff) #define METAL_REV_A0 0x00 #define METAL_REV_A1 0x01 @@ -866,6 +868,7 @@ #define CPMU_CTRL_LINK_IDLE_MODE 0x00000200 #define CPMU_CTRL_LINK_AWARE_MODE 0x00000400 #define CPMU_CTRL_LINK_SPEED_MODE 0x00004000 +#define CPMU_CTRL_GPHY_10MB_RXONLY 0x00010000 #define TG3_CPMU_LSPD_10MB_CLK 0x00003604 #define CPMU_LSPD_10MB_MACCLK_MASK 0x001f0000 #define CPMU_LSPD_10MB_MACCLK_6_25 0x00130000 @@ -1559,7 +1562,24 @@ /* 0x702c unused */ #define NVRAM_ADDR_LOCKOUT 0x00007030 -/* 0x7034 --> 0x7c00 unused */ +/* 0x7034 --> 0x7500 unused */ + +#define OTP_MODE 0x00007500 +#define OTP_MODE_OTP_THRU_GRC 0x00000001 +#define OTP_CTRL 0x00007504 +#define OTP_CTRL_OTP_PROG_ENABLE 0x00200000 +#define OTP_CTRL_OTP_CMD_READ 0x00000000 +#define OTP_CTRL_OTP_CMD_INIT 0x00000008 +#define OTP_CTRL_OTP_CMD_START 0x00000001 +#define OTP_STATUS 0x00007508 +#define OTP_STATUS_CMD_DONE 0x00000001 +#define OTP_ADDRESS 0x0000750c +#define OTP_ADDRESS_MAGIC1 0x000000a0 +#define OTP_ADDRESS_MAGIC2 0x00000080 +/* 0x7510 unused */ + +#define OTP_READ_DATA 0x00007514 +/* 0x7518 --> 0x7c04 unused */ #define PCIE_TRANSACTION_CFG 0x00007c04 #define PCIE_TRANS_CFG_1SHOT_MSI 0x20000000 @@ -1568,6 +1588,28 @@ #define PCIE_PWR_MGMT_THRESH 0x00007d28 #define PCIE_PWR_MGMT_L1_THRESH_MSK 0x0000ff00 + +/* OTP bit definitions */ +#define TG3_OTP_AGCTGT_MASK 0x000000e0 +#define TG3_OTP_AGCTGT_SHIFT 1 +#define TG3_OTP_HPFFLTR_MASK 0x00000300 +#define TG3_OTP_HPFFLTR_SHIFT 1 +#define TG3_OTP_HPFOVER_MASK 0x00000400 +#define TG3_OTP_HPFOVER_SHIFT 1 +#define TG3_OTP_LPFDIS_MASK 0x00000800 +#define TG3_OTP_LPFDIS_SHIFT 11 +#define TG3_OTP_VDAC_MASK 0xff000000 +#define TG3_OTP_VDAC_SHIFT 24 +#define TG3_OTP_10BTAMP_MASK 0x0000f000 +#define TG3_OTP_10BTAMP_SHIFT 8 +#define TG3_OTP_ROFF_MASK 0x00e00000 +#define TG3_OTP_ROFF_SHIFT 11 +#define TG3_OTP_RCOFF_MASK 0x001c0000 +#define TG3_OTP_RCOFF_SHIFT 16 + +#define TG3_OTP_DEFAULT 0x286c1640 + + #define TG3_EEPROM_MAGIC 0x669955aa #define TG3_EEPROM_MAGIC_FW 0xa5000000 #define TG3_EEPROM_MAGIC_FW_MSK 0xff000000 @@ -1705,15 +1747,31 @@ #define MII_TG3_DSP_RW_PORT 0x15 /* DSP coefficient read/write port */ -#define MII_TG3_DSP_ADDRESS 0x17 /* DSP address register */ #define MII_TG3_EPHY_PTEST 0x17 /* 5906 PHY register */ +#define MII_TG3_DSP_ADDRESS 0x17 /* DSP address register */ + +#define MII_TG3_DSP_TAP1 0x0001 +#define MII_TG3_DSP_TAP1_AGCTGT_DFLT 0x0007 +#define MII_TG3_DSP_AADJ1CH0 0x001f +#define MII_TG3_DSP_AADJ1CH3 0x601f +#define MII_TG3_DSP_AADJ1CH3_ADCCKADJ 0x0002 +#define MII_TG3_DSP_EXP8 0x0708 +#define MII_TG3_DSP_EXP8_REJ2MHz 0x0001 +#define MII_TG3_DSP_EXP8_AEDW 0x0200 +#define MII_TG3_DSP_EXP75 0x0f75 +#define MII_TG3_DSP_EXP96 0x0f96 +#define MII_TG3_DSP_EXP97 0x0f97 #define MII_TG3_AUX_CTRL 0x18 /* auxilliary control register */ #define MII_TG3_AUXCTL_MISC_WREN 0x8000 #define MII_TG3_AUXCTL_MISC_FORCE_AMDIX 0x0200 #define MII_TG3_AUXCTL_MISC_RDSEL_MISC 0x7000 -#define MII_TG3_AUXCTL_SHDWSEL_MISC 0x0007 +#define MII_TG3_AUXCTL_SHDWSEL_MISC 0x0007 + +#define MII_TG3_AUXCTL_ACTL_SMDSP_ENA 0x0800 +#define MII_TG3_AUXCTL_ACTL_TX_6DB 0x0400 +#define MII_TG3_AUXCTL_SHDWSEL_AUXCTL 0x0000 #define MII_TG3_AUX_STAT 0x19 /* auxilliary status register */ #define MII_TG3_AUX_STAT_LPASS 0x0004 @@ -1743,6 +1801,20 @@ #define MII_TG3_INT_DUPLEXCHG 0x0008 #define MII_TG3_INT_ANEG_PAGE_RX 0x0400 +#define MII_TG3_MISC_SHDW 0x1c +#define MII_TG3_MISC_SHDW_WREN 0x8000 +#define MII_TG3_MISC_SHDW_SCR5_SEL 0x1400 +#define MII_TG3_MISC_SHDW_APD_SEL 0x2800 + +#define MII_TG3_MISC_SHDW_SCR5_C125OE 0x0001 +#define MII_TG3_MISC_SHDW_SCR5_DLLAPD 0x0002 +#define MII_TG3_MISC_SHDW_SCR5_SDTL 0x0004 +#define MII_TG3_MISC_SHDW_SCR5_DLPTLM 0x0008 +#define MII_TG3_MISC_SHDW_SCR5_LPED 0x0010 + +#define MII_TG3_MISC_SHDW_APD_WKTM_84MS 0x0001 +#define MII_TG3_MISC_SHDW_APD_ENABLE 0x0020 + #define MII_TG3_EPHY_TEST 0x1f /* 5906 PHY register */ #define MII_TG3_EPHY_SHADOW_EN 0x80 @@ -2473,6 +2545,7 @@ struct tg3 { #define PHY_REV_BCM5411_X0 0x1 /* Found on Netgear GA302T */ u32 led_ctrl; + u32 phy_otp; u16 pci_cmd; char board_part_number[24]; -- cgit v0.10.2 From 23556323b22fef35bdc36465b7e7439ba3748c9f Mon Sep 17 00:00:00 2001 From: Pavel Emelyanov Date: Fri, 4 Apr 2008 12:45:12 -0700 Subject: [VLAN]: Fix egress priority mappings leak. These entries are allocated in vlan_dev_set_egress_priority, but are never released and leaks on vlan device removal. Drop these in vlan's ->uninit callback - after the device is brought down and everyone is notified about it is going to be unregistered. Found during testing vlan netnsization patchset. Signed-off-by: Pavel Emelyanov Acked-by: Patrick McHardy Signed-off-by: David S. Miller diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c index 480ea90..41a76a0 100644 --- a/net/8021q/vlan_dev.c +++ b/net/8021q/vlan_dev.c @@ -692,6 +692,20 @@ static int vlan_dev_init(struct net_device *dev) return 0; } +static void vlan_dev_uninit(struct net_device *dev) +{ + struct vlan_priority_tci_mapping *pm; + struct vlan_dev_info *vlan = vlan_dev_info(dev); + int i; + + for (i = 0; i < ARRAY_SIZE(vlan->egress_priority_map); i++) { + while ((pm = vlan->egress_priority_map[i]) != NULL) { + vlan->egress_priority_map[i] = pm->next; + kfree(pm); + } + } +} + void vlan_setup(struct net_device *dev) { ether_setup(dev); @@ -701,6 +715,7 @@ void vlan_setup(struct net_device *dev) dev->change_mtu = vlan_dev_change_mtu; dev->init = vlan_dev_init; + dev->uninit = vlan_dev_uninit; dev->open = vlan_dev_open; dev->stop = vlan_dev_stop; dev->set_mac_address = vlan_dev_set_mac_address; -- cgit v0.10.2 From 5da4e37e59663bd1e9eae1d717e2ceb178a485b8 Mon Sep 17 00:00:00 2001 From: Harvey Harrison Date: Wed, 2 Apr 2008 17:33:35 -0700 Subject: net: marvell.c fix sparse shadowed variable warning The other if blocks don't redeclare temp, remove the redeclaration in the final if() block. drivers/net/phy/marvell.c:214:7: warning: symbol 'temp' shadows an earlier one drivers/net/phy/marvell.c:160:6: originally declared here Signed-off-by: Harvey Harrison Signed-off-by: Jeff Garzik diff --git a/drivers/net/phy/marvell.c b/drivers/net/phy/marvell.c index 3353991..32a8503 100644 --- a/drivers/net/phy/marvell.c +++ b/drivers/net/phy/marvell.c @@ -211,8 +211,6 @@ static int m88e1111_config_init(struct phy_device *phydev) } if (phydev->interface == PHY_INTERFACE_MODE_SGMII) { - int temp; - temp = phy_read(phydev, MII_M1111_PHY_EXT_SR); if (temp < 0) return temp; -- cgit v0.10.2 From e28e3a614cedb11637f6cc7a30f0812963df62fe Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Mon, 31 Mar 2008 01:40:04 +0300 Subject: net/tokenring/olympic.c section fixes My previous section fix only turned one section problem into another section problem. This patch fixes it for real. Signed-off-by: Adrian Bunk Signed-off-by: Jeff Garzik diff --git a/drivers/net/tokenring/olympic.c b/drivers/net/tokenring/olympic.c index 433c994..db4ca4f 100644 --- a/drivers/net/tokenring/olympic.c +++ b/drivers/net/tokenring/olympic.c @@ -117,7 +117,7 @@ * Official releases will only have an a.b.c version number format. */ -static char version[] __devinitdata = +static char version[] = "Olympic.c v1.0.5 6/04/02 - Peter De Schrijver & Mike Phillips" ; static char *open_maj_error[] = {"No error", "Lobe Media Test", "Physical Insertion", @@ -290,7 +290,7 @@ op_disable_dev: return i; } -static int __devinit olympic_init(struct net_device *dev) +static int olympic_init(struct net_device *dev) { struct olympic_private *olympic_priv; u8 __iomem *olympic_mmio, *init_srb,*adapter_addr; @@ -434,7 +434,7 @@ static int __devinit olympic_init(struct net_device *dev) } -static int __devinit olympic_open(struct net_device *dev) +static int olympic_open(struct net_device *dev) { struct olympic_private *olympic_priv=netdev_priv(dev); u8 __iomem *olympic_mmio=olympic_priv->olympic_mmio,*init_srb; -- cgit v0.10.2 From 30ecce908b944079181938e61ddbc00c8b23798c Mon Sep 17 00:00:00 2001 From: Al Viro Date: Wed, 26 Mar 2008 05:57:12 +0000 Subject: fix endian lossage in forcedeth a) if you initialize something with le32_to_cpu(...), then |= it with host-endian and feed to cpu_to_le32(), it's most definitely *not* __le32. As sparse would've told you... b) the whole sequence is |= cpu_to_le32(host-endian constant) Signed-off-by: Al Viro Signed-off-by: Jeff Garzik diff --git a/drivers/net/forcedeth.c b/drivers/net/forcedeth.c index 980c2c2..419f533 100644 --- a/drivers/net/forcedeth.c +++ b/drivers/net/forcedeth.c @@ -2112,9 +2112,8 @@ static inline void nv_tx_flip_ownership(struct net_device *dev) np->tx_pkts_in_progress--; if (np->tx_change_owner) { - __le32 flaglen = le32_to_cpu(np->tx_change_owner->first_tx_desc->flaglen); - flaglen |= NV_TX2_VALID; - np->tx_change_owner->first_tx_desc->flaglen = cpu_to_le32(flaglen); + np->tx_change_owner->first_tx_desc->flaglen |= + cpu_to_le32(NV_TX2_VALID); np->tx_pkts_in_progress++; np->tx_change_owner = np->tx_change_owner->next_tx_ctx; -- cgit v0.10.2 From 877cb0d4af2658beb5f89d38ae51968782f62fad Mon Sep 17 00:00:00 2001 From: Holger Schurig Date: Wed, 2 Apr 2008 16:34:51 +0200 Subject: libertas: fix mode initialization problem After moving lbs_find_best_network_ssid() from scan.c to assoc.c gcc was able to deduce that new_mode might stay uninitialized. Signed-off-by: Holger Schurig Acked-by: Dan Williams Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/libertas/assoc.c b/drivers/net/wireless/libertas/assoc.c index 87e145f..6a24ed60 100644 --- a/drivers/net/wireless/libertas/assoc.c +++ b/drivers/net/wireless/libertas/assoc.c @@ -541,7 +541,7 @@ void lbs_association_worker(struct work_struct *work) } if (find_any_ssid) { - u8 new_mode; + u8 new_mode = assoc_req->mode; ret = lbs_find_best_network_ssid(priv, assoc_req->ssid, &assoc_req->ssid_len, assoc_req->mode, &new_mode); -- cgit v0.10.2 From 3f2eeac97952b262f2b904c6150a9879777995eb Mon Sep 17 00:00:00 2001 From: Daniel Drake Date: Wed, 2 Apr 2008 20:33:54 +0100 Subject: ipw2200: set MAC address on radiotap interface Commit bada339ba24dee9e143bfb42e1dc61f146619846 enforces that all interfaces have a valid MAC address before they are brought up. ipw2200 does not assign a MAC address to it's radiotap interface, meaning that the radiotap interface cannot be brought up in 2.6.24. https://bugs.gentoo.org/show_bug.cgi?id=215714 Fix this by copying the MAC address from the real interface. Signed-off-by: Daniel Drake Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/ipw2200.c b/drivers/net/wireless/ipw2200.c index a56d9fc..b34c275 100644 --- a/drivers/net/wireless/ipw2200.c +++ b/drivers/net/wireless/ipw2200.c @@ -11576,6 +11576,7 @@ static int ipw_prom_alloc(struct ipw_priv *priv) priv->prom_priv->priv = priv; strcpy(priv->prom_net_dev->name, "rtap%d"); + memcpy(priv->prom_net_dev->dev_addr, priv->mac_addr, ETH_ALEN); priv->prom_net_dev->type = ARPHRD_IEEE80211_RADIOTAP; priv->prom_net_dev->open = ipw_prom_open; -- cgit v0.10.2 From 7981a35ed0f64ca49b1a0c0acecbc9b644a8a2e3 Mon Sep 17 00:00:00 2001 From: Abhijeet Kolekar Date: Fri, 4 Apr 2008 14:32:01 -0700 Subject: iwlwifi: fix n-band association problem This patch enables the IWL4965_HT flag (n-band) in Kconfig. Removed the "depends on n" from Kconfig for config IWL4965_HT Signed-off-by: Abhijeet Kolekar Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/iwlwifi/Kconfig b/drivers/net/wireless/iwlwifi/Kconfig index b79a35a..b54ff71 100644 --- a/drivers/net/wireless/iwlwifi/Kconfig +++ b/drivers/net/wireless/iwlwifi/Kconfig @@ -35,7 +35,6 @@ config IWL4965_HT bool "Enable 802.11n HT features in iwl4965 driver" depends on EXPERIMENTAL depends on IWL4965 && IWL4965_QOS - depends on n ---help--- This option enables IEEE 802.11n High Throughput features for the iwl4965 driver. -- cgit v0.10.2 From 881400a20c3551e90eed1062cf0387fa686a2fd0 Mon Sep 17 00:00:00 2001 From: Stefano Brivio Date: Sun, 6 Apr 2008 17:05:07 +0200 Subject: b43legacy: fix bcm4303 crash This fixes an hard crash which happened upon driver loading on bcm4303 rev. 2 devices. Signed-off-by: Stefano Brivio Signed-off-by: John W. Linville diff --git a/drivers/ssb/main.c b/drivers/ssb/main.c index bedb2b4..72017bf 100644 --- a/drivers/ssb/main.c +++ b/drivers/ssb/main.c @@ -1044,6 +1044,12 @@ int ssb_bus_may_powerdown(struct ssb_bus *bus) goto out; cc = &bus->chipco; + + if (!cc->dev) + goto out; + if (cc->dev->id.revision < 5) + goto out; + ssb_chipco_set_clockmode(cc, SSB_CLKMODE_SLOW); err = ssb_pci_xtal(bus, SSB_GPIO_XTAL | SSB_GPIO_PLL, 0); if (err) -- cgit v0.10.2 From 16f2e85d3151efa643879fa5aa87c9d77d60f57e Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 7 Apr 2008 14:35:46 +0200 Subject: nl80211: fix STA AID bug This fixes the STA AID setting and actually makes hostapd/mac80211 work properly in presence of power-saving stations. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index e3a214f..f68a5c8 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -945,7 +945,7 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info) nla_len(info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES]); params.listen_interval = nla_get_u16(info->attrs[NL80211_ATTR_STA_LISTEN_INTERVAL]); - params.listen_interval = nla_get_u16(info->attrs[NL80211_ATTR_STA_AID]); + params.aid = nla_get_u16(info->attrs[NL80211_ATTR_STA_AID]); if (parse_station_flags(info->attrs[NL80211_ATTR_STA_FLAGS], ¶ms.station_flags)) -- cgit v0.10.2 From 1b69d745397eac12b3f8a2eb6b799cd476aef282 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ilpo=20J=C3=A4rvinen?= Date: Mon, 7 Apr 2008 22:31:38 -0700 Subject: [TCP]: Restore 2.6.24 mark_head_lost behavior for newreno/fack MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The fast retransmission can be forced locally to the rfc3517 branch in tcp_update_scoreboard instead of making such fragile constructs deeper in tcp_mark_head_lost. This is necessary for the next patch which must not have loopholes for cnt > packets check. As one can notice, readability got some improvements too because of this :-). Signed-off-by: Ilpo Järvinen Signed-off-by: David S. Miller diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index 7facdb0..5573202 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -2134,7 +2134,7 @@ static void tcp_verify_retransmit_hint(struct tcp_sock *tp, struct sk_buff *skb) /* Mark head of queue up as lost. With RFC3517 SACK, the packets is * is against sacked "cnt", otherwise it's against facked "cnt" */ -static void tcp_mark_head_lost(struct sock *sk, int packets, int fast_rexmit) +static void tcp_mark_head_lost(struct sock *sk, int packets) { struct tcp_sock *tp = tcp_sk(sk); struct sk_buff *skb; @@ -2161,7 +2161,7 @@ static void tcp_mark_head_lost(struct sock *sk, int packets, int fast_rexmit) (TCP_SKB_CB(skb)->sacked & TCPCB_SACKED_ACKED)) cnt += tcp_skb_pcount(skb); - if (((!fast_rexmit || (tp->lost_out > 0)) && (cnt > packets)) || + if ((cnt > packets) || after(TCP_SKB_CB(skb)->end_seq, tp->high_seq)) break; if (!(TCP_SKB_CB(skb)->sacked & (TCPCB_SACKED_ACKED|TCPCB_LOST))) { @@ -2180,17 +2180,17 @@ static void tcp_update_scoreboard(struct sock *sk, int fast_rexmit) struct tcp_sock *tp = tcp_sk(sk); if (tcp_is_reno(tp)) { - tcp_mark_head_lost(sk, 1, fast_rexmit); + tcp_mark_head_lost(sk, 1); } else if (tcp_is_fack(tp)) { int lost = tp->fackets_out - tp->reordering; if (lost <= 0) lost = 1; - tcp_mark_head_lost(sk, lost, fast_rexmit); + tcp_mark_head_lost(sk, lost); } else { int sacked_upto = tp->sacked_out - tp->reordering; - if (sacked_upto < 0) - sacked_upto = 0; - tcp_mark_head_lost(sk, sacked_upto, fast_rexmit); + if (sacked_upto < fast_rexmit) + sacked_upto = fast_rexmit; + tcp_mark_head_lost(sk, sacked_upto); } /* New heuristics: it is possible only after we switched @@ -2524,7 +2524,7 @@ static void tcp_fastretrans_alert(struct sock *sk, int pkts_acked, int flag) before(tp->snd_una, tp->high_seq) && icsk->icsk_ca_state != TCP_CA_Open && tp->fackets_out > tp->reordering) { - tcp_mark_head_lost(sk, tp->fackets_out - tp->reordering, 0); + tcp_mark_head_lost(sk, tp->fackets_out - tp->reordering); NET_INC_STATS_BH(LINUX_MIB_TCPLOSS); } -- cgit v0.10.2 From c137f3dda04b0aee1bc6889cdc69185f53df8a82 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ilpo=20J=C3=A4rvinen?= Date: Mon, 7 Apr 2008 22:32:38 -0700 Subject: [TCP]: Fix NewReno's fast rexmit/recovery problems with GSOed skb MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes a long-standing bug which makes NewReno recovery crippled. With GSO the whole head skb was marked as LOST which is in violation of NewReno procedure that only wants to mark one packet and ended up breaking our TCP code by causing counter overflow because our code was built on top of assumption about valid NewReno procedure. This manifested as triggering a WARN_ON for the overflow in a number of places. It seems relatively safe alternative to just do nothing if tcp_fragment fails due to oom because another duplicate ACK is likely to be received soon and the fragmentation will be retried. Special thanks goes to Soeren Sonnenburg who was lucky enough to be able to reproduce this so that the warning for the overflow was hit. It's not as easy task as it seems even if this bug happens quite often because the amount of outstanding data is pretty significant for the mismarkings to lead to an overflow. Because it's very late in 2.6.25-rc cycle (if this even makes in time), I didn't want to touch anything with SACK enabled here. Fragmenting might be useful for it as well but it's more or less a policy decision rather than mandatory fix. Thus there's no need to rush and we can postpone considering tcp_fragment with SACK for 2.6.26. In 2.6.24 and earlier, this very same bug existed but the effect is slightly different because of a small changes in the if conditions that fit to the patch's context. With them nothing got lost marker and thus no retransmissions happened. Signed-off-by: Ilpo Järvinen Signed-off-by: David S. Miller diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index 5573202..7d09587 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -2138,7 +2138,9 @@ static void tcp_mark_head_lost(struct sock *sk, int packets) { struct tcp_sock *tp = tcp_sk(sk); struct sk_buff *skb; - int cnt; + int cnt, oldcnt; + int err; + unsigned int mss; BUG_TRAP(packets <= tp->packets_out); if (tp->lost_skb_hint) { @@ -2157,13 +2159,25 @@ static void tcp_mark_head_lost(struct sock *sk, int packets) tp->lost_skb_hint = skb; tp->lost_cnt_hint = cnt; + if (after(TCP_SKB_CB(skb)->end_seq, tp->high_seq)) + break; + + oldcnt = cnt; if (tcp_is_fack(tp) || tcp_is_reno(tp) || (TCP_SKB_CB(skb)->sacked & TCPCB_SACKED_ACKED)) cnt += tcp_skb_pcount(skb); - if ((cnt > packets) || - after(TCP_SKB_CB(skb)->end_seq, tp->high_seq)) - break; + if (cnt > packets) { + if (tcp_is_sack(tp) || (oldcnt >= packets)) + break; + + mss = skb_shinfo(skb)->gso_size; + err = tcp_fragment(sk, skb, (packets - oldcnt) * mss, mss); + if (err < 0) + break; + cnt = packets; + } + if (!(TCP_SKB_CB(skb)->sacked & (TCPCB_SACKED_ACKED|TCPCB_LOST))) { TCP_SKB_CB(skb)->sacked |= TCPCB_LOST; tp->lost_out += tcp_skb_pcount(skb); -- cgit v0.10.2 From 882bebaaca4bb1484078d44ef011f918c0e1e14e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ilpo=20J=C3=A4rvinen?= Date: Mon, 7 Apr 2008 22:33:07 -0700 Subject: [TCP]: tcp_simple_retransmit can cause S+L MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This fixes Bugzilla #10384 tcp_simple_retransmit does L increment without any checking whatsoever for overflowing S+L when Reno is in use. The simplest scenario I can currently think of is rather complex in practice (there might be some more straightforward cases though). Ie., if mss is reduced during mtu probing, it may end up marking everything lost and if some duplicate ACKs arrived prior to that sacked_out will be non-zero as well, leading to S+L > packets_out, tcp_clean_rtx_queue on the next cumulative ACK or tcp_fastretrans_alert on the next duplicate ACK will fix the S counter. More straightforward (but questionable) solution would be to just call tcp_reset_reno_sack() in tcp_simple_retransmit but it would negatively impact the probe's retransmission, ie., the retransmissions would not occur if some duplicate ACKs had arrived. So I had to add reno sacked_out reseting to CA_Loss state when the first cumulative ACK arrives (this stale sacked_out might actually be the explanation for the reports of left_out overflows in kernel prior to 2.6.23 and S+L overflow reports of 2.6.24). However, this alone won't be enough to fix kernel before 2.6.24 because it is building on top of the commit 1b6d427bb7e ([TCP]: Reduce sacked_out with reno when purging write_queue) to keep the sacked_out from overflowing. Signed-off-by: Ilpo Järvinen Reported-by: Alessandro Suardi Signed-off-by: David S. Miller diff --git a/include/net/tcp.h b/include/net/tcp.h index 7de4ea3..4fd3eb2 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h @@ -752,6 +752,8 @@ static inline unsigned int tcp_packets_in_flight(const struct tcp_sock *tp) return tp->packets_out - tcp_left_out(tp) + tp->retrans_out; } +extern int tcp_limit_reno_sacked(struct tcp_sock *tp); + /* If cwnd > ssthresh, we may raise ssthresh to be half-way to cwnd. * The exception is rate halving phase, when cwnd is decreasing towards * ssthresh. diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index 7d09587..b4812c3 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -1625,13 +1625,11 @@ out: return flag; } -/* If we receive more dupacks than we expected counting segments - * in assumption of absent reordering, interpret this as reordering. - * The only another reason could be bug in receiver TCP. +/* Limits sacked_out so that sum with lost_out isn't ever larger than + * packets_out. Returns zero if sacked_out adjustement wasn't necessary. */ -static void tcp_check_reno_reordering(struct sock *sk, const int addend) +int tcp_limit_reno_sacked(struct tcp_sock *tp) { - struct tcp_sock *tp = tcp_sk(sk); u32 holes; holes = max(tp->lost_out, 1U); @@ -1639,8 +1637,20 @@ static void tcp_check_reno_reordering(struct sock *sk, const int addend) if ((tp->sacked_out + holes) > tp->packets_out) { tp->sacked_out = tp->packets_out - holes; - tcp_update_reordering(sk, tp->packets_out + addend, 0); + return 1; } + return 0; +} + +/* If we receive more dupacks than we expected counting segments + * in assumption of absent reordering, interpret this as reordering. + * The only another reason could be bug in receiver TCP. + */ +static void tcp_check_reno_reordering(struct sock *sk, const int addend) +{ + struct tcp_sock *tp = tcp_sk(sk); + if (tcp_limit_reno_sacked(tp)) + tcp_update_reordering(sk, tp->packets_out + addend, 0); } /* Emulate SACKs for SACKless connection: account for a new dupack. */ @@ -2600,6 +2610,8 @@ static void tcp_fastretrans_alert(struct sock *sk, int pkts_acked, int flag) case TCP_CA_Loss: if (flag & FLAG_DATA_ACKED) icsk->icsk_retransmits = 0; + if (tcp_is_reno(tp) && flag & FLAG_SND_UNA_ADVANCED) + tcp_reset_reno_sack(tp); if (!tcp_try_undo_loss(sk)) { tcp_moderate_cwnd(tp); tcp_xmit_retransmit_queue(sk); diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index 72b9350..d29ef79 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c @@ -1808,6 +1808,9 @@ void tcp_simple_retransmit(struct sock *sk) if (!lost) return; + if (tcp_is_reno(tp)) + tcp_limit_reno_sacked(tp); + tcp_verify_left_out(tp); /* Don't muck with the congestion window here. -- cgit v0.10.2 From 6adb4f733e9996b4fd68a6db50dd51bd2463ccac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ilpo=20J=C3=A4rvinen?= Date: Mon, 7 Apr 2008 22:33:57 -0700 Subject: [TCP]: Don't allow FRTO to take place while MTU is being probed MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit MTU probe can cause some remedies for FRTO because the normal packet ordering may be violated allowing FRTO to make a wrong decision (it might not be that serious threat for anything though). Thus it's safer to not run FRTO while MTU probe is underway. It seems that the basic FRTO variant should also look for an skb at probe_seq.start to check if that's retransmitted one but I didn't implement it now (plain seqno in window check isn't robust against wraparounds). Signed-off-by: Ilpo Järvinen Signed-off-by: David S. Miller diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index b4812c3..5119856 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -1691,11 +1691,16 @@ static inline void tcp_reset_reno_sack(struct tcp_sock *tp) int tcp_use_frto(struct sock *sk) { const struct tcp_sock *tp = tcp_sk(sk); + const struct inet_connection_sock *icsk = inet_csk(sk); struct sk_buff *skb; if (!sysctl_tcp_frto) return 0; + /* MTU probe and F-RTO won't really play nicely along currently */ + if (icsk->icsk_mtup.probe_size) + return 0; + if (IsSackFrto()) return 1; -- cgit v0.10.2 From 21f644f3eabde637f255f75ad05d0821a7a36b7f Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Tue, 8 Apr 2008 16:50:44 -0700 Subject: [NET]: Undo code bloat in hot paths due to print_mac(). If print_mac() is used inside of a pr_debug() the compiler can't see that the call is redundant so still performs it even of pr_debug() ends up being a nop. So don't use print_mac() in such cases in hot code paths, use MAC_FMT et al. instead. As noted by Joe Perches, pr_debug() could be modified to handle this better, but that is a change to an interface used by the entire kernel and thus needs to be validated carefully. This here is thus the less risky fix for 2.6.25 Signed-off-by: David S. Miller diff --git a/drivers/net/starfire.c b/drivers/net/starfire.c index c49214f..7b7b171 100644 --- a/drivers/net/starfire.c +++ b/drivers/net/starfire.c @@ -1472,13 +1472,12 @@ static int __netdev_rx(struct net_device *dev, int *quota) #ifndef final_version /* Remove after testing. */ /* You will want this info for the initial debug. */ if (debug > 5) { - DECLARE_MAC_BUF(mac); - DECLARE_MAC_BUF(mac2); - - printk(KERN_DEBUG " Rx data %s %s" + printk(KERN_DEBUG " Rx data " MAC_FMT " " MAC_FMT " %2.2x%2.2x.\n", - print_mac(mac, &skb->data[0]), - print_mac(mac2, &skb->data[6]), + skb->data[0], skb->data[1], skb->data[2], + skb->data[3], skb->data[4], skb->data[5], + skb->data[6], skb->data[7], skb->data[8], + skb->data[9], skb->data[10], skb->data[11], skb->data[12], skb->data[13]); } #endif diff --git a/drivers/net/tokenring/olympic.c b/drivers/net/tokenring/olympic.c index db4ca4f..0ab51a0 100644 --- a/drivers/net/tokenring/olympic.c +++ b/drivers/net/tokenring/olympic.c @@ -1438,13 +1438,18 @@ static void olympic_arb_cmd(struct net_device *dev) if (olympic_priv->olympic_network_monitor) { struct trh_hdr *mac_hdr; - DECLARE_MAC_BUF(mac); printk(KERN_WARNING "%s: Received MAC Frame, details: \n",dev->name); mac_hdr = tr_hdr(mac_frame); - printk(KERN_WARNING "%s: MAC Frame Dest. Addr: %s\n", - dev->name, print_mac(mac, mac_hdr->daddr)); - printk(KERN_WARNING "%s: MAC Frame Srce. Addr: %s\n", - dev->name, print_mac(mac, mac_hdr->saddr)); + printk(KERN_WARNING "%s: MAC Frame Dest. Addr: " + MAC_FMT " \n", dev->name, + mac_hdr->daddr[0], mac_hdr->daddr[1], + mac_hdr->daddr[2], mac_hdr->daddr[3], + mac_hdr->daddr[4], mac_hdr->daddr[5]); + printk(KERN_WARNING "%s: MAC Frame Srce. Addr: " + MAC_FMT " \n", dev->name, + mac_hdr->saddr[0], mac_hdr->saddr[1], + mac_hdr->saddr[2], mac_hdr->saddr[3], + mac_hdr->saddr[4], mac_hdr->saddr[5]); } netif_rx(mac_frame); dev->last_rx = jiffies; diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index b58472c..d02d9d7 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c @@ -234,11 +234,12 @@ static int start_xmit(struct sk_buff *skb, struct net_device *dev) struct scatterlist sg[1+MAX_SKB_FRAGS]; struct virtio_net_hdr *hdr; const unsigned char *dest = ((struct ethhdr *)skb->data)->h_dest; - DECLARE_MAC_BUF(mac); sg_init_table(sg, 1+MAX_SKB_FRAGS); - pr_debug("%s: xmit %p %s\n", dev->name, skb, print_mac(mac, dest)); + pr_debug("%s: xmit %p " MAC_FMT "\n", dev->name, skb, + dest[0], dest[1], dest[2], + dest[3], dest[4], dest[5]); /* Encode metadata header at front. */ hdr = skb_vnet_hdr(skb); diff --git a/drivers/net/wireless/hostap/hostap_80211_rx.c b/drivers/net/wireless/hostap/hostap_80211_rx.c index 49978bd..4fd7380 100644 --- a/drivers/net/wireless/hostap/hostap_80211_rx.c +++ b/drivers/net/wireless/hostap/hostap_80211_rx.c @@ -635,7 +635,6 @@ hostap_rx_frame_decrypt(local_info_t *local, struct sk_buff *skb, { struct ieee80211_hdr_4addr *hdr; int res, hdrlen; - DECLARE_MAC_BUF(mac); if (crypt == NULL || crypt->ops->decrypt_mpdu == NULL) return 0; @@ -647,8 +646,10 @@ hostap_rx_frame_decrypt(local_info_t *local, struct sk_buff *skb, strcmp(crypt->ops->name, "TKIP") == 0) { if (net_ratelimit()) { printk(KERN_DEBUG "%s: TKIP countermeasures: dropped " - "received packet from %s\n", - local->dev->name, print_mac(mac, hdr->addr2)); + "received packet from " MAC_FMT "\n", + local->dev->name, + hdr->addr2[0], hdr->addr2[1], hdr->addr2[2], + hdr->addr2[3], hdr->addr2[4], hdr->addr2[5]); } return -1; } @@ -657,9 +658,12 @@ hostap_rx_frame_decrypt(local_info_t *local, struct sk_buff *skb, res = crypt->ops->decrypt_mpdu(skb, hdrlen, crypt->priv); atomic_dec(&crypt->refcnt); if (res < 0) { - printk(KERN_DEBUG "%s: decryption failed (SA=%s" + printk(KERN_DEBUG "%s: decryption failed (SA=" MAC_FMT ") res=%d\n", - local->dev->name, print_mac(mac, hdr->addr2), res); + local->dev->name, + hdr->addr2[0], hdr->addr2[1], hdr->addr2[2], + hdr->addr2[3], hdr->addr2[4], hdr->addr2[5], + res); local->comm_tallies.rx_discards_wep_undecryptable++; return -1; } @@ -721,7 +725,6 @@ void hostap_80211_rx(struct net_device *dev, struct sk_buff *skb, struct ieee80211_crypt_data *crypt = NULL; void *sta = NULL; int keyidx = 0; - DECLARE_MAC_BUF(mac); iface = netdev_priv(dev); local = iface->local; @@ -798,8 +801,10 @@ void hostap_80211_rx(struct net_device *dev, struct sk_buff *skb, * frames silently instead of filling system log with * these reports. */ printk(KERN_DEBUG "%s: WEP decryption failed (not set)" - " (SA=%s)\n", - local->dev->name, print_mac(mac, hdr->addr2)); + " (SA=" MAC_FMT ")\n", + local->dev->name, + hdr->addr2[0], hdr->addr2[1], hdr->addr2[2], + hdr->addr2[3], hdr->addr2[4], hdr->addr2[5]); #endif local->comm_tallies.rx_discards_wep_undecryptable++; goto rx_dropped; @@ -813,8 +818,9 @@ void hostap_80211_rx(struct net_device *dev, struct sk_buff *skb, (keyidx = hostap_rx_frame_decrypt(local, skb, crypt)) < 0) { printk(KERN_DEBUG "%s: failed to decrypt mgmt::auth " - "from %s\n", dev->name, - print_mac(mac, hdr->addr2)); + "from " MAC_FMT "\n", dev->name, + hdr->addr2[0], hdr->addr2[1], hdr->addr2[2], + hdr->addr2[3], hdr->addr2[4], hdr->addr2[5]); /* TODO: could inform hostapd about this so that it * could send auth failure report */ goto rx_dropped; @@ -982,8 +988,10 @@ void hostap_80211_rx(struct net_device *dev, struct sk_buff *skb, "unencrypted EAPOL frame\n", local->dev->name); } else { printk(KERN_DEBUG "%s: encryption configured, but RX " - "frame not encrypted (SA=%s)\n", - local->dev->name, print_mac(mac, hdr->addr2)); + "frame not encrypted (SA=" MAC_FMT ")\n", + local->dev->name, + hdr->addr2[0], hdr->addr2[1], hdr->addr2[2], + hdr->addr2[3], hdr->addr2[4], hdr->addr2[5]); goto rx_dropped; } } @@ -992,9 +1000,10 @@ void hostap_80211_rx(struct net_device *dev, struct sk_buff *skb, !hostap_is_eapol_frame(local, skb)) { if (net_ratelimit()) { printk(KERN_DEBUG "%s: dropped unencrypted RX data " - "frame from %s" - " (drop_unencrypted=1)\n", - dev->name, print_mac(mac, hdr->addr2)); + "frame from " MAC_FMT " (drop_unencrypted=1)\n", + dev->name, + hdr->addr2[0], hdr->addr2[1], hdr->addr2[2], + hdr->addr2[3], hdr->addr2[4], hdr->addr2[5]); } goto rx_dropped; } diff --git a/drivers/net/wireless/hostap/hostap_80211_tx.c b/drivers/net/wireless/hostap/hostap_80211_tx.c index e7afc3e..921c984 100644 --- a/drivers/net/wireless/hostap/hostap_80211_tx.c +++ b/drivers/net/wireless/hostap/hostap_80211_tx.c @@ -314,7 +314,6 @@ static struct sk_buff * hostap_tx_encrypt(struct sk_buff *skb, struct ieee80211_hdr_4addr *hdr; u16 fc; int prefix_len, postfix_len, hdr_len, res; - DECLARE_MAC_BUF(mac); iface = netdev_priv(skb->dev); local = iface->local; @@ -329,8 +328,10 @@ static struct sk_buff * hostap_tx_encrypt(struct sk_buff *skb, hdr = (struct ieee80211_hdr_4addr *) skb->data; if (net_ratelimit()) { printk(KERN_DEBUG "%s: TKIP countermeasures: dropped " - "TX packet to %s\n", - local->dev->name, print_mac(mac, hdr->addr1)); + "TX packet to " MAC_FMT "\n", + local->dev->name, + hdr->addr1[0], hdr->addr1[1], hdr->addr1[2], + hdr->addr1[3], hdr->addr1[4], hdr->addr1[5]); } kfree_skb(skb); return NULL; diff --git a/drivers/net/wireless/hostap/hostap_ap.c b/drivers/net/wireless/hostap/hostap_ap.c index ad040a3..0acd958 100644 --- a/drivers/net/wireless/hostap/hostap_ap.c +++ b/drivers/net/wireless/hostap/hostap_ap.c @@ -632,7 +632,6 @@ static void hostap_ap_tx_cb_auth(struct sk_buff *skb, int ok, void *data) __le16 *pos; struct sta_info *sta = NULL; char *txt = NULL; - DECLARE_MAC_BUF(mac); if (ap->local->hostapd) { dev_kfree_skb(skb); @@ -684,10 +683,12 @@ static void hostap_ap_tx_cb_auth(struct sk_buff *skb, int ok, void *data) if (sta) atomic_dec(&sta->users); if (txt) { - PDEBUG(DEBUG_AP, "%s: %s auth_cb - alg=%d " + PDEBUG(DEBUG_AP, "%s: " MAC_FMT " auth_cb - alg=%d " "trans#=%d status=%d - %s\n", - dev->name, print_mac(mac, hdr->addr1), auth_alg, - auth_transaction, status, txt); + dev->name, + hdr->addr1[0], hdr->addr1[1], hdr->addr1[2], + hdr->addr1[3], hdr->addr1[4], hdr->addr1[5], + auth_alg, auth_transaction, status, txt); } dev_kfree_skb(skb); } @@ -703,7 +704,6 @@ static void hostap_ap_tx_cb_assoc(struct sk_buff *skb, int ok, void *data) __le16 *pos; struct sta_info *sta = NULL; char *txt = NULL; - DECLARE_MAC_BUF(mac); if (ap->local->hostapd) { dev_kfree_skb(skb); @@ -754,8 +754,11 @@ static void hostap_ap_tx_cb_assoc(struct sk_buff *skb, int ok, void *data) if (sta) atomic_dec(&sta->users); if (txt) { - PDEBUG(DEBUG_AP, "%s: %s assoc_cb - %s\n", - dev->name, print_mac(mac, hdr->addr1), txt); + PDEBUG(DEBUG_AP, "%s: " MAC_FMT " assoc_cb - %s\n", + dev->name, + hdr->addr1[0], hdr->addr1[1], hdr->addr1[2], + hdr->addr1[3], hdr->addr1[4], hdr->addr1[5], + txt); } dev_kfree_skb(skb); } @@ -767,7 +770,6 @@ static void hostap_ap_tx_cb_poll(struct sk_buff *skb, int ok, void *data) struct ap_data *ap = data; struct ieee80211_hdr_4addr *hdr; struct sta_info *sta; - DECLARE_MAC_BUF(mac); if (skb->len < 24) goto fail; @@ -779,9 +781,11 @@ static void hostap_ap_tx_cb_poll(struct sk_buff *skb, int ok, void *data) sta->flags &= ~WLAN_STA_PENDING_POLL; spin_unlock(&ap->sta_table_lock); } else { - PDEBUG(DEBUG_AP, "%s: STA %s" + PDEBUG(DEBUG_AP, "%s: STA " MAC_FMT " did not ACK activity poll frame\n", - ap->local->dev->name, print_mac(mac, hdr->addr1)); + ap->local->dev->name, + hdr->addr1[0], hdr->addr1[1], hdr->addr1[2], + hdr->addr1[3], hdr->addr1[4], hdr->addr1[5]); } fail: @@ -1306,7 +1310,6 @@ static void handle_authen(local_info_t *local, struct sk_buff *skb, struct sta_info *sta = NULL; struct ieee80211_crypt_data *crypt; char *txt = ""; - DECLARE_MAC_BUF(mac); len = skb->len - IEEE80211_MGMT_HDR_LEN; @@ -1315,8 +1318,9 @@ static void handle_authen(local_info_t *local, struct sk_buff *skb, if (len < 6) { PDEBUG(DEBUG_AP, "%s: handle_authen - too short payload " - "(len=%d) from %s\n", dev->name, len, - print_mac(mac, hdr->addr2)); + "(len=%d) from " MAC_FMT "\n", dev->name, len, + hdr->addr2[0], hdr->addr2[1], hdr->addr2[2], + hdr->addr2[3], hdr->addr2[4], hdr->addr2[5]); return; } @@ -1381,8 +1385,10 @@ static void handle_authen(local_info_t *local, struct sk_buff *skb, if (time_after(jiffies, sta->u.ap.last_beacon + (10 * sta->listen_interval * HZ) / 1024)) { PDEBUG(DEBUG_AP, "%s: no beacons received for a while," - " assuming AP %s is now STA\n", - dev->name, print_mac(mac, sta->addr)); + " assuming AP " MAC_FMT " is now STA\n", + dev->name, + sta->addr[0], sta->addr[1], sta->addr[2], + sta->addr[3], sta->addr[4], sta->addr[5]); sta->ap = 0; sta->flags = 0; sta->u.sta.challenge = NULL; @@ -1497,10 +1503,13 @@ static void handle_authen(local_info_t *local, struct sk_buff *skb, } if (resp) { - PDEBUG(DEBUG_AP, "%s: %s auth (alg=%d " + PDEBUG(DEBUG_AP, "%s: " MAC_FMT " auth (alg=%d " "trans#=%d stat=%d len=%d fc=%04x) ==> %d (%s)\n", - dev->name, print_mac(mac, hdr->addr2), auth_alg, - auth_transaction, status_code, len, fc, resp, txt); + dev->name, + hdr->addr2[0], hdr->addr2[1], hdr->addr2[2], + hdr->addr2[3], hdr->addr2[4], hdr->addr2[5], + auth_alg, auth_transaction, status_code, len, + fc, resp, txt); } } @@ -1519,14 +1528,15 @@ static void handle_assoc(local_info_t *local, struct sk_buff *skb, int send_deauth = 0; char *txt = ""; u8 prev_ap[ETH_ALEN]; - DECLARE_MAC_BUF(mac); left = len = skb->len - IEEE80211_MGMT_HDR_LEN; if (len < (reassoc ? 10 : 4)) { PDEBUG(DEBUG_AP, "%s: handle_assoc - too short payload " - "(len=%d, reassoc=%d) from %s\n", - dev->name, len, reassoc, print_mac(mac, hdr->addr2)); + "(len=%d, reassoc=%d) from " MAC_FMT "\n", + dev->name, len, reassoc, + hdr->addr2[0], hdr->addr2[1], hdr->addr2[2], + hdr->addr2[3], hdr->addr2[4], hdr->addr2[5]); return; } @@ -1603,9 +1613,12 @@ static void handle_assoc(local_info_t *local, struct sk_buff *skb, } if (left > 0) { - PDEBUG(DEBUG_AP, "%s: assoc from %s" + PDEBUG(DEBUG_AP, "%s: assoc from " MAC_FMT " with extra data (%d bytes) [", - dev->name, print_mac(mac, hdr->addr2), left); + dev->name, + hdr->addr2[0], hdr->addr2[1], hdr->addr2[2], + hdr->addr2[3], hdr->addr2[4], hdr->addr2[5], + left); while (left > 0) { PDEBUG2(DEBUG_AP, "<%02x>", *u); u++; left--; @@ -1704,10 +1717,15 @@ static void handle_assoc(local_info_t *local, struct sk_buff *skb, } #if 0 - PDEBUG(DEBUG_AP, "%s: %s %sassoc (len=%d " - "prev_ap=%s) => %d(%d) (%s)\n", - dev->name, print_mac(mac, hdr->addr2), reassoc ? "re" : "", len, - print_mac(mac, prev_ap), resp, send_deauth, txt); + PDEBUG(DEBUG_AP, "%s: " MAC_FMT" %sassoc (len=%d " + "prev_ap=" MAC_FMT") => %d(%d) (%s)\n", + dev->name, + hdr->addr2[0], hdr->addr2[1], hdr->addr2[2], + hdr->addr2[3], hdr->addr2[4], hdr->addr2[5], + reassoc ? "re" : "", len, + prev_ap[0], prev_ap[1], prev_ap[2], + prev_ap[3], prev_ap[4], prev_ap[5], + resp, send_deauth, txt); #endif } @@ -1735,9 +1753,11 @@ static void handle_deauth(local_info_t *local, struct sk_buff *skb, pos = (__le16 *) body; reason_code = le16_to_cpu(*pos); - PDEBUG(DEBUG_AP, "%s: deauthentication: %s len=%d, " - "reason_code=%d\n", dev->name, print_mac(mac, hdr->addr2), len, - reason_code); + PDEBUG(DEBUG_AP, "%s: deauthentication: " MAC_FMT " len=%d, " + "reason_code=%d\n", dev->name, + hdr->addr2[0], hdr->addr2[1], hdr->addr2[2], + hdr->addr2[3], hdr->addr2[4], hdr->addr2[5], + len, reason_code); spin_lock_bh(&local->ap->sta_table_lock); sta = ap_get_sta(local->ap, hdr->addr2); @@ -1748,9 +1768,11 @@ static void handle_deauth(local_info_t *local, struct sk_buff *skb, } spin_unlock_bh(&local->ap->sta_table_lock); if (sta == NULL) { - printk("%s: deauthentication from %s, " + printk("%s: deauthentication from " MAC_FMT ", " "reason_code=%d, but STA not authenticated\n", dev->name, - print_mac(mac, hdr->addr2), reason_code); + hdr->addr2[0], hdr->addr2[1], hdr->addr2[2], + hdr->addr2[3], hdr->addr2[4], hdr->addr2[5], + reason_code); } } @@ -1766,7 +1788,6 @@ static void handle_disassoc(local_info_t *local, struct sk_buff *skb, u16 reason_code; __le16 *pos; struct sta_info *sta = NULL; - DECLARE_MAC_BUF(mac); len = skb->len - IEEE80211_MGMT_HDR_LEN; @@ -1778,9 +1799,11 @@ static void handle_disassoc(local_info_t *local, struct sk_buff *skb, pos = (__le16 *) body; reason_code = le16_to_cpu(*pos); - PDEBUG(DEBUG_AP, "%s: disassociation: %s len=%d, " - "reason_code=%d\n", dev->name, print_mac(mac, hdr->addr2), len, - reason_code); + PDEBUG(DEBUG_AP, "%s: disassociation: " MAC_FMT " len=%d, " + "reason_code=%d\n", dev->name, + hdr->addr2[0], hdr->addr2[1], hdr->addr2[2], + hdr->addr2[3], hdr->addr2[4], hdr->addr2[5], + len, reason_code); spin_lock_bh(&local->ap->sta_table_lock); sta = ap_get_sta(local->ap, hdr->addr2); @@ -1791,9 +1814,12 @@ static void handle_disassoc(local_info_t *local, struct sk_buff *skb, } spin_unlock_bh(&local->ap->sta_table_lock); if (sta == NULL) { - printk("%s: disassociation from %s, " + printk("%s: disassociation from " MAC_FMT ", " "reason_code=%d, but STA not authenticated\n", - dev->name, print_mac(mac, hdr->addr2), reason_code); + dev->name, + hdr->addr2[0], hdr->addr2[1], hdr->addr2[2], + hdr->addr2[3], hdr->addr2[4], hdr->addr2[5], + reason_code); } } @@ -1882,16 +1908,20 @@ static void handle_pspoll(local_info_t *local, struct sta_info *sta; u16 aid; struct sk_buff *skb; - DECLARE_MAC_BUF(mac); - PDEBUG(DEBUG_PS2, "handle_pspoll: BSSID=%s" - ", TA=%s PWRMGT=%d\n", - print_mac(mac, hdr->addr1), print_mac(mac, hdr->addr2), + PDEBUG(DEBUG_PS2, "handle_pspoll: BSSID=" MAC_FMT + ", TA=" MAC_FMT " PWRMGT=%d\n", + hdr->addr1[0], hdr->addr1[1], hdr->addr1[2], + hdr->addr1[3], hdr->addr1[4], hdr->addr1[5], + hdr->addr2[0], hdr->addr2[1], hdr->addr2[2], + hdr->addr2[3], hdr->addr2[4], hdr->addr2[5], !!(le16_to_cpu(hdr->frame_ctl) & IEEE80211_FCTL_PM)); if (memcmp(hdr->addr1, dev->dev_addr, ETH_ALEN)) { - PDEBUG(DEBUG_AP, "handle_pspoll - addr1(BSSID)=%s" - " not own MAC\n", print_mac(mac, hdr->addr1)); + PDEBUG(DEBUG_AP, "handle_pspoll - addr1(BSSID)=" MAC_FMT + " not own MAC\n", + hdr->addr1[0], hdr->addr1[1], hdr->addr1[2], + hdr->addr1[3], hdr->addr1[4], hdr->addr1[5]); return; } @@ -1969,7 +1999,6 @@ static void handle_wds_oper_queue(struct work_struct *work) wds_oper_queue); local_info_t *local = ap->local; struct wds_oper_data *entry, *prev; - DECLARE_MAC_BUF(mac); spin_lock_bh(&local->lock); entry = local->ap->wds_oper_entries; @@ -1978,10 +2007,11 @@ static void handle_wds_oper_queue(struct work_struct *work) while (entry) { PDEBUG(DEBUG_AP, "%s: %s automatic WDS connection " - "to AP %s\n", + "to AP " MAC_FMT "\n", local->dev->name, entry->type == WDS_ADD ? "adding" : "removing", - print_mac(mac, entry->addr)); + entry->addr[0], entry->addr[1], entry->addr[2], + entry->addr[3], entry->addr[4], entry->addr[5]); if (entry->type == WDS_ADD) prism2_wds_add(local, entry->addr, 0); else if (entry->type == WDS_DEL) @@ -2158,7 +2188,6 @@ static void handle_ap_item(local_info_t *local, struct sk_buff *skb, #endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */ u16 fc, type, stype; struct ieee80211_hdr_4addr *hdr; - DECLARE_MAC_BUF(mac); /* FIX: should give skb->len to handler functions and check that the * buffer is long enough */ @@ -2187,8 +2216,9 @@ static void handle_ap_item(local_info_t *local, struct sk_buff *skb, if (memcmp(hdr->addr1, dev->dev_addr, ETH_ALEN)) { PDEBUG(DEBUG_AP, "handle_ap_item - addr1(BSSID)=" - "%s not own MAC\n", - print_mac(mac, hdr->addr1)); + MAC_FMT " not own MAC\n", + hdr->addr1[0], hdr->addr1[1], hdr->addr1[2], + hdr->addr1[3], hdr->addr1[4], hdr->addr1[5]); goto done; } @@ -2224,14 +2254,18 @@ static void handle_ap_item(local_info_t *local, struct sk_buff *skb, } if (memcmp(hdr->addr1, dev->dev_addr, ETH_ALEN)) { - PDEBUG(DEBUG_AP, "handle_ap_item - addr1(DA)=%s" - " not own MAC\n", print_mac(mac, hdr->addr1)); + PDEBUG(DEBUG_AP, "handle_ap_item - addr1(DA)=" MAC_FMT + " not own MAC\n", + hdr->addr1[0], hdr->addr1[1], hdr->addr1[2], + hdr->addr1[3], hdr->addr1[4], hdr->addr1[5]); goto done; } if (memcmp(hdr->addr3, dev->dev_addr, ETH_ALEN)) { - PDEBUG(DEBUG_AP, "handle_ap_item - addr3(BSSID)=%s" - " not own MAC\n", print_mac(mac, hdr->addr3)); + PDEBUG(DEBUG_AP, "handle_ap_item - addr3(BSSID)=" MAC_FMT + " not own MAC\n", + hdr->addr3[0], hdr->addr3[1], hdr->addr3[2], + hdr->addr3[3], hdr->addr3[4], hdr->addr3[5]); goto done; } @@ -2312,7 +2346,6 @@ static void schedule_packet_send(local_info_t *local, struct sta_info *sta) struct sk_buff *skb; struct ieee80211_hdr_4addr *hdr; struct hostap_80211_rx_status rx_stats; - DECLARE_MAC_BUF(mac); if (skb_queue_empty(&sta->tx_buf)) return; @@ -2334,7 +2367,9 @@ static void schedule_packet_send(local_info_t *local, struct sta_info *sta) hdr->duration_id = cpu_to_le16(sta->aid | BIT(15) | BIT(14)); PDEBUG(DEBUG_PS2, "%s: Scheduling buffered packet delivery for STA " - "%s\n", local->dev->name, print_mac(mac, sta->addr)); + MAC_FMT "\n", local->dev->name, + sta->addr[0], sta->addr[1], sta->addr[2], + sta->addr[3], sta->addr[4], sta->addr[5]); skb->dev = local->dev; @@ -2661,7 +2696,6 @@ static int ap_update_sta_tx_rate(struct sta_info *sta, struct net_device *dev) int ret = sta->tx_rate; struct hostap_interface *iface; local_info_t *local; - DECLARE_MAC_BUF(mac); iface = netdev_priv(dev); local = iface->local; @@ -2689,9 +2723,12 @@ static int ap_update_sta_tx_rate(struct sta_info *sta, struct net_device *dev) case 3: sta->tx_rate = 110; break; default: sta->tx_rate = 0; break; } - PDEBUG(DEBUG_AP, "%s: STA %s" + PDEBUG(DEBUG_AP, "%s: STA " MAC_FMT " TX rate raised to %d\n", - dev->name, print_mac(mac, sta->addr), sta->tx_rate); + dev->name, + sta->addr[0], sta->addr[1], sta->addr[2], + sta->addr[3], sta->addr[4], sta->addr[5], + sta->tx_rate); } sta->tx_since_last_failure = 0; } @@ -2709,7 +2746,6 @@ ap_tx_ret hostap_handle_sta_tx(local_info_t *local, struct hostap_tx_data *tx) int set_tim, ret; struct ieee80211_hdr_4addr *hdr; struct hostap_skb_tx_data *meta; - DECLARE_MAC_BUF(mac); meta = (struct hostap_skb_tx_data *) skb->cb; ret = AP_TX_CONTINUE; @@ -2745,8 +2781,9 @@ ap_tx_ret hostap_handle_sta_tx(local_info_t *local, struct hostap_tx_data *tx) * print out any errors here. */ if (net_ratelimit()) { printk(KERN_DEBUG "AP: drop packet to non-associated " - "STA %s\n", - print_mac(mac, hdr->addr1)); + "STA " MAC_FMT "\n", + hdr->addr1[0], hdr->addr1[1], hdr->addr1[2], + hdr->addr1[3], hdr->addr1[4], hdr->addr1[5]); } #endif local->ap->tx_drop_nonassoc++; @@ -2784,9 +2821,11 @@ ap_tx_ret hostap_handle_sta_tx(local_info_t *local, struct hostap_tx_data *tx) } if (skb_queue_len(&sta->tx_buf) >= STA_MAX_TX_BUFFER) { - PDEBUG(DEBUG_PS, "%s: No more space in STA (%s" + PDEBUG(DEBUG_PS, "%s: No more space in STA (" MAC_FMT ")'s PS mode buffer\n", - local->dev->name, print_mac(mac, sta->addr)); + local->dev->name, + sta->addr[0], sta->addr[1], sta->addr[2], + sta->addr[3], sta->addr[4], sta->addr[5]); /* Make sure that TIM is set for the station (it might not be * after AP wlan hw reset). */ /* FIX: should fix hw reset to restore bits based on STA @@ -2850,7 +2889,6 @@ void hostap_handle_sta_tx_exc(local_info_t *local, struct sk_buff *skb) struct sta_info *sta; struct ieee80211_hdr_4addr *hdr; struct hostap_skb_tx_data *meta; - DECLARE_MAC_BUF(mac); hdr = (struct ieee80211_hdr_4addr *) skb->data; meta = (struct hostap_skb_tx_data *) skb->cb; @@ -2859,9 +2897,12 @@ void hostap_handle_sta_tx_exc(local_info_t *local, struct sk_buff *skb) sta = ap_get_sta(local->ap, hdr->addr1); if (!sta) { spin_unlock(&local->ap->sta_table_lock); - PDEBUG(DEBUG_AP, "%s: Could not find STA %s" + PDEBUG(DEBUG_AP, "%s: Could not find STA " MAC_FMT " for this TX error (@%lu)\n", - local->dev->name, print_mac(mac, hdr->addr1), jiffies); + local->dev->name, + hdr->addr1[0], hdr->addr1[1], hdr->addr1[2], + hdr->addr1[3], hdr->addr1[4], hdr->addr1[5], + jiffies); return; } @@ -2888,9 +2929,11 @@ void hostap_handle_sta_tx_exc(local_info_t *local, struct sk_buff *skb) case 3: sta->tx_rate = 110; break; default: sta->tx_rate = 0; break; } - PDEBUG(DEBUG_AP, "%s: STA %s" + PDEBUG(DEBUG_AP, "%s: STA " MAC_FMT " TX rate lowered to %d\n", - local->dev->name, print_mac(mac, sta->addr), + local->dev->name, + sta->addr[0], sta->addr[1], sta->addr[2], + sta->addr[3], sta->addr[4], sta->addr[5], sta->tx_rate); } sta->tx_consecutive_exc = 0; @@ -2956,7 +2999,6 @@ ap_rx_ret hostap_handle_sta_rx(local_info_t *local, struct net_device *dev, struct sta_info *sta; u16 fc, type, stype; struct ieee80211_hdr_4addr *hdr; - DECLARE_MAC_BUF(mac); if (local->ap == NULL) return AP_RX_CONTINUE; @@ -2988,9 +3030,12 @@ ap_rx_ret hostap_handle_sta_rx(local_info_t *local, struct net_device *dev, } else { printk(KERN_DEBUG "%s: dropped received packet" " from non-associated STA " - "%s" + MAC_FMT " (type=0x%02x, subtype=0x%02x)\n", - dev->name, print_mac(mac, hdr->addr2), + dev->name, + hdr->addr2[0], hdr->addr2[1], + hdr->addr2[2], hdr->addr2[3], + hdr->addr2[4], hdr->addr2[5], type >> 2, stype >> 4); hostap_rx(dev, skb, rx_stats); #endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */ @@ -3025,8 +3070,11 @@ ap_rx_ret hostap_handle_sta_rx(local_info_t *local, struct net_device *dev, * being associated. */ printk(KERN_DEBUG "%s: rejected received nullfunc " "frame without ToDS from not associated STA " - "%s\n", - dev->name, print_mac(mac, hdr->addr2)); + MAC_FMT "\n", + dev->name, + hdr->addr2[0], hdr->addr2[1], + hdr->addr2[2], hdr->addr2[3], + hdr->addr2[4], hdr->addr2[5]); hostap_rx(dev, skb, rx_stats); #endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */ } @@ -3043,9 +3091,12 @@ ap_rx_ret hostap_handle_sta_rx(local_info_t *local, struct net_device *dev, * If BSSID is own, report the dropping of this frame. */ if (memcmp(hdr->addr3, dev->dev_addr, ETH_ALEN) == 0) { printk(KERN_DEBUG "%s: dropped received packet from " - "%s with no ToDS flag " + MAC_FMT " with no ToDS flag " "(type=0x%02x, subtype=0x%02x)\n", dev->name, - print_mac(mac, hdr->addr2), type >> 2, stype >> 4); + hdr->addr2[0], hdr->addr2[1], + hdr->addr2[2], hdr->addr2[3], + hdr->addr2[4], hdr->addr2[5], + type >> 2, stype >> 4); hostap_dump_rx_80211(dev->name, skb, rx_stats); } ret = AP_RX_DROP; diff --git a/drivers/net/wireless/ipw2200.c b/drivers/net/wireless/ipw2200.c index a56d9fc..0d78e40 100644 --- a/drivers/net/wireless/ipw2200.c +++ b/drivers/net/wireless/ipw2200.c @@ -10192,7 +10192,6 @@ static int ipw_tx_skb(struct ipw_priv *priv, struct ieee80211_txb *txb, u8 id, hdr_len, unicast; u16 remaining_bytes; int fc; - DECLARE_MAC_BUF(mac); hdr_len = ieee80211_get_hdrlen(le16_to_cpu(hdr->frame_ctl)); switch (priv->ieee->iw_mode) { @@ -10203,8 +10202,10 @@ static int ipw_tx_skb(struct ipw_priv *priv, struct ieee80211_txb *txb, id = ipw_add_station(priv, hdr->addr1); if (id == IPW_INVALID_STATION) { IPW_WARNING("Attempt to send data to " - "invalid cell: %s\n", - print_mac(mac, hdr->addr1)); + "invalid cell: " MAC_FMT "\n", + hdr->addr1[0], hdr->addr1[1], + hdr->addr1[2], hdr->addr1[3], + hdr->addr1[4], hdr->addr1[5]); goto drop; } } diff --git a/net/atm/lec.c b/net/atm/lec.c index a2efa7f..3235c57 100644 --- a/net/atm/lec.c +++ b/net/atm/lec.c @@ -266,7 +266,6 @@ static int lec_start_xmit(struct sk_buff *skb, struct net_device *dev) char buf[300]; int i = 0; #endif /* DUMP_PACKETS >0 */ - DECLARE_MAC_BUF(mac); pr_debug("lec_start_xmit called\n"); if (!priv->lecd) { @@ -374,15 +373,19 @@ static int lec_start_xmit(struct sk_buff *skb, struct net_device *dev) if (entry && (entry->tx_wait.qlen < LEC_UNRES_QUE_LEN)) { pr_debug("%s:lec_start_xmit: queuing packet, ", dev->name); - pr_debug("MAC address %s\n", - print_mac(mac, lec_h->h_dest)); + pr_debug("MAC address " MAC_FMT "\n", + lec_h->h_dest[0], lec_h->h_dest[1], + lec_h->h_dest[2], lec_h->h_dest[3], + lec_h->h_dest[4], lec_h->h_dest[5]); skb_queue_tail(&entry->tx_wait, skb); } else { pr_debug ("%s:lec_start_xmit: tx queue full or no arp entry, dropping, ", dev->name); - pr_debug("MAC address %s\n", - print_mac(mac, lec_h->h_dest)); + pr_debug("MAC address " MAC_FMT "\n", + lec_h->h_dest[0], lec_h->h_dest[1], + lec_h->h_dest[2], lec_h->h_dest[3], + lec_h->h_dest[4], lec_h->h_dest[5]); priv->stats.tx_dropped++; dev_kfree_skb(skb); } @@ -394,8 +397,10 @@ static int lec_start_xmit(struct sk_buff *skb, struct net_device *dev) while (entry && (skb2 = skb_dequeue(&entry->tx_wait))) { pr_debug("lec.c: emptying tx queue, "); - pr_debug("MAC address %s\n", - print_mac(mac, lec_h->h_dest)); + pr_debug("MAC address " MAC_FMT "\n", + lec_h->h_dest[0], lec_h->h_dest[1], + lec_h->h_dest[2], lec_h->h_dest[3], + lec_h->h_dest[4], lec_h->h_dest[5]); lec_send(vcc, skb2, priv); } @@ -449,7 +454,6 @@ static int lec_atm_send(struct atm_vcc *vcc, struct sk_buff *skb) struct lec_arp_table *entry; int i; char *tmp; /* FIXME */ - DECLARE_MAC_BUF(mac); atomic_sub(skb->truesize, &sk_atm(vcc)->sk_wmem_alloc); mesg = (struct atmlec_msg *)skb->data; @@ -536,9 +540,14 @@ static int lec_atm_send(struct atm_vcc *vcc, struct sk_buff *skb) struct net_bridge_fdb_entry *f; pr_debug - ("%s: bridge zeppelin asks about %s\n", + ("%s: bridge zeppelin asks about " MAC_FMT "\n", dev->name, - print_mac(mac, mesg->content.proxy.mac_addr)); + mesg->content.proxy.mac_addr[0], + mesg->content.proxy.mac_addr[1], + mesg->content.proxy.mac_addr[2], + mesg->content.proxy.mac_addr[3], + mesg->content.proxy.mac_addr[4], + mesg->content.proxy.mac_addr[5]); if (br_fdb_get_hook == NULL || dev->br_port == NULL) break; diff --git a/net/ieee80211/ieee80211_rx.c b/net/ieee80211/ieee80211_rx.c index 1e3f87c..200ee1e 100644 --- a/net/ieee80211/ieee80211_rx.c +++ b/net/ieee80211/ieee80211_rx.c @@ -271,7 +271,6 @@ ieee80211_rx_frame_decrypt(struct ieee80211_device *ieee, struct sk_buff *skb, { struct ieee80211_hdr_3addr *hdr; int res, hdrlen; - DECLARE_MAC_BUF(mac); if (crypt == NULL || crypt->ops->decrypt_mpdu == NULL) return 0; @@ -283,8 +282,12 @@ ieee80211_rx_frame_decrypt(struct ieee80211_device *ieee, struct sk_buff *skb, res = crypt->ops->decrypt_mpdu(skb, hdrlen, crypt->priv); atomic_dec(&crypt->refcnt); if (res < 0) { - IEEE80211_DEBUG_DROP("decryption failed (SA=%s" - ") res=%d\n", print_mac(mac, hdr->addr2), res); + IEEE80211_DEBUG_DROP("decryption failed (SA=" MAC_FMT + ") res=%d\n", + hdr->addr2[0], hdr->addr2[1], + hdr->addr2[2], hdr->addr2[3], + hdr->addr2[4], hdr->addr2[5], + res); if (res == -2) IEEE80211_DEBUG_DROP("Decryption failed ICV " "mismatch (key %d)\n", @@ -304,7 +307,6 @@ ieee80211_rx_frame_decrypt_msdu(struct ieee80211_device *ieee, { struct ieee80211_hdr_3addr *hdr; int res, hdrlen; - DECLARE_MAC_BUF(mac); if (crypt == NULL || crypt->ops->decrypt_msdu == NULL) return 0; @@ -317,8 +319,12 @@ ieee80211_rx_frame_decrypt_msdu(struct ieee80211_device *ieee, atomic_dec(&crypt->refcnt); if (res < 0) { printk(KERN_DEBUG "%s: MSDU decryption/MIC verification failed" - " (SA=%s keyidx=%d)\n", - ieee->dev->name, print_mac(mac, hdr->addr2), keyidx); + " (SA=" MAC_FMT " keyidx=%d)\n", + ieee->dev->name, + hdr->addr2[0], hdr->addr2[1], + hdr->addr2[2], hdr->addr2[3], + hdr->addr2[4], hdr->addr2[5], + keyidx); return -1; } @@ -462,8 +468,10 @@ int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb, * frames silently instead of filling system log with * these reports. */ IEEE80211_DEBUG_DROP("Decryption failed (not set)" - " (SA=%s)\n", - print_mac(mac, hdr->addr2)); + " (SA=" MAC_FMT ")\n", + hdr->addr2[0], hdr->addr2[1], + hdr->addr2[2], hdr->addr2[3], + hdr->addr2[4], hdr->addr2[5]); ieee->ieee_stats.rx_discards_undecryptable++; goto rx_dropped; } @@ -474,8 +482,10 @@ int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb, fc & IEEE80211_FCTL_PROTECTED && ieee->host_decrypt && (keyidx = hostap_rx_frame_decrypt(ieee, skb, crypt)) < 0) { printk(KERN_DEBUG "%s: failed to decrypt mgmt::auth " - "from %s\n", dev->name, - print_mac(mac, hdr->addr2)); + "from " MAC_FMT "\n", dev->name, + hdr->addr2[0], hdr->addr2[1], + hdr->addr2[2], hdr->addr2[3], + hdr->addr2[4], hdr->addr2[5]); /* TODO: could inform hostapd about this so that it * could send auth failure report */ goto rx_dropped; @@ -653,8 +663,11 @@ int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb, * configured */ } else { IEEE80211_DEBUG_DROP("encryption configured, but RX " - "frame not encrypted (SA=%s" - ")\n", print_mac(mac, hdr->addr2)); + "frame not encrypted (SA=" + MAC_FMT ")\n", + hdr->addr2[0], hdr->addr2[1], + hdr->addr2[2], hdr->addr2[3], + hdr->addr2[4], hdr->addr2[5]); goto rx_dropped; } } @@ -662,9 +675,11 @@ int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb, if (crypt && !(fc & IEEE80211_FCTL_PROTECTED) && !ieee->open_wep && !ieee80211_is_eapol_frame(ieee, skb)) { IEEE80211_DEBUG_DROP("dropped unencrypted RX data " - "frame from %s" + "frame from " MAC_FMT " (drop_unencrypted=1)\n", - print_mac(mac, hdr->addr2)); + hdr->addr2[0], hdr->addr2[1], + hdr->addr2[2], hdr->addr2[3], + hdr->addr2[4], hdr->addr2[5]); goto rx_dropped; } -- cgit v0.10.2 From 216bce90b811a35eb5cd2ed8216bdbb1753e9b2b Mon Sep 17 00:00:00 2001 From: Vladimir Koutny Date: Mon, 31 Mar 2008 17:05:10 +0200 Subject: mac80211: use short_preamble mode from capability if ERP IE not present When associating to a b-only AP where there is no ERP IE, short preamble mode is left at previous state (probably also protection mode). In this case, disable protection and use short preamble mode as specified in capability field. The same is done if capability field is changed on-the-fly. Signed-off-by: Vladimir Koutny Signed-off-by: John W. Linville diff --git a/net/mac80211/ieee80211_sta.c b/net/mac80211/ieee80211_sta.c index e0c72d0..c170685 100644 --- a/net/mac80211/ieee80211_sta.c +++ b/net/mac80211/ieee80211_sta.c @@ -312,14 +312,12 @@ static void ieee80211_sta_wmm_params(struct net_device *dev, } } - -static u32 ieee80211_handle_erp_ie(struct ieee80211_sub_if_data *sdata, - u8 erp_value) +static u32 ieee80211_handle_protect_preamb(struct ieee80211_sub_if_data *sdata, + bool use_protection, + bool use_short_preamble) { struct ieee80211_bss_conf *bss_conf = &sdata->bss_conf; struct ieee80211_if_sta *ifsta = &sdata->u.sta; - bool use_protection = (erp_value & WLAN_ERP_USE_PROTECTION) != 0; - bool use_short_preamble = (erp_value & WLAN_ERP_BARKER_PREAMBLE) == 0; DECLARE_MAC_BUF(mac); u32 changed = 0; @@ -350,6 +348,32 @@ static u32 ieee80211_handle_erp_ie(struct ieee80211_sub_if_data *sdata, return changed; } +static u32 ieee80211_handle_erp_ie(struct ieee80211_sub_if_data *sdata, + u8 erp_value) +{ + bool use_protection = (erp_value & WLAN_ERP_USE_PROTECTION) != 0; + bool use_short_preamble = (erp_value & WLAN_ERP_BARKER_PREAMBLE) == 0; + + return ieee80211_handle_protect_preamb(sdata, + use_protection, use_short_preamble); +} + +static u32 ieee80211_handle_bss_capability(struct ieee80211_sub_if_data *sdata, + struct ieee80211_sta_bss *bss) +{ + u32 changed = 0; + + if (bss->has_erp_value) + changed |= ieee80211_handle_erp_ie(sdata, bss->erp_value); + else { + u16 capab = bss->capability; + changed |= ieee80211_handle_protect_preamb(sdata, false, + (capab & WLAN_CAPABILITY_SHORT_PREAMBLE) != 0); + } + + return changed; +} + int ieee80211_ht_cap_ie_to_ht_info(struct ieee80211_ht_cap *ht_cap_ie, struct ieee80211_ht_info *ht_info) { @@ -468,9 +492,7 @@ static void ieee80211_set_associated(struct net_device *dev, local->hw.conf.channel, ifsta->ssid, ifsta->ssid_len); if (bss) { - if (bss->has_erp_value) - changed |= ieee80211_handle_erp_ie( - sdata, bss->erp_value); + changed |= ieee80211_handle_bss_capability(sdata, bss); ieee80211_rx_bss_put(dev, bss); } @@ -2116,6 +2138,11 @@ static void ieee80211_rx_mgmt_beacon(struct net_device *dev, if (elems.erp_info && elems.erp_info_len >= 1) changed |= ieee80211_handle_erp_ie(sdata, elems.erp_info[0]); + else { + u16 capab = le16_to_cpu(mgmt->u.beacon.capab_info); + changed |= ieee80211_handle_protect_preamb(sdata, false, + (capab & WLAN_CAPABILITY_SHORT_PREAMBLE) != 0); + } if (elems.ht_cap_elem && elems.ht_info_elem && elems.wmm_param && local->ops->conf_ht && -- cgit v0.10.2 From b63009b456c8d9abe684bdf8d4bd8f27eb040019 Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Tue, 8 Apr 2008 10:28:24 +0200 Subject: ssb-pcicore: Fix IRQ TPS flag handling This fixes the TPS flag handling for the SSB pcicore driver. This fixes interrupts on some devices. Signed-off-by: Michael Buesch Signed-off-by: John W. Linville diff --git a/drivers/ssb/driver_pcicore.c b/drivers/ssb/driver_pcicore.c index 74b9a8a..5d777f2 100644 --- a/drivers/ssb/driver_pcicore.c +++ b/drivers/ssb/driver_pcicore.c @@ -551,7 +551,7 @@ int ssb_pcicore_dev_irqvecs_enable(struct ssb_pcicore *pc, } else { tmp = ssb_read32(dev, SSB_TPSFLAG); tmp &= SSB_TPSFLAG_BPFLAG; - intvec |= tmp; + intvec |= (1 << tmp); } ssb_write32(pdev, SSB_INTVEC, intvec); } -- cgit v0.10.2 From 2633da237ba29875294f8680ebece5900ccdcc05 Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Tue, 8 Apr 2008 11:17:29 +0200 Subject: ssb-mipscore: Fix interrupt vectors This fixes assignment of the interrupt vectors on the SSB MIPS core. Signed-off-by: Michael Buesch Signed-off-by: John W. Linville diff --git a/drivers/ssb/driver_mipscore.c b/drivers/ssb/driver_mipscore.c index 3d3dd32..a9e7eb4 100644 --- a/drivers/ssb/driver_mipscore.c +++ b/drivers/ssb/driver_mipscore.c @@ -109,12 +109,13 @@ static void set_irq(struct ssb_device *dev, unsigned int irq) clear_irq(bus, oldirq); /* assign the new one */ - if (irq == 0) - ssb_write32(mdev, SSB_INTVEC, ((1 << irqflag) & ssb_read32(mdev, SSB_INTVEC))); - - irqflag <<= ipsflag_irq_shift[irq]; - irqflag |= (ssb_read32(mdev, SSB_IPSFLAG) & ~ipsflag_irq_mask[irq]); - ssb_write32(mdev, SSB_IPSFLAG, irqflag); + if (irq == 0) { + ssb_write32(mdev, SSB_INTVEC, ((1 << irqflag) | ssb_read32(mdev, SSB_INTVEC))); + } else { + irqflag <<= ipsflag_irq_shift[irq]; + irqflag |= (ssb_read32(mdev, SSB_IPSFLAG) & ~ipsflag_irq_mask[irq]); + ssb_write32(mdev, SSB_IPSFLAG, irqflag); + } } static void ssb_mips_serial_init(struct ssb_mipscore *mcore) -- cgit v0.10.2 From e91e9d490d9ae382003ef9d05fd50238db54c35b Mon Sep 17 00:00:00 2001 From: Daniel Wagner Date: Wed, 9 Apr 2008 16:29:01 +0200 Subject: rt61pci: rt61pci_beacon_update do not free skb twice The layer above will free the skb in an error case. Signed-off-by: Daniel Wagner Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c index 93ea212..ad2e7d5 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.c +++ b/drivers/net/wireless/rt2x00/rt61pci.c @@ -2399,10 +2399,8 @@ static int rt61pci_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb, * beacon frame. */ if (skb_headroom(skb) < TXD_DESC_SIZE) { - if (pskb_expand_head(skb, TXD_DESC_SIZE, 0, GFP_ATOMIC)) { - dev_kfree_skb(skb); + if (pskb_expand_head(skb, TXD_DESC_SIZE, 0, GFP_ATOMIC)) return -ENOMEM; - } } /* -- cgit v0.10.2 From bcf0dda8d2408fe1c1040cdec5a98e5fcad2ac72 Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Wed, 9 Apr 2008 15:08:24 -0700 Subject: [XFRM]: xfrm_user: fix selector family initialization Commit df9dcb45 ([IPSEC]: Fix inter address family IPsec tunnel handling) broke openswan by removing the selector initialization for tunnel mode in case it is uninitialized. This patch restores the initialization, fixing openswan, but probably breaking inter-family tunnels again (unknown since the patch author disappeared). The correct thing for inter-family tunnels is probably to simply initialize the selector family explicitly. Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c index 5d96f27..019d21d 100644 --- a/net/xfrm/xfrm_user.c +++ b/net/xfrm/xfrm_user.c @@ -288,7 +288,7 @@ static void copy_from_user_state(struct xfrm_state *x, struct xfrm_usersa_info * memcpy(&x->props.saddr, &p->saddr, sizeof(x->props.saddr)); x->props.flags = p->flags; - if (x->props.mode == XFRM_MODE_TRANSPORT) + if (!x->sel.family) x->sel.family = p->family; } -- cgit v0.10.2 From 1b9b70ea2ebaab26c3e4fed385dfab6fc16359ed Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Wed, 9 Apr 2008 15:14:18 -0700 Subject: [NETFILTER]: xt_hashlimit: fix mask calculation Shifts larger than the data type are undefined, don't try to shift an u32 by 32. Also remove some special-casing of bitmasks divisible by 32. Based on patch by Jan Engelhardt . Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller diff --git a/net/netfilter/xt_hashlimit.c b/net/netfilter/xt_hashlimit.c index dc29007..40d344b 100644 --- a/net/netfilter/xt_hashlimit.c +++ b/net/netfilter/xt_hashlimit.c @@ -466,38 +466,25 @@ static inline void rateinfo_recalc(struct dsthash_ent *dh, unsigned long now) static inline __be32 maskl(__be32 a, unsigned int l) { - return htonl(ntohl(a) & ~(~(u_int32_t)0 >> l)); + return l ? htonl(ntohl(a) & ~0 << (32 - l)) : 0; } #if defined(CONFIG_IP6_NF_IPTABLES) || defined(CONFIG_IP6_NF_IPTABLES_MODULE) static void hashlimit_ipv6_mask(__be32 *i, unsigned int p) { switch (p) { - case 0: - i[0] = i[1] = 0; - i[2] = i[3] = 0; - break; - case 1 ... 31: + case 0 ... 31: i[0] = maskl(i[0], p); i[1] = i[2] = i[3] = 0; break; - case 32: - i[1] = i[2] = i[3] = 0; - break; - case 33 ... 63: + case 32 ... 63: i[1] = maskl(i[1], p - 32); i[2] = i[3] = 0; break; - case 64: - i[2] = i[3] = 0; - break; - case 65 ... 95: + case 64 ... 95: i[2] = maskl(i[2], p - 64); i[3] = 0; - case 96: - i[3] = 0; - break; - case 97 ... 127: + case 96 ... 127: i[3] = maskl(i[3], p - 96); break; case 128: -- cgit v0.10.2 From 475959d4773e53a2700e523dd30acebbd47556a5 Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Wed, 9 Apr 2008 15:14:58 -0700 Subject: [NETFILTER]: nf_nat: autoload IPv4 connection tracking Without this patch, the generic L3 tracker would kick in if nf_conntrack_ipv4 was not loaded before nf_nat, which would lead to translation problems with ICMP errors. NAT does not make sense without IPv4 connection tracking anyway, so just add a call to need_ipv4_conntrack(). Signed-off-by: Jan Engelhardt Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller diff --git a/net/ipv4/netfilter/nf_nat_core.c b/net/ipv4/netfilter/nf_nat_core.c index 0d5fa3a..36b4e3b 100644 --- a/net/ipv4/netfilter/nf_nat_core.c +++ b/net/ipv4/netfilter/nf_nat_core.c @@ -629,6 +629,8 @@ static int __init nf_nat_init(void) size_t i; int ret; + need_ipv4_conntrack(); + ret = nf_ct_extend_register(&nat_extend); if (ret < 0) { printk(KERN_ERR "nf_nat_core: Unable to register extension\n"); -- cgit v0.10.2 From 619c714c1d6e4dff00ddde582d78492fd95452d6 Mon Sep 17 00:00:00 2001 From: Eliezer Tamir Date: Wed, 9 Apr 2008 15:25:46 -0700 Subject: BNX2X: Correct bringing chip out of reset Fixed bug: Wrong register was written to when bringing the chip out of reset. [ Bump driver version and release date -DaveM ] Signed-off-by: Eliezer Tamir Signed-off-by: David S. Miller diff --git a/drivers/net/bnx2x.c b/drivers/net/bnx2x.c index de32b3f..7bdb5af 100644 --- a/drivers/net/bnx2x.c +++ b/drivers/net/bnx2x.c @@ -63,8 +63,8 @@ #include "bnx2x.h" #include "bnx2x_init.h" -#define DRV_MODULE_VERSION "1.42.3" -#define DRV_MODULE_RELDATE "2008/3/9" +#define DRV_MODULE_VERSION "1.42.4" +#define DRV_MODULE_RELDATE "2008/4/9" #define BNX2X_BC_VER 0x040200 /* Time in jiffies before concluding the transmitter is hung. */ @@ -6153,7 +6153,7 @@ static int bnx2x_function_init(struct bnx2x *bp, int mode) func, mode); REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_1_SET, 0xffffffff); - REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_1_SET, + REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_SET, 0xfffc); bnx2x_init_block(bp, MISC_COMMON_START, MISC_COMMON_END); -- cgit v0.10.2 From 951e07c930f5f66b676eaa4c32a1b0d8e2d7d06a Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Thu, 10 Apr 2008 01:29:36 -0700 Subject: [IPV4]: Fix byte value boundary check in do_ip_getsockopt(). This fixes kernel bugzilla 10371. As reported by M.Piechaczek@osmosys.tv, if we try to grab a char sized socket option value, as in: unsigned char ttl = 255; socklen_t len = sizeof(ttl); setsockopt(socket, IPPROTO_IP, IP_MULTICAST_TTL, &ttl, &len); getsockopt(socket, IPPROTO_IP, IP_MULTICAST_TTL, &ttl, &len); The ttl returned will be wrong on big-endian, and on both little- endian and big-endian the next three bytes in userspace are written with garbage. It's because of this test in do_ip_getsockopt(): if (len < sizeof(int) && len > 0 && val>=0 && val<255) { It should allow a 'val' of 255 to pass here, but it doesn't so it copies a full 'int' back to userspace. On little-endian that will write the correct value into the location but it spams on the next three bytes in userspace. On big endian it writes the wrong value into the location and spams the next three bytes. Signed-off-by: David S. Miller diff --git a/net/ipv4/ip_sockglue.c b/net/ipv4/ip_sockglue.c index f72457b..c2921d0 100644 --- a/net/ipv4/ip_sockglue.c +++ b/net/ipv4/ip_sockglue.c @@ -1132,7 +1132,7 @@ static int do_ip_getsockopt(struct sock *sk, int level, int optname, } release_sock(sk); - if (len < sizeof(int) && len > 0 && val>=0 && val<255) { + if (len < sizeof(int) && len > 0 && val>=0 && val<=255) { unsigned char ucval = (unsigned char)val; len = 1; if (put_user(len, optlen)) -- cgit v0.10.2 From 7951f0b03a63d657c72c7d54d306ef3357e7e604 Mon Sep 17 00:00:00 2001 From: Daniel Lezcano Date: Thu, 10 Apr 2008 20:53:10 -0700 Subject: [NETNS][IPV6] tcp - assign the netns for timewait sockets Copy the network namespace from the socket to the timewait socket. Signed-off-by: Daniel Lezcano Acked-by: Mark Lord Signed-off-by: David S. Miller diff --git a/net/ipv4/inet_timewait_sock.c b/net/ipv4/inet_timewait_sock.c index 876169f..717c411 100644 --- a/net/ipv4/inet_timewait_sock.c +++ b/net/ipv4/inet_timewait_sock.c @@ -124,6 +124,7 @@ struct inet_timewait_sock *inet_twsk_alloc(const struct sock *sk, const int stat tw->tw_hash = sk->sk_hash; tw->tw_ipv6only = 0; tw->tw_prot = sk->sk_prot_creator; + tw->tw_net = sk->sk_net; atomic_set(&tw->tw_refcnt, 1); inet_twsk_dead_node_init(tw); __module_get(tw->tw_prot->owner); -- cgit v0.10.2 From c63eddb200690023e7c67f4dd9f132ad91660517 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Thu, 10 Apr 2008 15:06:14 -0500 Subject: sky2: missing chip name for Yukon Supreme Any usage of sky2 on new Yukon Supreme would cause a NULL dereference. The chip is very new, so the support is still untested; vendor has not sent any eval hardware. Signed-off-by: Stephen Hemminger Signed-off-by: Jeff Garzik diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index 853bce0..f226bca 100644 --- a/drivers/net/sky2.c +++ b/drivers/net/sky2.c @@ -154,6 +154,7 @@ static const char *yukon2_name[] = { "EC", /* 0xb6 */ "FE", /* 0xb7 */ "FE+", /* 0xb8 */ + "Supreme", /* 0xb9 */ }; static void sky2_set_multicast(struct net_device *dev); -- cgit v0.10.2 From 9a3c243d7d87f401682247dbeff94067d814c192 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Fri, 11 Apr 2008 14:05:50 +0200 Subject: fs_enet: Don't call NAPI functions when NAPI is not used. fs_enet_close() calls napi_disable() unconditionally. This patch skips the call when use_napi isn't set. Signed-off-by: Laurent Pinchart Signed-off-by: Jeff Garzik diff --git a/drivers/net/fs_enet/fs_enet-main.c b/drivers/net/fs_enet/fs_enet-main.c index af869cf..940e204 100644 --- a/drivers/net/fs_enet/fs_enet-main.c +++ b/drivers/net/fs_enet/fs_enet-main.c @@ -835,7 +835,8 @@ static int fs_enet_close(struct net_device *dev) netif_stop_queue(dev); netif_carrier_off(dev); - napi_disable(&fep->napi); + if (fep->fpi->use_napi) + napi_disable(&fep->napi); phy_stop(fep->phydev); spin_lock_irqsave(&fep->lock, flags); -- cgit v0.10.2 From 3d137fdd16b26be31a653f83d6ce4d3a1ed8701e Mon Sep 17 00:00:00 2001 From: Joakim Tjernlund Date: Fri, 11 Apr 2008 00:54:43 +0200 Subject: ucc_geth: fix non-functional fixed phy support The new Fixed PHY method, fixed-link property, isn't impl. for ucc_geth which makes fixed PHYs non functional. Add support for the new method to restore the Fixed PHY functionality. Signed-off-by: Joakim Tjernlund Signed-off-by: Li Yang Signed-off-by: Jeff Garzik diff --git a/drivers/net/ucc_geth.c b/drivers/net/ucc_geth.c index 8cc3166..0ee4c16 100644 --- a/drivers/net/ucc_geth.c +++ b/drivers/net/ucc_geth.c @@ -3833,6 +3833,7 @@ static int ucc_geth_probe(struct of_device* ofdev, const struct of_device_id *ma struct device_node *phy; int err, ucc_num, max_speed = 0; const phandle *ph; + const u32 *fixed_link; const unsigned int *prop; const char *sprop; const void *mac_addr; @@ -3923,18 +3924,38 @@ static int ucc_geth_probe(struct of_device* ofdev, const struct of_device_id *ma ug_info->uf_info.regs = res.start; ug_info->uf_info.irq = irq_of_parse_and_map(np, 0); + fixed_link = of_get_property(np, "fixed-link", NULL); + if (fixed_link) { + ug_info->mdio_bus = 0; + ug_info->phy_address = fixed_link[0]; + phy = NULL; + } else { + ph = of_get_property(np, "phy-handle", NULL); + phy = of_find_node_by_phandle(*ph); - ph = of_get_property(np, "phy-handle", NULL); - phy = of_find_node_by_phandle(*ph); + if (phy == NULL) + return -ENODEV; - if (phy == NULL) - return -ENODEV; + /* set the PHY address */ + prop = of_get_property(phy, "reg", NULL); + if (prop == NULL) + return -1; + ug_info->phy_address = *prop; + + /* Set the bus id */ + mdio = of_get_parent(phy); + + if (mdio == NULL) + return -1; - /* set the PHY address */ - prop = of_get_property(phy, "reg", NULL); - if (prop == NULL) - return -1; - ug_info->phy_address = *prop; + err = of_address_to_resource(mdio, 0, &res); + of_node_put(mdio); + + if (err) + return -1; + + ug_info->mdio_bus = res.start; + } /* get the phy interface type, or default to MII */ prop = of_get_property(np, "phy-connection-type", NULL); @@ -3979,20 +4000,6 @@ static int ucc_geth_probe(struct of_device* ofdev, const struct of_device_id *ma ug_info->numThreadsRx = UCC_GETH_NUM_OF_THREADS_4; } - /* Set the bus id */ - mdio = of_get_parent(phy); - - if (mdio == NULL) - return -1; - - err = of_address_to_resource(mdio, 0, &res); - of_node_put(mdio); - - if (err) - return -1; - - ug_info->mdio_bus = res.start; - if (netif_msg_probe(&debug)) printk(KERN_INFO "ucc_geth: UCC%1d at 0x%8x (irq = %d) \n", ug_info->uf_info.ucc_num + 1, ug_info->uf_info.regs, -- cgit v0.10.2 From 84b7901f8d5a17536ef2df7fd628ab865df8fe3a Mon Sep 17 00:00:00 2001 From: Atsushi Nemoto Date: Thu, 10 Apr 2008 23:30:07 +0900 Subject: macb: Call phy_disconnect on removing Call phy_disconnect() on remove routine. Otherwise the phy timer causes a kernel crash when unloading. Signed-off-by: Atsushi Nemoto Signed-off-by: Jeff Garzik diff --git a/drivers/net/macb.c b/drivers/net/macb.c index 1d210ed..10fcea5 100644 --- a/drivers/net/macb.c +++ b/drivers/net/macb.c @@ -1257,6 +1257,8 @@ static int __exit macb_remove(struct platform_device *pdev) if (dev) { bp = netdev_priv(dev); + if (bp->phy_dev) + phy_disconnect(bp->phy_dev); mdiobus_unregister(&bp->mii_bus); kfree(bp->mii_bus.irq); unregister_netdev(dev); -- cgit v0.10.2 From 72cfe92266540d8510946921a599f140a3d4aaa8 Mon Sep 17 00:00:00 2001 From: Atsushi Nemoto Date: Sat, 12 Apr 2008 00:58:14 +0900 Subject: macb: Use semicolon instead of comma for statement It seems no good reason to use comma here. Signed-off-by: Atsushi Nemoto Signed-off-by: Jeff Garzik diff --git a/drivers/net/macb.c b/drivers/net/macb.c index 10fcea5..489c7c3 100644 --- a/drivers/net/macb.c +++ b/drivers/net/macb.c @@ -242,12 +242,12 @@ static int macb_mii_init(struct macb *bp) /* Enable managment port */ macb_writel(bp, NCR, MACB_BIT(MPE)); - bp->mii_bus.name = "MACB_mii_bus", - bp->mii_bus.read = &macb_mdio_read, - bp->mii_bus.write = &macb_mdio_write, - bp->mii_bus.reset = &macb_mdio_reset, - bp->mii_bus.id = bp->pdev->id, - bp->mii_bus.priv = bp, + bp->mii_bus.name = "MACB_mii_bus"; + bp->mii_bus.read = &macb_mdio_read; + bp->mii_bus.write = &macb_mdio_write; + bp->mii_bus.reset = &macb_mdio_reset; + bp->mii_bus.id = bp->pdev->id; + bp->mii_bus.priv = bp; bp->mii_bus.dev = &bp->dev->dev; pdata = bp->pdev->dev.platform_data; -- cgit v0.10.2 From a376e79c6079c2ba6c5fadb0e85a3bb7e465ad89 Mon Sep 17 00:00:00 2001 From: Ayaz Abdulla Date: Thu, 10 Apr 2008 21:30:35 -0700 Subject: forcedeth: mac address fix This critical patch fixes a mac address issue recently introduced. If the device's mac address was in correct order and the flag NVREG_TRANSMITPOLL_MAC_ADDR_REV was set, during nv_remove the flag would get cleared. During next load, the mac address would get reversed because the flag is missing. As it has been indicated previously, the flag is cleared across a low power transition. Therefore, the driver should set the mac address back into the reversed order when clearing the flag. Also, the driver should set back the flag after a low power transition to protect against kexec command calling nv_probe a second time. Signed-off-by: Ayaz Abdulla Cc: "Yinghai Lu" Signed-off-by: Andrew Morton Signed-off-by: Jeff Garzik diff --git a/drivers/net/forcedeth.c b/drivers/net/forcedeth.c index 419f533..9f088a4 100644 --- a/drivers/net/forcedeth.c +++ b/drivers/net/forcedeth.c @@ -5316,8 +5316,7 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i /* check the workaround bit for correct mac address order */ txreg = readl(base + NvRegTransmitPoll); - if ((txreg & NVREG_TRANSMITPOLL_MAC_ADDR_REV) || - (id->driver_data & DEV_HAS_CORRECT_MACADDR)) { + if (id->driver_data & DEV_HAS_CORRECT_MACADDR) { /* mac address is already in correct order */ dev->dev_addr[0] = (np->orig_mac[0] >> 0) & 0xff; dev->dev_addr[1] = (np->orig_mac[0] >> 8) & 0xff; @@ -5325,6 +5324,22 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i dev->dev_addr[3] = (np->orig_mac[0] >> 24) & 0xff; dev->dev_addr[4] = (np->orig_mac[1] >> 0) & 0xff; dev->dev_addr[5] = (np->orig_mac[1] >> 8) & 0xff; + } else if (txreg & NVREG_TRANSMITPOLL_MAC_ADDR_REV) { + /* mac address is already in correct order */ + dev->dev_addr[0] = (np->orig_mac[0] >> 0) & 0xff; + dev->dev_addr[1] = (np->orig_mac[0] >> 8) & 0xff; + dev->dev_addr[2] = (np->orig_mac[0] >> 16) & 0xff; + dev->dev_addr[3] = (np->orig_mac[0] >> 24) & 0xff; + dev->dev_addr[4] = (np->orig_mac[1] >> 0) & 0xff; + dev->dev_addr[5] = (np->orig_mac[1] >> 8) & 0xff; + /* + * Set orig mac address back to the reversed version. + * This flag will be cleared during low power transition. + * Therefore, we should always put back the reversed address. + */ + np->orig_mac[0] = (dev->dev_addr[5] << 0) + (dev->dev_addr[4] << 8) + + (dev->dev_addr[3] << 16) + (dev->dev_addr[2] << 24); + np->orig_mac[1] = (dev->dev_addr[1] << 0) + (dev->dev_addr[0] << 8); } else { /* need to reverse mac address to correct order */ dev->dev_addr[0] = (np->orig_mac[1] >> 8) & 0xff; @@ -5595,7 +5610,9 @@ out: static int nv_resume(struct pci_dev *pdev) { struct net_device *dev = pci_get_drvdata(pdev); + u8 __iomem *base = get_hwbase(dev); int rc = 0; + u32 txreg; if (!netif_running(dev)) goto out; @@ -5606,6 +5623,11 @@ static int nv_resume(struct pci_dev *pdev) pci_restore_state(pdev); pci_enable_wake(pdev, PCI_D0, 0); + /* restore mac address reverse flag */ + txreg = readl(base + NvRegTransmitPoll); + txreg |= NVREG_TRANSMITPOLL_MAC_ADDR_REV; + writel(txreg, base + NvRegTransmitPoll); + rc = nv_open(dev); out: return rc; -- cgit v0.10.2 From c500cb265e35c76d741714a61bc635e0f02d64d2 Mon Sep 17 00:00:00 2001 From: Sonic Zhang Date: Thu, 10 Apr 2008 21:30:37 -0700 Subject: smc91x driver: fix bug: print warning only in interrupt mode http://blackfin.uclinux.org/gf/project/uclinux-dist/tracker/?action=TrackerItemEdit&tracker_item_id=3956 Signed-off-by: Sonic Zhang Signed-off-by: Bryan Wu Signed-off-by: Andrew Morton Signed-off-by: Jeff Garzik diff --git a/drivers/net/smc91x.c b/drivers/net/smc91x.c index 4020e9e..63a54e2 100644 --- a/drivers/net/smc91x.c +++ b/drivers/net/smc91x.c @@ -1326,9 +1326,11 @@ static irqreturn_t smc_interrupt(int irq, void *dev_id) SMC_SET_INT_MASK(mask); spin_unlock(&lp->lock); +#ifndef CONFIG_NET_POLL_CONTROLLER if (timeout == MAX_IRQ_LOOPS) PRINTK("%s: spurious interrupt (mask = 0x%02x)\n", dev->name, mask); +#endif DBG(3, "%s: Interrupt done (%d loops)\n", dev->name, MAX_IRQ_LOOPS - timeout); -- cgit v0.10.2 From 5a81f14330ce70bc256b624593768fd1b4170d27 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Thu, 10 Apr 2008 21:30:38 -0700 Subject: sc92031: sysfs link missing Add missing sysfs device association. Compile tested only -ENOHW. Addresses http://bugzilla.kernel.org/show_bug.cgi?id=10380 Signed-off-by: Stephen Hemminger Cc: Cesar Eduardo Barros Cc: Signed-off-by: Andrew Morton Signed-off-by: Jeff Garzik diff --git a/drivers/net/sc92031.c b/drivers/net/sc92031.c index 37b4239..15fcee5 100644 --- a/drivers/net/sc92031.c +++ b/drivers/net/sc92031.c @@ -1446,6 +1446,7 @@ static int __devinit sc92031_probe(struct pci_dev *pdev, } pci_set_drvdata(pdev, dev); + SET_NETDEV_DEV(dev, &pdev->dev); #if SC92031_USE_BAR == 0 dev->mem_start = pci_resource_start(pdev, SC92031_USE_BAR); -- cgit v0.10.2 From 44fb3126d7e6fb411775551b4653643f1d28ebe9 Mon Sep 17 00:00:00 2001 From: Thomas Klein Date: Fri, 4 Apr 2008 15:04:53 +0200 Subject: ehea: Fix DLPAR memory add support This patch fixes two weaknesses in send/receive packet handling which may lead to kernel panics during DLPAR memory add operations. Signed-off-by: Thomas Klein Signed-off-by: Jeff Garzik diff --git a/drivers/net/ehea/ehea.h b/drivers/net/ehea/ehea.h index 93b7fb2..a8d3280 100644 --- a/drivers/net/ehea/ehea.h +++ b/drivers/net/ehea/ehea.h @@ -40,7 +40,7 @@ #include #define DRV_NAME "ehea" -#define DRV_VERSION "EHEA_0089" +#define DRV_VERSION "EHEA_0090" /* eHEA capability flags */ #define DLPAR_PORT_ADD_REM 1 @@ -371,6 +371,7 @@ struct ehea_port_res { struct ehea_q_skb_arr rq2_skba; struct ehea_q_skb_arr rq3_skba; struct ehea_q_skb_arr sq_skba; + int sq_skba_size; spinlock_t netif_queue; int queue_stopped; int swqe_refill_th; diff --git a/drivers/net/ehea/ehea_main.c b/drivers/net/ehea/ehea_main.c index 07c742d..f460b62 100644 --- a/drivers/net/ehea/ehea_main.c +++ b/drivers/net/ehea/ehea_main.c @@ -349,7 +349,8 @@ static void ehea_refill_rq1(struct ehea_port_res *pr, int index, int nr_of_wqes) pr->rq1_skba.os_skbs = 0; if (unlikely(test_bit(__EHEA_STOP_XFER, &ehea_driver_flags))) { - pr->rq1_skba.index = index; + if (nr_of_wqes > 0) + pr->rq1_skba.index = index; pr->rq1_skba.os_skbs = fill_wqes; return; } @@ -1464,7 +1465,9 @@ static int ehea_init_port_res(struct ehea_port *port, struct ehea_port_res *pr, init_attr->act_nr_rwqes_rq2, init_attr->act_nr_rwqes_rq3); - ret = ehea_init_q_skba(&pr->sq_skba, init_attr->act_nr_send_wqes + 1); + pr->sq_skba_size = init_attr->act_nr_send_wqes + 1; + + ret = ehea_init_q_skba(&pr->sq_skba, pr->sq_skba_size); ret |= ehea_init_q_skba(&pr->rq1_skba, init_attr->act_nr_rwqes_rq1 + 1); ret |= ehea_init_q_skba(&pr->rq2_skba, init_attr->act_nr_rwqes_rq2 + 1); ret |= ehea_init_q_skba(&pr->rq3_skba, init_attr->act_nr_rwqes_rq3 + 1); @@ -2621,6 +2624,22 @@ void ehea_purge_sq(struct ehea_qp *orig_qp) } } +void ehea_flush_sq(struct ehea_port *port) +{ + int i; + + for (i = 0; i < port->num_def_qps + port->num_add_tx_qps; i++) { + struct ehea_port_res *pr = &port->port_res[i]; + int swqe_max = pr->sq_skba_size - 2 - pr->swqe_ll_count; + int k = 0; + while (atomic_read(&pr->swqe_avail) < swqe_max) { + msleep(5); + if (++k == 20) + break; + } + } +} + int ehea_stop_qps(struct net_device *dev) { struct ehea_port *port = netdev_priv(dev); @@ -2845,6 +2864,7 @@ static void ehea_rereg_mrs(struct work_struct *work) if (dev->flags & IFF_UP) { down(&port->port_lock); netif_stop_queue(dev); + ehea_flush_sq(port); ret = ehea_stop_qps(dev); if (ret) { up(&port->port_lock); -- cgit v0.10.2 From 16a79142e51f9eedbf3ae9a20d9cdb2f88c86acc Mon Sep 17 00:00:00 2001 From: Krzysztof Halasa Date: Sat, 12 Apr 2008 10:10:40 +0200 Subject: Mark generic HDLC + PPP as broken. PPP support in generic HDLC in Linux 2.6.25 is broken and will cause a kernel panic when a device configured in PPP mode is activated. It will be replaced by new PPP implementation after Linux 2.6.25 is released. This affects only PPP support in generic HDLC (mostly Hitachi SCA and SCA-II based drivers, wanxl, and few others). Standalone syncppp and async PPP support are not affected. Signed-off-by: Krzysztof Halasa Signed-off-by: Jeff Garzik diff --git a/drivers/net/wan/Kconfig b/drivers/net/wan/Kconfig index a3df09e..8005dd1 100644 --- a/drivers/net/wan/Kconfig +++ b/drivers/net/wan/Kconfig @@ -150,9 +150,13 @@ config HDLC_FR config HDLC_PPP tristate "Synchronous Point-to-Point Protocol (PPP) support" - depends on HDLC + depends on HDLC && BROKEN help Generic HDLC driver supporting PPP over WAN connections. + This module is currently broken and will cause a kernel panic + when a device configured in PPP mode is activated. + + It will be replaced by new PPP implementation in Linux 2.6.26. If unsure, say N. -- cgit v0.10.2 From 2de58e30db3f7e83592e22fb459dd6695b648889 Mon Sep 17 00:00:00 2001 From: Sergei Shtylyov Date: Sat, 12 Apr 2008 18:30:58 -0700 Subject: tg3: fix MMIO for PPC 44x platforms The driver stores the PCI resource addresses into 'unsigned long' variable before calling ioremap_nocache() on them. This warrants kernel oops when the registers are accessed on PPC 44x platforms which (being 32-bit) have PCI memory space mapped beyond 4 GB. The arch/ppc/ kernel has a fixup in ioremap() that creates an illusion that the PCI memory resource is mapped below 4 GB, but arch/powerpc/ code got rid of this trick, having instead CONFIG_RESOURCES_64BIT enabled. [ Bump driver version and release date -DaveM ] Signed-off-by: Sergei Shtylyov Signed-off-by: David S. Miller diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index d4655b2..96043c5 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -64,8 +64,8 @@ #define DRV_MODULE_NAME "tg3" #define PFX DRV_MODULE_NAME ": " -#define DRV_MODULE_VERSION "3.89" -#define DRV_MODULE_RELDATE "April 03, 2008" +#define DRV_MODULE_VERSION "3.90" +#define DRV_MODULE_RELDATE "April 12, 2008" #define TG3_DEF_MAC_MODE 0 #define TG3_DEF_RX_MODE 0 @@ -12578,7 +12578,8 @@ static int __devinit tg3_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) { static int tg3_version_printed = 0; - unsigned long tg3reg_base, tg3reg_len; + resource_size_t tg3reg_base; + unsigned long tg3reg_len; struct net_device *dev; struct tg3 *tp; int err, pm_cap; -- cgit v0.10.2 From ae1b6a31b1f9ef2c7ba5ef89799f210a9ba6937c Mon Sep 17 00:00:00 2001 From: Pavel Emelyanov Date: Sat, 12 Apr 2008 18:33:50 -0700 Subject: [AX25]: Potential ax25_uid_assoc-s leaks on module unload. The ax25_uid_free call walks the ax25_uid_list and releases entries from it. The problem is that after the fisrt call to hlist_del_init the hlist_for_each_entry (which hides behind the ax25_uid_for_each) will consider the current position to be the last and will return. Thus, the whole list will be left not freed. Signed-off-by: Pavel Emelyanov Signed-off-by: David S. Miller diff --git a/net/ax25/ax25_uid.c b/net/ax25/ax25_uid.c index 5f4eb73..57aeba7 100644 --- a/net/ax25/ax25_uid.c +++ b/net/ax25/ax25_uid.c @@ -218,9 +218,11 @@ void __exit ax25_uid_free(void) struct hlist_node *node; write_lock(&ax25_uid_lock); +again: ax25_uid_for_each(ax25_uid, node, &ax25_uid_list) { hlist_del_init(&ax25_uid->uid_node); ax25_uid_put(ax25_uid); + goto again; } write_unlock(&ax25_uid_lock); } -- cgit v0.10.2 From 028b027524b162eef90839a92ba4b8bddf23e06c Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Sat, 12 Apr 2008 18:35:41 -0700 Subject: [DCCP]: Fix skb->cb conflicts with IP dev_queue_xmit() and the other IP output functions expect to get a skb with clear or properly initialized skb->cb. Unlike TCP and UDP, the dccp_skb_cb doesn't contain a struct inet_skb_parm at the beginning, so the DCCP-specific data is interpreted by the IP output functions. This can cause false negatives for the conditional POST_ROUTING hook invocation, making the packet bypass the hook. Add a inet_skb_parm/inet6_skb_parm union to the beginning of dccp_skb_cb to avoid clashes. Also add a BUILD_BUG_ON to make sure it fits in the cb. [ Combined with patch from Gerrit Renker to remove two now unnecessary memsets of IPCB(skb)->opt ] Signed-off-by: Patrick McHardy Acked-by: Arnaldo Carvalho de Melo Signed-off-by: David S. Miller diff --git a/net/dccp/dccp.h b/net/dccp/dccp.h index 287a62b..ba2ef94 100644 --- a/net/dccp/dccp.h +++ b/net/dccp/dccp.h @@ -325,6 +325,12 @@ static inline int dccp_bad_service_code(const struct sock *sk, * This is used for transmission as well as for reception. */ struct dccp_skb_cb { + union { + struct inet_skb_parm h4; +#if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE) + struct inet6_skb_parm h6; +#endif + } header; __u8 dccpd_type:4; __u8 dccpd_ccval:4; __u8 dccpd_reset_code, diff --git a/net/dccp/ipv4.c b/net/dccp/ipv4.c index 474075a..b337044 100644 --- a/net/dccp/ipv4.c +++ b/net/dccp/ipv4.c @@ -489,7 +489,6 @@ static int dccp_v4_send_response(struct sock *sk, struct request_sock *req, dh->dccph_checksum = dccp_v4_csum_finish(skb, ireq->loc_addr, ireq->rmt_addr); - memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt)); err = ip_build_and_send_pkt(skb, sk, ireq->loc_addr, ireq->rmt_addr, ireq->opt); diff --git a/net/dccp/output.c b/net/dccp/output.c index 3b763db..3d7d628d 100644 --- a/net/dccp/output.c +++ b/net/dccp/output.c @@ -126,7 +126,6 @@ static int dccp_transmit_skb(struct sock *sk, struct sk_buff *skb) DCCP_INC_STATS(DCCP_MIB_OUTSEGS); - memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt)); err = icsk->icsk_af_ops->queue_xmit(skb, 0); return net_xmit_eval(err); } diff --git a/net/dccp/proto.c b/net/dccp/proto.c index e3f5d37..c91d3c1 100644 --- a/net/dccp/proto.c +++ b/net/dccp/proto.c @@ -1057,6 +1057,9 @@ static int __init dccp_init(void) int ehash_order, bhash_order, i; int rc = -ENOBUFS; + BUILD_BUG_ON(sizeof(struct dccp_skb_cb) > + FIELD_SIZEOF(struct sk_buff, cb)); + dccp_hashinfo.bind_bucket_cachep = kmem_cache_create("dccp_bind_bucket", sizeof(struct inet_bind_bucket), 0, -- cgit v0.10.2 From e56cfad132f2ae269082359d279c17230c987e74 Mon Sep 17 00:00:00 2001 From: Jarek Poplawski Date: Sat, 12 Apr 2008 18:37:13 -0700 Subject: [NET_SCHED] cls_u32: refcounting fix for u32_delete() Deleting of nonroot hnodes mostly doesn't work in u32_delete(): refcnt == 1 is expected, but such hnodes' refcnts are initialized with 0 and charged only with "link" nodes. Now they'll start with 1 like usual. Thanks to Patrick McHardy for an improving suggestion. Signed-off-by: Jarek Poplawski Acked-by: Jamal Hadi Salim Signed-off-by: David S. Miller diff --git a/net/sched/cls_u32.c b/net/sched/cls_u32.c index c5c16b4..4d75544 100644 --- a/net/sched/cls_u32.c +++ b/net/sched/cls_u32.c @@ -411,8 +411,10 @@ static void u32_destroy(struct tcf_proto *tp) } } - for (ht=tp_c->hlist; ht; ht = ht->next) + for (ht = tp_c->hlist; ht; ht = ht->next) { + ht->refcnt--; u32_clear_hnode(tp, ht); + } while ((ht = tp_c->hlist) != NULL) { tp_c->hlist = ht->next; @@ -441,8 +443,12 @@ static int u32_delete(struct tcf_proto *tp, unsigned long arg) if (tp->root == ht) return -EINVAL; - if (--ht->refcnt == 0) + if (ht->refcnt == 1) { + ht->refcnt--; u32_destroy_hnode(tp, ht); + } else { + return -EBUSY; + } return 0; } @@ -568,7 +574,7 @@ static int u32_change(struct tcf_proto *tp, unsigned long base, u32 handle, if (ht == NULL) return -ENOBUFS; ht->tp_c = tp_c; - ht->refcnt = 0; + ht->refcnt = 1; ht->divisor = divisor; ht->handle = handle; ht->prio = tp->prio; -- cgit v0.10.2 From 72da7b3860cabf427590b4982bc880bafab4d5c8 Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Sat, 12 Apr 2008 18:39:19 -0700 Subject: [SCTP]: Add check for hmac_algo parameter in sctp_verify_param() RFC 4890 has the following text: The HMAC algorithm based on SHA-1 MUST be supported and included in the HMAC-ALGO parameter. As a result, we need to check in sctp_verify_param() that HMAC_SHA1 is present in the list. If not, we should probably treat this as a protocol violation. It should also be a protocol violation if the HMAC parameter is empty. Signed-off-by: Wei Yongjun Signed-off-by: Vlad Yasevich Signed-off-by: David S. Miller diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c index 578630e..36ebb39 100644 --- a/net/sctp/sm_make_chunk.c +++ b/net/sctp/sm_make_chunk.c @@ -1982,7 +1982,10 @@ static sctp_ierror_t sctp_verify_param(const struct sctp_association *asoc, struct sctp_chunk *chunk, struct sctp_chunk **err_chunk) { + struct sctp_hmac_algo_param *hmacs; int retval = SCTP_IERROR_NO_ERROR; + __u16 n_elt, id = 0; + int i; /* FIXME - This routine is not looking at each parameter per the * chunk type, i.e., unrecognized parameters should be further @@ -2056,9 +2059,29 @@ static sctp_ierror_t sctp_verify_param(const struct sctp_association *asoc, break; case SCTP_PARAM_HMAC_ALGO: - if (sctp_auth_enable) - break; - /* Fall Through */ + if (!sctp_auth_enable) + goto fallthrough; + + hmacs = (struct sctp_hmac_algo_param *)param.p; + n_elt = (ntohs(param.p->length) - sizeof(sctp_paramhdr_t)) >> 1; + + /* SCTP-AUTH: Section 6.1 + * The HMAC algorithm based on SHA-1 MUST be supported and + * included in the HMAC-ALGO parameter. + */ + for (i = 0; i < n_elt; i++) { + id = ntohs(hmacs->hmac_ids[i]); + + if (id == SCTP_AUTH_HMAC_ID_SHA1) + break; + } + + if (id != SCTP_AUTH_HMAC_ID_SHA1) { + sctp_process_inv_paramlength(asoc, param.p, chunk, + err_chunk); + retval = SCTP_IERROR_ABORT; + } + break; fallthrough: default: SCTP_DEBUG_PRINTK("Unrecognized param: %d for chunk %d.\n", -- cgit v0.10.2 From f4ad85ca3ef8a1ede76c5020a28a8f4057b4d24f Mon Sep 17 00:00:00 2001 From: Gui Jianfeng Date: Sat, 12 Apr 2008 18:39:34 -0700 Subject: [SCTP]: Fix protocol violation when receiving an error lenght INIT-ACK When receiving an error length INIT-ACK during COOKIE-WAIT, a 0-vtag ABORT will be responsed. This action violates the protocol apparently. This patch achieves the following things. 1 If the INIT-ACK contains all the fixed parameters, use init-tag recorded from INIT-ACK as vtag. 2 If the INIT-ACK doesn't contain all the fixed parameters, just reflect its vtag. Signed-off-by: Gui Jianfeng Signed-off-by: Vlad Yasevich Signed-off-by: David S. Miller diff --git a/include/net/sctp/command.h b/include/net/sctp/command.h index 10ae2da..35b1e83 100644 --- a/include/net/sctp/command.h +++ b/include/net/sctp/command.h @@ -104,6 +104,7 @@ typedef enum { SCTP_CMD_ADAPTATION_IND, /* generate and send adaptation event */ SCTP_CMD_ASSOC_SHKEY, /* generate the association shared keys */ SCTP_CMD_T1_RETRAN, /* Mark for retransmission after T1 timeout */ + SCTP_CMD_UPDATE_INITTAG, /* Update peer inittag */ SCTP_CMD_LAST } sctp_verb_t; diff --git a/net/sctp/outqueue.c b/net/sctp/outqueue.c index 1bb3c5c..c071446 100644 --- a/net/sctp/outqueue.c +++ b/net/sctp/outqueue.c @@ -793,6 +793,9 @@ int sctp_outq_flush(struct sctp_outq *q, int rtx_timeout) break; case SCTP_CID_ABORT: + if (sctp_test_T_bit(chunk)) { + packet->vtag = asoc->c.my_vtag; + } case SCTP_CID_SACK: case SCTP_CID_HEARTBEAT: case SCTP_CID_HEARTBEAT_ACK: diff --git a/net/sctp/sm_sideeffect.c b/net/sctp/sm_sideeffect.c index 28eb38e..a4763fd 100644 --- a/net/sctp/sm_sideeffect.c +++ b/net/sctp/sm_sideeffect.c @@ -1536,6 +1536,9 @@ static int sctp_cmd_interpreter(sctp_event_t event_type, error = sctp_auth_asoc_init_active_key(asoc, GFP_ATOMIC); break; + case SCTP_CMD_UPDATE_INITTAG: + asoc->peer.i.init_tag = cmd->obj.u32; + break; default: printk(KERN_WARNING "Impossible command: %u, %p\n", diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c index f2ed647..3ef9749 100644 --- a/net/sctp/sm_statefuns.c +++ b/net/sctp/sm_statefuns.c @@ -4144,6 +4144,24 @@ static sctp_disposition_t sctp_sf_abort_violation( goto nomem; if (asoc) { + /* Treat INIT-ACK as a special case during COOKIE-WAIT. */ + if (chunk->chunk_hdr->type == SCTP_CID_INIT_ACK && + !asoc->peer.i.init_tag) { + sctp_initack_chunk_t *initack; + + initack = (sctp_initack_chunk_t *)chunk->chunk_hdr; + if (!sctp_chunk_length_valid(chunk, + sizeof(sctp_initack_chunk_t))) + abort->chunk_hdr->flags |= SCTP_CHUNK_FLAG_T; + else { + unsigned int inittag; + + inittag = ntohl(initack->init_hdr.init_tag); + sctp_add_cmd_sf(commands, SCTP_CMD_UPDATE_INITTAG, + SCTP_U32(inittag)); + } + } + sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(abort)); SCTP_INC_STATS(SCTP_MIB_OUTCTRLCHUNKS); -- cgit v0.10.2 From ab38fb04c9f8928cfaf6f4966633d783419906a1 Mon Sep 17 00:00:00 2001 From: Vlad Yasevich Date: Sat, 12 Apr 2008 18:40:06 -0700 Subject: [SCTP]: Fix compiler warning about const qualifiers Fix 3 warnings about discarding const qualifiers: net/sctp/ulpevent.c:862: warning: passing argument 1 of 'sctp_event2skb' discards qualifiers from pointer target type net/sctp/sm_statefuns.c:4393: warning: passing argument 1 of 'SCTP_ASOC' discards qualifiers from pointer target type net/sctp/socket.c:5874: warning: passing argument 1 of 'cmsg_nxthdr' discards qualifiers from pointer target type Signed-off-by: Vlad Yasevich Signed-off-by: David S. Miller diff --git a/include/net/sctp/ulpevent.h b/include/net/sctp/ulpevent.h index 9bcfc12..7ea12e8 100644 --- a/include/net/sctp/ulpevent.h +++ b/include/net/sctp/ulpevent.h @@ -67,7 +67,7 @@ struct sctp_ulpevent { }; /* Retrieve the skb this event sits inside of. */ -static inline struct sk_buff *sctp_event2skb(struct sctp_ulpevent *ev) +static inline struct sk_buff *sctp_event2skb(const struct sctp_ulpevent *ev) { return container_of((void *)ev, struct sk_buff, cb); } diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c index 3ef9749..07194c2 100644 --- a/net/sctp/sm_statefuns.c +++ b/net/sctp/sm_statefuns.c @@ -4367,6 +4367,7 @@ sctp_disposition_t sctp_sf_do_prm_asoc(const struct sctp_endpoint *ep, sctp_cmd_seq_t *commands) { struct sctp_chunk *repl; + struct sctp_association* my_asoc; /* The comment below says that we enter COOKIE-WAIT AFTER * sending the INIT, but that doesn't actually work in our @@ -4390,8 +4391,8 @@ sctp_disposition_t sctp_sf_do_prm_asoc(const struct sctp_endpoint *ep, /* Cast away the const modifier, as we want to just * rerun it through as a sideffect. */ - sctp_add_cmd_sf(commands, SCTP_CMD_NEW_ASOC, - SCTP_ASOC((struct sctp_association *) asoc)); + my_asoc = (struct sctp_association *)asoc; + sctp_add_cmd_sf(commands, SCTP_CMD_NEW_ASOC, SCTP_ASOC(my_asoc)); /* Choose transport for INIT. */ sctp_add_cmd_sf(commands, SCTP_CMD_INIT_CHOOSE_TRANSPORT, diff --git a/net/sctp/socket.c b/net/sctp/socket.c index d994d82..998e63a 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c @@ -5868,11 +5868,12 @@ SCTP_STATIC int sctp_msghdr_parse(const struct msghdr *msg, sctp_cmsgs_t *cmsgs) { struct cmsghdr *cmsg; + struct msghdr *my_msg = (struct msghdr *)msg; for (cmsg = CMSG_FIRSTHDR(msg); cmsg != NULL; - cmsg = CMSG_NXTHDR((struct msghdr*)msg, cmsg)) { - if (!CMSG_OK(msg, cmsg)) + cmsg = CMSG_NXTHDR(my_msg, cmsg)) { + if (!CMSG_OK(my_msg, cmsg)) return -EINVAL; /* Should we parse this header or ignore? */ diff --git a/net/sctp/ulpevent.c b/net/sctp/ulpevent.c index b43f1f1..ce6cda6 100644 --- a/net/sctp/ulpevent.c +++ b/net/sctp/ulpevent.c @@ -859,7 +859,7 @@ __u16 sctp_ulpevent_get_notification_type(const struct sctp_ulpevent *event) union sctp_notification *notification; struct sk_buff *skb; - skb = sctp_event2skb((struct sctp_ulpevent *)event); + skb = sctp_event2skb(event); notification = (union sctp_notification *) skb->data; return notification->sn_header.sn_type; } -- cgit v0.10.2 From a40a7d15ba602b547f56b7b19e0282fe4fc3dee3 Mon Sep 17 00:00:00 2001 From: Pavel Emelyanov Date: Sat, 12 Apr 2008 18:40:38 -0700 Subject: [SCTP]: IPv4 vs IPv6 addresses mess in sctp_inet[6]addr_event. All IP addresses that are present in a system are duplicated on struct sctp_sockaddr_entry. They are linked in the global list called sctp_local_addr_list. And this struct unions IPv4 and IPv6 addresses. So, there can be rare case, when a sockaddr_in.sin_addr coincides with the corresponding part of the sockaddr_in6 and the notifier for IPv4 will carry away an IPv6 entry. The fix is to check the family before comparing the addresses. Signed-off-by: Pavel Emelyanov Signed-off-by: Vlad Yasevich Signed-off-by: David S. Miller diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c index b1e05d7..85f1495 100644 --- a/net/sctp/ipv6.c +++ b/net/sctp/ipv6.c @@ -110,8 +110,9 @@ static int sctp_inet6addr_event(struct notifier_block *this, unsigned long ev, spin_lock_bh(&sctp_local_addr_lock); list_for_each_entry_safe(addr, temp, &sctp_local_addr_list, list) { - if (ipv6_addr_equal(&addr->a.v6.sin6_addr, - &ifa->addr)) { + if (addr->a.sa.sa_family == AF_INET6 && + ipv6_addr_equal(&addr->a.v6.sin6_addr, + &ifa->addr)) { found = 1; addr->valid = 0; list_del_rcu(&addr->list); diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c index f90091a..c2dd65d 100644 --- a/net/sctp/protocol.c +++ b/net/sctp/protocol.c @@ -647,7 +647,9 @@ static int sctp_inetaddr_event(struct notifier_block *this, unsigned long ev, spin_lock_bh(&sctp_local_addr_lock); list_for_each_entry_safe(addr, temp, &sctp_local_addr_list, list) { - if (addr->a.v4.sin_addr.s_addr == ifa->ifa_local) { + if (addr->a.sa.sa_family == AF_INET && + addr->a.v4.sin_addr.s_addr == + ifa->ifa_local) { found = 1; addr->valid = 0; list_del_rcu(&addr->list); -- cgit v0.10.2 From 14daa02139dcb3193b2b0250c0720a23ef610c49 Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Sat, 12 Apr 2008 18:48:58 -0700 Subject: net: make struct tun_struct private to tun.c There's no reason for this to be in the header, and it just hurts recompile time. Signed-off-by: Rusty Russell Acked-by: Max Krasnyanskiy Signed-off-by: David S. Miller diff --git a/drivers/net/tun.c b/drivers/net/tun.c index 7b816a0..970ec47 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c @@ -67,9 +67,42 @@ #include #include +/* Uncomment to enable debugging */ +/* #define TUN_DEBUG 1 */ + #ifdef TUN_DEBUG static int debug; + +#define DBG if(tun->debug)printk +#define DBG1 if(debug==2)printk +#else +#define DBG( a... ) +#define DBG1( a... ) +#endif + +struct tun_struct { + struct list_head list; + unsigned long flags; + int attached; + uid_t owner; + gid_t group; + + wait_queue_head_t read_wait; + struct sk_buff_head readq; + + struct net_device *dev; + + struct fasync_struct *fasync; + + unsigned long if_flags; + u8 dev_addr[ETH_ALEN]; + u32 chr_filter[2]; + u32 net_filter[2]; + +#ifdef TUN_DEBUG + int debug; #endif +}; /* Network device part of the driver */ diff --git a/include/linux/Kbuild b/include/linux/Kbuild index 9cdd12a..cedbbd8 100644 --- a/include/linux/Kbuild +++ b/include/linux/Kbuild @@ -86,6 +86,7 @@ header-y += if_plip.h header-y += if_ppp.h header-y += if_slip.h header-y += if_strip.h +header-y += if_tun.h header-y += if_tunnel.h header-y += in6.h header-y += in_route.h @@ -229,7 +230,6 @@ unifdef-y += if_link.h unifdef-y += if_pppol2tp.h unifdef-y += if_pppox.h unifdef-y += if_tr.h -unifdef-y += if_tun.h unifdef-y += if_vlan.h unifdef-y += if_wanpipe.h unifdef-y += igmp.h diff --git a/include/linux/if_tun.h b/include/linux/if_tun.h index 72f1c5f..8c71fe2 100644 --- a/include/linux/if_tun.h +++ b/include/linux/if_tun.h @@ -18,47 +18,8 @@ #ifndef __IF_TUN_H #define __IF_TUN_H -/* Uncomment to enable debugging */ -/* #define TUN_DEBUG 1 */ - #include -#ifdef __KERNEL__ - -#ifdef TUN_DEBUG -#define DBG if(tun->debug)printk -#define DBG1 if(debug==2)printk -#else -#define DBG( a... ) -#define DBG1( a... ) -#endif - -struct tun_struct { - struct list_head list; - unsigned long flags; - int attached; - uid_t owner; - gid_t group; - - wait_queue_head_t read_wait; - struct sk_buff_head readq; - - struct net_device *dev; - - struct fasync_struct *fasync; - - unsigned long if_flags; - u8 dev_addr[ETH_ALEN]; - u32 chr_filter[2]; - u32 net_filter[2]; - -#ifdef TUN_DEBUG - int debug; -#endif -}; - -#endif /* __KERNEL__ */ - /* Read queue size */ #define TUN_READQ_SIZE 500 -- cgit v0.10.2 From e01bf1c83332c4653ffd30eed20a94a9c83d82b2 Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Sat, 12 Apr 2008 18:49:30 -0700 Subject: net: check for underlength tap writes If the user gives a packet under 14 bytes, we'll end up reading off the end of the skb (not oopsing, just reading off the end). Signed-off-by: Rusty Russell Acked-by: Max Krasnyanskiy Signed-off-by: David S. Miller diff --git a/drivers/net/tun.c b/drivers/net/tun.c index 970ec47..5b5d875 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c @@ -286,8 +286,11 @@ static __inline__ ssize_t tun_get_user(struct tun_struct *tun, struct iovec *iv, return -EFAULT; } - if ((tun->flags & TUN_TYPE_MASK) == TUN_TAP_DEV) + if ((tun->flags & TUN_TYPE_MASK) == TUN_TAP_DEV) { align = NET_IP_ALIGN; + if (unlikely(len < ETH_HLEN)) + return -EINVAL; + } if (!(skb = alloc_skb(len + align, GFP_KERNEL))) { tun->dev->stats.rx_dropped++; -- cgit v0.10.2 From f37f0afb2916ccf287428983026261db78c7661a Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Sun, 13 Apr 2008 21:39:26 -0700 Subject: [SOCK] sk_stamp: should be initialized to ktime_set(-1L, 0) Problem spotted by Andrew Brampton Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller diff --git a/net/core/sock.c b/net/core/sock.c index 2654c14..7a0567b 100644 --- a/net/core/sock.c +++ b/net/core/sock.c @@ -1725,7 +1725,7 @@ void sock_init_data(struct socket *sock, struct sock *sk) sk->sk_rcvtimeo = MAX_SCHEDULE_TIMEOUT; sk->sk_sndtimeo = MAX_SCHEDULE_TIMEOUT; - sk->sk_stamp = ktime_set(-1L, -1L); + sk->sk_stamp = ktime_set(-1L, 0); atomic_set(&sk->sk_refcnt, 1); atomic_set(&sk->sk_drops, 0); -- cgit v0.10.2 From 4c821d753d5c097babd6609bcd85f08e254a3505 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Sun, 13 Apr 2008 21:52:48 -0700 Subject: [NET]: Fix kernel-doc for skb_segment The kernel-doc comment for skb_segment is clearly wrong. This states what it actually does. Signed-off-by: Ben Hutchings Signed-off-by: David S. Miller diff --git a/net/core/skbuff.c b/net/core/skbuff.c index 0d0fd28..6087013 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c @@ -2131,8 +2131,8 @@ EXPORT_SYMBOL_GPL(skb_pull_rcsum); * @features: features for the output path (see dev->features) * * This function performs segmentation on the given skb. It returns - * the segment at the given position. It returns NULL if there are - * no more segments to generate, or when an error is encountered. + * a pointer to the first in a list of new skbs for the segments. + * In case of error it returns ERR_PTR(err). */ struct sk_buff *skb_segment(struct sk_buff *skb, int features) { -- cgit v0.10.2 From d2dcba612b357a4687843ad4f46629d219233fd7 Mon Sep 17 00:00:00 2001 From: Paul Bolle Date: Sun, 13 Apr 2008 22:44:20 -0700 Subject: [ISDN]: Do not validate ISDN net device address prior to interface-up Commit bada339 (Validate device addr prior to interface-up) caused a regression in the ISDN network code, see: http://bugzilla.kernel.org/show_bug.cgi?id=9923 The trivial fix is to remove the pointer to eth_validate_addr() in the net_device struct in isdn_net_init(). Signed-off-by: Paul Bolle Signed-off-by: David S. Miller diff --git a/drivers/isdn/i4l/isdn_net.c b/drivers/isdn/i4l/isdn_net.c index ced83c2..ef1a300 100644 --- a/drivers/isdn/i4l/isdn_net.c +++ b/drivers/isdn/i4l/isdn_net.c @@ -2010,6 +2010,7 @@ isdn_net_init(struct net_device *ndev) ndev->flags = IFF_NOARP|IFF_POINTOPOINT; ndev->type = ARPHRD_ETHER; ndev->addr_len = ETH_ALEN; + ndev->validate_addr = NULL; /* for clients with MPPP maybe higher values better */ ndev->tx_queue_len = 30; -- cgit v0.10.2 From 2ed9926e16094ad143b96b09c64cba8bcba05ee1 Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Sun, 13 Apr 2008 22:45:40 -0700 Subject: [NET]: Return more appropriate error from eth_validate_addr(). Paul Bolle wrote: > http://bugzilla.kernel.org/show_bug.cgi?id=9923 would have been much easier to > track down if eth_validate_addr() would somehow complain aloud if an address > is invalid. Shouldn't it make at least some noise? I guess it should return -EADDRNOTAVAIL similar to eth_mac_addr() when validation fails. Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller diff --git a/net/ethernet/eth.c b/net/ethernet/eth.c index a7b4175..a80839b 100644 --- a/net/ethernet/eth.c +++ b/net/ethernet/eth.c @@ -301,7 +301,7 @@ static int eth_change_mtu(struct net_device *dev, int new_mtu) static int eth_validate_addr(struct net_device *dev) { if (!is_valid_ether_addr(dev->dev_addr)) - return -EINVAL; + return -EADDRNOTAVAIL; return 0; } -- cgit v0.10.2 From b45e9189c058bfa495073951ff461ee0eea968be Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Sun, 13 Apr 2008 23:14:15 -0700 Subject: [IPV6]: Fix ipv6 address fetching in raw6_icmp_error(). Fixes kernel bugzilla 10437 Based almost entirely upon a patch by Dmitry Butskoy. When deciding what raw sockets to deliver the ICMPv6 to, we should use the addresses in the ICMPv6 quoted IPV6 header, not the top-level one. Signed-off-by: David S. Miller diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c index 8897ccf..0a6fbc1 100644 --- a/net/ipv6/raw.c +++ b/net/ipv6/raw.c @@ -372,8 +372,10 @@ void raw6_icmp_error(struct sk_buff *skb, int nexthdr, read_lock(&raw_v6_hashinfo.lock); sk = sk_head(&raw_v6_hashinfo.ht[hash]); if (sk != NULL) { - saddr = &ipv6_hdr(skb)->saddr; - daddr = &ipv6_hdr(skb)->daddr; + struct ipv6hdr *hdr = (struct ipv6hdr *) skb->data; + + saddr = &hdr->saddr; + daddr = &hdr->daddr; net = skb->dev->nd_net; while ((sk = __raw_v6_lookup(net, sk, nexthdr, saddr, daddr, -- cgit v0.10.2 From 7cd636fe9ce5de0051c11283911baca4291868c8 Mon Sep 17 00:00:00 2001 From: YOSHIFUJI Hideaki Date: Sun, 13 Apr 2008 23:33:52 -0700 Subject: [IPV6]: IPv6 extension header structures need to be packed. struct ipv6_opt_hdr is the common structure for IPv6 extension headers, and it is common to increment the pointer to get the real content. On the other hand, since the structure consists only of 1-byte next-header field and 1-byte length field, size of that structure depends on architecture; 2 or 4. Add "packed" attribute to get 2. Signed-off-by: YOSHIFUJI Hideaki Signed-off-by: David S. Miller diff --git a/include/linux/ipv6.h b/include/linux/ipv6.h index 4aaefc3..134c8e5 100644 --- a/include/linux/ipv6.h +++ b/include/linux/ipv6.h @@ -53,7 +53,7 @@ struct ipv6_opt_hdr { /* * TLV encoded option data follows. */ -}; +} __attribute__ ((packed)); /* required for some archs */ #define ipv6_destopt_hdr ipv6_opt_hdr #define ipv6_hopopt_hdr ipv6_opt_hdr -- cgit v0.10.2 From e9df2e8fd8fbc95c57dbd1d33dada66c4627b44c Mon Sep 17 00:00:00 2001 From: YOSHIFUJI Hideaki Date: Sun, 13 Apr 2008 23:40:51 -0700 Subject: [IPV6]: Use appropriate sock tclass setting for routing lookup. Signed-off-by: YOSHIFUJI Hideaki Signed-off-by: David S. Miller diff --git a/include/net/inet_ecn.h b/include/net/inet_ecn.h index ba33db0..7040a78 100644 --- a/include/net/inet_ecn.h +++ b/include/net/inet_ecn.h @@ -47,7 +47,7 @@ static inline __u8 INET_ECN_encapsulate(__u8 outer, __u8 inner) } while (0) #define IP6_ECN_flow_xmit(sk, label) do { \ - if (INET_ECN_is_capable(inet_sk(sk)->tos)) \ + if (INET_ECN_is_capable(inet6_sk(sk)->tclass)) \ (label) |= htonl(INET_ECN_ECT_0 << 20); \ } while (0) -- cgit v0.10.2 From b077d7ababdb5433aef18c62bf1f785e8729f49a Mon Sep 17 00:00:00 2001 From: YOSHIFUJI Hideaki Date: Sun, 13 Apr 2008 23:42:18 -0700 Subject: [IPV6] ADDRCONF: Ensure disabling multicast RS even if privacy extensions are disabled. Signed-off-by: YOSHIFUJI Hideaki Signed-off-by: David S. Miller diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index a65935a..b9eeb4f 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c @@ -371,6 +371,15 @@ static struct inet6_dev * ipv6_add_dev(struct net_device *dev) */ in6_dev_hold(ndev); +#if defined(CONFIG_IPV6_SIT) || defined(CONFIG_IPV6_SIT_MODULE) + if (dev->type == ARPHRD_SIT && (dev->priv_flags & IFF_ISATAP)) { + printk(KERN_INFO + "%s: Disabled Multicast RS\n", + dev->name); + ndev->cnf.rtr_solicits = 0; + } +#endif + #ifdef CONFIG_IPV6_PRIVACY setup_timer(&ndev->regen_timer, ipv6_regen_rndid, (unsigned long)ndev); if ((dev->flags&IFF_LOOPBACK) || @@ -383,13 +392,6 @@ static struct inet6_dev * ipv6_add_dev(struct net_device *dev) "%s: Disabled Privacy Extensions\n", dev->name); ndev->cnf.use_tempaddr = -1; - - if (dev->type == ARPHRD_SIT && (dev->priv_flags & IFF_ISATAP)) { - printk(KERN_INFO - "%s: Disabled Multicast RS\n", - dev->name); - ndev->cnf.rtr_solicits = 0; - } } else { in6_dev_hold(ndev); ipv6_regen_rndid((unsigned long) ndev); -- cgit v0.10.2 From 9625ed72e8bd619c3984f3024bd37143b7f0c7b0 Mon Sep 17 00:00:00 2001 From: YOSHIFUJI Hideaki Date: Sun, 13 Apr 2008 23:47:11 -0700 Subject: [IPV6] ADDRCONF: Don't generate temporary address for ip6-ip6 interface. As far as I can remember, I was going to disable privacy extensions on all "tunnel" interfaces. Disable it on ip6-ip6 interface as well. Also, just remove ifdefs for SIT for simplicity. Signed-off-by: YOSHIFUJI Hideaki Signed-off-by: David S. Miller diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index b9eeb4f..e08955b 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c @@ -384,9 +384,8 @@ static struct inet6_dev * ipv6_add_dev(struct net_device *dev) setup_timer(&ndev->regen_timer, ipv6_regen_rndid, (unsigned long)ndev); if ((dev->flags&IFF_LOOPBACK) || dev->type == ARPHRD_TUNNEL || -#if defined(CONFIG_IPV6_SIT) || defined(CONFIG_IPV6_SIT_MODULE) + dev->type == ARPHRD_TUNNEL6 || dev->type == ARPHRD_SIT || -#endif dev->type == ARPHRD_NONE) { printk(KERN_INFO "%s: Disabled Privacy Extensions\n", -- cgit v0.10.2 From 4dee959723e2bf3a0f9343a46841cd2f0029d424 Mon Sep 17 00:00:00 2001 From: Pavel Emelyanov Date: Mon, 14 Apr 2008 00:44:52 -0700 Subject: [NETFILTER]: ipt_CLUSTERIP: fix race between clusterip_config_find_get and _entry_put Consider we are putting a clusterip_config entry with the "entries" count == 1, and on the other CPU there's a clusterip_config_find_get in progress: CPU1: CPU2: clusterip_config_entry_put: clusterip_config_find_get: if (atomic_dec_and_test(&c->entries)) { /* true */ read_lock_bh(&clusterip_lock); c = __clusterip_config_find(clusterip); /* found - it's still in list */ ... atomic_inc(&c->entries); read_unlock_bh(&clusterip_lock); write_lock_bh(&clusterip_lock); list_del(&c->list); write_unlock_bh(&clusterip_lock); ... dev_put(c->dev); Oops! We have an entry returned by the clusterip_config_find_get, which is a) not in list b) has a stale dev pointer. The problems will happen when the CPU2 will release the entry - it will remove it from the list for the 2nd time, thus spoiling it, and will put a stale dev pointer. The fix is to make atomic_dec_and_test under the clusterip_lock. Signed-off-by: Pavel Emelyanov Signed-off-by: Patrick McHardy diff --git a/net/ipv4/netfilter/ipt_CLUSTERIP.c b/net/ipv4/netfilter/ipt_CLUSTERIP.c index 52926c8..a12dd32 100644 --- a/net/ipv4/netfilter/ipt_CLUSTERIP.c +++ b/net/ipv4/netfilter/ipt_CLUSTERIP.c @@ -82,8 +82,8 @@ clusterip_config_put(struct clusterip_config *c) static inline void clusterip_config_entry_put(struct clusterip_config *c) { + write_lock_bh(&clusterip_lock); if (atomic_dec_and_test(&c->entries)) { - write_lock_bh(&clusterip_lock); list_del(&c->list); write_unlock_bh(&clusterip_lock); @@ -96,7 +96,9 @@ clusterip_config_entry_put(struct clusterip_config *c) #ifdef CONFIG_PROC_FS remove_proc_entry(c->pde->name, c->pde->parent); #endif + return; } + write_unlock_bh(&clusterip_lock); } static struct clusterip_config * -- cgit v0.10.2 From 159d83363b629c91d020734207c1bc788b96af5a Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Mon, 14 Apr 2008 00:46:01 -0700 Subject: [BRIDGE]: Fix crash in __ip_route_output_key with bridge netfilter The bridge netfilter code attaches a fake dst_entry with a pointer to a fake net_device structure to skbs it passes up to IPv4 netfilter. This leads to crashes when the skb is passed to __ip_route_output_key when dereferencing the namespace pointer. Since bridging can currently only operate in the init_net namespace, the easiest fix for now is to initialize the nd_net pointer of the fake net_device struct to &init_net. Should fix bugzilla 10323: http://bugzilla.kernel.org/show_bug.cgi?id=10323 Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller diff --git a/net/bridge/br_netfilter.c b/net/bridge/br_netfilter.c index 1c0efd8..af7e8be 100644 --- a/net/bridge/br_netfilter.c +++ b/net/bridge/br_netfilter.c @@ -110,7 +110,8 @@ static inline __be16 pppoe_proto(const struct sk_buff *skb) * ipt_REJECT needs it. Future netfilter modules might * require us to fill additional fields. */ static struct net_device __fake_net_device = { - .hard_header_len = ETH_HLEN + .hard_header_len = ETH_HLEN, + .nd_net = &init_net, }; static struct rtable __fake_rtable = { -- cgit v0.10.2