From af2681828af5f2b42e12e8b16ba0cf113cf486c8 Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Thu, 3 Apr 2008 12:52:19 -0700 Subject: [PATCH 01/10] [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 --- net/ipv4/icmp.c | 24 +++++++++++++----------- net/ipv6/icmp.c | 22 ++++++++++++---------- 2 files changed, 25 insertions(+), 21 deletions(-) diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c index a944e8053e28..40508babad8c 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 f204a7275a0d..893287ecc628 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; From 439e23857a21c3a953826eed23c818697a97de1a Mon Sep 17 00:00:00 2001 From: "Denis V. Lunev" Date: Thu, 3 Apr 2008 13:30:17 -0700 Subject: [PATCH 02/10] [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 --- net/ipv6/addrconf.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index e7a1882db048..4fa9da0be19a 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); From eb867579311a9c1e998d6911af056772c400122a Mon Sep 17 00:00:00 2001 From: "Denis V. Lunev" Date: Thu, 3 Apr 2008 13:31:53 -0700 Subject: [PATCH 03/10] [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 --- net/ipv6/addrconf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index 4fa9da0be19a..a65935a9afd9 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); From 84f59370c519449c70dcc813b050f5cbbf0098e7 Mon Sep 17 00:00:00 2001 From: "Denis V. Lunev" Date: Thu, 3 Apr 2008 13:33:00 -0700 Subject: [PATCH 04/10] [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 --- net/ipv6/anycast.c | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/net/ipv6/anycast.c b/net/ipv6/anycast.c index 9c7f83fbc3a1..e5f56c953b58 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; From 61407f80f72970d52d4339f81c6c3cd03f4ca0f0 Mon Sep 17 00:00:00 2001 From: Andi Kleen Date: Thu, 3 Apr 2008 14:07:02 -0700 Subject: [PATCH 05/10] [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 --- lib/random32.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/lib/random32.c b/lib/random32.c index ec7f81d3fb18..ca87d86992bd 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); From b2a5c19ca0315723cecb9489ff8b67c4f17367b4 Mon Sep 17 00:00:00 2001 From: Matt Carlson Date: Thu, 3 Apr 2008 21:44:44 -0700 Subject: [PATCH 06/10] [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 --- drivers/net/tg3.c | 154 ++++++++++++++++++++++++++++++++++++++++++---- drivers/net/tg3.h | 79 +++++++++++++++++++++++- 2 files changed, 219 insertions(+), 14 deletions(-) diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index f9ef8bd8b11e..d4655b2d1f3f 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 3938eb35ce8c..c1075a73d66c 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]; From 23556323b22fef35bdc36465b7e7439ba3748c9f Mon Sep 17 00:00:00 2001 From: Pavel Emelyanov Date: Fri, 4 Apr 2008 12:45:12 -0700 Subject: [PATCH 07/10] [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 --- net/8021q/vlan_dev.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c index 480ea90e7dcd..41a76a05e6fd 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; From 5da4e37e59663bd1e9eae1d717e2ceb178a485b8 Mon Sep 17 00:00:00 2001 From: Harvey Harrison Date: Wed, 2 Apr 2008 17:33:35 -0700 Subject: [PATCH 08/10] 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 --- drivers/net/phy/marvell.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/net/phy/marvell.c b/drivers/net/phy/marvell.c index 33539917e9b8..32a8503a7acd 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; From e28e3a614cedb11637f6cc7a30f0812963df62fe Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Mon, 31 Mar 2008 01:40:04 +0300 Subject: [PATCH 09/10] 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 --- drivers/net/tokenring/olympic.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/net/tokenring/olympic.c b/drivers/net/tokenring/olympic.c index 433c994ea9d8..db4ca4f0b846 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 @@ static int __devinit olympic_probe(struct pci_dev *pdev, const struct pci_device 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; From 30ecce908b944079181938e61ddbc00c8b23798c Mon Sep 17 00:00:00 2001 From: Al Viro Date: Wed, 26 Mar 2008 05:57:12 +0000 Subject: [PATCH 10/10] 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 --- drivers/net/forcedeth.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/net/forcedeth.c b/drivers/net/forcedeth.c index 980c2c229a71..419f533006ab 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;